ReactOS  0.4.13-dev-650-g34bf247
cpu_i386.c File Reference
#include <assert.h>
#include "ntstatus.h"
#include "dbghelp_private.h"
#include "wine/winbase16.h"
#include "winternl.h"
#include "wine/debug.h"
Include dependency graph for cpu_i386.c:

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 
#define V86_FLAG   0x00020000
 
#define IS_VM86_MODE(ctx)   (ctx->EFlags & V86_FLAG)
 
#define __CurrentModeCount   0
 
#define __CurrentSwitch   1
 
#define __NextSwitch   2
 
#define curr_mode   (frame->Reserved[__CurrentModeCount] & 0x0F)
 
#define curr_count   (frame->Reserved[__CurrentModeCount] >> 4)
 
#define curr_switch   (frame->Reserved[__CurrentSwitch])
 
#define next_switch   (frame->Reserved[__NextSwitch])
 
#define set_curr_mode(m)   {frame->Reserved[__CurrentModeCount] &= ~0x0F; frame->Reserved[__CurrentModeCount] |= (m & 0x0F);}
 
#define inc_curr_count()   (frame->Reserved[__CurrentModeCount] += 0x10)
 

Enumerations

enum  st_mode { stm_start, stm_32bit, stm_16bit, stm_done }
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (dbghelp)
 
static BOOL i386_get_addr (HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
 
static BOOL i386_stack_walk (struct cpu_stack_walk *csw, LPSTACKFRAME64 frame, CONTEXT *context)
 
static unsigned i386_map_dwarf_register (unsigned regno, BOOL eh_frame)
 
static voidi386_fetch_context_reg (CONTEXT *ctx, unsigned regno, unsigned *size)
 
static const chari386_fetch_regname (unsigned regno)
 
static BOOL i386_fetch_minidump_thread (struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
 
static BOOL i386_fetch_minidump_module (struct dump_context *dc, unsigned index, unsigned flags)
 

Variables

DECLSPEC_HIDDEN struct cpu cpu_i386
 

Macro Definition Documentation

◆ __CurrentModeCount

#define __CurrentModeCount   0

Definition at line 146 of file cpu_i386.c.

◆ __CurrentSwitch

#define __CurrentSwitch   1

Definition at line 147 of file cpu_i386.c.

◆ __NextSwitch

#define __NextSwitch   2

Definition at line 148 of file cpu_i386.c.

◆ curr_count

#define curr_count   (frame->Reserved[__CurrentModeCount] >> 4)

Definition at line 151 of file cpu_i386.c.

◆ curr_mode

#define curr_mode   (frame->Reserved[__CurrentModeCount] & 0x0F)

Definition at line 150 of file cpu_i386.c.

◆ curr_switch

#define curr_switch   (frame->Reserved[__CurrentSwitch])

Definition at line 152 of file cpu_i386.c.

◆ inc_curr_count

#define inc_curr_count ( )    (frame->Reserved[__CurrentModeCount] += 0x10)

Definition at line 156 of file cpu_i386.c.

◆ IS_VM86_MODE

#define IS_VM86_MODE (   ctx)    (ctx->EFlags & V86_FLAG)

Definition at line 38 of file cpu_i386.c.

◆ next_switch

#define next_switch   (frame->Reserved[__NextSwitch])

Definition at line 153 of file cpu_i386.c.

◆ set_curr_mode

#define set_curr_mode (   m)    {frame->Reserved[__CurrentModeCount] &= ~0x0F; frame->Reserved[__CurrentModeCount] |= (m & 0x0F);}

Definition at line 155 of file cpu_i386.c.

◆ V86_FLAG

#define V86_FLAG   0x00020000

Definition at line 36 of file cpu_i386.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 25 of file cpu_i386.c.

Enumeration Type Documentation

◆ st_mode

Enumerator
stm_start 
stm_32bit 
stm_16bit 
stm_done 

Definition at line 143 of file cpu_i386.c.

Function Documentation

◆ i386_fetch_context_reg()

static void* i386_fetch_context_reg ( CONTEXT ctx,
unsigned  regno,
unsigned *  size 
)
static

Definition at line 581 of file cpu_i386.c.

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 }
ULONG Esp
Definition: nt_native.h:1479
ULONG Eip
Definition: nt_native.h:1476
FLOATING_SAVE_AREA FloatSave
Definition: nt_native.h:1446
ULONG Ecx
Definition: nt_native.h:1467
ULONG SegGs
Definition: nt_native.h:1453
ULONG SegFs
Definition: nt_native.h:1454
ULONG SegDs
Definition: nt_native.h:1456
#define DWORD
Definition: nt_native.h:44
ULONG SegEs
Definition: nt_native.h:1455
ULONG Esi
Definition: nt_native.h:1464
#define FIXME(fmt,...)
Definition: debug.h:110
ULONG SegCs
Definition: nt_native.h:1477
smooth NULL
Definition: ftsmooth.c:416
ULONG Edx
Definition: nt_native.h:1466
ULONG EFlags
Definition: nt_native.h:1478
ULONG Ebx
Definition: nt_native.h:1465
UCHAR RegisterArea[SIZE_OF_80387_REGISTERS]
Definition: nt_native.h:1390
GLsizeiptr size
Definition: glext.h:5919
ULONG Eax
Definition: nt_native.h:1468
ULONG SegSs
Definition: nt_native.h:1480
ULONG Ebp
Definition: nt_native.h:1475
ULONG Edi
Definition: nt_native.h:1463

◆ i386_fetch_minidump_module()

static BOOL i386_fetch_minidump_module ( struct dump_context dc,
unsigned  index,
unsigned  flags 
)
static

Definition at line 699 of file cpu_i386.c.

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 }

