changeset 141:90690a001172

Fixing back to back association and encoding issue. - Fix problem of _deoptimize_classdata() and _optimize_classdata() - They don't deoptimize or optimize field indices for _DEX_ClassData.
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 14 Aug 2011 21:18:48 +0800
parents d4e794249b0f
children 50d09eba5166
files paraspace/dex_deptracker.py paraspace/dexfile.py paraspace/tests/dex_deptracker_test.py paraspace/tests/injection_test.py
diffstat 4 files changed, 322 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dex_deptracker.py	Thu Aug 11 09:20:46 2011 +0800
+++ b/paraspace/dex_deptracker.py	Sun Aug 14 21:18:48 2011 +0800
@@ -162,6 +162,11 @@
             elif isinstance(value_type, dexfile.depend_idx):
                 depend_name = value_type.depend_on
                 dep_decls[from_name] = (dexfile.depend_idx, depend_name)
+            elif isinstance(value_type, dexfile.depend_idx_rel):
+                depend_name = value_type.depend_on
+                relative_to = value_type.relative_to
+                dep_decls[from_name] = (dexfile.depend_idx_rel, depend_name,
+                                        relative_to)
                 pass
             pass
         pass
@@ -364,12 +369,12 @@
         
         return value
 
-    def sizeof(self, value):
-        sz = self.back_type.sizeof(value)
+    def sizeof(self, value, parents):
+        sz = self.back_type.sizeof(value, parents)
         return sz
 
-    def compute_size(self, back_obj):
-        self.back_type.compute_size(back_obj)
+    def compute_size(self, back_obj, parents):
+        self.back_type.compute_size(back_obj, parents)
         pass
 
     def to_str(self, back_obj):
@@ -588,6 +593,13 @@
                 _install_idx_marker(name_path)
                 pass
             pass
+        elif dep_type == dexfile.depend_idx_rel:
+            name_path = dep[1]
+            if name_path not in all_markers:
+                all_markers.add(name_path)
+                _install_idx_marker(name_path)
+                pass
+            pass
         else:
             raise TypeError, 'Invalid type of depend %s' % (repr(dep_type))
         pass
@@ -643,31 +655,11 @@
 
 
 def _build_associations(root_obj):
-    def get_elts(parent, path):
-        parts = path.split('.')
-        obj = parent
-        for part in parts:
-            obj = _dex_tree_get_child(obj, part)
-            if isinstance(obj, dexfile.cond) and not obj.is_true:
-                return ()
-            pass
-        return 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()
-            for parent in rev_parents:
-                if isinstance(parent, dexfile.composite):
-                    break
-                pass
-            
-            left_elts = get_elts(parent, obj.left)
-            right_elts = get_elts(parent, obj.right)
-            obj.build_associations(left_elts, right_elts)
+            parent = _find_parent_of_clazz(dexfile.composite, node.parents)
+            obj.build_associations(parent)
             pass
         pass
     pass
@@ -721,7 +713,7 @@
             clazz = clazz.back_type
             pass
         
-        if isinstance(clazz, dexfile.ref):
+        if isinstance(clazz, dexfile.value_ref):
             pclazz_name, attr_name = _split_name_path_clazz_attr(name_path)
             if not attr_name:
                 raise ValueError, \
@@ -791,10 +783,20 @@
             _dex_tree_set_child(imm_parent, name, depon1)
         elif dep_type == dexfile.depend_off:
             depon_name_path = dep[1]
+            try:
+                depon = markers_info[depon_name_path][obj]
+            except:
+                print depon_name_path
+                raise
+            name = name_path.split('.')[-1]
+            _dex_tree_set_child(imm_parent, name, depon)
+        elif dep_type == dexfile.depend_idx:
+            depon_name_path = dep[1]
             depon = markers_info[depon_name_path][obj]
             name = name_path.split('.')[-1]
             _dex_tree_set_child(imm_parent, name, depon)
-        elif dep_type == dexfile.depend_idx:
+        elif dep_type == dexfile.depend_idx_rel:
+            # Value after _build_associations()
             depon_name_path = dep[1]
             depon = markers_info[depon_name_path][obj]
             name = name_path.split('.')[-1]
@@ -815,6 +817,26 @@
 #
 def _deoptimize_classdata(dexroot):
     for classdata in dexroot.classDatas.items:
