From: Yonghong Song <yonghong.song@linux.dev>
To: Alan Maguire <alan.maguire@oracle.com>,
Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>,
dwarves@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
bpf@vger.kernel.org, kernel-team@fb.com
Subject: Re: [PATCH dwarves v9 0/6] pahole: Encode true signatures in kernel BTF
Date: Wed, 24 Jun 2026 14:00:10 -0700 [thread overview]
Message-ID: <9207f019-d487-411f-aef0-ec1fd1c333d5@linux.dev> (raw)
In-Reply-To: <9f594fec-7044-44a8-8d92-10aaffbd5bbe@oracle.com>
On 6/24/26 10:59 AM, Alan Maguire wrote:
> On 24/06/2026 06:25, Yonghong Song wrote:
>> Current vmlinux BTF encoding is based on the source level signatures.
>> But the compiler may do some optimization and changed the signature.
>> If the user tried with source level signature, their initial implementation
>> may have wrong results and then the user need to check what is the
>> problem and work around it, e.g. through kprobe since kprobe does not
>> need vmlinux BTF.
>>
>> Majority of changed signatures are due to dead argument elimination.
>> The following is a more complex one. The original source signature:
>> typedef struct {
>> union {
>> void *kernel;
>> void __user *user;
>> };
>> bool is_kernel : 1;
>> } sockptr_t;
>> typedef sockptr_t bpfptr_t;
>> static int map_create(union bpf_attr *attr, bpfptr_t uattr) { ... }
>> After compiler optimization, the signature becomes:
>> static int map_create(union bpf_attr *attr, bool uattr__is_kernel) { ... }
>> In the above, uattr__is_kernel corresponds to 'is_kernel' field in sockptr_t.
>> This makes it easier for developers to understand what changed.
>>
>> The new signature needs to properly follow ABI specification based on
>> locations. Otherwise, that signature should be discarded. For example,
>>
>> 0x0242f1f7: DW_TAG_subprogram
>> DW_AT_name ("memblock_find_in_range")
>> DW_AT_calling_convention (DW_CC_nocall)
>> DW_AT_type (0x0242decc "phys_addr_t")
>> ...
>> 0x0242f22e: DW_TAG_formal_parameter
>> DW_AT_location (indexed (0x14a) loclist = 0x005595bc:
>> [0xffffffff87a000f9, 0xffffffff87a00178): DW_OP_reg5 RDI
>> [0xffffffff87a00178, 0xffffffff87a001be): DW_OP_reg14 R14
>> [0xffffffff87a001be, 0xffffffff87a001c7): DW_OP_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value
>> [0xffffffff87a001c7, 0xffffffff87a00214): DW_OP_reg14 R14)
>> DW_AT_name ("start")
>> DW_AT_type (0x0242decc "phys_addr_t")
>> ...
>> 0x0242f239: DW_TAG_formal_parameter
>> DW_AT_location (indexed (0x14b) loclist = 0x005595e6:
>> [0xffffffff87a000f9, 0xffffffff87a00175): DW_OP_reg4 RSI
>> [0xffffffff87a00175, 0xffffffff87a001b8): DW_OP_reg3 RBX
>> [0xffffffff87a001b8, 0xffffffff87a001c7): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value
>> [0xffffffff87a001c7, 0xffffffff87a00214): DW_OP_reg3 RBX)
>> DW_AT_name ("end")
>> DW_AT_type (0x0242decc "phys_addr_t")
>> ...
>> 0x0242f245: DW_TAG_formal_parameter
>> DW_AT_location (indexed (0x14c) loclist = 0x00559610:
>> [0xffffffff87a001e3, 0xffffffff87a001ef): DW_OP_breg4 RSI+0)
>> DW_AT_name ("size")
>> DW_AT_type (0x0242decc "phys_addr_t")
>> ...
>> 0x0242f250: DW_TAG_formal_parameter
>> DW_AT_const_value (4096)
>> DW_AT_name ("align")
>> DW_AT_type (0x0242decc "phys_addr_t")
>> ...
>>
>> The third argument should correspond to RDX for x86_64. But the location suggests that
>> the parameter value is stored in the address with 'RSI + 0'. It is not clear whether
>> the parameter value is stored in RDX or not. So we have to discard this funciton in
>> vmlinux BTF to avoid incorrect true signatures.
>>
>> For llvm, any function having
>> DW_AT_calling_convention (DW_CC_nocall)
>> in dwarf DW_TAG_subprogram will indicate that this function has signature changed.
>> But for non DW_CC_nocall functions, it is possible that true signature still not
>> available due to locations. So every functions will be checked.
>>
>> I did experiment with latest bpf-next. For x86_64, there are 69103 kernel functions
>> and 875 kernel functions having signature changed. A series of patches are intended
>> to ensure true signatures are properly represented. Eventually, only 20 functions
>> cannot have true signatures due to locations.
>>
>> For arm64, there are 863 kernel functions having signature changed, and
>> 108 functions cannot have true signatures due to locations. I checked those
>> functions and look like llvm arm64 backend more relaxed to compute parameter
>> values.
>>
>> For full testing, I enabled true signature support in kernel scripts/Makefile.btf like below:
>> -pahole-flags-$(call test-ge, $(pahole-ver), 131) += --btf_features=attributes
>> +pahole-flags-$(call test-ge, $(pahole-ver), 131) += --btf_features=attributes --btf_features=+true_signature
>>
>> See individual patches for details.
>>
> Seeing a new CI failure [1] with this series in the btf_functions test for clang (x86_64/aarch64):
>
> 1: btf_functions.sh
> Validation of BTF encoding of functions.
> This may take some time.
> libbpf: STRUCT 'elf_note_info' size=248 vlen=8 cand_id[1195975] canon_id[1193376] shallow-equal but not equiv for field#0 'thread': 0
> ERROR: mismatch : BTF 'void btf_verifier_log_vsi(struct btf_verifier_env *, const struct btf_type *, const struct btf_var_secinfo *, const char *, ...);' not found; DWARF ''
> Test ./btf_functions.sh failed
> Test data is in /tmp/btf_functions.sh.v9s3w4
>
> The test does not run with true signature enabled, and I think the problem here
> is that previously this function would have been skipped. So it may be true signature
> leaking into non-true signature behaviour but I'm not 100%
>
> [1] https://github.com/alan-maguire/dwarves/actions/runs/28104464362/job/83214808300#step:7:12
The issue seems due to patch:
btf_encoder: Avoid comparing inlined and out-of-line function prototypes
Taking the above patch out, ./btf_functions.sh runs successfully:
$ ./btf_functions.sh
vmlinux:/home/yhs/work/linux-bld/vmlinux
outdir:/tmp/btf_functions.sh.sXwgqd
Validation of BTF encoding of functions.
This may take some time.
libbpf: STRUCT 'elf_note_info' size=248 vlen=8 cand_id[1405697] canon_id[1403135] shallow-equal but not equiv for field#0 'thread': 0
libbpf: STRUCT 'pt_iommu_map_args' size=48 vlen=6 cand_id[3100130] canon_id[3098170] shallow-equal but not equiv for field#1 'attrs': 0
Test ./btf_functions.sh passed
So the patch 'btf_encoder: Avoid comparing inlined and out-of-line function prototypes'
needs change and need more careful reviews. I will remove it in the next revision.
>
>> Changelog:
>> v8 -> v9:
>> - v8: https://lore.kernel.org/bpf/20260623222850.3290612-1-yonghong.song@linux.dev/
>> - v8 made a mistake where all functions go through main loop in
>> function__analyze_parameter_locations(). This is not correct as it includes functions
>> whose signature is not changed. See function
>> function__match_clang_parameter_locations().
>> - Add a change in btf_encoder to avoid comparing inlined and out-of-line function prototypes.
>> This allows some functions to be in btf.
>> - Add one more test, clang_parm_optimized_stack_2, where a global function, with
>> many unused parameters, gets properly handling in location checking.
>> v7 -> v8:
>> - v7: https://lore.kernel.org/bpf/20260623040704.2732530-1-yonghong.song@linux.dev/
>> - Both Check and Analyze phases go through all functions.
>> - Require true_signature in btf_encoder to have name like <paramName>__<field>.
>> - Remove signature_changed (from nocall). It is possible that function signatures
>> are not changed but the location reigsters do not match.
>> v6 -> v7:
>> - v6: https://lore.kernel.org/bpf/20260618011358.632394-1-yonghong.song@linux.dev/
>> - Ensure that 'collect' and 'analyze' have the same location checking.
>> - In 'analyze' stage, undo true_sig_member_name if the next expected register
>> matches the previous source type although the previous parameter may
>> only use half of the value.
>> v5 -> v6:
>> - v5: https://lore.kernel.org/bpf/20260523165712.1225231-1-yonghong.song@linux.dev/
>> - The previous change relies on parameter__new() to collect and analyze each
>> parameter to decide true signatures. The new one separates collecting and
>> analyzing phase from Alan. This two-phase makes logic easy to understand.
>> - In btf_encoder.c, remove usage of skip_idx to simplify the code.
>> v4 -> v5:
>> - v4: https://lore.kernel.org/bpf/20260326013144.2901265-1-yonghong.song@linux.dev/
>> - Check info.signature_changed only under clang.
>> - Fix an uninitialized varable issue (var reg_dix) for gcc.
>> v3 -> v4:
>> - v3: https://lore.kernel.org/bpf/20260320190917.1970524-1-yonghong.song@linux.dev/
>> - Add simple prescan of parameter registers in order to get true signatures
>> for those functions where optimization could happen but compiler didn't do it.
>> - Do not create a new name (e.g. "uattr__is_kernel") with malloc at parameter_reg()
>> stage. Instead remember both "uattr" and "is_kernel" and later generate the
>> name "uattr_is_kernel" in btf encoder.
>> - Add comments to explain how to handle parameters which may take two registers.
>> - Fix some test failures on aarch64.
>> v2 -> v3:
>> - v2: https://lore.kernel.org/bpf/20260309153215.1917033-1-yonghong.song@linux.dev/
>> - Change tests by using newly added test_lib.sh.
>> - Simplify to get bool variable producer_clang.
>> - Try to avoid producer_clang appearance in dwarf_loader.c in order to avoid
>> clear separation between clang and gcc.
>> v1 -> v2:
>> - v1: https://lore.kernel.org/bpf/20260305225455.1151066-1-yonghong.song@linux.dev/
>> - Added producer_clang guarding in btf_encoder. Otherwise, gcc kernel build
>> will crash pahole.
>> - Fix an early return in parameter__reg() which didn't do pthread_mutex_unlock()
>> which caused the deadlock for arm64.
>> - Add a few more places to guard with producer_clang and conf->true_signature
>> to maintain the previous behavior if not clang or conf->true_signature is false.
>>
>> Yonghong Song (6):
>> dwarf_loader: Detect aggregate ABI register usage and signature
>> changes
>> dwarf_loader: Collect per-parameter information
>> dwarf_loader: Analyze per-parameter information for true signatures
>> btf_encoder: Emit true function signatures
>> btf_encoder: Avoid comparing inlined and out-of-line function
>> prototypes
>> tests: Add BTF true_signature encoding tests
>>
>> btf_encoder.c | 53 ++-
>> dwarf_loader.c | 603 +++++++++++++++++++++++---
>> dwarves.h | 14 +
>> tests/clang_parm_aggregate_1.sh | 85 ++++
>> tests/clang_parm_aggregate_2.sh | 88 ++++
>> tests/clang_parm_memory.sh | 77 ++++
>> tests/clang_parm_optimized.sh | 63 +++
>> tests/clang_parm_optimized_stack_1.sh | 63 +++
>> tests/clang_parm_optimized_stack_2.sh | 63 +++
>> 9 files changed, 1042 insertions(+), 67 deletions(-)
>> create mode 100755 tests/clang_parm_aggregate_1.sh
>> create mode 100755 tests/clang_parm_aggregate_2.sh
>> create mode 100755 tests/clang_parm_memory.sh
>> create mode 100755 tests/clang_parm_optimized.sh
>> create mode 100755 tests/clang_parm_optimized_stack_1.sh
>> create mode 100755 tests/clang_parm_optimized_stack_2.sh
>>
prev parent reply other threads:[~2026-06-24 21:00 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-24 5:25 [PATCH dwarves v9 0/6] pahole: Encode true signatures in kernel BTF Yonghong Song
2026-06-24 5:25 ` [PATCH dwarves v9 1/6] dwarf_loader: Detect aggregate ABI register usage and signature changes Yonghong Song
2026-06-24 5:26 ` [PATCH dwarves v9 2/6] dwarf_loader: Collect per-parameter information Yonghong Song
2026-06-24 5:26 ` [PATCH dwarves v9 3/6] dwarf_loader: Analyze per-parameter information for true signatures Yonghong Song
2026-06-24 5:26 ` [PATCH dwarves v9 4/6] btf_encoder: Emit true function signatures Yonghong Song
2026-06-24 5:26 ` [PATCH dwarves v9 5/6] btf_encoder: Avoid comparing inlined and out-of-line function prototypes Yonghong Song
2026-06-24 5:26 ` [PATCH dwarves v9 6/6] tests: Add BTF true_signature encoding tests Yonghong Song
2026-06-24 17:59 ` [PATCH dwarves v9 0/6] pahole: Encode true signatures in kernel BTF Alan Maguire
2026-06-24 21:00 ` Yonghong Song [this message]
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=9207f019-d487-411f-aef0-ec1fd1c333d5@linux.dev \
--to=yonghong.song@linux.dev \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=arnaldo.melo@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=kernel-team@fb.com \
/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