diff paraspace/dex_deptracker.py @ 53:705356005362

Fix bug of install marker through ref
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 22 Jun 2011 20:22:03 +0800
parents 67aa8ca8fff3
children 870312703ba1
line wrap: on
line diff
--- a/paraspace/dex_deptracker.py	Tue Jun 21 18:36:45 2011 +0800
+++ b/paraspace/dex_deptracker.py	Wed Jun 22 20:22:03 2011 +0800
@@ -10,6 +10,10 @@
     obj = dexfile
     parent = None
     for name in name_path.split('.'):
+        while isinstance(obj, _marker):
+            obj = obj.back_type
+            pass
+        
         if isinstance(parent, dexfile.array) and obj == list:
             # array.items.<num>
             obj = parent.child_type
@@ -253,6 +257,20 @@
     return dex_types
 
 
+def _all_dex_type_to_names():
+    def check_marker(value, name):
+        while isinstance(value, _marker):
+            value = value.back_type
+            pass
+        return value, name
+    
+    dex_types = dict([check_marker(value, name)
+                      for name, value in dexfile.__dict__.items()
+                      if name.startswith('_DEX_')])
+    dex_types[dexfile.DEXFile] = 'DEXFile'
+    return dex_types
+
+
 def collect_all_dep_decls():
     dex_types = _all_dex_types()
 
@@ -267,6 +285,10 @@
 
 class _marker(dexfile.null_relocatable):
     back_type = None
+
+    def set_marker(self, obj, off):
+        raise NotImplementedError, \
+            'The marker does not implement set_marker()'
     pass
 
 class _uid_marker(_marker):
@@ -283,7 +305,8 @@
             value.data_uid = _uid_marker.uid_seq
         except AttributeError:
             raise AttributeError, \
-                'can not depend on non-instance (%s)' % (self.name_path)
+                'can not depend on non-instance (%s/%s)' % \
+                (self.name_path, repr(value))
         _uid_marker.uid_seq = _uid_marker.uid_seq + 1
         
         return value
@@ -315,6 +338,9 @@
 
     def __call__(self, *args, **kws):
         return self.back_type(*args, **kws)
+
+    def set_marker(self, obj, off):
+        pass
     pass
 
 
@@ -336,6 +362,10 @@
         assert obj.data_offset not in id_item_map
         id_item_map[obj.data_offset] = obj
         pass
+
+    def set_marker(self, obj, off):
+        obj.data_offset = off
+        pass
     pass
 
 
@@ -387,6 +417,10 @@
             pass
         
         raise RuntimeError, 'can not find relative offset depend'
+
+    def set_marker(self, obj, off):
+        obj.data_offset = off
+        pass
     pass
 
 
@@ -411,13 +445,17 @@
             id_item_map[idx] = item
             pass
         pass
+
+    def set_marker(self, obj, off):
+        pass
     pass
 
 
 def _install_offset_marker(name_path):
     obj, parent = _resolve_name_path(name_path)
-    while isinstance(parent, dexfile.ref):
-        obj, parent = _resolve_name_path(parent.target_path)
+    while isinstance(obj, dexfile.ref):
+        name_path = obj.target_path
+        obj, parent = _resolve_name_path(name_path)
         pass
     marker = _offset_marker(obj, name_path)
     name = name_path.split('.')[-1]
@@ -427,8 +465,9 @@
 
 def _install_rel_offset_marker(name_path):
     obj, parent = _resolve_name_path(name_path)
-    while isinstance(parent, dexfile.ref):
-        obj, parent = _resolve_name_path(parent.target_path)
+    while isinstance(obj, dexfile.ref):
+        name_path = obj.target_path
+        obj, parent = _resolve_name_path(name_path)
         pass
     marker = _rel_offset_marker(obj, name_path)
     name = name_path.split('.')[-1]
@@ -438,8 +477,9 @@
 
 def _install_uid_marker(name_path):
     obj, parent = _resolve_name_path(name_path)
-    while isinstance(parent, dexfile.ref):
-        obj, parent = _resolve_name_path(parent.target_path)
+    while isinstance(obj, dexfile.ref):
+        name_path = obj.target_path
+        obj, parent = _resolve_name_path(name_path)
         pass
     marker = _uid_marker(obj, name_path)
     name = name_path.split('.')[-1]
@@ -449,8 +489,9 @@
 
 def _install_idx_marker(name_path):
     obj, parent = _resolve_name_path(name_path)
-    while isinstance(parent, dexfile.ref):
-        obj, parent = _resolve_name_path(parent.target_path)
+    while isinstance(obj, dexfile.ref):
+        name_path = obj.target_path
+        obj, parent = _resolve_name_path(name_path)
         pass
     marker = _idx_marker(obj, name_path)
     name = name_path.split('.')[-1]
@@ -630,6 +671,9 @@
             continue
         
         marker, dummy_parent = _resolve_name_path(name_path)
+        while isinstance(marker, dexfile.ref):
+            marker, dummy = _resolve_name_path(marker.target_path)
+            pass
         marker.link_prepare(obj, name_path, parents, markers_info)
         pass
 
@@ -677,6 +721,8 @@
 
 
 def _build_depon_dep_map(all_dep_decls):
+    from itertools import chain
+    
     def _build_sub_depon_dep(from_path, dep):
         depon1 = dep[1]
         sub = [(depon1, from_path)]
@@ -692,32 +738,55 @@
                       for from_path, dep in all_dep_decls.items()]
     depon_dep_lst = chain(*depon_dep_lsts)
     depon_dep_map = dict(depon_dep_lst)
-    pass
+    return depon_dep_map
 
 
 def update_offset(dexroot, all_dep_decls):
     from dexfile import man_off
+
+    depon_dep_map = _build_depon_dep_map(all_dep_decls)
+    dex_type_names = _all_dex_type_to_names()
+
+    def make_path(obj, path_parts, obj_name):
+        if isinstance(obj, dexfile.composite):
+            type_name = dex_type_names[obj.__class__]
+            return [type_name]
+        return path_parts + [obj_name]
     
     moff = man_off(0)
-    queue = [dexroot]
+    queue = [(dexroot, ['DEXFile'])]
     
     while queue:
-        obj = queue.pop()
-        if isinstance(obj, _marker):
-            obj.set_marker(moff())
+        obj, path_parts = queue.pop()
+        name_path = '.'.join(path_parts)
+        
+        if name_path in depon_dep_map:
+            marker, dummy = _resolve_name_path(name_path)
+            marker.set_marker(obj, moff())
             pass
-        if isinstance(obj, dexfile.relocatable):
-            moff(obj.sizeof())
-            pass
+
+        if isinstance(obj, (tuple, list)):
+            attrs = [(elt, path_parts + [str(idx)])
+                     for idx, elt in enumerate(obj)]
+            attrs.reverse()
+            queue = queue + attrs
+            continue
         
         if isinstance(obj, dexfile.ref):
             continue
+
         if not isinstance(obj, dexfile.relocatable):
+            clazz, parent = _resolve_name_path(name_path)
+            moff(clazz.sizeof(obj))
             continue
         
-        children = list(obj.children())
-        attrs = [_dex_tree_get_child(obj, child)
-                 for child in children]
+        moff(obj.sizeof(obj))
+        
+        children = obj.children()
+        attr_n_names = [(_dex_tree_get_child(obj, child_name), child_name)
+                      for child_name in children]
+        attrs = [(attr, make_path(attr, path_parts, attr_name))
+                 for attr, attr_name in attr_n_names]
         attrs.reverse()
         queue = queue + attrs
         pass