aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 14:39:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 14:39:34 -0400
commit654443e20dfc0617231f28a07c96a979ee1a0239 (patch)
treea0dc3f093eb13892539082e663607c34b4fc2d07 /tools/perf
parent2c01e7bc46f10e9190818437e564f7e0db875ae9 (diff)
parent9cba26e66d09bf394ae5a739627a1dc8b7cae6f4 (diff)
Merge branch 'perf-uprobes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull user-space probe instrumentation from Ingo Molnar: "The uprobes code originates from SystemTap and has been used for years in Fedora and RHEL kernels. This version is much rewritten, reviews from PeterZ, Oleg and myself shaped the end result. This tree includes uprobes support in 'perf probe' - but SystemTap (and other tools) can take advantage of user probe points as well. Sample usage of uprobes via perf, for example to profile malloc() calls without modifying user-space binaries. First boot a new kernel with CONFIG_UPROBE_EVENT=y enabled. If you don't know which function you want to probe you can pick one from 'perf top' or can get a list all functions that can be probed within libc (binaries can be specified as well): $ perf probe -F -x /lib/libc.so.6 To probe libc's malloc(): $ perf probe -x /lib64/libc.so.6 malloc Added new event: probe_libc:malloc (on 0x7eac0) You can now use it in all perf tools, such as: perf record -e probe_libc:malloc -aR sleep 1 Make use of it to create a call graph (as the flat profile is going to look very boring): $ perf record -e probe_libc:malloc -gR make [ perf record: Woken up 173 times to write data ] [ perf record: Captured and wrote 44.190 MB perf.data (~1930712 $ perf report | less 32.03% git libc-2.15.so [.] malloc | --- malloc 29.49% cc1 libc-2.15.so [.] malloc | --- malloc | |--0.95%-- 0x208eb1000000000 | |--0.63%-- htab_traverse_noresize 11.04% as libc-2.15.so [.] malloc | --- malloc | 7.15% ld libc-2.15.so [.] malloc | --- malloc | 5.07% sh libc-2.15.so [.] malloc | --- malloc | 4.99% python-config libc-2.15.so [.] malloc | --- malloc | 4.54% make libc-2.15.so [.] malloc | --- malloc | |--7.34%-- glob | | | |--93.18%-- 0x41588f | | | --6.82%-- glob | 0x41588f ... Or: $ perf report -g flat | less # Overhead Command Shared Object Symbol # ........ ............. ............. .......... # 32.03% git libc-2.15.so [.] malloc 27.19% malloc 29.49% cc1 libc-2.15.so [.] malloc 24.77% malloc 11.04% as libc-2.15.so [.] malloc 11.02% malloc 7.15% ld libc-2.15.so [.] malloc 6.57% malloc ... The core uprobes design is fairly straightforward: uprobes probe points register themselves at (inode:offset) addresses of libraries/binaries, after which all existing (or new) vmas that map that address will have a software breakpoint injected at that address. vmas are COW-ed to preserve original content. The probe points are kept in an rbtree. If user-space executes the probed inode:offset instruction address then an event is generated which can be recovered from the regular perf event channels and mmap-ed ring-buffer. Multiple probes at the same address are supported, they create a dynamic callback list of event consumers. The basic model is further complicated by the XOL speedup: the original instruction that is probed is copied (in an architecture specific fashion) and executed out of line when the probe triggers. The XOL area is a single vma per process, with a fixed number of entries (which limits probe execution parallelism). The API: uprobes are installed/removed via /sys/kernel/debug/tracing/uprobe_events, the API is integrated to align with the kprobes interface as much as possible, but is separate to it. Injecting a probe point is privileged operation, which can be relaxed by setting perf_paranoid to -1. You can use multiple probes as well and mix them with kprobes and regular PMU events or tracepoints, when instrumenting a task." Fix up trivial conflicts in mm/memory.c due to previous cleanup of unmap_single_vma(). * 'perf-uprobes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (21 commits) perf probe: Detect probe target when m/x options are absent perf probe: Provide perf interface for uprobes tracing: Fix kconfig warning due to a typo tracing: Provide trace events interface for uprobes tracing: Extract out common code for kprobes/uprobes trace events tracing: Modify is_delete, is_return from int to bool uprobes/core: Decrement uprobe count before the pages are unmapped uprobes/core: Make background page replacement logic account for rss_stat counters uprobes/core: Optimize probe hits with the help of a counter uprobes/core: Allocate XOL slots for uprobes use uprobes/core: Handle breakpoint and singlestep exceptions uprobes/core: Rename bkpt to swbp uprobes/core: Make order of function parameters consistent across functions uprobes/core: Make macro names consistent uprobes: Update copyright notices uprobes/core: Move insn to arch specific structure uprobes/core: Remove uprobe_opcode_sz uprobes/core: Make instruction tables volatile uprobes: Move to kernel/events/ uprobes/core: Clean up, refactor and improve the code ...
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-probe.txt19
-rw-r--r--tools/perf/builtin-probe.c86
-rw-r--r--tools/perf/util/probe-event.c422
-rw-r--r--tools/perf/util/probe-event.h12
-rw-r--r--tools/perf/util/symbol.c8
-rw-r--r--tools/perf/util/symbol.h1
6 files changed, 447 insertions, 101 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 2780d9ce48b..b715cb71592 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -77,7 +77,8 @@ OPTIONS
77 77
78-F:: 78-F::
79--funcs:: 79--funcs::
80 Show available functions in given module or kernel. 80 Show available functions in given module or kernel. With -x/--exec,
81 can also list functions in a user space executable / shared library.
81 82
82--filter=FILTER:: 83--filter=FILTER::
83 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob 84 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob
@@ -98,6 +99,15 @@ OPTIONS
98--max-probes:: 99--max-probes::
99 Set the maximum number of probe points for an event. Default is 128. 100 Set the maximum number of probe points for an event. Default is 128.
100 101
102-x::
103--exec=PATH::
104 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option.
106
107In absence of -m/-x options, perf probe checks if the first argument after
108the options is an absolute path name. If its an absolute path, perf probe
109uses it as a target module/target user space binary to probe.
110
101PROBE SYNTAX 111PROBE SYNTAX
102------------ 112------------
103Probe points are defined by following syntax. 113Probe points are defined by following syntax.
@@ -182,6 +192,13 @@ Delete all probes on schedule().
182 192
183 ./perf probe --del='schedule*' 193 ./perf probe --del='schedule*'
184 194
195Add probes at zfree() function on /bin/zsh
196
197 ./perf probe -x /bin/zsh zfree or ./perf probe /bin/zsh zfree
198
199Add probes at malloc() function on libc
200
201 ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc
185 202
186SEE ALSO 203SEE ALSO
187-------- 204--------
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 4935c09dd5b..e215ae61b2a 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -54,6 +54,7 @@ static struct {
54 bool show_ext_vars; 54 bool show_ext_vars;
55 bool show_funcs; 55 bool show_funcs;
56 bool mod_events; 56 bool mod_events;
57 bool uprobes;
57 int nevents; 58 int nevents;
58 struct perf_probe_event events[MAX_PROBES]; 59 struct perf_probe_event events[MAX_PROBES];
59 struct strlist *dellist; 60 struct strlist *dellist;
@@ -75,6 +76,8 @@ static int parse_probe_event(const char *str)
75 return -1; 76 return -1;
76 } 77 }
77 78
79 pev->uprobes = params.uprobes;
80
78 /* Parse a perf-probe command into event */ 81 /* Parse a perf-probe command into event */
79 ret = parse_perf_probe_command(str, pev); 82 ret = parse_perf_probe_command(str, pev);
80 pr_debug("%d arguments\n", pev->nargs); 83 pr_debug("%d arguments\n", pev->nargs);
@@ -82,21 +85,58 @@ static int parse_probe_event(const char *str)
82 return ret; 85 return ret;
83} 86}
84 87
88static int set_target(const char *ptr)
89{
90 int found = 0;
91 const char *buf;
92
93 /*
94 * The first argument after options can be an absolute path
95 * to an executable / library or kernel module.
96 *
97 * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH,
98 * short module name.
99 */
100 if (!params.target && ptr && *ptr == '/') {
101 params.target = ptr;
102 found = 1;
103 buf = ptr + (strlen(ptr) - 3);
104
105 if (strcmp(buf, ".ko"))
106 params.uprobes = true;
107
108 }
109
110 return found;
111}
112
85static int parse_probe_event_argv(int argc, const char **argv) 113static int parse_probe_event_argv(int argc, const char **argv)
86{ 114{
87 int i, len, ret; 115 int i, len, ret, found_target;
88 char *buf; 116 char *buf;
89 117
118 found_target = set_target(argv[0]);
119 if (found_target && argc == 1)
120 return 0;
121
90 /* Bind up rest arguments */ 122 /* Bind up rest arguments */
91 len = 0; 123 len = 0;
92 for (i = 0; i < argc; i++) 124 for (i = 0; i < argc; i++) {
125 if (i == 0 && found_target)
126 continue;
127
93 len += strlen(argv[i]) + 1; 128 len += strlen(argv[i]) + 1;
129 }
94 buf = zalloc(len + 1); 130 buf = zalloc(len + 1);
95 if (buf == NULL) 131 if (buf == NULL)
96 return -ENOMEM; 132 return -ENOMEM;
97 len = 0; 133 len = 0;
98 for (i = 0; i < argc; i++) 134 for (i = 0; i < argc; i++) {
135 if (i == 0 && found_target)
136 continue;
137
99 len += sprintf(&buf[len], "%s ", argv[i]); 138 len += sprintf(&buf[len], "%s ", argv[i]);
139 }
100 params.mod_events = true; 140 params.mod_events = true;
101 ret = parse_probe_event(buf); 141 ret = parse_probe_event(buf);
102 free(buf); 142 free(buf);
@@ -125,6 +165,28 @@ static int opt_del_probe_event(const struct option *opt __used,
125 return 0; 165 return 0;
126} 166}
127 167
168static int opt_set_target(const struct option *opt, const char *str,
169 int unset __used)
170{
171 int ret = -ENOENT;
172
173 if (str && !params.target) {
174 if (!strcmp(opt->long_name, "exec"))
175 params.uprobes = true;
176#ifdef DWARF_SUPPORT
177 else if (!strcmp(opt->long_name, "module"))
178 params.uprobes = false;
179#endif
180 else
181 return ret;
182
183 params.target = str;
184 ret = 0;
185 }
186
187 return ret;
188}
189
128#ifdef DWARF_SUPPORT 190#ifdef DWARF_SUPPORT
129static int opt_show_lines(const struct option *opt __used, 191static int opt_show_lines(const struct option *opt __used,
130 const char *str, int unset __used) 192 const char *str, int unset __used)
@@ -246,9 +308,9 @@ static const struct option options[] = {
246 "file", "vmlinux pathname"), 308 "file", "vmlinux pathname"),
247 OPT_STRING('s', "source", &symbol_conf.source_prefix, 309 OPT_STRING('s', "source", &symbol_conf.source_prefix,
248 "directory", "path to kernel source"), 310 "directory", "path to kernel source"),
249 OPT_STRING('m', "module", &params.target, 311 OPT_CALLBACK('m', "module", NULL, "modname|path",
250 "modname|path", 312 "target module name (for online) or path (for offline)",
251 "target module name (for online) or path (for offline)"), 313 opt_set_target),
252#endif 314#endif
253 OPT__DRY_RUN(&probe_event_dry_run), 315 OPT__DRY_RUN(&probe_event_dry_run),
254 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 316 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
@@ -260,6 +322,8 @@ static const struct option options[] = {
260 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" 322 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
261 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", 323 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
262 opt_set_filter), 324 opt_set_filter),
325 OPT_CALLBACK('x', "exec", NULL, "executable|path",
326 "target executable name or path", opt_set_target),
263 OPT_END() 327 OPT_END()
264}; 328};
265 329
@@ -310,6 +374,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
310 pr_err(" Error: Don't use --list with --funcs.\n"); 374 pr_err(" Error: Don't use --list with --funcs.\n");
311 usage_with_options(probe_usage, options); 375 usage_with_options(probe_usage, options);
312 } 376 }
377 if (params.uprobes) {
378 pr_warning(" Error: Don't use --list with --exec.\n");
379 usage_with_options(probe_usage, options);
380 }
313 ret = show_perf_probe_events(); 381 ret = show_perf_probe_events();
314 if (ret < 0) 382 if (ret < 0)
315 pr_err(" Error: Failed to show event list. (%d)\n", 383 pr_err(" Error: Failed to show event list. (%d)\n",
@@ -333,8 +401,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
333 if (!params.filter) 401 if (!params.filter)
334 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 402 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
335 NULL); 403 NULL);
336 ret = show_available_funcs(params.target, 404 ret = show_available_funcs(params.target, params.filter,
337 params.filter); 405 params.uprobes);
338 strfilter__delete(params.filter); 406 strfilter__delete(params.filter);
339 if (ret < 0) 407 if (ret < 0)
340 pr_err(" Error: Failed to show functions." 408 pr_err(" Error: Failed to show functions."
@@ -343,7 +411,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
343 } 411 }
344 412
345#ifdef DWARF_SUPPORT 413#ifdef DWARF_SUPPORT
346 if (params.show_lines) { 414 if (params.show_lines && !params.uprobes) {
347 if (params.mod_events) { 415 if (params.mod_events) {
348 pr_err(" Error: Don't use --line with" 416 pr_err(" Error: Don't use --line with"
349 " --add/--del.\n"); 417 " --add/--del.\n");
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 8a8ee64e72d..59dccc98b55 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -44,6 +44,7 @@
44#include "trace-event.h" /* For __unused */ 44#include "trace-event.h" /* For __unused */
45#include "probe-event.h" 45#include "probe-event.h"
46#include "probe-finder.h" 46#include "probe-finder.h"
47#include "session.h"
47 48
48#define MAX_CMDLEN 256 49#define MAX_CMDLEN 256
49#define MAX_PROBE_ARGS 128 50#define MAX_PROBE_ARGS 128
@@ -70,6 +71,8 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
70} 71}
71 72
72static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 73static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
74static int convert_name_to_addr(struct perf_probe_event *pev,
75 const char *exec);
73static struct machine machine; 76static struct machine machine;
74 77
75/* Initialize symbol maps and path of vmlinux/modules */ 78/* Initialize symbol maps and path of vmlinux/modules */
@@ -170,6 +173,34 @@ const char *kernel_get_module_path(const char *module)
170 return (dso) ? dso->long_name : NULL; 173 return (dso) ? dso->long_name : NULL;
171} 174}
172 175
176static int init_user_exec(void)
177{
178 int ret = 0;
179
180 symbol_conf.try_vmlinux_path = false;
181 symbol_conf.sort_by_name = true;
182 ret = symbol__init();
183
184 if (ret < 0)
185 pr_debug("Failed to init symbol map.\n");
186
187 return ret;
188}
189
190static int convert_to_perf_probe_point(struct probe_trace_point *tp,
191 struct perf_probe_point *pp)
192{
193 pp->function = strdup(tp->symbol);
194
195 if (pp->function == NULL)
196 return -ENOMEM;
197
198 pp->offset = tp->offset;
199 pp->retprobe = tp->retprobe;
200
201 return 0;
202}
203
173#ifdef DWARF_SUPPORT 204#ifdef DWARF_SUPPORT
174/* Open new debuginfo of given module */ 205/* Open new debuginfo of given module */
175static struct debuginfo *open_debuginfo(const char *module) 206static struct debuginfo *open_debuginfo(const char *module)
@@ -224,10 +255,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
224 if (ret <= 0) { 255 if (ret <= 0) {
225 pr_debug("Failed to find corresponding probes from " 256 pr_debug("Failed to find corresponding probes from "
226 "debuginfo. Use kprobe event information.\n"); 257 "debuginfo. Use kprobe event information.\n");
227 pp->function = strdup(tp->symbol); 258 return convert_to_perf_probe_point(tp, pp);
228 if (pp->function == NULL)
229 return -ENOMEM;
230 pp->offset = tp->offset;
231 } 259 }
232 pp->retprobe = tp->retprobe; 260 pp->retprobe = tp->retprobe;
233 261
@@ -275,9 +303,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
275 int max_tevs, const char *target) 303 int max_tevs, const char *target)
276{ 304{
277 bool need_dwarf = perf_probe_event_need_dwarf(pev); 305 bool need_dwarf = perf_probe_event_need_dwarf(pev);
278 struct debuginfo *dinfo = open_debuginfo(target); 306 struct debuginfo *dinfo;
279 int ntevs, ret = 0; 307 int ntevs, ret = 0;
280 308
309 if (pev->uprobes) {
310 if (need_dwarf) {
311 pr_warning("Debuginfo-analysis is not yet supported"
312 " with -x/--exec option.\n");
313 return -ENOSYS;
314 }
315 return convert_name_to_addr(pev, target);
316 }
317
318 dinfo = open_debuginfo(target);
319
281 if (!dinfo) { 320 if (!dinfo) {
282 if (need_dwarf) { 321 if (need_dwarf) {
283 pr_warning("Failed to open debuginfo file.\n"); 322 pr_warning("Failed to open debuginfo file.\n");
@@ -603,23 +642,22 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
603 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); 642 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
604 return -ENOENT; 643 return -ENOENT;
605 } 644 }
606 pp->function = strdup(tp->symbol);
607 if (pp->function == NULL)
608 return -ENOMEM;
609 pp->offset = tp->offset;
610 pp->retprobe = tp->retprobe;
611 645
612 return 0; 646 return convert_to_perf_probe_point(tp, pp);
613} 647}
614 648
615static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 649static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
616 struct probe_trace_event **tevs __unused, 650 struct probe_trace_event **tevs __unused,
617 int max_tevs __unused, const char *mod __unused) 651 int max_tevs __unused, const char *target)
618{ 652{
619 if (perf_probe_event_need_dwarf(pev)) { 653 if (perf_probe_event_need_dwarf(pev)) {
620 pr_warning("Debuginfo-analysis is not supported.\n"); 654 pr_warning("Debuginfo-analysis is not supported.\n");
621 return -ENOSYS; 655 return -ENOSYS;
622 } 656 }
657
658 if (pev->uprobes)
659 return convert_name_to_addr(pev, target);
660
623 return 0; 661 return 0;
624} 662}
625 663
@@ -1341,11 +1379,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1341 if (buf == NULL) 1379 if (buf == NULL)
1342 return NULL; 1380 return NULL;
1343 1381
1344 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", 1382 if (tev->uprobes)
1345 tp->retprobe ? 'r' : 'p', 1383 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s",
1346 tev->group, tev->event, 1384 tp->retprobe ? 'r' : 'p',
1347 tp->module ?: "", tp->module ? ":" : "", 1385 tev->group, tev->event,
1348 tp->symbol, tp->offset); 1386 tp->module, tp->symbol);
1387 else
1388 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
1389 tp->retprobe ? 'r' : 'p',
1390 tev->group, tev->event,
1391 tp->module ?: "", tp->module ? ":" : "",
1392 tp->symbol, tp->offset);
1393
1349 if (len <= 0) 1394 if (len <= 0)
1350 goto error; 1395 goto error;
1351 1396
@@ -1364,7 +1409,7 @@ error:
1364} 1409}
1365 1410
1366static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1411static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1367 struct perf_probe_event *pev) 1412 struct perf_probe_event *pev, bool is_kprobe)
1368{ 1413{
1369 char buf[64] = ""; 1414 char buf[64] = "";
1370 int i, ret; 1415 int i, ret;
@@ -1376,7 +1421,11 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1376 return -ENOMEM; 1421 return -ENOMEM;
1377 1422
1378 /* Convert trace_point to probe_point */ 1423 /* Convert trace_point to probe_point */
1379 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); 1424 if (is_kprobe)
1425 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1426 else
1427 ret = convert_to_perf_probe_point(&tev->point, &pev->point);
1428
1380 if (ret < 0) 1429 if (ret < 0)
1381 return ret; 1430 return ret;
1382 1431
@@ -1472,7 +1521,26 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1472 memset(tev, 0, sizeof(*tev)); 1521 memset(tev, 0, sizeof(*tev));
1473} 1522}
1474 1523
1475static int open_kprobe_events(bool readwrite) 1524static void print_warn_msg(const char *file, bool is_kprobe)
1525{
1526
1527 if (errno == ENOENT) {
1528 const char *config;
1529
1530 if (!is_kprobe)
1531 config = "CONFIG_UPROBE_EVENTS";
1532 else
1533 config = "CONFIG_KPROBE_EVENTS";
1534
1535 pr_warning("%s file does not exist - please rebuild kernel"
1536 " with %s.\n", file, config);
1537 } else
1538 pr_warning("Failed to open %s file: %s\n", file,
1539 strerror(errno));
1540}
1541
1542static int open_probe_events(const char *trace_file, bool readwrite,
1543 bool is_kprobe)
1476{ 1544{
1477 char buf[PATH_MAX]; 1545 char buf[PATH_MAX];
1478 const char *__debugfs; 1546 const char *__debugfs;
@@ -1484,27 +1552,31 @@ static int open_kprobe_events(bool readwrite)
1484 return -ENOENT; 1552 return -ENOENT;
1485 } 1553 }
1486 1554
1487 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); 1555 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1488 if (ret >= 0) { 1556 if (ret >= 0) {
1489 pr_debug("Opening %s write=%d\n", buf, readwrite); 1557 pr_debug("Opening %s write=%d\n", buf, readwrite);
1490 if (readwrite && !probe_event_dry_run) 1558 if (readwrite && !probe_event_dry_run)
1491 ret = open(buf, O_RDWR, O_APPEND); 1559 ret = open(buf, O_RDWR, O_APPEND);
1492 else 1560 else
1493 ret = open(buf, O_RDONLY, 0); 1561 ret = open(buf, O_RDONLY, 0);
1494 }
1495 1562
1496 if (ret < 0) { 1563 if (ret < 0)
1497 if (errno == ENOENT) 1564 print_warn_msg(buf, is_kprobe);
1498 pr_warning("kprobe_events file does not exist - please"
1499 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
1500 else
1501 pr_warning("Failed to open kprobe_events file: %s\n",
1502 strerror(errno));
1503 } 1565 }
1504 return ret; 1566 return ret;
1505} 1567}
1506 1568
1507/* Get raw string list of current kprobe_events */ 1569static int open_kprobe_events(bool readwrite)
1570{
1571 return open_probe_events("tracing/kprobe_events", readwrite, true);
1572}
1573
1574static int open_uprobe_events(bool readwrite)
1575{
1576 return open_probe_events("tracing/uprobe_events", readwrite, false);
1577}
1578
1579/* Get raw string list of current kprobe_events or uprobe_events */
1508static struct strlist *get_probe_trace_command_rawlist(int fd) 1580static struct strlist *get_probe_trace_command_rawlist(int fd)
1509{ 1581{
1510 int ret, idx; 1582 int ret, idx;
@@ -1569,36 +1641,26 @@ static int show_perf_probe_event(struct perf_probe_event *pev)
1569 return ret; 1641 return ret;
1570} 1642}
1571 1643
1572/* List up current perf-probe events */ 1644static int __show_perf_probe_events(int fd, bool is_kprobe)
1573int show_perf_probe_events(void)
1574{ 1645{
1575 int fd, ret; 1646 int ret = 0;
1576 struct probe_trace_event tev; 1647 struct probe_trace_event tev;
1577 struct perf_probe_event pev; 1648 struct perf_probe_event pev;
1578 struct strlist *rawlist; 1649 struct strlist *rawlist;
1579 struct str_node *ent; 1650 struct str_node *ent;
1580 1651
1581 setup_pager();
1582 ret = init_vmlinux();
1583 if (ret < 0)
1584 return ret;
1585
1586 memset(&tev, 0, sizeof(tev)); 1652 memset(&tev, 0, sizeof(tev));
1587 memset(&pev, 0, sizeof(pev)); 1653 memset(&pev, 0, sizeof(pev));
1588 1654
1589 fd = open_kprobe_events(false);
1590 if (fd < 0)
1591 return fd;
1592
1593 rawlist = get_probe_trace_command_rawlist(fd); 1655 rawlist = get_probe_trace_command_rawlist(fd);
1594 close(fd);
1595 if (!rawlist) 1656 if (!rawlist)
1596 return -ENOENT; 1657 return -ENOENT;
1597 1658
1598 strlist__for_each(ent, rawlist) { 1659 strlist__for_each(ent, rawlist) {
1599 ret = parse_probe_trace_command(ent->s, &tev); 1660 ret = parse_probe_trace_command(ent->s, &tev);
1600 if (ret >= 0) { 1661 if (ret >= 0) {
1601 ret = convert_to_perf_probe_event(&tev, &pev); 1662 ret = convert_to_perf_probe_event(&tev, &pev,
1663 is_kprobe);
1602 if (ret >= 0) 1664 if (ret >= 0)
1603 ret = show_perf_probe_event(&pev); 1665 ret = show_perf_probe_event(&pev);
1604 } 1666 }
@@ -1612,6 +1674,33 @@ int show_perf_probe_events(void)
1612 return ret; 1674 return ret;
1613} 1675}
1614 1676
1677/* List up current perf-probe events */
1678int show_perf_probe_events(void)
1679{
1680 int fd, ret;
1681
1682 setup_pager();
1683 fd = open_kprobe_events(false);
1684
1685 if (fd < 0)
1686 return fd;
1687
1688 ret = init_vmlinux();
1689 if (ret < 0)
1690 return ret;
1691
1692 ret = __show_perf_probe_events(fd, true);
1693 close(fd);
1694
1695 fd = open_uprobe_events(false);
1696 if (fd >= 0) {
1697 ret = __show_perf_probe_events(fd, false);
1698 close(fd);
1699 }
1700
1701 return ret;
1702}
1703
1615/* Get current perf-probe event names */ 1704/* Get current perf-probe event names */
1616static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1705static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1617{ 1706{
@@ -1717,7 +1806,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1717 const char *event, *group; 1806 const char *event, *group;
1718 struct strlist *namelist; 1807 struct strlist *namelist;
1719 1808
1720 fd = open_kprobe_events(true); 1809 if (pev->uprobes)
1810 fd = open_uprobe_events(true);
1811 else
1812 fd = open_kprobe_events(true);
1813
1721 if (fd < 0) 1814 if (fd < 0)
1722 return fd; 1815 return fd;
1723 /* Get current event names */ 1816 /* Get current event names */
@@ -1829,6 +1922,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1829 tev->point.offset = pev->point.offset; 1922 tev->point.offset = pev->point.offset;
1830 tev->point.retprobe = pev->point.retprobe; 1923 tev->point.retprobe = pev->point.retprobe;
1831 tev->nargs = pev->nargs; 1924 tev->nargs = pev->nargs;
1925 tev->uprobes = pev->uprobes;
1926
1832 if (tev->nargs) { 1927 if (tev->nargs) {
1833 tev->args = zalloc(sizeof(struct probe_trace_arg) 1928 tev->args = zalloc(sizeof(struct probe_trace_arg)
1834 * tev->nargs); 1929 * tev->nargs);
@@ -1859,6 +1954,9 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1859 } 1954 }
1860 } 1955 }
1861 1956
1957 if (pev->uprobes)
1958 return 1;
1959
1862 /* Currently just checking function name from symbol map */ 1960 /* Currently just checking function name from symbol map */
1863 sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 1961 sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1864 if (!sym) { 1962 if (!sym) {
@@ -1894,12 +1992,18 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1894 int i, j, ret; 1992 int i, j, ret;
1895 struct __event_package *pkgs; 1993 struct __event_package *pkgs;
1896 1994
1995 ret = 0;
1897 pkgs = zalloc(sizeof(struct __event_package) * npevs); 1996 pkgs = zalloc(sizeof(struct __event_package) * npevs);
1997
1898 if (pkgs == NULL) 1998 if (pkgs == NULL)
1899 return -ENOMEM; 1999 return -ENOMEM;
1900 2000
1901 /* Init vmlinux path */ 2001 if (!pevs->uprobes)
1902 ret = init_vmlinux(); 2002 /* Init vmlinux path */
2003 ret = init_vmlinux();
2004 else
2005 ret = init_user_exec();
2006
1903 if (ret < 0) { 2007 if (ret < 0) {
1904 free(pkgs); 2008 free(pkgs);
1905 return ret; 2009 return ret;
@@ -1971,23 +2075,15 @@ error:
1971 return ret; 2075 return ret;
1972} 2076}
1973 2077
1974static int del_trace_probe_event(int fd, const char *group, 2078static int del_trace_probe_event(int fd, const char *buf,
1975 const char *event, struct strlist *namelist) 2079 struct strlist *namelist)
1976{ 2080{
1977 char buf[128];
1978 struct str_node *ent, *n; 2081 struct str_node *ent, *n;
1979 int found = 0, ret = 0; 2082 int ret = -1;
1980
1981 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1982 if (ret < 0) {
1983 pr_err("Failed to copy event.\n");
1984 return ret;
1985 }
1986 2083
1987 if (strpbrk(buf, "*?")) { /* Glob-exp */ 2084 if (strpbrk(buf, "*?")) { /* Glob-exp */
1988 strlist__for_each_safe(ent, n, namelist) 2085 strlist__for_each_safe(ent, n, namelist)
1989 if (strglobmatch(ent->s, buf)) { 2086 if (strglobmatch(ent->s, buf)) {
1990 found++;
1991 ret = __del_trace_probe_event(fd, ent); 2087 ret = __del_trace_probe_event(fd, ent);
1992 if (ret < 0) 2088 if (ret < 0)
1993 break; 2089 break;
@@ -1996,40 +2092,43 @@ static int del_trace_probe_event(int fd, const char *group,
1996 } else { 2092 } else {
1997 ent = strlist__find(namelist, buf); 2093 ent = strlist__find(namelist, buf);
1998 if (ent) { 2094 if (ent) {
1999 found++;
2000 ret = __del_trace_probe_event(fd, ent); 2095 ret = __del_trace_probe_event(fd, ent);
2001 if (ret >= 0) 2096 if (ret >= 0)
2002 strlist__remove(namelist, ent); 2097 strlist__remove(namelist, ent);
2003 } 2098 }
2004 } 2099 }
2005 if (found == 0 && ret >= 0)
2006 pr_info("Info: Event \"%s\" does not exist.\n", buf);
2007 2100
2008 return ret; 2101 return ret;
2009} 2102}
2010 2103
2011int del_perf_probe_events(struct strlist *dellist) 2104int del_perf_probe_events(struct strlist *dellist)
2012{ 2105{
2013 int fd, ret = 0; 2106 int ret = -1, ufd = -1, kfd = -1;
2107 char buf[128];
2014 const char *group, *event; 2108 const char *group, *event;
2015 char *p, *str; 2109 char *p, *str;
2016 struct str_node *ent; 2110 struct str_node *ent;
2017 struct strlist *namelist; 2111 struct strlist *namelist = NULL, *unamelist = NULL;
2018
2019 fd = open_kprobe_events(true);
2020 if (fd < 0)
2021 return fd;
2022 2112
2023 /* Get current event names */ 2113 /* Get current event names */
2024 namelist = get_probe_trace_event_names(fd, true); 2114 kfd = open_kprobe_events(true);
2025 if (namelist == NULL) 2115 if (kfd < 0)
2026 return -EINVAL; 2116 return kfd;
2117
2118 namelist = get_probe_trace_event_names(kfd, true);
2119 ufd = open_uprobe_events(true);
2120
2121 if (ufd >= 0)
2122 unamelist = get_probe_trace_event_names(ufd, true);
2123
2124 if (namelist == NULL && unamelist == NULL)
2125 goto error;
2027 2126
2028 strlist__for_each(ent, dellist) { 2127 strlist__for_each(ent, dellist) {
2029 str = strdup(ent->s); 2128 str = strdup(ent->s);
2030 if (str == NULL) { 2129 if (str == NULL) {
2031 ret = -ENOMEM; 2130 ret = -ENOMEM;
2032 break; 2131 goto error;
2033 } 2132 }
2034 pr_debug("Parsing: %s\n", str); 2133 pr_debug("Parsing: %s\n", str);
2035 p = strchr(str, ':'); 2134 p = strchr(str, ':');
@@ -2041,17 +2140,46 @@ int del_perf_probe_events(struct strlist *dellist)
2041 group = "*"; 2140 group = "*";
2042 event = str; 2141 event = str;
2043 } 2142 }
2143
2144 ret = e_snprintf(buf, 128, "%s:%s", group, event);
2145 if (ret < 0) {
2146 pr_err("Failed to copy event.");
2147 free(str);
2148 goto error;
2149 }
2150
2044 pr_debug("Group: %s, Event: %s\n", group, event); 2151 pr_debug("Group: %s, Event: %s\n", group, event);
2045 ret = del_trace_probe_event(fd, group, event, namelist); 2152
2153 if (namelist)
2154 ret = del_trace_probe_event(kfd, buf, namelist);
2155
2156 if (unamelist && ret != 0)
2157 ret = del_trace_probe_event(ufd, buf, unamelist);
2158
2159 if (ret != 0)
2160 pr_info("Info: Event \"%s\" does not exist.\n", buf);
2161
2046 free(str); 2162 free(str);
2047 if (ret < 0)
2048 break;
2049 } 2163 }
2050 strlist__delete(namelist); 2164
2051 close(fd); 2165error:
2166 if (kfd >= 0) {
2167 if (namelist)
2168 strlist__delete(namelist);
2169
2170 close(kfd);
2171 }
2172
2173 if (ufd >= 0) {
2174 if (unamelist)
2175 strlist__delete(unamelist);
2176
2177 close(ufd);
2178 }
2052 2179
2053 return ret; 2180 return ret;
2054} 2181}
2182
2055/* TODO: don't use a global variable for filter ... */ 2183/* TODO: don't use a global variable for filter ... */
2056static struct strfilter *available_func_filter; 2184static struct strfilter *available_func_filter;
2057 2185
@@ -2068,30 +2196,152 @@ static int filter_available_functions(struct map *map __unused,
2068 return 1; 2196 return 1;
2069} 2197}
2070 2198
2071int show_available_funcs(const char *target, struct strfilter *_filter) 2199static int __show_available_funcs(struct map *map)
2200{
2201 if (map__load(map, filter_available_functions)) {
2202 pr_err("Failed to load map.\n");
2203 return -EINVAL;
2204 }
2205 if (!dso__sorted_by_name(map->dso, map->type))
2206 dso__sort_by_name(map->dso, map->type);
2207
2208 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2209 return 0;
2210}
2211
2212static int available_kernel_funcs(const char *module)
2072{ 2213{
2073 struct map *map; 2214 struct map *map;
2074 int ret; 2215 int ret;
2075 2216
2076 setup_pager();
2077
2078 ret = init_vmlinux(); 2217 ret = init_vmlinux();
2079 if (ret < 0) 2218 if (ret < 0)
2080 return ret; 2219 return ret;
2081 2220
2082 map = kernel_get_module_map(target); 2221 map = kernel_get_module_map(module);
2083 if (!map) { 2222 if (!map) {
2084 pr_err("Failed to find %s map.\n", (target) ? : "kernel"); 2223 pr_err("Failed to find %s map.\n", (module) ? : "kernel");
2085 return -EINVAL; 2224 return -EINVAL;
2086 } 2225 }
2226 return __show_available_funcs(map);
2227}
2228
2229static int available_user_funcs(const char *target)
2230{
2231 struct map *map;
2232 int ret;
2233
2234 ret = init_user_exec();
2235 if (ret < 0)
2236 return ret;
2237
2238 map = dso__new_map(target);
2239 ret = __show_available_funcs(map);
2240 dso__delete(map->dso);
2241 map__delete(map);
2242 return ret;
2243}
2244
2245int show_available_funcs(const char *target, struct strfilter *_filter,
2246 bool user)
2247{
2248 setup_pager();
2087 available_func_filter = _filter; 2249 available_func_filter = _filter;
2250
2251 if (!user)
2252 return available_kernel_funcs(target);
2253
2254 return available_user_funcs(target);
2255}
2256
2257/*
2258 * uprobe_events only accepts address:
2259 * Convert function and any offset to address
2260 */
2261static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2262{
2263 struct perf_probe_point *pp = &pev->point;
2264 struct symbol *sym;
2265 struct map *map = NULL;
2266 char *function = NULL, *name = NULL;
2267 int ret = -EINVAL;
2268 unsigned long long vaddr = 0;
2269
2270 if (!pp->function) {
2271 pr_warning("No function specified for uprobes");
2272 goto out;
2273 }
2274
2275 function = strdup(pp->function);
2276 if (!function) {
2277 pr_warning("Failed to allocate memory by strdup.\n");
2278 ret = -ENOMEM;
2279 goto out;
2280 }
2281
2282 name = realpath(exec, NULL);
2283 if (!name) {
2284 pr_warning("Cannot find realpath for %s.\n", exec);
2285 goto out;
2286 }
2287 map = dso__new_map(name);
2288 if (!map) {
2289 pr_warning("Cannot find appropriate DSO for %s.\n", exec);
2290 goto out;
2291 }
2292 available_func_filter = strfilter__new(function, NULL);
2088 if (map__load(map, filter_available_functions)) { 2293 if (map__load(map, filter_available_functions)) {
2089 pr_err("Failed to load map.\n"); 2294 pr_err("Failed to load map.\n");
2090 return -EINVAL; 2295 goto out;
2091 } 2296 }
2092 if (!dso__sorted_by_name(map->dso, map->type))
2093 dso__sort_by_name(map->dso, map->type);
2094 2297
2095 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2298 sym = map__find_symbol_by_name(map, function, NULL);
2096 return 0; 2299 if (!sym) {
2300 pr_warning("Cannot find %s in DSO %s\n", function, exec);
2301 goto out;
2302 }
2303
2304 if (map->start > sym->start)
2305 vaddr = map->start;
2306 vaddr += sym->start + pp->offset + map->pgoff;
2307 pp->offset = 0;
2308
2309 if (!pev->event) {
2310 pev->event = function;
2311 function = NULL;
2312 }
2313 if (!pev->group) {
2314 char *ptr1, *ptr2;
2315
2316 pev->group = zalloc(sizeof(char *) * 64);
2317 ptr1 = strdup(basename(exec));
2318 if (ptr1) {
2319 ptr2 = strpbrk(ptr1, "-._");
2320 if (ptr2)
2321 *ptr2 = '\0';
2322 e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP,
2323 ptr1);
2324 free(ptr1);
2325 }
2326 }
2327 free(pp->function);
2328 pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
2329 if (!pp->function) {
2330 ret = -ENOMEM;
2331 pr_warning("Failed to allocate memory by zalloc.\n");
2332 goto out;
2333 }
2334 e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr);
2335 ret = 0;
2336
2337out:
2338 if (map) {
2339 dso__delete(map->dso);
2340 map__delete(map);
2341 }
2342 if (function)
2343 free(function);
2344 if (name)
2345 free(name);
2346 return ret;
2097} 2347}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index a7dee835f49..f9f3de8b422 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -7,7 +7,7 @@
7 7
8extern bool probe_event_dry_run; 8extern bool probe_event_dry_run;
9 9
10/* kprobe-tracer tracing point */ 10/* kprobe-tracer and uprobe-tracer tracing point */
11struct probe_trace_point { 11struct probe_trace_point {
12 char *symbol; /* Base symbol */ 12 char *symbol; /* Base symbol */
13 char *module; /* Module name */ 13 char *module; /* Module name */
@@ -21,7 +21,7 @@ struct probe_trace_arg_ref {
21 long offset; /* Offset value */ 21 long offset; /* Offset value */
22}; 22};
23 23
24/* kprobe-tracer tracing argument */ 24/* kprobe-tracer and uprobe-tracer tracing argument */
25struct probe_trace_arg { 25struct probe_trace_arg {
26 char *name; /* Argument name */ 26 char *name; /* Argument name */
27 char *value; /* Base value */ 27 char *value; /* Base value */
@@ -29,12 +29,13 @@ struct probe_trace_arg {
29 struct probe_trace_arg_ref *ref; /* Referencing offset */ 29 struct probe_trace_arg_ref *ref; /* Referencing offset */
30}; 30};
31 31
32/* kprobe-tracer tracing event (point + arg) */ 32/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */
33struct probe_trace_event { 33struct probe_trace_event {
34 char *event; /* Event name */ 34 char *event; /* Event name */
35 char *group; /* Group name */ 35 char *group; /* Group name */
36 struct probe_trace_point point; /* Trace point */ 36 struct probe_trace_point point; /* Trace point */
37 int nargs; /* Number of args */ 37 int nargs; /* Number of args */
38 bool uprobes; /* uprobes only */
38 struct probe_trace_arg *args; /* Arguments */ 39 struct probe_trace_arg *args; /* Arguments */
39}; 40};
40 41
@@ -70,6 +71,7 @@ struct perf_probe_event {
70 char *group; /* Group name */ 71 char *group; /* Group name */
71 struct perf_probe_point point; /* Probe point */ 72 struct perf_probe_point point; /* Probe point */
72 int nargs; /* Number of arguments */ 73 int nargs; /* Number of arguments */
74 bool uprobes;
73 struct perf_probe_arg *args; /* Arguments */ 75 struct perf_probe_arg *args; /* Arguments */
74}; 76};
75 77
@@ -129,8 +131,8 @@ extern int show_line_range(struct line_range *lr, const char *module);
129extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 131extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
130 int max_probe_points, const char *module, 132 int max_probe_points, const char *module,
131 struct strfilter *filter, bool externs); 133 struct strfilter *filter, bool externs);
132extern int show_available_funcs(const char *module, struct strfilter *filter); 134extern int show_available_funcs(const char *module, struct strfilter *filter,
133 135 bool user);
134 136
135/* Maximum index number of event-name postfix */ 137/* Maximum index number of event-name postfix */
136#define MAX_EVENT_INDEX 1024 138#define MAX_EVENT_INDEX 1024
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index ab9867b2b43..e2ba8858f3e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2783,3 +2783,11 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
2783 2783
2784 return ret; 2784 return ret;
2785} 2785}
2786
2787struct map *dso__new_map(const char *name)
2788{
2789 struct dso *dso = dso__new(name);
2790 struct map *map = map__new2(0, dso, MAP__FUNCTION);
2791
2792 return map;
2793}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 1f003884f1a..5649d63798c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -242,6 +242,7 @@ void dso__set_long_name(struct dso *dso, char *name);
242void dso__set_build_id(struct dso *dso, void *build_id); 242void dso__set_build_id(struct dso *dso, void *build_id);
243void dso__read_running_kernel_build_id(struct dso *dso, 243void dso__read_running_kernel_build_id(struct dso *dso,
244 struct machine *machine); 244 struct machine *machine);
245struct map *dso__new_map(const char *name);
245struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 246struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
246 u64 addr); 247 u64 addr);
247struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 248struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,