* 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.
This commit is contained in:
Nick Clifton 2011-06-10 14:04:25 +00:00
parent 12af614e24
commit 894891db7f
11 changed files with 144 additions and 22 deletions

View 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> 2011-06-09 Tristan Gingold <gingold@adacore.com>
* elfnn-ia64.c (elfNN_ia64_relax_section, elfNN_ia64_choose_gp) * elfnn-ia64.c (elfNN_ia64_relax_section, elfNN_ia64_choose_gp)

View File

@ -13744,6 +13744,10 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
dynobj = elf_hash_table (info)->dynobj; dynobj = elf_hash_table (info)->dynobj;
sgot = htab->root.sgotplt; 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"); sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created) if (elf_hash_table (info)->dynamic_sections_created)

View File

@ -4498,6 +4498,7 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
bfd *dynobj; bfd *dynobj;
struct elf32_hppa_link_hash_table *htab; struct elf32_hppa_link_hash_table *htab;
asection *sdyn; asection *sdyn;
asection * sgot;
htab = hppa_link_hash_table (info); htab = hppa_link_hash_table (info);
if (htab == NULL) if (htab == NULL)
@ -4505,6 +4506,12 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
dynobj = htab->etab.dynobj; 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"); sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (htab->etab.dynamic_sections_created) 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. /* Fill in the first entry in the global offset table.
We use it to point to our dynamic section, if we have one. */ We use it to point to our dynamic section, if we have one. */
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0, 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. */ /* 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. */ /* Set .got entry size. */
elf_section_data (htab->sgot->output_section) elf_section_data (sgot->output_section)
->this_hdr.sh_entsize = GOT_ENTRY_SIZE; ->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
} }
@ -4601,8 +4608,8 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
if ((htab->splt->output_offset if ((htab->splt->output_offset
+ htab->splt->output_section->vma + htab->splt->output_section->vma
+ htab->splt->size) + htab->splt->size)
!= (htab->sgot->output_offset != (sgot->output_offset
+ htab->sgot->output_section->vma)) + sgot->output_section->vma))
{ {
(*_bfd_error_handler) (*_bfd_error_handler)
(_(".got section not immediately after .plt section")); (_(".got section not immediately after .plt section"));

View 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 /* Let the backend create the rest of the sections. This lets the
backend set the right flags. The backend will normally create backend set the right flags. The backend will normally create
the .got and .plt sections. */ 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; return FALSE;
elf_hash_table (info)->dynamic_sections_created = TRUE; 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); (_("%B: could not find output section %s"), abfd, name);
goto error_return; 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; dyn.d_un.d_ptr = o->vma;
break; break;
@ -11235,7 +11243,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
continue; continue;
if ((elf_section_data (o->output_section)->this_hdr.sh_type if ((elf_section_data (o->output_section)->this_hdr.sh_type
!= SHT_STRTAB) != SHT_STRTAB)
|| strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0) && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0))
{ {
/* FIXME: octets_per_byte. */ /* FIXME: octets_per_byte. */
if (! bfd_set_section_contents (abfd, o->output_section, if (! bfd_set_section_contents (abfd, o->output_section,

View File

@ -1566,6 +1566,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
struct bfd_link_hash_entry *h; struct bfd_link_hash_entry *h;
bfd_boolean cycle; bfd_boolean cycle;
BFD_ASSERT (section != NULL);
if (bfd_is_ind_section (section) if (bfd_is_ind_section (section)
|| (flags & BSF_INDIRECT) != 0) || (flags & BSF_INDIRECT) != 0)
row = INDR_ROW; row = INDR_ROW;

View 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> 2011-06-08 H.J. Lu <hongjiu.lu@intel.com>
* ld-x86-64/x86-64.exp: Build x32 DSO from x86-64 object file * ld-x86-64/x86-64.exp: Build x32 DSO from x86-64 object file

View File

@ -49,6 +49,45 @@ run_ld_link_tests {
{symbol3w.s} {} "symbol3w.a"} {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]] set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
foreach t $test_list { foreach t $test_list {
# We need to strip the ".d", but can leave the dirname. # We need to strip the ".d", but can leave the dirname.

View File

@ -0,0 +1,2 @@
.*warning: section '.hash' is being made into a note
.*

View File

@ -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

View File

@ -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/ : { *(*) }
}

View 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 # List contains test-items with 3 items followed by 2 lists, one item and
# one optional item: # one optional item:
# 0:name 1:ld/ar options 2:assembler options # 0:name
# 3:filenames of assembler files 4: action and options. 5: name of output file # 1:ld/ar options
# 6:compiler flags (optional) # 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: # Actions: { command command-line-options file-containg-expected-output-regexps }
# objdump: Apply objdump options on result. Compare with regex (last arg). # Commands:
# nm: Apply nm options on result. Compare with regex (last arg). # objdump: Apply objdump options on result.
# readelf: Apply readelf options on result. Compare with regex (last arg). # nm: Apply nm options on result.
# ld: Don't apply anything on result. Compare output during linking with # readelf: Apply readelf options on result.
# regex (second arg). Note that this *must* be the first action if it # ld: Don't apply anything on result. Compare output during linking with
# is to be used at all; in all other cases, any output from the linker # the file containing regexps (which is the second arg, not the third).
# during linking is treated as a sign of an error and FAILs the test. # 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 } { proc run_ld_link_tests { ldtests } {
global ld global ld
@ -1019,11 +1025,11 @@ proc run_ld_link_tests { ldtests } {
} }
if { $action == "ld" } { if { $action == "ld" } {
set dumpfile [lindex $actionlist 1] set regexpfile $progopts
verbose "dumpfile is $dumpfile" verbose "regexpfile is $srcdir/$subdir/$regexpfile"
set_file_contents "tmpdir/ld.messages" "$ld_output" set_file_contents "tmpdir/ld.messages" "$ld_output"
verbose "ld.messages has '[file_contents tmpdir/ld.messages]'" 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 verbose "output is $ld_output" 2
set failed 1 set failed 1
break break