Add support for elf properties section.
authorMikhail Kashkarov <m.kashkarov@partner.samsung.com>
Mon, 17 Oct 2016 14:29:43 +0000 (15:29 +0100)
committerMikhail Kashkarov <m.kashkarov@partner.samsung.com>
Thu, 18 Jul 2019 11:22:04 +0000 (14:22 +0300)
This is a set of the following backports/cherry-picks to support
.note.gnu.property section.

- Display unknown notes.  Decode NT_GNU_HWCAP notes.
- Add support for displaying and merging GNU_BUILD_NOTEs.
- Fix snafu parsing GNU_BUILD_NOTEs on ARM and AArch64 architectures.
- Fix reading numeric values from GNU BUILD NOTEs.
- Properly dump NT_GNU_PROPERTY_TYPE_0
- Try harder to find the correct symbol to associate with OPEN GNU BUILD notes.
- Add support for a GNU BUILD note type to record the enum size.
- Update support for GNU BUILD notes so that version notes can contain extra information, and stack protection notes can contain numeric values.
- Add note merging to strip and add code to merge stack size notes.
- Fix shift overflow when parsing an overlarge note value.
- Improve decoding of corrupt/unrecognised gnu build attribute notes.
- Fix off by one error when checking for empty note names.
- Add support for version 2 of the GNU Build Attribute note specification.
- Add test of V2 GNU build attribute notes.
- Always pass a valid section header offset to elf_parse_notes
- Re-apply "elf: Properly compute offsets of note descriptor and next note"
- Work around integer overflows when readelf is checking for corrupt ELF notes when run on a 32-bit host.
- Fix a seg-fault when displaying notes from a prorgam segment.  Check for a NULL string section before attempting compute the name of a separate debug info file.
- Properly handle note sections and segments
- ld: Support ELF GNU program properties
- merge_gnu_build_notes reloc deletion
- Add support for v3 binary annotation notes.
- Fix displaying the value associated a GNU BUILD note that uses an ascii name.
- Combine ,gnu.build.attributes.* sections into one .gnu.build.attributes section during linking.
- Improve readelf's selection of a file start symbol when displaying a gnu build attribute.

Change-Id: I7d828cfcc17eda6dcbfe6967e2f26b4d67238406

SHA's:

1449284bd80db7bb4cbe7fef21e1e8b753135af6
9ef920e933bf2ea228c909cf81636e6d9577e51e
c871dadee1817d4b9f3ba6ee792730c9eccf88e0
79a964dca572024447adf92e50959dc88aa4f27a
1fc87489b40b3100badf184a7c266387bae47def
c799a79d66d09c442d85467986c2e8873f09297c
a8be5506b626a57f84771c5ddfaefabf2d61c017
75d7d2986cf896fac8f0690db68ebc552e0b0339
1d15e434f43bc41a07bc7b0648fcb7e6ccbe8dcc
ddef72cdc10d82ba011a7ff81cafbbd3466acf54
3e6b644558f941d3fe482e15efbc53d8f39ef8b7
b06b2c92c06cf100f259f218337d007ee0b1c884
88305e1b9f4592a2ab129015ce409fcc16613ebb
714da62f64ef5527a22a3e897f7e21f69e442ade
08698b7b46c9c932530dcbcd7e851d27a7d2c503
276da9b31bd6e3eb8d1dd814c867266f59f29093
6ab2c4ed51f9c4243691755e1b1d2149c6a426f4
4dff97b2ce94bbb9c0c16e0e4129060b9a894f13
82ed9683ec099d8205dc499ac84febc975235af6
46bed6796d5821832e8ba373ddb2e7fdc45a109d
ee7e95efb98186c09dc2c39b32263aa15b147bb0
6f156d7a4ad1c245b357dc50f63f3564d397839e
0dd6ae21da832f351a3722d2f8bac187fc3bdfef
7d8a31665739412395f6dd370d2279acd322e78e
8fd75781892c7458702f72b3b9cb1927609716de

Change-Id: I7b201b6c0776c3a7e7e25cdbbb937170da244405

85 files changed:
ChangeLog
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/configure
bfd/configure.ac
bfd/elf-bfd.h
bfd/elf-properties.c [new file with mode: 0644]
bfd/elf.c
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elfxx-target.h
binutils/ChangeLog
binutils/NEWS
binutils/doc/binutils.texi
binutils/objcopy.c
binutils/readelf.c
binutils/testsuite/binutils-all/i386/pr21231a.d [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/pr21231a.s [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/pr21231b.d [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/pr21231b.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-2-32.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-2-32.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-2-64.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-2-64.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-3-32.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-3-32.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-3-64.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-3-64.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-3.32.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-4-32.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-4-32.s [new file with mode: 0644]
binutils/testsuite/binutils-all/note-4-64.d [new file with mode: 0644]
binutils/testsuite/binutils-all/note-4-64.s [new file with mode: 0644]
binutils/testsuite/binutils-all/objcopy.exp
binutils/testsuite/binutils-all/readelf.n
binutils/testsuite/binutils-all/x86-64/pr21231a.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/pr21231a.s [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/pr21231b.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/pr21231b.s [new file with mode: 0644]
gold/ChangeLog
gold/layout.cc
include/ChangeLog
include/elf/common.h
include/elf/external.h
ld/ChangeLog
ld/NEWS
ld/emultempl/elf32.em
ld/scripttempl/elf.sc
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pass.c [new file with mode: 0644]
ld/testsuite/ld-i386/property-1.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-2.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-3.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-4.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-5.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-6.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-6a.c [new file with mode: 0644]
ld/testsuite/ld-i386/property-6b.c [new file with mode: 0644]
ld/testsuite/ld-i386/property-6c.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-7.r [new file with mode: 0644]
ld/testsuite/ld-i386/property-no-copy.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-stack.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-unsorted-1.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-unsorted-2.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-1.S [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-2.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/pass.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-1.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-2.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-3.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-4.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-5.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-6.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-6a.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-6b.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-6c.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-7.r [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-no-copy.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-stack.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-unsorted-1.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-unsorted-2.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-1.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-2.S [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 699c656..6df861f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2018-03-23  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (get_symbol_for_build_attribute): Skip ARM mapping
+       symbols.
+       (print_gnu_build_attribute_description): If no file start symbol
+       could be found, look for one two bytes into the file.
+       * testsuite/binutils-all/note-4-64.s: Set the address of the file
+       start symbol to two bytes into the file.
+       * testsuite/binutils-all/note-4-32.s: Likewise.
+
+2017-03-17  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_name): Fix off by one error
+       printing the value for a build note with an ascii name.
+
 2016-06-28  Walter Lee  <walt@tilera.com>
 
        * configure.ac (tilepro-*-*): Add gdb to noconfigdirs.
index ca7f80a..cafb664 100644 (file)
@@ -1,3 +1,56 @@
+2017-04-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * Makefile.am (BFD32_BACKENDS): Add elf-properties.lo.
+       (BFD32_BACKENDS_CFILES): Add elf-properties.c.
+       * configure.ac (elf): Add elf-properties.lo.
+       * Makefile.in: Regenerated.
+       * configure: Likewise.
+       * elf-bfd.h (elf_property_kind): New.
+       (elf_property): Likewise.
+       (elf_property_list): Likewise.
+       (elf_properties): Likewise.
+       (_bfd_elf_parse_gnu_properties): Likewise.
+       (_bfd_elf_get_property): Likewise.
+       (_bfd_elf_link_setup_gnu_properties): Likewise.
+       (elf_backend_data): Add parse_gnu_properties, merge_gnu_properties
+       and setup_gnu_properties.
+       (elf_obj_tdata): Add properties.
+       * elf-properties.c: New file.
+       * elf32-i386.c (elf_i386_parse_gnu_properties): New.
+       (elf_i386_merge_gnu_properties): Likewise.
+       (elf_backend_parse_gnu_properties): Likewise.
+       (elf_backend_merge_gnu_properties): Likewise.
+       * elf64-x86-64.c (elf_x86_64_parse_gnu_properties): Likewise.
+       (elf_x86_64_merge_gnu_properties): Likewise.
+       (elf_backend_parse_gnu_properties): Likewise.
+       (elf_backend_merge_gnu_properties): Likewise.
+       * elfxx-target.h (elf_backend_merge_gnu_properties): Likewise.
+       (elf_backend_parse_gnu_properties): Likewise.
+       (elf_backend_setup_gnu_properties): Likewise.
+       (elfNN_bed): Add elf_backend_parse_gnu_properties,
+       elf_backend_merge_gnu_properties and
+       elf_backend_setup_gnu_properties.
+
+2017-11-24  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/22444
+       * elf.c (elf_read_notes): Add an argument for note aligment.
+       (elf_parse_notes): Likewise.
+       (_bfd_elf_make_section_from_shdr): Pass section aligment to
+       elf_parse_notes.
+       (bfd_section_from_phdr): Pass segment aligment to elf_read_notes.
+       (elf_parse_notes): Add an argument for note aligment.  Use
+       ELF_NOTE_DESC_OFFSET to get the offset of the note descriptor.
+       Use ELF_NOTE_NEXT_OFFSET to get the offset of the next note
+       entry.
+       (elf_read_notes): Add an argument for note aligment and pass it
+       to elf_parse_notes.
+
+2016-12-02  Gary Benson  <gbenson@redhat.com>
+
+       * elf.c (_bfd_elf_make_section_from_shdr): Pass offset to
+       elf_parse_notes.
+
 2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/20830
index 6720f86..d3aece9 100644 (file)
@@ -315,6 +315,7 @@ BFD32_BACKENDS = \
        elf-m10200.lo \
        elf-m10300.lo \
        elf-nacl.lo \
+       elf-properties.lo \
        elf-strtab.lo \
        elf-vxworks.lo \
        elf.lo \
@@ -507,6 +508,7 @@ BFD32_BACKENDS_CFILES = \
        elf-m10200.c \
        elf-m10300.c \
        elf-nacl.c \
+       elf-properties.c \
        elf-strtab.c \
        elf-vxworks.c \
        elf.c \
index 7283ed9..b2c48ea 100644 (file)
@@ -648,6 +648,7 @@ BFD32_BACKENDS = \
        elf-m10200.lo \
        elf-m10300.lo \
        elf-nacl.lo \
+       elf-properties.lo \
        elf-strtab.lo \
        elf-vxworks.lo \
        elf.lo \
@@ -840,6 +841,7 @@ BFD32_BACKENDS_CFILES = \
        elf-m10200.c \
        elf-m10300.c \
        elf-nacl.c \
+       elf-properties.c \
        elf-strtab.c \
        elf-vxworks.c \
        elf.c \
@@ -1448,6 +1450,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-m10200.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-m10300.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-nacl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-properties.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-strtab.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-vxworks.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf.Plo@am__quote@
index 6e6283d..130678f 100755 (executable)
@@ -14190,7 +14190,7 @@ selarchs="$f"
 # Target backend .o files.
 tb=
 
-elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo
+elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-properties.lo
      elf-eh-frame.lo dwarf1.lo dwarf2.lo"
 coffgen="coffgen.lo dwarf2.lo"
 coff="cofflink.lo $coffgen"
index 669cff7..0ecbf08 100644 (file)
@@ -365,7 +365,7 @@ selarchs="$f"
 # Target backend .o files.
 tb=
 
-elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo
+elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-properties.lo
      elf-eh-frame.lo dwarf1.lo dwarf2.lo"
 coffgen="coffgen.lo dwarf2.lo"
 coff="cofflink.lo $coffgen"
index 163ef35..b2f7bf4 100644 (file)
@@ -754,6 +754,41 @@ typedef asection * (*elf_gc_mark_hook_fn)
   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
    struct elf_link_hash_entry *, Elf_Internal_Sym *);
 
+enum elf_property_kind
+ {
+    /* A new property.  */
+    property_unknown = 0,
+    /* A property ignored by backend.  */
+    property_ignored,
+    /* A corrupt property reported by backend.  */
+    property_corrupt,
+    /* A property should be removed due to property merge.  */
+    property_remove,
+    /* A property which is a number.  */
+    property_number
+ };
+
+typedef struct elf_property
+{
+  unsigned int pr_type;
+  unsigned int pr_datasz;
+  union
+    {
+      /* For property_number, this is a number.  */
+      bfd_vma number;
+      /* Add a new one if elf_property_kind is updated.  */
+    } u;
+  enum elf_property_kind pr_kind;
+} elf_property;
+
+typedef struct elf_property_list
+{
+  struct elf_property_list *next;
+  struct elf_property property;
+} elf_property_list;
+
+struct bfd_elf_section_reloc_data;
+
 struct elf_backend_data
 {
   /* The architecture for this backend.  */
@@ -1360,6 +1395,19 @@ struct elf_backend_data
      or give an error and return FALSE.  */
   bfd_boolean (*obj_attrs_handle_unknown) (bfd *, int);
 
+  /* Parse GNU properties.  Return the property kind.  If the property
+     is corrupt, issue an error message and return property_corrupt.  */
+  enum elf_property_kind (*parse_gnu_properties) (bfd *, unsigned int,
+                                                 bfd_byte *,
+                                                 unsigned int);
+
+  /* Merge GNU properties.  Return TRUE if property is updated.  */
+  bfd_boolean (*merge_gnu_properties) (bfd *, elf_property *,
+                                      elf_property *);
+
+  /* Set up GNU properties.  */
+  void (*setup_gnu_properties) (struct bfd_link_info *);
+
   /* Encoding used for compact EH tables.  */
   int (*compact_eh_encoding) (struct bfd_link_info *);
 
@@ -1761,6 +1809,10 @@ struct elf_obj_tdata
   /* Symbol buffer.  */
   void *symbuf;
 
+  /* List of GNU properties.  Will be updated by setup_gnu_properties
+     after all input GNU properties are merged for output.  */
+  elf_property_list *properties;
+
   obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
   obj_attribute_list *other_obj_attributes[2];
 
@@ -1845,6 +1897,7 @@ struct elf_obj_tdata
   (elf_known_obj_attributes (bfd) [OBJ_ATTR_PROC])
 #define elf_other_obj_attributes_proc(bfd) \
   (elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC])
+#define elf_properties(bfd) (elf_tdata (bfd) -> properties)
 \f
 extern void _bfd_elf_swap_verdef_in
   (bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *);
@@ -2496,6 +2549,13 @@ extern bfd_boolean _bfd_elf_merge_unknown_attribute_low (bfd *, bfd *, int);
 extern bfd_boolean _bfd_elf_merge_unknown_attribute_list (bfd *, bfd *);
 extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec);
 
+extern bfd_boolean _bfd_elf_parse_gnu_properties
+  (bfd *, Elf_Internal_Note *);
+extern elf_property * _bfd_elf_get_property
+  (bfd *, unsigned int, unsigned int);
+extern void _bfd_elf_link_setup_gnu_properties
+  (struct bfd_link_info *);
+
 /* The linker may need to keep track of the number of relocs that it
    decides to copy as dynamic relocs in check_relocs for each symbol.
    This is so that it can later discard them if they are found to be
diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c
new file mode 100644 (file)
index 0000000..a0456f8
--- /dev/null
@@ -0,0 +1,483 @@
+/* ELF program property support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* GNU program property draft is at:
+
+   https://github.com/hjl-tools/linux-abi/wiki/property-draft.pdf
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* Get a property, allocate a new one if needed.  */
+
+elf_property *
+_bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
+{
+  elf_property_list *p, **lastp;
+
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    {
+      /* Never should happen.  */
+      abort ();
+    }
+
+  /* Keep the property list in order of type.  */
+  lastp = &elf_properties (abfd);
+  for (p = *lastp; p; p = p->next)
+    {
+      /* Reuse the existing entry.  */
+      if (type == p->property.pr_type)
+       {
+         if (datasz > p->property.pr_datasz)
+           {
+             /* This can happen when mixing 32-bit and 64-bit objects.  */
+             p->property.pr_datasz = datasz;
+           }
+         return &p->property;
+       }
+      else if (type < p->property.pr_type)
+       break;
+      lastp = &p->next;
+    }
+  p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
+  if (p == NULL)
+    {
+      _bfd_error_handler (_("%B: out of memory in _bfd_elf_get_property"),
+                         abfd);
+      _exit (EXIT_FAILURE);
+    }
+  memset (p, 0, sizeof (*p));
+  p->property.pr_type = type;
+  p->property.pr_datasz = datasz;
+  p->next = *lastp;
+  *lastp = p;
+  return &p->property;
+}
+
+/* Parse GNU properties.  */
+
+bfd_boolean
+_bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
+  bfd_byte *ptr = (bfd_byte *) note->descdata;
+  bfd_byte *ptr_end = ptr + note->descsz;
+
+  if (note->descsz < 8 || (note->descsz % align_size) != 0)
+    {
+bad_size:
+      _bfd_error_handler
+       (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx\n"),
+        abfd, note->type, note->descsz);
+      return FALSE;
+    }
+
+  while (1)
+    {
+      unsigned int type = bfd_h_get_32 (abfd, ptr);
+      unsigned int datasz = bfd_h_get_32 (abfd, ptr + 4);
+      elf_property *prop;
+
+      ptr += 8;
+
+      if ((ptr + datasz) > ptr_end)
+       {
+         _bfd_error_handler
+           (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x\n"),
+            abfd, note->type, type, datasz);
+         /* Clear all properties.  */
+         elf_properties (abfd) = NULL;
+         return FALSE;
+       }
+
+      if (type >= GNU_PROPERTY_LOPROC)
+       {
+         if (type < GNU_PROPERTY_LOUSER && bed->parse_gnu_properties)
+           {
+             enum elf_property_kind kind
+               = bed->parse_gnu_properties (abfd, type, ptr, datasz);
+             if (kind == property_corrupt)
+               {
+                 /* Clear all properties.  */
+                 elf_properties (abfd) = NULL;
+                 return FALSE;
+               }
+             else if (kind != property_ignored)
+               goto next;
+           }
+       }
+      else
+       {
+         switch (type)
+           {
+           case GNU_PROPERTY_STACK_SIZE:
+             if (datasz != align_size)
+               {
+                 _bfd_error_handler
+                   (_("warning: %B: corrupt stack size: 0x%x\n"),
+                    abfd, datasz);
+                 /* Clear all properties.  */
+                 elf_properties (abfd) = NULL;
+                 return FALSE;
+               }
+             prop = _bfd_elf_get_property (abfd, type, datasz);
+             if (datasz == 8)
+               prop->u.number = bfd_h_get_64 (abfd, ptr);
+             else
+               prop->u.number = bfd_h_get_32 (abfd, ptr);
+             prop->pr_kind = property_number;
+             goto next;
+
+           case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+             if (datasz != 0)
+               {
+                 _bfd_error_handler
+                   (_("warning: %B: corrupt no copy on protected size: 0x%x\n"),
+                    abfd, datasz);
+                 /* Clear all properties.  */
+                 elf_properties (abfd) = NULL;
+                 return FALSE;
+               }
+             prop = _bfd_elf_get_property (abfd, type, datasz);
+             prop->pr_kind = property_number;
+             goto next;
+
+           default:
+             break;
+           }
+       }
+
+      _bfd_error_handler
+       (_("warning: %B: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x\n"),
+        abfd, note->type, type);
+
+next:
+      ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
+      if (ptr == ptr_end)
+       break;
+
+      if (ptr > (ptr_end - 8))
+       goto bad_size;
+    }
+
+  return TRUE;
+}
+
+/* Merge GNU property BPROP with APROP.  If APROP isn't NULL, return TRUE
+   if APROP is updated.  Otherwise, return TRUE if BPROP should be merged
+   with ABFD.  */
+
+static bfd_boolean
+elf_merge_gnu_properties (bfd *abfd, elf_property *aprop,
+                         elf_property *bprop)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
+
+  if (bed->merge_gnu_properties != NULL
+      && pr_type >= GNU_PROPERTY_LOPROC
+      && pr_type < GNU_PROPERTY_LOUSER)
+    return bed->merge_gnu_properties (abfd, aprop, bprop);
+
+  switch (pr_type)
+    {
+    case GNU_PROPERTY_STACK_SIZE:
+      if (aprop != NULL && bprop != NULL)
+       {
+         if (bprop->u.number > aprop->u.number)
+           {
+             aprop->u.number = bprop->u.number;
+             return TRUE;
+           }
+         break;
+       }
+      /* FALLTHROUGH */
+
+    case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+      /* Return TRUE if APROP is NULL to indicate that BPROP should
+        be added to ABFD.  */
+      return aprop == NULL;
+
+    default:
+      /* Never should happen.  */
+      abort ();
+    }
+
+  return FALSE;
+}
+
+/* Return the property of TYPE on *LISTP and remove it from *LISTP.
+   Return NULL if not found.  */
+
+static elf_property *
+elf_find_and_remove_property (elf_property_list **listp,
+                             unsigned int type)
+{
+  elf_property_list *list;
+
+  for (list = *listp; list; list = list->next)
+    {
+      if (type == list->property.pr_type)
+       {
+         /* Remove this property.  */
+         *listp = list->next;
+         return &list->property;
+       }
+      else if (type < list->property.pr_type)
+       break;
+      listp = &list->next;
+    }
+
+  return NULL;
+}
+
+/* Merge GNU property list *LISTP with ABFD.  */
+
+static void
+elf_merge_gnu_property_list (bfd *abfd, elf_property_list **listp)
+{
+  elf_property_list *p, **lastp;
+  elf_property *pr;
+
+  /* Merge each GNU property in ABFD with the one on *LISTP.  */
+  lastp = &elf_properties (abfd);
+  for (p = *lastp; p; p = p->next)
+    {
+      pr = elf_find_and_remove_property (listp, p->property.pr_type);
+      /* Pass NULL to elf_merge_gnu_properties for the property which
+        isn't on *LISTP.  */
+      elf_merge_gnu_properties (abfd, &p->property, pr);
+      if (p->property.pr_kind == property_remove)
+       {
+         /* Remove this property.  */
+         *lastp = p->next;
+         continue;
+       }
+      lastp = &p->next;
+    }
+
+  /* Merge the remaining properties on *LISTP with ABFD.  */
+  for (p = *listp; p != NULL; p = p->next)
+    if (elf_merge_gnu_properties (abfd, NULL, &p->property))
+      {
+       pr = _bfd_elf_get_property (abfd, p->property.pr_type,
+                                   p->property.pr_datasz);
+       /* It must be a new property.  */
+       if (pr->pr_kind != property_unknown)
+         abort ();
+       /* Add a new property.  */
+       *pr = p->property;
+      }
+}
+
+/* Set up GNU properties.  */
+
+void
+_bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
+{
+  bfd *abfd, *first_pbfd = NULL;
+  elf_property_list *list;
+  asection *sec;
+  bfd_boolean has_properties = FALSE;
+  const struct elf_backend_data *bed
+    = get_elf_backend_data (info->output_bfd);
+  unsigned int elfclass = bed->s->elfclass;
+  int elf_machine_code = bed->elf_machine_code;
+
+  /* Find the first relocatable ELF input with GNU properties.  */
+  for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+       && bfd_count_sections (abfd) != 0
+       && elf_properties (abfd) != NULL)
+      {
+       has_properties = TRUE;
+
+       /* Ignore GNU properties from ELF objects with different machine
+          code or class.  */
+       if ((elf_machine_code
+            == get_elf_backend_data (abfd)->elf_machine_code)
+           && (elfclass
+               == get_elf_backend_data (abfd)->s->elfclass))
+         {
+           /* Keep .note.gnu.property section in FIRST_PBFD.  */
+           first_pbfd = abfd;
+           break;
+         }
+      }
+
+  /* Do nothing if there is no .note.gnu.property section.  */
+  if (!has_properties)
+    return;
+
+  /* Merge .note.gnu.property sections.  */
+  for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
+    if (abfd != first_pbfd && bfd_count_sections (abfd) != 0)
+      {
+       elf_property_list *null_ptr = NULL;
+       elf_property_list **listp = &null_ptr;
+
+       /* Merge .note.gnu.property section in relocatable ELF input.  */
+       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+         {
+           list = elf_properties (abfd);
+
+           /* Ignore GNU properties from ELF objects with different
+              machine code.  */
+           if (list != NULL
+               && (elf_machine_code
+                   == get_elf_backend_data (abfd)->elf_machine_code))
+             listp = &elf_properties (abfd);
+         }
+       else
+         list = NULL;
+
+       /* Merge properties with FIRST_PBFD.  FIRST_PBFD can be NULL
+          when all properties are from ELF objects with different
+          machine code or class.  */
+       if (first_pbfd != NULL)
+         elf_merge_gnu_property_list (first_pbfd, listp);
+
+       if (list != NULL)
+         {
+           /* Discard .note.gnu.property section in the rest inputs.  */
+           sec = bfd_get_section_by_name (abfd,
+                                          NOTE_GNU_PROPERTY_SECTION_NAME);
+           sec->output_section = bfd_abs_section_ptr;
+         }
+      }
+
+  /* Rewrite .note.gnu.property section so that GNU properties are
+     always sorted by type even if input GNU properties aren't sorted.  */
+  if (first_pbfd != NULL)
+    {
+      unsigned int size;
+      unsigned int descsz;
+      bfd_byte *contents;
+      Elf_External_Note *e_note;
+      unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
+
+      sec = bfd_get_section_by_name (first_pbfd,
+                                    NOTE_GNU_PROPERTY_SECTION_NAME);
+
+      /* Update stack size in .note.gnu.property with -z stack-size=N
+        if N > 0.  */
+      if (info->stacksize > 0)
+       {
+         elf_property *p;
+         bfd_vma stacksize = info->stacksize;
+
+         p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE,
+                                    align_size);
+         if (p->pr_kind == property_unknown)
+           {
+             /* Create GNU_PROPERTY_STACK_SIZE.  */
+             p->u.number = stacksize;
+             p->pr_kind = property_number;
+           }
+         else if (stacksize > p->u.number)
+           p->u.number = stacksize;
+       }
+      else if (elf_properties (first_pbfd) == NULL)
+       {
+         /* Discard .note.gnu.property section if all properties have
+            been removed.  */
+         sec->output_section = bfd_abs_section_ptr;
+         return;
+       }
+
+      /* Compute the section size.  */
+      descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+      descsz = (descsz + 3) & -(unsigned int) 4;
+      size = descsz;
+      for (list = elf_properties (first_pbfd);
+          list != NULL;
+          list = list->next)
+       {
+         /* There are 4 byte type + 4 byte datasz for each property.  */
+         size += 4 + 4 + list->property.pr_datasz;
+         /* Align each property.  */
+         size = (size + (align_size - 1)) & ~(align_size - 1);
+       }
+
+      /* Update .note.gnu.property section now.  */
+      sec->size = size;
+      contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
+
+      e_note = (Elf_External_Note *) contents;
+      bfd_h_put_32 (first_pbfd, sizeof "GNU", &e_note->namesz);
+      bfd_h_put_32 (first_pbfd, size - descsz, &e_note->descsz);
+      bfd_h_put_32 (first_pbfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type);
+      memcpy (e_note->name, "GNU", sizeof "GNU");
+
+      size = descsz;
+      for (list = elf_properties (first_pbfd);
+          list != NULL;
+          list = list->next)
+       {
+         /* There are 4 byte type + 4 byte datasz for each property.  */
+         bfd_h_put_32 (first_pbfd, list->property.pr_type,
+                       contents + size);
+         bfd_h_put_32 (first_pbfd, list->property.pr_datasz,
+                       contents + size + 4);
+         size += 4 + 4;
+
+         /* Write out property value.  */
+         switch (list->property.pr_kind)
+           {
+           case property_number:
+             switch (list->property.pr_datasz)
+               {
+               default:
+                 /* Never should happen.  */
+                 abort ();
+
+               case 0:
+                 break;
+
+               case 4:
+                 bfd_h_put_32 (first_pbfd, list->property.u.number,
+                               contents + size);
+                 break;
+
+               case 8:
+                 bfd_h_put_64 (first_pbfd, list->property.u.number,
+                               contents + size);
+                 break;
+               }
+             break;
+
+           default:
+             /* Never should happen.  */
+             abort ();
+           }
+         size += list->property.pr_datasz;
+
+         /* Align each property.  */
+         size = (size + (align_size - 1)) & ~ (align_size - 1);
+       }
+
+      /* Cache the section contents for elf_link_input_bfd.  */
+      elf_section_data (sec)->this_hdr.contents = contents;
+    }
+}
index cb4de50..e1c9498 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -52,9 +52,10 @@ static int elf_sort_sections (const void *, const void *);
 static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
 static bfd_boolean prep_headers (bfd *);
 static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
