aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c180
1 files changed, 135 insertions, 45 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 128aaab0aeda..f0223166e761 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -31,6 +31,7 @@
31#include <string.h> 31#include <string.h>
32#include <stdarg.h> 32#include <stdarg.h>
33#include <limits.h> 33#include <limits.h>
34#include <elf.h>
34 35
35#undef _GNU_SOURCE 36#undef _GNU_SOURCE
36#include "util.h" 37#include "util.h"
@@ -111,7 +112,25 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
111 NULL); 112 NULL);
112} 113}
113 114
114const char *kernel_get_module_path(const char *module) 115static struct map *kernel_get_module_map(const char *module)
116{
117 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps;
119
120 if (!module)
121 module = "kernel";
122
123 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
124 struct map *pos = rb_entry(nd, struct map, rb_node);
125 if (strncmp(pos->dso->short_name + 1, module,
126 pos->dso->short_name_len - 2) == 0) {
127 return pos;
128 }
129 }
130 return NULL;
131}
132
133static struct dso *kernel_get_module_dso(const char *module)
115{ 134{
116 struct dso *dso; 135 struct dso *dso;
117 struct map *map; 136 struct map *map;
@@ -141,7 +160,13 @@ const char *kernel_get_module_path(const char *module)
141 } 160 }
142 } 161 }
143found: 162found:
144 return dso->long_name; 163 return dso;
164}
165
166const char *kernel_get_module_path(const char *module)
167{
168 struct dso *dso = kernel_get_module_dso(module);
169 return (dso) ? dso->long_name : NULL;
145} 170}
146 171
147#ifdef DWARF_SUPPORT 172#ifdef DWARF_SUPPORT
@@ -172,7 +197,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
172 sym = __find_kernel_function_by_name(tp->symbol, &map); 197 sym = __find_kernel_function_by_name(tp->symbol, &map);
173 if (sym) { 198 if (sym) {
174 addr = map->unmap_ip(map, sym->start + tp->offset); 199 addr = map->unmap_ip(map, sym->start + tp->offset);
175 pr_debug("try to find %s+%ld@%llx\n", tp->symbol, 200 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
176 tp->offset, addr); 201 tp->offset, addr);
177 ret = find_perf_probe_point((unsigned long)addr, pp); 202 ret = find_perf_probe_point((unsigned long)addr, pp);
178 } 203 }
@@ -209,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
209 234
210 /* Searching trace events corresponding to probe event */ 235 /* Searching trace events corresponding to probe event */
211 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
212 close(fd);
213 237
214 if (ntevs > 0) { /* Succeeded to find trace events */ 238 if (ntevs > 0) { /* Succeeded to find trace events */
215 pr_debug("find %d probe_trace_events.\n", ntevs); 239 pr_debug("find %d probe_trace_events.\n", ntevs);
@@ -363,7 +387,6 @@ int show_line_range(struct line_range *lr, const char *module)
363 } 387 }
364 388
365 ret = find_line_range(fd, lr); 389 ret = find_line_range(fd, lr);
366 close(fd);
367 if (ret == 0) { 390 if (ret == 0) {
368 pr_warning("Specified source line is not found.\n"); 391 pr_warning("Specified source line is not found.\n");
369 return -ENOENT; 392 return -ENOENT;
@@ -384,7 +407,7 @@ int show_line_range(struct line_range *lr, const char *module)
384 setup_pager(); 407 setup_pager();
385 408
386 if (lr->function) 409 if (lr->function)
387 fprintf(stdout, "<%s:%d>\n", lr->function, 410 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
388 lr->start - lr->offset); 411 lr->start - lr->offset);
389 else 412 else
390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 413 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
@@ -426,12 +449,14 @@ end:
426} 449}
427 450
428static int show_available_vars_at(int fd, struct perf_probe_event *pev, 451static int show_available_vars_at(int fd, struct perf_probe_event *pev,
429 int max_vls, bool externs) 452 int max_vls, struct strfilter *_filter,
453 bool externs)
430{ 454{
431 char *buf; 455 char *buf;
432 int ret, i; 456 int ret, i, nvars;
433 struct str_node *node; 457 struct str_node *node;
434 struct variable_list *vls = NULL, *vl; 458 struct variable_list *vls = NULL, *vl;
459 const char *var;
435 460
436 buf = synthesize_perf_probe_point(&pev->point); 461 buf = synthesize_perf_probe_point(&pev->point);
437 if (!buf) 462 if (!buf)
@@ -439,36 +464,45 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
439 pr_debug("Searching variables at %s\n", buf); 464 pr_debug("Searching variables at %s\n", buf);
440 465
441 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 466 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
442 if (ret > 0) { 467 if (ret <= 0) {
443 /* Some variables were found */ 468 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
444 fprintf(stdout, "Available variables at %s\n", buf); 469 goto end;
445 for (i = 0; i < ret; i++) { 470 }
446 vl = &vls[i]; 471 /* Some variables are found */
447 /* 472 fprintf(stdout, "Available variables at %s\n", buf);
448 * A probe point might be converted to 473 for (i = 0; i < ret; i++) {
449 * several trace points. 474 vl = &vls[i];
450 */ 475 /*
451 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 476 * A probe point might be converted to
452 vl->point.offset); 477 * several trace points.
453 free(vl->point.symbol); 478 */
454 if (vl->vars) { 479 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
455 strlist__for_each(node, vl->vars) 480 vl->point.offset);
481 free(vl->point.symbol);
482 nvars = 0;
483 if (vl->vars) {
484 strlist__for_each(node, vl->vars) {
485 var = strchr(node->s, '\t') + 1;
486 if (strfilter__compare(_filter, var)) {
456 fprintf(stdout, "\t\t%s\n", node->s); 487 fprintf(stdout, "\t\t%s\n", node->s);
457 strlist__delete(vl->vars); 488 nvars++;
458 } else 489 }
459 fprintf(stdout, "(No variables)\n"); 490 }
491 strlist__delete(vl->vars);
460 } 492 }
461 free(vls); 493 if (nvars == 0)
462 } else 494 fprintf(stdout, "\t\t(No matched variables)\n");
463 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 495 }
464 496 free(vls);
497end:
465 free(buf); 498 free(buf);
466 return ret; 499 return ret;
467} 500}
468 501
469/* Show available variables on given probe point */ 502/* Show available variables on given probe point */
470int show_available_vars(struct perf_probe_event *pevs, int npevs, 503int show_available_vars(struct perf_probe_event *pevs, int npevs,
471 int max_vls, const char *module, bool externs) 504 int max_vls, const char *module,
505 struct strfilter *_filter, bool externs)
472{ 506{
473 int i, fd, ret = 0; 507 int i, fd, ret = 0;
474 508
@@ -476,18 +510,18 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
476 if (ret < 0) 510 if (ret < 0)
477 return ret; 511 return ret;
478 512
479 fd = open_vmlinux(module);
480 if (fd < 0) {
481 pr_warning("Failed to open debug information file.\n");
482 return fd;
483 }
484
485 setup_pager(); 513 setup_pager();
486 514
487 for (i = 0; i < npevs && ret >= 0; i++) 515 for (i = 0; i < npevs && ret >= 0; i++) {
488 ret = show_available_vars_at(fd, &pevs[i], max_vls, externs); 516 fd = open_vmlinux(module);
489 517 if (fd < 0) {
490 close(fd); 518 pr_warning("Failed to open debug information file.\n");
519 ret = fd;
520 break;
521 }
522 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
523 externs);
524 }
491 return ret; 525 return ret;
492} 526}
493 527
@@ -531,7 +565,9 @@ int show_line_range(struct line_range *lr __unused, const char *module __unused)
531 565
532int show_available_vars(struct perf_probe_event *pevs __unused, 566int show_available_vars(struct perf_probe_event *pevs __unused,
533 int npevs __unused, int max_vls __unused, 567 int npevs __unused, int max_vls __unused,
534 const char *module __unused, bool externs __unused) 568 const char *module __unused,
569 struct strfilter *filter __unused,
570 bool externs __unused)
535{ 571{
536 pr_warning("Debuginfo-analysis is not supported.\n"); 572 pr_warning("Debuginfo-analysis is not supported.\n");
537 return -ENOSYS; 573 return -ENOSYS;
@@ -556,11 +592,11 @@ static int parse_line_num(char **ptr, int *val, const char *what)
556 * The line range syntax is described by: 592 * The line range syntax is described by:
557 * 593 *
558 * SRC[:SLN[+NUM|-ELN]] 594 * SRC[:SLN[+NUM|-ELN]]
559 * FNC[:SLN[+NUM|-ELN]] 595 * FNC[@SRC][:SLN[+NUM|-ELN]]
560 */ 596 */
561int parse_line_range_desc(const char *arg, struct line_range *lr) 597int parse_line_range_desc(const char *arg, struct line_range *lr)
562{ 598{
563 char *range, *name = strdup(arg); 599 char *range, *file, *name = strdup(arg);
564 int err; 600 int err;
565 601
566 if (!name) 602 if (!name)
@@ -610,7 +646,16 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
610 } 646 }
611 } 647 }
612 648
613 if (strchr(name, '.')) 649 file = strchr(name, '@');
650 if (file) {
651 *file = '\0';
652 lr->file = strdup(++file);
653 if (lr->file == NULL) {
654 err = -ENOMEM;
655 goto err;
656 }
657 lr->function = name;
658 } else if (strchr(name, '.'))
614 lr->file = name; 659 lr->file = name;
615 else 660 else
616 lr->function = name; 661 lr->function = name;
@@ -1784,9 +1829,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1784 } 1829 }
1785 1830
1786 /* Loop 2: add all events */ 1831 /* Loop 2: add all events */
1787 for (i = 0; i < npevs && ret >= 0; i++) 1832 for (i = 0; i < npevs; i++) {
1788 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1833 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1789 pkgs[i].ntevs, force_add); 1834 pkgs[i].ntevs, force_add);
1835 if (ret < 0)
1836 break;
1837 }
1790end: 1838end:
1791 /* Loop 3: cleanup and free trace events */ 1839 /* Loop 3: cleanup and free trace events */
1792 for (i = 0; i < npevs; i++) { 1840 for (i = 0; i < npevs; i++) {
@@ -1912,4 +1960,46 @@ int del_perf_probe_events(struct strlist *dellist)
1912 1960
1913 return ret; 1961 return ret;
1914} 1962}
1963/* TODO: don't use a global variable for filter ... */
1964static struct strfilter *available_func_filter;
1965
1966/*
1967 * If a symbol corresponds to a function with global binding and
1968 * matches filter return 0. For all others return 1.
1969 */
1970static int filter_available_functions(struct map *map __unused,
1971 struct symbol *sym)
1972{
1973 if (sym->binding == STB_GLOBAL &&
1974 strfilter__compare(available_func_filter, sym->name))
1975 return 0;
1976 return 1;
1977}
1915 1978
1979int show_available_funcs(const char *module, struct strfilter *_filter)
1980{
1981 struct map *map;
1982 int ret;
1983
1984 setup_pager();
1985
1986 ret = init_vmlinux();
1987 if (ret < 0)
1988 return ret;
1989
1990 map = kernel_get_module_map(module);
1991 if (!map) {
1992 pr_err("Failed to find %s map.\n", (module) ? : "kernel");
1993 return -EINVAL;
1994 }
1995 available_func_filter = _filter;
1996 if (map__load(map, filter_available_functions)) {
1997 pr_err("Failed to load map.\n");
1998 return -EINVAL;
1999 }
2000 if (!dso__sorted_by_name(map->dso, map->type))
2001 dso__sort_by_name(map->dso, map->type);
2002
2003 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2004 return 0;
2005}