summaryrefslogtreecommitdiff
path: root/tools/objtool/trace.c
diff options
context:
space:
mode:
authorAlexandre Chartre <alexandre.chartre@oracle.com>2025-11-21 10:53:25 +0100
committerPeter Zijlstra <peterz@infradead.org>2025-11-21 15:30:11 +0100
commit350c7ab8577a32c101a097f4c072220d9ce64f3b (patch)
treea457d1edb33c417c5342e503f90d02314eabcf66 /tools/objtool/trace.c
parent9b580accac003767a461bf52d738ad1ab4e8ccfa (diff)
objtool: Improve tracing of alternative instructions
When tracing function validation, improve the reporting of alternative instruction by more clearly showing the different alternatives beginning and end. Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Josh Poimboeuf <jpoimboe@kernel.org> Link: https://patch.msgid.link/20251121095340.464045-16-alexandre.chartre@oracle.com
Diffstat (limited to 'tools/objtool/trace.c')
-rw-r--r--tools/objtool/trace.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/tools/objtool/trace.c b/tools/objtool/trace.c
index d70d47081e82..5dec44dab781 100644
--- a/tools/objtool/trace.c
+++ b/tools/objtool/trace.c
@@ -146,3 +146,58 @@ void trace_insn_state(struct instruction *insn, struct insn_state *sprev,
insn->trace = 1;
}
+
+void trace_alt_begin(struct instruction *orig_insn, struct alternative *alt,
+ char *alt_name)
+{
+ struct instruction *alt_insn;
+ char suffix[2];
+
+ alt_insn = alt->insn;
+
+ if (alt->type == ALT_TYPE_EX_TABLE) {
+ /*
+ * When there is an exception table then the instruction
+ * at the original location is executed but it can cause
+ * an exception. In that case, the execution will be
+ * redirected to the alternative instruction.
+ *
+ * The instruction at the original location can have
+ * instruction alternatives, so we just print the location
+ * of the instruction that can cause the exception and
+ * not the instruction itself.
+ */
+ TRACE_ALT_INFO_NOADDR(orig_insn, "/ ", "%s for instruction at 0x%lx <%s+0x%lx>",
+ alt_name,
+ orig_insn->offset, orig_insn->sym->name,
+ orig_insn->offset - orig_insn->sym->offset);
+ } else {
+ TRACE_ALT_INFO_NOADDR(orig_insn, "/ ", "%s", alt_name);
+ }
+
+ if (alt->type == ALT_TYPE_JUMP_TABLE) {
+ /*
+ * For a jump alternative, if the default instruction is
+ * a NOP then it is replaced with the jmp instruction,
+ * otherwise it is replaced with a NOP instruction.
+ */
+ trace_depth++;
+ if (orig_insn->type == INSN_NOP) {
+ suffix[0] = (orig_insn->len == 5) ? 'q' : '\0';
+ TRACE_ADDR(orig_insn, "jmp%-3s %lx <%s+0x%lx>", suffix,
+ alt_insn->offset, alt_insn->sym->name,
+ alt_insn->offset - alt_insn->sym->offset);
+ } else {
+ TRACE_ADDR(orig_insn, "nop%d", orig_insn->len);
+ trace_depth--;
+ }
+ }
+}
+
+void trace_alt_end(struct instruction *orig_insn, struct alternative *alt,
+ char *alt_name)
+{
+ if (alt->type == ALT_TYPE_JUMP_TABLE && orig_insn->type == INSN_NOP)
+ trace_depth--;
+ TRACE_ALT_INFO_NOADDR(orig_insn, "\\ ", "%s", alt_name);
+}