# HG changeset patch # User Thinker K.F. Li # Date 1308745323 -28800 # Node ID 705356005362fd695179a8d80b4724557fc758aa # Parent 67aa8ca8fff310106f06a0168d46dd3ebc7efbbc Fix bug of install marker through ref diff -r 67aa8ca8fff3 -r 705356005362 paraspace/dex_deptracker.py --- 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. 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 diff -r 67aa8ca8fff3 -r 705356005362 paraspace/dexfile.py --- a/paraspace/dexfile.py Tue Jun 21 18:36:45 2011 +0800 +++ b/paraspace/dexfile.py Wed Jun 22 20:22:03 2011 +0800 @@ -427,7 +427,6 @@ # class ref(_dex_type): target_path = None - target = None def __init__(self, target_path=None): self.target_path = target_path @@ -638,7 +637,9 @@ return data def children(self): - return ('value',) + if self.is_true: + return ('value',) + return () pass @@ -702,7 +703,7 @@ pass -class abs_value(relocatable): +class abs_value(_dex_type): value = None def __init__(self, value): @@ -710,9 +711,8 @@ pass def parse(self, parse, data, off): - obj = abs_value(self.value) - return obj - + return self.value + def sizeof(self, v): return 0 @@ -720,7 +720,7 @@ return '' def children(self): - return ('value',) + return () pass @@ -992,10 +992,10 @@ startAddr = uint32 insnCount = uint16 handlerOff = depend_off_rel('_DEX_Code.handlers_size', - '_DEX_Try.catch_ref.target')(uint16) + '_DEX_Try.catch_ref')(uint16) catch_ref = ref('_DEX_Catch') - child_names = 'startAddr insnCount handlerOff'.split() + child_names = 'startAddr insnCount handlerOff catch_ref'.split() pass @@ -1021,7 +1021,7 @@ _DEX_CatchAllHandler) try_ref = ref('_DEX_Try') - child_names = 'size handlers catchAllHandler'.split() + child_names = 'size handlers catchAllHandler try_ref'.split() @property def catchesAll(self): @@ -1431,7 +1431,7 @@ return ''.join(opcodebins) def children(self): - return ('opcodes',) + return () pass @@ -1587,7 +1587,6 @@ map_items = [self.block_defs[map_item.type] for map_item in self.maps.items.items] children = map_items + ['maps'] - print children return children pass diff -r 67aa8ca8fff3 -r 705356005362 paraspace/tests/dexfile_test.py --- a/paraspace/tests/dexfile_test.py Tue Jun 21 18:36:45 2011 +0800 +++ b/paraspace/tests/dexfile_test.py Wed Jun 22 20:22:03 2011 +0800 @@ -37,7 +37,7 @@ assert deps['_DEX_ClassDef.staticValuesOffRef.value'][1] == \ '_DEX_EncodedArrayItem' assert deps['_DEX_Try.handlerOff'][0] == dexfile.depend_off_rel - assert deps['_DEX_Try.handlerOff'][1] == '_DEX_Try.catch_ref.target' + assert deps['_DEX_Try.handlerOff'][1] == '_DEX_Try.catch_ref' assert deps['_DEX_Try.handlerOff'][2] == '_DEX_Code.handlers_size' pass @@ -179,6 +179,7 @@ def install_markers_test(): from paraspace.dex_deptracker import collect_all_dep_decls from paraspace.dex_deptracker import _install_markers, _idx_marker + from paraspace.dex_deptracker import _marker from paraspace.dex_deptracker import _offset_marker, _rel_offset_marker from paraspace.dex_deptracker import _patch_dex_type_markers @@ -195,6 +196,7 @@ assert isinstance(dexfile._DEX_TypeList, _offset_marker) assert isinstance(dexfile.DEXFile.typeLists.child_type.value, _offset_marker) + assert isinstance(dexfile._DEX_Catch, _marker) pass @@ -228,7 +230,6 @@ 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() @@ -260,3 +261,36 @@ assert isinstance(clazz_def.annotationsOffRef.value, dexfile._DEX_AnnotationsDirectoryItem) pass + + +def update_offset_test(): + from paraspace.dex_deptracker import collect_all_dep_decls + from paraspace.dex_deptracker import build_dependencies + from paraspace.dex_deptracker import _install_markers + from paraspace.dex_deptracker import _patch_dex_type_markers + from paraspace.dex_deptracker import update_offset + + _install_dexfile_4_deptracker() + + all_dep_decls = collect_all_dep_decls() + _install_markers(all_dep_decls) + _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) + + offset0 = dex.typeLists.items[0].value.data_offset + dex.typeLists.items[0].value.data_offset = 0 + offset1 = dex.typeLists.items[1].value.data_offset + dex.typeLists.items[1].value.data_offset = 0 + + update_offset(dex, all_dep_decls) + + print dex.typeLists.items[0].value.data_offset + assert dex.typeLists.items[0].value.data_offset == offset0 + assert dex.typeLists.items[1].value.data_offset == offset1 + pass