comparison paraspace/injection.py @ 111:3820379b34e8

Add dexfile_insert_class_relative()
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 01 Aug 2011 22:23:55 +0800
parents 6380730a80b4
children 650dcb9c01ee
comparison
equal deleted inserted replaced
110:6380730a80b4 111:3820379b34e8
92 _dex_tree_set_child(dex, count_name, count + 1) 92 _dex_tree_set_child(dex, count_name, count + 1)
93 pass 93 pass
94 pass 94 pass
95 95
96 96
97 ## \brief Clone a class definition item 97 ## \brief Clone a composite object.
98 # 98 #
99 # \param dex is the DEXFile that clazz is cloning for. 99 # \param dex is the DEXFile that the composite object is cloning for.
100 # \param clazz is the class definition item that is cloning. 100 # \param comobj is composite object that is cloning.
101 # 101 #
102 def _clone_classdef(dex, clazz): 102 def _clone_composite(dex, comobj):
103 from copy import copy 103 from copy import copy
104 from paraspace.dexfile import _DEX_StringDataItem, _DEX_StringId 104 from paraspace.dexfile import _DEX_StringDataItem, _DEX_StringId
105 from paraspace.dexfile import _DEX_TypeId 105 from paraspace.dexfile import _DEX_TypeId
106 from paraspace.dex_deptracker import _dex_tree_set_child 106 from paraspace.dex_deptracker import _dex_tree_set_child
107 from paraspace.dex_deptracker import _dex_tree_get_child 107 from paraspace.dex_deptracker import _dex_tree_get_child
173 dex_append_obj_list(dex, typeid) 173 dex_append_obj_list(dex, typeid)
174 pass 174 pass
175 pass 175 pass
176 pass 176 pass
177 177
178 def has_classdef(clazz): 178 _travel_desc_relocatable(comobj, cloner, visit_log)
179 class_typeIds = set([classdef.classIdx
180 for classdef in dex.classDefs.items])
181 return clazz.classIdx in class_typeIds
182
183 _travel_desc_relocatable(clazz, cloner, visit_log)
184 179
185 merge_unique_strdata() 180 merge_unique_strdata()
186 merge_unique_strid() 181 merge_unique_strid()
187 merge_unique_typeid() 182 merge_unique_typeid()
188 183
193 continue 188 continue
194 relink_dependencies(obj) 189 relink_dependencies(obj)
195 dex_append_obj_list(dex, obj) 190 dex_append_obj_list(dex, obj)
196 pass 191 pass
197 192
193 clone = visit_log[id(comobj)]
194 return clone
195
196
197 ## \brief Clone a class definition item
198 #
199 # \param dex is the DEXFile that clazz is cloning for.
200 # \param clazz is the class definition item that is cloning.
201 # \return the cloning _DEX_ClassDef.
202 #
203 def _clone_classdef(dex, clazz):
204 from paraspace.dexfile import DEXFile_linked, _DEX_ClassDef
205
206 def has_classdef(clazz):
207 classname = DEXFile_linked.get_classdef_name(clazz)
208 try:
209 dex.find_class_name(classname)
210 except ValueError:
211 return False
212 return True
213
214 assert isinstance(clazz, _DEX_ClassDef)
215
198 if has_classdef(clazz): 216 if has_classdef(clazz):
199 raise RuntimeError, \ 217 raise RuntimeError, \
200 'clone a class \'%s\'that is already in the DEXFile' % \ 218 'clone a class \'%s\'that is already in the DEXFile' % \
201 classdef_name(clazz) 219 classdef_name(clazz)
202 220
203 clone = visit_log[id(clazz)] 221 clone = _clone_composite(dex, clazz)
204 return clone 222 return clone
205 223
206 224
207 ## \brief Clone a class definition and insert into a DEXFile. 225 ## \brief Clone a class definition and insert into a DEXFile.
208 # 226 #
210 # insert it into another one. 228 # insert it into another one.
211 # 229 #
212 # \param dex is a DEXFile_linked to insert the clone. 230 # \param dex is a DEXFile_linked to insert the clone.
213 # \param class_def is a class definition going to be cloned. 231 # \param class_def is a class definition going to be cloned.
214 # 232 #
215 def dexfile_insert_class(dex, class_def): 233 def dexfile_insert_class(dex, classdef):
216 clone = _clone_classdef(dex, class_def) 234 clone = _clone_classdef(dex, classdef)
217 return clone 235 return clone
236
237
238 ## \brief Collect info of classes mentioned by the code of given class.
239 def _find_class_relative(dex, classdef):
240 def classify_typeids_defined(dex, typeids):
241 classdefs = []
242 undef_typeids = []
243 for typeid in typeids:
244 try:
245 classdef = dex.find_class_typeid(typeid)
246 except ValueError:
247 undef_typeids.append(typeid)
248 else:
249 classdefs.append(classdef)
250 pass
251 pass
252 return classdefs, undef_typeids
253
254 typeidxs = collect_typeidxs_mentioned_by_class(dex, classdef)
255 typeids = [dex.find_typeid_idx(typeidx)
256 for typeidx in typeidxs]
257
258 classdefs, typeids = classify_typeids_defined(dex, typeids)
259
260 return classdefs, typeids
261
262
263 def dexfile_insert_classdefs(dex_dst, dex_src, classdefs):
264 for classdef in classdefs:
265 dexfile_insert_class(dex_dst, classdef)
266 pass
267 pass
268
269
270 ## \brief Clone and insert a _DEX_TypeId to another DEXFile_linked.
271 #
272 # \param dex_dst is a DEXFile_linked where the cloning one is inserted.
273 # \param dex_src is a DEXFile_linked where the cloned one is from.
274 # \param typeid is a _DEX_TypeId that is cloned.
275 # \return the cloning _DEX_TypeId.
276 #
277 def dexfile_insert_typeid(dex_dst, dex_src, typeid):
278 from paraspace.dexfile import _DEX_TypeId, DEXFile_linked
279
280 assert isinstance(typeid, _DEX_TypeId)
281
282 cloning = _clone_composite(dex_dst, typeid)
283
284 methodids = dex_src.find_methodids_typeid(dex_src, typeid)
285 for methodid in methodids:
286 _clone_composite(dex_dst, methodid)
287 pass
288
289 return cloning
290
291
292 ## \brief Clone and insert a list of _DEX_TypeId objects to a DEXFile_linked.
293 def dexfile_insert_typeids(dex_dst, dex_src, typeids):
294 for typeid in typeids:
295 dexfile_insert_typeid(dex_dst, dex_src, typeid)
296 pass
297 pass
298
299
300 ## \brief Collects relative type IDs and classes definition for given class.
301 def collect_classdef_relative(dex, classdef):
302 rel_classdefs = set([classdef])
303 rel_typeids = set()
304
305 classdef_queue = [classdef]
306 while classdef_queue:
307 cur_classdef = classdef_queue.pop(0)
308
309 classdefs, typeids = _find_class_relative(dex, classdef)
310 rel_typeids.update(typeids)
311 new_classdefs = list(set(classdefs) - rel_classdefs)
312 classdef_queue = classdef_queue + new_classdefs
313 rel_classdefs.update(new_classdefs)
314 pass
315 return rel_classdefs, rel_typeids
316
317
318 ## \brief Clone and insert given and relative classes into another DEXFile.
319 #
320 # \param dex_dst is a DEXFile_linked where the class will be inserted.
321 # \param dex_src is a DEXFile_linked where the cloned class is from.
322 # \param classdef is a _DEX_ClassDef that will be cloned.
323 #
324 def dexfile_insert_class_relative(dex_dst, dex_src, classdef):
325 from paraspace.dexfile import DEXFile_linked
326
327 def classdef_not_in_dst(classdef):
328 classname = DEXFile_linked.get_classdef_name(classdef)
329 try:
330 dex_dst.find_class_name(classname)
331 except ValueError:
332 return True
333 return False
334
335 def typeid_not_in_dst(typeid):
336 typename = DEXFile_linked.get_typeid_name(typeid)
337 try:
338 dex_dst.find_typeid_name(typename)
339 except ValueError:
340 return True
341 return False
342
343 relative_classdefs, relative_typeids = \
344 collect_classdef_relative(dex_src, classdef)
345
346 inserting_classdefs = filter(classdef_not_in_dst, relative_classdefs)
347 inserting_typeids = filter(typeid_not_in_dst, relative_typeids)
348
349 dexfile_insert_classdefs(dex_dst, dex_src, inserting_classdefs)
350 dexfile_insert_typeids(dex_dst, dex_src, inserting_typeids)
351
352 classname = DEXFile_linked.get_classdef_name(classdef)
353 cloning = dex_dst.find_class_name(classname)
354
355 return cloning
218 356
219 357
220 ## \brief Redirect types and methods for the code of given method. 358 ## \brief Redirect types and methods for the code of given method.
221 def method_redirect_types(dex, method, types_redir, methods_redir): 359 def method_redirect_types(dex, method, types_redir, methods_redir):
222 from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes 360 from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes