Many DW_AT_subroutine DIEs do not have address info associated directly; some use DW_AT_ranges, and some have address info stored with the associated abstract origin. Use these information sources to improve address retrieval for "struct function" representations. Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> --- dwarf_loader.c | 29 +++++++++++++++++++++++++---- dwarves.h | 3 ++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/dwarf_loader.c b/dwarf_loader.c index e1ba7bc..d46e82a 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -1519,6 +1519,17 @@ static struct function *function__new(Dwarf_Die *die, struct cu *cu, struct conf func->vtable_entry = -1; if (dwarf_hasattr(die, DW_AT_vtable_elem_location)) func->vtable_entry = attr_offset(die, DW_AT_vtable_elem_location); + /* some functions will have entry address in the start address + * in DW_AT_ranges. + */ + if (dwarf_hasattr(die, DW_AT_ranges)) { + Dwarf_Addr base, start, high_pc; + ptrdiff_t offset = 0; + + dwarf_ranges(die, offset, &base, &start, &high_pc); + if (start) + func->addr = (uint64_t)start; + } func->cu_total_size_inline_expansions = 0; func->cu_total_nr_inline_expansions = 0; func->priv = NULL; @@ -2805,7 +2816,7 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu) case DW_TAG_subprogram: { struct function *fn = tag__function(tag); - if (fn->name == 0) { + if (fn->name == 0 || function__addr(fn) == 0) { if (dtag->abstract_origin == 0 && dtag->specification == 0) { /* @@ -2818,9 +2829,19 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu) dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, abstract_origin); if (dtype == NULL) dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, specification); - if (dtype != NULL) - fn->name = tag__function(dtag__tag(dtype))->name; - else { + if (dtype != NULL) { + struct function *dfn = tag__function(dtag__tag(dtype)); + if (fn->name == 0) + fn->name = dfn->name; + /* share function address info between tag and + * abstract origin. + */ + if (!function__addr(fn)) + fn->addr = function__addr(dfn); + else if (!function__addr(dfn)) + dfn->addr = function__addr(fn); + } + if (fn->name == 0) { fprintf(stderr, "%s: couldn't find name for " "function %#llx, abstract_origin=%#llx," diff --git a/dwarves.h b/dwarves.h index 36c6898..847e13d 100644 --- a/dwarves.h +++ b/dwarves.h @@ -1081,6 +1081,7 @@ struct function { const char *name; const char *linkage_name; const char *alias; /* name.isra.0 */ + uint64_t addr; uint32_t cu_total_size_inline_expansions; uint16_t cu_total_nr_inline_expansions; uint8_t inlined:2; @@ -1146,7 +1147,7 @@ const char *function__prototype_conf(const struct function *func, static __pure inline uint64_t function__addr(const struct function *func) { - return func->lexblock.ip.addr; + return func->lexblock.ip.addr ?: func->addr; } static __pure inline uint32_t function__size(const struct function *func) -- 2.39.3