diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 299 |
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 | ||
29 | static bool dso__build_id_equal(const struct dso *self, u8 *build_id); | ||
30 | static int elf_read_build_id(Elf *elf, void *bf, size_t size); | ||
28 | static void dsos__add(struct list_head *head, struct dso *dso); | 31 | static void dsos__add(struct list_head *head, struct dso *dso); |
29 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
30 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 33 | static 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 | ||
46 | int 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 | |||
43 | bool dso__loaded(const struct dso *self, enum map_type type) | 54 | bool 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 | ||
949 | static 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 | |||
936 | static int dso__load_sym(struct dso *self, struct map *map, const char *name, | 968 | static 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 | ||
1154 | int filename__read_build_id(const char *filename, void *bf, size_t size) | 1214 | static 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 | } |
1220 | out_elf_end: | 1269 | |
1270 | out: | ||
1271 | return err; | ||
1272 | } | ||
1273 | |||
1274 | int 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); |
1222 | out_close: | 1295 | out_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 |
1330 | more: | 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; | ||
1376 | compare_build_id: | ||
1377 | if (!dso__build_id_equal(self, build_id)) | ||
1378 | goto more; | ||
1379 | } | ||
1380 | open_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 | } |
1398 | out: | 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 | ||
2110 | void 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 | |||
2051 | int machine__create_kernel_maps(struct machine *self) | 2140 | int 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 | ||
2281 | void 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 | |||
2192 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid) | 2290 | int 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 | ||
2384 | void 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 | |||
2286 | int machine__load_kallsyms(struct machine *self, const char *filename, | 2397 | int 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 | { |