changeset 105:f14c32108164

Test dexfile_redirect_types
author Thinker K.F. Li <thinker@codemud.net>
date Thu, 28 Jul 2011 13:25:55 +0800
parents 61cef1662035
children 7821c6e89622
files paraspace/injection.py paraspace/tests/injection_test.py
diffstat 2 files changed, 90 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/injection.py	Thu Jul 28 00:06:54 2011 +0800
+++ b/paraspace/injection.py	Thu Jul 28 13:25:55 2011 +0800
@@ -65,6 +65,9 @@
     return type_2_attr
 
 
+_saved_dex_type_2_array_attr_map = dex_type_2_array_attr_map
+
+
 ## \brief Append a object to appropriate list of a DEXFile object.
 #
 # Skip the object if found no appropriate list.
@@ -99,6 +102,8 @@
     from copy import copy
     from paraspace.dexfile import _DEX_StringDataItem, _DEX_StringId
     from paraspace.dexfile import _DEX_TypeId
+    from paraspace.dex_deptracker import _dex_tree_set_child
+    from paraspace.dex_deptracker import _dex_tree_get_child
     
     visit_log = {}
     
@@ -108,9 +113,11 @@
 
     def relink_dependencies(clone):
         rel_children = _relocatable_children(clone)
+        print clone
         for attr, value in rel_children:
             clone_value = visit_log[id(value)]
-            setattr(clone, attr, clone_value)
+            print attr, _dex_tree_get_child(clone, attr), clone_value
+            _dex_tree_set_child(clone, attr, clone_value)
             pass
         pass
 
@@ -180,6 +187,7 @@
     merge_unique_strid()
     merge_unique_typeid()
     
+    print visit_log
     for obj in visit_log.values():
         if isinstance(obj, (_DEX_StringDataItem,
                             _DEX_StringId,
@@ -234,7 +242,7 @@
             methodidx = args[2]
             methodid = dex.find_methodid_idx(methodidx)
             method_typeid = methodid.classIdx
-            method_typeidx = dex.get_idx_typeid(method_typeidx)
+            method_typeidx = dex.get_idx_typeid(method_typeid)
             if method_typeidx not in redirect_map:
                 return opcode, args
             
@@ -279,7 +287,7 @@
 def dexfile_redirect_types(dex, redirect_map, excludes=set([])):
     for classdef in dex.classDefs.items:
         typeid = classdef.classIdx
-        idx = dex.get_index_typeid(typeid)
+        idx = dex.get_idx_typeid(typeid)
         if idx in excludes:
             continue
         class_redirect_types(dex, classdef, redirect_map)
--- a/paraspace/tests/injection_test.py	Thu Jul 28 00:06:54 2011 +0800
+++ b/paraspace/tests/injection_test.py	Thu Jul 28 13:25:55 2011 +0800
@@ -5,6 +5,7 @@
     global dexfile
     import imp, sys
     from paraspace import dex_deptracker
+    from paraspace import injection
     
     try:
         new_dexfile = imp.load_compiled('dexfile', dexfile.__file__)
@@ -14,6 +15,9 @@
     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
@@ -98,3 +102,78 @@
     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_types
+    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)
+    
+    print helloworld_linked.codeItems.items
+    fakefile_def = \
+        fakefile_linked.find_class_name('Lcom/codemud/fakefile/fakefile;')
+    clone = dexfile_insert_class(helloworld_linked, fakefile_def)
+
+    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)
+
+    redirect_map = {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]
+    print clone.classDataOffRef.value, fakefile_def.classDataOffRef.value
+    print fakefile_def.classDataOffRef.value.directMethods.items
+    print fakefile_methods
+    print [method.codeOffRef.value for method in fakefile_def.classDataOffRef.value.directMethods.items]
+    print fakefile_codes
+    
+    dexfile_redirect_types(helloworld_linked, redirect_map, excludes)
+
+    print helloworld_linked.codeItems.items
+    for code in helloworld_linked.codeItems.items:
+        print code
+        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