All of lore.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: Yanbo Zhao <yzhao62@ncsu.edu>, linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v2 3/3] perf annotate: Resolve C++ virtual function calls in x86 insn tracking
Date: Fri, 2 Oct 2026 15:56:46 -0700	[thread overview]
Message-ID: <asA2rgBbNuwh-zR-@google.com> (raw)
In-Reply-To: <20260930211112.B2A431F000FF@smtp.kernel.org>

On Wed, Sep 30, 2026 at 09:11:12PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [Medium] perf: cross-platform analysis broken by hardcoded host pointer size
> - [Medium] perf: vtable pointer load ignores multi-register index
> --
> 
> commit a71181b28893b295ef8ae1558faf7b1c66e3593b
> Author: Yanbo Zhao <yzhao62@ncsu.edu>
> 
> perf annotate: Resolve C++ virtual function calls in x86 insn tracking
> 
> This commit introduces tracking of C++ virtual function calls by resolving
> vtable pointer loads and virtual function calls through the vtable in x86
> instruction state tracking. It enhances update_insn_state_x86() to handle
> TSR_KIND_VTABLE_PTR and TSR_KIND_VFUNC_PTR register states.
> 
> > diff --git a/tools/perf/util/annotate-arch/annotate-x86.c b/tools/perf/util/annotate-arch/annotate-x86.c
> > index 1acf31a2c7597..d21192b74b6bf 100644
> > --- a/tools/perf/util/annotate-arch/annotate-x86.c
> > +++ b/tools/perf/util/annotate-arch/annotate-x86.c
> 
> [ ... ]
> 
> > @@ -216,6 +216,29 @@ static void invalidate_reg_state(struct type_state_reg *reg)
> >  	reg->copied_from = -1;
> >  }
> >  
> > +/*
> > + * Get the return type of the C++ virtual function at the @offset in the
> > + * vtable of @class_die.  Returns false if it's not found or the function
> > + * returns void.
> > + */
> > +static bool vtable_get_rettype(Dwarf_Die *class_die, int offset,
> > +			       Dwarf_Die *type_die)
> > +{
> > +	Dwarf_Die func_die;
> > +	int index;
> > +
> > +	if (offset < 0)
> > +		return false;
> > +
> > +	/* TODO: arch-dependent pointer size */
> > +	index = offset / sizeof(void *);
> 
> [Severity: Medium]
> Will dividing the target's vtable byte offset by the host's sizeof(void *)
> compute an incorrect slot index when analyzing data from an architecture
> with a different pointer size?
> 
> Relying on host execution details like sizeof(void *) breaks
> cross-platform analysis (e.g., analyzing 32-bit x86 perf.data on a
> 64-bit host).

I think this is fine for now as we also have other places assuming the
host pointer size.  We'll fix it later.

> 
> > +
> > +	if (die_find_virtual_func(class_die, index, &func_die) == NULL)
> > +		return false;
> > +
> > +	return die_get_real_type(&func_die, type_die) != NULL;
> > +}
> > +
> >  static void update_insn_state_x86(struct type_state *state,
> 
> [ ... ]
> 
> > @@ -622,13 +669,38 @@ static void update_insn_state_x86(struct type_state *state,
> >  			}
> >  			pr_debug_type_name(&tsr->type, tsr->kind);
> >  		}
> > +		/* Load a function pointer from the vtable (for 'call *%reg') */
> > +		else if (has_reg_type(state, sreg) && state->regs[sreg].ok &&
> > +			 state->regs[sreg].kind == TSR_KIND_VTABLE_PTR &&
> > +			 vtable_get_rettype(&state->regs[sreg].type, src->offset,
> > +					    &type_die)) {
> 
> [Severity: Medium]
> Does this query the wrong vtable slot by ignoring the index register when
> src->multi_regs is true?
> 
> If the operand is an indexed memory reference using multiple registers
> (e.g., mov 0x8(%rbx, %rcx, 8), %rax), src->offset contains only the
> static displacement part, not the dynamic index. Should this verify
> !src->multi_regs before querying the DWARF vtable with src->offset?

Multiple register is not handled well in the current code.  Dealing with
dynamic index would require more careful instruction tracking.

Anyway, it'd be safer to check !src->multi_regs here.

Thanks,
Namhyung

> 
> > +			tsr->type = type_die;
> > +			tsr->kind = TSR_KIND_VFUNC_PTR;
> > +			tsr->offset = 0;
> > +			tsr->ok = true;
> > +
> > +			pr_debug_dtp("mov [%x] %#x(reg%d) -> reg%d",
> > +				     insn_offset, src->offset, sreg, dst->reg1);
> > +			pr_debug_type_name(&tsr->type, tsr->kind);
> > +		}
> >  		/* And then dereference the pointer if it has one */
> 
> [ ... ]
> 
> > diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
> > index 8a9d3f2eec4dc..e9bf76cc28633 100644
> > --- a/tools/perf/util/annotate-data.c
> > +++ b/tools/perf/util/annotate-data.c
> 
> [ ... ]
> 
> > @@ -715,8 +723,11 @@ void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
> >  			    Dwarf_Die *type_die, int ptr_offset)
> >  {
> >  	Dwarf_Word size;
> > +	bool is_pointer = (kind == TSR_KIND_POINTER ||
> > +			   kind == TSR_KIND_VTABLE_PTR ||
> > +			   kind == TSR_KIND_VFUNC_PTR);
> >  
> > -	if (kind == TSR_KIND_POINTER) {
> > +	if (is_pointer) {
> >  		/* TODO: arch-dependent pointer size */
> >  		size = sizeof(void *);
> >  	}
> 
> [Severity: Medium]
> Like the vtable_get_rettype() issue above, will hardcoding the host's
> pointer size here corrupt the stack state tracking for the target
> architecture?
> 
> [ ... ]
> 
> > diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
> > index 5478c134e7e3b..5d96ee4c866b6 100644
> > --- a/tools/perf/util/disasm.c
> > +++ b/tools/perf/util/disasm.c
> 
> [ ... ]
> 
> > @@ -300,6 +300,11 @@ static int call__parse(const struct arch *arch, struct ins_operands *ops, struct
> >  	if (tok != NULL) {
> >  		endptr++;
> >  
> > +		/* Save the operand (without '*') to extract register and offset */
> > +		ops->target.raw = strdup(tok + 1);
> 
> [Severity: Low]
> This is a pre-existing issue, but this file calls strdup() without
> explicitly including <string.h>.
> 
> Can we add the explicit <string.h> include? The perf subsystem guide states
> that POSIX standard headers should be explicitly included to prevent musl
> compilation failures from missing implicit inclusions.
> 
> > +		if (ops->target.raw == NULL)
> > +			return -1;
> > +
> >  		/* Indirect call can use a non-rip register and offset: callq  *0x8(%rbx).
> >  		 * Do not parse such instruction.  */
> >  		if (strstr(endptr, "(%r") == NULL)
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260930210038.196928-1-yzhao62@ncsu.edu?part=3

  reply	other threads:[~2026-10-02 22:56 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 21:00 [PATCH v2 0/3] perf annotate: Data type profiling support for C++ classes and virtual calls Yanbo Zhao
2026-09-30 21:00 ` [PATCH v2 1/3] perf dwarf-aux: Add die_is_compound_type() to handle C++ class types Yanbo Zhao
2026-09-30 21:10   ` sashiko-bot
2026-10-01 18:14     ` Namhyung Kim
2026-10-02 16:34       ` Arnaldo Carvalho de Melo
2026-10-04 19:54         ` Yanbo Zhao
2026-09-30 21:00 ` [PATCH v2 2/3] perf dwarf-aux: Add C++ vtable helpers Yanbo Zhao
2026-09-30 21:10   ` sashiko-bot
2026-10-02 22:52     ` Namhyung Kim
2026-10-04 19:56       ` Yanbo Zhao
2026-09-30 21:00 ` [PATCH v2 3/3] perf annotate: Resolve C++ virtual function calls in x86 insn tracking Yanbo Zhao
2026-09-30 21:11   ` sashiko-bot
2026-10-02 22:56     ` Namhyung Kim [this message]
2026-10-04 19:57       ` Yanbo Zhao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=asA2rgBbNuwh-zR-@google.com \
    --to=namhyung@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=yzhao62@ncsu.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.