All of lore.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Peter Zijlstra <peterz@infradead.org>,
	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 02/23] perf dwarf-aux: Add die_collect_vars()
Date: Mon, 18 Mar 2024 22:50:54 -0700	[thread overview]
Message-ID: <20240319055115.4063940-3-namhyung@kernel.org> (raw)
In-Reply-To: <20240319055115.4063940-1-namhyung@kernel.org>

The die_collect_vars() is to find all variable information in the scope
including function parameters.  The struct die_var_type is to save the
type of the variable with the location (reg and offset) as well as where
it's defined in the code (addr).

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/dwarf-aux.c | 118 +++++++++++++++++++++++++++---------
 tools/perf/util/dwarf-aux.h |  17 ++++++
 2 files changed, 107 insertions(+), 28 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index e84d0d6a7750..785aa7a3d725 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1136,6 +1136,40 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
 	return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
 }
 
+#if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT)
+static int reg_from_dwarf_op(Dwarf_Op *op)
+{
+	switch (op->atom) {
+	case DW_OP_reg0 ... DW_OP_reg31:
+		return op->atom - DW_OP_reg0;
+	case DW_OP_breg0 ... DW_OP_breg31:
+		return op->atom - DW_OP_breg0;
+	case DW_OP_regx:
+	case DW_OP_bregx:
+		return op->number;
+	default:
+		break;
+	}
+	return -1;
+}
+
+static int offset_from_dwarf_op(Dwarf_Op *op)
+{
+	switch (op->atom) {
+	case DW_OP_reg0 ... DW_OP_reg31:
+	case DW_OP_regx:
+		return 0;
+	case DW_OP_breg0 ... DW_OP_breg31:
+		return op->number;
+	case DW_OP_bregx:
+		return op->number2;
+	default:
+		break;
+	}
+	return -1;
+}
+#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */
+
 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
 /**
  * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
@@ -1476,41 +1510,69 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
 		*offset = data.offset;
 	return result;
 }
-#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */
 
-#ifdef HAVE_DWARF_CFI_SUPPORT
-static int reg_from_dwarf_op(Dwarf_Op *op)
+static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg)
 {
-	switch (op->atom) {
-	case DW_OP_reg0 ... DW_OP_reg31:
-		return op->atom - DW_OP_reg0;
-	case DW_OP_breg0 ... DW_OP_breg31:
-		return op->atom - DW_OP_breg0;
-	case DW_OP_regx:
-	case DW_OP_bregx:
-		return op->number;
-	default:
-		break;
-	}
-	return -1;
+	struct die_var_type **var_types = arg;
+	Dwarf_Die type_die;
+	int tag = dwarf_tag(die_mem);
+	Dwarf_Attribute attr;
+	Dwarf_Addr base, start, end;
+	Dwarf_Op *ops;
+	size_t nops;
+	struct die_var_type *vt;
+
+	if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter)
+		return DIE_FIND_CB_SIBLING;
+
+	if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL)
+		return DIE_FIND_CB_SIBLING;
+
+	/*
+	 * Only collect the first location as it can reconstruct the
+	 * remaining state by following the instructions.
+	 * start = 0 means it covers the whole range.
+	 */
+	if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0)
+		return DIE_FIND_CB_SIBLING;
+
+	if (die_get_real_type(die_mem, &type_die) == NULL)
+		return DIE_FIND_CB_SIBLING;
+
+	vt = malloc(sizeof(*vt));
+	if (vt == NULL)
+		return DIE_FIND_CB_END;
+
+	vt->die_off = dwarf_dieoffset(&type_die);
+	vt->addr = start;
+	vt->reg = reg_from_dwarf_op(ops);
+	vt->offset = offset_from_dwarf_op(ops);
+	vt->next = *var_types;
+	*var_types = vt;
+
+	return DIE_FIND_CB_SIBLING;
 }
 
-static int offset_from_dwarf_op(Dwarf_Op *op)
+/**
+ * die_collect_vars - Save all variables and parameters
+ * @sc_die: a scope DIE
+ * @var_types: a pointer to save the resulting list
+ *
+ * Save all variables and parameters in the @sc_die and save them to @var_types.
+ * The @var_types is a singly-linked list containing type and location info.
+ * Actual type can be retrieved using dwarf_offdie() with 'die_off' later.
+ *
+ * Callers should free @var_types.
+ */
+void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types)
 {
-	switch (op->atom) {
-	case DW_OP_reg0 ... DW_OP_reg31:
-	case DW_OP_regx:
-		return 0;
-	case DW_OP_breg0 ... DW_OP_breg31:
-		return op->number;
-	case DW_OP_bregx:
-		return op->number2;
-	default:
-		break;
-	}
-	return -1;
+	Dwarf_Die die_mem;
+
+	die_find_child(sc_die, __die_collect_vars_cb, (void *)var_types, &die_mem);
 }
+#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */
 
+#ifdef HAVE_DWARF_CFI_SUPPORT
 /**
  * die_get_cfa - Get frame base information
  * @dwarf: a Dwarf info
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 9973801a20c1..cd171b06fd4c 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -135,6 +135,15 @@ void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
 /* Get the list of including scopes */
 int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes);
 
