diff paraspace/dex_deptracker.py @ 43:5cea19126a11

Fix issue of _build_refs() - _build_refs() does not handle dexfile.cond well when traveling. - fix it - Move from ref.get_value() to ref.set_value().
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 19 Jun 2011 19:36:36 +0800
parents 8ca4a6bc6b79
children 94e80f7a61b5
line wrap: on
line diff
--- a/paraspace/dex_deptracker.py	Sun Jun 19 14:26:09 2011 +0800
+++ b/paraspace/dex_deptracker.py	Sun Jun 19 19:36:36 2011 +0800
@@ -175,14 +175,30 @@
 
 
 def _dex_tree_set_child(obj, child_name, value):
+    child_parts = child_name.split('.')
+    for child_part in child_parts[:-1]:
+        if isinstance(obj, list):
+            idx = int(child_part)
+            obj = obj[idx]
+            continue
+        
+        if isinstance(obj, dexfile.switch):
+            assert obj.map[eval(child_part)] == obj.child_type
+            obj = obj.value
+            continue
+        
+        obj = getattr(obj, child_part)
+        pass
+    
+    last_part = child_parts[-1]
     if isinstance(obj, list):
-        idx = int(child_name)
+        idx = int(last_part)
         obj[idx] = value
     elif isinstance(obj, dexfile.switch):
-        assert obj.map[eval(child_name)] == obj.child_type
+        assert obj.map[eval(last_part)] == obj.child_type
         obj.value = value
     else:
-        setattr(obj, child_name, value)
+        setattr(obj, last_part, value)
         pass
     pass
 
@@ -530,12 +546,58 @@
     pass
 
 
+## \brief Find a parent that is an instance of given clazz from a list.
+#
+def _find_parent_of_clazz(clazz, parents):
+    rev_parents = list(parents)
+    rev_parents.reverse()
+    for parent in rev_parents:
+        if isinstance(parent, clazz):
+            return parent
+        pass
+    raise TypeError, 'can not find a prent of %s type' % (repr(clazz))
+
+
+def _split_name_path_clazz_attr(name_path):
+    idx = name_path.index('.')
+    if idx >= 0:
+        clazz = name_path[:idx]
+        attr = name_path[idx + 1:]
+    else:
+        clazz = name_path
+        attr = None
+        pass
+    return clazz, attr
+
+
+## \brief Setup value of refs.
+#
 def _build_refs(root_obj):
     for obj, parents, name_path in \
             _travel_dex_relocatable(root_obj):
-        if not isinstance(obj, dexfile.value_ref):
+        if not parents:
+            continue
+
+        imm_parent = parents[-1]
+        if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true:
             continue
-        obj.set_value(parents)
+        
+        clazz, pclazz = _resolve_name_path(name_path)
+        while isinstance(clazz, dexfile.depend):
+            clazz = clazz.child_type
+            pass
+        
+        if isinstance(clazz, dexfile.ref):
+            pclazz_name, attr_name = _split_name_path_clazz_attr(name_path)
+            if not attr_name:
+                raise ValueError, \
+                    'not attribute name in name path (%s)' % (name_path)
+            
+            parent = _find_parent_of_clazz(dexfile.composite, parents)
+            
+            value = clazz.get_value(parents)
+            _dex_tree_set_child(parent, attr_name, value)
+            pass
         pass
     pass
 
@@ -570,7 +632,8 @@
         if name_path not in all_dep_decls:
             continue
 
-        if obj is None and isinstance(parents[-1], dexfile.cond):
+        imm_parent = parents[-1]
+        if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true:
             continue
 
         dep = all_dep_decls[name_path]
@@ -579,21 +642,18 @@
             depon1 = _rel_offset_marker.find_depon(dep[1], parents)
             depon2 = _rel_offset_marker.find_depon(dep[2], parents)
 
-            parent = parents[-1]
             name = name_path.split('.')[-1]
-            _dex_tree_set_child(parent, name, (depon1, depon2))
+            _dex_tree_set_child(imm_parent, name, (depon1, depon2))
         elif dep_type == dexfile.depend_off:
             depon_name_path = dep[1]
             depon = markers_info[depon_name_path][obj]
-            parent = parents[-1]
             name = name_path.split('.')[-1]
-            _dex_tree_set_child(parent, name, depon)
+            _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]
-            parent = parents[-1]
             name = name_path.split('.')[-1]
-            _dex_tree_set_child(parent, name, depon)
+            _dex_tree_set_child(imm_parent, name, depon)
         else:
             raise TypeError, 'invalid depend type %s' % (repr(dep_type))
         pass