diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/builtin-record.c | 19 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 44 | ||||
| -rw-r--r-- | tools/perf/util/debug.c | 10 | ||||
| -rw-r--r-- | tools/perf/util/debug.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.c | 72 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 3 |
8 files changed, 132 insertions, 21 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6febcc168a8..db6adecf46f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -275,11 +275,10 @@ try_again: | |||
| 275 | !no_inherit) < 0) { | 275 | !no_inherit) < 0) { |
| 276 | int err = errno; | 276 | int err = errno; |
| 277 | 277 | ||
| 278 | if (err == EPERM || err == EACCES) | 278 | if (err == EPERM || err == EACCES) { |
| 279 | die("Permission error - are you root?\n" | 279 | ui__warning_paranoid(); |
| 280 | "\t Consider tweaking" | 280 | exit(EXIT_FAILURE); |
| 281 | " /proc/sys/kernel/perf_event_paranoid.\n"); | 281 | } else if (err == ENODEV && cpu_list) { |
| 282 | else if (err == ENODEV && cpu_list) { | ||
| 283 | die("No such device - did you specify" | 282 | die("No such device - did you specify" |
| 284 | " an out-of-range profile CPU?\n"); | 283 | " an out-of-range profile CPU?\n"); |
| 285 | } else if (err == EINVAL && sample_id_all_avail) { | 284 | } else if (err == EINVAL && sample_id_all_avail) { |
| @@ -302,11 +301,19 @@ try_again: | |||
| 302 | && attr->config == PERF_COUNT_HW_CPU_CYCLES) { | 301 | && attr->config == PERF_COUNT_HW_CPU_CYCLES) { |
| 303 | 302 | ||
| 304 | if (verbose) | 303 | if (verbose) |
| 305 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | 304 | ui__warning("The cycles event is not supported, " |
| 305 | "trying to fall back to cpu-clock-ticks\n"); | ||
| 306 | attr->type = PERF_TYPE_SOFTWARE; | 306 | attr->type = PERF_TYPE_SOFTWARE; |
| 307 | attr->config = PERF_COUNT_SW_CPU_CLOCK; | 307 | attr->config = PERF_COUNT_SW_CPU_CLOCK; |
| 308 | goto try_again; | 308 | goto try_again; |
| 309 | } | 309 | } |
| 310 | |||
| 311 | if (err == ENOENT) { | ||
| 312 | ui__warning("The %s event is not supported.\n", | ||
| 313 | event_name(pos)); | ||
| 314 | exit(EXIT_FAILURE); | ||
| 315 | } | ||
| 316 | |||
| 310 | printf("\n"); | 317 | printf("\n"); |
| 311 | error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", | 318 | error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", |
| 312 | err, strerror(err)); | 319 | err, strerror(err)); |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 676b4fb0070..fc1273e976c 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -850,10 +850,10 @@ try_again: | |||
| 850 | top.evlist->threads, group, inherit) < 0) { | 850 | top.evlist->threads, group, inherit) < 0) { |
| 851 | int err = errno; | 851 | int err = errno; |
| 852 | 852 | ||
| 853 | if (err == EPERM || err == EACCES) | 853 | if (err == EPERM || err == EACCES) { |
| 854 | die("Permission error - are you root?\n" | 854 | ui__warning_paranoid(); |
| 855 | "\t Consider tweaking" | 855 | goto out_err; |
| 856 | " /proc/sys/kernel/perf_event_paranoid.\n"); | 856 | } |
| 857 | /* | 857 | /* |
| 858 | * If it's cycles then fall back to hrtimer | 858 | * If it's cycles then fall back to hrtimer |
| 859 | * based cpu-clock-tick sw counter, which | 859 | * based cpu-clock-tick sw counter, which |
| @@ -861,25 +861,41 @@ try_again: | |||
| 861 | */ | 861 | */ |
| 862 | if (attr->type == PERF_TYPE_HARDWARE && | 862 | if (attr->type == PERF_TYPE_HARDWARE && |
| 863 | attr->config == PERF_COUNT_HW_CPU_CYCLES) { | 863 | attr->config == PERF_COUNT_HW_CPU_CYCLES) { |
| 864 | |||
| 865 | if (verbose) | 864 | if (verbose) |
| 866 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | 865 | ui__warning("Cycles event not supported,\n" |
| 866 | "trying to fall back to cpu-clock-ticks\n"); | ||
| 867 | 867 | ||
| 868 | attr->type = PERF_TYPE_SOFTWARE; | 868 | attr->type = PERF_TYPE_SOFTWARE; |
| 869 | attr->config = PERF_COUNT_SW_CPU_CLOCK; | 869 | attr->config = PERF_COUNT_SW_CPU_CLOCK; |
| 870 | goto try_again; | 870 | goto try_again; |
| 871 | } | 871 | } |
| 872 | printf("\n"); | 872 | |
| 873 | error("sys_perf_event_open() syscall returned with %d " | 873 | if (err == ENOENT) { |
| 874 | "(%s). /bin/dmesg may provide additional information.\n", | 874 | ui__warning("The %s event is not supported.\n", |
| 875 | err, strerror(err)); | 875 | event_name(counter)); |
| 876 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 876 | goto out_err; |
| 877 | exit(-1); | 877 | } |
| 878 | |||
| 879 | ui__warning("The sys_perf_event_open() syscall " | ||
| 880 | "returned with %d (%s). /bin/dmesg " | ||
| 881 | "may provide additional information.\n" | ||
| 882 | "No CONFIG_PERF_EVENTS=y kernel support " | ||
| 883 | "configured?\n", err, strerror(err)); | ||
| 884 | goto out_err; | ||
| 878 | } | 885 | } |
| 879 | } | 886 | } |
| 880 | 887 | ||
| 881 | if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) | 888 | if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) { |
| 882 | die("failed to mmap with %d (%s)\n", errno, strerror(errno)); | 889 | ui__warning("Failed to mmap with %d (%s)\n", |
| 890 | errno, strerror(errno)); | ||
| 891 | goto out_err; | ||
| 892 | } | ||
| 893 | |||
| 894 | return; | ||
| 895 | |||
| 896 | out_err: | ||
| 897 | exit_browser(0); | ||
| 898 | exit(0); | ||
| 883 | } | 899 | } |
| 884 | 900 | ||
| 885 | static int __cmd_top(void) | 901 | static int __cmd_top(void) |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index d4536a9e0d8..155749d7435 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
| @@ -57,6 +57,16 @@ void ui__warning(const char *format, ...) | |||
| 57 | } | 57 | } |
| 58 | #endif | 58 | #endif |
| 59 | 59 | ||
| 60 | void ui__warning_paranoid(void) | ||
| 61 | { | ||
| 62 | ui__warning("Permission error - are you root?\n" | ||
| 63 | "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" | ||
| 64 | " -1 - Not paranoid at all\n" | ||
| 65 | " 0 - Disallow raw tracepoint access for unpriv\n" | ||
| 66 | " 1 - Disallow cpu events for unpriv\n" | ||
| 67 | " 2 - Disallow kernel profiling for unpriv\n"); | ||
| 68 | } | ||
| 69 | |||
| 60 | void trace_event(union perf_event *event) | 70 | void trace_event(union perf_event *event) |
| 61 | { | 71 | { |
| 62 | unsigned char *raw_event = (void *)event; | 72 | unsigned char *raw_event = (void *)event; |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 93516cf4682..fd53db47e3d 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
| @@ -36,5 +36,6 @@ int ui_helpline__show_help(const char *format, va_list ap); | |||
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 38 | void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
| 39 | void ui__warning_paranoid(void); | ||
| 39 | 40 | ||
| 40 | #endif /* __PERF_DEBUG_H */ | 41 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2b15c362ef5..1023f67633a 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -710,7 +710,7 @@ try_again: | |||
| 710 | * in the whole kernel symbol list. | 710 | * in the whole kernel symbol list. |
| 711 | */ | 711 | */ |
| 712 | if ((long long)al->addr < 0 && | 712 | if ((long long)al->addr < 0 && |
| 713 | cpumode == PERF_RECORD_MISC_KERNEL && | 713 | cpumode == PERF_RECORD_MISC_USER && |
| 714 | machine && mg != &machine->kmaps) { | 714 | machine && mg != &machine->kmaps) { |
| 715 | mg = &machine->kmaps; | 715 | mg = &machine->kmaps; |
| 716 | goto try_again; | 716 | goto try_again; |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 194f9e2a328..ff416b85f7e 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -1435,6 +1435,38 @@ static int find_probe_point_by_func(struct probe_finder *pf) | |||
| 1435 | return _param.retval; | 1435 | return _param.retval; |
| 1436 | } | 1436 | } |
| 1437 | 1437 | ||
| 1438 | struct pubname_callback_param { | ||
| 1439 | char *function; | ||
| 1440 | char *file; | ||
| 1441 | Dwarf_Die *cu_die; | ||
| 1442 | Dwarf_Die *sp_die; | ||
| 1443 | int found; | ||
| 1444 | }; | ||
| 1445 | |||
| 1446 | static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) | ||
| 1447 | { | ||
| 1448 | struct pubname_callback_param *param = data; | ||
| 1449 | |||
| 1450 | if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { | ||
| 1451 | if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) | ||
| 1452 | return DWARF_CB_OK; | ||
| 1453 | |||
| 1454 | if (die_compare_name(param->sp_die, param->function)) { | ||
| 1455 | if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) | ||
| 1456 | return DWARF_CB_OK; | ||
| 1457 | |||
| 1458 | if (param->file && | ||
| 1459 | strtailcmp(param->file, dwarf_decl_file(param->sp_die))) | ||
| 1460 | return DWARF_CB_OK; | ||
| 1461 | |||
| 1462 | param->found = 1; | ||
| 1463 | return DWARF_CB_ABORT; | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | return DWARF_CB_OK; | ||
| 1468 | } | ||
| 1469 | |||
| 1438 | /* Find probe points from debuginfo */ | 1470 | /* Find probe points from debuginfo */ |
| 1439 | static int find_probes(int fd, struct probe_finder *pf) | 1471 | static int find_probes(int fd, struct probe_finder *pf) |
| 1440 | { | 1472 | { |
| @@ -1461,6 +1493,27 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
| 1461 | 1493 | ||
| 1462 | off = 0; | 1494 | off = 0; |
| 1463 | line_list__init(&pf->lcache); | 1495 | line_list__init(&pf->lcache); |
| 1496 | |||
| 1497 | /* Fastpath: lookup by function name from .debug_pubnames section */ | ||
| 1498 | if (pp->function) { | ||
| 1499 | struct pubname_callback_param pubname_param = { | ||
| 1500 | .function = pp->function, | ||
| 1501 | .file = pp->file, | ||
| 1502 | .cu_die = &pf->cu_die, | ||
| 1503 | .sp_die = &pf->sp_die, | ||
| 1504 | }; | ||
| 1505 | struct dwarf_callback_param probe_param = { | ||
| 1506 | .data = pf, | ||
| 1507 | }; | ||
| 1508 | |||
| 1509 | dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | ||
| 1510 | if (pubname_param.found) { | ||
| 1511 | ret = probe_point_search_cb(&pf->sp_die, &probe_param); | ||
| 1512 | if (ret) | ||
| 1513 | goto found; | ||
| 1514 | } | ||
| 1515 | } | ||
| 1516 | |||
| 1464 | /* Loop on CUs (Compilation Unit) */ | 1517 | /* Loop on CUs (Compilation Unit) */ |
| 1465 | while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { | 1518 | while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { |
| 1466 | /* Get the DIE(Debugging Information Entry) of this CU */ | 1519 | /* Get the DIE(Debugging Information Entry) of this CU */ |
| @@ -1488,6 +1541,8 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
| 1488 | } | 1541 | } |
| 1489 | off = noff; | 1542 | off = noff; |
| 1490 | } | 1543 | } |
| 1544 | |||
| 1545 | found: | ||
| 1491 | line_list__free(&pf->lcache); | 1546 | line_list__free(&pf->lcache); |
| 1492 | if (dwfl) | 1547 | if (dwfl) |
| 1493 | dwfl_end(dwfl); | 1548 | dwfl_end(dwfl); |
| @@ -1895,6 +1950,22 @@ int find_line_range(int fd, struct line_range *lr) | |||
| 1895 | return -EBADF; | 1950 | return -EBADF; |
| 1896 | } | 1951 | } |
| 1897 | 1952 | ||
| 1953 | /* Fastpath: lookup by function name from .debug_pubnames section */ | ||
| 1954 | if (lr->function) { | ||
| 1955 | struct pubname_callback_param pubname_param = { | ||
| 1956 | .function = lr->function, .file = lr->file, | ||
| 1957 | .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; | ||
| 1958 | struct dwarf_callback_param line_range_param = { | ||
| 1959 | .data = (void *)&lf, .retval = 0}; | ||
| 1960 | |||
| 1961 | dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | ||
| 1962 | if (pubname_param.found) { | ||
| 1963 | line_range_search_cb(&lf.sp_die, &line_range_param); | ||
| 1964 | if (lf.found) | ||
| 1965 | goto found; | ||
| 1966 | } | ||
| 1967 | } | ||
| 1968 | |||
| 1898 | /* Loop on CUs (Compilation Unit) */ | 1969 | /* Loop on CUs (Compilation Unit) */ |
| 1899 | while (!lf.found && ret >= 0) { | 1970 | while (!lf.found && ret >= 0) { |
| 1900 | if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) | 1971 | if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) |
| @@ -1923,6 +1994,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
| 1923 | off = noff; | 1994 | off = noff; |
| 1924 | } | 1995 | } |
| 1925 | 1996 | ||
| 1997 | found: | ||
| 1926 | /* Store comp_dir */ | 1998 | /* Store comp_dir */ |
| 1927 | if (lf.found) { | 1999 | if (lf.found) { |
| 1928 | comp_dir = cu_get_comp_dir(&lf.cu_die); | 2000 | comp_dir = cu_get_comp_dir(&lf.cu_die); |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index beaefc3c122..605730a366d 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
| @@ -49,6 +49,7 @@ struct probe_finder { | |||
| 49 | Dwarf_Addr addr; /* Address */ | 49 | Dwarf_Addr addr; /* Address */ |
| 50 | const char *fname; /* Real file name */ | 50 | const char *fname; /* Real file name */ |
| 51 | Dwarf_Die cu_die; /* Current CU */ | 51 | Dwarf_Die cu_die; /* Current CU */ |
| 52 | Dwarf_Die sp_die; | ||
| 52 | struct list_head lcache; /* Line cache for lazy match */ | 53 | struct list_head lcache; /* Line cache for lazy match */ |
| 53 | 54 | ||
| 54 | /* For variable searching */ | 55 | /* For variable searching */ |
| @@ -83,6 +84,7 @@ struct line_finder { | |||
| 83 | int lno_s; /* Start line number */ | 84 | int lno_s; /* Start line number */ |
| 84 | int lno_e; /* End line number */ | 85 | int lno_e; /* End line number */ |
| 85 | Dwarf_Die cu_die; /* Current CU */ | 86 | Dwarf_Die cu_die; /* Current CU */ |
| 87 | Dwarf_Die sp_die; | ||
| 86 | int found; | 88 | int found; |
| 87 | }; | 89 | }; |
| 88 | 90 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 17df793c892..8f73907a959 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
| 1196 | if (curr_dso == NULL) | 1196 | if (curr_dso == NULL) |
| 1197 | goto out_elf_end; | 1197 | goto out_elf_end; |
| 1198 | curr_dso->kernel = self->kernel; | 1198 | curr_dso->kernel = self->kernel; |
| 1199 | curr_dso->long_name = self->long_name; | ||
| 1200 | curr_dso->long_name_len = self->long_name_len; | ||
| 1199 | curr_map = map__new2(start, curr_dso, | 1201 | curr_map = map__new2(start, curr_dso, |
| 1200 | map->type); | 1202 | map->type); |
| 1201 | if (curr_map == NULL) { | 1203 | if (curr_map == NULL) { |
| @@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, | |||
| 1842 | if (fd < 0) | 1844 | if (fd < 0) |
| 1843 | return -1; | 1845 | return -1; |
| 1844 | 1846 | ||
| 1847 | dso__set_long_name(self, (char *)vmlinux); | ||
| 1845 | dso__set_loaded(self, map->type); | 1848 | dso__set_loaded(self, map->type); |
| 1846 | err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); | 1849 | err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); |
| 1847 | close(fd); | 1850 | close(fd); |