+        fields = classdata.staticFields.items
+        if len(fields) > 1:
+            firstfield = fields[0]
+            lastidx = firstfield.fieldIdx
+            for field in fields[1:]:
+                field.fieldIdx = field.fieldIdx + lastidx
+                lastidx = field.fieldIdx
+                pass
+            pass
+        
+        fields = classdata.instanceFields.items
+        if len(fields) > 1:
+            firstfield = fields[0]
+            lastidx = firstfield.fieldIdx
+            for field in fields[1:]:
+                field.fieldIdx = field.fieldIdx + lastidx
+                lastidx = field.fieldIdx
+                pass
+            pass
+        
         methods = classdata.directMethods.items
         if len(methods) > 1:
             firstmethod = methods[0]
@@ -844,6 +866,28 @@
 #
 def _optimize_classdata(dexroot):
     for classdata in dexroot.classDatas.items:
+        fields = classdata.staticFields.items
+        if len(fields) > 1:
+            firstfield = fields[0]
+            lastidx = firstfield.fieldIdx
+            for field in fields[1:]:
+                save_idx = field.fieldIdx
+                field.fieldIdx = field.fieldIdx - lastidx
+                lastidx = save_idx
+                pass
+            pass
+        
+        fields = classdata.instanceFields.items
+        if len(fields) > 1:
+            firstfield = fields[0]
+            lastidx = firstfield.fieldIdx
+            for field in fields[1:]:
+                save_idx = field.fieldIdx
+                field.fieldIdx = field.fieldIdx - lastidx
+                lastidx = save_idx
+                pass
+            pass
+        
         methods = classdata.directMethods.items
         if len(methods) > 1:
             firstmethod = methods[0]
@@ -871,9 +915,9 @@
 
 def build_dependencies(dexroot, all_dep_decls):
     _deoptimize_classdata(dexroot)
-    _build_associations(dexroot)
     _build_refs(dexroot)
     _link_dependencies(dexroot, all_dep_decls)
+    _build_associations(dexroot)
     pass
 
 
@@ -930,6 +974,8 @@
 def update_offset(dexroot, all_dep_decls):
     from paraspace.dexfile import man_off
 
+    _build_associations(dexroot)
+    
     depon_dep_map = _build_depon_dep_map(all_dep_decls)
     dex_type_names = _all_dex_type_to_names()
 
@@ -951,13 +997,13 @@
         
         obj_clazz, parent_clazz = _resolve_name_path(name_path)
         if isinstance(obj_clazz, dexfile.depend):
-            obj_clazz.compute_size(obj)
-            moff(obj_clazz.sizeof(obj))
+            obj_clazz.compute_size(obj, [grand, parent])
+            moff(obj_clazz.sizeof(obj, [grand, parent]))
             continue
         
         if name_path in depon_dep_map:
             marker, dummy = _resolve_name_path(name_path)
-            while isinstance(marker, dexfile.ref):
+            while isinstance(marker, dexfile.value_ref):
                 marker, dummy = _resolve_name_path(marker.target_path)
                 try:
                     obj = obj[0]
@@ -984,8 +1030,8 @@
                 name = name_path.split('.')[-1]
                 _dex_tree_set_child(parent, name, obj)
                 pass
-            obj_clazz.compute_size(obj)
-            moff(obj_clazz.sizeof(obj))
+            obj_clazz.compute_size(obj, [grand, parent])
+            moff(obj_clazz.sizeof(obj, [grand, parent]))
             continue
         
         children = obj.children()
@@ -1038,7 +1084,7 @@
             pass
         pass
     
-    classdef_raw_size = dexfile.array.sizeof(dex.classDefs)
+    classdef_raw_size = dexfile.array.sizeof(dex.classDefs, [dex])
     header.dataOff = header.classDefsOff + classdef_raw_size
     header.dataSize = header.fileSize - header.dataOff
     pass
@@ -1052,10 +1098,12 @@
         attr_name = dexfile.DEXFile.block_defs[map_item.type]
         obj = getattr(dex, attr_name)
         
-        data_sz = obj.sizeof(obj)
+        data_sz = obj.sizeof(obj, [dex, dex.maps, dex.maps.items,
+                                   dex.maps.items.items])
         map_item.offset = moff(data_sz)
         if attr_name == 'maps':
-            padding_sz = dexfile.auto_align.sizeof(dex.maps.padding)
+            padding_sz = dexfile.auto_align.sizeof(dex.maps.padding,
+                                                   [dex, dex.maps])
             map_item.offset = map_item.offset + padding_sz
             pass
         
@@ -1070,7 +1118,7 @@
 
 def _sync_DEXFile_fields(dex):
     dex.compute_size()
-    dex.header.fileSize = dex.sizeof(dex)
+    dex.header.fileSize = dex.sizeof()
     
     _sync_dex_maps(dex)
     _sync_dex_header(dex)
