comparison paraspace/dex_deptracker.py @ 132:75a31967ebee

Following the ref in resotre_dependencies()
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 09 Aug 2011 15:30:45 +0800
parents 52749d91cc22
children ddf8a20ecc4b
comparison
equal deleted inserted replaced
131:044bfc415577 132:75a31967ebee
216 setattr(obj, last_part, value) 216 setattr(obj, last_part, value)
217 pass 217 pass
218 pass 218 pass
219 219
220 220
221 class _travel_rel_node(object):
222 obj = None
223 parents = None
224 name_path = None
225 origin_path = None
226 pass
227
221 ## \brief Travel the tree of relocatable objects and their attributes. 228 ## \brief Travel the tree of relocatable objects and their attributes.
222 # 229 #
223 # \param skip_func is a function that returns true for skip a subtree. 230 # \param skip_func is a function that returns true for skip a subtree.
224 # 231 #
225 # \ref skip_func is called for every relocatable and their attributes 232 # \ref skip_func is called for every relocatable and their attributes
226 # to determines if visiting the object and subtree. 233 # to determines if visiting the object and subtree.
227 # 234 #
235 # NOTE:
236 # You never know what information you will use later. Use an object
237 # instead of tuple to carry information. You can extend states an object
238 # later. But, it is hard to extend a tuple. That is why _travel_rel_node
239 # instances are used to replace tuples, here.
240 #
228 def _travel_dex_relocatable(root_obj, parents=[], skip_func=None): 241 def _travel_dex_relocatable(root_obj, parents=[], skip_func=None):
229 stk = [(root_obj, parents, root_obj.__class__.__name__)] 242 root_node = _travel_rel_node()
243 root_node.obj = root_obj
244 root_node.parents = parents
245 root_node.name_path = root_obj.__class__.__name__
246 root_node.origin_path = root_obj.__class__.__name__
247 stk = [root_node]
230 248
231 def make_travel_info(obj, obj_name, child_name, parents): 249 def make_travel_info(obj, obj_name, child_name, parents):
232 child_parents = parents + [obj] 250 child_parents = parents + [obj]
233 child_obj = _dex_tree_get_child(obj, child_name) 251 child_obj = _dex_tree_get_child(obj, child_name)
234 child_path = obj_name + '.' + child_name 252 child_path = obj_name + '.' + child_name
253 origin_path = child_path
235 254
236 child_clazz, dummy = _resolve_name_path(child_path) 255 child_clazz, dummy = _resolve_name_path(child_path)
237 if not isinstance(child_clazz, dexfile.depend): 256 if not isinstance(child_clazz, dexfile.depend):
238 if isinstance(child_obj, dexfile.composite): 257 if isinstance(child_obj, dexfile.composite):
239 child_path = child_obj.__class__.__name__ 258 child_path = child_obj.__class__.__name__
240 pass 259 pass
241 pass 260 pass
242 return (child_obj, child_parents, child_path) 261
262 node = _travel_rel_node()
263 node.obj = child_obj
264 node.parents = child_parents
265 node.name_path = child_path
266 node.origin_path = origin_path
267
268 return node
243 269
244 while stk: 270 while stk:
245 obj, parents, obj_name = stk.pop(0) 271 node = stk.pop(0)
272 obj, parents, obj_name = node.obj, node.parents, node.name_path
246 if skip_func and skip_func(obj, parents, obj_name): 273 if skip_func and skip_func(obj, parents, obj_name):
247 continue 274 continue
248 yield (obj, parents, obj_name) 275 yield node
249 276
250 if isinstance(obj, list): 277 if isinstance(obj, list):
251 children = [make_travel_info(obj, obj_name, repr(idx), parents) 278 children = [make_travel_info(obj, obj_name, repr(idx), parents)
252 for idx in range(len(obj))] 279 for idx in range(len(obj))]
253 stk.extend(children) 280 stk.extend(children)
620 if isinstance(obj, dexfile.cond) and not obj.is_true: 647 if isinstance(obj, dexfile.cond) and not obj.is_true:
621 return () 648 return ()
622 pass 649 pass
623 return obj 650 return obj
624 651
625 for obj, parents, name_path in \ 652 for node in _travel_dex_relocatable(root_obj):
626 _travel_dex_relocatable(root_obj): 653 obj = node.obj
654 parents = node.parents
655
627 if isinstance(obj, dexfile._objs_asso): 656 if isinstance(obj, dexfile._objs_asso):
628 rev_parents = list(parents) 657 rev_parents = list(parents)
629 rev_parents.reverse() 658 rev_parents.reverse()
630 for parent in rev_parents: 659 for parent in rev_parents:
631 if isinstance(parent, dexfile.composite): 660 if isinstance(parent, dexfile.composite):
650 return parent 679 return parent
651 pass 680 pass
652 raise TypeError, 'can not find a prent of %s type' % (repr(clazz)) 681 raise TypeError, 'can not find a prent of %s type' % (repr(clazz))
653 682
654 683
684 ## \brief Split a name path into class and attribute parts.
685 #
686 # \param name_path is a name path string.
687 # \return a tuple in pattern (class name, attribute name)
688 #
655 def _split_name_path_clazz_attr(name_path): 689 def _split_name_path_clazz_attr(name_path):
656 idx = name_path.index('.') 690 idx = name_path.index('.')
657 if idx >= 0: 691 if idx >= 0:
658 clazz = name_path[:idx] 692 clazz = name_path[:idx]
659 attr = name_path[idx + 1:] 693 attr = name_path[idx + 1:]
665 699
666 700
667 ## \brief Setup value of refs. 701 ## \brief Setup value of refs.
668 # 702 #
669 def _build_refs(root_obj): 703 def _build_refs(root_obj):
670 for obj, parents, name_path in \ 704 for node in _travel_dex_relocatable(root_obj):
671 _travel_dex_relocatable(root_obj): 705 name_path = node.name_path
706 parents = node.parents
707
672 if not parents: 708 if not parents:
673 continue 709 continue
674 710
675 imm_parent = parents[-1] 711 imm_parent = parents[-1]
676 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true: 712 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true:
708 pass 744 pass
709 745
710 # 746 #
711 # Collect marked objects 747 # Collect marked objects
712 # 748 #
713 for obj, parents, name_path in \ 749 for node in _travel_dex_relocatable(root_obj):
714 _travel_dex_relocatable(root_obj): 750 obj = node.obj
751 parents = node.parents
752 name_path = node.name_path
753
715 if name_path not in markers_info: 754 if name_path not in markers_info:
716 continue 755 continue
717 756
718 marker, dummy_parent = _resolve_name_path(name_path) 757 marker, dummy_parent = _resolve_name_path(name_path)
719 while isinstance(marker, dexfile.ref): 758 while isinstance(marker, dexfile.ref):
723 pass 762 pass
724 763
725 # 764 #
726 # Link depend source to marked target 765 # Link depend source to marked target
727 # 766 #
728 for obj, parents, name_path in \ 767 for node in _travel_dex_relocatable(root_obj):
729 _travel_dex_relocatable(root_obj): 768 obj = node.obj
769 parents = node.parents
770 name_path = node.name_path
730 if name_path not in all_dep_decls: 771 if name_path not in all_dep_decls:
731 continue 772 continue
732 773
733 imm_parent = parents[-1] 774 imm_parent = parents[-1]
734 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true: 775 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true:
799 # restore_dependencies(). 840 # restore_dependencies().
800 # 841 #
801 def dex_sort_sorted_arrays(dex): 842 def dex_sort_sorted_arrays(dex):
802 assert isinstance(dex, dexfile.DEXFile_linked) 843 assert isinstance(dex, dexfile.DEXFile_linked)
803 844
804 for obj, parents, name_path in _travel_dex_relocatable(dex): 845 for node in _travel_dex_relocatable(dex):
846 obj = node.obj
805 if isinstance(obj, dexfile.array_sorted): 847 if isinstance(obj, dexfile.array_sorted):
806 obj.items.sort() 848 obj.items.sort()
807 pass 849 pass
808 pass 850 pass
809 pass 851 pass
971 1013
972 ## \brief Restore to raw value before linking for dependencies. 1014 ## \brief Restore to raw value before linking for dependencies.
973 # 1015 #
974 def restore_dependencies(dexroot, all_dep_decls): 1016 def restore_dependencies(dexroot, all_dep_decls):
975 update_offset(dexroot, all_dep_decls) 1017 update_offset(dexroot, all_dep_decls)
976 1018
977 for obj, parents, name_path in \ 1019 def set_child(node, value):
978 _travel_dex_relocatable(dexroot): 1020 vtype, dummy = _resolve_name_path(node.origin_path)
1021 while isinstance(vtype, dexfile.null_relocatable):
1022 vtype = vtype.back_type
1023 pass
1024
1025 if isinstance(vtype, dexfile.ref):
1026 name_path = vtype.target_path
1027 print 'REF', node.origin_path, name_path, '0x%x' % value
1028 else:
1029 name_path = node.origin_path
1030 pass
1031
1032 parent_clazzname, attr_name = _split_name_path_clazz_attr(name_path)
1033 parent_clazz, dummy = _resolve_name_path(parent_clazzname)
1034 parent_clazz = _skip_marker_clazz(parent_clazz)
1035 clazz_parent = _find_parent_of_clazz(parent_clazz, node.parents)
1036
1037 _dex_tree_set_child(clazz_parent, attr_name, value)
1038 pass
1039
1040 for node in _travel_dex_relocatable(dexroot):
1041 obj = node.obj
1042 parents = node.parents
1043 name_path = node.name_path
1044
979 if name_path not in all_dep_decls: 1045 if name_path not in all_dep_decls:
980 continue 1046 continue
981 1047
982 imm_parent = parents[-1] 1048 imm_parent = parents[-1]
983 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true: 1049 if isinstance(imm_parent, dexfile.cond) and not imm_parent.is_true:
987 dep_type = dep[0] 1053 dep_type = dep[0]
988 if dep_type == dexfile.depend_off_rel: 1054 if dep_type == dexfile.depend_off_rel:
989 relative_to = _rel_offset_marker.find_depon(dep[2], parents) 1055 relative_to = _rel_offset_marker.find_depon(dep[2], parents)
990 depon = obj 1056 depon = obj
991 rel_off = depon.data_offset - relative_to.data_offset 1057 rel_off = depon.data_offset - relative_to.data_offset
992 1058 set_child(node, rel_off)
993 name = name_path.split('.')[-1]
994 _dex_tree_set_child(imm_parent, name, rel_off)
995 elif dep_type == dexfile.depend_off: 1059 elif dep_type == dexfile.depend_off:
996 depon = obj 1060 depon = obj
997 name = name_path.split('.')[-1] 1061 set_child(node, depon.data_offset)
998 _dex_tree_set_child(imm_parent, name, depon.data_offset)
999 elif dep_type == dexfile.depend_idx: 1062 elif dep_type == dexfile.depend_idx:
1000 depon = obj 1063 depon = obj
1001 name = name_path.split('.')[-1] 1064 set_child(node, depon.data_idx)
1002 _dex_tree_set_child(imm_parent, name, depon.data_idx)
1003 else: 1065 else:
1004 raise TypeError, 'invalid depend type %s' % (repr(dep_type)) 1066 raise TypeError, 'invalid depend type %s' % (repr(dep_type))
1005 pass 1067 pass
1006 1068
1007 _sync_DEXFile_fields(dexroot) 1069 _sync_DEXFile_fields(dexroot)