diff mbox

Find debug symbols file by buildid for coff file format also

Message ID 1426520230-18940-1-git-send-email-jon.turney@dronecode.org.uk
State New
Headers show

Commit Message

Jon TURNEY March 16, 2015, 3:37 p.m. UTC
bfd/ChangeLog:

2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>

	* elf-bfd.h : Remove struct elf_build_id.
	* bfd.c : Add struct bfd_build_id.
	* bfd-in2.h: Regenerate.
	* elf.c (elfobj_grok_gnu_build_id): Update to use bfd_build_id.
	* libpei.h: Add protoype and macros for
	bfd_XXi_slurp_codeview_record.
	* peXXigen.c (_bfd_XXi_slurp_codeview_record): Make public
	* peicode.h (pe_bfd_read_buildid): Add.
	(pe_bfd_object_p): Use pe_bfd_read_buildid().

gdb/ChangeLog:

2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>

	* build-id.c (build_id_bfd_get): Use bfd_build_id.
	(build_id_verify): Ditto.
	* build-id.h: Ditto.
	(find_separate_debug_file_by_buildid): Ditto.
	* python/py-objfile.c (objfpy_get_build_id)
	(objfpy_build_id_matches, objfpy_lookup_objfile_by_build_id): Ditto.
	* coffread.c (coff_symfile_read): Try
	find_separate_debug_file_by_buildid.

gdb/doc/ChangeLog:

2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>

	* gdb.texinfo (Separate Debug Files): Document that COFF is also
	supported.
---
 bfd/bfd-in2.h           |   9 +++++
 bfd/bfd.c               |   9 +++++
 bfd/elf-bfd.h           |  10 -----
 bfd/elf.c               |  12 +++---
 bfd/libpei.h            |   4 ++
 bfd/peXXigen.c          |   2 +-
 bfd/peicode.h           | 100 ++++++++++++++++++++++++++++++++++++++++++++++--
 gdb/build-id.c          |  23 ++++++-----
 gdb/build-id.h          |   2 +-
 gdb/coffread.c          |   6 ++-
 gdb/doc/gdb.texinfo     |   2 +-
 gdb/python/py-objfile.c |   7 ++--
 12 files changed, 146 insertions(+), 40 deletions(-)

Comments

Eli Zaretskii March 16, 2015, 4:30 p.m. UTC | #1
> From: Jon TURNEY <jon.turney@dronecode.org.uk>
> Cc: Jon TURNEY <jon.turney@dronecode.org.uk>
> Date: Mon, 16 Mar 2015 15:37:10 +0000
> 
> bfd/ChangeLog:
> 
> 2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>
> 
> 	* elf-bfd.h : Remove struct elf_build_id.
> 	* bfd.c : Add struct bfd_build_id.
> 	* bfd-in2.h: Regenerate.
> 	* elf.c (elfobj_grok_gnu_build_id): Update to use bfd_build_id.
> 	* libpei.h: Add protoype and macros for
> 	bfd_XXi_slurp_codeview_record.
> 	* peXXigen.c (_bfd_XXi_slurp_codeview_record): Make public
> 	* peicode.h (pe_bfd_read_buildid): Add.
> 	(pe_bfd_object_p): Use pe_bfd_read_buildid().
> 
> gdb/ChangeLog:
> 
> 2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>
> 
> 	* build-id.c (build_id_bfd_get): Use bfd_build_id.
> 	(build_id_verify): Ditto.
> 	* build-id.h: Ditto.
> 	(find_separate_debug_file_by_buildid): Ditto.
> 	* python/py-objfile.c (objfpy_get_build_id)
> 	(objfpy_build_id_matches, objfpy_lookup_objfile_by_build_id): Ditto.
> 	* coffread.c (coff_symfile_read): Try
> 	find_separate_debug_file_by_buildid.
> 
> gdb/doc/ChangeLog:
> 
> 2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>
> 
> 	* gdb.texinfo (Separate Debug Files): Document that COFF is also
> 	supported.

The gdb.texinfo part is OK, except that AFAIK PE is not the same as
COFF, so I suggest to amend the ChangeLog entry above.

Thanks.
Jon TURNEY March 17, 2015, 12:56 p.m. UTC | #2
On 16/03/2015 16:30, Eli Zaretskii wrote:
[...]
>>
>> gdb/doc/ChangeLog:
>>
>> 2015-03-14  Jon TURNEY  <jon.turney@dronecode.org.uk>
>>
>> 	* gdb.texinfo (Separate Debug Files): Document that COFF is also
>> 	supported.
>
> The gdb.texinfo part is OK, except that AFAIK PE is not the same as
> COFF, so I suggest to amend the ChangeLog entry above.

