[PATCH 3/7] dbghelp/dwarf: generate proper inline function

Eric Pouech eric.pouech at gmail.com
Thu Oct 28 01:57:50 CDT 2021


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

---
 dlls/dbghelp/dbghelp_private.h |   16 +++++++
 dlls/dbghelp/dwarf.c           |   81 +++++++++++++++++++++++-------------
 dlls/dbghelp/symbol.c          |   90 ++++++++++++++++++++++++++++++++--------
 3 files changed, 141 insertions(+), 46 deletions(-)

diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index 7dfb7a7c6dd..34f51c28608 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -805,6 +805,13 @@ extern struct symt_function*
                                       const char* name,
                                       ULONG_PTR addr, ULONG_PTR size,
                                       struct symt* type) DECLSPEC_HIDDEN;
+extern struct symt_inlinesite*
+                    symt_new_inlinesite(struct module* module,
+                                        struct symt_function* func,
+                                        struct symt* parent,
+                                        const char* name,
+                                        ULONG_PTR addr,
+                                        struct symt* type) DECLSPEC_HIDDEN;
 extern void         symt_add_func_line(struct module* module,
                                        struct symt_function* func, 
                                        unsigned source_idx, int line_num, 
@@ -894,6 +901,15 @@ 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*
+                    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;
+}
 
 /* Inline context encoding (different from what native does):
  * bits 31:30: 3 ignore (includes INLINE_FRAME_CONTEXT_IGNORE=0xFFFFFFFF)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index ef86e6bffe0..a01b72c4fc8 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -1811,7 +1811,8 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_debug_info_t* di)
 typedef struct dwarf2_subprogram_s
 {
     dwarf2_parse_context_t*     ctx;
-    struct symt_function*       func;
+    struct symt_function*       top_func;
+    struct symt_function*       current_func; /* either symt_function* or symt_inlinesite* */
     struct symt_block*          current_block;
     BOOL                        non_computed_variable;
     struct location             frame;
@@ -1870,8 +1871,8 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
             /* either a pmt/variable relative to frame pointer or
              * pmt/variable in a register
              */
-            if (subpgm->func)
-                symt_add_func_local(subpgm->ctx->module_ctx->module, subpgm->func,
+            if (subpgm->current_func)
+                symt_add_func_local(subpgm->ctx->module_ctx->module, subpgm->current_func,
                                     is_pmt ? DataIsParam : DataIsLocal,
                                     &loc, subpgm->current_block, param_type, name.u.string);
             break;
@@ -1935,11 +1936,12 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
                   debugstr_a(name.u.string), value.form);
             V_VT(&v) = VT_EMPTY;
         }
-        if (subpgm->func)
+        if (subpgm->current_func)
         {
-            if (is_pmt) FIXME("Unsupported constant (parameter) %s in function '%s'\n", debugstr_a(name.u.string), subpgm->func->hash_elt.name);
+            if (is_pmt) WARN("Constant parameter %s reported as local variable in function '%s'\n",
+                             debugstr_a(name.u.string), subpgm->current_func->hash_elt.name);
             di->symt = &symt_add_func_constant(subpgm->ctx->module_ctx->module,
-                                               subpgm->func, subpgm->current_block,
+                                               subpgm->current_func, subpgm->current_block,
                                                param_type, name.u.string, &v)->symt;
         }
         else
@@ -1948,12 +1950,12 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
     }
     else
     {
-        if (subpgm->func)
+        if (subpgm->current_func)
         {
             /* local variable has been optimized away... report anyway */
             loc.kind = loc_error;
             loc.reg = loc_err_no_location;
-            symt_add_func_local(subpgm->ctx->module_ctx->module, subpgm->func,
+            symt_add_func_local(subpgm->ctx->module_ctx->module, subpgm->current_func,
                                 is_pmt ? DataIsParam : DataIsLocal,
                                 &loc, subpgm->current_block, param_type, name.u.string);
         }
@@ -1966,9 +1968,9 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
                 WARN("dropping global variable %s which has been optimized away\n", debugstr_a(name.u.string));
         }
     }