-static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
+static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type,
+                                  size_t align) ;
 static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
-                                   file_ptr offset);
+                                   file_ptr offset, size_t align);
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -1042,7 +1043,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
        return FALSE;
 
-      elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
+      elf_parse_notes (abfd, (char *) contents, hdr->sh_size,
+                      hdr->sh_offset, hdr->sh_addralign);
       free (contents);
     }
 
@@ -2942,7 +2944,8 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
     case PT_NOTE:
       if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note"))
        return FALSE;
-      if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
+      if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz,
+                           hdr->p_align))
        return FALSE;
       return TRUE;
 
@@ -9512,6 +9515,9 @@ elfobj_grok_gnu_note (bfd *abfd, Elf_Internal_Note *note)
     default:
       return TRUE;
 
+    case NT_GNU_PROPERTY_TYPE_0:
+      return _bfd_elf_parse_gnu_properties (abfd, note);
+
     case NT_GNU_BUILD_ID:
       return elfobj_grok_gnu_build_id (abfd, note);
     }
@@ -10554,14 +10560,21 @@ elfcore_write_register_note (bfd *abfd,
 }
 
 static bfd_boolean
-elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
+elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
+                size_t align)
 {
   char *p;
 
+  /* NB: CORE PT_NOTE segments may have p_align values of 0 or 1.
+     gABI specifies that PT_NOTE alignment should be aligned to 4
+     bytes for 32-bit objects and to 8 bytes for 64-bit objects.  If
+     align is less than 4, we use 4 byte alignment.   */
+  if (align < 4)
+    align = 4;
+
   p = buf;
   while (p < buf + size)
     {
-      /* FIXME: bad alignment assumption.  */
       Elf_External_Note *xnp = (Elf_External_Note *) p;
       Elf_Internal_Note in;
 
@@ -10576,7 +10589,7 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
        return FALSE;
 
       in.descsz = H_GET_32 (abfd, xnp->descsz);
-      in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
+      in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align);
       in.descpos = offset + (in.descdata - buf);
       if (in.descsz != 0
          && (in.descdata >= buf + size
@@ -10638,14 +10651,15 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
          break;
        }
 
-      p = in.descdata + BFD_ALIGN (in.descsz, 4);
+      p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
     }
 
   return TRUE;
 }
 
 static bfd_boolean
-elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
+elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size,
+               size_t align)
 {
   char *buf;
 
@@ -10664,7 +10678,7 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
   buf[size] = 0;
 
   if (bfd_bread (buf, size, abfd) != size
-      || !elf_parse_notes (abfd, buf, size, offset))
+      || !elf_parse_notes (abfd, buf, size, offset, align))
     {
       free (buf);
       return FALSE;
index 9eeeb37..b1d76f1 100644 (file)
@@ -6131,6 +6131,78 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
   return _bfd_elf_hash_symbol (h);
 }
 
+/* Parse i386 GNU properties.  */
+
+static enum elf_property_kind
+elf_i386_parse_gnu_properties (bfd *abfd, unsigned int type,
+                              bfd_byte *ptr, unsigned int datasz)
+{
+  elf_property *prop;
+
+  switch (type)
+    {
+    case GNU_PROPERTY_X86_ISA_1_USED:
+    case GNU_PROPERTY_X86_ISA_1_NEEDED:
+      if (datasz != 4)
+       {
+         _bfd_error_handler
+           ((type == GNU_PROPERTY_X86_ISA_1_USED
+             ? _("error: %B: <corrupt x86 ISA used size: 0x%x>\n")
+             : _("error: %B: <corrupt x86 ISA needed size: 0x%x>\n")),
+            abfd, datasz);
+         return property_corrupt;
+       }
+      prop = _bfd_elf_get_property (abfd, type, datasz);
+      prop->u.number = bfd_h_get_32 (abfd, ptr);
+      prop->pr_kind = property_number;
+      break;
+
+    default:
+      return property_ignored;
+    }
+
+  return property_number;
+}
+
+/* Merge i386 GNU property BPROP with APROP.  If APROP isn't NULL,
+   return TRUE if APROP is updated.  Otherwise, return TRUE if BPROP
+   should be merged with ABFD.  */
+
+static bfd_boolean
+elf_i386_merge_gnu_properties (bfd *abfd ATTRIBUTE_UNUSED,
+                              elf_property *aprop,
+                              elf_property *bprop)
+{
+  unsigned int number;
+  bfd_boolean updated = FALSE;
+  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
+
+  switch (pr_type)
+    {
+    case GNU_PROPERTY_X86_ISA_1_USED:
+    case GNU_PROPERTY_X86_ISA_1_NEEDED:
+      if (aprop != NULL && bprop != NULL)
+       {
+         number = aprop->u.number;
+         aprop->u.number = number | bprop->u.number;
+         updated = number != (unsigned int) aprop->u.number;
+       }
+      else
+       {
+         /* Return TRUE if APROP is NULL to indicate that BPROP should
+            be added to ABFD.  */
+         updated = aprop == NULL;
+       }
+      break;
+
+    default:
+      /* Never should happen.  */
+      abort ();
+    }
+
+  return updated;
+}
+
 #define TARGET_LITTLE_SYM              i386_elf32_vec
 #define TARGET_LITTLE_NAME             "elf32-i386"
 #define ELF_ARCH                       bfd_arch_i386
@@ -6180,6 +6252,8 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_hash_symbol                      elf_i386_hash_symbol
 #define elf_backend_fixup_symbol             elf_i386_fixup_symbol
+#define elf_backend_parse_gnu_properties      elf_i386_parse_gnu_properties
+#define elf_backend_merge_gnu_properties      elf_i386_merge_gnu_properties
 
 #include "elf32-target.h"
 
index 1b80c31..74098e9 100644 (file)
@@ -6792,8 +6792,80 @@ elf_x86_64_relocs_compatible (const bfd_target *input,
          && _bfd_elf_relocs_compatible (input, output));
 }
 
+/* Parse x86-64 GNU properties.  */
+
+static enum elf_property_kind
+elf_x86_64_parse_gnu_properties (bfd *abfd, unsigned int type,
+                                bfd_byte *ptr, unsigned int datasz)
+{
+  elf_property *prop;
+
+  switch (type)
+    {
+    case GNU_PROPERTY_X86_ISA_1_USED:
+    case GNU_PROPERTY_X86_ISA_1_NEEDED:
+      if (datasz != 4)
+       {
+         _bfd_error_handler
+           ((type == GNU_PROPERTY_X86_ISA_1_USED
+             ? _("error: %B: <corrupt x86 ISA used size: 0x%x>\n")
+             : _("error: %B: <corrupt x86 ISA needed size: 0x%x>\n")),
+            abfd, datasz);
+         return property_corrupt;
+       }
+      prop = _bfd_elf_get_property (abfd, type, datasz);
+      prop->u.number = bfd_h_get_32 (abfd, ptr);
+      prop->pr_kind = property_number;
+      break;
+
+    default:
+      return property_ignored;
+    }
+
+  return property_number;
+}
+
+/* Merge x86-64 GNU property BPROP with APROP.  If APROP isn't NULL,
+   return TRUE if APROP is updated.  Otherwise, return TRUE if BPROP
+   should be merged with ABFD.  */
+
+static bfd_boolean
+elf_x86_64_merge_gnu_properties (bfd *abfd ATTRIBUTE_UNUSED,
+                                elf_property *aprop,
+                                elf_property *bprop)
+{
+  unsigned int number;
+  bfd_boolean updated = FALSE;
+  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
+
+  switch (pr_type)
+    {
+    case GNU_PROPERTY_X86_ISA_1_USED:
+    case GNU_PROPERTY_X86_ISA_1_NEEDED:
+      if (aprop != NULL && bprop != NULL)
+       {
+         number = aprop->u.number;
+         aprop->u.number = number | bprop->u.number;
+         updated = number != (unsigned int) aprop->u.number;
+       }
+      else
+       {
+         /* Return TRUE if APROP is NULL to indicate that BPROP should
+            be added to ABFD.  */
+         updated = aprop == NULL;
+       }
+      break;
+
+    default:
+      /* Never should happen.  */
+      abort ();
+    }
+
+  return updated;
+}
+
 static const struct bfd_elf_special_section
