* elflink.c (_bfd_elf_link_create_dynamic_sections): If the
authorNick Clifton <nickc@redhat.com>
Fri, 10 Jun 2011 14:04:25 +0000 (14:04 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 10 Jun 2011 14:04:25 +0000 (14:04 +0000)
backend does not provide a function for creating dynamic sections
then fail.
(bfd_elf_final_link): Issue a warning message if a dynamic section
has the SHT_NOTE type.
(bfd_elf_final_link): Do not look for dynamic strings in a section
that does not have the SHT_STRTAB type or the name .dynstr.
* elf32-arm.c (elf32_arm_finish_dynamic_sections): Fail if the got
section is not in the output binary.
* elf32-hppa.c (elf32_hppa_finish_dynamic_sections): Likewise.

* ld-elf/elf.exp: Add test for linking a shared library with a
broken linker script that marks dynamic sections as being notes.
* ld-elf/note-3.s: New test source file.
* ld-elf/note-3.t: New test linker script.
* ld-elf/note-3.l: Expected output from the linker.
* lib/ld-lib.exp (run_ld_link_tests): Improve description.

bfd/ChangeLog
bfd/elf32-arm.c
bfd/elf32-hppa.c
bfd/elflink.c
bfd/linker.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/note-3.l [new file with mode: 0644]
ld/testsuite/ld-elf/note-3.s [new file with mode: 0644]
ld/testsuite/ld-elf/note-3.t [new file with mode: 0644]
ld/testsuite/lib/ld-lib.exp

index 58aa6e7..1e72bf2 100644 (file)
@@ -1,3 +1,16 @@
+2011-06-10  Nick Clifton  <nickc@redhat.com>
+
+       * elflink.c (_bfd_elf_link_create_dynamic_sections): If the
+       backend does not provide a function for creating dynamic sections
+       then fail.
+       (bfd_elf_final_link): Issue a warning message if a dynamic section
+       has the SHT_NOTE type.
+       (bfd_elf_final_link): Do not look for dynamic strings in a section
+       that does not have the SHT_STRTAB type or the name .dynstr.
+       * elf32-arm.c (elf32_arm_finish_dynamic_sections): Fail if the got
+       section is not in the output binary.
+       * elf32-hppa.c (elf32_hppa_finish_dynamic_sections): Likewise.
+
 2011-06-09  Tristan Gingold  <gingold@adacore.com>
 
        * elfnn-ia64.c (elfNN_ia64_relax_section, elfNN_ia64_choose_gp)
index d5a4a4e..8ace48a 100644 (file)
@@ -13744,6 +13744,10 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
   dynobj = elf_hash_table (info)->dynobj;
 
   sgot = htab->root.sgotplt;
+  /* A broken linker script might have discarded the dynamic sections.
+     Catch this here so that we do not seg-fault later on.  */
+  if (sgot != NULL && bfd_is_abs_section (sgot->output_section))
+    return FALSE;
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
index 81bc042..e70d7e5 100644 (file)
@@ -4498,6 +4498,7 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
   bfd *dynobj;
   struct elf32_hppa_link_hash_table *htab;
   asection *sdyn;
+  asection * sgot;
 
   htab = hppa_link_hash_table (info);
   if (htab == NULL)
@@ -4505,6 +4506,12 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
 
   dynobj = htab->etab.dynobj;
 
+  sgot = htab->sgot;
+  /* A broken linker script might have discarded the dynamic sections.
+     Catch this here so that we do not seg-fault later on.  */
+  if (sgot != NULL && bfd_is_abs_section (sgot->output_section))
+    return FALSE;
+
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
   if (htab->etab.dynamic_sections_created)
@@ -4569,19 +4576,19 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  if (htab->sgot != NULL && htab->sgot->size != 0)
+  if (sgot != NULL && sgot->size != 0)
     {
       /* Fill in the first entry in the global offset table.
         We use it to point to our dynamic section, if we have one.  */
       bfd_put_32 (output_bfd,
                  sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0,
-                 htab->sgot->contents);
+                 sgot->contents);
 
       /* The second entry is reserved for use by the dynamic linker.  */
-      memset (htab->sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
+      memset (sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
 
       /* Set .got entry size.  */
-      elf_section_data (htab->sgot->output_section)
+      elf_section_data (sgot->output_section)
        ->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
     }
 
@@ -4601,8 +4608,8 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
          if ((htab->splt->output_offset
               + htab->splt->output_section->vma
               + htab->splt->size)
-             != (htab->sgot->output_offset
-                 + htab->sgot->output_section->vma))
+             != (sgot->output_offset
+                 + sgot->output_section->vma))
            {
              (*_bfd_error_handler)
                (_(".got section not immediately after .plt section"));
index 639c3e7..ef7a524 100644 (file)
@@ -286,7 +286,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   /* Let the backend create the rest of the sections.  This lets the
      backend set the right flags.  The backend will normally create
      the .got and .plt sections.  */
-  if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
+  if (bed->elf_backend_create_dynamic_sections == NULL
+      || ! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
     return FALSE;
 
   elf_hash_table (info)->dynamic_sections_created = TRUE;
@@ -11148,6 +11149,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                    (_("%B: could not find output section %s"), abfd, name);
                  goto error_return;
                }
+             if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE)
+               {
+                 (*_bfd_error_handler)
+                   (_("warning: section '%s' is being made into a note"), name);
+                 bfd_set_error (bfd_error_nonrepresentable_section);
+                 goto error_return;
+               }
              dyn.d_un.d_ptr = o->vma;
              break;
 
@@ -11235,7 +11243,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            continue;
          if ((elf_section_data (o->output_section)->this_hdr.sh_type
               != SHT_STRTAB)
-             || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
+             && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0))
            {
              /* FIXME: octets_per_byte.  */
              if (! bfd_set_section_contents (abfd, o->output_section,
index 90ab63e..bac5417 100644 (file)
@@ -1566,6 +1566,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   struct bfd_link_hash_entry *h;
   bfd_boolean cycle;
 
+  BFD_ASSERT (section != NULL);
+
   if (bfd_is_ind_section (section)
       || (flags & BSF_INDIRECT) != 0)
     row = INDR_ROW;
index 43b678f..d224e3c 100644 (file)
@@ -1,3 +1,12 @@
+2011-06-10  Nick Clifton  <nickc@redhat.com>
+
+       * ld-elf/elf.exp: Add test for linking a shared library with a
+       broken linker script that marks dynamic sections as being notes.
+       * ld-elf/note-3.s: New test source file.
+       * ld-elf/note-3.t: New test linker script.
+       * ld-elf/note-3.l: Expected output from the linker.
+       * lib/ld-lib.exp (run_ld_link_tests): Improve description.
+
 2011-06-08  H.J. Lu  <hongjiu.lu@intel.com>
 
        * ld-x86-64/x86-64.exp: Build x32 DSO from x86-64 object file
index e991f83..61efc4a 100644 (file)
@@ -49,6 +49,45 @@ run_ld_link_tests {
      {symbol3w.s} {} "symbol3w.a"}
 }
 
+# Run a test to check linking a shared library with a broken linker
+# script that accidentally marks dynamic sections as notes.  The
+# resulting executable is not expected to work, but the linker
+# should not seg-fault whilst creating the binary.
+#
+# Only run the test on targets thats support creating shared libraries.
+if {    ! [istarget arc-*-*]
+     && ! [istarget avr-*-*]
+     && ! [istarget cr16-*-*]
+     && ! [istarget cris*-*-*]
+     && ! [istarget crx-*-*]
+     && ! [istarget d10v-*-*]
+     && ! [istarget d30v-*-*]
+     && ! [istarget dlx-*-*]
+     && ! [istarget fr30-*-*]
+     && ! [istarget frv-*-*]
+     && ! [istarget h8300-*-*]
+     && ! [istarget ip2k-*-*]
+     && ! [istarget m32r-*-*]
+     && ! [istarget mcore*-*-*]
+     && ! [istarget mn10200-*-*]
+     && ! [istarget msp430-*-*]
+     && ! [istarget openrisc-*-*]
+     && ! [istarget or32-*-*]
+     && ! [istarget pj-*-*]
+     && ! [istarget rx-*-*]
+     && ! [istarget v850-*-*]
+     && ! [istarget *-*-irix*]
+     && ! [istarget *-*-rtems] } {
+  run_ld_link_tests {
+      {"Build shared library for next test"
+       "-shared" "" "note-3.s" {} "note-3.so" }
+      {"Link using broken linker script"
+        "--script note-3.t tmpdir/note-3.so" "" ""
+         { { ld "note-3.l" } }
+         "a.out" }
+  }
+}
+
 set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
 foreach t $test_list {
     # We need to strip the ".d", but can leave the dirname.
diff --git a/ld/testsuite/ld-elf/note-3.l b/ld/testsuite/ld-elf/note-3.l
new file mode 100644 (file)
index 0000000..551ebaa
--- /dev/null
@@ -0,0 +1,2 @@
+.*warning: section '.hash' is being made into a note
+.*
diff --git a/ld/testsuite/ld-elf/note-3.s b/ld/testsuite/ld-elf/note-3.s
new file mode 100644 (file)
index 0000000..3a1d190
--- /dev/null
@@ -0,0 +1,10 @@
+       .globl _entry
+       .text
+_entry:
+       .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+       .global foo
+foo:
+       .byte 9
+       
+       .section .note,"",%note
+       .byte 0
diff --git a/ld/testsuite/ld-elf/note-3.t b/ld/testsuite/ld-elf/note-3.t
new file mode 100644 (file)
index 0000000..13324ae
--- /dev/null
@@ -0,0 +1,22 @@
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS ;
+  note PT_NOTE;
+}
+SECTIONS
+{
+  . = . + SIZEOF_HEADERS ;
+  .text : { *(.text) *(.rodata) } :text
+  .note : { *(.note) } :note :text
+
+  /* BUG:  This linker script is broken here.  It has not reset the
+     output segment for the following sections, so they are all
+     treated as notes...   */
+  
+  .hash : { *(.hash) }
+  
+  .dynstr : { *(.dynstr) }
+  .dynsym : { *(.dynsym) }
+  .got.plt : { *(.got.plt) *(.igot.plt) }
+  /DISCARD/ : { *(*) }
+}
index 62e0ff7..2020372 100644 (file)
@@ -903,18 +903,24 @@ proc ar_simple_create { ar aropts target objects } {
 
 # List contains test-items with 3 items followed by 2 lists, one item and
 # one optional item:
-# 0:name 1:ld/ar options 2:assembler options
-# 3:filenames of assembler files 4: action and options. 5: name of output file
-# 6:compiler flags (optional)
+#  0:name
+#  1:ld/ar options
+#  2:assembler options
+#  3:filenames of assembler files
+#  4:list of actions, options and expected outputs.
+#  5:name of output file
+#  6:compiler flags (optional)
 #
-# Actions:
-# objdump: Apply objdump options on result.  Compare with regex (last arg).
-# nm: Apply nm options on result.  Compare with regex (last arg).
-# readelf: Apply readelf options on result.  Compare with regex (last arg).
-# ld: Don't apply anything on result.  Compare output during linking with 
-#     regex (second arg).  Note that this *must* be the first action if it
-#     is to be used at all; in all other cases, any output from the linker
-#     during linking is treated as a sign of an error and FAILs the test.
+# Actions: { command command-line-options file-containg-expected-output-regexps }
+# Commands:
+#   objdump: Apply objdump options on result.
+#   nm: Apply nm options on result.
+#   readelf: Apply readelf options on result.
+#   ld: Don't apply anything on result.  Compare output during linking with 
+#     the file containing regexps (which is the second arg, not the third).
+#     Note that this *must* be the first action if it is to be used at all;
+#     in all other cases, any output from the linker during linking is
+#     treated as a sign of an error and FAILs the test.
 #
 proc run_ld_link_tests { ldtests } {
     global ld
@@ -1019,11 +1025,11 @@ proc run_ld_link_tests { ldtests } {
                    }
 
                if { $action == "ld" } {
-                   set dumpfile [lindex $actionlist 1]
-                   verbose "dumpfile is $dumpfile"
+                   set regexpfile $progopts
+                   verbose "regexpfile is $srcdir/$subdir/$regexpfile"
                    set_file_contents "tmpdir/ld.messages" "$ld_output"
                    verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
-                   if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$dumpfile"] } then {
+                   if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$regexpfile"] } then {
                        verbose "output is $ld_output" 2
                        set failed 1
                        break