ReactOS 0.4.15-dev-8428-g6910fa6
cpu_i386.c
Go to the documentation of this file.
1/*
2 * File cpu_i386.c
3 *
4 * Copyright (C) 2009-2009, Eric Pouech.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <assert.h>
22
23#ifndef DBGHELP_STATIC_LIB
24#include "ntstatus.h"
25#define WIN32_NO_STATUS
26#include "dbghelp_private.h"
27#include "wine/winbase16.h"
28#include "winternl.h"
29#include "wine/debug.h"
30#else
31#include "dbghelp_private.h"
32#endif
33
35
36#define V86_FLAG 0x00020000
37
38#define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
39
40#if defined(__i386__) && !defined(DBGHELP_STATIC_LIB)
41static ADDRESS_MODE get_selector_type(HANDLE hThread, const CONTEXT* ctx, WORD sel)
42{
43 LDT_ENTRY le;
44
45 if (IS_VM86_MODE(ctx)) return AddrModeReal;
46 /* null or system selector */
47 if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
48 if (hThread && GetThreadSelectorEntry(hThread, sel, &le))
49 return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
50 /* selector doesn't exist */
51 return -1;
52}
53
54static BOOL i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
55 unsigned seg, ULONG_PTR offset)
56{
57 addr->Mode = AddrModeFlat;
58 addr->Segment = seg;
59 addr->Offset = offset;
60 if (seg)
61 {
62 switch (addr->Mode = get_selector_type(hThread, ctx, seg))
63 {
64 case AddrModeReal:
65 case AddrMode1616:
66 addr->Offset &= 0xffff;
67 break;
68 case AddrModeFlat:
69 case AddrMode1632:
70 break;
71 default:
72 return FALSE;
73 }
74 }
75 return TRUE;
76}
77#endif
78
79#ifndef DBGHELP_STATIC_LIB
82{
83#ifdef __i386__
84 switch (ca)
85 {
86 case cpu_addr_pc: return i386_build_addr(hThread, ctx, addr, ctx->SegCs, ctx->Eip);
87 case cpu_addr_stack: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Esp);
88 case cpu_addr_frame: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Ebp);
89 }
90#endif
91 return FALSE;
92}
93
94/* fetch_next_frame32()
95 *
96 * modify (at least) context.{eip, esp, ebp} using unwind information
97 * either out of debug info (dwarf, pdb), or simple stack unwind
98 */
100 union ctx *pcontext, DWORD_PTR curr_pc)
101{
102 DWORD64 xframe;
103 struct pdb_cmd_pair cpair[4];
104 DWORD val32;
105 WOW64_CONTEXT *context = &pcontext->x86;
106
107 if (dwarf2_virtual_unwind(csw, curr_pc, pcontext, &xframe))
108 {
109 context->Esp = xframe;
110 return TRUE;
111 }
112 cpair[0].name = "$ebp"; cpair[0].pvalue = &context->Ebp;
113 cpair[1].name = "$esp"; cpair[1].pvalue = &context->Esp;
114 cpair[2].name = "$eip"; cpair[2].pvalue = &context->Eip;
115 cpair[3].name = NULL; cpair[3].pvalue = NULL;
116
117 if (!pdb_virtual_unwind(csw, curr_pc, pcontext, cpair))
118 {
119 /* do a simple unwind using ebp
120 * we assume a "regular" prologue in the function has been used
121 */
122 if (!context->Ebp) return FALSE;
123 context->Esp = context->Ebp + 2 * sizeof(DWORD);
124 if (!sw_read_mem(csw, context->Ebp + sizeof(DWORD), &val32, sizeof(DWORD)))
125 {
126 WARN("Cannot read new frame offset %p\n",
127 (void*)(DWORD_PTR)(context->Ebp + (int)sizeof(DWORD)));
128 return FALSE;
129 }
130 context->Eip = val32;
131 /* "pop up" previous EBP value */
132 if (!sw_read_mem(csw, context->Ebp, &val32, sizeof(DWORD)))
133 return FALSE;
134 context->Ebp = val32;
135 }
136 return TRUE;
137}
138
140
141/* indexes in Reserved array */
142#define __CurrentModeCount 0
143#define __CurrentSwitch 1
144#define __NextSwitch 2
145
146#define curr_mode (frame->Reserved[__CurrentModeCount] & 0x0F)
147#define curr_count (frame->Reserved[__CurrentModeCount] >> 4)
148#define curr_switch (frame->Reserved[__CurrentSwitch])
149#define next_switch (frame->Reserved[__NextSwitch])
150
151#define set_curr_mode(m) {frame->Reserved[__CurrentModeCount] &= ~0x0F; frame->Reserved[__CurrentModeCount] |= (m & 0x0F);}
152#define inc_curr_count() (frame->Reserved[__CurrentModeCount] += 0x10)
153
155 union ctx *context)
156{
157 STACK32FRAME frame32;
158 STACK16FRAME frame16;
159 char ch;
160 ADDRESS64 tmp;
161 DWORD p;
162 WORD val16;
163 DWORD val32;
164 BOOL do_switch;
165 unsigned deltapc;
166 union ctx _context;
167
168 /* sanity check */
169 if (curr_mode >= stm_done) return FALSE;
170
171 TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p\n",
172 wine_dbgstr_addr(&frame->AddrPC),
176 curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
178 (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch);
179
180 /* if we're at first call (which doesn't actually unwind, it just computes ReturnPC,
181 * or if we're doing the first real unwind (count == 1), then we can directly use
182 * eip. otherwise, eip is *after* the insn that actually made the call to
183 * previous frame, so decrease eip by delta pc (1!) so that we're inside previous
184 * insn.
185 * Doing so, we ensure that the pc used for unwinding is always inside the function
186 * we want to use for next frame
187 */
188 deltapc = curr_count <= 1 ? 0 : 1;
189
190 if (!context)
191 {
192 /* setup a pseudo context for the rest of the code (esp. unwinding) */
193 context = &_context;
194 memset(context, 0, sizeof(*context));
196 if (frame->AddrPC.Mode != AddrModeFlat)
197 context->x86.SegCs = frame->AddrPC.Segment;
198 context->x86.Eip = frame->AddrPC.Offset;
199 if (frame->AddrFrame.Mode != AddrModeFlat)
200 context->x86.SegSs = frame->AddrFrame.Segment;
201 context->x86.Ebp = frame->AddrFrame.Offset;
202 if (frame->AddrStack.Mode != AddrModeFlat)
203 context->x86.SegSs = frame->AddrStack.Segment;
204 context->x86.Esp = frame->AddrStack.Offset;
205 }
206
207 if (curr_mode == stm_start)
208 {
210
211 if ((frame->AddrPC.Mode == AddrModeFlat) &&
212 (frame->AddrFrame.Mode != AddrModeFlat))
213 {
214 WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
215 goto done_err;
216 }
217
218 /* Init done */
220
221 /* cur_switch holds address of SystemReserved1[0] field in TEB in debuggee
222 * address space
223 */
225 sizeof(info), NULL) == STATUS_SUCCESS)
226 {
227 curr_switch = (DWORD_PTR)info.TebBaseAddress + FIELD_OFFSET(TEB, SystemReserved1[0]);
228 if (!sw_read_mem(csw, curr_switch, &p, sizeof(p)))
229 {
230 WARN("Can't read TEB:SystemReserved1[0]\n");
231 goto done_err;
232 }
233 next_switch = p;
234 if (!next_switch) /* no 16-bit stack */
235 {
236 curr_switch = 0;
237 }
238 else if (curr_mode == stm_16bit)
239 {
240 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
241 {
242 WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
243 goto done_err;
244 }
245 curr_switch = (DWORD)frame32.frame16;
246 tmp.Mode = AddrMode1616;
249 if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
250 curr_switch = 0xFFFFFFFF;
251 }
252 else
253 {
254 tmp.Mode = AddrMode1616;
257 p = sw_xlat_addr(csw, &tmp);
258 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
259 {
260 WARN("Bad stack frame 0x%08x\n", p);
261 goto done_err;
262 }
263 curr_switch = (DWORD_PTR)frame16.frame32;
264 if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
265 curr_switch = 0xFFFFFFFF;
266 }
267 }
268 else
269 /* FIXME: this will allow it to work when we're not attached to a live target,
270 * but the 16 <=> 32 switch facility won't be available.
271 */
272 curr_switch = 0;
274 /* don't set up AddrStack on first call. Either the caller has set it up, or
275 * we will get it in the next frame
276 */
277 memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
278 }
279 else
280 {
281 if (frame->AddrFrame.Mode == AddrModeFlat)
282 {
284 do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
285 }
286 else
287 {
289 do_switch = curr_switch &&
292 }
293
294 if (do_switch)
295 {
296 if (curr_mode == stm_16bit)
297 {
298 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
299 {
300 WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
301 goto done_err;
302 }
303
304 frame->AddrPC.Mode = AddrModeFlat;
305 frame->AddrPC.Segment = 0;
306 frame->AddrPC.Offset = frame32.retaddr;
307 frame->AddrFrame.Mode = AddrModeFlat;
308 frame->AddrFrame.Segment = 0;
309 frame->AddrFrame.Offset = frame32.ebp;
310
311 frame->AddrStack.Mode = AddrModeFlat;
312 frame->AddrStack.Segment = 0;
314 frame->AddrReturn.Segment = 0;
315
317 tmp.Mode = AddrMode1616;
320 p = sw_xlat_addr(csw, &tmp);
321
322 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
323 {
324 WARN("Bad stack frame 0x%08x\n", p);
325 goto done_err;
326 }
327 curr_switch = (DWORD_PTR)frame16.frame32;
329 if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
330 curr_switch = 0;
331 }
332 else
333 {
334 tmp.Mode = AddrMode1616;
337 p = sw_xlat_addr(csw, &tmp);
338
339 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
340 {
341 WARN("Bad stack frame 0x%08x\n", p);
342 goto done_err;
343 }
344
345 TRACE("Got a 16 bit stack switch:"
346 "\n\tframe32: %p"
347 "\n\tedx:%08x ecx:%08x ebp:%08x"
348 "\n\tds:%04x es:%04x fs:%04x gs:%04x"
349 "\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
350 "\n\tentry_ip:%04x entry_point:%08x"
351 "\n\tbp:%04x ip:%04x cs:%04x\n",
352 frame16.frame32,
353 frame16.edx, frame16.ecx, frame16.ebp,
354 frame16.ds, frame16.es, frame16.fs, frame16.gs,
355 frame16.callfrom_ip, frame16.module_cs, frame16.relay,
356 frame16.entry_ip, frame16.entry_point,
357 frame16.bp, frame16.ip, frame16.cs);
358
359 frame->AddrPC.Mode = AddrMode1616;
360 frame->AddrPC.Segment = frame16.cs;
361 frame->AddrPC.Offset = frame16.ip;
362
363 frame->AddrFrame.Mode = AddrMode1616;
365 frame->AddrFrame.Offset = frame16.bp;
366
367 frame->AddrStack.Mode = AddrMode1616;
369
371 frame->AddrReturn.Segment = frame16.cs;
372
374 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
375 {
376 WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
377 goto done_err;
378 }
379 curr_switch = (DWORD)frame32.frame16;
380 tmp.Mode = AddrMode1616;
383
384 if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
385 curr_switch = 0;
387 }
388 }
389 else
390 {
391 if (curr_mode == stm_16bit)
392 {
393 frame->AddrPC = frame->AddrReturn;
394 frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
395 /* "pop up" previous BP value */
396 if (!frame->AddrFrame.Offset ||
397 !sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
398 &val16, sizeof(WORD)))
399 goto done_err;
400 frame->AddrFrame.Offset = val16;
401 }
402 else
403 {
404 if (!fetch_next_frame32(csw, context, sw_xlat_addr(csw, &frame->AddrPC) - deltapc))
405 goto done_err;
406
407 frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrPC.Mode = AddrModeFlat;
408 frame->AddrStack.Offset = context->x86.Esp;
409 frame->AddrFrame.Offset = context->x86.Ebp;
410 if (frame->AddrReturn.Offset != context->x86.Eip)
411 FIXME("new PC=%s different from Eip=%x\n",
413 frame->AddrPC.Offset = context->x86.Eip;
414 }
415 }
416 }
417
418 if (curr_mode == stm_16bit)
419 {
420 unsigned int i;
421
422 p = sw_xlat_addr(csw, &frame->AddrFrame);
423 if (!sw_read_mem(csw, p + sizeof(WORD), &val16, sizeof(WORD)))
424 goto done_err;
425 frame->AddrReturn.Offset = val16;
426 /* get potential cs if a far call was used */
427 if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val16, sizeof(WORD)))
428 goto done_err;
429 if (frame->AddrFrame.Offset & 1)
430 frame->AddrReturn.Segment = val16; /* far call assumed */
431 else
432 {
433 /* not explicitly marked as far call,
434 * but check whether it could be anyway
435 */
436 if ((val16 & 7) == 7 && val16 != frame->AddrReturn.Segment)
437 {
438 LDT_ENTRY le;
439
440 if (GetThreadSelectorEntry(csw->hThread, val16, &le) &&
441 (le.HighWord.Bits.Type & 0x08)) /* code segment */
442 {
443 /* it is very uncommon to push a code segment cs as
444 * a parameter, so this should work in most cases
445 */
446 frame->AddrReturn.Segment = val16;
447 }
448 }
449 }
450 frame->AddrFrame.Offset &= ~1;
451 /* we "pop" parameters as 16 bit entities... of course, this won't
452 * work if the parameter is in fact bigger than 16bit, but
453 * there's no way to know that here
454 */
455 for (i = 0; i < ARRAY_SIZE(frame->Params); i++)
456 {
457 sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val16, sizeof(val16));
458 frame->Params[i] = val16;
459 }
460 if (context)
461 {
462#define SET(field, seg, reg) \
463 switch (frame->field.Mode) \
464 { \
465 case AddrModeFlat: context->x86.reg = frame->field.Offset; break; \
466 case AddrMode1616: context->x86.seg = frame->field.Segment; context->x86.reg = frame->field.Offset; break; \
467 default: assert(0); \
468 }
469 SET(AddrStack, SegSs, Esp);
470 SET(AddrFrame, SegSs, Ebp);
471 SET(AddrReturn, SegCs, Eip);
472#undef SET
473 }
474 }
475 else
476 {
477 unsigned int i;
478 union ctx newctx = *context;
479
480 if (!fetch_next_frame32(csw, &newctx, frame->AddrPC.Offset - deltapc))
481 goto done_err;
483 frame->AddrReturn.Offset = newctx.x86.Eip;
484
485 for (i = 0; i < ARRAY_SIZE(frame->Params); i++)
486 {
487 sw_read_mem(csw, frame->AddrFrame.Offset + (2 + i) * sizeof(DWORD), &val32, sizeof(val32));
488 frame->Params[i] = val32;
489 }
490 }
491
492 frame->Far = TRUE;
493 frame->Virtual = TRUE;
494 p = sw_xlat_addr(csw, &frame->AddrPC);
495 if (p && sw_module_base(csw, p))
496 frame->FuncTableEntry = sw_table_access(csw, p);
497 else
498 frame->FuncTableEntry = NULL;
499
501 TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p FuncTable=%p\n",
502 wine_dbgstr_addr(&frame->AddrPC),
506 curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
508 (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch, frame->FuncTableEntry);
509
510 return TRUE;
511done_err:
513 return FALSE;
514}
515#endif /* DBGHELP_STATIC_LIB */
516
517static unsigned i386_map_dwarf_register(unsigned regno, const struct module* module, BOOL eh_frame)
518{
519 unsigned reg;
520
521 switch (regno)
522 {
523 case 0: reg = CV_REG_EAX; break;
524 case 1: reg = CV_REG_ECX; break;
525 case 2: reg = CV_REG_EDX; break;
526 case 3: reg = CV_REG_EBX; break;
527 case 4:
528 case 5:
529 /* On OS X, DWARF eh_frame uses a different mapping for the registers. It's
530 apparently the mapping as emitted by GCC, at least at some point in its history. */
531 if (eh_frame && module->type == DMT_MACHO)
532 reg = (regno == 4) ? CV_REG_EBP : CV_REG_ESP;
533 else
534 reg = (regno == 4) ? CV_REG_ESP : CV_REG_EBP;
535 break;
536 case 6: reg = CV_REG_ESI; break;
537 case 7: reg = CV_REG_EDI; break;
538 case 8: reg = CV_REG_EIP; break;
539 case 9: reg = CV_REG_EFLAGS; break;
540 case 10: reg = CV_REG_CS; break;
541 case 11: reg = CV_REG_SS; break;
542 case 12: reg = CV_REG_DS; break;
543 case 13: reg = CV_REG_ES; break;
544 case 14: reg = CV_REG_FS; break;
545 case 15: reg = CV_REG_GS; break;
546 case 16: case 17: case 18: case 19:
547 case 20: case 21: case 22: case 23:
548 reg = CV_REG_ST0 + regno - 16; break;
549 case 24: reg = CV_REG_CTRL; break;
550 case 25: reg = CV_REG_STAT; break;
551 case 26: reg = CV_REG_TAG; break;
552 case 27: reg = CV_REG_FPCS; break;
553 case 28: reg = CV_REG_FPIP; break;
554 case 29: reg = CV_REG_FPDS; break;
555 case 30: reg = CV_REG_FPDO; break;
556/*
557reg: fop 31
558*/
559 case 32: case 33: case 34: case 35:
560 case 36: case 37: case 38: case 39:
561 reg = CV_REG_XMM0 + regno - 32; break;
562 case 40: reg = CV_REG_MXCSR; break;
563 default:
564 FIXME("Don't know how to map register %d\n", regno);
565 return 0;
566 }
567 return reg;
568}
569
570static void *i386_fetch_context_reg(union ctx *pctx, unsigned regno, unsigned *size)
571{
572 WOW64_CONTEXT *ctx = &pctx->x86;
573
574 switch (regno)
575 {
576 case CV_REG_EAX: *size = sizeof(ctx->Eax); return &ctx->Eax;
577 case CV_REG_EDX: *size = sizeof(ctx->Edx); return &ctx->Edx;
578 case CV_REG_ECX: *size = sizeof(ctx->Ecx); return &ctx->Ecx;
579 case CV_REG_EBX: *size = sizeof(ctx->Ebx); return &ctx->Ebx;
580 case CV_REG_ESI: *size = sizeof(ctx->Esi); return &ctx->Esi;
581 case CV_REG_EDI: *size = sizeof(ctx->Edi); return &ctx->Edi;
582 case CV_REG_EBP: *size = sizeof(ctx->Ebp); return &ctx->Ebp;
583 case CV_REG_ESP: *size = sizeof(ctx->Esp); return &ctx->Esp;
584 case CV_REG_EIP: *size = sizeof(ctx->Eip); return &ctx->Eip;
585
586 /* These are x87 floating point registers... They do not match a C type in
587 * the Linux ABI, so hardcode their 80-bitness. */
588 case CV_REG_ST0 + 0: *size = 10; return &ctx->FloatSave.RegisterArea[0*10];
589 case CV_REG_ST0 + 1: *size = 10; return &ctx->FloatSave.RegisterArea[1*10];
590 case CV_REG_ST0 + 2: *size = 10; return &ctx->FloatSave.RegisterArea[2*10];
591 case CV_REG_ST0 + 3: *size = 10; return &ctx->FloatSave.RegisterArea[3*10];
592 case CV_REG_ST0 + 4: *size = 10; return &ctx->FloatSave.RegisterArea[4*10];
593 case CV_REG_ST0 + 5: *size = 10; return &ctx->FloatSave.RegisterArea[5*10];
594 case CV_REG_ST0 + 6: *size = 10; return &ctx->FloatSave.RegisterArea[6*10];
595 case CV_REG_ST0 + 7: *size = 10; return &ctx->FloatSave.RegisterArea[7*10];
596
597 case CV_REG_CTRL: *size = sizeof(DWORD); return &ctx->FloatSave.ControlWord;
598 case CV_REG_STAT: *size = sizeof(DWORD); return &ctx->FloatSave.StatusWord;
599 case CV_REG_TAG: *size = sizeof(DWORD); return &ctx->FloatSave.TagWord;
600 case CV_REG_FPCS: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorSelector;
601 case CV_REG_FPIP: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorOffset;
602 case CV_REG_FPDS: *size = sizeof(DWORD); return &ctx->FloatSave.DataSelector;
603 case CV_REG_FPDO: *size = sizeof(DWORD); return &ctx->FloatSave.DataOffset;
604
605 case CV_REG_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
606 case CV_REG_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
607 case CV_REG_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
608 case CV_REG_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
609 case CV_REG_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
610 case CV_REG_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
611 case CV_REG_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
612
613 case CV_REG_XMM0 + 0: *size = 16; return &ctx->ExtendedRegisters[10*16];
614 case CV_REG_XMM0 + 1: *size = 16; return &ctx->ExtendedRegisters[11*16];
615 case CV_REG_XMM0 + 2: *size = 16; return &ctx->ExtendedRegisters[12*16];
616 case CV_REG_XMM0 + 3: *size = 16; return &ctx->ExtendedRegisters[13*16];
617 case CV_REG_XMM0 + 4: *size = 16; return &ctx->ExtendedRegisters[14*16];
618 case CV_REG_XMM0 + 5: *size = 16; return &ctx->ExtendedRegisters[15*16];
619 case CV_REG_XMM0 + 6: *size = 16; return &ctx->ExtendedRegisters[16*16];
620 case CV_REG_XMM0 + 7: *size = 16; return &ctx->ExtendedRegisters[17*16];
621
622 case CV_REG_MXCSR: *size = sizeof(DWORD); return &ctx->ExtendedRegisters[24];
623 }
624 FIXME("Unknown register %x\n", regno);
625 return NULL;
626}
627
628static const char* i386_fetch_regname(unsigned regno)
629{
630 switch (regno)
631 {
632 case CV_REG_EAX: return "eax";
633 case CV_REG_EDX: return "edx";
634 case CV_REG_ECX: return "ecx";
635 case CV_REG_EBX: return "ebx";
636 case CV_REG_ESI: return "esi";
637 case CV_REG_EDI: return "edi";
638 case CV_REG_EBP: return "ebp";
639 case CV_REG_ESP: return "esp";
640 case CV_REG_EIP: return "eip";
641
642 case CV_REG_ST0 + 0: return "st0";
643 case CV_REG_ST0 + 1: return "st1";
644 case CV_REG_ST0 + 2: return "st2";
645 case CV_REG_ST0 + 3: return "st3";
646 case CV_REG_ST0 + 4: return "st4";
647 case CV_REG_ST0 + 5: return "st5";
648 case CV_REG_ST0 + 6: return "st6";
649 case CV_REG_ST0 + 7: return "st7";
650
651 case CV_REG_EFLAGS: return "eflags";
652 case CV_REG_ES: return "es";
653 case CV_REG_CS: return "cs";
654 case CV_REG_SS: return "ss";
655 case CV_REG_DS: return "ds";
656 case CV_REG_FS: return "fs";
657 case CV_REG_GS: return "gs";
658
659 case CV_REG_CTRL: return "fpControl";
660 case CV_REG_STAT: return "fpStatus";
661 case CV_REG_TAG: return "fpTag";
662 case CV_REG_FPCS: return "fpCS";
663 case CV_REG_FPIP: return "fpIP";
664 case CV_REG_FPDS: return "fpDS";
665 case CV_REG_FPDO: return "fpData";
666
667 case CV_REG_XMM0 + 0: return "xmm0";
668 case CV_REG_XMM0 + 1: return "xmm1";
669 case CV_REG_XMM0 + 2: return "xmm2";
670 case CV_REG_XMM0 + 3: return "xmm3";
671 case CV_REG_XMM0 + 4: return "xmm4";
672 case CV_REG_XMM0 + 5: return "xmm5";
673 case CV_REG_XMM0 + 6: return "xmm6";
674 case CV_REG_XMM0 + 7: return "xmm7";
675
676 case CV_REG_MXCSR: return "MxCSR";
677 }
678 FIXME("Unknown register %x\n", regno);
679 return NULL;
680}
681
682#ifndef DBGHELP_STATIC_LIB
683static BOOL i386_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
684{
685 if (ctx->ContextFlags && (flags & ThreadWriteInstructionWindow))
686 {
687 /* FIXME: crop values across module boundaries, */
688#ifdef __i386__
689 ULONG base = ctx->Eip <= 0x80 ? 0 : ctx->Eip - 0x80;
690 minidump_add_memory_block(dc, base, ctx->Eip + 0x80 - base, 0);
691#endif
692 }
693
694 return TRUE;
695}
696#endif
697
698static BOOL i386_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags)
699{
700 /* FIXME: actually, we should probably take care of FPO data, unless it's stored in
701 * function table minidump stream
702 */
703 return FALSE;
704}
705
708 4,
710#ifndef DBGHELP_STATIC_LIB
713#else
714 NULL,
715 NULL,
716#endif
717 NULL,
721#ifndef DBGHELP_STATIC_LIB
724#else
725 NULL,
726 NULL,
727#endif
728};
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define next_switch
Definition: cpu_i386.c:149
static const char * i386_fetch_regname(unsigned regno)
Definition: cpu_i386.c:628
#define set_curr_mode(m)
Definition: cpu_i386.c:151
st_mode
Definition: cpu_i386.c:139
@ stm_start
Definition: cpu_i386.c:139
@ stm_done
Definition: cpu_i386.c:139
@ stm_16bit
Definition: cpu_i386.c:139
@ stm_32bit
Definition: cpu_i386.c:139
#define curr_count
Definition: cpu_i386.c:147
#define curr_mode
Definition: cpu_i386.c:146
static BOOL i386_fetch_minidump_module(struct dump_context *dc, unsigned index, unsigned flags)
Definition: cpu_i386.c:698
DECLSPEC_HIDDEN struct cpu cpu_i386
Definition: cpu_i386.c:706
#define IS_VM86_MODE(ctx)
Definition: cpu_i386.c:38
static BOOL i386_get_addr(HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
Definition: cpu_i386.c:80
static BOOL fetch_next_frame32(struct cpu_stack_walk *csw, union ctx *pcontext, DWORD_PTR curr_pc)
Definition: cpu_i386.c:99
static unsigned i386_map_dwarf_register(unsigned regno, const struct module *module, BOOL eh_frame)
Definition: cpu_i386.c:517
#define inc_curr_count()
Definition: cpu_i386.c:152
static BOOL i386_fetch_minidump_thread(struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
Definition: cpu_i386.c:683
#define curr_switch
Definition: cpu_i386.c:148
static BOOL i386_stack_walk(struct cpu_stack_walk *csw, STACKFRAME64 *frame, union ctx *context)
Definition: cpu_i386.c:154
#define SET(field, seg, reg)
static void * i386_fetch_context_reg(union ctx *pctx, unsigned regno, unsigned *size)
Definition: cpu_i386.c:570
cpu_addr
@ cpu_addr_frame
@ cpu_addr_pc
@ cpu_addr_stack
void * sw_table_access(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:119
BOOL pdb_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, union ctx *context, struct pdb_cmd_pair *cpair) DECLSPEC_HIDDEN
Definition: msc.c:3200
BOOL dwarf2_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, union ctx *ctx, DWORD64 *cfa) DECLSPEC_HIDDEN
Definition: dwarf.c:3258
DWORD64 sw_module_base(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:127
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN
Definition: minidump.c:355
BOOL sw_read_mem(struct cpu_stack_walk *csw, DWORD64 addr, void *ptr, DWORD sz) DECLSPEC_HIDDEN
Definition: stack.c:95
DWORD64 sw_xlat_addr(struct cpu_stack_walk *csw, ADDRESS64 *addr) DECLSPEC_HIDDEN
Definition: stack.c:104
@ DMT_MACHO
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
static const WCHAR ca[]
Definition: main.c:455
#define WOW64_CONTEXT_CONTROL
Definition: compat.h:218
@ ThreadBasicInformation
Definition: compat.h:935
ADDRESS_MODE
Definition: compat.h:1155
@ AddrModeReal
Definition: compat.h:1158
@ AddrModeFlat
Definition: compat.h:1159
@ AddrMode1616
Definition: compat.h:1156
@ AddrMode1632
Definition: compat.h:1157
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
@ CV_REG_MXCSR
Definition: compat.h:1748
@ CV_REG_EFLAGS
Definition: compat.h:1713
@ CV_REG_SS
Definition: compat.h:1706
@ CV_REG_EBX
Definition: compat.h:1699
@ CV_REG_XMM0
Definition: compat.h:1744
@ CV_REG_ESI
Definition: compat.h:1702
@ CV_REG_TAG
Definition: compat.h:1735
@ CV_REG_EIP
Definition: compat.h:1712
@ CV_REG_FPDS
Definition: compat.h:1739
@ CV_REG_ECX
Definition: compat.h:1697
@ CV_REG_ST0
Definition: compat.h:1732
@ CV_REG_EBP
Definition: compat.h:1701
@ CV_REG_CS
Definition: compat.h:1705
@ CV_REG_EAX
Definition: compat.h:1696
@ CV_REG_FS
Definition: compat.h:1708
@ CV_REG_STAT
Definition: compat.h:1734
@ CV_REG_CTRL
Definition: compat.h:1733
@ CV_REG_EDI
Definition: compat.h:1703
@ CV_REG_ES
Definition: compat.h:1704
@ CV_REG_ESP
Definition: compat.h:1700
@ CV_REG_FPCS
Definition: compat.h:1737
@ CV_REG_GS
Definition: compat.h:1709
@ CV_REG_DS
Definition: compat.h:1707
@ CV_REG_EDX
Definition: compat.h:1698
@ CV_REG_FPIP
Definition: compat.h:1736
@ CV_REG_FPDO
Definition: compat.h:1738
@ ThreadWriteInstructionWindow
Definition: compat.h:1150
#define WOW64_CONTEXT_SEGMENTS
Definition: compat.h:220
const char * wine_dbgstr_addr(const ADDRESS64 *addr)
Definition: dbghelp.c:142
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:830
#define assert(x)
Definition: debug.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static int reg
Definition: i386-dis.c:1290
if(dx< 0)
Definition: linetemp.h:194
static const WCHAR dc[]
HANDLE hThread
Definition: wizard.c:28
#define DWORD
Definition: nt_native.h:44
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
Definition: compat.h:777
struct _LDT_ENTRY::@354::@356 Bits
union _LDT_ENTRY::@354 HighWord
DWORD relay
Definition: compat.h:2475
DWORD ecx
Definition: compat.h:2467
DWORD ebp
Definition: compat.h:2468
DWORD callfrom_ip
Definition: compat.h:2473
DWORD edx
Definition: compat.h:2466
WORD entry_ip
Definition: compat.h:2476
STACK32FRAME * frame32
Definition: compat.h:2465
DWORD entry_point
Definition: compat.h:2477
DWORD module_cs
Definition: compat.h:2474
DWORD retaddr
Definition: compat.h:2457
DWORD ebp
Definition: compat.h:2456
SEGPTR frame16
Definition: compat.h:2452
PVOID FuncTableEntry
Definition: compat.h:1406
ADDRESS64 AddrBStore
Definition: compat.h:1405
ADDRESS64 AddrStack
Definition: compat.h:1404
ADDRESS64 AddrFrame
Definition: compat.h:1403
ADDRESS64 AddrPC
Definition: compat.h:1401
DWORD64 Params[4]
Definition: compat.h:1407
BOOL Virtual
Definition: compat.h:1409
ADDRESS64 AddrReturn
Definition: compat.h:1402
Definition: compat.h:836
DWORD Eip
Definition: compat.h:274
WORD Segment
Definition: compat.h:1175
ADDRESS_MODE Mode
Definition: compat.h:1176
DWORD64 Offset
Definition: compat.h:1174
Definition: http.c:7252
enum module_type type
const char * name
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint64_t DWORD64
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
WOW64_CONTEXT x86
#define SELECTOROF(ptr)
Definition: windef16.h:50
#define OFFSETOF(ptr)
Definition: windef16.h:51