changeset 58:c2a4921ec83b

Fix issue misbehavior for dependency when update_offset() - If value of a depenend object is linked to its depend-on, it's size should be computed with value from depend-on. But, it was not. - It is fixed by awaring linking of depend objects in dex_deptracker.update_offset() and depend classes.
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 26 Jun 2011 21:34:52 +0800
parents fa8fe7d714b9
children 08c220217076
files paraspace/dex_deptracker.py paraspace/dexfile.py paraspace/tests/dexfile_test.py
diffstat 3 files changed, 65 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dex_deptracker.py	Sat Jun 25 08:16:16 2011 +0800
+++ b/paraspace/dex_deptracker.py	Sun Jun 26 21:34:52 2011 +0800
@@ -6,13 +6,18 @@
                dexfile.switch)
 
 
+def _skip_marker_clazz(marker):
+    while isinstance(marker, _marker):
+        marker = marker.back_type
+        pass
+    return marker
+
+
 def _resolve_name_path(name_path):
     obj = dexfile
     parent = None
     for name in name_path.split('.'):
-        while isinstance(obj, _marker):
-            obj = obj.back_type
-            pass
+        obj = _skip_marker_clazz(obj)
         
         if isinstance(parent, dexfile.array) and obj == list:
             # array.items.<num>
@@ -53,12 +58,7 @@
             return False
         return True
     
-    #
-    # pass throught markers
-    #
-    while isinstance(clazz, _marker):
-        clazz = clazz.back_type
-        pass
+    clazz = _skip_marker_clazz(clazz)
     
     travel_queue = [(getattr(clazz, attr_name), name_path + '.' + attr_name)
                     for attr_name in dir(clazz)
@@ -270,9 +270,7 @@
 
 def _all_dex_type_to_names():
     def check_marker(value, name):
-        while isinstance(value, _marker):
-            value = value.back_type
-            pass
+        value = _skip_marker_clazz(value)
         return value, name
     
     dex_types = dict([check_marker(value, name)
@@ -454,6 +452,7 @@
             pass
         for idx, item in enumerate(obj.items):
             id_item_map[idx] = item
+            item.data_idx = idx
             pass
         pass
 
@@ -720,7 +719,7 @@
             depon1 = markers_info[dep[1]][offset]
 
             name = name_path.split('.')[-1]
-            _dex_tree_set_child(imm_parent, name, (depon1, depon2))
+            _dex_tree_set_child(imm_parent, name, depon1)
         elif dep_type == dexfile.depend_off:
             depon_name_path = dep[1]
             depon = markers_info[depon_name_path][obj]
@@ -771,21 +770,25 @@
     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):
+    def make_path(obj, parent_path, obj_name):
+        name_path = parent_path + '.' + obj_name
+        
         if isinstance(obj, dexfile.composite):
-            type_name = dex_type_names[obj.__class__]
-            return [type_name]
-        return path_parts + [obj_name]
+            if name_path not in all_dep_decls:
+                type_name = dex_type_names[obj.__class__]
+                return type_name
+            pass
+        return name_path
     
     moff = man_off(0)
-    queue = [(dexroot, ['DEXFile'])]
+    queue = [(dexroot, 'DEXFile')]
     
     while queue:
-        obj, path_parts = queue.pop()
-        name_path = '.'.join(path_parts)
+        obj, name_path = queue.pop()
         
-        obj_clazz = _resolve_name_path(name_path)
+        obj_clazz, parent_clazz = _resolve_name_path(name_path)
         if isinstance(obj_clazz, dexfile.depend):
+            moff(obj_clazz.sizeof(obj))
             continue
         
         if name_path in depon_dep_map:
@@ -802,7 +805,7 @@
             pass
 
         if isinstance(obj, (tuple, list)):
-            attrs = [(elt, make_path(elt, path_parts, str(idx)))
+            attrs = [(elt, make_path(elt, name_path, str(idx)))
                      for idx, elt in enumerate(obj)]
             attrs.reverse()
             queue = queue + attrs
@@ -816,12 +819,10 @@
             moff(clazz.sizeof(obj))
             continue
         
-        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))
+        attrs = [(attr, make_path(attr, name_path, attr_name))
                  for attr, attr_name in attr_n_names]
         attrs.reverse()
         queue = queue + attrs
--- a/paraspace/dexfile.py	Sat Jun 25 08:16:16 2011 +0800
+++ b/paraspace/dexfile.py	Sun Jun 26 21:34:52 2011 +0800
@@ -755,6 +755,18 @@
         return v
 
     def sizeof(self, v):
+        from paraspace.dex_deptracker import _resolve_name_path
+        from paraspace.dex_deptracker import _skip_marker_clazz
+        
+        depon_clazz, dummy = _resolve_name_path(self.depend_on)
+        depon_clazz = _skip_marker_clazz(depon_clazz)
+        if type(depon_clazz) == type and \
+                isinstance(v, depon_clazz):
+            v = v.data_offset
+        elif type(depon_clazz) != type and \
+                isinstance(v, depon_clazz.__class__):
+            v = v.data_offset
+            pass
         v = self.back_type.sizeof(v)
         return v
 
@@ -793,6 +805,24 @@
 
 
 class depend_idx(depend):
+    def sizeof(self, v):
+        from paraspace.dex_deptracker import _resolve_name_path
+        from paraspace.dex_deptracker import _skip_marker_clazz
+        
+        depon_clazz, dummy = _resolve_name_path(self.depend_on)
+        depon_clazz = _skip_marker_clazz(depon_clazz)
+        do_child_clazz = depon_clazz.child_type # depon_clazz must be an array
+        
+        if type(do_child_clazz) == type and \
+                isinstance(v, do_child_clazz):
+            v = v.data_idx
+        elif type(do_child_clazz) != type and \
+                isinstance(v, do_child_clazz.__class__):
+            v = v.data_idx
+            pass
+        v = self.back_type.sizeof(v)
+        return v
+        pass
     pass
 
 
--- a/paraspace/tests/dexfile_test.py	Sat Jun 25 08:16:16 2011 +0800
+++ b/paraspace/tests/dexfile_test.py	Sun Jun 26 21:34:52 2011 +0800
@@ -59,6 +59,10 @@
     obj, parent = _resolve_name_path('_DEX_AnnotationMember_noname.value.' + 
                                      repr(key))
     assert isinstance(obj, dexfile.abs_value)
+
+    obj, parent = _resolve_name_path('_DEX_AnnotationSetItem.annotationOffs.'
+                                     'items.0')
+    assert isinstance(obj, dexfile.depend_off)
     pass
 
 
@@ -223,6 +227,9 @@
     
     code_item = dex.codeItems.items[0]
     assert code_item.debugInfoOff.__class__.__name__ == '_DEX_DebugInfoItem'
+
+    stringid = dex.stringIds.items[0]
+    assert isinstance(stringid.stringDataOff, dexfile._DEX_StringDataItem)
     pass
 
 
@@ -288,9 +295,10 @@
     offset1 = dex.typeLists.items[1].value.data_offset
     dex.typeLists.items[1].value.data_offset = 0
     
+    print 'update_offset()'
     update_offset(dex, all_dep_decls)
 
-    print dex.typeLists.items[0].value.data_offset
+    print dex.typeLists.items[0].value.data_offset, offset0
     assert dex.typeLists.items[0].value.data_offset == offset0
     assert dex.typeLists.items[1].value.data_offset == offset1
     pass