This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 4/4] Add ld --build-id support for pe/coff
- From: Jon TURNEY <jon dot turney at dronecode dot org dot uk>
- To: binutils at sourceware dot org
- Cc: Jon TURNEY <jon dot turney at dronecode dot org dot uk>
- Date: Thu, 23 Jan 2014 17:46:09 +0000
- Subject: [PATCH 4/4] Add ld --build-id support for pe/coff
- Authentication-results: sourceware.org; auth=none
- References: <1390499169-5908-1-git-send-email-jon dot turney at dronecode dot org dot uk>
Add ld --build-id option for pe/coff, which adds a .build-id section containing
a CodeView record, pointed to by the debug directory.
Note that the pe/coff build-id is a fixed length of 16 bytes, not a variable
length like an ELF .note.gnu.build-id.
XXX: There is an unfortunate degree of code duplication between 32 and 64 bit
pe/coff variants, but this is hard to avoid given the way the code is
structured. :-(
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
bfd/ChangeLog:
2014-01-20 Jon TURNEY <jon.turney@dronecode.org.uk>
* libcoff-in.h (pe_tdata): Add build-id data.
* libcoff.h: Regenerate.
* coffcode.h (coff_write_object_contents): Run build_id
after_write_object_contents hook.
ld/ChangeLog:
2014-01-20 Jon TURNEY <jon.turney@dronecode.org.uk>
* emultempl/pe.em (gld${EMULATION_NAME}_handle_option):
(pecoff_checksum_contents, write_build_id, setup_build_id)
(gld_${EMULATION_NAME}_after_open): Handle and implement
build-id option.
* emultempl/pep.em: Ditto.
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
---
bfd/coffcode.h | 10 ++-
bfd/libcoff-in.h | 8 +++
bfd/libcoff.h | 8 +++
ld/NEWS | 2 +
ld/emultempl/pe.em | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++-
ld/emultempl/pep.em | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++-
6 files changed, 420 insertions(+), 4 deletions(-)
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 542b5b7..786c114 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -4325,7 +4325,15 @@ coff_write_object_contents (bfd * abfd)
}
#endif
- /* Now write them. */
+#ifdef COFF_WITH_PE
+ /* After object contents are finalized so we can compute a reasonable hash,
+ but before header is written so we can update it to point to debug directory */
+ struct pe_tdata *pe = pe_data(abfd);
+ if (pe->build_id.after_write_object_contents != NULL)
+ (*pe->build_id.after_write_object_contents) (abfd);
+#endif
+
+ /* Now write header. */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
return FALSE;
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 49b5f10..69fc1e0 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -119,6 +119,14 @@ typedef struct pe_tdata
bfd_boolean insert_timestamp;
bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
flagword real_flags;
+
+ /* build-id info. */
+ struct
+ {
+ bfd_boolean (*after_write_object_contents) (bfd *);
+ const char *style;
+ asection *sec;
+ } build_id;
} pe_data_type;
#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 19b6d9c..3f91c93 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -123,6 +123,14 @@ typedef struct pe_tdata
bfd_boolean insert_timestamp;
bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *);
flagword real_flags;
+
+ /* build-id info. */
+ struct
+ {
+ bfd_boolean (*after_write_object_contents) (bfd *);
+ const char *style;
+ asection *sec;
+ } build_id;
} pe_data_type;
#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
diff --git a/ld/NEWS b/ld/NEWS
index c59040e..481ccd6 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,7 @@
-*- text -*-
+* x86/x86_64 pe-coff now supports the --build-id option.
+
* Add support for the Andes NDS32.
Changes in 2.24:
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 5d6da9e..f2e950f 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -66,6 +66,7 @@ fragment <<EOF
#include "ldlex.h"
#include "ldmisc.h"
#include "ldctor.h"
+#include "ldbuildid.h"
#include "coff/internal.h"
/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
@@ -73,9 +74,10 @@ fragment <<EOF
#include "coff/i386.h"
#include "coff/pe.h"
-/* FIXME: This is a BFD internal header file, and we should not be
+/* FIXME: These are BFD internal header files, and we should not be
using it here. */
#include "../bfd/libcoff.h"
+#include "../bfd/libpei.h"
#include "deffile.h"
#include "pe-dll.h"
@@ -131,6 +133,7 @@ static char * thumb_entry_symbol = NULL;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = 0;
static bfd_boolean insert_timestamp = FALSE;
+static const char *emit_build_id;
#ifdef DLL_SUPPORT
static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */
@@ -268,6 +271,7 @@ fragment <<EOF
#define OPTION_TERMINAL_SERVER_AWARE (OPTION_WDM_DRIVER + 1)
/* Determinism. */
#define OPTION_INSERT_TIMESTAMP (OPTION_TERMINAL_SERVER_AWARE + 1)
+#define OPTION_BUILD_ID (OPTION_INSERT_TIMESTAMP + 1)
static void
gld${EMULATION_NAME}_add_options
@@ -346,6 +350,7 @@ gld${EMULATION_NAME}_add_options
{"no-bind", no_argument, NULL, OPTION_NO_BIND},
{"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
{"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
{NULL, no_argument, NULL, 0}
};
@@ -493,6 +498,7 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
fprintf (file, _(" --no-bind Do not bind this image\n"));
fprintf (file, _(" --wdmdriver Driver uses the WDM model\n"));
fprintf (file, _(" --tsaware Image is Terminal Server aware\n"));
+ fprintf (file, _(" --build-id[=STYLE] Generate build ID\n"));
}
@@ -687,6 +693,7 @@ set_pe_stack_heap (char *resname, char *comname)
einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
}
+#define DEFAULT_BUILD_ID_STYLE "md5"
static bfd_boolean
gld${EMULATION_NAME}_handle_option (int optc)
@@ -872,6 +879,17 @@ gld${EMULATION_NAME}_handle_option (int optc)
case OPTION_TERMINAL_SERVER_AWARE:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
break;
+ case OPTION_BUILD_ID:
+ if (emit_build_id != NULL)
+ {
+ free ((char *) emit_build_id);
+ emit_build_id = NULL;
+ }
+ if (optarg == NULL)
+ optarg = DEFAULT_BUILD_ID_STYLE;
+ if (strcmp (optarg, "none"))
+ emit_build_id = xstrdup (optarg);
+ break;
}
/* Set DLLCharacteristics bits */
@@ -1227,6 +1245,163 @@ debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
*found = 1;
}
+static bfd_boolean
+pecoff_checksum_contents(bfd *abfd,
+ void (*process) (const void *, size_t, void *),
+ void *arg)
+{
+ file_ptr filepos = (file_ptr) 0;
+
+ while (1)
+ {
+ unsigned char b;
+ int status;
+
+ if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
+ return 0;
+
+ status = bfd_bread (&b, (bfd_size_type) 1, abfd);
+ if (status < 1)
+ {
+ break;
+ }
+
+ (*process) (&b, 1, arg);
+ filepos += 1;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+write_build_id (bfd *abfd)
+{
+ struct pe_tdata *t = pe_data(abfd);
+ asection *asec;
+ struct bfd_link_order *link_order = NULL;
+ unsigned char *contents;
+ bfd_size_type size;
+
+ /* find the section the .build-id output section has been merged info */
+ for (asec = abfd->sections; asec != NULL; asec = asec->next)
+ {
+ struct bfd_link_order *l = NULL;
+ for (l = asec->map_head.link_order; l != NULL; l = l->next)
+ {
+ if ((l->type == bfd_indirect_link_order))
+ {
+ if (l->u.indirect.section == t->build_id.sec)
+ {
+ link_order = l;
+ break;
+ }
+ }
+ }
+
+ if (link_order)
+ break;
+ }
+
+ if (!link_order)
+ {
+ einfo (_("%P: warning: .build-id section discarded,"
+ " --build-id ignored.\n"));
+ return TRUE;
+ }
+
+ if (t->build_id.sec->contents == NULL)
+ t->build_id.sec->contents = (unsigned char *) xmalloc (t->build_id.sec->size);
+ contents = t->build_id.sec->contents;
+ size = t->build_id.sec->size;
+
+ bfd_size_type build_id_size = compute_build_id_size(t->build_id.style);
+ unsigned char *build_id = xmalloc(build_id_size);
+ generate_build_id(abfd, t->build_id.style, pecoff_checksum_contents, build_id);
+
+ bfd_vma ib = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase;
+
+ /* Construct a debug directory entry which points to an immediately following CodeView record */
+ struct internal_IMAGE_DEBUG_DIRECTORY idd;
+ idd.Characteristics = 0;
+ idd.TimeDateStamp = 0;
+ idd.MajorVersion = 0;
+ idd.MinorVersion = 0;
+ idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW;
+ idd.SizeOfData = sizeof(CV_INFO_PDB70) + 1;
+ idd.AddressOfRawData = asec->vma - ib + link_order->offset + sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+ idd.PointerToRawData = asec->filepos + link_order->offset + sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+
+ struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *)contents;
+ _bfd_XXi_swap_debugdir_out(abfd, &idd, ext);
+
+ /* Write the debug directory enttry */
+ if (bfd_seek (abfd, asec->filepos + link_order->offset, SEEK_SET) != 0)
+ return 0;
+
+ if ((bfd_bwrite (contents, size, abfd) != size))
+ return 0;
+
+ /* construct the CodeView record */
+ CODEVIEW_INFO cvinfo;
+ cvinfo.CVSignature = CVINFO_PDB70_CVSIGNATURE;
+ cvinfo.Age = 1;
+
+ /* zero pad or truncate the generated build_id to fit in the CodeView record */
+ memset(&(cvinfo.Signature), 0, CV_INFO_SIGNATURE_LENGTH);
+ memcpy(&(cvinfo.Signature), build_id, (build_id_size > CV_INFO_SIGNATURE_LENGTH) ? CV_INFO_SIGNATURE_LENGTH : build_id_size);
+
+ free(build_id);
+
+ /* Write the codeview record */
+ if (_bfd_XXi_write_codeview_record(abfd, idd.PointerToRawData, &cvinfo) == 0)
+ return 0;
+
+ /* Record the location of the debug directory in the data directory */
+ pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress = asec->vma - ib + link_order->offset;
+ pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size = sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+
+ return TRUE;
+}
+
+/* Make .build-id section, and set up coff_tdata->build_id. */
+static bfd_boolean
+setup_build_id (bfd *ibfd)
+{
+ asection *s;
+ flagword flags;
+
+ if (!validate_build_id_style (emit_build_id))
+ {
+ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+ return FALSE;
+ }
+
+ flags = (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
+ s = bfd_make_section_anyway_with_flags (ibfd, ".build-id", flags);
+ if (s != NULL)
+ {
+ struct pe_tdata *t = pe_data(link_info.output_bfd);
+ t->build_id.after_write_object_contents = &write_build_id;
+ t->build_id.style = emit_build_id;
+ t->build_id.sec = s;
+
+ /*
+ section is a fixed size:
+ one IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
+ pointing at a CV_INFO_PDB70 record containing the build-id, with a
+ null byte for PdbFileName
+ */
+ s->size = sizeof(struct external_IMAGE_DEBUG_DIRECTORY) + sizeof(CV_INFO_PDB70) + 1;
+
+ return TRUE;
+ }
+
+ einfo ("%P: warning: Cannot create .build-id section,"
+ " --build-id ignored.\n");
+ return FALSE;
+}
+
static void
gld_${EMULATION_NAME}_after_open (void)
{
@@ -1249,6 +1424,26 @@ gld_${EMULATION_NAME}_after_open (void)
}
#endif
+ if (emit_build_id != NULL)
+ {
+ bfd *abfd;
+
+ /* Find a COFF input. */
+ for (abfd = link_info.input_bfds;
+ abfd != (bfd *) NULL; abfd = abfd->link_next)
+ if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ break;
+
+ /* If there are no COFF input files do not try to
+ add a build-id section. */
+ if (abfd == NULL
+ || !setup_build_id (abfd))
+ {
+ free ((char *) emit_build_id);
+ emit_build_id = NULL;
+ }
+ }
+
/* Pass the wacky PE command line options into the output bfd.
FIXME: This should be done via a function, rather than by
including an internal BFD header. */
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index b738800..750c127 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -64,6 +64,7 @@ fragment <<EOF
#include "ldlex.h"
#include "ldmisc.h"
#include "ldctor.h"
+#include "ldbuildid.h"
#include "coff/internal.h"
/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
@@ -71,9 +72,10 @@ fragment <<EOF
#include "coff/x86_64.h"
#include "coff/pe.h"
-/* FIXME: This is a BFD internal header file, and we should not be
+/* FIXME: These are BFD internal header files, and we should not be
using it here. */
#include "../bfd/libcoff.h"
+#include "../bfd/libpei.h"
#undef AOUTSZ
#define AOUTSZ PEPAOUTSZ
@@ -146,6 +148,7 @@ static int support_old_code = 0;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = 0;
static bfd_boolean insert_timestamp = FALSE;
+static const char *emit_build_id;
#ifdef DLL_SUPPORT
static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */
@@ -242,7 +245,8 @@ enum options
OPTION_NO_BIND,
OPTION_WDM_DRIVER,
OPTION_INSERT_TIMESTAMP,
- OPTION_TERMINAL_SERVER_AWARE
+ OPTION_TERMINAL_SERVER_AWARE,
+ OPTION_BUILD_ID
};
static void
@@ -318,6 +322,7 @@ gld${EMULATION_NAME}_add_options
{"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
{"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
{"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
{NULL, no_argument, NULL, 0}
};
@@ -453,6 +458,7 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
fprintf (file, _(" --no-bind Do not bind this image\n"));
fprintf (file, _(" --wdmdriver Driver uses the WDM model\n"));
fprintf (file, _(" --tsaware Image is Terminal Server aware\n"));
+ fprintf (file, _(" --build-id[=STYLE] Generate build ID\n"));
#endif
}
@@ -643,6 +649,7 @@ set_pep_stack_heap (char *resname, char *comname)
einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
}
+#define DEFAULT_BUILD_ID_STYLE "md5"
static bfd_boolean
gld${EMULATION_NAME}_handle_option (int optc)
@@ -816,6 +823,17 @@ gld${EMULATION_NAME}_handle_option (int optc)
case OPTION_TERMINAL_SERVER_AWARE:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
break;
+ case OPTION_BUILD_ID:
+ if (emit_build_id != NULL)
+ {
+ free ((char *) emit_build_id);
+ emit_build_id = NULL;
+ }
+ if (optarg == NULL)
+ optarg = DEFAULT_BUILD_ID_STYLE;
+ if (strcmp (optarg, "none"))
+ emit_build_id = xstrdup (optarg);
+ break;
}
/* Set DLLCharacteristics bits */
@@ -1191,6 +1209,163 @@ debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
*found = 1;
}
+static bfd_boolean
+pecoff_checksum_contents(bfd *abfd,
+ void (*process) (const void *, size_t, void *),
+ void *arg)
+{
+ file_ptr filepos = (file_ptr) 0;
+
+ while (1)
+ {
+ unsigned char b;
+ int status;
+
+ if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
+ return 0;
+
+ status = bfd_bread (&b, (bfd_size_type) 1, abfd);
+ if (status < 1)
+ {
+ break;
+ }
+
+ (*process) (&b, 1, arg);
+ filepos += 1;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+write_build_id (bfd *abfd)
+{
+ struct pe_tdata *t = pe_data(abfd);
+ asection *asec;
+ struct bfd_link_order *link_order = NULL;
+ unsigned char *contents;
+ bfd_size_type size;
+
+ /* find the section the .build-id output section has been merged info */
+ for (asec = abfd->sections; asec != NULL; asec = asec->next)
+ {
+ struct bfd_link_order *l = NULL;
+ for (l = asec->map_head.link_order; l != NULL; l = l->next)
+ {
+ if ((l->type == bfd_indirect_link_order))
+ {
+ if (l->u.indirect.section == t->build_id.sec)
+ {
+ link_order = l;
+ break;
+ }
+ }
+ }
+
+ if (link_order)
+ break;
+ }
+
+ if (!link_order)
+ {
+ einfo (_("%P: warning: .build-id section discarded,"
+ " --build-id ignored.\n"));
+ return TRUE;
+ }
+
+ if (t->build_id.sec->contents == NULL)
+ t->build_id.sec->contents = (unsigned char *) xmalloc (t->build_id.sec->size);
+ contents = t->build_id.sec->contents;
+ size = t->build_id.sec->size;
+
+ bfd_size_type build_id_size = compute_build_id_size(t->build_id.style);
+ unsigned char *build_id = xmalloc(build_id_size);
+ generate_build_id(abfd, t->build_id.style, pecoff_checksum_contents, build_id);
+
+ bfd_vma ib = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase;
+
+ /* Construct a debug directory entry which points to an immediately following CodeView record */
+ struct internal_IMAGE_DEBUG_DIRECTORY idd;
+ idd.Characteristics = 0;
+ idd.TimeDateStamp = 0;
+ idd.MajorVersion = 0;
+ idd.MinorVersion = 0;
+ idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW;
+ idd.SizeOfData = sizeof(CV_INFO_PDB70) + 1;
+ idd.AddressOfRawData = asec->vma - ib + link_order->offset + sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+ idd.PointerToRawData = asec->filepos + link_order->offset + sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+
+ struct external_IMAGE_DEBUG_DIRECTORY *ext = (struct external_IMAGE_DEBUG_DIRECTORY *)contents;
+ _bfd_XXi_swap_debugdir_out(abfd, &idd, ext);
+
+ /* Write the debug directory enttry */
+ if (bfd_seek (abfd, asec->filepos + link_order->offset, SEEK_SET) != 0)
+ return 0;
+
+ if ((bfd_bwrite (contents, size, abfd) != size))
+ return 0;
+
+ /* construct the CodeView record */
+ CODEVIEW_INFO cvinfo;
+ cvinfo.CVSignature = CVINFO_PDB70_CVSIGNATURE;
+ cvinfo.Age = 1;
+
+ /* zero pad or truncate the generated build_id to fit in the CodeView record */
+ memset(&(cvinfo.Signature), 0, CV_INFO_SIGNATURE_LENGTH);
+ memcpy(&(cvinfo.Signature), build_id, (build_id_size > CV_INFO_SIGNATURE_LENGTH) ? CV_INFO_SIGNATURE_LENGTH : build_id_size);
+
+ free(build_id);
+
+ /* Write the codeview record */
+ if (_bfd_XXi_write_codeview_record(abfd, idd.PointerToRawData, &cvinfo) == 0)
+ return 0;
+
+ /* Record the location of the debug directory in the data directory */
+ pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress = asec->vma - ib + link_order->offset;
+ pe_data (link_info.output_bfd)->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size = sizeof(struct external_IMAGE_DEBUG_DIRECTORY);
+
+ return TRUE;
+}
+
+/* Make .build-id section, and set up coff_tdata->build_id. */
+static bfd_boolean
+setup_build_id (bfd *ibfd)
+{
+ asection *s;
+ flagword flags;
+
+ if (!validate_build_id_style (emit_build_id))
+ {
+ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+ return FALSE;
+ }
+
+ flags = (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
+ s = bfd_make_section_anyway_with_flags (ibfd, ".build-id", flags);
+ if (s != NULL)
+ {
+ struct pe_tdata *t = pe_data(link_info.output_bfd);
+ t->build_id.after_write_object_contents = &write_build_id;
+ t->build_id.style = emit_build_id;
+ t->build_id.sec = s;
+
+ /*
+ section is a fixed size:
+ one IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
+ pointing at a CV_INFO_PDB70 record containing the build-id, with a
+ null byte for PdbFileName
+ */
+ s->size = sizeof(struct external_IMAGE_DEBUG_DIRECTORY) + sizeof(CV_INFO_PDB70) + 1;
+
+ return TRUE;
+ }
+
+ einfo ("%P: warning: Cannot create .build-id section,"
+ " --build-id ignored.\n");
+ return FALSE;
+}
+
static void
gld_${EMULATION_NAME}_after_open (void)
{
@@ -1214,6 +1389,26 @@ gld_${EMULATION_NAME}_after_open (void)
}
#endif
+ if (emit_build_id != NULL)
+ {
+ bfd *abfd;
+
+ /* Find a COFF input. */
+ for (abfd = link_info.input_bfds;
+ abfd != (bfd *) NULL; abfd = abfd->link_next)
+ if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ break;
+
+ /* If there are no COFF input files do not try to
+ add a build-id section. */
+ if (abfd == NULL
+ || !setup_build_id (abfd))
+ {
+ free ((char *) emit_build_id);
+ emit_build_id = NULL;
+ }
+ }
+
/* Pass the wacky PE command line options into the output bfd.
FIXME: This should be done via a function, rather than by
including an internal BFD header. */
--
1.8.3.4