diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-11-23 13:39:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-23 13:51:48 -0500 |
commit | cc612d8199089413719397c9d92e5823da578eac (patch) | |
tree | aec84294a839bc82b738326ed5f338e6ebc47a30 | |
parent | 1b290d670ffa883b7e062177463a8efd00eaa2c1 (diff) |
perf symbols: Look for vmlinux in more places
Now that we can check the buildid to see if it really matches,
this can be done safely:
vmlinux
/boot/vmlinux
/boot/vmlinux-<uts.release>
/lib/modules/<uts.release>/build/vmlinux
/usr/lib/debug/lib/modules/%s/vmlinux
More can be added - if you know about distros that put the
vmlinux somewhere else please let us know.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259001550-8194-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | tools/perf/builtin-annotate.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 3 | ||||
-rw-r--r-- | tools/perf/util/data_map.c | 4 | ||||
-rw-r--r-- | tools/perf/util/data_map.h | 2 | ||||
-rw-r--r-- | tools/perf/util/header.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 113 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 4 |
11 files changed, 122 insertions, 23 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 203152729a68..6b13a1ecf1e7 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -37,6 +37,7 @@ static bool use_modules; | |||
37 | 37 | ||
38 | static unsigned long page_size; | 38 | static unsigned long page_size; |
39 | static unsigned long mmap_window = 32; | 39 | static unsigned long mmap_window = 32; |
40 | const char *vmlinux_name; | ||
40 | 41 | ||
41 | struct sym_hist { | 42 | struct sym_hist { |
42 | u64 sum; | 43 | u64 sum; |
@@ -637,7 +638,7 @@ static int __cmd_annotate(void) | |||
637 | exit(0); | 638 | exit(0); |
638 | } | 639 | } |
639 | 640 | ||
640 | if (kernel_maps__init(use_modules) < 0) { | 641 | if (kernel_maps__init(vmlinux_name, true, use_modules) < 0) { |
641 | pr_err("failed to create kernel maps for symbol resolution\b"); | 642 | pr_err("failed to create kernel maps for symbol resolution\b"); |
642 | return -1; | 643 | return -1; |
643 | } | 644 | } |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 4145049e7bf5..5d8aeae50004 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -291,7 +291,7 @@ static int read_events(void) | |||
291 | register_idle_thread(); | 291 | register_idle_thread(); |
292 | register_perf_file_handler(&file_handler); | 292 | register_perf_file_handler(&file_handler); |
293 | 293 | ||
294 | return mmap_dispatch_perf_file(&header, input_name, 0, 0, | 294 | return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0, |
295 | &cwdlen, &cwd); | 295 | &cwdlen, &cwd); |
296 | } | 296 | } |
297 | 297 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7e690f73b516..fe474b7f8ad0 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -52,6 +52,7 @@ static char *pretty_printing_style = default_pretty_printing_style; | |||
52 | static int exclude_other = 1; | 52 | static int exclude_other = 1; |
53 | 53 | ||
54 | static char callchain_default_opt[] = "fractal,0.5"; | 54 | static char callchain_default_opt[] = "fractal,0.5"; |
55 | const char *vmlinux_name; | ||
55 | 56 | ||
56 | static char *cwd; | 57 | static char *cwd; |
57 | static int cwdlen; | 58 | static int cwdlen; |
@@ -925,8 +926,9 @@ static int __cmd_report(void) | |||
925 | 926 | ||
926 | register_perf_file_handler(&file_handler); | 927 | register_perf_file_handler(&file_handler); |
927 | 928 | ||
928 | ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths, | 929 | ret = mmap_dispatch_perf_file(&header, input_name, vmlinux_name, |
929 | &cwdlen, &cwd); | 930 | !vmlinux_name, force, |
931 | full_paths, &cwdlen, &cwd); | ||
930 | if (ret) | 932 | if (ret) |
931 | return ret; | 933 | return ret; |
932 | 934 | ||
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index df44b756cecc..260f57a72ee0 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1718,7 +1718,8 @@ static int read_events(void) | |||
1718 | register_idle_thread(); | 1718 | register_idle_thread(); |
1719 | register_perf_file_handler(&file_handler); | 1719 | register_perf_file_handler(&file_handler); |
1720 | 1720 | ||
1721 | return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd); | 1721 | return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0, |
1722 | &cwdlen, &cwd); | ||
1722 | } | 1723 | } |
1723 | 1724 | ||
1724 | static void print_bad_events(void) | 1725 | static void print_bad_events(void) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ea49c2e9dda3..eef9caab6eee 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -79,6 +79,7 @@ static int dump_symtab = 0; | |||
79 | static bool hide_kernel_symbols = false; | 79 | static bool hide_kernel_symbols = false; |
80 | static bool hide_user_symbols = false; | 80 | static bool hide_user_symbols = false; |
81 | static struct winsize winsize; | 81 | static struct winsize winsize; |
82 | const char *vmlinux_name; | ||
82 | static const char *graph_line = | 83 | static const char *graph_line = |
83 | "_____________________________________________________________________" | 84 | "_____________________________________________________________________" |
84 | "_____________________________________________________________________"; | 85 | "_____________________________________________________________________"; |
@@ -1341,7 +1342,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1341 | if (delay_secs < 1) | 1342 | if (delay_secs < 1) |
1342 | delay_secs = 1; | 1343 | delay_secs = 1; |
1343 | 1344 | ||
1344 | err = kernel_maps__init(true); | 1345 | err = kernel_maps__init(vmlinux_name, !vmlinux_name, true); |
1345 | if (err < 0) | 1346 | if (err < 0) |
1346 | return err; | 1347 | return err; |
1347 | parse_source(sym_filter_entry); | 1348 | parse_source(sym_filter_entry); |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d042d656c561..b71198e5dc14 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -131,7 +131,8 @@ static int __cmd_trace(void) | |||
131 | register_idle_thread(); | 131 | register_idle_thread(); |
132 | register_perf_file_handler(&file_handler); | 132 | register_perf_file_handler(&file_handler); |
133 | 133 | ||
134 | return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd); | 134 | return mmap_dispatch_perf_file(&header, input_name, NULL, false, |
135 | 0, 0, &cwdlen, &cwd); | ||
135 | } | 136 | } |
136 | 137 | ||
137 | static const char * const annotate_usage[] = { | 138 | static const char * const annotate_usage[] = { |
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index e7b6c2bea3de..f318d19b2562 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c | |||
@@ -101,6 +101,8 @@ out: | |||
101 | 101 | ||
102 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 102 | int mmap_dispatch_perf_file(struct perf_header **pheader, |
103 | const char *input_name, | 103 | const char *input_name, |
104 | const char *vmlinux_name, | ||
105 | bool try_vmlinux_path, | ||
104 | int force, | 106 | int force, |
105 | int full_paths, | 107 | int full_paths, |
106 | int *cwdlen, | 108 | int *cwdlen, |
@@ -171,7 +173,7 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, | |||
171 | goto out_delete; | 173 | goto out_delete; |
172 | 174 | ||
173 | err = -ENOMEM; | 175 | err = -ENOMEM; |
174 | if (kernel_maps__init(true) < 0) { | 176 | if (kernel_maps__init(vmlinux_name, try_vmlinux_path, true) < 0) { |
175 | pr_err("failed to setup the kernel maps to resolve symbols\n"); | 177 | pr_err("failed to setup the kernel maps to resolve symbols\n"); |
176 | goto out_delete; | 178 | goto out_delete; |
177 | } | 179 | } |
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index ae036ecd7625..3f0d21b3819e 100644 --- a/tools/perf/util/data_map.h +++ b/tools/perf/util/data_map.h | |||
@@ -23,6 +23,8 @@ struct perf_file_handler { | |||
23 | void register_perf_file_handler(struct perf_file_handler *handler); | 23 | void register_perf_file_handler(struct perf_file_handler *handler); |
24 | int mmap_dispatch_perf_file(struct perf_header **pheader, | 24 | int mmap_dispatch_perf_file(struct perf_header **pheader, |
25 | const char *input_name, | 25 | const char *input_name, |
26 | const char *vmlinux_name, | ||
27 | bool try_vmlinux_path, | ||
26 | int force, | 28 | int force, |
27 | int full_paths, | 29 | int full_paths, |
28 | int *cwdlen, | 30 | int *cwdlen, |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ac3410b8e9e3..1332f8ec04aa 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -257,7 +257,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
257 | * Read the kernel buildid nad the list of loaded modules with | 257 | * Read the kernel buildid nad the list of loaded modules with |
258 | * its build_ids: | 258 | * its build_ids: |
259 | */ | 259 | */ |
260 | kernel_maps__init(true); | 260 | kernel_maps__init(NULL, false, true); |
261 | 261 | ||
262 | /* Write build-ids */ | 262 | /* Write build-ids */ |
263 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | 263 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 74b5b8a16951..44d81d5ae8cf 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -34,6 +34,8 @@ static void kernel_maps__insert(struct map *map); | |||
34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
35 | symbol_filter_t filter); | 35 | symbol_filter_t filter); |
36 | unsigned int symbol__priv_size; | 36 | unsigned int symbol__priv_size; |
37 | static int vmlinux_path__nr_entries; | ||
38 | static char **vmlinux_path; | ||
37 | 39 | ||
38 | static struct rb_root kernel_maps; | 40 | static struct rb_root kernel_maps; |
39 | 41 | ||
@@ -1386,15 +1388,43 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1386 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 1388 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
1387 | symbol_filter_t filter) | 1389 | symbol_filter_t filter) |
1388 | { | 1390 | { |
1389 | int err = dso__load_vmlinux(self, map, self->name, filter); | 1391 | int err; |
1392 | bool is_kallsyms; | ||
1393 | |||
1394 | if (vmlinux_path != NULL) { | ||
1395 | int i; | ||
1396 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | ||
1397 | vmlinux_path__nr_entries); | ||
1398 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | ||
1399 | err = dso__load_vmlinux(self, map, vmlinux_path[i], | ||
1400 | filter); | ||
1401 | if (err > 0) { | ||
1402 | pr_debug("Using %s for symbols\n", | ||
1403 | vmlinux_path[i]); | ||
1404 | dso__set_long_name(self, | ||
1405 | strdup(vmlinux_path[i])); | ||
1406 | goto out_fixup; | ||
1407 | } | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | is_kallsyms = self->long_name[0] == '['; | ||
1412 | if (is_kallsyms) | ||
1413 | goto do_kallsyms; | ||
1390 | 1414 | ||
1415 | err = dso__load_vmlinux(self, map, self->long_name, filter); | ||
1391 | if (err <= 0) { | 1416 | if (err <= 0) { |
1417 | pr_info("The file %s cannot be used, " | ||
1418 | "trying to use /proc/kallsyms...", self->long_name); | ||
1419 | sleep(2); | ||
1420 | do_kallsyms: | ||
1392 | err = kernel_maps__load_kallsyms(filter); | 1421 | err = kernel_maps__load_kallsyms(filter); |
1393 | if (err > 0) | 1422 | if (err > 0 && !is_kallsyms) |
1394 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); | 1423 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); |
1395 | } | 1424 | } |
1396 | 1425 | ||
1397 | if (err > 0) { | 1426 | if (err > 0) { |
1427 | out_fixup: | ||
1398 | map__fixup_start(map); | 1428 | map__fixup_start(map); |
1399 | map__fixup_end(map); | 1429 | map__fixup_end(map); |
1400 | } | 1430 | } |
@@ -1403,9 +1433,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1403 | } | 1433 | } |
1404 | 1434 | ||
1405 | LIST_HEAD(dsos); | 1435 | LIST_HEAD(dsos); |
1406 | struct dso *vdso; | 1436 | struct dso *vdso; |
1407 | |||
1408 | const char *vmlinux_name = "vmlinux"; | ||
1409 | 1437 | ||
1410 | static void dsos__add(struct dso *dso) | 1438 | static void dsos__add(struct dso *dso) |
1411 | { | 1439 | { |
@@ -1457,9 +1485,9 @@ size_t dsos__fprintf_buildid(FILE *fp) | |||
1457 | return ret; | 1485 | return ret; |
1458 | } | 1486 | } |
1459 | 1487 | ||
1460 | static int kernel_maps__create_kernel_map(void) | 1488 | static int kernel_maps__create_kernel_map(const char *vmlinux_name) |
1461 | { | 1489 | { |
1462 | struct dso *kernel = dso__new(vmlinux_name); | 1490 | struct dso *kernel = dso__new(vmlinux_name ?: "[kernel.kallsyms]"); |
1463 | 1491 | ||
1464 | if (kernel == NULL) | 1492 | if (kernel == NULL) |
1465 | return -1; | 1493 | return -1; |
@@ -1468,10 +1496,10 @@ static int kernel_maps__create_kernel_map(void) | |||
1468 | if (kernel_map == NULL) | 1496 | if (kernel_map == NULL) |
1469 | goto out_delete_kernel_dso; | 1497 | goto out_delete_kernel_dso; |
1470 | 1498 | ||
1471 | kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip; | 1499 | kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip; |
1500 | kernel->short_name = "[kernel]"; | ||
1501 | kernel->kernel = 1; | ||
1472 | 1502 | ||
1473 | kernel->short_name = "[kernel]"; | ||
1474 | kernel->kernel = 1; | ||
1475 | vdso = dso__new("[vdso]"); | 1503 | vdso = dso__new("[vdso]"); |
1476 | if (vdso == NULL) | 1504 | if (vdso == NULL) |
1477 | goto out_delete_kernel_map; | 1505 | goto out_delete_kernel_map; |
@@ -1494,11 +1522,72 @@ out_delete_kernel_dso: | |||
1494 | return -1; | 1522 | return -1; |
1495 | } | 1523 | } |
1496 | 1524 | ||
1497 | int kernel_maps__init(bool use_modules) | 1525 | static void vmlinux_path__exit(void) |
1526 | { | ||
1527 | while (--vmlinux_path__nr_entries >= 0) { | ||
1528 | free(vmlinux_path[vmlinux_path__nr_entries]); | ||
1529 | vmlinux_path[vmlinux_path__nr_entries] = NULL; | ||
1530 | } | ||
1531 | |||
1532 | free(vmlinux_path); | ||
1533 | vmlinux_path = NULL; | ||
1534 | } | ||
1535 | |||
1536 | static int vmlinux_path__init(void) | ||
1537 | { | ||
1538 | struct utsname uts; | ||
1539 | char bf[PATH_MAX]; | ||
1540 | |||
1541 | if (uname(&uts) < 0) | ||
1542 | return -1; | ||
1543 | |||
1544 | vmlinux_path = malloc(sizeof(char *) * 5); | ||
1545 | if (vmlinux_path == NULL) | ||
1546 | return -1; | ||
1547 | |||
1548 | vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux"); | ||
1549 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1550 | goto out_fail; | ||
1551 | ++vmlinux_path__nr_entries; | ||
1552 | vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux"); | ||
1553 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1554 | goto out_fail; | ||
1555 | ++vmlinux_path__nr_entries; | ||
1556 | snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); | ||
1557 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | ||
1558 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1559 | goto out_fail; | ||
1560 | ++vmlinux_path__nr_entries; | ||
1561 | snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); | ||
1562 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | ||
1563 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1564 | goto out_fail; | ||
1565 | ++vmlinux_path__nr_entries; | ||
1566 | snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", | ||
1567 | uts.release); | ||
1568 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | ||
1569 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1570 | goto out_fail; | ||
1571 | ++vmlinux_path__nr_entries; | ||
1572 | |||
1573 | return 0; | ||
1574 | |||
1575 | out_fail: | ||
1576 | vmlinux_path__exit(); | ||
1577 | return -1; | ||
1578 | } | ||
1579 | |||
1580 | int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path, | ||
1581 | bool use_modules) | ||
1498 | { | 1582 | { |
1499 | if (kernel_maps__create_kernel_map() < 0) | 1583 | if (try_vmlinux_path && vmlinux_path__init() < 0) |
1500 | return -1; | 1584 | return -1; |
1501 | 1585 | ||
1586 | if (kernel_maps__create_kernel_map(vmlinux_name) < 0) { | ||
1587 | vmlinux_path__exit(); | ||
1588 | return -1; | ||
1589 | } | ||
1590 | |||
1502 | if (use_modules && kernel_maps__create_module_maps() < 0) | 1591 | if (use_modules && kernel_maps__create_module_maps() < 0) |
1503 | pr_debug("Failed to load list of modules in use, " | 1592 | pr_debug("Failed to load list of modules in use, " |
1504 | "continuing...\n"); | 1593 | "continuing...\n"); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 7a129047c47d..8c4d026e067a 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -93,7 +93,8 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size); | |||
93 | bool dsos__read_build_ids(void); | 93 | bool dsos__read_build_ids(void); |
94 | int build_id__sprintf(u8 *self, int len, char *bf); | 94 | int build_id__sprintf(u8 *self, int len, char *bf); |
95 | 95 | ||
96 | int kernel_maps__init(bool use_modules); | 96 | int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path, |
97 | bool use_modules); | ||
97 | size_t kernel_maps__fprintf(FILE *fp); | 98 | size_t kernel_maps__fprintf(FILE *fp); |
98 | 99 | ||
99 | void symbol__init(unsigned int priv_size); | 100 | void symbol__init(unsigned int priv_size); |
@@ -101,5 +102,4 @@ void symbol__init(unsigned int priv_size); | |||
101 | extern struct list_head dsos; | 102 | extern struct list_head dsos; |
102 | extern struct map *kernel_map; | 103 | extern struct map *kernel_map; |
103 | extern struct dso *vdso; | 104 | extern struct dso *vdso; |
104 | extern const char *vmlinux_name; | ||
105 | #endif /* __PERF_SYMBOL */ | 105 | #endif /* __PERF_SYMBOL */ |