Re: [PATCH dwarves v3 1/9] dwarf_loader: Reduce parameter checking with clang DW_AT_calling_convention attr

Alan Maguire
2026-03-23T12:56:58Z

On 22/03/2026 17:36, Yonghong Song wrote:
>
>
> On 3/21/26 4:10 PM, Jiri Olsa wrote:
>> On Fri, Mar 20, 2026 at 12:09:22PM -0700, Yonghong Song wrote:
>>> Currently every function is checked for its parameters to identify whether
>>> the signature changed or not. If signature indeed changed, pahole may do
>>> some adjustment for parameters for true signatures.
>>>
>>> In clang, any function with the following attribute
>>>        DW_AT_calling_convention        (DW_CC_nocall)
>>> indicates this function having signature changed.
>>> pahole can take advantage of this to avoid parameter checking if
>>> DW_AT_calling_convention is not DW_CC_nocall.
>>>
>>> But more importantly, DW_CC_nocall can identify signature-changed functions
>>> and parameters can be checked one-after-another to create the true
>>> signatures. Otherwise, it takes more effort to identify whether a
>>> function has signature changed or not. For example, for funciton
>>>    __bpf_kfunc static void bbr_main(struct sock *sk, u32 ack, int flag,
>>>       const struct rate_sample *rs) { ... }
>>> and bbr_main() is a callback function in
>>>    .cong_control   = bbr_main
>>> in 'struct tcp_congestion_ops tcp_bbr_cong_ops'.
>>> In the above bbr_main(...), parameter 'ack' and 'flag' are not used.
>>> The following are some details:
>>>
>>> 0x0a713b8d:     DW_TAG_formal_parameter
>>>                    DW_AT_location        (indexed (0x28) loclist = 0x0166d452:
>>>                       [0xffffffff83e77fd9, 0xffffffff83e78016): DW_OP_reg5 RDI
>>>                       ...
>>>                    DW_AT_name    ("sk")
>>>                    DW_AT_type    (0x0a6f5b2b "sock *")
>>>                    ...
>>>
>>> 0x0a713b98:     DW_TAG_formal_parameter
>>>                    DW_AT_name    ("ack")
>>>                    DW_AT_type    (0x0a6f58fd "u32")
>>>                    ...
>>>
>>> 0x0a713ba2:     DW_TAG_formal_parameter
>>>                    DW_AT_name    ("flag")
>>>                    DW_AT_type    (0x0a6f57d1 "int")
>>>                    ...
>>>
>>> 0x0a713bac:     DW_TAG_formal_parameter
>>>                    DW_AT_location        (indexed (0x29) loclist = 0x0166d4a8:
>>>                       [0xffffffff83e77fd9, 0xffffffff83e78016): DW_OP_reg2 RCX
>>>                       ...
>>>                    DW_AT_name    ("rs")
>>>                    DW_AT_type    (0x0a710da5 "const rate_sample *")
>>>                    DW_AT_decl_line       (1027)
>>>
>>> Some analysis for the above dwarf can conclude that the 'ark' and 'flag'
>>> may be related to RSI and RDX, considering the last one is RCX. Basically this
>>> requires all parameters are available to collectively decide whether the
>>> true signature can be found or not. In such case, DW_CC_nocall can make things
>>> easier as parameter can be checked one after another.
>>>
>>> For a clang built bpf-next kernel, in non-LTO setup, the number of kernel functions
>>> is 69103 and the number of signature changed functions is 875, based on
>>>        DW_AT_calling_convention        (DW_CC_nocall)
>>> indication.
>> we don't display these stats, right? would be great and probably easy
>> to count different flags and aggregate them
>
> The actual stats will be different depending on kernel code and compiler optimization.
> But I think I can still count them for each commit so people will know
> which change caused how much true signature.
>

I'll send a patch shortly that does kernel build/compare functions for LLVM/clang [1];
currently our pahole CI only covers gcc kernel builds. That will show differences
between pahole next and the current changes in github; that workflow has been handy for
seeing the effects of pahole changes on the set of vmlinux functions.

We should also look at extending pfunct to do more stats; I've got a few patches which
get it to support split BTF and add a manual page. It has some basic stats if I
remember correctly, but it would be nice to extend those at some stage.

[1] https://github.com/alan-maguire/dwarves/actions/runs/23435796365/job/68173414313

>>
>>> Among 875 signature changed functions, after this patch, 495 functions
>>> can have proper true signatures, mostly due to simple dead argument
>>> elimination. The number of remaining functions, which cannot get the
>>> true signature, is 379. They will be addressed in the subsequent commits.
>> after this change I have more functions added (below) and I checked
>> few and they seem ok (w/o DW_CC_nocall)
>
> Most global functions should be okay. But some global functions
> esp. if argument is more than 8 byte (struct type), they may be
> considered as signature change with the current implementation.
>
>>
>> jirka
>>
>>
>> acpi_ex_do_debug_object
>> add_bits
>> amd_pstate_get_mode_string
>> dma_alloc_from_contiguous
>> do_set_pmd
>> dst_destroy
>> find_cpio_data
>> find_microcode_in_initrd
>> ima_write_policy
>> insn_init
>> io_tx_ubuf_complete
>> ip6_protocol_deliver_rcu
>> kvm_tdp_mmu_unmap_gfn_range
>> net_dim_get_def_rx_moderation
>> net_dim_get_def_tx_moderation
>> pinctrl_commit_state
>> string_unescape
>> syscall_copy_user_array
>> tdp_mmu_zap_leafs
>> usb_speed_string
>> __vlan_find_dev_deep_rcu
>> __vxlan_fdb_delete
>> xfs_bmbt_maxrecs
>> xfs_inobt_maxrecs
>> ZSTD_buildSequencesStatistics
>> ZSTD_copyCCtx
>> ZSTD_findFrameSizeInfo
>> ZSTD_get1BlockSummary
>> zstd_get_cparams
>> ZSTD_getCParams
>> ZSTD_getCParamsFromCCtxParams
>> ZSTD_getCParamsFromCDict
>> ZSTD_getCParams_internal
>> zstd_get_params
>> ZSTD_getParams
>