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 /tools/perf/util | |
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>
Diffstat (limited to 'tools/perf/util')
-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 |
5 files changed, 109 insertions, 16 deletions
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 */ |