From: Alexandre Chartre <alexandre.chartre@oracle.com>
To: linux-kernel@vger.kernel.org, mingo@kernel.org,
jpoimboe@kernel.org, peterz@infradead.org
Cc: alexandre.chartre@oracle.com
Subject: [PATCH v3 18/28] objtool: Disassemble group alternatives
Date: Wed, 12 Nov 2025 17:03:05 +0100 [thread overview]
Message-ID: <20251112160315.2207947-19-alexandre.chartre@oracle.com> (raw)
In-Reply-To: <20251112160315.2207947-1-alexandre.chartre@oracle.com>
When using the --disas option, disassemble all group alternatives.
Jump tables and exception tables (which are handled as alternatives)
are not disassembled at the moment.
Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
---
tools/objtool/disas.c | 146 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 138 insertions(+), 8 deletions(-)
diff --git a/tools/objtool/disas.c b/tools/objtool/disas.c
index 43dc51f614f1c..28c77762b1bd5 100644
--- a/tools/objtool/disas.c
+++ b/tools/objtool/disas.c
@@ -47,8 +47,14 @@ struct disas_alt {
struct alternative *alt; /* alternative or NULL if default code */
char *name; /* name for this alternative */
int width; /* formatting width */
+ char *insn[DISAS_ALT_INSN_MAX]; /* alternative instructions */
};
+#define DALT_DEFAULT(dalt) (!(dalt)->alt)
+#define DALT_INSN(dalt) (DALT_DEFAULT(dalt) ? (dalt)->orig_insn : (dalt)->alt->insn)
+#define DALT_GROUP(dalt) (DALT_INSN(dalt)->alt_group)
+#define DALT_ALTID(dalt) ((dalt)->orig_insn->offset)
+
/*
* Wrapper around asprintf() to allocate and format a string.
* Return the allocated string or NULL on error.
@@ -470,6 +476,21 @@ size_t disas_insn(struct disas_context *dctx, struct instruction *insn)
return disasm(insn->offset, &dctx->info);
}
+static struct instruction *next_insn_same_alt(struct objtool_file *file,
+ struct alt_group *alt_grp,
+ struct instruction *insn)
+{
+ if (alt_grp->last_insn == insn || alt_grp->nop == insn)
+ return NULL;
+
+ return next_insn_same_sec(file, insn);
+}
+
+#define alt_for_each_insn(file, alt_grp, insn) \
+ for (insn = alt_grp->first_insn; \
+ insn; \
+ insn = next_insn_same_alt(file, alt_grp, insn))
+
/*
* Initialize an alternative. The default alternative should be initialized
* with alt=NULL.
@@ -490,6 +511,83 @@ static int disas_alt_init(struct disas_alt *dalt,
return 0;
}
+static int disas_alt_add_insn(struct disas_alt *dalt, int index, char *insn_str)
+{
+ int len;
+
+ if (index >= DISAS_ALT_INSN_MAX) {
+ WARN("Alternative %lx.%s has more instructions than supported",
+ DALT_ALTID(dalt), dalt->name);
+ return -1;
+ }
+
+ len = strlen(insn_str);
+ dalt->insn[index] = insn_str;
+ if (len > dalt->width)
+ dalt->width = len;
+
+ return 0;
+}
+
+/*
+ * Disassemble an alternative and store instructions in the disas_alt
+ * structure. Return the number of instructions in the alternative.
+ */
+static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
+{
+ struct objtool_file *file;
+ struct instruction *insn;
+ char *str;
+ int count;
+ int err;
+
+ file = dctx->file;
+ count = 0;
+
+ alt_for_each_insn(file, DALT_GROUP(dalt), insn) {
+
+ disas_insn(dctx, insn);
+ str = strdup(disas_result(dctx));
+ if (!str)
+ return -1;
+
+ err = disas_alt_add_insn(dalt, count, str);
+ if (err)
+ break;
+ count++;
+ }
+
+ return count;
+}
+
+/*
+ * Disassemble the default alternative.
+ */
+static int disas_alt_default(struct disas_context *dctx, struct disas_alt *dalt)
+{
+ char *str;
+ int err;
+
+ if (DALT_GROUP(dalt))
+ return disas_alt_group(dctx, dalt);
+
+ /*
+ * Default alternative with no alt_group: this is the default
+ * code associated with either a jump table or an exception
+ * table and no other instruction alternatives. In that case
+ * the default alternative is made of a single instruction.
+ */
+ disas_insn(dctx, dalt->orig_insn);
+ str = strdup(disas_result(dctx));
+ if (!str)
+ return -1;
+ err = disas_alt_add_insn(dalt, 0, str);
+ if (err)
+ return -1;
+
+ return 1;
+}
+
/*
* Disassemble an alternative.
*
@@ -502,22 +600,30 @@ static void *disas_alt(struct disas_context *dctx,
{
struct disas_alt alts[DISAS_ALT_MAX] = { 0 };
struct alternative *alt;
+ struct disas_alt *dalt;
+ int insn_count;
int alt_count;
int alt_id;
- int i;
+ char *str;
+ int count;
+ int i, j;
int err;
alt_id = orig_insn->offset;
/*
- * Initialize the default alternative.
+ * Initialize and disassemble the default alternative.
*/
err = disas_alt_init(&alts[0], orig_insn, NULL, 0);
if (err)
goto error;
+ insn_count = disas_alt_default(dctx, &alts[0]);
+ if (insn_count < 0)
+ goto error;
+
/*
- * Initialize all other alternatives.
+ * Initialize and disassemble all other alternatives.
*/
i = 1;
for (alt = orig_insn->alts; alt; alt = alt->next) {
@@ -526,10 +632,25 @@ static void *disas_alt(struct disas_context *dctx,
orig_insn->offset);
break;
}
- err = disas_alt_init(&alts[i], orig_insn, alt, i);
+ dalt = &alts[i];
+ err = disas_alt_init(dalt, orig_insn, alt, i);
if (err)
goto error;
+ /*
+ * Only group alternatives are supported at the moment.
+ */
+ switch (dalt->alt->type) {
+ case ALT_TYPE_INSTRUCTIONS:
+ count = disas_alt_group(dctx, dalt);
+ break;
+ default:
+ count = 0;
+ }
+ if (count < 0)
+ goto error;
+
+ insn_count = count > insn_count ? count : insn_count;
i++;
}
alt_count = i;
@@ -545,11 +666,20 @@ static void *disas_alt(struct disas_context *dctx,
printf("\n");
/*
- * Currently we are not disassembling any alternative but just
- * printing alternative names. Return NULL to have disas_func()
- * resume the disassembly with the default alternative.
+ * Print instructions for each alternative.
*/
- return NULL;
+ for (j = 0; j < insn_count; j++) {
+ disas_print_info(stdout, NULL, -2, NULL);
+ for (i = 0; i < alt_count; i++) {
+ dalt = &alts[i];
+ str = dalt->insn[j];
+ printf("| %-*s ", dalt->width, str ?: "");
+ free(str);
+ }
+ printf("\n");
+ }
+
+ return orig_insn->alt_group ? orig_insn->alt_group->last_insn : orig_insn;
error:
WARN("Failed to disassemble alternative %x", alt_id);
--
2.43.5
next prev parent reply other threads:[~2025-11-12 16:04 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-12 16:02 [PATCH v3 00/28] objtool: Function validation tracing Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 01/28] objtool: Move disassembly functions to a separated file Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 02/28] objtool: Create disassembly context Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 03/28] objtool: Disassemble code with libopcodes instead of running objdump Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 04/28] tool build: Remove annoying newline in build output Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 05/28] objtool: Print symbol during disassembly Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 06/28] objtool: Store instruction disassembly result Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 07/28] objtool: Disassemble instruction on warning or backtrace Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 08/28] objtool: Extract code to validate instruction from the validate branch loop Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 09/28] objtool: Record symbol name max length Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 10/28] objtool: Add option to trace function validation Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 11/28] objtool: Trace instruction state changes during " Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 12/28] objtool: Improve register reporting " Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 13/28] objtool: Identify the different types of alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 14/28] objtool: Improve tracing of alternative instructions Alexandre Chartre
2025-11-13 5:14 ` kernel test robot
2025-11-12 16:03 ` [PATCH v3 15/28] objtool: Do not validate IBT for .return_sites and .call_sites Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 16/28] objtool: Add the --disas=<function-pattern> action Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 17/28] objtool: Print headers for alternatives Alexandre Chartre
2025-11-12 16:03 ` Alexandre Chartre [this message]
2025-11-12 16:03 ` [PATCH v3 19/28] objtool: Print addresses with alternative instructions Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 20/28] objtool: Disassemble exception table alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 21/28] objtool: Disassemble jump " Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 22/28] objtool: Fix address references in alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 23/28] objtool: Provide access to feature and flags of group alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 24/28] objtool: Function to get the name of a CPU feature Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 25/28] objtool: Improve naming of group alternatives Alexandre Chartre
2025-11-13 5:15 ` kernel test robot
2025-11-12 16:03 ` [PATCH v3 26/28] objtool: Get the destination name of a PV call Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 27/28] objtool: Improve the disassembly of the pv_ops call Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 28/28] objtool: Print single line for alternatives with one instruction Alexandre Chartre
2025-11-13 9:21 ` [PATCH v3 00/28] objtool: Function validation tracing Alexandre Chartre
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=20251112160315.2207947-19-alexandre.chartre@oracle.com \
--to=alexandre.chartre@oracle.com \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.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
all inboxes | Powered by JetHome®