perf annotate-data: Handle direct use of stack pointer without fbreg
authorNamhyung Kim <namhyung@kernel.org>
Sun, 26 Jan 2025 21:02:42 +0000 (13:02 -0800)
committerNamhyung Kim <namhyung@kernel.org>
Wed, 26 Feb 2025 21:42:49 +0000 (13:42 -0800)
Sometimes compiler generates code to use the stack pointer register
without frame pointer.  As we know RSP is the stack register on x86,
let's treat it as same as fbreg.  But the offset would be opposite
direction so update the debug message accordingly.

Reported-by: Blake Jones <blakejones@google.com>
Link: https://lore.kernel.org/r/20250126210242.1181225-1-namhyung@kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/arch/x86/annotate/instructions.c
tools/perf/util/annotate-data.c

index ae94b1f0b9cce1d3c0e4617abef106309b484e6c..c6d403eae7441168f666bc89cd54c46f934f3c9e 100644 (file)
@@ -410,7 +410,7 @@ static void update_insn_state_x86(struct type_state *state,
 
 retry:
                /* Check stack variables with offset */
-               if (sreg == fbreg) {
+               if (sreg == fbreg || sreg == state->stack_reg) {
                        struct type_state_stack *stack;
                        int offset = src->offset - fboff;
 
@@ -433,8 +433,13 @@ retry:
                                return;
                        }
 
-                       pr_debug_dtp("mov [%x] -%#x(stack) -> reg%d",
-                                    insn_offset, -offset, dst->reg1);
+                       if (sreg == fbreg) {
+                               pr_debug_dtp("mov [%x] -%#x(stack) -> reg%d",
+                                            insn_offset, -offset, dst->reg1);
+                       } else {
+                               pr_debug_dtp("mov [%x] %#x(reg%d) -> reg%d",
+                                            insn_offset, offset, sreg, dst->reg1);
+                       }
                        pr_debug_type_name(&tsr->type, tsr->kind);
                }
                /* And then dereference the pointer if it has one */
@@ -561,7 +566,7 @@ retry:
                        return;
 
                /* Check stack variables with offset */
-               if (dst->reg1 == fbreg) {
+               if (dst->reg1 == fbreg || dst->reg1 == state->stack_reg) {
                        struct type_state_stack *stack;
                        int offset = dst->offset - fboff;
 
@@ -584,8 +589,13 @@ retry:
                                                    &tsr->type);
                        }
 
-                       pr_debug_dtp("mov [%x] reg%d -> -%#x(stack)",
-                                    insn_offset, src->reg1, -offset);
+                       if (dst->reg1 == fbreg) {
+                               pr_debug_dtp("mov [%x] reg%d -> -%#x(stack)",
+                                            insn_offset, src->reg1, -offset);
+                       } else {
+                               pr_debug_dtp("mov [%x] reg%d -> %#x(reg%d)",
+                                            insn_offset, src->reg1, offset, dst->reg1);
+                       }
                        pr_debug_type_name(&tsr->type, tsr->kind);
                }
                /*
index 976abedca09ef5473afb2fd256452d536a42f3e4..eaf96fa80c830d0515fa35c04648f9adac6919cd 100644 (file)
@@ -830,7 +830,7 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo
                if (!dwarf_offdie(dloc->di->dbg, var->die_off, &mem_die))
                        continue;
 
-               if (var->reg == DWARF_REG_FB || var->reg == fbreg) {
+               if (var->reg == DWARF_REG_FB || var->reg == fbreg || var->reg == state->stack_reg) {
                        int offset = var->offset;
                        struct type_state_stack *stack;
 
@@ -845,8 +845,13 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo
                        findnew_stack_state(state, offset, TSR_KIND_TYPE,
                                            &mem_die);
 
-                       pr_debug_dtp("var [%"PRIx64"] -%#x(stack)",
-                                    insn_offset, -offset);
+                       if (var->reg == state->stack_reg) {
+                               pr_debug_dtp("var [%"PRIx64"] %#x(reg%d)",
+                                            insn_offset, offset, state->stack_reg);
+                       } else {
+                               pr_debug_dtp("var [%"PRIx64"] -%#x(stack)",
+                                            insn_offset, -offset);
+                       }
                        pr_debug_type_name(&mem_die, TSR_KIND_TYPE);
                } else if (has_reg_type(state, var->reg) && var->offset == 0) {
                        struct type_state_reg *reg;
@@ -1127,10 +1132,10 @@ again:
        }
 
 check_non_register:
-       if (reg == dloc->fbreg) {
+       if (reg == dloc->fbreg || reg == state->stack_reg) {
                struct type_state_stack *stack;
 
-               pr_debug_dtp("fbreg");
+               pr_debug_dtp("%s", reg == dloc->fbreg ? "fbreg" : "stack");
 
                stack = find_stack_state(state, dloc->type_offset);
                if (stack == NULL) {