Eric Pouech : dbghelp/dwarf: Store each subrange for an inlined function.

Alexandre Julliard julliard at winehq.org
Thu Oct 28 16:07:45 CDT 2021


Module: wine
Branch: master
Commit: fb34c82ef80c4657ea262e4e2f121208db741da0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fb34c82ef80c4657ea262e4e2f121208db741da0

Author: Eric Pouech <eric.pouech at gmail.com>
Date:   Thu Oct 28 08:58:04 2021 +0200

dbghelp/dwarf: Store each subrange for an inlined function.

Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dbghelp/dbghelp_private.h | 15 ++++++++++
 dlls/dbghelp/dwarf.c           | 63 ++++++++++++++++++++++++++++++++++++++++++
 dlls/dbghelp/symbol.c          | 36 ++++++++++++++++++++++++
 3 files changed, 114 insertions(+)

diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index 34f51c28608..2a277a14751 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -268,6 +268,18 @@ struct addr_range
     DWORD64                     high;           /* absolute address of first byte after the range */
 };
 
+/* tests whether ar2 is inside ar1 */
+static inline BOOL addr_range_inside(const struct addr_range* ar1, const struct addr_range* ar2)
+{
+    return ar1->low <= ar2->low && ar2->high <= ar1->high;
+}
+
+/* tests whether ar1 and ar2 are disjoint */
+static inline BOOL addr_range_disjoint(const struct addr_range* ar1, const struct addr_range* ar2)
+{
+    return ar1->high <= ar2->low || ar2->high <= ar1->low;
+}
+
 /* a symt_inlinesite* can be casted to a symt_function* to access all function bits */
 struct symt_inlinesite
 {
@@ -841,6 +853,9 @@ extern struct symt_hierarchy_point*
                                             enum SymTagEnum point, 
                                             const struct location* loc,
                                             const char* name) DECLSPEC_HIDDEN;
+extern BOOL         symt_add_inlinesite_range(struct module* module,
+                                              struct symt_inlinesite* inlined,
+                                              ULONG_PTR low, ULONG_PTR high) DECLSPEC_HIDDEN;
 extern struct symt_thunk*
                     symt_new_thunk(struct module* module, 
                                    struct symt_compiland* parent,
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index a01b72c4fc8..1ea8d2df773 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -1272,6 +1272,66 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in
     }
 }
 
+static BOOL dwarf2_feed_inlined_ranges(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di,
+                                       struct symt_inlinesite* inlined)
+{
+    struct attribute            range;
+
+    if (dwarf2_find_attribute(di, DW_AT_ranges, &range))
+    {
+        dwarf2_traverse_context_t   traverse;
+
+        traverse.data = ctx->module_ctx->sections[section_ranges].address + range.u.uvalue;
+        traverse.end_data = ctx->module_ctx->sections[section_ranges].address +
+            ctx->module_ctx->sections[section_ranges].size;
+
+        while (traverse.data + 2 * ctx->head.word_size < traverse.end_data)
+        {
+            ULONG_PTR low = dwarf2_parse_addr_head(&traverse, &ctx->head);
+            ULONG_PTR high = dwarf2_parse_addr_head(&traverse, &ctx->head);
+            if (low == 0 && high == 0) break;
+            if (low == (ctx->head.word_size == 8 ? (~(DWORD64)0u) : (DWORD64)(~0u)))
+                FIXME("unsupported yet (base address selection)\n");
+            /* range values are relative to start of compilation unit */
+            symt_add_inlinesite_range(ctx->module_ctx->module, inlined,
+                                      ctx->compiland->address + low, ctx->compiland->address + high);
+        }
+
+        return TRUE;
+    }
+    else
+    {
+        struct attribute            low_pc;
+        struct attribute            high_pc;
+
+        if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc) ||
+            !dwarf2_find_attribute(di, DW_AT_high_pc, &high_pc))
+            return FALSE;
+        if (ctx->head.version >= 4)
+            switch (high_pc.form)
+            {
+            case DW_FORM_addr:
+                break;
+            case DW_FORM_data1:
+            case DW_FORM_data2:
+            case DW_FORM_data4:
+            case DW_FORM_data8:
+            case DW_FORM_sdata:
+            case DW_FORM_udata:
+                /* From dwarf4 on, when FORM's class is constant, high_pc is an offset from low_pc */
+                high_pc.u.uvalue += low_pc.u.uvalue;
+                break;
+            default:
+                FIXME("Unsupported class for high_pc\n");
+                break;
+            }
+        symt_add_inlinesite_range(ctx->module_ctx->module, inlined,
+                                  ctx->module_ctx->load_offset + low_pc.u.uvalue,
+                                  ctx->module_ctx->load_offset + high_pc.u.uvalue);
+        return TRUE;
+    }
+}
+
 /******************************************************************
  *		dwarf2_read_one_debug_info
  *
@@ -2038,6 +2098,9 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
     subpgm->current_func = (struct symt_function*)inlined;
     subpgm->current_block = NULL;
 
+    if (!dwarf2_feed_inlined_ranges(subpgm->ctx, di, inlined))
+        WARN("cannot read ranges\n");
+
     children = dwarf2_get_di_children(di);
     if (children) for (i = 0; i < vector_length(children); i++)
     {
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index aebe5fee098..9b7c5f3078e 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -576,6 +576,42 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module,
     return sym;
 }
 
+/* low and high are absolute addresses */
+BOOL symt_add_inlinesite_range(struct module* module,
+                               struct symt_inlinesite* inlined,
+                               ULONG_PTR low, ULONG_PTR high)
+{
+    struct addr_range* p;
+
+    p = vector_add(&inlined->vranges, &module->pool);
+    p->low = low;
+    p->high = high;
+    if (TRUE)
+    {
+        int i;
+
+        /* see dbghelp_private.h for the assumptions */
+        for (i = 0; i < inlined->vranges.num_elts - 1; i++)
+        {
+            if (!addr_range_disjoint((struct addr_range*)vector_at(&inlined->vranges, i), p))
+            {
+                FIXME("Added addr_range isn't disjoint from siblings\n");
+            }
+        }
+        for ( ; inlined->func.symt.tag != SymTagFunction; inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined))
+        {
+            for (i = 0; i < inlined->vranges.num_elts; i++)
+            {
+                struct addr_range* ar = (struct addr_range*)vector_at(&inlined->vranges, i);
+                if (!addr_range_disjoint(ar, p) && !addr_range_inside(ar, p))
+                    FIXME("Added addr_range not compatible with parent\n");
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 struct symt_thunk* symt_new_thunk(struct module* module, 
                                   struct symt_compiland* compiland, 
                                   const char* name, THUNK_ORDINAL ord,




More information about the wine-cvs mailing list