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

Source Code for Module envi.registers

  1  """
 
  2  Similar to the memory subsystem, this is a unified way to
 
  3  access information about objects which contain registers
 
  4  """ 
  5  
 
  6  import envi.bits as e_bits 
  7  
 
8 -class InvalidRegisterName(Exception):
9 pass
10
11 -class RegisterContext:
12
13 - def __init__(self, regdef=(), metas=(), pcindex=None, spindex=None):
14 """ 15 Hand in a register definition which consists of 16 a list of (<name>, <width>) tuples. 17 """ 18 self.loadRegDef(regdef) 19 self.loadRegMetas(metas) 20 self.setRegisterIndexes(pcindex, spindex) 21 22 self._rctx_dirty = False
23
24 - def getRegisterSnap(self):
25 """ 26 Use this to bulk save off the register state. 27 """ 28 return list(self._rctx_vals)
29
30 - def setRegisterSnap(self, snap):
31 """ 32 Use this to bulk restore the register state. 33 34 NOTE: This may only be used under the assumption that the 35 RegisterContext has been initialized the same way 36 (like context switches in tracers, or emulaction snaps) 37 """ 38 self._rctx_vals = list(snap)
39
40 - def isDirty(self):
41 """ 42 Returns true if registers in this context have been modififed 43 since their import. 44 """ 45 return self._rctx_dirty
46
47 - def setIsDirty(self, bool):
48 self._rctx_dirty = bool
49
50 - def setRegisterIndexes(self, pcindex, spindex):
51 self._rctx_pcindex = pcindex 52 self._rctx_spindex = spindex
53
54 - def loadRegDef(self, regdef, defval=0):
55 """ 56 Load a register definition. A register definition consists 57 of a list of tuples with the following format: 58 (regname, regwidth) 59 60 NOTE: All widths in envi RegisterContexts are in bits. 61 """ 62 self._rctx_regdef = regdef # Save this for snaps etc.. 63 self._rctx_names = {} 64 self._rctx_ids = {} 65 self._rctx_widths = [] 66 self._rctx_vals = [] 67 self._rctx_masks = [] 68 69 for i,(name,width) in enumerate(regdef): 70 self._rctx_names[name] = i 71 self._rctx_ids[i] = name 72 self._rctx_widths.append(width) 73 self._rctx_masks.append((2**width)-1) 74 self._rctx_vals.append(defval)
75
76 - def getRegDef(self):
77 return self._rctx_regdef
78
79 - def loadRegMetas(self, metas):
80 """ 81 Load a set of defined "meta" registers for this architecture. Meta 82 registers are defined as registers who exist as a subset of the bits 83 in some other "real" register. The argument metas is a list of tuples 84 with the following format: 85 (regname, reg_shift_offset, reg_width) 86 The given example is for the AX register in the i386 subsystem 87 regname: "ax" 88 reg_shift_offset: 0 89 reg_width: 16 90 """ 91 self._rctx_regmetas = metas 92 for name,idx,offset,width in metas: 93 self.addMetaRegister(name,idx, offset, width)
94
95 - def addMetaRegister(self, name, idx, offset, width):
96 """ 97 Meta registers are registers which are really just directly 98 addressable parts of already existing registers (eax -> al). 99 100 To add a meta register, you give the name, the idx of the *real* 101 register, the width of the meta reg, and it's left shifted (in bits) 102 offset into the real register value. The RegisterContext will take 103 care of accesses after that. 104 """ 105 newidx = (offset << 24) + (width << 16) + idx 106 self._rctx_names[name] = newidx 107 self._rctx_ids[newidx] = name
108
109 - def isMetaRegister(self, index):
110 return (index & 0xffff) == index
111
112 - def _rctx_Import(self, sobj):
113 """ 114 Given an object with attributes with the same names as 115 registers in our context, populate our values from it. 116 117 NOTE: This also clears the dirty flag 118 """ 119 # On import from a structure, we are clean again. 120 self._rctx_dirty = False 121 for name,idx in self._rctx_names.items(): 122 # Skip meta registers 123 if (idx & 0xffff) != idx: 124 continue 125 x = getattr(sobj, name, None) 126 if x != None: 127 self._rctx_vals[idx] = x
128
129 - def _rctx_Export(self, sobj):
130 """ 131 Given an object with attributes with the same names as 132 registers in our context, set the ones he has to match 133 our values. 134 """ 135 for name,idx in self._rctx_names.items(): 136 # Skip meta registers 137 if (idx & 0xffff) != idx: 138 continue 139 if hasattr(sobj, name): 140 setattr(sobj, name, self._rctx_vals[idx])
141
142 - def reprRegister(self, idx):
143 """ 144 This may be used to allow a register context to provide 145 extended repr (flags breakouts, etc) info about a register. 146 """ 147 width = self._rctx_widths.get(idx) 148 reg = self.getRegisger(idx) 149 return e_bits.hex(reg, width/8)
150
151 - def getRegisterInfo(self, meta=False):
152 """ 153 Return an object which can be stored off, and restored 154 to re-initialize a register context. (much like snapshot 155 but it takes the definitions with it) 156 """ 157 regdef = self._rctx_regdef 158 regmeta = self._rctx_regmetas 159 pcindex = self._rctx_pcindex 160 spindex = self._rctx_spindex 161 snap = self.getRegisterSnap() 162 163 return (regdef, regmeta, pcindex, spindex, snap)
164
165 - def setRegisterInfo(self, info):
166 """ 167 Import the exported data from 168 """ 169 regdef, regmeta, pcindex, spindex, snap = info 170 self.loadRegDef(regdef) 171 self.loadRegMetas(regmeta) 172 self.setRegisterIndexes(pcindex, spindex) 173 self.setRegisterSnap(snap)
174
175 - def getRegisterName(self, index):
176 return self._rctx_ids.get(index,"REG%.8x" % index)
177
178 - def getProgramCounter(self):
179 """ 180 Get the value of the program counter for this register 181 context. 182 """ 183 return self.getRegister(self._rctx_pcindex)
184
185 - def setProgramCounter(self, value):
186 """ 187 Set the value of the program counter for this register 188 contex. 189 """ 190 self.setRegister(self._rctx_pcindex, value)
191
192 - def getStackCounter(self):
193 return self.getRegister(self._rctx_spindex)
194
195 - def setStackCounter(self, value):
196 self.setRegister(self._rctx_spindex, value)
197
198 - def getRegisterByName(self, name):
199 idx = self._rctx_names.get(name) 200 if idx == None: 201 raise InvalidRegisterName("Unknown Register: %s" % name) 202 return self.getRegister(idx)
203
204 - def setRegisterByName(self, name, value):
205 idx = self._rctx_names.get(name) 206 if idx == None: 207 raise InvalidRegisterName("Unknown Register: %s" % name) 208 self.setRegister(idx, value)
209
210 - def getRegisterNames(self):
211 """ 212 """ 213 return self._rctx_names.keys()
214
215 - def getRegisterNameIndexes(self):
216 ''' 217 Return a list of all the "real" (non meta) registers and their indexes. 218 219 Example: for regname, regidx in x.getRegisterNameIndexes(): 220 ''' 221 return self._rctx_names.items()
222
223 - def getRegisters(self):
224 """ 225 Get all the *real* registers from this context as a dictionary of name 226 value pairs. 227 """ 228 ret = {} 229 for name,idx in self._rctx_names.items(): 230 if (idx & 0xffff) != idx: 231 continue 232 ret[name] = self.getRegister(idx) 233 return ret
234
235 - def setRegisters(self, regdict):
236 """ 237 For any name value pairs in the specified dictionary, set the current 238 register values in this context. 239 """ 240 for name,value in regdict.items(): 241 self.setRegisterByName(name, value)
242
243 - def getRegisterIndex(self, name):
244 """ 245 Get a register index by name. 246 (faster to use the index multiple times) 247 """ 248 return self._rctx_names.get(name)
249
250 - def getRegisterWidth(self, index):
251 """ 252 Return the width of the register which lives at the specified 253 index (width is always in bits). 254 """ 255 ridx = index & 0xffff 256 if ridx == index: 257 return self._rctx_widths[index] 258 width = (index >> 16) & 0xff 259 return width
260
261 - def getRegister(self, index):
262 """ 263 Return the current value of the specified register index. 264 """ 265 ridx = index & 0xffff 266 value = self._rctx_vals[ridx] 267 if ridx != index: 268 value = self._xlateToMetaReg(index, value) 269 return value
270
271 - def getMetaRegInfo(self, index):
272 ''' 273 Return the appropriate realreg, shift, mask info 274 for the specified metareg idx (or None if it's not 275 meta). 276 277 Example: 278 real_reg, lshift, mask = r.getMetaRegInfo(x) 279 ''' 280 ridx = index & 0xffff 281 if ridx == index: 282 return None 283 284 offset = (index >> 24) & 0xff 285 width = (index >> 16) & 0xff 286 287 mask = (2**width)-1 288 return ridx, offset, mask
289
290 - def _xlateToMetaReg(self, index, value):
291 ''' 292 Translate a register value to the meta register value 293 (used when getting a meta register) 294 ''' 295 ridx = index & 0xffff 296 offset = (index >> 24) & 0xff 297 width = (index >> 16) & 0xff 298 299 mask = (2**width)-1 300 301 if offset != 0: 302 value >>= offset 303 304 return value & mask
305 306
307 - def _xlateToNativeReg(self, index, value):
308 ''' 309 Translate a register value to the native register value 310 (used when setting a meta register) 311 ''' 312 ridx = index & 0xffff 313 offset = (index >> 24) & 0xff 314 width = (index >> 16) & 0xff 315 316 #FIXME is it faster to generate or look thses up? 317 mask = (2**width)-1 318 mask = mask << offset 319 320 # NOTE: basewidth is in *bits* 321 basewidth = self._rctx_widths[ridx] 322 basemask = (2**basewidth)-1 323 324 # cut a whole in basemask at the size/offset of mask 325 finalmask = basemask ^ mask 326 327 curval = self._rctx_vals[ridx] 328 329 if offset: 330 value <<= offset 331 332 #NOTE value is first for object stuff in symboliks 333 return value | (curval & finalmask)
334
335 - def setRegister(self, index, value):
336 """ 337 Set a register value by index. 338 """ 339 self._rctx_dirty = True 340 341 ridx = index & 0xffff 342 343 # If it's a meta register index, lets mask it into 344 # the real thing... 345 if ridx != index: 346 value = self._xlateToNativeReg(index, value) 347 348 self._rctx_vals[ridx] = (value & self._rctx_masks[ridx])
349
350 -def addLocalEnums(l, regdef):
351 """ 352 Update a dictionary (or module locals) with REG_FOO index 353 values for all the base registers defined in regdef. 354 """ 355 for i,(rname,width) in enumerate(regdef): 356 l["REG_%s" % rname.upper()] = i
357
358 -def addLocalMetas(l, metas):
359 """ 360 Update a dictionary (or module locals) with REG_FOO index 361 values for all meta registers defined in metas. 362 """ 363 for name,idx,offset,width in metas: 364 l["REG_%s" % name.upper()] = (offset << 24) | (width << 16) | idx
365