Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966369AbcKOELm (ORCPT ); Mon, 14 Nov 2016 23:11:42 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:25505 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965957AbcKOEIX (ORCPT ); Mon, 14 Nov 2016 23:08:23 -0500 From: Wang Nan To: , CC: , , , , Wang Nan , Jiri Olsa Subject: [PATCH 30/34] perf clang: Link BPF functions declaration into perf Date: Tue, 15 Nov 2016 04:06:13 +0000 Message-ID: <20161115040617.69788-31-wangnan0@huawei.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161115040617.69788-1-wangnan0@huawei.com> References: <20161115040617.69788-1-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10652 Lines: 286 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 Cc: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Zefan Li Cc: pi3orama@163.com --- 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 + * #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 + * #include + * 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 + * {NULL, -1}, + * }; + * int capable(int x) {return 1;} + * int trace_printk_init_buffers(void) {return 0;} + * static int x; + * void *metadata_dst_alloc_percpu(int a, int b) {return &x;} + * int ___ratelimit(void *a, const void *func) {return 0;} + * extern const struct bpf_verifier_ops * + * find_prog_type_export(enum bpf_prog_type type); + * extern int printf(const char *fmt, ...); + * int main(int argc, char *argv[]) + * { + * struct bpf_func *f = &bpf_funcs[0]; + * printf("#ifndef BPF_FUNCS_DEFINED\n"); + * printf("#define BPF_FUNCS_DEFINED\n"); + * while (f->id != -1) { + * enum bpf_prog_type t; + * const enum bpf_arg_type *argt; + * const struct bpf_verifier_ops *ops = NULL; + * const struct bpf_func_proto *proto = NULL; + * if (f->id == 0) + * goto skip; + * for (t = BPF_PROG_TYPE_UNSPEC + 1; ; t++) { + * ops = find_prog_type_export(t); + * if (!ops) + * break; + * proto = ops->get_func_proto(f->id); + * if (proto) + * break; + * } + * if (!proto) { + * printf("static void (*%s)(void) = (void *)-1;\n", f->name); + * continue; + * } + * printf("static "); + * switch (proto->ret_type) { + * case RET_INTEGER: + * printf("long "); + * break; + * case RET_PTR_TO_MAP_VALUE_OR_NULL: + * printf("void *"); + * break; + * default: + * case RET_VOID: + * printf("void "); + * break; + * } + * printf("(*bpf_%s)(", f->name); + * for (argt = &proto->arg1_type; argt <= &proto->arg5_type; argt++) { + * if (*argt == ARG_DONTCARE) { + * if (argt == &proto->arg1_type) + * printf("void"); + * else if (strcmp(f->name, "trace_printk") == 0) { + * printf(", ..."); + * goto finish; + * } + * goto finish; + * } + * if (argt != &proto->arg1_type) + * printf(", "); + * switch (*argt) { + * case ARG_CONST_MAP_PTR: + * case ARG_PTR_TO_MAP_KEY: + * case ARG_PTR_TO_MAP_VALUE: + * case ARG_PTR_TO_STACK: + * case ARG_PTR_TO_RAW_STACK: + * case ARG_PTR_TO_CTX: + * printf("void *"); + * break; + * default: + * printf("unsigned long"); + * break; + * } + * } + * finish: + * printf(") = (void *)%d;\n", f->id); + * skip: + * f++; + * } + * printf("#endif\n"); + * return 0; + * } + * EOF + * make -j8 KBUILD_CFLAGS_KERNEL=-mpreferred-stack-boundary=4 kernel/bpf/main.o $FIXOBJLIST + * rm -f ./syms.c + * export LANG=POSIX + * export LC_ALL=POSIX + * dolink 2>&1 | \ + * grep 'undefined reference' | \ + * awk -F "\`" '{print $2}' | \ + * sed "s/'$//g" | sort | uniq | \ + * xargs -n 1 sh -c 'echo "int $1 __attribute__((weak));" >> ./syms.c' sh + * dolink + * cd $KERNEL_DIR + * unset X + * cat << EOF > $OUTPUT + * /$X* + * * This file is generated by following script: + * * + * EOF + * cat $0 | awk '$0 != "" {print " * " $0}' >> $OUTPUT + * echo ' *''/' >> $OUTPUT + * echo '#include "clang-bpf-includes.h"' >> $OUTPUT + * echo 'const char clang_builtin_bpf_funcs_str[] =' >> $OUTPUT + * echo '"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"' >> $OUTPUT + * $TEMP_KBUILD/gen | awk '{print "\""$0"\\n\""}' >> $OUTPUT + * echo '"#endif\n"' >> $OUTPUT + * echo ';' >> $OUTPUT + * echo "Finish generating " $OUTPUT + */ +#include "clang-bpf-includes.h" +const char clang_builtin_bpf_funcs_str[] = +"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n" +"#ifndef BPF_FUNCS_DEFINED\n" +"#define BPF_FUNCS_DEFINED\n" +"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" +"static long (*bpf_probe_read)(void *, unsigned long, unsigned long) = (void *)4;\n" +"static long (*bpf_ktime_get_ns)(void) = (void *)5;\n" +"static long (*bpf_trace_printk)(void *, unsigned long, ...) = (void *)6;\n" +"static long (*bpf_get_prandom_u32)(void) = (void *)7;\n" +"static long (*bpf_get_smp_processor_id)(void) = (void *)8;\n" +"static long (*bpf_skb_store_bytes)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)9;\n" +"static long (*bpf_l3_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)10;\n" +"static long (*bpf_l4_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)11;\n" +"static void (*bpf_tail_call)(void *, void *, unsigned long) = (void *)12;\n" +"static long (*bpf_clone_redirect)(void *, unsigned long, unsigned long) = (void *)13;\n" +"static long (*bpf_get_current_pid_tgid)(void) = (void *)14;\n" +"static long (*bpf_get_current_uid_gid)(void) = (void *)15;\n" +"static long (*bpf_get_current_comm)(void *, unsigned long) = (void *)16;\n" +"static long (*bpf_get_cgroup_classid)(void *) = (void *)17;\n" +"static long (*bpf_skb_vlan_push)(void *, unsigned long, unsigned long) = (void *)18;\n" +"static long (*bpf_skb_vlan_pop)(void *) = (void *)19;\n" +"static long (*bpf_skb_get_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)20;\n" +"static long (*bpf_skb_set_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)21;\n" +"static long (*bpf_perf_event_read)(void *, unsigned long) = (void *)22;\n" +"static long (*bpf_redirect)(unsigned long, unsigned long) = (void *)23;\n" +"static long (*bpf_get_route_realm)(void *) = (void *)24;\n" +"static long (*bpf_perf_event_output)(void *, void *, unsigned long, void *, unsigned long) = (void *)25;\n" +"static long (*bpf_skb_load_bytes)(void *, unsigned long, void *, unsigned long) = (void *)26;\n" +"static long (*bpf_get_stackid)(void *, void *, unsigned long) = (void *)27;\n" +"static long (*bpf_csum_diff)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)28;\n" +"static long (*bpf_skb_get_tunnel_opt)(void *, void *, unsigned long) = (void *)29;\n" +"static long (*bpf_skb_set_tunnel_opt)(void *, void *, unsigned long) = (void *)30;\n" +"static long (*bpf_skb_change_proto)(void *, unsigned long, unsigned long) = (void *)31;\n" +"static long (*bpf_skb_change_type)(void *, unsigned long) = (void *)32;\n" +"static long (*bpf_skb_under_cgroup)(void *, void *, unsigned long) = (void *)33;\n" +"static long (*bpf_get_hash_recalc)(void *) = (void *)34;\n" +"static long (*bpf_get_current_task)(void) = (void *)35;\n" +"static long (*bpf_probe_write_user)(unsigned long, void *, unsigned long) = (void *)36;\n" +"static long (*bpf_current_task_under_cgroup)(void *, unsigned long) = (void *)37;\n" +"static long (*bpf_skb_change_tail)(void *, unsigned long, unsigned long) = (void *)38;\n" +"static long (*bpf_skb_pull_data)(void *, unsigned long) = (void *)39;\n" +"static long (*bpf_csum_update)(void *, unsigned long) = (void *)40;\n" +"static long (*bpf_set_hash_invalid)(void *) = (void *)41;\n" +"#endif\n" +"#endif\n" +; diff --git a/tools/perf/util/c++/clang-bpf-includes.h b/tools/perf/util/c++/clang-bpf-includes.h new file mode 100644 index 0000000..385a5bb --- /dev/null +++ b/tools/perf/util/c++/clang-bpf-includes.h @@ -0,0 +1,12 @@ +#ifndef CLANG_BPF_INCLUDS_H +#define CLANG_BPF_INCLUDS_H +#ifdef __cplusplus +extern "C" { +#endif + +extern const char clang_builtin_bpf_funcs_str[]; + +#ifdef __cplusplus +} +#endif +#endif -- 2.10.1