From patchwork Mon Mar 16 15:37:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Turney X-Patchwork-Id: 5632 Received: (qmail 87101 invoked by alias); 16 Mar 2015 15:37:42 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 87089 invoked by uid 89); 16 Mar 2015 15:37:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 X-HELO: rgout0503.bt.lon5.cpcloud.co.uk Received: from rgout0503.bt.lon5.cpcloud.co.uk (HELO rgout0503.bt.lon5.cpcloud.co.uk) (65.20.0.224) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 16 Mar 2015 15:37:40 +0000 X-OWM-Source-IP: 31.51.206.246(GB) X-OWM-Env-Sender: jonturney@btinternet.com X-CTCH-RefID: str=0001.0A090203.5506F8C1.0026, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-Junkmail-Premium-Raw: score=27/50, refid=2.7.2:2015.3.12.92119:17:27.888, ip=31.51.206.246, rules=__HAS_FROM, __TO_MALFORMED_2, __TO_NO_NAME, __SUBJ_ALPHA_END, __HAS_MSGID, __SANE_MSGID, __HAS_X_MAILER, __ANY_URI, __URI_NO_WWW, __URI_NO_PATH, BODY_SIZE_10000_PLUS, __MIME_TEXT_ONLY, RDNS_GENERIC_POOLED, __URI_NS, SXL_IP_DYNAMIC[246.206.51.31.fur], HTML_00_01, HTML_00_10, RDNS_SUSP_GENERIC, RDNS_SUSP X-CTCH-Spam: Unknown Received: from localhost.localdomain (31.51.206.246) by rgout05.bt.lon5.cpcloud.co.uk (8.6.122.06) (authenticated as jonturney@btinternet.com) id 5500B92A008A2138; Mon, 16 Mar 2015 15:37:33 +0000 From: Jon TURNEY To: gdb-patches@sourceware.org Cc: Jon TURNEY Subject: [PATCH] Find debug symbols file by buildid for coff file format also Date: Mon, 16 Mar 2015 15:37:10 +0000 Message-Id: <1426520230-18940-1-git-send-email-jon.turney@dronecode.org.uk> bfd/ChangeLog: 2015-03-14 Jon TURNEY * 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 * 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 * 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(-) 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;