memory_map.py revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 5import bisect 6 7 8class Map(object): 9 """Models the memory map of a given |backends.Process|. 10 11 This is typically obtained by calling backends.Process.DumpMemoryMaps().""" 12 13 def __init__(self): 14 self._entries = [] 15 16 def Add(self, entry): 17 assert(isinstance(entry, MapEntry)) 18 bisect.insort_right(self._entries, entry) 19 20 def Lookup(self, addr): 21 """Returns the MapEntry containing the given address, if any.""" 22 idx = bisect.bisect_right(self._entries, addr) - 1 23 if idx < 0: 24 return None 25 entry = self._entries[idx] 26 assert(addr >= entry.start) 27 # bisect_right returns the latest element <= addr, but addr might fall after 28 # its end (in which case we want to return None here). 29 if addr > entry.end: 30 return None 31 return entry 32 33 def __getitem__(self, index): 34 return self._entries[index] 35 36 def __len__(self): 37 return len(self._entries) 38 39 40class MapEntry(object): 41 """An entry (address range + stats) in a memory |Map|.""" 42 PAGE_SIZE = 4096 43 44 def __init__(self, start, end, prot_flags, mapped_file, mapped_offset): 45 assert(end > start) 46 assert(start >= 0) 47 self.start = start 48 self.end = end 49 self.prot_flags = prot_flags 50 self.mapped_file = mapped_file 51 self.mapped_offset = mapped_offset 52 self.priv_dirty_bytes = 0 53 self.priv_clean_bytes = 0 54 self.shared_dirty_bytes = 0 55 self.shared_clean_bytes = 0 56 # resident_pages is a bitmap (array of bytes) in which each bit represents 57 # the presence of its corresponding page. 58 self.resident_pages = [] 59 60 def GetRelativeOffset(self, abs_addr): 61 """Converts abs_addr to the corresponding offset in the mapped file.""" 62 assert(abs_addr >= self.start and abs_addr <= self.end) 63 return abs_addr - self.start + self.mapped_offset 64 65 def IsPageResident(self, relative_page_index): 66 """Checks whether a given memory page is resident in memory.""" 67 assert(relative_page_index >= 0 and 68 relative_page_index < self.len / MapEntry.PAGE_SIZE) 69 assert(len(self.resident_pages) * MapEntry.PAGE_SIZE * 8 >= self.len) 70 arr_idx = relative_page_index / 8 71 arr_bit = relative_page_index % 8 72 return (self.resident_pages[arr_idx] & (1 << arr_bit)) != 0 73 74 def __cmp__(self, other): 75 """Comparison operator required for bisect.""" 76 if isinstance(other, MapEntry): 77 return self.start - other.start 78 elif isinstance(other, int): 79 return self.start - other 80 else: 81 raise Exception('Cannot compare with %s' % other.__class__) 82 83 @property 84 def len(self): 85 return self.end - self.start + 1 86