All of lore.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Jiri Olsa <jolsa@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>
Cc: Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Ingo Molnar <mingo@kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	linux-perf-users@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Stephane Eranian <eranian@google.com>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	linux-toolchains@vger.kernel.org,
	linux-trace-devel@vger.kernel.org
Subject: [PATCH 30/48] perf annotate-data: Support global variables
Date: Wed, 11 Oct 2023 20:50:53 -0700	[thread overview]
Message-ID: <20231012035111.676789-31-namhyung@kernel.org> (raw)
In-Reply-To: <20231012035111.676789-1-namhyung@kernel.org>

Global variables are accessed using PC-relative address so it needs to
be handled separately.  The PC-rel addressing is detected by using
DWARF_REG_PC.  On x86, %rip register would be used.

The address can be calculated using the ip and offset in the
instruction.  But it should start from the next instruction so add
calculate_pcrel_addr() to do it properly.

But global variables defined in a different file would only have a
declaration which doesn't include a location list.  So it first tries
to get the type info using the address, and then looks up the variable
declarations using name.  The name of global variables should be get
from the symbol table.  The declaration would have the type info.

So extend find_var_type() to take both address and name for global
variables.

The stat is now looks like:

  Annotate data type stats:
  total 294, ok 153 (52.0%), bad 141 (48.0%)
  -----------------------------------------------------------
          30 : no_sym
          32 : no_mem_ops
          61 : no_var
          10 : no_typeinfo
           8 : bad_offset

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/annotate-data.c | 38 ++++++++++++++++------
 tools/perf/util/annotate-data.h |  6 ++--
 tools/perf/util/annotate.c      | 57 +++++++++++++++++++++++++++++++--
 tools/perf/util/annotate.h      |  4 +++
 4 files changed, 92 insertions(+), 13 deletions(-)

diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 3d4bd5040782..857e2fbe83f2 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -257,7 +257,8 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset,
 
 /* The result will be saved in @type_die */
 static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr,
-			      struct annotated_op_loc *loc, Dwarf_Die *type_die)
+			      const char *var_name, struct annotated_op_loc *loc,
+			      Dwarf_Die *type_die)
 {
 	Dwarf_Die cu_die, var_die;
 	Dwarf_Die *scopes = NULL;
@@ -275,11 +276,21 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr,
 	reg = loc->reg1;
 	offset = loc->offset;
 
-	if (reg == DWARF_REG_PC &&
-	    die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) {
-		ret = check_variable(&var_die, type_die, offset,
-				     /*is_pointer=*/false);
-		goto out;
+	if (reg == DWARF_REG_PC) {
+		if (die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) {
+			ret = check_variable(&var_die, type_die, offset,
+					     /*is_pointer=*/false);
+			loc->offset = offset;
+			goto out;
+		}
+
+		if (var_name && die_find_variable_at(&cu_die, var_name, pc,
+						     &var_die)) {
+			ret = check_variable(&var_die, type_die, 0,
+					     /*is_pointer=*/false);
+			/* loc->offset will be updated by the caller */
+			goto out;
+		}
 	}
 
 	/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
@@ -302,6 +313,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr,
 		/* Found a variable, see if it's correct */
 		ret = check_variable(&var_die, type_die, offset,
 				     reg != DWARF_REG_PC);
+		loc->offset = offset;
 		goto out;
 	}
 
@@ -323,13 +335,21 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr,
  * @ms: map and symbol at the location
  * @ip: instruction address of the memory access
  * @loc: instruction operand location
+ * @addr: data address of the memory access
+ * @var_name: global variable name
  *
  * This functions searches the debug information of the binary to get the data
- * type it accesses.  The exact location is expressed by (ip, reg, offset).
+ * type it accesses.  The exact location is expressed by (@ip, reg, offset)
+ * for pointer variables or (@ip, @addr) for global variables.  Note that global
+ * variables might update the @loc->offset after finding the start of the variable.
+ * If it cannot find a global variable by address, it tried to fine a declaration
+ * of the variable using @var_name.  In that case, @loc->offset won't be updated.
+ *
  * It return %NULL if not found.
  */
 struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
-					   struct annotated_op_loc *loc)
+					   struct annotated_op_loc *loc, u64 addr,
+					   const char *var_name)
 {
 	struct annotated_data_type *result = NULL;
 	struct dso *dso = ms->map->dso;
@@ -349,7 +369,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
 	 * a file address for DWARF processing.
 	 */
 	pc = map__rip_2objdump(ms->map, ip);
-	if (find_data_type_die(di, pc, 0, loc, &type_die) < 0)
+	if (find_data_type_die(di, pc, addr, var_name, loc, &type_die) < 0)
 		goto out;
 
 	result = dso__findnew_data_type(dso, &type_die);
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 214c625e7bc9..1b0db8e8c40e 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -107,7 +107,8 @@ extern struct annotated_data_stat ann_data_stat;
 
 /* Returns data type at the location (ip, reg, offset) */
 struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
-					   struct annotated_op_loc *loc);
+					   struct annotated_op_loc *loc, u64 addr,
+					   const char *var_name);
 
 /* Update type access histogram at the given offset */
 int annotated_data_type__update_samples(struct annotated_data_type *adt,
@@ -121,7 +122,8 @@ void annotated_data_type__tree_delete(struct rb_root *root);
 
 static inline struct annotated_data_type *
 find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused,
-	       struct annotated_op_loc *loc __maybe_unused)
+	       struct annotated_op_loc *loc __maybe_unused,
+	       u64 addr __maybe_unused, const char *var_name __maybe_unused)
 {
 	return NULL;
 }
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index dbbd349e67fc..fe0074bb98f0 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -37,6 +37,7 @@
 #include "util/sharded_mutex.h"
 #include "arch/common.h"
 #include "namespaces.h"
