aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-12-22 05:54:50 -0500
committerIngo Molnar <mingo@elte.hu>2010-12-22 05:54:50 -0500
commit8c1df4002aa425973d7d25ffa56c042acd953bed (patch)
tree441e39bf3a43bb3e4c4965ed2081b9bb90edd1ea /tools/perf/util
parent6c529a266bdc590a870ee2d2092ff6527eff427b (diff)
parent21dd9ae5a4e9f717f3957ec934dd3158129436b8 (diff)
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/hist.c14
-rw-r--r--tools/perf/util/probe-event.c220
-rw-r--r--tools/perf/util/probe-finder.c42
-rw-r--r--tools/perf/util/session.c11
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/symbol.c72
-rw-r--r--tools/perf/util/symbol.h1
7 files changed, 236 insertions, 129 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a3b84160c42e..d5036700a435 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1092,6 +1092,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1092 FILE *file; 1092 FILE *file;
1093 int err = 0; 1093 int err = 0;
1094 u64 len; 1094 u64 len;
1095 char symfs_filename[PATH_MAX];
1096
1097 if (filename) {
1098 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1099 symbol_conf.symfs, filename);
1100 }
1095 1101
1096 if (filename == NULL) { 1102 if (filename == NULL) {
1097 if (dso->has_build_id) { 1103 if (dso->has_build_id) {
@@ -1100,9 +1106,9 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1100 return -ENOMEM; 1106 return -ENOMEM;
1101 } 1107 }
1102 goto fallback; 1108 goto fallback;
1103 } else if (readlink(filename, command, sizeof(command)) < 0 || 1109 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1104 strstr(command, "[kernel.kallsyms]") || 1110 strstr(command, "[kernel.kallsyms]") ||
1105 access(filename, R_OK)) { 1111 access(symfs_filename, R_OK)) {
1106 free(filename); 1112 free(filename);
1107fallback: 1113fallback:
1108 /* 1114 /*
@@ -1111,6 +1117,8 @@ fallback:
1111 * DSO is the same as when 'perf record' ran. 1117 * DSO is the same as when 'perf record' ran.
1112 */ 1118 */
1113 filename = dso->long_name; 1119 filename = dso->long_name;
1120 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1121 symbol_conf.symfs, filename);
1114 free_filename = false; 1122 free_filename = false;
1115 } 1123 }
1116 1124
@@ -1137,7 +1145,7 @@ fallback:
1137 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", 1145 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand",
1138 map__rip_2objdump(map, sym->start), 1146 map__rip_2objdump(map, sym->start),
1139 map__rip_2objdump(map, sym->end), 1147 map__rip_2objdump(map, sym->end),
1140 filename, filename); 1148 symfs_filename, filename);
1141 1149
1142 pr_debug("Executing: %s\n", command); 1150 pr_debug("Executing: %s\n", command);
1143 1151
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3b6a5297bf16..099336ed34b4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@ static int init_vmlinux(void)
95 goto out; 95 goto out;
96 96
97 if (machine__create_kernel_maps(&machine) < 0) { 97 if (machine__create_kernel_maps(&machine) < 0) {
98 pr_debug("machine__create_kernel_maps "); 98 pr_debug("machine__create_kernel_maps() failed.\n");
99 goto out; 99 goto out;
100 } 100 }
101out: 101out:
@@ -140,7 +140,8 @@ static int open_vmlinux(const char *module)
140{ 140{
141 const char *path = kernel_get_module_path(module); 141 const char *path = kernel_get_module_path(module);
142 if (!path) { 142 if (!path) {
143 pr_err("Failed to find path of %s module", module ?: "kernel"); 143 pr_err("Failed to find path of %s module.\n",
144 module ?: "kernel");
144 return -ENOENT; 145 return -ENOENT;
145 } 146 }
146 pr_debug("Try to open %s\n", path); 147 pr_debug("Try to open %s\n", path);
@@ -217,7 +218,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
217 pr_warning("Warning: No dwarf info found in the vmlinux - " 218 pr_warning("Warning: No dwarf info found in the vmlinux - "
218 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 219 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
219 if (!need_dwarf) { 220 if (!need_dwarf) {
220 pr_debug("Trying to use symbols.\nn"); 221 pr_debug("Trying to use symbols.\n");
221 return 0; 222 return 0;
222 } 223 }
223 } 224 }
@@ -286,42 +287,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
286#define LINEBUF_SIZE 256 287#define LINEBUF_SIZE 256
287#define NR_ADDITIONAL_LINES 2 288#define NR_ADDITIONAL_LINES 2
288 289
289static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 290static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
290{ 291{
291 char buf[LINEBUF_SIZE]; 292 char buf[LINEBUF_SIZE];
292 const char *color = PERF_COLOR_BLUE; 293 const char *color = show_num ? "" : PERF_COLOR_BLUE;
294 const char *prefix = NULL;
293 295
294 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 296 do {
295 goto error;
296 if (!skip) {
297 if (show_num)
298 fprintf(stdout, "%7d %s", l, buf);
299 else
300 color_fprintf(stdout, color, " %s", buf);
301 }
302
303 while (strlen(buf) == LINEBUF_SIZE - 1 &&
304 buf[LINEBUF_SIZE - 2] != '\n') {
305 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 297 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
306 goto error; 298 goto error;
307 if (!skip) { 299 if (skip)
308 if (show_num) 300 continue;
309 fprintf(stdout, "%s", buf); 301 if (!prefix) {
310 else 302 prefix = show_num ? "%7d " : " ";
311 color_fprintf(stdout, color, "%s", buf); 303 color_fprintf(stdout, color, prefix, l);
312 } 304 }
313 } 305 color_fprintf(stdout, color, "%s", buf);
314 306
315 return 0; 307 } while (strchr(buf, '\n') == NULL);
308
309 return 1;
316error: 310error:
317 if (feof(fp)) 311 if (ferror(fp)) {
318 pr_warning("Source file is shorter than expected.\n"); 312 pr_warning("Source file is shorter than expected.\n");
319 else 313 return -1;
320 pr_warning("File read error: %s\n", strerror(errno)); 314 }
315 return 0;
316}
321 317
322 return -1; 318static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
319{
320 int rv = __show_one_line(fp, l, skip, show_num);
321 if (rv == 0) {
322 pr_warning("Source file is shorter than expected.\n");
323 rv = -1;
324 }
325 return rv;
323} 326}
324 327
328#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
329#define show_one_line(f,l) _show_one_line(f,l,false,false)
330#define skip_one_line(f,l) _show_one_line(f,l,true,false)
331#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
332
325/* 333/*
326 * Show line-range always requires debuginfo to find source file and 334 * Show line-range always requires debuginfo to find source file and
327 * line number. 335 * line number.
@@ -370,7 +378,7 @@ int show_line_range(struct line_range *lr, const char *module)
370 fprintf(stdout, "<%s:%d>\n", lr->function, 378 fprintf(stdout, "<%s:%d>\n", lr->function,
371 lr->start - lr->offset); 379 lr->start - lr->offset);
372 else 380 else
373 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 381 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
374 382
375 fp = fopen(lr->path, "r"); 383 fp = fopen(lr->path, "r");
376 if (fp == NULL) { 384 if (fp == NULL) {
@@ -379,26 +387,30 @@ int show_line_range(struct line_range *lr, const char *module)
379 return -errno; 387 return -errno;
380 } 388 }
381 /* Skip to starting line number */ 389 /* Skip to starting line number */
382 while (l < lr->start && ret >= 0) 390 while (l < lr->start) {
383 ret = show_one_line(fp, l++, true, false); 391 ret = skip_one_line(fp, l++);
384 if (ret < 0) 392 if (ret < 0)
385 goto end; 393 goto end;
394 }
386 395
387 list_for_each_entry(ln, &lr->line_list, list) { 396 list_for_each_entry(ln, &lr->line_list, list) {
388 while (ln->line > l && ret >= 0) 397 for (; ln->line > l; l++) {
389 ret = show_one_line(fp, (l++) - lr->offset, 398 ret = show_one_line(fp, l - lr->offset);
390 false, false); 399 if (ret < 0)
391 if (ret >= 0) 400 goto end;
392 ret = show_one_line(fp, (l++) - lr->offset, 401 }
393 false, true); 402 ret = show_one_line_with_num(fp, l++ - lr->offset);
394 if (ret < 0) 403 if (ret < 0)
395 goto end; 404 goto end;
396 } 405 }
397 406
398 if (lr->end == INT_MAX) 407 if (lr->end == INT_MAX)
399 lr->end = l + NR_ADDITIONAL_LINES; 408 lr->end = l + NR_ADDITIONAL_LINES;
400 while (l <= lr->end && !feof(fp) && ret >= 0) 409 while (l <= lr->end) {
401 ret = show_one_line(fp, (l++) - lr->offset, false, false); 410 ret = show_one_line_or_eof(fp, l++ - lr->offset);
411 if (ret <= 0)
412 break;
413 }
402end: 414end:
403 fclose(fp); 415 fclose(fp);
404 return ret; 416 return ret;
@@ -457,7 +469,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
457 469
458 fd = open_vmlinux(module); 470 fd = open_vmlinux(module);
459 if (fd < 0) { 471 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n"); 472 pr_warning("Failed to open debug information file.\n");
461 return fd; 473 return fd;
462 } 474 }
463 475
@@ -517,56 +529,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
517} 529}
518#endif 530#endif
519 531
532static int parse_line_num(char **ptr, int *val, const char *what)
533{
534 const char *start = *ptr;
535
536 errno = 0;
537 *val = strtol(*ptr, ptr, 0);
538 if (errno || *ptr == start) {
539 semantic_error("'%s' is not a valid number.\n", what);
540 return -EINVAL;
541 }
542 return 0;
543}
544
545/*
546 * Stuff 'lr' according to the line range described by 'arg'.
547 * The line range syntax is described by:
548 *
549 * SRC[:SLN[+NUM|-ELN]]
550 * FNC[:SLN[+NUM|-ELN]]
551 */
520int parse_line_range_desc(const char *arg, struct line_range *lr) 552int parse_line_range_desc(const char *arg, struct line_range *lr)
521{ 553{
522 const char *ptr; 554 char *range, *name = strdup(arg);
523 char *tmp; 555 int err;
524 /* 556
525 * <Syntax> 557 if (!name)
526 * SRC:SLN[+NUM|-ELN] 558 return -ENOMEM;
527 * FUNC[:SLN[+NUM|-ELN]] 559
528 */ 560 lr->start = 0;
529 ptr = strchr(arg, ':'); 561 lr->end = INT_MAX;
530 if (ptr) { 562
531 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 563 range = strchr(name, ':');
532 if (*tmp == '+') { 564 if (range) {
533 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 565 *range++ = '\0';
534 lr->end--; /* 566
535 * Adjust the number of lines here. 567 err = parse_line_num(&range, &lr->start, "start line");
536 * If the number of lines == 1, the 568 if (err)
537 * the end of line should be equal to 569 goto err;
538 * the start of line. 570
539 */ 571 if (*range == '+' || *range == '-') {
540 } else if (*tmp == '-') 572 const char c = *range++;
541 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 573
542 else 574 err = parse_line_num(&range, &lr->end, "end line");
543 lr->end = INT_MAX; 575 if (err)
576 goto err;
577
578 if (c == '+') {
579 lr->end += lr->start;
580 /*
581 * Adjust the number of lines here.
582 * If the number of lines == 1, the
583 * the end of line should be equal to
584 * the start of line.
585 */
586 lr->end--;
587 }
588 }
589
544 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 590 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
591
592 err = -EINVAL;
545 if (lr->start > lr->end) { 593 if (lr->start > lr->end) {
546 semantic_error("Start line must be smaller" 594 semantic_error("Start line must be smaller"
547 " than end line.\n"); 595 " than end line.\n");
548 return -EINVAL; 596 goto err;
549 } 597 }
550 if (*tmp != '\0') { 598 if (*range != '\0') {
551 semantic_error("Tailing with invalid character '%d'.\n", 599 semantic_error("Tailing with invalid str '%s'.\n", range);
552 *tmp); 600 goto err;
553 return -EINVAL;
554 } 601 }
555 tmp = strndup(arg, (ptr - arg));
556 } else {
557 tmp = strdup(arg);
558 lr->end = INT_MAX;
559 } 602 }
560 603
561 if (tmp == NULL) 604 if (strchr(name, '.'))
562 return -ENOMEM; 605 lr->file = name;
563
564 if (strchr(tmp, '.'))
565 lr->file = tmp;
566 else 606 else
567 lr->function = tmp; 607 lr->function = name;
568 608
569 return 0; 609 return 0;
610err:
611 free(name);
612 return err;
570} 613}
571 614
572/* Check the name is good for event/group */ 615/* Check the name is good for event/group */
@@ -690,39 +733,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
690 733
691 /* Exclusion check */ 734 /* Exclusion check */
692 if (pp->lazy_line && pp->line) { 735 if (pp->lazy_line && pp->line) {
693 semantic_error("Lazy pattern can't be used with line number."); 736 semantic_error("Lazy pattern can't be used with"
737 " line number.\n");
694 return -EINVAL; 738 return -EINVAL;
695 } 739 }
696 740
697 if (pp->lazy_line && pp->offset) { 741 if (pp->lazy_line && pp->offset) {
698 semantic_error("Lazy pattern can't be used with offset."); 742 semantic_error("Lazy pattern can't be used with offset.\n");
699 return -EINVAL; 743 return -EINVAL;
700 } 744 }
701 745
702 if (pp->line && pp->offset) { 746 if (pp->line && pp->offset) {
703 semantic_error("Offset can't be used with line number."); 747 semantic_error("Offset can't be used with line number.\n");
704 return -EINVAL; 748 return -EINVAL;
705 } 749 }
706 750
707 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 751 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
708 semantic_error("File always requires line number or " 752 semantic_error("File always requires line number or "
709 "lazy pattern."); 753 "lazy pattern.\n");
710 return -EINVAL; 754 return -EINVAL;
711 } 755 }
712 756
713 if (pp->offset && !pp->function) { 757 if (pp->offset && !pp->function) {
714 semantic_error("Offset requires an entry function."); 758 semantic_error("Offset requires an entry function.\n");
715 return -EINVAL; 759 return -EINVAL;
716 } 760 }
717 761
718 if (pp->retprobe && !pp->function) { 762 if (pp->retprobe && !pp->function) {
719 semantic_error("Return probe requires an entry function."); 763 semantic_error("Return probe requires an entry function.\n");
720 return -EINVAL; 764 return -EINVAL;
721 } 765 }
722 766
723 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 767 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
724 semantic_error("Offset/Line/Lazy pattern can't be used with " 768 semantic_error("Offset/Line/Lazy pattern can't be used with "
725 "return probe."); 769 "return probe.\n");
726 return -EINVAL; 770 return -EINVAL;
727 } 771 }
728 772
@@ -996,7 +1040,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
996 1040
997 return tmp - buf; 1041 return tmp - buf;
998error: 1042error:
999 pr_debug("Failed to synthesize perf probe argument: %s", 1043 pr_debug("Failed to synthesize perf probe argument: %s\n",
1000 strerror(-ret)); 1044 strerror(-ret));
1001 return ret; 1045 return ret;
1002} 1046}
@@ -1046,7 +1090,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1046 1090
1047 return buf; 1091 return buf;
1048error: 1092error:
1049 pr_debug("Failed to synthesize perf probe point: %s", 1093 pr_debug("Failed to synthesize perf probe point: %s\n",
1050 strerror(-ret)); 1094 strerror(-ret));
1051 if (buf) 1095 if (buf)
1052 free(buf); 1096 free(buf);
@@ -1787,7 +1831,7 @@ static int del_trace_probe_event(int fd, const char *group,
1787 1831
1788 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1832 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1789 if (ret < 0) { 1833 if (ret < 0) {
1790 pr_err("Failed to copy event."); 1834 pr_err("Failed to copy event.\n");
1791 return ret; 1835 return ret;
1792 } 1836 }
1793 1837
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3991d73d1cff..90b629226bd7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -627,8 +627,8 @@ static_var:
627 regs = get_arch_regstr(regn); 627 regs = get_arch_regstr(regn);
628 if (!regs) { 628 if (!regs) {
629 /* This should be a bug in DWARF or this tool */ 629 /* This should be a bug in DWARF or this tool */
630 pr_warning("Mapping for DWARF register number %u " 630 pr_warning("Mapping for the register number %u "
631 "missing on this architecture.", regn); 631 "missing on this architecture.\n", regn);
632 return -ERANGE; 632 return -ERANGE;
633 } 633 }
634 634
@@ -674,13 +674,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
674 if (ret != DW_TAG_pointer_type && 674 if (ret != DW_TAG_pointer_type &&
675 ret != DW_TAG_array_type) { 675 ret != DW_TAG_array_type) {
676 pr_warning("Failed to cast into string: " 676 pr_warning("Failed to cast into string: "
677 "%s(%s) is not a pointer nor array.", 677 "%s(%s) is not a pointer nor array.\n",
678 dwarf_diename(vr_die), dwarf_diename(&type)); 678 dwarf_diename(vr_die), dwarf_diename(&type));
679 return -EINVAL; 679 return -EINVAL;
680 } 680 }
681 if (ret == DW_TAG_pointer_type) { 681 if (ret == DW_TAG_pointer_type) {
682 if (die_get_real_type(&type, &type) == NULL) { 682 if (die_get_real_type(&type, &type) == NULL) {
683 pr_warning("Failed to get a type information."); 683 pr_warning("Failed to get a type"
684 " information.\n");
684 return -ENOENT; 685 return -ENOENT;
685 } 686 }
686 while (*ref_ptr) 687 while (*ref_ptr)
@@ -695,7 +696,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
695 if (!die_compare_name(&type, "char") && 696 if (!die_compare_name(&type, "char") &&
696 !die_compare_name(&type, "unsigned char")) { 697 !die_compare_name(&type, "unsigned char")) {
697 pr_warning("Failed to cast into string: " 698 pr_warning("Failed to cast into string: "
698 "%s is not (unsigned) char *.", 699 "%s is not (unsigned) char *.\n",
699 dwarf_diename(vr_die)); 700 dwarf_diename(vr_die));
700 return -EINVAL; 701 return -EINVAL;
701 } 702 }
@@ -805,8 +806,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
805 return -EINVAL; 806 return -EINVAL;
806 } 807 }
807 if (field->name[0] == '[') { 808 if (field->name[0] == '[') {
808 pr_err("Semantic error: %s is not a pointor nor array.", 809 pr_err("Semantic error: %s is not a pointor"
809 varname); 810 " nor array.\n", varname);
810 return -EINVAL; 811 return -EINVAL;
811 } 812 }
812 if (field->ref) { 813 if (field->ref) {
@@ -953,7 +954,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
953 name = dwarf_diename(sp_die); 954 name = dwarf_diename(sp_die);
954 if (name) { 955 if (name) {
955 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 956 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
956 pr_warning("Failed to get entry pc of %s\n", 957 pr_warning("Failed to get entry address of %s\n",
957 dwarf_diename(sp_die)); 958 dwarf_diename(sp_die));
958 return -ENOENT; 959 return -ENOENT;
959 } 960 }
@@ -969,7 +970,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
969 if (retprobe) { 970 if (retprobe) {
970 if (eaddr != paddr) { 971 if (eaddr != paddr) {
971 pr_warning("Return probe must be on the head of" 972 pr_warning("Return probe must be on the head of"
972 " a real function\n"); 973 " a real function.\n");
973 return -EINVAL; 974 return -EINVAL;
974 } 975 }
975 tp->retprobe = true; 976 tp->retprobe = true;
@@ -1008,7 +1009,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1008 Dwarf_Frame *frame; 1009 Dwarf_Frame *frame;
1009 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 1010 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
1010 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 1011 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
1011 pr_warning("Failed to get CFA on 0x%jx\n", 1012 pr_warning("Failed to get call frame on 0x%jx\n",
1012 (uintmax_t)pf->addr); 1013 (uintmax_t)pf->addr);
1013 return -ENOENT; 1014 return -ENOENT;
1014 } 1015 }
@@ -1035,7 +1036,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
1035 int ret = 0; 1036 int ret = 0;
1036 1037
1037 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1038 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1038 pr_warning("No source lines found in this CU.\n"); 1039 pr_warning("No source lines found.\n");
1039 return -ENOENT; 1040 return -ENOENT;
1040 } 1041 }
1041 1042
@@ -1137,7 +1138,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1137 } 1138 }
1138 1139
1139 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1140 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1140 pr_warning("No source lines found in this CU.\n"); 1141 pr_warning("No source lines found.\n");
1141 return -ENOENT; 1142 return -ENOENT;
1142 } 1143 }
1143 1144
@@ -1195,7 +1196,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1195 else { 1196 else {
1196 /* Get probe address */ 1197 /* Get probe address */
1197 if (dwarf_entrypc(in_die, &addr) != 0) { 1198 if (dwarf_entrypc(in_die, &addr) != 0) {
1198 pr_warning("Failed to get entry pc of %s.\n", 1199 pr_warning("Failed to get entry address of %s.\n",
1199 dwarf_diename(in_die)); 1200 dwarf_diename(in_die));
1200 param->retval = -ENOENT; 1201 param->retval = -ENOENT;
1201 return DWARF_CB_ABORT; 1202 return DWARF_CB_ABORT;
@@ -1236,8 +1237,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1236 param->retval = find_probe_point_lazy(sp_die, pf); 1237 param->retval = find_probe_point_lazy(sp_die, pf);
1237 else { 1238 else {
1238 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1239 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1239 pr_warning("Failed to get entry pc of %s.\n", 1240 pr_warning("Failed to get entry address of "
1240 dwarf_diename(sp_die)); 1241 "%s.\n", dwarf_diename(sp_die));
1241 param->retval = -ENOENT; 1242 param->retval = -ENOENT;
1242 return DWARF_CB_ABORT; 1243 return DWARF_CB_ABORT;
1243 } 1244 }
@@ -1279,7 +1280,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1279 1280
1280 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1281 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1281 if (!dbg) { 1282 if (!dbg) {
1282 pr_warning("No dwarf info found in the vmlinux - " 1283 pr_warning("No debug information found in the vmlinux - "
1283 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1284 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1284 return -EBADF; 1285 return -EBADF;
1285 } 1286 }
@@ -1524,7 +1525,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1524 /* Open the live linux kernel */ 1525 /* Open the live linux kernel */
1525 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1526 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1526 if (!dbg) { 1527 if (!dbg) {
1527 pr_warning("No dwarf info found in the vmlinux - " 1528 pr_warning("No debug information found in the vmlinux - "
1528 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1529 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1529 ret = -EINVAL; 1530 ret = -EINVAL;
1530 goto end; 1531 goto end;
@@ -1534,7 +1535,8 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1534 addr += bias; 1535 addr += bias;
1535 /* Find cu die */ 1536 /* Find cu die */
1536 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1537 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1537 pr_warning("No CU DIE is found at %lx\n", addr); 1538 pr_warning("Failed to find debug information for address %lx\n",
1539 addr);
1538 ret = -EINVAL; 1540 ret = -EINVAL;
1539 goto end; 1541 goto end;
1540 } 1542 }
@@ -1659,7 +1661,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1659 1661
1660 line_list__init(&lf->lr->line_list); 1662 line_list__init(&lf->lr->line_list);
1661 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1663 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1662 pr_warning("No source lines found in this CU.\n"); 1664 pr_warning("No source lines found.\n");
1663 return -ENOENT; 1665 return -ENOENT;
1664 } 1666 }
1665 1667
@@ -1784,7 +1786,7 @@ int find_line_range(int fd, struct line_range *lr)
1784 1786
1785 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1787 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1786 if (!dbg) { 1788 if (!dbg) {
1787 pr_warning("No dwarf info found in the vmlinux - " 1789 pr_warning("No debug information found in the vmlinux - "
1788 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1790 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1789 return -EBADF; 1791 return -EBADF;
1790 } 1792 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b59abf5aba36..0f7e544544f5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -125,7 +125,9 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
125 machines__destroy_guest_kernel_maps(&self->machines); 125 machines__destroy_guest_kernel_maps(&self->machines);
126} 126}
127 127
128struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 128struct perf_session *perf_session__new(const char *filename, int mode,
129 bool force, bool repipe,
130 struct perf_event_ops *ops)
129{ 131{
130 size_t len = filename ? strlen(filename) + 1 : 0; 132 size_t len = filename ? strlen(filename) + 1 : 0;
131 struct perf_session *self = zalloc(sizeof(*self) + len); 133 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -170,6 +172,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
170 } 172 }
171 173
172 perf_session__update_sample_type(self); 174 perf_session__update_sample_type(self);
175
176 if (ops && ops->ordering_requires_timestamps &&
177 ops->ordered_samples && !self->sample_id_all) {
178 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
179 ops->ordered_samples = false;
180 }
181
173out: 182out:
174 return self; 183 return self;
175out_free: 184out_free:
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index ac36f99f14af..ffe4b98db8f0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -78,9 +78,12 @@ struct perf_event_ops {
78 build_id; 78 build_id;
79 event_op2 finished_round; 79 event_op2 finished_round;
80 bool ordered_samples; 80 bool ordered_samples;
81 bool ordering_requires_timestamps;
81}; 82};
82 83
83struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); 84struct perf_session *perf_session__new(const char *filename, int mode,
85 bool force, bool repipe,
86 struct perf_event_ops *ops);
84void perf_session__delete(struct perf_session *self); 87void perf_session__delete(struct perf_session *self);
85 88
86void perf_event_header__bswap(struct perf_event_header *self); 89void perf_event_header__bswap(struct perf_event_header *self);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index ceefa6568def..561db6361f57 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -41,6 +41,7 @@ struct symbol_conf symbol_conf = {
41 .exclude_other = true, 41 .exclude_other = true,
42 .use_modules = true, 42 .use_modules = true,
43 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
44 .symfs = "",
44}; 45};
45 46
46int dso__name_len(const struct dso *self) 47int dso__name_len(const struct dso *self)
@@ -839,8 +840,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
839 char sympltname[1024]; 840 char sympltname[1024];
840 Elf *elf; 841 Elf *elf;
841 int nr = 0, symidx, fd, err = 0; 842 int nr = 0, symidx, fd, err = 0;
843 char name[PATH_MAX];
842 844
843 fd = open(self->long_name, O_RDONLY); 845 snprintf(name, sizeof(name), "%s%s",
846 symbol_conf.symfs, self->long_name);
847 fd = open(name, O_RDONLY);
844 if (fd < 0) 848 if (fd < 0)
845 goto out; 849 goto out;
846 850
@@ -1452,16 +1456,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1452 self->origin++) { 1456 self->origin++) {
1453 switch (self->origin) { 1457 switch (self->origin) {
1454 case DSO__ORIG_BUILD_ID_CACHE: 1458 case DSO__ORIG_BUILD_ID_CACHE:
1455 if (dso__build_id_filename(self, name, size) == NULL) 1459 /* skip the locally configured cache if a symfs is given */
1460 if (symbol_conf.symfs[0] ||
1461 (dso__build_id_filename(self, name, size) == NULL)) {
1456 continue; 1462 continue;
1463 }
1457 break; 1464 break;
1458 case DSO__ORIG_FEDORA: 1465 case DSO__ORIG_FEDORA:
1459 snprintf(name, size, "/usr/lib/debug%s.debug", 1466 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1460 self->long_name); 1467 symbol_conf.symfs, self->long_name);
1461 break; 1468 break;
1462 case DSO__ORIG_UBUNTU: 1469 case DSO__ORIG_UBUNTU:
1463 snprintf(name, size, "/usr/lib/debug%s", 1470 snprintf(name, size, "%s/usr/lib/debug%s",
1464 self->long_name); 1471 symbol_conf.symfs, self->long_name);
1465 break; 1472 break;
1466 case DSO__ORIG_BUILDID: { 1473 case DSO__ORIG_BUILDID: {
1467 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1474 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1473,19 +1480,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1473 sizeof(self->build_id), 1480 sizeof(self->build_id),
1474 build_id_hex); 1481 build_id_hex);
1475 snprintf(name, size, 1482 snprintf(name, size,
1476 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1483 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1477 build_id_hex, build_id_hex + 2); 1484 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1478 } 1485 }
1479 break; 1486 break;
1480 case DSO__ORIG_DSO: 1487 case DSO__ORIG_DSO:
1481 snprintf(name, size, "%s", self->long_name); 1488 snprintf(name, size, "%s%s",
1489 symbol_conf.symfs, self->long_name);
1482 break; 1490 break;
1483 case DSO__ORIG_GUEST_KMODULE: 1491 case DSO__ORIG_GUEST_KMODULE:
1484 if (map->groups && map->groups->machine) 1492 if (map->groups && map->groups->machine)
1485 root_dir = map->groups->machine->root_dir; 1493 root_dir = map->groups->machine->root_dir;
1486 else 1494 else
1487 root_dir = ""; 1495 root_dir = "";
1488 snprintf(name, size, "%s%s", root_dir, self->long_name); 1496 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1497 root_dir, self->long_name);
1498 break;
1499
1500 case DSO__ORIG_KMODULE:
1501 snprintf(name, size, "%s%s", symbol_conf.symfs,
1502 self->long_name);
1489 break; 1503 break;
1490 1504
1491 default: 1505 default:
@@ -1784,17 +1798,20 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1784 const char *vmlinux, symbol_filter_t filter) 1798 const char *vmlinux, symbol_filter_t filter)
1785{ 1799{
1786 int err = -1, fd; 1800 int err = -1, fd;
1801 char symfs_vmlinux[PATH_MAX];
1787 1802
1788 fd = open(vmlinux, O_RDONLY); 1803 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
1804 symbol_conf.symfs, vmlinux);
1805 fd = open(symfs_vmlinux, O_RDONLY);
1789 if (fd < 0) 1806 if (fd < 0)
1790 return -1; 1807 return -1;
1791 1808
1792 dso__set_loaded(self, map->type); 1809 dso__set_loaded(self, map->type);
1793 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); 1810 err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
1794 close(fd); 1811 close(fd);
1795 1812
1796 if (err > 0) 1813 if (err > 0)
1797 pr_debug("Using %s for symbols\n", vmlinux); 1814 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1798 1815
1799 return err; 1816 return err;
1800} 1817}
@@ -1872,6 +1889,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1872 goto out_fixup; 1889 goto out_fixup;
1873 } 1890 }
1874 1891
1892 /* do not try local files if a symfs was given */
1893 if (symbol_conf.symfs[0] != 0)
1894 return -1;
1895
1875 /* 1896 /*
1876 * Say the kernel DSO was created when processing the build-id header table, 1897 * Say the kernel DSO was created when processing the build-id header table,
1877 * we have a build-id, so check if it is the same as the running kernel, 1898 * we have a build-id, so check if it is the same as the running kernel,
@@ -2262,9 +2283,6 @@ static int vmlinux_path__init(void)
2262 struct utsname uts; 2283 struct utsname uts;
2263 char bf[PATH_MAX]; 2284 char bf[PATH_MAX];
2264 2285
2265 if (uname(&uts) < 0)
2266 return -1;
2267
2268 vmlinux_path = malloc(sizeof(char *) * 5); 2286 vmlinux_path = malloc(sizeof(char *) * 5);
2269 if (vmlinux_path == NULL) 2287 if (vmlinux_path == NULL)
2270 return -1; 2288 return -1;
@@ -2277,6 +2295,14 @@ static int vmlinux_path__init(void)
2277 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2295 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2278 goto out_fail; 2296 goto out_fail;
2279 ++vmlinux_path__nr_entries; 2297 ++vmlinux_path__nr_entries;
2298
2299 /* only try running kernel version if no symfs was given */
2300 if (symbol_conf.symfs[0] != 0)
2301 return 0;
2302
2303 if (uname(&uts) < 0)
2304 return -1;
2305
2280 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2306 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2281 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2307 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2282 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2308 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2336,6 +2362,8 @@ static int setup_list(struct strlist **list, const char *list_str,
2336 2362
2337int symbol__init(void) 2363int symbol__init(void)
2338{ 2364{
2365 const char *symfs;
2366
2339 if (symbol_conf.initialized) 2367 if (symbol_conf.initialized)
2340 return 0; 2368 return 0;
2341 2369
@@ -2364,6 +2392,18 @@ int symbol__init(void)
2364 symbol_conf.sym_list_str, "symbol") < 0) 2392 symbol_conf.sym_list_str, "symbol") < 0)
2365 goto out_free_comm_list; 2393 goto out_free_comm_list;
2366 2394
2395 /*
2396 * A path to symbols of "/" is identical to ""
2397 * reset here for simplicity.
2398 */
2399 symfs = realpath(symbol_conf.symfs, NULL);
2400 if (symfs == NULL)
2401 symfs = symbol_conf.symfs;
2402 if (strcmp(symfs, "/") == 0)
2403 symbol_conf.symfs = "";
2404 if (symfs != symbol_conf.symfs)
2405 free((void *)symfs);
2406
2367 symbol_conf.initialized = true; 2407 symbol_conf.initialized = true;
2368 return 0; 2408 return 0;
2369 2409
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 12defbe18c13..bcd2f986927e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -86,6 +86,7 @@ struct symbol_conf {
86 struct strlist *dso_list, 86 struct strlist *dso_list,
87 *comm_list, 87 *comm_list,
88 *sym_list; 88 *sym_list;
89 const char *symfs;
89}; 90};
90 91
91extern struct symbol_conf symbol_conf; 92extern struct symbol_conf symbol_conf;