# HG changeset patch # User Thinker K.F. Li # Date 1312896493 -28800 # Node ID b488ca519709cbb4f573aad36988bbe5dedad680 # Parent 3dee4d929e1ff3a55584b757df98e5aa2cff5f0e Make sure elements are absolute incremental for sorted arrays when injecting. - All sorted array of DEXFile must be absolute incremental. - If injected one is the same order as one already in the array, the one in array are used to replace injected one. - All references to clone and injected one refer to ones already in array instead. diff -r 3dee4d929e1f -r b488ca519709 paraspace/injection.py --- a/paraspace/injection.py Tue Aug 09 17:23:01 2011 +0800 +++ b/paraspace/injection.py Tue Aug 09 21:28:13 2011 +0800 @@ -77,6 +77,7 @@ from paraspace.dex_deptracker import _dex_tree_get_child from paraspace.dex_deptracker import _dex_tree_set_child from paraspace.dexfile import _DEX_TypeList, _DEX_TypeList_align + from paraspace.dexfile import array_sorted if isinstance(obj, _DEX_TypeList): wrapper = _DEX_TypeList_align() @@ -91,6 +92,13 @@ return array = getattr(dex, attr) + + if isinstance(array, array_sorted): + if obj in array.items: + idx = array.items.index(obj) + return array.items[idx] + pass + array.items.append(obj) count_name = array.count_name @@ -98,7 +106,8 @@ count = _dex_tree_get_child(dex, count_name) _dex_tree_set_child(dex, count_name, count + 1) pass - pass + + return obj ## \brief Clone a composite object. @@ -188,13 +197,26 @@ merge_unique_strid() merge_unique_typeid() - for obj in visit_log.values(): + relink_list = [] + for key, obj in visit_log.items(): + if isinstance(obj, (_DEX_StringDataItem, + _DEX_StringId, + _DEX_TypeId)): + continue + r = dex_append_obj_list(dex, obj) + if r and r is not obj: + visit_log[key] = r + else: + relink_list.append(obj) + pass + pass + + for obj in relink_list: if isinstance(obj, (_DEX_StringDataItem, _DEX_StringId, _DEX_TypeId)): continue relink_dependencies(obj) - dex_append_obj_list(dex, obj) pass clone = visit_log[id(comobj)] @@ -660,11 +682,8 @@ # 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 - +def inject_redir_no_restore(src_linked, inj_classname, + dst_linked, redir_classname, decls): inj_classdef = src_linked.find_class_name(inj_classname) injected_classdefs = inject_classdefs(dst_linked, src_linked, [inj_classdef]) @@ -682,7 +701,22 @@ for classdef in injected_classdefs] dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir, excludes=injected_typeidxs) + pass + + +## \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 + inject_redir_no_restore(src_linked, inj_classname, + dst_linked, redir_classname, decls) dex_sort_sorted_arrays(dst_linked) restore_dependencies(dst_linked, decls) pass diff -r 3dee4d929e1f -r b488ca519709 paraspace/tests/dex_deptracker_test.py --- a/paraspace/tests/dex_deptracker_test.py Tue Aug 09 17:23:01 2011 +0800 +++ b/paraspace/tests/dex_deptracker_test.py Tue Aug 09 21:28:13 2011 +0800 @@ -228,4 +228,10 @@ assert typeid10 > typeid12 assert hello_linked.typeIds.items[10] == typeid12 assert hello_linked.typeIds.items[12] == typeid10 + + for protoid0, protoid1 in map(None, + hello_linked.protoIds.items[:-1], + hello_linked.protoIds.items[1:]): + assert protoid0 < protoid1 + pass pass diff -r 3dee4d929e1f -r b488ca519709 paraspace/tests/injection_test.py --- a/paraspace/tests/injection_test.py Tue Aug 09 17:23:01 2011 +0800 +++ b/paraspace/tests/injection_test.py Tue Aug 09 21:28:13 2011 +0800 @@ -492,3 +492,54 @@ 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