[PATCH 02/15] dbghelp: introduce a couple of helpers to manage inline contexts

Eric Pouech eric.pouech at gmail.com
Fri Oct 22 02:15:04 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(&current->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