changeset 145:c4324c3461e8

Redirect string indices. - Change names of *redirect_types*() to *redirect_indices*(). - Redirect string indices in method_redirect_indices() too.
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 15 Aug 2011 15:25:39 +0800
parents 46e40afd4558
children 032877e14560
files paraspace/injection.py paraspace/tests/injection_test.py
diffstat 2 files changed, 98 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/injection.py	Mon Aug 15 11:13:56 2011 +0800
+++ b/paraspace/injection.py	Mon Aug 15 15:25:39 2011 +0800
@@ -387,8 +387,9 @@
     return cloning_classdefs, cloning_typeids
 
 
-## \brief Redirect types and methods for the code of given method.
-def method_redirect_typeidxs(dex, method, typeidxs_redir, methods_redir):
+## \brief Redirect types, methods and strings for the code of given method.
+def method_redirect_indices(dex, method, typeidxs_redir, methods_redir,
+                            stridxs_redir):
     from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes
     from paraspace.dalvik_opcodes import encode_opcode_vectors
     from paraspace.dexfile import DEXFile_linked
@@ -428,6 +429,12 @@
                 return opcode, args
             
             return opcode, (args[0], methods_redir[methodidx], args[2])
+        elif opcode == all_opcodes.OP_CONST_STRING:
+            stridx = args[1]
+            if stridx not in stridxs_redir:
+                return opcode, args
+
+            return opcode, (args[0], stridxs_redir[stridx])
         return opcode, args
     
     new_op_vectors = [redirect(opcode, args) for opcode, args in op_vectors]
@@ -475,18 +482,22 @@
 # \param dex is a DEXFile_linked.
 # \param classdef is a class definition.
 # \param typeidxs_redir is a map of types.
+# \param stridxs_redir is a map of strings.
 # \param methods_redir is a map of methods.
 #
-def class_redirect_types(dex, classdef, typeidxs_redir, methods_redir):
+def class_redirect_indices(dex, classdef, typeidxs_redir, methods_redir,
+                           stridxs_redir):
     if not classdef.classDataOffRef.is_true:
         return
     
     classdata = classdef.classDataOffRef.value
     for method in classdata.directMethods.items:
-        method_redirect_typeidxs(dex, method, typeidxs_redir, methods_redir)
+        method_redirect_indices(dex, method, typeidxs_redir, methods_redir,
+                                stridxs_redir)
         pass
     for method in classdata.virtualMethods.items:
-        method_redirect_typeidxs(dex, method, typeidxs_redir, methods_redir)
+        method_redirect_indices(dex, method, typeidxs_redir, methods_redir,
+                                stridxs_redir)
         pass
     pass
 
@@ -515,29 +526,50 @@
     return methods_map
 
 
+## \brief Make a map to map string indices from source to destinate DEX.
+#
+# \param dex_src is soruce of the mapping.
+# \param dex_dst is destination of the mapping.
+# \param classdefs is _DEX_ClassDefs from dex_src.
+# \return a mapping for string indices.
+#
+def make_stridxs_redir_map(dex_src, dex_dst):
+    stridxs_map = {}
+    for idx, strid in enumerate(dex_src.stringIds.items):
+        try:
+            tgt_idx = dex_dst.stringIds.items.index(strid)
+        except ValueError:
+            continue
+        stridxs_map[idx] = tgt_idx
+        pass
+    return stridxs_map
+
+
 ## \biref Redirect types of all code in given DEXFile_linked.
-def dexfile_redirect_types(dex, typeidxs_redir, methods_redir,
-                           excludes=set([])):
+def dexfile_redirect_indices(dex, typeidxs_redir, methods_redir, stridxs_redir,
+                             excludes=set([])):
     for classdef in dex.classDefs.items:
         typeid = classdef.classIdx
         idx = dex.get_idx_typeid(typeid)
         if idx in excludes:
             continue
