Commit d832d51c authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

dbghelp/dwarf: Add a helper to jump into another debug_info.

This helper takes into account that source and destination debug_info can be in different dwarf units, and even different debug files (DWZ). Signed-off-by: 's avatarEric Pouech <eric.pouech@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent def87b2a
...@@ -134,6 +134,7 @@ struct attribute ...@@ -134,6 +134,7 @@ struct attribute
const char* string; const char* string;
struct dwarf2_block block; struct dwarf2_block block;
} u; } u;
const struct dwarf2_debug_info_s* debug_info;
}; };
typedef struct dwarf2_debug_info_s typedef struct dwarf2_debug_info_s
...@@ -711,6 +712,8 @@ static BOOL dwarf2_fill_attr(const dwarf2_parse_context_t* ctx, ...@@ -711,6 +712,8 @@ static BOOL dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
return TRUE; return TRUE;
} }
static dwarf2_debug_info_t* dwarf2_jump_to_debug_info(struct attribute* attr);
static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di, static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di,
unsigned at, struct attribute* attr) unsigned at, struct attribute* attr)
{ {
...@@ -722,6 +725,7 @@ static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di, ...@@ -722,6 +725,7 @@ static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di,
while (di) while (di)
{ {
ref_abbrev_attr = NULL; ref_abbrev_attr = NULL;
attr->debug_info = di;
for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next) for (i = 0, abbrev_attr = di->abbrev->attrs; abbrev_attr; i++, abbrev_attr = abbrev_attr->next)
{ {
if (abbrev_attr->attribute == at) if (abbrev_attr->attribute == at)
...@@ -743,12 +747,49 @@ static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di, ...@@ -743,12 +747,49 @@ static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di,
/* do we have either an abstract origin or a specification debug entry to look into ? */ /* do we have either an abstract origin or a specification debug entry to look into ? */
if (!ref_abbrev_attr || !dwarf2_fill_attr(di->unit_ctx, ref_abbrev_attr, di->data[refidx], attr)) if (!ref_abbrev_attr || !dwarf2_fill_attr(di->unit_ctx, ref_abbrev_attr, di->data[refidx], attr))
break; break;
if (!(di = sparse_array_find(&di->unit_ctx->debug_info_table, attr->u.uvalue))) if (!(di = dwarf2_jump_to_debug_info(attr)))
{
FIXME("Should have found the debug info entry\n"); FIXME("Should have found the debug info entry\n");
break;
}
} }
return FALSE; return FALSE;
} }
static dwarf2_debug_info_t* dwarf2_jump_to_debug_info(struct attribute* attr)
{
dwarf2_parse_context_t* ref_ctx = NULL;
BOOL with_other = TRUE;
dwarf2_debug_info_t* ret;
switch (attr->form)
{
case DW_FORM_ref_addr:
ref_ctx = dwarf2_locate_cu(attr->debug_info->unit_ctx->module_ctx, attr->u.uvalue);
break;
default:
with_other = FALSE;
ref_ctx = attr->debug_info->unit_ctx;
break;
}
if (!ref_ctx) return FALSE;
/* There are cases where we end up with a circular reference between two (or more)
* compilation units. Before this happens, try to see if we can refer to an already
* loaded debug_info in the target compilation unit (even if all the debug_info
* haven't been loaded yet).
*/
if (ref_ctx->status == UNIT_BEINGLOADED &&
(ret = sparse_array_find(&ref_ctx->debug_info_table, attr->u.uvalue)))
return ret;
if (with_other)
{
/* ensure CU is fully loaded */
if (ref_ctx != attr->debug_info->unit_ctx && !dwarf2_parse_compilation_unit(ref_ctx))
return NULL;
}
return sparse_array_find(&ref_ctx->debug_info_table, attr->u.uvalue);
}
static void dwarf2_load_one_entry(dwarf2_debug_info_t*); static void dwarf2_load_one_entry(dwarf2_debug_info_t*);
#define Wine_DW_no_register 0x7FFFFFFF #define Wine_DW_no_register 0x7FFFFFFF
...@@ -1069,24 +1110,9 @@ static struct symt* dwarf2_lookup_type(const dwarf2_debug_info_t* di) ...@@ -1069,24 +1110,9 @@ static struct symt* dwarf2_lookup_type(const dwarf2_debug_info_t* di)
if (!dwarf2_find_attribute(di, DW_AT_type, &attr)) if (!dwarf2_find_attribute(di, DW_AT_type, &attr))
/* this is only valid if current language of CU is C or C++ */ /* this is only valid if current language of CU is C or C++ */
return di->unit_ctx->module_ctx->symt_cache[sc_void]; return di->unit_ctx->module_ctx->symt_cache[sc_void];
if (!(type = sparse_array_find(&di->unit_ctx->debug_info_table, attr.u.uvalue))) if (!(type = dwarf2_jump_to_debug_info(&attr)))
{ return di->unit_ctx->module_ctx->symt_cache[sc_unknown];
if (attr.form == DW_FORM_ref_addr)
{
dwarf2_parse_context_t* ref_ctx = dwarf2_locate_cu(di->unit_ctx->module_ctx, attr.u.uvalue);
/* ensure CU is fully loaded */
if (ref_ctx && dwarf2_parse_compilation_unit(ref_ctx))
{
type = sparse_array_find(&ref_ctx->debug_info_table, attr.u.uvalue);
if (type) TRACE("Found type ref %lx in another CU %s\n", attr.u.uvalue, dwarf2_debug_unit_ctx(ref_ctx));
}
}
if (!type)
{
FIXME("Unable to find back reference to type 0x%lx (form=0x%lx)\n", attr.u.uvalue, attr.form);
return di->unit_ctx->module_ctx->symt_cache[sc_unknown];
}
}
if (type == di) if (type == di)
{ {
FIXME("Reference to itself\n"); FIXME("Reference to itself\n");
...@@ -1112,17 +1138,13 @@ static const char* dwarf2_get_cpp_name(dwarf2_debug_info_t* di, const char* name ...@@ -1112,17 +1138,13 @@ static const char* dwarf2_get_cpp_name(dwarf2_debug_info_t* di, const char* name
struct attribute spec; struct attribute spec;
if (di->abbrev->tag == DW_TAG_compile_unit) return name; if (di->abbrev->tag == DW_TAG_compile_unit) return name;
if (!di->unit_ctx->cpp_name)
di->unit_ctx->cpp_name = pool_alloc(&di->unit_ctx->pool, MAX_SYM_NAME);
last = di->unit_ctx->cpp_name + MAX_SYM_NAME - strlen(name) - 1;
strcpy(last, name);
/* if the di is a definition, but has also a (previous) declaration, then scope must /* if the di is a definition, but has also a (previous) declaration, then scope must
* be gotten from declaration not definition * be gotten from declaration not definition
*/ */
if (dwarf2_find_attribute(di, DW_AT_specification, &spec) && spec.gotten_from == attr_direct) if (dwarf2_find_attribute(di, DW_AT_specification, &spec) && spec.gotten_from == attr_direct)
{ {
di = sparse_array_find(&di->unit_ctx->debug_info_table, spec.u.uvalue); di = dwarf2_jump_to_debug_info(&spec);
if (!di) if (!di)
{ {
FIXME("Should have found the debug info entry\n"); FIXME("Should have found the debug info entry\n");
...@@ -1130,6 +1152,11 @@ static const char* dwarf2_get_cpp_name(dwarf2_debug_info_t* di, const char* name ...@@ -1130,6 +1152,11 @@ static const char* dwarf2_get_cpp_name(dwarf2_debug_info_t* di, const char* name
} }
} }
if (!di->unit_ctx->cpp_name)
di->unit_ctx->cpp_name = pool_alloc(&di->unit_ctx->pool, MAX_SYM_NAME);
last = di->unit_ctx->cpp_name + MAX_SYM_NAME - strlen(name) - 1;
strcpy(last, name);
for (di = di->parent; di; di = di->parent) for (di = di->parent; di; di = di->parent)
{ {
switch (di->abbrev->tag) switch (di->abbrev->tag)
...@@ -1295,7 +1322,7 @@ static struct vector* dwarf2_get_di_children(dwarf2_debug_info_t* di) ...@@ -1295,7 +1322,7 @@ static struct vector* dwarf2_get_di_children(dwarf2_debug_info_t* di)
if (di->abbrev->have_child) if (di->abbrev->have_child)
return &di->children; return &di->children;
if (!dwarf2_find_attribute(di, DW_AT_specification, &spec)) break; if (!dwarf2_find_attribute(di, DW_AT_specification, &spec)) break;
if (!(di = sparse_array_find(&di->unit_ctx->debug_info_table, spec.u.uvalue))) if (!(di = dwarf2_jump_to_debug_info(&spec)))
FIXME("Should have found the debug info entry\n"); FIXME("Should have found the debug info entry\n");
} }
return NULL; return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment