This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ld --build-id
- From: Roland McGrath <roland at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Sun, 1 Jul 2007 15:01:51 -0700 (PDT)
- Subject: [PATCH] ld --build-id
This patch adds a new option to ld for ELF targets, --build-id.
It generates a synthetic ELF note section containing "unique build ID" bits
chosen by ld. See http://fedoraproject.org/wiki/RolandMcGrath/BuildID for
a description of the whole plan motivating this.
This is done as an ld option to be efficient and foolproof to enable for
every compilation (vs some script adding a generated object into the link).
It's done the way it is so it can use no more and no less than the exact
final ELF bits of the output to contribute to selecting a unique ID. This
is the best way to ensure that deterministic styles of ID generation
(i.e. cryptographic hash) will always yield identical results for repeated
builds reproduced precisely.
Ok to commit?
Thanks,
Roland
---
include/elf/
2007-07-01 Roland McGrath <roland@redhat.com>
* common.h (NT_GNU_HWCAP, NT_GNU_BUILD_ID): New macros.
binutils/
* readelf.c (get_gnu_elf_note_type): New function.
(process_note): Use it for "GNU" name.
include/
2007-07-01 Roland McGrath <roland@redhat.com>
* bfdlink.h (struct bfd_link_info): Add member emit_note_gnu_build_id.
bfd/
2007-07-01 Roland McGrath <roland@redhat.com>
* elf-bfd.h (struct elf_obj_tdata): Add members
emit_note_gnu_build_id and note_gnu_build_id_sec.
* elf.c (_bfd_id_note_section_size): New global function.
(read_hex, _bfd_elf_write_build_id_section): New static functions.
(_bfd_elf_write_object_contents): Call _bfd_elf_write_build_id_section
if emit_note_gnu_build_id is set.
* Makefile.am (elf.lo): Update dependencies.
* elf-bfd.h (struct elf_size_info): Add checksum_contents hook.
(bfd_elf32_checksum_contents, bfd_elf64_checksum_contents): Declare.
* elfcode.h (elf_checksum_contents): New macro and function.
(NAME(_bfd_elf,size_info)): Initialize checksum_contents hook.
ld/
2007-07-01 Roland McGrath <roland@redhat.com>
* emultempl/elf32.em (gld${EMULATION_NAME}_add_option): Add --build-id.
(gld${EMULATION_NAME}_handle_option): Handle --build-id.
(gld${EMULATION_NAME}_list_options): List --build-id.
(gld${EMULATION_NAME}_after_open): If --build-id was given,
synthesize a ".note.gnu.build-id" section and cache it in elf_tdata.
* ld.texinfo (Options): Describe --build-id.
* NEWS: Mention --build-id.
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.85
diff -B -b -p -u -r1.85 common.h
--- include/elf/common.h 29 Jun 2007 16:29:16 -0000 1.85
+++ include/elf/common.h 1 Jul 2007 21:43:25 -0000
@@ -413,9 +413,13 @@
#define NT_VERSION 1 /* Contains a version string. */
#define NT_ARCH 2 /* Contains an architecture string. */
-/* Values for GNU .note.ABI-tag notes. Note name is "GNU". */
+/* Values for notes in non-core files using name "GNU". */
#define NT_GNU_ABI_TAG 1
+#define NT_GNU_HWCAP 2 /* Used by ld.so and kernel vDSO. */
+#define NT_GNU_BUILD_ID 3 /* Generated by ld --build-id. */
+
+/* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */
#define GNU_ABI_TAG_LINUX 0
#define GNU_ABI_TAG_HURD 1
#define GNU_ABI_TAG_SOLARIS 2
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.368
diff -B -b -p -u -r1.368 readelf.c
--- binutils/readelf.c 30 Jun 2007 00:03:40 -0000 1.368
+++ binutils/readelf.c 1 Jul 2007 21:43:27 -0000
@@ -9128,6 +9128,27 @@ get_note_type (unsigned e_type)
}
static const char *
+get_gnu_elf_note_type (unsigned e_type)
+{
+ static char buff[64];
+
+ switch (e_type)
+ {
+ case NT_GNU_ABI_TAG:
+ return _("NT_GNU_ABI_TAG (ABI version tag)");
+ case NT_GNU_HWCAP:
+ return _("NT_GNU_HWCAP (DSO-supplied software HWCAP info)");
+ case NT_GNU_BUILD_ID:
+ return _("NT_GNU_BUILD_ID (unique build ID bitstring)");
+ default:
+ break;
+ }
+
+ snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+ return buff;
+}
+
+static const char *
get_netbsd_elfcore_note_type (unsigned e_type)
{
static char buff[64];
@@ -9204,6 +9225,10 @@ process_note (Elf_Internal_Note *pnote)
note type strings. */
nt = get_note_type (pnote->type);
+ else if (const_strneq (pnote->namedata, "GNU"))
+ /* GNU-specific object file notes. */
+ nt = get_gnu_elf_note_type (pnote->type);
+
else if (const_strneq (pnote->namedata, "NetBSD-CORE"))
/* NetBSD-specific core file notes. */
nt = get_netbsd_elfcore_note_type (pnote->type);
Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.68
diff -B -b -p -u -r1.68 bfdlink.h
--- include/bfdlink.h 31 May 2007 15:04:51 -0000 1.68
+++ include/bfdlink.h 1 Jul 2007 21:43:29 -0000
@@ -347,6 +347,9 @@ struct bfd_link_info
--dynamic-list command line options. */
unsigned int dynamic: 1;
+ /* Non-NULL if .note.gnu.build-id section should be created. */
+ char *emit_note_gnu_build_id;
+
/* What to do with unresolved symbols in an object file.
When producing executables the default is GENERATE_ERROR.
When producing shared libraries the default is IGNORE. The
Index: bfd/Makefile.am
===================================================================
RCS file: /cvs/src/src/bfd/Makefile.am,v
retrieving revision 1.200
diff -B -b -p -u -r1.200 Makefile.am
--- bfd/Makefile.am 29 Jun 2007 16:29:15 -0000 1.200
+++ bfd/Makefile.am 1 Jul 2007 21:43:31 -0000
@@ -1298,7 +1298,8 @@ efi-app-ia32.lo: efi-app-ia32.c $(INCDIR
peicode.h libpei.h
elf.lo: elf.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
- $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/libiberty.h
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/libiberty.h \
+ $(INCDIR)/safe-ctype.h $(INCDIR)/md5.h
elf32-am33lin.lo: elf32-am33lin.c $(INCDIR)/filenames.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mn10300.h \
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.234
diff -B -b -p -u -r1.234 elf-bfd.h
--- bfd/elf-bfd.h 29 Jun 2007 16:29:15 -0000 1.234
+++ bfd/elf-bfd.h 1 Jul 2007 21:43:33 -0000
@@ -447,6 +447,8 @@ struct elf_size_info {
(bfd *, const Elf_Internal_Phdr *, unsigned int);
bfd_boolean
(*write_shdrs_and_ehdr) (bfd *);
+ bfd_boolean (*checksum_contents)
+ (bfd * , void (*) (const void *, size_t, void *), void *);
void (*write_relocs)
(bfd *, asection *, void *);
bfd_boolean (*swap_symbol_in)
@@ -1465,6 +1467,10 @@ struct elf_obj_tdata
obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
obj_attribute_list *other_obj_attributes[2];
+
+ /* The .note.gnu.build-id section and --build-id option setting, or NULL. */
+ char *emit_note_gnu_build_id;
+ asection *note_gnu_build_id_sec;
};
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
@@ -1868,6 +1874,8 @@ extern bfd_boolean bfd_elf32_write_shdrs
(bfd *);
extern int bfd_elf32_write_out_phdrs
(bfd *, const Elf_Internal_Phdr *, unsigned int);
+extern bfd_boolean bfd_elf32_checksum_contents
+ (bfd * , void (*) (const void *, size_t, void *), void *);
extern void bfd_elf32_write_relocs
(bfd *, asection *, void *);
extern bfd_boolean bfd_elf32_slurp_reloc_table
@@ -1910,6 +1918,8 @@ extern bfd_boolean bfd_elf64_write_shdrs
(bfd *);
extern int bfd_elf64_write_out_phdrs
(bfd *, const Elf_Internal_Phdr *, unsigned int);
+extern bfd_boolean bfd_elf64_checksum_contents
+ (bfd * , void (*) (const void *, size_t, void *), void *);
extern void bfd_elf64_write_relocs
(bfd *, asection *, void *);
extern bfd_boolean bfd_elf64_slurp_reloc_table
@@ -2035,6 +2045,9 @@ extern int _bfd_elf_obj_attrs_arg_type (
extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
+extern bfd_size_type _bfd_id_note_section_size
+ (bfd *abfd, struct bfd_link_info *link_info);
+
/* Large common section. */
extern asection _bfd_elf_large_com_section;
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.394
diff -B -b -p -u -r1.394 elf.c
--- bfd/elf.c 29 Jun 2007 16:29:15 -0000 1.394
+++ bfd/elf.c 1 Jul 2007 21:43:36 -0000
@@ -40,6 +40,8 @@ SECTION
#define ARCH_SIZE 0
#include "elf-bfd.h"
#include "libiberty.h"
+#include "safe-ctype.h"
+#include "md5.h"
static int elf_sort_sections (const void *, const void *);
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
@@ -5072,6 +5074,149 @@ _bfd_elf_assign_file_positions_for_reloc
elf_tdata (abfd)->next_file_pos = off;
}
+bfd_size_type
+_bfd_id_note_section_size (bfd *abfd, struct bfd_link_info *link_info)
+{
+ const char *style = link_info->emit_note_gnu_build_id;
+ bfd_size_type size;
+
+ abfd = abfd;
+
+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+ size = BFD_ALIGN (size, 4);
+
+ if (!strcmp (style, "md5") || !strcmp (style, "uuid"))
+ size += 128 / 8;
+#if 0 /* libiberty has md5 but not sha1 */
+ else if (!strcmp (style, "sha1"))
+ size += 160 / 8;
+#endif
+ else if (!strncmp (style, "0x", 2))
+ {
+ /* ID is in string form (hex). Convert to bits. */
+ const char *id = style + 2;
+ do
+ {
+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
+ {
+ ++size;
+ id += 2;
+ }
+ else if (*id == '-' || *id == ':')
+ ++id;
+ else
+ {
+ size = 0;
+ break;
+ }
+ } while (*id != '\0');
+ }
+ else
+ size = 0;
+
+ return size;
+}
+
+static unsigned char
+read_hex (const char xdigit)
+{
+ if (ISDIGIT (xdigit))
+ return xdigit - '0';
+ if (ISUPPER (xdigit))
+ return xdigit - 'A' + 0xa;
+ if (ISLOWER (xdigit))
+ return xdigit - 'a' + 0xa;
+ abort ();
+ return 0;
+}
+
+static bfd_boolean
+_bfd_elf_write_build_id_section (bfd *abfd, const char *style)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ asection *asec;
+ Elf_Internal_Shdr *i_shdr;
+ unsigned char *contents, *id_bits;
+ bfd_size_type size;
+ Elf_External_Note *e_note;
+
+ asec = elf_tdata (abfd)->note_gnu_build_id_sec;
+ if (asec->output_section == NULL)
+ {
+ _bfd_error_handler (_(".note.gnu.build-id section missing"));
+ return FALSE;
+ }
+ i_shdr = &elf_section_data (asec->output_section)->this_hdr;
+
+ if (i_shdr->contents == NULL)
+ {
+ BFD_ASSERT (asec->output_offset == 0);
+ i_shdr->contents = bfd_zalloc (abfd, i_shdr->sh_size);
+ if (i_shdr->contents == NULL)
+ return FALSE;
+ }
+ contents = i_shdr->contents + asec->output_offset;
+
+ e_note = (void *) contents;
+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+ size = BFD_ALIGN (size, 4);
+ id_bits = contents + size;
+ size = asec->size - size;
+
+ bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
+ bfd_h_put_32 (abfd, size, &e_note->descsz);
+ bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
+ memcpy (e_note->name, "GNU", sizeof "GNU");
+
+ if (!strcmp (style, "md5"))
+ {
+ struct md5_ctx ctx;
+ md5_init_ctx (&ctx);
+ if (bed->s->checksum_contents (abfd,
+ (void (*) (const void *, size_t, void *))
+ &md5_process_bytes,
+ &ctx))
+ md5_finish_ctx (&ctx, id_bits);
+ else
+ return FALSE;
+ }
+ else if (!strcmp (style, "uuid"))
+ {
+ int n;
+ int fd = open ("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+ n = read (fd, id_bits, size);
+ close (fd);
+ if (n < (int) size)
+ return FALSE;
+ }
+ else if (!strncmp (style, "0x", 2))
+ {
+ /* ID is in string form (hex). Convert to bits. */
+ const char *id = style + 2;
+ size_t n = 0;
+ do
+ {
+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
+ {
+ id_bits[n] = read_hex (*id++) << 4;
+ id_bits[n++] |= read_hex (*id++);
+ }
+ else if (*id == '-' || *id == ':')
+ ++id;
+ else
+ abort (); /* Should have been validated earlier. */
+ } while (*id != '\0');
+ }
+ else
+ abort (); /* Should have been validated earlier. */
+
+ size = i_shdr->sh_size;
+ return (bfd_seek (abfd, i_shdr->sh_offset, SEEK_SET) == 0
+ && bfd_bwrite (i_shdr->contents, size, abfd) == size);
+}
+
bfd_boolean
_bfd_elf_write_object_contents (bfd *abfd)
{
@@ -5080,6 +5225,7 @@ _bfd_elf_write_object_contents (bfd *abf
Elf_Internal_Shdr **i_shdrp;
bfd_boolean failed;
unsigned int count, num_sec;
+ char *id_style;
if (! abfd->output_has_begun
&& ! _bfd_elf_compute_section_file_positions (abfd, NULL))
@@ -5123,7 +5269,15 @@ _bfd_elf_write_object_contents (bfd *abf
(*bed->elf_backend_final_write_processing) (abfd,
elf_tdata (abfd)->linker);
- return bed->s->write_shdrs_and_ehdr (abfd);
+ if (!bed->s->write_shdrs_and_ehdr (abfd))
+ return FALSE;
+
+ /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */
+ id_style = elf_tdata (abfd)->emit_note_gnu_build_id;
+ if (id_style && !_bfd_elf_write_build_id_section (abfd, id_style))
+ return FALSE;
+
+ return TRUE;
}
bfd_boolean
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.82
diff -B -b -p -u -r1.82 elfcode.h
--- bfd/elfcode.h 26 Apr 2007 14:46:57 -0000 1.82
+++ bfd/elfcode.h 1 Jul 2007 21:43:38 -0000
@@ -120,6 +120,7 @@ Foundation, Inc., 51 Franklin Street - F
#define elf_find_section NAME(bfd_elf,find_section)
#define elf_write_shdrs_and_ehdr NAME(bfd_elf,write_shdrs_and_ehdr)
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs)
+#define elf_checksum_contents NAME(bfd_elf,checksum_contents)
#define elf_write_relocs NAME(bfd_elf,write_relocs)
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table)
@@ -1103,6 +1104,53 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
return TRUE;
}
+bfd_boolean
+elf_checksum_contents (bfd *abfd,
+ void (*process) (const void *, size_t, void *),
+ void *arg)
+{
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+ Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
+ Elf_Internal_Phdr *i_phdrp = elf_tdata (abfd)->phdr;
+ unsigned int count, num;
+
+ {
+ Elf_External_Ehdr x_ehdr;
+ Elf_Internal_Ehdr i_ehdr;
+
+ i_ehdr = *i_ehdrp;
+ i_ehdr.e_phoff = i_ehdr.e_shoff = 0;
+ elf_swap_ehdr_out (abfd, &i_ehdr, &x_ehdr);
+ (*process) (&x_ehdr, sizeof x_ehdr, arg);
+ }
+
+ num = i_ehdrp->e_phnum;
+ for (count = 0; count < num; count++)
+ {
+ Elf_External_Phdr x_phdr;
+ elf_swap_phdr_out (abfd, &i_phdrp[count], &x_phdr);
+ (*process) (&x_phdr, sizeof x_phdr, arg);
+ }
+
+ num = elf_numsections (abfd);
+ for (count = 0; count < num; count++)
+ {
+ Elf_Internal_Shdr i_shdr;
+ Elf_External_Shdr x_shdr;
+
+ i_shdr = *i_shdrp[count];
+ i_shdr.sh_offset = 0;
+
+ elf_swap_shdr_out (abfd, &i_shdr, &x_shdr);
+ (*process) (&x_shdr, sizeof x_shdr, arg);
+
+ if (i_shdr.contents)
+ (*process) (i_shdr.contents, i_shdr.sh_size, arg);
+ }
+
+ return TRUE;
+}
+
long
elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
{
@@ -1801,6 +1849,7 @@ const struct elf_size_info NAME(_bfd_elf
ELFCLASS, EV_CURRENT,
elf_write_out_phdrs,
elf_write_shdrs_and_ehdr,
+ elf_checksum_contents,
elf_write_relocs,
elf_swap_symbol_in,
elf_swap_symbol_out,
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.178
diff -B -b -p -u -r1.178 elf32.em
--- ld/emultempl/elf32.em 26 Apr 2007 14:46:59 -0000 1.178
+++ ld/emultempl/elf32.em 1 Jul 2007 21:43:40 -0000
@@ -865,6 +865,45 @@ gld${EMULATION_NAME}_after_open (void)
{
struct bfd_link_needed_list *needed, *l;
+ if (link_info.emit_note_gnu_build_id)
+ {
+ bfd *abfd;
+ asection *s;
+ bfd_size_type size;
+
+ abfd = link_info.input_bfds;
+
+ size = _bfd_id_note_section_size (abfd, &link_info);
+ if (size == 0)
+ {
+ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ else
+ {
+ s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
+ SEC_ALLOC | SEC_LOAD
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED
+ | SEC_READONLY | SEC_DATA);
+ if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
+ {
+ struct elf_obj_tdata *t = elf_tdata (output_bfd);
+ t->emit_note_gnu_build_id = link_info.emit_note_gnu_build_id;
+ t->note_gnu_build_id_sec = s;
+ elf_section_type (s) = SHT_NOTE;
+ s->size = size;
+ }
+ else
+ {
+ einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+ " --build-id ignored.\n");
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ }
+ }
+
if (link_info.eh_frame_hdr
&& ! link_info.traditional_format
&& ! link_info.relocatable)
@@ -1759,6 +1798,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1)
#define OPTION_EXCLUDE_LIBS (OPTION_EH_FRAME_HDR + 1)
#define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_BUILD_ID (OPTION_HASH_STYLE + 1)
static void
gld${EMULATION_NAME}_add_options
@@ -1767,6 +1807,7 @@ gld${EMULATION_NAME}_add_options
{
static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
static const struct option xtra_long[] = {
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
@@ -1797,6 +1838,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
}
+#define DEFAULT_BUILD_ID_STYLE "md5"
+
static bfd_boolean
gld${EMULATION_NAME}_handle_option (int optc)
{
@@ -1805,6 +1848,18 @@ gld${EMULATION_NAME}_handle_option (int
default:
return FALSE;
+ case OPTION_BUILD_ID:
+ if (link_info.emit_note_gnu_build_id != NULL)
+ {
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ if (optarg == NULL)
+ optarg = DEFAULT_BUILD_ID_STYLE;
+ if (strcmp (optarg, "none"))
+ link_info.emit_note_gnu_build_id = xstrdup (optarg);
+ break;
+
EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
@@ -1958,6 +2013,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
static void
gld${EMULATION_NAME}_list_options (FILE * file)
{
+ fprintf (file, _(" --build-id[=STYLE]\tGenerate build ID note\n"));
EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
Index: ld/NEWS
===================================================================
RCS file: /cvs/src/src/ld/NEWS,v
retrieving revision 1.76
diff -B -b -p -u -r1.76 NEWS
--- ld/NEWS 29 Jun 2007 18:44:09 -0000 1.76
+++ ld/NEWS 1 Jul 2007 21:43:42 -0000
@@ -1,4 +1,8 @@
-*- text -*-
+
+* ELF: New --build-id option to generate a unique per-binary identifier
+ embedded in a note section.
+
* Added support for National Semicondutor CompactRISC (ie CR16) target.
* -l:foo now searches the library path for a filename called foo,
@@ -32,7 +36,7 @@
collection.
* ARM: Added --vfp11-denorm-fix option to work around an erratum in current
-VFP11 coprocessors.
+ VFP11 coprocessors.
Changes in 2.17: