diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1062,6 +1062,7 @@ elf_i386_tls_transition (struct bfd_link 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 || 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 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 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 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 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_b 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_b 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_b 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,