[PATCH 1/2] tools/perf: Add field to annotation options to determine disassembler used
Venkat Rao Bagalkote
venkat88 at linux.ibm.com
Wed Mar 5 22:57:15 AEDT 2025
Applied this patch on next-20250227, and issue is fixed.
./perf -v
perf version 6.14.rc4.g2a432e11ebbb
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
./perf annotate --stdio 1> out 2>err
Please add below tag.
Tested-By: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
Regards,
Venkat.
On 04/03/25 9:11 pm, Athira Rajeev wrote:
> 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 at ibm.com>
> Signed-off-by: Athira Rajeev <atrajeev at linux.ibm.com>
> ---
> tools/perf/util/annotate.h | 1 +
> tools/perf/util/disasm.c | 22 +++++++++++++---------
> 2 files changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
> index 98db1b88daf4..30a344afd91a 100644
> --- a/tools/perf/util/annotate.h
> +++ b/tools/perf/util/annotate.h
> @@ -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;
> diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
> index 50c5c206b70e..a53e8c4e5bca 100644
> --- a/tools/perf/util/disasm.c
> +++ b/tools/perf/util/disasm.c
> @@ -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)
> @@ -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);
> @@ -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;
> @@ -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;
> @@ -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)
More information about the Linuxppc-dev
mailing list