diff options
| -rw-r--r-- | tools/perf/util/symbol.c | 80 |
1 files changed, 47 insertions, 33 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 242d2b216f46..b812ace91c60 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #define NT_GNU_BUILD_ID 3 | 26 | #define NT_GNU_BUILD_ID 3 |
| 27 | #endif | 27 | #endif |
| 28 | 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); | ||
| 29 | static void dsos__add(struct list_head *head, struct dso *dso); | 31 | static void dsos__add(struct list_head *head, struct dso *dso); |
| 30 | 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); |
| 31 | 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, |
| @@ -993,6 +995,17 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
| 993 | goto out_elf_end; | 995 | goto out_elf_end; |
| 994 | } | 996 | } |
| 995 | 997 | ||
| 998 | if (self->has_build_id) { | ||
| 999 | u8 build_id[BUILD_ID_SIZE]; | ||
| 1000 | |||
| 1001 | if (elf_read_build_id(elf, build_id, | ||
| 1002 | BUILD_ID_SIZE) != BUILD_ID_SIZE) | ||
| 1003 | goto out_elf_end; | ||
| 1004 | |||
| 1005 | if (!dso__build_id_equal(self, build_id)) | ||
| 1006 | goto out_elf_end; | ||
| 1007 | } | ||
| 1008 | |||
| 996 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 1009 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); |
| 997 | if (sec == NULL) { | 1010 | if (sec == NULL) { |
| 998 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); | 1011 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); |
| @@ -1193,37 +1206,26 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | |||
| 1193 | */ | 1206 | */ |
| 1194 | #define NOTE_ALIGN(n) (((n) + 3) & -4U) | 1207 | #define NOTE_ALIGN(n) (((n) + 3) & -4U) |
| 1195 | 1208 | ||
| 1196 | int filename__read_build_id(const char *filename, void *bf, size_t size) | 1209 | static int elf_read_build_id(Elf *elf, void *bf, size_t size) |
| 1197 | { | 1210 | { |
| 1198 | int fd, err = -1; | 1211 | int err = -1; |
| 1199 | GElf_Ehdr ehdr; | 1212 | GElf_Ehdr ehdr; |
| 1200 | GElf_Shdr shdr; | 1213 | GElf_Shdr shdr; |
| 1201 | Elf_Data *data; | 1214 | Elf_Data *data; |
| 1202 | Elf_Scn *sec; | 1215 | Elf_Scn *sec; |
| 1203 | Elf_Kind ek; | 1216 | Elf_Kind ek; |
| 1204 | void *ptr; | 1217 | void *ptr; |
| 1205 | Elf *elf; | ||
| 1206 | 1218 | ||
| 1207 | if (size < BUILD_ID_SIZE) | 1219 | if (size < BUILD_ID_SIZE) |
| 1208 | goto out; | 1220 | goto out; |
| 1209 | 1221 | ||
| 1210 | fd = open(filename, O_RDONLY); | ||
| 1211 | if (fd < 0) | ||
| 1212 | goto out; | ||
| 1213 | |||
| 1214 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
| 1215 | if (elf == NULL) { | ||
| 1216 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); | ||
| 1217 | goto out_close; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | ek = elf_kind(elf); | 1222 | ek = elf_kind(elf); |
| 1221 | if (ek != ELF_K_ELF) | 1223 | if (ek != ELF_K_ELF) |
| 1222 | goto out_elf_end; | 1224 | goto out; |
| 1223 | 1225 | ||
| 1224 | if (gelf_getehdr(elf, &ehdr) == NULL) { | 1226 | if (gelf_getehdr(elf, &ehdr) == NULL) { |
| 1225 | pr_err("%s: cannot get elf header.\n", __func__); | 1227 | pr_err("%s: cannot get elf header.\n", __func__); |
| 1226 | goto out_elf_end; | 1228 | goto out; |
| 1227 | } | 1229 | } |
| 1228 | 1230 | ||
| 1229 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1231 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
| @@ -1232,12 +1234,12 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
| 1232 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1234 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
| 1233 | ".notes", NULL); | 1235 | ".notes", NULL); |
| 1234 | if (sec == NULL) | 1236 | if (sec == NULL) |
| 1235 | goto out_elf_end; | 1237 | goto out; |
| 1236 | } | 1238 | } |
| 1237 | 1239 | ||
| 1238 | data = elf_getdata(sec, NULL); | 1240 | data = elf_getdata(sec, NULL); |
| 1239 | if (data == NULL) | 1241 | if (data == NULL) |
| 1240 | goto out_elf_end; | 1242 | goto out; |
| 1241 | 1243 | ||
| 1242 | ptr = data->d_buf; | 1244 | ptr = data->d_buf; |
| 1243 | while (ptr < (data->d_buf + data->d_size)) { | 1245 | while (ptr < (data->d_buf + data->d_size)) { |
| @@ -1259,7 +1261,31 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
| 1259 | } | 1261 | } |
| 1260 | ptr += descsz; | 1262 | ptr += descsz; |
| 1261 | } | 1263 | } |
| 1262 | out_elf_end: | 1264 | |
| 1265 | out: | ||
| 1266 | return err; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | int filename__read_build_id(const char *filename, void *bf, size_t size) | ||
| 1270 | { | ||
| 1271 | int fd, err = -1; | ||
| 1272 | Elf *elf; | ||
| 1273 | |||
| 1274 | if (size < BUILD_ID_SIZE) | ||
| 1275 | goto out; | ||
| 1276 | |||
| 1277 | fd = open(filename, O_RDONLY); | ||
| 1278 | if (fd < 0) | ||
| 1279 | goto out; | ||
| 1280 | |||
| 1281 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
| 1282 | if (elf == NULL) { | ||
| 1283 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); | ||
| 1284 | goto out_close; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | err = elf_read_build_id(elf, bf, size); | ||
| 1288 | |||
| 1263 | elf_end(elf); | 1289 | elf_end(elf); |
| 1264 | out_close: | 1290 | out_close: |
| 1265 | close(fd); | 1291 | close(fd); |
| @@ -1335,7 +1361,6 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1335 | { | 1361 | { |
| 1336 | int size = PATH_MAX; | 1362 | int size = PATH_MAX; |
| 1337 | char *name; | 1363 | char *name; |
| 1338 | u8 build_id[BUILD_ID_SIZE]; | ||
| 1339 | int ret = -1; | 1364 | int ret = -1; |
| 1340 | int fd; | 1365 | int fd; |
| 1341 | struct machine *machine; | 1366 | struct machine *machine; |
| @@ -1382,16 +1407,14 @@ more: | |||
| 1382 | self->long_name); | 1407 | self->long_name); |
| 1383 | break; | 1408 | break; |
| 1384 | case DSO__ORIG_BUILDID: | 1409 | case DSO__ORIG_BUILDID: |
| 1385 | if (filename__read_build_id(self->long_name, build_id, | 1410 | if (self->has_build_id) { |
| 1386 | sizeof(build_id))) { | ||
| 1387 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1411 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
| 1388 | build_id__sprintf(build_id, sizeof(build_id), | 1412 | build_id__sprintf(self->build_id, |
| 1413 | sizeof(self->build_id), | ||
| 1389 | build_id_hex); | 1414 | build_id_hex); |
| 1390 | snprintf(name, size, | 1415 | snprintf(name, size, |
| 1391 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 1416 | "/usr/lib/debug/.build-id/%.2s/%s.debug", |
| 1392 | build_id_hex, build_id_hex + 2); | 1417 | build_id_hex, build_id_hex + 2); |
| 1393 | if (self->has_build_id) | ||
| 1394 | goto compare_build_id; | ||
| 1395 | break; | 1418 | break; |
| 1396 | } | 1419 | } |
| 1397 | self->origin++; | 1420 | self->origin++; |
| @@ -1410,15 +1433,6 @@ more: | |||
| 1410 | default: | 1433 | default: |
| 1411 | goto out; | 1434 | goto out; |
| 1412 | } | 1435 | } |
| 1413 | |||
| 1414 | if (self->has_build_id) { | ||
| 1415 | if (filename__read_build_id(name, build_id, | ||
| 1416 | sizeof(build_id)) < 0) | ||
| 1417 | goto more; | ||
| 1418 | compare_build_id: | ||
| 1419 | if (!dso__build_id_equal(self, build_id)) | ||
| 1420 | goto more; | ||
| 1421 | } | ||
| 1422 | open_file: | 1436 | open_file: |
| 1423 | fd = open(name, O_RDONLY); | 1437 | fd = open(name, O_RDONLY); |
| 1424 | } while (fd < 0); | 1438 | } while (fd < 0); |
