Skip to content

Commit

Permalink
perf annotate: Add annotation_options.disassembler_used
Browse files Browse the repository at this point in the history
When doing "perf annotate", perf tool provides option to
use specific disassembler like llvm/objdump/capstone. The
order picked is to use llvm first and if that fails fallback
to objdump ie to use PERF_DISASM_LLVM, PERF_DISASM_CAPSTONE
and PERF_DISASM_OBJDUMP

In powerpc, when using "data type" sort keys, first preferred
approach is to read the raw instruction from the DSO. In objdump
is specified in "--objdump" option, it picks the symbol disassemble
using objdump. Currently disasm_line__parse_powerpc() function
uses length of the "line" to determine if objdump is used.
But there are few cases, where if objdump doesn't recognise the
instruction, the disassembled string will be empty.

Example:

     134cdc:	c4 05 82 41 	beq     1352a0 <getcwd+0x6e0>
     134ce0:	ac 00 8e 40 	bne     cr3,134d8c <getcwd+0x1cc>
     134ce4:	0f 00 10 04 	pld     r9,1028308
====>134ce8:	d4 b0 20 e5
     134cec:	16 00 40 39 	li      r10,22
     134cf0:	48 01 21 ea 	ld      r17,328(r1)

So depending on length of line will give bad results.

Add a new filed to annotation options structure,
"struct annotation_options" to save the disassembler used.
Use this info to determine if disassembly is done while
parsing the disasm line.

Reported-by: Tejas Manhas <Tejas.Manhas1@ibm.com>
Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com>
Tested-By: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Link: https://lore.kernel.org/r/20250304154114.62093-1-atrajeev@linux.ibm.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
  • Loading branch information
Athira Rajeev authored and Namhyung Kim committed Mar 7, 2025
1 parent b0920ab commit dab8c32
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
1 change: 1 addition & 0 deletions tools/perf/util/annotate.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct annotation_options {
full_addr;
u8 offset_level;
u8 disassemblers[MAX_DISASSEMBLERS];
u8 disassembler_used;
int min_pcnt;
int max_lines;
int context;
Expand Down
22 changes: 13 additions & 9 deletions tools/perf/util/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static int call__scnprintf(struct ins *ins, char *bf, size_t size,

static void ins__sort(struct arch *arch);
static int disasm_line__parse(char *line, const char **namep, char **rawp);
static int disasm_line__parse_powerpc(struct disasm_line *dl);
static int disasm_line__parse_powerpc(struct disasm_line *dl, struct annotate_args *args);
static char *expand_tabs(char *line, char **storage, size_t *storage_len);

static __attribute__((constructor)) void symbol__init_regexpr(void)
Expand Down Expand Up @@ -968,24 +968,24 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
#define PPC_OP(op) (((op) >> 26) & 0x3F)
#define RAW_BYTES 11

static int disasm_line__parse_powerpc(struct disasm_line *dl)
static int disasm_line__parse_powerpc(struct disasm_line *dl, struct annotate_args *args)
{
char *line = dl->al.line;
const char **namep = &dl->ins.name;
char **rawp = &dl->ops.raw;
char *tmp_raw_insn, *name_raw_insn = skip_spaces(line);
char *name = skip_spaces(name_raw_insn + RAW_BYTES);
int objdump = 0;
int disasm = 0;

if (strlen(line) > RAW_BYTES)
objdump = 1;
if (args->options->disassembler_used)
disasm = 1;

if (name_raw_insn[0] == '\0')
return -1;

if (objdump) {
if (disasm)
disasm_line__parse(name, namep, rawp);
} else
else
*namep = "";

tmp_raw_insn = strndup(name_raw_insn, 11);
Expand All @@ -995,7 +995,7 @@ static int disasm_line__parse_powerpc(struct disasm_line *dl)
remove_spaces(tmp_raw_insn);

sscanf(tmp_raw_insn, "%x", &dl->raw.raw_insn);
if (objdump)
if (disasm)
dl->raw.raw_insn = be32_to_cpu(dl->raw.raw_insn);

return 0;
Expand Down Expand Up @@ -1054,7 +1054,7 @@ struct disasm_line *disasm_line__new(struct annotate_args *args)

if (args->offset != -1) {
if (arch__is(args->arch, "powerpc")) {
if (disasm_line__parse_powerpc(dl) < 0)
if (disasm_line__parse_powerpc(dl, args) < 0)
goto out_free_line;
} else if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;
Expand Down Expand Up @@ -2289,16 +2289,20 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)

switch (dis) {
case PERF_DISASM_LLVM:
args->options->disassembler_used = PERF_DISASM_LLVM;
err = symbol__disassemble_llvm(symfs_filename, sym, args);
break;
case PERF_DISASM_CAPSTONE:
args->options->disassembler_used = PERF_DISASM_CAPSTONE;
err = symbol__disassemble_capstone(symfs_filename, sym, args);
break;
case PERF_DISASM_OBJDUMP:
args->options->disassembler_used = PERF_DISASM_OBJDUMP;
err = symbol__disassemble_objdump(symfs_filename, sym, args);
break;
case PERF_DISASM_UNKNOWN: /* End of disassemblers. */
default:
args->options->disassembler_used = PERF_DISASM_UNKNOWN;
goto out_remove_tmp;
}
if (err == 0)
Expand Down

0 comments on commit dab8c32

Please sign in to comment.