4ede5d
diff -rupN binutils.orig/binutils/objcopy.c binutils-2.30/binutils/objcopy.c
4ede5d
--- binutils.orig/binutils/objcopy.c	2019-10-28 17:08:43.352324932 +0000
4ede5d
+++ binutils-2.30/binutils/objcopy.c	2019-10-28 17:20:26.378052081 +0000
4ede5d
@@ -97,8 +97,14 @@ static int deterministic = -1;		/* Enabl
4ede5d
 static int status = 0;			/* Exit status.  */
4ede5d
 
4ede5d
 static bfd_boolean    merge_notes = FALSE;	/* Merge note sections.  */
4ede5d
-static bfd_byte *     merged_notes = NULL;	/* Contents on note section undergoing a merge.  */
4ede5d
-static bfd_size_type  merged_size = 0;		/* New, smaller size of the merged note section.  */
4ede5d
+
4ede5d
+typedef struct merged_note_section
4ede5d
+{
4ede5d
+  asection *                    sec;	 /* The section that is being merged.  */
4ede5d
+  bfd_byte *                    contents;/* New contents of the section.  */
4ede5d
+  bfd_size_type                 size;	 /* New size of the section.  */
4ede5d
+  struct merged_note_section *  next;  	 /* Link to next merged note section.  */
4ede5d
+} merged_note_section;
4ede5d
 
4ede5d
 enum strip_action
4ede5d
 {
4ede5d
@@ -1259,7 +1265,7 @@ is_update_section (bfd *abfd ATTRIBUTE_U
4ede5d
 }
4ede5d
 
4ede5d
 static bfd_boolean
4ede5d
-is_merged_note_section (bfd * abfd, asection * sec)
4ede5d
+is_mergeable_note_section (bfd * abfd, asection * sec)
4ede5d
 {
4ede5d
   if (merge_notes
4ede5d
       && bfd_get_flavour (abfd) == bfd_target_elf_flavour
4ede5d
@@ -1268,9 +1274,9 @@ is_merged_note_section (bfd * abfd, asec
4ede5d
 	 We should add support for more note types.  */
4ede5d
       && ((elf_section_data (sec)->this_hdr.sh_flags & SHF_GNU_BUILD_NOTE) != 0
4ede5d
 	  /* Old versions of GAS (prior to 2.27) could not set the section
4ede5d
-	     flags to OS-specific values, so we also accept sections with the
4ede5d
-	     expected name.  */
4ede5d
-	  || (strcmp (sec->name, GNU_BUILD_ATTRS_SECTION_NAME) == 0)))
4ede5d
+	     flags to OS-specific values, so we also accept sections that
4ede5d
+	     start with the expected name.  */
4ede5d
+	  || (CONST_STRNEQ (sec->name, GNU_BUILD_ATTRS_SECTION_NAME))))
4ede5d
     return TRUE;
4ede5d
 
4ede5d
   return FALSE;
4ede5d
@@ -1893,56 +1899,81 @@ copy_unknown_object (bfd *ibfd, bfd *obf
4ede5d
   return TRUE;
4ede5d
 }
4ede5d
 
4ede5d
-/* Returns the number of bytes needed to store VAL.  */
4ede5d
-
4ede5d
-static inline unsigned int
4ede5d
-num_bytes (unsigned long val)
4ede5d
-{
4ede5d
-  unsigned int count = 0;
4ede5d
-
4ede5d
-  /* FIXME: There must be a faster way to do this.  */
4ede5d
-  while (val)
4ede5d
-    {
4ede5d
-      count ++;
4ede5d
-      val >>= 8;
4ede5d
-    }
4ede5d
-  return count;
4ede5d
-}
4ede5d
-
4ede5d
 typedef struct objcopy_internal_note
4ede5d
 {
4ede5d
   Elf_Internal_Note  note;
4ede5d
+  unsigned long      padded_namesz;
4ede5d
   bfd_vma            start;
4ede5d
   bfd_vma            end;
4ede5d
-  bfd_boolean        modified;
4ede5d
 } objcopy_internal_note;
4ede5d
   
4ede5d
-/* Returns TRUE if a gap does, or could, exist between the address range
4ede5d
-   covered by PNOTE1 and PNOTE2.  */
4ede5d
+#define DEBUG_MERGE 0
4ede5d
+
4ede5d
+#if DEBUG_MERGE
4ede5d
+#define merge_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
4ede5d
+#else
4ede5d
+#define merge_debug(format, ...)
4ede5d
+#endif
4ede5d
+
4ede5d
+/* Returns TRUE iff PNOTE1 overlaps or adjoins PNOTE2.  */
4ede5d
 
4ede5d
 static bfd_boolean
4ede5d
-gap_exists (objcopy_internal_note * pnote1,
4ede5d
-	    objcopy_internal_note * pnote2)
4ede5d
+overlaps_or_adjoins (objcopy_internal_note * pnote1,
4ede5d
+		     objcopy_internal_note * pnote2)
4ede5d
 {
4ede5d
-  /* Without range end notes, we assume that a gap might exist.  */
4ede5d
-  if (pnote1->end == 0 || pnote2->end == 0)
4ede5d
+  if (pnote1->end < pnote2->start)
4ede5d
+    /* FIXME: Alignment of 16 bytes taken from x86_64 binaries.
4ede5d
+       Really we should extract the alignment of the section
4ede5d
+       covered by the notes.  */
4ede5d
+    return BFD_ALIGN (pnote1->end, 16) < pnote2->start;
4ede5d
+
4ede5d
+  if (pnote2->end < pnote2->start)
4ede5d
+    return BFD_ALIGN (pnote2->end, 16) < pnote1->start;
4ede5d
+
4ede5d
+  if (pnote1->end < pnote2->end)
4ede5d
     return TRUE;
4ede5d
 
4ede5d
-  /* FIXME: Alignment of 16 bytes taken from x86_64 binaries.
4ede5d
-     Really we should extract the alignment of the section covered by the notes.  */
4ede5d
-  return BFD_ALIGN (pnote1->end, 16) < pnote2->start;
4ede5d
+  if (pnote2->end < pnote1->end)
4ede5d
+    return TRUE;
4ede5d
+
4ede5d
+  return FALSE;
4ede5d
+}
4ede5d
+
4ede5d
+/* Returns TRUE iff NEEDLE is fully contained by HAYSTACK.  */
4ede5d
+
4ede5d
+static bfd_boolean
4ede5d
+contained_by (objcopy_internal_note * needle,
4ede5d
+	      objcopy_internal_note * haystack)
4ede5d
+{
4ede5d
+  return needle->start >= haystack->start && needle->end <= haystack->end;
4ede5d
 }
4ede5d
 
4ede5d
 static bfd_boolean
4ede5d
 is_open_note (objcopy_internal_note * pnote)
4ede5d
 {
4ede5d
-  return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_OPEN);
4ede5d
+  return pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
4ede5d
 }
4ede5d
 
4ede5d
 static bfd_boolean
4ede5d
 is_func_note (objcopy_internal_note * pnote)
4ede5d
 {
4ede5d
-  return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_FUNC);
4ede5d
+  return pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_FUNC;
4ede5d
+}
4ede5d
+
4ede5d
+static bfd_boolean
4ede5d
+is_deleted_note (objcopy_internal_note * pnote)
4ede5d
+{
4ede5d
+  return pnote->note.type == 0;
4ede5d
+}
4ede5d
+
4ede5d
+static bfd_boolean
4ede5d
+is_version_note (objcopy_internal_note * pnote)
4ede5d
+{
4ede5d
+  return (pnote->note.namesz > 4
4ede5d
+	  && pnote->note.namedata[0] == 'G'
4ede5d
+	  && pnote->note.namedata[1] == 'A'
4ede5d
+	  && pnote->note.namedata[2] == '$'
4ede5d
+	  && pnote->note.namedata[3] == GNU_BUILD_ATTRIBUTE_VERSION);
4ede5d
 }
4ede5d
 
4ede5d
 static bfd_boolean
4ede5d
@@ -1955,11 +1986,97 @@ is_64bit (bfd * abfd)
4ede5d
   return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64;
4ede5d
 }
4ede5d
 
4ede5d
+/* This sorting function is used to get the notes into an order
4ede5d
+   that makes merging easy.  */
4ede5d
+
4ede5d
+static int
4ede5d
+compare_gnu_build_notes (const void * data1, const void * data2)
4ede5d
+{
4ede5d
+  objcopy_internal_note * pnote1 = (objcopy_internal_note *) data1;
4ede5d
+  objcopy_internal_note * pnote2 = (objcopy_internal_note *) data2;
4ede5d
+
4ede5d
+  /* Sort notes based upon the attribute they record.  */
4ede5d
+  int cmp = memcmp (pnote1->note.namedata + 3,
4ede5d
+		    pnote2->note.namedata + 3,
4ede5d
+		    pnote1->note.namesz < pnote2->note.namesz ?
4ede5d
+		    pnote1->note.namesz - 3 : pnote2->note.namesz - 3);
4ede5d
+  if (cmp)
4ede5d
+    return cmp;
4ede5d
+  
4ede5d
+  if (pnote1->end < pnote2->start)
4ede5d
+    return -1;
4ede5d
+  if (pnote1->start > pnote2->end)
4ede5d
+    return 1;
4ede5d
+
4ede5d
+  /* Overlaps - we should merge the two ranges.  */
4ede5d
+  if (pnote1->start < pnote2->start)
4ede5d
+    return -1;
4ede5d
+  if (pnote1->end > pnote2->end)
4ede5d
+    return 1;
4ede5d
+  
4ede5d
+  /* Put OPEN notes before function notes.  */
4ede5d
+  if (is_open_note (pnote1) && ! is_open_note (pnote2))
4ede5d
+    return -1;
4ede5d
+  if (! is_open_note (pnote1) && is_open_note (pnote2))
4ede5d
+    return 1;
4ede5d
+  
4ede5d
+  return 0;
4ede5d
+}
4ede5d
+
4ede5d
+/* This sorting function is used to get the notes into an order
4ede5d
+   that makes eliminating address ranges easier.  */
4ede5d
+
4ede5d
+static int
4ede5d
+sort_gnu_build_notes (const void * data1, const void * data2)
4ede5d
+{
4ede5d
+  objcopy_internal_note * pnote1 = (objcopy_internal_note *) data1;
4ede5d
+  objcopy_internal_note * pnote2 = (objcopy_internal_note *) data2;
4ede5d
+
4ede5d
+  if (pnote1->note.type != pnote2->note.type)
4ede5d
+    {
4ede5d
+      /* Move deleted notes to the end.  */
4ede5d
+      if (is_deleted_note (pnote1))     /* 1: OFD 2: OFD */
4ede5d
+	return 1;
4ede5d
+
4ede5d
+      /* Move OPEN notes to the start.  */
4ede5d
+      if (is_open_note (pnote1))	/* 1: OF  2: OFD */
4ede5d
+	return -1;
4ede5d
+
4ede5d
+      if (is_deleted_note (pnote2))	/* 1: F   2: O D */
4ede5d
+	return 1;
4ede5d
+
4ede5d
+      return 1;				/* 1: F   2: O   */
4ede5d
+    }
4ede5d
+  
4ede5d
+  /* Sort by starting address.  */
4ede5d
+  if (pnote1->start < pnote2->start)
4ede5d
+    return -1;
4ede5d
+  if (pnote1->start > pnote2->start)
4ede5d
+    return 1;
4ede5d
+
4ede5d
+  /* Then by end address (bigger range first).  */
4ede5d
+  if (pnote1->end > pnote2->end)
4ede5d
+    return -1;
4ede5d
+  if (pnote1->end < pnote2->end)
4ede5d
+    return 1;
4ede5d
+
4ede5d
+  /* Then by attribute type.  */
4ede5d
+  if (pnote1->note.namesz > 4
4ede5d
+      && pnote2->note.namesz > 4
4ede5d
+      && pnote1->note.namedata[3] != pnote2->note.namedata[3])
4ede5d
+    return pnote1->note.namedata[3] - pnote2->note.namedata[3];
4ede5d
+  
4ede5d
+  return 0;
4ede5d
+}
4ede5d
+
4ede5d
 /* Merge the notes on SEC, removing redundant entries.
4ede5d
    Returns the new, smaller size of the section upon success.  */
