From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Alan Maguire <alan.maguire@oracle.com>
Cc: Jiri Olsa <jolsa@kernel.org>,
Clark Williams <williams@redhat.com>,
dwarves@vger.kernel.org, bpf@vger.kernel.org,
Andrii Nakryiko <andrii@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Mark Wieelard <mjw@redhat.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 06/12] dwarf_loader: Allow forcing the merge of CUs for solving inter CU tag references
Date: Fri, 31 Jul 2026 16:30:54 -0300 [thread overview]
Message-ID: <20260731193102.110693-7-acme@kernel.org> (raw)
In-Reply-To: <20260731193102.110693-1-acme@kernel.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
The Linux perf tool now includes some Rust code that then gets linked
into perf and comes with its DWARF that has tags referencing tags in
different CUs, and as the current DWARF loading algorithm uses
parallelization and recodes the big DWARF types (DWARF_off, usually
64-bit) into smaller ones as a step into converting to CTF (initially)
and later BTF, the resolution fails.
There is a case where this inter CU happens, LTO builds, and so there is
an alternative algorithm for that case, that serializes DWARF CU loading
and merges all the CUs into just one meta/mega-CU, which then has all
the types and thus doesn't have a problem with inter CU references, as
the recoding into smaller ids is done only after all CUs are loaded.
So while we don't refactor the loading in a way that allows for inter CU
while allowing parallelization, maybe by doing the recoding just at the
end of parallel loading, add minimal code to force this CU merging for
experimentation in such cases, getting back the regression test
prettify_perf.data.sh to work, making it force CU merging.
$ pahole ~/bin/perf > unmerged.txt
<Suppress lots of warnings when recoding DWARF types.>
$ pahole --features=force_cu_merging ~/bin/perf > merged.txt
$
With the current set of Rust types that are representable with the
pahole data structures and then pretty printed as if they were C we see
12 differences:
$ diff -u unmerged.txt merged.txt | grep ^@@ | wc -l
12
$ diff -u unmerged.txt merged.txt | wc -l
198
Of this kind, due to some types not being resolved as tags are
referencing tags in other CUs.
$ diff -u unmerged.txt merged.txt | head
--- unmerged.txt 2026-03-23 17:56:54.971785023 -0300
+++ merged.txt 2026-03-23 17:56:59.826872178 -0300
@@ -9643,10 +9643,11 @@
u64 __0 __attribute__((__aligned__(8))); /* 0 8 */
struct Abbreviation __1 __attribute__((__aligned__(8))); /* 8 112 */
- /* XXX last struct has 5 bytes of padding */
+ /* XXX last struct has 16 bytes of padding, 1 hole */
/* size: 120, cachelines: 2, members: 2 */
$
Now the pretty printing perf.data test case passes:
⬢ [acme@toolbx tests]$ ./prettify_perf.data.sh
Pretty printing of files using DWARF type information.
Test ./prettify_perf.data.sh passed
⬢ [acme@toolbx tests]$
This was implemented reusing the --btf_features mechanism that now can
be accessed as well via --features, as this is not strictly a BTF
feature but, as Alan Maguire suggested, it is desirable to ask for that
feature to be enabled when we know it is needed bug can't guarantee that
the available pahole version has the feature and not have it fail
because it doesn't implement --force_cu_merging, which the
--btf_features=force_cu_merging, now also avaialbe as
--features=force_cu_merging, allows as it ignores unknown features.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
dwarf_loader.c | 2 +-
dwarves.h | 1 +
man-pages/pahole.1 | 18 ++++++++++++++++--
pahole.c | 11 ++++++++++-
tests/prettify_perf.data.sh | 4 ++--
5 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 934d410b2f983828..99bc121a377fbd8b 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -4693,7 +4693,7 @@ static int cus__load_module(struct cus *cus, struct conf_load *conf,
cus__remove(cus, type_cu);
}
- if (cus__merging_cu(dw, elf)) {
+ if (conf->force_cu_merging || cus__merging_cu(dw, elf)) {
res = cus__merge_and_process_cu(cus, conf, mod, dw, elf, filename,
build_id, build_id_len,
type_cu ? type_dcu : NULL);
diff --git a/dwarves.h b/dwarves.h
index dd9aa332e61c77f0..38fec59ca78990df 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -112,6 +112,7 @@ struct conf_load {
const char *kabi_prefix;
struct btf *base_btf;
struct conf_fprintf *conf_fprintf;
+ bool force_cu_merging;
};
/** struct conf_fprintf - hints to the __fprintf routines
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index 21378a224847eb45..e3ce737460efec72 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -314,8 +314,10 @@ Generate BTF for functions with optimization-related suffixes (.isra, .constprop
Allow using all the BTF features supported by pahole.
.TP
-.B \-\-btf_features=FEATURE_LIST
-Encode BTF using the specified feature list, or specify 'default' for all
+.B \-\-features=FEATURE_LIST
+This is also available as \-\-btf_features=FEATURE_LIST, unknown features,
+like those added in newer versions of pahole, are ignored. BTF encoding
+configuration is the major user. Using 'default' will enable all
standard features supported.
This option can be used as an alternative to using multiple BTF-related options,
and 'default' represents the standard set of BTF features that are in use for
@@ -364,6 +366,18 @@ Supported non-standard features (not enabled for 'default')
layout Encode information about BTF kinds available at encoding
time in layout section in BTF.
+Non-standard, non-BTF related features:
+
+ force_cu_merging Force merging all CUs into one. Use when there are
+ references across CUs. This happens in some LTO cases
+ and was observed with Rust CUs, where types tags
+ (function parameters, abstract origins for inlines, etc)
+ reference types in another CU.
+ For LTO this is being autodetected and the merging of
+ cus is done automatically, but for the Rust case, and
+ maybe others this is needed with the current DWARF
+ loading algorithm.
+
.fi
So for example, specifying \-\-btf_encode=var,enum64 will result in a BTF
diff --git a/pahole.c b/pahole.c
index 0a7b810568f0dfeb..b7559a124a86d722 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1154,6 +1154,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
#define ARG_padding 348
#define ARGP_with_embedded_flexible_array 349
#define ARGP_btf_attributes 350
+#define ARGP_features 351
/* --btf_features=feature1[,feature2,..] allows us to specify
* a list of requested BTF features or "default" to enable all default
@@ -1241,7 +1242,8 @@ struct btf_feature {
BTF_NON_DEFAULT_FEATURE_CHECK(attributes, btf_attributes, false,
attributes_check),
BTF_NON_DEFAULT_FEATURE(true_signature, true_signature, false),
- BTF_NON_DEFAULT_FEATURE_CHECK(layout, btf_gen_layout, false, layout_check)
+ BTF_NON_DEFAULT_FEATURE_CHECK(layout, btf_gen_layout, false, layout_check),
+ BTF_NON_DEFAULT_FEATURE(force_cu_merging, force_cu_merging, false),
};
#define BTF_MAX_FEATURE_STR 1024
@@ -1816,6 +1818,12 @@ static const struct argp_option pahole__options[] = {
.arg = "FEATURE_LIST",
.doc = "Specify supported BTF features in FEATURE_LIST or 'default' for default set of supported features. See the pahole manual page for the list of supported, default features."
},
+ {
+ .name = "features",
+ .key = ARGP_features,
+ .arg = "FEATURE_LIST",
+ .doc = "Specify supported features in FEATURE_LIST or 'default' for default set of supported features. See the pahole manual page for the list of supported, default features."
+ },
{
.name = "supported_btf_features",
.key = ARGP_supported_btf_features,
@@ -2028,6 +2036,7 @@ static error_t pahole__options_parser(int key, char *arg,
conf_load.reproducible_build = true; break;
case ARGP_running_kernel_vmlinux:
show_running_kernel_vmlinux = true; break;
+ case ARGP_features:
case ARGP_btf_features:
parse_btf_features(arg, false); break;
case ARGP_supported_btf_features:
diff --git a/tests/prettify_perf.data.sh b/tests/prettify_perf.data.sh
index 1fae95154d710aae..384c250ff4e01a4c 100755
--- a/tests/prettify_perf.data.sh
+++ b/tests/prettify_perf.data.sh
@@ -25,7 +25,7 @@ fi
perf_lacks_type_info() {
local type_keyword=$1
local type_name=$2
- if ! pahole -C $type_name $perf | grep -q "^$type_keyword $type_name {"; then
+ if ! pahole --features=force_cu_merging -C $type_name $perf | grep -q "^$type_keyword $type_name {"; then
info_log "skip: $perf doesn't have '$type_keyword $type_name' type info"
test_skip
fi
@@ -41,7 +41,7 @@ $perf record --quiet -o $perf_data sleep 0.00001
number_of_filtered_perf_record_metadata() {
local metadata_record=$1
- local count=$(pahole -F dwarf -V $perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C "perf_event_header(sizeof,type,type_enum=perf_event_type+perf_user_event_type,filter=type==PERF_RECORD_$metadata_record)" --prettify $perf_data | grep ".type = PERF_RECORD_$metadata_record," | wc -l)
+ local count=$(pahole --features=force_cu_merging -F dwarf -V $perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C "perf_event_header(sizeof,type,type_enum=perf_event_type+perf_user_event_type,filter=type==PERF_RECORD_$metadata_record)" --prettify $perf_data | grep ".type = PERF_RECORD_$metadata_record," | wc -l)
echo "$count"
}
--
2.55.0
next prev parent reply other threads:[~2026-07-31 19:31 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 19:30 [PATCHES 00/12] pahole: Support more rust tags and references to dwz alternate debug files Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 01/12] dwarf_loader: Initial support for DW_TAG_variant_part Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 02/12] dwarf_loader: Initial support for DW_TAG_subprogram in DW_TAG_enumeration Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 03/12] dwarf_loader: Populate DW_TAG_variant children in DW_TAG_variant_part Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 04/12] btf_encoder: Encode variant parts as union members in BTF Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 05/12] dwarf_loader: Handle DW_FORM_block in attr_numeric for Rust discriminant values Arnaldo Carvalho de Melo
2026-07-31 19:30 ` Arnaldo Carvalho de Melo [this message]
2026-07-31 19:30 ` [PATCH 07/12] dwarf_loader: Support DW_TAG_imported_unit for same-file partial units Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 08/12] dwarf_loader: Fix cus__merging_cu failing to detect DW_FORM_ref_addr Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 09/12] dwarf_loader: Add cu parameter to tag__set_spec() and dwarf_tag__set_attr_type() Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 10/12] dwarf_loader: Support DW_FORM_GNU_ref_alt references to dwz alternate debug files Arnaldo Carvalho de Melo
2026-07-31 19:30 ` [PATCH 11/12] tests: Add inter-CU type reference comparison test Arnaldo Carvalho de Melo
2026-07-31 19:31 ` [PATCH 12/12] scripts: Add vmlinux_comparison.py for DWARF/BTF analysis Arnaldo Carvalho de Melo
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=20260731193102.110693-7-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=jolsa@kernel.org \
--cc=mjw@redhat.com \
--cc=williams@redhat.com \
--cc=yonghong.song@linux.dev \
/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