-  elf_x86_64_special_sections[]=
+elf_x86_64_special_sections[]=
 {
   { STRING_COMMA_LEN (".gnu.linkonce.lb"), -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
   { STRING_COMMA_LEN (".gnu.linkonce.lr"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
@@ -6882,6 +6954,10 @@ static const struct bfd_elf_special_section
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_fixup_symbol \
   elf_x86_64_fixup_symbol
+#define elf_backend_parse_gnu_properties \
+  elf_x86_64_parse_gnu_properties
+#define elf_backend_merge_gnu_properties \
+ elf_x86_64_merge_gnu_properties
 
 #include "elf64-target.h"
 
index 97aa5e6..b69284f 100644 (file)
 #ifndef elf_backend_obj_attrs_handle_unknown
 #define elf_backend_obj_attrs_handle_unknown   NULL
 #endif
+#ifndef elf_backend_parse_gnu_properties
+#define elf_backend_parse_gnu_properties       NULL
+#endif
+#ifndef elf_backend_merge_gnu_properties
+#define elf_backend_merge_gnu_properties       NULL
+#endif
+#ifndef elf_backend_setup_gnu_properties
+#define elf_backend_setup_gnu_properties       _bfd_elf_link_setup_gnu_properties
+#endif
 #ifndef elf_backend_static_tls_alignment
 #define elf_backend_static_tls_alignment       1
 #endif
@@ -815,6 +824,9 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_obj_attrs_section_type,
   elf_backend_obj_attrs_order,
   elf_backend_obj_attrs_handle_unknown,
+  elf_backend_parse_gnu_properties,
+  elf_backend_merge_gnu_properties,
+  elf_backend_setup_gnu_properties,
   elf_backend_compact_eh_encoding,
   elf_backend_cant_unwind_opcode,
   elf_backend_static_tls_alignment,
index edfdc02..8c852bd 100644 (file)
@@ -1,3 +1,230 @@
+2018-01-03  Nick Clifton  <nickc@redhat.com>
+
+       * objcopy.c (objcopy_internal_note): New structure.
+       (gap_exists): New function.
+       (is_open_note): New function.
+       (is_func_note): New function.
+       (is_64bit): New function.
+       (merge_gnu_build_notes): Handle v3 notes.  Do not merge
+       if there are relocations against the notes.
+       * readelf.c (get_note_type): Use short names for build attribute
+       notes.
+       (print_symbol_for_build_attribute): Rename to
+       get_symbol_for_build_attribute.  Returns the found symbol rather
+       than printing it.
+       (print_gnu_build_attribute_description): Maintain address ranges
+       for function notes as well as global notes.  Handle v3 notes.
+       (print_gnu_build_attribute_name): Use more space for printing the
+       name in wide mode.
+       * testsuite/binutils-all/note-2-32.s: Use .dc.l instead of .word.
+       Eliminate symbol references in order to remove the need for
+       relocations.
+       * testsuite/binutils-all/note-2-64.s: Likewise.
+       * testsuite/binutils-all/note-3-32.s: Add a size to the note_1
+       symbol.
+       * testsuite/binutils-all/note-3-64.s: Likewise.
+       * testsuite/binutils-all/mips/mips-note-2r-n32.d: Update expected
+       output.
+       * testsuite/binutils-all/mips/mips-note-2r-n64.d: Likewise.
+       * testsuite/binutils-all/mips/mips-note-2r.d: Likewise.
+       * testsuite/binutils-all/note-2-32.d: Likewise.
+       * testsuite/binutils-all/note-2-64.d: Likewise.
+       * testsuite/binutils-all/note-3-32.d: Likewise.
+       * testsuite/binutils-all/note-3-64.d: Likewise.
+       * testsuite/binutils-all/note-4-64.s: New test.  Checks v3 notes.
+       * testsuite/binutils-all/note-4-32.s: New test.
+       * testsuite/binutils-all/note-4-64.d: New test result file.
+       * testsuite/binutils-all/note-4-32.d: New test result file.
+
+2017-05-01  Alan Modra  <amodra@gmail.com>
+
+       * objcopy.c (merge_gnu_build_notes): Correct code deleting
+       relocs.
+
+2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/22490
+       * readelf.c (process_notes_at): Add an argument for note
+       alignment.  If note alignment is less than 4, use 4 byte
+       alignment.  Otherwise, skip notes if alignment isn't 4 nor
+       8 bytes.
+       (process_corefile_note_segments): Pass segment alignment to
+       process_notes_at.
+       (process_note_sections): Pass section alignment to
+       process_notes_at.
+       (process_object): Call load_separate_debug_file only if
+       e_shstrndx != SHN_UNDEF.
+
+2017-11-27  Nick Clifton  <nickc@redhat.com>
+
+       PR 22490
+       * readelf.c (dump_section_as_bytes): Check for a NULL string
+       section pointer.
+       (process_notes_at): Compute the alignment to use if displaying
+       notes from a segment.
+
+2017-11-02  Mingi Cho  <mgcho.minic@gmail.com>
+
+       PR 22384
+       * readelf.c (print_gnu_property_note): Improve overflow checks so
+       that they will work on a 32-bit host.
+
+2017-11-24  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/22444
+       * readelf.c (process_notes_at): Use ELF_NOTE_DESC_OFFSET to get
+       the offset of the note descriptor.  Use ELF_NOTE_NEXT_OFFSET to
+       get the offset of the next note entry.
+
+2017-08-17  Nick Clifton  <nickc@redhat.com>
+
+       * testsuite/binutils-all/note-3-64.s: New test.  Checks assembly
+       and decoding of version2 GNU build attribute notes.
+       * testsuite/binutils-all/note-3-32.s: New test.  32-bit version of
+       the above test.
+       * testsuite/binutils-all/note-3-64.d: New test driver.
+       * testsuite/binutils-all/note-3-32.d: New test driver.
+       * testsuite/binutils-all/objcopy.exp: Run the new test.
+       * readelf.c (is_64bit_abs_reloc): Add R_SPARC_64.
+
+2017-06-28  Nick Clifton  <nickc@redhat.com>
+
+       * objcopy.c (merge_gnu_build_notes): Add support for version 2 notes.
+       * readelf.c (print_gnu_build_attribute_name): Likewise.
+
+2017-04-28  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/21439
+       * readelf.c (print_gnu_build_attribute_name): Allow for an empty
+       name field.
+
+2017-04-26  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (process_section_headers): Warn about overlarge
+       sections.
+       (print_gnu_build_attribute_name): Print the number of unrecognised
+       note types.  Fix formatting in the presence of errors.
+       (testsuite/binutils-all/note-2-32.s): Fix encoding of numeric notes.
+       (testsuite/binutils-all/note-2-64.s): Likewise.
+
+2017-04-21  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/21378
+       * readelf.c (print_gnu_build_attribute_name): Check for an
+       overlarge name field.
+
+2017-04-13  Nick Clifton  <nickc@redhat.com>
+
+       * objcopy.c: Add --no-merge-notes option to disable note merging.
+       Add --[no-]merge-notes option to strip, and enable it by default.
+       (num_bytes): New function.
+       (merge_gnu_build_notes): Add code to merge stack size notes.
+       * binutils.texi: Update strip and objcopy documentation.
+       * readelf.c (print_gnu_build_attribute_name): Use defined
+       constants for note types.
+
+2017-03-21  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_name): Allow stack
+       protection notes to contain numeric values.  Use a colon rather
+       than a space to separate a string name from its values.  Decode
+       the numeric value of a stack protection note.
+       * objcopy.c (merge_gnu_build_notes): Allow version notes to
+       contain extra text after the protocol version number.
+
+2017-03-16  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_name): Add support for
+       GNU_BUILD_ATTRIBUTE_SHORT_ENUM.
+
+2017-03-14  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_description): Move symbol
+       printing code to...
+       (print_symbol_for_build_attribute): New function.  ...here.
+       Add to find the best symbol to associate with an OPEN note.
+       Add code to cache the symbol table and string table, so that they
+       are not loaded every time a note is displayed.
+       * testsuite/binutils-all/note-2-32.s: Add a function symbol.
+       * testsuite/binutils-all/note-2-64.s: Likewise.
+       * testsuite/binutils-all/note-2-32.d: Update expected note output.
+       * testsuite/binutils-all/note-2-64.d: Likewise.
+
+2017-03-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/21231
+       * readelf.c (decode_x86_isa): Change argument to unsigned int.
+       (print_gnu_property_note): Retrieve property type and datasz as
+       4-byte integer.  Consolidate property datasz check.  Check
+       GNU_PROPERTY_LOPROC and GNU_PROPERTY_LOUSER.
+       * testsuite/binutils-all/i386/pr21231a.d: New file.
+       * testsuite/binutils-all/i386/pr21231a.s: Likewise.
+       * testsuite/binutils-all/i386/pr21231b.d: Likewise.
+       * testsuite/binutils-all/i386/pr21231b.s: Likewise.
+       * testsuite/binutils-all/x86-64/pr21231a.d: Likewise.
+       * testsuite/binutils-all/x86-64/pr21231a.s: Likewise.
+       * testsuite/binutils-all/x86-64/pr21231b.d: Likewise.
+       * testsuite/binutils-all/x86-64/pr21231b.s: Likewise.
+
+2017-03-06  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_name): Read byte values
+       from the name string as unsigned bytes.
+       (process_notes_at): Use memcpy to copy an unterminated name
+       string.
+
+2017-03-02  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (print_gnu_build_attribute_description): Use global
+       symbols for OPEN attributes if at all possible.
+
+2017-03-01  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (get_note_type): Add support for GNU_BUILD_NOTEs.
+       (get_gnu_elf_note_type): Add support for GNU_PROPERTY_NOTEs.
+       (decode_x86_isa): New function.
+       (print_gnu_property_note): New function.
+       (print_gnu_note): Handle GNU_PROPERTY_NOTEs.
+       (print_gnu_build_attribute_description): New function.
+       (print_gnu_build_attribute_name): New function.
+       (process_note): Add support for GNU_BUILD_NOTEs.
+       * objcopy.c (--merge-notes): New command line option.
+       (copy_options): Add merge-notes.
+       (copy_usage): Likewise.
+       (is_merge_note_section): New function.
+       (merge_gnu_build_notes): New function.
+       (copy_object): Merge note sections if asked to do so.
+       (skip_section): Add skip_copy parameter.  Add support for skipping
+       merged note sections.
+       (copy_relocations_in_section): Update call to skip_section.
+       (copy_section): Likewise.
+       (copy_main): Add support for merge-notes option.
+       * doc/binutils.texi: Document the new option to objcopy.
+       * NEWS: Mention the new feature.
+       * testsuite/binutils-all/note-2-32.d: New test.  Checks note
+       merging on 32-bit targets.
+       * testsuite/binutils-all/note-2-32.s: New test source file.
+       * testsuite/binutils-all/note-2-64.d: New test.  Like note-2-32.d
+       but for 64-bit targets.
+       * testsuite/binutils-all/note-2-64.s: New test source file.
+       * testsuite/binutils-all/objcopy.exp: Run the new test.
+
+2016-10-17  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (apply_relocations): Fail if the symbol table section
+       linked to by the reloc section does not have either the SHT_SYMTAB
+       or SHT_DYNSYM type.
+       (print_gnu_note): Decode the contents of NT_GNU_HWCAP notes.
+       Print the contents of unknown note types.
+       (process_note): Add the file and section to the parameter list.
+       Use print_symbol to display the note name.
+       Display the contents of unknown note types.
+       (process_corefile_note_segment): Rename to process_notes_at.
+       Add section parameter.  Apply relocations to the notes when
+       loading from a section.  Display section name when processing
+       notes in a section.
+       * testsuite/binutils-all/readelf.n: Update expected output.
+
 2017-04-03  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21343
index 5bc6888..9431b5f 100644 (file)
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add --merge-notes options to objcopy to reduce the size of notes in
+  a binary file by merging and deleting redundant notes.
+
 Changes in 2.27:
 
 * Add a configure option, --enable-64-bit-archive, to force use of a
index 5a004a3..65f43e4 100644 (file)
@@ -1131,6 +1131,8 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
         [@option{--compress-debug-sections}]
         [@option{--decompress-debug-sections}]
         [@option{--elf-stt-common=@var{val}}]
+        [@option{--merge-notes}]
+        [@option{--no-merge-notes}]
         [@option{-v}|@option{--verbose}]
         [@option{-V}|@option{--version}]
         [@option{--help}] [@option{--info}]
@@ -1894,6 +1896,11 @@ converted to the @code{STT_COMMON} or @code{STT_OBJECT} type.
 @code{STT_COMMON}. @option{--elf-stt-common=no} converts common symbol
 type to @code{STT_OBJECT}.
 
+@item --merge-notes
+@itemx --no-merge-notes
+For ELF files, attempt (or do not attempt) to reduce the size of any
+SHT_NOTE type sections by removing duplicate notes.
+
 @item -V
 @itemx --version
 Show the version number of @command{objcopy}.
@@ -2959,7 +2966,8 @@ strip [@option{-F} @var{bfdname} |@option{--target=}@var{bfdname}]
       [@option{-s}|@option{--strip-all}]
       [@option{-S}|@option{-g}|@option{-d}|@option{--strip-debug}]
       [@option{--strip-dwo}]
-      [@option{-K} @var{symbolname} |@option{--keep-symbol=}@var{symbolname}]
+      [@option{-K} @var{symbolname}|@option{--keep-symbol=}@var{symbolname}]
+      [@option{-M}|@option{--merge-notes}][@option{--no-merge-notes}]
       [@option{-N} @var{symbolname} |@option{--strip-symbol=}@var{symbolname}]
       [@option{-w}|@option{--wildcard}]
       [@option{-x}|@option{--discard-all}] [@option{-X} |@option{--discard-locals}]
@@ -3045,6 +3053,13 @@ Remove all symbols that are not needed for relocation processing.
 When stripping symbols, keep symbol @var{symbolname} even if it would
 normally be stripped.  This option may be given more than once.
 
+@item -M
+@itemx --merge-notes
+@itemx --no-merge-notes
+For ELF files, attempt (or do not attempt) to reduce the size of any
+SHT_NOTE type sections by removing duplicate notes.  The default is to
+attempt this reduction.
+
 @item -N @var{symbolname}
 @itemx --strip-symbol=@var{symbolname}
 Remove symbol @var{symbolname} from the source file. This option may be
index 4bb625a..b8b86ef 100644 (file)
@@ -31,6 +31,7 @@
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
+#include "safe-ctype.h"
 
 /* FIXME: See bfd/peXXigen.c for why we include an architecture specific
    header in generic PE code.  */
@@ -95,7 +96,11 @@ static int copy_width = 1;
 static bfd_boolean verbose;            /* Print file and target names.  */
 static bfd_boolean preserve_dates;     /* Preserve input file timestamp.  */
 static int deterministic = -1;         /* Enable deterministic archives.  */
