comparison paraspace/injection.py @ 135:b488ca519709

Make sure elements are absolute incremental for sorted arrays when injecting. - All sorted array of DEXFile must be absolute incremental. - If injected one is the same order as one already in the array, the one in array are used to replace injected one. - All references to clone and injected one refer to ones already in array instead.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 09 Aug 2011 21:28:13 +0800
parents 3dee4d929e1f
children 987fead83ce3
comparison
equal deleted inserted replaced
134:3dee4d929e1f 135:b488ca519709
75 # 75 #
76 def dex_append_obj_list(dex, obj): 76 def dex_append_obj_list(dex, obj):
77 from paraspace.dex_deptracker import _dex_tree_get_child 77 from paraspace.dex_deptracker import _dex_tree_get_child
78 from paraspace.dex_deptracker import _dex_tree_set_child 78 from paraspace.dex_deptracker import _dex_tree_set_child
79 from paraspace.dexfile import _DEX_TypeList, _DEX_TypeList_align 79 from paraspace.dexfile import _DEX_TypeList, _DEX_TypeList_align
80 from paraspace.dexfile import array_sorted
80 81
81 if isinstance(obj, _DEX_TypeList): 82 if isinstance(obj, _DEX_TypeList):
82 wrapper = _DEX_TypeList_align() 83 wrapper = _DEX_TypeList_align()
83 wrapper.value = obj 84 wrapper.value = obj
84 obj = wrapper 85 obj = wrapper
89 attr = type_2_attr[obj.__class__] 90 attr = type_2_attr[obj.__class__]
90 except KeyError: 91 except KeyError:
91 return 92 return
92 93
93 array = getattr(dex, attr) 94 array = getattr(dex, attr)
95
96 if isinstance(array, array_sorted):
97 if obj in array.items:
98 idx = array.items.index(obj)
99 return array.items[idx]
100 pass
101
94 array.items.append(obj) 102 array.items.append(obj)
95 103
96 count_name = array.count_name 104 count_name = array.count_name
97 if count_name: 105 if count_name:
98 count = _dex_tree_get_child(dex, count_name) 106 count = _dex_tree_get_child(dex, count_name)
99 _dex_tree_set_child(dex, count_name, count + 1) 107 _dex_tree_set_child(dex, count_name, count + 1)
100 pass 108 pass
101 pass 109
110 return obj
102 111
103 112
104 ## \brief Clone a composite object. 113 ## \brief Clone a composite object.
105 # 114 #
106 # \param dex is the DEXFile that the composite object is cloning for. 115 # \param dex is the DEXFile that the composite object is cloning for.
186 195
187 merge_unique_strdata() 196 merge_unique_strdata()
188 merge_unique_strid() 197 merge_unique_strid()
189 merge_unique_typeid() 198 merge_unique_typeid()
190 199
191 for obj in visit_log.values(): 200 relink_list = []
201 for key, obj in visit_log.items():
202 if isinstance(obj, (_DEX_StringDataItem,
203 _DEX_StringId,
204 _DEX_TypeId)):
205 continue
206 r = dex_append_obj_list(dex, obj)
207 if r and r is not obj:
208 visit_log[key] = r
209 else:
210 relink_list.append(obj)
211 pass
212 pass
213
214 for obj in relink_list:
192 if isinstance(obj, (_DEX_StringDataItem, 215 if isinstance(obj, (_DEX_StringDataItem,
193 _DEX_StringId, 216 _DEX_StringId,
194 _DEX_TypeId)): 217 _DEX_TypeId)):
195 continue 218 continue
196 relink_dependencies(obj) 219 relink_dependencies(obj)
197 dex_append_obj_list(dex, obj)
198 pass 220 pass
199 221
200 clone = visit_log[id(comobj)] 222 clone = visit_log[id(comobj)]
201 return clone 223 return clone
202 224
658 # 680 #
659 # The _DEX_ClassDef given by inj_classname would be inserted to dst_linked, 681 # The _DEX_ClassDef given by inj_classname would be inserted to dst_linked,
660 # and redirect all invoking of type, given by redir_classname, to 682 # and redirect all invoking of type, given by redir_classname, to
661 # the injected one. 683 # the injected one.
662 # 684 #
663 def inject_redir(src_linked, inj_classname, 685 def inject_redir_no_restore(src_linked, inj_classname,
664 dst_linked, redir_classname, decls): 686 dst_linked, redir_classname, decls):
665 from paraspace.dex_deptracker import dex_sort_sorted_arrays
666 from paraspace.dex_deptracker import restore_dependencies
667
668 inj_classdef = src_linked.find_class_name(inj_classname) 687 inj_classdef = src_linked.find_class_name(inj_classname)
669 injected_classdefs = inject_classdefs(dst_linked, src_linked, 688 injected_classdefs = inject_classdefs(dst_linked, src_linked,
670 [inj_classdef]) 689 [inj_classdef])
671 690
672 redir_typeid = dst_linked.find_typeid_name(redir_classname) 691 redir_typeid = dst_linked.find_typeid_name(redir_classname)
680 699
681 injected_typeidxs = [dst_linked.get_idx_classdef(classdef) 700 injected_typeidxs = [dst_linked.get_idx_classdef(classdef)
682 for classdef in injected_classdefs] 701 for classdef in injected_classdefs]
683 dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir, 702 dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir,
684 excludes=injected_typeidxs) 703 excludes=injected_typeidxs)
685 704 pass
705
706
707 ## \brief Inject and redirect a _DEX_ClassDef from one linked to another.
708 #
709 # The _DEX_ClassDef given by inj_classname would be inserted to dst_linked,
710 # and redirect all invoking of type, given by redir_classname, to
711 # the injected one.
712 #
713 def inject_redir(src_linked, inj_classname,
714 dst_linked, redir_classname, decls):
715 from paraspace.dex_deptracker import dex_sort_sorted_arrays
716 from paraspace.dex_deptracker import restore_dependencies
717
718 inject_redir_no_restore(src_linked, inj_classname,
719 dst_linked, redir_classname, decls)
686 dex_sort_sorted_arrays(dst_linked) 720 dex_sort_sorted_arrays(dst_linked)
687 restore_dependencies(dst_linked, decls) 721 restore_dependencies(dst_linked, decls)
688 pass 722 pass