Yes, this should say PE in the ChangeLog (and subject).
diff mbox

Patch

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 2d2e7ac..5da34b7 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6289,6 +6289,12 @@  enum bfd_plugin_format
     bfd_plugin_no = 2
   };
 
+struct bfd_build_id
+  {
+    size_t size;
+    bfd_byte data[1];
+  };
+
 struct bfd
 {
   /* The filename the application opened the BFD with.  */
@@ -6565,6 +6571,9 @@  struct bfd
      struct objalloc *, but we use void * to avoid requiring the inclusion
      of objalloc.h.  */
   void *memory;
+
+  /* For input BFDs, the build ID, if the object has one. */
+  const struct bfd_build_id *build_id;
 };
 
 /* See note beside bfd_set_section_userdata.  */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 5ae5eca..1869b2c 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -51,6 +51,12 @@  CODE_FRAGMENT
 .    bfd_plugin_no = 2
 .  };
 .
+.struct bfd_build_id
+.  {
+.    size_t size;
+.    bfd_byte data[1];
+.  };
+.
 .struct bfd
 .{
 .  {* The filename the application opened the BFD with.  *}
@@ -327,6 +333,9 @@  CODE_FRAGMENT
 .     struct objalloc *, but we use void * to avoid requiring the inclusion
 .     of objalloc.h.  *}
 .  void *memory;
+.
+.  {* For input BFDs, the build ID, if the object has one. *}
+.  const struct bfd_build_id *build_id;
 .};
 .
 .{* See note beside bfd_set_section_userdata.  *}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 13c32e0..75cbbe3 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1524,13 +1524,6 @@  struct sdt_note
   bfd_byte data[1];
 };
 
-/* NT_GNU_BUILD_ID note type info for input BFDs.  */
-struct elf_build_id
-{
-  size_t size;
-  bfd_byte data[1];
-};
-
 /* tdata information grabbed from an elf core file.  */
 struct core_elf_obj_tdata
 {
@@ -1665,9 +1658,6 @@  struct elf_obj_tdata
   obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
   obj_attribute_list *other_obj_attributes[2];
 
-  /* NT_GNU_BUILD_ID note type.  */
-  struct elf_build_id *build_id;
-
   /* Linked-list containing information about every Systemtap section
      found in the object file.  Each section corresponds to one entry
      in the list.  */
diff --git a/bfd/elf.c b/bfd/elf.c
index 13d4272..6513790 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -8830,18 +8830,18 @@  elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 static bfd_boolean
 elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
 {
-  struct elf_obj_tdata *t;
+  struct bfd_build_id* build_id;
 
   if (note->descsz == 0)
     return FALSE;
 
-  t = elf_tdata (abfd);
-  t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz);
-  if (t->build_id == NULL)
+  build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) - 1 + note->descsz);
+  if (build_id == NULL)
     return FALSE;
 
-  t->build_id->size = note->descsz;
-  memcpy (t->build_id->data, note->descdata, note->descsz);
+  build_id->size = note->descsz;
+  memcpy (build_id->data, note->descdata, note->descsz);
+  abfd->build_id = build_id;
 
   return TRUE;
 }
diff --git a/bfd/libpei.h b/bfd/libpei.h
index d19a3b2..a6f3da0 100644
--- a/bfd/libpei.h
+++ b/bfd/libpei.h
@@ -238,6 +238,7 @@ 
 #define _bfd_XXi_swap_debugdir_in			_bfd_pex64i_swap_debugdir_in
 #define _bfd_XXi_swap_debugdir_out			_bfd_pex64i_swap_debugdir_out
 #define _bfd_XXi_write_codeview_record			_bfd_pex64i_write_codeview_record
+#define _bfd_XXi_slurp_codeview_record			_bfd_pex64i_slurp_codeview_record
 
 #elif defined COFF_WITH_pep
 
@@ -272,6 +273,7 @@ 
 #define _bfd_XXi_swap_debugdir_in			_bfd_pepi_swap_debugdir_in
 #define _bfd_XXi_swap_debugdir_out			_bfd_pepi_swap_debugdir_out
 #define _bfd_XXi_write_codeview_record			_bfd_pepi_write_codeview_record
+#define _bfd_XXi_slurp_codeview_record			_bfd_pepi_slurp_codeview_record
 
 #else /* !COFF_WITH_pep */
 
@@ -306,6 +308,7 @@ 
 #define _bfd_XXi_swap_debugdir_in			_bfd_pei_swap_debugdir_in
 #define _bfd_XXi_swap_debugdir_out			_bfd_pei_swap_debugdir_out
 #define _bfd_XXi_write_codeview_record			_bfd_pei_write_codeview_record
