aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorDave Martin <dave.martin@linaro.org>2010-07-30 08:08:08 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-07-30 08:53:30 -0400
commit21916c380d93ab59d6d07ee198fb31c8f1338e26 (patch)
tree8d7d491ea6549b74144efa5ba63c4240f84a874a /tools/perf
parent6e406257b3794009e3b7a6d48b54beb547719565 (diff)
perf tools: Factor out buildid reading and make it implicit in dso__load
If we have a buildid, then we never want to load an image which has no buildid, or which has a different buildid, so it makes sense for the check to be built into dso__load and not done separately. This is fine for old distros which don't use buildid at all since we do no check in that case. This refactoring also alleviates some subtle race condition issues by not opening ELF images twice to check the buildid and then load the symbols, which could lead to weirdness if an image is replaced under our feet. Signed-off-by: Dave Martin <dave.martin@linaro.org> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/symbol.c80
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
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);
29static void dsos__add(struct list_head *head, struct dso *dso); 31static void dsos__add(struct list_head *head, struct dso *dso);
30static 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);
31static int dso__load_kernel_sym(struct dso *self, struct map *map, 33static 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
1196int filename__read_build_id(const char *filename, void *bf, size_t size) 1209static 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 }
1262out_elf_end: 1264
1265out:
1266 return err;
1267}
1268
1269int 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);
1264out_close: 1290out_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;
1418compare_build_id:
1419 if (!dso__build_id_equal(self, build_id))
1420 goto more;
1421 }
1422open_file: 1436open_file:
1423 fd = open(name, O_RDONLY); 1437 fd = open(name, O_RDONLY);
1424 } while (fd < 0); 1438 } while (fd < 0);