diff options
author | Wang Nan <wangnan0@huawei.com> | 2016-02-22 04:10:36 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-02-22 11:02:44 -0500 |
commit | 95088a591e197610bd03f4059f5fdbe9e376425b (patch) | |
tree | b48f2529838b72d00d2caba00bb0cfbf0bddd790 /tools/perf/util/parse-events.c | |
parent | e571e029bdbf59f485fe67740b7a4ef421e1d55d (diff) |
perf tools: Apply tracepoint event definition options to BPF script
Users can pass options to tracepoints defined in the BPF script. For
example:
# perf record -e ./test.c/no-inherit/ bash
# dd if=/dev/zero of=/dev/null count=10000
# exit
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.022 MB perf.data (139 samples) ]
(no-inherit works, only the sys_read issued by bash are captured, at
least 10000 sys_read issued by dd are skipped.)
test.c:
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("func=sys_read")
int bpf_func__sys_read(void *ctx)
{
return 1;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
no-inherit is applied to the kprobe event defined in test.c.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Cody P Schafer <dev@codyps.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jeremie Galarneau <jeremie.galarneau@efficios.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kirill Smelkov <kirr@nexedi.com>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1456132275-98875-10-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6e2f20334379..4c19d5e79d8c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -581,6 +581,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
581 | struct __add_bpf_event_param { | 581 | struct __add_bpf_event_param { |
582 | struct parse_events_evlist *data; | 582 | struct parse_events_evlist *data; |
583 | struct list_head *list; | 583 | struct list_head *list; |
584 | struct list_head *head_config; | ||
584 | }; | 585 | }; |
585 | 586 | ||
586 | static int add_bpf_event(struct probe_trace_event *tev, int fd, | 587 | static int add_bpf_event(struct probe_trace_event *tev, int fd, |
@@ -597,7 +598,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd, | |||
597 | tev->group, tev->event, fd); | 598 | tev->group, tev->event, fd); |
598 | 599 | ||
599 | err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, | 600 | err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, |
600 | tev->event, evlist->error, NULL); | 601 | tev->event, evlist->error, |
602 | param->head_config); | ||
601 | if (err) { | 603 | if (err) { |
602 | struct perf_evsel *evsel, *tmp; | 604 | struct perf_evsel *evsel, *tmp; |
603 | 605 | ||
@@ -622,11 +624,12 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd, | |||
622 | 624 | ||
623 | int parse_events_load_bpf_obj(struct parse_events_evlist *data, | 625 | int parse_events_load_bpf_obj(struct parse_events_evlist *data, |
624 | struct list_head *list, | 626 | struct list_head *list, |
625 | struct bpf_object *obj) | 627 | struct bpf_object *obj, |
628 | struct list_head *head_config) | ||
626 | { | 629 | { |
627 | int err; | 630 | int err; |
628 | char errbuf[BUFSIZ]; | 631 | char errbuf[BUFSIZ]; |
629 | struct __add_bpf_event_param param = {data, list}; | 632 | struct __add_bpf_event_param param = {data, list, head_config}; |
630 | static bool registered_unprobe_atexit = false; | 633 | static bool registered_unprobe_atexit = false; |
631 | 634 | ||
632 | if (IS_ERR(obj) || !obj) { | 635 | if (IS_ERR(obj) || !obj) { |
@@ -720,14 +723,47 @@ parse_events_config_bpf(struct parse_events_evlist *data, | |||
720 | return 0; | 723 | return 0; |
721 | } | 724 | } |
722 | 725 | ||
726 | /* | ||
727 | * Split config terms: | ||
728 | * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ... | ||
729 | * 'call-graph=fp' is 'evt config', should be applied to each | ||
730 | * events in bpf.c. | ||
731 | * 'map:array.value[0]=1' is 'obj config', should be processed | ||
732 | * with parse_events_config_bpf. | ||
733 | * | ||
734 | * Move object config terms from the first list to obj_head_config. | ||
735 | */ | ||
736 | static void | ||
737 | split_bpf_config_terms(struct list_head *evt_head_config, | ||
738 | struct list_head *obj_head_config) | ||
739 | { | ||
740 | struct parse_events_term *term, *temp; | ||
741 | |||
742 | /* | ||
743 | * Currectly, all possible user config term | ||
744 | * belong to bpf object. parse_events__is_hardcoded_term() | ||
745 | * happends to be a good flag. | ||
746 | * | ||
747 | * See parse_events_config_bpf() and | ||
748 | * config_term_tracepoint(). | ||
749 | */ | ||
750 | list_for_each_entry_safe(term, temp, evt_head_config, list) | ||
751 | if (!parse_events__is_hardcoded_term(term)) | ||
752 | list_move_tail(&term->list, obj_head_config); | ||
753 | } | ||
754 | |||
723 | int parse_events_load_bpf(struct parse_events_evlist *data, | 755 | int parse_events_load_bpf(struct parse_events_evlist *data, |
724 | struct list_head *list, | 756 | struct list_head *list, |
725 | char *bpf_file_name, | 757 | char *bpf_file_name, |
726 | bool source, | 758 | bool source, |
727 | struct list_head *head_config) | 759 | struct list_head *head_config) |
728 | { | 760 | { |
729 | struct bpf_object *obj; | ||
730 | int err; | 761 | int err; |
762 | struct bpf_object *obj; | ||
763 | LIST_HEAD(obj_head_config); | ||
764 | |||
765 | if (head_config) | ||
766 | split_bpf_config_terms(head_config, &obj_head_config); | ||
731 | 767 | ||
732 | obj = bpf__prepare_load(bpf_file_name, source); | 768 | obj = bpf__prepare_load(bpf_file_name, source); |
733 | if (IS_ERR(obj)) { | 769 | if (IS_ERR(obj)) { |
@@ -749,10 +785,18 @@ int parse_events_load_bpf(struct parse_events_evlist *data, | |||
749 | return err; | 785 | return err; |
750 | } | 786 | } |
751 | 787 | ||
752 | err = parse_events_load_bpf_obj(data, list, obj); | 788 | err = parse_events_load_bpf_obj(data, list, obj, head_config); |
753 | if (err) | 789 | if (err) |
754 | return err; | 790 | return err; |
755 | return parse_events_config_bpf(data, obj, head_config); | 791 | err = parse_events_config_bpf(data, obj, &obj_head_config); |
792 | |||
793 | /* | ||
794 | * Caller doesn't know anything about obj_head_config, | ||
795 | * so combine them together again before returnning. | ||
796 | */ | ||
797 | if (head_config) | ||
798 | list_splice_tail(&obj_head_config, head_config); | ||
799 | return err; | ||
756 | } | 800 | } |
757 | 801 | ||
758 | static int | 802 | static int |