diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2017-04-24 20:15:31 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2017-04-26 13:17:07 +0100 |
commit | 23ec1e32b1ab714649a7c25e49b5d721fe3bd3db (patch) | |
tree | 86f02a16d136cb6895ca179e1ba5d9e8dda7ccc7 /bfd/elflink.c | |
parent | c46cec3a8cfe02fbe0f6c67ba53abc5369c5c659 (diff) | |
download | gdb-23ec1e32b1ab714649a7c25e49b5d721fe3bd3db.zip gdb-23ec1e32b1ab714649a7c25e49b5d721fe3bd3db.tar.gz gdb-23ec1e32b1ab714649a7c25e49b5d721fe3bd3db.tar.bz2 |
PR ld/21334: Always call `_bfd_elf_link_renumber_dynsyms' if required
Complement commit e17b0c351f0b ("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.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 05b1211..73af763 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -6460,7 +6460,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, &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, §ion_sym_count); } @@ -6828,6 +6832,8 @@ bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) { const struct elf_backend_data *bed; + unsigned long section_sym_count; + bfd_size_type dynsymcount; if (!is_elf_hash_table (info->hash)) 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->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, + §ion_sym_count); + if (elf_hash_table (info)->dynamic_sections_created) { bfd *dynobj; asection *s; - bfd_size_type dynsymcount; - unsigned long section_sym_count; unsigned int dtagcount; 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, - §ion_sym_count); - /* Work out the size of the symbol version section. */ s = bfd_get_linker_section (dynobj, ".gnu.version"); BFD_ASSERT (s != NULL); |