From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932628AbbJNPtb (ORCPT ); Wed, 14 Oct 2015 11:49:31 -0400 Received: from mail-pa0-f43.google.com ([209.85.220.43]:34409 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932198AbbJNPt3 (ORCPT ); Wed, 14 Oct 2015 11:49:29 -0400 Date: Thu, 15 Oct 2015 00:45:26 +0900 From: Namhyung Kim To: Wang Nan Cc: acme@kernel.org, ast@plumgrid.com, brendan.d.gregg@gmail.com, a.p.zijlstra@chello.nl, daniel@iogearbox.net, dsahern@gmail.com, hekuang@huawei.com, jolsa@kernel.org, lizefan@huawei.com, masami.hiramatsu.pt@hitachi.com, paulus@samba.org, linux-kernel@vger.kernel.org, pi3orama@163.com, xiakaixu@huawei.com, Arnaldo Carvalho de Melo Subject: Re: [PATCH 09/31] perf tools: Compile scriptlets to BPF objects when passing '.c' to --event Message-ID: <20151014154526.GB4085@danjae.kornet> References: <1444826502-49291-1-git-send-email-wangnan0@huawei.com> <1444826502-49291-10-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <1444826502-49291-10-git-send-email-wangnan0@huawei.com> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Oct 14, 2015 at 12:41:20PM +0000, Wang Nan wrote: > This patch provides infrastructure for passing source files to --event > directly using: > > # perf record --event bpf-file.c command > > This patch does following works: > > 1) Allow passing '.c' file to '--event'. parse_events_load_bpf() is > expanded to allow caller tell it whether the passed file is source > file or object. > > 2) llvm__compile_bpf() is called to compile the '.c' file, the result > is saved into memory. Use bpf_object__open_buffer() to load the > in-memory object. > > Introduces a bpf-script-example.c so we can manually test it: > > # perf record --clang-opt "-DLINUX_VERSION_CODE=0x40200" --event ./bpf-script-example.c sleep 1 > > Note that '--clang-opt' must put before '--event'. > > Futher patches will merge it into a testcase so can be tested automatically. > > Signed-off-by: Wang Nan > Signed-off-by: He Kuang > Acked-by: Alexei Starovoitov > Cc: Brendan Gregg > Cc: Daniel Borkmann > Cc: David Ahern > Cc: Jiri Olsa > Cc: Kaixu Xia > Cc: Masami Hiramatsu > Cc: Namhyung Kim > Cc: Peter Zijlstra > Cc: Zefan Li > Cc: pi3orama@163.com > Signed-off-by: Arnaldo Carvalho de Melo > Link: http://lkml.kernel.org/n/ebpf-6yw9eg0ej3l4jnqhinngkw86@git.kernel.org > --- > tools/perf/tests/bpf-script-example.c | 44 +++++++++++++++++++++++++++++++++++ > tools/perf/util/bpf-loader.c | 17 ++++++++++++-- > tools/perf/util/bpf-loader.h | 5 ++-- > tools/perf/util/parse-events.c | 5 ++-- > tools/perf/util/parse-events.h | 3 ++- > tools/perf/util/parse-events.l | 3 +++ > tools/perf/util/parse-events.y | 15 ++++++++++-- > 7 files changed, 83 insertions(+), 9 deletions(-) > create mode 100644 tools/perf/tests/bpf-script-example.c > > diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c > new file mode 100644 > index 0000000..410a70b > --- /dev/null > +++ b/tools/perf/tests/bpf-script-example.c Shouldn't it be a part of the next patch? Thanks, Namhyung > @@ -0,0 +1,44 @@ > +#ifndef LINUX_VERSION_CODE > +# error Need LINUX_VERSION_CODE > +# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig' > +#endif > +#define BPF_ANY 0 > +#define BPF_MAP_TYPE_ARRAY 2 > +#define BPF_FUNC_map_lookup_elem 1 > +#define BPF_FUNC_map_update_elem 2 > + > +static void *(*bpf_map_lookup_elem)(void *map, void *key) = > + (void *) BPF_FUNC_map_lookup_elem; > +static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) = > + (void *) BPF_FUNC_map_update_elem; > + > +struct bpf_map_def { > + unsigned int type; > + unsigned int key_size; > + unsigned int value_size; > + unsigned int max_entries; > +}; > + > +#define SEC(NAME) __attribute__((section(NAME), used)) > +struct bpf_map_def SEC("maps") flip_table = { > + .type = BPF_MAP_TYPE_ARRAY, > + .key_size = sizeof(int), > + .value_size = sizeof(int), > + .max_entries = 1, > +}; > + > +SEC("func=sys_epoll_pwait") > +int bpf_func__sys_epoll_pwait(void *ctx) > +{ > + int ind =0; > + int *flag = bpf_map_lookup_elem(&flip_table, &ind); > + int new_flag; > + if (!flag) > + return 0; > + /* flip flag and store back */ > + new_flag = !*flag; > + bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY); > + return new_flag; > +} > +char _license[] SEC("license") = "GPL"; > +int _version SEC("version") = LINUX_VERSION_CODE; > diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c > index aa784a4..ba6f752 100644 > --- a/tools/perf/util/bpf-loader.c > +++ b/tools/perf/util/bpf-loader.c > @@ -12,6 +12,7 @@ > #include "bpf-loader.h" > #include "probe-event.h" > #include "probe-finder.h" // for MAX_PROBES > +#include "llvm-utils.h" > > #define DEFINE_PRINT_FN(name, level) \ > static int libbpf_##name(const char *fmt, ...) \ > @@ -33,7 +34,7 @@ struct bpf_prog_priv { > struct perf_probe_event pev; > }; > > -struct bpf_object *bpf__prepare_load(const char *filename) > +struct bpf_object *bpf__prepare_load(const char *filename, bool source) > { > struct bpf_object *obj; > static bool libbpf_initialized; > @@ -45,7 +46,19 @@ struct bpf_object *bpf__prepare_load(const char *filename) > libbpf_initialized = true; > } > > - obj = bpf_object__open(filename); > + if (source) { > + int err; > + void *obj_buf; > + size_t obj_buf_sz; > + > + err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); > + if (err) > + return ERR_PTR(err); > + obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); > + free(obj_buf); > + } else > + obj = bpf_object__open(filename); > + > if (!obj) { > pr_debug("bpf: failed to load %s\n", filename); > return ERR_PTR(-EINVAL); > diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h > index a8f25ee..ccd8d7f 100644 > --- a/tools/perf/util/bpf-loader.h > +++ b/tools/perf/util/bpf-loader.h > @@ -18,7 +18,7 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, > int fd, void *arg); > > #ifdef HAVE_LIBBPF_SUPPORT > -struct bpf_object *bpf__prepare_load(const char *filename); > +struct bpf_object *bpf__prepare_load(const char *filename, bool source); > > void bpf__clear(void); > > @@ -34,7 +34,8 @@ int bpf__foreach_tev(struct bpf_object *obj, > bpf_prog_iter_callback_t func, void *arg); > #else > static inline struct bpf_object * > -bpf__prepare_load(const char *filename __maybe_unused) > +bpf__prepare_load(const char *filename __maybe_unused, > + bool source __maybe_unused) > { > pr_debug("ERROR: eBPF object loading is disabled during compiling.\n"); > return ERR_PTR(-ENOTSUP); > diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c > index 5087023..4849dbd 100644 > --- a/tools/perf/util/parse-events.c > +++ b/tools/perf/util/parse-events.c > @@ -626,11 +626,12 @@ errout: > > int parse_events_load_bpf(struct parse_events_evlist *data, > struct list_head *list, > - char *bpf_file_name) > + char *bpf_file_name, > + bool source) > { > struct bpf_object *obj; > > - obj = bpf__prepare_load(bpf_file_name); > + obj = bpf__prepare_load(bpf_file_name, source); > if (IS_ERR(obj) || !obj) { > char errbuf[BUFSIZ]; > int err; > diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h > index fbb16c7..8f17c83 100644 > --- a/tools/perf/util/parse-events.h > +++ b/tools/perf/util/parse-events.h > @@ -123,7 +123,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx, > struct list_head *head_config); > int parse_events_load_bpf(struct parse_events_evlist *data, > struct list_head *list, > - char *bpf_file_name); > + char *bpf_file_name, > + bool source); > /* Provide this function for perf test */ > struct bpf_object; > int parse_events_load_bpf_obj(struct parse_events_evlist *data, > diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l > index 5e5d31a..eeea4e1 100644 > --- a/tools/perf/util/parse-events.l > +++ b/tools/perf/util/parse-events.l > @@ -116,6 +116,7 @@ group [^,{}/]*[{][^}]*[}][^,{}/]* > event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* > event [^,{}/]+ > bpf_object .*\.(o|bpf) > +bpf_source .*\.c > > num_dec [0-9]+ > num_hex 0x[a-fA-F0-9]+ > @@ -161,6 +162,7 @@ modifier_bp [rwx]{1,3} > > {event_pmu} | > {bpf_object} | > +{bpf_source} | > {event} { > BEGIN(INITIAL); > REWIND(1); > @@ -267,6 +269,7 @@ r{num_raw_hex} { return raw(yyscanner); } > > {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } > {bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } > +{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); } > {name} { return pmu_str_check(yyscanner); } > "/" { BEGIN(config); return '/'; } > - { return '-'; } > diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y > index 497f19b..ad37996 100644 > --- a/tools/perf/util/parse-events.y > +++ b/tools/perf/util/parse-events.y > @@ -42,7 +42,7 @@ static inc_group_count(struct list_head *list, > %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM > %token PE_EVENT_NAME > %token PE_NAME > -%token PE_BPF_OBJECT > +%token PE_BPF_OBJECT PE_BPF_SOURCE > %token PE_MODIFIER_EVENT PE_MODIFIER_BP > %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT > %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP > @@ -55,6 +55,7 @@ static inc_group_count(struct list_head *list, > %type PE_TERM > %type PE_NAME > %type PE_BPF_OBJECT > +%type PE_BPF_SOURCE > %type PE_NAME_CACHE_TYPE > %type PE_NAME_CACHE_OP_RESULT > %type PE_MODIFIER_EVENT > @@ -461,7 +462,17 @@ PE_BPF_OBJECT > struct list_head *list; > > ALLOC_LIST(list); > - ABORT_ON(parse_events_load_bpf(data, list, $1)); > + ABORT_ON(parse_events_load_bpf(data, list, $1, false)); > + $$ = list; > +} > +| > +PE_BPF_SOURCE > +{ > + struct parse_events_evlist *data = _data; > + struct list_head *list; > + > + ALLOC_LIST(list); > + ABORT_ON(parse_events_load_bpf(data, list, $1, true)); > $$ = list; > } > > -- > 1.8.3.4 >