Cover the arm64 even-register rule for 16-byte aligned arguments: f_even() and f_stack() where the rule does not bite, f_odd() and f_odd_tail() where it leaves a register hole, and f_box() where the alignment comes from a struct member rather than from the parameter type itself. The test results on arm64: $ VERBOSE=1 ./clang_parm_align16.sh Validation of BTF encoding of over-aligned arguments. BTF: u64 f_even(u64 a, u64 b, __int128 v); BTF: u64 f_odd(u64 a, __int128 v, u64 b); BTF: u64 f_odd_tail(u64 a, __int128 v, u64 b, u64 c, u64 d); BTF: u64 f_stack(u64 a, u64 b, u64 c, u64 d, u64 e, u64 f, u64 g, __int128 v); BTF: u64 f_box(u64 a, struct box s, u64 b); Test ./clang_parm_align16.sh passed Signed-off-by: Yonghong Song --- tests/clang_parm_align16.sh | 77 +++++++++++++++++++++++++++++++++++++ tests/test_lib.sh | 3 +- 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100755 tests/clang_parm_align16.sh diff --git a/tests/clang_parm_align16.sh b/tests/clang_parm_align16.sh new file mode 100755 index 0000000..484aeb6 --- /dev/null +++ b/tests/clang_parm_align16.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 over-aligned arguments." + +align16="${outdir}/align16" +CC=$(which clang 2>/dev/null) + +if [[ -z "$CC" ]]; then + info_log "skip: clang not available" + test_skip +fi + +arch=$(uname -m) +if [[ "$arch" != "aarch64" ]]; then + info_log "skip: test is arm64 only, running on $arch" + test_skip +fi + +# arm64 makes an argument whose alignment is 16 start on an even-numbered +# argument register, so f_odd() passes a in x0, v in x2:x3 -- leaving x1 as a +# hole -- and b in x4. pahole has to account for that hole, otherwise every +# parameter after v looks like it is in an unexpected register and the whole +# function is dropped from BTF. +cat > ${align16}.c << EOF +typedef unsigned long long u64; +struct box { __int128 v; }; + +__attribute__((noinline)) u64 f_even(u64 a, u64 b, __int128 v) +{ return a + b + (u64)v; } + +__attribute__((noinline)) u64 f_odd(u64 a, __int128 v, u64 b) +{ return a + b + (u64)v; } + +__attribute__((noinline)) u64 f_odd_tail(u64 a, __int128 v, u64 b, u64 c, u64 d) +{ return a + b + c + d + (u64)v; } + +__attribute__((noinline)) u64 f_stack(u64 a, u64 b, u64 c, u64 d, u64 e, u64 f, + u64 g, __int128 v) +{ return a + b + c + d + e + f + g + (u64)v; } + +__attribute__((noinline)) u64 f_box(u64 a, struct box s, u64 b) +{ return a + b + (u64)s.v; } + +u64 (*keep[])() = { (u64(*)())f_even, (u64(*)())f_odd, (u64(*)())f_odd_tail, + (u64(*)())f_stack, (u64(*)())f_box }; +EOF + +${CC} -g -O2 -c -o ${align16}.o ${align16}.c 2>/dev/null +if [[ $? -ne 0 ]]; then + info_log "skip: clang could not compile ${align16}.c" + test_skip +fi + +LLVM_OBJCOPY=objcopy pahole -J --btf_features=consistent_func ${align16}.o +if [[ $? -ne 0 ]]; then + error_log "Could not encode BTF for ${align16}.o" + test_fail +fi + +for fn in f_even f_odd f_odd_tail f_stack f_box; do + encoded=$(pfunct --all --format_path=btf ${align16}.o | grep " ${fn}(") + verbose_log "BTF: $encoded" + if [[ -z "$encoded" ]]; then + error_log "${fn}() is missing from BTF" + test_fail + fi +done + +test_pass diff --git a/tests/test_lib.sh b/tests/test_lib.sh index e2a7218..e2d0b0c 100755 --- a/tests/test_lib.sh +++ b/tests/test_lib.sh @@ -661,8 +661,7 @@ check_bpftool_btf_support() cleanup() { if [ -n "$outdir" ] && [ -d "$outdir" ]; then - rm ${outdir}/* - rmdir $outdir + rm -rf "$outdir" fi return 0 } -- 2.53.0-Meta