ReactOS  0.4.14-dev-50-g13bb5e2
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)
41 static 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 
54 static BOOL i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
55  unsigned seg, unsigned long 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
81  enum cpu_addr ca, ADDRESS64* addr)
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 #endif /* DBGHELP_STATIC_LIB */
94 
95 #if defined(__i386__) && !defined(DBGHELP_STATIC_LIB)
96 /* fetch_next_frame32()
97  *
98  * modify (at least) context.{eip, esp, ebp} using unwind information
99  * either out of debug info (dwarf, pdb), or simple stack unwind
100  */
101 static BOOL fetch_next_frame32(struct cpu_stack_walk* csw,
102  CONTEXT* context, DWORD_PTR curr_pc)
103 {
104  DWORD_PTR xframe;
105  struct pdb_cmd_pair cpair[4];
106  DWORD val32;
107 
108  if (dwarf2_virtual_unwind(csw, curr_pc, context, &xframe))
109  {
110  context->Esp = xframe;
111  return TRUE;
112  }
113  cpair[0].name = "$ebp"; cpair[0].pvalue = &context->Ebp;
114  cpair[1].name = "$esp"; cpair[1].pvalue = &context->Esp;
115  cpair[2].name = "$eip"; cpair[2].pvalue = &context->Eip;
116  cpair[3].name = NULL; cpair[3].pvalue = NULL;
117 
118 #ifndef DBGHELP_STATIC_LIB
119  if (!pdb_virtual_unwind(csw, curr_pc, context, cpair))
120 #endif
121  {
122  /* do a simple unwind using ebp
123  * we assume a "regular" prologue in the function has been used
124  */
125  if (!context->Ebp) return FALSE;
126  context->Esp = context->Ebp + 2 * sizeof(DWORD);
127  if (!sw_read_mem(csw, context->Ebp + sizeof(DWORD), &val32, sizeof(DWORD)))
128  {
129  WARN("Cannot read new frame offset %p\n",
130  (void*)(DWORD_PTR)(context->Ebp + (int)sizeof(DWORD)));
131  return FALSE;
132  }
133  context->Eip = val32;
134  /* "pop up" previous EBP value */
135  if (!sw_read_mem(csw, context->Ebp, &val32, sizeof(DWORD)))
136  return FALSE;
137  context->Ebp = val32;
138  }
139  return TRUE;
140 }
141 #endif
142 
144 
145 /* indexes in Reserved array */
146 #define __CurrentModeCount 0
147 #define __CurrentSwitch 1
148 #define __NextSwitch 2
149 
150 #define curr_mode (frame->Reserved[__CurrentModeCount] & 0x0F)
151 #define curr_count (frame->Reserved[__CurrentModeCount] >> 4)
152 #define curr_switch (frame->Reserved[__CurrentSwitch])
153 #define next_switch (frame->Reserved[__NextSwitch])
154 
155 #define set_curr_mode(m) {frame->Reserved[__CurrentModeCount] &= ~0x0F; frame->Reserved[__CurrentModeCount] |= (m & 0x0F);}
156 #define inc_curr_count() (frame->Reserved[__CurrentModeCount] += 0x10)
157 
158 #ifndef DBGHELP_STATIC_LIB
160 {
161  STACK32FRAME frame32;
162  STACK16FRAME frame16;
163  char ch;
164  ADDRESS64 tmp;
165  DWORD p;
166  WORD val16;
167  DWORD val32;
168  BOOL do_switch;
169 #ifdef __i386__
170  unsigned deltapc;
171  CONTEXT _context;
172 #endif
173 
174  /* sanity check */
175  if (curr_mode >= stm_done) return FALSE;
176 
177  TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p\n",
178  wine_dbgstr_addr(&frame->AddrPC),
179  wine_dbgstr_addr(&frame->AddrFrame),
180  wine_dbgstr_addr(&frame->AddrReturn),
181  wine_dbgstr_addr(&frame->AddrStack),
182  curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
184  (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch);
185 
186 #ifdef __i386__
187  /* if we're at first call (which doesn't actually unwind, it just computes ReturnPC,
188  * or if we're doing the first real unwind (count == 1), then we can directly use
189  * eip. otherwise, eip is *after* the insn that actually made the call to
190  * previous frame, so decrease eip by delta pc (1!) so that we're inside previous
191  * insn.
192  * Doing so, we ensure that the pc used for unwinding is always inside the function
193  * we want to use for next frame
194  */
195  deltapc = curr_count <= 1 ? 0 : 1;
196 
197  if (!context)
198  {
199  /* setup a pseudo context for the rest of the code (esp. unwinding) */
200  context = &_context;
201  memset(context, 0, sizeof(*context));
202  context->ContextFlags = CONTEXT_CONTROL | CONTEXT_SEGMENTS;
203  if (frame->AddrPC.Mode != AddrModeFlat) context->SegCs = frame->AddrPC.Segment;
204  context->Eip = frame->AddrPC.Offset;
205  if (frame->AddrFrame.Mode != AddrModeFlat) context->SegSs = frame->AddrFrame.Segment;
206  context->Ebp = frame->AddrFrame.Offset;
207  if (frame->AddrStack.Mode != AddrModeFlat) context->SegSs = frame->AddrStack.Segment;
208  context->Esp = frame->AddrStack.Offset;
209  }
210 #endif
211  if (curr_mode == stm_start)
212  {
214 
215  if ((frame->AddrPC.Mode == AddrModeFlat) &&
216  (frame->AddrFrame.Mode != AddrModeFlat))
217  {
218  WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
219  goto done_err;
220  }
221 
222  /* Init done */
224 
225  /* cur_switch holds address of SystemReserved1[0] field in TEB in debuggee
226  * address space
227  */
229  sizeof(info), NULL) == STATUS_SUCCESS)
230  {
231  curr_switch = (DWORD_PTR)info.TebBaseAddress + FIELD_OFFSET(TEB, SystemReserved1[0]);
232  if (!sw_read_mem(csw, curr_switch, &p, sizeof(p)))
233  {
234  WARN("Can't read TEB:SystemReserved1[0]\n");
235  goto done_err;
236  }
237  next_switch = p;
238  if (!next_switch) /* no 16-bit stack */
239  {
240  curr_switch = 0;
241  }
242  else if (curr_mode == stm_16bit)
243  {
244  if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
245  {
246  WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
247  goto done_err;
248  }
249  curr_switch = (DWORD)frame32.frame16;
250  tmp.Mode = AddrMode1616;
252  tmp.Offset = OFFSETOF(curr_switch);
253  if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
254  curr_switch = 0xFFFFFFFF;
255  }
256  else
257  {
258  tmp.Mode = AddrMode1616;
260  tmp.Offset = OFFSETOF(next_switch);
261  p = sw_xlat_addr(csw, &tmp);
262  if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
263  {
264  WARN("Bad stack frame 0x%08x\n", p);
265  goto done_err;
266  }
267  curr_switch = (DWORD_PTR)frame16.frame32;
268  if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
269  curr_switch = 0xFFFFFFFF;
270  }
271  }
272  else
273  /* FIXME: this will allow it to work when we're not attached to a live target,
274  * but the 16 <=> 32 switch facility won't be available.
275  */
276  curr_switch = 0;
278  /* don't set up AddrStack on first call. Either the caller has set it up, or
279  * we will get it in the next frame
280  */
281  memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
282  }
283  else
284  {
285  if (frame->AddrFrame.Mode == AddrModeFlat)
286  {
288  do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
289  }
290  else
291  {
293  do_switch = curr_switch &&
296  }
297 
298  if (do_switch)
299  {
300  if (curr_mode == stm_16bit)
301  {
302  if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
303  {
304  WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
305  goto done_err;
306  }
307 
308  frame->AddrPC.Mode = AddrModeFlat;
309  frame->AddrPC.Segment = 0;
310  frame->AddrPC.Offset = frame32.retaddr;
311  frame->AddrFrame.Mode = AddrModeFlat;
312  frame->AddrFrame.Segment = 0;
313  frame->AddrFrame.Offset = frame32.ebp;
314 
315  frame->AddrStack.Mode = AddrModeFlat;
316  frame->AddrStack.Segment = 0;
317  frame->AddrReturn.Mode = AddrModeFlat;
318  frame->AddrReturn.Segment = 0;
319 
321  tmp.Mode = AddrMode1616;
323  tmp.Offset = OFFSETOF(next_switch);
324  p = sw_xlat_addr(csw, &tmp);
325 
326  if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
327  {
328  WARN("Bad stack frame 0x%08x\n", p);
329  goto done_err;
330  }
331  curr_switch = (DWORD_PTR)frame16.frame32;
333  if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
334  curr_switch = 0;
335  }
336  else
337  {
338  tmp.Mode = AddrMode1616;
340  tmp.Offset = OFFSETOF(next_switch);
341  p = sw_xlat_addr(csw, &tmp);
342 
343  if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
344  {
345  WARN("Bad stack frame 0x%08x\n", p);
346  goto done_err;
347  }
348 
349  TRACE("Got a 16 bit stack switch:"
350  "\n\tframe32: %p"
351  "\n\tedx:%08x ecx:%08x ebp:%08x"
352  "\n\tds:%04x es:%04x fs:%04x gs:%04x"
353  "\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
354  "\n\tentry_ip:%04x entry_point:%08x"
355  "\n\tbp:%04x ip:%04x cs:%04x\n",
356  frame16.frame32,
357  frame16.edx, frame16.ecx, frame16.ebp,
358  frame16.ds, frame16.es, frame16.fs, frame16.gs,
359  frame16.callfrom_ip, frame16.module_cs, frame16.relay,
360  frame16.entry_ip, frame16.entry_point,
361  frame16.bp, frame16.ip, frame16.cs);
362 
363  frame->AddrPC.Mode = AddrMode1616;
364  frame->AddrPC.Segment = frame16.cs;
365  frame->AddrPC.Offset = frame16.ip;
366 
367  frame->AddrFrame.Mode = AddrMode1616;
369  frame->AddrFrame.Offset = frame16.bp;
370 
371  frame->AddrStack.Mode = AddrMode1616;
373 
374  frame->AddrReturn.Mode = AddrMode1616;
375  frame->AddrReturn.Segment = frame16.cs;
376 
378  if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
379  {
380  WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
381  goto done_err;
382  }
383  curr_switch = (DWORD)frame32.frame16;
384  tmp.Mode = AddrMode1616;
386  tmp.Offset = OFFSETOF(curr_switch);
387 
388  if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
389  curr_switch = 0;
391  }
392  }
393  else
394  {
395  if (curr_mode == stm_16bit)
396  {
397  frame->AddrPC = frame->AddrReturn;
398  frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
399  /* "pop up" previous BP value */
400  if (!frame->AddrFrame.Offset ||
401  !sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
402  &val16, sizeof(WORD)))
403  goto done_err;
404  frame->AddrFrame.Offset = val16;
405  }
406  else
407  {
408 #ifdef __i386__
409  if (!fetch_next_frame32(csw, context, sw_xlat_addr(csw, &frame->AddrPC) - deltapc))
410  goto done_err;
411 
412  frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrPC.Mode = AddrModeFlat;
413  frame->AddrStack.Offset = context->Esp;
414  frame->AddrFrame.Offset = context->Ebp;
415  if (frame->AddrReturn.Offset != context->Eip)
416  FIXME("new PC=%s different from Eip=%x\n",
418  frame->AddrPC.Offset = context->Eip;
419 #endif
420  }
421  }
422  }
423 
424  if (curr_mode == stm_16bit)
425  {
426  unsigned int i;
427 
428  p = sw_xlat_addr(csw, &frame->AddrFrame);
429  if (!sw_read_mem(csw, p + sizeof(WORD), &val16, sizeof(WORD)))
430  goto done_err;
431  frame->AddrReturn.Offset = val16;
432  /* get potential cs if a far call was used */
433  if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val16, sizeof(WORD)))
434  goto done_err;
435  if (frame->AddrFrame.Offset & 1)
436  frame->AddrReturn.Segment = val16; /* far call assumed */
437  else
438  {
439  /* not explicitly marked as far call,
440  * but check whether it could be anyway
441  */
442  if ((val16 & 7) == 7 && val16 != frame->AddrReturn.Segment)
443  {
444  LDT_ENTRY le;
445 
446  if (GetThreadSelectorEntry(csw->hThread, val16, &le) &&
447  (le.HighWord.Bits.Type & 0x08)) /* code segment */
448  {
449  /* it is very uncommon to push a code segment cs as
450  * a parameter, so this should work in most cases
451  */
452  frame->AddrReturn.Segment = val16;
453  }
454  }
455  }
456  frame->AddrFrame.Offset &= ~1;
457  /* we "pop" parameters as 16 bit entities... of course, this won't
458  * work if the parameter is in fact bigger than 16bit, but
459  * there's no way to know that here
460  */
461  for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
462  {
463  sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val16, sizeof(val16));
464  frame->Params[i] = val16;
465  }
466 #ifdef __i386__
467  if (context)
468  {
469 #define SET(field, seg, reg) \
470  switch (frame->field.Mode) \
471  { \
472  case AddrModeFlat: context->reg = frame->field.Offset; break; \
473  case AddrMode1616: context->seg = frame->field.Segment; context->reg = frame->field.Offset; break; \
474  default: assert(0); \
475  }
476  SET(AddrStack, SegSs, Esp);
477  SET(AddrFrame, SegSs, Ebp);
478  SET(AddrReturn, SegCs, Eip);
479 #undef SET
480  }
481 #endif
482  }
483  else
484  {
485  unsigned int i;
486 #ifdef __i386__
487  CONTEXT newctx = *context;
488 
489  if (!fetch_next_frame32(csw, &newctx, frame->AddrPC.Offset - deltapc))
490  goto done_err;
491  frame->AddrReturn.Mode = AddrModeFlat;
492  frame->AddrReturn.Offset = newctx.Eip;
493 #endif
494  for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
495  {
496  sw_read_mem(csw, frame->AddrFrame.Offset + (2 + i) * sizeof(DWORD), &val32, sizeof(val32));
497  frame->Params[i] = val32;
498  }
499  }
500 
501  frame->Far = TRUE;
502  frame->Virtual = TRUE;
503  p = sw_xlat_addr(csw, &frame->AddrPC);
504  if (p && sw_module_base(csw, p))
505  frame->FuncTableEntry = sw_table_access(csw, p);
506  else
507  frame->FuncTableEntry = NULL;
508 
509  inc_curr_count();
510  TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p FuncTable=%p\n",
511  wine_dbgstr_addr(&frame->AddrPC),
512  wine_dbgstr_addr(&frame->AddrFrame),
513  wine_dbgstr_addr(&frame->AddrReturn),
514  wine_dbgstr_addr(&frame->AddrStack),
515  curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
517  (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch, frame->FuncTableEntry);
518 
519  return TRUE;
520 done_err:
522  return FALSE;
523 }
524 #endif /* DBGHELP_STATIC_LIB */
525 
526 static unsigned i386_map_dwarf_register(unsigned regno, BOOL eh_frame)
527 {
528  unsigned reg;
529 
530  switch (regno)
531  {
532  case 0: reg = CV_REG_EAX; break;
533  case 1: reg = CV_REG_ECX; break;
534  case 2: reg = CV_REG_EDX; break;
535  case 3: reg = CV_REG_EBX; break;
536  case 4:
537  case 5:
538 #ifdef __APPLE__
539  /* On OS X, DWARF eh_frame uses a different mapping for the registers. It's
540  apparently the mapping as emitted by GCC, at least at some point in its history. */
541  if (eh_frame)
542  reg = (regno == 4) ? CV_REG_EBP : CV_REG_ESP;
543  else
544 #endif
545  reg = (regno == 4) ? CV_REG_ESP : CV_REG_EBP;
546  break;
547  case 6: reg = CV_REG_ESI; break;
548  case 7: reg = CV_REG_EDI; break;
549  case 8: reg = CV_REG_EIP; break;
550  case 9: reg = CV_REG_EFLAGS; break;
551  case 10: reg = CV_REG_CS; break;
552  case 11: reg = CV_REG_SS; break;
553  case 12: reg = CV_REG_DS; break;
554  case 13: reg = CV_REG_ES; break;
555  case 14: reg = CV_REG_FS; break;
556  case 15: reg = CV_REG_GS; break;
557  case 16: case 17: case 18: case 19:
558  case 20: case 21: case 22: case 23:
559  reg = CV_REG_ST0 + regno - 16; break;
560  case 24: reg = CV_REG_CTRL; break;
561  case 25: reg = CV_REG_STAT; break;
562  case 26: reg = CV_REG_TAG; break;
563  case 27: reg = CV_REG_FPCS; break;
564  case 28: reg = CV_REG_FPIP; break;
565  case 29: reg = CV_REG_FPDS; break;
566  case 30: reg = CV_REG_FPDO; break;
567 /*
568 reg: fop 31
569 */
570  case 32: case 33: case 34: case 35:
571  case 36: case 37: case 38: case 39:
572  reg = CV_REG_XMM0 + regno - 32; break;
573  case 40: reg = CV_REG_MXCSR; break;
574  default:
575  FIXME("Don't know how to map register %d\n", regno);
576  return 0;
577  }
578  return reg;
579 }
580 
581 static void* i386_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
582 {
583 #ifdef __i386__
584  switch (regno)
585  {
586  case CV_REG_EAX: *size = sizeof(ctx->Eax); return &ctx->Eax;
587  case CV_REG_EDX: *size = sizeof(ctx->Edx); return &ctx->Edx;
588  case CV_REG_ECX: *size = sizeof(ctx->Ecx); return &ctx->Ecx;
589  case CV_REG_EBX: *size = sizeof(ctx->Ebx); return &ctx->Ebx;
590  case CV_REG_ESI: *size = sizeof(ctx->Esi); return &ctx->Esi;
591  case CV_REG_EDI: *size = sizeof(ctx->Edi); return &ctx->Edi;
592  case CV_REG_EBP: *size = sizeof(ctx->Ebp); return &ctx->Ebp;
593  case CV_REG_ESP: *size = sizeof(ctx->Esp); return &ctx->Esp;
594  case CV_REG_EIP: *size = sizeof(ctx->Eip); return &ctx->Eip;
595 
596  /* These are x87 floating point registers... They do not match a C type in
597  * the Linux ABI, so hardcode their 80-bitness. */
598  case CV_REG_ST0 + 0: *size = 10; return &ctx->FloatSave.RegisterArea[0*10];
599  case CV_REG_ST0 + 1: *size = 10; return &ctx->FloatSave.RegisterArea[1*10];
600  case CV_REG_ST0 + 2: *size = 10; return &ctx->FloatSave.RegisterArea[2*10];
601  case CV_REG_ST0 + 3: *size = 10; return &ctx->FloatSave.RegisterArea[3*10];
602  case CV_REG_ST0 + 4: *size = 10; return &ctx->FloatSave.RegisterArea[4*10];
603  case CV_REG_ST0 + 5: *size = 10; return &ctx->FloatSave.RegisterArea[5*10];
604  case CV_REG_ST0 + 6: *size = 10; return &ctx->FloatSave.RegisterArea[6*10];
605  case CV_REG_ST0 + 7: *size = 10; return &ctx->FloatSave.RegisterArea[7*10];
606 
607  case CV_REG_CTRL: *size = sizeof(DWORD); return &ctx->FloatSave.ControlWord;
608  case CV_REG_STAT: *size = sizeof(DWORD); return &ctx->FloatSave.StatusWord;
609  case CV_REG_TAG: *size = sizeof(DWORD); return &ctx->FloatSave.TagWord;
610  case CV_REG_FPCS: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorSelector;
611  case CV_REG_FPIP: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorOffset;
612  case CV_REG_FPDS: *size = sizeof(DWORD); return &ctx->FloatSave.DataSelector;
613  case CV_REG_FPDO: *size = sizeof(DWORD); return &ctx->FloatSave.DataOffset;
614 
615  case CV_REG_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
616  case CV_REG_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
617  case CV_REG_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
618  case CV_REG_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
619  case CV_REG_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
620  case CV_REG_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
621  case CV_REG_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
622 
623  }
624 #endif
625  FIXME("Unknown register %x\n", regno);
626  return NULL;
627 }
628 
629 static const char* i386_fetch_regname(unsigned regno)
630 {
631  switch (regno)
632  {
633  case CV_REG_EAX: return "eax";
634  case CV_REG_EDX: return "edx";
635  case CV_REG_ECX: return "ecx";
636  case CV_REG_EBX: return "ebx";
637  case CV_REG_ESI: return "esi";
638  case CV_REG_EDI: return "edi";
639  case CV_REG_EBP: return "ebp";
640  case CV_REG_ESP: return "esp";
641  case CV_REG_EIP: return "eip";
642 
643  case CV_REG_ST0 + 0: return "st0";
644  case CV_REG_ST0 + 1: return "st1";
645  case CV_REG_ST0 + 2: return "st2";
646  case CV_REG_ST0 + 3: return "st3";
647  case CV_REG_ST0 + 4: return "st4";
648  case CV_REG_ST0 + 5: return "st5";
649  case CV_REG_ST0 + 6: return "st6";
650  case CV_REG_ST0 + 7: return "st7";
651 
652  case CV_REG_EFLAGS: return "eflags";
653  case CV_REG_ES: return "es";
654  case CV_REG_CS: return "cs";
655  case CV_REG_SS: return "ss";
656  case CV_REG_DS: return "ds";
657  case CV_REG_FS: return "fs";
658  case CV_REG_GS: return "gs";
659 
660  case CV_REG_CTRL: return "fpControl";
661  case CV_REG_STAT: return "fpStatus";
662  case CV_REG_TAG: return "fpTag";
663  case CV_REG_FPCS: return "fpCS";
664  case CV_REG_FPIP: return "fpIP";
665  case CV_REG_FPDS: return "fpDS";
666  case CV_REG_FPDO: return "fpData";
667 
668  case CV_REG_XMM0 + 0: return "xmm0";
669  case CV_REG_XMM0 + 1: return "xmm1";
670  case CV_REG_XMM0 + 2: return "xmm2";
671  case CV_REG_XMM0 + 3: return "xmm3";
672  case CV_REG_XMM0 + 4: return "xmm4";
673  case CV_REG_XMM0 + 5: return "xmm5";
674  case CV_REG_XMM0 + 6: return "xmm6";
675  case CV_REG_XMM0 + 7: return "xmm7";
676 
677  case CV_REG_MXCSR: return "MxCSR";
678  }
679  FIXME("Unknown register %x\n", regno);
680  return NULL;
681 }
682 
683 #ifndef DBGHELP_STATIC_LIB
684 static BOOL i386_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
685 {
687  {
688  /* FIXME: crop values across module boundaries, */
689 #ifdef __i386__
690  ULONG base = ctx->Eip <= 0x80 ? 0 : ctx->Eip - 0x80;
691  minidump_add_memory_block(dc, base, ctx->Eip + 0x80 - base, 0);
692 #endif
693  }
694 
695  return TRUE;
696 }
697 #endif
698 
699 static BOOL i386_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags)
700 {
701  /* FIXME: actually, we should probably take care of FPO data, unless it's stored in
702  * function table minidump stream
703  */
704  return FALSE;
705 }
706 
709  4,
710  CV_REG_EBP,
711 #ifndef DBGHELP_STATIC_LIB
714 #else
715  NULL,
716  NULL,
717 #endif
718  NULL,
722 #ifndef DBGHELP_STATIC_LIB
725 #else
726  NULL,
727  NULL,
728 #endif
729 };
char * name
Definition: wpp.c:36
#define OFFSETOF(ptr)
Definition: windef16.h:51
#define TRUE
Definition: types.h:120
#define set_curr_mode(m)
Definition: cpu_i386.c:155
#define IS_VM86_MODE(ctx)
Definition: cpu_i386.c:38
ULONG Esp
Definition: nt_native.h:1479
#define DWORD_PTR
Definition: treelist.c:76
ULONG Eip
Definition: nt_native.h:1476
FLOATING_SAVE_AREA FloatSave
Definition: nt_native.h:1446
Definition: http.c:6587
static BOOL i386_stack_walk(struct cpu_stack_walk *csw, LPSTACKFRAME64 frame, CONTEXT *context)
Definition: cpu_i386.c:159
struct _LDT_ENTRY::@342::@344 Bits
STACK32FRAME * frame32
Definition: compat.h:2106
#define WARN(fmt,...)
Definition: debug.h:111
ULONG Ecx
Definition: nt_native.h:1467
GLintptr offset
Definition: glext.h:5920
void * sw_table_access(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:120
#define assert(x)
Definition: debug.h:53
HDC dc
Definition: cylfrac.c:34
DWORD64 Params[4]
Definition: compat.h:1048
ULONG SegGs
Definition: nt_native.h:1453
static unsigned i386_map_dwarf_register(unsigned regno, BOOL eh_frame)
Definition: cpu_i386.c:526
ULONG SegFs
Definition: nt_native.h:1454
ULONG SegDs
Definition: nt_native.h:1456
ADDRESS64 AddrBStore
Definition: compat.h:1046
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN
Definition: minidump.c:338
#define curr_mode
Definition: cpu_i386.c:150
#define DWORD
Definition: nt_native.h:44
#define CONTEXT_SEGMENTS
Definition: nt_native.h:1371
WORD Segment
Definition: compat.h:816
struct _test_info info[]
Definition: SetCursorPos.c:19
#define SELECTOROF(ptr)
Definition: windef16.h:50
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
BOOL dwarf2_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, CONTEXT *context, ULONG_PTR *cfa) DECLSPEC_HIDDEN
Definition: dwarf.c:3265
BOOL pdb_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, CONTEXT *context, struct pdb_cmd_pair *cpair) DECLSPEC_HIDDEN
Definition: msc.c:3202
DWORD ebp
Definition: compat.h:2097
ADDRESS_MODE
Definition: compat.h:795
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD callfrom_ip
Definition: compat.h:2114
ULONG SegEs
Definition: nt_native.h:1455
ULONG Esi
Definition: nt_native.h:1464
#define FIXME(fmt,...)
Definition: debug.h:110
cpu_addr
DWORD64 sw_module_base(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:128
ULONG SegCs
Definition: nt_native.h:1477
#define inc_curr_count()
Definition: cpu_i386.c:156
#define next_switch
Definition: cpu_i386.c:153
smooth NULL
Definition: ftsmooth.c:416
ULONG Edx
Definition: nt_native.h:1466
SEGPTR frame16
Definition: compat.h:2093
ULONG EFlags
Definition: nt_native.h:1478
DWORD64 sw_xlat_addr(struct cpu_stack_walk *csw, ADDRESS64 *addr) DECLSPEC_HIDDEN
Definition: stack.c:105
GLuint index
Definition: glext.h:6031
#define curr_switch
Definition: cpu_i386.c:152
ULONG Ebx
Definition: nt_native.h:1465
DWORD ecx
Definition: compat.h:2108
ULONG ContextFlags
Definition: compat.h:331
static BOOL i386_fetch_minidump_thread(struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
Definition: cpu_i386.c:684
DWORD ebp
Definition: compat.h:2109
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
UCHAR RegisterArea[SIZE_OF_80387_REGISTERS]
Definition: nt_native.h:1390
const char * wine_dbgstr_addr(const ADDRESS64 *addr)
Definition: dbghelp.c:123
#define TRACE(s)
Definition: solgame.cpp:4
#define CONTEXT_CONTROL
Definition: compat.h:265
GLsizeiptr size
Definition: glext.h:5919
if(!(yy_init))
Definition: macro.lex.yy.c:714
static void * i386_fetch_context_reg(CONTEXT *ctx, unsigned regno, unsigned *size)
Definition: cpu_i386.c:581
DWORD retaddr
Definition: compat.h:2098
DWORD entry_point
Definition: compat.h:2118
DWORD64 Offset
Definition: compat.h:815
ADDRESS64 AddrReturn
Definition: compat.h:1043
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD module_cs
Definition: compat.h:2115
union _LDT_ENTRY::@342 HighWord
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
GLbitfield flags
Definition: glext.h:7161
PVOID FuncTableEntry
Definition: compat.h:1047
ADDRESS64 AddrStack
Definition: compat.h:1045
GLenum const GLvoid * addr
Definition: glext.h:9621
DECLSPEC_HIDDEN struct cpu cpu_i386
Definition: cpu_i386.c:707
seg
Definition: i386-dis.c:3857
ULONG Eax
Definition: nt_native.h:1468
uint32_t DWORD_PTR
Definition: typedefs.h:63
DWORD relay
Definition: compat.h:2116
Definition: compat.h:428
BOOL sw_read_mem(struct cpu_stack_walk *csw, DWORD64 addr, void *ptr, DWORD sz) DECLSPEC_HIDDEN
Definition: stack.c:96
Definition: compat.h:484
st_mode
Definition: cpu_i386.c:143
static const char * i386_fetch_regname(unsigned regno)
Definition: cpu_i386.c:629
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
ULONG SegSs
Definition: nt_native.h:1480
WORD entry_ip
Definition: compat.h:2117
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:829
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static BOOL i386_fetch_minidump_module(struct dump_context *dc, unsigned index, unsigned flags)
Definition: cpu_i386.c:699
ADDRESS64 AddrPC
Definition: compat.h:1042
static int reg
Definition: i386-dis.c:1275
HANDLE hThread
Definition: wizard.c:27
Definition: tnmain.cpp:412
unsigned int ULONG
Definition: retypes.h:1
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
#define curr_count
Definition: cpu_i386.c:151
GLfloat GLfloat p
Definition: glext.h:8902
static const WCHAR ca[]
Definition: main.c:457
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define memset(x, y, z)
Definition: compat.h:39
ADDRESS_MODE Mode
Definition: compat.h:817
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp)
ULONG Ebp
Definition: nt_native.h:1475
DWORD edx
Definition: compat.h:2107
ULONG Edi
Definition: nt_native.h:1463
ADDRESS64 AddrFrame
Definition: compat.h:1044
BOOL Virtual
Definition: compat.h:1050
static BOOL i386_get_addr(HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
Definition: cpu_i386.c:80