Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp_private.h | 31 ++++++++++++++++ dlls/dbghelp/symbol.c | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 761af2ef9e1..ed6b3a5bfa9 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -911,3 +911,34 @@ 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* + symt_get_function_from_inlined(struct symt_inlinesite* inlined) +{ + while (!symt_check_tag(&inlined->func.symt, SymTagFunction)) + inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined); + return &inlined->func; +} +extern struct symt_inlinesite* + symt_find_inlined_site(struct module* module, + DWORD64 addr, DWORD inline_ctx) DECLSPEC_HIDDEN; +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) + * 2 regular frame + * 1 frame with inlined function(s). + * 0 init (includes INLINE_FRAME_CONTEXT_INIT=0) + * 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 cb39fd5b422..b171b6c3c4f 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1179,6 +1179,83 @@ 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) +{ + struct symt* symt = &inlined->func.symt; + + do + { + assert(symt); + if (symt->tag == SymTagBlock) + symt = ((struct symt_block*)symt)->container; + else + symt = ((struct symt_function*)symt)->container; + } while (symt->tag == SymTagBlock); + assert(symt->tag == SymTagFunction || symt->tag == SymTagInlineSite); + return symt; +} + +/* lookup in module for an inline site (from addr and inline_ctx) */ +struct symt_inlinesite* symt_find_inlined_site(struct module* module, DWORD64 addr, DWORD inline_ctx) +{ + struct symt_ht* symt = symt_find_nearest(module, addr); + + if (symt_check_tag(&symt->symt, SymTagFunction)) + { + struct symt_function* func = (struct symt_function*)symt; + struct symt_inlinesite* curr = symt_find_lowest_inlined(func, addr); + DWORD depth = IFC_DEPTH(inline_ctx); + + if (curr) + for ( ; &curr->func != func; curr = (struct symt_inlinesite*)symt_get_upper_inlined(curr)) + if (depth-- == 0) return curr; + } + return NULL; +} + +DWORD symt_get_inlinesite_depth(HANDLE hProcess, DWORD64 addr) +{ + struct module_pair pair; + struct symt_ht* symt; + + if (!module_init_pair(&pair, hProcess, addr)) return FALSE; + + 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) + { + DWORD depth = 0; + for ( ; &inlined->func.symt != &symt->symt; inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined)) + ++depth; + return depth; + } + } + return 0; +} + /****************************************************************** * sym_enum *