The following series implements: - local scope management in dbghelp (instead of SymSetContext) - basic implementation of some inline context oriented APIs of dbghelp (when the inline context doesn't represent an inlined frame) - let winedbg use all those APIs instead of the (old = non inline context oriented APIs)
A+
---
Eric Pouech (10): dbghelp: let StackWalkEx() succeed even when inline mode is requested dbghelp: implement SymFromInlineContext() when context isn't in inline mode dbghelp: implement SymGetLineFromInlineContext*() when context isn't in inline mode dbghelp: add local scope information in struct process dbghelp: implement SymSetScopeFromAddr() and SymSetScopeFromIndex() dbghelp: rewrite SymSetContext() on top of SymSetScopeFromAddr() dbghelp: implement SymSetScopeFromInlineContext() when context isn't inlined programs/winedbg: add a pair of helpers for accessing frames' internal info programs/winedbg: use SymSetScopeFromAddr() instead of SymSetContext() programs/winedbg: use inline contexts oriented APIs for stack backtrace
dlls/dbghelp/dbghelp.c | 60 ++++++++++------ dlls/dbghelp/dbghelp_private.h | 23 +++++++ dlls/dbghelp/dwarf.c | 2 +- dlls/dbghelp/module.c | 10 ++- dlls/dbghelp/stack.c | 10 ++- dlls/dbghelp/symbol.c | 68 +++++++++++++----- programs/winedbg/debugger.h | 15 +++- programs/winedbg/stack.c | 121 +++++++++++++++------------------ programs/winedbg/symbol.c | 23 ++++--- 9 files changed, 212 insertions(+), 120 deletions(-)
fallback to regular StackWalki64() behavior
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/stack.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/stack.c b/dlls/dbghelp/stack.c index 6c70fc805cb..a93c454036c 100644 --- a/dlls/dbghelp/stack.c +++ b/dlls/dbghelp/stack.c @@ -298,9 +298,13 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread, } if (frame->InlineFrameContext != INLINE_FRAME_CONTEXT_IGNORE) { - FIXME("Inlined contexts are not supported yet\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + static BOOL once; + if (!once) + { + FIXME("Inlined contexts are not supported yet\n"); + once = TRUE; + } + frame->InlineFrameContext = INLINE_FRAME_CONTEXT_IGNORE; }
csw.hProcess = hProcess;
introduce also the bit-wise definition of an inline context
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp_private.h | 21 +++++++++++++++++++++ dlls/dbghelp/symbol.c | 15 ++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 2ebe6699a1d..6217701a457 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -845,3 +845,24 @@ extern struct symt_pointer* extern struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, const char* name) DECLSPEC_HIDDEN; + +/* Inline context encoding (different from what native does): + * bits 31:30: 3 ignore (includes INLINE_FRAME_CONTEXT_IGNORE=0xFFFFFFFF) + * 2 regular frame + * 1 frame with inlined function(s). + * 0 init (includes INLINE_FRAME_CONTEXT_INIT=0) + * so either stackwalkex is called with: + * - inlinectx=IGNORE, and we use (old) StackWalk64 behavior: + * - inlinectx=INIT, and StackWalkEx will upon return swing back&forth between: + * INLINE when the frame is from an inline site (inside a function) + * REGULAR when the frame is for a function without inline site + * bits 29:00 depth of inline site (way too big!!) + * 0 being the lowest inline site + */ +#define IFC_MODE_IGNORE 0xC0000000 +#define IFC_MODE_REGULAR 0x80000000 +#define IFC_MODE_INLINE 0x40000000 +#define IFC_MODE_INIT 0x00000000 +#define IFC_DEPTH_MASK 0x3FFFFFFF +#define IFC_MODE(x) ((x) & ~IFC_DEPTH_MASK) +#define IFC_DEPTH(x) ((x) & IFC_DEPTH_MASK) diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 19374999070..21616627af9 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -2497,9 +2497,18 @@ PWSTR WINAPI SymSetHomeDirectoryW(HANDLE hProcess, PCWSTR dir) */ BOOL WINAPI SymFromInlineContext(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, PDWORD64 disp, PSYMBOL_INFO si) { - FIXME("(%p, %#I64x, 0x%x, %p, %p): stub\n", hProcess, addr, inline_ctx, disp, si); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%p, %#I64x, 0x%x, %p, %p)\n", hProcess, addr, inline_ctx, disp, si); + + switch (IFC_MODE(inline_ctx)) + { + case IFC_MODE_IGNORE: + case IFC_MODE_REGULAR: + return SymFromAddr(hProcess, addr, disp, si); + case IFC_MODE_INLINE: + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } }
/******************************************************************
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/symbol.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 21616627af9..82c69b2e848 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -2537,16 +2537,37 @@ BOOL WINAPI SymFromInlineContextW(HANDLE hProcess, DWORD64 addr, ULONG inline_ct return ret; }
+static BOOL get_line_from_inline_context(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, + struct internal_line_t* intl) +{ + switch (IFC_MODE(inline_ctx)) + { + case IFC_MODE_INLINE: + case IFC_MODE_IGNORE: + case IFC_MODE_REGULAR: + return get_line_from_addr(hProcess, addr, disp, intl); + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + /****************************************************************** * SymGetLineFromInlineContext (DBGHELP.@) * */ BOOL WINAPI SymGetLineFromInlineContext(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, PIMAGEHLP_LINE64 line) { - FIXME("(%p, %#I64x, 0x%x, %#I64x, %p, %p): stub!\n", + struct internal_line_t intl; + + TRACE("(%p, %#I64x, 0x%x, %#I64x, %p, %p)\n", hProcess, addr, inline_ctx, mod_addr, disp, line); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + + if (line->SizeOfStruct < sizeof(*line)) return FALSE; + init_internal_line(&intl, FALSE); + + if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &intl)) return FALSE; + return internal_line_copy_toA64(&intl, line); }
/****************************************************************** @@ -2555,8 +2576,14 @@ BOOL WINAPI SymGetLineFromInlineContext(HANDLE hProcess, DWORD64 addr, ULONG inl */ BOOL WINAPI SymGetLineFromInlineContextW(HANDLE hProcess, DWORD64 addr, ULONG inline_ctx, DWORD64 mod_addr, PDWORD disp, PIMAGEHLP_LINEW64 line) { - FIXME("(%p, %#I64x, 0x%x, %#I64x, %p, %p): stub!\n", + struct internal_line_t intl; + + TRACE("(%p, %#I64x, 0x%x, %#I64x, %p, %p)\n", hProcess, addr, inline_ctx, mod_addr, disp, line); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + + if (line->SizeOfStruct < sizeof(*line)) return FALSE; + init_internal_line(&intl, TRUE); + + if (!get_line_from_inline_context(hProcess, addr, inline_ctx, mod_addr, disp, &intl)) return FALSE; + return internal_line_copy_toW64(&intl, line); }
- made SymSetContext() generate this information - let SymEnumSymboli() (when dealing with local symbols) use this information instead of the stack frame
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.c | 14 ++++++++++++-- dlls/dbghelp/dbghelp_private.h | 2 ++ dlls/dbghelp/dwarf.c | 2 +- dlls/dbghelp/module.c | 10 +++++++++- dlls/dbghelp/symbol.c | 14 ++++++-------- 5 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index 00f02423fef..64ceb447ee9 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -606,11 +606,21 @@ BOOL WINAPI SymSetParentWindow(HWND hwnd) BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context) { - struct process* pcs = process_find_by_handle(hProcess); + struct process* pcs; + struct module_pair pair; + struct symt_ht* sym; + + pair.pcs = pcs = process_find_by_handle(hProcess); if (!pcs) return FALSE;
- if (!module_find_by_addr(pcs, StackFrame->InstructionOffset, DMT_UNKNOWN)) + pair.requested = module_find_by_addr(pair.pcs, StackFrame->InstructionOffset, DMT_UNKNOWN); + if (!module_get_debug(&pair)) return FALSE; return FALSE; + if ((sym = symt_find_nearest(pair.effective, StackFrame->InstructionOffset)) == NULL) return FALSE; + if (sym->symt.tag != SymTagFunction) return FALSE; + pcs->localscope_pc = StackFrame->InstructionOffset; + pcs->localscope_symt = &sym->symt; + if (pcs->ctx_frame.ReturnOffset == StackFrame->ReturnOffset && pcs->ctx_frame.FrameOffset == StackFrame->FrameOffset && pcs->ctx_frame.StackOffset == StackFrame->StackOffset) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 6217701a457..7ab7d1b7fc3 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -438,6 +438,8 @@ struct process ULONG_PTR dbg_hdr_addr;
IMAGEHLP_STACK_FRAME ctx_frame; + DWORD64 localscope_pc; + struct symt* localscope_symt;
unsigned buffer_size; void* buffer; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index e1c77569622..c503be4dcc1 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -3723,7 +3723,7 @@ static void dwarf2_location_compute(struct process* pcs, else { /* instruction pointer relative to compiland's start */ - ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address; + ip = pcs->localscope_pc - ((struct symt_compiland*)func->container)->address;
if ((err = loc_compute_frame(pcs, modfmt, func, ip, head, &frame)) == 0) { diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index f0fd2a55016..8168e727c52 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -1048,7 +1048,15 @@ BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll) if (!pcs) return FALSE; module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); if (!module) return FALSE; - return module_remove(pcs, module); + if (!module_remove(pcs, module)) return FALSE; + /* remove local scope if defined inside this module */ + if (pcs->localscope_pc >= module->module.BaseOfImage && + pcs->localscope_pc < module->module.BaseOfImage + module->module.ImageSize) + { + pcs->localscope_pc = 0; + pcs->localscope_symt = NULL; + } + return TRUE; }
/****************************************************************** diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 82c69b2e848..0f53bcd023c 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1028,7 +1028,7 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair, struct symt_function* func, const struct vector* v) { struct symt* lsym = NULL; - DWORD_PTR pc = pair->pcs->ctx_frame.InstructionOffset; + DWORD_PTR pc = pair->pcs->localscope_pc; unsigned int i; WCHAR* nameW; BOOL ret; @@ -1074,21 +1074,19 @@ static BOOL symt_enum_locals(struct process* pcs, const WCHAR* mask, const struct sym_enum* se) { struct module_pair pair; - struct symt_ht* sym; - DWORD_PTR pc = pcs->ctx_frame.InstructionOffset;
se->sym_info->SizeOfStruct = sizeof(*se->sym_info); se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
pair.pcs = pcs; - pair.requested = module_find_by_addr(pair.pcs, pc, DMT_UNKNOWN); + pair.requested = module_find_by_addr(pair.pcs, pcs->localscope_pc, DMT_UNKNOWN); if (!module_get_debug(&pair)) return FALSE; - if ((sym = symt_find_nearest(pair.effective, pc)) == NULL) return FALSE;
- if (sym->symt.tag == SymTagFunction) + if (symt_check_tag(pcs->localscope_symt, SymTagFunction) || + symt_check_tag(pcs->localscope_symt, SymTagInlineSite)) { - return symt_enum_locals_helper(&pair, mask ? mask : L"*", se, (struct symt_function*)sym, - &((struct symt_function*)sym)->vchildren); + struct symt_function* func = (struct symt_function*)pcs->localscope_symt; + return symt_enum_locals_helper(&pair, mask ? mask : L"*", se, func, &func->vchildren); } return FALSE; }
using the new local_scope framework
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index 64ceb447ee9..81a43327708 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -644,11 +644,18 @@ BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, */ BOOL WINAPI SymSetScopeFromAddr(HANDLE hProcess, ULONG64 addr) { - struct process* pcs; + struct module_pair pair; + struct symt_ht* sym;
- FIXME("(%p %#I64x): stub\n", hProcess, addr); + TRACE("(%p %#I64x)\n", hProcess, addr); + + if (!module_init_pair(&pair, hProcess, addr)) return FALSE; + if ((sym = symt_find_nearest(pair.effective, addr)) == NULL) return FALSE; + if (sym->symt.tag != SymTagFunction) return FALSE; + + pair.pcs->localscope_pc = addr; + pair.pcs->localscope_symt = &sym->symt;
- if (!(pcs = process_find_by_handle(hProcess))) return FALSE; return TRUE; }
@@ -657,11 +664,18 @@ BOOL WINAPI SymSetScopeFromAddr(HANDLE hProcess, ULONG64 addr) */ BOOL WINAPI SymSetScopeFromIndex(HANDLE hProcess, ULONG64 addr, DWORD index) { - struct process* pcs; + struct module_pair pair; + struct symt* sym;
- FIXME("(%p %#I64x %u): stub\n", hProcess, addr, index); + TRACE("(%p %#I64x %u)\n", hProcess, addr, index); + + if (!module_init_pair(&pair, hProcess, addr)) return FALSE; + sym = symt_index2ptr(pair.effective, index); + if (!symt_check_tag(sym, SymTagFunction)) return FALSE; + + pair.pcs->localscope_pc = ((struct symt_function*)sym)->address; /* FIXME of FuncDebugStart when it exists? */ + pair.pcs->localscope_symt = sym;
- if (!(pcs = process_find_by_handle(hProcess))) return FALSE; return TRUE; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index 81a43327708..eb0977dff36 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -607,34 +607,27 @@ BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context) { struct process* pcs; - struct module_pair pair; - struct symt_ht* sym; + BOOL same;
- pair.pcs = pcs = process_find_by_handle(hProcess); - if (!pcs) return FALSE; + if (!(pcs = process_find_by_handle(hProcess))) return FALSE; + same = pcs->ctx_frame.ReturnOffset == StackFrame->ReturnOffset && + pcs->ctx_frame.FrameOffset == StackFrame->FrameOffset && + pcs->ctx_frame.StackOffset == StackFrame->StackOffset;
- pair.requested = module_find_by_addr(pair.pcs, StackFrame->InstructionOffset, DMT_UNKNOWN); - if (!module_get_debug(&pair)) return FALSE; + if (!SymSetScopeFromAddr(hProcess, StackFrame->InstructionOffset)) return FALSE; - if ((sym = symt_find_nearest(pair.effective, StackFrame->InstructionOffset)) == NULL) return FALSE; - if (sym->symt.tag != SymTagFunction) return FALSE; - pcs->localscope_pc = StackFrame->InstructionOffset; - pcs->localscope_symt = &sym->symt;
- if (pcs->ctx_frame.ReturnOffset == StackFrame->ReturnOffset && - pcs->ctx_frame.FrameOffset == StackFrame->FrameOffset && - pcs->ctx_frame.StackOffset == StackFrame->StackOffset) + pcs->ctx_frame = *StackFrame; + if (same) { TRACE("Setting same frame {rtn=%I64x frm=%I64x stk=%I64x}\n", pcs->ctx_frame.ReturnOffset, pcs->ctx_frame.FrameOffset, pcs->ctx_frame.StackOffset); - pcs->ctx_frame.InstructionOffset = StackFrame->InstructionOffset; SetLastError(ERROR_SUCCESS); return FALSE; }
- pcs->ctx_frame = *StackFrame; /* Context is not (no longer?) used */ return TRUE; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index eb0977dff36..0b1e20e93c0 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -677,12 +677,17 @@ BOOL WINAPI SymSetScopeFromIndex(HANDLE hProcess, ULONG64 addr, DWORD index) */ BOOL WINAPI SymSetScopeFromInlineContext(HANDLE hProcess, ULONG64 addr, DWORD inlinectx) { - struct process* pcs; - - FIXME("(%p %#I64x %u): stub\n", hProcess, addr, inlinectx); + TRACE("(%p %I64x %x)\n", hProcess, addr, inlinectx);
- if (!(pcs = process_find_by_handle(hProcess))) return FALSE; - return TRUE; + switch (IFC_MODE(inlinectx)) + { + case IFC_MODE_IGNORE: + case IFC_MODE_REGULAR: return SymSetScopeFromAddr(hProcess, addr); + case IFC_MODE_INLINE: + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } }
/******************************************************************
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 13 ++++++++++++- programs/winedbg/stack.c | 16 ++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 6ed0f8bfe2f..7af9e0d75e4 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -179,7 +179,7 @@ struct dbg_thread * - only valid when in_exception is TRUE */ EXCEPTION_RECORD excpt_record; /* only valid when in_exception is TRUE */ - struct + struct dbg_frame { ADDRESS64 addr_pc; ADDRESS64 addr_frame; @@ -390,6 +390,17 @@ extern BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf); extern BOOL stack_get_register_frame(const struct dbg_internal_var* div, DWORD_PTR** pval); extern unsigned stack_fetch_frames(const dbg_ctx_t *ctx); extern BOOL stack_get_current_symbol(SYMBOL_INFO* sym); +static inline struct dbg_frame* + stack_get_thread_frame(struct dbg_thread* thd, unsigned nf) +{ + if (!thd->frames || nf >= thd->num_frames) return NULL; + return &thd->frames[nf]; +} +static inline struct dbg_frame* + stack_get_curr_frame(void) +{ + return stack_get_thread_frame(dbg_curr_thread, dbg_curr_thread->curr_frame); +}
/* symbol.c */ extern enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* addr, BOOL bp_disp); diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index 396caf11edd..9c22587a864 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -111,10 +111,10 @@ BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf)
BOOL stack_get_register_frame(const struct dbg_internal_var* div, DWORD_PTR** pval) { - if (dbg_curr_thread->frames == NULL) return FALSE; - if (dbg_curr_thread->frames[dbg_curr_thread->curr_frame].is_ctx_valid) - *pval = (DWORD_PTR*)((char*)&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].context + - (DWORD_PTR)div->pval); + struct dbg_frame* currfrm = stack_get_curr_frame(); + if (currfrm == NULL) return FALSE; + if (currfrm->is_ctx_valid) + *pval = (DWORD_PTR*)((char*)&currfrm->context + (DWORD_PTR)div->pval); else { enum be_cpu_addr kind; @@ -125,13 +125,13 @@ BOOL stack_get_register_frame(const struct dbg_internal_var* div, DWORD_PTR** pv switch (kind) { case be_cpu_addr_pc: - *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_pc; + *pval = &currfrm->linear_pc; break; case be_cpu_addr_stack: - *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_stack; + *pval = &currfrm->linear_stack; break; case be_cpu_addr_frame: - *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_frame; + *pval = &currfrm->linear_frame; break; } } @@ -143,7 +143,7 @@ BOOL stack_set_frame(int newframe) ADDRESS64 addr; if (!stack_set_frame_internal(newframe)) return FALSE; addr.Mode = AddrModeFlat; - addr.Offset = (DWORD_PTR)memory_to_linear_addr(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_pc); + addr.Offset = (DWORD_PTR)memory_to_linear_addr(&stack_get_curr_frame()->addr_pc); source_list_from_addr(&addr, 0); return TRUE; }
this allows to simplify a bit the frame internal storage (no longer using IMAGEHLP_STACK_FRAME structure)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 1 programs/winedbg/stack.c | 88 ++++++++++++++++++------------------------- programs/winedbg/symbol.c | 23 ++++++----- 3 files changed, 48 insertions(+), 64 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 7af9e0d75e4..498a1a0516d 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -386,7 +386,6 @@ extern void source_free_files(struct dbg_process* p); extern void stack_info(int len); extern void stack_backtrace(DWORD threadID); extern BOOL stack_set_frame(int newframe); -extern BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf); extern BOOL stack_get_register_frame(const struct dbg_internal_var* div, DWORD_PTR** pval); extern unsigned stack_fetch_frames(const dbg_ctx_t *ctx); extern BOOL stack_get_current_symbol(SYMBOL_INFO* sym); diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index 9c22587a864..317eb5626dd 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -64,6 +64,26 @@ void stack_info(int len) } }
+static BOOL stack_set_local_scope(void) +{ + struct dbg_frame* frm = stack_get_thread_frame(dbg_curr_thread, dbg_curr_thread->curr_frame); + + if (!frm) return FALSE; + /* if we're not the first frame, linear_pc is the return address + * after the call instruction (at least on most processors I know of). + * However, there are cases where this address is outside of the + * current function or inline site. + * This happens when the called function is marked <NO RETURN>, in which + * case the compiler can omit the epilog (gcc 4 does it). + * This happens also for inline sites, where the epilog (of the inline + * site) isn't present. + * Therefore, we decrement linear_pc in order to ensure that + * the considered address is really inside the current function or inline site. + */ + return SymSetScopeFromAddr(dbg_curr_process->handle, + (dbg_curr_thread->curr_frame) ? frm->linear_pc - 1 : frm->linear_pc); +} + static BOOL stack_set_frame_internal(int newframe) { if (newframe >= dbg_curr_thread->num_frames) @@ -73,42 +93,12 @@ static BOOL stack_set_frame_internal(int newframe)
if (dbg_curr_thread->curr_frame != newframe) { - IMAGEHLP_STACK_FRAME ihsf; - dbg_curr_thread->curr_frame = newframe; - stack_get_current_frame(&ihsf); - SymSetContext(dbg_curr_process->handle, &ihsf, NULL); + stack_set_local_scope(); } return TRUE; }
-static BOOL stack_get_frame(int nf, IMAGEHLP_STACK_FRAME* ihsf) -{ - memset(ihsf, 0, sizeof(*ihsf)); - ihsf->InstructionOffset = dbg_curr_thread->frames[nf].linear_pc; - /* if we're not the first frame, InstructionOffset is the return address - * after the call instruction (at least on most processors I know of). - * However, there are cases where this address is outside of the current function. - * This happens when the called function is marked <NO RETURN>, in which - * case the compiler can omit the epilog (gcc 4 does it) - * Therefore, we decrement InstructionOffset in order to ensure that - * the considered address is really inside the current function. - */ - if (nf) ihsf->InstructionOffset--; - ihsf->FrameOffset = dbg_curr_thread->frames[nf].linear_frame; - ihsf->StackOffset = dbg_curr_thread->frames[nf].linear_stack; - return TRUE; -} - -BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf) -{ - /* - * If we don't have a valid backtrace, then just return. - */ - if (dbg_curr_thread->frames == NULL) return FALSE; - return stack_get_frame(dbg_curr_thread->curr_frame, ihsf); -} - BOOL stack_get_register_frame(const struct dbg_internal_var* div, DWORD_PTR** pval) { struct dbg_frame* currfrm = stack_get_curr_frame(); @@ -155,12 +145,11 @@ BOOL stack_set_frame(int newframe) */ BOOL stack_get_current_symbol(SYMBOL_INFO* symbol) { - IMAGEHLP_STACK_FRAME ihsf; DWORD64 disp; + struct dbg_frame* frm = stack_get_curr_frame();
- if (!stack_get_current_frame(&ihsf)) return FALSE; - return SymFromAddr(dbg_curr_process->handle, ihsf.InstructionOffset, - &disp, symbol); + if (frm == NULL) return FALSE; + return SymFromAddr(dbg_curr_process->handle, frm->linear_pc, &disp, symbol); }
static BOOL CALLBACK stack_read_mem(HANDLE hProc, DWORD64 addr, @@ -260,27 +249,26 @@ static BOOL WINAPI sym_enum_cb(PSYMBOL_INFO sym_info, ULONG size, PVOID user) return TRUE; }
-static void stack_print_addr_and_args(int nf) +static void stack_print_addr_and_args(void) { char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; - IMAGEHLP_STACK_FRAME ihsf; IMAGEHLP_LINE64 il; IMAGEHLP_MODULE im; DWORD64 disp64; + struct dbg_frame* frm = stack_get_curr_frame();
- print_bare_address(&dbg_curr_thread->frames[nf].addr_pc); - - stack_get_frame(nf, &ihsf); + if (!frm) return; + print_bare_address(&frm->addr_pc);
/* grab module where symbol is. If we don't have a module, we cannot print more */ im.SizeOfStruct = sizeof(im); - if (!SymGetModuleInfo(dbg_curr_process->handle, ihsf.InstructionOffset, &im)) + if (!SymGetModuleInfo(dbg_curr_process->handle, frm->linear_pc, &im)) return;
si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; - if (SymFromAddr(dbg_curr_process->handle, ihsf.InstructionOffset, &disp64, si)) + if (SymFromAddr(dbg_curr_process->handle, frm->linear_pc, &disp64, si)) { struct sym_enum se; DWORD disp; @@ -288,21 +276,19 @@ static void stack_print_addr_and_args(int nf) dbg_printf(" %s", si->Name); if (disp64) dbg_printf("+0x%I64x", disp64);
- SymSetContext(dbg_curr_process->handle, &ihsf, NULL); + stack_set_local_scope(); se.first = TRUE; - se.frame = ihsf.FrameOffset; + se.frame = frm->linear_frame; dbg_printf("("); SymEnumSymbols(dbg_curr_process->handle, 0, NULL, sym_enum_cb, &se); dbg_printf(")");
il.SizeOfStruct = sizeof(il); - if (SymGetLineFromAddr64(dbg_curr_process->handle, - ihsf.InstructionOffset, &disp, &il)) + if (SymGetLineFromAddr64(dbg_curr_process->handle, frm->linear_pc, &disp, &il)) dbg_printf(" [%s:%u]", il.FileName, il.LineNumber); dbg_printf(" in %s", im.ModuleName); } - else dbg_printf(" in %s (+0x%I64x)", - im.ModuleName, ihsf.InstructionOffset - im.BaseOfImage); + else dbg_printf(" in %s (+0x%Ix)", im.ModuleName, frm->linear_pc - im.BaseOfImage); }
/****************************************************************** @@ -313,7 +299,6 @@ static void stack_print_addr_and_args(int nf) static void backtrace(void) { unsigned cf = dbg_curr_thread->curr_frame; - IMAGEHLP_STACK_FRAME ihsf;
dbg_printf("Backtrace:\n"); for (dbg_curr_thread->curr_frame = 0; @@ -323,7 +308,7 @@ static void backtrace(void) dbg_printf("%s%d ", (cf == dbg_curr_thread->curr_frame ? "=>" : " "), dbg_curr_thread->curr_frame); - stack_print_addr_and_args(dbg_curr_thread->curr_frame); + stack_print_addr_and_args(); dbg_printf(" ("); print_bare_address(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_frame); dbg_printf(")\n"); @@ -331,8 +316,7 @@ static void backtrace(void) /* reset context to current stack frame */ dbg_curr_thread->curr_frame = cf; if (!dbg_curr_thread->frames) return; - stack_get_frame(dbg_curr_thread->curr_frame, &ihsf); - SymSetContext(dbg_curr_process->handle, &ihsf, NULL); + stack_set_local_scope(); }
/****************************************************************** diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index 7067b886f44..67be370cc5b 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -366,7 +366,7 @@ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, int i; char buffer[512]; BOOL opt; - IMAGEHLP_STACK_FRAME ihsf; + struct dbg_frame* frm;
if (strlen(name) + 4 > sizeof(buffer)) { @@ -421,9 +421,9 @@ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
/* now grab local symbols */ - if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV) + if ((frm = stack_get_curr_frame()) && sgv.num < NUMDBGV) { - sgv.frame_offset = ihsf.FrameOffset; + sgv.frame_offset = frm->linear_frame; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); }
@@ -491,16 +491,16 @@ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, BOOL symbol_is_local(const char* name) { struct sgv_data sgv; - IMAGEHLP_STACK_FRAME ihsf; + struct dbg_frame* frm;
sgv.num = 0; sgv.num_thunks = 0; sgv.name = name; sgv.do_thunks = FALSE;
- if (stack_get_current_frame(&ihsf)) + if ((frm = stack_get_curr_frame())) { - sgv.frame_offset = ihsf.FrameOffset; + sgv.frame_offset = frm->linear_frame; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } return sgv.num > 0; @@ -748,15 +748,16 @@ static BOOL CALLBACK info_locals_cb(PSYMBOL_INFO sym, ULONG size, PVOID ctx)
BOOL symbol_info_locals(void) { - IMAGEHLP_STACK_FRAME ihsf; ADDRESS64 addr; + struct dbg_frame* frm; + + if (!(frm = stack_get_curr_frame())) return FALSE;
- stack_get_current_frame(&ihsf); addr.Mode = AddrModeFlat; - addr.Offset = ihsf.InstructionOffset; + addr.Offset = frm->linear_pc; print_address(&addr, FALSE); - dbg_printf(": (%0*lx)\n", ADDRWIDTH, (DWORD_PTR)ihsf.FrameOffset); - SymEnumSymbols(dbg_curr_process->handle, 0, NULL, info_locals_cb, (void*)(DWORD_PTR)ihsf.FrameOffset); + dbg_printf(": (%0*lx)\n", ADDRWIDTH, (DWORD_PTR)frm->linear_frame); + SymEnumSymbols(dbg_curr_process->handle, 0, NULL, info_locals_cb, (void*)frm->linear_frame);
return TRUE;
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 1 + programs/winedbg/stack.c | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 498a1a0516d..28126c28930 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -188,6 +188,7 @@ struct dbg_thread DWORD_PTR linear_frame; DWORD_PTR linear_stack; dbg_ctx_t context; /* context we got out of stackwalk for this frame */ + DWORD inline_ctx; BOOL is_ctx_valid; /* is the context above valid */ }* frames; int num_frames; diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index 317eb5626dd..4d2389ee345 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -80,8 +80,9 @@ static BOOL stack_set_local_scope(void) * Therefore, we decrement linear_pc in order to ensure that * the considered address is really inside the current function or inline site. */ - return SymSetScopeFromAddr(dbg_curr_process->handle, - (dbg_curr_thread->curr_frame) ? frm->linear_pc - 1 : frm->linear_pc); + return SymSetScopeFromInlineContext(dbg_curr_process->handle, + (dbg_curr_thread->curr_frame) ? frm->linear_pc - 1 : frm->linear_pc, + frm->inline_ctx); }
static BOOL stack_set_frame_internal(int newframe) @@ -149,7 +150,7 @@ BOOL stack_get_current_symbol(SYMBOL_INFO* symbol) struct dbg_frame* frm = stack_get_curr_frame();
if (frm == NULL) return FALSE; - return SymFromAddr(dbg_curr_process->handle, frm->linear_pc, &disp, symbol); + return SymFromInlineContext(dbg_curr_process->handle, frm->linear_pc, frm->inline_ctx, &disp, symbol); }
static BOOL CALLBACK stack_read_mem(HANDLE hProc, DWORD64 addr, @@ -173,21 +174,23 @@ static BOOL CALLBACK stack_read_mem(HANDLE hProc, DWORD64 addr, */ unsigned stack_fetch_frames(const dbg_ctx_t* _ctx) { - STACKFRAME64 sf; - unsigned nf = 0; + STACKFRAME_EX sf; + unsigned nf = 0; /* as native stackwalk can modify the context passed to it, simply copy * it to avoid any damage */ - dbg_ctx_t ctx = *_ctx; - BOOL ret; + dbg_ctx_t ctx = *_ctx; + BOOL ret;
HeapFree(GetProcessHeap(), 0, dbg_curr_thread->frames); dbg_curr_thread->frames = NULL;
memset(&sf, 0, sizeof(sf)); + sf.StackFrameSize = sizeof(sf); dbg_curr_process->be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_frame, &sf.AddrFrame); dbg_curr_process->be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_pc, &sf.AddrPC); dbg_curr_process->be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_stack, &sf.AddrStack); + sf.InlineFrameContext = INLINE_FRAME_CONTEXT_INIT;
/* don't confuse StackWalk by passing in inconsistent addresses */ if ((sf.AddrPC.Mode == AddrModeFlat) && (sf.AddrFrame.Mode != AddrModeFlat)) @@ -196,9 +199,9 @@ unsigned stack_fetch_frames(const dbg_ctx_t* _ctx) sf.AddrFrame.Mode = AddrModeFlat; }
- while ((ret = StackWalk64(dbg_curr_process->be_cpu->machine, dbg_curr_process->handle, + while ((ret = StackWalkEx(dbg_curr_process->be_cpu->machine, dbg_curr_process->handle, dbg_curr_thread->handle, &sf, &ctx, stack_read_mem, - SymFunctionTableAccess64, SymGetModuleBase64, NULL)) || + SymFunctionTableAccess64, SymGetModuleBase64, NULL, SYM_STKWALK_DEFAULT)) || nf == 0) /* we always register first frame information */ { dbg_curr_thread->frames = dbg_heap_realloc(dbg_curr_thread->frames, @@ -211,6 +214,7 @@ unsigned stack_fetch_frames(const dbg_ctx_t* _ctx) dbg_curr_thread->frames[nf].addr_stack = sf.AddrStack; dbg_curr_thread->frames[nf].linear_stack = (DWORD_PTR)memory_to_linear_addr(&sf.AddrStack); dbg_curr_thread->frames[nf].context = ctx; + dbg_curr_thread->frames[nf].inline_ctx = sf.InlineFrameContext; /* FIXME: can this heuristic be improved: we declare first context always valid, and next ones * if it has been modified by the call to StackWalk... */ @@ -268,7 +272,7 @@ static void stack_print_addr_and_args(void)
si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; - if (SymFromAddr(dbg_curr_process->handle, frm->linear_pc, &disp64, si)) + if (SymFromInlineContext(dbg_curr_process->handle, frm->linear_pc, frm->inline_ctx, &disp64, si)) { struct sym_enum se; DWORD disp; @@ -284,7 +288,8 @@ static void stack_print_addr_and_args(void) dbg_printf(")");
il.SizeOfStruct = sizeof(il); - if (SymGetLineFromAddr64(dbg_curr_process->handle, frm->linear_pc, &disp, &il)) + if (SymGetLineFromInlineContext(dbg_curr_process->handle, frm->linear_pc, frm->inline_ctx, + 0, &disp, &il)) dbg_printf(" [%s:%u]", il.FileName, il.LineNumber); dbg_printf(" in %s", im.ModuleName); }