-    if (is_pmt && subpgm->func && symt_check_tag(subpgm->func->type, SymTagFunctionType))
+    if (is_pmt && subpgm->current_func && symt_check_tag(subpgm->current_func->type, SymTagFunctionType))
         symt_add_function_signature_parameter(subpgm->ctx->module_ctx->module,
-                                              (struct symt_function_signature*)subpgm->func->type,
+                                              (struct symt_function_signature*)subpgm->current_func->type,
                                               param_type);
 
     if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n");
@@ -1988,8 +1990,8 @@ static void dwarf2_parse_subprogram_label(dwarf2_subprogram_t* subpgm,
         name.u.string = NULL;
 
     loc.kind = loc_absolute;
-    loc.offset = subpgm->ctx->module_ctx->load_offset + low_pc.u.uvalue - subpgm->func->address;
-    symt_add_function_point(subpgm->ctx->module_ctx->module, subpgm->func, SymTagLabel,
+    loc.offset = subpgm->ctx->module_ctx->load_offset + low_pc.u.uvalue - subpgm->top_func->address;
+    symt_add_function_point(subpgm->ctx->module_ctx->module, subpgm->top_func, SymTagLabel,
                             &loc, name.u.string);
 }
 
@@ -2001,7 +2003,11 @@ static struct symt* dwarf2_parse_subroutine_type(dwarf2_debug_info_t* di);
 static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
                                             dwarf2_debug_info_t* di)
 {
+    struct attribute    name;
     ULONG_PTR           low_pc, high_pc;
+    struct symt*        ret_type;
+    struct symt_function_signature* sig_type;
+    struct symt_inlinesite* inlined;
     struct vector*      children;
     dwarf2_debug_info_t*child;
     unsigned int        i;
@@ -2013,10 +2019,24 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
         WARN("cannot read range\n");
         return;
     }
+    if (!dwarf2_find_attribute(di, DW_AT_name, &name))
+    {
+        FIXME("No name for function... dropping function\n");
+        return;
+    }
+    ret_type = dwarf2_lookup_type(di);
 
-    subpgm->current_block = symt_open_func_block(subpgm->ctx->module_ctx->module, subpgm->func, subpgm->current_block,
-                                                 subpgm->ctx->module_ctx->load_offset + low_pc - subpgm->func->address,
-                                                 high_pc - low_pc);
+    /* FIXME: assuming C source code */
+    sig_type = symt_new_function_signature(subpgm->ctx->module_ctx->module, ret_type, CV_CALL_FAR_C);
+
+    inlined = symt_new_inlinesite(subpgm->ctx->module_ctx->module,
+                                  subpgm->top_func,
+                                  subpgm->current_block ? &subpgm->current_block->symt : &subpgm->current_func->symt,
+                                  dwarf2_get_cpp_name(di, name.u.string),
+                                  subpgm->ctx->module_ctx->load_offset + low_pc,
+                                  &sig_type->symt);
+    subpgm->current_func = (struct symt_function*)inlined;
+    subpgm->current_block = NULL;
 
     children = dwarf2_get_di_children(di);
     if (children) for (i = 0; i < vector_length(children); i++)
@@ -2046,9 +2066,9 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
                   child->abbrev->tag, dwarf2_debug_di(di));
         }
     }
-    symt_close_func_block(subpgm->ctx->module_ctx->module, subpgm->func, subpgm->current_block, 0);
-    subpgm->current_block = symt_check_tag(subpgm->current_block->container, SymTagBlock) ?
-        (struct symt_block*)subpgm->current_block->container : NULL;
+    subpgm->current_block = symt_check_tag(subpgm->current_func->container, SymTagBlock) ?
+        (struct symt_block*)subpgm->current_func->container : NULL;
+    subpgm->current_func = (struct symt_function*)symt_get_upper_inlined((struct symt_inlinesite*)subpgm->current_func);
 }
 
 static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
