Commit aff95e0d authored by Alexandre Chartre's avatar Alexandre Chartre Committed by Peter Zijlstra
Browse files

objtool: Add wide output for disassembly



Add the --wide option to provide a wide output when disassembling.
With this option, the disassembly of alternatives is displayed
side-by-side instead of one above the other.

Signed-off-by: default avatarAlexandre Chartre <alexandre.chartre@oracle.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
Link: https://patch.msgid.link/20251121095340.464045-30-alexandre.chartre@oracle.com
parent 07d70b27
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ static const struct option check_options[] = {
	OPT_STRING(0,		 "trace", &opts.trace, "func", "trace function validation"),
	OPT_BOOLEAN('v',	 "verbose", &opts.verbose, "verbose warnings"),
	OPT_BOOLEAN(0,		 "werror", &opts.werror, "return error on warnings"),
	OPT_BOOLEAN(0,		 "wide", &opts.wide, "wide output"),

	OPT_END(),
};
+94 −1
Original line number Diff line number Diff line
@@ -856,6 +856,95 @@ static int disas_alt_default(struct disas_context *dctx, struct disas_alt *dalt)
	return 1;
}

/*
 * For each alternative, if there is an instruction at the specified
 * offset then print this instruction, otherwise print a blank entry.
 * The offset is an offset from the start of the alternative.
 *
 * Return the offset for the next instructions to print, or -1 if all
 * instructions have been printed.
 */
static int disas_alt_print_insn(struct disas_alt *dalts, int alt_count,
				int insn_count, int offset)
{
	struct disas_alt *dalt;
	int offset_next;
	char *str;
	int i, j;

	offset_next = -1;

	for (i = 0; i < alt_count; i++) {
		dalt = &dalts[i];
		j = dalt->insn_idx;
		if (j == -1) {
			printf("| %-*s ", dalt->width, "");
			continue;
		}

		if (dalt->insn[j].offset == offset) {
			str = dalt->insn[j].str;
			printf("| %-*s ", dalt->width, str ?: "");
			if (++j < insn_count) {
				dalt->insn_idx = j;
			} else {
				dalt->insn_idx = -1;
				continue;
			}
		} else {
			printf("| %-*s ", dalt->width, "");
		}

		if (dalt->insn[j].offset > 0 &&
		    (offset_next == -1 ||
		     (dalt->insn[j].offset < offset_next)))
			offset_next = dalt->insn[j].offset;
	}
	printf("\n");

	return offset_next;
}

/*
 * Print all alternatives side-by-side.
 */
static void disas_alt_print_wide(char *alt_name, struct disas_alt *dalts, int alt_count,
				 int insn_count)
{
	struct instruction *orig_insn;
	int offset_next;
	int offset;
	int i;

	orig_insn = dalts[0].orig_insn;

	/*
	 * Print an header with the name of each alternative.
	 */
	disas_print_info(stdout, orig_insn, -2, NULL);

	if (strlen(alt_name) > dalts[0].width)
		dalts[0].width = strlen(alt_name);
	printf("| %-*s ", dalts[0].width, alt_name);

	for (i = 1; i < alt_count; i++)
		printf("| %-*s ", dalts[i].width, dalts[i].name);

	printf("\n");

	/*
	 * Print instructions for each alternative.
	 */
	offset_next = 0;
	do {
		offset = offset_next;
		disas_print(stdout, orig_insn->sec, orig_insn->offset + offset,
			    -2, NULL);
		offset_next = disas_alt_print_insn(dalts, alt_count, insn_count,
						   offset);
	} while (offset_next > offset);
}

/*
 * Print all alternatives one above the other.
 */
@@ -993,6 +1082,10 @@ static void *disas_alt(struct disas_context *dctx,
	/*
	 * Print default and non-default alternatives.
	 */

	if (opts.wide)
		disas_alt_print_wide(alt_name, dalts, alt_count, insn_count);
	else
		disas_alt_print_compact(alt_name, dalts, alt_count, insn_count);

	last_insn = orig_insn->alt_group ? orig_insn->alt_group->last_insn :
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct opts {
	const char *trace;
	bool verbose;
	bool werror;
	bool wide;
};

extern struct opts opts;