# HG changeset patch # User Thinker K.F. Li # Date 1312875045 -28800 # Node ID 75a31967ebee926c522b271262335c2f37bee2a1 # Parent 044bfc4155772e7282aad553516ffdb29cffa9db Following the ref in resotre_dependencies() diff -r 044bfc415577 -r 75a31967ebee Doxyfile --- a/Doxyfile Tue Aug 09 11:47:43 2011 +0800 +++ b/Doxyfile Tue Aug 09 15:30:45 2011 +0800 @@ -303,7 +303,7 @@ # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. diff -r 044bfc415577 -r 75a31967ebee paraspace/dex_deptracker.py --- a/paraspace/dex_deptracker.py Tue Aug 09 11:47:43 2011 +0800 +++ b/paraspace/dex_deptracker.py Tue Aug 09 15:30:45 2011 +0800 @@ -218,6 +218,13 @@ pass +class _travel_rel_node(object): + obj = None + parents = None + name_path = None + origin_path = None + pass + ## \brief Travel the tree of relocatable objects and their attributes. # # \param skip_func is a function that returns true for skip a subtree. @@ -225,13 +232,25 @@ # \ref skip_func is called for every relocatable and their attributes # to determines if visiting the object and subtree. # +# NOTE: +# You never know what information you will use later. Use an object +# instead of tuple to carry information. You can extend states an object +# later. But, it is hard to extend a tuple. That is why _travel_rel_node +# instances are used to replace tuples, here. +# def _travel_dex_relocatable(root_obj, parents=[], skip_func=None): - stk = [(root_obj, parents, root_obj.__class__.__name__)] + root_node = _travel_rel_node() + root_node.obj = root_obj + root_node.parents = parents + root_node.name_path = root_obj.__class__.__name__ + root_node.origin_path = root_obj.__class__.__name__ + stk = [root_node] def make_travel_info(obj, obj_name, child_name, parents): child_parents = parents + [obj] child_obj = _dex_tree_get_child(obj, child_name) child_path = obj_name + '.' + child_name + origin_path = child_path child_clazz, dummy = _resolve_name_path(child_path) if not isinstance(child_clazz, dexfile.depend): @@ -239,13 +258,21 @@ child_path = child_obj.__class__.__name__ pass pass - return (child_obj, child_parents, child_path) + + node = _travel_rel_node() + node.obj = child_obj + node.parents = child_parents + node.name_path = child_path + node.origin_path = origin_path + + return node while stk: - obj, parents, obj_name = stk.pop(0) + node = stk.pop(0) + obj, parents, obj_name = node.obj, node.parents, node.name_path if skip_func and skip_func(obj, parents, obj_name): continue - yield (obj, parents, obj_name) + yield node if isinstance(obj, list): children = [make_travel_info(obj, obj_name, repr(idx), parents) @@ -622,8 +649,10 @@ pass return obj - for obj, parents, name_path in \ - _travel_dex_relocatable(root_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() @@ -652,6 +681,11 @@ raise TypeError, 'can not find a prent of %s type' % (repr(clazz)) +## \brief Split a name path into class and attribute parts. +# +# \param name_path is a name path string. +# \return a tuple in pattern (class name, attribute name) +# def _split_name_path_clazz_attr(name_path): idx = name_path.index('.') if idx >= 0: @@ -667,8 +701,10 @@ ## \brief Setup value of refs. # def _build_refs(root_obj): - for obj, parents, name_path in \ - _travel_dex_relocatable(root_obj): + for node in _travel_dex_relocatable(root_obj): + name_path = node.name_path + parents = node.parents + if not parents: continue @@ -710,8 +746,11 @@ # # Collect marked objects # - for obj, parents, name_path in \ - _travel_dex_relocatable(root_obj): + for node in _travel_dex_relocatable(root_obj): + obj = node.obj + parents = node.parents + name_path = node.name_path + if name_path not in markers_info: continue @@ -725,8 +764,10 @@ # # Link depend source to marked target # - for obj, parents, name_path in \ - _travel_dex_relocatable(root_obj): + for node in _travel_dex_relocatable(root_obj): + obj = node.obj + parents = node.parents + name_path = node.name_path if name_path not in all_dep_decls: continue @@ -801,7 +842,8 @@ def dex_sort_sorted_arrays(dex): assert isinstance(dex, dexfile.DEXFile_linked) - for obj, parents, name_path in _travel_dex_relocatable(dex): + for node in _travel_dex_relocatable(dex): + obj = node.obj if isinstance(obj, dexfile.array_sorted): obj.items.sort() pass @@ -973,9 +1015,33 @@ # def restore_dependencies(dexroot, all_dep_decls): update_offset(dexroot, all_dep_decls) + + def set_child(node, value): + vtype, dummy = _resolve_name_path(node.origin_path) + while isinstance(vtype, dexfile.null_relocatable): + vtype = vtype.back_type + pass + + if isinstance(vtype, dexfile.ref): + name_path = vtype.target_path + print 'REF', node.origin_path, name_path, '0x%x' % value + else: + name_path = node.origin_path + pass + + parent_clazzname, attr_name = _split_name_path_clazz_attr(name_path) + parent_clazz, dummy = _resolve_name_path(parent_clazzname) + parent_clazz = _skip_marker_clazz(parent_clazz) + clazz_parent = _find_parent_of_clazz(parent_clazz, node.parents) + + _dex_tree_set_child(clazz_parent, attr_name, value) + pass - for obj, parents, name_path in \ - _travel_dex_relocatable(dexroot): + for node in _travel_dex_relocatable(dexroot): + obj = node.obj + parents = node.parents + name_path = node.name_path + if name_path not in all_dep_decls: continue @@ -989,17 +1055,13 @@ relative_to = _rel_offset_marker.find_depon(dep[2], parents) depon = obj rel_off = depon.data_offset - relative_to.data_offset - - name = name_path.split('.')[-1] - _dex_tree_set_child(imm_parent, name, rel_off) + set_child(node, rel_off) elif dep_type == dexfile.depend_off: depon = obj - name = name_path.split('.')[-1] - _dex_tree_set_child(imm_parent, name, depon.data_offset) + set_child(node, depon.data_offset) elif dep_type == dexfile.depend_idx: depon = obj - name = name_path.split('.')[-1] - _dex_tree_set_child(imm_parent, name, depon.data_idx) + set_child(node, depon.data_idx) else: raise TypeError, 'invalid depend type %s' % (repr(dep_type)) pass diff -r 044bfc415577 -r 75a31967ebee paraspace/dexfile.py --- a/paraspace/dexfile.py Tue Aug 09 11:47:43 2011 +0800 +++ b/paraspace/dexfile.py Tue Aug 09 15:30:45 2011 +0800 @@ -533,6 +533,28 @@ attr_path = '.'.join(pparts[1:]) value = _dex_tree_get_child(parent, attr_path) return value + + def set_value(self, value, parents): + from paraspace.dex_deptracker import _resolve_name_path + from paraspace.dex_deptracker import _dex_tree_get_child + + pparts = self.target_path.split('.') + 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(parent, clazz): + break + pass + else: + raise ValueError, 'can not find %s' % (self.target_path) + + attr_path = '.'.join(pparts[1:]) + _dex_tree_set_child(parent, attr_path, value) + pass pass diff -r 044bfc415577 -r 75a31967ebee paraspace/tests/dexfile_test.py --- a/paraspace/tests/dexfile_test.py Tue Aug 09 11:47:43 2011 +0800 +++ b/paraspace/tests/dexfile_test.py Tue Aug 09 15:30:45 2011 +0800 @@ -118,7 +118,7 @@ dexroot = dex.typeLists.items[0].value itr = _travel_dex_relocatable(dexroot) - pathes = [v[2] for v in itr] + pathes = [node.name_path for node in itr] assert len(pathes) == 6 assert '_DEX_TypeList' in pathes assert '_DEX_TypeList.num' in pathes diff -r 044bfc415577 -r 75a31967ebee paraspace/tests/injection_test.py --- a/paraspace/tests/injection_test.py Tue Aug 09 11:47:43 2011 +0800 +++ b/paraspace/tests/injection_test.py Tue Aug 09 15:30:45 2011 +0800 @@ -425,6 +425,9 @@ # It is possible restore_dependencies() does not following \ref ref # object to set offset value on referenced attribute. # +# It is also possible dexfile_insert_classdefs_relative() does not +# put injected objects into lists properly. +# def map_verify_error_test(): from paraspace.dex_deptracker import prepare_dep_decls from paraspace.injection import inject_redir @@ -451,7 +454,7 @@ hello_linked, 'Ljava/io/File;', all_dep_decls) for idx, item in enumerate(hello_linked.maps.items.items): - if item.type != dexfile._DEX_MapItem.name_to_types['kDexTypeTypeList']: + if item.type == dexfile._DEX_MapItem.name_to_types['kDexTypeTypeList']: break pass else: @@ -464,20 +467,28 @@ for idx, protoid in enumerate(hello_linked.protoIds.items): off = protoid.parametersOff try: - assert off >= typelist_start - assert off < typelist_stop + if off != 0: + assert off >= typelist_start + assert off < typelist_stop + pass + pass except: - print 'ERROR: protoid idx @', idx, protoid + print 'ERROR: protoid idx@%d %s 0x%x' % (idx, repr(protoid), off) + print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop) raise pass for idx, classdef in enumerate(hello_linked.classDefs.items): off = classdef.interfacesOff try: - assert off >= typelist_start - assert off < typelist_stop + if off != 0: + assert off >= typelist_start + assert off < typelist_stop + pass + pass except: - print 'ERROR: classdef idx @', idx, classdef + print 'ERROR: classdef idx@%d %s 0x%x' % (idx, repr(classdef), off) + print 'start 0x%x stop 0x%x' % (typelist_start, typelist_stop) raise pass pass