# define ElfXX_Ehdr Elf32_Ehdr
# define ElfXX_Shdr Elf32_Shdr
# define ElfXX_Phdr Elf32_Phdr
+# define ElfXX_Nhdr Elf32_Nhdr
# define ElfXX_Sym Elf32_Sym
+# define ElfXX_Off Elf32_Off
# define ElfXX_Word Elf32_Word
# define ElfXX_Addr Elf32_Addr
# define ElfXX_Dyn Elf32_Dyn
# define ElfXX_Ehdr Elf64_Ehdr
# define ElfXX_Shdr Elf64_Shdr
# define ElfXX_Phdr Elf64_Phdr
+# define ElfXX_Nhdr Elf64_Nhdr
# define ElfXX_Sym Elf64_Sym
+# define ElfXX_Off Elf64_Off
# define ElfXX_Word Elf64_Word
# define ElfXX_Addr Elf64_Addr
# define ElfXX_Dyn Elf64_Dyn
}
+/*
+ * Look for a build-id in an ELF image. The build-id specification
+ * can be found here:
+ *
+ * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
+ */
+static
+Char *find_buildid(Addr image, UWord n_image)
+{
+ Char* buildid = NULL;
+ ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
+
+#ifdef NT_GNU_BUILD_ID
+ if (n_image >= sizeof(ElfXX_Ehdr) &&
+ ML_(is_elf_object_file)(ehdr, n_image)) {
+ Word i;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ ElfXX_Phdr* phdr = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize);
+
+ if (phdr->p_type == PT_NOTE) {
+ ElfXX_Off offset = phdr->p_offset;
+
+ while (offset < phdr->p_offset + phdr->p_filesz) {
+ ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
+ Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
+ UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
+ Word j;
+
+ if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
+ note->n_type == NT_GNU_BUILD_ID) {
+ buildid = ML_(dinfo_zalloc)("di.fbi.1", note->n_descsz * 2 + 1);
+
+ for (j = 0; j < note->n_descsz; j++) {
+ VG_(sprintf)(buildid + VG_(strlen)(buildid), "%02x", desc[j]);
+ }
+ }
+
+ offset = offset + sizeof(ElfXX_Nhdr)
+ + ((note->n_namesz + 3) & ~3)
+ + ((note->n_descsz + 3) & ~3);
+ }
+ }
+ }
+ }
+#endif
+
+ return buildid;
+}
+
/*
* This routine for calculating the CRC for a separate debug file
* is GPLed code borrowed from GNU binutils.
* not match the value from the main object file.
*/
static
-Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size )
+Addr open_debug_file( Char* name, Char* buildid, UInt crc, /*OUT*/UWord* size )
{
SysRes fd, sres;
struct vg_stat stat_buf;
if (VG_(clo_verbosity) > 1)
VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
-
+
*size = stat_buf.size;
sres = VG_(am_mmap_file_float_valgrind)
if (sr_isError(sres))
return 0;
- calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
- if (calccrc != crc) {
- SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
- vg_assert(!sr_isError(res));
+ if (buildid) {
+ Char* debug_buildid = find_buildid(sr_Res(sres), *size);
+ if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
+ SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
+ vg_assert(!sr_isError(res));
+ if (VG_(clo_verbosity) > 1)
+ VG_(message)(Vg_DebugMsg,
+ " .. build-id mismatch (found %s wanted %s)\n", debug_buildid, buildid);
+ ML_(dinfo_free)(debug_buildid);
+ return 0;
+ }
+ ML_(dinfo_free)(debug_buildid);
+
if (VG_(clo_verbosity) > 1)
- VG_(message)(Vg_DebugMsg,
- " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
- return 0;
- }
+ VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
+ } else {
+ calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
+ if (calccrc != crc) {
+ SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
+ vg_assert(!sr_isError(res));
+ if (VG_(clo_verbosity) > 1)
+ VG_(message)(Vg_DebugMsg,
+ " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
+ return 0;
+ }
- if (VG_(clo_verbosity) > 1)
- VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
+ if (VG_(clo_verbosity) > 1)
+ VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
+ }
return sr_Res(sres);
}
*/
static
Addr find_debug_file( struct _DebugInfo* di,
- Char* objpath, Char* debugname,
- UInt crc, /*OUT*/UWord* size )
+ Char* objpath, Char* buildid,
+ Char* debugname, UInt crc,
+ /*OUT*/UWord* size )
{
- Char *objdir = ML_(dinfo_strdup)("di.fdf.1", objpath);
- Char *objdirptr;
- Char *debugpath;
+ Char *debugpath = NULL;
Addr addr = 0;
-
- if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
- *objdirptr = '\0';
- debugpath = ML_(dinfo_zalloc)(
- "di.fdf.2",
- VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
-
- VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
+ if (buildid != NULL) {
+ debugpath = ML_(dinfo_zalloc)(
+ "di.fdf.1",
+ VG_(strlen)(buildid) + 33);
+
+ VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
+ buildid[0], buildid[1], buildid + 2);
+
+ if ((addr = open_debug_file(debugpath, buildid, 0, size)) == 0) {
+ ML_(dinfo_free)(debugpath);
+ debugpath = NULL;
+ }
+ }
+
+ if (addr == 0 && debugname != NULL) {
+ Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
+ Char *objdirptr;
+
+ if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
+ *objdirptr = '\0';
+
+ debugpath = ML_(dinfo_zalloc)(
+ "di.fdf.3",
+ VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
- if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
- VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
- if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
- VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
- addr = open_debug_file(debugpath, crc, size);
+ VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
+
+ if ((addr = open_debug_file(debugpath, NULL, crc, size)) == 0) {
+ VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
+ if ((addr = open_debug_file(debugpath, NULL, crc, size)) == 0) {
+ VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
+ addr = open_debug_file(debugpath, NULL, crc, size);
+ }
}
+
+ ML_(dinfo_free)(objdir);
}
if (addr) {
}
ML_(dinfo_free)(debugpath);
- ML_(dinfo_free)(objdir);
-
+
return addr;
}
Addr rw_svma_limit = 0;
PtrdiffT rw_bias = 0;
+ /* Build ID */
+ Char* buildid = NULL;
+
vg_assert(di);
vg_assert(di->have_rx_map == True);
vg_assert(di->have_rw_map == True);
# undef FIND
}
-
- /* Did we find a debuglink section? */
- if (debuglink_img != NULL) {
- UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
- UInt crc;
- vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
+ /* Look for a build-id */
+ buildid = find_buildid(oimage, n_oimage);
- /* Extract the CRC from the debuglink section */
- crc = *(UInt *)(debuglink_img + crc_offset);
+ /* Look for a debug image */
+ if (buildid != NULL || debuglink_img != NULL) {
+ /* Do have a debuglink section? */
+ if (debuglink_img != NULL) {
+ UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
+ UInt crc;
+
+ vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
+
+ /* Extract the CRC from the debuglink section */
+ crc = *(UInt *)(debuglink_img + crc_offset);
+
+ /* See if we can find a matching debug file */
+ dimage = find_debug_file( di, di->filename, buildid,
+ debuglink_img, crc, &n_dimage );
+ } else {
+ /* See if we can find a matching debug file */
+ dimage = find_debug_file( di, di->filename, buildid, NULL, 0, &n_dimage );
+ }
- /* See if we can find a matching debug file */
- dimage = find_debug_file( di, di->filename, debuglink_img,
- crc, &n_dimage );
+ ML_(dinfo_free)(buildid);
if (dimage != 0
&& n_dimage >= sizeof(ElfXX_Ehdr)