diff options
author | Maciej W. Rozycki <macro@mips.com> | 2018-07-11 17:44:45 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@mips.com> | 2018-07-11 17:44:45 +0100 |
commit | 9143e72c6d4ddefbcb41c0f6361ad140354145ef (patch) | |
tree | 92c02bfaf506d52724d22dc7164d76d4dad698ea /bfd/elfxx-mips.c | |
parent | 04879304dea94c02f19fa5c219d2cbee6269f9af (diff) | |
download | binutils-gdb-9143e72c6d4ddefbcb41c0f6361ad140354145ef.tar.gz |
PR ld/22570: MIPS/BFD: Fix TLS relocation resolution for PIE executables
Correct a commit 0e1862bb401f ("Add output_type to bfd_link_info") issue
and use `bfd_link_dll' rather than `bfd_link_pic' in determining whether
to fully resolve GD, LD and IE TLS relocations referring to symbols
locally defined rather than deferring them to the load time by means of
dynamic relocations.
Such symbols cannot be preempted in PIE executables, which are
necessarily PIC, and therefore their values (thread pointer offsets) are
fixed at the static link time as is the associated module ID of the main
executable.
Given the `tlsbin-o32.s' and `tlsdyn-o32.s' sources from our test suite
this removes the absolute TLS relocations from the static:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000 R_MIPS_NONE *ABS*
1000002c R_MIPS_TLS_TPREL32 *ABS*
10000030 R_MIPS_TLS_DTPMOD32 *ABS*
10000038 R_MIPS_TLS_DTPMOD32 *ABS*
and the dynamic:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000 R_MIPS_NONE *ABS*
1000002c R_MIPS_TLS_TPREL32 *ABS*
10000038 R_MIPS_TLS_DTPMOD32 *ABS*
10000044 R_MIPS_TLS_DTPMOD32 *ABS*
10000030 R_MIPS_TLS_DTPMOD32 tlsvar_gd
10000034 R_MIPS_TLS_DTPREL32 tlsvar_gd
10000040 R_MIPS_TLS_TPREL32 tlsvar_ie
PIE executable respectively, as reported by `objdump -R', and fills the
corresponding GOT slots with the values expected, as recorded with the
test cases added. The new output from `objdump -R' is:
DYNAMIC RELOCATION RECORDS (none)
and:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000 R_MIPS_NONE *ABS*
10000030 R_MIPS_TLS_DTPMOD32 tlsvar_gd
10000034 R_MIPS_TLS_DTPREL32 tlsvar_gd
10000040 R_MIPS_TLS_TPREL32 tlsvar_ie
for the static and the dynamic executable respectively.
2018-07-11 Maciej W. Rozycki <macro@mips.com>
Rich Felker <bugdal@aerifal.cx>
bfd/
PR ld/22570
* elfxx-mips.c (mips_tls_got_relocs): Use `bfd_link_dll' rather
than `bfd_link_pic' to determine whether dynamic relocations are
to be produced.
(mips_elf_initialize_tls_slots): Likewise.
ld/
PR ld/22570
* testsuite/ld-mips-elf/tlsbin-pie-o32.d: New test.
* testsuite/ld-mips-elf/tlsbin-pie-o32.got: New test.
* testsuite/ld-mips-elf/tlsdyn-pie-o32.d: New test.
* testsuite/ld-mips-elf/tlsdyn-pie-o32.got: New test.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r-- | bfd/elfxx-mips.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 990e3a1e551..a35390783b2 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -3255,7 +3255,7 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type, && (!bfd_link_pic (info) || !SYMBOL_REFERENCES_LOCAL (info, h))) indx = h->dynindx; - if ((bfd_link_pic (info) || indx != 0) + if ((bfd_link_dll (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) @@ -3273,7 +3273,7 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type, return 1; case GOT_TLS_LDM: - return bfd_link_pic (info) ? 1 : 0; + return bfd_link_dll (info) ? 1 : 0; default: return 0; @@ -3367,7 +3367,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info, if (entry->tls_initialized) return; - if ((bfd_link_pic (info) || indx != 0) + if ((bfd_link_dll (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) @@ -3442,7 +3442,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info, sgot->contents + got_offset + MIPS_ELF_GOT_SIZE (abfd)); - if (!bfd_link_pic (info)) + if (!bfd_link_dll (info)) MIPS_ELF_PUT_WORD (abfd, 1, sgot->contents + got_offset); else |