diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 19 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 86 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 422 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 12 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 8 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
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 | |||
107 | In absence of -m/-x options, perf probe checks if the first argument after | ||
108 | the options is an absolute path name. If its an absolute path, perf probe | ||
109 | uses it as a target module/target user space binary to probe. | ||
110 | |||
101 | PROBE SYNTAX | 111 | PROBE SYNTAX |
102 | ------------ | 112 | ------------ |
103 | Probe points are defined by following syntax. | 113 | Probe 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 | ||
195 | Add probes at zfree() function on /bin/zsh | ||
196 | |||
197 | ./perf probe -x /bin/zsh zfree or ./perf probe /bin/zsh zfree | ||
198 | |||
199 | Add 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 | ||
186 | SEE ALSO | 203 | SEE 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 | ||
88 | static 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 | |||
85 | static int parse_probe_event_argv(int argc, const char **argv) | 113 | static 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 | ||
168 | static 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 |
129 | static int opt_show_lines(const struct option *opt __used, | 191 | static 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", ¶ms.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", ¶ms.max_probe_points, | 316 | OPT_INTEGER('\0', "max-probes", ¶ms.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 | ||
72 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | 73 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); |
74 | static int convert_name_to_addr(struct perf_probe_event *pev, | ||
75 | const char *exec); | ||
73 | static struct machine machine; | 76 | static 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 | ||
176 | static 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 | |||
190 | static 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 */ |
175 | static struct debuginfo *open_debuginfo(const char *module) | 206 | static 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 | ||
615 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 649 | static 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 | ||
1366 | static int convert_to_perf_probe_event(struct probe_trace_event *tev, | 1411 | static 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 | ||
1475 | static int open_kprobe_events(bool readwrite) | 1524 | static 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 | |||
1542 | static 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 */ | 1569 | static int open_kprobe_events(bool readwrite) |
1570 | { | ||
1571 | return open_probe_events("tracing/kprobe_events", readwrite, true); | ||
1572 | } | ||
1573 | |||
1574 | static 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 */ | ||
1508 | static struct strlist *get_probe_trace_command_rawlist(int fd) | 1580 | static 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 */ | 1644 | static int __show_perf_probe_events(int fd, bool is_kprobe) |
1573 | int 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 */ | ||
1678 | int 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 */ |
1616 | static struct strlist *get_probe_trace_event_names(int fd, bool include_group) | 1705 | static 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 | ||
1974 | static int del_trace_probe_event(int fd, const char *group, | 2078 | static 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 | ||
2011 | int del_perf_probe_events(struct strlist *dellist) | 2104 | int 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); | 2165 | error: |
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 ... */ |
2056 | static struct strfilter *available_func_filter; | 2184 | static 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 | ||
2071 | int show_available_funcs(const char *target, struct strfilter *_filter) | 2199 | static 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 | |||
2212 | static 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 | |||
2229 | static 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 | |||
2245 | int 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 | */ | ||
2261 | static 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 | |||
2337 | out: | ||
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 | ||
8 | extern bool probe_event_dry_run; | 8 | extern bool probe_event_dry_run; |
9 | 9 | ||
10 | /* kprobe-tracer tracing point */ | 10 | /* kprobe-tracer and uprobe-tracer tracing point */ |
11 | struct probe_trace_point { | 11 | struct 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 */ |
25 | struct probe_trace_arg { | 25 | struct 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) */ |
33 | struct probe_trace_event { | 33 | struct 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); | |||
129 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, | 131 | extern 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); |
132 | extern int show_available_funcs(const char *module, struct strfilter *filter); | 134 | extern 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 | |||
2787 | struct 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); | |||
242 | void dso__set_build_id(struct dso *dso, void *build_id); | 242 | void dso__set_build_id(struct dso *dso, void *build_id); |
243 | void dso__read_running_kernel_build_id(struct dso *dso, | 243 | void dso__read_running_kernel_build_id(struct dso *dso, |
244 | struct machine *machine); | 244 | struct machine *machine); |
245 | struct map *dso__new_map(const char *name); | ||
245 | struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | 246 | struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, |
246 | u64 addr); | 247 | u64 addr); |
247 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 248 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |