# HG changeset patch # User Thinker K.F. Li # Date 1307430162 -28800 # Node ID b30a0d29a62f5409fa81e9f0cde357f8e92f6f07 # Parent 670167ed06bba475ab5d7c5ebeba9ac00a507cf0 Debugging _travel_dex_type diff -r 670167ed06bb -r b30a0d29a62f paraspace/dex_deptracker.py --- a/paraspace/dex_deptracker.py Tue Jun 07 00:21:17 2011 +0800 +++ b/paraspace/dex_deptracker.py Tue Jun 07 15:02:42 2011 +0800 @@ -35,7 +35,49 @@ return obj, parent +def _travel_dex_type(clazz, name_path): + if isinstance(clazz, _marker): + clazz = clazz.back_type + pass + + travel_queue = [(getattr(clazz, attr_name), name_path + '.' + attr_name) + for attr_name in dir(clazz) + if not attr_name.startswith('_')] + while travel_queue: + attr, name_path = travel_queue.pop(0) + yield attr, name_path + + if isinstance(attr, _marker): + # + # transparent. Enqueue back_type with the same name again. + # + child = attr.back_type + travel_queue.append((child, name_path)) + continue + + if isinstance(attr, _nest_types): + if isinstance(attr, dexfile.array): + child_name = name_path + '.items.*' + child = attr.child_type + travel_queue.append((child, child_name)) + elif isinstance(attr, dexfile.cond): + child_name = name_path + '.value' + child = attr.child_type + travel_queue.append((child, child_name)) + elif isinstance(attr, dexfile.switch): + for key in attr.map.keys(): + child_name = name_path + '.' + repr(key) + child = attr.map[key] + travel_queue.append((child, child_name)) + pass + pass + pass + pass + pass + + def _find_dep_decls_from_clazz(name_path, clazz, dex_types): + # XXX: implements the loop with _travel_dex_type() dep_decls = {} for attr in dir(clazz): @@ -129,23 +171,31 @@ def _travel_dex_relocatable(root_obj, parents=[]): stk = [(root_obj, parents, root_obj.__class__.__name__)] - + + def make_travel_info(obj, obj_name, child_name): + child_parents = parents + [obj] + child_obj = _dex_tree_get_child(obj, child_name) + if isinstance(child_obj, dexfile.composite): + child_path = child_obj.__class__.__name__ + else: + child_path = obj_name + '.' + child_name + pass + return (child_obj, child_parents, child_path) + while stk: obj, parents, obj_name = stk.pop(0) yield (obj, parents, obj_name) if isinstance(obj, list): - children = [(value, parents + [obj], obj_name + '.' + repr(idx)) - for idx, value in enumerate(obj)] + children = [make_travel_info(obj, obj_name, repr(idx)) + for idx in range(len(obj))] stk.extend(children) continue if not isinstance(obj, dexfile.relocatable): continue - child_parents = parents + [obj] - children = [(_dex_tree_get_child(obj, child_name), - child_parents, obj_name + '.' + child_name) + children = [make_travel_info(obj, obj_name, child_name) for child_name in obj.children()] stk.extend(children) pass @@ -172,9 +222,12 @@ return all_dep_decls -class _uid_marker(dexfile.relocatable): +class _marker(dexfile.relocatable): + back_type = None + pass + +class _uid_marker(_marker): uid_seq = 0 - back_type = None def __init__(self, back_type, name_path): self.back_type = back_type @@ -361,6 +414,49 @@ pass +def _patch_dex_type_markers(all_dep_decls): + import itertools + marked_types = dict([(marker.back_type, name) + for name, marker in _all_dex_types().items() + if isinstance(marker, _marker)]) + + travel_iters = [_travel_dex_type(dex_type, name_path) + for name_path, dex_type in _all_dex_types().items()] + marked_type_refs = [(name_path, marked_types[attr]) + for attr, name_path in itertools.chain(*travel_iters) + if type(attr) == type and + issubclass(attr, dexfile.composite) and + attr in marked_types] + print marked_type_refs + + def patch_ref(name_path, depon_path): + depon, depon_parent = _resolve_name_path(depon_path) + + path_elms = name_path.split('.') + parent_path = '.'.join(path_elms[:-1]) + parent, grand = _resolve_name_path(parent_path) + + if isinstance(grand, _nest_types): + if isinstance(grand, (dexfile.array, dexfile.cond)): + grand.child_type = depon + elif isinstance(grand, dexfile.switch): + key = eval(path_elms[-1]) + grand.map[key] = depon + else: + raise RuntimeError, 'should not be here' + pass + else: + name = path_elms[-1] + setattr(parent, name, depon) + pass + pass + + for name_path, depon_path in marked_type_refs: + patch_ref(name_path, depon_path) + pass + pass + + def _link_dependencies(root_obj, all_dep_decls): markers_info = {} depon_src_map = {} @@ -388,6 +484,7 @@ # for obj, parents, name_path in \ _travel_dex_relocatable(root_obj): + print name_path if name_path not in all_dep_decls: continue @@ -396,20 +493,20 @@ dep = all_dep_decls[name_path] dep_type = dep[0] - if isinstance(dep_type, dexfile.depend_off_rel): + if dep_type == dexfile.depend_off_rel: depon1 = _rel_offset_marker.find_depon(dep[1]) depon2 = _rel_offset_marker.find_depon(dep[2]) parent = parents[-1] name = name_path.split('.')[-1] _dex_tree_set_child(parent, name, (depon1, depon2)) - elif isinstance(dep_type, dexfile.depend_off): + elif dep_type == dexfile.depend_off: depon_name_path = dep[1] depon = markers_info[depon_name_path] parent = parents[-1] name = name_path.split('.')[-1] _dex_tree_set_child(parent, name, depon) - elif isinstance(dep_type, dexfile.depend_idx): + elif dep_type == dexfile.depend_idx: depon_name_path = dep[1] depon = markers_info[depon_name_path] parent = parents[-1] diff -r 670167ed06bb -r b30a0d29a62f paraspace/tests/dexfile_test.py --- a/paraspace/tests/dexfile_test.py Tue Jun 07 00:21:17 2011 +0800 +++ b/paraspace/tests/dexfile_test.py Tue Jun 07 15:02:42 2011 +0800 @@ -130,10 +130,24 @@ pass +def travel_dex_type_test(): + from paraspace.dex_deptracker import _travel_dex_type + + attr_infos = [attr_info + for attr_info in \ + _travel_dex_type(dexfile._DEX_AnnotationsDirectoryItem, + '_DEX_AnnotationsDirectoryItem') + ] + print attr_infos + assert len(attr_infos) == 10 + pass + + 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 _offset_marker, _rel_offset_marker + from paraspace.dex_deptracker import _patch_dex_type_markers _install_dexfile_4_deptracker() @@ -143,19 +157,27 @@ assert isinstance(dexfile._DEX_Code.back_type.handlers_size, _rel_offset_marker) assert dexfile._DEX_TypeList.__class__ == _offset_marker + + _patch_dex_type_markers(all_dep_decls) + print all_dep_decls.keys() + print dexfile.DEXFile.typeLists.child_type + assert isinstance(dexfile.DEXFile.typeLists.child_type, _offset_marker) pass + def link_dependencies_test(): from paraspace.dex_deptracker import collect_all_dep_decls from paraspace.dex_deptracker import _link_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, '..', '..') @@ -163,4 +185,8 @@ dex = dexfile.DEXFile.open(testdatapath) _link_dependencies(dex, all_dep_decls) + + code_item = dex.codeItems.items[0] + print code_item.debugInfoOff.__class__ + assert code_item.debugInfoOff.__class__ == dexfile._DEX_DebugInfoItem pass