dbghelp: Implement StackWalkEx for inlined frames.
Signed-off-by: Eric Pouech <eric.pouech@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fb34c82ef8
commit
82bac5d080
|
@ -916,6 +916,8 @@ extern struct symt_pointer*
|
||||||
extern struct symt_typedef*
|
extern struct symt_typedef*
|
||||||
symt_new_typedef(struct module* module, struct symt* ref,
|
symt_new_typedef(struct module* module, struct symt* ref,
|
||||||
const char* name) DECLSPEC_HIDDEN;
|
const char* name) DECLSPEC_HIDDEN;
|
||||||
|
extern struct symt_inlinesite*
|
||||||
|
symt_find_lowest_inlined(struct symt_function* func, DWORD64 addr) DECLSPEC_HIDDEN;
|
||||||
extern struct symt*
|
extern struct symt*
|
||||||
symt_get_upper_inlined(struct symt_inlinesite* inlined) DECLSPEC_HIDDEN;
|
symt_get_upper_inlined(struct symt_inlinesite* inlined) DECLSPEC_HIDDEN;
|
||||||
static inline struct symt_function*
|
static inline struct symt_function*
|
||||||
|
@ -925,6 +927,7 @@ static inline struct symt_function*
|
||||||
inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined);
|
inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined);
|
||||||
return &inlined->func;
|
return &inlined->func;
|
||||||
}
|
}
|
||||||
|
extern DWORD symt_get_inlinesite_depth(HANDLE hProcess, DWORD64 addr) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Inline context encoding (different from what native does):
|
/* Inline context encoding (different from what native does):
|
||||||
* bits 31:30: 3 ignore (includes INLINE_FRAME_CONTEXT_IGNORE=0xFFFFFFFF)
|
* bits 31:30: 3 ignore (includes INLINE_FRAME_CONTEXT_IGNORE=0xFFFFFFFF)
|
||||||
|
|
|
@ -274,6 +274,7 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
||||||
{
|
{
|
||||||
struct cpu_stack_walk csw;
|
struct cpu_stack_walk csw;
|
||||||
struct cpu* cpu;
|
struct cpu* cpu;
|
||||||
|
DWORD64 addr;
|
||||||
|
|
||||||
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p, 0x%x)\n",
|
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p, 0x%x)\n",
|
||||||
MachineType, hProcess, hThread, frame, ctx,
|
MachineType, hProcess, hThread, frame, ctx,
|
||||||
|
@ -296,16 +297,6 @@ BOOL WINAPI StackWalkEx(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
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.hProcess = hProcess;
|
||||||
csw.hThread = hThread;
|
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_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
|
||||||
csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
|
csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
|
||||||
|
|
||||||
|
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 (!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 */
|
/* we don't handle KdHelp */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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 */
|
/* 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)
|
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;
|
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
|
* sym_enum
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue