Module: wine Branch: master Commit: 1b68d4e7cec5b6d79b3811a34f59c3790d5a5e6a URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b68d4e7cec5b6d79b3811a34f...
Author: Eric Pouech eric.pouech@orange.fr Date: Thu Apr 1 21:24:20 2010 +0200
dbghelp: Extend dwarf stack unwinding by reading information out of .debug_frame sections.
Implement dwarf stack unwinding for i386 CPU.
---
dlls/dbghelp/cpu_i386.c | 31 +++++++++++++++++++++++++++++++ dlls/dbghelp/dwarf.c | 24 +++++++++++++++++------- 2 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/dlls/dbghelp/cpu_i386.c b/dlls/dbghelp/cpu_i386.c index 7a951f7..dc00410 100644 --- a/dlls/dbghelp/cpu_i386.c +++ b/dlls/dbghelp/cpu_i386.c @@ -107,6 +107,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO DWORD p; WORD val; BOOL do_switch; + unsigned deltapc = 1;
/* sanity check */ 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 */ curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit; + deltapc = 0;
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee * 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 */ 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 { @@ -317,6 +334,18 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO } 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); /* "pop up" previous EBP value */ 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), frame->Params, sizeof(frame->Params)); } + goto done_pep; /* just to ensure done_pep label is referenced */ +done_pep:
frame->Far = TRUE; frame->Virtual = TRUE; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 78860d7..68e322c 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -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, 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* cie_ptr; const unsigned char* last_cie_ptr = (const unsigned char*)~0; unsigned len, id; 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) { /* 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"); ptr_blk = fde_ctx->data + len; id = dwarf2_parse_u4(fde_ctx); - if (id == 0) /* FIXME DW_CIE_ID */ + if (id == cie_id) { last_cie_ptr = fde_ctx->data - 8; /* 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; 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) { 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->end_data = cie_ptr + 4; 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"); return FALSE; @@ -2925,10 +2928,17 @@ 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 - (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)) { - TRACE("Couldn't find information for %lx\n", ip); - return FALSE; + 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); + return FALSE; + } }
TRACE("function %lx/%lx code_align %lu data_align %ld retaddr %s\n",