diff --git a/tools/perf/util/annotate-arch/annotate-x86.c b/tools/perf/util/annotate-arch/annotate-x86.c index 21729e153fa0..3a6ea7e978e0 100644 --- a/tools/perf/util/annotate-arch/annotate-x86.c +++ b/tools/perf/util/annotate-arch/annotate-x86.c @@ -753,15 +753,24 @@ static void update_insn_state_x86(struct type_state *state, } /* Case 3. register to memory transfers */ if (!src->mem_ref && dst->mem_ref) { - if (!has_reg_type(state, src->reg1) || - !state->regs[src->reg1].ok) - return; - /* Check stack variables with offset */ if (dst->reg1 == fbreg || dst->reg1 == state->stack_reg) { struct type_state_stack *stack; int offset = dst->offset - fboff; + if (!has_reg_type(state, src->reg1) || + !state->regs[src->reg1].ok) { + stack = find_stack_state(state, offset); + /* + * Preserve compound states when only a member + * is overwritten. + */ + if (stack && !stack->compound) + delete_stack_state(state, offset); + + return; + } + tsr = &state->regs[src->reg1]; stack = find_stack_state(state, offset); diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 9ed0780d6244..1d47db3a9dd9 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -761,6 +761,16 @@ struct type_state_stack *findnew_stack_state(struct type_state *state, return stack; } +void delete_stack_state(struct type_state *state, int offset) +{ + struct type_state_stack *stack = find_stack_state(state, offset); + + if (stack) { + list_del(&stack->list); + free(stack); + } +} + void invalidate_reg_state(struct type_state_reg *reg) { reg->kind = TSR_KIND_INVALID; diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index dccd56759cea..425d9ddfad41 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -268,6 +268,7 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, Dwarf_Die *type_die, int ptr_offset, u64 imm_value); struct type_state_stack *find_stack_state(struct type_state *state, int offset); +void delete_stack_state(struct type_state *state, int offset); void invalidate_reg_state(struct type_state_reg *reg); bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc, u64 ip, u64 var_addr, int *var_offset,