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