dbghelp: In i386 stack unwinder, ensure we always return decent 64bit values.
This commit is contained in:
parent
a74c29e081
commit
c5f329e62c
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue