Message ID | 20210223132321.220570-1-jolsa@kernel.org |
---|---|
State | New |
Headers | show |
Series | [RFC] dwarves/pahole: Add test scripts | expand |
On Wed, Feb 24, 2021 at 10:30:45AM -0700, Nathan Chancellor wrote: SNIP > > + > > +build() > > +{ > > + local name=$1 > > + local opts=$2 > > A more robust way to handle this might be > > shift > local opts=$@ > > > + > > + echo "build ${name} (${OUTPUT}/output)" > > + > > + mkdir -p ${OBJECTS}/${name} > > + mkdir -p ${OUTPUT} > > + > > + pushd ${KDIR} > > + make ${opts} -j"$(nproc)" O=${OUTPUT} olddefconfig > ${OUTPUT}/output 2>&1 > > Then change this to > > make "${opts[@]}" > > shellcheck complains about implicit word splitting (and finds some other > things in the other script). I have no doutbs ;-) ok SNIP > > + > > + PAHOLE=$(realpath ${PAHOLE}) > > + OBJECTS=$(realpath ${OBJECTS}) > > + > > + echo "output: ${OUTPUT}" > > + echo "kdir: ${KDIR}" > > + echo "pahole: ${PAHOLE}" > > + echo "objects: ${OBJECTS}" > > + echo > > + > > + mkdir -p ${OBJECTS} > > + > > + echo "cleanup ${KDIR}" > > + make -C ${KDIR} mrproper > > + > > + > > + build x86-clang "LLVM=1" > > With that change above, you could unquote these options and just pass > them in as regular parameters. ok I see, that'd be easier and better looking, I'll change this > > > + build x86-gcc "" > > + > > + build aarch64-clang "ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- LLVM=1" > > + build aarch64-gcc "ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-" > > + > > +# build powerpc-clang "ARCH=powerpc CROSS_COMPILE=powerpc64-linux-gnu- LLVM=1" > > + build powerpc-gcc "ARCH=powerpc CROSS_COMPILE=powerpc64-linux-gnu-" > > + > > +# build powerpcle-clang "ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu- LLVM=1" > > + build powerpcle-gcc "ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu-" > > + > > +# build s390x-clang "ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- LLVM=1" > > powerpc64le and s390 can build with CC=clang, instead of LLVM=1. I got some strange error when building ppc and s390 with LLVM=1, but I did not check it deeply.. I'll try with CC=clang then, great > > I will see if I can give this a run locally over the next week or so. thanks, jirka
Em Tue, Feb 23, 2021 at 02:23:21PM +0100, Jiri Olsa escreveu: > hi, > I cleaned up a bit my testing scripts, that I'm using for testing > btf encoding changes. It's far from ideal and convoluted, but let's > have discussion if this could be kicked into something useful for > everybody. > > There are 2 scripts: > kernel-objects-build.sh - compiles kernel for several archs and > stores vmlinux and kernel modules > > kernel-objects-test.sh - goes through objects stored by ^^^ > and runs tests on each of them > > The general idea is that all objects are compiled already with > BTF debuginfo with available pahole. The test script then: > - takes each objects and dumps its current BTF data > - then create new BTF data with given pahole binary > - dumps the new BTF data and makes the comparison > > I was thinking about support for comparing 2 pahole binaries, > but so far that did not fit into my workflow. Normally I have > latest globally available pahole, which is used to build the > kernel binaries and then I'm playing with new pahole binary, > which I'm putting to the test. > > Example.. prepare vmlinux and modules for all archs: > > $ ./kernel-objects-build.sh > output: /tmp/pahole.test.nsQ > kdir: /home/jolsa/linux > pahole: /opt/dwarves/bin/pahole > objects: /home/jolsa/.pahole_test_objects > > cleanup /home/jolsa/linux > ... > > All objects are stored under ~/pahole_test_objects/ directories: > > $ ls ~/.pahole_test_objects/ > aarch64-clang > aarch64-gcc > powerpc-gcc > powerpcle-gcc > s390x-gcc > x86-clang > x86-gcc > > Each containing vmlinux and modules: > > $ ls ~/.pahole_test_objects/x86-gcc/ > efivarfs.ko iptable_nat.ko nf_log_arp.ko nf_log_common.ko nf_log_ipv4.ko nf_log_ipv6.ko > vmlinux x86_pkg_temp_thermal.ko xt_addrtype.ko xt_LOG.ko xt_mark.ko xt_MASQUERADE.ko xt_nat.ko > > Run test on all of them with new './pahole' binary: > > $ ./kernel-objects-test.sh -B ~/linux/tools/bpf/bpftool/bpftool -P ./pahole > pahole: /home/jolsa/pahole/build/pahole > bpftool: /home/jolsa/linux/tools/bpf/bpftool/bpftool > base: /tmp/pahole.test.oxv > objects: /home/jolsa/.pahole_test_objects > fail: no > cleanup: yes > > test_funcs on /home/jolsa/.pahole_test_objects/aarch64-clang/vmlinux ... OK > test_format_c on /home/jolsa/.pahole_test_objects/aarch64-clang/vmlinux ... OK > test_btfdiff on /home/jolsa/.pahole_test_objects/aarch64-clang/vmlinux ... FAIL > test_funcs on /home/jolsa/.pahole_test_objects/aarch64-clang/8021q.ko ... OK > test_format_c on /home/jolsa/.pahole_test_objects/aarch64-clang/8021q.ko ... OK > test_funcs on /home/jolsa/.pahole_test_objects/aarch64-clang/act_gact.ko ... OK > test_format_c on /home/jolsa/.pahole_test_objects/aarch64-clang/act_gact.ko ... OK > ... > > There are several options that helps to set other binaries/dirs > or stop and debug issues. > > thoughts? So far: should look in other places for getting the kernel sources directory, myne is at $(HOME)/git/linux/, kernel-objects-build.sh is looking at $(HOME)/linux/ Maybe we can use this, if there is any locally built kernel: [acme@quaco pahole]$ ls -la /lib/modules/5.10.0-rc5/source lrwxrwxrwx. 1 root root 20 Nov 23 2020 /lib/modules/5.10.0-rc5/source -> /home/acme/git/linux [acme@quaco pahole]$ Or look at $HOME/git/linux/ too if not finding it in $HOME/linux/ Also it is building in the source tree, would be better to create a temp dir and use O=. Trying it: ⬢[acme@toolbox pahole]$ ./kernel-objects-build.sh output: /tmp/pahole.test.0su kdir: /var/home/acme/git/linux pahole: /var/home/acme/git/pahole/build/pahole objects: /var/home/acme/.pahole_test_objects cleanup /var/home/acme/git/linux make: Entering directory '/var/home/acme/git/linux' make: Leaving directory '/var/home/acme/git/linux' build x86-clang (/tmp/pahole.test.0su/output) ~/git/linux ~/git/pahole ~/git/pahole build x86-gcc (/tmp/pahole.test.0su/output) ~/git/linux ~/git/pahole rpm~/git/pahole build aarch64-clang (/tmp/pahole.test.0su/output) ~/git/linux ~/git/pahole ⬢[acme@toolbox pahole]$ ⬢[acme@toolbox pahole]$ ls -la ~/.pahole_test_objects/ total 0 drwxr-xr-x. 1 acme acme 58 Aug 20 17:24 . drwx------. 1 acme acme 1346 Aug 20 17:31 .. drwxr-xr-x. 1 acme acme 0 Aug 20 17:24 aarch64-clang drwxr-xr-x. 1 acme acme 258 Aug 20 17:21 x86-clang drwxr-xr-x. 1 acme acme 258 Aug 20 17:24 x86-gcc ⬢[acme@toolbox pahole]$ ⬢[acme@toolbox pahole]$ ls -la ~/.pahole_test_objects/aarch64-clang/ total 0 drwxr-xr-x. 1 acme acme 0 Aug 20 17:24 . drwxr-xr-x. 1 acme acme 58 Aug 20 17:24 .. ⬢[acme@toolbox pahole]$ ls -la ~/.pahole_test_objects/x86-clang/ total 592512 drwxr-xr-x. 1 acme acme 258 Aug 20 17:21 . drwxr-xr-x. 1 acme acme 58 Aug 20 17:24 .. -rw-r--r--. 1 acme acme 392920 Aug 20 17:21 efivarfs.ko -rw-r--r--. 1 acme acme 388384 Aug 20 17:21 iptable_nat.ko -rw-r--r--. 1 acme acme 471896 Aug 20 17:21 nf_log_syslog.ko -rwxr-xr-x. 1 acme acme 603366392 Aug 20 17:21 vmlinux -rw-r--r--. 1 acme acme 245272 Aug 20 17:21 x86_pkg_temp_thermal.ko -rw-r--r--. 1 acme acme 397128 Aug 20 17:21 xt_addrtype.ko -rw-r--r--. 1 acme acme 375536 Aug 20 17:21 xt_LOG.ko -rw-r--r--. 1 acme acme 292320 Aug 20 17:21 xt_mark.ko -rw-r--r--. 1 acme acme 383824 Aug 20 17:21 xt_MASQUERADE.ko -rw-r--r--. 1 acme acme 401672 Aug 20 17:21 xt_nat.ko ⬢[acme@toolbox pahole]$ ls -la ~/.pahole_test_objects/x86-gcc/ total 699988 drwxr-xr-x. 1 acme acme 258 Aug 20 17:24 . drwxr-xr-x. 1 acme acme 58 Aug 20 17:24 .. -rw-r--r--. 1 acme acme 485112 Aug 20 17:24 efivarfs.ko -rw-r--r--. 1 acme acme 419520 Aug 20 17:24 iptable_nat.ko -rw-r--r--. 1 acme acme 514512 Aug 20 17:24 nf_log_syslog.ko -rwxr-xr-x. 1 acme acme 713044328 Aug 20 17:24 vmlinux -rw-r--r--. 1 acme acme 301256 Aug 20 17:24 x86_pkg_temp_thermal.ko -rw-r--r--. 1 acme acme 431712 Aug 20 17:24 xt_addrtype.ko -rw-r--r--. 1 acme acme 403384 Aug 20 17:24 xt_LOG.ko -rw-r--r--. 1 acme acme 316528 Aug 20 17:24 xt_mark.ko -rw-r--r--. 1 acme acme 411992 Aug 20 17:24 xt_MASQUERADE.ko -rw-r--r--. 1 acme acme 435312 Aug 20 17:24 xt_nat.ko ⬢[acme@toolbox pahole]$ It didn't build bpftool so I have to do it now: ⬢[acme@toolbox pahole]$ cd ../linux ⬢[acme@toolbox linux]$ make -C tools/bpf/bpftool/ make: Entering directory '/var/home/acme/git/linux/tools/bpf/bpftool' Auto-detecting system features: ... libbfd: [ on ] ... disassembler-four-args: [ on ] ... zlib: [ on ] ... libcap: [ on ] ... clang-bpf-co-re: [ on ] CC btf.o <SNIP> CC struct_ops.o CC tracelog.o CC xlated_dumper.o CC jit_disasm.o CC disasm.o LINK bpftool make: Leaving directory '/var/home/acme/git/linux/tools/bpf/bpftool' ⬢[acme@toolbox linux]$ ⬢[acme@toolbox linux]$ cd - /var/home/acme/git/pahole ⬢[acme@toolbox pahole]$ ⬢[acme@toolbox pahole]$ ./kernel-objects-test.sh -B ~/git/linux/tools/bpf/bpftool/bpftool -P build/pahole /usr/bin/which: no bpftool in (/var/home/acme/.local/bin:/var/home/acme/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin) pahole: /var/home/acme/git/pahole/build/pahole bpftool: /var/home/acme/git/linux/tools/bpf/bpftool/bpftool base: /tmp/pahole.test.4of objects: /var/home/acme/.pahole_test_objects fail: no cleanup: yes test_funcs on /var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux ... cp: cannot stat '/var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux': No such file or directory Error: failed to load BTF from /tmp/pahole.test.4of/object: No such file or directory pahole: /tmp/pahole.test.4of/object: No such file or directory Error: failed to load BTF from /tmp/pahole.test.4of/object: No such file or directory OK test_format_c on /var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux ... cp: cannot stat '/var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux': No such file or directory Error: failed to load BTF from /tmp/pahole.test.4of/object: No such file or directory pahole: /tmp/pahole.test.4of/object: No such file or directory Error: failed to load BTF from /tmp/pahole.test.4of/object: No such file or directory OK test_btfdiff on /var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux ... OK ls: cannot access '/var/home/acme/.pahole_test_objects/aarch64-clang/*.ko': No such file or directory test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/vmlinux ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/vmlinux ... OK test_btfdiff on /var/home/acme/.pahole_test_objects/x86-clang/vmlinux ... FAIL test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/efivarfs.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/efivarfs.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/iptable_nat.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/iptable_nat.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/nf_log_syslog.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/nf_log_syslog.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/x86_pkg_temp_thermal.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/x86_pkg_temp_thermal.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/xt_addrtype.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/xt_addrtype.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/xt_LOG.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/xt_LOG.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/xt_mark.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/xt_mark.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/xt_MASQUERADE.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/xt_MASQUERADE.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-clang/xt_nat.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-clang/xt_nat.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux ... Ignoring zero-sized per-CPU variable 'pagesets'... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux ... Ignoring zero-sized per-CPU variable 'pagesets'... OK test_btfdiff on /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux ... FAIL test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/efivarfs.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/efivarfs.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/iptable_nat.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/iptable_nat.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/nf_log_syslog.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/nf_log_syslog.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/x86_pkg_temp_thermal.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/x86_pkg_temp_thermal.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/xt_addrtype.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/xt_addrtype.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/xt_LOG.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/xt_LOG.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/xt_mark.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/xt_mark.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/xt_MASQUERADE.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/xt_MASQUERADE.ko ... OK test_funcs on /var/home/acme/.pahole_test_objects/x86-gcc/xt_nat.ko ... OK test_format_c on /var/home/acme/.pahole_test_objects/x86-gcc/xt_nat.ko ... OK ⬢[acme@toolbox pahole]$ So, now looking at: test_btfdiff on /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux ... FAIL Overall, I like it, will add also the 'fullcircle' test for some of the single CU kernel objects and add detached BTF tests. - Arnaldo
Em Fri, Aug 20, 2021 at 05:39:22PM -0300, Arnaldo Carvalho de Melo escreveu: > So, now looking at: > test_btfdiff on /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux ... FAIL Minor stuff, why would BTF get that const and DWARF not? ⬢[acme@toolbox pahole]$ btfdiff /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux --- /tmp/btfdiff.dwarf.j8SZhr 2021-08-20 17:40:52.052186096 -0300 +++ /tmp/btfdiff.btf.5QMi8C 2021-08-20 17:40:52.298191569 -0300 @@ -33719,7 +33719,7 @@ struct e1000_option { /* XXX 4 bytes hole, try to pack */ - struct e1000_opt_list * p; /* 40 8 */ + const struct e1000_opt_list * p; /* 40 8 */ } l; /* 32 16 */ } arg; /* 32 16 */ ⬢[acme@toolbox pahole]$ btfdiff /var/home/acme/.pahole_test_objects/x86-clang/vmlinux --- /tmp/btfdiff.dwarf.1TAWtj 2021-08-20 17:41:18.821781610 -0300 +++ /tmp/btfdiff.btf.FMLZRt 2021-08-20 17:41:19.058786883 -0300 @@ -21584,7 +21584,7 @@ struct cpu_rmap { struct { u16 index; /* 16 2 */ u16 dist; /* 18 2 */ - } near[0]; /* 16 0 */ + } near[]; /* 16 0 */ /* size: 16, cachelines: 1, members: 5 */ /* last cacheline: 16 bytes */ @@ -65743,7 +65743,7 @@ struct linux_efi_memreserve { struct { phys_addr_t base; /* 16 8 */ phys_addr_t size; /* 24 8 */ - } entry[0]; /* 16 0 */ + } entry[]; /* 16 0 */ /* size: 16, cachelines: 1, members: 4 */ /* last cacheline: 16 bytes */ @@ -72814,7 +72814,7 @@ struct netlink_policy_dump_state { struct { const struct nla_policy * policy; /* 16 8 */ unsigned int maxtype; /* 24 4 */ - } policies[0]; /* 16 0 */ + } policies[]; /* 16 0 */ /* size: 16, cachelines: 1, members: 4 */ /* sum members: 12, holes: 1, sum holes: 4 */ ⬢[acme@toolbox pahole]$o I see, there are two declarations for this struct, one at: drivers/net/ethernet/intel/e1000/e1000_param.c 166 struct e1000_option { 167 enum { enable_option, range_option, list_option } type; 168 const char *name; 169 const char *err; 170 int def; 171 union { 172 struct { /* range_option info */ 173 int min; 174 int max; 175 } r; 176 struct { /* list_option info */ 177 int nr; 178 const struct e1000_opt_list { int i; char *str; } *p; 179 } l; 180 } arg; 181 }; and the other at (note that extra 'e' after 1000 :) ): drivers/net/ethernet/intel/e1000e/param.c 141 struct e1000_option { 142 enum { enable_option, range_option, list_option } type; 143 const char *name; 144 const char *err; 145 int def; 146 union { 147 /* range_option info */ 148 struct { 149 int min; 150 int max; 151 } r; 152 /* list_option info */ 153 struct { 154 int nr; 155 struct e1000_opt_list { 156 int i; 157 char *str; 158 } *p; 159 } l; 160 } arg; 161 }; The only difference is that 'const'. I _guess_ that the BTF deduplicator is picking the one with the 'const' while pahole's (which is just used when pretty printing, not when BTF encoding) with the other (it shouldn't as per my intention, I'm not arguing about if both should appear as different types). I tested it with: pahole -j -F dwarf -C e1000_option /var/home/acme/.pahole_test_objects/x86-gcc/vmlinux to use the new DWARF multithreaded loading, like 'btfdiff' now does, and its related to which of these types get loaded first, but its just related to pahole pretty printing, not for the BTF encoding, where all types will be passed to BTF for deduplication. Same thing happens with clang, its just that when pretty printing in this test run the clang multithreaded DWARF loading saw the type that BTF picked (the one with 'const'). When I re-run it with: ⬢[acme@toolbox pahole]$ git diff diff --git a/btfdiff b/btfdiff index 77543630d1965b5e..71d3dbf5fc861e16 100755 --- a/btfdiff +++ b/btfdiff @@ -26,7 +26,6 @@ pahole_bin=${PAHOLE-"pahole"} ${pahole_bin} -F dwarf \ --flat_arrays \ --sort \ - --jobs \ --suppress_aligned_attribute \ --suppress_force_paddings \ --suppress_packed \ ⬢[acme@toolbox pahole]$ git diff I get: test_btfdiff on /var/home/acme/.pahole_test_objects/aarch64-clang/vmlinux ... OK test_btfdiff on /var/home/acme/.pahole_test_objects/x86-clang/vmlinux ... FAIL clang's is just that zero entries array diff again. I'll get 1.22 out of the door tomorrow as it passed these tests and also the ones at libbpf github CI and my local ones and get these scripts merged in 1.23, will check the clang output as well. Thanks for the scripts! - Arnaldo
diff --git a/kernel-objects-build.sh b/kernel-objects-build.sh new file mode 100755 index 000000000000..b92729994ded --- /dev/null +++ b/kernel-objects-build.sh @@ -0,0 +1,132 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +set -u +set -e + +exec 2>&1 + +OBJECTS="${HOME}/.pahole_test_objects" +KDIR=${HOME}/linux +PAHOLE=$(which pahole) +OUTPUT= + +usage() +{ + cat <<EOF +Usage: $0 [-k KERNEL] [-O OUTPUT] [-o OBJECTS] + +The script prepares vmlinux and kernel modules for different archs/C: + + - x86 gcc/clang + - arm64 gcc/clang + - powerpc gcc + - s390x gcc + +Options: + -k) Update kernel tree directory (default HOME/linux) + -O) Update temp output directory (default mktemp /tmp/pahole.test.XXX) + -o) Update final objects directory (default HOME/.pahole.test.XXX) + +Make images under '/tmp/build', and place it under 'objects': + + $ $0 -o objects -O /tmp/build/ + +EOF +} + +build() +{ + local name=$1 + local opts=$2 + + echo "build ${name} (${OUTPUT}/output)" + + mkdir -p ${OBJECTS}/${name} + mkdir -p ${OUTPUT} + + pushd ${KDIR} + make ${opts} -j"$(nproc)" O=${OUTPUT} olddefconfig > ${OUTPUT}/output 2>&1 + scripts/config \ + --file ${OUTPUT}/.config \ + -e BPF_SYSCALL \ + -e DEBUG_INFO \ + -e DEBUG_INFO_BTF \ + -e FTRACE \ + -e FUNCTION_TRACER \ + >> ${OUTPUT}/output 2>&1 + make ${opts} -j"$(nproc)" O=${OUTPUT} PAHOLE=${PAHOLE} olddefconfig all >> ${OUTPUT}/output 2>&1 + + cp ${OUTPUT}/vmlinux ${OBJECTS}/${name} + find ${OUTPUT} -name '*.ko' | xargs cp -t ${OBJECTS}/${name} + + rm -rf ${OUTPUT} + popd +} + +main() +{ + while getopts 'k:o:O:' opt; do + case ${opt} in + k) + KDIR="$OPTARG" + ;; + O) + OUTPUT="$OPTARG" + ;; + o) + OBJECTS="$OPTARG" + ;; + esac + done + shift $((OPTIND -1)) + + if [[ $# -ne 0 ]]; then + usage + exit 1 + fi + + if [[ "${OUTPUT}" == "" ]]; then + OUTPUT=$(mktemp -d /tmp/pahole.test.XXX) + fi + + PAHOLE=$(realpath ${PAHOLE}) + OBJECTS=$(realpath ${OBJECTS}) + + echo "output: ${OUTPUT}" + echo "kdir: ${KDIR}" + echo "pahole: ${PAHOLE}" + echo "objects: ${OBJECTS}" + echo + + mkdir -p ${OBJECTS} + + echo "cleanup ${KDIR}" + make -C ${KDIR} mrproper + + + build x86-clang "LLVM=1" + build x86-gcc "" + + build aarch64-clang "ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- LLVM=1" + build aarch64-gcc "ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-" + +# build powerpc-clang "ARCH=powerpc CROSS_COMPILE=powerpc64-linux-gnu- LLVM=1" + build powerpc-gcc "ARCH=powerpc CROSS_COMPILE=powerpc64-linux-gnu-" + +# build powerpcle-clang "ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu- LLVM=1" + build powerpcle-gcc "ARCH=powerpc CROSS_COMPILE=powerpc64le-linux-gnu-" + +# build s390x-clang "ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- LLVM=1" + build s390x-gcc "ARCH=s390 CROSS_COMPILE=s390x-linux-gnu-" +} + +catch() +{ + local exit_code=$1 + exit ${exit_code} +} + +trap 'catch "$?"' EXIT + +main "$@" diff --git a/kernel-objects-test.sh b/kernel-objects-test.sh new file mode 100755 index 000000000000..a34c22c2eb09 --- /dev/null +++ b/kernel-objects-test.sh @@ -0,0 +1,282 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +set -u + +exec 2>&1 + +PAHOLE=$(which pahole) +BPFTOOL=$(which bpftool) +BTFDIFF=$(which btfdiff) + +OBJECTS="$HOME/.pahole_test_objects" +CLEANUP="yes" +BASE= +FAIL="no" + +function test_funcs() +{ + local vmlinux=$1 + local obj=$2 + local err=0 + + cp ${obj} ${BASE}/object + + if [[ ${obj} == *.ko ]]; then + ${BPFTOOL} --base ${vmlinux} btf dump file ${BASE}/object > ${BASE}/btf.old + ${PAHOLE} -V -J --btf_base ${vmlinux} ${BASE}/object > ${BASE}/output + ${BPFTOOL} --base ${vmlinux} btf dump file ${BASE}/object > ${BASE}/btf.new + else + ${BPFTOOL} btf dump file ${BASE}/object > ${BASE}/btf.old + ${PAHOLE} -V -J ${BASE}/object > ${BASE}/output + ${BPFTOOL} btf dump file ${BASE}/object > ${BASE}/btf.new + fi + + diff -puw ${BASE}/btf.old ${BASE}/btf.new > ${BASE}/diff.all + if [ $? -ne 0 ]; then + funcs_old=${BASE}/funcs.old + funcs_new=${BASE}/funcs.new + + cat ${BASE}/btf.old | grep 'FUNC ' | awk '{ print $3 }' | sort | uniq > ${funcs_old} + cat ${BASE}/btf.new | grep 'FUNC ' | awk '{ print $3 }' | sort | uniq > ${funcs_new} + + diff -puw ${funcs_old} ${funcs_new} > ${BASE}/diff.funcs + fi + + if [[ $? -ne 0 ]]; then + err=1 + fi + + return ${err}; +} + +function test_format_c() +{ + local vmlinux=$1 + local obj=$2 + local err=0 + + cp ${obj} ${BASE}/object + + if [[ ${obj} == *.ko ]]; then + ${BPFTOOL} --base ${vmlinux} btf dump file ${BASE}/object format c > ${BASE}/c.old + ${PAHOLE} -V -J --btf_base ${vmlinux} ${BASE}/object > ${BASE}/output + ${BPFTOOL} --base ${vmlinux} btf dump file ${BASE}/object format c > ${BASE}/c.new + else + ${BPFTOOL} btf dump file ${BASE}/object format c > ${BASE}/c.old + ${PAHOLE} -V -J ${BASE}/object > ${BASE}/output + ${BPFTOOL} btf dump file ${BASE}/object format c > ${BASE}/c.new + fi + + diff -puw ${BASE}/c.old ${BASE}/c.new > ${BASE}/diff.all + if [[ $? -ne 0 ]]; then + err=1 + fi + + return ${err}; +} + +function test_btfdiff() +{ + local vmlinux=$1 + local obj=$2 + local err=0 + + if [[ -x ${BTFDIFF} ]]; then + ${BTFDIFF} ${obj} > ${BASE}/output + if [[ -s "${BASE}/output" ]]; then + err=1 + fi + else + err=2 + fi + + return ${err} +} + +usage() +{ + cat <<EOF +Usage: $0 [-f] [-o object] [-O objects] [-b BASE] [-P PAHOLE] [-B BPFTOOL] -- [test] + +The script runs tests on objects with BTF data. + +Options: + -f) Stop on failure + -o) Run tests on specific objects + -O) Update the root objects directory (default HOME/.pahole_test_objects) + -b) Update work base/temporary directory (default mktemp -d /tmp/pahole.test.XXX) + -P) Update pahole path (default which pahole) + -B) Update bpftool path (default which bpftool) + +Test image under 'objects': + + $ $0 -O objects/ + +Test specific image (objects/aarch64-clang) and stop on failure: + + $ $0 -o o objects/aarch64-clang -f + +Run specific test (test_format_c): + + $ $0 -o o objects/aarch64-clang -f test_format_c +EOF +} + +do_test() +{ + local test_name=$1 + local vmlinux=$2 + local obj=$3 + + printf "%-15s on %s ... " "${test_name}" "${obj}" + + eval ${test_name} ${vmlinux} ${obj} + local err=$? + + case ${err} in + 0) + echo "OK" + ;; + 1) + echo "FAIL" + ;; + 2) + echo "SKIP" + ;; + esac + + if [[ ${err} -eq 1 && "${FAIL}" == "yes" ]]; then + exit 1 + fi + + return ${err} +} + +run_tests() +{ + local vmlinux=$1 + local obj=$2 + local test_name=$3 + + if [[ "${test_name}" != "all" ]]; then + do_test ${test_name} ${vmlinux} ${obj} + else + do_test test_funcs ${vmlinux} ${obj} + do_test test_format_c ${vmlinux} ${obj} + + # btfdiff is only for vmlinux + if [[ ${obj} != *.ko ]]; then + do_test test_btfdiff ${vmlinux} ${obj} + fi + fi +} + +do_obj() +{ + local obj=$1 + local test_name=$2 + local vmlinux=${obj}/vmlinux + + run_tests ${vmlinux} ${vmlinux} ${test_name} + + for kmod in $(ls ${obj}/*.ko); do + run_tests ${vmlinux} ${kmod} ${test_name} + done +} + +main() +{ + local test_name="all" + + while getopts 'b:o:dhP:B:fO:' opt; do + case ${opt} in + f) + FAIL="yes" + CLEANUP="no" + ;; + o) + obj="$OPTARG" + ;; + O) + OBJECTS="$OPTARG" + ;; + b) + BASE="$OPTARG" + ;; + P) + PAHOLE="$OPTARG" + ;; + B) + BPFTOOL="$OPTARG" + ;; + h) + usage + exit 0 + ;; + \? ) + echo "Invalid Option: -$OPTARG" + usage + exit 1 + ;; + : ) + echo "Invalid Option: -$OPTARG requires an argument" + usage + exit 1 + ;; + esac + done + shift $((OPTIND -1)) + + if [[ $# -gt 1 ]]; then + echo "Invalid test: $@" + usage + exit 1 + fi + + if [[ $# -eq 1 ]]; then + test_name="$@" + fi + + if [[ "${BASE}" == "" ]]; then + BASE=$(mktemp -d /tmp/pahole.test.XXX) + else + mkdir -p ${BASE} + fi + + PAHOLE=$(realpath ${PAHOLE}) + BPFTOOL=$(realpath ${BPFTOOL}) + OBJECTS=$(realpath ${OBJECTS}) + + echo "pahole: ${PAHOLE}" + echo "bpftool: ${BPFTOOL}" + echo "base: ${BASE}" + echo "objects: ${obj:-${OBJECTS}}" + echo "fail: ${FAIL}" + echo "cleanup: ${CLEANUP}" + echo + + if [[ "${obj:=""}" != "" ]]; then + do_obj ${obj} ${test_name} + else + for obj in $(ls ${OBJECTS}); do + do_obj ${OBJECTS}/${obj} ${test_name} + done + fi +} + +catch() +{ + local exit_code=$1 + if [[ "${BASE:=""}" != "" && "${CLEANUP}" == "yes" ]]; then + rm -rf ${BASE} + else + echo + echo "Keeping test data in: ${BASE}" + fi + exit ${exit_code} +} + +trap 'catch "$?"' EXIT + +main "$@"