@@ -2067,8 +2087,8 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
         return;
     }
 
-    subpgm->current_block = symt_open_func_block(subpgm->ctx->module_ctx->module, subpgm->func, subpgm->current_block,
-                                                 subpgm->ctx->module_ctx->load_offset + low_pc - subpgm->func->address,
+    subpgm->current_block = symt_open_func_block(subpgm->ctx->module_ctx->module, subpgm->current_func, subpgm->current_block,
+                                                 subpgm->ctx->module_ctx->load_offset + low_pc - subpgm->current_func->address,
                                                  high_pc - low_pc);
 
     children = dwarf2_get_di_children(di);
@@ -2128,7 +2148,7 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
         }
     }
 
-    symt_close_func_block(subpgm->ctx->module_ctx->module, subpgm->func, subpgm->current_block, 0);
+    symt_close_func_block(subpgm->ctx->module_ctx->module, subpgm->current_func, subpgm->current_block, 0);
     subpgm->current_block = symt_check_tag(subpgm->current_block->container, SymTagBlock) ?
         (struct symt_block*)subpgm->current_block->container : NULL;
 }
@@ -2187,11 +2207,12 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di)
 
     /* FIXME: assuming C source code */
     sig_type = symt_new_function_signature(di->unit_ctx->module_ctx->module, ret_type, CV_CALL_FAR_C);
-    subpgm.func = symt_new_function(di->unit_ctx->module_ctx->module, di->unit_ctx->compiland,
-                                    dwarf2_get_cpp_name(di, name.u.string),
-                                    di->unit_ctx->module_ctx->load_offset + low_pc, high_pc - low_pc,
-                                    &sig_type->symt);
-    di->symt = &subpgm.func->symt;
+    subpgm.top_func = symt_new_function(di->unit_ctx->module_ctx->module, di->unit_ctx->compiland,
+                                        dwarf2_get_cpp_name(di, name.u.string),
+                                        di->unit_ctx->module_ctx->load_offset + low_pc, high_pc - low_pc,
+                                        &sig_type->symt);
+    subpgm.current_func = subpgm.top_func;
+    di->symt = &subpgm.top_func->symt;
     subpgm.ctx = di->unit_ctx;
     if (!dwarf2_compute_location_attr(di->unit_ctx, di, DW_AT_frame_base,
                                       &subpgm.frame, NULL))