+#include "thread.h"
 #include <regex.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
@@ -3700,6 +3701,30 @@ static bool is_stack_operation(struct arch *arch, struct disasm_line *dl)
 	return false;
 }
 
+u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset,
+			struct disasm_line *dl)
+{
+	struct annotation *notes;
+	struct disasm_line *next;
+	u64 addr;
+
+	notes = symbol__annotation(ms->sym);
+	/*
+	 * PC-relative addressing starts from the next instruction address
+	 * But the IP is for the current instruction.  Since disasm_line
+	 * doesn't have the instruction size, calculate it using the next
+	 * disasm_line.  If it's the last one, we can use symbol's end
+	 * address directly.
+	 */
+	if (&dl->al.node == notes->src->source.prev)
+		addr = ms->sym->end + offset;
+	else {
+		next = list_next_entry(dl, al.node);
+		addr = ip + (next->al.offset - dl->al.offset) + offset;
+	}
+	return map__rip_2objdump(ms->map, addr);
+}
+
 /**
  * hist_entry__get_data_type - find data type for given hist entry
  * @he: hist entry
@@ -3719,7 +3744,9 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
 	struct annotated_op_loc *op_loc;
 	struct annotated_data_type *mem_type;
 	struct annotated_item_stat *istat;
-	u64 ip = he->ip;
+	u64 ip = he->ip, addr = 0;
+	const char *var_name = NULL;
+	int var_offset;
 	int i;
 
 	ann_data_stat.total++;
@@ -3773,12 +3800,38 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
 		/* Recalculate IP because of LOCK prefix or insn fusion */
 		ip = ms->sym->start + dl->al.offset;
 
-		mem_type = find_data_type(ms, ip, op_loc);
+		var_offset = op_loc->offset;
+
+		/* PC-relative addressing */
+		if (op_loc->reg1 == DWARF_REG_PC) {
+			struct addr_location al;
+			struct symbol *var;
+			u64 map_addr;
+
+			addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl);
+			/* Kernel symbols might be relocated */
+			map_addr = addr + map__reloc(ms->map);
+
+			addr_location__init(&al);
+			var = thread__find_symbol_fb(he->thread, he->cpumode,
+						     map_addr, &al);
+			if (var) {
+				var_name = var->name;
+				/* Calculate type offset from the start of variable */
+				var_offset = map_addr - map__unmap_ip(al.map, var->start);
+			}
+			addr_location__exit(&al);
+		}
+
+		mem_type = find_data_type(ms, ip, op_loc, addr, var_name);
 		if (mem_type)
 			istat->good++;
 		else
 			istat->bad++;
 
