Mercurial > paraspace
changeset 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 | 8fc294b06e22 |
files | paraspace/dex_deptracker.py paraspace/dexfile.py paraspace/tests/dexfile_test.py |
diffstat | 3 files changed, 120 insertions(+), 38 deletions(-) [+] |
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
--- a/paraspace/dexfile.py Sun Jun 19 14:26:09 2011 +0800 +++ b/paraspace/dexfile.py Sun Jun 19 19:36:36 2011 +0800 @@ -23,26 +23,6 @@ pass -## \brief Get attribute of an object for a given path. -# -def _dex_tree_get_child(obj, child_name): - child_parts = child_name.split('.') - for child_part in child_parts: - 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 - return obj - - def _to_uint(data): v = 0 sh = 0 @@ -441,7 +421,7 @@ def to_str(): return '' - def set_value(self, parents): + def get_value(self, parents): pass pass @@ -449,15 +429,19 @@ ## \brief Reference to a value from a given path. # class value_ref(ref): - def set_value(self, parents): + def get_value(self, parents): + from paraspace.dex_deptracker import _resolve_name_path + from paraspace.dex_deptracker import _dex_tree_get_child + pparts = self.target_path.split('.') - clazz = pparts[0] + clazz_name = pparts[0] + clazz, dummy = _resolve_name_path(clazz_name) rev_parents = list(parents) rev_parents.reverse() for parent in rev_parents: - if isinstance(rev_parents, clazz): + if isinstance(parent, clazz): break pass else: @@ -465,8 +449,7 @@ attr_path = '.'.join(pparts[1:]) value = _dex_tree_get_child(parent, attr_path) - self.target = value - pass + return value pass @@ -603,6 +586,7 @@ condition = None child_type = None value = None + is_true = None def __init__(self, cond, child_type): self.condition = cond @@ -612,13 +596,17 @@ def parse(self, parent, data, off): if self.condition(parent, data, off): value = self.child_type.parse(parent, data, off) + is_true = True else: value = None + is_true = False pass obj = cond(self.condition, self.child_type) obj.value = value obj.data_size = self.sizeof(obj) + obj.is_true = is_true + return obj def sizeof(self, v):
--- a/paraspace/tests/dexfile_test.py Sun Jun 19 14:26:09 2011 +0800 +++ b/paraspace/tests/dexfile_test.py Sun Jun 19 19:36:36 2011 +0800 @@ -222,3 +222,37 @@ code_item = dex.codeItems.items[0] assert code_item.debugInfoOff.__class__.__name__ == '_DEX_DebugInfoItem' pass + + +def link_dependencies_cond_value_ref_test(): + from paraspace.dex_deptracker import collect_all_dep_decls + from paraspace.dex_deptracker import build_dependencies + from paraspace.dex_deptracker import _install_markers, _idx_marker + from paraspace.dex_deptracker import _offset_marker, _rel_offset_marker + from paraspace.dex_deptracker import _patch_dex_type_markers + + _install_dexfile_4_deptracker() + + all_dep_decls = collect_all_dep_decls() + _install_markers(all_dep_decls) + assert isinstance(dexfile.DEXFile.typeIds, _idx_marker) + _patch_dex_type_markers(all_dep_decls) + + srcdir = os.path.dirname(__file__) + srcroot = os.path.join(srcdir, '..', '..') + testdatapath = os.path.join(srcroot, 'data', 'testdata1.dex') + dex = dexfile.DEXFile.open(testdatapath) + + build_dependencies(dex, all_dep_decls) + + code_item = dex.codeItems.items[0] + assert code_item.debugInfoOff.__class__.__name__ == '_DEX_DebugInfoItem' + + anno_dir_item = dex.annotationsDirectoryItems.items[0] + assert isinstance(anno_dir_item.classAnnotationsOffRef.value, + dexfile._DEX_AnnotationSetItem) + + anno_dir_item = dex.annotationsDirectoryItems.items[1] + assert isinstance(anno_dir_item.classAnnotationsOffRef.value, + dexfile._DEX_AnnotationSetItem) + pass