comparison paraspace/injection.py @ 150:1eb1b2ca5de4

Use classdef_rel_set to carry relative information. - Use an object to carry information of relative objects is more extensible than a tuple. - We can add more information without affecting others.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 16 Aug 2011 14:53:41 +0800
parents d4533a59c694
children 91fabeaffce8
comparison
equal deleted inserted replaced
149:d4533a59c694 150:1eb1b2ca5de4
264 # \param class_def is a class definition going to be cloned. 264 # \param class_def is a class definition going to be cloned.
265 # 265 #
266 def dexfile_insert_class(dex, classdef): 266 def dexfile_insert_class(dex, classdef):
267 clone = _clone_classdef(dex, classdef) 267 clone = _clone_classdef(dex, classdef)
268 return clone 268 return clone
269
270
271 ## \biref Relative object set for a _DEX_ClassData.
272 class classdef_rel_set(object):
273 classdefs = None
274 typeids = None
275 strids = None
276
277 def __init__(self, classdefs, typeids, strids):
278 self.classdefs = set(classdefs)
279 self.typeids = set(typeids)
280 self.strids = set(strids)
281 pass
282
283 @staticmethod
284 def dup(src):
285 return relative_obj_set(src.classdefs, src.typeids, src.strids)
286
287 def update(self, new_data):
288 self.classdefs.update(new_data.classdefs)
289 self.typeids.update(new_data.typeids)
290 self.strids.update(new_data.strids)
291 pass
292 pass
269 293
270 294
271 ## \brief Collect info of classes mentioned by the code of given class. 295 ## \brief Collect info of classes mentioned by the code of given class.
272 def _find_class_relative(dex, classdef): 296 def _find_class_relative(dex, classdef):
273 def classify_typeids_defined(dex, typeids): 297 def classify_typeids_defined(dex, typeids):
290 for typeidx in typeidxs] 314 for typeidx in typeidxs]
291 strids = [dex.find_strid_idx(idx) for idx in stridxs] 315 strids = [dex.find_strid_idx(idx) for idx in stridxs]
292 316
293 classdefs, typeids = classify_typeids_defined(dex, typeids) 317 classdefs, typeids = classify_typeids_defined(dex, typeids)
294 318
295 return classdefs, typeids, strids 319 rel_set = classdef_rel_set(classdefs, typeids, strids)
320 return rel_set
296 321
297 322
298 def dexfile_insert_classdefs(dex_dst, dex_src, classdefs): 323 def dexfile_insert_classdefs(dex_dst, dex_src, classdefs):
299 clones = [dexfile_insert_class(dex_dst, classdef) 324 clones = [dexfile_insert_class(dex_dst, classdef)
300 for classdef in classdefs] 325 for classdef in classdefs]
367 return clones 392 return clones
368 393
369 394
370 ## \brief Collects relative type IDs and classes definition for given class. 395 ## \brief Collects relative type IDs and classes definition for given class.
371 def collect_classdefs_relative(dex, classdefs): 396 def collect_classdefs_relative(dex, classdefs):
372 rel_classdefs = set(classdefs) 397 rel_set = classdef_rel_set(classdefs, [], [])
373 rel_typeids = set()
374 rel_strids = set()
375 398
376 classdef_queue = list(classdefs) 399 classdef_queue = list(classdefs)
377 while classdef_queue: 400 while classdef_queue:
378 cur_classdef = classdef_queue.pop(0) 401 cur_classdef = classdef_queue.pop(0)
379 402
380 classdefs, typeids, strids = _find_class_relative(dex, cur_classdef) 403 new_rel_set = _find_class_relative(dex, cur_classdef)
381 rel_typeids.update(typeids) 404 rel_set.update(new_rel_set)
382 new_classdefs = list(set(classdefs) - rel_classdefs) 405 new_classdefs = new_rel_set.classdefs - rel_set.classdefs
383 classdef_queue = classdef_queue + new_classdefs 406 classdef_queue = classdef_queue + list(new_classdefs)
384 rel_classdefs.update(new_classdefs) 407 pass
385 rel_strids.update(strids) 408 return rel_set
386 pass
387 return rel_classdefs, rel_typeids, rel_strids
388 409
389 410
390 ## \brief Clone and insert given and relative classes into another DEXFile. 411 ## \brief Clone and insert given and relative classes into another DEXFile.
391 # 412 #
392 # \param dex_dst is a DEXFile_linked where the class will be inserted. 413 # \param dex_dst is a DEXFile_linked where the class will be inserted.
403 dex_dst.find_class_name(classname) 424 dex_dst.find_class_name(classname)
404 except ValueError: 425 except ValueError:
405 return True 426 return True
406 return False 427 return False
407 428
408 relative_classdefs, relative_typeids, relative_strids = \ 429 rel_set = collect_classdefs_relative(dex_src, classdefs)
409 collect_classdefs_relative(dex_src, classdefs) 430
410 431 for classdef in rel_set.classdefs:
411 for classdef in relative_classdefs:
412 if classdef_not_in_dst(classdef): 432 if classdef_not_in_dst(classdef):
413 continue 433 continue
414 raise ValueError, '%s is already in DEX %s: can not insert it' % \ 434 raise ValueError, '%s is already in DEX %s: can not insert it' % \
415 (repr(classdef), repr(dex_dst)) 435 (repr(classdef), repr(dex_dst))
416 436
417 cloning_classdefs = \ 437 cloning_classdefs = \
418 dexfile_insert_classdefs(dex_dst, dex_src, relative_classdefs) 438 dexfile_insert_classdefs(dex_dst, dex_src, rel_set.classdefs)
419 cloning_typeids = \ 439 cloning_typeids = \
420 dexfile_insert_or_merge_typeids(dex_dst, dex_src, relative_typeids) 440 dexfile_insert_or_merge_typeids(dex_dst, dex_src, rel_set.typeids)
421 cloning_strids = \ 441 cloning_strids = \
422 dexfile_insert_stringids(dex_dst, dex_src, relative_strids) 442 dexfile_insert_stringids(dex_dst, dex_src, rel_set.strids)
423 443
424 return cloning_classdefs, cloning_typeids, cloning_strids 444 cloning = classdef_rel_set(cloning_classdefs, cloning_typeids,
445 cloning_strids)
446 return cloning
425 447
426 448
427 ## \brief Redirect types, methods and strings for the code of given method. 449 ## \brief Redirect types, methods and strings for the code of given method.
428 def method_redirect_indices(dex, method, typeidxs_redir, methods_redir, 450 def method_redirect_indices(dex, method, typeidxs_redir, methods_redir,
429 stridxs_redir): 451 stridxs_redir):
722 return typeidxs_map 744 return typeidxs_map
723 745
724 746
725 ## \brief Redirect code for methods of injected classes. 747 ## \brief Redirect code for methods of injected classes.
726 def redirect_injected_code(dex_dst, dex_src, classdefs): 748 def redirect_injected_code(dex_dst, dex_src, classdefs):
727 relative_classdefs, relative_typeids, relative_strids = \ 749 rel_set = collect_classdefs_relative(dex_src, classdefs)
728 collect_classdefs_relative(dex_src, classdefs)
729 750
730 typeidxs_redir = \ 751 typeidxs_redir = \
731 make_typeidxs_map_after_injection(dex_dst, dex_src, \ 752 make_typeidxs_map_after_injection(dex_dst, dex_src, \
732 relative_classdefs, \ 753 rel_set.classdefs, \
733 relative_typeids) 754 rel_set.typeids)
734 methodidxs_redir = \ 755 methodidxs_redir = \
735 make_methodidxs_redir_map(dex_src, dex_dst, typeidxs_redir) 756 make_methodidxs_redir_map(dex_src, dex_dst, typeidxs_redir)
736 757
737 stridxs_redir = \ 758 stridxs_redir = \
738 make_stridxs_redir_map(dex_src, dex_dst) 759 make_stridxs_redir_map(dex_src, dex_dst)
756 777
757 assert isinstance(classdefs, (list, tuple)) 778 assert isinstance(classdefs, (list, tuple))
758 assert isinstance(dex_dst, DEXFile_linked) 779 assert isinstance(dex_dst, DEXFile_linked)
759 assert isinstance(dex_src, DEXFile_linked) 780 assert isinstance(dex_src, DEXFile_linked)
760 781
761 injected_classdefs, injected_typeids, injected_strids = \ 782 rel_set = dexfile_insert_classdefs_relative(dex_dst, dex_src, classdefs)
762 dexfile_insert_classdefs_relative(dex_dst, dex_src, classdefs)
763 redirect_injected_code(dex_dst, dex_src, classdefs) 783 redirect_injected_code(dex_dst, dex_src, classdefs)
764 return injected_classdefs 784 return list(rel_set.classdefs)
765 785
766 786
767 ## \brief Redirect all references of given class and its methods. 787 ## \brief Redirect all references of given class and its methods.
768 # 788 #
769 # Redirect all references of given class and its methods to target class. 789 # Redirect all references of given class and its methods to target class.