dbghelp: Extend dwarf stack unwinding by reading information out of .debug_frame sections.
Implement dwarf stack unwinding for i386 CPU.
This commit is contained in:
parent
34ef8d2113
commit
1b68d4e7ce
|
@ -107,6 +107,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
||||||
DWORD p;
|
DWORD p;
|
||||||
WORD val;
|
WORD val;
|
||||||
BOOL do_switch;
|
BOOL do_switch;
|
||||||
|
unsigned deltapc = 1;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (curr_mode >= stm_done) return FALSE;
|
if (curr_mode >= stm_done) return FALSE;
|
||||||
|
@ -132,6 +133,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
||||||
|
|
||||||
/* Init done */
|
/* Init done */
|
||||||
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
|
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
|
||||||
|
deltapc = 0;
|
||||||
|
|
||||||
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
|
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
|
||||||
* address space
|
* address space
|
||||||
|
@ -191,6 +193,21 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
||||||
* we will get it in the next frame
|
* we will get it in the next frame
|
||||||
*/
|
*/
|
||||||
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
|
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
|
||||||
|
#ifdef __i386__
|
||||||
|
if (curr_mode == stm_32bit)
|
||||||
|
{
|
||||||
|
DWORD_PTR xframe;
|
||||||
|
|
||||||
|
if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
|
||||||
|
{
|
||||||
|
frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
|
||||||
|
frame->AddrStack.Offset = context->Esp = xframe;
|
||||||
|
frame->AddrFrame.Offset = context->Ebp;
|
||||||
|
frame->AddrReturn.Offset = context->Eip;
|
||||||
|
goto done_pep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -317,6 +334,18 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef __i386__
|
||||||
|
DWORD_PTR xframe;
|
||||||
|
|
||||||
|
if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
|
||||||
|
{
|
||||||
|
frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
|
||||||
|
frame->AddrStack.Offset = context->Esp = xframe;
|
||||||
|
frame->AddrFrame.Offset = context->Ebp;
|
||||||
|
frame->AddrReturn.Offset = context->Eip;
|
||||||
|
goto done_pep;
|
||||||
|
}
|
||||||
|
#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,
|
||||||
|
@ -381,6 +410,8 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
||||||
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
|
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
|
||||||
frame->Params, sizeof(frame->Params));
|
frame->Params, sizeof(frame->Params));
|
||||||
}
|
}
|
||||||
|
goto done_pep; /* just to ensure done_pep label is referenced */
|
||||||
|
done_pep:
|
||||||
|
|
||||||
frame->Far = TRUE;
|
frame->Far = TRUE;
|
||||||
frame->Virtual = TRUE;
|
frame->Virtual = TRUE;
|
||||||
|
|
|
@ -2403,14 +2403,17 @@ static BOOL parse_cie_details(dwarf2_traverse_context_t* ctx, struct frame_info*
|
||||||
|
|
||||||
static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR delta,
|
static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR delta,
|
||||||
dwarf2_traverse_context_t* fde_ctx, dwarf2_traverse_context_t* cie_ctx,
|
dwarf2_traverse_context_t* fde_ctx, dwarf2_traverse_context_t* cie_ctx,
|
||||||
struct frame_info* info)
|
struct frame_info* info, BOOL in_eh_frame)
|
||||||
{
|
{
|
||||||
const unsigned char* ptr_blk;
|
const unsigned char* ptr_blk;
|
||||||
const unsigned char* cie_ptr;
|
const unsigned char* cie_ptr;
|
||||||
const unsigned char* last_cie_ptr = (const unsigned char*)~0;
|
const unsigned char* last_cie_ptr = (const unsigned char*)~0;
|
||||||
unsigned len, id;
|
unsigned len, id;
|
||||||
unsigned long start, range;
|
unsigned long start, range;
|
||||||
|
unsigned cie_id;
|
||||||
|
const BYTE* start_data = fde_ctx->data;
|
||||||
|
|
||||||
|
cie_id = in_eh_frame ? 0 : DW_CIE_ID;
|
||||||
for (; fde_ctx->data + 2 * 4 < fde_ctx->end_data; fde_ctx->data = ptr_blk)
|
for (; fde_ctx->data + 2 * 4 < fde_ctx->end_data; fde_ctx->data = ptr_blk)
|
||||||
{
|
{
|
||||||
/* find the FDE for address addr (skip CIE) */
|
/* find the FDE for address addr (skip CIE) */
|
||||||
|
@ -2418,7 +2421,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
|
||||||
if (len == 0xffffffff) FIXME("Unsupported yet 64-bit CIEs\n");
|
if (len == 0xffffffff) FIXME("Unsupported yet 64-bit CIEs\n");
|
||||||
ptr_blk = fde_ctx->data + len;
|
ptr_blk = fde_ctx->data + len;
|
||||||
id = dwarf2_parse_u4(fde_ctx);
|
id = dwarf2_parse_u4(fde_ctx);
|
||||||
if (id == 0) /* FIXME DW_CIE_ID */
|
if (id == cie_id)
|
||||||
{
|
{
|
||||||
last_cie_ptr = fde_ctx->data - 8;
|
last_cie_ptr = fde_ctx->data - 8;
|
||||||
/* we need some bits out of the CIE in order to parse all contents */
|
/* we need some bits out of the CIE in order to parse all contents */
|
||||||
|
@ -2428,7 +2431,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
|
||||||
cie_ctx->word_size = fde_ctx->word_size;
|
cie_ctx->word_size = fde_ctx->word_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cie_ptr = fde_ctx->data - id - 4;
|
cie_ptr = (in_eh_frame) ? fde_ctx->data - id - 4 : start_data + id;
|
||||||
if (cie_ptr != last_cie_ptr)
|
if (cie_ptr != last_cie_ptr)
|
||||||
{
|
{
|
||||||
last_cie_ptr = cie_ptr;
|
last_cie_ptr = cie_ptr;
|
||||||
|
@ -2436,7 +2439,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
|
||||||
cie_ctx->word_size = fde_ctx->word_size;
|
cie_ctx->word_size = fde_ctx->word_size;
|
||||||
cie_ctx->end_data = cie_ptr + 4;
|
cie_ctx->end_data = cie_ptr + 4;
|
||||||
cie_ctx->end_data = cie_ptr + 4 + dwarf2_parse_u4(cie_ctx);
|
cie_ctx->end_data = cie_ptr + 4 + dwarf2_parse_u4(cie_ctx);
|
||||||
if (dwarf2_parse_u4(cie_ctx) != 0) /* FIXME DW_CIE_ID */
|
if (dwarf2_parse_u4(cie_ctx) != cie_id)
|
||||||
{
|
{
|
||||||
FIXME("wrong CIE pointer\n");
|
FIXME("wrong CIE pointer\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2925,11 +2928,18 @@ BOOL dwarf2_virtual_unwind(struct cpu_stack_walk* csw, ULONG_PTR ip, CONTEXT* co
|
||||||
*/
|
*/
|
||||||
delta = pair.effective->module.BaseOfImage + modfmt->u.dwarf2_info->eh_frame.rva -
|
delta = pair.effective->module.BaseOfImage + modfmt->u.dwarf2_info->eh_frame.rva -
|
||||||
(DWORD_PTR)modfmt->u.dwarf2_info->eh_frame.address;
|
(DWORD_PTR)modfmt->u.dwarf2_info->eh_frame.address;
|
||||||
if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info))
|
if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, TRUE))
|
||||||
|
{
|
||||||
|
fde_ctx.data = modfmt->u.dwarf2_info->debug_frame.address;
|
||||||
|
fde_ctx.end_data = fde_ctx.data + modfmt->u.dwarf2_info->debug_frame.size;
|
||||||
|
fde_ctx.word_size = modfmt->u.dwarf2_info->word_size;
|
||||||
|
delta = pair.effective->reloc_delta;
|
||||||
|
if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, FALSE))
|
||||||
{
|
{
|
||||||
TRACE("Couldn't find information for %lx\n", ip);
|
TRACE("Couldn't find information for %lx\n", ip);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("function %lx/%lx code_align %lu data_align %ld retaddr %s\n",
|
TRACE("function %lx/%lx code_align %lu data_align %ld retaddr %s\n",
|
||||||
ip, info.ip, info.code_align, info.data_align,
|
ip, info.ip, info.code_align, info.data_align,
|
||||||
|
|
Loading…
Reference in New Issue