1# Copyright (c) 2012 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 re 6 7 8_MAPS_PATTERN = re.compile( 9 r'^([a-f0-9]+)-([a-f0-9]+)\s+(.)(.)(.)(.)\s+([a-f0-9]+)\s+(\S+):(\S+)\s+' 10 r'(\d+)\s*(.*)$', re.IGNORECASE) 11 12 13class ProcMapsEntry(object): 14 """A class representing one line in /proc/.../maps.""" 15 16 def __init__( 17 self, begin, end, readable, writable, executable, private, offset, 18 major, minor, inode, name): 19 self.begin = begin 20 self.end = end 21 self.readable = readable 22 self.writable = writable 23 self.executable = executable 24 self.private = private 25 self.offset = offset 26 self.major = major 27 self.minor = minor 28 self.inode = inode 29 self.name = name 30 31 def as_dict(self): 32 return { 33 'begin': self.begin, 34 'end': self.end, 35 'readable': self.readable, 36 'writable': self.writable, 37 'executable': self.executable, 38 'private': self.private, 39 'offset': self.offset, 40 'major': self.major, 41 'minor': self.minor, 42 'inode': self.inode, 43 'name': self.name, 44 } 45 46 47class ProcMaps(object): 48 """A class representing contents in /proc/.../maps.""" 49 50 def __init__(self): 51 self._sorted_indexes = [] 52 self._dictionary = {} 53 self._sorted = True 54 55 def iter(self, condition): 56 if not self._sorted: 57 self._sorted_indexes.sort() 58 self._sorted = True 59 for index in self._sorted_indexes: 60 if not condition or condition(self._dictionary[index]): 61 yield self._dictionary[index] 62 63 def __iter__(self): 64 if not self._sorted: 65 self._sorted_indexes.sort() 66 self._sorted = True 67 for index in self._sorted_indexes: 68 yield self._dictionary[index] 69 70 @staticmethod 71 def load(f): 72 table = ProcMaps() 73 for line in f: 74 table.append_line(line) 75 return table 76 77 def append_line(self, line): 78 entry = self.parse_line(line) 79 if entry: 80 self._append_entry(entry) 81 82 @staticmethod 83 def parse_line(line): 84 matched = _MAPS_PATTERN.match(line) 85 if matched: 86 return ProcMapsEntry( # pylint: disable=W0212 87 int(matched.group(1), 16), # begin 88 int(matched.group(2), 16), # end 89 matched.group(3), # readable 90 matched.group(4), # writable 91 matched.group(5), # executable 92 matched.group(6), # private 93 int(matched.group(7), 16), # offset 94 matched.group(8), # major 95 matched.group(9), # minor 96 int(matched.group(10), 10), # inode 97 matched.group(11) # name 98 ) 99 else: 100 return None 101 102 @staticmethod 103 def constants(entry): 104 return (entry.writable == '-' and entry.executable == '-' and re.match( 105 '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', 106 entry.name)) 107 108 @staticmethod 109 def executable(entry): 110 return (entry.executable == 'x' and re.match( 111 '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', 112 entry.name)) 113 114 @staticmethod 115 def executable_and_constants(entry): 116 return (((entry.writable == '-' and entry.executable == '-') or 117 entry.executable == 'x') and re.match( 118 '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', 119 entry.name)) 120 121 def _append_entry(self, entry): 122 if self._sorted_indexes and self._sorted_indexes[-1] > entry.begin: 123 self._sorted = False 124 self._sorted_indexes.append(entry.begin) 125 self._dictionary[entry.begin] = entry 126