aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-diff.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt3
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-timechart.c2
-rw-r--r--tools/perf/util/hist.c14
-rw-r--r--tools/perf/util/symbol.c72
-rw-r--r--tools/perf/util/symbol.h1
9 files changed, 81 insertions, 19 deletions
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 6a9ec2b35310..74d7481ed7a6 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -66,6 +66,8 @@ OPTIONS
66--force:: 66--force::
67 Don't complain, do it. 67 Don't complain, do it.
68 68
69--symfs=<directory>::
70 Look for files with symbols relative to this directory.
69 71
70SEE ALSO 72SEE ALSO
71-------- 73--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index fefea77ec6e9..8ba03d6e5398 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -116,6 +116,9 @@ OPTIONS
116--force:: 116--force::
117 Don't complain, do it. 117 Don't complain, do it.
118 118
119--symfs=<directory>::
120 Look for files with symbols relative to this directory.
121
119SEE ALSO 122SEE ALSO
120-------- 123--------
121linkperf:perf-stat[1] 124linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 4b1788355eca..d7b79e2ba2ad 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -38,6 +38,8 @@ OPTIONS
38--process:: 38--process::
39 Select the processes to display, by name or PID 39 Select the processes to display, by name or PID
40 40
41--symfs=<directory>::
42 Look for files with symbols relative to this directory.
41 43
42SEE ALSO 44SEE ALSO
43-------- 45--------
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 97846dcafc63..3153e492dbcc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -194,6 +194,8 @@ static const struct option options[] = {
194 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 194 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
195 "separator for columns, no spaces will be added between " 195 "separator for columns, no spaces will be added between "
196 "columns '.' is reserved."), 196 "columns '.' is reserved."),
197 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
198 "Look for files with symbols relative to this directory"),
197 OPT_END() 199 OPT_END()
198}; 200};
199 201
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4af7ce6e1555..75183a4518e6 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -483,6 +483,8 @@ static const struct option options[] = {
483 "columns '.' is reserved."), 483 "columns '.' is reserved."),
484 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 484 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
485 "Only display entries resolved to a symbol"), 485 "Only display entries resolved to a symbol"),
486 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
487 "Look for files with symbols relative to this directory"),
486 OPT_END() 488 OPT_END()
487}; 489};
488 490
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 459b5e3db267..d75084bccdb7 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1022,6 +1022,8 @@ static const struct option options[] = {
1022 OPT_CALLBACK('p', "process", NULL, "process", 1022 OPT_CALLBACK('p', "process", NULL, "process",
1023 "process selector. Pass a pid or process name.", 1023 "process selector. Pass a pid or process name.",
1024 parse_process), 1024 parse_process),
1025 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1026 "Look for files with symbols relative to this directory"),
1025 OPT_END() 1027 OPT_END()
1026}; 1028};
1027 1029
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/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;