| Home | Trees | Indices | Help |
|
|---|
|
|
1 # Copyright (c) 2009, Mario Vilas
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 #
7 # * Redistributions of source code must retain the above copyright notice,
8 # this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above copyright
10 # notice,this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution.
12 # * Neither the name of the copyright holder nor the names of its
13 # contributors may be used to endorse or promote products derived from
14 # this software without specific prior written permission.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 # POSSIBILITY OF SUCH DAMAGE.
27
28 """
29 Debugging API wrappers in ctypes.
30
31 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/Win32APIWrappers}
32 """
33
34 __revision__ = "$Id: context_i386.py 382 2009-08-25 21:20:54Z QvasiModo $"
35
36 from defines import *
37
38 # The following values specify the type of access in the first parameter
39 # of the exception record whan the exception code specifies an access
40 # violation.
41 EXCEPTION_READ_FAULT = 0 # exception caused by a read
42 EXCEPTION_WRITE_FAULT = 1 # exception caused by a write
43 EXCEPTION_EXECUTE_FAULT = 8 # exception caused by an instruction fetch
44
45 CONTEXT_i386 = 0x00010000 # this assumes that i386 and
46 CONTEXT_i486 = 0x00010000 # i486 have identical context records
47
48 CONTEXT_CONTROL = (CONTEXT_i386 | 0x00000001L) # SS:SP, CS:IP, FLAGS, BP
49 CONTEXT_INTEGER = (CONTEXT_i386 | 0x00000002L) # AX, BX, CX, DX, SI, DI
50 CONTEXT_SEGMENTS = (CONTEXT_i386 | 0x00000004L) # DS, ES, FS, GS
51 CONTEXT_FLOATING_POINT = (CONTEXT_i386 | 0x00000008L) # 387 state
52 CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x00000010L) # DB 0-3,6,7
53 CONTEXT_EXTENDED_REGISTERS = (CONTEXT_i386 | 0x00000020L) # cpu specific extensions
54
55 CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
56
57 CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
58 CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \
59 CONTEXT_EXTENDED_REGISTERS)
60
61 SIZE_OF_80387_REGISTERS = 80
62 MAXIMUM_SUPPORTED_EXTENSION = 512
63
64 # typedef struct _FLOATING_SAVE_AREA {
65 # DWORD ControlWord;
66 # DWORD StatusWord;
67 # DWORD TagWord;
68 # DWORD ErrorOffset;
69 # DWORD ErrorSelector;
70 # DWORD DataOffset;
71 # DWORD DataSelector;
72 # BYTE RegisterArea[SIZE_OF_80387_REGISTERS];
73 # DWORD Cr0NpxState;
74 # } FLOATING_SAVE_AREA;
75 -class FLOATING_SAVE_AREA(Structure):
76 _pack_ = 1
77 _fields_ = [
78 ('ControlWord', DWORD),
79 ('StatusWord', DWORD),
80 ('TagWord', DWORD),
81 ('ErrorOffset', DWORD),
82 ('ErrorSelector', DWORD),
83 ('DataOffset', DWORD),
84 ('DataSelector', DWORD),
85 ('RegisterArea', BYTE * SIZE_OF_80387_REGISTERS),
86 ('Cr0NpxState', DWORD),
87 ]
88
89 _integer_members = ('ControlWord', 'StatusWord', 'TagWord', 'ErrorOffset', 'ErrorSelector', 'DataOffset', 'DataSelector', 'Cr0NpxState')
90
91 @classmethod
93 'Instance a new structure from a Python dictionary.'
94 fsa = dict(fsa)
95 s = cls()
96 for key in cls._integer_members:
97 setattr(s, key, fsa.get(key))
98 ra = fsa.get('RegisterArea', None)
99 if ra is not None:
100 for index in xrange(0, SIZE_OF_80387_REGISTERS):
101 s.RegisterArea[index] = ra[index]
102 return s
103
105 'Convert a structure into a Python dictionary.'
106 fsa = dict()
107 for key in self._integer_members:
108 fsa[key] = getattr(self, key)
109 ra = [ self.RegisterArea[index] for index in xrange(0, SIZE_OF_80387_REGISTERS) ]
110 ra = tuple(ra)
111 fsa['RegisterArea'] = ra
112 return fsa
113
114 PFLOATING_SAVE_AREA = POINTER(FLOATING_SAVE_AREA)
115 LPFLOATING_SAVE_AREA = PFLOATING_SAVE_AREA
116
117 # typedef struct _CONTEXT {
118 # DWORD ContextFlags;
119 # DWORD Dr0;
120 # DWORD Dr1;
121 # DWORD Dr2;
122 # DWORD Dr3;
123 # DWORD Dr6;
124 # DWORD Dr7;
125 # FLOATING_SAVE_AREA FloatSave;
126 # DWORD SegGs;
127 # DWORD SegFs;
128 # DWORD SegEs;
129 # DWORD SegDs;
130 # DWORD Edi;
131 # DWORD Esi;
132 # DWORD Ebx;
133 # DWORD Edx;
134 # DWORD Ecx;
135 # DWORD Eax;
136 # DWORD Ebp;
137 # DWORD Eip;
138 # DWORD SegCs;
139 # DWORD EFlags;
140 # DWORD Esp;
141 # DWORD SegSs;
142 # BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
143 # } CONTEXT;
144 -class CONTEXT(Structure):
145 arch = 'i386'
146
147 _pack_ = 1
148
149 # Context Frame
150 #
151 # This frame has a several purposes: 1) it is used as an argument to
152 # NtContinue, 2) is is used to constuct a call frame for APC delivery,
153 # and 3) it is used in the user level thread creation routines.
154 #
155 # The layout of the record conforms to a standard call frame.
156
157 _fields_ = [
158
159 # The flags values within this flag control the contents of
160 # a CONTEXT record.
161 #
162 # If the context record is used as an input parameter, then
163 # for each portion of the context record controlled by a flag
164 # whose value is set, it is assumed that that portion of the
165 # context record contains valid context. If the context record
166 # is being used to modify a threads context, then only that
167 # portion of the threads context will be modified.
168 #
169 # If the context record is used as an IN OUT parameter to capture
170 # the context of a thread, then only those portions of the thread's
171 # context corresponding to set flags will be returned.
172 #
173 # The context record is never used as an OUT only parameter.
174
175 ('ContextFlags', DWORD),
176
177 # This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
178 # set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
179 # included in CONTEXT_FULL.
180
181 ('Dr0', DWORD),
182 ('Dr1', DWORD),
183 ('Dr2', DWORD),
184 ('Dr3', DWORD),
185 ('Dr6', DWORD),
186 ('Dr7', DWORD),
187
188 # This section is specified/returned if the
189 # ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
190
191 ('FloatSave', FLOATING_SAVE_AREA),
192
193 # This section is specified/returned if the
194 # ContextFlags word contains the flag CONTEXT_SEGMENTS.
195
196 ('SegGs', DWORD),
197 ('SegFs', DWORD),
198 ('SegEs', DWORD),
199 ('SegDs', DWORD),
200
201 # This section is specified/returned if the
202 # ContextFlags word contains the flag CONTEXT_INTEGER.
203
204 ('Edi', DWORD),
205 ('Esi', DWORD),
206 ('Ebx', DWORD),
207 ('Edx', DWORD),
208 ('Ecx', DWORD),
209 ('Eax', DWORD),
210
211 # This section is specified/returned if the
212 # ContextFlags word contains the flag CONTEXT_CONTROL.
213
214 ('Ebp', DWORD),
215 ('Eip', DWORD),
216 ('SegCs', DWORD), # MUST BE SANITIZED
217 ('EFlags', DWORD), # MUST BE SANITIZED
218 ('Esp', DWORD),
219 ('SegSs', DWORD),
220
221 # This section is specified/returned if the ContextFlags word
222 # contains the flag CONTEXT_EXTENDED_REGISTERS.
223 # The format and contexts are processor specific.
224
225 ('ExtendedRegisters', BYTE * MAXIMUM_SUPPORTED_EXTENSION),
226 ]
227
228 _ctx_debug = ('Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7')
229 _ctx_segs = ('SegGs', 'SegFs', 'SegEs', 'SegDs', )
230 _ctx_int = ('Edi', 'Esi', 'Ebx', 'Edx', 'Ecx', 'Eax')
231 _ctx_ctrl = ('Ebp', 'Eip', 'SegCs', 'EFlags', 'Esp', 'SegSs')
232
233 @classmethod
235 'Instance a new structure from a Python dictionary.'
236 ctx = Context(ctx)
237 s = cls()
238 ContextFlags = ctx['ContextFlags']
239 setattr(s, 'ContextFlags', ContextFlags)
240 if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS:
241 for key in s._ctx_debug:
242 setattr(s, key, ctx[key])
243 if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT:
244 fsa = ctx['FloatSave']
245 s.FloatSave = FLOATING_SAVE_AREA.from_dict(fsa)
246 if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS:
247 for key in s._ctx_segs:
248 setattr(s, key, ctx[key])
249 if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER:
250 for key in s._ctx_int:
251 setattr(s, key, ctx[key])
252 if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL:
253 for key in s._ctx_ctrl:
254 setattr(s, key, ctx[key])
255 if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS:
256 er = ctx['ExtendedRegisters']
257 for index in xrange(0, MAXIMUM_SUPPORTED_EXTENSION):
258 s.ExtendedRegisters[index] = er[index]
259 return s
260
262 'Convert a structure into a Python dictionary.'
263 ctx = Context()
264 ContextFlags = self.ContextFlags
265 ctx['ContextFlags'] = ContextFlags
266 if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS:
267 for key in self._ctx_debug:
268 ctx[key] = getattr(self, key)
269 if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT:
270 ctx['FloatSave'] = self.FloatSave.to_dict()
271 if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS:
272 for key in self._ctx_segs:
273 ctx[key] = getattr(self, key)
274 if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER:
275 for key in self._ctx_int:
276 ctx[key] = getattr(self, key)
277 if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL:
278 for key in self._ctx_ctrl:
279 ctx[key] = getattr(self, key)
280 if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS:
281 er = [ self.ExtendedRegisters[index] for index in xrange(0, MAXIMUM_SUPPORTED_EXTENSION) ]
282 er = tuple(er)
283 ctx['ExtendedRegisters'] = er
284 return ctx
285
286 PCONTEXT = POINTER(CONTEXT)
287 LPCONTEXT = PCONTEXT
290 """
291 Register context dictionary for the %s architecture.
292 """ % CONTEXT.arch
293 arch = CONTEXT.arch
294
298 self['Eip'] = value
299 pc = property(__get_pc, __set_pc)
300
304 self['Esp'] = value
305 sp = property(__get_sp, __set_sp)
306
310 self['Ebp'] = value
311 fp = property(__get_fp, __set_fp)
312
313 #--- LDT_ENTRY structure ------------------------------------------------------
314
315 # typedef struct _LDT_ENTRY {
316 # WORD LimitLow;
317 # WORD BaseLow;
318 # union {
319 # struct {
320 # BYTE BaseMid;
321 # BYTE Flags1;
322 # BYTE Flags2;
323 # BYTE BaseHi;
324 # } Bytes;
325 # struct {
326 # DWORD BaseMid :8;
327 # DWORD Type :5;
328 # DWORD Dpl :2;
329 # DWORD Pres :1;
330 # DWORD LimitHi :4;
331 # DWORD Sys :1;
332 # DWORD Reserved_0 :1;
333 # DWORD Default_Big :1;
334 # DWORD Granularity :1;
335 # DWORD BaseHi :8;
336 # } Bits;
337 # } HighWord;
338 # } LDT_ENTRY,
339 # *PLDT_ENTRY;
340
341 -class _LDT_ENTRY_BYTES_(Structure):
342 _pack_ = 1
343 _fields_ = [
344 ('BaseMid', BYTE),
345 ('Flags1', BYTE),
346 ('Flags2', BYTE),
347 ('BaseHi', BYTE),
348 ]
349
351 _pack_ = 1
352 _fields_ = [
353 ('BaseMid', DWORD, 8),
354 ('Type', DWORD, 5),
355 ('Dpl', DWORD, 2),
356 ('Pres', DWORD, 1),
357 ('LimitHi', DWORD, 4),
358 ('Sys', DWORD, 1),
359 ('Reserved_0', DWORD, 1),
360 ('Default_Big', DWORD, 1),
361 ('Granularity', DWORD, 1),
362 ('BaseHi', DWORD, 8),
363 ]
364
366 _pack_ = 1
367 _fields_ = [
368 ('Bytes', _LDT_ENTRY_BYTES_),
369 ('Bits', _LDT_ENTRY_BITS_),
370 ]
371
373 _pack_ = 1
374 _fields_ = [
375 ('LimitLow', WORD),
376 ('BaseLow', WORD),
377 ('HighWord', _LDT_ENTRY_HIGHWORD_),
378 ]
379
380 PLDT_ENTRY = POINTER(LDT_ENTRY)
381 LPLDT_ENTRY = PLDT_ENTRY
382
383 ###############################################################################
384
385 # BOOL WINAPI GetThreadSelectorEntry(
386 # __in HANDLE hThread,
387 # __in DWORD dwSelector,
388 # __out LPLDT_ENTRY lpSelectorEntry
389 # );
390 -def GetThreadSelectorEntry(hThread, dwSelector):
391 _GetThreadSelectorEntry = windll.kernel32.GetThreadSelectorEntry
392 _GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, LPLDT_ENTRY]
393 _GetThreadSelectorEntry.restype = bool
394 _GetThreadSelectorEntry.errcheck = RaiseIfZero
395
396 ldt = LDT_ENTRY()
397 _GetThreadSelectorEntry(hThread, dwSelector, ctypes.byref(ldt))
398 return ldt
399
400 # BOOL WINAPI GetThreadContext(
401 # __in HANDLE hThread,
402 # __inout LPCONTEXT lpContext
403 # );
404 -def GetThreadContext(hThread, ContextFlags = None):
405 _GetThreadContext = windll.kernel32.GetThreadContext
406 _GetThreadContext.argtypes = [HANDLE, LPCONTEXT]
407 _GetThreadContext.restype = bool
408 _GetThreadContext.errcheck = RaiseIfZero
409
410 if ContextFlags is None:
411 ContextFlags = CONTEXT_ALL
412 lpContext = CONTEXT()
413 lpContext.ContextFlags = ContextFlags
414 _GetThreadContext(hThread, ctypes.byref(lpContext))
415 return lpContext.to_dict()
416
417 # BOOL WINAPI SetThreadContext(
418 # __in HANDLE hThread,
419 # __in const CONTEXT* lpContext
420 # );
421 -def SetThreadContext(hThread, lpContext):
422 _SetThreadContext = windll.kernel32.SetThreadContext
423 _SetThreadContext.argtypes = [HANDLE, LPCONTEXT]
424 _SetThreadContext.restype = bool
425 _SetThreadContext.errcheck = RaiseIfZero
426
427 if isinstance(lpContext, dict):
428 lpContext = CONTEXT.from_dict(lpContext)
429 _SetThreadContext(hThread, ctypes.byref(lpContext))
430
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Feb 12 19:47:52 2010 | http://epydoc.sourceforge.net |