Stop generating GNU build notes for linkonce sections.
authorNick Clifton <nickc@redhat.com>
Mon, 14 May 2018 14:32:43 +0000 (15:32 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 14 May 2018 14:32:43 +0000 (15:32 +0100)
gas * write.c (maybe_generate_build_notes): Generate notes on a
per-code-section basis.  Skip linkonce sections.

ld * testsuite/ld-elf/notes.exp: New file: Run new test.
* testsuite/ld-elf/note1_1.s: New file: Source file for test.
* testsuite/ld-elf/note1_2.s: New file: Source file for test.
* testsuite/ld-elf/note1.r: New file: Expected readelf output.

gas/ChangeLog
gas/write.c
ld/ChangeLog
ld/testsuite/ld-elf/note1.r [new file with mode: 0644]
ld/testsuite/ld-elf/note1_1.s [new file with mode: 0644]
ld/testsuite/ld-elf/note1_2.s [new file with mode: 0644]
ld/testsuite/ld-elf/notes.exp [new file with mode: 0644]

index 8322ccf..358f033 100644 (file)
@@ -1,5 +1,10 @@
 2018-05-14  Nick Clifton  <nickc@redhat.com>
 
+       * write.c (maybe_generate_build_notes): Generate notes on a
+       per-code-section basis.  Skip linkonce sections.
+
+2018-05-14  Nick Clifton  <nickc@redhat.com>
+
        PR 23153
        * as.c (main): When checking for an output file that is also an
        input file, also check that the inode is not zero.
index b902bf8..39c894a 100644 (file)
@@ -1946,6 +1946,7 @@ maybe_generate_build_notes (void)
   segT      sec;
   char *    note;
   offsetT   note_size;
+  offsetT   total_size;
   offsetT   desc_size;
   offsetT   desc2_offset;
   int       desc_reloc;
@@ -1963,7 +1964,8 @@ maybe_generate_build_notes (void)
                         SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA);
   bfd_set_section_alignment (stdoutput, sec, 2);
 
-  /* Create a version note.  */
+  /* Work out the size of the notes that we will create,
+     and the relocation we should use.  */
   if (bfd_arch_bits_per_address (stdoutput) <= 32)
     {
       note_size = 28;
@@ -1997,65 +1999,59 @@ maybe_generate_build_notes (void)
        desc_reloc = BFD_RELOC_64;
     }
   
-  frag_now_fix ();
-  note = frag_more (note_size);
-  memset (note, 0, note_size);
+  /* We have to create a note for *each* code section.
+     Linker garbage collection might discard some.  */
+  total_size = 0;
+  note = NULL;
 
-  if (target_big_endian)
-    {
-      note[3] = 8; /* strlen (name) + 1.  */
-      note[7] = desc_size; /* Two 8-byte offsets.  */
-      note[10] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
-      note[11] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
-    }
-  else
-    {
-      note[0] = 8; /* strlen (name) + 1.  */
-      note[4] = desc_size; /* Two 8-byte offsets.  */
-      note[8] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
-      note[9] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
-    }
-
-  /* The a1 version number indicates that this note was
-     generated by the assembler and not the gcc annobin plugin.  */
-  memcpy (note + 12, "GA$\ 13a1", 8);
-
-  /* Find the first code section symbol.  */
   for (sym = symbol_rootP; sym != NULL; sym = sym->sy_next)
     if (sym->bsym != NULL
        && sym->bsym->flags & BSF_SECTION_SYM
        && sym->bsym->section != NULL
-       && sym->bsym->section->flags & SEC_CODE)
+       /* Skip linkonce sections - we cannot these section symbols as they may disappear.  */
+       && (sym->bsym->section->flags & (SEC_CODE | SEC_LINK_ONCE)) == SEC_CODE
+       /* Not all linkonce sections are flagged...  */
+       && strncmp (S_GET_NAME (sym), ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) != 0)
       {
-       /* Found one - now create a relocation against this symbol.  */
-       create_note_reloc (sec, sym, 20, desc_reloc, 0, note);
-       break;
-      }
+       /* Create a version note.  */
+       frag_now_fix ();
+       note = frag_more (note_size);
+       memset (note, 0, note_size);
 
-  /* Find the last code section symbol.  */
-  if (sym)
-    {
-      for (sym = symbol_lastP; sym != NULL; sym = sym->sy_previous)
-       if (sym->bsym != NULL
-           && sym->bsym->flags & BSF_SECTION_SYM
-           && sym->bsym->section != NULL
-           && sym->bsym->section->flags & SEC_CODE)
+       if (target_big_endian)
          {
-           /* Create a relocation against the end of this symbol.  */
-           create_note_reloc (sec, sym, desc2_offset, desc_reloc,
-                              bfd_get_section_size (sym->bsym->section),
-                              note);
-           break;
+           note[3] = 8; /* strlen (name) + 1.  */
+           note[7] = desc_size; /* Two 8-byte offsets.  */
+           note[10] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
+           note[11] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
+         }
+       else
+         {
+           note[0] = 8; /* strlen (name) + 1.  */
+           note[4] = desc_size; /* Two 8-byte offsets.  */
+           note[8] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
+           note[9] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
          }
-    }
-  /* else - if we were unable to find any code section symbols then
-     probably there is no code in the output.  So leaving the start
-     and end values as zero in the note is OK.  */
 
