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.
12 """Models the memory map of a given |backends.Process|.
14 This is typically obtained by calling backends.Process.DumpMemoryMaps()."""
17 self.entries = [] # List of |MapEntry|, sorted by start address.
20 assert(isinstance(entry, MapEntry))
21 bisect.insort_right(self.entries, entry)
23 def Lookup(self, addr):
24 """Returns the MapEntry containing the given address, if any."""
25 idx = bisect.bisect_right(self.entries, addr) - 1
28 entry = self.entries[idx]
29 assert(addr >= entry.start)
30 # bisect_right returns the latest element <= addr, but addr might fall after
31 # its end (in which case we want to return None here).
36 def __getitem__(self, index):
37 return self.entries[index]
40 return len(self.entries)
43 class MapEntry(object):
44 """An entry (address range + stats) in a memory |Map|."""
46 def __init__(self, start, end, prot_flags, mapped_file, mapped_offset,
47 priv_dirty_bytes=0, priv_clean_bytes=0, shared_dirty_bytes=0,
48 shared_clean_bytes=0, resident_pages=None):
53 self.prot_flags = prot_flags
54 self.mapped_file = mapped_file
55 self.mapped_offset = mapped_offset
56 self.priv_dirty_bytes = priv_dirty_bytes
57 self.priv_clean_bytes = priv_clean_bytes
58 self.shared_dirty_bytes = shared_dirty_bytes
59 self.shared_clean_bytes = shared_clean_bytes
60 # resident_pages is a bitmap (array of bytes) in which each bit represents
61 # the presence of its corresponding page.
62 self.resident_pages = resident_pages or []
64 def GetRelativeMMOffset(self, abs_addr):
65 """Converts abs_addr to the corresponding offset in the mm.
68 A tuple: (page_index, offset_in_page)
70 assert(self.Contains(abs_addr))
71 offset = abs_addr - self.start
72 return (offset / PAGE_SIZE, offset & (PAGE_SIZE - 1))
74 def GetRelativeFileOffset(self, abs_addr):
75 """Converts abs_addr to the corresponding offset in the mapped file."""
76 assert(self.Contains(abs_addr))
77 return abs_addr - self.start + self.mapped_offset
79 def IsPageResident(self, relative_page_index):
80 """Checks whether a given memory page is resident in memory."""
81 assert(relative_page_index >= 0 and
82 relative_page_index < self.len / PAGE_SIZE)
83 arr_idx = relative_page_index / 8
84 arr_bit = relative_page_index % 8
85 # Trailing zeros are trimmed by memdump (to optimize dump time).
86 if arr_idx >= len(self.resident_pages):
88 return (self.resident_pages[arr_idx] & (1 << arr_bit)) != 0
90 def Contains(self, abs_addr):
91 """Determines whether a given absolute address belongs to the current mm."""
92 return abs_addr >= self.start and abs_addr <= self.end
94 def __cmp__(self, other):
95 """Comparison operator required for bisect."""
96 if isinstance(other, MapEntry):
97 return self.start - other.start
98 elif isinstance(other, (long, int)):
99 return self.start - other
101 raise Exception('Cannot compare with %s' % other.__class__)
105 return self.end - self.start + 1
109 return self.len / PAGE_SIZE
113 return (self.priv_dirty_bytes + self.priv_clean_bytes +
114 self.shared_dirty_bytes + self.shared_clean_bytes)