Linux Perf Users
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Yanbo Zhao <yzhao62@ncsu.edu>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Ian Rogers <irogers@google.com>,
	Kan Liang <kan.liang@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	James Clark <james.clark@linaro.org>, Zecheng Li <zli94@ncsu.edu>,
	Xu Liu <xliuprof@google.com>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 0/3] perf annotate: Data type profiling support for C++ classes and virtual calls
Date: Wed, 7 Oct 2026 09:02:38 -0700	[thread overview]
Message-ID: <asZtHmjHDA--hXVM@google.com> (raw)
In-Reply-To: <20261005201010.36493-1-yzhao62@ncsu.edu>

Hello Yanbo,

On Mon, Oct 05, 2026 at 04:10:07PM -0400, Yanbo Zhao wrote:
> Hello,
> 
> Data type profiling currently only understands C struct/union types.
> For C++ workloads, member accesses through base class subobjects
> cannot be resolved, and virtual function calls (indirect calls through
> the vtable) lose the return type of the callee: the register holding
> the returned value becomes unknown, which matters when it's used
> directly to access memory like 'p->next()->val' where no DWARF
> variable describes the temporary.
> 
> This series extends data type profiling to C++:
> 
> Patch 1 introduces die_is_compound_type() covering DW_TAG_class_type
> as well and accepts DW_TAG_inheritance in the offset-based member
> lookup so that it descends into base class subobjects.  It handles
> empty base classes, members placed in the tail padding of a base and
> virtual base classes.
> 
> Patch 2 adds the DWARF helpers for virtual calls: the vtable slot index
> of a virtual function, the virtual function at a slot of a class
> (following the primary base class chain), and the class of the vtable
> pointer at an offset of a type.
> 
> Patch 3 tracks the vtable pointer and the virtual function pointer
> loaded from it in the x86 instruction tracking, and resolves the
> return type of 'call *N(%reg)' and 'call *%reg' through them.
> 
> Tested on x86-64 with GCC 15 (-O2 -g) using small programs covering
> single/multiple inheritance, empty base optimization, tail padding
> reuse, virtual inheritance, direct calls through the vtable and the
> speculatively devirtualized form.  In all cases the access to the
> returned pointer after a virtual call is annotated with the right type
> and member, e.g.:
> 
>   movq    (%rbp), %rax           # data-type: struct Node +0 (_vptr.Node)
>   movq    (%rax), %rax
>   cmpq    %r14, %rax
>   je      0x1240
>   movq    %rbp, %rdi
>   callq   *%rax
>   addq    8(%rax), %r12          # data-type: struct Node +0x8 (val)
> 
> The existing results for C code are unchanged and the added cost on
> the common path (a pointer dereference) is a tag check on the resolved
> member type.

Thanks for working on this!

Reviewed-by: Namhyung Kim <namhyung@kernel.org>

Thanks,
Namhyung