-  /* FIXME: Maybe add a note recording the assembler command line and version ?  */
+       /* The a1 version number indicates that this note was
+          generated by the assembler and not the gcc annobin plugin.  */
+       memcpy (note + 12, "GA$\ 13a1", 8);
+
+       /* Create a relocation to install the start address of the note...  */
+       create_note_reloc (sec, sym, 20, desc_reloc, 0, note);
+
+       /* ...and another one to install the end address.  */
+       create_note_reloc (sec, sym, desc2_offset, desc_reloc,
+                          bfd_get_section_size (sym->bsym->section),
+                          note);
+
+       total_size += note_size;
+       /* FIXME: Maybe add a note recording the assembler command line and version ?  */
+      }
 
   /* Install the note(s) into the section.  */
-  bfd_set_section_contents (stdoutput, sec, (bfd_byte *) note, 0, note_size);
+  if (total_size)
+    bfd_set_section_contents (stdoutput, sec, (bfd_byte *) note, 0, total_size);
   subsegs_finish_section (sec);
   relax_segment (seg_info (sec)->frchainP->frch_root, sec, 0);
   size_seg (stdoutput, sec, NULL);
index fbc4d59..bb20a46 100644 (file)
@@ -1,3 +1,10 @@
+2018-05-14  Nick Clifton  <nickc@redhat.com>
+
+       * testsuite/ld-elf/notes.exp: New file: Run new test.
+       * testsuite/ld-elf/note1_1.s: New file: Source file for test.
+       * testsuite/ld-elf/note1_2.s: New file: Source file for test.
+       * testsuite/ld-elf/note1.r: New file: Expected readelf output.
+
 2018-05-14  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/23169
diff --git a/ld/testsuite/ld-elf/note1.r b/ld/testsuite/ld-elf/note1.r
new file mode 100644 (file)
index 0000000..58886d8
--- /dev/null
@@ -0,0 +1,6 @@
+#...
+Displaying notes found in: .gnu.build.attributes
+[      ]+Owner[        ]+Data size[    ]+Description
+[      ]+GA\$<version>3a1[     ]+0x000000(08|10)[      ]+OPEN[         ]+Applies to region from 0.*
+[      ]+GA\$<version>3a1[     ]+0x000000(08|10)[      ]+OPEN[         ]+Applies to region from 0.*
+#pass
diff --git a/ld/testsuite/ld-elf/note1_1.s b/ld/testsuite/ld-elf/note1_1.s
new file mode 100644 (file)
index 0000000..e9d80fb
--- /dev/null
@@ -0,0 +1,17 @@
+       .section .gnu.linkonce.t.thunk.ax,"ax",%progbits
+       .globl  thunk.ax
+       .hidden thunk.ax
+       .p2align 4
+       .type thunk.ax,%function
+thunk.ax:
+       .dc.l 0
+       .size thunk.ax, . - thunk.ax
+
+       .p2align 4
+       .globl foo
+       .type  foo,%function
+foo:
+       .dc.a thunk.ax
+       .dc.l 0
+       .size foo, . - foo
+
diff --git a/ld/testsuite/ld-elf/note1_2.s b/ld/testsuite/ld-elf/note1_2.s
new file mode 100644 (file)
index 0000000..8162d38
--- /dev/null
@@ -0,0 +1,17 @@
+
+       .section .gnu.linkonce.t.thunk.ax,"ax",%progbits
+       .globl  thunk.ax
+       .hidden thunk.ax
+       .p2align 4
+       .type   thunk.ax,%function
+thunk.ax:
+       .dc.l   0
+       .size thunk.ax, . - thunk.ax
+
+       .p2align 4
+       .globl bar
+       .type  bar,%function
+bar:
+       .dc.a   thunk.ax
+       .dc.l   0
+       .size bar, . - bar
diff --git a/ld/testsuite/ld-elf/notes.exp b/ld/testsuite/ld-elf/notes.exp
new file mode 100644 (file)
index 0000000..5f55d46
--- /dev/null
@@ -0,0 +1,43 @@
+# Expect script for various ELF based Note tests.
+#   Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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.
+#
+
+# Exclude non-ELF targets.
+
+if ![is_elf_format] {
+    return
+}
+
+set old_ldflags $LDFLAGS
+if { [istarget spu*-*-*] } {
+    set LDFLAGS "$LDFLAGS --local-store 0:0"
+}
+
+if { [is_remote host] } then {
+    remote_download host merge.ld
+}
+
+run_ld_link_tests [list \
+    [list "Linkonce sections with assembler generated notes" \
+       "-r" "" "--generate-missing-build-notes=yes" \
+        {note1_1.s note1_2.s} \
+        {{readelf {--wide --notes} note1.r}} \
+        "note1.so" ] \
+]