Skip to content

Commit 23322f8

Browse files
committed
perf annotate: Add annotation_options.disassembler_used
JIRA: https://issues.redhat.com/browse/RHEL-78197 upstream ======== commit dab8c32 Author: Athira Rajeev <atrajeev@linux.ibm.com> Date: Tue Mar 4 21:11:13 2025 +0530 description =========== 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> Signed-off-by: Michael Petlan <mpetlan@redhat.com>
1 parent 2a21cf4 commit 23322f8

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

tools/perf/util/annotate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct annotation_options {
5858
full_addr;
5959
u8 offset_level;
6060
u8 disassemblers[MAX_DISASSEMBLERS];
61+
u8 disassembler_used;
6162
int min_pcnt;
6263
int max_lines;
6364
int context;

tools/perf/util/disasm.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static int call__scnprintf(struct ins *ins, char *bf, size_t size,
4848

4949
static void ins__sort(struct arch *arch);
5050
static int disasm_line__parse(char *line, const char **namep, char **rawp);
51-
static int disasm_line__parse_powerpc(struct disasm_line *dl);
51+
static int disasm_line__parse_powerpc(struct disasm_line *dl, struct annotate_args *args);
5252
static char *expand_tabs(char *line, char **storage, size_t *storage_len);
5353

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

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

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

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

986-
if (objdump) {
986+
if (disasm)
987987
disasm_line__parse(name, namep, rawp);
988-
} else
988+
else
989989
*namep = "";
990990

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

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

10011001
return 0;
@@ -1054,7 +1054,7 @@ struct disasm_line *disasm_line__new(struct annotate_args *args)
10541054

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

22902290
switch (dis) {
22912291
case PERF_DISASM_LLVM:
2292+
args->options->disassembler_used = PERF_DISASM_LLVM;
22922293
err = symbol__disassemble_llvm(symfs_filename, sym, args);
22932294
break;
22942295
case PERF_DISASM_CAPSTONE:
2296+
args->options->disassembler_used = PERF_DISASM_CAPSTONE;
22952297
err = symbol__disassemble_capstone(symfs_filename, sym, args);
22962298
break;
22972299
case PERF_DISASM_OBJDUMP:
2300+
args->options->disassembler_used = PERF_DISASM_OBJDUMP;
22982301
err = symbol__disassemble_objdump(symfs_filename, sym, args);
22992302
break;
23002303
case PERF_DISASM_UNKNOWN: /* End of disassemblers. */
23012304
default:
2305+
args->options->disassembler_used = PERF_DISASM_UNKNOWN;
23022306
goto out_remove_tmp;
23032307
}
23042308
if (err == 0)

0 commit comments

Comments
 (0)