> 
> Changes in v3:
> - Rebased onto the current perf-tools-next.
> 
> Patch 1:
> - No change.
> 
> Patch 2:
> - Check the value of DW_AT_virtuality instead of its presence (Sashiko,
>   Namhyung).
> - Bound the base class walks in die_find_virtual_func() and
>   die_get_vptr_class() with MAX_TYPE_CHASE (Sashiko, Namhyung).
> 
> Patch 3:
> - Check !src->multi_regs when loading a function pointer from the
>   vtable and when marking a register as the vtable pointer (Sashiko,
>   Namhyung).
> - Set ops->target.multi_regs in call__parse() so that an indirect call
>   with an index register is not resolved by the displacement alone.
> 
> The recursion depth limit in __die_find_member_offset_cb() reported
> for the patch 1 will be sent as a separate patch on top of this series
> as discussed.
> 
> Changes in v2:
> 
> Patch 1:
> - Explain DW_TAG_inheritance with an example DWARF in the commit
>   message (Namhyung).
> - Skip virtual base classes whose location is a runtime expression
>   instead of falling back to offset 0 (Sashiko).
> - Match a base class in the offset lookup only if it actually has a
>   member at the offset, to handle empty base optimization and tail
>   padding reuse where a member of the derived class shares the offset
>   with the base (Sashiko).
> - Keep looking at the next sibling in fill_member_name() when an
>   anonymous child (base class) has nothing at the offset.
> 
> Patch 2:
> - Drop the non-existent DW_AT_vtable_elem_index and the DW_LANG_*
>   fallback macros (Namhyung).
> - Drop cu_get_language(), cu_is_cplusplus(), die_get_base_class(),
>   die_get_parent() and die_find_member_by_offset() which are not
>   needed anymore (Namhyung).
> - Document that die_get_vtable_index() returns the vtable slot index
>   and that GCC and Clang both emit the index as DW_OP_constu
>   (Namhyung, Sashiko).
> - Fix die_find_virtual_func() to return the function DIE instead of
>   the DW_TAG_inheritance DIE when found in a base class (Sashiko).
> - Follow only the primary base class chain in die_find_virtual_func()
>   since non-primary bases have their own secondary vtables, and skip
>   an empty base at offset 0 which is not the primary base.
> - Add die_get_vptr_class() to find the class of the vtable pointer
>   through base class subobjects, and die_is_vtbl_ptr_type() to
>   identify the vtable pointer by its type ('__vtbl_ptr_type').
> 
> Patch 3:
> - Remove the receiver ('this' pointer) register update after the call
>   which was dead code and not needed, and the arg0_reg field (Sashiko,
>   Namhyung).  The 'this' pointer lives in a callee-saved register or
>   on the stack across the call and DWARF location lists cover it.
> - Handle 'call *%reg' by tracking the function pointer loaded from the
>   vtable as TSR_KIND_VFUNC_PTR with its return type (Sashiko).  This
>   form is common due to speculative devirtualization by GCC.
> - Strip the leading '*' of an indirect call operand in call__parse()
>   instead of extract_reg_offset() so that both forms are parsed.
> - Ignore void virtual functions instead of aborting (Namhyung).
> - Keep the existing pointer dereference branch and its fall-through
>   intact; the vtable pointer is detected from the resolved member
>   type there instead of a separate lookup before it.
> - Treat the new register kinds as pointers when saved to the stack.
> 
> v2: https://lore.kernel.org/r/20260930210038.196928-1-yzhao62@ncsu.edu
> v1: https://lore.kernel.org/r/20260821050207.4517-1-yzhao62@ncsu.edu
> 
> Thanks,
> Yanbo
> 
> Yanbo Zhao (3):
>   perf dwarf-aux: Add die_is_compound_type() to handle C++ class types
>   perf dwarf-aux: Add C++ vtable helpers
>   perf annotate: Resolve C++ virtual function calls in x86 insn tracking
> 
>  tools/perf/util/annotate-arch/annotate-x86.c |  77 ++++-
>  tools/perf/util/annotate-data.c              |  61 ++--
>  tools/perf/util/annotate-data.h              |   4 +
>  tools/perf/util/disasm.c                     |   7 +
>  tools/perf/util/dwarf-aux.c                  | 282 ++++++++++++++++++-
>  tools/perf/util/dwarf-aux.h                  |  21 ++
>  6 files changed, 426 insertions(+), 26 deletions(-)
> 
> base-commit: 1dc462fc214907671600172280c2e79ef9fe6fcf
> -- 
> 2.53.0
> 

  parent reply	other threads:[~2026-10-07 16:02 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 20:10 [PATCH v3 0/3] perf annotate: Data type profiling support for C++ classes and virtual calls Yanbo Zhao
2026-10-05 20:10 ` [PATCH v3 1/3] perf dwarf-aux: Add die_is_compound_type() to handle C++ class types Yanbo Zhao
2026-10-05 20:16   ` sashiko-bot
2026-10-05 20:10 ` [PATCH v3 2/3] perf dwarf-aux: Add C++ vtable helpers Yanbo Zhao
2026-10-05 20:17   ` sashiko-bot
2026-10-05 20:10 ` [PATCH v3 3/3] perf annotate: Resolve C++ virtual function calls in x86 insn tracking Yanbo Zhao
2026-10-05 20:18   ` sashiko-bot
2026-10-07 16:02 ` Namhyung Kim [this message]
2026-10-07 16:13   ` [PATCH v3 0/3] perf annotate: Data type profiling support for C++ classes and virtual calls 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=asZtHmjHDA--hXVM@google.com \
    --to=namhyung@kernel.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=xliuprof@google.com \
    --cc=yzhao62@ncsu.edu \
    --cc=zli94@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox