Re: [PATCH dwarves v6 0/5] pahole: Encode true signatures in kernel BTF
Alan Maguire <[email protected]> Sat, 20 Jun 2026 09:46:40 +0100
| Newsgroups | org.kernel.vger.dwarves,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
On 18/06/2026 02:13, 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.
> 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.
>
hi Yonghong, changes look good but we do hit a CI issue; specifically
in run_selftests in [1] for gcc+aarch64:
3: clang_parm_aggregate.sh
Validation of BTF encoding of true_signatures.
On arm64, BTF and DWARF signatures should be the same but they are not: BTF: long foo(struct t a__f1, struct t b, int i); ; DWARF long foo(struct t a, struct t b, int i);
Test ./clang_parm_aggregate.sh failed
Test data is in /tmp/clang_parm_aggregate.sh.NH5a6D
I think the problem is that as well as creating aggregate parameter names we
need to decide whether they should actually be used; in this case it looks like
we hit a function using aggregates, but without DW_CC_nocall. Perhaps the
reason is that the calling conventions are preserved while we only get a piece
of the "struct t a" argument? Something like [2] seems to resolve the problem,
please take a look and feel free to roll the fix into one of the patches if it makes
sense. You might find it convenient to use the merges of your series at [3]; they
merge your work with Vineet's tag changes now that they have landed (just patch 1
required merging IIRC).
I also think it would be better to add clang+aarch64 to the CI matrix in light of
your changes, since it will give us test coverage for changed functions for clang
for both x86_64 and aarch64; I've sent [4] to do that.
[1] https://github.com/alan-maguire/dwarves/actions/runs/27839367799/job/82394707921#step:7:24
[2] https://github.com/acmel/dwarves/commit/22d0512680d2ff5b6dd4d1e34ae603efe0f2d098
[3] https://github.com/alan-maguire/dwarves/commits/dwarves-true-sig-v6/
[4] https://lore.kernel.org/dwarves/[email protected]/
> Changelog:
> v5 -> v6:
> - v5: https://lore.kernel.org/bpf/[email protected]/
> - 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/[email protected]/
> - 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/[email protected]/
> - 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/[email protected]/
> - 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/[email protected]/
> - 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 (5):
> 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
> tests: add BTF true_signature encoding tests
>
> btf_encoder.c | 24 +-
> dwarf_loader.c | 548 ++++++++++++++++++++++++----
> dwarves.h | 14 +
> tests/clang_parm_aggregate.sh | 85 +++++
> tests/clang_parm_memory.sh | 77 ++++
> tests/clang_parm_optimized.sh | 63 ++++
> tests/clang_parm_optimized_stack.sh | 63 ++++
> 7 files changed, 812 insertions(+), 62 deletions(-)
> create mode 100755 tests/clang_parm_aggregate.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.sh
>