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.c159
1 files changed, 126 insertions, 33 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6e29d9c9dccc..5ddee66020a7 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
@@ -384,7 +409,7 @@ int show_line_range(struct line_range *lr, const char *module)
384 setup_pager(); 409 setup_pager();
385 410
386 if (lr->function) 411 if (lr->function)
387 fprintf(stdout, "<%s:%d>\n", lr->function, 412 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
388 lr->start - lr->offset); 413 lr->start - lr->offset);
389 else 414 else
390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 415 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
@@ -426,12 +451,14 @@ end:
426} 451}
427 452
428static int show_available_vars_at(int fd, struct perf_probe_event *pev, 453static int show_available_vars_at(int fd, struct perf_probe_event *pev,
429 int max_vls, bool externs) 454 int max_vls, struct strfilter *_filter,
455 bool externs)
430{ 456{
431 char *buf; 457 char *buf;
432 int ret, i; 458 int ret, i, nvars;
433 struct str_node *node; 459 struct str_node *node;
434 struct variable_list *vls = NULL, *vl; 460 struct variable_list *vls = NULL, *vl;
461 const char *var;
435 462
436 buf = synthesize_perf_probe_point(&pev->point); 463 buf = synthesize_perf_probe_point(&pev->point);
437 if (!buf) 464 if (!buf)
@@ -439,36 +466,45 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
439 pr_debug("Searching variables at %s\n", buf); 466 pr_debug("Searching variables at %s\n", buf);
440 467
441 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 468 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
442 if (ret > 0) { 469 if (ret <= 0) {
443 /* Some variables were found */ 470 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
444 fprintf(stdout, "Available variables at %s\n", buf); 471 goto end;
445 for (i = 0; i < ret; i++) { 472 }
446 vl = &vls[i]; 473 /* Some variables are found */
447 /* 474 fprintf(stdout, "Available variables at %s\n", buf);
448 * A probe point might be converted to 475 for (i = 0; i < ret; i++) {
449 * several trace points. 476 vl = &vls[i];
450 */ 477 /*
451 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 478 * A probe point might be converted to
452 vl->point.offset); 479 * several trace points.
453 free(vl->point.symbol); 480 */
454 if (vl->vars) { 481 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
455 strlist__for_each(node, vl->vars) 482 vl->point.offset);
483 free(vl->point.symbol);
484 nvars = 0;
485 if (vl->vars) {
486 strlist__for_each(node, vl->vars) {
487 var = strchr(node->s, '\t') + 1;
488 if (strfilter__compare(_filter, var)) {
456 fprintf(stdout, "\t\t%s\n", node->s); 489 fprintf(stdout, "\t\t%s\n", node->s);
457 strlist__delete(vl->vars); 490 nvars++;
458 } else 491 }
459 fprintf(stdout, "(No variables)\n"); 492 }
493 strlist__delete(vl->vars);
460 } 494 }
461 free(vls); 495 if (nvars == 0)
462 } else 496 fprintf(stdout, "\t\t(No matched variables)\n");
463 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 497 }
464 498 free(vls);
499end:
465 free(buf); 500 free(buf);
466 return ret; 501 return ret;
467} 502}
468 503
469/* Show available variables on given probe point */ 504/* Show available variables on given probe point */
470int show_available_vars(struct perf_probe_event *pevs, int npevs, 505int show_available_vars(struct perf_probe_event *pevs, int npevs,
471 int max_vls, const char *module, bool externs) 506 int max_vls, const char *module,
507 struct strfilter *_filter, bool externs)
472{ 508{
473 int i, fd, ret = 0; 509 int i, fd, ret = 0;
474 510
@@ -485,7 +521,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
485 setup_pager(); 521 setup_pager();
486 522
487 for (i = 0; i < npevs && ret >= 0; i++) 523 for (i = 0; i < npevs && ret >= 0; i++)
488 ret = show_available_vars_at(fd, &pevs[i], max_vls, externs); 524 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
525 externs);
489 526
490 close(fd); 527 close(fd);
491 return ret; 528 return ret;
@@ -531,7 +568,9 @@ int show_line_range(struct line_range *lr __unused, const char *module __unused)
531 568
532int show_available_vars(struct perf_probe_event *pevs __unused, 569int show_available_vars(struct perf_probe_event *pevs __unused,
533 int npevs __unused, int max_vls __unused, 570 int npevs __unused, int max_vls __unused,
534 const char *module __unused, bool externs __unused) 571 const char *module __unused,
572 struct strfilter *filter __unused,
573 bool externs __unused)
535{ 574{
536 pr_warning("Debuginfo-analysis is not supported.\n"); 575 pr_warning("Debuginfo-analysis is not supported.\n");
537 return -ENOSYS; 576 return -ENOSYS;
@@ -556,11 +595,11 @@ static int parse_line_num(char **ptr, int *val, const char *what)
556 * The line range syntax is described by: 595 * The line range syntax is described by:
557 * 596 *
558 * SRC[:SLN[+NUM|-ELN]] 597 * SRC[:SLN[+NUM|-ELN]]
559 * FNC[:SLN[+NUM|-ELN]] 598 * FNC[@SRC][:SLN[+NUM|-ELN]]
560 */ 599 */
561int parse_line_range_desc(const char *arg, struct line_range *lr) 600int parse_line_range_desc(const char *arg, struct line_range *lr)
562{ 601{
563 char *range, *name = strdup(arg); 602 char *range, *file, *name = strdup(arg);
564 int err; 603 int err;
565 604
566 if (!name) 605 if (!name)
@@ -610,7 +649,16 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
610 } 649 }
611 } 650 }
612 651
613 if (strchr(name, '.')) 652 file = strchr(name, '@');
653 if (file) {
654 *file = '\0';
655 lr->file = strdup(++file);
656 if (lr->file == NULL) {
657 err = -ENOMEM;
658 goto err;
659 }
660 lr->function = name;
661 } else if (strchr(name, '.'))
614 lr->file = name; 662 lr->file = name;
615 else 663 else
616 lr->function = name; 664 lr->function = name;
@@ -1784,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1784 } 1832 }
1785 1833
1786 /* Loop 2: add all events */ 1834 /* Loop 2: add all events */
1787 for (i = 0; i < npevs && ret >= 0; i++) 1835 for (i = 0; i < npevs; i++) {
1788 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1836 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1789 pkgs[i].ntevs, force_add); 1837 pkgs[i].ntevs, force_add);
1838 if (ret < 0)
1839 break;
1840 }
1790end: 1841end:
1791 /* Loop 3: cleanup and free trace events */ 1842 /* Loop 3: cleanup and free trace events */
1792 for (i = 0; i < npevs; i++) { 1843 for (i = 0; i < npevs; i++) {
@@ -1912,4 +1963,46 @@ int del_perf_probe_events(struct strlist *dellist)
1912 1963
1913 return ret; 1964 return ret;
1914} 1965}
1966/* TODO: don't use a global variable for filter ... */
1967static struct strfilter *available_func_filter;
1968
1969/*
1970 * If a symbol corresponds to a function with global binding and
1971 * matches filter return 0. For all others return 1.
1972 */
1973static int filter_available_functions(struct map *map __unused,
1974 struct symbol *sym)
1975{
1976 if (sym->binding == STB_GLOBAL &&
1977 strfilter__compare(available_func_filter, sym->name))
1978 return 0;
1979 return 1;
1980}
1981
1982int show_available_funcs(const char *module, struct strfilter *_filter)
1983{
1984 struct map *map;
1985 int ret;
1986
1987 setup_pager();
1988
1989 ret = init_vmlinux();
1990 if (ret < 0)
1991 return ret;
1915 1992
1993 map = kernel_get_module_map(module);
1994 if (!map) {
1995 pr_err("Failed to find %s map.\n", (module) ? : "kernel");
1996 return -EINVAL;
1997 }
1998 available_func_filter = _filter;
1999 if (map__load(map, filter_available_functions)) {
2000 pr_err("Failed to load map.\n");
2001 return -EINVAL;
2002 }
2003 if (!dso__sorted_by_name(map->dso, map->type))
2004 dso__sort_by_name(map->dso, map->type);
2005
2006 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2007 return 0;
2008}