-static int status = 0;         /* Exit status.  */
+static int status = 0;                 /* Exit status.  */
+
+static bfd_boolean    merge_notes = FALSE;     /* Merge note sections.  */
+static bfd_byte *     merged_notes = NULL;     /* Contents on note section undergoing a merge.  */
+static bfd_size_type  merged_size = 0;         /* New, smaller size of the merged note section.  */
 
 enum strip_action
 {
@@ -315,6 +320,8 @@ enum command_line_switch
   OPTION_LOCALIZE_HIDDEN,
   OPTION_LOCALIZE_SYMBOLS,
   OPTION_LONG_SECTION_NAMES,
+  OPTION_MERGE_NOTES,
+  OPTION_NO_MERGE_NOTES,
   OPTION_NO_CHANGE_WARNINGS,
   OPTION_ONLY_KEEP_DEBUG,
   OPTION_PAD_TO,
@@ -361,6 +368,8 @@ static struct option strip_options[] =
   {"input-target", required_argument, 0, 'I'},
   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
   {"keep-symbol", required_argument, 0, 'K'},
+  {"merge-notes", no_argument, 0, 'M'},
+  {"no-merge-notes", no_argument, 0, OPTION_NO_MERGE_NOTES},
   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
   {"output-file", required_argument, 0, 'o'},
   {"output-format", required_argument, 0, 'O'},        /* Obsolete */
@@ -434,6 +443,8 @@ static struct option copy_options[] =
   {"localize-symbol", required_argument, 0, 'L'},
   {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
   {"long-section-names", required_argument, 0, OPTION_LONG_SECTION_NAMES},
+  {"merge-notes", no_argument, 0, 'M'},
+  {"no-merge-notes", no_argument, 0, OPTION_NO_MERGE_NOTES},
   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
   {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
@@ -630,6 +641,8 @@ copy_usage (FILE *stream, int exit_status)
      --decompress-debug-sections   Decompress DWARF debug sections using zlib\n\
      --elf-stt-common=[yes|no]     Generate ELF common symbols with STT_COMMON\n\
                                      type\n\
+  -M  --merge-notes                Remove redundant entries in note sections\n\
+      --no-merge-notes             Do not attempt to remove redundant notes (default)\n\
   -v --verbose                     List all object files modified\n\
   @<file>                          Read options from <file>\n\
   -V --version                     Display this program's version number\n\
@@ -673,6 +686,8 @@ strip_usage (FILE *stream, int exit_status)
      --strip-dwo                   Remove all DWO sections\n\
      --strip-unneeded              Remove all symbols not needed by relocations\n\
      --only-keep-debug             Strip everything but the debug information\n\
+  -M  --merge-notes                Remove redundant entries in note sections (default)\n\
+      --no-merge-notes             Do not attempt to remove redundant notes\n\
   -N --strip-symbol=<name>         Do not copy symbol <name>\n\
   -K --keep-symbol=<name>          Do not strip symbol <name>\n\
      --keep-file-symbols           Do not strip file symbol(s)\n\
@@ -1179,6 +1194,20 @@ is_update_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
   return FALSE;
 }
 
+static bfd_boolean
+is_merged_note_section (bfd * abfd, asection * sec)
+{
+  if (merge_notes
+      && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && elf_section_data (sec)->this_hdr.sh_type == SHT_NOTE
+      /* FIXME: We currently only support merging GNU_BUILD_NOTEs.
+        We should add support for more note types.  */
+      && elf_section_data (sec)->this_hdr.sh_flags & SHF_GNU_BUILD_NOTE)
+    return TRUE;
+
+  return FALSE;
+}
+
 /* See if a non-group section is being removed.  */
 
 static bfd_boolean
@@ -1796,6 +1825,517 @@ copy_unknown_object (bfd *ibfd, bfd *obfd)
   return TRUE;
 }
 
+/* Returns the number of bytes needed to store VAL.  */
+
+static inline unsigned int
+num_bytes (unsigned long val)
+{
+  unsigned int count = 0;
+
+  /* FIXME: There must be a faster way to do this.  */
+  while (val)
+    {
+      count ++;
+      val >>= 8;
+    }
+  return count;
+}
+
+typedef struct objcopy_internal_note
+{
+  Elf_Internal_Note  note;
+  bfd_vma            start;
+  bfd_vma            end;
+  bfd_boolean        modified;
+} objcopy_internal_note;
+  
+/* Returns TRUE if a gap does, or could, exist between the address range
+   covered by PNOTE1 and PNOTE2.  */
+
+static bfd_boolean
+gap_exists (objcopy_internal_note * pnote1,
+           objcopy_internal_note * pnote2)
+{
+  /* Without range end notes, we assume that a gap might exist.  */
+  if (pnote1->end == 0 || pnote2->end == 0)
+    return TRUE;
+
+  /* FIXME: Alignment of 16 bytes taken from x86_64 binaries.
+     Really we should extract the alignment of the section covered by the notes.  */
+  return BFD_ALIGN (pnote1->end, 16) < pnote2->start;
+}
+
+static bfd_boolean
+is_open_note (objcopy_internal_note * pnote)
+{
+  return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_OPEN);
+}
+
+static bfd_boolean
+is_func_note (objcopy_internal_note * pnote)
+{
+  return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_FUNC);
+}
+
+static bfd_boolean
+is_64bit (bfd * abfd)
+{
+  /* Should never happen, but let's be paranoid.  */
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return FALSE;
+
+  return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64;
+}
+
+/* Merge the notes on SEC, removing redundant entries.
+   Returns the new, smaller size of the section upon success.  */
+
+static bfd_size_type
+merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte * contents)
+{
+  objcopy_internal_note *  pnotes_end;
+  objcopy_internal_note *  pnotes = NULL;
+  objcopy_internal_note *  pnote;
+  bfd_size_type       remain = size;
+  unsigned            version_1_seen = 0;
+  unsigned            version_2_seen = 0;
+  unsigned            version_3_seen = 0;
+  bfd_boolean         duplicate_found = FALSE;
+  const char *        err = NULL;
+  bfd_byte *          in = contents;
+  int                 attribute_type_byte;
+  int                 val_start;
+  unsigned long       previous_func_start = 0;
+  unsigned long       previous_open_start = 0;
+  unsigned long       previous_func_end = 0;
+  unsigned long       previous_open_end = 0;
+  long                relsize;
+
+
+  relsize = bfd_get_reloc_upper_bound (abfd, sec);
+  if (relsize > 0)
+    {
+      arelent **  relpp;
+      long        relcount;
+
+      /* If there are relocs associated with this section then we
+        cannot safely merge it.  */
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (abfd, sec, relpp, isympp);
+      free (relpp);
+      if (relcount != 0)
+       goto done;
+    }
+  
+  /* Make a copy of the notes and convert to our internal format.
+     Minimum size of a note is 12 bytes.  */
+  pnote = pnotes = (objcopy_internal_note *) xcalloc ((size / 12), sizeof (* pnote));
+  while (remain >= 12)
+    {
+      bfd_vma start, end;
+
+      pnote->note.namesz = (bfd_get_32 (abfd, in    ) + 3) & ~3;
+      pnote->note.descsz = (bfd_get_32 (abfd, in + 4) + 3) & ~3;
+      pnote->note.type   =  bfd_get_32 (abfd, in + 8);
+
+      if (pnote->note.type    != NT_GNU_BUILD_ATTRIBUTE_OPEN
+         && pnote->note.type != NT_GNU_BUILD_ATTRIBUTE_FUNC)
+       {
+         err = _("corrupt GNU build attribute note: wrong note type");
+         goto done;
+       }
+
+      if (pnote->note.namesz + pnote->note.descsz + 12 > remain)
+       {
+         err = _("corrupt GNU build attribute note: note too big");
+         goto done;
+       }
+
+      if (pnote->note.namesz < 2)
+       {
+         err = _("corrupt GNU build attribute note: name too small");
+         goto done;
+       }
+
+      pnote->note.namedata = (char *)(in + 12);
+      pnote->note.descdata = (char *)(in + 12 + pnote->note.namesz);
+
+      remain -= 12 + pnote->note.namesz + pnote->note.descsz;
+      in     += 12 + pnote->note.namesz + pnote->note.descsz;
+
+      if (pnote->note.namesz > 2
+         && pnote->note.namedata[0] == '$'
+         && pnote->note.namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION
+         && pnote->note.namedata[2] == '1')
+       ++ version_1_seen;
+      else if (pnote->note.namesz > 4
+              && pnote->note.namedata[0] == 'G'
+              && pnote->note.namedata[1] == 'A'
+              && pnote->note.namedata[2] == '$'
+              && pnote->note.namedata[3] == GNU_BUILD_ATTRIBUTE_VERSION)
+       {
+         if (pnote->note.namedata[4] == '2')
+           ++ version_2_seen;
+         else if (pnote->note.namedata[4] == '3')
+           ++ version_3_seen;
+         else
+           {
+             err = _("corrupt GNU build attribute note: unsupported version");
+             goto done;
+           }
+       }
+
+      switch (pnote->note.descsz)
+       {
+       case 0:
+         start = end = 0;
+         break;
+
+       case 4:
+         start = bfd_get_32 (abfd, pnote->note.descdata);
+         /* FIXME: For version 1 and 2 notes we should try to
+            calculate the end address by finding a symbol whose
+            value is START, and then adding in its size.
+
+            For now though, since v1 and v2 was not intended to
+            handle gaps, we chose an artificially large end
+            address.  */
+         end = 0x7ffffffffffffffUL;
+         break;
+         
+       case 8:
+         if (! is_64bit (abfd))
+           {
+             start = bfd_get_32 (abfd, pnote->note.descdata);
+             end = bfd_get_32 (abfd, pnote->note.descdata + 4);
+           }
+         else
+           {
+             start = bfd_get_64 (abfd, pnote->note.descdata);
+             /* FIXME: For version 1 and 2 notes we should try to
+                calculate the end address by finding a symbol whose
+                value is START, and then adding in its size.
+
+                For now though, since v1 and v2 was not intended to
+                handle gaps, we chose an artificially large end
+                address.  */
+             end = 0x7ffffffffffffffUL;
+           }
+         break;
+
+       case 16:
+         start = bfd_get_64 (abfd, pnote->note.descdata);
+         end = bfd_get_64 (abfd, pnote->note.descdata + 8);
+         break;
+         
+       default:
+         err = _("corrupt GNU build attribute note: bad description size");
+         goto done;
+       }
+
+      if (is_open_note (pnote))
+       {
+         if (start)
+           previous_open_start = start;
+
+         pnote->start = previous_open_start;
+
+         if (end)
+           previous_open_end = end;
+
+         pnote->end = previous_open_end;
+       }
+      else
+       {
+         if (start)
+           previous_func_start = start;
+
+         pnote->start = previous_func_start;
+
+         if (end)
+           previous_func_end = end;
+
+         pnote->end = previous_func_end;
+       }
+
+      if (pnote->note.namedata[pnote->note.namesz - 1] != 0)
+       {
+         err = _("corrupt GNU build attribute note: name not NUL terminated");
+         goto done;
+       }
+
+      pnote ++;
+    }
+
+  pnotes_end = pnote;
+
+  /* Check that the notes are valid.  */
+  if (remain != 0)
+    {
+      err = _("corrupt GNU build attribute notes: excess data at end");
+      goto done;
+    }
+
+  if (version_1_seen == 0 && version_2_seen == 0 && version_3_seen == 0)
+    {
+      err = _("bad GNU build attribute notes: no known versions detected");
+      goto done;
+    }
+
+  if ((version_1_seen > 0 && version_2_seen > 0)
+      || (version_1_seen > 0 && version_3_seen > 0)
+      || (version_2_seen > 0 && version_3_seen > 0))
+    {
+      err = _("bad GNU build attribute notes: multiple different versions");
+      goto done;
+    }
+
+  /* Merging is only needed if there is more than one version note...  */
+  if (version_1_seen == 1 || version_2_seen == 1 || version_3_seen == 1)
+    goto done;
+
+  attribute_type_byte = version_1_seen ? 1 : 3;
+  val_start = attribute_type_byte + 1;
+
+  /* The first note should be the first version note.  */
+  if (pnotes[0].note.namedata[attribute_type_byte] != GNU_BUILD_ATTRIBUTE_VERSION)
+    {
+      err = _("bad GNU build attribute notes: first note not version note");
+      goto done;
+    }
+
+  /* Now merge the notes.  The rules are:
+     1. Preserve the ordering of the notes.
+     2. Preserve any NT_GNU_BUILD_ATTRIBUTE_FUNC notes.
+     3. Eliminate any NT_GNU_BUILD_ATTRIBUTE_OPEN notes that have the same
+        full name field as the immediately preceeding note with the same type
+       of name and whose address ranges coincide.
+       IE - it there are gaps in the coverage of the notes, then these gaps
+       must be preserved.
+     4. Combine the numeric value of any NT_GNU_BUILD_ATTRIBUTE_OPEN notes
+        of type GNU_BUILD_ATTRIBUTE_STACK_SIZE.
+     5. If an NT_GNU_BUILD_ATTRIBUTE_OPEN note is going to be preserved and
+        its description field is empty then the nearest preceeding OPEN note
+       with a non-empty description field must also be preserved *OR* the
+       description field of the note must be changed to contain the starting
+       address to which it refers.  */
+  for (pnote = pnotes + 1; pnote < pnotes_end; pnote ++)
+    {
+      int                      note_type;
+      objcopy_internal_note *  back;
+      objcopy_internal_note *  prev_open_with_range = NULL;
+
+      /* Rule 2 - preserve function notes.  */
+      if (! is_open_note (pnote))
+       continue;
+
+      note_type = pnote->note.namedata[attribute_type_byte];
+
+      /* Scan backwards from pnote, looking for duplicates.
+        Clear the type field of any found - but do not delete them just yet.  */
+      for (back = pnote - 1; back >= pnotes; back --)
+       {
+         int back_type = back->note.namedata[attribute_type_byte];
+
+         /* If this is the first open note with an address
+            range that we have encountered then record it.  */
+         if (prev_open_with_range == NULL
+             && back->note.descsz > 0
+             && ! is_func_note (back))
+           prev_open_with_range = back;
+
+         if (! is_open_note (back))
+           continue;
+
+         /* If the two notes are different then keep on searching.  */
+         if (back_type != note_type)
+           continue;
+
+         /* Rule 4 - combine stack size notes.  */
+         if (back_type == GNU_BUILD_ATTRIBUTE_STACK_SIZE)
+           {
+             unsigned char * name;
+             unsigned long   note_val;
+             unsigned long   back_val;
+             unsigned int    shift;
+             unsigned int    bytes;
+             unsigned long   byte;
+
+             for (shift = 0, note_val = 0,
+                    bytes = pnote->note.namesz - val_start,
+                    name = (unsigned char *) pnote->note.namedata + val_start;
+                  bytes--;)
+               {
+                 byte = (* name ++) & 0xff;
+                 note_val |= byte << shift;
+                 shift += 8;
+               }
+
+             for (shift = 0, back_val = 0,
+                    bytes = back->note.namesz - val_start,
+                    name = (unsigned char *) back->note.namedata + val_start;
+                  bytes--;)
+               {
+                 byte = (* name ++) & 0xff;
+                 back_val |= byte << shift;
+                 shift += 8;
+               }
+
+             back_val += note_val;
+             if (num_bytes (back_val) >= back->note.namesz - val_start)
+               {
+                 /* We have a problem - the new value requires more bytes of
+                    storage in the name field than are available.  Currently
+                    we have no way of fixing this, so we just preserve both
+                    notes.  */
+                 continue;
+               }
+
+             /* Write the new val into back.  */
+             name = (unsigned char *) back->note.namedata + val_start;
+             while (name < (unsigned char *) back->note.namedata
+                    + back->note.namesz)
+               {
+                 byte = back_val & 0xff;
+                 * name ++ = byte;
+                 if (back_val == 0)
+                   break;
+                 back_val >>= 8;
+               }
+
+             duplicate_found = TRUE;
+             pnote->note.type = 0;
+             break;
+           }
+
+         /* Rule 3 - combine identical open notes.  */
+         if (back->note.namesz == pnote->note.namesz
+             && memcmp (back->note.namedata,
+                        pnote->note.namedata, back->note.namesz) == 0
+             && ! gap_exists (back, pnote))
+           {
+             duplicate_found = TRUE;
+             pnote->note.type = 0;
+
+             if (pnote->end > back->end)
+               back->end = pnote->end;
+
+             if (version_3_seen)
+               back->modified = TRUE;
+             break;
+           }
+
+         /* Rule 5 - Since we are keeping this note we must check to see
+            if its description refers back to an earlier OPEN version
+            note that has been scheduled for deletion.  If so then we
+            must make sure that version note is also preserved.  */
+         if (version_3_seen)
+           {
+             /* As of version 3 we can just
+                move the range into the note.  */
+             pnote->modified = TRUE;
+             pnote->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC;
+             back->modified = TRUE;
+             back->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC;
+           }
+         else
+           {
+             if (pnote->note.descsz == 0
+                 && prev_open_with_range != NULL
+                 && prev_open_with_range->note.type == 0)
+               prev_open_with_range->note.type = NT_GNU_BUILD_ATTRIBUTE_OPEN;
+           }
+
+         /* We have found a similar attribute but the details do not match.
+            Stop searching backwards.  */
+         break;
+       }
+    }
+
+  if (duplicate_found)
+    {
+      bfd_byte *     new_contents;
+      bfd_byte *     old;
+      bfd_byte *     new;
+      bfd_size_type  new_size;
+      bfd_vma        prev_start = 0;
+      bfd_vma        prev_end = 0;
+
+      /* Eliminate the duplicates.  */
+      new = new_contents = xmalloc (size);
+      for (pnote = pnotes, old = contents;
+          pnote < pnotes_end;
+          pnote ++)
+       {
+         bfd_size_type note_size = 12 + pnote->note.namesz + pnote->note.descsz;
+
+         if (pnote->note.type != 0)
+           {
+             if (pnote->modified)
+               {
+                 /* If the note has been modified then we must copy it by
+                    hand, potentially adding in a new description field.  */
+                 if (pnote->start == prev_start && pnote->end == prev_end)
+                   {
+                     bfd_put_32 (abfd, pnote->note.namesz, new);
+                     bfd_put_32 (abfd, 0, new + 4);
+                     bfd_put_32 (abfd, pnote->note.type, new + 8);
+                     new += 12;
+                     memcpy (new, pnote->note.namedata, pnote->note.namesz);
+                     new += pnote->note.namesz;
+                   }
+                 else
+                   {
+                     bfd_put_32 (abfd, pnote->note.namesz, new);
+                     bfd_put_32 (abfd, is_64bit (abfd) ? 16 : 8, new + 4);
+                     bfd_put_32 (abfd, pnote->note.type, new + 8);
+                     new += 12;
+                     memcpy (new, pnote->note.namedata, pnote->note.namesz);
+                     new += pnote->note.namesz;
+                     if (is_64bit (abfd))
+                       {
+                         bfd_put_64 (abfd, pnote->start, new);
+                         bfd_put_64 (abfd, pnote->end, new + 8);
+                         new += 16;
+                       }
+                     else
+                       {
+                         bfd_put_32 (abfd, pnote->start, new);
+                         bfd_put_32 (abfd, pnote->end, new + 4);
+                         new += 8;
+                       }
+                   }
+               }
+             else
+               {
+                 memcpy (new, old, note_size);
+                 new += note_size;
+               }
+             prev_start = pnote->start;
+             prev_end = pnote->end;
+           }
+
+         old += note_size;
+       }
+
+      new_size = new - new_contents;
+      memcpy (contents, new_contents, new_size);
+      size = new_size;
+      free (new_contents);
+    }
+
+ done:
+  if (err)
+    {
+      bfd_set_error (bfd_error_bad_value);
+      bfd_nonfatal_message (NULL, abfd, sec, err);
+      status = 1;
+    }
+
+  free (pnotes);
+  return size;
+}
+
 /* Copy object file IBFD onto OBFD.
    Returns TRUE upon success, FALSE otherwise.  */
 
@@ -1805,6 +2345,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
   bfd_vma start;
   long symcount;
   asection **osections = NULL;
+  asection *osec;
   asection *gnu_debuglink_section = NULL;
   bfd_size_type *gaps = NULL;
   bfd_size_type max_gap = 0;
@@ -2105,8 +2646,6 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
           pupdate != NULL;
           pupdate = pupdate->next)
        {
-         asection *osec;
-
          pupdate->section = bfd_get_section_by_name (ibfd, pupdate->name);
          if (pupdate->section == NULL)
            {
@@ -2123,16 +2662,63 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
        }
     }
 
