| Trees | Indices | Help |
|---|
|
|
1 """
2 x86 Support Module
3 """
4 # Copyright (C) 2007 Invisigoth - See LICENSE file for details
5 import vtrace
6 import struct
7 import traceback
8 import types
9 import vtrace.breakpoints as breakpoints
10
11 import envi.archs.i386 as e_i386
12
13 # Pre-populating these saves a little processing
14 # time (important in tight watchpoint loops)
15 drnames = ["debug%d" % d for d in range(8)]
16
17 dbg_status = "debug6"
18 dbg_ctrl = "debug7"
19
20 dbg_execute = 0
21 dbg_write = 1
22 dbg_read_write = 3
23
24 dbg_types = {
25 "x":dbg_execute,
26 "w":dbg_write,
27 "rw":dbg_read_write,
28 }
29
34 # FIXME change this to storing debug0 index and using setRegister()
35
37
38 idx = None
39 for i in range(4):
40 if not self.hwdebug[i]:
41 idx = i
42 break
43
44 if idx == None:
45 raise Exception("ERROR: there... are... 4... debug registers!")
46
47 pbits = dbg_types.get(perms)
48 if pbits == None:
49 raise Exception("Unsupported watchpoint perms %s (x86 supports x,w,rw)" % perms)
50
51 if pbits == dbg_execute and size != 1:
52 raise Exception("Watchpoint for execute *must* be 1 byte long!")
53
54 if size not in [1,2,4]:
55 raise Exception("Unsupported watchpoint size %d (x86 supports 1,2,4)" % size)
56
57 ctrl = 0
58
59 self.hwdebug[idx] = address
60
61 ctrl |= 1 << (2*idx) # Enabled
62 mask = ((size-1) << 2) + pbits # perms and size
63 ctrl |= (mask << (16+(4*idx)))
64 #ctrl |= 0x100 # Local exact (ignored by p6+ for read)
65
66 for tid in self.getThreads().keys():
67 ctx = self.getRegisterContext(tid)
68 ctrl_orig = ctx.getRegister(e_i386.REG_DEBUG7)
69 #print "debug%d: %.8x debug7: %.8x" % (idx,address,ctrl|ctrl_orig)
70 ctx.setRegister(e_i386.REG_DEBUG7, ctrl_orig | ctrl)
71 ctx.setRegister(e_i386.REG_DEBUG0 + idx, address)
72 return
73
75 idx = None
76 for i in range(4):
77 if self.hwdebug[i] == address:
78 idx = i
79 break
80
81 if idx == None:
82 raise Exception("Watchpoint not found at 0x%.8x" % address)
83
84 self.hwdebug[idx] = 0
85
86 ctrl_disable = ~(1 << (2*idx)) # we are not enabled
87 ctrl_disperm = ~(0xf << (16+(4*idx))) # mask off the rwx stuff
88 ctrl_mask = ctrl_disable & ctrl_disperm
89
90 for tid in self.getThreads().keys():
91 ctx = self.getRegisterContext(tid)
92 ctrl = ctx.getRegister(e_i386.REG_DEBUG7)
93 ctrl &= ctrl_mask
94 #print "debug%d: %.8x debug7: %.8x" % (idx,address,ctrl|ctrl_orig)
95 ctx.setRegister(e_i386.REG_DEBUG7, ctrl)
96 ctx.setRegister(e_i386.REG_DEBUG0 + idx, 0)
97 return
98
100 regs = self.getRegisters()
101 status = regs.get(dbg_status)
102 #print "STATUS %.8x" % status
103 if status == None:
104 return None
105 x = status & 0x0f
106 if not x:
107 return None
108
109 for i in range(4):
110 if (x >> i) & 1:
111 return self.hwdebug[i]
112 return None
113
114
116
118 # Mixin our i386 envi architecture module and register context
119 e_i386.i386Module.__init__(self)
120 # FIXME tracer base should inherit from RegisterContext and we should
121 # just have to load a register definition!
122 e_i386.i386RegisterContext.__init__(self)
123 i386WatchMixin.__init__(self)
124
125 self.setMeta('Architecture', 'i386')
126
128 self.requireAttached()
129 current = 0
130 sanity = 1000
131 frames = []
132
133 #FIXME make these by register index
134 #FIXME make these GPREG stuff! (then both are the same)
135 ebp = self.getRegisterByName("ebp")
136 eip = self.getRegisterByName("eip")
137 frames.append((eip,ebp))
138
139 while ebp != 0 and current < sanity:
140 try:
141 buf = self.readMemory(ebp, 8)
142 ebp,eip = struct.unpack("<LL",buf)
143 frames.append((eip,ebp))
144 current += 1
145 except:
146 break
147
148 return frames
149
151 buf = ""
152 finalargs = []
153 saved_regs = self.getRegisters()
154 sp = self.getStackCounter()
155 pc = self.getProgramCounter()
156
157 for arg in args:
158 if type(arg) == types.StringType: # Nicly map strings into mem
159 buf = arg+"\x00\x00"+buf # Pad with a null for convenience
160 finalargs.append(sp - len(buf))
161 else:
162 finalargs.append(arg)
163
164 m = len(buf) % 4
165 if m:
166 buf = ("\x00" * (4-m)) + buf
167
168 # Args are
169 #finalargs.reverse()
170 buf = struct.pack("<%dI" % len(finalargs), *finalargs) + buf
171
172 # Saved EIP is target addr so when we hit the break...
173 buf = struct.pack("<I", address) + buf
174 # Calc the new stack pointer
175 newsp = sp-len(buf)
176 # Write the stack buffer in
177 self.writeMemory(newsp, buf)
178 # Setup the stack pointer
179 self.setStackCounter(newsp)
180 # Setup the instruction pointer
181 self.setProgramCounter(address)
182 # Add the magical call-break
183 callbreak = breakpoints.CallBreak(address, saved_regs)
184 self.addBreakpoint(callbreak)
185 # Continue until the CallBreak has been hit
186 while not callbreak.endregs:
187 self.run()
188 return callbreak.endregs
189
| Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Fri Nov 16 18:22:29 2012 | http://epydoc.sourceforge.net |