changeset 149:d4533a59c694

inject_classdefs() also inject relative _DEX_StringIds.
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 15 Aug 2011 21:51:39 +0800
parents 90e181f2a0c5
children 1eb1b2ca5de4
files paraspace/dexfile.py paraspace/injection.py paraspace/tests/injection_test.py
diffstat 3 files changed, 69 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dexfile.py	Mon Aug 15 19:32:46 2011 +0800
+++ b/paraspace/dexfile.py	Mon Aug 15 21:51:39 2011 +0800
@@ -2354,6 +2354,10 @@
         protoid.returnTypeIdx = rtype
         protoid.parametersOffRef = param_cond
         return protoid
+
+    ## \brief Return _DEX_StringId of given index.
+    def find_strid_idx(self, idx):
+        return self.stringIds.items[idx]
     pass
 
 
--- a/paraspace/injection.py	Mon Aug 15 19:32:46 2011 +0800
+++ b/paraspace/injection.py	Mon Aug 15 21:51:39 2011 +0800
@@ -284,13 +284,15 @@
             pass
         return classdefs, undef_typeids
 
-    typeidxs = collect_typeidxs_mentioned_by_class(dex, classdef)
+    typeidxs, stridxs = \
+        collect_typeidxs_stridxs_mentioned_by_class(dex, classdef)
     typeids = [dex.find_typeid_idx(typeidx)
                for typeidx in typeidxs]
+    strids = [dex.find_strid_idx(idx) for idx in stridxs]
     
     classdefs, typeids = classify_typeids_defined(dex, typeids)
     
-    return classdefs, typeids
+    return classdefs, typeids, strids
 
 
 def dexfile_insert_classdefs(dex_dst, dex_src, classdefs):
@@ -299,6 +301,19 @@
     return clones
 
 
+## \brief Insert _DEX_StringId into another DEX.
+def dexfile_insert_stringid(dex_dst, dex_src, strid):
+    clone = _clone_composite(dex_dst, strid)
+    return clone
+
+
+## \brief Insert _DEX_StringIds into another DEX.
+def dexfile_insert_stringids(dex_dst, dex_src, strids):
+    clones = [dexfile_insert_stringid(dex_dst, dex_src, strid)
+              for strid in strids]
+    return clones
+
+
 ## \brief Clone and insert a _DEX_TypeId to another DEXFile_linked.
 #
 # \param dex_dst is a DEXFile_linked where the cloning one is inserted.
@@ -356,18 +371,20 @@
 def collect_classdefs_relative(dex, classdefs):
     rel_classdefs = set(classdefs)
     rel_typeids = set()
+    rel_strids = set()
     
     classdef_queue = list(classdefs)
     while classdef_queue:
         cur_classdef = classdef_queue.pop(0)
         
-        classdefs, typeids = _find_class_relative(dex, cur_classdef)
+        classdefs, typeids, strids = _find_class_relative(dex, cur_classdef)
         rel_typeids.update(typeids)
         new_classdefs = list(set(classdefs) - rel_classdefs)
         classdef_queue = classdef_queue + new_classdefs
         rel_classdefs.update(new_classdefs)
+        rel_strids.update(strids)
         pass
-    return rel_classdefs, rel_typeids
+    return rel_classdefs, rel_typeids, rel_strids
 
 
 ## \brief Clone and insert given and relative classes into another DEXFile.
@@ -388,7 +405,7 @@
             return True
         return False
 
-    relative_classdefs, relative_typeids = \
+    relative_classdefs, relative_typeids, relative_strids = \
         collect_classdefs_relative(dex_src, classdefs)
     
     for classdef in relative_classdefs:
@@ -401,8 +418,10 @@
         dexfile_insert_classdefs(dex_dst, dex_src, relative_classdefs)
     cloning_typeids = \
         dexfile_insert_or_merge_typeids(dex_dst, dex_src, relative_typeids)
+    cloning_strids = \
+        dexfile_insert_stringids(dex_dst, dex_src, relative_strids)
 
-    return cloning_classdefs, cloning_typeids
+    return cloning_classdefs, cloning_typeids, cloning_strids
 
 
 ## \brief Redirect types, methods and strings for the code of given method.
@@ -592,12 +611,12 @@
     pass
 
 
-## \brief Collect all type indices mentioned in the code of given method.
+## \brief Collect all type and string indices mentioned in the method code.
 #
 # \param method is a \ref _DEX_Method.
 # \return a list of type indices mentioned in the code.
 #
-def collect_typeidxs_in_method(dex, method):
+def collect_typeidxs_stridxs_in_method(dex, method):
     from paraspace.dexfile import _DEX_Method, DEXFile_linked
     from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes
     from itertools import chain
@@ -614,7 +633,7 @@
         code, args = op_vector
         
         if code == all_opcodes.OP_NEW_INSTANCE:
-            return (args[1],)
+            return args[1]
         
         if code in (all_opcodes.OP_INVOKE_DIRECT,
                     all_opcodes.OP_INVOKE_VIRTUAL,
@@ -623,7 +642,7 @@
                     all_opcodes.OP_INVOKE_INTERFACE):
             methodidx = args[2]
             method_typeidx = get_typeidx_methodidx(methodidx)
