[PATCH 07/10] dbghelp/dwarf: Added support for OP_call_frame_cfa

Eric Pouech eric.pouech at gmail.com
Fri Sep 24 10:32:52 CDT 2021


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

---
 dlls/dbghelp/dwarf.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 4edba930698..e48993e6293 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -234,6 +234,7 @@ struct dwarf2_module_info_s
 
 #define loc_dwarf2_location_list        (loc_user + 0)
 #define loc_dwarf2_block                (loc_user + 1)
+#define loc_dwarf2_frame_cfa            (loc_user + 2)
 
 /* forward declarations */
 static struct symt* dwarf2_parse_enumeration_type(dwarf2_debug_info_t* entry);
@@ -1085,8 +1086,13 @@ static BOOL dwarf2_compute_location_attr(dwarf2_parse_context_t* ctx,
     }
 
     /* assume we have a block form */
-
-    if (xloc.u.block.size)
+    if (dw == DW_AT_frame_base && xloc.u.block.size == 1 && *xloc.u.block.ptr == DW_OP_call_frame_cfa)
+    {
+        loc->kind = loc_dwarf2_frame_cfa;
+        loc->reg = Wine_DW_no_register;
+        loc->offset = 0;
+    }
+    else if (xloc.u.block.size)
     {
         dwarf2_traverse_context_t       lctx;
         enum location_error             err;
@@ -2818,6 +2824,8 @@ static const dwarf2_cuhead_t* get_cuhead_from_func(const struct symt_function* f
     return NULL;
 }
 
+static BOOL compute_call_frame_cfa(struct process* pcs, ULONG_PTR ip, struct location* frame);
+
 static enum location_error loc_compute_frame(struct process* pcs,
                                              const struct module_format* modfmt,
                                              const struct symt_function* func,
@@ -2858,6 +2866,9 @@ static enum location_error loc_compute_frame(struct process* pcs,
                     return loc_err_too_complex;
                 }
                 break;
+            case loc_dwarf2_frame_cfa:
+                if (!compute_call_frame_cfa(pcs, ip, frame)) return loc_err_internal;
+                break;
             default:
                 WARN("Unsupported frame kind %d\n", pframe->kind);
                 return loc_err_internal;
@@ -3647,6 +3658,48 @@ BOOL dwarf2_virtual_unwind(struct cpu_stack_walk *csw, ULONG_PTR ip,
     return TRUE;
 }
 
+static BOOL compute_call_frame_cfa(struct process* pcs, ULONG_PTR ip, struct location* frame)
+{
+    struct module_pair pair;
+    struct frame_info info;
+
+    pair.pcs = pcs;
+    if (!(pair.requested = module_find_by_addr(pair.pcs, ip, DMT_UNKNOWN)) ||
+        !module_get_debug(&pair))
+        return FALSE;
+    if (!dwarf2_fetch_frame_info(pair.effective, dbghelp_current_cpu, ip, &info)) return FALSE;
+
+    /* beginning of function, or no available dwarf information ? */
+    if (ip == info.ip || info.state.rules[info.retaddr_reg] == RULE_UNSET)
+    {
+        /* fake the default unwinder */
+        frame->kind = loc_regrel;
+        frame->reg = dbghelp_current_cpu->frame_regno;
+        frame->offset = dbghelp_current_cpu->word_size; /* FIXME stack direction */
+    }
+    else
+    {
+        /* we expect to translate the call_frame_cfa into a regrel location...
+         * that should cover most of the cases
+         */
+        switch (info.state.cfa_rule)
+        {
+        case RULE_EXPRESSION:
+            FIXME("Too complex expression for frame_CFA resolution (RULE_EXPRESSION)\n");
+            break;
+        case RULE_VAL_EXPRESSION:
+            FIXME("Too complex expression for frame_CFA resolution (RULE_VAL_EXPRESSION)\n");
+            break;
+        default:
+            frame->kind = loc_regrel;
+            frame->reg = dbghelp_current_cpu->map_dwarf_register(info.state.cfa_reg, pair.effective, TRUE);
+            frame->offset = info.state.cfa_offset;
+            break;
+        }
+    }
+    return TRUE;
+}
+
 static void dwarf2_location_compute(struct process* pcs,
                                     const struct module_format* modfmt,
                                     const struct symt_function* func,




More information about the wine-devel mailing list