[PATCH 5/7] dbghelp: implement StackWalkEx for inlined frames

Eric Pouech eric.pouech at gmail.com
Thu Oct 28 01:58:17 CDT 2021


Signed-off-by: Eric Pouech <eric.pouech at gmail.com>

---
 dlls/dbghelp/dbghelp_private.h |    3 +++
 dlls/dbghelp/stack.c           |   38 ++++++++++++++++++++++++++-----------
 dlls/dbghelp/symbol.c          |   41 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index c5d637e2f8c..074685b7173 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(&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)
 {
@@ -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
  *




More information about the wine-devel mailing list