+#define _bfd_XXi_slurp_codeview_record			_bfd_pei_slurp_codeview_record
 
 #endif /* !COFF_WITH_pep */
 
@@ -351,6 +354,7 @@  bfd_boolean _bfd_XXi_final_link_postscript (bfd *, struct coff_final_link_info *
 void        _bfd_XXi_swap_debugdir_in (bfd *, void *, void *);
 unsigned    _bfd_XXi_swap_debugdir_out (bfd *, void *, void *);
 unsigned    _bfd_XXi_write_codeview_record (bfd *, file_ptr, CODEVIEW_INFO *);
+CODEVIEW_INFO * _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo);
 
 /* The following are needed only for ONE of pe or pei, but don't
    otherwise vary; peicode.h fixes up ifdefs but we provide the
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 6aa18ca..4ed9579 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -1140,7 +1140,7 @@  _bfd_XXi_swap_debugdir_out (bfd * abfd, void * inp, void * extp)
   return sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
 }
 
-static CODEVIEW_INFO *
+CODEVIEW_INFO *
 _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo)
 {
   char buffer[256+1];
diff --git a/bfd/peicode.h b/bfd/peicode.h
index e36568a..2209f70 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -1246,6 +1246,87 @@  pe_ILF_object_p (bfd * abfd)
   return abfd->xvec;
 }
 
+static void
+pe_bfd_read_buildid(bfd *abfd)
+{
+  pe_data_type *pe = pe_data (abfd);
+  struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+  asection *section;
+  bfd_byte *data = 0;
+  bfd_size_type dataoff;
+  unsigned int i;
+
+  bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
+  bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
+
+  if (size == 0)
+    return;
+
+  addr += extra->ImageBase;
+
+  /* Search for the section containing the DebugDirectory */
+  for (section = abfd->sections; section != NULL; section = section->next)
+    {
+      if ((addr >= section->vma) && (addr < (section->vma + section->size)))
+        break;
+    }
+
+  if (section == NULL)
+    {
+      return;
+    }
+  else if (!(section->flags & SEC_HAS_CONTENTS))
+    {
+      return;
+    }
+
+  dataoff = addr - section->vma;
+
+  /* Read the whole section. */
+  if (!bfd_malloc_and_get_section (abfd, section, &data))
+    {
+      if (data != NULL)
+	free (data);
+      return;
+    }
+
+  /* Search for a CodeView entry in the DebugDirectory */
+  for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
+    {
+      struct external_IMAGE_DEBUG_DIRECTORY *ext
+	= &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i];
+      struct internal_IMAGE_DEBUG_DIRECTORY idd;
+
+      _bfd_XXi_swap_debugdir_in (abfd, ext, &idd);
+
+      if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
+        {
+          char buffer[256 + 1];
+          CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
+
+          /*
+            The debug entry doesn't have to have to be in a section, in which
+            case AddressOfRawData is 0, so always use PointerToRawData.
+          */
+          if (_bfd_XXi_slurp_codeview_record (abfd,
+                                              (file_ptr) idd.PointerToRawData,
+                                              idd.SizeOfData, cvinfo))
+            {
+              struct bfd_build_id* build_id = bfd_alloc(abfd,
+                         sizeof(struct bfd_build_id) + cvinfo->SignatureLength);
+              if (build_id)
+                {
+                  build_id->size = cvinfo->SignatureLength;
+                  memcpy(build_id->data,  cvinfo->Signature,
+                         cvinfo->SignatureLength);
+                  abfd->build_id = build_id;
+                }
+            }
+          break;
+        }
+    }
+}
+
 static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
@@ -1256,6 +1337,7 @@  pe_bfd_object_p (bfd * abfd)
   struct internal_aouthdr internal_a;
   file_ptr opt_hdr_size;
   file_ptr offset;
+  const bfd_target *result;
 
   /* Detect if this a Microsoft Import Library Format element.  */
   /* First read the beginning of the header.  */
@@ -1349,10 +1431,20 @@  pe_bfd_object_p (bfd * abfd)
 	return NULL;
     }
 
-  return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
-                            (opt_hdr_size != 0
-                             ? &internal_a
-                             : (struct internal_aouthdr *) NULL));
+
+  result = coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
+                               (opt_hdr_size != 0
+                                ? &internal_a
+                                : (struct internal_aouthdr *) NULL));
+
+
+  if (result)
+    {
+      /* Now the whole header has been processed, see if there is a build-id */
+      pe_bfd_read_buildid(abfd);
+    }
+
+  return result;
 }
 
 #define coff_object_p pe_bfd_object_p
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 3a6ebb1..37c311b 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -19,7 +19,6 @@ 
 
 #include "defs.h"
 #include "bfd.h"