@@ -1130,6 +1178,10 @@
         elif dep_type == dexfile.depend_idx:
             depon = obj
             set_child(node, depon.data_idx)
+        elif dep_type == dexfile.depend_idx_rel:
+            dep, dummy = _resolve_name_path(node.origin_path)
+            idx = dep.get_value(obj, parents)
+            set_child(node, idx)
         else:
             raise TypeError, 'invalid depend type %s' % (repr(dep_type))
         pass
--- a/paraspace/dexfile.py	Thu Aug 11 09:20:46 2011 +0800
+++ b/paraspace/dexfile.py	Sun Aug 14 21:18:48 2011 +0800
@@ -79,7 +79,15 @@
 
 
 def _uleb128_sz(v):
-    return len(_to_uleb128(v))
+    if v & ~0x3fff:
+        if v & 0xf0000000:
+            return 5
+        elif v & 0xfe00000:
+            return 4
+        return 3
+    if v & 0x3f80:
+        return 2
+    return 1
 
 
 def _leb128(data):
@@ -107,11 +115,11 @@
     return len(_to_leb128(v))
 
 
-def _compute_sz(o, _type):
+def _compute_sz(o, _type, parents):
     if hasattr(o, 'compute_size'):
-        _type.compute_size(o)
+        _type.compute_size(o, parents)
         pass
-    return _type.sizeof(o)
+    return _type.sizeof(o, parents)
 
 
 class _dex_type(object):
@@ -148,11 +156,11 @@
         obj.data = data[off:off + obj.data_size]
         return obj
 
-    def compute_size(self, v):
+    def compute_size(self, v, parents):
         v.data_size = len(v.data)
         pass
 
-    def sizeof(self, v):
+    def sizeof(self, v, parents):
         return v.data_size
 
     def to_str(self, v):
@@ -180,7 +188,7 @@
         return tap()
 
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 0
 
     @staticmethod
@@ -196,11 +204,11 @@
         return v
 
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 4
 
     @staticmethod
@@ -217,11 +225,11 @@
         return v
     
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 2
 
     @staticmethod
@@ -237,11 +245,11 @@
         return v
     
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 1
 
     @staticmethod
@@ -257,11 +265,11 @@
         return v
     
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 4
 
     @staticmethod
@@ -278,11 +286,11 @@
         return v
 
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 2
 
     @staticmethod
@@ -298,11 +306,11 @@
         return v
 
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return _uleb128_sz(v)
 
     @staticmethod
@@ -318,11 +326,11 @@
         return v
 
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return _leb128_sz(v)
 
     @staticmethod
@@ -347,11 +355,11 @@
         return self.recompute_align(off)
 
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
     
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return v
 
     @staticmethod
@@ -360,12 +368,6 @@
     pass
 
 
-def _get_sz(o):
-    if isinstance(o, relocatable):
-        return o.data_size
-    return o.__class__.sizeof(o)
-
-
 ## \biref Associate objects from two set of objects.
 #
 class _objs_asso(_dex_type):
@@ -380,21 +382,29 @@
     # elements.
     #
     def _update_refs(self, left_elt, right_elt):
-        lref = getattr(left_elt, self.left_ref)
-        if not isinstance(right_elt, lref.target_path):
-            raise TypeError, 'invalid target_path in left %s' % (repr(le))
+        from paraspace.dex_deptracker import _resolve_name_path
+        from paraspace.dex_deptracker import _dex_tree_set_child
+        from paraspace.dex_deptracker import _split_name_path_clazz_attr
         
-        rref = getattr(right_elt, self.right_ref)
-        if not isinstance(left_elt, rref.target_path):
-            raise TypeError, 'invalid target_path in right %s' % (repr(re))
+        lref, dummy = _resolve_name_path(self.left_ref)
+        if not isinstance(lref, ref):
+            raise TypeError, '%s must be a ref' % (self.left_ref)
+        rref, dummy = _resolve_name_path(self.right_ref)
+        if not isinstance(rref, ref):
+            raise TypeError, '%s must be a ref' % (self.right_ref)
         
-        new_lref = ref(lref.target_path)
-        new_lref.target = right_elt
-        setattr(left_elt, self.left_ref, new_lref)
+        clazzname, lattr = _split_name_path_clazz_attr(self.left_ref)
+        clazzname, rattr = _split_name_path_clazz_attr(self.right_ref)
+        
+        if left_elt is not None:
+            new_lref = lref.build_value_instance(right_elt)
+            _dex_tree_set_child(left_elt, lattr, new_lref)
+            pass
 
