Commit be96ea8ffa788dccb1ba895cced29db6687c4911

Authored by Stephane Eranian
Committed by Arnaldo Carvalho de Melo
1 parent 936be50306

perf symbols: Fix issue with binaries using 16-bytes buildids (v2)

Buildid can vary in size. According to the man page of ld, buildid can
be 160 bits (sha1) or 128 bits (md5, uuid). Perf assumes buildid size of
20 bytes (160 bits) regardless. When dealing with md5 buildids, it would
thus read more than needed and that would cause mismatches and samples
without symbols.

This patch fixes this by taking into account the actual buildid size as
encoded int he section header. The leftover bytes are also cleared.

This second version fixes a minor issue with the memset() base position.

Cc: David S. Miller <davem@davemloft.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Stephane Eranian <eranian@gmail.com>
Link: http://lkml.kernel.org/r/4cc1af3c.8ee7d80a.5a28.ffff868e@mx.google.com
Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 1 changed file with 13 additions and 11 deletions Side-by-side Diff

tools/perf/util/symbol.c
... ... @@ -1170,8 +1170,7 @@
1170 1170 if (dso->has_build_id) {
1171 1171 u8 build_id[BUILD_ID_SIZE];
1172 1172  
1173   - if (elf_read_build_id(elf, build_id,
1174   - BUILD_ID_SIZE) != BUILD_ID_SIZE)
  1173 + if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1175 1174 goto out_elf_end;
1176 1175  
1177 1176 if (!dso__build_id_equal(dso, build_id))
... ... @@ -1443,8 +1442,8 @@
1443 1442 ptr = data->d_buf;
1444 1443 while (ptr < (data->d_buf + data->d_size)) {
1445 1444 GElf_Nhdr *nhdr = ptr;
1446   - int namesz = NOTE_ALIGN(nhdr->n_namesz),
1447   - descsz = NOTE_ALIGN(nhdr->n_descsz);
  1445 + size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
  1446 + descsz = NOTE_ALIGN(nhdr->n_descsz);
1448 1447 const char *name;
1449 1448  
1450 1449 ptr += sizeof(*nhdr);
... ... @@ -1453,8 +1452,10 @@
1453 1452 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1454 1453 nhdr->n_namesz == sizeof("GNU")) {
1455 1454 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1456   - memcpy(bf, ptr, BUILD_ID_SIZE);
1457   - err = BUILD_ID_SIZE;
  1455 + size_t sz = min(size, descsz);
  1456 + memcpy(bf, ptr, sz);
  1457 + memset(bf + sz, 0, size - sz);
  1458 + err = descsz;
1458 1459 break;
1459 1460 }
1460 1461 }
... ... @@ -1506,7 +1507,7 @@
1506 1507 while (1) {
1507 1508 char bf[BUFSIZ];
1508 1509 GElf_Nhdr nhdr;
1509   - int namesz, descsz;
  1510 + size_t namesz, descsz;
1510 1511  
1511 1512 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1512 1513 break;
1513 1514  
1514 1515  
... ... @@ -1515,15 +1516,16 @@
1515 1516 descsz = NOTE_ALIGN(nhdr.n_descsz);
1516 1517 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1517 1518 nhdr.n_namesz == sizeof("GNU")) {
1518   - if (read(fd, bf, namesz) != namesz)
  1519 + if (read(fd, bf, namesz) != (ssize_t)namesz)
1519 1520 break;
1520 1521 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1521   - if (read(fd, build_id,
1522   - BUILD_ID_SIZE) == BUILD_ID_SIZE) {
  1522 + size_t sz = min(descsz, size);
  1523 + if (read(fd, build_id, sz) == (ssize_t)sz) {
  1524 + memset(build_id + sz, 0, size - sz);
1523 1525 err = 0;
1524 1526 break;
1525 1527 }
1526   - } else if (read(fd, bf, descsz) != descsz)
  1528 + } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1527 1529 break;
1528 1530 } else {
1529 1531 int n = namesz + descsz;