4ede5d
 
4ede5d
 static bfd_size_type
4ede5d
-merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte * contents)
4ede5d
+merge_gnu_build_notes (bfd *          abfd,
4ede5d
+		       asection *     sec,
4ede5d
+		       bfd_size_type  size,
4ede5d
+		       bfd_byte *     contents)
4ede5d
 {
4ede5d
   objcopy_internal_note *  pnotes_end;
4ede5d
   objcopy_internal_note *  pnotes = NULL;
4ede5d
@@ -1968,18 +2085,14 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
   unsigned            version_1_seen = 0;
4ede5d
   unsigned            version_2_seen = 0;
4ede5d
   unsigned            version_3_seen = 0;
4ede5d
-  bfd_boolean         duplicate_found = FALSE;
4ede5d
   const char *        err = NULL;
4ede5d
   bfd_byte *          in = contents;
4ede5d
-  int                 attribute_type_byte;
4ede5d
-  int                 val_start;
4ede5d
   unsigned long       previous_func_start = 0;
4ede5d
   unsigned long       previous_open_start = 0;
4ede5d
   unsigned long       previous_func_end = 0;
4ede5d
   unsigned long       previous_open_end = 0;
4ede5d
   long                relsize;
4ede5d
 
4ede5d
-
4ede5d
   relsize = bfd_get_reloc_upper_bound (abfd, sec);
4ede5d
   if (relsize > 0)
4ede5d
     {
4ede5d
@@ -1992,19 +2105,33 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
       relcount = bfd_canonicalize_reloc (abfd, sec, relpp, isympp);
4ede5d
       free (relpp);
4ede5d
       if (relcount != 0)
4ede5d
-	goto done;
4ede5d
+	{
4ede5d
+	  if (! is_strip)
4ede5d
+	    non_fatal (_("%s[%s]: Cannot merge - there are relocations against this section"),
4ede5d
+		       bfd_get_filename (abfd), bfd_section_name (abfd, sec));
4ede5d
+	  goto done;
4ede5d
+	}
4ede5d
     }
4ede5d
   
4ede5d
   /* Make a copy of the notes and convert to our internal format.
4ede5d
-     Minimum size of a note is 12 bytes.  */
4ede5d
-  pnote = pnotes = (objcopy_internal_note *) xcalloc ((size / 12), sizeof (* pnote));
4ede5d
+     Minimum size of a note is 12 bytes.  Also locate the version
4ede5d
+     notes and check them.  */
4ede5d
+  pnote = pnotes = (objcopy_internal_note *)
4ede5d
+    xcalloc ((size / 12), sizeof (* pnote));
4ede5d
   while (remain >= 12)
4ede5d
     {
4ede5d
       bfd_vma start, end;
4ede5d
 
4ede5d
-      pnote->note.namesz = (bfd_get_32 (abfd, in    ) + 3) & ~3;
4ede5d
-      pnote->note.descsz = (bfd_get_32 (abfd, in + 4) + 3) & ~3;
4ede5d
-      pnote->note.type   =  bfd_get_32 (abfd, in + 8);
4ede5d
+      pnote->note.namesz   = bfd_get_32 (abfd, in);
4ede5d
+      pnote->note.descsz   = bfd_get_32 (abfd, in + 4);
4ede5d
+      pnote->note.type     = bfd_get_32 (abfd, in + 8);
4ede5d
+      pnote->padded_namesz = (pnote->note.namesz + 3) & ~3;
4ede5d
+
4ede5d
+      if (((pnote->note.descsz + 3) & ~3) != pnote->note.descsz)
4ede5d
+	{
4ede5d
+	  err = _("corrupt GNU build attribute note: description size not a factor of 4");
4ede5d
+	  goto done;
4ede5d
+	}
4ede5d
 
4ede5d
       if (pnote->note.type    != NT_GNU_BUILD_ATTRIBUTE_OPEN
4ede5d
 	  && pnote->note.type != NT_GNU_BUILD_ATTRIBUTE_FUNC)
4ede5d
@@ -2013,7 +2140,7 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
 	  goto done;
4ede5d
 	}
4ede5d
 
4ede5d
-      if (pnote->note.namesz + pnote->note.descsz + 12 > remain)
4ede5d
+      if (pnote->padded_namesz + pnote->note.descsz + 12 > remain)
4ede5d
 	{
4ede5d
 	  err = _("corrupt GNU build attribute note: note too big");
4ede5d
 	  goto done;
4ede5d
@@ -2026,21 +2153,17 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
 	}
4ede5d
 
4ede5d
       pnote->note.namedata = (char *)(in + 12);
4ede5d
-      pnote->note.descdata = (char *)(in + 12 + pnote->note.namesz);
4ede5d
+      pnote->note.descdata = (char *)(in + 12 + pnote->padded_namesz);
4ede5d
 
4ede5d
-      remain -= 12 + pnote->note.namesz + pnote->note.descsz;
4ede5d
-      in     += 12 + pnote->note.namesz + pnote->note.descsz;
4ede5d
+      remain -= 12 + pnote->padded_namesz + pnote->note.descsz;
4ede5d
+      in     += 12 + pnote->padded_namesz + pnote->note.descsz;
4ede5d
 
4ede5d
       if (pnote->note.namesz > 2
4ede5d
 	  && pnote->note.namedata[0] == '$'
4ede5d
 	  && pnote->note.namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION
4ede5d
 	  && pnote->note.namedata[2] == '1')
4ede5d
 	++ version_1_seen;
4ede5d
-      else if (pnote->note.namesz > 4
4ede5d
-	       && pnote->note.namedata[0] == 'G'
4ede5d
-	       && pnote->note.namedata[1] == 'A'
4ede5d
-	       && pnote->note.namedata[2] == '$'
4ede5d
-	       && pnote->note.namedata[3] == GNU_BUILD_ATTRIBUTE_VERSION)
4ede5d
+      else if (is_version_note (pnote))
4ede5d
 	{
4ede5d
 	  if (pnote->note.namedata[4] == '2')
4ede5d
 	    ++ version_2_seen;
4ede5d
@@ -2146,11 +2269,18 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
 
4ede5d
   if (version_1_seen == 0 && version_2_seen == 0 && version_3_seen == 0)
4ede5d
     {
4ede5d
+#if 0
4ede5d
       err = _("bad GNU build attribute notes: no known versions detected");
4ede5d
       goto done;
4ede5d
+#else
4ede5d
+      /* This happens with glibc.  No idea why.  */
4ede5d
+      non_fatal (_("%s[%s]: Warning: version note missing - assuming version 3"),
4ede5d
+		 bfd_get_filename (abfd), bfd_section_name (abfd, sec));
4ede5d
+      version_3_seen = 2;
4ede5d
+#endif
4ede5d
     }
4ede5d
 
4ede5d
-  if ((version_1_seen > 0 && version_2_seen > 0)
4ede5d
+  if (   (version_1_seen > 0 && version_2_seen > 0)
4ede5d
       || (version_1_seen > 0 && version_3_seen > 0)
4ede5d
       || (version_2_seen > 0 && version_3_seen > 0))
4ede5d
     {
4ede5d
@@ -2158,271 +2288,215 @@ merge_gnu_build_notes (bfd * abfd, asect
4ede5d
       goto done;
4ede5d
     }
4ede5d
 
4ede5d
-  /* Merging is only needed if there is more than one version note...  */
4ede5d
-  if (version_1_seen == 1 || version_2_seen == 1 || version_3_seen == 1)
4ede5d
-    goto done;
4ede5d
-
4ede5d
-  attribute_type_byte = version_1_seen ? 1 : 3;
4ede5d
-  val_start = attribute_type_byte + 1;
4ede5d
-
4ede5d
-  /* The first note should be the first version note.  */
4ede5d
-  if (pnotes[0].note.namedata[attribute_type_byte] != GNU_BUILD_ATTRIBUTE_VERSION)
4ede5d
+  /* We are now only supporting the merging v3+ notes
4ede5d
+     - it makes things much simpler.  */
4ede5d
+  if (version_3_seen == 0)
4ede5d
     {
4ede5d
-      err = _("bad GNU build attribute notes: first note not version note");
4ede5d
+      merge_debug ("%s: skipping merge - not using v3 notes", bfd_section_name (sec));
4ede5d
       goto done;
4ede5d
     }
4ede5d
 
4ede5d
+  merge_debug ("Merging section %s which contains %ld notes\n",
4ede5d
+	       sec->name, pnotes_end - pnotes);
4ede5d
+
4ede5d
+  /* Sort the notes.  */
4ede5d
+  qsort (pnotes, pnotes_end - pnotes, sizeof (* pnotes),
4ede5d
+	 compare_gnu_build_notes);
4ede5d
+
4ede5d
+#if DEBUG_MERGE
4ede5d
+  merge_debug ("Results of initial sort:\n");
4ede5d
+  for (pnote = pnotes; pnote < pnotes_end; pnote ++)
4ede5d
+    merge_debug ("offset %#08lx range %#08lx..%#08lx type %ld attribute %d namesz %ld\n",
4ede5d
+		 (pnote->note.namedata - (char *) contents) - 12,
4ede5d
+		 pnote->start, pnote->end,
4ede5d
+		 pnote->note.type,
4ede5d
+		 pnote->note.namedata[3],
4ede5d
+		 pnote->note.namesz
4ede5d
+		 );
4ede5d
+#endif
4ede5d
+
4ede5d
   /* Now merge the notes.  The rules are:
4ede5d
-     1. Preserve the ordering of the notes.
4ede5d
-     2. Preserve any NT_GNU_BUILD_ATTRIBUTE_FUNC notes.
4ede5d
-     3. Eliminate any NT_GNU_BUILD_ATTRIBUTE_OPEN notes that have the same
4ede5d
-        full name field as the immediately preceeding note with the same type
4ede5d
-	of name and whose address ranges coincide.
4ede5d
-	IE - if there are gaps in the coverage of the notes, then these gaps
4ede5d
-	must be preserved.
4ede5d
-     4. Combine the numeric value of any NT_GNU_BUILD_ATTRIBUTE_OPEN notes
4ede5d
-        of type GNU_BUILD_ATTRIBUTE_STACK_SIZE.
4ede5d
-     5. If an NT_GNU_BUILD_ATTRIBUTE_OPEN note is going to be preserved and
4ede5d
-        its description field is empty then the nearest preceeding OPEN note
4ede5d
-	with a non-empty description field must also be preserved *OR* the
4ede5d
-	description field of the note must be changed to contain the starting
4ede5d
-	address to which it refers.
4ede5d
-     6. Notes with the same start and end address can be deleted.  */
4ede5d
+     1. If a note has a zero range, it can be eliminated.
4ede5d
+     2. If two notes have the same namedata then:
4ede5d
+        2a. If one note's range is fully covered by the other note
4ede5d
+	    then it can be deleted.
4ede5d
+	2b. If one note's range partially overlaps or adjoins the
4ede5d
+	    other note then if they are both of the same type (open
4ede5d
+	    or func) then they can be merged and one deleted.  If
4ede5d
+	    they are of different types then they cannot be merged.  */
4ede5d
   for (pnote = pnotes + 1; pnote < pnotes_end; pnote ++)
4ede5d
     {
4ede5d
-      int                      note_type;
4ede5d
-      objcopy_internal_note *  back;
4ede5d
-      objcopy_internal_note *  prev_open_with_range = NULL;
4ede5d
+      /* Skip already deleted notes.
4ede5d
+	 FIXME: Can this happen ?  We are scanning forwards and
4ede5d
+	 deleting backwards after all.  */
4ede5d
+      if (is_deleted_note (pnote))
4ede5d
+	continue;
4ede5d
 
4ede5d
-      /* Rule 6 - delete 0-range notes.  */
4ede5d
+      /* Rule 1 - delete 0-range notes.  */
4ede5d
       if (pnote->start == pnote->end)
4ede5d
 	{
4ede5d
-	  duplicate_found = TRUE;
4ede5d
+	  merge_debug ("Delete note at offset %#08lx - empty range\n",
4ede5d
+		       (pnote->note.namedata - (char *) contents) - 12);
4ede5d
 	  pnote->note.type = 0;
4ede5d
 	  continue;
4ede5d
 	}
4ede5d
 
4ede5d
-      /* Rule 2 - preserve function notes.  */
4ede5d
-      if (! is_open_note (pnote))
4ede5d
-	{
4ede5d
-	  int iter;
4ede5d
-
4ede5d
-	  /* Check to see if there is an identical previous function note.
4ede5d
-	     This can happen with overlays for example.  */
4ede5d
-	  for (iter = 0, back = pnote -1; back >= pnotes; back --)
4ede5d
-	    {
4ede5d
-	      if (back->start == pnote->start
4ede5d
-		  && back->end == pnote->end
4ede5d
-		  && back->note.namesz == pnote->note.namesz
4ede5d
-		  && memcmp (back->note.namedata, pnote->note.namedata, pnote->note.namesz) == 0)
4ede5d
-		{
4ede5d
-		  duplicate_found = TRUE;
4ede5d
-		  pnote->note.type = 0;
4ede5d
-		  break;
4ede5d
-		}
4ede5d
-
4ede5d
-	      /* Don't scan too far back however.  */
4ede5d
-	      if (iter ++ > 16)
4ede5d
-		break;
4ede5d
-	    }
4ede5d
-	  continue;
4ede5d
-	}
4ede5d
-
4ede5d
-      note_type = pnote->note.namedata[attribute_type_byte];
4ede5d
-
4ede5d
-      /* Scan backwards from pnote, looking for duplicates.
4ede5d
-	 Clear the type field of any found - but do not delete them just yet.  */
4ede5d
-      for (back = pnote - 1; back >= pnotes; back --)
4ede5d
-	{
4ede5d
-	  int back_type = back->note.namedata[attribute_type_byte];
4ede5d
-
4ede5d
-	  /* If this is the first open note with an address
4ede5d
-	     range that	we have encountered then record it.  */
4ede5d
-	  if (prev_open_with_range == NULL
4ede5d
-	      && back->note.descsz > 0
4ede5d
-	      && ! is_func_note (back))
4ede5d
-	    prev_open_with_range = back;
4ede5d
-
4ede5d
-	  if (! is_open_note (back))
4ede5d
-	    continue;
4ede5d
+      int iter;
4ede5d
+      objcopy_internal_note * back;
4ede5d
 
4ede5d
-	  /* If the two notes are different then keep on searching.  */
4ede5d
-	  if (back_type != note_type)
4ede5d
+      /* Rule 2: Check to see if there is an identical previous note.  */
4ede5d
+      for (iter = 0, back = pnote - 1; back >= pnotes; back --)
4ede5d
+	{
4ede5d
+	  if (is_deleted_note (back))
4ede5d
 	    continue;
4ede5d
 
4ede5d
-	  /* Rule 4 - combine stack size notes.  */
4ede5d
-	  if (back_type == GNU_BUILD_ATTRIBUTE_STACK_SIZE)
4ede5d
+	  /* Our sorting function should have placed all identically
4ede5d
+	     attributed notes together, so if we see a note of a different
4ede5d
+	     attribute type stop searching.  */
4ede5d
+	  if (back->note.namesz != pnote->note.namesz
4ede5d
+	      || memcmp (back->note.namedata,
4ede5d
+			 pnote->note.namedata, pnote->note.namesz) != 0)
4ede5d
+	    break;
4ede5d
+	  
4ede5d
+	  if (back->start == pnote->start
4ede5d
+	      && back->end == pnote->end)
4ede5d
 	    {
4ede5d
-	      unsigned char * name;
4ede5d
-	      unsigned long   note_val;
4ede5d
-	      unsigned long   back_val;
4ede5d
-	      unsigned int    shift;
4ede5d
-	      unsigned int    bytes;
4ede5d
-	      unsigned long   byte;
4ede5d
-
4ede5d
-	      for (shift = 0, note_val = 0,
4ede5d
-		     bytes = pnote->note.namesz - val_start,
4ede5d
-		     name = (unsigned char *) pnote->note.namedata + val_start;
4ede5d
-		   bytes--;)
4ede5d
-		{
4ede5d
-		  byte = (* name ++) & 0xff;
4ede5d
-		  note_val |= byte << shift;
4ede5d
-		  shift += 8;
4ede5d
-		}
4ede5d
-
4ede5d
-	      for (shift = 0, back_val = 0,
4ede5d
-		     bytes = back->note.namesz - val_start,
4ede5d
-		     name = (unsigned char *) back->note.namedata + val_start;
4ede5d
-		   bytes--;)
4ede5d
-		{
4ede5d
-		  byte = (* name ++) & 0xff;
4ede5d
-		  back_val |= byte << shift;
4ede5d
-		  shift += 8;
4ede5d
-		}
4ede5d
-
4ede5d
-	      back_val += note_val;
4ede5d
-	      if (num_bytes (back_val) >= back->note.namesz - val_start)
4ede5d
-		{
4ede5d
-		  /* We have a problem - the new value requires more bytes of
4ede5d
-		     storage in the name field than are available.  Currently
4ede5d
-		     we have no way of fixing this, so we just preserve both
4ede5d
-		     notes.  */
4ede5d
-		  continue;
4ede5d
-		}
4ede5d
-
4ede5d
-	      /* Write the new val into back.  */
4ede5d
-	      name = (unsigned char *) back->note.namedata + val_start;
4ede5d
-	      while (name < (unsigned char *) back->note.namedata
4ede5d
-		     + back->note.namesz)
4ede5d
-		{
4ede5d
-		  byte = back_val & 0xff;
4ede5d
-		  * name ++ = byte;
4ede5d
-		  if (back_val == 0)
4ede5d
-		    break;
4ede5d
-		  back_val >>= 8;
4ede5d
-		}
4ede5d
-
4ede5d
-	      duplicate_found = TRUE;
4ede5d
+	      merge_debug ("Delete note at offset %#08lx - duplicate of note at offset %#08lx\n",
4ede5d
+			   (pnote->note.namedata - (char *) contents) - 12,
4ede5d
+			   (back->note.namedata - (char *) contents) - 12);
4ede5d
 	      pnote->note.type = 0;
4ede5d
 	      break;
4ede5d
 	    }
4ede5d
 
4ede5d
-	  /* Rule 3 - combine identical open notes.  */
4ede5d
-	  if (back->note.namesz == pnote->note.namesz
4ede5d
-	      && memcmp (back->note.namedata,
4ede5d
-			 pnote->note.namedata, back->note.namesz) == 0
4ede5d
-	      && ! gap_exists (back, pnote))
4ede5d
+	  /* Rule 2a.  */
4ede5d
+	  if (contained_by (pnote, back))
4ede5d
 	    {
4ede5d
-	      duplicate_found = TRUE;
4ede5d
+	      merge_debug ("Delete note at offset %#08lx - fully contained by note at %#08lx\n",
4ede5d
+			   (pnote->note.namedata - (char *) contents) - 12,
4ede5d
+			   (back->note.namedata - (char *) contents) - 12);
4ede5d
 	      pnote->note.type = 0;
4ede5d
+	      break;
4ede5d
+	    }
4ede5d
 
4ede5d
-	      if (pnote->end > back->end)
4ede5d
-		back->end = pnote->end;
4ede5d
+#if DEBUG_MERGE
4ede5d
+	  /* This should not happen as we have sorted the
4ede5d
+	     notes with earlier starting addresses first.  */
4ede5d
+	  if (contained_by (back, pnote))
4ede5d
+	    merge_debug ("ERROR: UNEXPECTED CONTAINMENT\n");
4ede5d
+#endif
4ede5d
+
4ede5d
+	  /* Rule 2b.  */
4ede5d
+	  if (overlaps_or_adjoins (back, pnote)
4ede5d
+	      && is_func_note (back) == is_func_note (pnote))
4ede5d
+	    {
4ede5d
+	      merge_debug ("Delete note at offset %#08lx - merge into note at %#08lx\n",
4ede5d
+			   (pnote->note.namedata - (char *) contents) - 12,
4ede5d
+			   (back->note.namedata - (char *) contents) - 12);
4ede5d
 
4ede5d
-	      if (version_3_seen)
4ede5d
-		back->modified = TRUE;
4ede5d
+	      back->end   = back->end > pnote->end ? back->end : pnote->end;
4ede5d
+	      back->start = back->start < pnote->start ? back->start : pnote->start;
4ede5d
+	      pnote->note.type = 0;
4ede5d
 	      break;
4ede5d
 	    }
4ede5d
 
4ede5d
-	  /* Rule 5 - Since we are keeping this note we must check to see
4ede5d
-	     if its description refers back to an earlier OPEN version
4ede5d
-	     note that has been scheduled for deletion.  If so then we
4ede5d
-	     must make sure that version note is also preserved.  */
4ede5d
-	  if (version_3_seen)
4ede5d
-	    {
4ede5d
-	      /* As of version 3 we can just
4ede5d
-		 move the range into the note.  */
4ede5d
-	      pnote->modified = TRUE;
4ede5d
-	      pnote->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC;
4ede5d
-	      back->modified = TRUE;
4ede5d
-	      back->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC;
4ede5d
-	    }
4ede5d
-	  else
4ede5d
+	  /* Don't scan too far back however.  */
4ede5d
+	  if (iter ++ > 16)
4ede5d
 	    {
4ede5d
-	      if (pnote->note.descsz == 0
4ede5d
-		  && prev_open_with_range != NULL
4ede5d
-		  && prev_open_with_range->note.type == 0)
4ede5d
-		prev_open_with_range->note.type = NT_GNU_BUILD_ATTRIBUTE_OPEN;
4ede5d
+	      /* FIXME: Not sure if this can ever be triggered.  */
4ede5d
+	      merge_debug ("ITERATION LIMIT REACHED\n");
4ede5d
+	      break;
4ede5d
 	    }
4ede5d
-
4ede5d
-	  /* We have found a similar attribute but the details do not match.
4ede5d
-	     Stop searching backwards.  */
4ede5d
-	  break;
4ede5d
 	}
4ede5d
-    }
4ede5d
-
4ede5d
-  if (duplicate_found)
4ede5d
-    {
4ede5d
-      bfd_byte *     new_contents;
4ede5d
-      bfd_byte *     old;
4ede5d
-      bfd_byte *     new;
4ede5d
-      bfd_size_type  new_size;
4ede5d
-      bfd_vma        prev_start = 0;
4ede5d
-      bfd_vma        prev_end = 0;
4ede5d
-
4ede5d
-      /* Eliminate the duplicates.  */
4ede5d
-      new = new_contents = xmalloc (size);
4ede5d
-      for (pnote = pnotes, old = contents;
4ede5d
-	   pnote < pnotes_end;
4ede5d
-	   pnote ++)
4ede5d
-	{
4ede5d
-	  bfd_size_type note_size = 12 + pnote->note.namesz + pnote->note.descsz;
4ede5d
-
4ede5d
-	  if (pnote->note.type != 0)
4ede5d
+#if DEBUG_MERGE
4ede5d
+      if (! is_deleted_note (pnote))
4ede5d
+	merge_debug ("Unable to do anything with note at %#08lx\n",
4ede5d
+		     (pnote->note.namedata - (char *) contents) - 12);
4ede5d
+#endif		     
4ede5d
+    }
4ede5d
+
4ede5d
+  /* Resort the notes.  */
4ede5d
+  merge_debug ("Final sorting of notes\n");
4ede5d
+  qsort (pnotes, pnotes_end - pnotes, sizeof (* pnotes), sort_gnu_build_notes);
4ede5d
+
4ede5d
+  /* Reconstruct the ELF notes.  */
4ede5d
+  bfd_byte *     new_contents;
4ede5d
+  bfd_byte *     old;
4ede5d
+  bfd_byte *     new;
4ede5d
+  bfd_size_type  new_size;
4ede5d
+  bfd_vma        prev_start = 0;
4ede5d
+  bfd_vma        prev_end = 0;
4ede5d
+
4ede5d
+  new = new_contents = xmalloc (size);
4ede5d
+  for (pnote = pnotes, old = contents;
4ede5d
+       pnote < pnotes_end;
4ede5d
+       pnote ++)
4ede5d
+    {
4ede5d
+      bfd_size_type note_size = 12 + pnote->padded_namesz + pnote->note.descsz;
4ede5d
+
4ede5d
+      if (! is_deleted_note (pnote))
4ede5d
+	{
4ede5d
+	  /* Create the note, potentially using the
4ede5d
+	     address range of the previous note.  */
4ede5d
+	  if (pnote->start == prev_start && pnote->end == prev_end)
4ede5d
+	    {
4ede5d
+	      bfd_put_32 (abfd, pnote->note.namesz, new);
4ede5d
+	      bfd_put_32 (abfd, 0, new + 4);
4ede5d
+	      bfd_put_32 (abfd, pnote->note.type, new + 8);
4ede5d
+	      new += 12;
4ede5d
+	      memcpy (new, pnote->note.namedata, pnote->note.namesz);
4ede5d
+	      if (pnote->note.namesz < pnote->padded_namesz)
4ede5d
+		memset (new + pnote->note.namesz, 0, pnote->padded_namesz - pnote->note.namesz);
4ede5d
+	      new += pnote->padded_namesz;
4ede5d
+	    }
4ede5d
+	  else
4ede5d
 	    {
4ede5d
-	      if (pnote->modified)
4ede5d
+	      bfd_put_32 (abfd, pnote->note.namesz, new);
4ede5d
+	      bfd_put_32 (abfd, is_64bit (abfd) ? 16 : 8, new + 4);
4ede5d
+	      bfd_put_32 (abfd, pnote->note.type, new + 8);
4ede5d
+	      new += 12;
4ede5d
+	      memcpy (new, pnote->note.namedata, pnote->note.namesz);
4ede5d
+	      if (pnote->note.namesz < pnote->padded_namesz)
4ede5d
+		memset (new + pnote->note.namesz, 0, pnote->padded_namesz - pnote->note.namesz);
4ede5d
+	      new += pnote->padded_namesz;
4ede5d
+	      if (is_64bit (abfd))
4ede5d
 		{
4ede5d
-		  /* If the note has been modified then we must copy it by
4ede5d
-		     hand, potentially adding in a new description field.  */
4ede5d
-		  if (pnote->start == prev_start && pnote->end == prev_end)
4ede5d
-		    {
4ede5d
-		      bfd_put_32 (abfd, pnote->note.namesz, new);
4ede5d
-		      bfd_put_32 (abfd, 0, new + 4);
4ede5d
-		      bfd_put_32 (abfd, pnote->note.type, new + 8);
4ede5d
-		      new += 12;
4ede5d
-		      memcpy (new, pnote->note.namedata, pnote->note.namesz);
4ede5d
-		      new += pnote->note.namesz;
4ede5d
-		    }
4ede5d
-		  else
4ede5d
-		    {
4ede5d
-		      bfd_put_32 (abfd, pnote->note.namesz, new);
4ede5d
-		      bfd_put_32 (abfd, is_64bit (abfd) ? 16 : 8, new + 4);
4ede5d
-		      bfd_put_32 (abfd, pnote->note.type, new + 8);
4ede5d
-		      new += 12;
4ede5d
-		      memcpy (new, pnote->note.namedata, pnote->note.namesz);
4ede5d
-		      new += pnote->note.namesz;
4ede5d
-		      if (is_64bit (abfd))
4ede5d
-			{
4ede5d
-			  bfd_put_64 (abfd, pnote->start, new);
4ede5d
-			  bfd_put_64 (abfd, pnote->end, new + 8);
4ede5d
-			  new += 16;
4ede5d
-			}
4ede5d
-		      else
4ede5d
-			{
4ede5d
-			  bfd_put_32 (abfd, pnote->start, new);
4ede5d
-			  bfd_put_32 (abfd, pnote->end, new + 4);
4ede5d
-			  new += 8;
4ede5d
-			}
4ede5d
-		    }
4ede5d
+		  bfd_put_64 (abfd, pnote->start, new);
4ede5d
+		  bfd_put_64 (abfd, pnote->end, new + 8);
4ede5d
+		  new += 16;
4ede5d
 		}
4ede5d
 	      else
4ede5d
 		{
4ede5d
-		  memcpy (new, old, note_size);
4ede5d
-		  new += note_size;
4ede5d
+		  bfd_put_32 (abfd, pnote->start, new);
4ede5d
+		  bfd_put_32 (abfd, pnote->end, new + 4);
4ede5d
+		  new += 8;
4ede5d
 		}
4ede5d
+
4ede5d
 	      prev_start = pnote->start;
4ede5d
 	      prev_end = pnote->end;
4ede5d
 	    }
4ede5d
-
4ede5d
-	  old += note_size;
4ede5d
 	}
4ede5d
 
4ede5d
-      new_size = new - new_contents;
4ede5d
-      memcpy (contents, new_contents, new_size);
4ede5d
-      size = new_size;
4ede5d
-      free (new_contents);
4ede5d
+      old += note_size;
4ede5d
     }
4ede5d
 
4ede5d
+#if DEBUG_MERGE
4ede5d
+  merge_debug ("Results of merge:\n");
4ede5d
+  for (pnote = pnotes; pnote < pnotes_end; pnote ++)
4ede5d
+    if (! is_deleted_note (pnote))
4ede5d
+      merge_debug ("offset %#08lx range %#08lx..%#08lx type %ld attribute %d namesz %ld\n",
4ede5d
+		   (pnote->note.namedata - (char *) contents) - 12,
4ede5d
+		   pnote->start, pnote->end,
4ede5d
+		   pnote->note.type,
4ede5d
+		   pnote->note.namedata[3],
4ede5d
+		   pnote->note.namesz
4ede5d
+		   );
4ede5d
+#endif
4ede5d
+  
4ede5d
+  new_size = new - new_contents;
4ede5d
+  memcpy (contents, new_contents, new_size);
4ede5d
+  size = new_size;
4ede5d
+  free (new_contents);
4ede5d
+
4ede5d
  done:
4ede5d
   if (err)
4ede5d
     {
4ede5d
@@ -2761,52 +2835,61 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	}
4ede5d
     }
4ede5d
 
4ede5d
+  merged_note_section * merged_note_sections = NULL;
4ede5d
   if (merge_notes)
4ede5d
     {
4ede5d
       /* This palaver is necessary because we must set the output
4ede5d
 	 section size first, before its contents are ready.  */
4ede5d
-      osec = bfd_get_section_by_name (ibfd, GNU_BUILD_ATTRS_SECTION_NAME);
4ede5d
-      if (osec && is_merged_note_section (ibfd, osec))
4ede5d
+      for (osec = ibfd->sections; osec != NULL; osec = osec->next)
4ede5d
 	{
4ede5d
-	  bfd_size_type size;
4ede5d
-	  
4ede5d
-	  size = bfd_get_section_size (osec);
4ede5d
+	  if (! is_mergeable_note_section (ibfd, osec))
4ede5d
+	    continue;
4ede5d
+
4ede5d
+	  bfd_size_type size = bfd_section_size (obfd, osec);
4ede5d
 	  if (size == 0)
4ede5d
 	    {
4ede5d
-	      bfd_nonfatal_message (NULL, ibfd, osec, _("warning: note section is empty"));
4ede5d
-	      merge_notes = FALSE;
4ede5d
+	      bfd_nonfatal_message (NULL, ibfd, osec,
4ede5d
+				    _("warning: note section is empty"));
4ede5d
+	      continue;
4ede5d
 	    }
4ede5d
-	  else if (! bfd_get_full_section_contents (ibfd, osec, & merged_notes))
4ede5d
+
4ede5d
+	  merged_note_section * merged = xmalloc (sizeof * merged);
4ede5d
+	  merged->contents = NULL;
4ede5d
+	  if (! bfd_get_full_section_contents (ibfd, osec, & merged->contents))
4ede5d
 	    {
4ede5d
-	      bfd_nonfatal_message (NULL, ibfd, osec, _("warning: could not load note section"));
4ede5d
-	      free (merged_notes);
4ede5d
-	      merged_notes = NULL;
4ede5d
-	      merge_notes = FALSE;
4ede5d
+	      bfd_nonfatal_message (NULL, ibfd, osec,
4ede5d
+				    _("warning: could not load note section"));
4ede5d
+	      free (merged->contents);
4ede5d
+	      free (merged);
4ede5d
+	      continue;
4ede5d
 	    }
4ede5d
-	  else
4ede5d
+
4ede5d
+	  merged->size = merge_gnu_build_notes (ibfd, osec, size,
4ede5d
+						merged->contents);
4ede5d
+	  if (merged->size == size)
4ede5d
+	    {
4ede5d
+	      /* Merging achieves nothing.  */
4ede5d
+	      merge_debug ("Merge of section %s achieved nothing - skipping\n",
4ede5d
+			   bfd_section_name (obfd, osec));
4ede5d
+	      free (merged->contents);
4ede5d
+	      free (merged);
4ede5d
+	      continue;
4ede5d
+	    }
4ede5d
+
4ede5d
+	  if (osec->output_section == NULL
4ede5d
+	      || !bfd_set_section_size (obfd, osec->output_section, merged->size))
4ede5d
 	    {
4ede5d
-	      merged_size = merge_gnu_build_notes (ibfd, osec, size, merged_notes);
4ede5d
-	      if (merged_size == size)
4ede5d
-		{
4ede5d
-		  /* Merging achieves nothing.  */
4ede5d
-		  free (merged_notes);
4ede5d
-		  merged_notes = NULL;
4ede5d
-		  merge_notes = FALSE;
4ede5d
-		  merged_size = 0;
4ede5d
-		}
4ede5d
-	      else
4ede5d
-		{
4ede5d
-		  if (osec->output_section == NULL
4ede5d
-		      || ! bfd_set_section_size (obfd, osec->output_section, merged_size))
4ede5d
-		    {
4ede5d
-		      bfd_nonfatal_message (NULL, obfd, osec, _("warning: failed to set merged notes size"));
4ede5d
-		      free (merged_notes);
4ede5d
-		      merged_notes = NULL;
4ede5d
-		      merge_notes = FALSE;
4ede5d
-		      merged_size = 0;
4ede5d
-		    }
4ede5d
-		}
4ede5d
+	      bfd_nonfatal_message (NULL, obfd, osec,
4ede5d
+				    _("warning: failed to set merged notes size"));
4ede5d
+	      free (merged->contents);
4ede5d
+	      free (merged);
4ede5d
+	      continue;
4ede5d
 	    }
4ede5d
+
4ede5d
+	  /* Add section to list of merged sections.  */
4ede5d
+	  merged->sec  = osec;
4ede5d
+	  merged->next = merged_note_sections;
4ede5d
+	  merged_note_sections = merged;
4ede5d
 	}
4ede5d
     }
4ede5d
 
4ede5d
@@ -3134,25 +3217,72 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	}
4ede5d
     }
4ede5d
 
4ede5d
-  if (merge_notes)
4ede5d
+  if (merged_note_sections != NULL)
4ede5d
     {
4ede5d
-      osec = bfd_get_section_by_name (obfd, GNU_BUILD_ATTRS_SECTION_NAME);
4ede5d
-      if (osec && is_merged_note_section (obfd, osec))
4ede5d
+      merged_note_section * merged = NULL;
4ede5d
+
4ede5d
+      for (osec = obfd->sections; osec != NULL; osec = osec->next)
4ede5d
 	{
4ede5d
-	  if (! bfd_set_section_contents (obfd, osec, merged_notes, 0, merged_size))
4ede5d
+	  if (! is_mergeable_note_section (obfd, osec))
4ede5d
+	    continue;
4ede5d
+
4ede5d
+	  if (merged == NULL)
4ede5d
+	    merged = merged_note_sections;
4ede5d
+
4ede5d
+	  /* It is likely that output sections are in the same order
4ede5d
+	     as the input sections, but do not assume that this is
4ede5d
+	     the case.  */
4ede5d
+	  if (strcmp (bfd_section_name (obfd, merged->sec),
4ede5d
+		      bfd_section_name (obfd, osec)) != 0)
4ede5d
+	    {
4ede5d
+	      for (merged = merged_note_sections;
4ede5d
+		   merged != NULL;
4ede5d
+		   merged = merged->next)
4ede5d
+		if (strcmp (bfd_section_name (obfd, merged->sec),
4ede5d
+			    bfd_section_name (obfd, osec)) == 0)
4ede5d
+		  break;
4ede5d
+
4ede5d
+	      if (merged == NULL)
4ede5d
+		{
4ede5d
+		  bfd_nonfatal_message
4ede5d
+		    (NULL, obfd, osec,
4ede5d
+		     _("error: failed to copy merged notes into output"));
4ede5d
+		  continue;
4ede5d
+		}
4ede5d
+	    }
4ede5d
+
4ede5d
+	  if (! is_mergeable_note_section (obfd, osec))
4ede5d
 	    {
4ede5d
-	      bfd_nonfatal_message (NULL, obfd, osec, _("error: failed to copy merged notes into output"));
4ede5d
-	      /* There is a potential resource leak here, but it is not important.  */
4ede5d
-	      /* coverity[leaked_storage: FALSE] */
4ede5d
+	      bfd_nonfatal_message
4ede5d
+		(NULL, obfd, osec,
4ede5d
+		 _("error: failed to copy merged notes into output"));
4ede5d
+	      continue;
4ede5d
+	    }
4ede5d
+
4ede5d
+	  if (! bfd_set_section_contents (obfd, osec, merged->contents, 0,
4ede5d
+					  merged->size))
4ede5d
+	    {
4ede5d
+	      bfd_nonfatal_message
4ede5d
+		(NULL, obfd, osec,
4ede5d
+		 _("error: failed to copy merged notes into output"));
4ede5d
 	      return FALSE;
4ede5d
 	    }
4ede5d
+
4ede5d
+	  merged = merged->next;
4ede5d
+	}
4ede5d
+
4ede5d
+      /* Free the memory.  */
4ede5d
+      merged_note_section * next;
4ede5d
+      for (merged = merged_note_sections; merged != NULL; merged = next)
4ede5d
+	{
4ede5d
+	  next = merged->next;
4ede5d
+	  free (merged->contents);
4ede5d
+	  free (merged);
4ede5d
 	}
4ede5d
-      else if (! is_strip)
4ede5d
-	bfd_nonfatal_message (NULL, obfd, osec, _("could not find any mergeable note sections"));
4ede5d
-      free (merged_notes);
4ede5d
-      merged_notes = NULL;
4ede5d
-      merge_notes = FALSE;
4ede5d
     }
4ede5d
+  else if (merge_notes && ! is_strip)
4ede5d
+    non_fatal (_("%s: Could not find any mergeable note sections"),
4ede5d
+	       bfd_get_filename (ibfd));
4ede5d
 
4ede5d
   if (gnu_debuglink_filename != NULL)
4ede5d
     {
4ede5d
@@ -3915,7 +4045,7 @@ skip_section (bfd *ibfd, sec_ptr isectio
4ede5d
 
4ede5d
   /* When merging a note section we skip the copying of the contents,
4ede5d
      but not the copying of the relocs associated with the contents.  */
4ede5d
-  if (skip_copy && is_merged_note_section (ibfd, isection))
4ede5d
+  if (skip_copy && is_mergeable_note_section (ibfd, isection))
4ede5d
     return TRUE;
4ede5d
 
4ede5d
   flags = bfd_get_section_flags (ibfd, isection);
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-2-32.d binutils-2.30/binutils/testsuite/binutils-all/note-2-32.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-2-32.d	2019-10-28 17:08:43.358324887 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-2-32.d	2019-10-28 17:16:57.804615900 +0000
4ede5d
@@ -5,13 +5,12 @@
4ede5d
 #source: note-2-32.s
4ede5d
 
4ede5d
 #...
4ede5d
-  Owner                 Data size	Description
4ede5d
-[ 	]+\$<version>1[ 	]+0x00000004[ 	]+OPEN[ 	]+Applies to region from 0x100 \(note1.s\)
4ede5d
-[ 	]+\$<tool>gcc 7.0.1[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\+<stack prot>true[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\*<PIC>static[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\*<ABI>0x0[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\$<version>1[ 	]+0x00000004[ 	]+OPEN[ 	]+Applies to region from 0x104 \(note2.s\)
4ede5d
-[ 	]+!<stack prot>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x104
4ede5d
-[ 	]+\*<PIC>pic[ 	]+0x00000004[ 	]+func[ 	]+Applies to region from 0x104 \(func1\)
4ede5d
+[ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x10b \(note1.s\)
4ede5d
+[ 	]+GA\$<tool>gcc 7.0.1[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x10b
4ede5d
+[ 	]+GA\*<ABI>0x0[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x108 \(note1.s\)
4ede5d
+[ 	]+GA\+<stack prot>true[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x104 \(note1.s\)
4ede5d
+[ 	]+GA\*<PIC>static[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x104
4ede5d
+[ 	]+GA!<stack prot>false[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x104 to 0x108 \(note2.s\)
4ede5d
+[ 	]+GA\*<PIC>pic[ 	]+0x00000008[ 	]+func[ 	]+Applies to region from 0x104 to 0x106 \(func1\)
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-2-32.s binutils-2.30/binutils/testsuite/binutils-all/note-2-32.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-2-32.s	2019-10-28 17:08:43.355324910 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-2-32.s	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -6,32 +6,37 @@ note1.s:
4ede5d
 	
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
 	.balign 4
4ede5d
-	.dc.l 4
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 8
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "$?1"
4ede5d
+	.asciz "GA$?3p1"
4ede5d
 	.dc.l 0x100
4ede5d
+	.dc.l 0x104
4ede5d
 
4ede5d
-	.dc.l 12
4ede5d
+	.dc.l 14
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "$?gcc 7.0.1"
4ede5d
+	.asciz "GA$?gcc 7.0.1"
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
-	.dc.l 3
4ede5d
+	.dc.l 5
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2b, 0x2, 0
4ede5d
-	.dc.b 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2b, 0x2, 0
4ede5d
+	.dc.b 0,0,0
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2a, 0x7, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
+	
4ede5d
 	.popsection
4ede5d
 
4ede5d
 
4ede5d
@@ -42,33 +47,38 @@ func1:
4ede5d
 	.dc.l 0x100
4ede5d
 	
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
-	.dc.l 4 	
4ede5d
-	.dc.l 4		
4ede5d
+	.dc.l 8	
4ede5d
+	.dc.l 8		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?1"	
4ede5d
+	.asciz "GA$?3p1"	
4ede5d
 	.dc.l 0x104	
4ede5d
-
4ede5d
-	.dc.l 12 	
4ede5d
+	.dc.l 0x108
4ede5d
+	
4ede5d
+	.dc.l 14 	
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?gcc 7.0.1"	
4ede5d
+	.asciz "GA$?gcc 7.0.1"
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
-	.dc.l 3		
4ede5d
+	.dc.l 5	
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.dc.b 0x21, 0x2, 0
4ede5d
-	.dc.b 0 	
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x2, 0
4ede5d
+	.dc.b 0,0,0
4ede5d
 
4ede5d
-	.dc.l 4		
4ede5d
-	.dc.l 4		
4ede5d
+	.dc.l 6	
4ede5d
+	.dc.l 8		
4ede5d
 	.dc.l 0x101	
4ede5d
-	.dc.b 0x2a, 0x7, 1, 0
4ede5d
-	.dc.l 0x104	
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 1, 0
4ede5d
+	.dc.b 0,0
4ede5d
+	.dc.l 0x104
4ede5d
+	.dc.l 0x106
4ede5d
 	
4ede5d
-	.dc.l 4		
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.dc.b 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
 	.popsection
4ede5d
 
4ede5d
 	
4ede5d
@@ -77,16 +87,18 @@ note3.s:
4ede5d
 	.dc.l 0x100
4ede5d
 	
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
-	.dc.l 4 	
4ede5d
-	.dc.l 4		
4ede5d
+	.dc.l 8	
4ede5d
+	.dc.l 8		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?1"	
4ede5d
+	.asciz "GA$?3p1"	
4ede5d
 	.dc.l 0x108
4ede5d
+	.dc.l 0x10b
4ede5d
 
4ede5d
-	.dc.l 12 	
4ede5d
+	.dc.l 14	
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?gcc 7.0.1"	
4ede5d
+	.asciz "GA$?gcc 7.0.1"
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
 	.popsection
4ede5d
 	
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-2-64.d binutils-2.30/binutils/testsuite/binutils-all/note-2-64.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-2-64.d	2019-10-28 17:08:43.356324902 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-2-64.d	2019-10-28 17:17:05.724556490 +0000
4ede5d
@@ -3,19 +3,18 @@
4ede5d
 #objcopy: --merge-notes
4ede5d
 #name: merge notes section (64-bits)
4ede5d
 #source: note-2-64.s
4ede5d
-#not-target: sparc64-*-*
4ede5d
+#not-target: sparc64-*-*
4ede5d
 # Internally the Sparc64 backend uses two relocs for every one reloc visible externally.
4ede5d
 # Unfortunately the BFD library does not provide a target specific way to delete individual
4ede5d
 # relocs, so the note merging feature fails.
4ede5d
 
4ede5d
 #...
4ede5d
-  Owner                 Data size	Description
4ede5d
-[ 	]+\$<version>1[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 \(note1.s\)
4ede5d
-[ 	]+\$<tool>gcc 7.0.1[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\+<stack prot>true[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\*<PIC>static[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\*<ABI>0x0[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100
4ede5d
-[ 	]+\$<version>1[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x104 \(note2.s\)
4ede5d
-[ 	]+!<stack prot>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x104
4ede5d
-[ 	]+\*<PIC>pic[ 	]+0x00000008[ 	]+func[ 	]+Applies to region from 0x104 \(func1\)
4ede5d
+[ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x10b \(note1.s\)
4ede5d
+[ 	]+GA\$<tool>gcc 7.0.1[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x10b
4ede5d
+[ 	]+GA\*<ABI>0x0[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x108 \(note1.s\)
4ede5d
+[ 	]+GA\+<stack prot>true[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x104 \(note1.s\)
4ede5d
+[ 	]+GA\*<PIC>static[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x104
4ede5d
+[ 	]+GA!<stack prot>false[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x104 to 0x108 \(note2.s\)
4ede5d
+[ 	]+GA\*<PIC>pic[ 	]+0x00000010[ 	]+func[ 	]+Applies to region from 0x104 to 0x106 \(func1\)
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-2-64.s binutils-2.30/binutils/testsuite/binutils-all/note-2-64.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-2-64.s	2019-10-28 17:08:43.354324917 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-2-64.s	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -6,32 +6,43 @@ note1.s:
4ede5d
 	
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
 	.balign 4
4ede5d
-	.dc.l 4
4ede5d
 	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "$?1"
4ede5d
+	.asciz "GA$?3p1"
4ede5d
 	.8byte 0x100
4ede5d
+	.8byte 0x104
4ede5d
 
4ede5d
-	.dc.l 12
4ede5d
+	.dc.l 14
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "$?gcc 7.0.1"
4ede5d
+	.asciz "GA$?gcc 7.0.1"
4ede5d
+	.dc.b 0,0
4ede5d
+	
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2b, 0x2, 0
4ede5d
+	.dc.b 0,0,0
4ede5d
 
4ede5d
-	.dc.l 3
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2b, 0x2, 0
4ede5d
-	.dc.b 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2a, 0x7, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0x100
4ede5d
-	.dc.b 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
+
4ede5d
 	.popsection
4ede5d
 
4ede5d
 
4ede5d
@@ -43,33 +54,38 @@ func1:
4ede5d
 	.dc.l 0x100
4ede5d
 
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
-	.dc.l 4 	
4ede5d
-	.dc.l 8		
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 16		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?1"	
4ede5d
+	.asciz "GA$?3p1"
4ede5d
 	.8byte 0x104	
4ede5d
+	.8byte 0x108	
4ede5d
 
4ede5d
-	.dc.l 12 	
4ede5d
+	.dc.l 14 	
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?gcc 7.0.1"	
4ede5d
-
4ede5d
-	.dc.l 3		
4ede5d
+	.asciz "GA$?gcc 7.0.1"	
4ede5d
+	.dc.b 0,0
4ede5d
+	
4ede5d
+	.dc.l 5		
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.dc.b 0x21, 0x2, 0
4ede5d
-	.dc.b 0 	
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x2, 0
4ede5d
+	.dc.b 0,0,7 	
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
-	.dc.l 8	
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 16
4ede5d
 	.dc.l 0x101	
4ede5d
-	.dc.b 0x2a, 0x7, 1, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 1, 0
4ede5d
+	.dc.b 0,0
4ede5d
 	.8byte 0x104	
4ede5d
+	.8byte 0x106	
4ede5d
 
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.dc.b 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0, 0
4ede5d
+	.dc.b 0,0
4ede5d
 	.popsection
4ede5d
 	
4ede5d
 
4ede5d
@@ -78,15 +94,17 @@ note3.s:
4ede5d
 	.dc.l 0x100
4ede5d
 	
4ede5d
 	.pushsection .gnu.build.attributes, "0x100000", %note
4ede5d
-	.dc.l 4 	
4ede5d
-	.dc.l 8		
4ede5d
+	.dc.l 8	
4ede5d
+	.dc.l 16	
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?1"	
4ede5d
+	.asciz "GA$?3p1"
4ede5d
 	.8byte 0x108
4ede5d
+	.8byte 0x10b
4ede5d
 
4ede5d
-	.dc.l 12 	
4ede5d
+	.dc.l 14 	
4ede5d
 	.dc.l 0		
4ede5d
 	.dc.l 0x100	
4ede5d
-	.asciz "$?gcc 7.0.1"	
4ede5d
+	.asciz "GA$?gcc 7.0.1"
4ede5d
+	.dc.b 0,0
4ede5d
 
4ede5d
 	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-3-32.d binutils-2.30/binutils/testsuite/binutils-all/note-3-32.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-3-32.d	2019-10-28 17:08:43.356324902 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-3-32.d	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -7,12 +7,12 @@
4ede5d
 #...
4ede5d
 Displaying notes found in: .gnu.build.attributes
4ede5d
 [ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
-[ 	]+GA\$<version>2p1[ 	]+0x0000000.[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122 \(note_1.s\)
4ede5d
-[ 	]+GA\$<tool>gcc 6.3.1 20161221[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x0000000.[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122 \(note_1.s\)
4ede5d
 [ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\$<tool>gcc 6.3.1 20161221[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 [ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 [ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-3-32.s binutils-2.30/binutils/testsuite/binutils-all/note-3-32.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-3-32.s	2019-10-28 17:08:43.354324917 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-3-32.s	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -9,10 +9,11 @@ note_1.s:
4ede5d
 	.balign 4
4ede5d
 
4ede5d
 	.dc.l 8
4ede5d
-	.dc.l 4
4ede5d
+	.dc.l 8
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "GA$?2p1"
4ede5d
-	.dc.l note_1.s
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.dc.l 0x100 /* note_1.s */
4ede5d
+	.dc.l 0x122 /* note_1.s end */
4ede5d
 
4ede5d
 	.dc.l 23
4ede5d
 	.dc.l 0
4ede5d
@@ -55,4 +56,12 @@ note_1.s:
4ede5d
 	.dc.l 0x100
4ede5d
 	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
 	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+
4ede5d
 	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-3-64.d binutils-2.30/binutils/testsuite/binutils-all/note-3-64.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-3-64.d	2019-10-28 17:08:43.357324895 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-3-64.d	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -7,12 +7,12 @@
4ede5d
 #...
4ede5d
 Displaying notes found in: .gnu.build.attributes
4ede5d
 [ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
-[ 	]+GA\$<version>2p1[ 	]+0x0000000.[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122 \(note_1.s\)
4ede5d
-[ 	]+GA\$<tool>gcc 6.3.1 20161221[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122 \(note_1.s\)
4ede5d
 [ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\$<tool>gcc 6.3.1 20161221[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 [ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 [ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
-[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x122
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-3-64.s binutils-2.30/binutils/testsuite/binutils-all/note-3-64.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-3-64.s	2019-10-28 17:08:43.357324895 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-3-64.s	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -9,10 +9,11 @@ note_1.s:
4ede5d
 	.balign 4
4ede5d
 
4ede5d
 	.dc.l 8
4ede5d
-	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
 	.dc.l 0x100
4ede5d
-	.asciz "GA$?2p1"
4ede5d
-	.8byte note_1.s
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.8byte 0x100 /* note_1.s */
4ede5d
+	.8byte 0x122 /* note_1 end */
4ede5d
 
4ede5d
 	.dc.l 23
4ede5d
 	.dc.l 0
4ede5d
@@ -55,4 +56,11 @@ note_1.s:
4ede5d
 	.dc.l 0x100
4ede5d
 	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
 	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
 	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-4-32.d binutils-2.30/binutils/testsuite/binutils-all/note-4-32.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-4-32.d	2019-10-28 17:08:43.357324895 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-4-32.d	2019-10-28 17:17:19.515453041 +0000
4ede5d
@@ -7,13 +7,13 @@
4ede5d
 #...
4ede5d
 Displaying notes found in: .gnu.build.attributes
4ede5d
 [ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
-[ 	]+GA\$<version>3p3[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110 \(note_4.s\)
4ede5d
-[ 	]+GA\$<tool>gcc 7.2.1 20170915[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x110
4ede5d
-[ 	]+GA\*<stack prot>strong[ 	]+0x00000008[ 	]+func[ 	]+Applies to region from 0x108 to 0x10c.*
4ede5d
+[ 	]+GA\$<version>3p3[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110 \(note_4.s\)
4ede5d
+[ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\$<tool>gcc 7.2.1 20170915[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x10. to 0x110
4ede5d
+[ 	]+GA\*<stack prot>strong[ 	]+0x00000008[ 	]+func[ 	]+Applies to region from 0x10. to 0x10c.*
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-4-32.s binutils-2.30/binutils/testsuite/binutils-all/note-4-32.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-4-32.s	2019-10-28 17:08:43.355324910 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-4-32.s	2019-10-28 17:17:23.931419915 +0000
4ede5d
@@ -1,6 +1,6 @@
4ede5d
 	.text
4ede5d
 	.org 0x100
4ede5d
-note_4.s:
4ede5d
+	.equiv note_4.s, . + 2
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0
4ede5d
 
4ede5d
@@ -18,8 +18,8 @@ note_4.s_end:
4ede5d
 	.dc.l 8
4ede5d
 	.dc.l 0x100
4ede5d
 	.asciz "GA$?3p3"
4ede5d
-	.dc.l note_4.s
4ede5d
-	.dc.l note_4.s_end
4ede5d
+	.dc.l 0x100 /* note_4.s - 2 */
4ede5d
+	.dc.l 0x110 /* note_4.s_end */
4ede5d
 
4ede5d
 	.dc.l 23
4ede5d
 	.dc.l 0
4ede5d
@@ -63,12 +63,18 @@ note_4.s_end:
4ede5d
 	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
 	.dc.b 0, 0, 0
4ede5d
 
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
 	.dc.l 6
4ede5d
 	.dc.l 8
4ede5d
 	.dc.l 0x101
4ede5d
 	.dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0
4ede5d
 	.dc.b 0, 0
4ede5d
-	.dc.l bar
4ede5d
-	.dc.l bar_end
4ede5d
+	.dc.l 0x108 /* bar */
4ede5d
+	.dc.l 0x10c /* bar_end */
4ede5d
 	
4ede5d
 	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-4-64.d binutils-2.30/binutils/testsuite/binutils-all/note-4-64.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-4-64.d	2019-10-28 17:08:43.356324902 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-4-64.d	2019-10-28 17:09:04.609165478 +0000
4ede5d
@@ -8,13 +8,13 @@
4ede5d
 #...
4ede5d
 Displaying notes found in: .gnu.build.attributes
4ede5d
 [ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
-[ 	]+GA\$<version>3p3[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120 \(note_4.s\)
4ede5d
+[ 	]+GA\$<version>3p3[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120.*
4ede5d
-[ 	]+GA\$<tool>gcc 7.2.1 20170915[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
-[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
 [ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
-[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
+[ 	]+GA\$<tool>gcc 7.2.1 20170915[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
 [ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
 [ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
-[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
-[ 	]+GA\*<stack prot>strong[ 	]+0x00000010[ 	]+func[ 	]+Applies to region from 0x110 to 0x11c.*
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x120
4ede5d
+[ 	]+GA\*<stack prot>strong[ 	]+0x00000010[ 	]+func[ 	]+Applies to region from 0x110 to 0x120.*
4ede5d
 #...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-4-64.s binutils-2.30/binutils/testsuite/binutils-all/note-4-64.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-4-64.s	2019-10-28 17:08:43.356324902 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-4-64.s	2019-10-28 17:17:29.355379229 +0000
4ede5d
@@ -1,6 +1,6 @@
4ede5d
 	.text
4ede5d
 	.org 0x100
4ede5d
-note_4.s:
4ede5d
+	.equiv note_4.s, . + 2
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0
4ede5d
 	.dc.l 0
4ede5d
@@ -22,8 +22,8 @@ note_4.s_end:
4ede5d
 	.dc.l 16
4ede5d
 	.dc.l 0x100
4ede5d
 	.asciz "GA$?3p3"
4ede5d
-	.8byte note_4.s
4ede5d
-	.8byte note_4.s_end
4ede5d
+	.8byte 0x100 /* note_4.s - 2 */
4ede5d
+	.8byte 0x120 /* note_4.s_end */
4ede5d
 
4ede5d
 	.dc.l 23
4ede5d
 	.dc.l 0
4ede5d
@@ -68,11 +68,17 @@ note_4.s_end:
4ede5d
 	.dc.b 0, 0, 0
4ede5d
 
4ede5d
 	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
 	.dc.l 16
4ede5d
 	.dc.l 0x101
4ede5d
 	.dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0
4ede5d
 	.dc.b 0, 0
4ede5d
-	.8byte bar
4ede5d
-	.8byte bar_end
4ede5d
+	.8byte 0x110 /* bar */
4ede5d
+	.8byte 0x120 /* bar_end */
4ede5d
 	
4ede5d
 	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-6-32.d binutils-2.30/binutils/testsuite/binutils-all/note-6-32.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-6-32.d	1970-01-01 01:00:00.000000000 +0100
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-6-32.d	2019-10-28 17:17:38.955307217 +0000
4ede5d
@@ -0,0 +1,20 @@
4ede5d
+#PROG: objcopy
4ede5d
+#readelf: --notes --wide
4ede5d
+#objcopy: --merge-notes
4ede5d
+#name: v3 gnu build attribute note merging (32-bit)
4ede5d
+#source: note-6-32.s
4ede5d
+
4ede5d
+#...
4ede5d
+Displaying notes found in: .gnu.build.attributes
4ede5d
+[ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000008[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106 \(note_test\)
4ede5d
+[ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\$<tool>gcc 8.3.1 20190507[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000008[ 	]+func[ 	]+Applies to region from 0x102 to 0x106
4ede5d
+[ 	]+GA\$<tool>hello world[ 	]+0x00000000[ 	]+func[ 	]+Applies to region from 0x102 to 0x106
4ede5d
+#...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-6-32.s binutils-2.30/binutils/testsuite/binutils-all/note-6-32.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-6-32.s	1970-01-01 01:00:00.000000000 +0100
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-6-32.s	2019-10-28 17:17:38.955307217 +0000
4ede5d
@@ -0,0 +1,145 @@
4ede5d
+	.text
4ede5d
+	.org    0x100
4ede5d
+	.global note_test
4ede5d
+note_test:	
4ede5d
+note_1_start:
4ede5d
+	.word 0
4ede5d
+note_1_end:
4ede5d
+note_2_start:
4ede5d
+	.word 0
4ede5d
+note_2_end:
4ede5d
+note_3_start:
4ede5d
+	.word 0
4ede5d
+note_3_end:
4ede5d
+note_test_end:	
4ede5d
+	.size   note_test, note_test_end - note_test
4ede5d
+	
4ede5d
+	.pushsection .gnu.build.attributes, "", %note
4ede5d
+	.balign 4
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.4byte 0x100  /* note_1_start */
4ede5d
+	.4byte 0x102  /* note_1_end */
4ede5d
+
4ede5d
+	.dc.l 23
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?gcc 8.3.1 20190507"
4ede5d
+	.dc.b 0
4ede5d
+
4ede5d
+	.dc.l 10
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.4byte 0x102  /* note_2_start */
4ede5d
+	.4byte 0x106  /* note_3_end */
4ede5d
+
4ede5d
+	.dc.l 23
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?gcc 8.3.1 20190507"
4ede5d
+	.dc.b 0
4ede5d
+
4ede5d
+	.dc.l 10
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.4byte 0x102  /* note_2_start */
4ede5d
+	.4byte 0x104  /* note_2_end */
4ede5d
+
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?hello world"
4ede5d
+
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.4byte 0x104  /* note_3_start */
4ede5d
+	.4byte 0x106  /* note_3_end */
4ede5d
+
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?hello world"
4ede5d
+
4ede5d
+	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-6-64.d binutils-2.30/binutils/testsuite/binutils-all/note-6-64.d
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-6-64.d	1970-01-01 01:00:00.000000000 +0100
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-6-64.d	2019-10-28 17:17:43.659271931 +0000
4ede5d
@@ -0,0 +1,20 @@
4ede5d
+#PROG: objcopy
4ede5d
+#readelf: --notes --wide
4ede5d
+#objcopy: --merge-notes
4ede5d
+#name: v3 gnu build attribute note merging (64-bit)
4ede5d
+#source: note-6-64.s
4ede5d
+
4ede5d
+#...
4ede5d
+Displaying notes found in: .gnu.build.attributes
4ede5d
+[ 	]+Owner[ 	]+Data size[ 	]+Description
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000010[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106 \(note_test\)
4ede5d
+[ 	]+GA\*<stack prot>off[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\$<tool>gcc 8.3.1 20190507[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*<ABI>0x[0-9a-f]+[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*<PIC>PIC[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\!<short enum>false[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*FORTIFY:0xff[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\*GOW:0x700[ 	]+0x00000000[ 	]+OPEN[ 	]+Applies to region from 0x100 to 0x106
4ede5d
+[ 	]+GA\$<version>3p1[ 	]+0x00000010[ 	]+func[ 	]+Applies to region from 0x102 to 0x106
4ede5d
+[ 	]+GA\$<tool>hello world[ 	]+0x00000000[ 	]+func[ 	]+Applies to region from 0x102 to 0x106
4ede5d
+#...
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/note-6-64.s binutils-2.30/binutils/testsuite/binutils-all/note-6-64.s
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/note-6-64.s	1970-01-01 01:00:00.000000000 +0100
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/note-6-64.s	2019-10-28 17:17:43.659271931 +0000
4ede5d
@@ -0,0 +1,145 @@
4ede5d
+	.text
4ede5d
+	.org    0x100
4ede5d
+	.global note_test
4ede5d
+note_test:	
4ede5d
+note_1_start:
4ede5d
+	.word 0
4ede5d
+note_1_end:
4ede5d
+note_2_start:
4ede5d
+	.word 0
4ede5d
+note_2_end:
4ede5d
+note_3_start:
4ede5d
+	.word 0
4ede5d
+note_3_end:
4ede5d
+note_test_end:	
4ede5d
+	.size   note_test, note_test_end - note_test
4ede5d
+	
4ede5d
+	.pushsection .gnu.build.attributes, "", %note
4ede5d
+	.balign 4
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.8byte 0x100  /* note_1_start */
4ede5d
+	.8byte 0x102  /* note_1_end */
4ede5d
+
4ede5d
+	.dc.l 23
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?gcc 8.3.1 20190507"
4ede5d
+	.dc.b 0
4ede5d
+
4ede5d
+	.dc.l 10
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.8byte 0x102  /* note_2_start */
4ede5d
+	.8byte 0x106  /* note_3_end */
4ede5d
+
4ede5d
+	.dc.l 23
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.asciz "GA$?gcc 8.3.1 20190507"
4ede5d
+	.dc.b 0
4ede5d
+
4ede5d
+	.dc.l 10
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 6
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0
4ede5d
+	.dc.b 0, 0
4ede5d
+
4ede5d
+	.dc.l 5
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x21, 0x8, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+	.dc.l 13
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x100
4ede5d
+	.dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0
4ede5d
+	.dc.b 0, 0, 0
4ede5d
+
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.8byte 0x102  /* note_2_start */
4ede5d
+	.8byte 0x104  /* note_2_end */
4ede5d
+
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?hello world"
4ede5d
+
4ede5d
+
4ede5d
+	.dc.l 8
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?3p1"
4ede5d
+	.8byte 0x104  /* note_3_start */
4ede5d
+	.8byte 0x106  /* note_3_end */
4ede5d
+
4ede5d
+	.dc.l 16
4ede5d
+	.dc.l 0
4ede5d
+	.dc.l 0x101
4ede5d
+	.asciz "GA$?hello world"
4ede5d
+
4ede5d
+	.popsection
4ede5d
diff -rupN binutils.orig/binutils/testsuite/binutils-all/objcopy.exp binutils-2.30/binutils/testsuite/binutils-all/objcopy.exp
4ede5d
--- binutils.orig/binutils/testsuite/binutils-all/objcopy.exp	2019-10-28 17:08:43.353324925 +0000
4ede5d
+++ binutils-2.30/binutils/testsuite/binutils-all/objcopy.exp	2019-10-28 17:09:04.610165471 +0000
4ede5d
@@ -1057,10 +1057,12 @@ if [is_elf_format] {
4ede5d
 	run_dump_test "note-2-64"
4ede5d
 	run_dump_test "note-3-64"
4ede5d
 	run_dump_test "note-4-64"
4ede5d
+	run_dump_test "note-6-64"
4ede5d
     } else {
4ede5d
 	run_dump_test "note-2-32"
4ede5d
 	run_dump_test "note-3-32"
4ede5d
 	run_dump_test "note-4-32"
4ede5d
+	run_dump_test "note-6-32"
4ede5d
     }
4ede5d
     run_dump_test "note-5"
4ede5d
 }
4ede5d
--- binutils.orig/binutils/objcopy.c	2019-11-06 10:21:47.933091869 +0000
4ede5d
+++ binutils-2.30/binutils/objcopy.c	2019-11-06 15:12:26.964599817 +0000
4ede5d
@@ -2502,7 +2502,7 @@ merge_gnu_build_notes (bfd *          ab
4ede5d
     {
4ede5d
       bfd_set_error (bfd_error_bad_value);
4ede5d
       bfd_nonfatal_message (NULL, abfd, sec, err);
4ede5d
-      status = 1;
4ede5d
+      /* status = 1; */
4ede5d
     }
4ede5d
 
4ede5d
   free (pnotes);
4ede5d
@@ -2859,7 +2859,7 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message (NULL, ibfd, osec,
4ede5d
 				    _("warning: could not load note section"));
4ede5d
-	      free (merged->contents);
4ede5d
+	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
 	      free (merged);
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
@@ -2871,7 +2871,7 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	      /* Merging achieves nothing.  */
4ede5d
 	      merge_debug ("Merge of section %s achieved nothing - skipping\n",
4ede5d
 			   bfd_section_name (obfd, osec));
4ede5d
-	      free (merged->contents);
4ede5d
+	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
 	      free (merged);
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
@@ -2881,7 +2881,7 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message (NULL, obfd, osec,
4ede5d
 				    _("warning: failed to set merged notes size"));
4ede5d
-	      free (merged->contents);
4ede5d
+	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
 	      free (merged);
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
--- binutils.orig/binutils/objcopy.c	2019-11-06 16:37:57.018843494 +0000
4ede5d
+++ binutils-2.30/binutils/objcopy.c	2019-11-06 16:40:52.669564222 +0000
4ede5d
@@ -2845,7 +2845,13 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	  if (! is_mergeable_note_section (ibfd, osec))
4ede5d
 	    continue;
4ede5d
 
4ede5d
+	  /* If the section is going to be completly deleted then
4ede5d
+	     do not bother to merge it.  */
4ede5d
+	  if (osec->output_section == NULL)
4ede5d
+	    continue;
4ede5d
+
4ede5d
 	  bfd_size_type size = bfd_section_size (obfd, osec);
4ede5d
+
4ede5d
 	  if (size == 0)
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message (NULL, ibfd, osec,
4ede5d
@@ -2859,29 +2865,22 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message (NULL, ibfd, osec,
4ede5d
 				    _("warning: could not load note section"));
4ede5d
-	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
 	      free (merged);
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
 
4ede5d
 	  merged->size = merge_gnu_build_notes (ibfd, osec, size,
4ede5d
 						merged->contents);
4ede5d
-	  if (merged->size == size)
4ede5d
-	    {
4ede5d
-	      /* Merging achieves nothing.  */
4ede5d
-	      merge_debug ("Merge of section %s achieved nothing - skipping\n",
4ede5d
-			   bfd_section_name (obfd, osec));
4ede5d
-	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
-	      free (merged);
4ede5d
-	      continue;
4ede5d
-	    }
4ede5d
+	  /* FIXME: Once we have read the contents in, we must write
4ede5d
+	     them out again.  So even if the mergeing has achieved
4ede5d
+	     nothing we still add this entry to the merge list.  */
4ede5d
 
4ede5d
-	  if (osec->output_section == NULL
4ede5d
-	      || !bfd_set_section_size (obfd, osec->output_section, merged->size))
4ede5d
+	  if (size != merged->size
4ede5d
+	      && !bfd_set_section_size (obfd, osec->output_section, merged->size))
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message (NULL, obfd, osec,
4ede5d
 				    _("warning: failed to set merged notes size"));
4ede5d
-	      /* Do NOT free merged->contents - it is cached and might be used elsewhere.  */
4ede5d
+	      free (merged->contents);
4ede5d
 	      free (merged);
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
@@ -3246,16 +3245,16 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 		{
4ede5d
 		  bfd_nonfatal_message
4ede5d
 		    (NULL, obfd, osec,
4ede5d
-		     _("error: failed to copy merged notes into output"));
4ede5d
+		     _("error: failed to locate merged notes"));
4ede5d
 		  continue;
4ede5d
 		}
4ede5d
 	    }
4ede5d
 
4ede5d
-	  if (! is_mergeable_note_section (obfd, osec))
4ede5d
+	  if (merged->contents == NULL)
4ede5d
 	    {
4ede5d
 	      bfd_nonfatal_message
4ede5d
 		(NULL, obfd, osec,
4ede5d
-		 _("error: failed to copy merged notes into output"));
4ede5d
+		 _("error: failed to merged notes"));
4ede5d
 	      continue;
4ede5d
 	    }
4ede5d
 
4ede5d
--- binutils.orig/binutils/objcopy.c	2019-11-20 10:59:20.993888328 +0000
4ede5d
+++ binutils-2.30/binutils/objcopy.c	2019-11-20 16:59:50.714905419 +0000
4ede5d
@@ -2292,7 +2292,7 @@ merge_gnu_build_notes (bfd *          ab
4ede5d
      - it makes things much simpler.  */
4ede5d
   if (version_3_seen == 0)
4ede5d
     {
4ede5d
-      merge_debug ("%s: skipping merge - not using v3 notes", bfd_section_name (sec));
4ede5d
+      merge_debug ("%s: skipping merge - not using v3 notes", bfd_section_name (abfd, sec));
4ede5d
       goto done;
4ede5d
     }
4ede5d
 
4ede5d
@@ -2324,7 +2324,7 @@ merge_gnu_build_notes (bfd *          ab
4ede5d
 	    other note then if they are both of the same type (open
4ede5d
 	    or func) then they can be merged and one deleted.  If
4ede5d
 	    they are of different types then they cannot be merged.  */
4ede5d
-  for (pnote = pnotes + 1; pnote < pnotes_end; pnote ++)
4ede5d
+  for (pnote = pnotes; pnote < pnotes_end; pnote ++)
4ede5d
     {
4ede5d
       /* Skip already deleted notes.
4ede5d
 	 FIXME: Can this happen ?  We are scanning forwards and
4ede5d
@@ -2426,7 +2426,9 @@ merge_gnu_build_notes (bfd *          ab
4ede5d
   bfd_vma        prev_start = 0;
4ede5d
   bfd_vma        prev_end = 0;
4ede5d
 
4ede5d
-  new = new_contents = xmalloc (size);
4ede5d
+  /* Not sure how, but the notes might grow in size.
4ede5d
+     (eg see PR 1774507).  Allow for this here.  */
4ede5d
+  new = new_contents = xmalloc (size * 2);
4ede5d
   for (pnote = pnotes, old = contents;
4ede5d
        pnote < pnotes_end;
4ede5d
        pnote ++)
4ede5d
@@ -2493,8 +2495,11 @@ merge_gnu_build_notes (bfd *          ab
4ede5d
 #endif
4ede5d
   
4ede5d
   new_size = new - new_contents;
4ede5d
-  memcpy (contents, new_contents, new_size);
4ede5d
-  size = new_size;
4ede5d
+  if (new_size < size)
4ede5d
+    {
4ede5d
+      memcpy (contents, new_contents, new_size);
4ede5d
+      size = new_size;
4ede5d
+    }
4ede5d
   free (new_contents);
4ede5d
 
4ede5d
  done:
4ede5d
@@ -2940,6 +2945,7 @@ copy_object (bfd *ibfd, bfd *obfd, const
4ede5d
 			     pdump->filename,
4ede5d
 			     strerror (errno));
4ede5d
 		  free (contents);
4ede5d
+		  fclose (f);
4ede5d
 		  /* There is a potential resource leak here, but it is not important.  */
4ede5d
 		  /* coverity[leaked_storage: FALSE] */
4ede5d
 		  return FALSE;