-        class_redirect_types(dex, classdef, typeidxs_redir, methods_redir)
+        class_redirect_indices(dex, classdef, typeidxs_redir, methods_redir,
+                               stridxs_redir)
         pass
     pass
 
 
 ## \brief Redirect types for code of types specified by given indices.
-def dexfile_redirect_types_typeidxs(dex, typeidxs_redir, methodidxs_redir,
-                                    typeidxs):
+def dexfile_redirect_indices_typeidxs(dex, typeidxs_redir, methodidxs_redir,
+                                      stridxs_redir, typeidxs):
     typeidxs = set(typeidxs)
     for classdef in dex.classDefs.items:
         typeid = classdef.classIdx
         idx = dex.get_idx_typeid(typeid)
         if idx not in typeidxs:
             continue
-        class_redirect_types(dex, classdef, typeidxs_redir, methodidxs_redir)
+        class_redirect_indices(dex, classdef, typeidxs_redir,
+                               methodidxs_redir, stridxs_redir)
         pass
     pass
 
@@ -649,10 +681,14 @@
                                               relative_typeids)
     methodidxs_redir = \
         make_methodidxs_redir_map(dex_src, dex_dst, typeidxs_redir)
+
+    stridxs_redir = \
+        make_stridxs_redir_map(dex_src, dex_dst)
     
-    dexfile_redirect_types_typeidxs(dex_dst, typeidxs_redir,
-                                    methodidxs_redir,
-                                    typeidxs_redir.values())
+    dexfile_redirect_indices_typeidxs(dex_dst, typeidxs_redir,
+                                      methodidxs_redir,
+                                      stridxs_redir,
+                                      typeidxs_redir.values())
     pass
 
 
@@ -676,6 +712,31 @@
     return injected_classdefs
 
 
+## \brief Redirect all references of given class and its methods.
+#
+# Redirect all references of given class and its methods to target class.
+#
+def redirect_type(dex, src_classname, tgt_classname, exclude_classnames):
+    src_typeid = dex.find_typeid_name(src_classname)
+    src_typeidx = dex.get_idx_typeid(src_typeid)
+    tgt_typeid = dex.find_typeid_name(tgt_classname)
+    tgt_typeidx = dex.get_idx_typeid(tgt_typeid)
+    typeidxs_redir = {src_typeidx: tgt_typeidx}
+    
+    methodidxs_redir = \
+        make_methodidxs_redir_map(dex, dex, typeidxs_redir)
+
+    stridxs_redir = {}
+    
+    ex_typeids = [dex.find_typeid_name(name)
+                   for name in exclude_classnames]
+    ex_typeidxs = [dex.get_idx_typeid(typeid)
+                   for typeid in ex_typeids]
+    dexfile_redirect_indices(dex, typeidxs_redir, methodidxs_redir,
+                             stridxs_redir, excludes=ex_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,
@@ -687,20 +748,9 @@
     inj_classdef = src_linked.find_class_name(inj_classname)
     injected_classdefs = inject_classdefs(dst_linked, src_linked,
                                           [inj_classdef])
-    
-    redir_typeid = dst_linked.find_typeid_name(redir_classname)
-    redir_typeidx = dst_linked.get_idx_typeid(redir_typeid)
-    inj_typeid = dst_linked.find_typeid_name(inj_classname)
-    inj_typeidx = dst_linked.get_idx_typeid(inj_typeid)
-    typeidxs_redir = {redir_typeidx: inj_typeidx}
-    
-    methodidxs_redir = \
-        make_methodidxs_redir_map(dst_linked, dst_linked, typeidxs_redir)
-    
-    injected_typeidxs = [dst_linked.get_idx_classdef(classdef)
-                         for classdef in injected_classdefs]
-    dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir,
-                           excludes=injected_typeidxs)
+    excludes = [dst_linked.get_classdef_name(classdef)
+                for classdef in injected_classdefs]
+    redirect_type(dst_linked, redir_classname, inj_classname, excludes)
     pass
 
 
