[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210224173045.GA51663@24bbad8f3778>
Date: Wed, 24 Feb 2021 10:30:45 -0700
From: Nathan Chancellor <nathan@...nel.org>
To: Jiri Olsa <jolsa@...nel.org>
Cc: Arnaldo Carvalho de Melo <acme@...nel.org>,
Andrii Nakryiko <andriin@...com>, dwarves@...r.kernel.org,
netdev@...r.kernel.org, bpf@...r.kernel.org,
Alexei Starovoitov <ast@...nel.org>,
Yonghong Song <yhs@...com>, Hao Luo <haoluo@...gle.com>,
Martin KaFai Lau <kafai@...com>,
Song Liu <songliubraving@...com>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...omium.org>,
Sedat Dilek <sedat.dilek@...il.com>
Subject: Re: [RFC] dwarves/pahole: Add test scripts
Hi Jiri,
Just some drive by comments. I think the idea is neat, I am always a fan
of automating more things :)
On Tue, Feb 23, 2021 at 02:23:21PM +0100, Jiri Olsa wrote:
> 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?
>
> thanks,
> jirka
>
>
> ---
> kernel-objects-build.sh | 132 +++++++++++++++++++
> kernel-objects-test.sh | 282 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 414 insertions(+)
> create mode 100755 kernel-objects-build.sh
> create mode 100755 kernel-objects-test.sh
>
> 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
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).
> + 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"
With that change above, you could unquote these options and just pass
them in as regular parameters.
> + 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 will see if I can give this a run locally over the next week or so.
Cheers,
Nathan
> + 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 "$@"
> --
> 2.29.2
>
Powered by blists - more mailing lists