summaryrefslogtreecommitdiff
path: root/tools/perf/util/annotate-data.c
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2024-03-19 08:51:03 +0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2024-03-21 16:41:28 +0300
commit1ebb5e17ef21b492ee60654d4e22cbfb3763661f (patch)
tree5a28fb9c6f5ecdab00c96b5655f11bed3b69cb73 /tools/perf/util/annotate-data.c
parent4f903455befa257c50422a4570c4dca0020a1fc8 (diff)
downloadlinux-1ebb5e17ef21b492ee60654d4e22cbfb3763661f.tar.xz
perf annotate-data: Add get_global_var_type()
Accessing global variable is common when it tracks execution later. Factor out the common code into a function for later use. It adds thread and cpumode to struct data_loc_info to find (global) symbols if needed. Also remove var_name as it's retrieved in the helper function. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: https://lore.kernel.org/r/20240319055115.4063940-12-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/annotate-data.c')
-rw-r--r--tools/perf/util/annotate-data.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 592437b6c097..3b661e693410 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -22,6 +22,7 @@
#include "strbuf.h"
#include "symbol.h"
#include "symbol_conf.h"
+#include "thread.h"
#define pr_debug_dtp(fmt, ...) \
do { \
@@ -382,6 +383,50 @@ static struct type_state_stack *findnew_stack_state(struct type_state *state,
return stack;
}
+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)
+{
+ u64 pc, mem_addr;
+ int offset;
+ bool is_pointer = false;
+ const char *var_name = NULL;
+ Dwarf_Die var_die;
+ struct addr_location al;
+ struct symbol *sym;
+
+ /* Try to get the variable by address first */
+ if (die_find_variable_by_addr(cu_die, var_addr, &var_die, &offset) &&
+ check_variable(&var_die, type_die, offset, is_pointer) == 0) {
+ *var_offset = offset;
+ return true;
+ }
+
+ /* Kernel symbols might be relocated */
+ mem_addr = var_addr + map__reloc(dloc->ms->map);
+
+ addr_location__init(&al);
+ sym = thread__find_symbol_fb(dloc->thread, dloc->cpumode,
+ mem_addr, &al);
+ if (sym) {
+ var_name = sym->name;
+ /* Calculate type offset from the start of variable */
+ *var_offset = mem_addr - map__unmap_ip(al.map, sym->start);
+ }
+ addr_location__exit(&al);
+ if (var_name == NULL)
+ return false;
+
+ pc = map__rip_2objdump(dloc->ms->map, ip);
+
+ /* Try to get the name of global variable */
+ if (die_find_variable_at(cu_die, var_name, pc, &var_die) &&
+ check_variable(&var_die, type_die, *var_offset, is_pointer) == 0)
+ return true;
+
+ return false;
+}
+
/**
* update_var_state - Update type state using given variables
* @state: type state table
@@ -637,24 +682,14 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)
pr_debug_dtp("CU die offset: %#lx\n", (long)dwarf_dieoffset(&cu_die));
if (reg == DWARF_REG_PC) {
- if (die_find_variable_by_addr(&cu_die, dloc->var_addr, &var_die,
- &offset)) {
- ret = check_variable(&var_die, type_die, offset,
- /*is_pointer=*/false);
+ if (get_global_var_type(&cu_die, dloc, dloc->ip, dloc->var_addr,
+ &offset, type_die)) {
dloc->type_offset = offset;
pr_debug_dtp("found PC-rel by addr=%#"PRIx64" offset=%#x\n",
dloc->var_addr, offset);
goto out;
}
-
- if (dloc->var_name &&
- die_find_variable_at(&cu_die, dloc->var_name, pc, &var_die)) {
- ret = check_variable(&var_die, type_die, dloc->type_offset,
- /*is_pointer=*/false);
- /* dloc->type_offset was updated by the caller */
- goto out;
- }
}
/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
@@ -769,8 +804,7 @@ struct annotated_data_type *find_data_type(struct data_loc_info *dloc)
* The type offset is the same as instruction offset by default.
* But when finding a global variable, the offset won't be valid.
*/
- if (dloc->var_name == NULL)
- dloc->type_offset = dloc->op->offset;
+ dloc->type_offset = dloc->op->offset;
dloc->fbreg = -1;