-        new_rref = ref(rref.target_path)
-        new_rref.target = left_elt
-        setattr(right_elt, self.right_ref, new_rref)
+        if right_elt is not None:
+            new_rref = lref.build_value_instance(left_elt)
+            _dex_tree_set_child(right_elt, rattr, new_rref)
+            pass
         pass
     
     ## \brief Assocate elements from left list to a respective right element.
@@ -407,14 +417,15 @@
     def parse(self, parent, data, off):
         return self
 
-    def sizeof(self, obj):
+    def sizeof(self, obj, parents):
         return 0
 
+    @staticmethod
     def to_str(self):
         return ''
 
     @staticmethod
-    def compute_size(self):
+    def compute_size(self, parents):
         pass
 
     def children(self):
@@ -439,7 +450,6 @@
     #
     def build_associations(self, parent):
         from paraspace.dex_deptracker import _dex_tree_get_child
-        from paraspace.dex_deptracker import _dex_tree_set_child
         from paraspace.dex_deptracker import _split_name_path_clazz_attr
         
         left_attr = _split_name_path_clazz_attr(self.left)
@@ -463,8 +473,6 @@
 #
 class back2back(_objs_asso):
     def __init__(self, left, left_ref, right_ref):
-        if not isinstance(left, array):
-            raise TypeError, 'back_type must be an array'
         self.left = left
         self.right = left
         self.left_ref = left_ref
@@ -473,7 +481,6 @@
 
     def build_associations(self, parent):
         from paraspace.dex_deptracker import _dex_tree_get_child
-        from paraspace.dex_deptracker import _dex_tree_set_child
         from paraspace.dex_deptracker import _split_name_path_clazz_attr
         
         dummy, attr = _split_name_path_clazz_attr(self.left)
@@ -481,11 +488,13 @@
         if not isinstance(target_array, array):
             raise TypeError, 'left of %x must be an array' % (repr(self))
 
-        left_ref_attr = _split_name_path_clazz_attr(self.left_ref)
-        right_ref_attr = _split_name_path_clazz_attr(self.right_ref)
-        for left, right in map(None, target_array[:-1], target_array[1:]):
-            _dex_tree_set_child(left, left_ref_attr, right)
-            _dex_tree_set_child(right, right_ref_attr, left)
+        items = target_array.items
+        if len(items) > 0:
+            self._update_refs(None, items[0])
+            self._update_refs(items[-1], None)
+            for left, right in map(None, items[:-1], items[1:]):
+                self._update_refs(left, right)
+                pass
             pass
         pass
     pass
@@ -499,13 +508,13 @@
         pass
 
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return v.data_size
 
     def to_str(self):
         pass
 
-    def compute_size(self):
+    def compute_size(self, parents):
         pass
 
     def children(self):
@@ -535,11 +544,11 @@
         pass
 
     @staticmethod
-    def sizeof(v):
+    def sizeof(v, parents):
         return 0
 
     @staticmethod
-    def compute_size(self):
+    def compute_size(self, parents):
         pass
 
     @staticmethod
@@ -551,6 +560,12 @@
 
     def children(self):
         return []
+
+    ## \brief Build a new instance with target value.
+    def build_value_instance(self, value):
+        vref = self.__class__(self.target_path)
+        vref.target = value
+        return vref
     pass
 
 
@@ -629,19 +644,20 @@
         
         def parse():
             item = obj.child_type.parse(parent, data, moff())
-            item_sz = obj.child_type.sizeof(item)
+            item_sz = obj.child_type.sizeof(item, [parent, self, items])
             moff(item_sz)
             return item
         
-        items = [parse() for i in range(nitem)]
+        items = []
+        items.extend([parse() for i in range(nitem)])
         
         obj.items = items
         obj.data_size = moff() - off
         return obj
 
     @staticmethod
