Re: [PATCH dwarves v7 0/5] pahole: Encode true signatures in kernel BTF

Yonghong Song <[email protected]> Tue, 23 Jun 2026 09:58:09 -0700
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <[email protected]>

On 6/23/26 9:02 AM, Alan Maguire wrote:
> On 23/06/2026 14:11, Alan Maguire wrote:
>> On 23/06/2026 13:28, Jiri Olsa wrote:
>>> On Mon, Jun 22, 2026 at 09:07:04PM -0700, 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.
>>> hi,
>>> I tried to get the numbers from my setup and noticed that some new
>>> functions were included in BTF compared to the current version
>>> (functions diff attached below)
>>>
>>> like for "arp_process" function the current pahole gives me:
>>>
>>>    arp_process : skipping BTF encoding of function due to unexpected register usage for parameter
>>>
>>> but it's included in BTF generated with the new pahole.
>>>
>>> in addition to your explanation above also one of the commit says:
>>>
>>>       - a parameter with no location, a constant value, or (for non-clang) no
>>>         register found is marked optimized out
>>>
>>> please check below, it seems like 2nd argument of arp_process has no location,
>>> so iiuc it should not be included in BTF, right?
>>>
>>> thanks,
>>> jirka
>>>
>>>
>> thanks for catching this; it looks like we return a bit early before detecting
>> missing locations in the non-true-signature code. If you get a chance, would you
>> mind trying the attached patch to see if it fixes the problem?
>>
>> If the fix works and Yonghong is happy with it we can add it as a followup
>> and land the true signature series to save another round.
> actually sorry that patch leaked true signature partial names for gcc; updated
> patch attached.

The whole clang signature_changed thing can be removed.

I want to see whether cu->producer_clang can be removed in

                 } else if (pos->has_const_value && !cu->producer_clang) {
                         pos->optimized = 1;
                 } else if (true_sig_enabled) {
                         if (regs_available &&
                             ftype__next_parameter_preserves_slots(ftype, pos, reg_idx, slots, cu)) {
                                 reg_idx += slots;
                                 continue;
                         }
                         
                         pos->optimized = 1;
                         consumes_register = false;
                 }


For clang, we cannot just do pos->optimized = 1 just due to pos->has_const_value though.