PR ld/21334: Always call `_bfd_elf_link_renumber_dynsyms' if required

Complement commit e17b0c351f ("MIPS/BFD: Respect the ELF gABI dynamic
symbol table sort requirement") and correct an inconsistency in dynamic
symbol accounting data causing an assertion failure in the MIPS backend:

ld: BFD (GNU Binutils) 2.28.51.20170330 assertion fail
../../binutils-gdb/bfd/elfxx-mips.c:3860

in the course of making a GOT entry in a static binary to satisfy a GOT
relocation present in input, due to the local dynamic symbol count not
having been established.

To do so let backends request `_bfd_elf_link_renumber_dynsyms' to be
always called, rather than where a dynamic binary is linked only, and
then make this request in the MIPS backend.

	bfd/
	PR ld/21334
	* elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
	member.
	* elfxx-target.h [!elf_backend_always_renumber_dynsyms]
	(elf_backend_always_renumber_dynsyms): Define.
	(elfNN_bed): Initialize `always_renumber_dynsyms' member.
	* elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
	* elflink.c (bfd_elf_size_dynamic_sections): Also call
	`_bfd_elf_link_renumber_dynsyms' if the backend has requested
	it.
	(bfd_elf_size_dynsym_hash_dynstr): Likewise.

	ld/
	PR ld/21334
	* testsuite/ld-mips-elf/pr21334.dd: New test.
	* testsuite/ld-mips-elf/pr21334.gd: New test.
	* testsuite/ld-mips-elf/pr21334.ld: New test linker script.
	* testsuite/ld-mips-elf/pr21334.s: New test source.
	* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
This commit is contained in:
Maciej W. Rozycki 2017-04-24 20:15:31 +01:00
parent c46cec3a8c
commit 23ec1e32b1
11 changed files with 116 additions and 12 deletions

View File

@ -1,3 +1,17 @@
2017-04-26 Maciej W. Rozycki <macro@imgtec.com>
PR ld/21334
* elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
member.
* elfxx-target.h [!elf_backend_always_renumber_dynsyms]
(elf_backend_always_renumber_dynsyms): Define.
(elfNN_bed): Initialize `always_renumber_dynsyms' member.
* elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
* elflink.c (bfd_elf_size_dynamic_sections): Also call
`_bfd_elf_link_renumber_dynsyms' if the backend has requested
it.
(bfd_elf_size_dynsym_hash_dynstr): Likewise.
2017-04-26 Maciej W. Rozycki <macro@imgtec.com> 2017-04-26 Maciej W. Rozycki <macro@imgtec.com>
* elflink.c (bfd_elf_size_dynamic_sections): Only call * elflink.c (bfd_elf_size_dynamic_sections): Only call

View File

@ -1531,6 +1531,10 @@ struct elf_backend_data
/* Address of protected data defined in the shared library may be /* Address of protected data defined in the shared library may be
external, i.e., due to copy relocation. */ external, i.e., due to copy relocation. */
unsigned extern_protected_data : 1; unsigned extern_protected_data : 1;
/* True if `_bfd_elf_link_renumber_dynsyms' must be called even for
static binaries. */
unsigned always_renumber_dynsyms : 1;
}; };
/* Information about reloc sections associated with a bfd_elf_section_data /* Information about reloc sections associated with a bfd_elf_section_data

View File

@ -6460,7 +6460,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
&sweep_info); &sweep_info);
if (elf_hash_table (info)->dynamic_sections_created) /* We need to reassign dynsym indices now that symbols may have
been removed. See the call in `bfd_elf_size_dynsym_hash_dynstr'
for the details of the conditions used here. */
if (elf_hash_table (info)->dynamic_sections_created
|| bed->always_renumber_dynsyms)
_bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count); _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
} }
@ -6828,6 +6832,8 @@ bfd_boolean
bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
{ {
const struct elf_backend_data *bed; const struct elf_backend_data *bed;
unsigned long section_sym_count;
bfd_size_type dynsymcount;
if (!is_elf_hash_table (info->hash)) if (!is_elf_hash_table (info->hash))
return TRUE; return TRUE;
@ -6835,24 +6841,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
bed = get_elf_backend_data (output_bfd); bed = get_elf_backend_data (output_bfd);
(*bed->elf_backend_init_index_section) (output_bfd, info); (*bed->elf_backend_init_index_section) (output_bfd, info);
/* Assign dynsym indices. In a shared library we generate a section
symbol for each output section, which come first. Next come all
of the back-end allocated local dynamic syms, followed by the rest
of the global symbols.
This is usually not needed for static binaries, however backends
can request to always do it, e.g. the MIPS backend uses dynamic
symbol counts to lay out GOT, which will be produced in the
presence of GOT relocations even in static binaries (holding fixed
data in that case, to satisfy those relocations). */
if (elf_hash_table (info)->dynamic_sections_created
|| bed->always_renumber_dynsyms)
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
&section_sym_count);
if (elf_hash_table (info)->dynamic_sections_created) if (elf_hash_table (info)->dynamic_sections_created)
{ {
bfd *dynobj; bfd *dynobj;
asection *s; asection *s;
bfd_size_type dynsymcount;
unsigned long section_sym_count;
unsigned int dtagcount; unsigned int dtagcount;
dynobj = elf_hash_table (info)->dynobj; dynobj = elf_hash_table (info)->dynobj;
/* Assign dynsym indicies. In a shared library we generate a
section symbol for each output section, which come first.
Next come all of the back-end allocated local dynamic syms,
followed by the rest of the global symbols. */
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
&section_sym_count);
/* Work out the size of the symbol version section. */ /* Work out the size of the symbol version section. */
s = bfd_get_linker_section (dynobj, ".gnu.version"); s = bfd_get_linker_section (dynobj, ".gnu.version");
BFD_ASSERT (s != NULL); BFD_ASSERT (s != NULL);

View File

@ -194,3 +194,4 @@ literal_reloc_p (int r_type)
#define elf_backend_post_process_headers _bfd_mips_post_process_headers #define elf_backend_post_process_headers _bfd_mips_post_process_headers
#define elf_backend_compact_eh_encoding _bfd_mips_elf_compact_eh_encoding #define elf_backend_compact_eh_encoding _bfd_mips_elf_compact_eh_encoding
#define elf_backend_cant_unwind_opcode _bfd_mips_elf_cant_unwind_opcode #define elf_backend_cant_unwind_opcode _bfd_mips_elf_cant_unwind_opcode
#define elf_backend_always_renumber_dynsyms TRUE

View File

@ -126,6 +126,9 @@
#ifndef elf_backend_extern_protected_data #ifndef elf_backend_extern_protected_data
#define elf_backend_extern_protected_data 0 #define elf_backend_extern_protected_data 0
#endif #endif
#ifndef elf_backend_always_renumber_dynsyms
#define elf_backend_always_renumber_dynsyms FALSE
#endif
#ifndef elf_backend_stack_align #ifndef elf_backend_stack_align
#define elf_backend_stack_align 16 #define elf_backend_stack_align 16
#endif #endif
@ -878,7 +881,8 @@ static struct elf_backend_data elfNN_bed =
elf_backend_no_page_alias, elf_backend_no_page_alias,
elf_backend_default_execstack, elf_backend_default_execstack,
elf_backend_caches_rawsize, elf_backend_caches_rawsize,
elf_backend_extern_protected_data elf_backend_extern_protected_data,
elf_backend_always_renumber_dynsyms
}; };
/* Forward declaration for use when initialising alternative_target field. */ /* Forward declaration for use when initialising alternative_target field. */

