changeset 132:75a31967ebee

Following the ref in resotre_dependencies()
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 09 Aug 2011 15:30:45 +0800
parents 044bfc415577
children ddf8a20ecc4b
files Doxyfile paraspace/dex_deptracker.py paraspace/dexfile.py paraspace/tests/dexfile_test.py paraspace/tests/injection_test.py
diffstat 5 files changed, 126 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/Doxyfile	Tue Aug 09 11:47:43 2011 +0800
+++ b/Doxyfile	Tue Aug 09 15:30:45 2011 +0800
@@ -303,7 +303,7 @@
 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class
 # will be included in the documentation.
 
-EXTRACT_PRIVATE        = NO
+EXTRACT_PRIVATE        = YES
 
 # If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
--- a/paraspace/dex_deptracker.py	Tue Aug 09 11:47:43 2011 +0800
+++ b/paraspace/dex_deptracker.py	Tue Aug 09 15:30:45 2011 +0800
@@ -218,6 +218,13 @@
     pass
 
 
+class _travel_rel_node(object):
+    obj = None
+    parents = None
+    name_path = None
+    origin_path = None
+    pass
+
 ## \brief Travel the tree of relocatable objects and their attributes.
 #
 # \param skip_func is a function that returns true for skip a subtree.
@@ -225,13 +232,25 @@
 # \ref skip_func is called for every relocatable and their attributes
 # to determines if visiting the object and subtree.
 #
+# NOTE:
+# You never know what information you will use later.  Use an object
+# instead of tuple to carry information.  You can extend states an object
+# later.  But, it is hard to extend a tuple.  That is why _travel_rel_node
+# instances are used to replace tuples, here.
+#
 def _travel_dex_relocatable(root_obj, parents=[], skip_func=None):
-    stk = [(root_obj, parents, root_obj.__class__.__name__)]
+    root_node = _travel_rel_node()
+    root_node.obj = root_obj
+    root_node.parents = parents
+    root_node.name_path = root_obj.__class__.__name__
+    root_node.origin_path = root_obj.__class__.__name__
+    stk = [root_node]
     
     def make_travel_info(obj, obj_name, child_name, parents):
         child_parents = parents + [obj]
         child_obj = _dex_tree_get_child(obj, child_name)
         child_path = obj_name + '.' + child_name
+        origin_path = child_path
         
         child_clazz, dummy = _resolve_name_path(child_path)
         if not isinstance(child_clazz, dexfile.depend):
@@ -239,13 +258,21 @@
                 child_path = child_obj.__class__.__name__
                 pass
             pass
-        return (child_obj, child_parents, child_path)
+
+        node = _travel_rel_node()
+        node.obj = child_obj
+        node.parents = child_parents
+        node.name_path = child_path
+        node.origin_path = origin_path
+        
+        return node
     
     while stk:
-        obj, parents, obj_name = stk.pop(0)
+        node = stk.pop(0)
+        obj, parents, obj_name = node.obj, node.parents, node.name_path
         if skip_func and skip_func(obj, parents, obj_name):
             continue
