perf annotate: Fix register usage in data type profiling
authorNamhyung Kim <namhyung@kernel.org>
Fri, 6 Feb 2026 01:27:43 +0000 (17:27 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 6 Feb 2026 21:18:52 +0000 (18:18 -0300)
On data type profiling, it tried to match register name with a partial
string.  For example, it allowed to match with "%rbp)" or "%rdi,8)".

But with recent change in the area, it doesn't match anymore and break
the data type profiling.

Let's pass the correct register name by removing the unwanted part.

Add arch__dwarf_regnum() to handle it in a single place.

Closes: 7d3n23li6drroxrdlpxn7ixehdeszkjdftah3zyngjl2qs22ef@yelcjv53v42o
Reported-by: Dmitry Dolgov <9erthalion6@gmail.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zecheng Li <zli94@ncsu.edu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/annotate.c

index 880b1bd..2e35229 100644 (file)
@@ -2447,6 +2447,29 @@ int annotate_check_args(void)
        return 0;
 }
 
+static int arch__dwarf_regnum(const struct arch *arch, const char *str)
+{
+       const char *p;
+       char *regname, *q;
+       int reg;
+
+       p = strchr(str, arch->objdump.register_char);
+       if (p == NULL)
+               return -1;
+
+       regname = strdup(p);
+       if (regname == NULL)
+               return -1;
+
+       q = strpbrk(regname, ",) ");
+       if (q)
+               *q = '\0';
+
+       reg = get_dwarf_regnum(regname, arch->id.e_machine, arch->id.e_flags);
+       free(regname);
+       return reg;
+}
+
 /*
  * Get register number and access offset from the given instruction.
  * It assumes AT&T x86 asm format like OFFSET(REG).  Maybe it needs
@@ -2457,7 +2480,6 @@ static int extract_reg_offset(const struct arch *arch, const char *str,
                              struct annotated_op_loc *op_loc)
 {
        char *p;
-       char *regname;
 
        if (arch->objdump.register_char == 0)
                return -1;
@@ -2482,31 +2504,14 @@ static int extract_reg_offset(const struct arch *arch, const char *str,
        }
 
        op_loc->offset = strtol(str, &p, 0);
-
-       p = strchr(p, arch->objdump.register_char);
-       if (p == NULL)
+       op_loc->reg1 = arch__dwarf_regnum(arch, p);
+       if (op_loc->reg1 == -1)
                return -1;
 
-       regname = strdup(p);
-       if (regname == NULL)
-               return -1;
-
-       op_loc->reg1 = get_dwarf_regnum(regname, arch->id.e_machine, arch->id.e_flags);
-       free(regname);
-
        /* Get the second register */
-       if (op_loc->multi_regs) {
-               p = strchr(p + 1, arch->objdump.register_char);
-               if (p == NULL)
-                       return -1;
-
-               regname = strdup(p);
-               if (regname == NULL)
-                       return -1;
+       if (op_loc->multi_regs)
+               op_loc->reg2 = arch__dwarf_regnum(arch, p + 1);
 
-               op_loc->reg2 = get_dwarf_regnum(regname, arch->id.e_machine, arch->id.e_flags);
-               free(regname);
-       }
        return 0;
 }
 
@@ -2585,7 +2590,8 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
                        op_loc->multi_regs = multi_regs;
                        extract_reg_offset(arch, insn_str, op_loc);
                } else {
-                       char *s, *p = NULL;
+                       const char *s = insn_str;
+                       char *p = NULL;
 
                        if (arch__is_x86(arch)) {
                                /* FIXME: Handle other segment registers */
@@ -2599,21 +2605,14 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
                                }
                        }
 
-                       s = strdup(insn_str);
-                       if (s == NULL)
-                               return -1;
-
                        if (*s == arch->objdump.register_char) {
-                               op_loc->reg1 = get_dwarf_regnum(s,
-                                                               arch->id.e_machine,
-                                                               arch->id.e_flags);
+                               op_loc->reg1 = arch__dwarf_regnum(arch, s);
                        }
                        else if (*s == arch->objdump.imm_char) {
                                op_loc->offset = strtol(s + 1, &p, 0);
                                if (p && p != s + 1)
                                        op_loc->imm = true;
                        }
-                       free(s);
                }
        }