Home | History | Annotate | Download | only in subcommands
      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
    103