comparison paraspace/dex_deptracker.py @ 53:705356005362

Fix bug of install marker through ref
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 22 Jun 2011 20:22:03 +0800
parents 67aa8ca8fff3
children 870312703ba1
comparison
equal deleted inserted replaced
52:67aa8ca8fff3 53:705356005362
8 8
9 def _resolve_name_path(name_path): 9 def _resolve_name_path(name_path):
10 obj = dexfile 10 obj = dexfile
11 parent = None 11 parent = None
12 for name in name_path.split('.'): 12 for name in name_path.split('.'):
13 while isinstance(obj, _marker):
14 obj = obj.back_type
15 pass
16
13 if isinstance(parent, dexfile.array) and obj == list: 17 if isinstance(parent, dexfile.array) and obj == list:
14 # array.items.<num> 18 # array.items.<num>
15 obj = parent.child_type 19 obj = parent.child_type
16 parent = list 20 parent = list
17 continue 21 continue
251 if name.startswith('_DEX_')]) 255 if name.startswith('_DEX_')])
252 dex_types['DEXFile'] = dexfile.DEXFile 256 dex_types['DEXFile'] = dexfile.DEXFile
253 return dex_types 257 return dex_types
254 258
255 259
260 def _all_dex_type_to_names():
261 def check_marker(value, name):
262 while isinstance(value, _marker):
263 value = value.back_type
264 pass
265 return value, name
266
267 dex_types = dict([check_marker(value, name)
268 for name, value in dexfile.__dict__.items()
269 if name.startswith('_DEX_')])
270 dex_types[dexfile.DEXFile] = 'DEXFile'
271 return dex_types
272
273
256 def collect_all_dep_decls(): 274 def collect_all_dep_decls():
257 dex_types = _all_dex_types() 275 dex_types = _all_dex_types()
258 276
259 all_dep_decls = {} 277 all_dep_decls = {}
260 for name_path, clazz in dex_types.items(): 278 for name_path, clazz in dex_types.items():
265 return all_dep_decls 283 return all_dep_decls
266 284
267 285
268 class _marker(dexfile.null_relocatable): 286 class _marker(dexfile.null_relocatable):
269 back_type = None 287 back_type = None
288
289 def set_marker(self, obj, off):
290 raise NotImplementedError, \
291 'The marker does not implement set_marker()'
270 pass 292 pass
271 293
272 class _uid_marker(_marker): 294 class _uid_marker(_marker):
273 uid_seq = 0 295 uid_seq = 0
274 296
281 value = self.back_type.parse(parent, data, off) 303 value = self.back_type.parse(parent, data, off)
282 try: 304 try:
283 value.data_uid = _uid_marker.uid_seq 305 value.data_uid = _uid_marker.uid_seq
284 except AttributeError: 306 except AttributeError:
285 raise AttributeError, \ 307 raise AttributeError, \
286 'can not depend on non-instance (%s)' % (self.name_path) 308 'can not depend on non-instance (%s/%s)' % \
309 (self.name_path, repr(value))
287 _uid_marker.uid_seq = _uid_marker.uid_seq + 1 310 _uid_marker.uid_seq = _uid_marker.uid_seq + 1
288 311
289 return value 312 return value
290 313
291 def sizeof(self, value): 314 def sizeof(self, value):
313 def __getattr__(self, name): 336 def __getattr__(self, name):
314 return getattr(self.back_type, name) 337 return getattr(self.back_type, name)
315 338
316 def __call__(self, *args, **kws): 339 def __call__(self, *args, **kws):
317 return self.back_type(*args, **kws) 340 return self.back_type(*args, **kws)
341
342 def set_marker(self, obj, off):
343 pass
318 pass 344 pass
319 345
320 346
321 class _offset_marker(_uid_marker): 347 class _offset_marker(_uid_marker):
322 def parse(self, parent, data, off): 348 def parse(self, parent, data, off):
333 id_item_map = {} 359 id_item_map = {}
334 markers_info[name_path] = id_item_map 360 markers_info[name_path] = id_item_map
335 pass 361 pass
336 assert obj.data_offset not in id_item_map 362 assert obj.data_offset not in id_item_map
337 id_item_map[obj.data_offset] = obj 363 id_item_map[obj.data_offset] = obj
364 pass
365
366 def set_marker(self, obj, off):
367 obj.data_offset = off
338 pass 368 pass
339 pass 369 pass
340 370
341 371
342 class _rel_offset_marker(_offset_marker): 372 class _rel_offset_marker(_offset_marker):
385 depon = depons[0] 415 depon = depons[0]
386 return depon 416 return depon
387 pass 417 pass
388 418
389 raise RuntimeError, 'can not find relative offset depend' 419 raise RuntimeError, 'can not find relative offset depend'
420
421 def set_marker(self, obj, off):
422 obj.data_offset = off
423 pass
390 pass 424 pass
391 425
392 426
393 class _idx_marker(_uid_marker): 427 class _idx_marker(_uid_marker):
394 def parse(self, parent, data, off): 428 def parse(self, parent, data, off):
409 pass 443 pass
410 for idx, item in enumerate(obj.items): 444 for idx, item in enumerate(obj.items):
411 id_item_map[idx] = item 445 id_item_map[idx] = item
412 pass 446 pass
413 pass 447 pass
448
449 def set_marker(self, obj, off):
450 pass
414 pass 451 pass
415 452
416 453
417 def _install_offset_marker(name_path): 454 def _install_offset_marker(name_path):
418 obj, parent = _resolve_name_path(name_path) 455 obj, parent = _resolve_name_path(name_path)
419 while isinstance(parent, dexfile.ref): 456 while isinstance(obj, dexfile.ref):
420 obj, parent = _resolve_name_path(parent.target_path) 457 name_path = obj.target_path
458 obj, parent = _resolve_name_path(name_path)
421 pass 459 pass
422 marker = _offset_marker(obj, name_path) 460 marker = _offset_marker(obj, name_path)
423 name = name_path.split('.')[-1] 461 name = name_path.split('.')[-1]
424 _dex_tree_set_child(parent, name, marker) 462 _dex_tree_set_child(parent, name, marker)
425 pass 463 pass
426 464
427 465
428 def _install_rel_offset_marker(name_path): 466 def _install_rel_offset_marker(name_path):
429 obj, parent = _resolve_name_path(name_path) 467 obj, parent = _resolve_name_path(name_path)
430 while isinstance(parent, dexfile.ref): 468 while isinstance(obj, dexfile.ref):
431 obj, parent = _resolve_name_path(parent.target_path) 469 name_path = obj.target_path
470 obj, parent = _resolve_name_path(name_path)
432 pass 471 pass
433 marker = _rel_offset_marker(obj, name_path) 472 marker = _rel_offset_marker(obj, name_path)
434 name = name_path.split('.')[-1] 473 name = name_path.split('.')[-1]
435 _dex_tree_set_child(parent, name, marker) 474 _dex_tree_set_child(parent, name, marker)
436 pass 475 pass
437 476
438 477
439 def _install_uid_marker(name_path): 478 def _install_uid_marker(name_path):
440 obj, parent = _resolve_name_path(name_path) 479 obj, parent = _resolve_name_path(name_path)
441 while isinstance(parent, dexfile.ref): 480 while isinstance(obj, dexfile.ref):
442 obj, parent = _resolve_name_path(parent.target_path) 481 name_path = obj.target_path
482 obj, parent = _resolve_name_path(name_path)
443 pass 483 pass
444 marker = _uid_marker(obj, name_path) 484 marker = _uid_marker(obj, name_path)
445 name = name_path.split('.')[-1] 485 name = name_path.split('.')[-1]
446 _dex_tree_set_child(parent, name, marker) 486 _dex_tree_set_child(parent, name, marker)
447 pass 487 pass
448 488
449 489
450 def _install_idx_marker(name_path): 490 def _install_idx_marker(name_path):
451 obj, parent = _resolve_name_path(name_path) 491 obj, parent = _resolve_name_path(name_path)
452 while isinstance(parent, dexfile.ref): 492 while isinstance(obj, dexfile.ref):
453 obj, parent = _resolve_name_path(parent.target_path) 493 name_path = obj.target_path
494 obj, parent = _resolve_name_path(name_path)
454 pass 495 pass
455 marker = _idx_marker(obj, name_path) 496 marker = _idx_marker(obj, name_path)
456 name = name_path.split('.')[-1] 497 name = name_path.split('.')[-1]
457 _dex_tree_set_child(parent, name, marker) 498 _dex_tree_set_child(parent, name, marker)
458 pass 499 pass
628 _travel_dex_relocatable(root_obj): 669 _travel_dex_relocatable(root_obj):
629 if name_path not in markers_info: 670 if name_path not in markers_info:
630 continue 671 continue
631 672
632 marker, dummy_parent = _resolve_name_path(name_path) 673 marker, dummy_parent = _resolve_name_path(name_path)
674 while isinstance(marker, dexfile.ref):
675 marker, dummy = _resolve_name_path(marker.target_path)
676 pass
633 marker.link_prepare(obj, name_path, parents, markers_info) 677 marker.link_prepare(obj, name_path, parents, markers_info)
634 pass 678 pass
635 679
636 # 680 #
637 # Link depend source to marked target 681 # Link depend source to marked target
675 _link_dependencies(dexroot, all_dep_decls) 719 _link_dependencies(dexroot, all_dep_decls)
676 pass 720 pass
677 721
678 722
679 def _build_depon_dep_map(all_dep_decls): 723 def _build_depon_dep_map(all_dep_decls):
724 from itertools import chain
725
680 def _build_sub_depon_dep(from_path, dep): 726 def _build_sub_depon_dep(from_path, dep):
681 depon1 = dep[1] 727 depon1 = dep[1]
682 sub = [(depon1, from_path)] 728 sub = [(depon1, from_path)]
683 dep_type = dep[0] 729 dep_type = dep[0]
684 if dep_type == dexfile.depend_off_rel: 730 if dep_type == dexfile.depend_off_rel:
690 736
691 depon_dep_lsts = [_build_sub_depon_dep(from_path, dep) 737 depon_dep_lsts = [_build_sub_depon_dep(from_path, dep)
692 for from_path, dep in all_dep_decls.items()] 738 for from_path, dep in all_dep_decls.items()]
693 depon_dep_lst = chain(*depon_dep_lsts) 739 depon_dep_lst = chain(*depon_dep_lsts)
694 depon_dep_map = dict(depon_dep_lst) 740 depon_dep_map = dict(depon_dep_lst)
695 pass 741 return depon_dep_map
696 742
697 743
698 def update_offset(dexroot, all_dep_decls): 744 def update_offset(dexroot, all_dep_decls):
699 from dexfile import man_off 745 from dexfile import man_off
746
747 depon_dep_map = _build_depon_dep_map(all_dep_decls)
748 dex_type_names = _all_dex_type_to_names()
749
750 def make_path(obj, path_parts, obj_name):
751 if isinstance(obj, dexfile.composite):
752 type_name = dex_type_names[obj.__class__]
753 return [type_name]
754 return path_parts + [obj_name]
700 755
701 moff = man_off(0) 756 moff = man_off(0)
702 queue = [dexroot] 757 queue = [(dexroot, ['DEXFile'])]
703 758
704 while queue: 759 while queue:
705 obj = queue.pop() 760 obj, path_parts = queue.pop()
706 if isinstance(obj, _marker): 761 name_path = '.'.join(path_parts)
707 obj.set_marker(moff()) 762
708 pass 763 if name_path in depon_dep_map:
709 if isinstance(obj, dexfile.relocatable): 764 marker, dummy = _resolve_name_path(name_path)
710 moff(obj.sizeof()) 765 marker.set_marker(obj, moff())
711 pass 766 pass
767
768 if isinstance(obj, (tuple, list)):
769 attrs = [(elt, path_parts + [str(idx)])
770 for idx, elt in enumerate(obj)]
771 attrs.reverse()
772 queue = queue + attrs
773 continue
712 774
713 if isinstance(obj, dexfile.ref): 775 if isinstance(obj, dexfile.ref):
714 continue 776 continue
777
715 if not isinstance(obj, dexfile.relocatable): 778 if not isinstance(obj, dexfile.relocatable):
716 continue 779 clazz, parent = _resolve_name_path(name_path)
717 780 moff(clazz.sizeof(obj))
718 children = list(obj.children()) 781 continue
719 attrs = [_dex_tree_get_child(obj, child) 782
720 for child in children] 783 moff(obj.sizeof(obj))
784
785 children = obj.children()
786 attr_n_names = [(_dex_tree_get_child(obj, child_name), child_name)
787 for child_name in children]
788 attrs = [(attr, make_path(attr, path_parts, attr_name))
789 for attr, attr_name in attr_n_names]
721 attrs.reverse() 790 attrs.reverse()
722 queue = queue + attrs 791 queue = queue + attrs
723 pass 792 pass
724 pass 793 pass
725 794