diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 113 |
1 files changed, 63 insertions, 50 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 15ccfba8cdf8..f06c10f092ba 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <sys/param.h> | 11 | #include <sys/param.h> |
12 | #include <fcntl.h> | 12 | #include <fcntl.h> |
13 | #include <unistd.h> | 13 | #include <unistd.h> |
14 | #include <inttypes.h> | ||
14 | #include "build-id.h" | 15 | #include "build-id.h" |
15 | #include "debug.h" | 16 | #include "debug.h" |
16 | #include "symbol.h" | 17 | #include "symbol.h" |
@@ -153,7 +154,7 @@ static struct symbol *symbol__new(u64 start, u64 len, u8 binding, | |||
153 | self->binding = binding; | 154 | self->binding = binding; |
154 | self->namelen = namelen - 1; | 155 | self->namelen = namelen - 1; |
155 | 156 | ||
156 | pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); | 157 | pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end); |
157 | 158 | ||
158 | memcpy(self->name, name, namelen); | 159 | memcpy(self->name, name, namelen); |
159 | 160 | ||
@@ -167,7 +168,7 @@ void symbol__delete(struct symbol *self) | |||
167 | 168 | ||
168 | static size_t symbol__fprintf(struct symbol *self, FILE *fp) | 169 | static size_t symbol__fprintf(struct symbol *self, FILE *fp) |
169 | { | 170 | { |
170 | return fprintf(fp, " %llx-%llx %c %s\n", | 171 | return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", |
171 | self->start, self->end, | 172 | self->start, self->end, |
172 | self->binding == STB_GLOBAL ? 'g' : | 173 | self->binding == STB_GLOBAL ? 'g' : |
173 | self->binding == STB_LOCAL ? 'l' : 'w', | 174 | self->binding == STB_LOCAL ? 'l' : 'w', |
@@ -206,8 +207,7 @@ struct dso *dso__new(const char *name) | |||
206 | dso__set_short_name(self, self->name); | 207 | dso__set_short_name(self, self->name); |
207 | for (i = 0; i < MAP__NR_TYPES; ++i) | 208 | for (i = 0; i < MAP__NR_TYPES; ++i) |
208 | self->symbols[i] = self->symbol_names[i] = RB_ROOT; | 209 | self->symbols[i] = self->symbol_names[i] = RB_ROOT; |
209 | self->slen_calculated = 0; | 210 | self->symtab_type = SYMTAB__NOT_FOUND; |
210 | self->origin = DSO__ORIG_NOT_FOUND; | ||
211 | self->loaded = 0; | 211 | self->loaded = 0; |
212 | self->sorted_by_name = 0; | 212 | self->sorted_by_name = 0; |
213 | self->has_build_id = 0; | 213 | self->has_build_id = 0; |
@@ -680,9 +680,9 @@ int dso__load_kallsyms(struct dso *self, const char *filename, | |||
680 | return -1; | 680 | return -1; |
681 | 681 | ||
682 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) | 682 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
683 | self->origin = DSO__ORIG_GUEST_KERNEL; | 683 | self->symtab_type = SYMTAB__GUEST_KALLSYMS; |
684 | else | 684 | else |
685 | self->origin = DSO__ORIG_KERNEL; | 685 | self->symtab_type = SYMTAB__KALLSYMS; |
686 | 686 | ||
687 | return dso__split_kallsyms(self, map, filter); | 687 | return dso__split_kallsyms(self, map, filter); |
688 | } | 688 | } |
@@ -1161,6 +1161,13 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1161 | 1161 | ||
1162 | section_name = elf_sec__name(&shdr, secstrs); | 1162 | section_name = elf_sec__name(&shdr, secstrs); |
1163 | 1163 | ||
1164 | /* On ARM, symbols for thumb functions have 1 added to | ||
1165 | * the symbol address as a flag - remove it */ | ||
1166 | if ((ehdr.e_machine == EM_ARM) && | ||
1167 | (map->type == MAP__FUNCTION) && | ||
1168 | (sym.st_value & 1)) | ||
1169 | --sym.st_value; | ||
1170 | |||
1164 | if (self->kernel != DSO_TYPE_USER || kmodule) { | 1171 | if (self->kernel != DSO_TYPE_USER || kmodule) { |
1165 | char dso_name[PATH_MAX]; | 1172 | char dso_name[PATH_MAX]; |
1166 | 1173 | ||
@@ -1189,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1189 | if (curr_dso == NULL) | 1196 | if (curr_dso == NULL) |
1190 | goto out_elf_end; | 1197 | goto out_elf_end; |
1191 | 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; | ||
1192 | curr_map = map__new2(start, curr_dso, | 1201 | curr_map = map__new2(start, curr_dso, |
1193 | map->type); | 1202 | map->type); |
1194 | if (curr_map == NULL) { | 1203 | if (curr_map == NULL) { |
@@ -1197,7 +1206,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1197 | } | 1206 | } |
1198 | curr_map->map_ip = identity__map_ip; | 1207 | curr_map->map_ip = identity__map_ip; |
1199 | curr_map->unmap_ip = identity__map_ip; | 1208 | curr_map->unmap_ip = identity__map_ip; |
1200 | curr_dso->origin = self->origin; | 1209 | curr_dso->symtab_type = self->symtab_type; |
1201 | map_groups__insert(kmap->kmaps, curr_map); | 1210 | map_groups__insert(kmap->kmaps, curr_map); |
1202 | dsos__add(&self->node, curr_dso); | 1211 | dsos__add(&self->node, curr_dso); |
1203 | dso__set_loaded(curr_dso, map->type); | 1212 | dso__set_loaded(curr_dso, map->type); |
@@ -1208,8 +1217,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1208 | } | 1217 | } |
1209 | 1218 | ||
1210 | if (curr_dso->adjust_symbols) { | 1219 | if (curr_dso->adjust_symbols) { |
1211 | pr_debug4("%s: adjusting symbol: st_value: %#Lx " | 1220 | pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " |
1212 | "sh_addr: %#Lx sh_offset: %#Lx\n", __func__, | 1221 | "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, |
1213 | (u64)sym.st_value, (u64)shdr.sh_addr, | 1222 | (u64)sym.st_value, (u64)shdr.sh_addr, |
1214 | (u64)shdr.sh_offset); | 1223 | (u64)shdr.sh_offset); |
1215 | sym.st_value -= shdr.sh_addr - shdr.sh_offset; | 1224 | sym.st_value -= shdr.sh_addr - shdr.sh_offset; |
@@ -1423,21 +1432,21 @@ out: | |||
1423 | char dso__symtab_origin(const struct dso *self) | 1432 | char dso__symtab_origin(const struct dso *self) |
1424 | { | 1433 | { |
1425 | static const char origin[] = { | 1434 | static const char origin[] = { |
1426 | [DSO__ORIG_KERNEL] = 'k', | 1435 | [SYMTAB__KALLSYMS] = 'k', |
1427 | [DSO__ORIG_JAVA_JIT] = 'j', | 1436 | [SYMTAB__JAVA_JIT] = 'j', |
1428 | [DSO__ORIG_BUILD_ID_CACHE] = 'B', | 1437 | [SYMTAB__BUILD_ID_CACHE] = 'B', |
1429 | [DSO__ORIG_FEDORA] = 'f', | 1438 | [SYMTAB__FEDORA_DEBUGINFO] = 'f', |
1430 | [DSO__ORIG_UBUNTU] = 'u', | 1439 | [SYMTAB__UBUNTU_DEBUGINFO] = 'u', |
1431 | [DSO__ORIG_BUILDID] = 'b', | 1440 | [SYMTAB__BUILDID_DEBUGINFO] = 'b', |
1432 | [DSO__ORIG_DSO] = 'd', | 1441 | [SYMTAB__SYSTEM_PATH_DSO] = 'd', |
1433 | [DSO__ORIG_KMODULE] = 'K', | 1442 | [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', |
1434 | [DSO__ORIG_GUEST_KERNEL] = 'g', | 1443 | [SYMTAB__GUEST_KALLSYMS] = 'g', |
1435 | [DSO__ORIG_GUEST_KMODULE] = 'G', | 1444 | [SYMTAB__GUEST_KMODULE] = 'G', |
1436 | }; | 1445 | }; |
1437 | 1446 | ||
1438 | if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) | 1447 | if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND) |
1439 | return '!'; | 1448 | return '!'; |
1440 | return origin[self->origin]; | 1449 | return origin[self->symtab_type]; |
1441 | } | 1450 | } |
1442 | 1451 | ||
1443 | int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | 1452 | int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) |
@@ -1470,8 +1479,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1470 | 1479 | ||
1471 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { | 1480 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { |
1472 | ret = dso__load_perf_map(self, map, filter); | 1481 | ret = dso__load_perf_map(self, map, filter); |
1473 | self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : | 1482 | self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : |
1474 | DSO__ORIG_NOT_FOUND; | 1483 | SYMTAB__NOT_FOUND; |
1475 | return ret; | 1484 | return ret; |
1476 | } | 1485 | } |
1477 | 1486 | ||
@@ -1479,26 +1488,28 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1479 | * On the first pass, only load images if they have a full symtab. | 1488 | * On the first pass, only load images if they have a full symtab. |
1480 | * Failing that, do a second pass where we accept .dynsym also | 1489 | * Failing that, do a second pass where we accept .dynsym also |
1481 | */ | 1490 | */ |
1482 | for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1; | 1491 | want_symtab = 1; |
1483 | self->origin != DSO__ORIG_NOT_FOUND; | 1492 | restart: |
1484 | self->origin++) { | 1493 | for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; |
1485 | switch (self->origin) { | 1494 | self->symtab_type != SYMTAB__NOT_FOUND; |
1486 | case DSO__ORIG_BUILD_ID_CACHE: | 1495 | self->symtab_type++) { |
1496 | switch (self->symtab_type) { | ||
1497 | case SYMTAB__BUILD_ID_CACHE: | ||
1487 | /* skip the locally configured cache if a symfs is given */ | 1498 | /* skip the locally configured cache if a symfs is given */ |
1488 | if (symbol_conf.symfs[0] || | 1499 | if (symbol_conf.symfs[0] || |
1489 | (dso__build_id_filename(self, name, size) == NULL)) { | 1500 | (dso__build_id_filename(self, name, size) == NULL)) { |
1490 | continue; | 1501 | continue; |
1491 | } | 1502 | } |
1492 | break; | 1503 | break; |
1493 | case DSO__ORIG_FEDORA: | 1504 | case SYMTAB__FEDORA_DEBUGINFO: |
1494 | snprintf(name, size, "%s/usr/lib/debug%s.debug", | 1505 | snprintf(name, size, "%s/usr/lib/debug%s.debug", |
1495 | symbol_conf.symfs, self->long_name); | 1506 | symbol_conf.symfs, self->long_name); |
1496 | break; | 1507 | break; |
1497 | case DSO__ORIG_UBUNTU: | 1508 | case SYMTAB__UBUNTU_DEBUGINFO: |
1498 | snprintf(name, size, "%s/usr/lib/debug%s", | 1509 | snprintf(name, size, "%s/usr/lib/debug%s", |
1499 | symbol_conf.symfs, self->long_name); | 1510 | symbol_conf.symfs, self->long_name); |
1500 | break; | 1511 | break; |
1501 | case DSO__ORIG_BUILDID: { | 1512 | case SYMTAB__BUILDID_DEBUGINFO: { |
1502 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1513 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
1503 | 1514 | ||
1504 | if (!self->has_build_id) | 1515 | if (!self->has_build_id) |
@@ -1512,34 +1523,24 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1512 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); | 1523 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); |
1513 | } | 1524 | } |
1514 | break; | 1525 | break; |
1515 | case DSO__ORIG_DSO: | 1526 | case SYMTAB__SYSTEM_PATH_DSO: |
1516 | snprintf(name, size, "%s%s", | 1527 | snprintf(name, size, "%s%s", |
1517 | symbol_conf.symfs, self->long_name); | 1528 | symbol_conf.symfs, self->long_name); |
1518 | break; | 1529 | break; |
1519 | case DSO__ORIG_GUEST_KMODULE: | 1530 | case SYMTAB__GUEST_KMODULE: |
1520 | if (map->groups && map->groups->machine) | 1531 | if (map->groups && machine) |
1521 | root_dir = map->groups->machine->root_dir; | 1532 | root_dir = machine->root_dir; |
1522 | else | 1533 | else |
1523 | root_dir = ""; | 1534 | root_dir = ""; |
1524 | snprintf(name, size, "%s%s%s", symbol_conf.symfs, | 1535 | snprintf(name, size, "%s%s%s", symbol_conf.symfs, |
1525 | root_dir, self->long_name); | 1536 | root_dir, self->long_name); |
1526 | break; | 1537 | break; |
1527 | 1538 | ||
1528 | case DSO__ORIG_KMODULE: | 1539 | case SYMTAB__SYSTEM_PATH_KMODULE: |
1529 | snprintf(name, size, "%s%s", symbol_conf.symfs, | 1540 | snprintf(name, size, "%s%s", symbol_conf.symfs, |
1530 | self->long_name); | 1541 | self->long_name); |
1531 | break; | 1542 | break; |
1532 | 1543 | default:; | |
1533 | default: | ||
1534 | /* | ||
1535 | * If we wanted a full symtab but no image had one, | ||
1536 | * relax our requirements and repeat the search. | ||
1537 | */ | ||
1538 | if (want_symtab) { | ||
1539 | want_symtab = 0; | ||
1540 | self->origin = DSO__ORIG_BUILD_ID_CACHE; | ||
1541 | } else | ||
1542 | continue; | ||
1543 | } | 1544 | } |
1544 | 1545 | ||
1545 | /* Name is now the name of the next image to try */ | 1546 | /* Name is now the name of the next image to try */ |
@@ -1566,6 +1567,15 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1566 | } | 1567 | } |
1567 | } | 1568 | } |
1568 | 1569 | ||
1570 | /* | ||
1571 | * If we wanted a full symtab but no image had one, | ||
1572 | * relax our requirements and repeat the search. | ||
1573 | */ | ||
1574 | if (ret <= 0 && want_symtab) { | ||
1575 | want_symtab = 0; | ||
1576 | goto restart; | ||
1577 | } | ||
1578 | |||
1569 | free(name); | 1579 | free(name); |
1570 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) | 1580 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) |
1571 | return 0; | 1581 | return 0; |
@@ -1750,9 +1760,9 @@ struct map *machine__new_module(struct machine *self, u64 start, | |||
1750 | return NULL; | 1760 | return NULL; |
1751 | 1761 | ||
1752 | if (machine__is_host(self)) | 1762 | if (machine__is_host(self)) |
1753 | dso->origin = DSO__ORIG_KMODULE; | 1763 | dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; |
1754 | else | 1764 | else |
1755 | dso->origin = DSO__ORIG_GUEST_KMODULE; | 1765 | dso->symtab_type = SYMTAB__GUEST_KMODULE; |
1756 | map_groups__insert(&self->kmaps, map); | 1766 | map_groups__insert(&self->kmaps, map); |
1757 | return map; | 1767 | return map; |
1758 | } | 1768 | } |
@@ -1828,12 +1838,13 @@ int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1828 | int err = -1, fd; | 1838 | int err = -1, fd; |
1829 | char symfs_vmlinux[PATH_MAX]; | 1839 | char symfs_vmlinux[PATH_MAX]; |
1830 | 1840 | ||
1831 | snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s", | 1841 | snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", |
1832 | symbol_conf.symfs, vmlinux); | 1842 | symbol_conf.symfs, vmlinux); |
1833 | fd = open(symfs_vmlinux, O_RDONLY); | 1843 | fd = open(symfs_vmlinux, O_RDONLY); |
1834 | if (fd < 0) | 1844 | if (fd < 0) |
1835 | return -1; | 1845 | return -1; |
1836 | 1846 | ||
1847 | dso__set_long_name(self, (char *)vmlinux); | ||
1837 | dso__set_loaded(self, map->type); | 1848 | dso__set_loaded(self, map->type); |
1838 | 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); |
1839 | close(fd); | 1850 | close(fd); |
@@ -2395,6 +2406,8 @@ int symbol__init(void) | |||
2395 | if (symbol_conf.initialized) | 2406 | if (symbol_conf.initialized) |
2396 | return 0; | 2407 | return 0; |
2397 | 2408 | ||
2409 | symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); | ||
2410 | |||
2398 | elf_version(EV_CURRENT); | 2411 | elf_version(EV_CURRENT); |
2399 | if (symbol_conf.sort_by_name) | 2412 | if (symbol_conf.sort_by_name) |
2400 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - | 2413 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - |