linux-toolchains.vger.kernel.org archive mirror
 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>,
	Andi Kleen <ak@linux.intel.com>,
	linux-trace-devel@vger.kernel.org,
	linux-toolchains@vger.kernel.org
Subject: [PATCH 44/52] perf annotate-data: Add update_insn_state()
Date: Thu,  9 Nov 2023 16:00:03 -0800	[thread overview]
Message-ID: <20231110000012.3538610-45-namhyung@kernel.org> (raw)
In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org>

The update_insn_state() function is to update the type state table after
processing each instruction.  For now, it handles MOV (on x86) insn
to transfer type info from the source location to the target.

The location can be a register or a stack slot.  Check carefully when
memory reference happens and fetch the type correctly.  It basically
ignores write to a memory since it doesn't change the type info.  One
exception is writes to (new) stack slots for register spilling.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/util/annotate-data.c | 128 +++++++++++++++++++++++++++++++-
 tools/perf/util/annotate-data.h |  13 ++++
 tools/perf/util/annotate.c      |   1 +
 3 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 438d6234020b..09ccac1d0769 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -26,7 +26,6 @@
 struct type_state_reg {
 	Dwarf_Die type;
 	bool ok;
-	bool scratch;
 };
 
 /* Type information in a stack location, dynamically allocated */
@@ -382,7 +381,7 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc,
 			findnew_stack_state(state, var->offset, &mem_die);
 		} else if (var->reg == fbreg) {
 			findnew_stack_state(state, var->offset - fb_offset, &mem_die);
-		} else if (has_reg_type(state, var->reg)) {
+		} else if (has_reg_type(state, var->reg) && var->offset == 0) {
 			struct type_state_reg *reg;
 
 			reg = &state->regs[var->reg];
@@ -392,6 +391,131 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc,
 	}
 }
 
