BPF List
 help / color / mirror / Atom feed
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
>>


      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