aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-10-30 05:09:37 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-30 05:09:37 -0400
commitbebd23a2ed31d47e7dd746d3b125068aa2c42d85 (patch)
tree81cc1a59203c393286dba3e76daa343f5c35b127
parent66a565c203bc31b76969711fbd92da11bee2f129 (diff)
parent7ed4915ad60788d6b846e2cd034f49ee15698143 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Allow passing C language eBPF scriptlets via --event in all tools, so that it gets built using clang and then pass it to the kernel via sys_bpf(). (Wang Nan) - Wire up the loaded ebpf object file with associated kprobes, so that it can determine if the kprobes will be filtered or not. (Wang Nan) User visible changes: - Add cmd string table to decode sys_bpf first arg in 'trace'. (Arnaldo Carvalho de Melo) - Enable printing of branch stack in 'perf script'. (Stephane Eranian) - Pass the right file with debug info to libunwind. (Rabin Vincent) Build Fixes: - Make sure fixdep is built before libbpf, fixing a race. (Jiri Olsa) - Fix libiberty feature detection. (Rabin Vincent) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/build/feature/Makefile4
-rw-r--r--tools/perf/Documentation/perf-record.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt14
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-script.c82
-rw-r--r--tools/perf/builtin-trace.c7
-rw-r--r--tools/perf/tests/bpf-script-example.c44
-rw-r--r--tools/perf/util/bpf-loader.c17
-rw-r--r--tools/perf/util/bpf-loader.h5
-rw-r--r--tools/perf/util/evsel.c17
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/parse-events.c11
-rw-r--r--tools/perf/util/parse-events.h3
-rw-r--r--tools/perf/util/parse-events.l3
-rw-r--r--tools/perf/util/parse-events.y15
-rw-r--r--tools/perf/util/unwind-libunwind.c5
17 files changed, 227 insertions, 16 deletions
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index e43a2971bf56..cea04ce9f35c 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -132,10 +132,10 @@ test-libbfd.bin:
132 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 132 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
133 133
134test-liberty.bin: 134test-liberty.bin:
135 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 135 $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
136 136
137test-liberty-z.bin: 137test-liberty-z.bin:
138 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 138 $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
139 139
140test-cplus-demangle.bin: 140test-cplus-demangle.bin:
141 $(BUILD) -liberty 141 $(BUILD) -liberty
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 7ff6a9d0ea0d..e630a7d2c348 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -314,6 +314,12 @@ This option sets the time out limit. The default value is 500 ms.
314Record context switch events i.e. events of type PERF_RECORD_SWITCH or 314Record context switch events i.e. events of type PERF_RECORD_SWITCH or
315PERF_RECORD_SWITCH_CPU_WIDE. 315PERF_RECORD_SWITCH_CPU_WIDE.
316 316
317--clang-path::
318Path to clang binary to use for compiling BPF scriptlets.
319
320--clang-opt::
321Options passed to clang when compiling BPF scriptlets.
322
317SEE ALSO 323SEE ALSO
318-------- 324--------
319linkperf:perf-stat[1], linkperf:perf-list[1] 325linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index b3b42f9285df..382ddfb45d1d 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -112,11 +112,11 @@ OPTIONS
112--debug-mode:: 112--debug-mode::
113 Do various checks like samples ordering and lost events. 113 Do various checks like samples ordering and lost events.
114 114
115-f:: 115-F::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, flags. 119 srcline, period, iregs, brstack, brstacksym, flags.
120 Field list can be prepended with the type, trace, sw or hw, 120 Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -175,6 +175,16 @@ OPTIONS
175 Finally, a user may not set fields to none for all event types. 175 Finally, a user may not set fields to none for all event types.
176 i.e., -f "" is not allowed. 176 i.e., -f "" is not allowed.
177 177
178 The brstack output includes branch related information with raw addresses using the
179 /v/v/v/v/ syntax in the following order:
180 FROM: branch source instruction
181 TO : branch target instruction
182 M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported
183 X/- : X=branch inside a transactional region, -=not in transaction region or not supported
184 A/- : A=TSX abort entry, -=not aborted region or not supported
185
186 The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible.
187
178-k:: 188-k::
179--vmlinux=<file>:: 189--vmlinux=<file>::
180 vmlinux pathname 190 vmlinux pathname
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 1e2e2d1d26b7..0d19d5447d6c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -430,7 +430,7 @@ $(LIBAPI)-clean:
430 $(call QUIET_CLEAN, libapi) 430 $(call QUIET_CLEAN, libapi)
431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 431 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
432 432
433$(LIBBPF): FORCE 433$(LIBBPF): fixdep FORCE
434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a 434 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
435 435
436$(LIBBPF)-clean: 436$(LIBBPF)-clean:
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index de02267c73d8..199fc31e3919 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,7 @@
31#include "util/auxtrace.h" 31#include "util/auxtrace.h"
32#include "util/parse-branch-options.h" 32#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h" 33#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h"
34 35
35#include <unistd.h> 36#include <unistd.h>
36#include <sched.h> 37#include <sched.h>
@@ -1112,6 +1113,12 @@ struct option __record_options[] = {
1112 "per thread proc mmap processing timeout in ms"), 1113 "per thread proc mmap processing timeout in ms"),
1113 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1114 OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
1114 "Record context switch events"), 1115 "Record context switch events"),
1116#ifdef HAVE_LIBBPF_SUPPORT
1117 OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
1118 "clang binary to use for compiling BPF scriptlets"),
1119 OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
1120 "options passed to clang when compiling BPF scriptlets"),
1121#endif
1115 OPT_END() 1122 OPT_END()
1116}; 1123};
1117 1124
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 278acb22f029..72b5deb4bd79 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -51,6 +51,8 @@ enum perf_output_field {
51 PERF_OUTPUT_SRCLINE = 1U << 12, 51 PERF_OUTPUT_SRCLINE = 1U << 12,
52 PERF_OUTPUT_PERIOD = 1U << 13, 52 PERF_OUTPUT_PERIOD = 1U << 13,
53 PERF_OUTPUT_IREGS = 1U << 14, 53 PERF_OUTPUT_IREGS = 1U << 14,
54 PERF_OUTPUT_BRSTACK = 1U << 15,
55 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
54}; 56};
55 57
56struct output_option { 58struct output_option {
@@ -72,6 +74,8 @@ struct output_option {
72 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 74 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
73 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 75 {.str = "period", .field = PERF_OUTPUT_PERIOD},
74 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 76 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
77 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
78 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
75}; 79};
76 80
77/* default set to maintain compatibility with current format */ 81/* default set to maintain compatibility with current format */
@@ -425,6 +429,77 @@ static void print_sample_start(struct perf_sample *sample,
425 } 429 }
426} 430}
427 431
432static inline char
433mispred_str(struct branch_entry *br)
434{
435 if (!(br->flags.mispred || br->flags.predicted))
436 return '-';
437
438 return br->flags.predicted ? 'P' : 'M';
439}
440
441static void print_sample_brstack(union perf_event *event __maybe_unused,
442 struct perf_sample *sample,
443 struct thread *thread __maybe_unused,
444 struct perf_event_attr *attr __maybe_unused)
445{
446 struct branch_stack *br = sample->branch_stack;
447 u64 i;
448
449 if (!(br && br->nr))
450 return;
451
452 for (i = 0; i < br->nr; i++) {
453 printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ",
454 br->entries[i].from,
455 br->entries[i].to,
456 mispred_str( br->entries + i),
457 br->entries[i].flags.in_tx? 'X' : '-',
458 br->entries[i].flags.abort? 'A' : '-',
459 br->entries[i].flags.cycles);
460 }
461}
462
463static void print_sample_brstacksym(union perf_event *event __maybe_unused,
464 struct perf_sample *sample,
465 struct thread *thread __maybe_unused,
466 struct perf_event_attr *attr __maybe_unused)
467{
468 struct branch_stack *br = sample->branch_stack;
469 struct addr_location alf, alt;
470 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
471 u64 i, from, to;
472
473 if (!(br && br->nr))
474 return;
475
476 for (i = 0; i < br->nr; i++) {
477
478 memset(&alf, 0, sizeof(alf));
479 memset(&alt, 0, sizeof(alt));
480 from = br->entries[i].from;
481 to = br->entries[i].to;
482
483 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf);
484 if (alf.map)
485 alf.sym = map__find_symbol(alf.map, alf.addr, NULL);
486
487 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt);
488 if (alt.map)
489 alt.sym = map__find_symbol(alt.map, alt.addr, NULL);
490
491 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
492 putchar('/');
493 symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
494 printf("/%c/%c/%c/%d ",
495 mispred_str( br->entries + i),
496 br->entries[i].flags.in_tx? 'X' : '-',
497 br->entries[i].flags.abort? 'A' : '-',
498 br->entries[i].flags.cycles);
499 }
500}
501
502
428static void print_sample_addr(union perf_event *event, 503static void print_sample_addr(union perf_event *event,
429 struct perf_sample *sample, 504 struct perf_sample *sample,
430 struct thread *thread, 505 struct thread *thread,
@@ -560,6 +635,11 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
560 if (PRINT_FIELD(IREGS)) 635 if (PRINT_FIELD(IREGS))
561 print_sample_iregs(event, sample, thread, attr); 636 print_sample_iregs(event, sample, thread, attr);
562 637
638 if (PRINT_FIELD(BRSTACK))
639 print_sample_brstack(event, sample, thread, attr);
640 else if (PRINT_FIELD(BRSTACKSYM))
641 print_sample_brstacksym(event, sample, thread, attr);
642
563 printf("\n"); 643 printf("\n");
564} 644}
565 645
@@ -1681,7 +1761,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1681 "comma separated output fields prepend with 'type:'. " 1761 "comma separated output fields prepend with 'type:'. "
1682 "Valid types: hw,sw,trace,raw. " 1762 "Valid types: hw,sw,trace,raw. "
1683 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1763 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1684 "addr,symoff,period,iregs,flags", parse_output_fields), 1764 "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields),
1685 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1765 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1686 "system-wide collection from all CPUs"), 1766 "system-wide collection from all CPUs"),
1687 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1767 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 93b80f12f35e..c783d8fd3a80 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -585,6 +585,12 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc
585 585
586#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 586#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
587 587
588static const char *bpf_cmd[] = {
589 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
590 "MAP_GET_NEXT_KEY", "PROG_LOAD",
591};
592static DEFINE_STRARRAY(bpf_cmd);
593
588static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; 594static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
589static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); 595static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
590 596
@@ -1011,6 +1017,7 @@ static struct syscall_fmt {
1011 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 1017 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1012 [1] = SCA_ACCMODE, /* mode */ }, }, 1018 [1] = SCA_ACCMODE, /* mode */ }, },
1013 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 1019 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
1020 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
1014 { .name = "brk", .hexret = true, 1021 { .name = "brk", .hexret = true,
1015 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 1022 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
1016 { .name = "chdir", .errmsg = true, 1023 { .name = "chdir", .errmsg = true,
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
new file mode 100644
index 000000000000..410a70b93b93
--- /dev/null
+++ b/tools/perf/tests/bpf-script-example.c
@@ -0,0 +1,44 @@
1#ifndef LINUX_VERSION_CODE
2# error Need LINUX_VERSION_CODE
3# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
4#endif
5#define BPF_ANY 0
6#define BPF_MAP_TYPE_ARRAY 2
7#define BPF_FUNC_map_lookup_elem 1
8#define BPF_FUNC_map_update_elem 2
9
10static void *(*bpf_map_lookup_elem)(void *map, void *key) =
11 (void *) BPF_FUNC_map_lookup_elem;
12static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
13 (void *) BPF_FUNC_map_update_elem;
14
15struct bpf_map_def {
16 unsigned int type;
17 unsigned int key_size;
18 unsigned int value_size;
19 unsigned int max_entries;
20};
21
22#define SEC(NAME) __attribute__((section(NAME), used))
23struct bpf_map_def SEC("maps") flip_table = {
24 .type = BPF_MAP_TYPE_ARRAY,
25 .key_size = sizeof(int),
26 .value_size = sizeof(int),
27 .max_entries = 1,
28};
29
30SEC("func=sys_epoll_pwait")
31int bpf_func__sys_epoll_pwait(void *ctx)
32{
33 int ind =0;
34 int *flag = bpf_map_lookup_elem(&flip_table, &ind);
35 int new_flag;
36 if (!flag)
37 return 0;
38 /* flip flag and store back */
39 new_flag = !*flag;
40 bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY);
41 return new_flag;
42}
43char _license[] SEC("license") = "GPL";
44int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index aa784a498c48..ba6f7526b282 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -12,6 +12,7 @@
12#include "bpf-loader.h" 12#include "bpf-loader.h"
13#include "probe-event.h" 13#include "probe-event.h"
14#include "probe-finder.h" // for MAX_PROBES 14#include "probe-finder.h" // for MAX_PROBES
15#include "llvm-utils.h"
15 16
16#define DEFINE_PRINT_FN(name, level) \ 17#define DEFINE_PRINT_FN(name, level) \
17static int libbpf_##name(const char *fmt, ...) \ 18static int libbpf_##name(const char *fmt, ...) \
@@ -33,7 +34,7 @@ struct bpf_prog_priv {
33 struct perf_probe_event pev; 34 struct perf_probe_event pev;
34}; 35};
35 36
36struct bpf_object *bpf__prepare_load(const char *filename) 37struct bpf_object *bpf__prepare_load(const char *filename, bool source)
37{ 38{
38 struct bpf_object *obj; 39 struct bpf_object *obj;
39 static bool libbpf_initialized; 40 static bool libbpf_initialized;
@@ -45,7 +46,19 @@ struct bpf_object *bpf__prepare_load(const char *filename)
45 libbpf_initialized = true; 46 libbpf_initialized = true;
46 } 47 }
47 48
48 obj = bpf_object__open(filename); 49 if (source) {
50 int err;
51 void *obj_buf;
52 size_t obj_buf_sz;
53
54 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
55 if (err)
56 return ERR_PTR(err);
57 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
58 free(obj_buf);
59 } else
60 obj = bpf_object__open(filename);
61
49 if (!obj) { 62 if (!obj) {
50 pr_debug("bpf: failed to load %s\n", filename); 63 pr_debug("bpf: failed to load %s\n", filename);
51 return ERR_PTR(-EINVAL); 64 return ERR_PTR(-EINVAL);
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index a8f25ee06fc5..ccd8d7fd79d3 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,
18 int fd, void *arg); 18 int fd, void *arg);
19 19
20#ifdef HAVE_LIBBPF_SUPPORT 20#ifdef HAVE_LIBBPF_SUPPORT
21struct bpf_object *bpf__prepare_load(const char *filename); 21struct bpf_object *bpf__prepare_load(const char *filename, bool source);
22 22
23void bpf__clear(void); 23void bpf__clear(void);
24 24
@@ -34,7 +34,8 @@ int bpf__foreach_tev(struct bpf_object *obj,
34 bpf_prog_iter_callback_t func, void *arg); 34 bpf_prog_iter_callback_t func, void *arg);
35#else 35#else
36static inline struct bpf_object * 36static inline struct bpf_object *
37bpf__prepare_load(const char *filename __maybe_unused) 37bpf__prepare_load(const char *filename __maybe_unused,
38 bool source __maybe_unused)
38{ 39{
39 pr_debug("ERROR: eBPF object loading is disabled during compiling.\n"); 40 pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
40 return ERR_PTR(-ENOTSUP); 41 return ERR_PTR(-ENOTSUP);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3ac4ee9c6a6e..397fb4ed3c97 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -208,6 +208,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
208 evsel->unit = ""; 208 evsel->unit = "";
209 evsel->scale = 1.0; 209 evsel->scale = 1.0;
210 evsel->evlist = NULL; 210 evsel->evlist = NULL;
211 evsel->bpf_fd = -1;
211 INIT_LIST_HEAD(&evsel->node); 212 INIT_LIST_HEAD(&evsel->node);
212 INIT_LIST_HEAD(&evsel->config_terms); 213 INIT_LIST_HEAD(&evsel->config_terms);
213 perf_evsel__object.init(evsel); 214 perf_evsel__object.init(evsel);
@@ -1356,6 +1357,22 @@ retry_open:
1356 err); 1357 err);
1357 goto try_fallback; 1358 goto try_fallback;
1358 } 1359 }
1360
1361 if (evsel->bpf_fd >= 0) {
1362 int evt_fd = FD(evsel, cpu, thread);
1363 int bpf_fd = evsel->bpf_fd;
1364
1365 err = ioctl(evt_fd,
1366 PERF_EVENT_IOC_SET_BPF,
1367 bpf_fd);
1368 if (err && errno != EEXIST) {
1369 pr_err("failed to attach bpf fd %d: %s\n",
1370 bpf_fd, strerror(errno));
1371 err = -EINVAL;
1372 goto out_close;
1373 }
1374 }
1375
1359 set_rlimit = NO_CHANGE; 1376 set_rlimit = NO_CHANGE;
1360 1377
1361 /* 1378 /*
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 1e8ff1906f71..0e49bd742c63 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -123,6 +123,7 @@ struct perf_evsel {
123 char *group_name; 123 char *group_name;
124 bool cmdline_group_boundary; 124 bool cmdline_group_boundary;
125 struct list_head config_terms; 125 struct list_head config_terms;
126 int bpf_fd;
126}; 127};
127 128
128union u64_swap { 129union u64_swap {
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d97b03710331..bee60583839a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -542,6 +542,7 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
542 struct __add_bpf_event_param *param = _param; 542 struct __add_bpf_event_param *param = _param;
543 struct parse_events_evlist *evlist = param->data; 543 struct parse_events_evlist *evlist = param->data;
544 struct list_head *list = param->list; 544 struct list_head *list = param->list;
545 struct perf_evsel *pos;
545 int err; 546 int err;
546 547
547 pr_debug("add bpf event %s:%s and attach bpf program %d\n", 548 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
@@ -562,6 +563,11 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
562 } 563 }
563 pr_debug("adding %s:%s\n", tev->group, tev->event); 564 pr_debug("adding %s:%s\n", tev->group, tev->event);
564 565
566 list_for_each_entry(pos, &new_evsels, node) {
567 pr_debug("adding %s:%s to %p\n",
568 tev->group, tev->event, pos);
569 pos->bpf_fd = fd;
570 }
565 list_splice(&new_evsels, list); 571 list_splice(&new_evsels, list);
566 return 0; 572 return 0;
567} 573}
@@ -620,11 +626,12 @@ errout:
620 626
621int parse_events_load_bpf(struct parse_events_evlist *data, 627int parse_events_load_bpf(struct parse_events_evlist *data,
622 struct list_head *list, 628 struct list_head *list,
623 char *bpf_file_name) 629 char *bpf_file_name,
630 bool source)
624{ 631{
625 struct bpf_object *obj; 632 struct bpf_object *obj;
626 633
627 obj = bpf__prepare_load(bpf_file_name); 634 obj = bpf__prepare_load(bpf_file_name, source);
628 if (IS_ERR(obj) || !obj) { 635 if (IS_ERR(obj) || !obj) {
629 char errbuf[BUFSIZ]; 636 char errbuf[BUFSIZ];
630 int err; 637 int err;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 765018a17448..f1a6db107241 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -125,7 +125,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
125 struct list_head *head_config); 125 struct list_head *head_config);
126int parse_events_load_bpf(struct parse_events_evlist *data, 126int parse_events_load_bpf(struct parse_events_evlist *data,
127 struct list_head *list, 127 struct list_head *list,
128 char *bpf_file_name); 128 char *bpf_file_name,
129 bool source);
129/* Provide this function for perf test */ 130/* Provide this function for perf test */
130struct bpf_object; 131struct bpf_object;
131int parse_events_load_bpf_obj(struct parse_events_evlist *data, 132int 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 cf330ebf812c..58c5831ffd5c 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -116,6 +116,7 @@ group [^,{}/]*[{][^}]*[}][^,{}/]*
116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 116event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
117event [^,{}/]+ 117event [^,{}/]+
118bpf_object .*\.(o|bpf) 118bpf_object .*\.(o|bpf)
119bpf_source .*\.c
119 120
120num_dec [0-9]+ 121num_dec [0-9]+
121num_hex 0x[a-fA-F0-9]+ 122num_hex 0x[a-fA-F0-9]+
@@ -161,6 +162,7 @@ modifier_bp [rwx]{1,3}
161 162
162{event_pmu} | 163{event_pmu} |
163{bpf_object} | 164{bpf_object} |
165{bpf_source} |
164{event} { 166{event} {
165 BEGIN(INITIAL); 167 BEGIN(INITIAL);
166 REWIND(1); 168 REWIND(1);
@@ -269,6 +271,7 @@ r{num_raw_hex} { return raw(yyscanner); }
269 271
270{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 272{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
271{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } 273{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
274{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); }
272{name} { return pmu_str_check(yyscanner); } 275{name} { return pmu_str_check(yyscanner); }
273"/" { BEGIN(config); return '/'; } 276"/" { BEGIN(config); return '/'; }
274- { return '-'; } 277- { return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 497f19b20f0b..ad379968d4c1 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,
42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 42%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
43%token PE_EVENT_NAME 43%token PE_EVENT_NAME
44%token PE_NAME 44%token PE_NAME
45%token PE_BPF_OBJECT 45%token PE_BPF_OBJECT PE_BPF_SOURCE
46%token PE_MODIFIER_EVENT PE_MODIFIER_BP 46%token PE_MODIFIER_EVENT PE_MODIFIER_BP
47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -55,6 +55,7 @@ static inc_group_count(struct list_head *list,
55%type <num> PE_TERM 55%type <num> PE_TERM
56%type <str> PE_NAME 56%type <str> PE_NAME
57%type <str> PE_BPF_OBJECT 57%type <str> PE_BPF_OBJECT
58%type <str> PE_BPF_SOURCE
58%type <str> PE_NAME_CACHE_TYPE 59%type <str> PE_NAME_CACHE_TYPE
59%type <str> PE_NAME_CACHE_OP_RESULT 60%type <str> PE_NAME_CACHE_OP_RESULT
60%type <str> PE_MODIFIER_EVENT 61%type <str> PE_MODIFIER_EVENT
@@ -461,7 +462,17 @@ PE_BPF_OBJECT
461 struct list_head *list; 462 struct list_head *list;
462 463
463 ALLOC_LIST(list); 464 ALLOC_LIST(list);
464 ABORT_ON(parse_events_load_bpf(data, list, $1)); 465 ABORT_ON(parse_events_load_bpf(data, list, $1, false));
466 $$ = list;
467}
468|
469PE_BPF_SOURCE
470{
471 struct parse_events_evlist *data = _data;
472 struct list_head *list;
473
474 ALLOC_LIST(list);
475 ABORT_ON(parse_events_load_bpf(data, list, $1, true));
465 $$ = list; 476 $$ = list;
466} 477}
467 478
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index f729f9e99f99..c83832b555e5 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -360,12 +360,15 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
360 int fd = dso__data_get_fd(map->dso, ui->machine); 360 int fd = dso__data_get_fd(map->dso, ui->machine);
361 int is_exec = elf_is_exec(fd, map->dso->name); 361 int is_exec = elf_is_exec(fd, map->dso->name);
362 unw_word_t base = is_exec ? 0 : map->start; 362 unw_word_t base = is_exec ? 0 : map->start;
363 const char *symfile;
363 364
364 if (fd >= 0) 365 if (fd >= 0)
365 dso__data_put_fd(map->dso); 366 dso__data_put_fd(map->dso);
366 367
368 symfile = map->dso->symsrc_filename ?: map->dso->name;
369
367 memset(&di, 0, sizeof(di)); 370 memset(&di, 0, sizeof(di));
368 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 371 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
369 map->start, map->end)) 372 map->start, map->end))
370 return dwarf_search_unwind_table(as, ip, &di, pi, 373 return dwarf_search_unwind_table(as, ip, &di, pi,
371 need_unwind_info, arg); 374 need_unwind_info, arg);