@@ -711,13 +761,16 @@
 # injection, this function create maps for remapping indices mentioned
 # in the code.
 # 
-def _make_idx_map(saved_typeids, saved_methodids,
-                  new_typeids, new_methodids):
+def _make_idx_map(saved_typeids, saved_methodids, saved_strids,
+                  new_typeids, new_methodids, new_strids):
     methodidxs_map = dict([(idx, new_methodids.index(methodid))
                            for idx, methodid in enumerate(saved_methodids)])
     typeidxs_map = dict([(idx, new_typeids.index(typeid))
                          for idx, typeid in enumerate(saved_typeids)])
-    return typeidxs_map, methodidxs_map
+    stridxs_map = dict([(idx, new_strids.index(strid))
+                        for idx, strid in enumerate(saved_strids)])
+    
+    return typeidxs_map, methodidxs_map, stridxs_map
 
 
 ## \brief Sort sorted arrays and remapping indices for code blocks.
@@ -730,16 +783,19 @@
     
     saved_typeids = list(dex_linked.typeIds.items)
     saved_methodids = list(dex_linked.methodIds.items)
+    saved_strids = list(dex_linked.stringIds.items)
     
     dex_sort_sorted_arrays(dex_linked)
 
     new_typeids = dex_linked.typeIds.items
     new_methodids = dex_linked.methodIds.items
-    typeidxs_map, methodidxs_map = \
-        _make_idx_map(saved_typeids, saved_methodids, \
-                          new_typeids, new_methodids)
+    new_strids = dex_linked.stringIds.items
+    typeidxs_map, methodidxs_map, stridxs_map = \
+        _make_idx_map(saved_typeids, saved_methodids, saved_strids, \
+                          new_typeids, new_methodids, new_strids)
     
-    dexfile_redirect_types(dex_linked, typeidxs_map, methodidxs_map)
+    dexfile_redirect_indices(dex_linked, typeidxs_map, methodidxs_map,
+                             stridxs_map)
     pass
 
 
--- a/paraspace/tests/injection_test.py	Mon Aug 15 11:13:56 2011 +0800
+++ b/paraspace/tests/injection_test.py	Mon Aug 15 15:25:39 2011 +0800
@@ -106,7 +106,7 @@
 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.injection import dexfile_redirect_indices
     from paraspace.injection import make_methodidxs_redir_map
     from paraspace import dalvik_opcodes
     
@@ -160,8 +160,8 @@
     methods_redir = make_methodidxs_redir_map(helloworld_linked,
                                               helloworld_linked,
                                               types_redir)
-    dexfile_redirect_types(helloworld_linked, types_redir,
-                           methods_redir, excludes)
+    dexfile_redirect_indices(helloworld_linked, types_redir,
+                             methods_redir, excludes)
 
     for code in helloworld_linked.codeItems.items:
         op_vectors = dalvik_opcodes.decode_insn_blk(code.insns.data)
@@ -299,7 +299,7 @@
     from paraspace.dex_deptracker import prepare_dep_decls
     from paraspace.injection import inject_classdefs
     from paraspace.injection import make_methodidxs_redir_map
-    from paraspace.injection import dexfile_redirect_types
+    from paraspace.injection import dexfile_redirect_indices
     from paraspace import dalvik_opcodes
     from paraspace.dexfile import DEXFile_linked
     
@@ -366,8 +366,9 @@
         make_methodidxs_redir_map(helloworld_linked, \
                                       helloworld_linked, \
                                       typeidxs_redir_map)
-    dexfile_redirect_types(helloworld_linked, typeidxs_redir_map,
-                           methodidxs_redir_map, excludes=[fakefile_typeidx])
+    dexfile_redirect_indices(helloworld_linked, typeidxs_redir_map,
+                             methodidxs_redir_map, {},
+                             excludes=[fakefile_typeidx])
 
     cloning_initdef = \
         helloworld_linked.find_method_name_proto('<init>', \