perf script: Fix brcntr output with --xed

brcntr in perf script brstack insn currently outputs

  $ perf record -j any,counter ...
  $ perf script -F +brcntr,+brstackinsn
  ...
              BC1s 3450809 5665912.127194:     100127
  cpu_core/cycles/:      7f0475d6cc89 handle_intel.constprop.0+0x2b
  (/usr/lib64/ld-linux-
  x86-64.so.2)
          intel_check_word.constprop.0+224:
          00007f0475d6ca7e        insn: 00 4b db                  br_cntr: # PRED 21 cycles [21]
  ...

This has two issues:
- The description says no event is a single dash, but that is not what is printed.
- The b in brcntr is ambigious with the hex numbers in insns, which
  breaks with --xed. It parses the b as another instruction byte and
merges the instruction with a missing b and no space:

  $ perf script -F +brstackinsn,+brcntr --xed
  ...
          00005618c6d683b5                        jnz 0x5618c6d683bdr_cntr:       # PRED 5 cycles [1396] 8.60 IPC

This patches fixes these two problems. It moves the brcntr output into
the "#" comment which also looks nicer and also fixes the no event case.

  $ perf script -F +brstackinsn,+brcntr --xed
  ...
          00005618c6d6624f                        jnz 0x5618c6d65fb7 # br_cntr: -  MISPRED 1 cycles [1398] 3.00 IPC

Since the old broken format has shipped for a few releases there is a
risk of breaking some existing parser, but since this is a obscure
feature I hope they're not too common and can adapt.

Signed-off-by: Andi Kleen <andi@firstfloor.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Andi Kleen 2026-02-17 17:40:56 -08:00 committed by Namhyung Kim
parent c5a244bf17
commit 0feca0b788

View File

@ -1271,11 +1271,11 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
if (PRINT_FIELD(BRCNTR)) {
struct evsel *pos = evsel__leader(evsel);
unsigned int i = 0, j, num, mask, width;
unsigned int i = 0, j, num, mask, width, numprinted = 0;
perf_env__find_br_cntr_info(evsel__env(evsel), NULL, &width);
mask = (1L << width) - 1;
printed += fprintf(fp, "br_cntr: ");
printed += fprintf(fp, "\t# br_cntr: ");
evlist__for_each_entry_from(evsel->evlist, pos) {
if (!(pos->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS))
continue;
@ -1283,16 +1283,20 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
break;
num = (br_cntr >> (i++ * width)) & mask;
numprinted += num;
if (!verbose) {
for (j = 0; j < num; j++)
printed += fprintf(fp, "%s", pos->abbr_name);
} else
printed += fprintf(fp, "%s %d ", pos->name, num);
}
printed += fprintf(fp, "\t");
if (numprinted == 0 && !verbose)
printed += fprintf(fp, "-");
printed += fprintf(fp, " ");
}
printed += fprintf(fp, "#%s%s%s%s",
printed += fprintf(fp, "%s%s%s%s%s",
!PRINT_FIELD(BRCNTR) ? "#" : "",
en->flags.predicted ? " PRED" : "",
en->flags.mispred ? " MISPRED" : "",
en->flags.in_tx ? " INTX" : "",