All of lore.kernel.org
 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 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.