-        yield (obj, parents, obj_name)
+        yield node
         
         if isinstance(obj, list):
             children = [make_travel_info(obj, obj_name, repr(idx), parents)
@@ -622,8 +649,10 @@
             pass
         return obj
     
-    for obj, parents, name_path in \
-            _travel_dex_relocatable(root_obj):
+    for node in _travel_dex_relocatable(root_obj):
+        obj = node.obj
+        parents = node.parents
+        
         if isinstance(obj, dexfile._objs_asso):
             rev_parents = list(parents)
             rev_parents.reverse()
@@ -652,6 +681,11 @@
     raise TypeError, 'can not find a prent of %s type' % (repr(clazz))
 
 
+## \brief Split a name path into class and attribute parts.
+#
+# \param name_path is a name path string.
+# \return a tuple in pattern (class name, attribute name)
+#
 def _split_name_path_clazz_attr(name_path):
     idx = name_path.index('.')
     if idx >= 0:
@@ -667,8 +701,10 @@
 ## \brief Setup value of refs.
 #
 def _build_refs(root_obj):
-    for obj, parents, name_path in \
-            _travel_dex_relocatable(root_obj):
+    for node in _travel_dex_relocatable(root_obj):
+        name_path = node.name_path
+        parents = node.parents
+        
         if not parents:
             continue
 
@@ -710,8 +746,11 @@
     #
     # Collect marked objects
     #
-    for obj, parents, name_path in \
-            _travel_dex_relocatable(root_obj):
+    for node in _travel_dex_relocatable(root_obj):
+        obj = node.obj
+        parents = node.parents
+        name_path = node.name_path
+        
         if name_path not in markers_info:
             continue
         
@@ -725,8 +764,10 @@
     #
     # Link depend source to marked target
     #
-    for obj, parents, name_path in \
-            _travel_dex_relocatable(root_obj):
+    for node in _travel_dex_relocatable(root_obj):
+        obj = node.obj
+        parents = node.parents
+        name_path = node.name_path
         if name_path not in all_dep_decls:
             continue
 
@@ -801,7 +842,8 @@
 def dex_sort_sorted_arrays(dex):
     assert isinstance(dex, dexfile.DEXFile_linked)
     
-    for obj, parents, name_path in _travel_dex_relocatable(dex):
+    for node in _travel_dex_relocatable(dex):
+        obj = node.obj
         if isinstance(obj, dexfile.array_sorted):
             obj.items.sort()
             pass
@@ -973,9 +1015,33 @@
 #
 def restore_dependencies(dexroot, all_dep_decls):
     update_offset(dexroot, all_dep_decls)
+
+    def set_child(node, value):
+        vtype, dummy = _resolve_name_path(node.origin_path)
+        while isinstance(vtype, dexfile.null_relocatable):
+            vtype = vtype.back_type
+            pass
+        
+        if isinstance(vtype, dexfile.ref):
+            name_path = vtype.target_path
+            print 'REF', node.origin_path, name_path, '0x%x' % value
+        else:
+            name_path = node.origin_path
+            pass
+
+        parent_clazzname, attr_name = _split_name_path_clazz_attr(name_path)
+        parent_clazz, dummy = _resolve_name_path(parent_clazzname)
+        parent_clazz = _skip_marker_clazz(parent_clazz)
+        clazz_parent = _find_parent_of_clazz(parent_clazz, node.parents)
+        
+        _dex_tree_set_child(clazz_parent, attr_name, value)
+        pass
     
-    for obj, parents, name_path in \
-            _travel_dex_relocatable(dexroot):
+    for node in _travel_dex_relocatable(dexroot):
+        obj = node.obj
+        parents = node.parents
+        name_path = node.name_path
+        
         if name_path not in all_dep_decls:
             continue
 
@@ -989,17 +1055,13 @@
             relative_to = _rel_offset_marker.find_depon(dep[2], parents)
             depon = obj
             rel_off = depon.data_offset - relative_to.data_offset
-
-            name = name_path.split('.')[-1]
-            _dex_tree_set_child(imm_parent, name, rel_off)
+            set_child(node, rel_off)
         elif dep_type == dexfile.depend_off:
             depon = obj
-            name = name_path.split('.')[-1]
-            _dex_tree_set_child(imm_parent, name, depon.data_offset)
+            set_child(node, depon.data_offset)
         elif dep_type == dexfile.depend_idx:
             depon = obj
-            name = name_path.split('.')[-1]
-            _dex_tree_set_child(imm_parent, name, depon.data_idx)
+            set_child(node, depon.data_idx)
         else:
             raise TypeError, 'invalid depend type %s' % (repr(dep_type))
         pass
--- a/paraspace/dexfile.py	Tue Aug 09 11:47:43 2011 +0800
+++ b/paraspace/dexfile.py	Tue Aug 09 15:30:45 2011 +0800
@@ -533,6 +533,28 @@
         attr_path = '.'.join(pparts[1:])
         value = _dex_tree_get_child(parent, attr_path)
         return value
+
+    def set_value(self, value, parents):
+        from paraspace.dex_deptracker import _resolve_name_path
+        from paraspace.dex_deptracker import _dex_tree_get_child
+        
+        pparts = self.target_path.split('.')
+        clazz_name = pparts[0]
+        clazz, dummy = _resolve_name_path(clazz_name)
+        
+        rev_parents = list(parents)
+        rev_parents.reverse()
+        
+        for parent in rev_parents:
+            if isinstance(parent, clazz):
+               break
+            pass
+        else:
+            raise ValueError, 'can not find %s' % (self.target_path)
+
+        attr_path = '.'.join(pparts[1:])
+        _dex_tree_set_child(parent, attr_path, value)
+        pass
     pass
 
 
--- a/paraspace/tests/dexfile_test.py	Tue Aug 09 11:47:43 2011 +0800
+++ b/paraspace/tests/dexfile_test.py	Tue Aug 09 15:30:45 2011 +0800
@@ -118,7 +118,7 @@
     dexroot = dex.typeLists.items[0].value
 
     itr = _travel_dex_relocatable(dexroot)
-    pathes = [v[2] for v in itr]
+    pathes = [node.name_path for node in itr]
     assert len(pathes) == 6
     assert '_DEX_TypeList' in pathes
     assert '_DEX_TypeList.num' in pathes
--- a/paraspace/tests/injection_test.py	Tue Aug 09 11:47:43 2011 +0800
+++ b/paraspace/tests/injection_test.py	Tue Aug 09 15:30:45 2011 +0800
@@ -425,6 +425,9 @@
 # It is possible restore_dependencies() does not following \ref ref
 # object to set offset value on referenced attribute.
 #
+# It is also possible dexfile_insert_classdefs_relative() does not
+# put injected objects into lists properly.
+#
 def map_verify_error_test():
     from paraspace.dex_deptracker import prepare_dep_decls
     from paraspace.injection import inject_redir
@@ -451,7 +454,7 @@
                  hello_linked, 'Ljava/io/File;', all_dep_decls)
 
     for idx, item in enumerate(hello_linked.maps.items.items):
-        if item.type != dexfile._DEX_MapItem.name_to_types['kDexTypeTypeList']:
+        if item.type == dexfile._DEX_MapItem.name_to_types['kDexTypeTypeList']:
             break
         pass
     else:
@@ -464,20 +467,28 @@
     for idx, protoid in enumerate(hello_linked.protoIds.items):
         off = protoid.parametersOff
         try:
-            assert off >= typelist_start
-            assert off < typelist_stop
+            if off != 0:
+                assert off >= typelist_start
+                assert off < typelist_stop
+                pass
+            pass
         except:
-            print 'ERROR: protoid idx @', idx, protoid
+            print 'ERROR: protoid idx@%d %s 0x%x' % (idx, repr(protoid), off)
+            print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop)
             raise
         pass
 
     for idx, classdef in enumerate(hello_linked.classDefs.items):
         off = classdef.interfacesOff
         try:
-            assert off >= typelist_start
-            assert off < typelist_stop
+            if off != 0:
+                assert off >= typelist_start
+                assert off < typelist_stop
+                pass
+            pass
         except:
-            print 'ERROR: classdef idx @', idx, classdef
+            print 'ERROR: classdef idx@%d %s 0x%x' % (idx, repr(classdef), off)
+            print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop)
             raise
         pass
     pass