+/**
+ * update_insn_state - Update type state for an instruction
+ * @state: type state table
+ * @dloc: data location info
+ * @dl: disasm line for the instruction
+ *
+ * This function updates the @state table for the target operand of the
+ * instruction at @dl if it transfers the type like MOV on x86.  Since it
+ * tracks the type, it won't care about the values like in arithmetic
+ * instructions like ADD/SUB/MUL/DIV and INC/DEC.
+ *
+ * Note that ops->reg2 is only available when both mem_ref and multi_regs
+ * are true.
+ */
+void update_insn_state(struct type_state *state, struct data_loc_info *dloc,
+		       struct disasm_line *dl)
+{
+	struct annotated_insn_loc loc;
+	struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE];
+	struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
+	Dwarf_Die type_die;
+	int fbreg = dloc->fbreg;
+	int fboff = 0;
+
+	/* FIXME: remove x86 specific code and handle more instructions like LEA */
+	if (!strstr(dl->ins.name, "mov"))
+		return;
+
+	if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
+		return;
+
+	if (dloc->fb_cfa) {
+		u64 ip = dloc->ms->sym->start + dl->al.offset;
+		u64 pc = map__rip_2objdump(dloc->ms->map, ip);
+
+		if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0)
+			fbreg = -1;
+	}
+
+	/* Case 1. register to register transfers */
+	if (!src->mem_ref && !dst->mem_ref) {
+		if (!has_reg_type(state, dst->reg1))
+			return;
+
+		if (has_reg_type(state, src->reg1))
+			state->regs[dst->reg1] = state->regs[src->reg1];
+		else
+			state->regs[dst->reg1].ok = false;
+	}
+	/* Case 2. memory to register transers */
+	if (src->mem_ref && !dst->mem_ref) {
+		int sreg = src->reg1;
+
+		if (!has_reg_type(state, dst->reg1))
+			return;
+
+retry:
+		/* Check stack variables with offset */
+		if (sreg == fbreg) {
+			struct type_state_stack *stack;
+			int offset = src->offset - fboff;
+
+			stack = find_stack_state(state, offset);
+			if (stack && die_get_member_type(&stack->type,
+							 offset - stack->offset,
+							 &type_die)) {
+				state->regs[dst->reg1].type = type_die;
+				state->regs[dst->reg1].ok = true;
+			} else
+				state->regs[dst->reg1].ok = false;
+		}
+		/* And then dereference the pointer if it has one */
+		else if (has_reg_type(state, sreg) && state->regs[sreg].ok &&
+			 die_deref_ptr_type(&state->regs[sreg].type,
+					    src->offset, &type_die)) {
+			state->regs[dst->reg1].type = type_die;
+			state->regs[dst->reg1].ok = true;
+		}
+		/* Or try another register if any */
+		else if (src->multi_regs && sreg == src->reg1 &&
+			 src->reg1 != src->reg2) {
+			sreg = src->reg2;
+			goto retry;
+		}
+		/* It failed to get a type info, mark it as invalid */
+		else {
+			state->regs[dst->reg1].ok = false;
+		}
+	}
+	/* Case 3. register to memory transfers */
+	if (!src->mem_ref && dst->mem_ref) {
+		if (!has_reg_type(state, src->reg1) ||
+		    !state->regs[src->reg1].ok)
+			return;
+
+		/* Check stack variables with offset */
+		if (dst->reg1 == fbreg) {
+			struct type_state_stack *stack;
+			int offset = dst->offset - fboff;
+
+			stack = find_stack_state(state, offset);
+			if (stack) {
+				/*
+				 * The source register is likely to hold a type
+				 * of member if it's a compound type.  Do not
+				 * update the stack variable type since we can
+				 * get the member type later by using the
+				 * die_get_member_type().
+				 */
+				if (!stack->compound)
+					set_stack_state(stack, offset,
+							&state->regs[src->reg1].type);
+			} else {
+				findnew_stack_state(state, offset,
+						    &state->regs[src->reg1].type);
+			}
+		}
+		/*
+		 * Ignore other transfers since it'd set a value in a struct
+		 * and won't change the type.
+		 */
+	}
+	/* Case 4. memory to memory transfers (not handled for now) */
+}
+
 /* The result will be saved in @type_die */
 static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)
 {
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 7fbb9eb2e96f..ff9acf6ea808 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -11,6 +11,7 @@ struct annotated_op_loc;
 struct arch;
 struct debuginfo;
 struct die_var_type;
+struct disasm_line;
 struct evsel;
 struct map_symbol;
 struct type_state;
@@ -78,6 +79,7 @@ extern struct annotated_data_type stackop_type;
 
 /**
  * struct data_loc_info - Data location information
+ * @arch: architecture info
  * @ms: Map and Symbol info
  * @ip: Instruction address
  * @var_addr: Data address (for global variables)
@@ -90,6 +92,7 @@ extern struct annotated_data_type stackop_type;
  */
 struct data_loc_info {
 	/* These are input field, should be filled by caller */
+	struct arch *arch;
 	struct map_symbol *ms;
 	u64 ip;
 	u64 var_addr;
@@ -159,6 +162,10 @@ void exit_type_state(struct type_state *state);
 void update_var_state(struct type_state *state, struct data_loc_info *dloc,
 		      u64 addr, struct die_var_type *var_types);
 
+/* Update type state table for an instruction */
+void update_insn_state(struct type_state *state, struct data_loc_info *dloc,
+		       struct disasm_line *dl);
+
 #else /* HAVE_DWARF_SUPPORT */
 
 static inline struct annotated_data_type *
@@ -197,6 +204,12 @@ static inline void update_var_state(struct type_state *state __maybe_unused,
 {
 }
 
+static inline void update_insn_state(struct type_state *state __maybe_unused,
+				     struct data_loc_info *dloc __maybe_unused,
+				     struct disasm_line *dl __maybe_unused)
+{
+}
+
 #endif /* HAVE_DWARF_SUPPORT */
 
 #endif /* _PERF_ANNOTATE_DATA_H */
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d54a9ec16af4..ffbdba50b50a 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -3843,6 +3843,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
 
 	for_each_insn_op_loc(&loc, i, op_loc) {
 		struct data_loc_info dloc = {
+			.arch = arch,
 			.ms = ms,
 			/* Recalculate IP for LOCK prefix or insn fusion */
 			.ip = ms->sym->start + dl->al.offset,
-- 
2.42.0.869.gea05f2083d-goog


  parent reply	other threads:[~2023-11-10  0:04 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-09 23:59 [RFC 00/52] perf tools: Introduce data type profiling (v2) Namhyung Kim
2023-11-09 23:59 ` [PATCH 01/52] perf annotate: Pass "-l" option to objdump conditionally Namhyung Kim
2023-11-09 23:59 ` [PATCH 02/52] perf annotate: Move raw_comment and raw_func_start Namhyung Kim
2023-11-09 23:59 ` [PATCH 03/52] perf tools: Add util/debuginfo.[ch] files Namhyung Kim
2023-11-09 23:59 ` [PATCH 04/52] perf dwarf-aux: Fix die_get_typename() for void * Namhyung Kim
2023-11-09 23:59 ` [PATCH 05/52] perf dwarf-aux: Move #ifdef code to the header file Namhyung Kim
2023-11-09 23:59 ` [PATCH 06/52] perf dwarf-aux: Add die_get_scopes() helper Namhyung Kim
2023-11-09 23:59 ` [PATCH 07/52] perf dwarf-aux: Add die_find_variable_by_reg() helper Namhyung Kim
2023-11-09 23:59 ` [PATCH 08/52] perf build: Add feature check for dwarf_getcfi() Namhyung Kim
2023-11-10 10:26   ` Masami Hiramatsu
2023-11-09 23:59 ` [PATCH 09/52] perf probe: Convert to check dwarf_getcfi feature Namhyung Kim
2023-11-10 10:25   ` Masami Hiramatsu
2023-11-09 23:59 ` [PATCH 10/52] perf dwarf-aux: Factor out die_get_typename_from_type() Namhyung Kim
2023-11-09 23:59 ` [PATCH 11/52] perf dwarf-regs: Add get_dwarf_regnum() Namhyung Kim
2023-11-09 23:59 ` [PATCH 12/52] perf annotate-data: Add find_data_type() Namhyung Kim
     [not found]   ` <CA+JHD90fkWNrQWO5DrHeV8mCmFyKKqJ8fV=KwztRi7TSw+8yDg@mail.gmail.com>
2023-11-20 20:43     ` Namhyung Kim
2023-11-09 23:59 ` [PATCH 13/52] perf annotate-data: Add dso->data_types tree Namhyung Kim
2023-12-21 20:10   ` Arnaldo Carvalho de Melo
2023-12-21 20:13     ` Arnaldo Carvalho de Melo
2023-12-21 20:32       ` Arnaldo Carvalho de Melo
2023-11-09 23:59 ` [PATCH 14/52] perf annotate: Factor out evsel__get_arch() Namhyung Kim
2023-12-23 14:14   ` Arnaldo Carvalho de Melo
2023-11-09 23:59 ` [PATCH 15/52] perf annotate: Check if operand has multiple regs Namhyung Kim
2023-11-09 23:59 ` [PATCH 16/52] perf annotate: Add annotate_get_insn_location() Namhyung Kim
2023-11-09 23:59 ` [PATCH 17/52] perf annotate: Implement hist_entry__get_data_type() Namhyung Kim
2023-11-09 23:59 ` [PATCH 18/52] perf report: Add 'type' sort key Namhyung Kim
2023-11-21 17:55   ` Arnaldo Carvalho de Melo
2023-11-22 18:49     ` Namhyung Kim
2023-11-22 19:54       ` Arnaldo Carvalho de Melo
2023-11-22 21:13         ` Namhyung Kim
2023-11-23 13:40           ` Arnaldo Carvalho de Melo
2023-11-09 23:59 ` [PATCH 19/52] perf report: Support data type profiling Namhyung Kim
2023-11-09 23:59 ` [PATCH 20/52] perf annotate-data: Add member field in the data type Namhyung Kim
2023-11-09 23:59 ` [PATCH 21/52] perf annotate-data: Update sample histogram for type Namhyung Kim
2023-11-09 23:59 ` [PATCH 22/52] perf report: Add 'typeoff' sort key Namhyung Kim
2023-11-09 23:59 ` [PATCH 23/52] perf report: Add 'symoff' " Namhyung Kim
2023-12-23 14:29   ` Arnaldo Carvalho de Melo
2023-11-09 23:59 ` [PATCH 24/52] perf annotate: Add --data-type option Namhyung Kim
2023-11-09 23:59 ` [PATCH 25/52] perf annotate: Support event group display Namhyung Kim
2023-11-09 23:59 ` [PATCH 26/52] perf annotate: Add --type-stat option for debugging Namhyung Kim
2023-11-09 23:59 ` [PATCH 27/52] perf annotate: Add --insn-stat " Namhyung Kim
2023-11-09 23:59 ` [PATCH 28/52] perf annotate-data: Parse 'lock' prefix from llvm-objdump Namhyung Kim
2023-11-09 23:59 ` [PATCH 29/52] perf annotate-data: Handle macro fusion on x86 Namhyung Kim
2023-11-09 23:59 ` [PATCH 30/52] perf annotate-data: Handle array style accesses Namhyung Kim
2023-11-09 23:59 ` [PATCH 31/52] perf annotate-data: Add stack operation pseudo type Namhyung Kim
2023-11-09 23:59 ` [PATCH 32/52] perf dwarf-aux: Add die_find_variable_by_addr() Namhyung Kim
2023-11-27 22:07   ` Arnaldo Carvalho de Melo
2023-11-09 23:59 ` [PATCH 33/52] perf annotate-data: Handle PC-relative addressing Namhyung Kim
2023-11-09 23:59 ` [PATCH 34/52] perf annotate-data: Support global variables Namhyung Kim
2023-11-09 23:59 ` [PATCH 35/52] perf dwarf-aux: Add die_get_cfa() Namhyung Kim
2023-11-09 23:59 ` [PATCH 36/52] perf annotate-data: Support stack variables Namhyung Kim
2023-11-09 23:59 ` [PATCH 37/52] perf dwarf-aux: Check allowed DWARF Ops Namhyung Kim
2023-11-09 23:59 ` [PATCH 38/52] perf dwarf-aux: Add die_collect_vars() Namhyung Kim
2023-11-09 23:59 ` [PATCH 39/52] perf dwarf-aux: Handle type transfer for memory access Namhyung Kim
2023-11-09 23:59 ` [PATCH 40/52] perf annotate-data: Introduce struct data_loc_info Namhyung Kim
2023-11-10  0:00 ` [PATCH 41/52] perf map: Add map__objdump_2rip() Namhyung Kim
2023-11-10  0:00 ` [PATCH 42/52] perf annotate: Add annotate_get_basic_blocks() Namhyung Kim
2023-11-10  0:00 ` [PATCH 43/52] perf annotate-data: Maintain variable type info Namhyung Kim
2023-11-10  0:00 ` Namhyung Kim [this message]
2023-11-10  0:00 ` [PATCH 45/52] perf annotate-data: Handle global variable access Namhyung Kim
2023-11-10  0:00 ` [PATCH 46/52] perf annotate-data: Handle call instructions Namhyung Kim
2023-11-10  0:00 ` [PATCH 47/52] perf annotate-data: Implement instruction tracking Namhyung Kim
2023-11-10  0:00 ` [PATCH 48/52] perf annotate: Parse x86 segment register location Namhyung Kim
2023-11-10  0:00 ` [PATCH 49/52] perf annotate-data: Handle this-cpu variables in kernel Namhyung Kim
2023-11-10  0:00 ` [PATCH 50/52] perf annotate-data: Track instructions with a this-cpu variable Namhyung Kim
2023-11-10  0:00 ` [PATCH 51/52] perf annotate-data: Add stack canary type Namhyung Kim
2023-11-10  0:00 ` [PATCH 52/52] perf annotate-data: Add debug message Namhyung Kim
2023-11-10 12:05 ` [RFC 00/52] perf tools: Introduce data type profiling (v2) Arnaldo Carvalho de Melo
2023-11-11  2:27   ` 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=20231110000012.3538610-45-namhyung@kernel.org \
    --to=namhyung@kernel.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).