1# Copyright 2014 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"""This module classifies MemoryMap objects filtering their mmap entries.
6
7Two filters are currently available:
8  - 'mmap_file': 'foo.*\.so': matches any entry which mmap file is foo*.so.
9  - 'mmap_prot': 'rw.-': matches any entry which prot. flags is rw*-.
10"""
11
12import re
13
14from memory_inspector.classification import results
15from memory_inspector.classification import rules
16from memory_inspector.core import exceptions
17from memory_inspector.core import memory_map
18
19
20_RESULT_KEYS = ['RSS', 'Private Dirty', 'Private Clean', 'Shared Dirty',
21                'Shared Clean']
22
23
24def LoadRules(content):
25  """Loads and parses a mmap rule tree from a content (string).
26
27  Returns:
28    An instance of |rules.Rule|, which nodes are |_MmapRule| instances.
29  """
30  return rules.Load(content, _MmapRule)
31
32
33def Classify(mmap, rule_tree):
34  """Create aggregated results of memory maps using the provided rules.
35
36  Args:
37    mmap: the memory map dump being processed (a |memory_map.Map| instance).
38    rule_tree: the user-defined rules that define the filtering categories.
39
40  Returns:
41    An instance of |AggreatedResults|.
42  """
43  assert(isinstance(mmap, memory_map.Map))
44  assert(isinstance(rule_tree, rules.Rule))
45
46  res = results.AggreatedResults(rule_tree, _RESULT_KEYS)
47  for map_entry in mmap.entries:
48    values = [0, map_entry.priv_dirty_bytes, map_entry.priv_clean_bytes,
49              map_entry.shared_dirty_bytes, map_entry.shared_clean_bytes]
50    values[0] = values[1] + values[2] + values[3] + values[4]
51    res.AddToMatchingNodes(map_entry, values)
52  return res
53
54
55class _MmapRule(rules.Rule):
56  def __init__(self, name, filters):
57    super(_MmapRule, self).__init__(name)
58    try:
59      self._file_re = (
60          re.compile(filters['mmap_file']) if 'mmap_file' in filters else None)
61      self._prot_re = (
62          re.compile(filters['mmap_prot']) if 'mmap_prot' in filters else None)
63    except re.error, descr:
64      raise exceptions.MemoryInspectorException(
65        'Regex parse error "%s" : %s' % (filters, descr))
66
67  def Match(self, map_entry):
68    if self._file_re and not self._file_re.search(map_entry.mapped_file):
69      return False
70    if self._prot_re and not self._prot_re.search(map_entry.prot_flags):
71      return False
72    return True