diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 2a277a14751..014e793b6a1 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -916,6 +916,8 @@ extern struct symt_pointer* extern struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, const char* name) DECLSPEC_HIDDEN; +extern struct symt_inlinesite* + symt_find_lowest_inlined(struct symt_function* func, DWORD64 addr) DECLSPEC_HIDDEN; extern struct symt* symt_get_upper_inlined(struct symt_inlinesite* inlined) DECLSPEC_HIDDEN; static inline struct symt_function* @@ -925,6 +927,7 @@ static inline struct symt_function* inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined); return &inlined->func; } +extern DWORD symt_get_inlinesite_depth(HANDLE hProcess, DWORD64 addr) DECLSPEC_HIDDEN; /* Inline context encoding (different from what native does): * bits 31:30: 3 ignore (includes INLINE_FRAME_CONTEXT_IGNORE=0xFFFFFFFF) diff --git a/dlls/dbghelp/stack.c b/dlls/dbghelp/stack.c index a93c454036c..2271612bdd1 100644 --- a/dlls/dbghelp/stack.c +++ b/dlls/dbghelp/stack.c @@ -274,6 +274,7 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread, { struct cpu_stack_walk csw; struct cpu* cpu; + DWORD64 addr; TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p, 0x%x)\n", MachineType, hProcess, hThread, frame, ctx, @@ -296,16 +297,6 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread, SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - if (frame->InlineFrameContext != INLINE_FRAME_CONTEXT_IGNORE) - { - static BOOL once; - if (!once) - { - FIXME("Inlined contexts are not supported yet\n"); - once = TRUE; - } - frame->InlineFrameContext = INLINE_FRAME_CONTEXT_IGNORE; - } csw.hProcess = hProcess; csw.hThread = hThread; @@ -317,7 +308,32 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread, csw.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64; csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64; - if (!cpu->stack_walk(&csw, (STACKFRAME64*)frame, ctx)) return FALSE; + addr = sw_xlat_addr(&csw, &frame->AddrPC); + + if (IFC_MODE(frame->InlineFrameContext) == IFC_MODE_INLINE) + { + DWORD depth = symt_get_inlinesite_depth(hProcess, addr); + if (IFC_DEPTH(frame->InlineFrameContext) + 1 < depth) /* move to next inlined function? */ + { + TRACE("found inline ctx: depth=%u current=%u++\n", + depth, frame->InlineFrameContext); + frame->InlineFrameContext++; /* just increase index, FIXME detect overflow */ + } + else + { + frame->InlineFrameContext = IFC_MODE_REGULAR; /* move to next top level function */ + } + } + else + { + if (!cpu->stack_walk(&csw, (STACKFRAME64*)frame, ctx)) return FALSE; + if (frame->InlineFrameContext != INLINE_FRAME_CONTEXT_IGNORE) + { + addr = sw_xlat_addr(&csw, &frame->AddrPC); + frame->InlineFrameContext = symt_get_inlinesite_depth(hProcess, addr) == 0 ? IFC_MODE_REGULAR : IFC_MODE_INLINE; + TRACE("setting IFC mode to %x\n", frame->InlineFrameContext); + } + } /* we don't handle KdHelp */ diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 9b7c5f3078e..5dd989b5489 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1213,6 +1213,26 @@ void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si) MultiByteToWideChar(CP_ACP, 0, si->Name, -1, siw->Name, siw->MaxNameLen); } +/* return the lowest inline site inside a function */ +struct symt_inlinesite* symt_find_lowest_inlined(struct symt_function* func, DWORD64 addr) +{ + struct symt_inlinesite* current; + int i; + + assert(func->symt.tag == SymTagFunction); + for (current = func->next_inlinesite; current; current = current->func.next_inlinesite) + { + for (i = 0; i < current->vranges.num_elts; ++i) + { + struct addr_range* ar = (struct addr_range*)vector_at(¤t->vranges, i); + /* first matching range gives the lowest inline site; see dbghelp_private.h for details */ + if (ar->low <= addr && addr < ar->high) + return current; + } + } + return NULL; +} + /* from an inline function, get either the enclosing inlined function, or the top function when no inlined */ struct symt* symt_get_upper_inlined(struct symt_inlinesite* inlined) { @@ -1230,6 +1250,27 @@ struct symt* symt_get_upper_inlined(struct symt_inlinesite* inlined) return symt; } +DWORD symt_get_inlinesite_depth(HANDLE hProcess, DWORD64 addr) +{ + struct module_pair pair; + DWORD depth = 0; + + if (module_init_pair(&pair, hProcess, addr)) + { + struct symt_ht* symt = symt_find_nearest(pair.effective, addr); + if (symt_check_tag(&symt->symt, SymTagFunction)) + { + struct symt_inlinesite* inlined = symt_find_lowest_inlined((struct symt_function*)symt, addr); + if (inlined) + { + for ( ; &inlined->func.symt != &symt->symt; inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined)) + ++depth; + } + } + } + return depth; +} + /****************************************************************** * sym_enum *