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