+  if (merge_notes)
+    {
+      /* This palaver is necessary because we must set the output
+        section size first, before its contents are ready.  */
+      osec = bfd_get_section_by_name (ibfd, GNU_BUILD_ATTRS_SECTION_NAME);
+      if (osec && is_merged_note_section (ibfd, osec))
+       {
+         bfd_size_type size;
+         
+         size = bfd_get_section_size (osec);
+         if (size == 0)
+           {
+             bfd_nonfatal_message (NULL, ibfd, osec, _("warning: note section is empty"));
+             merge_notes = FALSE;
+           }
+         else if (! bfd_get_full_section_contents (ibfd, osec, & merged_notes))
+           {
+             bfd_nonfatal_message (NULL, ibfd, osec, _("warning: could not load note section"));
+             free (merged_notes);
+             merged_notes = NULL;
+             merge_notes = FALSE;
+           }
+         else
+           {
+             merged_size = merge_gnu_build_notes (ibfd, osec, size, merged_notes);
+             if (merged_size == size)
+               {
+                 /* Merging achieves nothing.  */
+                 free (merged_notes);
+                 merged_notes = NULL;
+                 merge_notes = FALSE;
+                 merged_size = 0;
+               }
+             else
+               {
+                 if (osec->output_section == NULL
+                     || ! bfd_set_section_size (obfd, osec->output_section, merged_size))
+                   {
+                     bfd_nonfatal_message (NULL, obfd, osec, _("warning: failed to set merged notes size"));
+                     free (merged_notes);
+                     merged_notes = NULL;
+                     merge_notes = FALSE;
+                     merged_size = 0;
+                   }
+               }
+           }
+       }
+    }
+
   if (dump_sections != NULL)
     {
       struct section_add * pdump;
 
       for (pdump = dump_sections; pdump != NULL; pdump = pdump->next)
        {
-         asection * sec;
-
-         sec = bfd_get_section_by_name (ibfd, pdump->name);
-         if (sec == NULL)
+         osec = bfd_get_section_by_name (ibfd, pdump->name);
+         if (osec == NULL)
            {
              bfd_nonfatal_message (NULL, ibfd, NULL,
                                    _("can't dump section '%s' - it does not exist"),
@@ -2140,17 +2726,17 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
              continue;
            }
 
-         if ((bfd_get_section_flags (ibfd, sec) & SEC_HAS_CONTENTS) == 0)
+         if ((bfd_get_section_flags (ibfd, osec) & SEC_HAS_CONTENTS) == 0)
            {
-             bfd_nonfatal_message (NULL, ibfd, sec,
+             bfd_nonfatal_message (NULL, ibfd, osec,
                                    _("can't dump section - it has no contents"));
              continue;
            }
 
-         bfd_size_type size = bfd_get_section_size (sec);
+         bfd_size_type size = bfd_get_section_size (osec);
          if (size == 0)
            {
-             bfd_nonfatal_message (NULL, ibfd, sec,
+             bfd_nonfatal_message (NULL, ibfd, osec,
                                    _("can't dump section - it is empty"));
              continue;
            }
@@ -2165,7 +2751,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
            }
 
          bfd_byte * contents = xmalloc (size);
-         if (bfd_get_section_contents (ibfd, sec, contents, 0, size))
+         if (bfd_get_section_contents (ibfd, osec, contents, 0, size))
            {
              if (fwrite (contents, 1, size, f) != size)
                {
@@ -2176,7 +2762,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
                }
            }
          else
-           bfd_nonfatal_message (NULL, ibfd, sec,
+           bfd_nonfatal_message (NULL, ibfd, osec,
                                  _("could not retrieve section contents"));
 
          fclose (f);
@@ -2214,7 +2800,6 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
            {
              bfd_vma debuglink_vma;
              asection * highest_section;
-             asection * sec;
 
              /* The PE spec requires that all sections be adjacent and sorted
                 in ascending order of VMA.  It also specifies that debug
@@ -2226,13 +2811,13 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
                 VMA which makes it contiguous with other debug sections.  So
                 walk the current section list, find the section with the
                 highest VMA and start the debuglink section after that one.  */
-             for (sec = obfd->sections, highest_section = NULL;
-                  sec != NULL;
-                  sec = sec->next)
-               if (sec->vma > 0
+             for (osec = obfd->sections, highest_section = NULL;
+                  osec != NULL;
+                  osec = osec->next)
+               if (osec->vma > 0
                    && (highest_section == NULL
-                       || sec->vma > highest_section->vma))
-                 highest_section = sec;
+                       || osec->vma > highest_section->vma))
+                 highest_section = osec;
 
              if (highest_section)
                debuglink_vma = BFD_ALIGN (highest_section->vma
@@ -2420,8 +3005,6 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
           pupdate != NULL;
           pupdate = pupdate->next)
        {
-         asection *osec;
-
          osec = pupdate->section->output_section;
          if (! bfd_set_section_contents (obfd, osec, pupdate->contents,
                                          0, pupdate->size))
@@ -2432,6 +3015,24 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
        }
     }
 
+  if (merge_notes)
+    {
+      osec = bfd_get_section_by_name (obfd, GNU_BUILD_ATTRS_SECTION_NAME);
+      if (osec && is_merged_note_section (obfd, osec))
+       {
+         if (! bfd_set_section_contents (obfd, osec, merged_notes, 0, merged_size))
+           {
+             bfd_nonfatal_message (NULL, obfd, osec, _("error: failed to copy merged notes into output"));
+             return FALSE;
+           }
+       }
+      else if (! is_strip)
+       bfd_nonfatal_message (NULL, obfd, osec, _("could not find any mergeable note sections"));
+      free (merged_notes);
+      merged_notes = NULL;
+      merge_notes = FALSE;
+    }
+
   if (gnu_debuglink_filename != NULL)
     {
       if (! bfd_fill_in_gnu_debuglink_section
@@ -3157,7 +3758,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 /* Return TRUE if input section ISECTION should be skipped.  */
 
 static bfd_boolean
-skip_section (bfd *ibfd, sec_ptr isection)
+skip_section (bfd *ibfd, sec_ptr isection, bfd_boolean skip_copy)
 {
   sec_ptr osection;
   bfd_size_type size;
@@ -3177,6 +3778,11 @@ skip_section (bfd *ibfd, sec_ptr isection)
   if (is_update_section (ibfd, isection))
     return TRUE;
 
+  /* When merging a note section we skip the copying of the contents,
+     but not the copying of the relocs associated with the contents.  */
+  if (skip_copy && is_merged_note_section (ibfd, isection))
+    return TRUE;
+
   flags = bfd_get_section_flags (ibfd, isection);
   if ((flags & SEC_GROUP) != 0)
     return TRUE;
@@ -3203,7 +3809,7 @@ copy_relocations_in_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
   long relcount;
   sec_ptr osection;
 
 if (skip_section (ibfd, isection))
if (skip_section (ibfd, isection, FALSE))
     return;
 
   osection = isection->output_section;
@@ -3290,7 +3896,7 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
   sec_ptr osection;
   bfd_size_type size;
 
-  if (skip_section (ibfd, isection))
+  if (skip_section (ibfd, isection, TRUE))
     return;
 
   osection = isection->output_section;
@@ -3574,6 +4180,8 @@ strip_main (int argc, char *argv[])
   int i;
   char *output_file = NULL;
 
+  merge_notes = TRUE;
+
   while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvwDU",
                           strip_options, (int *) 0)) != EOF)
     {
@@ -3609,6 +4217,12 @@ strip_main (int argc, char *argv[])
        case 'K':
          add_specific_symbol (optarg, keep_specific_htab);
          break;
+       case 'M':
+         merge_notes = TRUE;
+         break;
+       case OPTION_NO_MERGE_NOTES:
+         merge_notes = FALSE;
+         break;
        case 'N':
          add_specific_symbol (optarg, strip_specific_htab);
          break;
@@ -3938,7 +4552,7 @@ copy_main (int argc, char *argv[])
   struct stat statbuf;
   const bfd_arch_info_type *input_arch = NULL;
 
-  while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:wDU",
+  while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:MN:s:O:d:F:L:G:R:SpgxXHhVvW:wDU",
                           copy_options, (int *) 0)) != EOF)
     {
       switch (c)
@@ -4029,6 +4643,13 @@ copy_main (int argc, char *argv[])
          add_specific_symbol (optarg, keep_specific_htab);
          break;
 
+       case 'M':
+         merge_notes = TRUE;
+         break;
+       case OPTION_NO_MERGE_NOTES:
+         merge_notes = FALSE;
+         break;
+
        case 'N':
          add_specific_symbol (optarg, strip_specific_htab);
          break;
index 9a515ff..5acc770 100644 (file)
@@ -60,6 +60,7 @@
 #include "bucomm.h"
 #include "elfcomm.h"
 #include "dwarf.h"
+#include "libbfd.h"
 
 #include "elf/common.h"
 #include "elf/external.h"
@@ -287,7 +288,7 @@ enum versioned_symbol_info
   symbol_public
 };
 
-static const char *get_symbol_version_string
+static const char * get_symbol_version_string
   (FILE *file, int is_dynsym, const char *strtab,
    unsigned long int strtab_size, unsigned int si,
    Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info,
@@ -479,7 +480,7 @@ print_symbol (int width, const char *symbol)
 
   if (width < 0)
     {
-      /* Keep the width positive.  This also helps.  */
+      /* Keep the width positive.  This helps the code below.  */
       width = - width;
       extra_padding = TRUE;
     }
@@ -556,7 +557,7 @@ print_symbol (int width, const char *symbol)
   return num_printed;
 }
 
-/* Returns a pointer to a static buffer containing a  printable version of
+/* Returns a pointer to a static buffer containing a printable version of
    the given section's name.  Like print_symbol, except that it does not try
    to print multibyte characters, it just interprets them as hex values.  */
 
@@ -5920,6 +5921,13 @@ process_section_headers (FILE * file)
        i < elf_header.e_shnum;
        i++, section++)
     {
+      /* Check the sh_size field.  */
+      if (section->sh_size > current_file_size
+         && section->sh_type != SHT_NOBITS
+         && section->sh_type != SHT_NULL
+         && section->sh_type < SHT_LOOS)
+       warn (_("Size of section %u is larger than the entire file!\n"), i);
+
       printf ("  [%2u] ", i);
       if (do_section_details)
        printf ("%s\n      ", printable_section_name (section));
@@ -6128,7 +6136,7 @@ process_section_headers (FILE * file)
 static const char *
 get_group_flags (unsigned int flags)
 {
-  static char buff[32];
+  static char buff[128];
   switch (flags)
     {
     case 0:
@@ -10608,12 +10616,14 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn)
 }
 
 static const char *
-get_symbol_version_string (FILE *file, int is_dynsym,
-                          const char *strtab,
-                          unsigned long int strtab_size,
-                          unsigned int si, Elf_Internal_Sym *psym,
-                          enum versioned_symbol_info *sym_info,
-                          unsigned short *vna_other)
+get_symbol_version_string (FILE *                       file,
+                          bfd_boolean                  is_dynsym,
+                          const char *                 strtab,
+                          unsigned long int            strtab_size,
+                          unsigned int                 si,
+                          Elf_Internal_Sym *           psym,
+                          enum versioned_symbol_info * sym_info,
+                          unsigned short *             vna_other)
 {
   unsigned char data[2];
   unsigned short vers_data;
@@ -11766,7 +11776,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
-      return reloc_type == 54; /* R_SPARC_UA64.  */
+      return reloc_type == 32 /* R_SPARC_64.  */
+       || reloc_type == 54; /* R_SPARC_UA64.  */
     case EM_X86_64:
     case EM_L1OM:
     case EM_K1OM:
@@ -12005,7 +12016,7 @@ apply_relocations (void *                     file,
                   const Elf_Internal_Shdr *  section,
                   unsigned char *            start,
                   bfd_size_type              size,
-                  void **                     relocs_return,
+                  void **                    relocs_return,
                   unsigned long *            num_relocs_return)
 {
   Elf_Internal_Shdr * relsec;
@@ -12061,6 +12072,9 @@ apply_relocations (void *                     file,
        is_rela = FALSE;
 
       symsec = section_headers + relsec->sh_link;
+      if (symsec->sh_type != SHT_SYMTAB
+         && symsec->sh_type != SHT_DYNSYM)
+       return;
       symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms);
 
       for (rp = relocs; rp < relocs + num_relocs; ++rp)
@@ -15263,6 +15277,10 @@ get_note_type (unsigned e_type)
        return _("NT_VERSION (version)");
       case NT_ARCH:
        return _("NT_ARCH (architecture)");
+      case NT_GNU_BUILD_ATTRIBUTE_OPEN:
+       return _("OPEN");
+      case NT_GNU_BUILD_ATTRIBUTE_FUNC:
+       return _("func");
       default:
        break;
       }
@@ -15360,8 +15378,7 @@ print_core_note (Elf_Internal_Note *pnote)
 static const char *
 get_gnu_elf_note_type (unsigned e_type)
 {
-  static char buff[64];
-
+  /* NB/ Keep this switch statement in sync with print_gnu_note ().  */
   switch (e_type)
     {
     case NT_GNU_ABI_TAG:
@@ -15372,17 +15389,177 @@ get_gnu_elf_note_type (unsigned e_type)
       return _("NT_GNU_BUILD_ID (unique build ID bitstring)");
     case NT_GNU_GOLD_VERSION:
       return _("NT_GNU_GOLD_VERSION (gold version)");
+    case NT_GNU_PROPERTY_TYPE_0:
+      return _("NT_GNU_PROPERTY_TYPE_0");
+    case NT_GNU_BUILD_ATTRIBUTE_OPEN:
+      return _("NT_GNU_BUILD_ATTRIBUTE_OPEN");
+    case NT_GNU_BUILD_ATTRIBUTE_FUNC:
+      return _("NT_GNU_BUILD_ATTRIBUTE_FUNC");
     default:
-      break;
+      {
+       static char buff[64];
+
+       snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+       return buff;
+      }
     }
+}
 
-  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
-  return buff;
+static void
+decode_x86_isa (unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_X86_ISA_1_486: printf ("i486"); break;
+       case GNU_PROPERTY_X86_ISA_1_586: printf ("586"); break;
+       case GNU_PROPERTY_X86_ISA_1_686: printf ("686"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE: printf ("SSE"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE2: printf ("SSE2"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE3: printf ("SSE3"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSSE3: printf ("SSSE3"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_1: printf ("SSE4_1"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_2: printf ("SSE4_2"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX: printf ("AVX"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX2: printf ("AVX2"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512F: printf ("AVX512F"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512CD: printf ("AVX512CD"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512ER: printf ("AVX512ER"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512PF: printf ("AVX512PF"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512VL: printf ("AVX512VL"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512DQ: printf ("AVX512DQ"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512BW: printf ("AVX512BW"); break;
+       default: printf (_("<unknown: %x>"), bit); break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
 }
 
+static void
+print_gnu_property_note (Elf_Internal_Note * pnote)
+{
+  unsigned char * ptr = (unsigned char *) pnote->descdata;
+  unsigned char * ptr_end = ptr + pnote->descsz;
+  unsigned int    size = is_32bit_elf ? 4 : 8;
+
+  printf (_("      Properties: "));
+
+  if (pnote->descsz < 8 || (pnote->descsz % size) != 0)
+    {
+      printf (_("<corrupt GNU_PROPERTY_TYPE, size = %#lx>\n"), pnote->descsz);
+      return;
+    }
+
+  while (ptr < ptr_end)
+    {
+      unsigned int j;
+      unsigned int type;
+      unsigned int datasz;
+
+      if ((size_t) (ptr_end - ptr) < 8)
+       {
+         printf (_("<corrupt descsz: %#lx>\n"), pnote->descsz);
+         break;
+       }
+
+      type = byte_get (ptr, 4);
+      datasz = byte_get (ptr + 4, 4);
+
+      ptr += 8;
+
+      if (datasz > (size_t) (ptr_end - ptr))
+       {
+         printf (_("<corrupt type (%#x) datasz: %#x>\n"),
+                 type, datasz);
+         break;
+       }
+
+      if (type >= GNU_PROPERTY_LOPROC && type <= GNU_PROPERTY_HIPROC)
+       {
+         if (elf_header.e_machine == EM_X86_64
+             || elf_header.e_machine == EM_IAMCU
+             || elf_header.e_machine == EM_386)
+           {
+             switch (type)
+               {
+               case GNU_PROPERTY_X86_ISA_1_USED:
+                 printf ("x86 ISA used: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_isa (byte_get (ptr, 4));
+                 goto next;
+
+               case GNU_PROPERTY_X86_ISA_1_NEEDED:
+                 printf ("x86 ISA needed: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_isa (byte_get (ptr, 4));
+                 goto next;
+
+               default:
+                 break;
+               }
+           }
+       }
+      else
+       {
+         switch (type)
+           {
+           case GNU_PROPERTY_STACK_SIZE:
+             printf (_("stack size: "));
+             if (datasz != size)
+               printf (_("<corrupt length: %#x> "), datasz);
+             else
+               printf ("%#lx", (unsigned long) byte_get (ptr, size));
+             goto next;
+
+           case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+             printf ("no copy on protected ");
+             if (datasz)
+               printf (_("<corrupt length: %#x> "), datasz);
+             goto next;
+
+           default:
+             break;
+           }
+       }
+
+      if (type < GNU_PROPERTY_LOPROC)
+       printf (_("<unknown type %#x data: "), type);
+      else if (type < GNU_PROPERTY_LOUSER)
+       printf (_("<procesor-specific type %#x data: "), type);
+      else
+       printf (_("<application-specific type %#x data: "), type);
+      for (j = 0; j < datasz; ++j)
+       printf ("%02x ", ptr[j] & 0xff);
+      printf (">");
+
+next:
+      ptr += ((datasz + (size - 1)) & ~ (size - 1));
+      if (ptr == ptr_end)
+       break;
+
+      if (do_wide)
+       printf (", ");
+      else
+       printf ("\n\t");
+    }
+
+  printf ("\n");
+}
+
+
 static int
 print_gnu_note (Elf_Internal_Note *pnote)
 {
+  /* NB/ Keep this switch statement in sync with get_gnu_elf_note_type ().  */
   switch (pnote->type)
     {
     case NT_GNU_BUILD_ID:
@@ -15456,6 +15633,46 @@ print_gnu_note (Elf_Internal_Note *pnote)
        printf ("\n");
       }
       break;
+
+    case NT_GNU_HWCAP:
+      {
+       unsigned long num_entries, mask;
+
+       /* Hardware capabilities information.  Word 0 is the number of entries.
+          Word 1 is a bitmask of enabled entries.  The rest of the descriptor
+          is a series of entries, where each entry is a single byte followed
+          by a nul terminated string.  The byte gives the bit number to test
+          if enabled in the bitmask.  */
+       printf (_("      Hardware Capabilities: "));
+       if (pnote->descsz < 8)
+         {
+           printf (_("<corrupt GNU_HWCAP>\n"));
+           break;
+         }
+       num_entries = byte_get ((unsigned char *) pnote->descdata, 4);
+       mask = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       printf (_("num entries: %ld, enabled mask: %lx\n"), num_entries, mask);
+       /* FIXME: Add code to display the entries... */
+      }
+      break;
+
+    case NT_GNU_PROPERTY_TYPE_0:
+      print_gnu_property_note (pnote);
+      break;
+
+    default:
+      /* Handle unrecognised types.  An error message should have already been
+        created by get_gnu_elf_note_type(), so all that we need to do is to
+        display the data.  */
+      {
+       unsigned long i;
+
+       printf (_("    Description data: "));
+       for (i = 0; i < pnote->descsz; ++i)
+         printf ("%02x ", pnote->descdata[i] & 0xff);
+       printf ("\n");
+      }
+      break;
     }
 
   return 1;
@@ -15832,13 +16049,496 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
   return 1;
 }
 
+/* Find the symbol associated with a build attribute that is attached
+   to address OFFSET.  If PNAME is non-NULL then store the name of
+   the symbol (if found) in the provided pointer,  Returns NULL if a
+   symbol could not be found.  */
+
+static Elf_Internal_Sym *
+get_symbol_for_build_attribute (FILE *         file,
+                               unsigned long  offset,
+                               bfd_boolean    is_open_attr,
+                               const char **  pname)
+{
+  static FILE *             saved_file = NULL;
+  static char *             strtab;
+  static unsigned long      strtablen;
+  static Elf_Internal_Sym * symtab;
+  static unsigned long      nsyms;
+  Elf_Internal_Sym *  saved_sym = NULL;
+  Elf_Internal_Sym *  sym;
+
+  if (saved_file == NULL || file != saved_file)
+    {
+      Elf_Internal_Shdr * symsec;
+
+      /* Load the symbol and string sections.  */
+      for (symsec = section_headers;
+          symsec < section_headers + elf_header.e_shnum;
+          symsec ++)
+       {
+         if (symsec->sh_type == SHT_SYMTAB)
+           {
+             symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
+
+             if (symsec->sh_link < elf_header.e_shnum)
+               {
+                 Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+
+                 strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
+                                             1, strtab_sec->sh_size,
+                                             _("string table"));
+                 strtablen = strtab != NULL ? strtab_sec->sh_size : 0;
+               }
+           }
+       }
+      saved_file = file;
+    }
+
+  if (symtab == NULL || strtab == NULL)
+    return NULL;
+
+  /* Find a symbol whose value matches offset.  */
+  for (sym = symtab; sym < symtab + nsyms; sym ++)
+    if (sym->st_value == offset)
+      {
+       if (sym->st_name >= strtablen)
+         /* Huh ?  This should not happen.  */
+         continue;
+
+       if (strtab[sym->st_name] == 0)
+         continue;
+
+       /* The AArch64 and ARM architectures define mapping symbols
+          (eg $d, $x, $t) which we want to ignore.  */
+       if (strtab[sym->st_name] == '$'
+           && strtab[sym->st_name + 1] != 0
+           && strtab[sym->st_name + 2] == 0)
+         continue;
+
+       if (is_open_attr)
+         {
+           /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
+              and FILE or OBJECT symbols over NOTYPE symbols.  We skip
+              FUNC symbols entirely.  */
+           switch (ELF_ST_TYPE (sym->st_info))
+             {
+             case STT_OBJECT:
+             case STT_FILE:
+               saved_sym = sym;
+               if (sym->st_size)
+                 {
+                   /* If the symbol has a size associated
+                      with it then we can stop searching.  */
+                   sym = symtab + nsyms;
+                 }
+               continue;
+
+             case STT_FUNC:
+               /* Ignore function symbols.  */
+               continue;
+
+             default:
+               break;
+             }
+
+           switch (ELF_ST_BIND (sym->st_info))
+             {
+             case STB_GLOBAL:
+               if (saved_sym == NULL
+                   || ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
+                 saved_sym = sym;
+               break;
+
+             case STB_LOCAL:
+               if (saved_sym == NULL)
+                 saved_sym = sym;
+               break;
+
+             default:
+               break;
+             }
+         }
+       else
+         {
+           if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+             continue;
+
+           saved_sym = sym;
+           break;
+         }
+      }
+
+  if (saved_sym && pname)
+    * pname = strtab + saved_sym->st_name;
+
+  return saved_sym;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
+                                      FILE *              file)
+{
+  static unsigned long  global_offset = 0;
+  static unsigned long  global_end = 0;
+  static unsigned long  func_offset = 0;
+  static unsigned long  func_end = 0;
+
+  Elf_Internal_Sym *    sym;
+  const char *          name;
+  unsigned long         start;
+  unsigned long         end;
+  bfd_boolean           is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
+
+  switch (pnote->descsz)
+    {
+    case 0:
+      /* A zero-length description means that the range of
+        the previous note of the same type should be used.  */
+      if (is_open_attr)
+       {
+         if (global_end > global_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"),
+                   global_offset, global_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), global_offset);
+       }
+      else
+       {
+         if (func_end > func_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"), func_offset, func_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), func_offset);
+       }
+      return TRUE;
+
+    case 4:
+      start = byte_get ((unsigned char *) pnote->descdata, 4);
+      end = 0;
+      break;
+
+    case 8:
+      if (is_32bit_elf)
+       {
+         /* FIXME: We should check that version 3+ notes are being used here...  */
+         start = byte_get ((unsigned char *) pnote->descdata, 4);
+         end = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       }
+      else
+       {
+         start = byte_get ((unsigned char *) pnote->descdata, 8);
+         end = 0;
+       }
+      break;
+
+    case 16:
+      start = byte_get ((unsigned char *) pnote->descdata, 8);
+      end = byte_get ((unsigned char *) pnote->descdata + 8, 8);
+      break;
+      
+    default:
+      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
+      printf (_("    <invalid descsz>"));
+      return FALSE;
+    }
+
+  name = NULL;
+  sym = get_symbol_for_build_attribute (file, start, is_open_attr, & name);
+  /* As of version 5 of the annobin plugin, filename symbols are biased by 2
+     in order to avoid them being confused with the start address of the
+     first function in the file...  */
+  if (sym == NULL && is_open_attr)
+    sym = get_symbol_for_build_attribute (file, start + 2, is_open_attr,
+                                         & name);
+
+  if (end == 0 && sym != NULL && sym->st_size > 0)
+    end = start + sym->st_size;
+
+  if (is_open_attr)
+    {
+      /* FIXME: Need to properly allow for section alignment.  16 is just the alignment used on x86_64.  */
+      if (global_end > 0 && start > BFD_ALIGN (global_end, 16))
+       warn (_("Gap in build notes detected from %#lx to %#lx\n"),
+             global_end + 1, start - 1);
+
+      printf (_("    Applies to region from %#lx"), start);
+      global_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         global_end = end;
+       }
+    }
+  else
+    {
+      printf (_("    Applies to region from %#lx"), start);
+      func_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         func_end = end;
+       }
+    }
+
+  if (sym && name)
+    printf (_(" (%s)"), name);
+
+  printf ("\n");
+  return TRUE;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
+{
+  static const char string_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_STRING, 0 };
+  static const char number_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC, 0 };
+  static const char bool_expected [3] = { GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE, GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE, 0 };
+  char         name_type;
+  char         name_attribute;
+  const char * expected_types;
+  const char * name = pnote->namedata;
+  const char * text;
+  signed int   left;
+
+  if (name == NULL || pnote->namesz < 2)
+    {
+      error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
+      print_symbol (-20, _("  <corrupt name field>"));
+      return FALSE;
+    }
+
+  if (do_wide)
+    left = 28;
+  else
+    left = 20;
+
+  /* Version 2 of the spec adds a "GA" prefix to the name field.  */
+  if (name[0] == 'G' && name[1] == 'A')
+    {
+      if (pnote->namesz < 4)
+       {
+         error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
+         print_symbol (-20, _("  <corrupt name>"));
+         return FALSE;
+       }
+
+      printf ("GA");
+      name += 2;
+      left -= 2;
+    }
+
+  switch ((name_type = * name))
+    {
+    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+      printf ("%c", * name);
+      left --;
+      break;
+    default:
+      error (_("unrecognised attribute type in name field: %d\n"), name_type);
+      print_symbol (-20, _("<unknown name type>"));
+      return FALSE;
+    }
+
+  ++ name;
+  text = NULL;
+
+  switch ((name_attribute = * name))
+    {
+    case GNU_BUILD_ATTRIBUTE_VERSION:
+      text = _("<version>");
+      expected_types = string_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+      text = _("<stack prot>");
+      expected_types = "!+*";
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_RELRO:
+      text = _("<relro>");
+      expected_types = bool_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
+      text = _("<stack size>");
+      expected_types = number_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_TOOL:
+      text = _("<tool>");
+      expected_types = string_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_ABI:
+      text = _("<ABI>");
+      expected_types = "$*";
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_PIC:
+      text = _("<PIC>");
+      expected_types = number_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
+      text = _("<short enum>");
+      expected_types = bool_expected;
+      ++ name;
+      break;
+    default:
+      if (ISPRINT (* name))
+       {
+         int len = strnlen (name, pnote->namesz - (name - pnote->namedata)) + 1;
+
+         if (len > left && ! do_wide)
+           len = left;
+         printf ("%.*s:", len, name);
+         left -= len;
+         name += len;
+       }
+      else
+       {
+         static char tmpbuf [128];
+
+         error (_("unrecognised byte in name field: %d\n"), * name);
+         sprintf (tmpbuf, _("<unknown:_%d>"), * name);
+         text = tmpbuf;
+         name ++;
+       }
+      expected_types = "*$!+";
+      break;
+    }
+
+  if (text)
+    left -= printf ("%s", text);
+
+  if (strchr (expected_types, name_type) == NULL)
+    warn (_("attribute does not have an expected type (%c)\n"), name_type);
+
+  if ((unsigned long)(name - pnote->namedata) > pnote->namesz)
+    {
+      error (_("corrupt name field: namesz: %lu but parsing gets to %ld\n"),
+            (unsigned long) pnote->namesz,
+            (long) (name - pnote->namedata));
+      return FALSE;
+    }
+
+  if (left < 1 && ! do_wide)
+    return TRUE;
+
+  switch (name_type)
+    {
+    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+      {
+       unsigned int        bytes;
+       unsigned long long  val = 0;
+       unsigned int        shift = 0;
+       char *              decoded = NULL;
+
+       bytes = pnote->namesz - (name - pnote->namedata);
+       if (bytes > 0)
+         /* The -1 is because the name field is always 0 terminated, and we
+            want to be able to ensure that the shift in the while loop below
+            will not overflow.  */
+         -- bytes;
+
+       if (bytes > sizeof (val))
+         {
+           fprintf (stderr, "namesz %lx name %p namedata %p\n",
+                    pnote->namesz, name, pnote->namedata);
+           error (_("corrupt numeric name field: too many bytes in the value: %x\n"),
+                  bytes);
+           bytes = sizeof (val);
+         }
+       /* We do not bother to warn if bytes == 0 as this can
+          happen with some early versions of the gcc plugin.  */
+
+       while (bytes --)
+         {
+           unsigned long byte = (* name ++) & 0xff;
+
+           val |= byte << shift;
+           shift += 8;
+         }
+
+       switch (name_attribute)
+         {
+         case GNU_BUILD_ATTRIBUTE_PIC:
+           switch (val)
+             {
+             case 0: decoded = "static"; break;
+             case 1: decoded = "pic"; break;
+             case 2: decoded = "PIC"; break;
+             case 3: decoded = "pie"; break;
+             case 4: decoded = "PIE"; break;
+             default: break;
+             }
+           break;
+         case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+           switch (val)
+             {
+               /* Based upon the SPCT_FLAG_xxx enum values in gcc/cfgexpand.c.  */
+             case 0: decoded = "off"; break;
+             case 1: decoded = "on"; break;
+             case 2: decoded = "all"; break;
+             case 3: decoded = "strong"; break;
+             case 4: decoded = "explicit"; break;
+             default: break;
+             }
+           break;
+         default:
+           break;
+         }
+
+       if (decoded != NULL)
+         {
+           print_symbol (-left, decoded);
+           left = 0;
+         }
+       else if (val == 0)
+         {
+           printf ("0x0");
+           left -= 3;
+         }
+       else
+         {
+           if (do_wide)
+             left -= printf ("0x%llx", val);
+           else
+             left -= printf ("0x%-.*llx", left, val);
+         }
+      }
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+      left -= print_symbol (- left, name);
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+      left -= print_symbol (- left, "true");
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+      left -= print_symbol (- left, "false");
+      break;
+    }
+
+  if (do_wide && left > 0)
+    printf ("%-*s", left, " ");
+    
+  return TRUE;
+}
+
 /* Note that by the ELF standard, the name field is already null byte
    terminated, and namesz includes the terminating null byte.
    I.E. the value of namesz for the name "FSF" is 4.
 
    If the value of namesz is zero, there is no name present.  */
+
 static int
-process_note (Elf_Internal_Note * pnote)
+process_note (Elf_Internal_Note * pnote,
+             FILE * file)
 {
   const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
   const char * nt;
@@ -15883,7 +16583,18 @@ process_note (Elf_Internal_Note * pnote)
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  printf ("  %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt);
+  printf ("  ");
+
+  if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+      || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+    print_gnu_build_attribute_name (pnote);
+  else
+    print_symbol (-20, name);
+
+  if (do_wide)
+    printf (" 0x%08lx\t%s\t", pnote->descsz, nt);
+  else
+    printf (" 0x%08lx\t%s\n", pnote->descsz, nt);
 
   if (const_strneq (pnote->namedata, "IPF/VMS"))
     return print_ia64_vms_note (pnote);
@@ -15893,31 +16604,84 @@ process_note (Elf_Internal_Note * pnote)
     return print_stapsdt_note (pnote);
   else if (const_strneq (pnote->namedata, "CORE"))
     return print_core_note (pnote);
-  else
-    return 1;
-}
+  else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+          || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+    return print_gnu_build_attribute_description (pnote, file);
+
+  if (pnote->descsz)
+    {
+      unsigned long i;
+
+      printf (_("   description data: "));
+      for (i = 0; i < pnote->descsz; i++)
+       printf ("%02x ", pnote->descdata[i]);
+    }
+
+  if (do_wide)
+    printf ("\n");
 
+  return 1;
+}
 
 static int
-process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
+process_notes_at (FILE *              file,
+                 Elf_Internal_Shdr * section,
+                 bfd_vma             offset,
+                 bfd_vma             length,
+                 bfd_vma             align)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
-  char * end;
-  int res = 1;
+  char *              end;
+  bfd_boolean         res = TRUE;
 
   if (length <= 0)
     return 0;
 
-  pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
-                                          _("notes"));
+  if (section)
+    {
+      pnotes = (Elf_External_Note *) get_section_contents (section, file);
+      if (pnotes)
+       apply_relocations (file, section, (unsigned char *) pnotes, length, NULL, NULL);
+
+    }
+  else
+    {
+      pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
+                                              _("notes"));
+
+      /* FIXME: Core notes seem to be produced with
+        4-byte alignment even on 64-bit systems.  */
+      if (elf_header.e_type == ET_CORE)
+       align = 4;
+      else
+       align = is_32bit_elf ? 4 : 4;
+    }
   if (pnotes == NULL)
     return 0;
 
   external = pnotes;
 
-  printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
-         (unsigned long) offset, (unsigned long) length);
+  if (section)
+    printf (_("\nDisplaying notes found in: %s\n"), printable_section_name (section));
+  else
+    printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
+           (unsigned long) offset, (unsigned long) length);
+
+  /* NB: Some note sections may have alignment value of 0 or 1.  gABI
+     specifies that notes should be aligned to 4 bytes in 32-bit
+     objects and to 8 bytes in 64-bit objects.  As a Linux extension,
+     we also support 4 byte alignment in 64-bit objects.  If section
+     alignment is less than 4, we treate alignment as 4 bytes.   */
+  if (align < 4)
+    align = 4;
+  else if (align != 4 && align != 8)
+    {
+      warn (_("Corrupt note: alignment %ld, expecting 4 or 8\n"),
+           (long) align);
+      return FALSE;
+    }
+
   printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   end = (char *) pnotes + length;
@@ -15925,7 +16689,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
     {
       Elf_Internal_Note inote;
       size_t min_notesz;
-      char *next;
+      char * next;
       char * temp = NULL;
       size_t data_remaining = end - (char *) external;
 
@@ -15944,17 +16708,20 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
          inote.namesz   = BYTE_GET (external->namesz);
          inote.namedata = external->name;
          inote.descsz   = BYTE_GET (external->descsz);
-         inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+         inote.descdata = ((char *) external
+                           + ELF_NOTE_DESC_OFFSET (inote.namesz, align));
          /* PR 17531: file: 3443835e.  */
          if (inote.descdata < (char *) pnotes || inote.descdata > end)
            {
-             warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
+             warn (_("Corrupt note: name size is too big: (got: %lx, expected no more than: %lx)\n"),
+                   inote.namesz, (long)(end - inote.namedata));
              inote.descdata = inote.namedata;
              inote.namesz   = 0;
            }
 
          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
-         next = inote.descdata + align_power (inote.descsz, 2);
+         next = ((char *) external
+                 + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz, align));
        }
       else
        {
@@ -15989,8 +16756,8 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
        {
          warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
                (unsigned long) ((char *) external - (char *) pnotes));
-         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
-               inote.type, inote.namesz, inote.descsz);
+         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx, alignment: %u\n"),
+               inote.type, inote.namesz, inote.descsz, (int) align);
          break;
        }
 
@@ -16010,14 +16777,14 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
              break;
            }
 
-         strncpy (temp, inote.namedata, inote.namesz);
+         memcpy (temp, inote.namedata, inote.namesz);
          temp[inote.namesz] = 0;
 
          /* warn (_("'%s' NOTE name not properly null terminated\n"), temp);  */
          inote.namedata = temp;
        }
 
-      res &= process_note (& inote);
+      res &= process_note (& inote, file);
 
       if (temp != NULL)
        {
@@ -16046,9 +16813,10 @@ process_corefile_note_segments (FILE * file)
        i++, segment++)
     {
       if (segment->p_type == PT_NOTE)
-       res &= process_corefile_note_segment (file,
-                                             (bfd_vma) segment->p_offset,
-                                             (bfd_vma) segment->p_filesz);
+       res &= process_notes_at (file, NULL,
+                                (bfd_vma) segment->p_offset,
+                                (bfd_vma) segment->p_filesz,
+                                (bfd_vma) segment->p_align);
     }
 
   return res;
@@ -16149,9 +16917,10 @@ process_note_sections (FILE * file)
     {
       if (section->sh_type == SHT_NOTE)
        {
-         res &= process_corefile_note_segment (file,
-                                               (bfd_vma) section->sh_offset,
-                                               (bfd_vma) section->sh_size);
+         res &= process_notes_at (file, section,
+                                  (bfd_vma) section->sh_offset,
+                                  (bfd_vma) section->sh_size,
+                                  (bfd_vma) section->sh_addralign);
          n++;
        }
 
diff --git a/binutils/testsuite/binutils-all/i386/pr21231a.d b/binutils/testsuite/binutils-all/i386/pr21231a.d
new file mode 100644 (file)
index 0000000..7c13b85
--- /dev/null
@@ -0,0 +1,9 @@
+#PROG: objcopy
+#as: --32
+#objcopy:
+#readelf: -n
+
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x00000008      NT_GNU_PROPERTY_TYPE_0
+      Properties: no copy on protected 
diff --git a/binutils/testsuite/binutils-all/i386/pr21231a.s b/binutils/testsuite/binutils-all/i386/pr21231a.s
new file mode 100644 (file)
index 0000000..c2510af
--- /dev/null
@@ -0,0 +1,14 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 5f - 2f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:     .asciz "GNU"            /* vendor name.  */
+1:     .p2align 2
+2:
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 2
+5:
diff --git a/binutils/testsuite/binutils-all/i386/pr21231b.d b/binutils/testsuite/binutils-all/i386/pr21231b.d
new file mode 100644 (file)
index 0000000..29a8f44
--- /dev/null
@@ -0,0 +1,12 @@
+#PROG: objcopy
+#as: --32
+#objcopy:
+#readelf: -n
+
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x0000002c      NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       no copy on protected 
+       x86 ISA used: i486, 586, 686, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, AVX, AVX2, AVX512F, AVX512CD, AVX512ER, AVX512PF, AVX512VL, AVX512DQ, AVX512BW, <unknown: 40000>, <unknown: 80000>, <unknown: 100000>, <unknown: 200000>, <unknown: 400000>, <unknown: 800000>, <unknown: 1000000>, <unknown: 2000000>, <unknown: 4000000>, <unknown: 8000000>, <unknown: 10000000>, <unknown: 20000000>, <unknown: 40000000>, <unknown: 80000000>
+       x86 ISA needed: i486, 586, 686, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, AVX, AVX2, AVX512F, AVX512CD, AVX512ER, AVX512PF, AVX512VL
diff --git a/binutils/testsuite/binutils-all/i386/pr21231b.s b/binutils/testsuite/binutils-all/i386/pr21231b.s
new file mode 100644 (file)
index 0000000..3d54745
--- /dev/null
@@ -0,0 +1,35 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 5f - 2f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:     .asciz "GNU"            /* vendor name.  */
+1:     .p2align 2
+2:
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .dc.a 0x800000          /* Stack size.  */
+4:
+       .p2align 2
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .long -1
+4:
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .long 0xffff
+4:
+       .p2align 2
+5:
diff --git a/binutils/testsuite/binutils-all/note-2-32.d b/binutils/testsuite/binutils-all/note-2-32.d
new file mode 100644 (file)
index 0000000..a684032
--- /dev/null
@@ -0,0 +1,17 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: merge notes section (32-bits)
+#source: note-2-32.s
+
+#...
+  Owner                 Data size      Description
+[      ]+\$<version>1[         ]+0x00000004[   ]+OPEN[         ]+Applies to region from 0x100 \(note1.s\)
+[      ]+\$<tool>gcc 7.0.1[    ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\+<stack prot>true[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\*<PIC>static[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\*<ABI>0x0[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\$<version>1[         ]+0x00000004[   ]+OPEN[         ]+Applies to region from 0x104 \(note2.s\)
+[      ]+!<stack prot>false[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x104
+[      ]+\*<PIC>pic[   ]+0x00000004[   ]+func[         ]+Applies to region from 0x104 \(func1\)
+#...
diff --git a/binutils/testsuite/binutils-all/note-2-32.s b/binutils/testsuite/binutils-all/note-2-32.s
new file mode 100644 (file)
index 0000000..7b025ae
--- /dev/null
@@ -0,0 +1,93 @@
+       .text
+       .org 0x100
+       .global note1.s
+note1.s:
+       .dc.l 0
+       
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .balign 4
+       .dc.l 4
+       .dc.l 4
+       .dc.l 0x100
+       .asciz "$\ 11"
+       .dc.l 0x100
+
+       .dc.l 12
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "$\ 5gcc 7.0.1"
+
+       .dc.l 3
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2b, 0x2, 0
+       .dc.b 0
+
+       .dc.l 4
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2a, 0x7, 0, 0
+
+       .dc.l 4
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2a, 0x6, 0, 0
+       .popsection
+
+
+       .global note2.s
+note2.s:
+       .type func1, STT_FUNC
+func1: 
+       .dc.l 0x100
+       
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .dc.l 4         
+       .dc.l 4         
+       .dc.l 0x100     
+       .asciz "$\ 11"    
+       .dc.l 0x104     
+
+       .dc.l 12        
+       .dc.l 0         
+       .dc.l 0x100     
+       .asciz "$\ 5gcc 7.0.1"    
+
+       .dc.l 3         
+       .dc.l 0         
+       .dc.l 0x100     
+       .dc.b 0x21, 0x2, 0
+       .dc.b 0         
+
+       .dc.l 4         
+       .dc.l 4         
+       .dc.l 0x101     
+       .dc.b 0x2a, 0x7, 1, 0
+       .dc.l 0x104     
+       
+       .dc.l 4         
+       .dc.l 0         
+       .dc.l 0x100     
+       .dc.b 0x2a, 0x6, 0, 0
+       .popsection
+
+       
+       .global note3.s
+note3.s:
+       .dc.l 0x100
+       
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .dc.l 4         
+       .dc.l 4         
+       .dc.l 0x100     
+       .asciz "$\ 11"    
+       .dc.l 0x108
+
+       .dc.l 12        
+       .dc.l 0         
+       .dc.l 0x100     
+       .asciz "$\ 5gcc 7.0.1"    
+
+       .popsection
+       
+       
diff --git a/binutils/testsuite/binutils-all/note-2-64.d b/binutils/testsuite/binutils-all/note-2-64.d
new file mode 100644 (file)
index 0000000..1796d85
--- /dev/null
@@ -0,0 +1,17 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: merge notes section (64-bits)
+#source: note-2-64.s
+
+#...
+  Owner                 Data size      Description
+[      ]+\$<version>1[         ]+0x00000008[   ]+OPEN[         ]+Applies to region from 0x100 \(note1.s\)
+[      ]+\$<tool>gcc 7.0.1[    ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\+<stack prot>true[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\*<PIC>static[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\*<ABI>0x0[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100
+[      ]+\$<version>1[         ]+0x00000008[   ]+OPEN[         ]+Applies to region from 0x104 \(note2.s\)
+[      ]+!<stack prot>false[   ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x104
+[      ]+\*<PIC>pic[   ]+0x00000008[   ]+func[         ]+Applies to region from 0x104 \(func1\)
+#...
diff --git a/binutils/testsuite/binutils-all/note-2-64.s b/binutils/testsuite/binutils-all/note-2-64.s
new file mode 100644 (file)
index 0000000..02b84e4
--- /dev/null
@@ -0,0 +1,92 @@
+       .text
+       .org 0x100
+       .global note1.s
+note1.s:
+       .dc.l 0
+       
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .balign 4
+       .dc.l 4
+       .dc.l 8
+       .dc.l 0x100
+       .asciz "$\ 11"
+       .8byte 0x100
+
+       .dc.l 12
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "$\ 5gcc 7.0.1"
+
+       .dc.l 3
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2b, 0x2, 0
+       .dc.b 0
+
+       .dc.l 4
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2a, 0x7, 0, 0
+
+       .dc.l 4
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x2a, 0x6, 0, 0
+       .popsection
+
+
+       .global note2.s
+note2.s:
+       .global func1
+       .type func1, STT_FUNC
+func1: 
+       .dc.l 0x100
+
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .dc.l 4         
+       .dc.l 8         
+       .dc.l 0x100     
+       .asciz "$\ 11"    
+       .8byte 0x104    
+
+       .dc.l 12        
+       .dc.l 0         
+       .dc.l 0x100     
+       .asciz "$\ 5gcc 7.0.1"    
+
+       .dc.l 3         
+       .dc.l 0         
+       .dc.l 0x100     
+       .dc.b 0x21, 0x2, 0
+       .dc.b 0         
+
+       .dc.l 4
+       .dc.l 8 
+       .dc.l 0x101     
+       .dc.b 0x2a, 0x7, 1, 0
+       .8byte 0x104    
+
+       .dc.l 4
+       .dc.l 0         
+       .dc.l 0x100     
+       .dc.b 0x2a, 0x6, 0, 0
+       .popsection
+       
+
+       .global note3.s
+note3.s:
+       .dc.l 0x100
+       
+       .pushsection .gnu.build.attributes, "0x100000", %note
+       .dc.l 4         
+       .dc.l 8         
+       .dc.l 0x100     
+       .asciz "$\ 11"    
+       .8byte 0x108
+
+       .dc.l 12        
+       .dc.l 0         
+       .dc.l 0x100     
+       .asciz "$\ 5gcc 7.0.1"    
+
+       .popsection
diff --git a/binutils/testsuite/binutils-all/note-3-32.d b/binutils/testsuite/binutils-all/note-3-32.d
new file mode 100644 (file)
index 0000000..e35e9cc
--- /dev/null
@@ -0,0 +1,18 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: v2 gnu build attribute notes (32-bit)
+#source: note-3-32.s
+
+#...
+Displaying notes found in: .gnu.build.attributes
+[      ]+Owner[        ]+Data size[    ]+Description
+[      ]+GA\$<version>2p1[     ]+0x0000000.[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122 \(note_1.s\)
+[      ]+GA\$<tool>gcc 6.3.1 20161221[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*GOW:0x700[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<stack prot>off[  ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*FORTIFY:0xff[     ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<PIC>PIC[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\!<short enum>false[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<ABI>0x[0-9a-f]+[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+#...
diff --git a/binutils/testsuite/binutils-all/note-3-32.s b/binutils/testsuite/binutils-all/note-3-32.s
new file mode 100644 (file)
index 0000000..e2e06f9
--- /dev/null
@@ -0,0 +1,58 @@
+       .text
+       .org 0x100
+       .global note_1.s
+       .size   note_1.s, 0x22
+note_1.s:
+       .word 0
+       
+       .pushsection .gnu.build.attributes, "", %note
+       .balign 4
+
+       .dc.l 8
+       .dc.l 4
+       .dc.l 0x100
+       .asciz "GA$\ 12p1"
+       .dc.l note_1.s
+
+       .dc.l 23
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "GA$\ 5gcc 6.3.1 20161221"
+       .dc.b 0
+
+       .dc.l 10
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
+       .dc.b 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
+       .dc.b 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
+       .dc.b 0, 0
+
+       .dc.l 5
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x21, 0x8, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
+       .dc.b 0, 0, 0
+       .popsection
diff --git a/binutils/testsuite/binutils-all/note-3-64.d b/binutils/testsuite/binutils-all/note-3-64.d
new file mode 100644 (file)
index 0000000..9899ea1
--- /dev/null
@@ -0,0 +1,18 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: v2 gnu build attribute notes (64-bit)
+#source: note-3-64.s
+
+#...
+Displaying notes found in: .gnu.build.attributes
+[      ]+Owner[        ]+Data size[    ]+Description
+[      ]+GA\$<version>2p1[     ]+0x0000000.[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122 \(note_1.s\)
+[      ]+GA\$<tool>gcc 6.3.1 20161221[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*GOW:0x700[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<stack prot>off[  ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*FORTIFY:0xff[     ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<PIC>PIC[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\!<short enum>false[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+[      ]+GA\*<ABI>0x[0-9a-f]+[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x122
+#...
diff --git a/binutils/testsuite/binutils-all/note-3-64.s b/binutils/testsuite/binutils-all/note-3-64.s
new file mode 100644 (file)
index 0000000..e7d27d2
--- /dev/null
@@ -0,0 +1,58 @@
+       .text
+       .org 0x100
+       .global note_1.s
+       .size   note_1.s, 0x22
+note_1.s:
+       .word 0
+       
+       .pushsection .gnu.build.attributes, "", %note
+       .balign 4
+
+       .dc.l 8
+       .dc.l 8
+       .dc.l 0x100
+       .asciz "GA$\ 12p1"
+       .8byte note_1.s
+
+       .dc.l 23
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "GA$\ 5gcc 6.3.1 20161221"
+       .dc.b 0
+
+       .dc.l 10
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
+       .dc.b 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
+       .dc.b 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
+       .dc.b 0, 0
+
+       .dc.l 5
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x21, 0x8, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
+       .dc.b 0, 0, 0
+       .popsection
diff --git a/binutils/testsuite/binutils-all/note-3.32.s b/binutils/testsuite/binutils-all/note-3.32.s
new file mode 100644 (file)
index 0000000..84d8c89
--- /dev/null
@@ -0,0 +1,67 @@
+       .text
+       .org 0x100
+       .global note1.s
+note1.s:
+       .word 0
+       
+       .pushsection .gnu.build.attributes, "", %note
+       .balign 4
+
+       .dc.l 8
+       .dc.l 8
+       .dc.l 0x100
+       .asciz "GA$\ 12p1"
+       .quad note_1.s
+
+       .dc.l 23
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "GA$\ 5gcc 6.3.1 20161221"
+       .dc.b 0
+
+       .dc.l 10
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
+       .dc.b 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
+       .dc.b 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
+       .dc.b 0, 0
+
+       .dc.l 5
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x21, 0x8, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
+       .dc.b 0, 0, 0
+
+       .pushsection .note.gnu.property, "a", %note
+       .balign 4
+       .dc.l 4
+       .dc.l 32
+       .dc.l 0x5
+       .asciz "GNU"
+       .dc.b 0, 0, 0, 0xc0, 0x4, 0, 0, 0
+       .dc.b 0, 0x6, 0, 0, 0, 0, 0, 0
+       .dc.b 0x1, 0, 0, 0xc0, 0x4, 0, 0, 0
+       .dc.b 0, 0x6, 0, 0, 0, 0, 0, 0
diff --git a/binutils/testsuite/binutils-all/note-4-32.d b/binutils/testsuite/binutils-all/note-4-32.d
new file mode 100644 (file)
index 0000000..6c9e98e
--- /dev/null
@@ -0,0 +1,19 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: v3 gnu build attribute notes (32-bit)
+#source: note-4-32.s
+
+#...
+Displaying notes found in: .gnu.build.attributes
+[      ]+Owner[        ]+Data size[    ]+Description
+[      ]+GA\$<version>3p3[     ]+0x00000008[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110 \(note_4.s\)
+[      ]+GA\$<tool>gcc 7.2.1 20170915[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*GOW:0x700[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*<stack prot>off[  ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*FORTIFY:0xff[     ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*<PIC>PIC[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\!<short enum>false[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*<ABI>0x[0-9a-f]+[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x10. to 0x110
+[      ]+GA\*<stack prot>strong[       ]+0x00000008[   ]+func[         ]+Applies to region from 0x10. to 0x10c.*
+#...
diff --git a/binutils/testsuite/binutils-all/note-4-32.s b/binutils/testsuite/binutils-all/note-4-32.s
new file mode 100644 (file)
index 0000000..20d9e7b
--- /dev/null
@@ -0,0 +1,74 @@
+       .text
+       .org 0x100
+       .equiv note_4.s, . + 2
+       .dc.l 0
+       .dc.l 0
+
+       .type   bar, STT_FUNC
+bar:
+       .dc.l 0
+bar_end:
+       .dc.l 0
+note_4.s_end:
+       
+       .pushsection .gnu.build.attributes, "", %note
+       .balign 4
+
+       .dc.l 8
+       .dc.l 8
+       .dc.l 0x100
+       .asciz "GA$\ 13p3"
+       .dc.l note_4.s - 2
+       .dc.l note_4.s_end
+
+       .dc.l 23
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "GA$\ 5gcc 7.2.1 20170915"
+       .dc.b 0
+
+       .dc.l 10
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
+       .dc.b 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
+       .dc.b 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
+       .dc.b 0, 0
+
+       .dc.l 5
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x21, 0x8, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 8
+       .dc.l 0x101
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0
+       .dc.b 0, 0
+       .dc.l bar
+       .dc.l bar_end
+       
+       .popsection
diff --git a/binutils/testsuite/binutils-all/note-4-64.d b/binutils/testsuite/binutils-all/note-4-64.d
new file mode 100644 (file)
index 0000000..f81c9c4
--- /dev/null
@@ -0,0 +1,19 @@
+#PROG: objcopy
+#readelf: --notes --wide
+#objcopy: --merge-notes
+#name: v3 gnu build attribute notes (64-bit)
+#source: note-4-64.s
+
+#...
+Displaying notes found in: .gnu.build.attributes
+[      ]+Owner[        ]+Data size[    ]+Description
+[      ]+GA\$<version>3p3[     ]+0x00000010[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120 \(note_4.s\)
+[      ]+GA\$<tool>gcc 7.2.1 20170915[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*GOW:0x700[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*<stack prot>off[  ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*FORTIFY:0xff[     ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*<PIC>PIC[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\!<short enum>false[        ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*<ABI>0x[0-9a-f]+[         ]+0x00000000[   ]+OPEN[         ]+Applies to region from 0x100 to 0x120
+[      ]+GA\*<stack prot>strong[       ]+0x00000010[   ]+func[         ]+Applies to region from 0x110 to 0x11c.*
+#...
diff --git a/binutils/testsuite/binutils-all/note-4-64.s b/binutils/testsuite/binutils-all/note-4-64.s
new file mode 100644 (file)
index 0000000..1901682
--- /dev/null
@@ -0,0 +1,78 @@
+       .text
+       .org 0x100
+       .equiv note_4.s, . + 2
+       .dc.l 0
+       .dc.l 0
+       .dc.l 0
+       .dc.l 0
+
+       .type   bar, @function
+bar:
+       .dc.l 0
+       .dc.l 0
+       .dc.l 0
+bar_end:
+       .dc.l 0
+note_4.s_end:
+
+       .pushsection .gnu.build.attributes, "", %note
+       .balign 4
+
+       .dc.l 8
+       .dc.l 16
+       .dc.l 0x100
+       .asciz "GA$\ 13p3"
+       .8byte note_4.s - 2
+       .8byte note_4.s_end
+
+       .dc.l 23
+       .dc.l 0
+       .dc.l 0x100
+       .asciz "GA$\ 5gcc 7.2.1 20170915"
+       .dc.b 0
+
+       .dc.l 10
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
+       .dc.b 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
+       .dc.b 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
+       .dc.b 0, 0
+
+       .dc.l 5
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x21, 0x8, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 13
+       .dc.l 0
+       .dc.l 0x100
+       .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
+       .dc.b 0, 0, 0
+
+       .dc.l 6
+       .dc.l 16
+       .dc.l 0x101
+       .dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0
+       .dc.b 0, 0
+       .8byte bar
+       .8byte bar_end
+       
+       .popsection
index ccd4422..cf26f81 100644 (file)
@@ -1053,6 +1053,15 @@ if [is_elf_format] {
     run_dump_test "group-6"
     run_dump_test "copy-1"
     run_dump_test "note-1"
+    if [is_elf64 tmpdir/bintest.o] {
+       run_dump_test "note-2-64"
+       # run_dump_test "note-3-64"
+       # run_dump_test "note-4-64"
+    } else {
+       run_dump_test "note-2-32"
+       # run_dump_test "note-3-32"
+       # run_dump_test "note-4-32"
+    }
 }
 
 run_dump_test "copy-2"
index 7a44731..9c0f828 100644 (file)
@@ -1,5 +1,5 @@
 
-Displaying notes found at file offset 0x0*0.. with length 0x0*018:
+Displaying notes found in: \.note
   Owner[       ]*Data size[    ]*Description
   Version 1.0[         ]*0x0*0[        ]*NT_VERSION \(version\)
 #pass
diff --git a/binutils/testsuite/binutils-all/x86-64/pr21231a.d b/binutils/testsuite/binutils-all/x86-64/pr21231a.d
new file mode 100644 (file)
index 0000000..2a00048
--- /dev/null
@@ -0,0 +1,9 @@
+#PROG: objcopy
+#as: --64
+#objcopy:
+#readelf: -n
+
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x00000008      NT_GNU_PROPERTY_TYPE_0
+      Properties: no copy on protected 
diff --git a/binutils/testsuite/binutils-all/x86-64/pr21231a.s b/binutils/testsuite/binutils-all/x86-64/pr21231a.s
new file mode 100644 (file)
index 0000000..fef44e9
--- /dev/null
@@ -0,0 +1,14 @@
+       .section ".note.gnu.property", "a"
+       .p2align 3
+       .long 1f - 0f           /* name length.  */
+       .long 5f - 2f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:     .asciz "GNU"            /* vendor name.  */
+1:     .p2align 3
+2:
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 3
+5:
diff --git a/binutils/testsuite/binutils-all/x86-64/pr21231b.d b/binutils/testsuite/binutils-all/x86-64/pr21231b.d
new file mode 100644 (file)
index 0000000..9d7761c
--- /dev/null
@@ -0,0 +1,12 @@
+#PROG: objcopy
+#as: --64
+#objcopy:
+#readelf: -n
+
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x00000038      NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       no copy on protected 
+       x86 ISA used: i486, 586, 686, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, AVX, AVX2, AVX512F, AVX512CD, AVX512ER, AVX512PF, AVX512VL, AVX512DQ, AVX512BW, <unknown: 40000>, <unknown: 80000>, <unknown: 100000>, <unknown: 200000>, <unknown: 400000>, <unknown: 800000>, <unknown: 1000000>, <unknown: 2000000>, <unknown: 4000000>, <unknown: 8000000>, <unknown: 10000000>, <unknown: 20000000>, <unknown: 40000000>, <unknown: 80000000>
+       x86 ISA needed: i486, 586, 686, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, AVX, AVX2, AVX512F, AVX512CD, AVX512ER, AVX512PF, AVX512VL
diff --git a/binutils/testsuite/binutils-all/x86-64/pr21231b.s b/binutils/testsuite/binutils-all/x86-64/pr21231b.s
new file mode 100644 (file)
index 0000000..afba4de
--- /dev/null
@@ -0,0 +1,35 @@
+       .section ".note.gnu.property", "a"
+       .p2align 3
+       .long 1f - 0f           /* name length.  */
+       .long 5f - 2f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:     .asciz "GNU"            /* vendor name.  */
+1:     .p2align 3
+2:
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .dc.a 0x800000          /* Stack size.  */
+4:
+       .p2align 3
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 3
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .long -1
+4:
+       .p2align 3
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 4f - 3f           /* pr_datasz.  */
+3:
+       .long 0xffff
+4:
+       .p2align 3
+5:
index 82f133e..7ed8aaf 100644 (file)
@@ -1,3 +1,8 @@
+2018-07-30  Nick Clifton  <nickc@redhat.com>
+
+       * layout.cc (section_name_mapping): Add an entry for
+       .gnu.build.attributes.
+
 2016-10-21  Gergely Nagy  <ngg@tresorit.com>
 
        PR gold/17704
index 376051d..0d6998c 100644 (file)
@@ -5019,6 +5019,7 @@ const Layout::Section_name_mapping Layout::section_name_mapping[] =
   MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
   MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
   MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
+  MAPPING_INIT(".gnu.build.attributes.", ".gnu.build.attributes"),
 };
 #undef MAPPING_INIT
 #undef MAPPING_INIT_EXACT
index a766ecf..4d674df 100644 (file)
@@ -1,3 +1,65 @@
+2017-11-24  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/22444
+       * elf/external.h (ELF_ALIGN_UP): New.
+       (ELF_NOTE_DESC_OFFSET): Likewise.
+       (ELF_NOTE_NEXT_OFFSET): Likewise.
+
+2017-03-16  Nick Clifton  <nickc@redhat.com>
+
+       * elf/common.h (GNU_BUILD_ATTRIBUTE_SHORT_ENUM): New GNU BUILD
+       note type.
+
+2017-03-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/21231
+       * elf/common.h (GNU_PROPERTY_LOPROC): New.
+       (GNU_PROPERTY_HIPROC): Likewise.
+       (GNU_PROPERTY_LOUSER): Likewise.
+       (GNU_PROPERTY_HIUSER): Likewise.
+
+2017-03-01  Nick Clifton  <nickc@redhat.com>
+
+       * elf/common.h (SHF_GNU_BUILD_NOTE): Define.
+       (NT_GNU_PROPERTY_TYPE_0): Define.
+       (NT_GNU_BUILD_ATTRIBUTE_OPEN): Define.
+       (NT_GNU_BUILD_ATTRIBUTE_FUN): Define.
+       (GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC): Define.
+       (GNU_BUILD_ATTRIBUTE_TYPE_STRING): Define.
+       (GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE): Define.
+       (GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE): Define.
+       (GNU_BUILD_ATTRIBUTE_VERSION): Define.
+       (GNU_BUILD_ATTRIBUTE_STACK_PROT): Define.
+       (GNU_BUILD_ATTRIBUTE_RELRO): Define.
+       (GNU_BUILD_ATTRIBUTE_STACK_SIZE): Define.
+       (GNU_BUILD_ATTRIBUTE_TOOL): Define.
+       (GNU_BUILD_ATTRIBUTE_ABI): Define.
+       (GNU_BUILD_ATTRIBUTE_PIC): Define.
+       (NOTE_GNU_PROPERTY_SECTION_NAME): Define.
+       (GNU_BUILD_ATTRS_SECTION_NAME): Define.
+       (GNU_PROPERTY_STACK_SIZE): Define.
+       (GNU_PROPERTY_NO_COPY_ON_PROTECTED): Define.
+       (GNU_PROPERTY_X86_ISA_1_USED): Define.
+       (GNU_PROPERTY_X86_ISA_1_NEEDED): Define.
+       (GNU_PROPERTY_X86_ISA_1_486): Define.
+       (GNU_PROPERTY_X86_ISA_1_586): Define.
+       (GNU_PROPERTY_X86_ISA_1_686): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSE): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSE2): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSE3): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSSE3): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSE4_1): Define.
+       (GNU_PROPERTY_X86_ISA_1_SSE4_2): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX2): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512F): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512CD): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512ER): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512PF): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512VL): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512DQ): Define.
+       (GNU_PROPERTY_X86_ISA_1_AVX512BW): Define.
+
 2016-06-30  Matthew Wahab  <matthew.wahab@arm.com>
 
        * opcode/arm.h (ARM_ARCH_V8_2a): Add FPU_NEON_EXT_RDMA to the set
index d2da009..4d8e42e 100644 (file)
 
 /* #define SHF_MASKOS  0x0F000000    *//* OS-specific semantics */
 #define SHF_MASKOS     0x0FF00000      /* New value, Oct 4, 1999 Draft */
+#define SHF_GNU_BUILD_NOTE    (1 << 20)        /* Section contains GNU BUILD ATTRIBUTE notes.  */
 #define SHF_MASKPROC   0xF0000000      /* Processor-specific semantics */
 
 /* This used to be implemented as a processor specific section flag.
 #define NT_GNU_HWCAP           2       /* Used by ld.so and kernel vDSO.  */
 #define NT_GNU_BUILD_ID                3       /* Generated by ld --build-id.  */
 #define NT_GNU_GOLD_VERSION    4       /* Generated by gold.  */
+#define NT_GNU_PROPERTY_TYPE_0  5      /* Generated by gcc.  */
+
+#define NT_GNU_BUILD_ATTRIBUTE_OPEN    0x100
+#define NT_GNU_BUILD_ATTRIBUTE_FUNC    0x101
+
+#define GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC       '*'
+#define GNU_BUILD_ATTRIBUTE_TYPE_STRING                '$'
+#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE     '+'
+#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE    '!'
+
+#define GNU_BUILD_ATTRIBUTE_VERSION    1
+#define GNU_BUILD_ATTRIBUTE_STACK_PROT 2
+#define GNU_BUILD_ATTRIBUTE_RELRO      3
+#define GNU_BUILD_ATTRIBUTE_STACK_SIZE 4
+#define GNU_BUILD_ATTRIBUTE_TOOL       5
+#define GNU_BUILD_ATTRIBUTE_ABI                6
+#define GNU_BUILD_ATTRIBUTE_PIC                7
+#define GNU_BUILD_ATTRIBUTE_SHORT_ENUM 8
+
+#define NOTE_GNU_PROPERTY_SECTION_NAME ".note.gnu.property"
+#define GNU_BUILD_ATTRS_SECTION_NAME   ".gnu.build.attributes"
+
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0).  */
+#define GNU_PROPERTY_STACK_SIZE                        1
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED      2
+
+/* Processor-specific semantics, lo */
+#define GNU_PROPERTY_LOPROC  0xc0000000
+/* Processor-specific semantics, hi */
+#define GNU_PROPERTY_HIPROC  0xdfffffff
+/* Application-specific semantics, lo */
+#define GNU_PROPERTY_LOUSER  0xe0000000
+/* Application-specific semantics, hi */
+#define GNU_PROPERTY_HIUSER  0xffffffff
+
+#define GNU_PROPERTY_X86_ISA_1_USED            0xc0000000
+#define GNU_PROPERTY_X86_ISA_1_NEEDED          0xc0000001
+
+#define GNU_PROPERTY_X86_ISA_1_486           (1U << 0)
+#define GNU_PROPERTY_X86_ISA_1_586           (1U << 1)
+#define GNU_PROPERTY_X86_ISA_1_686           (1U << 2)
+#define GNU_PROPERTY_X86_ISA_1_SSE           (1U << 3)
+#define GNU_PROPERTY_X86_ISA_1_SSE2          (1U << 4)
+#define GNU_PROPERTY_X86_ISA_1_SSE3          (1U << 5)
+#define GNU_PROPERTY_X86_ISA_1_SSSE3         (1U << 6)
+#define GNU_PROPERTY_X86_ISA_1_SSE4_1        (1U << 7)
+#define GNU_PROPERTY_X86_ISA_1_SSE4_2        (1U << 8)
+#define GNU_PROPERTY_X86_ISA_1_AVX           (1U << 9)
+#define GNU_PROPERTY_X86_ISA_1_AVX2          (1U << 10)
+#define GNU_PROPERTY_X86_ISA_1_AVX512F       (1U << 11)
+#define GNU_PROPERTY_X86_ISA_1_AVX512CD      (1U << 12)
+#define GNU_PROPERTY_X86_ISA_1_AVX512ER      (1U << 13)
+#define GNU_PROPERTY_X86_ISA_1_AVX512PF      (1U << 14)
+#define GNU_PROPERTY_X86_ISA_1_AVX512VL      (1U << 15)
+#define GNU_PROPERTY_X86_ISA_1_AVX512DQ      (1U << 16)
+#define GNU_PROPERTY_X86_ISA_1_AVX512BW      (1U << 17)
 
 /* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG).  */
 #define GNU_ABI_TAG_LINUX      0
index d4d83ef..d7ef674 100644 (file)
@@ -183,6 +183,22 @@ typedef struct {
   char         name[1];                /* Start of the name+desc data */
 } Elf_External_Note;
 
+/* Align an address upward to a boundary, expressed as a number of bytes.
+   E.g. align to an 8-byte boundary with argument of 8.  */
+#define ELF_ALIGN_UP(addr, boundary) \
+  (((bfd_vma) (addr) + ((boundary) - 1)) & ~ (bfd_vma) ((boundary) -1))
+
+/* Compute the offset of the note descriptor from size of note entry's
+   owner string and note alignment.  */
+#define ELF_NOTE_DESC_OFFSET(namesz, align) \
+  ELF_ALIGN_UP (offsetof (Elf_External_Note, name) + (namesz), (align))
+
+/* Compute the offset of the next note entry from size of note entry's
+   owner string, size of the note descriptor and note alignment.  */
+#define ELF_NOTE_NEXT_OFFSET(namesz, descsz, align) \
+  ELF_ALIGN_UP (ELF_NOTE_DESC_OFFSET ((namesz), (align)) + (descsz), \
+               (align))
+
 /* Relocation Entries */
 typedef struct {
   unsigned char r_offset[4];   /* Location at which to apply the action */
index 21305c3..9f78900 100644 (file)
@@ -1,3 +1,51 @@
+2018-07-30  Nick Clifton  <nickc@redhat.com>
+
+       * scripttempl/elf.sc: Place .gnu.build.attributes sections with
+       other read-only sections.
+
+2017-04-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * ld/NEWS: Mention support for ELF GNU program properties.
+       * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Call
+       ELF setup_gnu_properties.
+       * testsuite/ld-i386/i386.exp: Run property tests for Linux/i386.
+       * testsuite/ld-i386/pass.c: New file.
+       * testsuite/ld-i386/property-1.r: Likewise.
+       * testsuite/ld-i386/property-2.r: Likewise.
+       * testsuite/ld-i386/property-3.r: Likewise.
+       * testsuite/ld-i386/property-4.r: Likewise.
+       * testsuite/ld-i386/property-5.r: Likewise.
+       * testsuite/ld-i386/property-6.r: Likewise.
+       * testsuite/ld-i386/property-6a.c: Likewise.
+       * testsuite/ld-i386/property-6b.c: Likewise.
+       * testsuite/ld-i386/property-6c.S: Likewise.
+       * testsuite/ld-i386/property-7.r: Likewise.
+       * testsuite/ld-i386/property-no-copy.S: Likewise.
+       * testsuite/ld-i386/property-stack.S: Likewise.
+       * testsuite/ld-i386/property-unsorted-1.S: Likewise.
+       * testsuite/ld-i386/property-unsorted-2.S: Likewise.
+       * testsuite/ld-i386/property-x86-1.S: Likewise.
+       * testsuite/ld-i386/property-x86-2.S: Likewise.
+       * testsuite/ld-x86-64/pass.c: Likewise.
+       * testsuite/ld-x86-64/property-1.r: Likewise.
+       * testsuite/ld-x86-64/property-2.r: Likewise.
+       * testsuite/ld-x86-64/property-3.r: Likewise.
+       * testsuite/ld-x86-64/property-4.r: Likewise.
+       * testsuite/ld-x86-64/property-5.r: Likewise.
+       * testsuite/ld-x86-64/property-6.r: Likewise.
+       * testsuite/ld-x86-64/property-6a.c: Likewise.
+       * testsuite/ld-x86-64/property-6b.c: Likewise.
+       * testsuite/ld-x86-64/property-6c.S: Likewise.
+       * testsuite/ld-x86-64/property-7.r: Likewise.
+       * testsuite/ld-x86-64/property-no-copy.S: Likewise.
+       * testsuite/ld-x86-64/property-stack.S: Likewise.
+       * testsuite/ld-x86-64/property-unsorted-1.S: Likewise.
+       * testsuite/ld-x86-64/property-unsorted-2.S: Likewise.
+       * testsuite/ld-x86-64/property-x86-1.S: Likewise.
+       * testsuite/ld-x86-64/property-x86-2.S: Likewise.
+       * testsuite/ld-x86-64/x86-64.exp: Run property tests for
+       Linux/x86-64.
+
 2017-01-10  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/20830
diff --git a/ld/NEWS b/ld/NEWS
index b988df0..d6c8ce0 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for ELF GNU program properties.
+
 Changes in 2.27:
 
 * Add a configure option --enable-relro to decide whether -z relro should
index 47fa549..8612b71 100644 (file)
@@ -1048,6 +1048,8 @@ gld${EMULATION_NAME}_after_open (void)
        }
     }
 
+  get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info);
+
   if (bfd_link_relocatable (&link_info))
     {
       if (link_info.execstack == ! link_info.noexecstack)
index f0c6439..6dcc00c 100644 (file)
@@ -538,6 +538,7 @@ cat <<EOF
   ${CREATE_SHLIB-${SDATA2}}
   ${CREATE_SHLIB-${SBSS2}}
   ${OTHER_READONLY_SECTIONS}
+  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
   .eh_frame_hdr : { *(.eh_frame_hdr) ${RELOCATING+*(.eh_frame_entry .eh_frame_entry.*)} }
   .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) ${RELOCATING+*(.eh_frame.*)} }
   .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table
index 7f72c6c..d28208a 100644 (file)
@@ -732,6 +732,174 @@ if { [isnative]
            {{objdump {-dw} pr19319.dd}} \
            "pr19319" \
        ] \
+       [list \
+           "Build property 1" \
+           "" \
+           "" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1" \
+       ] \
+       [list \
+           "Build property 1 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1.o" \
+       ] \
+       [list \
+           "Build property 1 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1.so" \
+       ] \
+       [list \
+           "Build property 2" \
+           "" \
+           "" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2" \
+       ] \
+       [list \
+           "Build property 2 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2.o" \
+       ] \
+       [list \
+           "Build property 2 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2.so" \
+       ] \
+       [list \
+           "Build property 3" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3" \
+       ] \
+       [list \
+           "Build property 3 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3.o" \
+       ] \
+       [list \
+           "Build property 3 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3.so" \
+       ] \
+       [list \
+           "Build property 4" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4" \
+       ] \
+       [list \
+           "Build property 4 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4.o" \
+       ] \
+       [list \
+           "Build property 4 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4.so" \
+       ] \
+       [list \
+           "Build property 4 (-Wl,-z,stack-size=0)" \
+           "-Wl,-z,stack-size=0" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4" \
+       ] \
+       [list \
+           "Build property 5" \
+           "-Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5" \
+       ] \
+       [list \
+           "Build property 5 (.o)" \
+           "-r -nostdlib -Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5.o" \
+       ] \
+       [list \
+           "Build property 5 (.so)" \
+           "-shared -Wl,-z,stack-size=0x900000" \
+           "-fPIC" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5.so" \
+       ] \
+       [list \
+           "Build property-6.so" \
+           "-shared" \
+           "-fPIC" \
+           {property-6a.c property-6c.S} \
+           {{readelf {-n} property-6.r}} \
+           "property-6.so" \
+       ] \
+       [list \
+           "Build property-6.o" \
+           "-r -nostdlib" \
+           "" \
+           {property-6b.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-6.o" \
+       ] \
+       [list \
+           "Build property-6" \
+           "-Wl,--as-needed tmpdir/property-6.o tmpdir/property-6.so" \
+           { dummy.s } \
+           "" \
+           {{readelf {-n} property-2.r}} \
+           "property-6" \
+       ] \
+       [list \
+           "Build property 7a (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {property-unsorted-1.S} \
+           {{readelf {-n} property-7.r}} \
+           "property-7a.o" \
+       ] \
+       [list \
+           "Build property 7b (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {property-unsorted-2.S} \
+           {{readelf {-n} property-7.r}} \
+           "property-7b.o" \
+       ] \
     ]
 
     run_ld_link_exec_tests [] [list \
@@ -810,6 +978,90 @@ if { [isnative]
            "got1" \
            "got1.out" \
        ] \
+       [list \
+           "Run property 1" \
+           "" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1" "pass.out" \
+       ] \
+       [list \
+           "Run property 1 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 1 (static)" \
+           "-static" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 2" \
+           "" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-2" "pass.out" \
+       ] \
+       [list \
+           "Run property 2 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-2-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 2 (static)" \
+           "-static" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-3-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 3" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S} \
+           "property-3" "pass.out" \
+       ] \
+       [list \
+           "Run property 3 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-x86-1.S property-stack.S} \
+           "property-3-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 3 (static)" \
+           "-static" \
+           "" \
+           {property-x86-1.S pass.c property-stack.S} \
+           "property-3-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 4" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           "property-4" "pass.out" \
+       ] \
+       [list \
+           "Run property 4 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           "property-4-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 4 (static)" \
+           "-static" \
+           "" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           "property-4-static" "pass.out" \
+       ] \
     ]
 
     undefined_weak "" ""
diff --git a/ld/testsuite/ld-i386/pass.c b/ld/testsuite/ld-i386/pass.c
new file mode 100644 (file)
index 0000000..8fb892c
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main ()
+{
+  printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/property-1.r b/ld/testsuite/ld-i386/property-1.r
new file mode 100644 (file)
index 0000000..d8f08c0
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: no copy on protected 
+
+#pass
diff --git a/ld/testsuite/ld-i386/property-2.r b/ld/testsuite/ld-i386/property-2.r
new file mode 100644 (file)
index 0000000..5e3d156
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+
+#pass
diff --git a/ld/testsuite/ld-i386/property-3.r b/ld/testsuite/ld-i386/property-3.r
new file mode 100644 (file)
index 0000000..0ed91f5
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       x86 ISA used: 586, SSE
+       x86 ISA needed: i486, 586
+#pass
diff --git a/ld/testsuite/ld-i386/property-4.r b/ld/testsuite/ld-i386/property-4.r
new file mode 100644 (file)
index 0000000..cb2bc15
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       x86 ISA used: i486, 586, SSE
+       x86 ISA needed: i486, 586, SSE
+#pass
diff --git a/ld/testsuite/ld-i386/property-5.r b/ld/testsuite/ld-i386/property-5.r
new file mode 100644 (file)
index 0000000..5529650
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x900000
+       x86 ISA used: i486, 586, SSE
+       x86 ISA needed: i486, 586, SSE
+#pass
diff --git a/ld/testsuite/ld-i386/property-6.r b/ld/testsuite/ld-i386/property-6.r
new file mode 100644 (file)
index 0000000..97a479f
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0xa00000
+
+#pass
diff --git a/ld/testsuite/ld-i386/property-6a.c b/ld/testsuite/ld-i386/property-6a.c
new file mode 100644 (file)
index 0000000..c7cc10b
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+property (void)
+{
+  printf ("PASS\n");
+}
diff --git a/ld/testsuite/ld-i386/property-6b.c b/ld/testsuite/ld-i386/property-6b.c
new file mode 100644 (file)
index 0000000..5336b0e
--- /dev/null
@@ -0,0 +1,8 @@
+extern void property (void);
+
+int
+main ()
+{
+  property ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/property-6c.S b/ld/testsuite/ld-i386/property-6c.S
new file mode 100644 (file)
index 0000000..13f729d
--- /dev/null
@@ -0,0 +1,18 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0xa00000          /* Stack size.  */
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-7.r b/ld/testsuite/ld-i386/property-7.r
new file mode 100644 (file)
index 0000000..ad6af84
--- /dev/null
@@ -0,0 +1,6 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       no copy on protected 
diff --git a/ld/testsuite/ld-i386/property-no-copy.S b/ld/testsuite/ld-i386/property-no-copy.S
new file mode 100644 (file)
index 0000000..3116911
--- /dev/null
@@ -0,0 +1,15 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-stack.S b/ld/testsuite/ld-i386/property-stack.S
new file mode 100644 (file)
index 0000000..5e9bcce
--- /dev/null
@@ -0,0 +1,18 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-unsorted-1.S b/ld/testsuite/ld-i386/property-unsorted-1.S
new file mode 100644 (file)
index 0000000..1cbb272
--- /dev/null
@@ -0,0 +1,34 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 2
+3:
+
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-unsorted-2.S b/ld/testsuite/ld-i386/property-unsorted-2.S
new file mode 100644 (file)
index 0000000..0289399
--- /dev/null
@@ -0,0 +1,22 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align 2
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-x86-1.S b/ld/testsuite/ld-i386/property-x86-1.S
new file mode 100644 (file)
index 0000000..953ca87
--- /dev/null
@@ -0,0 +1,32 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x600000          /* Stack size.  */
+5:
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0xa
+5:
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0x3
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-i386/property-x86-2.S b/ld/testsuite/ld-i386/property-x86-2.S
new file mode 100644 (file)
index 0000000..f11e1fe
--- /dev/null
@@ -0,0 +1,25 @@
+       .section ".note.gnu.property", "a"
+       .p2align 2
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0x3
+5:
+       .p2align 2
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0xa
+5:
+       .p2align 2
+3:
diff --git a/ld/testsuite/ld-x86-64/pass.c b/ld/testsuite/ld-x86-64/pass.c
new file mode 100644 (file)
index 0000000..8fb892c
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main ()
+{
+  printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/property-1.r b/ld/testsuite/ld-x86-64/property-1.r
new file mode 100644 (file)
index 0000000..d8f08c0
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: no copy on protected 
+
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-2.r b/ld/testsuite/ld-x86-64/property-2.r
new file mode 100644 (file)
index 0000000..5e3d156
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-3.r b/ld/testsuite/ld-x86-64/property-3.r
new file mode 100644 (file)
index 0000000..0ed91f5
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       x86 ISA used: 586, SSE
+       x86 ISA needed: i486, 586
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-4.r b/ld/testsuite/ld-x86-64/property-4.r
new file mode 100644 (file)
index 0000000..cb2bc15
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       x86 ISA used: i486, 586, SSE
+       x86 ISA needed: i486, 586, SSE
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-5.r b/ld/testsuite/ld-x86-64/property-5.r
new file mode 100644 (file)
index 0000000..5529650
--- /dev/null
@@ -0,0 +1,8 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x900000
+       x86 ISA used: i486, 586, SSE
+       x86 ISA needed: i486, 586, SSE
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-6.r b/ld/testsuite/ld-x86-64/property-6.r
new file mode 100644 (file)
index 0000000..97a479f
--- /dev/null
@@ -0,0 +1,7 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0xa00000
+
+#pass
diff --git a/ld/testsuite/ld-x86-64/property-6a.c b/ld/testsuite/ld-x86-64/property-6a.c
new file mode 100644 (file)
index 0000000..c7cc10b
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+property (void)
+{
+  printf ("PASS\n");
+}
diff --git a/ld/testsuite/ld-x86-64/property-6b.c b/ld/testsuite/ld-x86-64/property-6b.c
new file mode 100644 (file)
index 0000000..5336b0e
--- /dev/null
@@ -0,0 +1,8 @@
+extern void property (void);
+
+int
+main ()
+{
+  property ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/property-6c.S b/ld/testsuite/ld-x86-64/property-6c.S
new file mode 100644 (file)
index 0000000..41246d3
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0xa00000          /* Stack size.  */
+5:
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-7.r b/ld/testsuite/ld-x86-64/property-7.r
new file mode 100644 (file)
index 0000000..ad6af84
--- /dev/null
@@ -0,0 +1,6 @@
+#...
+Displaying notes found in: .note.gnu.property
+  Owner                 Data size      Description
+  GNU                  0x[0-9a-f]+     NT_GNU_PROPERTY_TYPE_0
+      Properties: stack size: 0x800000
+       no copy on protected 
diff --git a/ld/testsuite/ld-x86-64/property-no-copy.S b/ld/testsuite/ld-x86-64/property-no-copy.S
new file mode 100644 (file)
index 0000000..88cc252
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-stack.S b/ld/testsuite/ld-x86-64/property-stack.S
new file mode 100644 (file)
index 0000000..7f45654
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-unsorted-1.S b/ld/testsuite/ld-x86-64/property-unsorted-1.S
new file mode 100644 (file)
index 0000000..de96e7a
--- /dev/null
@@ -0,0 +1,39 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align ALIGN
+3:
+
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-unsorted-2.S b/ld/testsuite/ld-x86-64/property-unsorted-2.S
new file mode 100644 (file)
index 0000000..65d7fad
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+       .long 2                 /* pr_type.  */
+       .long 0                 /* pr_datasz.  */
+       .p2align ALIGN
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x800000          /* Stack size.  */
+5:
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-x86-1.S b/ld/testsuite/ld-x86-64/property-x86-1.S
new file mode 100644 (file)
index 0000000..33f2ccd
--- /dev/null
@@ -0,0 +1,37 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_STACK_SIZE */
+       .long 1                 /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .dc.a 0x600000          /* Stack size.  */
+5:
+       .p2align ALIGN
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0xa
+5:
+       .p2align ALIGN
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0x3
+5:
+       .p2align ALIGN
+3:
diff --git a/ld/testsuite/ld-x86-64/property-x86-2.S b/ld/testsuite/ld-x86-64/property-x86-2.S
new file mode 100644 (file)
index 0000000..132e521
--- /dev/null
@@ -0,0 +1,30 @@
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+       .section ".note.gnu.property", "a"
+       .p2align ALIGN
+       .long 1f - 0f           /* name length.  */
+       .long 3f - 1f           /* data length.  */
+       /* NT_GNU_PROPERTY_TYPE_0 */
+       .long 5                 /* note type.  */
+0:
+       .asciz "GNU"            /* vendor name.  */
+1:
+       .p2align ALIGN
+       /* GNU_PROPERTY_X86_ISA_1_USED */
+       .long 0xc0000000        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0x3
+5:
+       .p2align ALIGN
+       /* GNU_PROPERTY_X86_ISA_1_NEEDED */
+       .long 0xc0000001        /* pr_type.  */
+       .long 5f - 4f           /* pr_datasz.  */
+4:
+       .long 0xa
+5:
+       .p2align ALIGN
+3:
index 729a52d..7be4a21 100644 (file)
@@ -822,6 +822,174 @@ if { [isnative] && [which $CC] != 0 } {
            {{objdump {-dw} pr19319.dd}} \
            "pr19319" \
        ] \
+       [list \
+           "Build property 1" \
+           "" \
+           "" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1" \
+       ] \
+       [list \
+           "Build property 1 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1.o" \
+       ] \
+       [list \
+           "Build property 1 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {pass.c property-no-copy.S} \
+           {{readelf {-n} property-1.r}} \
+           "property-1.so" \
+       ] \
+       [list \
+           "Build property 2" \
+           "" \
+           "" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2" \
+       ] \
+       [list \
+           "Build property 2 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2.o" \
+       ] \
+       [list \
+           "Build property 2 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {pass.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-2.so" \
+       ] \
+       [list \
+           "Build property 3" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3" \
+       ] \
+       [list \
+           "Build property 3 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3.o" \
+       ] \
+       [list \
+           "Build property 3 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-3.r}} \
+           "property-3.so" \
+       ] \
+       [list \
+           "Build property 4" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4" \
+       ] \
+       [list \
+           "Build property 4 (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4.o" \
+       ] \
+       [list \
+           "Build property 4 (.so)" \
+           "-shared" \
+           "-fPIC" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4.so" \
+       ] \
+       [list \
+           "Build property 4 (-Wl,-z,stack-size=0)" \
+           "-Wl,-z,stack-size=0" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-4.r}} \
+           "property-4" \
+       ] \
+       [list \
+           "Build property 5" \
+           "-Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5" \
+       ] \
+       [list \
+           "Build property 5 (.o)" \
+           "-r -nostdlib -Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5.o" \
+       ] \
+       [list \
+           "Build property 5 (.so)" \
+           "-shared -Wl,-z,stack-size=0x900000" \
+           "-fPIC" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           {{readelf {-n} property-5.r}} \
+           "property-5.so" \
+       ] \
+       [list \
+           "Build property-6.so" \
+           "-shared" \
+           "-fPIC" \
+           {property-6a.c property-6c.S} \
+           {{readelf {-n} property-6.r}} \
+           "property-6.so" \
+       ] \
+       [list \
+           "Build property-6.o" \
+           "-r -nostdlib" \
+           "" \
+           {property-6b.c property-stack.S} \
+           {{readelf {-n} property-2.r}} \
+           "property-6.o" \
+       ] \
+       [list \
+           "Build property-6" \
+           "-Wl,--as-needed tmpdir/property-6.o tmpdir/property-6.so" \
+           { dummy.s } \
+           "" \
+           {{readelf {-n} property-2.r}} \
+           "property-6" \
+       ] \
+       [list \
+           "Build property 7a (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {property-unsorted-1.S} \
+           {{readelf {-n} property-7.r}} \
+           "property-7a.o" \
+       ] \
+       [list \
+           "Build property 7b (.o)" \
+           "-r -nostdlib" \
+           "" \
+           {property-unsorted-2.S} \
+           {{readelf {-n} property-7.r}} \
+           "property-7b.o" \
+       ] \
     ]
 
     run_ld_link_exec_tests [] [list \
@@ -892,6 +1060,111 @@ if { [isnative] && [which $CC] != 0 } {
            "gotpcrel1" \
            "gotpcrel1.out" \
        ] \
+       [list \
+           "Run property 1" \
+           "" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1" "pass.out" \
+       ] \
+       [list \
+           "Run property 1 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 1 (static)" \
+           "-static" \
+           "" \
+           {pass.c property-no-copy.S} \
+           "property-1-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 2" \
+           "" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-2" "pass.out" \
+       ] \
+       [list \
+           "Run property 2 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-2-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 2 (static)" \
+           "-static" \
+           "" \
+           {pass.c property-stack.S} \
+           "property-3-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 3" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S} \
+           "property-3" "pass.out" \
+       ] \
+       [list \
+           "Run property 3 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-x86-1.S property-stack.S} \
+           "property-3-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 3 (static)" \
+           "-static" \
+           "" \
+           {property-x86-1.S pass.c property-stack.S} \
+           "property-3-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 4" \
+           "" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           "property-4" "pass.out" \
+       ] \
+       [list \
+           "Run property 4 (PIE)" \
+           "-pie" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           "property-4-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 4 (static)" \
+           "-static" \
+           "" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           "property-4-static" "pass.out" \
+       ] \
+       [list \
+           "Run property 5" \
+           "-Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-stack.S property-x86-1.S property-x86-2.S} \
+           "property-5" "pass.out" \
+       ] \
+       [list \
+           "Run property 5 (PIE)" \
+           "-pie -Wl,-z,stack-size=0x900000" \
+           "" \
+           {pass.c property-x86-2.S property-x86-1.S property-stack.S} \
+           "property-5-pie" "pass.out" "-fPIE" \
+       ] \
+       [list \
+           "Run property 5 (static)" \
+           "-static -Wl,-z,stack-size=0x900000" \
+           "" \
+           {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
+           "property-5-static" "pass.out" \
+       ] \
     ]
 
     if { [istarget "x86_64-*-linux*"] \