diff paraspace/dex_deptracker.py @ 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 52749d91cc22
children ddf8a20ecc4b
line wrap: on
line diff
--- 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