-    def compute_size(self):
-        sizes = [_compute_sz(item, self.child_type)
+    def compute_size(self, parents):
+        sizes = [_compute_sz(item, self.child_type, parents)
                  for item in self.items]
         size = sum(sizes)
         self.data_size = size
@@ -663,6 +679,13 @@
 
 
 class array_relative(array):
+    def parse(self, parent, data, off):
+        nitem = parent
+        for name in self.count_name.split('.'):
+            nitem = getattr(nitem, name)
+            pass
+        obj = self.parse_nitem(parent, data, off, nitem)
+        return obj
     pass
 
 
@@ -690,18 +713,19 @@
             obj.parse_child(child_name, data, moff())
             child = getattr(obj, child_name)
             child_clazz = getattr(obj.__class__, child_name)
-            child_sz = child_clazz.sizeof(child)
+            child_sz = child_clazz.sizeof(child, [parent])
             moff(child_sz)
             pass
 
         obj.data_size = moff() - off
         return obj
 
-    def compute_size(self):
+    def compute_size(self, parents):
+        child_parents = parents + [self]
         children = [(getattr(self, child_name),
                      getattr(self.__class__, child_name))
                     for child_name in self.children()]
-        child_sizes = [_compute_sz(child, child_type)
+        child_sizes = [_compute_sz(child, child_type, child_parents)
                        for child, child_type in children]
         self.data_size = sum(child_sizes)
         pass
@@ -743,20 +767,20 @@
 
         obj = cond(self.condition, self.child_type)
         obj.value = value
-        obj.data_size = self.sizeof(obj)
+        obj.data_size = self.sizeof(obj, [parent])
         obj.is_true = is_true
         
         return obj
 
-    def sizeof(self, v):
+    def sizeof(self, v, parents):
         if v.value is None:
             return 0
-        return self.child_type.sizeof(v.value)
+        return self.child_type.sizeof(v.value, parents)
 
     @staticmethod
-    def compute_size(self):
+    def compute_size(self, parents):
         if self.is_true:
-            self.data_size = _compute_sz(self.value, self.child_type)
+            self.data_size = _compute_sz(self.value, self.child_type, parents)
         else:
             self.data_size = 0
             pass
@@ -811,17 +835,17 @@
         obj = switch(self.selector, self.map)
         obj.value = value
         obj.child_type = child_type
-        obj.data_size = self.sizeof(obj)
+        obj.data_size = self.sizeof(obj, [parent])
         obj._parent = parent
         return obj
     
     @staticmethod
-    def sizeof(v):
-        return v.child_type.sizeof(v.value)
+    def sizeof(v, parents):
+        return v.child_type.sizeof(v.value, parents)
 
     @staticmethod
-    def compute_size(self):
-        self.data_size = _compute_sz(self.value, self.child_type)
+    def compute_size(self, parents):
+        self.data_size = _compute_sz(self.value, self.child_type, parents)
         pass
 
     @staticmethod
@@ -846,10 +870,10 @@
         return self.value
     
     @staticmethod
-    def compute_size(v):
+    def compute_size(v, parents):
         pass
 
-    def sizeof(self, v):
+    def sizeof(self, v, parents):
         return 0
     
     @staticmethod
@@ -883,7 +907,7 @@
         v = self.back_type.parse(parent, data, off)
         return v
 
-    def sizeof(self, v):
+    def sizeof(self, v, parents):
         from paraspace.dex_deptracker import _resolve_name_path
         from paraspace.dex_deptracker import _skip_marker_clazz
         
@@ -896,11 +920,11 @@
                 isinstance(v, depon_clazz.__class__):
             v = v.data_offset
             pass
-        v = self.back_type.sizeof(v)
+        v = self.back_type.sizeof(v, parents)
         return v
 
-    def compute_size(self, child):
-        _compute_sz(child, self.back_type)
+    def compute_size(self, child, parents):
+        _compute_sz(child, self.back_type, parents)
         pass
 
     def to_str(self, child):
@@ -918,13 +942,13 @@
 
 
 class depend_off(depend):
-    def compute_size(self, child):
+    def compute_size(self, child, parents):
         pass
 
-    def sizeof(self, child):
+    def sizeof(self, child, parents):
         if isinstance(child, composite):
-            return self.back_type.sizeof(child.data_offset)
-        return self.back_type.sizeof(child)
+            return self.back_type.sizeof(child.data_offset, parents)
+        return self.back_type.sizeof(child, parents)
     pass
 
 
@@ -941,46 +965,72 @@
         v = super(depend_off_rel, self).parse(parent, data, off)
         return v
 
-    def compute_size(self, child):
+    def compute_size(self, child, parents):
         pass
 
-    def sizeof(self, child):
+    def sizeof(self, child, parents):
         if isinstance(child, composite):
             pivot = self._depon2_log[child] # depon2
             off_diff = child.data_offset - pivot.data_offset
-            return self.back_type.sizeof(off_diff)
-        return self.back_type.sizeof(child)
+            return self.back_type.sizeof(off_diff, parents)
+        return self.back_type.sizeof(child, parents)
     pass
 
 
 class depend_idx(depend):
-    def compute_size(self, child):
+    def compute_size(self, child, parents):
         pass
 
-    def sizeof(self, child):
+    def sizeof(self, child, parents):
         if isinstance(child, composite):
-            return self.back_type.sizeof(child.data_idx)
-        return self.back_type.sizeof(child)
+            return self.back_type.sizeof(child.data_idx, parents)
+        return self.back_type.sizeof(child, parents)
     pass
 
 
 class depend_idx_rel(depend):
+    relative_to = None
+    
     def __init__(self, relative_to, depend_on):
         super(depend_idx_rel, self).__init__(depend_on)
         self.relative_to = relative_to
         pass
-    
-    def compute_size(self, child):
+
+    def compute_size(self, child, parents):
         pass
 
-    def sizeof(self, child):
-        from paraspace.dex_deptracker import _dex_tree_set_child
-        
-        relative = _dex_tree_get_child([child], self.relative_to)
+    def sizeof(self, child, parents):
+        value = self.get_value(child, parents)
+        return self.back_type.sizeof(value, parents)
+
+    def get_value(self, child, parents):
+        from paraspace.dex_deptracker import _dex_tree_get_child
+        from paraspace.dex_deptracker import _split_name_path_clazz_attr
+        from paraspace.dex_deptracker import _find_parent_of_clazz
         
         if isinstance(child, composite):
-            return self.back_type.sizeof(child.data_idx - relative.data_idx)
-        return self.back_type.sizeof(child - relative)
+            clazz, attr = _split_name_path_clazz_attr(self.relative_to)
+            parent = parents[-1]
+            try:
+                relative = _dex_tree_get_child(parent, attr)
+            except:
+                relative = None
+                pass
+            # Following is a workaround for restore_dependencies().
+            # It is unncessary if restore_dependencies() construct a
+            # new tree.
+            if isinstance(relative, composite):
+                rel_idx = relative.data_idx
+            else:
+                rel_idx = relative
+                pass
+            
+            value = child.data_idx
+            if relative is not None:
+                value = value - rel_idx
+                pass
+            return value
+        return child
     pass
 
 
@@ -1220,35 +1270,51 @@
 
 
 class _DEX_Field(composite):
-    fieldIdx = depend_idx('DEXFile.fieldIds')(uleb128)
+    fieldIdx = depend_idx_rel('_DEX_Field.prev.target.fieldIdx',
+                              'DEXFile.fieldIds')(uleb128)
     accessFlags = uleb128
+    prev = ref('_DEX_Field')
+    next = ref('_DEX_Field')
 
-    child_names = 'fieldIdx accessFlags'.split()
+    child_names = 'fieldIdx accessFlags prev next'.split()
     pass
 
 
 class _DEX_Method(composite):
-    methodIdx = depend_idx('DEXFile.methodIds')(uleb128)
+    methodIdx = depend_idx_rel('_DEX_Method.prev.target.methodIdx',
+                               'DEXFile.methodIds')(uleb128)
     accessFlags = uleb128
     codeOff = uleb128
     codeOffRef = cond((lambda parent, data, off: parent.codeOff),
                       depend_off('_DEX_Code')
                       (value_ref('_DEX_Method.codeOff')))
+    prev = ref('_DEX_Method')
+    next = ref('_DEX_Method')
 
-    child_names = 'methodIdx accessFlags codeOff codeOffRef'.split()
+    child_names = 'methodIdx accessFlags codeOff codeOffRef prev next'.split()
     pass
 
 
 class _DEX_ClassData(composite):
     header = _DEX_ClassDataHeader
+    staticFields_b2b = back2back('_DEX_ClassData.staticFields',
+                                 '_DEX_Field.next', '_DEX_Field.prev')
     staticFields = array_relative('header.staticFieldsSize', _DEX_Field)
+    instanceFields_b2b = back2back('_DEX_ClassData.instanceFields',
+                                   '_DEX_Field.next', '_DEX_Field.prev')
     instanceFields = array_relative('header.instanceFieldsSize', _DEX_Field)
+    directMethods_b2b = back2back('_DEX_ClassData.directMethods',
+                                  '_DEX_Method.next', '_DEX_Method.prev')
     directMethods = array_relative('header.directMethodsSize', _DEX_Method)
+    virtualMethods_b2b = back2back('_DEX_ClassData.virtualMethods',
+                                  '_DEX_Method.next', '_DEX_Method.prev')
     virtualMethods = array_relative('header.virtualMethodsSize', _DEX_Method)
 
     child_names = \
         'header ' \
-        'staticFields instanceFields directMethods virtualMethods'.split()
+        'staticFields staticFields_b2b instanceFields instanceFields_b2b ' \
+        'directMethods directMethods_b2b ' \
+        'virtualMethods virtualMethods_b2b'.split()
     pass
 
 
@@ -1667,7 +1733,7 @@
         
         return self
 
-    def compute_size(self):
+    def compute_size(self, parents):
         import itertools
         
         def compute_opcode_size(code):
@@ -1709,7 +1775,7 @@
         pass
 
     @staticmethod
-    def sizeof(obj):
+    def sizeof(obj, parents):
         return obj.data_size
     
     @staticmethod
@@ -1803,7 +1869,7 @@
         self.data_size = sh + size + 1
         return self
 
-    def compute_size(self):
+    def compute_size(self, parents):
         size = len(self.data)
         self.size = size
         size_sz = _uleb128_sz(size)
@@ -1936,9 +2002,10 @@
 
         raw = self.to_str()
         sz = self.header.fileSize
-        nosum = _DEX_header.magic.sizeof(self.header.magic) + \
-            _DEX_header.checksum.sizeof(self.header.checksum) + \
-            _DEX_header.signature.sizeof(self.header.signature)
+        parents = [self]
+        nosum = _DEX_header.magic.sizeof(self.header.magic, parents) + \
+            _DEX_header.checksum.sizeof(self.header.checksum, parents) + \
+            _DEX_header.signature.sizeof(self.header.signature, parents)
         sha = sha1()
         sha.update(raw[nosum:])
         signature = sha.digest()
@@ -1950,11 +2017,19 @@
         
         raw = self.to_str()
         sz = self.header.fileSize
-        nosum = _DEX_header.magic.sizeof(self.header.magic) + \
-            _DEX_header.checksum.sizeof(self.header.checksum)
+        parents = [self]
+        nosum = _DEX_header.magic.sizeof(self.header.magic, parents) + \
+            _DEX_header.checksum.sizeof(self.header.checksum, parents)
         checksum = adler32(adler32_init_value, raw, nosum, sz - nosum)
         self.header.checksum = checksum
         pass
+
+    def compute_size(self):
+        super(DEXFile, self).compute_size([None])
+        pass
+
+    def sizeof(self):
+        return super(DEXFile, self).sizeof(self, [None])
     pass
 
 
@@ -2148,6 +2223,11 @@
         rtypename2 = DEXFile_linked.get_typeid_name(proto2.returnTypeIdx)
         if rtypename1 != rtypename2:
             return False
+        
+        if not (proto1.parametersOffRef.is_true or
+                proto2.parametersOffRef.is_true):
+            return True
+        
         typelist1 = proto1.parametersOffRef.value
         typelist2 = proto2.parametersOffRef.value
         if len(typelist1.typeItems.items) != len(typelist2.typeItems.items):
--- a/paraspace/tests/dex_deptracker_test.py	Thu Aug 11 09:20:46 2011 +0800
+++ b/paraspace/tests/dex_deptracker_test.py	Sun Aug 14 21:18:48 2011 +0800
@@ -51,10 +51,26 @@
     offset1 = dex.typeLists.items[1].value.data_offset
     dex.typeLists.items[1].value.data_offset = 0
 
+    classdata1 = dex.classDatas.items[1]
+    fields_methods_szs1 = [c.sizeof(c, [None])
+                           for c in classdata1.staticFields.items +
+                           classdata1.instanceFields.items +
+                           classdata1.directMethods.items +
+                           classdata1.virtualMethods.items]
     cdoffset0 = dex.classDatas.items[0].data_offset
     dex.classDatas.items[0].data_offset = 0
     cdoffset1 = dex.classDatas.items[1].data_offset
     dex.classDatas.items[1].data_offset = 0
+    cdoffset2 = dex.classDatas.items[2].data_offset
+    dex.classDatas.items[2].data_offset = 0
+    cdoffset4 = dex.classDatas.items[4].data_offset
+    dex.classDatas.items[4].data_offset = 0
+    cdoffset8 = dex.classDatas.items[8].data_offset
+    dex.classDatas.items[8].data_offset = 0
+    cdoffset15 = dex.classDatas.items[15].data_offset
+    dex.classDatas.items[15].data_offset = 0
+    cdoffset30 = dex.classDatas.items[30].data_offset
+    dex.classDatas.items[30].data_offset = 0
     cdoffsetlast = dex.classDatas.items[-1].data_offset
     dex.classDatas.items[-1].data_offset = 0
 
@@ -62,10 +78,23 @@
 
     update_offset(dex, all_dep_decls)
 
+    classdata1 = dex.classDatas.items[1]
+    for c1, c2 in map(None, classdata1.staticFields.items + \
+                          classdata1.instanceFields.items + \
+                          classdata1.directMethods.items + \
+                          classdata1.virtualMethods.items, \
+                          fields_methods_szs1):
+        assert c1.sizeof(c1, [None]) == c2
+        pass
     assert dex.typeLists.items[0].value.data_offset == offset0
     assert dex.typeLists.items[1].value.data_offset == offset1
     assert dex.classDatas.items[0].data_offset == cdoffset0
     assert dex.classDatas.items[1].data_offset == cdoffset1
+    assert dex.classDatas.items[2].data_offset == cdoffset2
+    assert dex.classDatas.items[4].data_offset == cdoffset4
+    assert dex.classDatas.items[8].data_offset == cdoffset8
+    assert dex.classDatas.items[15].data_offset == cdoffset15
+    assert dex.classDatas.items[30].data_offset == cdoffset30
     assert dex.classDatas.items[-1].data_offset == cdoffsetlast
     assert dex.typeIds.items[12].data_idx == 12
     pass
@@ -105,7 +134,7 @@
     pass
 
 
-def sizoef_after_build_dep_test():
+def sizeof_after_build_dep_test():
     from paraspace.dex_deptracker import update_offset
     
     _install_dexfile_4_deptracker()
@@ -120,7 +149,7 @@
     hello_dex = dexfile.DEXFile.open(helloworld_path)
     update_offset(hello_dex, decls)
     
-    get_sz = lambda x: x.sizeof(x)
+    get_sz = lambda x: x.sizeof(x, [hello_dex])
     assert get_sz(hello_dex.header) == 112
     assert get_sz(hello_dex.stringIds) == 0x168
     assert get_sz(hello_dex.typeIds) == (0x250-0x1d8)
@@ -137,17 +166,19 @@
     assert get_sz(hello_dex.annotationItems) == (0xf82-0xf31)
     assert get_sz(hello_dex.encodedArrayItems) == (0xf9d-0xf82)
     assert get_sz(hello_dex.classDatas) == (0x1024-0xf9d-1)
-    assert hello_dex.maps.sizeof(hello_dex.maps) == 0xd0
+    assert hello_dex.maps.sizeof(hello_dex.maps, [hello_dex]) == 0xd0
 
     hello_dex.compute_size()
-    unlinked_sz = hello_dex.sizeof(hello_dex)
+    unlinked_sz = hello_dex.sizeof()
+    unlinked_cdsize = hello_dex.classDatas.sizeof(hello_dex.classDatas, [hello_dex])
     assert unlinked_sz == hello_dex.header.fileSize
 
     hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, decls)
 
     hello_linked.compute_size()
-    linked_sz = hello_linked.sizeof(hello_linked)
+    linked_sz = hello_linked.sizeof()
     
+    get_sz = lambda x: x.sizeof(x, [hello_linked])
     assert get_sz(hello_linked.header) == 112
     assert get_sz(hello_linked.stringIds) == 0x168
     assert get_sz(hello_linked.typeIds) == (0x250-0x1d8)
@@ -164,6 +195,9 @@
     assert get_sz(hello_linked.annotationItems) == (0xf82-0xf31)
     assert get_sz(hello_linked.encodedArrayItems) == (0xf9d-0xf82)
 
+    linked_cdsize = hello_linked.classDatas.sizeof(hello_linked.classDatas,
+                                                   [hello_linked])
+    assert linked_cdsize == unlinked_cdsize # test for depend_idx_rel
     assert linked_sz == unlinked_sz
     
     first_strid = hello_linked.stringIds.items[0]
@@ -172,7 +206,7 @@
     hello_linked.stringIds.items.append(strid)
     
     hello_linked.compute_size()
-    linked_sz = hello_linked.sizeof(hello_linked)
+    linked_sz = hello_linked.sizeof()
     
     assert get_sz(hello_linked.header) == 112
     assert get_sz(hello_linked.stringIds) == 0x16c
--- a/paraspace/tests/injection_test.py	Thu Aug 11 09:20:46 2011 +0800
+++ b/paraspace/tests/injection_test.py	Sun Aug 14 21:18:48 2011 +0800
@@ -656,7 +656,6 @@
             method = hello_linked.find_method_idx(methodidx)
             blk = dexfile.DEXFile_linked.get_code_block_method(method)
             opvectors = decode_insn_blk(blk)
-            print opvectors
             pass
         pass
 
@@ -696,14 +695,11 @@
         elif methodname == 'write_file':
             assert methodid in hello_linked.methodIds.items
             methodidx = hello_linked.get_idx_methodid(methodid)
-            print dexfile.DEXFile_linked.get_typeid_name(methodid.classIdx)
             method = hello_linked.find_method_idx(methodidx)
             blk = dexfile.DEXFile_linked.get_code_block_method(method)
             opvectors = decode_insn_blk(blk)
-            print opvectors
             pass
         pass
-    assert False
     pass