aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c299
1 files changed, 205 insertions, 94 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 5b276833e2bf..6f0dd90c36ce 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -12,6 +12,7 @@
12#include <fcntl.h> 12#include <fcntl.h>
13#include <unistd.h> 13#include <unistd.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "debug.h"
15#include "symbol.h" 16#include "symbol.h"
16#include "strlist.h" 17#include "strlist.h"
17 18
@@ -25,6 +26,8 @@
25#define NT_GNU_BUILD_ID 3 26#define NT_GNU_BUILD_ID 3
26#endif 27#endif
27 28
29static bool dso__build_id_equal(const struct dso *self, u8 *build_id);
30static int elf_read_build_id(Elf *elf, void *bf, size_t size);
28static void dsos__add(struct list_head *head, struct dso *dso); 31static void dsos__add(struct list_head *head, struct dso *dso);
29static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 32static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
30static int dso__load_kernel_sym(struct dso *self, struct map *map, 33static int dso__load_kernel_sym(struct dso *self, struct map *map,
@@ -40,6 +43,14 @@ struct symbol_conf symbol_conf = {
40 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
41}; 44};
42 45
46int dso__name_len(const struct dso *self)
47{
48 if (verbose)
49 return self->long_name_len;
50
51 return self->short_name_len;
52}
53
43bool dso__loaded(const struct dso *self, enum map_type type) 54bool dso__loaded(const struct dso *self, enum map_type type)
44{ 55{
45 return self->loaded & (1 << type); 56 return self->loaded & (1 << type);
@@ -215,7 +226,9 @@ void dso__delete(struct dso *self)
215 int i; 226 int i;
216 for (i = 0; i < MAP__NR_TYPES; ++i) 227 for (i = 0; i < MAP__NR_TYPES; ++i)
217 symbols__delete(&self->symbols[i]); 228 symbols__delete(&self->symbols[i]);
218 if (self->long_name != self->name) 229 if (self->sname_alloc)
230 free((char *)self->short_name);
231 if (self->lname_alloc)
219 free(self->long_name); 232 free(self->long_name);
220 free(self); 233 free(self);
221} 234}
@@ -933,8 +946,28 @@ static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type
933 } 946 }
934} 947}
935 948
949static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
950{
951 Elf_Scn *sec = NULL;
952 GElf_Shdr shdr;
953 size_t cnt = 1;
954
955 while ((sec = elf_nextscn(elf, sec)) != NULL) {
956 gelf_getshdr(sec, &shdr);
957
958 if ((addr >= shdr.sh_addr) &&
959 (addr < (shdr.sh_addr + shdr.sh_size)))
960 return cnt;
961
962 ++cnt;
963 }
964
965 return -1;
966}
967
936static int dso__load_sym(struct dso *self, struct map *map, const char *name, 968static int dso__load_sym(struct dso *self, struct map *map, const char *name,
937 int fd, symbol_filter_t filter, int kmodule) 969 int fd, symbol_filter_t filter, int kmodule,
970 int want_symtab)
938{ 971{
939 struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; 972 struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
940 struct map *curr_map = map; 973 struct map *curr_map = map;
@@ -944,31 +977,51 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
944 int err = -1; 977 int err = -1;
945 uint32_t idx; 978 uint32_t idx;
946 GElf_Ehdr ehdr; 979 GElf_Ehdr ehdr;
947 GElf_Shdr shdr; 980 GElf_Shdr shdr, opdshdr;
948 Elf_Data *syms; 981 Elf_Data *syms, *opddata = NULL;
949 GElf_Sym sym; 982 GElf_Sym sym;
950 Elf_Scn *sec, *sec_strndx; 983 Elf_Scn *sec, *sec_strndx, *opdsec;
951 Elf *elf; 984 Elf *elf;
952 int nr = 0; 985 int nr = 0;
986 size_t opdidx = 0;
953 987
954 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 988 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
955 if (elf == NULL) { 989 if (elf == NULL) {
956 pr_err("%s: cannot read %s ELF file.\n", __func__, name); 990 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
957 goto out_close; 991 goto out_close;
958 } 992 }
959 993
960 if (gelf_getehdr(elf, &ehdr) == NULL) { 994 if (gelf_getehdr(elf, &ehdr) == NULL) {
961 pr_err("%s: cannot get elf header.\n", __func__); 995 pr_debug("%s: cannot get elf header.\n", __func__);
962 goto out_elf_end; 996 goto out_elf_end;
963 } 997 }
964 998
999 /* Always reject images with a mismatched build-id: */
1000 if (self->has_build_id) {
1001 u8 build_id[BUILD_ID_SIZE];
1002
1003 if (elf_read_build_id(elf, build_id,
1004 BUILD_ID_SIZE) != BUILD_ID_SIZE)
1005 goto out_elf_end;
1006
1007 if (!dso__build_id_equal(self, build_id))
1008 goto out_elf_end;
1009 }
1010
965 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 1011 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
966 if (sec == NULL) { 1012 if (sec == NULL) {
1013 if (want_symtab)
1014 goto out_elf_end;
1015
967 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); 1016 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
968 if (sec == NULL) 1017 if (sec == NULL)
969 goto out_elf_end; 1018 goto out_elf_end;
970 } 1019 }
971 1020
1021 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1022 if (opdsec)
1023 opddata = elf_rawdata(opdsec, NULL);
1024
972 syms = elf_getdata(sec, NULL); 1025 syms = elf_getdata(sec, NULL);
973 if (syms == NULL) 1026 if (syms == NULL)
974 goto out_elf_end; 1027 goto out_elf_end;
@@ -1013,6 +1066,13 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1013 if (!is_label && !elf_sym__is_a(&sym, map->type)) 1066 if (!is_label && !elf_sym__is_a(&sym, map->type))
1014 continue; 1067 continue;
1015 1068
1069 if (opdsec && sym.st_shndx == opdidx) {
1070 u32 offset = sym.st_value - opdshdr.sh_addr;
1071 u64 *opd = opddata->d_buf + offset;
1072 sym.st_value = *opd;
1073 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
1074 }
1075
1016 sec = elf_getscn(elf, sym.st_shndx); 1076 sec = elf_getscn(elf, sym.st_shndx);
1017 if (!sec) 1077 if (!sec)
1018 goto out_elf_end; 1078 goto out_elf_end;
@@ -1151,37 +1211,26 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1151 */ 1211 */
1152#define NOTE_ALIGN(n) (((n) + 3) & -4U) 1212#define NOTE_ALIGN(n) (((n) + 3) & -4U)
1153 1213
1154int filename__read_build_id(const char *filename, void *bf, size_t size) 1214static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1155{ 1215{
1156 int fd, err = -1; 1216 int err = -1;
1157 GElf_Ehdr ehdr; 1217 GElf_Ehdr ehdr;
1158 GElf_Shdr shdr; 1218 GElf_Shdr shdr;
1159 Elf_Data *data; 1219 Elf_Data *data;
1160 Elf_Scn *sec; 1220 Elf_Scn *sec;
1161 Elf_Kind ek; 1221 Elf_Kind ek;
1162 void *ptr; 1222 void *ptr;
1163 Elf *elf;
1164 1223
1165 if (size < BUILD_ID_SIZE) 1224 if (size < BUILD_ID_SIZE)
1166 goto out; 1225 goto out;
1167 1226
1168 fd = open(filename, O_RDONLY);
1169 if (fd < 0)
1170 goto out;
1171
1172 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1173 if (elf == NULL) {
1174 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1175 goto out_close;
1176 }
1177
1178 ek = elf_kind(elf); 1227 ek = elf_kind(elf);
1179 if (ek != ELF_K_ELF) 1228 if (ek != ELF_K_ELF)
1180 goto out_elf_end; 1229 goto out;
1181 1230
1182 if (gelf_getehdr(elf, &ehdr) == NULL) { 1231 if (gelf_getehdr(elf, &ehdr) == NULL) {
1183 pr_err("%s: cannot get elf header.\n", __func__); 1232 pr_err("%s: cannot get elf header.\n", __func__);
1184 goto out_elf_end; 1233 goto out;
1185 } 1234 }
1186 1235
1187 sec = elf_section_by_name(elf, &ehdr, &shdr, 1236 sec = elf_section_by_name(elf, &ehdr, &shdr,
@@ -1190,12 +1239,12 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
1190 sec = elf_section_by_name(elf, &ehdr, &shdr, 1239 sec = elf_section_by_name(elf, &ehdr, &shdr,
1191 ".notes", NULL); 1240 ".notes", NULL);
1192 if (sec == NULL) 1241 if (sec == NULL)
1193 goto out_elf_end; 1242 goto out;
1194 } 1243 }
1195 1244
1196 data = elf_getdata(sec, NULL); 1245 data = elf_getdata(sec, NULL);
1197 if (data == NULL) 1246 if (data == NULL)
1198 goto out_elf_end; 1247 goto out;
1199 1248
1200 ptr = data->d_buf; 1249 ptr = data->d_buf;
1201 while (ptr < (data->d_buf + data->d_size)) { 1250 while (ptr < (data->d_buf + data->d_size)) {
@@ -1217,7 +1266,31 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
1217 } 1266 }
1218 ptr += descsz; 1267 ptr += descsz;
1219 } 1268 }
1220out_elf_end: 1269
1270out:
1271 return err;
1272}
1273
1274int filename__read_build_id(const char *filename, void *bf, size_t size)
1275{
1276 int fd, err = -1;
1277 Elf *elf;
1278
1279 if (size < BUILD_ID_SIZE)
1280 goto out;
1281
1282 fd = open(filename, O_RDONLY);
1283 if (fd < 0)
1284 goto out;
1285
1286 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1287 if (elf == NULL) {
1288 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1289 goto out_close;
1290 }
1291
1292 err = elf_read_build_id(elf, bf, size);
1293
1221 elf_end(elf); 1294 elf_end(elf);
1222out_close: 1295out_close:
1223 close(fd); 1296 close(fd);
@@ -1293,11 +1366,11 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1293{ 1366{
1294 int size = PATH_MAX; 1367 int size = PATH_MAX;
1295 char *name; 1368 char *name;
1296 u8 build_id[BUILD_ID_SIZE];
1297 int ret = -1; 1369 int ret = -1;
1298 int fd; 1370 int fd;
1299 struct machine *machine; 1371 struct machine *machine;
1300 const char *root_dir; 1372 const char *root_dir;
1373 int want_symtab;
1301 1374
1302 dso__set_loaded(self, map->type); 1375 dso__set_loaded(self, map->type);
1303 1376
@@ -1324,13 +1397,18 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1324 return ret; 1397 return ret;
1325 } 1398 }
1326 1399
1327 self->origin = DSO__ORIG_BUILD_ID_CACHE; 1400 /* Iterate over candidate debug images.
1328 if (dso__build_id_filename(self, name, size) != NULL) 1401 * On the first pass, only load images if they have a full symtab.
1329 goto open_file; 1402 * Failing that, do a second pass where we accept .dynsym also
1330more: 1403 */
1331 do { 1404 for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1;
1332 self->origin++; 1405 self->origin != DSO__ORIG_NOT_FOUND;
1406 self->origin++) {
1333 switch (self->origin) { 1407 switch (self->origin) {
1408 case DSO__ORIG_BUILD_ID_CACHE:
1409 if (dso__build_id_filename(self, name, size) == NULL)
1410 continue;
1411 break;
1334 case DSO__ORIG_FEDORA: 1412 case DSO__ORIG_FEDORA:
1335 snprintf(name, size, "/usr/lib/debug%s.debug", 1413 snprintf(name, size, "/usr/lib/debug%s.debug",
1336 self->long_name); 1414 self->long_name);
@@ -1339,21 +1417,20 @@ more:
1339 snprintf(name, size, "/usr/lib/debug%s", 1417 snprintf(name, size, "/usr/lib/debug%s",
1340 self->long_name); 1418 self->long_name);
1341 break; 1419 break;
1342 case DSO__ORIG_BUILDID: 1420 case DSO__ORIG_BUILDID: {
1343 if (filename__read_build_id(self->long_name, build_id, 1421 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1344 sizeof(build_id))) { 1422
1345 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1423 if (!self->has_build_id)
1346 build_id__sprintf(build_id, sizeof(build_id), 1424 continue;
1347 build_id_hex); 1425
1348 snprintf(name, size, 1426 build_id__sprintf(self->build_id,
1349 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1427 sizeof(self->build_id),
1350 build_id_hex, build_id_hex + 2); 1428 build_id_hex);
1351 if (self->has_build_id) 1429 snprintf(name, size,
1352 goto compare_build_id; 1430 "/usr/lib/debug/.build-id/%.2s/%s.debug",
1353 break; 1431 build_id_hex, build_id_hex + 2);
1354 } 1432 }
1355 self->origin++; 1433 break;
1356 /* Fall thru */
1357 case DSO__ORIG_DSO: 1434 case DSO__ORIG_DSO:
1358 snprintf(name, size, "%s", self->long_name); 1435 snprintf(name, size, "%s", self->long_name);
1359 break; 1436 break;
@@ -1366,36 +1443,41 @@ more:
1366 break; 1443 break;
1367 1444
1368 default: 1445 default:
1369 goto out; 1446 /*
1447 * If we wanted a full symtab but no image had one,
1448 * relax our requirements and repeat the search.
1449 */
1450 if (want_symtab) {
1451 want_symtab = 0;
1452 self->origin = DSO__ORIG_BUILD_ID_CACHE;
1453 } else
1454 continue;
1370 } 1455 }
1371 1456
1372 if (self->has_build_id) { 1457 /* Name is now the name of the next image to try */
1373 if (filename__read_build_id(name, build_id,
1374 sizeof(build_id)) < 0)
1375 goto more;
1376compare_build_id:
1377 if (!dso__build_id_equal(self, build_id))
1378 goto more;
1379 }
1380open_file:
1381 fd = open(name, O_RDONLY); 1458 fd = open(name, O_RDONLY);
1382 } while (fd < 0); 1459 if (fd < 0)
1460 continue;
1383 1461
1384 ret = dso__load_sym(self, map, name, fd, filter, 0); 1462 ret = dso__load_sym(self, map, name, fd, filter, 0,
1385 close(fd); 1463 want_symtab);
1464 close(fd);
1386 1465
1387 /* 1466 /*
1388 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? 1467 * Some people seem to have debuginfo files _WITHOUT_ debug
1389 */ 1468 * info!?!?
1390 if (!ret) 1469 */
1391 goto more; 1470 if (!ret)
1471 continue;
1392 1472
1393 if (ret > 0) { 1473 if (ret > 0) {
1394 int nr_plt = dso__synthesize_plt_symbols(self, map, filter); 1474 int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
1395 if (nr_plt > 0) 1475 if (nr_plt > 0)
1396 ret += nr_plt; 1476 ret += nr_plt;
1477 break;
1478 }
1397 } 1479 }
1398out: 1480
1399 free(name); 1481 free(name);
1400 if (ret < 0 && strstr(self->name, " (deleted)") != NULL) 1482 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
1401 return 0; 1483 return 0;
@@ -1494,6 +1576,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self,
1494 goto out; 1576 goto out;
1495 } 1577 }
1496 dso__set_long_name(map->dso, long_name); 1578 dso__set_long_name(map->dso, long_name);
1579 map->dso->lname_alloc = 1;
1497 dso__kernel_module_get_build_id(map->dso, ""); 1580 dso__kernel_module_get_build_id(map->dso, "");
1498 } 1581 }
1499 } 1582 }
@@ -1656,36 +1739,12 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1656{ 1739{
1657 int err = -1, fd; 1740 int err = -1, fd;
1658 1741
1659 if (self->has_build_id) {
1660 u8 build_id[BUILD_ID_SIZE];
1661
1662 if (filename__read_build_id(vmlinux, build_id,
1663 sizeof(build_id)) < 0) {
1664 pr_debug("No build_id in %s, ignoring it\n", vmlinux);
1665 return -1;
1666 }
1667 if (!dso__build_id_equal(self, build_id)) {
1668 char expected_build_id[BUILD_ID_SIZE * 2 + 1],
1669 vmlinux_build_id[BUILD_ID_SIZE * 2 + 1];
1670
1671 build_id__sprintf(self->build_id,
1672 sizeof(self->build_id),
1673 expected_build_id);
1674 build_id__sprintf(build_id, sizeof(build_id),
1675 vmlinux_build_id);
1676 pr_debug("build_id in %s is %s while expected is %s, "
1677 "ignoring it\n", vmlinux, vmlinux_build_id,
1678 expected_build_id);
1679 return -1;
1680 }
1681 }
1682
1683 fd = open(vmlinux, O_RDONLY); 1742 fd = open(vmlinux, O_RDONLY);
1684 if (fd < 0) 1743 if (fd < 0)
1685 return -1; 1744 return -1;
1686 1745
1687 dso__set_loaded(self, map->type); 1746 dso__set_loaded(self, map->type);
1688 err = dso__load_sym(self, map, vmlinux, fd, filter, 0); 1747 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0);
1689 close(fd); 1748 close(fd);
1690 1749
1691 if (err > 0) 1750 if (err > 0)
@@ -2048,6 +2107,36 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
2048 return 0; 2107 return 0;
2049} 2108}
2050 2109
2110void machine__destroy_kernel_maps(struct machine *self)
2111{
2112 enum map_type type;
2113
2114 for (type = 0; type < MAP__NR_TYPES; ++type) {
2115 struct kmap *kmap;
2116
2117 if (self->vmlinux_maps[type] == NULL)
2118 continue;
2119
2120 kmap = map__kmap(self->vmlinux_maps[type]);
2121 map_groups__remove(&self->kmaps, self->vmlinux_maps[type]);
2122 if (kmap->ref_reloc_sym) {
2123 /*
2124 * ref_reloc_sym is shared among all maps, so free just
2125 * on one of them.
2126 */
2127 if (type == MAP__FUNCTION) {
2128 free((char *)kmap->ref_reloc_sym->name);
2129 kmap->ref_reloc_sym->name = NULL;
2130 free(kmap->ref_reloc_sym);
2131 }
2132 kmap->ref_reloc_sym = NULL;
2133 }
2134
2135 map__delete(self->vmlinux_maps[type]);
2136 self->vmlinux_maps[type] = NULL;
2137 }
2138}
2139
2051int machine__create_kernel_maps(struct machine *self) 2140int machine__create_kernel_maps(struct machine *self)
2052{ 2141{
2053 struct dso *kernel = machine__create_kernel(self); 2142 struct dso *kernel = machine__create_kernel(self);
@@ -2189,6 +2278,15 @@ out_free_comm_list:
2189 return -1; 2278 return -1;
2190} 2279}
2191 2280
2281void symbol__exit(void)
2282{
2283 strlist__delete(symbol_conf.sym_list);
2284 strlist__delete(symbol_conf.dso_list);
2285 strlist__delete(symbol_conf.comm_list);
2286 vmlinux_path__exit();
2287 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
2288}
2289
2192int machines__create_kernel_maps(struct rb_root *self, pid_t pid) 2290int machines__create_kernel_maps(struct rb_root *self, pid_t pid)
2193{ 2291{
2194 struct machine *machine = machines__findnew(self, pid); 2292 struct machine *machine = machines__findnew(self, pid);
@@ -2283,6 +2381,19 @@ failure:
2283 return ret; 2381 return ret;
2284} 2382}
2285 2383
2384void machines__destroy_guest_kernel_maps(struct rb_root *self)
2385{
2386 struct rb_node *next = rb_first(self);
2387
2388 while (next) {
2389 struct machine *pos = rb_entry(next, struct machine, rb_node);
2390
2391 next = rb_next(&pos->rb_node);
2392 rb_erase(&pos->rb_node, self);
2393 machine__delete(pos);
2394 }
2395}
2396
2286int machine__load_kallsyms(struct machine *self, const char *filename, 2397int machine__load_kallsyms(struct machine *self, const char *filename,
2287 enum map_type type, symbol_filter_t filter) 2398 enum map_type type, symbol_filter_t filter)
2288{ 2399{