Package envi :: Module resolver
[hide private]
[frames] | no frames]

Source Code for Module envi.resolver

  1  """ 
  2  The API describing what it means to be an envi compliant 
  3  symbol resolver. 
  4  """ 
  5   
  6  import types 
  7   
8 -class Symbol:
9
10 - def __init__(self, name, value, size=0, fname=None):
11 self.name = name 12 self.value = value 13 self.size = size 14 self.fname = fname
15
16 - def __eq__(self, other):
17 if not isinstance(other, Symbol): 18 return False 19 return long(self) == long(other)
20
21 - def __coerce__(self, value):
22 t = type(value) 23 if t == types.NoneType: 24 return (True, False) 25 return (value, t(self.value))
26
27 - def __hash__(self):
28 return hash(long(self))
29
30 - def __long__(self):
31 return long(self.value)
32
33 - def __int__(self):
34 return int(self.value)
35
36 - def __len__(self):
37 return self.size
38
39 - def __str__(self):
40 if self.fname != None: 41 return "%s.%s" % (self.fname, self.name) 42 return self.name
43
44 - def __repr__(self):
45 return str(self)
46
47 -class SymbolResolver:
48 49 """ 50 NOTE: Nothing should reach directly into a SymbolResolver! 51 """ 52
53 - def __init__(self, width=4, casesens=True):
54 self.width = width 55 self.widthmask = (2**(width*8))-1 56 self.casesens = casesens 57 # Lets use 4096 byte buckes for now 58 self.bucketsize = 4096 59 self.bucketmask = self.widthmask ^ (self.bucketsize-1) 60 self.buckets = {} 61 self.symnames = {} 62 self.symaddrs = {}
63
64 - def delSymbol(self, sym):
65 """ 66 Delete a symbol from the resolver's namespace 67 """ 68 symval = long(sym) 69 self.symaddrs.pop(symval, None) 70 71 bbase = symval & self.bucketmask 72 while bbase < symval: 73 bucket = self.buckets.get(bbase) 74 bucket.remove(sym) 75 bbase += self.bucketsize 76 77 subres = None 78 if sym.fname != None: 79 subres = self.symnames.get(sym.fname) 80 81 # Potentially del it from the sub resolver's namespace 82 if subres != None: 83 subres.delSymbol(sym) 84 85 # Otherwise del it from our namespace 86 else: 87 symname = sym.name 88 if not self.casesens: 89 symname = symname.lower() 90 self.symnames.pop(symname, None)
91
92 - def addSymbol(self, sym):
93 """ 94 Add a symbol to the resolver. 95 """ 96 # If the symbol has an fname, add it to the namespace 97 # for the FileSymbol inside us rather than our namespace. 98 99 symval = long(sym) 100 self.symaddrs[symval] = sym 101 102 bbase = symval & self.bucketmask 103 while bbase < symval: 104 bucket = self.buckets.get(bbase) 105 if bucket == None: 106 bucket = [] 107 self.buckets[bbase] = bucket 108 bucket.append(sym) 109 bbase += self.bucketsize 110 111 subres = None 112 if sym.fname != None: 113 subres = self.symnames.get(sym.fname) 114 115 # Potentially add it to the sub resolver's namespace 116 if subres != None: 117 subres.addSymbol(sym) 118 119 # Otherwise add it to our namespace 120 else: 121 symname = sym.name 122 if not self.casesens: 123 symname = symname.lower() 124 self.symnames[symname] = sym
125
126 - def getSymByName(self, name):
127 if not self.casesens: 128 name = name.lower() 129 return self.symnames.get(name)
130
131 - def getSymByAddr(self, va, exact=True):
132 """ 133 Return a symbol object for the given virtual address. 134 """ 135 va = va & self.widthmask 136 sym = self.symaddrs.get(va) 137 138 if sym != None: 139 return sym 140 141 if not exact: 142 b = va & self.bucketmask 143 best = 999999999 144 while sym == None: 145 bucket = self.buckets.get(b) 146 if bucket != None: 147 for s in bucket: 148 sva = long(s) 149 if sva > va: 150 continue 151 offset = va - sva 152 if offset < best: 153 best = offset 154 sym = s 155 # If we get more than 8k away, just get out... 156 if va - b > 8192: 157 break 158 # Move back to the previous bucket. 159 b -= self.bucketsize 160 161 # If we resolve a sub-resolver, see if he 162 # has finer resolution than we do... 163 if isinstance(sym, SymbolResolver): 164 ssym = sym.getSymByAddr(va, exact=exact) 165 if ssym != None: 166 return ssym 167 168 return sym
169
170 - def getSymList(self):
171 """ 172 Return a list of the symbols which are contained in this resolver. 173 """ 174 return self.symaddrs.values()
175
176 - def getSymHint(self, va, hidx):
177 """ 178 May be used by symbol resolvers who know what type they are 179 resolving to store and retrieve "hints" with indexes. 180 181 Used specifically by opcode render methods to resolve 182 any memory dereference info for a given operand. 183 184 NOTE: These are mostly symbolic references to FRAME LOCAL 185 names.... 186 """ 187 return None
188 189 # Some extension types 190
191 -class FunctionSymbol(Symbol):
192 """ 193 Used to represent functions. 194 """
195 - def __repr__(self):
196 return "%s.%s()" % (self.fname, self.name)
197
198 -class SectionSymbol(Symbol):
199 """ 200 Used for file sections/segments. 201 """
202 - def __repr__(self):
203 return "%s[%s]" % (self.fname,self.name)
204
205 -class FileSymbol(Symbol,SymbolResolver):
206 """ 207 A file symbol is both a symbol resolver of it's own, and 208 a symbol. 209 210 File symbols are used to do heirarchal symbol lookups and don't 211 actually add anything but the name to their lookup (it is assumed 212 that the parent Resolver of the FileSymbol takes care of addr lookups. 213 """
214 - def __init__(self, fname, base, size, width=4):
215 SymbolResolver.__init__(self, width=width) 216 Symbol.__init__(self, fname, base, size)
217
218 - def __getattr__(self, name):
219 """ 220 File symbols may be dereferenced like python objects to resolve 221 symbols within them. 222 """ 223 ret = self.getSymByName(name) 224 if ret == None: 225 raise AttributeError("%s has no symbol %s" % (self.name,name)) 226 return ret
227
228 - def __getitem__(self, name):
229 """ 230 Allow dictionary style access for mangled incompatible names... 231 """ 232 ret = self.getSymByName(name) 233 if ret == None: 234 raise KeyError("%s has no symbol %s" % (self.name,name)) 235 return ret
236