]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf annotate: Save pointer offset in stack state
authorZecheng Li <zecheng@google.com>
Mon, 13 Oct 2025 18:16:01 +0000 (18:16 +0000)
committerNamhyung Kim <namhyung@kernel.org>
Tue, 21 Oct 2025 13:02:49 +0000 (06:02 -0700)
The tracked pointer offset was not being preserved in the stack state,
which could lead to incorrect type analysis. This change adds a
ptr_offset field to the type_state_stack struct and passes it to
set_stack_state and findnew_stack_state to ensure the offset is
preserved after the pointer is loaded from a stack location. It improves
the type annotation coverage and quality.

Signed-off-by: Zecheng Li <zecheng@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/arch/x86/annotate/instructions.c
tools/perf/util/annotate-data.c
tools/perf/util/annotate-data.h

index def7729a394c95b2a83ce7096a2913973df26266..0c87e42ca3dc241baba892db8d6c570c90e0fd7c 100644 (file)
@@ -541,7 +541,7 @@ retry:
                        } else if (!stack->compound) {
                                tsr->type = stack->type;
                                tsr->kind = stack->kind;
-                               tsr->offset = 0;
+                               tsr->offset = stack->ptr_offset;
                                tsr->ok = true;
                        } else if (die_get_member_type(&stack->type,
                                                       offset - stack->offset,
@@ -724,10 +724,10 @@ retry:
                                 */
                                if (!stack->compound)
                                        set_stack_state(stack, offset, tsr->kind,
-                                                       &tsr->type);
+                                                       &tsr->type, tsr->offset);
                        } else {
                                findnew_stack_state(state, offset, tsr->kind,
-                                                   &tsr->type);
+                                                   &tsr->type, tsr->offset);
                        }
 
                        if (dst->reg1 == fbreg) {
index 4204a7956ee5a85c5d6d54082fa136ecc7b8bd55..e183c6104d5940d58321a0d8aa5e5a02d940e04a 100644 (file)
@@ -577,7 +577,7 @@ struct type_state_stack *find_stack_state(struct type_state *state,
 }
 
 void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
-                           Dwarf_Die *type_die)
+                           Dwarf_Die *type_die, int ptr_offset)
 {
        int tag;
        Dwarf_Word size;
@@ -592,6 +592,7 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
        stack->type = *type_die;
        stack->size = size;
        stack->offset = offset;
+       stack->ptr_offset = ptr_offset;
        stack->kind = kind;
 
        if (kind == TSR_KIND_POINTER) {
@@ -614,18 +615,19 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
 
 struct type_state_stack *findnew_stack_state(struct type_state *state,
                                                    int offset, u8 kind,
-                                                   Dwarf_Die *type_die)
+                                                   Dwarf_Die *type_die,
+                                                   int ptr_offset)
 {
        struct type_state_stack *stack = find_stack_state(state, offset);
 
        if (stack) {
-               set_stack_state(stack, offset, kind, type_die);
+               set_stack_state(stack, offset, kind, type_die, ptr_offset);
                return stack;
        }
 
        stack = malloc(sizeof(*stack));
        if (stack) {
-               set_stack_state(stack, offset, kind, type_die);
+               set_stack_state(stack, offset, kind, type_die, ptr_offset);
                list_add(&stack->list, &state->stack_vars);
        }
        return stack;
@@ -895,7 +897,7 @@ static void update_var_state(struct type_state *state, struct data_loc_info *dlo
                                continue;
 
                        findnew_stack_state(state, offset, TSR_KIND_TYPE,
-                                           &mem_die);
+                                           &mem_die, /*ptr_offset=*/0);
 
                        if (var->reg == state->stack_reg) {
                                pr_debug_dtp("var [%"PRIx64"] %#x(reg%d)",
index 14655b76db65ae64d5354ab97258070d259a9a7c..869307c7f1300bce90a928ff72c8fa51c58777d6 100644 (file)
@@ -191,6 +191,8 @@ struct type_state_stack {
        struct list_head list;
        Dwarf_Die type;
        int offset;
+       /* pointer offset, saves tsr->offset on the stack state */
+       int ptr_offset;
        int size;
        bool compound;
        u8 kind;
@@ -247,9 +249,10 @@ int annotated_data_type__get_member_name(struct annotated_data_type *adt,
 bool has_reg_type(struct type_state *state, int reg);
 struct type_state_stack *findnew_stack_state(struct type_state *state,
                                                int offset, u8 kind,
-                                               Dwarf_Die *type_die);
+                                               Dwarf_Die *type_die,
+                                               int ptr_offset);
 void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
-                               Dwarf_Die *type_die);
+                               Dwarf_Die *type_die, int ptr_offset);
 struct type_state_stack *find_stack_state(struct type_state *state,
                                                int offset);
 bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc,