aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /tools/perf/util/probe-event.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c524
1 files changed, 387 insertions, 137 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index fcc16e4349df..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"
@@ -74,10 +75,9 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
74static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 75static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
75static struct machine machine; 76static struct machine machine;
76 77
77/* Initialize symbol maps and path of vmlinux */ 78/* Initialize symbol maps and path of vmlinux/modules */
78static int init_vmlinux(void) 79static int init_vmlinux(void)
79{ 80{
80 struct dso *kernel;
81 int ret; 81 int ret;
82 82
83 symbol_conf.sort_by_name = true; 83 symbol_conf.sort_by_name = true;
@@ -91,33 +91,95 @@ static int init_vmlinux(void)
91 goto out; 91 goto out;
92 } 92 }
93 93
94 ret = machine__init(&machine, "/", 0); 94 ret = machine__init(&machine, "", HOST_KERNEL_ID);
95 if (ret < 0) 95 if (ret < 0)
96 goto out; 96 goto out;
97 97
98 kernel = dso__new_kernel(symbol_conf.vmlinux_name); 98 if (machine__create_kernel_maps(&machine) < 0) {
99 if (kernel == NULL) 99 pr_debug("machine__create_kernel_maps() failed.\n");
100 die("Failed to create kernel dso."); 100 goto out;
101 101 }
102 ret = __machine__create_kernel_maps(&machine, kernel);
103 if (ret < 0)
104 pr_debug("Failed to create kernel maps.\n");
105
106out: 102out:
107 if (ret < 0) 103 if (ret < 0)
108 pr_warning("Failed to init vmlinux path.\n"); 104 pr_warning("Failed to init vmlinux path.\n");
109 return ret; 105 return ret;
110} 106}
111 107
108static struct symbol *__find_kernel_function_by_name(const char *name,
109 struct map **mapp)
110{
111 return machine__find_kernel_function_by_name(&machine, name, mapp,
112 NULL);
113}
114
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)
134{
135 struct dso *dso;
136 struct map *map;
137 const char *vmlinux_name;
138
139 if (module) {
140 list_for_each_entry(dso, &machine.kernel_dsos, node) {
141 if (strncmp(dso->short_name + 1, module,
142 dso->short_name_len - 2) == 0)
143 goto found;
144 }
145 pr_debug("Failed to find module %s.\n", module);
146 return NULL;
147 }
148
149 map = machine.vmlinux_maps[MAP__FUNCTION];
150 dso = map->dso;
151
152 vmlinux_name = symbol_conf.vmlinux_name;
153 if (vmlinux_name) {
154 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
155 return NULL;
156 } else {
157 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
158 pr_debug("Failed to load kernel map.\n");
159 return NULL;
160 }
161 }
162found:
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;
170}
171
112#ifdef DWARF_SUPPORT 172#ifdef DWARF_SUPPORT
113static int open_vmlinux(void) 173static int open_vmlinux(const char *module)
114{ 174{
115 if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { 175 const char *path = kernel_get_module_path(module);
116 pr_debug("Failed to load kernel map.\n"); 176 if (!path) {
117 return -EINVAL; 177 pr_err("Failed to find path of %s module.\n",
178 module ?: "kernel");
179 return -ENOENT;
118 } 180 }
119 pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name); 181 pr_debug("Try to open %s\n", path);
120 return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY); 182 return open(path, O_RDONLY);
121} 183}
122 184
123/* 185/*
@@ -125,20 +187,19 @@ static int open_vmlinux(void)
125 * Currently only handles kprobes. 187 * Currently only handles kprobes.
126 */ 188 */
127static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 189static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
128 struct perf_probe_point *pp) 190 struct perf_probe_point *pp)
129{ 191{
130 struct symbol *sym; 192 struct symbol *sym;
131 int fd, ret = -ENOENT; 193 struct map *map;
194 u64 addr;
195 int ret = -ENOENT;
132 196
133 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], 197 sym = __find_kernel_function_by_name(tp->symbol, &map);
134 tp->symbol, NULL);
135 if (sym) { 198 if (sym) {
136 fd = open_vmlinux(); 199 addr = map->unmap_ip(map, sym->start + tp->offset);
137 if (fd >= 0) { 200 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
138 ret = find_perf_probe_point(fd, 201 tp->offset, addr);
139 sym->start + tp->offset, pp); 202 ret = find_perf_probe_point((unsigned long)addr, pp);
140 close(fd);
141 }
142 } 203 }
143 if (ret <= 0) { 204 if (ret <= 0) {
144 pr_debug("Failed to find corresponding probes from " 205 pr_debug("Failed to find corresponding probes from "
@@ -156,12 +217,12 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
156/* Try to find perf_probe_event with debuginfo */ 217/* Try to find perf_probe_event with debuginfo */
157static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 218static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
158 struct probe_trace_event **tevs, 219 struct probe_trace_event **tevs,
159 int max_tevs) 220 int max_tevs, const char *module)
160{ 221{
161 bool need_dwarf = perf_probe_event_need_dwarf(pev); 222 bool need_dwarf = perf_probe_event_need_dwarf(pev);
162 int fd, ntevs; 223 int fd, ntevs;
163 224
164 fd = open_vmlinux(); 225 fd = open_vmlinux(module);
165 if (fd < 0) { 226 if (fd < 0) {
166 if (need_dwarf) { 227 if (need_dwarf) {
167 pr_warning("Failed to open debuginfo file.\n"); 228 pr_warning("Failed to open debuginfo file.\n");
@@ -173,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
173 234
174 /* Searching trace events corresponding to probe event */ 235 /* Searching trace events corresponding to probe event */
175 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
176 close(fd);
177 237
178 if (ntevs > 0) { /* Succeeded to find trace events */ 238 if (ntevs > 0) { /* Succeeded to find trace events */
179 pr_debug("find %d probe_trace_events.\n", ntevs); 239 pr_debug("find %d probe_trace_events.\n", ntevs);
@@ -191,7 +251,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
191 pr_warning("Warning: No dwarf info found in the vmlinux - " 251 pr_warning("Warning: No dwarf info found in the vmlinux - "
192 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 252 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
193 if (!need_dwarf) { 253 if (!need_dwarf) {
194 pr_debug("Trying to use symbols.\nn"); 254 pr_debug("Trying to use symbols.\n");
195 return 0; 255 return 0;
196 } 256 }
197 } 257 }
@@ -260,47 +320,54 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
260#define LINEBUF_SIZE 256 320#define LINEBUF_SIZE 256
261#define NR_ADDITIONAL_LINES 2 321#define NR_ADDITIONAL_LINES 2
262 322
263static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 323static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
264{ 324{
265 char buf[LINEBUF_SIZE]; 325 char buf[LINEBUF_SIZE];
266 const char *color = PERF_COLOR_BLUE; 326 const char *color = show_num ? "" : PERF_COLOR_BLUE;
267 327 const char *prefix = NULL;
268 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
269 goto error;
270 if (!skip) {
271 if (show_num)
272 fprintf(stdout, "%7d %s", l, buf);
273 else
274 color_fprintf(stdout, color, " %s", buf);
275 }
276 328
277 while (strlen(buf) == LINEBUF_SIZE - 1 && 329 do {
278 buf[LINEBUF_SIZE - 2] != '\n') {
279 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 330 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
280 goto error; 331 goto error;
281 if (!skip) { 332 if (skip)
282 if (show_num) 333 continue;
283 fprintf(stdout, "%s", buf); 334 if (!prefix) {
284 else 335 prefix = show_num ? "%7d " : " ";
285 color_fprintf(stdout, color, "%s", buf); 336 color_fprintf(stdout, color, prefix, l);
286 } 337 }
287 } 338 color_fprintf(stdout, color, "%s", buf);
288 339
289 return 0; 340 } while (strchr(buf, '\n') == NULL);
341
342 return 1;
290error: 343error:
291 if (feof(fp)) 344 if (ferror(fp)) {
292 pr_warning("Source file is shorter than expected.\n");
293 else
294 pr_warning("File read error: %s\n", strerror(errno)); 345 pr_warning("File read error: %s\n", strerror(errno));
346 return -1;
347 }
348 return 0;
349}
295 350
296 return -1; 351static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
352{
353 int rv = __show_one_line(fp, l, skip, show_num);
354 if (rv == 0) {
355 pr_warning("Source file is shorter than expected.\n");
356 rv = -1;
357 }
358 return rv;
297} 359}
298 360
361#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
362#define show_one_line(f,l) _show_one_line(f,l,false,false)
363#define skip_one_line(f,l) _show_one_line(f,l,true,false)
364#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
365
299/* 366/*
300 * Show line-range always requires debuginfo to find source file and 367 * Show line-range always requires debuginfo to find source file and
301 * line number. 368 * line number.
302 */ 369 */
303int show_line_range(struct line_range *lr) 370int show_line_range(struct line_range *lr, const char *module)
304{ 371{
305 int l = 1; 372 int l = 1;
306 struct line_node *ln; 373 struct line_node *ln;
@@ -313,14 +380,13 @@ int show_line_range(struct line_range *lr)
313 if (ret < 0) 380 if (ret < 0)
314 return ret; 381 return ret;
315 382
316 fd = open_vmlinux(); 383 fd = open_vmlinux(module);
317 if (fd < 0) { 384 if (fd < 0) {
318 pr_warning("Failed to open debuginfo file.\n"); 385 pr_warning("Failed to open debuginfo file.\n");
319 return fd; 386 return fd;
320 } 387 }
321 388
322 ret = find_line_range(fd, lr); 389 ret = find_line_range(fd, lr);
323 close(fd);
324 if (ret == 0) { 390 if (ret == 0) {
325 pr_warning("Specified source line is not found.\n"); 391 pr_warning("Specified source line is not found.\n");
326 return -ENOENT; 392 return -ENOENT;
@@ -341,10 +407,10 @@ int show_line_range(struct line_range *lr)
341 setup_pager(); 407 setup_pager();
342 408
343 if (lr->function) 409 if (lr->function)
344 fprintf(stdout, "<%s:%d>\n", lr->function, 410 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
345 lr->start - lr->offset); 411 lr->start - lr->offset);
346 else 412 else
347 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 413 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
348 414
349 fp = fopen(lr->path, "r"); 415 fp = fopen(lr->path, "r");
350 if (fp == NULL) { 416 if (fp == NULL) {
@@ -353,36 +419,124 @@ int show_line_range(struct line_range *lr)
353 return -errno; 419 return -errno;
354 } 420 }
355 /* Skip to starting line number */ 421 /* Skip to starting line number */
356 while (l < lr->start && ret >= 0) 422 while (l < lr->start) {
357 ret = show_one_line(fp, l++, true, false); 423 ret = skip_one_line(fp, l++);
358 if (ret < 0) 424 if (ret < 0)
359 goto end; 425 goto end;
426 }
360 427
361 list_for_each_entry(ln, &lr->line_list, list) { 428 list_for_each_entry(ln, &lr->line_list, list) {
362 while (ln->line > l && ret >= 0) 429 for (; ln->line > l; l++) {
363 ret = show_one_line(fp, (l++) - lr->offset, 430 ret = show_one_line(fp, l - lr->offset);
364 false, false); 431 if (ret < 0)
365 if (ret >= 0) 432 goto end;
366 ret = show_one_line(fp, (l++) - lr->offset, 433 }
367 false, true); 434 ret = show_one_line_with_num(fp, l++ - lr->offset);
368 if (ret < 0) 435 if (ret < 0)
369 goto end; 436 goto end;
370 } 437 }
371 438
372 if (lr->end == INT_MAX) 439 if (lr->end == INT_MAX)
373 lr->end = l + NR_ADDITIONAL_LINES; 440 lr->end = l + NR_ADDITIONAL_LINES;
374 while (l <= lr->end && !feof(fp) && ret >= 0) 441 while (l <= lr->end) {
375 ret = show_one_line(fp, (l++) - lr->offset, false, false); 442 ret = show_one_line_or_eof(fp, l++ - lr->offset);
443 if (ret <= 0)
444 break;
445 }
376end: 446end:
377 fclose(fp); 447 fclose(fp);
378 return ret; 448 return ret;
379} 449}
380 450
451static int show_available_vars_at(int fd, struct perf_probe_event *pev,
452 int max_vls, struct strfilter *_filter,
453 bool externs)
454{
455 char *buf;
456 int ret, i, nvars;
457 struct str_node *node;
458 struct variable_list *vls = NULL, *vl;
459 const char *var;
460
461 buf = synthesize_perf_probe_point(&pev->point);
462 if (!buf)
463 return -EINVAL;
464 pr_debug("Searching variables at %s\n", buf);
465
466 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
467 if (ret <= 0) {
468 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
469 goto end;
470 }
471 /* Some variables are found */
472 fprintf(stdout, "Available variables at %s\n", buf);
473 for (i = 0; i < ret; i++) {
474 vl = &vls[i];
475 /*
476 * A probe point might be converted to
477 * several trace points.
478 */
479 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
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)) {
487 fprintf(stdout, "\t\t%s\n", node->s);
488 nvars++;
489 }
490 }
491 strlist__delete(vl->vars);
492 }
493 if (nvars == 0)
494 fprintf(stdout, "\t\t(No matched variables)\n");
495 }
496 free(vls);
497end:
498 free(buf);
499 return ret;
500}
501
502/* Show available variables on given probe point */
503int show_available_vars(struct perf_probe_event *pevs, int npevs,
504 int max_vls, const char *module,
505 struct strfilter *_filter, bool externs)
506{
507 int i, fd, ret = 0;
508
509 ret = init_vmlinux();
510 if (ret < 0)
511 return ret;
512
513 setup_pager();
514
515 for (i = 0; i < npevs && ret >= 0; i++) {
516 fd = open_vmlinux(module);
517 if (fd < 0) {
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 }
525 return ret;
526}
527
381#else /* !DWARF_SUPPORT */ 528#else /* !DWARF_SUPPORT */
382 529
383static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 530static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
384 struct perf_probe_point *pp) 531 struct perf_probe_point *pp)
385{ 532{
533 struct symbol *sym;
534
535 sym = __find_kernel_function_by_name(tp->symbol, NULL);
536 if (!sym) {
537 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
538 return -ENOENT;
539 }
386 pp->function = strdup(tp->symbol); 540 pp->function = strdup(tp->symbol);
387 if (pp->function == NULL) 541 if (pp->function == NULL)
388 return -ENOMEM; 542 return -ENOMEM;
@@ -394,7 +548,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
394 548
395static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 549static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
396 struct probe_trace_event **tevs __unused, 550 struct probe_trace_event **tevs __unused,
397 int max_tevs __unused) 551 int max_tevs __unused, const char *mod __unused)
398{ 552{
399 if (perf_probe_event_need_dwarf(pev)) { 553 if (perf_probe_event_need_dwarf(pev)) {
400 pr_warning("Debuginfo-analysis is not supported.\n"); 554 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -403,64 +557,113 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
403 return 0; 557 return 0;
404} 558}
405 559
406int show_line_range(struct line_range *lr __unused) 560int show_line_range(struct line_range *lr __unused, const char *module __unused)
407{ 561{
408 pr_warning("Debuginfo-analysis is not supported.\n"); 562 pr_warning("Debuginfo-analysis is not supported.\n");
409 return -ENOSYS; 563 return -ENOSYS;
410} 564}
411 565
566int show_available_vars(struct perf_probe_event *pevs __unused,
567 int npevs __unused, int max_vls __unused,
568 const char *module __unused,
569 struct strfilter *filter __unused,
570 bool externs __unused)
571{
572 pr_warning("Debuginfo-analysis is not supported.\n");
573 return -ENOSYS;
574}
412#endif 575#endif
413 576
577static int parse_line_num(char **ptr, int *val, const char *what)
578{
579 const char *start = *ptr;
580
581 errno = 0;
582 *val = strtol(*ptr, ptr, 0);
583 if (errno || *ptr == start) {
584 semantic_error("'%s' is not a valid number.\n", what);
585 return -EINVAL;
586 }
587 return 0;
588}
589
590/*
591 * Stuff 'lr' according to the line range described by 'arg'.
592 * The line range syntax is described by:
593 *
594 * SRC[:SLN[+NUM|-ELN]]
595 * FNC[@SRC][:SLN[+NUM|-ELN]]
596 */
414int parse_line_range_desc(const char *arg, struct line_range *lr) 597int parse_line_range_desc(const char *arg, struct line_range *lr)
415{ 598{
416 const char *ptr; 599 char *range, *file, *name = strdup(arg);
417 char *tmp; 600 int err;
418 /* 601
419 * <Syntax> 602 if (!name)
420 * SRC:SLN[+NUM|-ELN] 603 return -ENOMEM;
421 * FUNC[:SLN[+NUM|-ELN]] 604
422 */ 605 lr->start = 0;
423 ptr = strchr(arg, ':'); 606 lr->end = INT_MAX;
424 if (ptr) { 607
425 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 608 range = strchr(name, ':');
426 if (*tmp == '+') { 609 if (range) {
427 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 610 *range++ = '\0';
428 lr->end--; /* 611
429 * Adjust the number of lines here. 612 err = parse_line_num(&range, &lr->start, "start line");
430 * If the number of lines == 1, the 613 if (err)
431 * the end of line should be equal to 614 goto err;
432 * the start of line. 615
433 */ 616 if (*range == '+' || *range == '-') {
434 } else if (*tmp == '-') 617 const char c = *range++;
435 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 618
436 else 619 err = parse_line_num(&range, &lr->end, "end line");
437 lr->end = INT_MAX; 620 if (err)
621 goto err;
622
623 if (c == '+') {
624 lr->end += lr->start;
625 /*
626 * Adjust the number of lines here.
627 * If the number of lines == 1, the
628 * the end of line should be equal to
629 * the start of line.
630 */
631 lr->end--;
632 }
633 }
634
438 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 635 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
636
637 err = -EINVAL;
439 if (lr->start > lr->end) { 638 if (lr->start > lr->end) {
440 semantic_error("Start line must be smaller" 639 semantic_error("Start line must be smaller"
441 " than end line.\n"); 640 " than end line.\n");
442 return -EINVAL; 641 goto err;
443 } 642 }
444 if (*tmp != '\0') { 643 if (*range != '\0') {
445 semantic_error("Tailing with invalid character '%d'.\n", 644 semantic_error("Tailing with invalid str '%s'.\n", range);
446 *tmp); 645 goto err;
447 return -EINVAL;
448 } 646 }
449 tmp = strndup(arg, (ptr - arg));
450 } else {
451 tmp = strdup(arg);
452 lr->end = INT_MAX;
453 } 647 }
454 648
455 if (tmp == NULL) 649 file = strchr(name, '@');
456 return -ENOMEM; 650 if (file) {
457 651 *file = '\0';
458 if (strchr(tmp, '.')) 652 lr->file = strdup(++file);
459 lr->file = tmp; 653 if (lr->file == NULL) {
654 err = -ENOMEM;
655 goto err;
656 }
657 lr->function = name;
658 } else if (strchr(name, '.'))
659 lr->file = name;
460 else 660 else
461 lr->function = tmp; 661 lr->function = name;
462 662
463 return 0; 663 return 0;
664err:
665 free(name);
666 return err;
464} 667}
465 668
466/* Check the name is good for event/group */ 669/* Check the name is good for event/group */
@@ -584,39 +787,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
584 787
585 /* Exclusion check */ 788 /* Exclusion check */
586 if (pp->lazy_line && pp->line) { 789 if (pp->lazy_line && pp->line) {
587 semantic_error("Lazy pattern can't be used with line number."); 790 semantic_error("Lazy pattern can't be used with"
791 " line number.\n");
588 return -EINVAL; 792 return -EINVAL;
589 } 793 }
590 794
591 if (pp->lazy_line && pp->offset) { 795 if (pp->lazy_line && pp->offset) {
592 semantic_error("Lazy pattern can't be used with offset."); 796 semantic_error("Lazy pattern can't be used with offset.\n");
593 return -EINVAL; 797 return -EINVAL;
594 } 798 }
595 799
596 if (pp->line && pp->offset) { 800 if (pp->line && pp->offset) {
597 semantic_error("Offset can't be used with line number."); 801 semantic_error("Offset can't be used with line number.\n");
598 return -EINVAL; 802 return -EINVAL;
599 } 803 }
600 804
601 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 805 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
602 semantic_error("File always requires line number or " 806 semantic_error("File always requires line number or "
603 "lazy pattern."); 807 "lazy pattern.\n");
604 return -EINVAL; 808 return -EINVAL;
605 } 809 }
606 810
607 if (pp->offset && !pp->function) { 811 if (pp->offset && !pp->function) {
608 semantic_error("Offset requires an entry function."); 812 semantic_error("Offset requires an entry function.\n");
609 return -EINVAL; 813 return -EINVAL;
610 } 814 }
611 815
612 if (pp->retprobe && !pp->function) { 816 if (pp->retprobe && !pp->function) {
613 semantic_error("Return probe requires an entry function."); 817 semantic_error("Return probe requires an entry function.\n");
614 return -EINVAL; 818 return -EINVAL;
615 } 819 }
616 820
617 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 821 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
618 semantic_error("Offset/Line/Lazy pattern can't be used with " 822 semantic_error("Offset/Line/Lazy pattern can't be used with "
619 "return probe."); 823 "return probe.\n");
620 return -EINVAL; 824 return -EINVAL;
621 } 825 }
622 826
@@ -890,7 +1094,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
890 1094
891 return tmp - buf; 1095 return tmp - buf;
892error: 1096error:
893 pr_debug("Failed to synthesize perf probe argument: %s", 1097 pr_debug("Failed to synthesize perf probe argument: %s\n",
894 strerror(-ret)); 1098 strerror(-ret));
895 return ret; 1099 return ret;
896} 1100}
@@ -918,13 +1122,13 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
918 goto error; 1122 goto error;
919 } 1123 }
920 if (pp->file) { 1124 if (pp->file) {
921 len = strlen(pp->file) - 31; 1125 tmp = pp->file;
922 if (len < 0) 1126 len = strlen(tmp);
923 len = 0; 1127 if (len > 30) {
924 tmp = strchr(pp->file + len, '/'); 1128 tmp = strchr(pp->file + len - 30, '/');
925 if (!tmp) 1129 tmp = tmp ? tmp + 1 : pp->file + len - 30;
926 tmp = pp->file + len; 1130 }
927 ret = e_snprintf(file, 32, "@%s", tmp + 1); 1131 ret = e_snprintf(file, 32, "@%s", tmp);
928 if (ret <= 0) 1132 if (ret <= 0)
929 goto error; 1133 goto error;
930 } 1134 }
@@ -940,7 +1144,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
940 1144
941 return buf; 1145 return buf;
942error: 1146error:
943 pr_debug("Failed to synthesize perf probe point: %s", 1147 pr_debug("Failed to synthesize perf probe point: %s\n",
944 strerror(-ret)); 1148 strerror(-ret));
945 if (buf) 1149 if (buf)
946 free(buf); 1150 free(buf);
@@ -1087,7 +1291,7 @@ error:
1087} 1291}
1088 1292
1089static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1293static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1090 struct perf_probe_event *pev) 1294 struct perf_probe_event *pev)
1091{ 1295{
1092 char buf[64] = ""; 1296 char buf[64] = "";
1093 int i, ret; 1297 int i, ret;
@@ -1516,14 +1720,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1516 1720
1517static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1721static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1518 struct probe_trace_event **tevs, 1722 struct probe_trace_event **tevs,
1519 int max_tevs) 1723 int max_tevs, const char *module)
1520{ 1724{
1521 struct symbol *sym; 1725 struct symbol *sym;
1522 int ret = 0, i; 1726 int ret = 0, i;
1523 struct probe_trace_event *tev; 1727 struct probe_trace_event *tev;
1524 1728
1525 /* Convert perf_probe_event with debuginfo */ 1729 /* Convert perf_probe_event with debuginfo */
1526 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs); 1730 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1527 if (ret != 0) 1731 if (ret != 0)
1528 return ret; 1732 return ret;
1529 1733
@@ -1572,8 +1776,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1572 } 1776 }
1573 1777
1574 /* Currently just checking function name from symbol map */ 1778 /* Currently just checking function name from symbol map */
1575 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], 1779 sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1576 tev->point.symbol, NULL);
1577 if (!sym) { 1780 if (!sym) {
1578 pr_warning("Kernel symbol \'%s\' not found.\n", 1781 pr_warning("Kernel symbol \'%s\' not found.\n",
1579 tev->point.symbol); 1782 tev->point.symbol);
@@ -1596,7 +1799,7 @@ struct __event_package {
1596}; 1799};
1597 1800
1598int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1801int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1599 bool force_add, int max_tevs) 1802 int max_tevs, const char *module, bool force_add)
1600{ 1803{
1601 int i, j, ret; 1804 int i, j, ret;
1602 struct __event_package *pkgs; 1805 struct __event_package *pkgs;
@@ -1617,16 +1820,21 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1617 pkgs[i].pev = &pevs[i]; 1820 pkgs[i].pev = &pevs[i];
1618 /* Convert with or without debuginfo */ 1821 /* Convert with or without debuginfo */
1619 ret = convert_to_probe_trace_events(pkgs[i].pev, 1822 ret = convert_to_probe_trace_events(pkgs[i].pev,
1620 &pkgs[i].tevs, max_tevs); 1823 &pkgs[i].tevs,
1824 max_tevs,
1825 module);
1621 if (ret < 0) 1826 if (ret < 0)
1622 goto end; 1827 goto end;
1623 pkgs[i].ntevs = ret; 1828 pkgs[i].ntevs = ret;
1624 } 1829 }
1625 1830
1626 /* Loop 2: add all events */ 1831 /* Loop 2: add all events */
1627 for (i = 0; i < npevs && ret >= 0; i++) 1832 for (i = 0; i < npevs; i++) {
1628 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1833 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1629 pkgs[i].ntevs, force_add); 1834 pkgs[i].ntevs, force_add);
1835 if (ret < 0)
1836 break;
1837 }
1630end: 1838end:
1631 /* Loop 3: cleanup and free trace events */ 1839 /* Loop 3: cleanup and free trace events */
1632 for (i = 0; i < npevs; i++) { 1840 for (i = 0; i < npevs; i++) {
@@ -1680,7 +1888,7 @@ static int del_trace_probe_event(int fd, const char *group,
1680 1888
1681 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1889 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1682 if (ret < 0) { 1890 if (ret < 0) {
1683 pr_err("Failed to copy event."); 1891 pr_err("Failed to copy event.\n");
1684 return ret; 1892 return ret;
1685 } 1893 }
1686 1894
@@ -1752,4 +1960,46 @@ int del_perf_probe_events(struct strlist *dellist)
1752 1960
1753 return ret; 1961 return ret;
1754} 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}
1755 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}