-            return (method_typeidx,)
+            return method_typeidx
 
         if code in (all_opcodes.OP_INVOKE_VIRTUAL_RANGE,
                     all_opcodes.OP_INVOKE_DIRECT_RANGE,
@@ -632,33 +651,48 @@
                     all_opcodes.OP_INVOKE_INTERFACE_RANGE):
             methodidx = args[1]
             method_typeidx = get_typeidx_methodidx(methodidx)
-            return (method_typeidx,)
+            return method_typeidx
+
+        return None
+
+    def collect_strings_in_op_vector(op_vector):
+        code, args = op_vector
+        if code == all_opcodes.OP_CONST_STRING:
+            stridx = args[1]
+            return stridx
         
-        return ()
+        return None
 
     code_blk = DEXFile_linked.get_code_block_method(method)
     op_vectors = decode_insn_blk(code_blk)
     types_insns = [collect_types_in_op_vector(op_vector)
                    for op_vector in op_vectors]
-    typeidxs = list(chain(*types_insns))
+    typeidxs = [idx for idx in types_insns if idx is not None]
+
+    strs_insns = [collect_strings_in_op_vector(op_vectors)
+                  for op_vectors in op_vectors]
+    stridxs = [idx for idx in strs_insns if idx is not None]
     
-    return typeidxs
+    return typeidxs, stridxs
 
 
-## \brief Collect all type indices mentioned by the code of given class.
-def collect_typeidxs_mentioned_by_class(dex, classdef):
+## \brief Collect all type and string indices mentioned by the class code.
+def collect_typeidxs_stridxs_mentioned_by_class(dex, classdef):
     from paraspace.dexfile import DEXFile_linked
 
     assert isinstance(dex, DEXFile_linked)
     
     typeidxs = set()
+    stridxs = set()
     methods = DEXFile_linked.get_methods_classdef(classdef)
     for method in methods:
-        method_typeidxs = collect_typeidxs_in_method(dex, method)
+        method_typeidxs, method_stridxs = \
+            collect_typeidxs_stridxs_in_method(dex, method)
         typeidxs.update(method_typeidxs)
+        stridxs.update(method_stridxs)
         pass
     
-    return list(typeidxs)
+    return list(typeidxs), list(stridxs)
 
 
 ## \brief Make a mapping for type indices of injection.
@@ -690,7 +724,7 @@
 
 ## \brief Redirect code for methods of injected classes.
 def redirect_injected_code(dex_dst, dex_src, classdefs):
-    relative_classdefs, relative_typeids = \
+    relative_classdefs, relative_typeids, relative_strids = \
         collect_classdefs_relative(dex_src, classdefs)
     
     typeidxs_redir = \
@@ -724,7 +758,7 @@
     assert isinstance(dex_dst, DEXFile_linked)
     assert isinstance(dex_src, DEXFile_linked)
 
-    injected_classdefs, injected_typeids = \
+    injected_classdefs, injected_typeids, injected_strids = \
         dexfile_insert_classdefs_relative(dex_dst, dex_src, classdefs)
     redirect_injected_code(dex_dst, dex_src, classdefs)
     return injected_classdefs
--- a/paraspace/tests/injection_test.py	Mon Aug 15 19:32:46 2011 +0800
+++ b/paraspace/tests/injection_test.py	Mon Aug 15 21:51:39 2011 +0800
@@ -181,8 +181,8 @@
 
 def collect_types_in_method_test():
     from paraspace.dex_deptracker import prepare_dep_decls
-    from paraspace.injection import collect_typeidxs_in_method
-    from paraspace.injection import collect_typeidxs_mentioned_by_class
+    from paraspace.injection import collect_typeidxs_stridxs_in_method
+    from paraspace.injection import collect_typeidxs_stridxs_mentioned_by_class
     from paraspace.dexfile import DEXFile_linked
     
     _install_dexfile_4_deptracker()
@@ -203,15 +203,17 @@
 
     init_method = fakefile_linked.find_method_name('<init>', fakefile_def)
 
-    typeidxs = collect_typeidxs_in_method(fakefile_linked, init_method)
+    typeidxs, stridxs = \
+        collect_typeidxs_stridxs_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 = collect_typeidxs_mentioned_by_class(fakefile_linked,
-                                                   fakefile_def)
+    typeidxs, stridxs = \
+        collect_typeidxs_stridxs_mentioned_by_class(fakefile_linked, \
+                                                        fakefile_def)
     assert len(typeidxs) == 1
 
     typeid = fakefile_linked.find_typeid_idx(typeidxs[0])
@@ -261,9 +263,10 @@
     assert fakefile_dataheader.directMethodsSize == 1
     assert fakefile_dataheader.virtualMethodsSize == 0
 
-    classdefs, typeids = dexfile_insert_classdefs_relative(helloworld_linked,
-                                                           fakefile_linked,
-                                                           [fakefile_def])
+    classdefs, typeids, strids = \
+        dexfile_insert_classdefs_relative(helloworld_linked, \
+                                              fakefile_linked, \
+                                              [fakefile_def])
     assert classdefs
     assert len(classdefs) == 1
     assert classdefs[0] != fakefile_def