Re: [PATCH dwarves v3 9/9] tests: Add a few clang true signature tests
Alan Maguire <[email protected]> Mon, 23 Mar 2026 15:41:17 +0000
| Newsgroups | org.kernel.vger.dwarves,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
On 20/03/2026 19:10, Yonghong Song wrote:
> Three tests are added.
>
> Test 1: VERBOSE=1 ./clang_parm_optimized.sh
> BTF: char * foo(struct t * a, struct t * d);
> DWARF: char * foo(struct t * a, int b, struct t * d);
> where parameber 'b' is unused.
>
> Test 2: VERBOSE=1 ./clang_parm_optimized_stack.sh
> BTF: char * foo(struct t * a, struct t * d);
> DWARF: char * foo(struct t * a, int b1, int b2, int b3, int b4, int b5, int b6, struct t * d);
> where parameters 'b1' to 'b6' are unused.
>
> Test 3: VERBOSE=1 ./clang_parm_aggregate.sh
> BTF: long foo(long a__f1, struct t b, int i);
> DWARF: long foo(struct t a, struct t b, int i);
> where the 'struct t' definition is 'struct t { long f1; long f2; };', and
> a.f2 is not used in the function.
>
> Signed-off-by: Yonghong Song <[email protected]>
thanks for the tests! Ran this through CI [1] and got a failure on aarch64:
2: clang_parm_aggregate.sh
Validation of BTF encoding of true_signatures.
BTF and DWARF signatures should be different and they are not: BTF: long foo(struct t a, 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.YC44qj
---
And for a kernel LLVM build (enabled with [2]) we also see:
1: btf_functions.sh
Validation of BTF encoding of functions.
This may take some time.
ERROR: mismatch : BTF 'bool __scm_recv_common(struct sock *, struct msghdr *, struct scm_cookie *);' not found; DWARF ''
Test ./btf_functions.sh failed
Test data is in /tmp/btf_functions.sh.P23ipZ
This test compares BTF and DWARF representations, trying to ensure we see matches
between DWARF function signatures reported by pfunct for both BTF and DWARF. It might
be worth looking to see if we can refine the test here to handle functions with changed
signatures in DWARF, skipping those that have DW_CC_nocall say.
In the above case pfunct is reporting a signature with the flags field omitted. The
original signature looks like this:
static bool __scm_recv_common(struct sock *sk, struct msghdr *msg, struct scm_cookie *scm, int flags);
...so we don't find an equivalent match in DWARF as a result.
[1] https://github.com/alan-maguire/dwarves/actions/runs/23443008554/job/68198951034
[2] https://lore.kernel.org/dwarves/[email protected]/
> ---
> tests/clang_parm_aggregate.sh | 63 +++++++++++++++++++++++
> tests/clang_parm_optimized.sh | 77 +++++++++++++++++++++++++++++
> tests/clang_parm_optimized_stack.sh | 77 +++++++++++++++++++++++++++++
> 3 files changed, 217 insertions(+)
> create mode 100755 tests/clang_parm_aggregate.sh
> create mode 100755 tests/clang_parm_optimized.sh
> create mode 100755 tests/clang_parm_optimized_stack.sh
>
> diff --git a/tests/clang_parm_aggregate.sh b/tests/clang_parm_aggregate.sh
> new file mode 100755
> index 0000000..bf47c8c
> --- /dev/null
> +++ b/tests/clang_parm_aggregate.sh
> @@ -0,0 +1,63 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +source test_lib.sh
> +
> +outdir=$(make_tmpdir)
> +
> +# Comment this out to save test data.
> +trap cleanup EXIT
> +
> +title_log "Validation of BTF encoding of true_signatures."
> +
> +clang_true="${outdir}/clang_true"
> +CC=$(which clang 2>/dev/null)
> +
> +if [[ -z "$CC" ]]; then
> + info_log "skip: clang not available"
> + test_skip
> +fi
> +
> +cat > ${clang_true}.c << EOF
> +struct t { long f1; long f2; };
> +__attribute__((noinline)) static long foo(struct t a, struct t b, int i)
> +{
> + return a.f1 + b.f1 + b.f2 + i;
> +}
> +
> +struct t p1, p2;
> +int i;
> +int main()
> +{
> + return (int)foo(p1, p2, i);
> +}
> +EOF
> +
> +CFLAGS="$CFLAGS -g -O2"
> +${CC} ${CFLAGS} -o $clang_true ${clang_true}.c
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not compile ${clang_true}.c"
> + test_fail
> +fi
> +LLVM_OBJCOPY=objcopy pahole -J --btf_features=+true_signature $clang_true
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not encode BTF for $clang_true"
> + test_fail
> +fi
> +
> +btf_optimized=$(pfunct --all --format_path=btf $clang_true |grep "foo")
> +if [[ -z "$btf_optimized" ]]; then
> + info_log "skip: no optimizations applied."
> + test_skip
> +fi
> +
> +btf_cmp=$btf_optimized
> +dwarf=$(pfunct --all $clang_true |grep "foo")
> +
> +verbose_log "BTF: $btf_optimized DWARF: $dwarf"
> +
> +if [[ "$btf_cmp" == "$dwarf" ]]; then
> + error_log "BTF and DWARF signatures should be different and they are not: BTF: $btf_optimized ; DWARF $dwarf"
> + test_fail
> +fi
> +test_pass
> diff --git a/tests/clang_parm_optimized.sh b/tests/clang_parm_optimized.sh
> new file mode 100755
> index 0000000..379e6d5
> --- /dev/null
> +++ b/tests/clang_parm_optimized.sh
> @@ -0,0 +1,77 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +source test_lib.sh
> +
> +outdir=$(make_tmpdir)
> +
> +# Comment this out to save test data.
> +trap cleanup EXIT
> +
> +title_log "Validation of BTF encoding of true_signatures."
> +
> +clang_true="${outdir}/clang_true"
> +CC=$(which clang 2>/dev/null)
> +
> +if [[ -z "$CC" ]]; then
> + info_log "skip: clang not available"
> + test_skip
> +fi
> +
> +cat > ${clang_true}.c << EOF
> +struct t { int a; };
> +__attribute__((noinline)) char *tar(struct t *a, struct t *d)
> +{
> + if (a->a == d->a)
> + return (char *)10;
> + else
> + return (char *)0;
> +}
> +
> +__attribute__((noinline)) static char * foo(struct t *a, int b, struct t *d)
> +{
> + return tar(a, d);
> +}
> +
> +__attribute__((noinline)) char *bar(struct t *a, struct t *d)
> +{
> + return foo(a, 1, d);
> +}
> +
> +struct t p1, p2;
> +int main()
> +{
> + return !!bar(&p1, &p2);
> +}
> +EOF
> +
> +CFLAGS="$CFLAGS -g -O2"
> +${CC} ${CFLAGS} -o $clang_true ${clang_true}.c
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not compile ${clang_true}.c"
> + test_fail
> +fi
> +LLVM_OBJCOPY=objcopy pahole -J --btf_features=+true_signature $clang_true
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not encode BTF for $clang_true"
> + test_fail
> +fi
> +
> +btf_optimized=$(pfunct --all --format_path=btf $clang_true |grep "foo")
> +if [[ -z "$btf_optimized" ]]; then
> + info_log "skip: no optimizations applied."
> + test_skip
> +fi
> +
> +btf_cmp=$btf_optimized
> +dwarf=$(pfunct --all $clang_true |grep "foo")
> +
> +if [[ -n "$VERBOSE" ]]; then
> + printf " BTF: %s DWARF: %s\n" "$btf_optimized" "$dwarf"
> +fi
> +
> +if [[ "$btf_cmp" == "$dwarf" ]]; then
> + error_log "BTF and DWARF signatures should be different and they are not: BTF: $btf_optimized ; DWARF $dwarf"
> + test_fail
> +fi
> +test_pass
> diff --git a/tests/clang_parm_optimized_stack.sh b/tests/clang_parm_optimized_stack.sh
> new file mode 100755
> index 0000000..8638af7
> --- /dev/null
> +++ b/tests/clang_parm_optimized_stack.sh
> @@ -0,0 +1,77 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +source test_lib.sh
> +
> +outdir=$(make_tmpdir)
> +
> +# Comment this out to save test data.
> +trap cleanup EXIT
> +
> +title_log "Validation of BTF encoding of true_signatures."
> +
> +clang_true="${outdir}/clang_true"
> +CC=$(which clang 2>/dev/null)
> +
> +if [[ -z "$CC" ]]; then
> + info_log "skip: clang not available"
> + test_skip
> +fi
> +
> +cat > ${clang_true}.c << EOF
> +struct t { int a; };
> +__attribute__((noinline)) char *tar(struct t *a, struct t *d)
> +{
> + if (a->a == d->a)
> + return (char *)10;
> + else
> + return (char *)0;
> +}
> +
> +__attribute__((noinline)) static char * foo(struct t *a, int b1, int b2, int b3, int b4, int b5, int b6, struct t *d)
> +{
> + return tar(a, d);
> +}
> +
> +__attribute__((noinline)) char *bar(struct t *a, struct t *d)
> +{
> + return foo(a, 1, 2, 3, 4, 5, 6, d);
> +}
> +
> +struct t p1, p2;
> +int main()
> +{
> + return !!bar(&p1, &p2);
> +}
> +EOF
> +
> +CFLAGS="$CFLAGS -g -O2"
> +${CC} ${CFLAGS} -o $clang_true ${clang_true}.c
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not compile ${clang_true}.c"
> + test_fail
> +fi
> +LLVM_OBJCOPY=objcopy pahole -J --btf_features=+true_signature $clang_true
> +if [[ $? -ne 0 ]]; then
> + error_log "Could not encode BTF for $clang_true"
> + test_fail
> +fi
> +
> +btf_optimized=$(pfunct --all --format_path=btf $clang_true |grep "foo")
> +if [[ -z "$btf_optimized" ]]; then
> + info_log "skip: no optimizations applied."
> + test_skip
> +fi
> +
> +btf_cmp=$btf_optimized
> +dwarf=$(pfunct --all $clang_true |grep "foo")
> +
> +if [[ -n "$VERBOSE" ]]; then
> + printf " BTF: %s DWARF: %s\n" "$btf_optimized" "$dwarf"
> +fi
> +
> +if [[ "$btf_cmp" == "$dwarf" ]]; then
> + error_log "BTF and DWARF signatures should be different and they are not: BTF: $btf_optimized ; DWARF $dwarf"
> + test_fail
> +fi
> +test_pass