+/* Variable type information */
+struct die_var_type {
+	struct die_var_type *next;
+	u64 die_off;
+	u64 addr;
+	int reg;
+	int offset;
+};
+
 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
 
 /* Get byte offset range of given variable DIE */
@@ -149,6 +158,9 @@ Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg,
 Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
 				     Dwarf_Die *die_mem, int *offset);
 
+/* Save all variables and parameters in this scope */
+void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types);
+
 #else /*  HAVE_DWARF_GETLOCATIONS_SUPPORT */
 
 static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
@@ -176,6 +188,11 @@ static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unu
 	return NULL;
 }
 
+static inline void die_collect_vars(Dwarf_Die *sc_die __maybe_unused,
+				    struct die_var_type **var_types __maybe_unused)
+{
+}
+
 #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */
 
 #ifdef HAVE_DWARF_CFI_SUPPORT
-- 
2.44.0.291.gc1ea87d7ee-goog


  parent reply	other threads:[~2024-03-19  5:51 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-19  5:50 [PATCHSET 00/23] Remaining bits of data type profiling (v7) Namhyung Kim
2024-03-19  5:50 ` [PATCH 01/23] perf dwarf-aux: Remove unused pc argument Namhyung Kim
2024-03-19 13:43   ` Arnaldo Carvalho de Melo
2024-03-19 17:39     ` Namhyung Kim
2024-03-19  5:50 ` Namhyung Kim [this message]
2024-03-19 13:45   ` [PATCH 02/23] perf dwarf-aux: Add die_collect_vars() Arnaldo Carvalho de Melo
2024-03-19  5:50 ` [PATCH 03/23] perf dwarf-aux: Handle type transfer for memory access Namhyung Kim
2024-03-19 13:55   ` Arnaldo Carvalho de Melo
2024-03-19 17:41     ` Namhyung Kim
2024-03-19  5:50 ` [PATCH 04/23] perf dwarf-aux: Add die_find_func_rettype() Namhyung Kim
2024-03-19 13:56   ` Arnaldo Carvalho de Melo
2024-03-19 17:42     ` Namhyung Kim
2024-03-19 18:19       ` Arnaldo Carvalho de Melo
2024-03-19 20:33         ` Namhyung Kim
2024-03-19  5:50 ` [PATCH 05/23] perf map: Add map__objdump_2rip() Namhyung Kim
2024-03-19  5:50 ` [PATCH 06/23] perf annotate-data: Introduce struct data_loc_info Namhyung Kim
2024-03-19  5:50 ` [PATCH 07/23] perf annotate: Add annotate_get_basic_blocks() Namhyung Kim
2024-03-19  5:51 ` [PATCH 08/23] perf annotate-data: Add debug messages Namhyung Kim
2024-03-19 14:05   ` Arnaldo Carvalho de Melo
2024-03-19  5:51 ` [PATCH 09/23] perf annotate-data: Maintain variable type info Namhyung Kim
2024-03-19 14:07   ` Arnaldo Carvalho de Melo
2024-03-19 17:44     ` Namhyung Kim
2024-03-19 18:12       ` Arnaldo Carvalho de Melo
2024-03-19 20:34         ` Namhyung Kim
2024-03-19  5:51 ` [PATCH 10/23] perf annotate-data: Add update_insn_state() Namhyung Kim
2024-03-19  5:51 ` [PATCH 11/23] perf annotate-data: Add get_global_var_type() Namhyung Kim
2024-03-19  5:51 ` [PATCH 12/23] perf annotate-data: Handle global variable access Namhyung Kim
2024-03-19  5:51 ` [PATCH 13/23] perf annotate-data: Handle call instructions Namhyung Kim
2024-03-19  5:51 ` [PATCH 14/23] perf annotate-data: Implement instruction tracking Namhyung Kim
2024-03-19  5:51 ` [PATCH 15/23] perf annotate-data: Check register state for type Namhyung Kim
2024-03-19  5:51 ` [PATCH 16/23] perf annotate: Parse x86 segment register location Namhyung Kim
2024-03-19  5:51 ` [PATCH 17/23] perf annotate-data: Handle this-cpu variables in kernel Namhyung Kim
2024-03-19  5:51 ` [PATCH 18/23] perf annotate-data: Track instructions with a this-cpu variable Namhyung Kim
2024-03-19  5:51 ` [PATCH 19/23] perf annotate-data: Support general per-cpu access Namhyung Kim
2024-03-19  5:51 ` [PATCH 20/23] perf annotate-data: Handle ADD instructions Namhyung Kim
2024-03-19  5:51 ` [PATCH 21/23] perf annotate-data: Add stack canary type Namhyung Kim
2024-03-19  5:51 ` [PATCH 22/23] perf annotate-data: Add a cache for global variable types Namhyung Kim
2024-03-19 18:05   ` Namhyung Kim
2024-03-19 18:07     ` Arnaldo Carvalho de Melo
2024-03-19 18:09       ` Arnaldo Carvalho de Melo
2024-03-19 18:09       ` Namhyung Kim
2024-03-19  5:51 ` [PATCH 23/23] perf annotate-data: Do not retry for invalid types Namhyung Kim
2024-03-19 14:17 ` [PATCHSET 00/23] Remaining bits of data type profiling (v7) Arnaldo Carvalho de Melo

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=20240319055115.4063940-3-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.