dbghelp: In i386 stack unwinder, ensure we always return decent 64bit values.

This commit is contained in:
Eric Pouech 2011-03-13 21:30:12 +01:00 committed by Alexandre Julliard
parent a74c29e081
commit c5f329e62c
1 changed files with 23 additions and 18 deletions

View File

@ -105,7 +105,8 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
char ch; char ch;
ADDRESS64 tmp; ADDRESS64 tmp;
DWORD p; DWORD p;
WORD val; WORD val16;
DWORD val32;
BOOL do_switch; BOOL do_switch;
unsigned deltapc = 1; unsigned deltapc = 1;
#ifdef __i386__ #ifdef __i386__
@ -360,9 +361,9 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD); frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
/* "pop up" previous BP value */ /* "pop up" previous BP value */
if (!sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame), if (!sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
&val, sizeof(WORD))) &val16, sizeof(WORD)))
goto done_err; goto done_err;
frame->AddrFrame.Offset = val; frame->AddrFrame.Offset = val16;
} }
else else
{ {
@ -394,9 +395,9 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
#endif #endif
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD); frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */ /* "pop up" previous EBP value */
if (!sw_read_mem(csw, frame->AddrFrame.Offset, if (!sw_read_mem(csw, frame->AddrFrame.Offset, &val32, sizeof(DWORD)))
&frame->AddrFrame.Offset, sizeof(DWORD)))
goto done_err; goto done_err;
frame->AddrFrame.Offset = val32;
} }
} }
} }
@ -406,30 +407,30 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
unsigned int i; unsigned int i;
p = sw_xlat_addr(csw, &frame->AddrFrame); p = sw_xlat_addr(csw, &frame->AddrFrame);
if (!sw_read_mem(csw, p + sizeof(WORD), &val, sizeof(WORD))) if (!sw_read_mem(csw, p + sizeof(WORD), &val16, sizeof(WORD)))
goto done_err; goto done_err;
frame->AddrReturn.Offset = val; frame->AddrReturn.Offset = val16;
/* get potential cs if a far call was used */ /* get potential cs if a far call was used */
if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val, sizeof(WORD))) if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val16, sizeof(WORD)))
goto done_err; goto done_err;
if (frame->AddrFrame.Offset & 1) if (frame->AddrFrame.Offset & 1)
frame->AddrReturn.Segment = val; /* far call assumed */ frame->AddrReturn.Segment = val16; /* far call assumed */
else else
{ {
/* not explicitly marked as far call, /* not explicitly marked as far call,
* but check whether it could be anyway * but check whether it could be anyway
*/ */
if ((val & 7) == 7 && val != frame->AddrReturn.Segment) if ((val16 & 7) == 7 && val16 != frame->AddrReturn.Segment)
{ {
LDT_ENTRY le; LDT_ENTRY le;
if (GetThreadSelectorEntry(csw->hThread, val, &le) && if (GetThreadSelectorEntry(csw->hThread, val16, &le) &&
(le.HighWord.Bits.Type & 0x08)) /* code segment */ (le.HighWord.Bits.Type & 0x08)) /* code segment */
{ {
/* it is very uncommon to push a code segment cs as /* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases * a parameter, so this should work in most cases
*/ */
frame->AddrReturn.Segment = val; frame->AddrReturn.Segment = val16;
} }
} }
} }
@ -440,21 +441,25 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
*/ */
for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++) for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{ {
sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val, sizeof(val)); sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val16, sizeof(val16));
frame->Params[i] = val; frame->Params[i] = val16;
} }
} }
else else
{ {
if (!sw_read_mem(csw, frame->AddrFrame.Offset + sizeof(DWORD), unsigned int i;
&frame->AddrReturn.Offset, sizeof(DWORD))) if (!sw_read_mem(csw, frame->AddrFrame.Offset + sizeof(DWORD), &val32, sizeof(DWORD)))
{ {
WARN("Cannot read new frame offset %p\n", WARN("Cannot read new frame offset %p\n",
(void*)(DWORD_PTR)(frame->AddrFrame.Offset + (int)sizeof(DWORD))); (void*)(DWORD_PTR)(frame->AddrFrame.Offset + (int)sizeof(DWORD)));
goto done_err; goto done_err;
} }
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD), frame->AddrReturn.Offset = val32;
frame->Params, sizeof(frame->Params)); for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{
sw_read_mem(csw, frame->AddrFrame.Offset + (2 + i) * sizeof(DWORD), &val32, sizeof(val32));
frame->Params[i] = val32;
}
} }
#ifdef __i386__ #ifdef __i386__
if (context) if (context)