[PATCH 02/11] dbghelp: introduce a couple of helpers to manage inline contexts
Eric Pouech
eric.pouech at gmail.com
Wed Oct 20 11:35:56 CDT 2021
Signed-off-by: Eric Pouech <eric.pouech at 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
*
More information about the wine-devel
mailing list