[PATCH 15/22] [DbgHelp]: dwarf & inlined function support
Eric Pouech
eric.pouech at wanadoo.fr
Fri Nov 24 15:18:20 CST 2006
- extended support for inlined functions (and handle them
as generic blocks inside functions (except for parameters
which are converted into local variables)
- rewrote dwarf2_find_attribute so that it takes into account
the abstract origin information when available
A+
---
dlls/dbghelp/dwarf.c | 285 ++++++++++++++++++++++++++++----------------------
1 files changed, 162 insertions(+), 123 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index a61c833..75fe839 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -330,7 +330,7 @@ static const char* dwarf2_debug_ctx(cons
return wine_dbg_sprintf("ctx(%p,%s)", ctx, ctx->module->module.ModuleName);
}
-static const char* dwarf2_debug_di(dwarf2_debug_info_t* di)
+static const char* dwarf2_debug_di(const dwarf2_debug_info_t* di)
{
return wine_dbg_sprintf("debug_info(abbrev:%p,symt:%p)",
di->abbrev, di->symt);
@@ -442,118 +442,143 @@ static void dwarf2_swallow_attribute(dwa
ctx->data += step;
}
-static BOOL dwarf2_find_attribute(const dwarf2_parse_context_t* ctx,
- const dwarf2_debug_info_t* di,
- unsigned at, struct attribute* attr)
+static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
+ const dwarf2_abbrev_entry_attr_t* abbrev_attr,
+ const unsigned char* data,
+ struct attribute* attr)
{
- unsigned i;
- dwarf2_abbrev_entry_attr_t* abbrev_attr;
-
- for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next)
+ attr->form = abbrev_attr->form;
+ switch (attr->form)
{
- if (abbrev_attr->attribute == at)
- {
- attr->form = abbrev_attr->form;
- switch (attr->form)
- {
- case DW_FORM_ref_addr:
- case DW_FORM_addr:
- attr->u.uvalue = dwarf2_get_addr(di->data[i], ctx->word_size);
- TRACE("addr<0x%lx>\n", attr->u.uvalue);
- break;
+ case DW_FORM_ref_addr:
+ case DW_FORM_addr:
+ attr->u.uvalue = dwarf2_get_addr(data, ctx->word_size);
+ TRACE("addr<0x%lx>\n", attr->u.uvalue);
+ break;
- case DW_FORM_flag:
- attr->u.uvalue = dwarf2_get_byte(di->data[i]);
- TRACE("flag<0x%lx>\n", attr->u.uvalue);
- break;
+ case DW_FORM_flag:
+ attr->u.uvalue = dwarf2_get_byte(data);
+ TRACE("flag<0x%lx>\n", attr->u.uvalue);
+ break;
- case DW_FORM_data1:
- attr->u.uvalue = dwarf2_get_byte(di->data[i]);
- TRACE("data1<%lu>\n", attr->u.uvalue);
- break;
+ case DW_FORM_data1:
+ attr->u.uvalue = dwarf2_get_byte(data);
+ TRACE("data1<%lu>\n", attr->u.uvalue);
+ break;
- case DW_FORM_data2:
- attr->u.uvalue = dwarf2_get_u2(di->data[i]);
- TRACE("data2<%lu>\n", attr->u.uvalue);
- break;
+ case DW_FORM_data2:
+ attr->u.uvalue = dwarf2_get_u2(data);
+ TRACE("data2<%lu>\n", attr->u.uvalue);
+ break;
- case DW_FORM_data4:
- attr->u.uvalue = dwarf2_get_u4(di->data[i]);
- TRACE("data4<%lu>\n", attr->u.uvalue);
- break;
+ case DW_FORM_data4:
+ attr->u.uvalue = dwarf2_get_u4(data);
+ TRACE("data4<%lu>\n", attr->u.uvalue);
+ break;
- case DW_FORM_data8:
- FIXME("Unhandled 64bits support\n");
- break;
+ case DW_FORM_data8:
+ FIXME("Unhandled 64bits support\n");
+ break;
- case DW_FORM_ref1:
- attr->u.uvalue = ctx->ref_offset + dwarf2_get_byte(di->data[i]);
- TRACE("ref1<0x%lx>\n", attr->u.uvalue);
- break;
+ case DW_FORM_ref1:
+ attr->u.uvalue = ctx->ref_offset + dwarf2_get_byte(data);
+ TRACE("ref1<0x%lx>\n", attr->u.uvalue);
+ break;
- case DW_FORM_ref2:
- attr->u.uvalue = ctx->ref_offset + dwarf2_get_u2(di->data[i]);
- TRACE("ref2<0x%lx>\n", attr->u.uvalue);
- break;
+ case DW_FORM_ref2:
+ attr->u.uvalue = ctx->ref_offset + dwarf2_get_u2(data);
+ TRACE("ref2<0x%lx>\n", attr->u.uvalue);
+ break;
- case DW_FORM_ref4:
- attr->u.uvalue = ctx->ref_offset + dwarf2_get_u4(di->data[i]);
- TRACE("ref4<0x%lx>\n", attr->u.uvalue);
- break;
+ case DW_FORM_ref4:
+ attr->u.uvalue = ctx->ref_offset + dwarf2_get_u4(data);
+ TRACE("ref4<0x%lx>\n", attr->u.uvalue);
+ break;
- case DW_FORM_ref8:
- FIXME("Unhandled 64 bit support\n");
- break;
+ case DW_FORM_ref8:
+ FIXME("Unhandled 64 bit support\n");
+ break;
- case DW_FORM_sdata:
- attr->u.svalue = dwarf2_get_leb128_as_signed(di->data[i], NULL);
- break;
+ case DW_FORM_sdata:
+ attr->u.svalue = dwarf2_get_leb128_as_signed(data, NULL);
+ break;
- case DW_FORM_ref_udata:
- attr->u.uvalue = dwarf2_get_leb128_as_unsigned(di->data[i], NULL);
- break;
+ case DW_FORM_ref_udata:
+ attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
+ break;
- case DW_FORM_udata:
- attr->u.uvalue = dwarf2_get_leb128_as_unsigned(di->data[i], NULL);
- break;
+ case DW_FORM_udata:
+ attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL);
+ break;
- case DW_FORM_string:
- attr->u.string = (const char *)di->data[i];
- TRACE("string<%s>\n", attr->u.string);
- break;
+ case DW_FORM_string:
+ attr->u.string = (const char *)data;
+ TRACE("string<%s>\n", attr->u.string);
+ break;
- case DW_FORM_strp:
- {
- unsigned long offset = dwarf2_get_u4(di->data[i]);
- attr->u.string = (const char*)ctx->sections[section_string].address + offset;
- }
- TRACE("strp<%s>\n", attr->u.string);
- break;
- case DW_FORM_block:
- attr->u.block.size = dwarf2_get_leb128_as_unsigned(di->data[i], &attr->u.block.ptr);
- break;
+ case DW_FORM_strp:
+ {
+ unsigned long offset = dwarf2_get_u4(data);
+ attr->u.string = (const char*)ctx->sections[section_string].address + offset;
+ }
+ TRACE("strp<%s>\n", attr->u.string);
+ break;
+
+ case DW_FORM_block:
+ attr->u.block.size = dwarf2_get_leb128_as_unsigned(data, &attr->u.block.ptr);
+ break;
- case DW_FORM_block1:
- attr->u.block.size = dwarf2_get_byte(di->data[i]);
- attr->u.block.ptr = di->data[i] + 1;
- break;
+ case DW_FORM_block1:
+ attr->u.block.size = dwarf2_get_byte(data);
+ attr->u.block.ptr = data + 1;
+ break;
- case DW_FORM_block2:
- attr->u.block.size = dwarf2_get_u2(di->data[i]);
- attr->u.block.ptr = di->data[i] + 2;
- break;
+ case DW_FORM_block2:
+ attr->u.block.size = dwarf2_get_u2(data);
+ attr->u.block.ptr = data + 2;
+ break;
- case DW_FORM_block4:
- attr->u.block.size = dwarf2_get_u4(di->data[i]);
- attr->u.block.ptr = di->data[i] + 4;
- break;
+ case DW_FORM_block4:
+ attr->u.block.size = dwarf2_get_u4(data);
+ attr->u.block.ptr = data + 4;
+ break;
- default:
- FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
- break;
+ default:
+ FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
+ break;
+ }
+}
+
+static BOOL dwarf2_find_attribute(const dwarf2_parse_context_t* ctx,
+ const dwarf2_debug_info_t* di,
+ unsigned at, struct attribute* attr)
+{
+ unsigned i, ai = 0;
+ dwarf2_abbrev_entry_attr_t* abbrev_attr;
+ dwarf2_abbrev_entry_attr_t* abstract_abbrev_attr;
+
+ while (di)
+ {
+ abstract_abbrev_attr = NULL;
+ for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next)
+ {
+ if (abbrev_attr->attribute == at)
+ {
+ dwarf2_fill_attr(ctx, abbrev_attr, di->data[i], attr);
+ return TRUE;
+ }
+ if (abbrev_attr->attribute == DW_AT_abstract_origin &&
+ at != DW_AT_sibling)
+ {
+ abstract_abbrev_attr = abbrev_attr;
+ ai = i;
}
- return TRUE;
}
+ /* do we have an abstract origin debug entry to look into ? */
+ if (!abstract_abbrev_attr) break;
+ dwarf2_fill_attr(ctx, abstract_abbrev_attr, di->data[ai], attr);
+ if (!(di = sparse_array_find(&ctx->debug_info_table, attr->u.uvalue)))
+ FIXME("Should have found the debug info entry\n");
}
return FALSE;
}
@@ -1101,7 +1126,8 @@ static void dwarf2_parse_udt_member(dwar
}
else
loc.offset = 0;
- if (!dwarf2_find_attribute(ctx, di, DW_AT_bit_size, &bit_size)) bit_size.u.uvalue = 0;
+ if (!dwarf2_find_attribute(ctx, di, DW_AT_bit_size, &bit_size))
+ bit_size.u.uvalue = 0;
if (dwarf2_find_attribute(ctx, di, DW_AT_bit_offset, &bit_offset))
{
/* FIXME: we should only do this when implementation is LSB (which is
@@ -1247,15 +1273,17 @@ static void dwarf2_parse_variable(dwarf2
struct symt_block* block,
dwarf2_debug_info_t* di)
{
- struct symt* param_type;
- struct attribute name, value;
- struct location loc;
- BOOL is_pmt = di->abbrev->tag == DW_TAG_formal_parameter;
+ struct symt* param_type;
+ struct attribute name, value;
+ struct location loc;
+ BOOL is_pmt;
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
+ is_pmt = !block && di->abbrev->tag == DW_TAG_formal_parameter;
param_type = dwarf2_lookup_type(subpgm->ctx, di);
- dwarf2_find_name(subpgm->ctx, di, &name, "parameter");
+
+ dwarf2_find_name(subpgm->ctx, di, &name, NULL);
if (dwarf2_compute_location_attr(subpgm->ctx, di, DW_AT_location,
&loc, &subpgm->frame))
{
@@ -1314,7 +1342,7 @@ static void dwarf2_parse_subprogram_labe
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
- dwarf2_find_name(subpgm->ctx, di, &name, "label");
+ dwarf2_find_name(subpgm->ctx, di, &name, NULL);
loc.kind = loc_absolute;
loc.offset = subpgm->ctx->module->module.BaseOfImage + low_pc.u.uvalue,
@@ -1323,19 +1351,24 @@ static void dwarf2_parse_subprogram_labe
}
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
- struct symt_block* block_parent,
+ struct symt_block* parent_block,
dwarf2_debug_info_t* di);
static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
+ struct symt_block* parent_block,
dwarf2_debug_info_t* di)
{
+ struct symt_block* block;
+ struct attribute low_pc;
+ struct attribute high_pc;
+
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
- /* FIXME: attributes to handle:
- DW_AT_low_pc:
- DW_AT_high_pc:
- DW_AT_name:
- */
+ if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
+ if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
+
+ block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
+ low_pc.u.uvalue, high_pc.u.uvalue - low_pc.u.uvalue);
if (di->abbrev->have_child) /** any interest to not have child ? */
{
@@ -1349,23 +1382,14 @@ static void dwarf2_parse_inlined_subrout
switch (child->abbrev->tag)
{
case DW_TAG_formal_parameter:
- /* FIXME: this is not properly supported yet
- * dwarf2_parse_subprogram_parameter(ctx, child, NULL);
- */
- break;
case DW_TAG_variable:
- /* FIXME:
- * dwarf2_parse_variable(ctx, child);
- */
+ dwarf2_parse_variable(subpgm, block, child);
break;
case DW_TAG_lexical_block:
- /* FIXME:
- dwarf2_parse_subprogram_block(ctx, child, func);
- */
+ dwarf2_parse_subprogram_block(subpgm, block, child);
break;
case DW_TAG_inlined_subroutine:
- /* FIXME */
- dwarf2_parse_inlined_subroutine(subpgm, child);
+ dwarf2_parse_inlined_subroutine(subpgm, block, child);
break;
case DW_TAG_label:
dwarf2_parse_subprogram_label(subpgm, child);
@@ -1377,6 +1401,7 @@ static void dwarf2_parse_inlined_subrout
}
}
}
+ symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
}
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
@@ -1389,8 +1414,10 @@ static void dwarf2_parse_subprogram_bloc
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
- if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
- if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
+ if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc))
+ low_pc.u.uvalue = 0;
+ if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc))
+ high_pc.u.uvalue = 0;
block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
low_pc.u.uvalue, high_pc.u.uvalue - low_pc.u.uvalue);
@@ -1407,7 +1434,7 @@ static void dwarf2_parse_subprogram_bloc
switch (child->abbrev->tag)
{
case DW_TAG_inlined_subroutine:
- dwarf2_parse_inlined_subroutine(subpgm, child);
+ dwarf2_parse_inlined_subroutine(subpgm, block, child);
break;
case DW_TAG_variable:
dwarf2_parse_variable(subpgm, block, child);
@@ -1461,6 +1488,17 @@ static struct symt* dwarf2_parse_subprog
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+ /* if it's an abstract representation of an inline function, there should be
+ * a concrete object that we'll handle
+ */
+ if (dwarf2_find_attribute(ctx, di, DW_AT_inline, &inline_flags))
+ {
+ dwarf2_find_name(ctx, di, &name, "subprogram");
+ TRACE("Function %s declared as inlined (%ld)... skipping\n",
+ name.u.string, inline_flags.u.uvalue);
+ return NULL;
+ }
+
if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
if (!dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
/* As functions (defined as inline assembly) get debug info with dwarf
@@ -1470,9 +1508,10 @@ static struct symt* dwarf2_parse_subprog
if (elf_is_in_thunk_area(ctx->module->module.BaseOfImage + low_pc.u.uvalue,
ctx->thunks) >= 0)
return NULL;
- if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl)) is_decl.u.uvalue = 0;
- if (!dwarf2_find_attribute(ctx, di, DW_AT_inline, &inline_flags)) inline_flags.u.uvalue = 0;
- dwarf2_find_name(ctx, di, &name, "subprogram");
+ if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl))
+ is_decl.u.uvalue = 0;
+
+ dwarf2_find_name(ctx, di, &name, NULL);
ret_type = dwarf2_lookup_type(ctx, di);
/* FIXME: assuming C source code */
@@ -1518,7 +1557,7 @@ static struct symt* dwarf2_parse_subprog
dwarf2_parse_subprogram_block(&subpgm, NULL, child);
break;
case DW_TAG_inlined_subroutine:
- dwarf2_parse_inlined_subroutine(&subpgm, child);
+ dwarf2_parse_inlined_subroutine(&subpgm, NULL, child);
break;
case DW_TAG_subprogram:
/* FIXME: likely a declaration (to be checked)
More information about the wine-patches
mailing list