-#include "elf-bfd.h"
 #include "gdb_bfd.h"
 #include "build-id.h"
 #include "gdb_vecs.h"
@@ -29,19 +28,19 @@ 
 
 /* See build-id.h.  */
 
-const struct elf_build_id *
+const struct bfd_build_id *
 build_id_bfd_get (bfd *abfd)
 {
-  if (!bfd_check_format (abfd, bfd_object)
-      || bfd_get_flavour (abfd) != bfd_target_elf_flavour
-      /* Although this is ELF_specific, it is safe to do in generic
-	 code because it does not rely on any ELF-specific symbols at
-	 link time, and if the ELF code is not available in BFD, then
-	 ABFD will not have the ELF flavour.  */
-      || elf_tdata (abfd)->build_id == NULL)
+  if (!bfd_check_format (abfd, bfd_object))
     return NULL;
 
-  return elf_tdata (abfd)->build_id;
+  if (abfd->build_id != NULL)
+    {
+      return abfd->build_id;
+    }
+
+  /* No build-id */
+  return NULL;
 }
 
 /* See build-id.h.  */
@@ -49,7 +48,7 @@  build_id_bfd_get (bfd *abfd)
 int
 build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
 {
-  const struct elf_build_id *found;
+  const struct bfd_build_id *found;
   int retval = 0;
 
   found = build_id_bfd_get (abfd);
@@ -138,7 +137,7 @@  build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 char *
 find_separate_debug_file_by_buildid (struct objfile *objfile)
 {
-  const struct elf_build_id *build_id;
+  const struct bfd_build_id *build_id;
 
   build_id = build_id_bfd_get (objfile->obfd);
   if (build_id != NULL)
diff --git a/gdb/build-id.h b/gdb/build-id.h
index f77dda2..bea761b 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -22,7 +22,7 @@ 
 
 /* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
 
-extern const struct elf_build_id *build_id_bfd_get (bfd *abfd);
+extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
 
 /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value.
    Otherwise, issue a warning and return false.  */
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 28f7b18..5700655 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -41,6 +41,7 @@ 
 #include "coff-pe-read.h"
 
 #include "psymtab.h"
+#include "build-id.h"
 
 extern void _initialize_coffread (void);
 
@@ -727,7 +728,10 @@  coff_symfile_read (struct objfile *objfile, int symfile_flags)
     {
       char *debugfile;
 
-      debugfile = find_separate_debug_file_by_debuglink (objfile);
+      debugfile = find_separate_debug_file_by_buildid (objfile);
+
+      if (debugfile == NULL)
+	debugfile = find_separate_debug_file_by_debuglink (objfile);
       make_cleanup (xfree, debugfile);
 
       if (debugfile)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9e71642..2222445 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18022,7 +18022,7 @@  the executable and the debug file came from the same build.
 @item
 The executable contains a @dfn{build ID}, a unique bit string that is
 also present in the corresponding debug info file.  (This is supported
-only on some operating systems, notably those which use the ELF format
+only on some operating systems, when using the ELF or PE file formats
 for binary files and the @sc{gnu} Binutils.)  For more details about
 this feature, see the description of the @option{--build-id}
 command-line option in @ref{Options, , Command Line Options, ld.info,
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 157d200..c0e3f41 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -23,7 +23,6 @@ 
 #include "objfiles.h"
 #include "language.h"
 #include "build-id.h"
-#include "elf-bfd.h"
 #include "symtab.h"
 
 typedef struct
@@ -130,7 +129,7 @@  objfpy_get_build_id (PyObject *self, void *closure)
 {
   objfile_object *obj = (objfile_object *) self;
   struct objfile *objfile = obj->objfile;
-  const struct elf_build_id *build_id = NULL;
+  const struct bfd_build_id *build_id = NULL;
 
   OBJFPY_REQUIRE_VALID (obj);
 
@@ -433,7 +432,7 @@  objfpy_build_id_ok (const char *string)
    It is assumed that objfpy_build_id_ok (string) returns TRUE.  */
 
 static int
-objfpy_build_id_matches (const struct elf_build_id *build_id,
+objfpy_build_id_matches (const struct bfd_build_id *build_id,
 			 const char *string)
 {
   size_t i;
@@ -491,7 +490,7 @@  objfpy_lookup_objfile_by_build_id (const char *build_id)
 
   ALL_OBJFILES (objfile)
     {
-      const struct elf_build_id *obfd_build_id;
+      const struct bfd_build_id *obfd_build_id;
 
       if (objfile->obfd == NULL)
 	continue;