+		if (mem_type && var_name)
+			op_loc->offset = var_offset;
+
 		if (symbol_conf.annotate_data_sample) {
 			annotated_data_type__update_samples(mem_type, evsel,
 							    op_loc->offset,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 18a81faeb44b..99c8d30a2fa7 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -489,4 +489,8 @@ struct annotated_item_stat {
 };
 extern struct list_head ann_insn_stat;
 
+/* Calculate PC-relative address */
+u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset,
+			struct disasm_line *dl);
+
 #endif	/* __PERF_ANNOTATE_H */
-- 
2.42.0.655.g421f12c284-goog


  parent reply	other threads:[~2023-10-12  3:54 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-12  3:50 [RFC 00/48] perf tools: Introduce data type profiling (v1) Namhyung Kim
2023-10-12  3:50 ` [PATCH 01/48] perf annotate: Move raw_comment and raw_func_start Namhyung Kim
2023-10-12  3:50 ` [PATCH 02/48] perf annotate: Check if operand has multiple regs Namhyung Kim
2023-11-27 19:05   ` Arnaldo Carvalho de Melo
2023-10-12  3:50 ` [PATCH 03/48] perf tools: Add util/debuginfo.[ch] files Namhyung Kim
2023-10-12  3:50 ` [PATCH 04/48] perf dwarf-aux: Fix die_get_typename() for void * Namhyung Kim
2023-11-04 10:52   ` Masami Hiramatsu
2023-10-12  3:50 ` [PATCH 05/48] perf dwarf-aux: Move #ifdef code to the header file Namhyung Kim
2023-11-04 10:59   ` Masami Hiramatsu
2023-10-12  3:50 ` [PATCH 06/48] perf dwarf-aux: Add die_get_scopes() helper Namhyung Kim
2023-11-05  9:50   ` Masami Hiramatsu
2023-10-12  3:50 ` [PATCH 07/48] perf dwarf-aux: Add die_find_variable_by_reg() helper Namhyung Kim
2023-11-05  9:48   ` Masami Hiramatsu
2023-10-12  3:50 ` [PATCH 08/48] perf dwarf-aux: Factor out __die_get_typename() Namhyung Kim
2023-11-05  9:07   ` Masami Hiramatsu
2023-11-06  4:01     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 09/48] perf dwarf-regs: Add get_dwarf_regnum() Namhyung Kim
2023-11-05  8:36   ` Masami Hiramatsu
2023-11-06  4:12     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 10/48] perf annotate-data: Add find_data_type() Namhyung Kim
2023-10-12  3:50 ` [PATCH 11/48] perf annotate-data: Add dso->data_types tree Namhyung Kim
2023-10-12  3:50 ` [PATCH 12/48] perf annotate: Factor out evsel__get_arch() Namhyung Kim
2023-10-12  3:50 ` [PATCH 13/48] perf annotate: Add annotate_get_insn_location() Namhyung Kim
2023-10-23 16:38   ` Arnaldo Carvalho de Melo
2023-10-24 19:10     ` Namhyung Kim
2023-10-26  5:26       ` Namhyung Kim
2023-10-26 19:37         ` Arnaldo Carvalho de Melo
2023-10-12  3:50 ` [PATCH 14/48] perf annotate: Implement hist_entry__get_data_type() Namhyung Kim
2023-10-12  3:50 ` [PATCH 15/48] perf report: Add 'type' sort key Namhyung Kim
2023-10-23 16:53   ` Arnaldo Carvalho de Melo
2023-10-24 19:11     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 16/48] perf report: Support data type profiling Namhyung Kim
2023-10-12  3:50 ` [PATCH 17/48] perf annotate-data: Add member field in the data type Namhyung Kim
2023-10-12  3:50 ` [PATCH 18/48] perf annotate-data: Update sample histogram for type Namhyung Kim
2023-10-12  3:50 ` [PATCH 19/48] perf report: Add 'typeoff' sort key Namhyung Kim
2023-10-12  3:50 ` [PATCH 20/48] perf report: Add 'symoff' " Namhyung Kim
2023-10-12  3:50 ` [PATCH 21/48] perf annotate: Add --data-type option Namhyung Kim
2023-10-12  3:50 ` [PATCH 22/48] perf annotate: Add --type-stat option for debugging Namhyung Kim
2023-10-23 17:28   ` Arnaldo Carvalho de Melo
2023-10-23 17:40     ` Arnaldo Carvalho de Melo
2023-10-24 19:12       ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 23/48] perf annotate: Add --insn-stat " Namhyung Kim
2023-10-12  3:50 ` [PATCH 24/48] perf annotate-data: Parse 'lock' prefix from llvm-objdump Namhyung Kim
2023-10-12  3:50 ` [PATCH 25/48] perf annotate-data: Handle macro fusion on x86 Namhyung Kim
2023-10-12  3:50 ` [PATCH 26/48] perf annotate-data: Handle array style accesses Namhyung Kim
2023-10-12  3:50 ` [PATCH 27/48] perf annotate-data: Add stack operation pseudo type Namhyung Kim
2023-10-12  3:50 ` [PATCH 28/48] perf dwarf-aux: Add die_find_variable_by_addr() Namhyung Kim
2023-11-06 15:25   ` Masami Hiramatsu
2023-11-09  5:36     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 29/48] perf annotate-data: Handle PC-relative addressing Namhyung Kim
2023-10-12  3:50 ` Namhyung Kim [this message]
2023-10-12  3:50 ` [PATCH 31/48] perf dwarf-aux: Add die_get_cfa() Namhyung Kim
2023-11-07  0:50   ` Masami Hiramatsu
2023-11-08  5:28     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 32/48] perf annotate-data: Support stack variables Namhyung Kim
2023-10-12  3:50 ` [PATCH 33/48] perf dwarf-aux: Check allowed DWARF Ops Namhyung Kim
2023-11-07  9:32   ` Masami Hiramatsu
2023-11-08  5:34     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 34/48] perf dwarf-aux: Add die_collect_vars() Namhyung Kim
2023-11-08 10:52   ` Masami Hiramatsu
2023-11-09  5:05     ` Namhyung Kim
2023-10-12  3:50 ` [PATCH 35/48] perf dwarf-aux: Handle type transfer for memory access Namhyung Kim
2023-11-08 10:57   ` Masami Hiramatsu
2023-10-12  3:50 ` [PATCH 36/48] perf annotate-data: Introduce struct data_loc_info Namhyung Kim
2023-12-03 16:22   ` Athira Rajeev
2023-12-05  0:10     ` Namhyung Kim
2023-12-05  7:17       ` Athira Rajeev
2023-10-12  3:51 ` [PATCH 37/48] perf map: Add map__objdump_2rip() Namhyung Kim
2023-10-12  3:51 ` [PATCH 38/48] perf annotate: Add annotate_get_basic_blocks() Namhyung Kim
2023-10-12  3:51 ` [PATCH 39/48] perf annotate-data: Maintain variable type info Namhyung Kim
2023-10-12  3:51 ` [PATCH 40/48] perf annotate-data: Add update_insn_state() Namhyung Kim
2023-10-12  3:51 ` [PATCH 41/48] perf annotate-data: Handle global variable access Namhyung Kim
2023-10-12  3:51 ` [PATCH 42/48] perf annotate-data: Handle call instructions Namhyung Kim
2023-10-12  3:51 ` [PATCH 43/48] perf annotate-data: Implement instruction tracking Namhyung Kim
2023-10-12  3:51 ` [PATCH 44/48] perf annotate: Parse x86 segment register location Namhyung Kim
2023-10-12  3:51 ` [PATCH 45/48] perf annotate-data: Handle this-cpu variables in kernel Namhyung Kim
2023-10-12  3:51 ` [PATCH 46/48] perf annotate-data: Track instructions with a this-cpu variable Namhyung Kim
2023-10-12  3:51 ` [PATCH 47/48] perf annotate-data: Add stack canary type Namhyung Kim
2023-10-12  3:51 ` [PATCH 48/48] perf annotate-data: Add debug message Namhyung Kim
2023-10-12  6:03 ` [RFC 00/48] perf tools: Introduce data type profiling (v1) Ingo Molnar
2023-10-12 16:19   ` Namhyung Kim
2023-10-12 18:33     ` Ingo Molnar
2023-10-12 20:45       ` Namhyung Kim
2023-10-12  9:11 ` Peter Zijlstra
2023-10-12 16:41   ` Namhyung Kim
     [not found]     ` <CADzB+2mu98v9EUsA1Y-wVDSrXT2kznKi87Tb6QdN5y4mMFNsyg@mail.gmail.com>
2023-10-25  5:58       ` Namhyung Kim
2023-10-12  9:15 ` Peter Zijlstra
2023-10-12 16:52   ` Namhyung Kim
2023-10-13 14:15 ` Arnaldo Carvalho de Melo
2023-10-23 21:58 ` Andi Kleen
2023-10-24 19:16   ` Namhyung Kim
2023-10-25  2:09     ` Andi Kleen
2023-10-25  5:51       ` Namhyung Kim
2023-10-25 20:01         ` Andi Kleen
2023-11-08 17:12 ` Joe Mario
2023-11-09  4:48   ` Namhyung Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231012035111.676789-31-namhyung@kernel.org \
    --to=namhyung@kernel.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=eranian@google.com \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux-toolchains@vger.kernel.org \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.