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
10
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
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
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
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
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
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
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
120 self._rctx_dirty = False
121 for name,idx in self._rctx_names.items():
122
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
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
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
211 """
212 """
213 return self._rctx_names.keys()
214
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
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
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
317 mask = (2**width)-1
318 mask = mask << offset
319
320
321 basewidth = self._rctx_widths[ridx]
322 basemask = (2**basewidth)-1
323
324
325 finalmask = basemask ^ mask
326
327 curval = self._rctx_vals[ridx]
328
329 if offset:
330 value <<= offset
331
332
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
344
345 if ridx != index:
346 value = self._xlateToNativeReg(index, value)
347
348 self._rctx_vals[ridx] = (value & self._rctx_masks[ridx])
349
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
365