changeset 106:7821c6e89622

dexfile_redirect_types() is almost ready. fakefile.dex must be updated to provide correctly constructor signature.
author Thinker K.F. Li <thinker@codemud.net>
date Fri, 29 Jul 2011 16:17:15 +0800
parents f14c32108164
children 4b3573d039af
files paraspace/dexfile.py paraspace/injection.py paraspace/tests/injection_test.py
diffstat 3 files changed, 42 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dexfile.py	Thu Jul 28 13:25:55 2011 +0800
+++ b/paraspace/dexfile.py	Fri Jul 29 16:17:15 2011 +0800
@@ -1029,9 +1029,16 @@
     pass
 
 
+class _DEX_TypeList_typeid(composite):
+    typeIdx = depend_idx('DEXFile.typeIds')(uint16)
+
+    child_names = ('typeIdx',)
+    pass
+
+
 class _DEX_TypeList(composite):
     num = uint32
-    typeItems = array('num', depend_idx('DEXFile.typeIds')(uint16))
+    typeItems = array('num', _DEX_TypeList_typeid)
 
     child_names = 'num typeItems'.split()
     pass
@@ -1833,10 +1840,10 @@
         if len(typelist1.typeItems.items) != len(typelist2.typeItems.items):
             return False
 
-        for typeid1, typeid2 in map(None,
-                                    typelist1.typeItems.items,
-                                    typelist2.typeItems.items):
-            if typeid1 != typeid2:
+        for tl_typeid1, tl_typeid2 in map(None,
+                                          typelist1.typeItems.items,
+                                          typelist2.typeItems.items):
+            if tl_typeid1.typeIdx != tl_typeid2.typeIdx:
                 return False
             pass
         return True
@@ -1855,6 +1862,24 @@
                 return wmethod
             pass
         raise ValueError, 'can not find a method for given name and prototype'
+
+    @staticmethod
+    def get_param_typeids_protoid(protoid):
+        if not protoid.parametersOffRef.is_true:
+            return ()
+        tl_typeids = protoid.parametersOffRef.value.typeItems.items
+        typeids = [tl_typeid.typeIdx
+                   for tl_typeid in tl_typeids]
+        return typeids
+
+    ## \brief Dump content of a proto ID.
+    @staticmethod
+    def dump_protoid(protoid):
+        rtype_name = DEXFile_linked.get_typeid_name(protoid.returnTypeIdx)
+        param_types = DEXFile_linked.get_param_typeids_protoid(protoid)
+        ptype_names = [DEXFile_linked.get_typeid_name(ptype)
+                       for ptype in param_types]
+        return '(%s) --> %s' % (', '.join(ptype_names), rtype_name)
     pass
 
 
--- a/paraspace/injection.py	Thu Jul 28 13:25:55 2011 +0800
+++ b/paraspace/injection.py	Fri Jul 29 16:17:15 2011 +0800
@@ -1,16 +1,17 @@
 
 def _relocatable_children(obj):
+    from paraspace.dex_deptracker import _dex_tree_get_child
     from paraspace.dexfile import relocatable, array
-    
+
     if isinstance(obj, array):
-        if not obj.items:
-            return []
-        rel_children = [(repr(idx), elt)
-                        for idx, elt in enumerate(obj.items)
-                        if isinstance(elt, relocatable)]
+        rel_children = [('items.' + str(idx), value)
+                        for idx, value in enumerate(obj.items)
+                        if isinstance(value, relocatable)]
         return rel_children
     
-    attr_value_pairs = [(attr, getattr(obj, attr)) for attr in dir(obj)]
+    attrs = obj.children()
+    attr_value_pairs = [(attr, _dex_tree_get_child(obj, attr))
+                        for attr in attrs]
     rel_children = [(attr, value) for attr, value in attr_value_pairs
                     if isinstance(value, relocatable)]
     return rel_children
@@ -113,10 +114,8 @@
 
     def relink_dependencies(clone):
         rel_children = _relocatable_children(clone)
-        print clone
         for attr, value in rel_children:
             clone_value = visit_log[id(value)]
-            print attr, _dex_tree_get_child(clone, attr), clone_value
             _dex_tree_set_child(clone, attr, clone_value)
             pass
         pass
@@ -187,7 +186,6 @@
     merge_unique_strid()
     merge_unique_typeid()
     
-    print visit_log
     for obj in visit_log.values():
         if isinstance(obj, (_DEX_StringDataItem,
                             _DEX_StringId,
@@ -244,6 +242,7 @@
             method_typeid = methodid.classIdx
             method_typeidx = dex.get_idx_typeid(method_typeid)
             if method_typeidx not in redirect_map:
+                method_typeid = dex.find_typeid_idx(method_typeidx - 1)
                 return opcode, args
             
             new_method_typeidx = redirect_map[method_typeidx]
@@ -257,6 +256,8 @@
                                                         method_proto,
                                                         classdef)
             except:
+                print 'NOT FOUND', method_name, method_proto, dex.get_classdef_name(classdef)
+                print DEXFile_linked.dump_protoid(method_proto)
                 return opcode, args
             new_method_idx = dex.get_index_method(new_method)
             return opcode, (args[0], args[1], new_method_idx,
--- a/paraspace/tests/injection_test.py	Thu Jul 28 13:25:55 2011 +0800
+++ b/paraspace/tests/injection_test.py	Fri Jul 29 16:17:15 2011 +0800
@@ -136,7 +136,6 @@
         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)
@@ -153,17 +152,10 @@
     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:
@@ -171,6 +163,7 @@
                 pass
             elif opcode == dalvik_opcodes.all_opcodes.OP_INVOKE_DIRECT:
                 methodid = helloworld_linked.find_methodid_idx(args[2])
+                print fakefile_codes, code, args[2]
                 assert methodid.classIdx != File_typeid or \
                     code in fakefile_codes
                 pass