From 894891db7f1ff09f021a0d2c8bb471f3a73a776a Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 10 Jun 2011 14:04:25 +0000 Subject: [PATCH] * 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. * 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 | 13 +++++++++++++ bfd/elf32-arm.c | 4 ++++ bfd/elf32-hppa.c | 19 +++++++++++++------ bfd/elflink.c | 12 ++++++++++-- bfd/linker.c | 2 ++ ld/testsuite/ChangeLog | 9 +++++++++ ld/testsuite/ld-elf/elf.exp | 39 +++++++++++++++++++++++++++++++++++++++ ld/testsuite/ld-elf/note-3.l | 2 ++ ld/testsuite/ld-elf/note-3.s | 10 ++++++++++ ld/testsuite/ld-elf/note-3.t | 22 ++++++++++++++++++++++ ld/testsuite/lib/ld-lib.exp | 34 ++++++++++++++++++++-------------- 11 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 ld/testsuite/ld-elf/note-3.l create mode 100644 ld/testsuite/ld-elf/note-3.s create mode 100644 ld/testsuite/ld-elf/note-3.t diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 58aa6e7..1e72bf2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2011-06-10 Nick Clifton + + * 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 * elfnn-ia64.c (elfNN_ia64_relax_section, elfNN_ia64_choose_gp) diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index d5a4a4e..8ace48a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -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) diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 81bc042..e70d7e5 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -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")); diff --git a/bfd/elflink.c b/bfd/elflink.c index 639c3e7..ef7a524 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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, diff --git a/bfd/linker.c b/bfd/linker.c index 90ab63e..bac5417 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -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; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 43b678f..d224e3c 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2011-06-10 Nick Clifton + + * 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 * ld-x86-64/x86-64.exp: Build x32 DSO from x86-64 object file diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index e991f83..61efc4a 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -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 index 0000000..551ebaa --- /dev/null +++ b/ld/testsuite/ld-elf/note-3.l @@ -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 index 0000000..3a1d190 --- /dev/null +++ b/ld/testsuite/ld-elf/note-3.s @@ -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 index 0000000..13324ae --- /dev/null +++ b/ld/testsuite/ld-elf/note-3.t @@ -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/ : { *(*) } +} diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index 62e0ff7..2020372 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -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 -- 2.7.4