Mercurial > paraspace
view paraspace/tests/injection_test.py @ 152:bc213cb88636
Inject and redirect fields
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 16 Aug 2011 18:10:11 +0800 |
parents | 1eb1b2ca5de4 |
children | 6570b15d12d4 |
line wrap: on
line source
from paraspace import dexfile import os def _install_dexfile_4_deptracker(): global dexfile import imp, sys from paraspace import dex_deptracker from paraspace import injection try: new_dexfile = imp.load_compiled('dexfile', dexfile.__file__) except ImportError: new_dexfile = imp.load_source('dexfile', dexfile.__file__) pass dex_deptracker.dexfile = new_dexfile dexfile = new_dexfile dex_deptracker._nest_types = (dexfile.array, dexfile.cond, dexfile.switch) injection.dex_type_2_array_attr_map = \ injection._saved_dex_type_2_array_attr_map sys.modules['paraspace.dexfile'] = new_dexfile pass def _find_map(dex, map_type): for map in dex.maps.items.items: if map.type == map_type: return map pass pass def inject_fakefile_to_helloworld_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import dexfile_insert_class _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex') helloworld_dex = dexfile.DEXFile.open(helloworld_fn) classdef_map = _find_map(helloworld_dex, 0x0006) saved_classdef_map_sz = classdef_map.size saved_methodids_sz = len(helloworld_dex.methodIds.items) codeitems_map = _find_map(helloworld_dex, 0x2001) saved_codeitems_sz = codeitems_map.size helloworld_linked = \ dexfile.DEXFile_linked.build_dependencies(helloworld_dex, all_dep_decls) fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex') fakefile_dex = dexfile.DEXFile.open(fakefile_fn) fakefile_linked = \ dexfile.DEXFile_linked. \ build_dependencies(fakefile_dex, all_dep_decls) fakefile_def = fakefile_linked. \ find_class_name('Lcom/codemud/fakefile/fakefile;') fakefile_data = fakefile_def.classDataOffRef.value assert len(fakefile_data.directMethods.items) == 1 assert len(fakefile_data.virtualMethods.items) == 0 fakefile_dataheader = fakefile_data.header assert fakefile_dataheader.directMethodsSize == 1 assert fakefile_dataheader.virtualMethodsSize == 0 clone = dexfile_insert_class(helloworld_linked, fakefile_def) assert clone assert clone != fakefile_def helloworld_unlinked = helloworld_linked.get_unlinked() assert helloworld_unlinked # map size for classdef must be increased by 1 classdef_map = _find_map(helloworld_unlinked, 0x0006) assert classdef_map.size == saved_classdef_map_sz + 1 classdata_map = _find_map(helloworld_unlinked, 0x2000) assert classdata_map.size == classdef_map.size # Check strings strdatas = helloworld_unlinked.stringDataItems.items strs = sorted([strdata.data.data for strdata in strdatas]) assert len(strs) == len(set(strs)) # uniquely assert 'Lcom/codemud/fakefile/fakefile;' in strs # Check Method List methodids_map = _find_map(helloworld_unlinked, 0x0005) # method ids assert methodids_map.size == len(helloworld_unlinked.methodIds.items) assert methodids_map.size == saved_methodids_sz + 1 # Check Code item List codeitems_map = _find_map(helloworld_unlinked, 0x2001) assert codeitems_map.size == saved_codeitems_sz + 1 pass def redirect_types_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import dexfile_insert_class from paraspace.injection import dexfile_redirect_indices from paraspace.injection import make_methodidxs_redir_map from paraspace import dalvik_opcodes _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex') helloworld_dex = dexfile.DEXFile.open(helloworld_fn) classdef_map = _find_map(helloworld_dex, 0x0006) saved_classdef_map_sz = classdef_map.size saved_methodids_sz = len(helloworld_dex.methodIds.items) codeitems_map = _find_map(helloworld_dex, 0x2001) saved_codeitems_sz = codeitems_map.size helloworld_linked = \ dexfile.DEXFile_linked.build_dependencies(helloworld_dex, all_dep_decls) fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex') fakefile_dex = dexfile.DEXFile.open(fakefile_fn) fakefile_linked = \ dexfile.DEXFile_linked. \ build_dependencies(fakefile_dex, all_dep_decls) fakefile_def = \ fakefile_linked.find_class_name('Lcom/codemud/fakefile/fakefile;') clone = dexfile_insert_class(helloworld_linked, fakefile_def) init_method = fakefile_linked.find_method_name('<init>', fakefile_def) init_protoid = init_method.methodIdx.protoIdx File_typeid = helloworld_linked.find_typeid_name('Ljava/io/File;') assert File_typeid File_typeidx = helloworld_linked.get_idx_typeid(File_typeid) clone_typeidx = helloworld_linked.get_idx_typeid(clone.classIdx) types_redir = {File_typeidx: clone_typeidx} excludes = set([clone_typeidx]) fakefile_data = clone.classDataOffRef.value fakefile_methods = fakefile_data.directMethods.items fakefile_codes = [method.codeOffRef.value for method in fakefile_methods] methods_redir = make_methodidxs_redir_map(helloworld_linked, helloworld_linked, types_redir) dexfile_redirect_indices(helloworld_linked, types_redir, methods_redir, {}, excludes) for code in helloworld_linked.codeItems.items: op_vectors = dalvik_opcodes.decode_insn_blk(code.insns.data) for opcode, args in op_vectors: if opcode == dalvik_opcodes.all_opcodes.OP_NEW_INSTANCE: assert args[1] != File_typeidx pass elif opcode == dalvik_opcodes.all_opcodes.OP_INVOKE_DIRECT: methodid = helloworld_linked.find_methodid_idx(args[2]) assert methodid.classIdx != File_typeid or \ code in fakefile_codes pass pass pass pass def collect_types_in_method_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import \ collect_typeidxs_stridxs_fieldidxs_in_method from paraspace.injection import \ collect_typeidxs_stridxs_fieldidxs_mentioned_by_class from paraspace.dexfile import DEXFile_linked _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex') fakefile_dex = dexfile.DEXFile.open(fakefile_fn) fakefile_linked = \ dexfile.DEXFile_linked. \ build_dependencies(fakefile_dex, all_dep_decls) fakefile_def = \ fakefile_linked.find_class_name('Lcom/codemud/fakefile/fakefile;') init_method = fakefile_linked.find_method_name('<init>', fakefile_def) typeidxs, stridxs, fieldidxs = \ collect_typeidxs_stridxs_fieldidxs_in_method(fakefile_linked, \ init_method) assert len(typeidxs) == 1 typeid = fakefile_linked.find_typeid_idx(typeidxs[0]) typeid_name = DEXFile_linked.get_typeid_name(typeid) assert typeid_name == 'Ljava/io/File;' typeidxs, stridxs, fieldidxs = \ collect_typeidxs_stridxs_fieldidxs_mentioned_by_class(\ fakefile_linked, fakefile_def) assert len(typeidxs) == 1 typeid = fakefile_linked.find_typeid_idx(typeidxs[0]) typeid_name = DEXFile_linked.get_typeid_name(typeid) assert typeid_name == 'Ljava/io/File;' pass def dexfile_insert_classdefs_relative_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import dexfile_insert_classdefs_relative _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex') helloworld_dex = dexfile.DEXFile.open(helloworld_fn) classdef_map = _find_map(helloworld_dex, 0x0006) saved_classdef_map_sz = classdef_map.size saved_methodids_sz = len(helloworld_dex.methodIds.items) codeitems_map = _find_map(helloworld_dex, 0x2001) saved_codeitems_sz = codeitems_map.size helloworld_linked = \ dexfile.DEXFile_linked.build_dependencies(helloworld_dex, all_dep_decls) fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex') fakefile_dex = dexfile.DEXFile.open(fakefile_fn) fakefile_linked = \ dexfile.DEXFile_linked. \ build_dependencies(fakefile_dex, all_dep_decls) fakefile_def = fakefile_linked. \ find_class_name('Lcom/codemud/fakefile/fakefile;') fakefile_data = fakefile_def.classDataOffRef.value assert len(fakefile_data.directMethods.items) == 1 assert len(fakefile_data.virtualMethods.items) == 0 fakefile_dataheader = fakefile_data.header assert fakefile_dataheader.directMethodsSize == 1 assert fakefile_dataheader.virtualMethodsSize == 0 rel_set = dexfile_insert_classdefs_relative(helloworld_linked, fakefile_linked, [fakefile_def]) classdefs = list(rel_set.classdefs) assert classdefs assert len(classdefs) == 1 assert classdefs[0] != fakefile_def helloworld_unlinked = helloworld_linked.get_unlinked() assert helloworld_unlinked # map size for classdef must be increased by 1 classdef_map = _find_map(helloworld_unlinked, 0x0006) assert classdef_map.size == saved_classdef_map_sz + 1 classdata_map = _find_map(helloworld_unlinked, 0x2000) assert classdata_map.size == classdef_map.size # Check strings strdatas = helloworld_unlinked.stringDataItems.items strs = sorted([strdata.data.data for strdata in strdatas]) assert len(strs) == len(set(strs)) # uniquely assert 'Lcom/codemud/fakefile/fakefile;' in strs # Check Method List methodids_map = _find_map(helloworld_unlinked, 0x0005) # method ids assert methodids_map.size == len(helloworld_unlinked.methodIds.items) assert methodids_map.size == saved_methodids_sz + 1 # Check Code item List codeitems_map = _find_map(helloworld_unlinked, 0x2001) assert codeitems_map.size == saved_codeitems_sz + 1 pass def inject_classdefs_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import inject_classdefs from paraspace.injection import make_methodidxs_redir_map from paraspace.injection import dexfile_redirect_indices from paraspace import dalvik_opcodes from paraspace.dexfile import DEXFile_linked _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex') helloworld_dex = dexfile.DEXFile.open(helloworld_fn) classdef_map = _find_map(helloworld_dex, 0x0006) saved_classdef_map_sz = classdef_map.size saved_methodids_sz = len(helloworld_dex.methodIds.items) codeitems_map = _find_map(helloworld_dex, 0x2001) saved_codeitems_sz = codeitems_map.size helloworld_linked = \ dexfile.DEXFile_linked.build_dependencies(helloworld_dex, all_dep_decls) fakefile_fn = os.path.join(srcroot, 'data', 'fakefile.dex') fakefile_dex = dexfile.DEXFile.open(fakefile_fn) fakefile_linked = \ dexfile.DEXFile_linked. \ build_dependencies(fakefile_dex, all_dep_decls) fakefile_def = \ fakefile_linked.find_class_name('Lcom/codemud/fakefile/fakefile;') clonings = inject_classdefs(helloworld_linked, fakefile_linked, [fakefile_def]) assert clonings assert len(clonings) == 1 fakefile_cloning = clonings[0] method = helloworld_linked.find_method_name('<init>', fakefile_cloning) assert isinstance(method, dexfile._DEX_Method) V_typeid = helloworld_linked.find_typeid_name('V') file_typeid = helloworld_linked.find_typeid_name('Ljava/io/File;') file_typeidx = helloworld_linked.get_idx_typeid(file_typeid) str_typeid = helloworld_linked.find_typeid_name('Ljava/lang/String;') protoid = DEXFile_linked.make_protoid(V_typeid, (file_typeid, str_typeid)) initid = helloworld_linked.find_methodid_name_proto('<init>', protoid, file_typeid) initidx = helloworld_linked.get_idx_methodid(initid) insns_block = DEXFile_linked.get_code_block_method(method) opvectors = dalvik_opcodes.decode_insn_blk(insns_block) assert len(opvectors) == 2 opvector = opvectors[0] args = opvector[1] assert args[2] == initidx fakefile_typeidx = \ helloworld_linked.get_idx_typeid(fakefile_cloning.classIdx) typeidxs_redir_map = {file_typeidx: fakefile_typeidx} methodidxs_redir_map = \ make_methodidxs_redir_map(helloworld_linked, \ helloworld_linked, \ typeidxs_redir_map) dexfile_redirect_indices(helloworld_linked, typeidxs_redir_map, methodidxs_redir_map, {}, {}, excludes=[fakefile_typeidx]) cloning_initdef = \ helloworld_linked.find_method_name_proto('<init>', \ protoid, \ fakefile_cloning) fakefile_codes = [cloning_initdef.codeOffRef.value] for code in helloworld_linked.codeItems.items: op_vectors = dalvik_opcodes.decode_insn_blk(code.insns.data) for opcode, args in op_vectors: if opcode == dalvik_opcodes.all_opcodes.OP_NEW_INSTANCE: assert args[1] != file_typeidx pass elif opcode == dalvik_opcodes.all_opcodes.OP_INVOKE_DIRECT: methodid = helloworld_linked.find_methodid_idx(args[2]) assert methodid.classIdx != file_typeid or \ code in fakefile_codes pass 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. # # It is also possible dexfile_insert_classdefs_relative() does not # put injected objects into lists properly. # 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: if off != 0: assert off >= typelist_start assert off < typelist_stop pass pass except: print 'ERROR: protoid idx@%d %s 0x%x' % (idx, repr(protoid), off) print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop) raise pass for idx, classdef in enumerate(hello_linked.classDefs.items): off = classdef.interfacesOff try: if off != 0: assert off >= typelist_start assert off < typelist_stop pass pass except: print 'ERROR: classdef idx@%d %s 0x%x' % (idx, repr(classdef), off) print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop) raise pass pass ## \brief Test case for protoid out of order. # # Dalvik complaints that output of inject_redir() is out-of-order in # DEXFile.protoIds list. # \pre # E/dalvikvm( 298): Out-of-order proto_id arguments # E/dalvikvm( 298): Trouble with item 14 @ offset 0x304 # E/dalvikvm( 298): Cross-item verify of section type 0003 failed # E/dalvikvm( 298): ERROR: Byte swap + verify failed # E/dalvikvm( 298): Optimization failed # def proto_id_order_verify_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.dex_deptracker import dex_sort_sorted_arrays from paraspace.injection import inject_redir_no_restore _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_no_restore(fake_linked, 'Lcom/codemud/fakefile/fakefile;', hello_linked, 'Ljava/io/File;', all_dep_decls) dex_sort_sorted_arrays(hello_linked) pairs = map(None, hello_linked.protoIds.items[:-1], hello_linked.protoIds.items[1:]) for idx, (protoid0, protoid1) in enumerate(pairs): try: assert protoid0 < protoid1 except: print 'ERROR: protoid %d is out of order' % (idx + 1) raise pass pass ## \brief Test case for issue of bad offset list in _DEX_AnnotationSetItem. # # Values of _DEX_AnnotationSetItem.annotationOffs is corrupted after # injection. # \pre # E/dalvikvm( 300): No data map entry found @ 0xf31; expected 2004 # E/dalvikvm( 300): Trouble with item 0 @ offset 0x5c0 # E/dalvikvm( 300): Cross-item verify of section type 1003 failed # E/dalvikvm( 300): ERROR: Byte swap + verify failed # E/dalvikvm( 300): Optimization failed # # It must be the issue that back_type of an array can not be a \ref depend. # def annotation_set_items_verify_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.dex_deptracker import dex_sort_sorted_arrays from paraspace.injection import inject_redir_no_restore _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_no_restore(fake_linked, 'Lcom/codemud/fakefile/fakefile;', hello_linked, 'Ljava/io/File;', all_dep_decls) dex_sort_sorted_arrays(hello_linked) for setitem in hello_linked.annotationSetItems.items: for anno in setitem.annotationOffs.items: assert anno.offset in hello_linked.annotationItems.items pass pass pass ## \brief Test case for dalvik complaining fail to verify code. # # W/dalvikvm( 317): VFY: expected 1 args, found more (I) # W/dalvikvm( 317): VFY: rejecting call to Landroid/app/Activity;\ # .setContentView (I)V # W/dalvikvm( 317): VFY: rejecting opcode 0x6e at 0x0006 # W/dalvikvm( 317): VFY: rejected Lcom/codemud/helloworld/helloworld;\ # .onClick (Landroid/view/View;)V # W/dalvikvm( 317): Verifier rejected class Lcom/codemud/helloworld/\ # helloworld; # W/dalvikvm( 317): Class init failed in newInstance call (Lcom/codemud/\ # helloworl # # DEXFile.methodIds is a sorted array. The indices of _DEX_MethodIds would # be changed after injection and sorting, dex_sort_sorted_arrays(). # It means indices in code blocks are invalid. So, code blocks must be # rewrote with valid indices. # def code_verify_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import dex_sort_sorted_arrays_consistent from paraspace.injection import inject_redir_no_restore from paraspace.dalvik_opcodes import decode_insn_blk _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) helloworld_typeid = \ hello_linked.find_typeid_name('Lcom/codemud/helloworld/helloworld;') helloworld_methodids = \ hello_linked.find_methodids_typeid(helloworld_typeid) for methodid in helloworld_methodids: methodname = hello_linked.get_methodid_name(methodid) if methodname == 'onClick': methodidx = hello_linked.get_idx_methodid(methodid) method = hello_linked.find_method_idx(methodidx) blk = dexfile.DEXFile_linked.get_code_block_method(method) opvectors = decode_insn_blk(blk) methodidx = opvectors[4][1][2] saved_methodid0 = hello_linked.find_methodid_idx(methodidx) methodidx = opvectors[12][1][1] saved_methodid1 = hello_linked.find_methodid_idx(methodidx) elif methodname == 'write_file': assert methodid in hello_linked.methodIds.items methodidx = hello_linked.get_idx_methodid(methodid) method = hello_linked.find_method_idx(methodidx) blk = dexfile.DEXFile_linked.get_code_block_method(method) opvectors = decode_insn_blk(blk) pass pass inject_redir_no_restore(fake_linked, 'Lcom/codemud/fakefile/fakefile;', hello_linked, 'Ljava/io/File;', all_dep_decls) dex_sort_sorted_arrays_consistent(hello_linked) for methodid in hello_linked.methodIds.items: methodname = hello_linked.get_methodid_name(methodid) if methodname == 'setContentView': protoid = methodid.protoIdx sig = hello_linked.dump_protoid(protoid) assert sig == '(I) --> V' pass pass helloworld_typeid = \ hello_linked.find_typeid_name('Lcom/codemud/helloworld/helloworld;') helloworld_methodids = \ hello_linked.find_methodids_typeid(helloworld_typeid) for methodid in helloworld_methodids: methodname = hello_linked.get_methodid_name(methodid) if methodname == 'onClick': methodidx = hello_linked.get_idx_methodid(methodid) method = hello_linked.find_method_idx(methodidx) blk = dexfile.DEXFile_linked.get_code_block_method(method) opvectors = decode_insn_blk(blk) methodidx = opvectors[4][1][2] new_methodid0 = hello_linked.find_methodid_idx(methodidx) assert new_methodid0 is saved_methodid0 methodidx = opvectors[12][1][1] new_methodid1 = hello_linked.find_methodid_idx(methodidx) assert saved_methodid1 in hello_linked.methodIds.items assert new_methodid1 in hello_linked.methodIds.items assert new_methodid1 is saved_methodid1 pass elif methodname == 'write_file': assert methodid in hello_linked.methodIds.items methodidx = hello_linked.get_idx_methodid(methodid) method = hello_linked.find_method_idx(methodidx) blk = dexfile.DEXFile_linked.get_code_block_method(method) opvectors = decode_insn_blk(blk) # Check correctness of typeid of a new_instance. # This is an error of dex_sort_sorted_arrays_consistent(). assert opvectors[2][1][1] < len(hello_linked.typeIds.items) pass pass pass ## \brief Test case for checking methods of classdatas are consistent. # # Becase space optimization, DEX ecnode value for method indices # in \ref _DEX_Method. This test case make sure build_dependencies() # decode indices correctly. # # \see _deoptimize_classdata # def class_methods_consistent_test(): from paraspace.dex_deptracker import prepare_dep_decls _install_dexfile_4_deptracker() all_dep_decls = prepare_dep_decls() srcdir = os.path.dirname(__file__) datapath = os.path.join(srcdir, '..', '..', 'data') hello_path = os.path.join(datapath, 'helloworld.dex') hello_dex = dexfile.DEXFile.open(hello_path) hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, all_dep_decls) for classdata in hello_linked.classDatas.items: allmethods = classdata.directMethods.items + \ classdata.virtualMethods.items if len(allmethods) < 2: continue firstmethod = allmethods[0] firstmethodid = firstmethod.methodIdx for idx, method in enumerate(allmethods[1:]): try: assert method.methodIdx.classIdx == firstmethodid.classIdx except: print 'ERROR: method %d' % (idx + 1) raise pass pass pass ## \brief Test case for getting negative indices in _DEX_ClassDAta. # # It, possibly, caused by appling _optimize_classdata() at end of # restore_dependencies(). But, value was comes from # depend_idx_rel.get_value(). It already deoptimize the value. # def negative_depend_idx_rel_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.dex_deptracker import dex_sort_sorted_arrays 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) hello_linked.to_str() pass