@@ -2258,7 +2279,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di)
 
     if (subpgm.non_computed_variable || subpgm.frame.kind >= loc_user)
     {
-        symt_add_function_point(di->unit_ctx->module_ctx->module, subpgm.func, SymTagCustom,
+        symt_add_function_point(di->unit_ctx->module_ctx->module, subpgm.top_func, SymTagCustom,
                                 &subpgm.frame, NULL);
     }
 
@@ -2395,7 +2416,7 @@ static void dwarf2_load_one_entry(dwarf2_debug_info_t* di)
             dwarf2_subprogram_t subpgm;
 
             subpgm.ctx = di->unit_ctx;
-            subpgm.func = NULL;
+            subpgm.top_func = subpgm.current_func = NULL;
             subpgm.current_block = NULL;
             subpgm.frame.kind = loc_absolute;
             subpgm.frame.offset = 0;
@@ -2827,7 +2848,9 @@ static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const dwar
 
 static const dwarf2_cuhead_t* get_cuhead_from_func(const struct symt_function* func)
 {
-    if (func && symt_check_tag(func->container, SymTagCompiland))
+    if (symt_check_tag(&func->symt, SymTagInlineSite))
+        func = symt_get_function_from_inlined((struct symt_inlinesite*)func);
+    if (symt_check_tag(&func->symt, SymTagFunction) && symt_check_tag(func->container, SymTagCompiland))
     {
         struct symt_compiland* c = (struct symt_compiland*)func->container;
         return (const dwarf2_cuhead_t*)c->user;
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index 95cacc057a7..aebe5fee098 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -318,35 +318,74 @@ struct symt_data* symt_new_global_variable(struct module* module,
     return sym;
 }
 
-struct symt_function* symt_new_function(struct module* module, 
-                                        struct symt_compiland* compiland, 
+static void init_function_or_inlinesite(struct symt_function* sym,
+                                        struct module* module,
+                                        DWORD tag,
+                                        struct symt* container,
                                         const char* name,
                                         ULONG_PTR addr, ULONG_PTR size,
                                         struct symt* sig_type)
 {
-    struct symt_function*       sym;
-    struct symt**               p;
+    assert(!sig_type || sig_type->tag == SymTagFunctionType);
+    sym->symt.tag  = tag;
+    sym->hash_elt.name = pool_strdup(&module->pool, name);
+    sym->container = container;
+    sym->address   = addr;
+    sym->type      = sig_type;
+    sym->size      = size;
+    vector_init(&sym->vlines,  sizeof(struct line_info), 64);
+    vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+}
+
+struct symt_function* symt_new_function(struct module* module,
+                                        struct symt_compiland* compiland,
+                                        const char* name,
+                                        ULONG_PTR addr, ULONG_PTR size,
+                                        struct symt* sig_type)
+{
+    struct symt_function* sym;
 
     TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n",
                          debugstr_w(module->modulename), name, addr, addr + size - 1);
-
-    assert(!sig_type || sig_type->tag == SymTagFunctionType);
     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
     {
-        sym->symt.tag  = SymTagFunction;
-        sym->hash_elt.name = pool_strdup(&module->pool, name);
-        sym->container = &compiland->symt;
-        sym->address   = addr;
-        sym->type      = sig_type;
-        sym->size      = size;
-        vector_init(&sym->vlines,  sizeof(struct line_info), 64);
-        vector_init(&sym->vchildren, sizeof(struct symt*), 8);
+        struct symt** p;
+        init_function_or_inlinesite(sym, module, SymTagFunction, &compiland->symt, name, addr, size, sig_type);
+        sym->next_inlinesite = NULL; /* first of list */
         symt_add_module_ht(module, (struct symt_ht*)sym);
-        if (compiland)
+        p = vector_add(&compiland->vchildren, &module->pool);
+        *p = &sym->symt;
+    }
+    return sym;
+}
+
+struct symt_inlinesite* symt_new_inlinesite(struct module* module,
+                                            struct symt_function* func,
+                                            struct symt* container,
+                                            const char* name,
+                                            ULONG_PTR addr,
+                                            struct symt* sig_type)
+{
+    struct symt_inlinesite* sym;
+
+    TRACE_(dbghelp_symt)("Adding inline site %s @%lx\n", name, addr);
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        struct symt** p;
+        assert(container);
+        init_function_or_inlinesite(&sym->func, module, SymTagInlineSite, container, name, addr, 0, sig_type);
+        vector_init(&sym->vranges, sizeof(struct addr_range), 2); /* FIXME: number of elts => to be set on input */
+        /* chain inline sites */
+        sym->func.next_inlinesite = func->next_inlinesite;
+        func->next_inlinesite = sym;
+        if (container->tag == SymTagFunction || container->tag == SymTagInlineSite)
+            p = vector_add(&((struct symt_function*)container)->vchildren, &module->pool);
+        else
         {
-            p = vector_add(&compiland->vchildren, &module->pool);
-            *p = &sym->symt;
+            assert(container->tag == SymTagBlock);
+            p = vector_add(&((struct symt_block*)container)->vchildren, &module->pool);
         }
+        *p = &sym->func.symt;
     }
     return sym;
 }
@@ -1138,6 +1177,23 @@ void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si)
     MultiByteToWideChar(CP_ACP, 0, si->Name, -1, siw->Name, siw->MaxNameLen);
 }
 
+/* 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;
+}
+
 /******************************************************************
  *		sym_enum
  *




More information about the wine-devel mailing list