Mercurial > paraspace
changeset 131:044bfc415577
Fix issue of data map verification.
- Dalvik complain that data map generated by inject_redir.py is unexpected.
- Test case map_verify_error_test()
- Refactor inject_redir.py to paraspace.injection.inject_redir().
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 09 Aug 2011 11:47:43 +0800 |
parents | 117047deda64 |
children | 75a31967ebee |
files | examples/inject_redir.py paraspace/dexfile.py paraspace/injection.py paraspace/tests/dex_deptracker_test.py paraspace/tests/injection_test.py |
diffstat | 5 files changed, 165 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/inject_redir.py Tue Aug 09 00:07:04 2011 +0800 +++ b/examples/inject_redir.py Tue Aug 09 11:47:43 2011 +0800 @@ -7,10 +7,7 @@ # from paraspace.dexfile import DEXFile, DEXFile_linked from paraspace.dex_deptracker import prepare_dep_decls -from paraspace.dex_deptracker import restore_dependencies -from paraspace.dex_deptracker import dex_sort_sorted_arrays -from paraspace.injection import inject_classdefs, make_methodidxs_redir_map -from paraspace.injection import dexfile_redirect_types +from paraspace.injection import inject_redir import sys if len(sys.argv) != 6: @@ -21,42 +18,28 @@ sys.exit(1) pass -src_dexname = sys.argv[1] -inj_classname = sys.argv[2] -dst_dexname = sys.argv[3] -redir_classname = sys.argv[4] -output_name = sys.argv[5] -decls = prepare_dep_decls() - -src_dex = DEXFile.open(src_dexname) -src_linked = DEXFile_linked.build_dependencies(src_dex, decls) - -dst_dex = DEXFile.open(dst_dexname) -dst_linked = DEXFile_linked.build_dependencies(dst_dex, decls) - -inj_classdef = src_linked.find_class_name(inj_classname) -injected_classdefs = inject_classdefs(dst_linked, src_linked, [inj_classdef]) - -redir_typeid = dst_linked.find_typeid_name(redir_classname) -redir_typeidx = dst_linked.get_idx_typeid(redir_typeid) -inj_typeid = dst_linked.find_typeid_name(inj_classname) -inj_typeidx = dst_linked.get_idx_typeid(inj_typeid) -typeidxs_redir = {redir_typeidx: inj_typeidx} - -methodidxs_redir = \ - make_methodidxs_redir_map(dst_linked, dst_linked, typeidxs_redir) - -injected_typeidxs = [dst_linked.get_idx_classdef(classdef) - for classdef in injected_classdefs] -dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir, - excludes=injected_typeidxs) - -dex_sort_sorted_arrays(dst_linked) -restore_dependencies(dst_linked, decls) - -restore_raw = dst_linked.to_str() - -ofile = open(output_name, 'w') -ofile.write(restore_raw) -ofile.close() +if __name__ == '__main__': + src_dexname = sys.argv[1] + inj_classname = sys.argv[2] + dst_dexname = sys.argv[3] + redir_classname = sys.argv[4] + output_name = sys.argv[5] + + decls = prepare_dep_decls() + + src_dex = DEXFile.open(src_dexname) + src_linked = DEXFile_linked.build_dependencies(src_dex, decls) + + dst_dex = DEXFile.open(dst_dexname) + dst_linked = DEXFile_linked.build_dependencies(dst_dex, decls) + + inject_redir(src_linked, inj_classname, + dst_linked, redir_classname, decls) + + restore_raw = dst_linked.to_str() + + ofile = open(output_name, 'w') + ofile.write(restore_raw) + ofile.close() + pass
--- a/paraspace/dexfile.py Tue Aug 09 00:07:04 2011 +0800 +++ b/paraspace/dexfile.py Tue Aug 09 11:47:43 2011 +0800 @@ -971,6 +971,9 @@ 0x2005: 'kDexTypeEncodedArrayItem', 0x2006: 'kDexTypeAnnotationsDirectoryItem' } + + name_to_types = dict([(_name, _typenum) + for _typenum, _name in types.items()]) child_names = \ 'type unused size offset'.split()
--- a/paraspace/injection.py Tue Aug 09 00:07:04 2011 +0800 +++ b/paraspace/injection.py Tue Aug 09 11:47:43 2011 +0800 @@ -645,3 +645,37 @@ dexfile_insert_classdefs_relative(dex_dst, dex_src, classdefs) redirect_injected_code(dex_dst, dex_src, classdefs) return injected_classdefs + + +## \brief Inject and redirect a _DEX_ClassDef from one linked to another. +# +# The _DEX_ClassDef given by inj_classname would be inserted to dst_linked, +# and redirect all invoking of type, given by redir_classname, to +# the injected one. +# +def inject_redir(src_linked, inj_classname, + dst_linked, redir_classname, decls): + from paraspace.dex_deptracker import dex_sort_sorted_arrays + from paraspace.dex_deptracker import restore_dependencies + + inj_classdef = src_linked.find_class_name(inj_classname) + injected_classdefs = inject_classdefs(dst_linked, src_linked, + [inj_classdef]) + + redir_typeid = dst_linked.find_typeid_name(redir_classname) + redir_typeidx = dst_linked.get_idx_typeid(redir_typeid) + inj_typeid = dst_linked.find_typeid_name(inj_classname) + inj_typeidx = dst_linked.get_idx_typeid(inj_typeid) + typeidxs_redir = {redir_typeidx: inj_typeidx} + + methodidxs_redir = \ + make_methodidxs_redir_map(dst_linked, dst_linked, typeidxs_redir) + + injected_typeidxs = [dst_linked.get_idx_classdef(classdef) + for classdef in injected_classdefs] + dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir, + excludes=injected_typeidxs) + + dex_sort_sorted_arrays(dst_linked) + restore_dependencies(dst_linked, decls) + pass
--- a/paraspace/tests/dex_deptracker_test.py Tue Aug 09 00:07:04 2011 +0800 +++ b/paraspace/tests/dex_deptracker_test.py Tue Aug 09 11:47:43 2011 +0800 @@ -59,7 +59,7 @@ dex.classDatas.items[-1].data_offset = 0 dex.typeIds.items[12].data_idx = 0 - + update_offset(dex, all_dep_decls) assert dex.typeLists.items[0].value.data_offset == offset0 @@ -215,8 +215,17 @@ hello_linked.typeIds.items[0] = last hello_linked.typeIds.items[-1] = first + typeid10 = hello_linked.typeIds.items[10] + typeid12 = hello_linked.typeIds.items[12] + typeid10.descriptorIdx, typeid12.descriptorIdx = \ + typeid12.descriptorIdx, typeid10.descriptorIdx + dex_sort_sorted_arrays(hello_linked) assert hello_linked.typeIds.items[0] == first assert hello_linked.typeIds.items[-1] == last + + assert typeid10 > typeid12 + assert hello_linked.typeIds.items[10] == typeid12 + assert hello_linked.typeIds.items[12] == typeid10 pass
--- a/paraspace/tests/injection_test.py Tue Aug 09 00:07:04 2011 +0800 +++ b/paraspace/tests/injection_test.py Tue Aug 09 11:47:43 2011 +0800 @@ -388,3 +388,96 @@ pass pass pass + + +## \brief Test case for error of verifing data map. +# +# The output of inject_redir.py is not accepted by dalvik with following +# error messages. +# \pre +# E/dalvikvm( 302): Unexpected data map entry @ 0x930: expected 1001, \ +# found 2006 +# E/dalvikvm( 302): Trouble with item 0 @ offset 0x25c +# E/dalvikvm( 302): Cross-item verify of section type 0003 failed +# E/dalvikvm( 302): ERROR: Byte swap + verify failed +# E/dalvikvm( 302): Optimization failed +# +# The data map printed by paraspace.dexfile is +# \pre +# 0x0000(kDexTypeHeaderItem) size=1 offset=0x00000000 +# 0x0001(kDexTypeStringIdItem) size=92 offset=0x00000070 +# 0x0002(kDexTypeTypeIdItem) size=31 offset=0x000001e0 +# 0x0003(kDexTypeProtoIdItem) size=18 offset=0x0000025c +# 0x0004(kDexTypeFieldIdItem) size=7 offset=0x00000334 +# 0x0005(kDexTypeMethodIdItem) size=36 offset=0x0000036c +# 0x0006(kDexTypeClassDefItem) size=10 offset=0x0000048c +# 0x1003(kDexTypeAnnotationSetItem) size=7 offset=0x000005cc +# 0x2001(kDexTypeCodeItem) size=17 offset=0x0000061c +# 0x2006(kDexTypeAnnotationsDirectoryItem) size=7 offset=0x00000910 +# 0x1001(kDexTypeTypeList) size=12 offset=0x00000980 +# 0x2002(kDexTypeStringDataItem) size=92 offset=0x000009e2 +# 0x2003(kDexTypeDebugInfoItem) size=17 offset=0x00000f05 +# 0x2004(kDexTypeAnnotationItem) size=9 offset=0x00000fc1 +# 0x2005(kDexTypeEncodedArrayItem) size=5 offset=0x00001012 +# 0x2000(kDexTypeClassDataItem) size=10 offset=0x0000102d +# 0x1000(kDexTypeMapList) size=1 offset=0x000010c0 +# +# It is possible restore_dependencies() does not following \ref ref +# object to set offset value on referenced attribute. +# +def map_verify_error_test(): + from paraspace.dex_deptracker import prepare_dep_decls + from paraspace.injection import inject_redir + + _install_dexfile_4_deptracker() + + all_dep_decls = prepare_dep_decls() + + srcdir = os.path.dirname(__file__) + datapath = os.path.join(srcdir, '..', '..', 'data') + + fake_path = os.path.join(datapath, 'fakefile.dex') + hello_path = os.path.join(datapath, 'helloworld.dex') + + fake_dex = dexfile.DEXFile.open(fake_path) + fake_linked = dexfile.DEXFile_linked.build_dependencies(fake_dex, + all_dep_decls) + + hello_dex = dexfile.DEXFile.open(hello_path) + hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, + all_dep_decls) + + inject_redir(fake_linked, 'Lcom/codemud/fakefile/fakefile;', + hello_linked, 'Ljava/io/File;', all_dep_decls) + + for idx, item in enumerate(hello_linked.maps.items.items): + if item.type != dexfile._DEX_MapItem.name_to_types['kDexTypeTypeList']: + break + pass + else: + assert False + pass + typelist_start = item.offset + next_item = hello_linked.maps.items.items[idx + 1] + typelist_stop = next_item.offset + + for idx, protoid in enumerate(hello_linked.protoIds.items): + off = protoid.parametersOff + try: + assert off >= typelist_start + assert off < typelist_stop + except: + print 'ERROR: protoid idx @', idx, protoid + raise + pass + + for idx, classdef in enumerate(hello_linked.classDefs.items): + off = classdef.interfacesOff + try: + assert off >= typelist_start + assert off < typelist_stop + except: + print 'ERROR: classdef idx @', idx, classdef + raise + pass + pass