From 1bb82b89ae9d884016e55f2ade99c74fcc92a581 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Thu, 19 Jan 2023 13:48:58 -0800 Subject: [PATCH] i386: Don't emit unsupported TLS relocs on Solaris Emit R_386_TLS_LE and R_386_TLS_IE, instead of R_386_TLS_LE_32 and R_386_TLS_IE_32, on Solaris. PR ld/13671 * elf32-i386.c (elf_i386_tls_transition): Only emit R_386_TLS_LE, R_386_TLS_IE on Solaris. (elf_i386_relocate_section): Only use R_386_TLS_GD->R_386_TLS_LE transition on Solaris. Co-Authored-By: H.J. Lu --- bfd/elf32-i386.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 9e398eacb81..a542029c068 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1062,6 +1062,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, unsigned int from_type = *r_type; unsigned int to_type = from_type; bool check = true; + unsigned int to_le_type, to_ie_type; /* Skip TLS transition for functions. */ if (h != NULL @@ -1069,6 +1070,18 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, || h->type == STT_GNU_IFUNC)) return true; + if (get_elf_backend_data (abfd)->target_os == is_solaris) + { + /* NB: Solaris only supports R_386_TLS_LE and R_386_TLS_IE. */ + to_le_type = R_386_TLS_LE; + to_ie_type = R_386_TLS_IE; + } + else + { + to_le_type = R_386_TLS_LE_32; + to_ie_type = R_386_TLS_IE_32; + } + switch (from_type) { case R_386_TLS_GD: @@ -1080,10 +1093,10 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, if (bfd_link_executable (info)) { if (h == NULL) - to_type = R_386_TLS_LE_32; + to_type = to_le_type; else if (from_type != R_386_TLS_IE && from_type != R_386_TLS_GOTIE) - to_type = R_386_TLS_IE_32; + to_type = to_ie_type; } /* When we are called from elf_i386_relocate_section, there may @@ -1093,7 +1106,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, unsigned int new_to_type = to_type; if (TLS_TRANSITION_IE_TO_LE_P (info, h, tls_type)) - new_to_type = R_386_TLS_LE_32; + new_to_type = to_le_type; if (to_type == R_386_TLS_GD || to_type == R_386_TLS_GOTDESC @@ -1102,7 +1115,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, if (tls_type == GOT_TLS_IE_POS) new_to_type = R_386_TLS_GOTIE; else if (tls_type & GOT_TLS_IE) - new_to_type = R_386_TLS_IE_32; + new_to_type = to_ie_type; } /* We checked the transition before when we were called from @@ -1116,7 +1129,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, case R_386_TLS_LDM: if (bfd_link_executable (info)) - to_type = R_386_TLS_LE_32; + to_type = to_le_type; break; default: @@ -2024,6 +2037,7 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Rela *wrel; Elf_Internal_Rela *relend; bool is_vxworks_tls; + unsigned expected_tls_le; unsigned plt_entry_size; /* Skip if check_relocs or scan_relocs failed. */ @@ -2853,9 +2867,17 @@ elf_i386_relocate_section (bfd *output_bfd, relend, h, r_symndx, true)) return false; - if (r_type_tls == R_386_TLS_LE_32) + expected_tls_le = htab->elf.target_os == is_solaris + ? R_386_TLS_LE : R_386_TLS_LE_32; + if (r_type_tls == expected_tls_le) { - BFD_ASSERT (! unresolved_reloc); + /* NB: Solaris only supports R_386_TLS_GD->R_386_TLS_LE. */ + BFD_ASSERT (! unresolved_reloc + && (htab->elf.target_os != is_solaris + || (htab->elf.target_os == is_solaris + && (r_type == R_386_TLS_GD + || r_type == R_386_TLS_IE + || r_type == R_386_TLS_GOTIE)))); if (r_type == R_386_TLS_GD) { unsigned int type; @@ -3352,7 +3374,9 @@ elf_i386_relocate_section (bfd *output_bfd, into: movl %gs:0, %eax leal 0(%esi), %esi */ - BFD_ASSERT (r_type == R_386_TLS_LE_32); + expected_tls_le = htab->elf.target_os == is_solaris + ? R_386_TLS_LE : R_386_TLS_LE_32; + BFD_ASSERT (r_type == expected_tls_le); if (*(contents + rel->r_offset + 4) == 0xff || *(contents + rel->r_offset + 4) == 0x67) memcpy (contents + rel->r_offset - 2, -- 2.30.2