◆ i386_fetch_minidump_thread()

static BOOL i386_fetch_minidump_thread ( struct dump_context dc,
unsigned  index,
unsigned  flags,
const CONTEXT ctx 
)
static

Definition at line 684 of file cpu_i386.c.

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 }
#define TRUE
Definition: types.h:120
ULONG Eip
Definition: nt_native.h:1476
HDC dc
Definition: cylfrac.c:34
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN
Definition: minidump.c:338
ULONG ContextFlags
Definition: compat.h:331
GLbitfield flags
Definition: glext.h:7161
unsigned int ULONG
Definition: retypes.h:1

◆ i386_fetch_regname()

static const char* i386_fetch_regname ( unsigned  regno)
static

Definition at line 629 of file cpu_i386.c.

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 }
#define FIXME(fmt,...)
Definition: debug.h:110
smooth NULL
Definition: ftsmooth.c:416

◆ i386_get_addr()

static BOOL i386_get_addr ( HANDLE  hThread,
const CONTEXT ctx,
enum cpu_addr  ca,
ADDRESS64 addr 
)
static

Definition at line 80 of file cpu_i386.c.

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 }
ULONG Esp
Definition: nt_native.h:1479
ULONG Eip
Definition: nt_native.h:1476
ULONG SegCs
Definition: nt_native.h:1477
GLenum const GLvoid * addr
Definition: glext.h:9621
ULONG SegSs
Definition: nt_native.h:1480
HANDLE hThread
Definition: wizard.c:27
static const WCHAR ca[]
Definition: main.c:457
ULONG Ebp
Definition: nt_native.h:1475

◆ i386_map_dwarf_register()

static unsigned i386_map_dwarf_register ( unsigned  regno,
BOOL  eh_frame 
)
static

Definition at line 526 of file cpu_i386.c.

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 }
#define FIXME(fmt,...)
Definition: debug.h:110
static int reg
Definition: i386-dis.c:1275

◆ i386_stack_walk()

static BOOL i386_stack_walk ( struct cpu_stack_walk csw,
LPSTACKFRAME64  frame,
CONTEXT context 
)
static

Definition at line 159 of file cpu_i386.c.

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 }
#define OFFSETOF(ptr)
Definition: windef16.h:51
#define TRUE
Definition: types.h:120
#define set_curr_mode(m)
Definition: cpu_i386.c:155
#define DWORD_PTR
Definition: treelist.c:76
ULONG Eip
Definition: nt_native.h:1476
Definition: http.c:6587
STACK32FRAME * frame32
Definition: compat.h:2106
#define WARN(fmt,...)
Definition: debug.h:111
void * sw_table_access(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:120
#define assert(x)
Definition: debug.h:53
DWORD64 Params[4]
Definition: compat.h:1048
ADDRESS64 AddrBStore
Definition: compat.h:1046
#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
DWORD ebp
Definition: compat.h:2097
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD callfrom_ip
Definition: compat.h:2114
#define FIXME(fmt,...)
Definition: debug.h:110
DWORD64 sw_module_base(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:128
#define inc_curr_count()
Definition: cpu_i386.c:156
#define next_switch
Definition: cpu_i386.c:153
smooth NULL
Definition: ftsmooth.c:416
SEGPTR frame16
Definition: compat.h:2093
DWORD64 sw_xlat_addr(struct cpu_stack_walk *csw, ADDRESS64 *addr) DECLSPEC_HIDDEN
Definition: stack.c:105
#define curr_switch
Definition: cpu_i386.c:152
DWORD ecx
Definition: compat.h:2108
DWORD ebp
Definition: compat.h:2109
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
if(!(yy_init))
Definition: macro.lex.yy.c:714
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
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
PVOID FuncTableEntry
Definition: compat.h:1047
ADDRESS64 AddrStack
Definition: compat.h:1045
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
WORD entry_ip
Definition: compat.h:2117
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:791
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
ADDRESS64 AddrPC
Definition: compat.h:1042
union _LDT_ENTRY::@340 HighWord
Definition: tnmain.cpp:412
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
struct _LDT_ENTRY::@340::@342 Bits
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define memset(x, y, z)
Definition: compat.h:39
ADDRESS_MODE Mode
Definition: compat.h:817
DWORD edx
Definition: compat.h:2107
ADDRESS64 AddrFrame
Definition: compat.h:1044
BOOL Virtual
Definition: compat.h:1050

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( dbghelp  )

Variable Documentation

◆ cpu_i386

Initial value:
= {
4,
}
static BOOL i386_stack_walk(struct cpu_stack_walk *csw, LPSTACKFRAME64 frame, CONTEXT *context)
Definition: cpu_i386.c:159
static unsigned i386_map_dwarf_register(unsigned regno, BOOL eh_frame)
Definition: cpu_i386.c:526
smooth NULL
Definition: ftsmooth.c:416
static BOOL i386_fetch_minidump_thread(struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
Definition: cpu_i386.c:684
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
static void * i386_fetch_context_reg(CONTEXT *ctx, unsigned regno, unsigned *size)
Definition: cpu_i386.c:581
static const char * i386_fetch_regname(unsigned regno)
Definition: cpu_i386.c:629
static BOOL i386_fetch_minidump_module(struct dump_context *dc, unsigned index, unsigned flags)
Definition: cpu_i386.c:699
static BOOL i386_get_addr(HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
Definition: cpu_i386.c:80

Definition at line 707 of file cpu_i386.c.