17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# found in the LICENSE file.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport copy
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport logging
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport sys
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.range_dict import ExclusiveRangeDict
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.policy import PolicySet
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.subcommand import SubCommand
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochLOGGER = logging.getLogger('dmprof')
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass MapCommand(SubCommand):
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __init__(self):
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    super(MapCommand, self).__init__('Usage: %prog map <first-dump> <policy>')
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def do(self, sys_argv, out=sys.stdout):
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    _, args = self._parse_args(sys_argv, 2)
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    dump_path = args[1]
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    target_policy = args[2]
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    (bucket_set, dumps) = SubCommand.load_basic_files(dump_path, True)
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy))
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    MapCommand._output(dumps, bucket_set, policy_set[target_policy], out)
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return 0
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  @staticmethod
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def _output(dumps, bucket_set, policy, out):
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    """Prints all stacktraces in a given component of given depth.
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Args:
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        dumps: A list of Dump objects.
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        bucket_set: A BucketSet object.
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        policy: A Policy object.
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        out: An IO object to output.
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    """
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    max_dump_count = 0
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    range_dict = ExclusiveRangeDict(ListAttribute)
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for dump in dumps:
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      max_dump_count = max(max_dump_count, dump.count)
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      for key, value in dump.iter_map:
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        for begin, end, attr in range_dict.iter_range(key[0], key[1]):
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          attr[dump.count] = value
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    max_dump_count_digit = len(str(max_dump_count))
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for begin, end, attr in range_dict.iter_range():
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      out.write('%x-%x\n' % (begin, end))
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if len(attr) < max_dump_count:
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        attr[max_dump_count] = None
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      for index, value in enumerate(attr[1:]):
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        out.write('  #%0*d: ' % (max_dump_count_digit, index + 1))
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if not value:
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          out.write('None\n')
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        elif value[0] == 'hooked':
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          component_match, _ = policy.find_mmap(value, bucket_set)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          out.write('%s @ %d\n' % (component_match, value[1]['bucket_id']))
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        else:
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          component_match = policy.find_unhooked(value)
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          region_info = value[1]
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          size = region_info['committed']
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          out.write('%s [%d bytes] %s%s%s%s %s\n' % (
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              component_match, size, value[1]['vma']['readable'],
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              value[1]['vma']['writable'], value[1]['vma']['executable'],
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              value[1]['vma']['private'], value[1]['vma']['name']))
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass ListAttribute(ExclusiveRangeDict.RangeAttribute):
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  """Represents a list for an attribute in range_dict.ExclusiveRangeDict."""
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __init__(self):
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    super(ListAttribute, self).__init__()
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    self._list = []
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __str__(self):
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return str(self._list)
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __repr__(self):
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return 'ListAttribute' + str(self._list)
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __len__(self):
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return len(self._list)
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __iter__(self):
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for x in self._list:
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      yield x
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __getitem__(self, index):
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return self._list[index]
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def __setitem__(self, index, value):
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if index >= len(self._list):
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      self._list.extend([None] * (index + 1 - len(self._list)))
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    self._list[index] = value
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def copy(self):
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    new_list = ListAttribute()
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for index, item in enumerate(self._list):
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      new_list[index] = copy.deepcopy(item)
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return new_list
103