View File

@ -1,3 +1,12 @@
2017-04-26 Maciej W. Rozycki <macro@imgtec.com>
PR ld/21334
* testsuite/ld-mips-elf/pr21334.dd: New test.
* testsuite/ld-mips-elf/pr21334.gd: New test.
* testsuite/ld-mips-elf/pr21334.ld: New test linker script.
* testsuite/ld-mips-elf/pr21334.s: New test source.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
2017-04-24 H.J. Lu <hongjiu.lu@intel.com> 2017-04-24 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/ld-x86-64/no-plt.exp: Also check no-plt-1e.nd. * testsuite/ld-x86-64/no-plt.exp: Also check no-plt-1e.nd.

View File

@ -1129,3 +1129,13 @@ if { $linux_gnu } {
"export-$class-ref"]] "export-$class-ref"]]
} }
} }
# PR ld/21334 GOT relocation in static binary test.
run_ld_link_tests [list \
[list \
"PR ld/21233 MIPS GOT16 relocation in static binary" \
"$abi_ldflags(o32) -e foo -T pr21334.ld" "" "$abi_asflags(o32)" \
{pr21334.s} \
{{objdump {-d --prefix-addresses} pr21334.dd} \
{readelf -A pr21334.gd}} \
"pr21334"]]

View File

@ -0,0 +1,10 @@
.*: +file format .*mips.*
Disassembly of section \.text:
[0-9a-f]+ <[^>]*> lui gp,0x1
[0-9a-f]+ <[^>]*> addiu gp,gp,-32736
[0-9a-f]+ <[^>]*> addu gp,gp,t9
[0-9a-f]+ <[^>]*> lw v0,-32744\(gp\)
[0-9a-f]+ <[^>]*> jr ra
[0-9a-f]+ <[^>]*> addiu v0,v0,4
\.\.\.

View File

@ -0,0 +1,11 @@
Static GOT:
Canonical gp value: 00008020
Reserved entries:
Address Access Value
00000030 -32752\(gp\) 00000000
00000034 -32748\(gp\) 80000000
Local entries:
Address Access Value
00000038 -32744\(gp\) 00000000

View File

@ -0,0 +1,9 @@
SECTIONS
{
.text : { *(.text) }
HIDDEN (_gp = ALIGN (16) + 0x7ff0);
.got : { *(.got) }
.symtab : { *(.symtab) }
.strtab : { *(.strtab) }
/DISCARD/ : { *(*) }
}

View File

@ -0,0 +1,20 @@
.abicalls
.text
.set noreorder
.globl foo
.ent foo
foo:
.frame $sp, 0, $31
.mask 0x00000000, 0
.fmask 0x00000000, 0
.cpload $25
lw $2, %got(bar)($28)
jr $31
addiu $2, $2, 4
.end foo
.weak bar
.hidden bar
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16