Re: [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf

From: Alexei Starovoitov
Date: Sat Nov 26 2016 - 12:40:56 EST


On Sat, Nov 26, 2016 at 07:03:50AM +0000, Wang Nan wrote:
> Use a shell script to generate BPF functions declarations from kernel
> source code, embed the generated header into a C string. Following
> commits will utilizes clang's virtual file system to automatically
> include this header to all BPF scripts.
>
> The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
> This macro will be used by following commits to allow user disable this
> and other builtin includes.
>
> Signed-off-by: Wang Nan <wangnan0@xxxxxxxxxx>
> Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
> Cc: Alexei Starovoitov <ast@xxxxxx>
> Cc: He Kuang <hekuang@xxxxxxxxxx>
> Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
> Cc: Zefan Li <lizefan@xxxxxxxxxx>
> Cc: pi3orama@xxxxxxx
> ---
> tools/perf/util/c++/Build | 1 +
> tools/perf/util/c++/bpf-funcs-str.c | 228 +++++++++++++++++++++++++++++++
> tools/perf/util/c++/clang-bpf-includes.h | 12 ++
> 3 files changed, 241 insertions(+)
> create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
> create mode 100644 tools/perf/util/c++/clang-bpf-includes.h
>
> diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
> index 988fef1..bd71abf 100644
> --- a/tools/perf/util/c++/Build
> +++ b/tools/perf/util/c++/Build
> @@ -1,2 +1,3 @@
> libperf-$(CONFIG_CLANGLLVM) += clang.o
> libperf-$(CONFIG_CLANGLLVM) += clang-test.o
> +libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
> diff --git a/tools/perf/util/c++/bpf-funcs-str.c b/tools/perf/util/c++/bpf-funcs-str.c
> new file mode 100644
> index 0000000..f6bcf76
> --- /dev/null
> +++ b/tools/perf/util/c++/bpf-funcs-str.c
> @@ -0,0 +1,228 @@
> +/*
> + * This file is generated by following script:
> + *
> + * #!/bin/bash
> + * TEMP_KBUILD=$(mktemp -d)
> + * KERNEL_DIR=$(pwd)
> + * OUTPUT=tools/perf/util/c++/bpf-funcs-str.c
> + * rm -rf $OUTPUT
> + * echo "Use temp dir: $TEMP_KBUILD"
> + * function finish()
> + * {
> + * rm -rf $TEMP_KBUILD
> + * }
> + * trap finish EXIT
> + * SRCLIST=$(find -name "*.c" | xargs grep bpf_func_proto -l)
> + * cd $TEMP_KBUILD
> + * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
> + * cat << EOF >> ./.config
> + * CONFIG_BPF=y
> + * CONFIG_BPF_SYSCALL=y
> + * CONFIG_PERF_EVENTS=y
> + * CONFIG_SOCK_CGROUP_DATA=y
> + * EOF
> + * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
> + * FIXOBJLIST=""
> + * for src in ${SRCLIST}
> + * do
> + * mkdir -p $(dirname $src)
> + * cat << EOF > "${src}-fix.c"
> + * #include <linux/init.h>
> + * #undef __init
> + * #define __init __attribute__((constructor))
> + * #include "`basename $src`"
> + * EOF
> + * if [ $(basename $src) == "syscall.c" ]
> + * then
> + * cat << EOF >> "${src}-fix.c"
> + * const struct bpf_verifier_ops *
> + * find_prog_type_export(enum bpf_prog_type type)
> + * {
> + * struct bpf_prog_aux aux;
> + * struct bpf_prog p = {.aux = &aux };
> + * if (find_prog_type(type, &p))
> + * return NULL;
> + * return p.aux->ops;
> + * }
> + * EOF
> + * fi
> + * FIXOBJLIST="$FIXOBJLIST ${src}-fix.o"
> + * done
> + * function dolink()
> + * {
> + * touch ./syms.c
> + * echo gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
> + * gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
> + * }
> + * MAIN=kernel/bpf/main.c
> + * cat << EOF > $MAIN
> + * #include <uapi/linux/bpf.h>
> + * #include <linux/bpf.h>
> + * struct bpf_func {
> + * const char *name;
> + * int id;
> + * } bpf_funcs[] = {
> + * EOF
> + * grep '^[[:space:]]BPF_FUNC_[^ ]*,' $KERNEL_DIR/include/uapi/linux/bpf.h | \
> + * sed -e 's/.*BPF_FUNC_\([^,]*\),.*$/\1/g' | \
> + * xargs -n 1 sh -c 'echo {.name = \"$1\", .id = BPF_FUNC_$1}, >> '"$MAIN" sh
> + * cat << EOF >> $MAIN

This is pretty fragile and already broken.
Please just hardcode them as-is. There is no need to be so fancy.

> +"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
> +"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = (void *)2;\n"
> +"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"

just hard code this way.