Mercurial > paraspace
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) |