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.c189
1 files changed, 148 insertions, 41 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index fcc16e4349df..3b6a5297bf16 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -74,10 +74,9 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
74static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 74static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
75static struct machine machine; 75static struct machine machine;
76 76
77/* Initialize symbol maps and path of vmlinux */ 77/* Initialize symbol maps and path of vmlinux/modules */
78static int init_vmlinux(void) 78static int init_vmlinux(void)
79{ 79{
80 struct dso *kernel;
81 int ret; 80 int ret;
82 81
83 symbol_conf.sort_by_name = true; 82 symbol_conf.sort_by_name = true;
@@ -91,33 +90,61 @@ static int init_vmlinux(void)
91 goto out; 90 goto out;
92 } 91 }
93 92
94 ret = machine__init(&machine, "/", 0); 93 ret = machine__init(&machine, "", HOST_KERNEL_ID);
95 if (ret < 0) 94 if (ret < 0)
96 goto out; 95 goto out;
97 96
98 kernel = dso__new_kernel(symbol_conf.vmlinux_name); 97 if (machine__create_kernel_maps(&machine) < 0) {
99 if (kernel == NULL) 98 pr_debug("machine__create_kernel_maps ");
100 die("Failed to create kernel dso."); 99 goto out;
101 100 }
102 ret = __machine__create_kernel_maps(&machine, kernel);
103 if (ret < 0)
104 pr_debug("Failed to create kernel maps.\n");
105
106out: 101out:
107 if (ret < 0) 102 if (ret < 0)
108 pr_warning("Failed to init vmlinux path.\n"); 103 pr_warning("Failed to init vmlinux path.\n");
109 return ret; 104 return ret;
110} 105}
111 106
107static struct symbol *__find_kernel_function_by_name(const char *name,
108 struct map **mapp)
109{
110 return machine__find_kernel_function_by_name(&machine, name, mapp,
111 NULL);
112}
113
114const char *kernel_get_module_path(const char *module)
115{
116 struct dso *dso;
117
118 if (module) {
119 list_for_each_entry(dso, &machine.kernel_dsos, node) {
120 if (strncmp(dso->short_name + 1, module,
121 dso->short_name_len - 2) == 0)
122 goto found;
123 }
124 pr_debug("Failed to find module %s.\n", module);
125 return NULL;
126 } else {
127 dso = machine.vmlinux_maps[MAP__FUNCTION]->dso;
128 if (dso__load_vmlinux_path(dso,
129 machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
130 pr_debug("Failed to load kernel map.\n");
131 return NULL;
132 }
133 }
134found:
135 return dso->long_name;
136}
137
112#ifdef DWARF_SUPPORT 138#ifdef DWARF_SUPPORT
113static int open_vmlinux(void) 139static int open_vmlinux(const char *module)
114{ 140{
115 if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { 141 const char *path = kernel_get_module_path(module);
116 pr_debug("Failed to load kernel map.\n"); 142 if (!path) {
117 return -EINVAL; 143 pr_err("Failed to find path of %s module", module ?: "kernel");
144 return -ENOENT;
118 } 145 }
119 pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name); 146 pr_debug("Try to open %s\n", path);
120 return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY); 147 return open(path, O_RDONLY);
121} 148}
122 149
123/* 150/*
@@ -125,20 +152,19 @@ static int open_vmlinux(void)
125 * Currently only handles kprobes. 152 * Currently only handles kprobes.
126 */ 153 */
127static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 154static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
128 struct perf_probe_point *pp) 155 struct perf_probe_point *pp)
129{ 156{
130 struct symbol *sym; 157 struct symbol *sym;
131 int fd, ret = -ENOENT; 158 struct map *map;
159 u64 addr;
160 int ret = -ENOENT;
132 161
133 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], 162 sym = __find_kernel_function_by_name(tp->symbol, &map);
134 tp->symbol, NULL);
135 if (sym) { 163 if (sym) {
136 fd = open_vmlinux(); 164 addr = map->unmap_ip(map, sym->start + tp->offset);
137 if (fd >= 0) { 165 pr_debug("try to find %s+%ld@%llx\n", tp->symbol,
138 ret = find_perf_probe_point(fd, 166 tp->offset, addr);
139 sym->start + tp->offset, pp); 167 ret = find_perf_probe_point((unsigned long)addr, pp);
140 close(fd);
141 }
142 } 168 }
143 if (ret <= 0) { 169 if (ret <= 0) {
144 pr_debug("Failed to find corresponding probes from " 170 pr_debug("Failed to find corresponding probes from "
@@ -156,12 +182,12 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
156/* Try to find perf_probe_event with debuginfo */ 182/* Try to find perf_probe_event with debuginfo */
157static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 183static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
158 struct probe_trace_event **tevs, 184 struct probe_trace_event **tevs,
159 int max_tevs) 185 int max_tevs, const char *module)
160{ 186{
161 bool need_dwarf = perf_probe_event_need_dwarf(pev); 187 bool need_dwarf = perf_probe_event_need_dwarf(pev);
162 int fd, ntevs; 188 int fd, ntevs;
163 189
164 fd = open_vmlinux(); 190 fd = open_vmlinux(module);
165 if (fd < 0) { 191 if (fd < 0) {
166 if (need_dwarf) { 192 if (need_dwarf) {
167 pr_warning("Failed to open debuginfo file.\n"); 193 pr_warning("Failed to open debuginfo file.\n");
@@ -300,7 +326,7 @@ error:
300 * Show line-range always requires debuginfo to find source file and 326 * Show line-range always requires debuginfo to find source file and
301 * line number. 327 * line number.
302 */ 328 */
303int show_line_range(struct line_range *lr) 329int show_line_range(struct line_range *lr, const char *module)
304{ 330{
305 int l = 1; 331 int l = 1;
306 struct line_node *ln; 332 struct line_node *ln;
@@ -313,7 +339,7 @@ int show_line_range(struct line_range *lr)
313 if (ret < 0) 339 if (ret < 0)
314 return ret; 340 return ret;
315 341
316 fd = open_vmlinux(); 342 fd = open_vmlinux(module);
317 if (fd < 0) { 343 if (fd < 0) {
318 pr_warning("Failed to open debuginfo file.\n"); 344 pr_warning("Failed to open debuginfo file.\n");
319 return fd; 345 return fd;
@@ -378,11 +404,84 @@ end:
378 return ret; 404 return ret;
379} 405}
380 406
407static int show_available_vars_at(int fd, struct perf_probe_event *pev,
408 int max_vls, bool externs)
409{
410 char *buf;
411 int ret, i;
412 struct str_node *node;
413 struct variable_list *vls = NULL, *vl;
414
415 buf = synthesize_perf_probe_point(&pev->point);
416 if (!buf)
417 return -EINVAL;
418 pr_debug("Searching variables at %s\n", buf);
419
420 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
421 if (ret > 0) {
422 /* Some variables were found */
423 fprintf(stdout, "Available variables at %s\n", buf);
424 for (i = 0; i < ret; i++) {
425 vl = &vls[i];
426 /*
427 * A probe point might be converted to
428 * several trace points.
429 */
430 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
431 vl->point.offset);
432 free(vl->point.symbol);
433 if (vl->vars) {
434 strlist__for_each(node, vl->vars)
435 fprintf(stdout, "\t\t%s\n", node->s);
436 strlist__delete(vl->vars);
437 } else
438 fprintf(stdout, "(No variables)\n");
439 }
440 free(vls);
441 } else
442 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
443
444 free(buf);
445 return ret;
446}
447
448/* Show available variables on given probe point */
449int show_available_vars(struct perf_probe_event *pevs, int npevs,
450 int max_vls, const char *module, bool externs)
451{
452 int i, fd, ret = 0;
453
454 ret = init_vmlinux();
455 if (ret < 0)
456 return ret;
457
458 fd = open_vmlinux(module);
459 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n");
461 return fd;
462 }
463
464 setup_pager();
465
466 for (i = 0; i < npevs && ret >= 0; i++)
467 ret = show_available_vars_at(fd, &pevs[i], max_vls, externs);
468
469 close(fd);
470 return ret;
471}
472
381#else /* !DWARF_SUPPORT */ 473#else /* !DWARF_SUPPORT */
382 474
383static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 475static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
384 struct perf_probe_point *pp) 476 struct perf_probe_point *pp)
385{ 477{
478 struct symbol *sym;
479
480 sym = __find_kernel_function_by_name(tp->symbol, NULL);
481 if (!sym) {
482 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
483 return -ENOENT;
484 }
386 pp->function = strdup(tp->symbol); 485 pp->function = strdup(tp->symbol);
387 if (pp->function == NULL) 486 if (pp->function == NULL)
388 return -ENOMEM; 487 return -ENOMEM;
@@ -394,7 +493,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
394 493
395static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 494static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
396 struct probe_trace_event **tevs __unused, 495 struct probe_trace_event **tevs __unused,
397 int max_tevs __unused) 496 int max_tevs __unused, const char *mod __unused)
398{ 497{
399 if (perf_probe_event_need_dwarf(pev)) { 498 if (perf_probe_event_need_dwarf(pev)) {
400 pr_warning("Debuginfo-analysis is not supported.\n"); 499 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -403,12 +502,19 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
403 return 0; 502 return 0;
404} 503}
405 504
406int show_line_range(struct line_range *lr __unused) 505int show_line_range(struct line_range *lr __unused, const char *module __unused)
407{ 506{
408 pr_warning("Debuginfo-analysis is not supported.\n"); 507 pr_warning("Debuginfo-analysis is not supported.\n");
409 return -ENOSYS; 508 return -ENOSYS;
410} 509}
411 510
511int show_available_vars(struct perf_probe_event *pevs __unused,
512 int npevs __unused, int max_vls __unused,
513 const char *module __unused, bool externs __unused)
514{
515 pr_warning("Debuginfo-analysis is not supported.\n");
516 return -ENOSYS;
517}
412#endif 518#endif
413 519
414int parse_line_range_desc(const char *arg, struct line_range *lr) 520int parse_line_range_desc(const char *arg, struct line_range *lr)
@@ -1087,7 +1193,7 @@ error:
1087} 1193}
1088 1194
1089static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1195static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1090 struct perf_probe_event *pev) 1196 struct perf_probe_event *pev)
1091{ 1197{
1092 char buf[64] = ""; 1198 char buf[64] = "";
1093 int i, ret; 1199 int i, ret;
@@ -1516,14 +1622,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1516 1622
1517static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1623static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1518 struct probe_trace_event **tevs, 1624 struct probe_trace_event **tevs,
1519 int max_tevs) 1625 int max_tevs, const char *module)
1520{ 1626{
1521 struct symbol *sym; 1627 struct symbol *sym;
1522 int ret = 0, i; 1628 int ret = 0, i;
1523 struct probe_trace_event *tev; 1629 struct probe_trace_event *tev;
1524 1630
1525 /* Convert perf_probe_event with debuginfo */ 1631 /* Convert perf_probe_event with debuginfo */
1526 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs); 1632 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1527 if (ret != 0) 1633 if (ret != 0)
1528 return ret; 1634 return ret;
1529 1635
@@ -1572,8 +1678,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1572 } 1678 }
1573 1679
1574 /* Currently just checking function name from symbol map */ 1680 /* Currently just checking function name from symbol map */
1575 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], 1681 sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1576 tev->point.symbol, NULL);
1577 if (!sym) { 1682 if (!sym) {
1578 pr_warning("Kernel symbol \'%s\' not found.\n", 1683 pr_warning("Kernel symbol \'%s\' not found.\n",
1579 tev->point.symbol); 1684 tev->point.symbol);
@@ -1596,7 +1701,7 @@ struct __event_package {
1596}; 1701};
1597 1702
1598int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1703int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1599 bool force_add, int max_tevs) 1704 int max_tevs, const char *module, bool force_add)
1600{ 1705{
1601 int i, j, ret; 1706 int i, j, ret;
1602 struct __event_package *pkgs; 1707 struct __event_package *pkgs;
@@ -1617,7 +1722,9 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1617 pkgs[i].pev = &pevs[i]; 1722 pkgs[i].pev = &pevs[i];
1618 /* Convert with or without debuginfo */ 1723 /* Convert with or without debuginfo */
1619 ret = convert_to_probe_trace_events(pkgs[i].pev, 1724 ret = convert_to_probe_trace_events(pkgs[i].pev,
1620 &pkgs[i].tevs, max_tevs); 1725 &pkgs[i].tevs,
1726 max_tevs,
1727 module);
1621 if (ret < 0) 1728 if (ret < 0)
1622 goto end; 1729 goto end;
1623 pkgs[i].ntevs = ret; 1730 pkgs[i].ntevs = ret;