diff options
-rw-r--r-- | tools/perf/util/annotate-data.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 12d5faff3b7a..4dd0911904f2 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -28,6 +28,8 @@ /* register number of the stack pointer */ #define X86_REG_SP 7 +static void delete_var_types(struct die_var_type *var_types); + enum type_state_kind { TSR_KIND_INVALID = 0, TSR_KIND_TYPE, @@ -557,8 +559,8 @@ static bool global_var__add(struct data_loc_info *dloc, u64 addr, if (gvar == NULL) return false; - gvar->name = strdup(name); - if (gvar->name == NULL) { + gvar->name = name ? strdup(name) : NULL; + if (name && gvar->name == NULL) { free(gvar); return false; } @@ -612,6 +614,53 @@ static bool get_global_var_info(struct data_loc_info *dloc, u64 addr, return true; } +static void global_var__collect(struct data_loc_info *dloc) +{ + Dwarf *dwarf = dloc->di->dbg; + Dwarf_Off off, next_off; + Dwarf_Die cu_die, type_die; + size_t header_size; + + /* Iterate all CU and collect global variables that have no location in a register. */ + off = 0; + while (dwarf_nextcu(dwarf, off, &next_off, &header_size, + NULL, NULL, NULL) == 0) { + struct die_var_type *var_types = NULL; + struct die_var_type *pos; + + if (dwarf_offdie(dwarf, off + header_size, &cu_die) == NULL) { + off = next_off; + continue; + } + + die_collect_global_vars(&cu_die, &var_types); + + for (pos = var_types; pos; pos = pos->next) { + const char *var_name = NULL; + int var_offset = 0; + + if (pos->reg != -1) + continue; + + if (!dwarf_offdie(dwarf, pos->die_off, &type_die)) + continue; + + if (!get_global_var_info(dloc, pos->addr, &var_name, + &var_offset)) + continue; + + if (var_offset != 0) + continue; + + global_var__add(dloc, pos->addr, var_name, &type_die); + } + + delete_var_types(var_types); + + off = next_off; + } +} + static bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc, u64 ip, u64 var_addr, int *var_offset, Dwarf_Die *type_die) @@ -620,8 +669,12 @@ static bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc, int offset; const char *var_name = NULL; struct global_var_entry *gvar; + struct dso *dso = map__dso(dloc->ms->map); Dwarf_Die var_die; + if (RB_EMPTY_ROOT(&dso->global_vars)) + global_var__collect(dloc); + gvar = global_var__find(dloc, var_addr); if (gvar) { if (!dwarf_offdie(dloc->di->dbg, gvar->die_offset, type_die)) |