summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/objtool/disas.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/tools/objtool/disas.c b/tools/objtool/disas.c
index ae69bef2eb37..6083a64f6ae4 100644
--- a/tools/objtool/disas.c
+++ b/tools/objtool/disas.c
@@ -47,7 +47,11 @@ 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 */
+ struct {
+ char *str; /* instruction string */
+ int offset; /* instruction offset */
+ } insn[DISAS_ALT_INSN_MAX]; /* alternative instructions */
+ int insn_idx; /* index of the next instruction to print */
};
#define DALT_DEFAULT(dalt) (!(dalt)->alt)
@@ -361,10 +365,9 @@ char *disas_result(struct disas_context *dctx)
disas_print_insn(stdout, dctx, insn, depth, "\n")
/*
- * Print a message in the instruction flow. If insn is not NULL then
- * the instruction address is printed in addition of the message,
- * otherwise only the message is printed. In all cases, the instruction
- * itself is not printed.
+ * Print a message in the instruction flow. If sec is not NULL then the
+ * address at the section offset is printed in addition of the message,
+ * otherwise only the message is printed.
*/
static int disas_vprint(FILE *stream, struct section *sec, unsigned long offset,
int depth, const char *format, va_list ap)
@@ -607,6 +610,7 @@ static int disas_alt_init(struct disas_alt *dalt,
{
dalt->orig_insn = orig_insn;
dalt->alt = alt;
+ dalt->insn_idx = 0;
dalt->name = alt ? disas_alt_name(alt) : strdup("DEFAULT");
if (!dalt->name)
return -1;
@@ -615,7 +619,8 @@ 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)
+static int disas_alt_add_insn(struct disas_alt *dalt, int index, char *insn_str,
+ int offset)
{
int len;
@@ -626,7 +631,8 @@ static int disas_alt_add_insn(struct disas_alt *dalt, int index, char *insn_str)
}
len = strlen(insn_str);
- dalt->insn[index] = insn_str;
+ dalt->insn[index].str = insn_str;
+ dalt->insn[index].offset = offset;
if (len > dalt->width)
dalt->width = len;
@@ -641,12 +647,14 @@ static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
{
struct objtool_file *file;
struct instruction *insn;
+ int offset;
char *str;
int count;
int err;
file = dctx->file;
count = 0;
+ offset = 0;
alt_for_each_insn(file, DALT_GROUP(dalt), insn) {
@@ -655,9 +663,10 @@ static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
if (!str)
return -1;
- err = disas_alt_add_insn(dalt, count, str);
+ err = disas_alt_add_insn(dalt, count, str, offset);
if (err)
break;
+ offset += insn->len;
count++;
}
@@ -685,7 +694,7 @@ static int disas_alt_default(struct disas_context *dctx, struct disas_alt *dalt)
str = strdup(disas_result(dctx));
if (!str)
return -1;
- err = disas_alt_add_insn(dalt, 0, str);
+ err = disas_alt_add_insn(dalt, 0, str, 0);
if (err)
return -1;
@@ -710,9 +719,11 @@ static void disas_alt_print_compact(char *alt_name, struct disas_alt *dalts,
for (i = 0; i < alt_count; i++) {
printf("%*s= %s\n", len, "", dalts[i].name);
for (j = 0; j < insn_count; j++) {
- if (!dalts[i].insn[j])
+ if (!dalts[i].insn[j].str)
break;
- printf("%*s| %s\n", len, "", dalts[i].insn[j]);
+ disas_print(stdout, orig_insn->sec,
+ orig_insn->offset + dalts[i].insn[j].offset, 0,
+ "| %s\n", dalts[i].insn[j].str);
}
printf("%*s|\n", len, "");
}
@@ -811,7 +822,7 @@ done:
for (i = 0; i < alt_count; i++) {
free(dalts[i].name);
for (j = 0; j < insn_count; j++)
- free(dalts[i].insn[j]);
+ free(dalts[i].insn[j].str);
}
free(alt_name);