OLD | NEW |
(Empty) | |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import copy |
| 6 import logging |
| 7 import sys |
| 8 |
| 9 from lib.range_dict import ExclusiveRangeDict |
| 10 from lib.policy import PolicySet |
| 11 from lib.subcommand import SubCommand |
| 12 |
| 13 |
| 14 LOGGER = logging.getLogger('dmprof') |
| 15 |
| 16 |
| 17 class MapCommand(SubCommand): |
| 18 def __init__(self): |
| 19 super(MapCommand, self).__init__('Usage: %prog map <first-dump> <policy>') |
| 20 |
| 21 def do(self, sys_argv, out=sys.stdout): |
| 22 _, args = self._parse_args(sys_argv, 2) |
| 23 dump_path = args[1] |
| 24 target_policy = args[2] |
| 25 (bucket_set, dumps) = SubCommand.load_basic_files(dump_path, True) |
| 26 policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy)) |
| 27 |
| 28 MapCommand._output(dumps, bucket_set, policy_set[target_policy], out) |
| 29 return 0 |
| 30 |
| 31 @staticmethod |
| 32 def _output(dumps, bucket_set, policy, out): |
| 33 """Prints all stacktraces in a given component of given depth. |
| 34 |
| 35 Args: |
| 36 dumps: A list of Dump objects. |
| 37 bucket_set: A BucketSet object. |
| 38 policy: A Policy object. |
| 39 out: An IO object to output. |
| 40 """ |
| 41 max_dump_count = 0 |
| 42 range_dict = ExclusiveRangeDict(ListAttribute) |
| 43 for dump in dumps: |
| 44 max_dump_count = max(max_dump_count, dump.count) |
| 45 for key, value in dump.iter_map: |
| 46 for begin, end, attr in range_dict.iter_range(key[0], key[1]): |
| 47 attr[dump.count] = value |
| 48 |
| 49 max_dump_count_digit = len(str(max_dump_count)) |
| 50 for begin, end, attr in range_dict.iter_range(): |
| 51 out.write('%x-%x\n' % (begin, end)) |
| 52 if len(attr) < max_dump_count: |
| 53 attr[max_dump_count] = None |
| 54 for index, value in enumerate(attr[1:]): |
| 55 out.write(' #%0*d: ' % (max_dump_count_digit, index + 1)) |
| 56 if not value: |
| 57 out.write('None\n') |
| 58 elif value[0] == 'hooked': |
| 59 component_match, _ = policy.find_mmap(value, bucket_set) |
| 60 out.write('%s @ %d\n' % (component_match, value[1]['bucket_id'])) |
| 61 else: |
| 62 component_match = policy.find_unhooked(value) |
| 63 region_info = value[1] |
| 64 size = region_info['committed'] |
| 65 out.write('%s [%d bytes] %s%s%s%s %s\n' % ( |
| 66 component_match, size, value[1]['vma']['readable'], |
| 67 value[1]['vma']['writable'], value[1]['vma']['executable'], |
| 68 value[1]['vma']['private'], value[1]['vma']['name'])) |
| 69 |
| 70 |
| 71 class ListAttribute(ExclusiveRangeDict.RangeAttribute): |
| 72 """Represents a list for an attribute in range_dict.ExclusiveRangeDict.""" |
| 73 def __init__(self): |
| 74 super(ListAttribute, self).__init__() |
| 75 self._list = [] |
| 76 |
| 77 def __str__(self): |
| 78 return str(self._list) |
| 79 |
| 80 def __repr__(self): |
| 81 return 'ListAttribute' + str(self._list) |
| 82 |
| 83 def __len__(self): |
| 84 return len(self._list) |
| 85 |
| 86 def __iter__(self): |
| 87 for x in self._list: |
| 88 yield x |
| 89 |
| 90 def __getitem__(self, index): |
| 91 return self._list[index] |
| 92 |
| 93 def __setitem__(self, index, value): |
| 94 if index >= len(self._list): |
| 95 self._list.extend([None] * (index + 1 - len(self._list))) |
| 96 self._list[index] = value |
| 97 |
| 98 def copy(self): |
| 99 new_list = ListAttribute() |
| 100 for index, item in enumerate(self._list): |
| 101 new_list[index] = copy.deepcopy(item) |
| 102 return new_list |
OLD | NEW |