aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-07-14 02:54:13 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-14 02:54:13 -0400
commitb29c6574699dc475da5dbff8db19297b203aacce (patch)
tree688462638604b4d4c405dbf5a9a699bad52c6d9a /tools/perf
parent7b39cafb7aa68ef8e32a9f51fbe737d96084ca74 (diff)
parent8e5dc848356ecf6ea8d27d641c4d7ad8d42fe92b (diff)
Merge tag 'perf-core-for-mingo-20160713' 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: User visible changes: - Finish merging initial SDT (Statically Defined Traces) support, see cset comments for details about how it all works (Masami Hiramatsu) - Support attaching eBPF programs to tracepoints (Wang Nan) Infrastructure changes: - Fix up BITS_PER_LONG setting (Arnaldo Carvalho de Melo) - Add fallback from ELF_C_READ_MMAP to ELF_C_READ in objtool, fixing the build in libelf implementations lacking that elf_begin() cmd, such as Alpine Linux's (Arnaldo Carvalho de Melo) - Avoid checking code drift on busybox's diff in objtool (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-probe.txt11
-rw-r--r--tools/perf/Makefile.perf3
-rw-r--r--tools/perf/builtin-list.c6
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/config/Makefile10
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/make3
-rw-r--r--tools/perf/tests/sdt.c115
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/util/bpf-loader.c73
-rw-r--r--tools/perf/util/bpf-loader.h12
-rw-r--r--tools/perf/util/build-id.c76
-rw-r--r--tools/perf/util/build-id.h3
-rw-r--r--tools/perf/util/parse-events.c110
-rw-r--r--tools/perf/util/parse-events.h4
-rw-r--r--tools/perf/util/probe-event.c309
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-file.c57
-rw-r--r--tools/perf/util/probe-file.h14
20 files changed, 725 insertions, 90 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 7a258e953252..736da44596e4 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -151,6 +151,10 @@ Probe points are defined by following syntax.
151 3) Define event based on source file with lazy pattern 151 3) Define event based on source file with lazy pattern
152 [[GROUP:]EVENT=]SRC;PTN [ARG ...] 152 [[GROUP:]EVENT=]SRC;PTN [ARG ...]
153 153
154 4) Pre-defined SDT events or cached event with name
155 %[sdt_PROVIDER:]SDTEVENT
156 or,
157 sdt_PROVIDER:SDTEVENT
154 158
155'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe. 159'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe.
156Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the 160Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
@@ -158,6 +162,11 @@ modules.
158'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. 162'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function.
159It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. 163It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
160'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). 164'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
165'SDTEVENT' and 'PROVIDER' is the pre-defined event name which is defined by user SDT (Statically Defined Tracing) or the pre-cached probes with event name.
166Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events.
167
168For details of the SDT, see below.
169https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html
161 170
162PROBE ARGUMENT 171PROBE ARGUMENT
163-------------- 172--------------
@@ -237,4 +246,4 @@ Add probes at malloc() function on libc
237 246
238SEE ALSO 247SEE ALSO
239-------- 248--------
240linkperf:perf-trace[1], linkperf:perf-record[1] 249linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index feb2c66b110b..a129fbc1ed37 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak
81# 81#
82# Define NO_LIBBPF if you do not want BPF support 82# Define NO_LIBBPF if you do not want BPF support
83# 83#
84# Define NO_SDT if you do not want to define SDT event in perf tools,
85# note that it doesn't disable SDT scanning support.
86#
84# Define FEATURES_DUMP to provide features detection dump file 87# Define FEATURES_DUMP to provide features detection dump file
85# and bypass the feature detection 88# and bypass the feature detection
86 89
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 5e22db4684b8..88ee419e5189 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -25,7 +25,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
25 OPT_END() 25 OPT_END()
26 }; 26 };
27 const char * const list_usage[] = { 27 const char * const list_usage[] = {
28 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]", 28 "perf list [hw|sw|cache|tracepoint|pmu|sdt|event_glob]",
29 NULL 29 NULL
30 }; 30 };
31 31
@@ -62,6 +62,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
62 print_hwcache_events(NULL, raw_dump); 62 print_hwcache_events(NULL, raw_dump);
63 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
64 print_pmu_events(NULL, raw_dump); 64 print_pmu_events(NULL, raw_dump);
65 else if (strcmp(argv[i], "sdt") == 0)
66 print_sdt_events(NULL, NULL, raw_dump);
65 else if ((sep = strchr(argv[i], ':')) != NULL) { 67 else if ((sep = strchr(argv[i], ':')) != NULL) {
66 int sep_idx; 68 int sep_idx;
67 69
@@ -76,6 +78,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 78
77 s[sep_idx] = '\0'; 79 s[sep_idx] = '\0';
78 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 80 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
81 print_sdt_events(s, s + sep_idx + 1, raw_dump);
79 free(s); 82 free(s);
80 } else { 83 } else {
81 if (asprintf(&s, "*%s*", argv[i]) < 0) { 84 if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -89,6 +92,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
89 print_hwcache_events(s, raw_dump); 92 print_hwcache_events(s, raw_dump);
90 print_pmu_events(s, raw_dump); 93 print_pmu_events(s, raw_dump);
91 print_tracepoint_events(NULL, s, raw_dump); 94 print_tracepoint_events(NULL, s, raw_dump);
95 print_sdt_events(NULL, s, raw_dump);
92 free(s); 96 free(s);
93 } 97 }
94 } 98 }
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c6d890ad2c1a..ee5b42173ba3 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
370 struct str_node *nd; 370 struct str_node *nd;
371 int ret; 371 int ret;
372 372
373 bidlist = build_id_cache__list_all(); 373 bidlist = build_id_cache__list_all(false);
374 if (!bidlist) { 374 if (!bidlist) {
375 ret = -errno; 375 ret = -errno;
376 pr_debug("Failed to get buildids: %d\n", ret); 376 pr_debug("Failed to get buildids: %d\n", ret);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5ac428060779..24803c58049a 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -355,6 +355,16 @@ ifndef NO_LIBELF
355 endif # NO_LIBBPF 355 endif # NO_LIBBPF
356endif # NO_LIBELF 356endif # NO_LIBELF
357 357
358ifndef NO_SDT
359 ifneq ($(feature-sdt), 1)
360 msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev);
361 NO_SDT := 1;
362 else
363 CFLAGS += -DHAVE_SDT_EVENT
364 $(call detected,CONFIG_SDT_EVENT)
365 endif
366endif
367
358ifdef PERF_HAVE_JITDUMP 368ifdef PERF_HAVE_JITDUMP
359 ifndef NO_DWARF 369 ifndef NO_DWARF
360 $(call detected,CONFIG_JITDUMP) 370 $(call detected,CONFIG_JITDUMP)
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 66a28982547b..4158422cc2a6 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -39,6 +39,7 @@ perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o 40perf-y += event-times.o
41perf-y += backward-ring-buffer.o 41perf-y += backward-ring-buffer.o
42perf-y += sdt.o
42 43
43$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 44$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
44 $(call rule_mkdir) 45 $(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index c23cbf733549..4dd2d050788a 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -218,6 +218,10 @@ static struct test generic_tests[] = {
218 .func = test__cpu_map_print, 218 .func = test__cpu_map_print,
219 }, 219 },
220 { 220 {
221 .desc = "Test SDT event probing",
222 .func = test__sdt_event,
223 },
224 {
221 .func = NULL, 225 .func = NULL,
222 }, 226 },
223}; 227};
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 51966d92fc82..143f4d549769 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -82,6 +82,7 @@ make_no_auxtrace := NO_AUXTRACE=1
82make_no_libbpf := NO_LIBBPF=1 82make_no_libbpf := NO_LIBBPF=1
83make_no_libcrypto := NO_LIBCRYPTO=1 83make_no_libcrypto := NO_LIBCRYPTO=1
84make_with_babeltrace:= LIBBABELTRACE=1 84make_with_babeltrace:= LIBBABELTRACE=1
85make_no_sdt := NO_SDT=1
85make_tags := tags 86make_tags := tags
86make_cscope := cscope 87make_cscope := cscope
87make_help := help 88make_help := help
@@ -105,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
105make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 106make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
106make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 107make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
107make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 108make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
108make_minimal += NO_LIBCRYPTO=1 109make_minimal += NO_LIBCRYPTO=1 NO_SDT=1
109 110
110# $(run) contains all available tests 111# $(run) contains all available tests
111run := make_pure 112run := make_pure
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
new file mode 100644
index 000000000000..f59d210e1baf
--- /dev/null
+++ b/tools/perf/tests/sdt.c
@@ -0,0 +1,115 @@
1#include <stdio.h>
2#include <sys/epoll.h>
3#include <util/util.h>
4#include <util/evlist.h>
5#include <linux/filter.h>
6#include "tests.h"
7#include "debug.h"
8#include "probe-file.h"
9#include "build-id.h"
10
11/* To test SDT event, we need libelf support to scan elf binary */
12#if defined(HAVE_SDT_EVENT) && defined(HAVE_LIBELF_SUPPORT)
13
14#include <sys/sdt.h>
15
16static int target_function(void)
17{
18 DTRACE_PROBE(perf, test_target);
19 return TEST_OK;
20}
21
22/* Copied from builtin-buildid-cache.c */
23static int build_id_cache__add_file(const char *filename)
24{
25 char sbuild_id[SBUILD_ID_SIZE];
26 u8 build_id[BUILD_ID_SIZE];
27 int err;
28
29 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
30 if (err < 0) {
31 pr_debug("Failed to read build id of %s\n", filename);
32 return err;
33 }
34
35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
36 err = build_id_cache__add_s(sbuild_id, filename, false, false);
37 if (err < 0)
38 pr_debug("Failed to add build id cache of %s\n", filename);
39 return err;
40}
41
42static char *get_self_path(void)
43{
44 char *buf = calloc(PATH_MAX, sizeof(char));
45
46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) {
47 pr_debug("Failed to get correct path of perf\n");
48 free(buf);
49 return NULL;
50 }
51 return buf;
52}
53
54static int search_cached_probe(const char *target,
55 const char *group, const char *event)
56{
57 struct probe_cache *cache = probe_cache__new(target);
58 int ret = 0;
59
60 if (!cache) {
61 pr_debug("Failed to open probe cache of %s\n", target);
62 return -EINVAL;
63 }
64
65 if (!probe_cache__find_by_name(cache, group, event)) {
66 pr_debug("Failed to find %s:%s in the cache\n", group, event);
67 ret = -ENOENT;
68 }
69 probe_cache__delete(cache);
70
71 return ret;
72}
73
74int test__sdt_event(int subtests __maybe_unused)
75{
76 int ret = TEST_FAIL;
77 char __tempdir[] = "./test-buildid-XXXXXX";
78 char *tempdir = NULL, *myself = get_self_path();
79
80 if (myself == NULL || mkdtemp(__tempdir) == NULL) {
81 pr_debug("Failed to make a tempdir for build-id cache\n");
82 goto error;
83 }
84 /* Note that buildid_dir must be an absolute path */
85 tempdir = realpath(__tempdir, NULL);
86
87 /* At first, scan itself */
88 set_buildid_dir(tempdir);
89 if (build_id_cache__add_file(myself) < 0)
90 goto error_rmdir;
91
92 /* Open a cache and make sure the SDT is stored */
93 if (search_cached_probe(myself, "sdt_perf", "test_target") < 0)
94 goto error_rmdir;
95
96 /* TBD: probing on the SDT event and collect logs */
97
98 /* Call the target and get an event */
99 ret = target_function();
100
101error_rmdir:
102 /* Cleanup temporary buildid dir */
103 rm_rf(tempdir);
104error:
105 free(tempdir);
106 free(myself);
107 return ret;
108}
109#else
110int test__sdt_event(int subtests __maybe_unused)
111{
112 pr_debug("Skip SDT event test because SDT support is not compiled\n");
113 return TEST_SKIP;
114}
115#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 52f969570c97..a0288f8092b2 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -88,6 +88,7 @@ int test__event_update(int subtest);
88int test__event_times(int subtest); 88int test__event_times(int subtest);
89int test__backward_ring_buffer(int subtest); 89int test__backward_ring_buffer(int subtest);
90int test__cpu_map_print(int subtest); 90int test__cpu_map_print(int subtest);
91int test__sdt_event(int subtest);
91 92
92#if defined(__arm__) || defined(__aarch64__) 93#if defined(__arm__) || defined(__aarch64__)
93#ifdef HAVE_DWARF_UNWIND_SUPPORT 94#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 8445e89621fe..1f12e4e40006 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1)
37DEFINE_PRINT_FN(debug, 1) 37DEFINE_PRINT_FN(debug, 1)
38 38
39struct bpf_prog_priv { 39struct bpf_prog_priv {
40 bool is_tp;
41 char *sys_name;
42 char *evt_name;
40 struct perf_probe_event pev; 43 struct perf_probe_event pev;
41 bool need_prologue; 44 bool need_prologue;
42 struct bpf_insn *insns_buf; 45 struct bpf_insn *insns_buf;
@@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused,
118 cleanup_perf_probe_events(&priv->pev, 1); 121 cleanup_perf_probe_events(&priv->pev, 1);
119 zfree(&priv->insns_buf); 122 zfree(&priv->insns_buf);
120 zfree(&priv->type_mapping); 123 zfree(&priv->type_mapping);
124 zfree(&priv->sys_name);
125 zfree(&priv->evt_name);
121 free(priv); 126 free(priv);
122} 127}
123 128
@@ -269,7 +274,8 @@ nextline:
269} 274}
270 275
271static int 276static int
272parse_prog_config(const char *config_str, struct perf_probe_event *pev) 277parse_prog_config(const char *config_str, const char **p_main_str,
278 bool *is_tp, struct perf_probe_event *pev)
273{ 279{
274 int err; 280 int err;
275 const char *main_str = parse_prog_config_kvpair(config_str, pev); 281 const char *main_str = parse_prog_config_kvpair(config_str, pev);
@@ -277,6 +283,22 @@ parse_prog_config(const char *config_str, struct perf_probe_event *pev)
277 if (IS_ERR(main_str)) 283 if (IS_ERR(main_str))
278 return PTR_ERR(main_str); 284 return PTR_ERR(main_str);
279 285
286 *p_main_str = main_str;
287 if (!strchr(main_str, '=')) {
288 /* Is a tracepoint event? */
289 const char *s = strchr(main_str, ':');
290
291 if (!s) {
292 pr_debug("bpf: '%s' is not a valid tracepoint\n",
293 config_str);
294 return -BPF_LOADER_ERRNO__CONFIG;
295 }
296
297 *is_tp = true;
298 return 0;
299 }
300
301 *is_tp = false;
280 err = parse_perf_probe_command(main_str, pev); 302 err = parse_perf_probe_command(main_str, pev);
281 if (err < 0) { 303 if (err < 0) {
282 pr_debug("bpf: '%s' is not a valid config string\n", 304 pr_debug("bpf: '%s' is not a valid config string\n",
@@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog)
292{ 314{
293 struct perf_probe_event *pev = NULL; 315 struct perf_probe_event *pev = NULL;
294 struct bpf_prog_priv *priv = NULL; 316 struct bpf_prog_priv *priv = NULL;
295 const char *config_str; 317 const char *config_str, *main_str;
318 bool is_tp = false;
296 int err; 319 int err;
297 320
298 /* Initialize per-program probing setting */ 321 /* Initialize per-program probing setting */
@@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog)
313 pev = &priv->pev; 336 pev = &priv->pev;
314 337
315 pr_debug("bpf: config program '%s'\n", config_str); 338 pr_debug("bpf: config program '%s'\n", config_str);
316 err = parse_prog_config(config_str, pev); 339 err = parse_prog_config(config_str, &main_str, &is_tp, pev);
317 if (err) 340 if (err)
318 goto errout; 341 goto errout;
319 342
343 if (is_tp) {
344 char *s = strchr(main_str, ':');
345
346 priv->is_tp = true;
347 priv->sys_name = strndup(main_str, s - main_str);
348 priv->evt_name = strdup(s + 1);
349 goto set_priv;
350 }
351
320 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { 352 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
321 pr_debug("bpf: '%s': group for event is set and not '%s'.\n", 353 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
322 config_str, PERF_BPF_PROBE_GROUP); 354 config_str, PERF_BPF_PROBE_GROUP);
@@ -339,6 +371,7 @@ config_bpf_program(struct bpf_program *prog)
339 } 371 }
340 pr_debug("bpf: config '%s' is ok\n", config_str); 372 pr_debug("bpf: config '%s' is ok\n", config_str);
341 373
374set_priv:
342 err = bpf_program__set_priv(prog, priv, clear_prog_priv); 375 err = bpf_program__set_priv(prog, priv, clear_prog_priv);
343 if (err) { 376 if (err) {
344 pr_debug("Failed to set priv for program '%s'\n", config_str); 377 pr_debug("Failed to set priv for program '%s'\n", config_str);
@@ -387,7 +420,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
387 size_t prologue_cnt = 0; 420 size_t prologue_cnt = 0;
388 int i, err; 421 int i, err;
389 422
390 if (IS_ERR(priv) || !priv) 423 if (IS_ERR(priv) || !priv || priv->is_tp)
391 goto errout; 424 goto errout;
392 425
393 pev = &priv->pev; 426 pev = &priv->pev;
@@ -544,6 +577,11 @@ static int hook_load_preprocessor(struct bpf_program *prog)
544 return -BPF_LOADER_ERRNO__INTERNAL; 577 return -BPF_LOADER_ERRNO__INTERNAL;
545 } 578 }
546 579
580 if (priv->is_tp) {
581 priv->need_prologue = false;
582 return 0;
583 }
584
547 pev = &priv->pev; 585 pev = &priv->pev;
548 for (i = 0; i < pev->ntevs; i++) { 586 for (i = 0; i < pev->ntevs; i++) {
549 struct probe_trace_event *tev = &pev->tevs[i]; 587 struct probe_trace_event *tev = &pev->tevs[i];
@@ -610,6 +648,13 @@ int bpf__probe(struct bpf_object *obj)
610 err = PTR_ERR(priv); 648 err = PTR_ERR(priv);
611 goto out; 649 goto out;
612 } 650 }
651
652 if (priv->is_tp) {
653 bpf_program__set_tracepoint(prog);
654 continue;
655 }
656
657 bpf_program__set_kprobe(prog);
613 pev = &priv->pev; 658 pev = &priv->pev;
614 659
615 err = convert_perf_probe_events(pev, 1); 660 err = convert_perf_probe_events(pev, 1);
@@ -650,7 +695,7 @@ int bpf__unprobe(struct bpf_object *obj)
650 struct bpf_prog_priv *priv = bpf_program__priv(prog); 695 struct bpf_prog_priv *priv = bpf_program__priv(prog);
651 int i; 696 int i;
652 697
653 if (IS_ERR(priv) || !priv) 698 if (IS_ERR(priv) || !priv || priv->is_tp)
654 continue; 699 continue;
655 700
656 for (i = 0; i < priv->pev.ntevs; i++) { 701 for (i = 0; i < priv->pev.ntevs; i++) {
@@ -693,9 +738,9 @@ int bpf__load(struct bpf_object *obj)
693 return 0; 738 return 0;
694} 739}
695 740
696int bpf__foreach_tev(struct bpf_object *obj, 741int bpf__foreach_event(struct bpf_object *obj,
697 bpf_prog_iter_callback_t func, 742 bpf_prog_iter_callback_t func,
698 void *arg) 743 void *arg)
699{ 744{
700 struct bpf_program *prog; 745 struct bpf_program *prog;
701 int err; 746 int err;
@@ -711,6 +756,16 @@ int bpf__foreach_tev(struct bpf_object *obj,
711 return -BPF_LOADER_ERRNO__INTERNAL; 756 return -BPF_LOADER_ERRNO__INTERNAL;
712 } 757 }
713 758
759 if (priv->is_tp) {
760 fd = bpf_program__fd(prog);
761 err = (*func)(priv->sys_name, priv->evt_name, fd, arg);
762 if (err) {
763 pr_debug("bpf: tracepoint call back failed, stop iterate\n");
764 return err;
765 }
766 continue;
767 }
768
714 pev = &priv->pev; 769 pev = &priv->pev;
715 for (i = 0; i < pev->ntevs; i++) { 770 for (i = 0; i < pev->ntevs; i++) {
716 tev = &pev->tevs[i]; 771 tev = &pev->tevs[i];
@@ -728,7 +783,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
728 return fd; 783 return fd;
729 } 784 }
730 785
731 err = (*func)(tev, fd, arg); 786 err = (*func)(tev->group, tev->event, fd, arg);
732 if (err) { 787 if (err) {
733 pr_debug("bpf: call back failed, stop iterate\n"); 788 pr_debug("bpf: call back failed, stop iterate\n");
734 return err; 789 return err;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 941e17275aa7..f2b737b225f2 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -46,7 +46,7 @@ struct bpf_object;
46struct parse_events_term; 46struct parse_events_term;
47#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" 47#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
48 48
49typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, 49typedef int (*bpf_prog_iter_callback_t)(const char *group, const char *event,
50 int fd, void *arg); 50 int fd, void *arg);
51 51
52#ifdef HAVE_LIBBPF_SUPPORT 52#ifdef HAVE_LIBBPF_SUPPORT
@@ -67,8 +67,8 @@ int bpf__strerror_probe(struct bpf_object *obj, int err,
67int bpf__load(struct bpf_object *obj); 67int bpf__load(struct bpf_object *obj);
68int bpf__strerror_load(struct bpf_object *obj, int err, 68int bpf__strerror_load(struct bpf_object *obj, int err,
69 char *buf, size_t size); 69 char *buf, size_t size);
70int bpf__foreach_tev(struct bpf_object *obj, 70int bpf__foreach_event(struct bpf_object *obj,
71 bpf_prog_iter_callback_t func, void *arg); 71 bpf_prog_iter_callback_t func, void *arg);
72 72
73int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, 73int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term,
74 struct perf_evlist *evlist, int *error_pos); 74 struct perf_evlist *evlist, int *error_pos);
@@ -107,9 +107,9 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0
107static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; } 107static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
108 108
109static inline int 109static inline int
110bpf__foreach_tev(struct bpf_object *obj __maybe_unused, 110bpf__foreach_event(struct bpf_object *obj __maybe_unused,
111 bpf_prog_iter_callback_t func __maybe_unused, 111 bpf_prog_iter_callback_t func __maybe_unused,
112 void *arg __maybe_unused) 112 void *arg __maybe_unused)
113{ 113{
114 return 0; 114 return 0;
115} 115}
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 1e504e40dac8..5651f3c12f93 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -206,6 +206,31 @@ out:
206 return ret; 206 return ret;
207} 207}
208 208
209/* Check if the given build_id cache is valid on current running system */
210static bool build_id_cache__valid_id(char *sbuild_id)
211{
212 char real_sbuild_id[SBUILD_ID_SIZE] = "";
213 char *pathname;
214 int ret = 0;
215 bool result = false;
216
217 pathname = build_id_cache__origname(sbuild_id);
218 if (!pathname)
219 return false;
220
221 if (!strcmp(pathname, DSO__NAME_KALLSYMS))
222 ret = sysfs__sprintf_build_id("/", real_sbuild_id);
223 else if (pathname[0] == '/')
224 ret = filename__sprintf_build_id(pathname, real_sbuild_id);
225 else
226 ret = -EINVAL; /* Should we support other special DSO cache? */
227 if (ret >= 0)
228 result = (strcmp(sbuild_id, real_sbuild_id) == 0);
229 free(pathname);
230
231 return result;
232}
233
209static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso) 234static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
210{ 235{
211 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf"); 236 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
433 return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0'); 458 return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
434} 459}
435 460
436struct strlist *build_id_cache__list_all(void) 461struct strlist *build_id_cache__list_all(bool validonly)
437{ 462{
438 struct strlist *toplist, *linklist = NULL, *bidlist; 463 struct strlist *toplist, *linklist = NULL, *bidlist;
439 struct str_node *nd, *nd2; 464 struct str_node *nd, *nd2;
440 char *topdir, *linkdir = NULL; 465 char *topdir, *linkdir = NULL;
441 char sbuild_id[SBUILD_ID_SIZE]; 466 char sbuild_id[SBUILD_ID_SIZE];
442 467
468 /* for filename__ functions */
469 if (validonly)
470 symbol__init(NULL);
471
443 /* Open the top-level directory */ 472 /* Open the top-level directory */
444 if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0) 473 if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
445 return NULL; 474 return NULL;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)
470 if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s", 499 if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
471 nd->s, nd2->s) != SBUILD_ID_SIZE - 1) 500 nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
472 goto err_out; 501 goto err_out;
502 if (validonly && !build_id_cache__valid_id(sbuild_id))
503 continue;
473 if (strlist__add(bidlist, sbuild_id) < 0) 504 if (strlist__add(bidlist, sbuild_id) < 0)
474 goto err_out; 505 goto err_out;
475 } 506 }
@@ -492,6 +523,49 @@ err_out:
492 goto out_free; 523 goto out_free;
493} 524}
494 525
526static bool str_is_build_id(const char *maybe_sbuild_id, size_t len)
527{
528 size_t i;
529
530 for (i = 0; i < len; i++) {
531 if (!isxdigit(maybe_sbuild_id[i]))
532 return false;
533 }
534 return true;
535}
536
537/* Return the valid complete build-id */
538char *build_id_cache__complement(const char *incomplete_sbuild_id)
539{
540 struct strlist *bidlist;
541 struct str_node *nd, *cand = NULL;
542 char *sbuild_id = NULL;
543 size_t len = strlen(incomplete_sbuild_id);
544
545 if (len >= SBUILD_ID_SIZE ||
546 !str_is_build_id(incomplete_sbuild_id, len))
547 return NULL;
548
549 bidlist = build_id_cache__list_all(true);
550 if (!bidlist)
551 return NULL;
552
553 strlist__for_each_entry(nd, bidlist) {
554 if (strncmp(nd->s, incomplete_sbuild_id, len) != 0)
555 continue;
556 if (cand) { /* Error: There are more than 2 candidates. */
557 cand = NULL;
558 break;
559 }
560 cand = nd;
561 }
562 if (cand)
563 sbuild_id = strdup(cand->s);
564 strlist__delete(bidlist);
565
566 return sbuild_id;
567}
568
495char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 569char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
496 bool is_kallsyms, bool is_vdso) 570 bool is_kallsyms, bool is_vdso)
497{ 571{
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index b742e271ea2c..d27990610f9f 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -34,7 +34,8 @@ char *build_id_cache__origname(const char *sbuild_id);
34char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); 34char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
35char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 35char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
36 bool is_kallsyms, bool is_vdso); 36 bool is_kallsyms, bool is_vdso);
37struct strlist *build_id_cache__list_all(void); 37struct strlist *build_id_cache__list_all(bool validonly);
38char *build_id_cache__complement(const char *incomplete_sbuild_id);
38int build_id_cache__list_build_ids(const char *pathname, 39int build_id_cache__list_build_ids(const char *pathname,
39 struct strlist **result); 40 struct strlist **result);
40bool build_id_cache__cached(const char *sbuild_id); 41bool build_id_cache__cached(const char *sbuild_id);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index ebd87b773f56..375af0e02831 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -20,6 +20,7 @@
20#include "pmu.h" 20#include "pmu.h"
21#include "thread_map.h" 21#include "thread_map.h"
22#include "cpumap.h" 22#include "cpumap.h"
23#include "probe-file.h"
23#include "asm/bug.h" 24#include "asm/bug.h"
24 25
25#define MAX_NAME_LEN 100 26#define MAX_NAME_LEN 100
@@ -436,7 +437,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
436} 437}
437 438
438static void tracepoint_error(struct parse_events_error *e, int err, 439static void tracepoint_error(struct parse_events_error *e, int err,
439 char *sys, char *name) 440 const char *sys, const char *name)
440{ 441{
441 char help[BUFSIZ]; 442 char help[BUFSIZ];
442 443
@@ -466,7 +467,7 @@ static void tracepoint_error(struct parse_events_error *e, int err,
466} 467}
467 468
468static int add_tracepoint(struct list_head *list, int *idx, 469static int add_tracepoint(struct list_head *list, int *idx,
469 char *sys_name, char *evt_name, 470 const char *sys_name, const char *evt_name,
470 struct parse_events_error *err, 471 struct parse_events_error *err,
471 struct list_head *head_config) 472 struct list_head *head_config)
472{ 473{
@@ -491,7 +492,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
491} 492}
492 493
493static int add_tracepoint_multi_event(struct list_head *list, int *idx, 494static int add_tracepoint_multi_event(struct list_head *list, int *idx,
494 char *sys_name, char *evt_name, 495 const char *sys_name, const char *evt_name,
495 struct parse_events_error *err, 496 struct parse_events_error *err,
496 struct list_head *head_config) 497 struct list_head *head_config)
497{ 498{
@@ -533,7 +534,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
533} 534}
534 535
535static int add_tracepoint_event(struct list_head *list, int *idx, 536static int add_tracepoint_event(struct list_head *list, int *idx,
536 char *sys_name, char *evt_name, 537 const char *sys_name, const char *evt_name,
537 struct parse_events_error *err, 538 struct parse_events_error *err,
538 struct list_head *head_config) 539 struct list_head *head_config)
539{ 540{
@@ -545,7 +546,7 @@ static int add_tracepoint_event(struct list_head *list, int *idx,
545} 546}
546 547
547static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 548static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
548 char *sys_name, char *evt_name, 549 const char *sys_name, const char *evt_name,
549 struct parse_events_error *err, 550 struct parse_events_error *err,
550 struct list_head *head_config) 551 struct list_head *head_config)
551{ 552{
@@ -584,7 +585,7 @@ struct __add_bpf_event_param {
584 struct list_head *head_config; 585 struct list_head *head_config;
585}; 586};
586 587
587static int add_bpf_event(struct probe_trace_event *tev, int fd, 588static int add_bpf_event(const char *group, const char *event, int fd,
588 void *_param) 589 void *_param)
589{ 590{
590 LIST_HEAD(new_evsels); 591 LIST_HEAD(new_evsels);
@@ -595,27 +596,27 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
595 int err; 596 int err;
596 597
597 pr_debug("add bpf event %s:%s and attach bpf program %d\n", 598 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
598 tev->group, tev->event, fd); 599 group, event, fd);
599 600
600 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, 601 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, group,
601 tev->event, evlist->error, 602 event, evlist->error,
602 param->head_config); 603 param->head_config);
603 if (err) { 604 if (err) {
604 struct perf_evsel *evsel, *tmp; 605 struct perf_evsel *evsel, *tmp;
605 606
606 pr_debug("Failed to add BPF event %s:%s\n", 607 pr_debug("Failed to add BPF event %s:%s\n",
607 tev->group, tev->event); 608 group, event);
608 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { 609 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
609 list_del(&evsel->node); 610 list_del(&evsel->node);
610 perf_evsel__delete(evsel); 611 perf_evsel__delete(evsel);
611 } 612 }
612 return err; 613 return err;
613 } 614 }
614 pr_debug("adding %s:%s\n", tev->group, tev->event); 615 pr_debug("adding %s:%s\n", group, event);
615 616
616 list_for_each_entry(pos, &new_evsels, node) { 617 list_for_each_entry(pos, &new_evsels, node) {
617 pr_debug("adding %s:%s to %p\n", 618 pr_debug("adding %s:%s to %p\n",
618 tev->group, tev->event, pos); 619 group, event, pos);
619 pos->bpf_fd = fd; 620 pos->bpf_fd = fd;
620 } 621 }
621 list_splice(&new_evsels, list); 622 list_splice(&new_evsels, list);
@@ -661,7 +662,7 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
661 goto errout; 662 goto errout;
662 } 663 }
663 664
664 err = bpf__foreach_tev(obj, add_bpf_event, &param); 665 err = bpf__foreach_event(obj, add_bpf_event, &param);
665 if (err) { 666 if (err) {
666 snprintf(errbuf, sizeof(errbuf), 667 snprintf(errbuf, sizeof(errbuf),
667 "Attach events in BPF object failed"); 668 "Attach events in BPF object failed");
@@ -1126,7 +1127,7 @@ do { \
1126} 1127}
1127 1128
1128int parse_events_add_tracepoint(struct list_head *list, int *idx, 1129int parse_events_add_tracepoint(struct list_head *list, int *idx,
1129 char *sys, char *event, 1130 const char *sys, const char *event,
1130 struct parse_events_error *err, 1131 struct parse_events_error *err,
1131 struct list_head *head_config) 1132 struct list_head *head_config)
1132{ 1133{
@@ -1984,6 +1985,85 @@ static bool is_event_supported(u8 type, unsigned config)
1984 return ret; 1985 return ret;
1985} 1986}
1986 1987
1988void print_sdt_events(const char *subsys_glob, const char *event_glob,
1989 bool name_only)
1990{
1991 struct probe_cache *pcache;
1992 struct probe_cache_entry *ent;
1993 struct strlist *bidlist, *sdtlist;
1994 struct strlist_config cfg = {.dont_dupstr = true};
1995 struct str_node *nd, *nd2;
1996 char *buf, *path, *ptr = NULL;
1997 bool show_detail = false;
1998 int ret;
1999
2000 sdtlist = strlist__new(NULL, &cfg);
2001 if (!sdtlist) {
2002 pr_debug("Failed to allocate new strlist for SDT\n");
2003 return;
2004 }
2005 bidlist = build_id_cache__list_all(true);
2006 if (!bidlist) {
2007 pr_debug("Failed to get buildids: %d\n", errno);
2008 return;
2009 }
2010 strlist__for_each_entry(nd, bidlist) {
2011 pcache = probe_cache__new(nd->s);
2012 if (!pcache)
2013 continue;
2014 list_for_each_entry(ent, &pcache->entries, node) {
2015 if (!ent->sdt)
2016 continue;
2017 if (subsys_glob &&
2018 !strglobmatch(ent->pev.group, subsys_glob))
2019 continue;
2020 if (event_glob &&
2021 !strglobmatch(ent->pev.event, event_glob))
2022 continue;
2023 ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
2024 ent->pev.event, nd->s);
2025 if (ret > 0)
2026 strlist__add(sdtlist, buf);
2027 }
2028 probe_cache__delete(pcache);
2029 }
2030 strlist__delete(bidlist);
2031
2032 strlist__for_each_entry(nd, sdtlist) {
2033 buf = strchr(nd->s, '@');
2034 if (buf)
2035 *(buf++) = '\0';
2036 if (name_only) {
2037 printf("%s ", nd->s);
2038 continue;
2039 }
2040 nd2 = strlist__next(nd);
2041 if (nd2) {
2042 ptr = strchr(nd2->s, '@');
2043 if (ptr)
2044 *ptr = '\0';
2045 if (strcmp(nd->s, nd2->s) == 0)
2046 show_detail = true;
2047 }
2048 if (show_detail) {
2049 path = build_id_cache__origname(buf);
2050 ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
2051 if (ret > 0) {
2052 printf(" %-50s [%s]\n", buf, "SDT event");
2053 free(buf);
2054 }
2055 } else
2056 printf(" %-50s [%s]\n", nd->s, "SDT event");
2057 if (nd2) {
2058 if (strcmp(nd->s, nd2->s) != 0)
2059 show_detail = false;
2060 if (ptr)
2061 *ptr = '@';
2062 }
2063 }
2064 strlist__delete(sdtlist);
2065}
2066
1987int print_hwcache_events(const char *event_glob, bool name_only) 2067int print_hwcache_events(const char *event_glob, bool name_only)
1988{ 2068{
1989 unsigned int type, op, i, evt_i = 0, evt_num = 0; 2069 unsigned int type, op, i, evt_i = 0, evt_num = 0;
@@ -2166,6 +2246,8 @@ void print_events(const char *event_glob, bool name_only)
2166 } 2246 }
2167 2247
2168 print_tracepoint_events(NULL, NULL, name_only); 2248 print_tracepoint_events(NULL, NULL, name_only);
2249
2250 print_sdt_events(NULL, NULL, name_only);
2169} 2251}
2170 2252
2171int parse_events__is_hardcoded_term(struct parse_events_term *term) 2253int parse_events__is_hardcoded_term(struct parse_events_term *term)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 46c05ccd5dfe..b4aa7eb2df73 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -134,7 +134,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
134int parse_events__modifier_group(struct list_head *list, char *event_mod); 134int parse_events__modifier_group(struct list_head *list, char *event_mod);
135int parse_events_name(struct list_head *list, char *name); 135int parse_events_name(struct list_head *list, char *name);
136int parse_events_add_tracepoint(struct list_head *list, int *idx, 136int parse_events_add_tracepoint(struct list_head *list, int *idx,
137 char *sys, char *event, 137 const char *sys, const char *event,
138 struct parse_events_error *error, 138 struct parse_events_error *error,
139 struct list_head *head_config); 139 struct list_head *head_config);
140int parse_events_load_bpf(struct parse_events_evlist *data, 140int parse_events_load_bpf(struct parse_events_evlist *data,
@@ -183,6 +183,8 @@ void print_symbol_events(const char *event_glob, unsigned type,
183void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 183void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
184 bool name_only); 184 bool name_only);
185int print_hwcache_events(const char *event_glob, bool name_only); 185int print_hwcache_events(const char *event_glob, bool name_only);
186void print_sdt_events(const char *subsys_glob, const char *event_glob,
187 bool name_only);
186int is_valid_tracepoint(const char *event_string); 188int is_valid_tracepoint(const char *event_string);
187 189
188int valid_event_mount(const char *eventfs); 190int valid_event_mount(const char *eventfs);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 2b222a7955c9..d4f8835c0a27 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1197,6 +1197,34 @@ err:
1197 return err; 1197 return err;
1198} 1198}
1199 1199
1200static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
1201{
1202 char *ptr;
1203
1204 ptr = strchr(*arg, ':');
1205 if (ptr) {
1206 *ptr = '\0';
1207 if (!pev->sdt && !is_c_func_name(*arg))
1208 goto ng_name;
1209 pev->group = strdup(*arg);
1210 if (!pev->group)
1211 return -ENOMEM;
1212 *arg = ptr + 1;
1213 } else
1214 pev->group = NULL;
1215 if (!pev->sdt && !is_c_func_name(*arg)) {
1216ng_name:
1217 semantic_error("%s is bad for event name -it must "
1218 "follow C symbol-naming rule.\n", *arg);
1219 return -EINVAL;
1220 }
1221 pev->event = strdup(*arg);
1222 if (pev->event == NULL)
1223 return -ENOMEM;
1224
1225 return 0;
1226}
1227
1200/* Parse probepoint definition. */ 1228/* Parse probepoint definition. */
1201static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1229static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1202{ 1230{
@@ -1204,38 +1232,64 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1204 char *ptr, *tmp; 1232 char *ptr, *tmp;
1205 char c, nc = 0; 1233 char c, nc = 0;
1206 bool file_spec = false; 1234 bool file_spec = false;
1235 int ret;
1236
1207 /* 1237 /*
1208 * <Syntax> 1238 * <Syntax>
1209 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN] 1239 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
1210 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 1240 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
1241 * perf probe %[GRP:]SDT_EVENT
1211 */ 1242 */
1212 if (!arg) 1243 if (!arg)
1213 return -EINVAL; 1244 return -EINVAL;
1214 1245
1246 /*
1247 * If the probe point starts with '%',
1248 * or starts with "sdt_" and has a ':' but no '=',
1249 * then it should be a SDT/cached probe point.
1250 */
1251 if (arg[0] == '%' ||
1252 (!strncmp(arg, "sdt_", 4) &&
1253 !!strchr(arg, ':') && !strchr(arg, '='))) {
1254 pev->sdt = true;
1255 if (arg[0] == '%')
1256 arg++;
1257 }
1258
1215 ptr = strpbrk(arg, ";=@+%"); 1259 ptr = strpbrk(arg, ";=@+%");
1216 if (ptr && *ptr == '=') { /* Event name */ 1260 if (pev->sdt) {
1217 *ptr = '\0';
1218 tmp = ptr + 1;
1219 ptr = strchr(arg, ':');
1220 if (ptr) { 1261 if (ptr) {
1221 *ptr = '\0'; 1262 if (*ptr != '@') {
1222 if (!is_c_func_name(arg)) 1263 semantic_error("%s must be an SDT name.\n",
1223 goto not_fname; 1264 arg);
1224 pev->group = strdup(arg); 1265 return -EINVAL;
1225 if (!pev->group) 1266 }
1267 /* This must be a target file name or build id */
1268 tmp = build_id_cache__complement(ptr + 1);
1269 if (tmp) {
1270 pev->target = build_id_cache__origname(tmp);
1271 free(tmp);
1272 } else
1273 pev->target = strdup(ptr + 1);
1274 if (!pev->target)
1226 return -ENOMEM; 1275 return -ENOMEM;
1227 arg = ptr + 1; 1276 *ptr = '\0';
1228 } else
1229 pev->group = NULL;
1230 if (!is_c_func_name(arg)) {
1231not_fname:
1232 semantic_error("%s is bad for event name -it must "
1233 "follow C symbol-naming rule.\n", arg);
1234 return -EINVAL;
1235 } 1277 }
1236 pev->event = strdup(arg); 1278 ret = parse_perf_probe_event_name(&arg, pev);
1237 if (pev->event == NULL) 1279 if (ret == 0) {
1238 return -ENOMEM; 1280 if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
1281 ret = -errno;
1282 }
1283 return ret;
1284 }
1285
1286 if (ptr && *ptr == '=') { /* Event name */
1287 *ptr = '\0';
1288 tmp = ptr + 1;
1289 ret = parse_perf_probe_event_name(&arg, pev);
1290 if (ret < 0)
1291 return ret;
1292
1239 arg = tmp; 1293 arg = tmp;
1240 } 1294 }
1241 1295
@@ -1547,7 +1601,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1547 return true; 1601 return true;
1548 1602
1549 for (i = 0; i < pev->nargs; i++) 1603 for (i = 0; i < pev->nargs; i++)
1550 if (is_c_varname(pev->args[i].var)) 1604 if (is_c_varname(pev->args[i].var) ||
1605 !strcmp(pev->args[i].var, "$params") ||
1606 !strcmp(pev->args[i].var, "$vars"))
1551 return true; 1607 return true;
1552 1608
1553 return false; 1609 return false;
@@ -1609,6 +1665,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
1609 ret = -ENOMEM; 1665 ret = -ENOMEM;
1610 goto out; 1666 goto out;
1611 } 1667 }
1668 tev->uprobes = (tp->module[0] == '/');
1612 p++; 1669 p++;
1613 } else 1670 } else
1614 p = argv[1]; 1671 p = argv[1];
@@ -2483,7 +2540,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2483 int ret; 2540 int ret;
2484 2541
2485 /* If probe_event or trace_event already have the name, reuse it */ 2542 /* If probe_event or trace_event already have the name, reuse it */
2486 if (pev->event) 2543 if (pev->event && !pev->sdt)
2487 event = pev->event; 2544 event = pev->event;
2488 else if (tev->event) 2545 else if (tev->event)
2489 event = tev->event; 2546 event = tev->event;
@@ -2496,7 +2553,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2496 else 2553 else
2497 event = tev->point.realname; 2554 event = tev->point.realname;
2498 } 2555 }
2499 if (pev->group) 2556 if (pev->group && !pev->sdt)
2500 group = pev->group; 2557 group = pev->group;
2501 else if (tev->group) 2558 else if (tev->group)
2502 group = tev->group; 2559 group = tev->group;
@@ -2521,41 +2578,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2521 return 0; 2578 return 0;
2522} 2579}
2523 2580
2524static int __add_probe_trace_events(struct perf_probe_event *pev, 2581static int __open_probe_file_and_namelist(bool uprobe,
2525 struct probe_trace_event *tevs, 2582 struct strlist **namelist)
2526 int ntevs, bool allow_suffix)
2527{ 2583{
2528 int i, fd, ret; 2584 int fd;
2529 struct probe_trace_event *tev = NULL;
2530 struct probe_cache *cache = NULL;
2531 struct strlist *namelist;
2532 2585
2533 fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); 2586 fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0));
2534 if (fd < 0) 2587 if (fd < 0)
2535 return fd; 2588 return fd;
2536 2589
2537 /* Get current event names */ 2590 /* Get current event names */
2538 namelist = probe_file__get_namelist(fd); 2591 *namelist = probe_file__get_namelist(fd);
2539 if (!namelist) { 2592 if (!(*namelist)) {
2540 pr_debug("Failed to get current event list.\n"); 2593 pr_debug("Failed to get current event list.\n");
2541 ret = -ENOMEM; 2594 close(fd);
2542 goto close_out; 2595 return -ENOMEM;
2543 } 2596 }
2597 return fd;
2598}
2599
2600static int __add_probe_trace_events(struct perf_probe_event *pev,
2601 struct probe_trace_event *tevs,
2602 int ntevs, bool allow_suffix)
2603{
2604 int i, fd[2] = {-1, -1}, up, ret;
2605 struct probe_trace_event *tev = NULL;
2606 struct probe_cache *cache = NULL;
2607 struct strlist *namelist[2] = {NULL, NULL};
2608
2609 up = pev->uprobes ? 1 : 0;
2610 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
2611 if (fd[up] < 0)
2612 return fd[up];
2544 2613
2545 ret = 0; 2614 ret = 0;
2546 for (i = 0; i < ntevs; i++) { 2615 for (i = 0; i < ntevs; i++) {
2547 tev = &tevs[i]; 2616 tev = &tevs[i];
2617 up = tev->uprobes ? 1 : 0;
2618 if (fd[up] == -1) { /* Open the kprobe/uprobe_events */
2619 fd[up] = __open_probe_file_and_namelist(up,
2620 &namelist[up]);
2621 if (fd[up] < 0)
2622 goto close_out;
2623 }
2548 /* Skip if the symbol is out of .text or blacklisted */ 2624 /* Skip if the symbol is out of .text or blacklisted */
2549 if (!tev->point.symbol && !pev->uprobes) 2625 if (!tev->point.symbol && !pev->uprobes)
2550 continue; 2626 continue;
2551 2627
2552 /* Set new name for tev (and update namelist) */ 2628 /* Set new name for tev (and update namelist) */
2553 ret = probe_trace_event__set_name(tev, pev, namelist, 2629 ret = probe_trace_event__set_name(tev, pev, namelist[up],
2554 allow_suffix); 2630 allow_suffix);
2555 if (ret < 0) 2631 if (ret < 0)
2556 break; 2632 break;
2557 2633
2558 ret = probe_file__add_event(fd, tev); 2634 ret = probe_file__add_event(fd[up], tev);
2559 if (ret < 0) 2635 if (ret < 0)
2560 break; 2636 break;
2561 2637
@@ -2578,9 +2654,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2578 probe_cache__delete(cache); 2654 probe_cache__delete(cache);
2579 } 2655 }
2580 2656
2581 strlist__delete(namelist);
2582close_out: 2657close_out:
2583 close(fd); 2658 for (up = 0; up < 2; up++) {
2659 strlist__delete(namelist[up]);
2660 if (fd[up] >= 0)
2661 close(fd[up]);
2662 }
2584 return ret; 2663 return ret;
2585} 2664}
2586 2665
@@ -2859,6 +2938,142 @@ errout:
2859 2938
2860bool __weak arch__prefers_symtab(void) { return false; } 2939bool __weak arch__prefers_symtab(void) { return false; }
2861 2940
2941/* Concatinate two arrays */
2942static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
2943{
2944 void *ret;
2945
2946 ret = malloc(sz_a + sz_b);
2947 if (ret) {
2948 memcpy(ret, a, sz_a);
2949 memcpy(ret + sz_a, b, sz_b);
2950 }
2951 return ret;
2952}
2953
2954static int
2955concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
2956 struct probe_trace_event **tevs2, int ntevs2)
2957{
2958 struct probe_trace_event *new_tevs;
2959 int ret = 0;
2960
2961 if (ntevs == 0) {
2962 *tevs = *tevs2;
2963 *ntevs = ntevs2;
2964 *tevs2 = NULL;
2965 return 0;
2966 }
2967
2968 if (*ntevs + ntevs2 > probe_conf.max_probes)
2969 ret = -E2BIG;
2970 else {
2971 /* Concatinate the array of probe_trace_event */
2972 new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
2973 *tevs2, ntevs2 * sizeof(**tevs2));
2974 if (!new_tevs)
2975 ret = -ENOMEM;
2976 else {
2977 free(*tevs);
2978 *tevs = new_tevs;
2979 *ntevs += ntevs2;
2980 }
2981 }
2982 if (ret < 0)
2983 clear_probe_trace_events(*tevs2, ntevs2);
2984 zfree(tevs2);
2985
2986 return ret;
2987}
2988
2989/*
2990 * Try to find probe_trace_event from given probe caches. Return the number
2991 * of cached events found, if an error occurs return the error.
2992 */
2993static int find_cached_events(struct perf_probe_event *pev,
2994 struct probe_trace_event **tevs,
2995 const char *target)
2996{
2997 struct probe_cache *cache;
2998 struct probe_cache_entry *entry;
2999 struct probe_trace_event *tmp_tevs = NULL;
3000 int ntevs = 0;
3001 int ret = 0;
3002
3003 cache = probe_cache__new(target);
3004 /* Return 0 ("not found") if the target has no probe cache. */
3005 if (!cache)
3006 return 0;
3007
3008 for_each_probe_cache_entry(entry, cache) {
3009 /* Skip the cache entry which has no name */
3010 if (!entry->pev.event || !entry->pev.group)
3011 continue;
3012 if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) &&
3013 strglobmatch(entry->pev.event, pev->event)) {
3014 ret = probe_cache_entry__get_event(entry, &tmp_tevs);
3015 if (ret > 0)
3016 ret = concat_probe_trace_events(tevs, &ntevs,
3017 &tmp_tevs, ret);
3018 if (ret < 0)
3019 break;
3020 }
3021 }
3022 probe_cache__delete(cache);
3023 if (ret < 0) {
3024 clear_probe_trace_events(*tevs, ntevs);
3025 zfree(tevs);
3026 } else {
3027 ret = ntevs;
3028 if (ntevs > 0 && target && target[0] == '/')
3029 pev->uprobes = true;
3030 }
3031
3032 return ret;
3033}
3034
3035/* Try to find probe_trace_event from all probe caches */
3036static int find_cached_events_all(struct perf_probe_event *pev,
3037 struct probe_trace_event **tevs)
3038{
3039 struct probe_trace_event *tmp_tevs = NULL;
3040 struct strlist *bidlist;
3041 struct str_node *nd;
3042 char *pathname;
3043 int ntevs = 0;
3044 int ret;
3045
3046 /* Get the buildid list of all valid caches */
3047 bidlist = build_id_cache__list_all(true);
3048 if (!bidlist) {
3049 ret = -errno;
3050 pr_debug("Failed to get buildids: %d\n", ret);
3051 return ret;
3052 }
3053
3054 ret = 0;
3055 strlist__for_each_entry(nd, bidlist) {
3056 pathname = build_id_cache__origname(nd->s);
3057 ret = find_cached_events(pev, &tmp_tevs, pathname);
3058 /* In the case of cnt == 0, we just skip it */
3059 if (ret > 0)
3060 ret = concat_probe_trace_events(tevs, &ntevs,
3061 &tmp_tevs, ret);
3062 free(pathname);
3063 if (ret < 0)
3064 break;
3065 }
3066 strlist__delete(bidlist);
3067
3068 if (ret < 0) {
3069 clear_probe_trace_events(*tevs, ntevs);
3070 zfree(tevs);
3071 } else
3072 ret = ntevs;
3073
3074 return ret;
3075}
3076
2862static int find_probe_trace_events_from_cache(struct perf_probe_event *pev, 3077static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
2863 struct probe_trace_event **tevs) 3078 struct probe_trace_event **tevs)
2864{ 3079{
@@ -2868,13 +3083,21 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
2868 struct str_node *node; 3083 struct str_node *node;
2869 int ret, i; 3084 int ret, i;
2870 3085
3086 if (pev->sdt) {
3087 /* For SDT/cached events, we use special search functions */
3088 if (!pev->target)
3089 return find_cached_events_all(pev, tevs);
3090 else
3091 return find_cached_events(pev, tevs, pev->target);
3092 }
2871 cache = probe_cache__new(pev->target); 3093 cache = probe_cache__new(pev->target);
2872 if (!cache) 3094 if (!cache)
2873 return 0; 3095 return 0;
2874 3096
2875 entry = probe_cache__find(cache, pev); 3097 entry = probe_cache__find(cache, pev);
2876 if (!entry) { 3098 if (!entry) {
2877 ret = 0; 3099 /* SDT must be in the cache */
3100 ret = pev->sdt ? -ENOENT : 0;
2878 goto out; 3101 goto out;
2879 } 3102 }
2880 3103
@@ -2913,7 +3136,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2913{ 3136{
2914 int ret; 3137 int ret;
2915 3138
2916 if (!pev->group) { 3139 if (!pev->group && !pev->sdt) {
2917 /* Set group name if not given */ 3140 /* Set group name if not given */
2918 if (!pev->uprobes) { 3141 if (!pev->uprobes) {
2919 pev->group = strdup(PERFPROBE_GROUP); 3142 pev->group = strdup(PERFPROBE_GROUP);
@@ -2932,8 +3155,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2932 3155
2933 /* At first, we need to lookup cache entry */ 3156 /* At first, we need to lookup cache entry */
2934 ret = find_probe_trace_events_from_cache(pev, tevs); 3157 ret = find_probe_trace_events_from_cache(pev, tevs);
2935 if (ret > 0) 3158 if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */
2936 return ret; /* Found in probe cache */ 3159 return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
2937 3160
2938 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { 3161 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
2939 ret = find_probe_trace_events_from_map(pev, tevs); 3162 ret = find_probe_trace_events_from_map(pev, tevs);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 432b690d3f17..e18ea9fe6385 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -85,6 +85,7 @@ struct perf_probe_event {
85 char *group; /* Group name */ 85 char *group; /* Group name */
86 struct perf_probe_point point; /* Probe point */ 86 struct perf_probe_point point; /* Probe point */
87 int nargs; /* Number of arguments */ 87 int nargs; /* Number of arguments */
88 bool sdt; /* SDT/cached event flag */
88 bool uprobes; /* Uprobe event flag */ 89 bool uprobes; /* Uprobe event flag */
89 char *target; /* Target binary */ 90 char *target; /* Target binary */
90 struct perf_probe_arg *args; /* Arguments */ 91 struct perf_probe_arg *args; /* Arguments */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e705a742ee1e..9aed9c332da6 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -362,13 +362,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)
362 return entry; 362 return entry;
363} 363}
364 364
365/* For the kernel probe caches, pass target = NULL */ 365int probe_cache_entry__get_event(struct probe_cache_entry *entry,
366 struct probe_trace_event **tevs)
367{
368 struct probe_trace_event *tev;
369 struct str_node *node;
370 int ret, i;
371
372 ret = strlist__nr_entries(entry->tevlist);
373 if (ret > probe_conf.max_probes)
374 return -E2BIG;
375
376 *tevs = zalloc(ret * sizeof(*tev));
377 if (!*tevs)
378 return -ENOMEM;
379
380 i = 0;
381 strlist__for_each_entry(node, entry->tevlist) {
382 tev = &(*tevs)[i++];
383 ret = parse_probe_trace_command(node->s, tev);
384 if (ret < 0)
385 break;
386 }
387 return i;
388}
389
390/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
366static int probe_cache__open(struct probe_cache *pcache, const char *target) 391static int probe_cache__open(struct probe_cache *pcache, const char *target)
367{ 392{
368 char cpath[PATH_MAX]; 393 char cpath[PATH_MAX];
369 char sbuildid[SBUILD_ID_SIZE]; 394 char sbuildid[SBUILD_ID_SIZE];
370 char *dir_name = NULL; 395 char *dir_name = NULL;
371 bool is_kallsyms = !target; 396 bool is_kallsyms = false;
372 int ret, fd; 397 int ret, fd;
373 398
374 if (target && build_id_cache__cached(target)) { 399 if (target && build_id_cache__cached(target)) {
@@ -378,12 +403,13 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
378 goto found; 403 goto found;
379 } 404 }
380 405
381 if (target) 406 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
382 ret = filename__sprintf_build_id(target, sbuildid);
383 else {
384 target = DSO__NAME_KALLSYMS; 407 target = DSO__NAME_KALLSYMS;
408 is_kallsyms = true;
385 ret = sysfs__sprintf_build_id("/", sbuildid); 409 ret = sysfs__sprintf_build_id("/", sbuildid);
386 } 410 } else
411 ret = filename__sprintf_build_id(target, sbuildid);
412
387 if (ret < 0) { 413 if (ret < 0) {
388 pr_debug("Failed to get build-id from %s.\n", target); 414 pr_debug("Failed to get build-id from %s.\n", target);
389 return ret; 415 return ret;
@@ -546,7 +572,16 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
546 if (!cmd) 572 if (!cmd)
547 return NULL; 573 return NULL;
548 574
549 list_for_each_entry(entry, &pcache->entries, node) { 575 for_each_probe_cache_entry(entry, pcache) {
576 if (pev->sdt) {
577 if (entry->pev.event &&
578 streql(entry->pev.event, pev->event) &&
579 (!pev->group ||
580 streql(entry->pev.group, pev->group)))
581 goto found;
582
583 continue;
584 }
550 /* Hit if same event name or same command-string */ 585 /* Hit if same event name or same command-string */
551 if ((pev->event && 586 if ((pev->event &&
552 (streql(entry->pev.group, pev->group) && 587 (streql(entry->pev.group, pev->group) &&
@@ -567,7 +602,7 @@ probe_cache__find_by_name(struct probe_cache *pcache,
567{ 602{
568 struct probe_cache_entry *entry = NULL; 603 struct probe_cache_entry *entry = NULL;
569 604
570 list_for_each_entry(entry, &pcache->entries, node) { 605 for_each_probe_cache_entry(entry, pcache) {
571 /* Hit if same event name or same command-string */ 606 /* Hit if same event name or same command-string */
572 if (streql(entry->pev.group, group) && 607 if (streql(entry->pev.group, group) &&
573 streql(entry->pev.event, event)) 608 streql(entry->pev.event, event))
@@ -739,7 +774,7 @@ int probe_cache__commit(struct probe_cache *pcache)
739 if (ret < 0) 774 if (ret < 0)
740 goto out; 775 goto out;
741 776
742 list_for_each_entry(entry, &pcache->entries, node) { 777 for_each_probe_cache_entry(entry, pcache) {
743 ret = probe_cache_entry__write(entry, pcache->fd); 778 ret = probe_cache_entry__write(entry, pcache->fd);
744 pr_debug("Cache committed: %d\n", ret); 779 pr_debug("Cache committed: %d\n", ret);
745 if (ret < 0) 780 if (ret < 0)
@@ -781,7 +816,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache,
781{ 816{
782 struct probe_cache_entry *entry; 817 struct probe_cache_entry *entry;
783 818
784 list_for_each_entry(entry, &pcache->entries, node) { 819 for_each_probe_cache_entry(entry, pcache) {
785 if (probe_cache_entry__compare(entry, filter)) 820 if (probe_cache_entry__compare(entry, filter))
786 printf("%s\n", entry->spev); 821 printf("%s\n", entry->spev);
787 } 822 }
@@ -799,7 +834,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
799 pr_debug("list cache with filter: %s\n", buf); 834 pr_debug("list cache with filter: %s\n", buf);
800 free(buf); 835 free(buf);
801 836
802 bidlist = build_id_cache__list_all(); 837 bidlist = build_id_cache__list_all(true);
803 if (!bidlist) { 838 if (!bidlist) {
804 pr_debug("Failed to get buildids: %d\n", errno); 839 pr_debug("Failed to get buildids: %d\n", errno);
805 return -EINVAL; 840 return -EINVAL;
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ddf5ae212c2f..9577b5c0b487 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -21,7 +21,11 @@ struct probe_cache {
21 21
22#define PF_FL_UPROBE 1 22#define PF_FL_UPROBE 1
23#define PF_FL_RW 2 23#define PF_FL_RW 2
24#define for_each_probe_cache_entry(entry, pcache) \
25 list_for_each_entry(entry, &pcache->entries, node)
24 26
27/* probe-file.c depends on libelf */
28#ifdef HAVE_LIBELF_SUPPORT
25int probe_file__open(int flag); 29int probe_file__open(int flag);
26int probe_file__open_both(int *kfd, int *ufd, int flag); 30int probe_file__open_both(int *kfd, int *ufd, int flag);
27struct strlist *probe_file__get_namelist(int fd); 31struct strlist *probe_file__get_namelist(int fd);
@@ -32,6 +36,9 @@ int probe_file__get_events(int fd, struct strfilter *filter,
32 struct strlist *plist); 36 struct strlist *plist);
33int probe_file__del_strlist(int fd, struct strlist *namelist); 37int probe_file__del_strlist(int fd, struct strlist *namelist);
34 38
39int probe_cache_entry__get_event(struct probe_cache_entry *entry,
40 struct probe_trace_event **tevs);
41
35struct probe_cache *probe_cache__new(const char *target); 42struct probe_cache *probe_cache__new(const char *target);
36int probe_cache__add_entry(struct probe_cache *pcache, 43int probe_cache__add_entry(struct probe_cache *pcache,
37 struct perf_probe_event *pev, 44 struct perf_probe_event *pev,
@@ -47,4 +54,11 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
47struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache, 54struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
48 const char *group, const char *event); 55 const char *group, const char *event);
49int probe_cache__show_all_caches(struct strfilter *filter); 56int probe_cache__show_all_caches(struct strfilter *filter);
57#else /* ! HAVE_LIBELF_SUPPORT */
58static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
59{
60 return NULL;
61}
62#define probe_cache__delete(pcache) do {} while (0)
63#endif
50#endif 64#endif