From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754847AbbJOCNv (ORCPT ); Wed, 14 Oct 2015 22:13:51 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:60220 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752957AbbJOCNt (ORCPT ); Wed, 14 Oct 2015 22:13:49 -0400 Message-ID: <561F0B1D.4050405@huawei.com> Date: Thu, 15 Oct 2015 10:10:37 +0800 From: "Wangnan (F)" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: Namhyung Kim CC: , , , , , , , , , , , , , , Arnaldo Carvalho de Melo Subject: Re: [PATCH 09/31] perf tools: Compile scriptlets to BPF objects when passing '.c' to --event References: <1444826502-49291-1-git-send-email-wangnan0@huawei.com> <1444826502-49291-10-git-send-email-wangnan0@huawei.com> <20151014154526.GB4085@danjae.kornet> In-Reply-To: <20151014154526.GB4085@danjae.kornet> Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.111.66.109] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2015/10/14 23:45, Namhyung Kim wrote: > 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? I think putting the sample file in this patch should be better. In commit message I show a cmdline to utilize scriptlet compiling. If we put the sample code into next patch, then people get to this point have to write his/her own script to test scriptlet compiling manually. Thank you. > 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 >>