changeset 135:b488ca519709

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.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 09 Aug 2011 21:28:13 +0800
parents 3dee4d929e1f
children f31bfe55d9c2
files paraspace/injection.py paraspace/tests/dex_deptracker_test.py paraspace/tests/injection_test.py
diffstat 3 files changed, 99 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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