From 1726740baee385b3e744e40bfe51e6debd5436ba Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 22 Oct 2014 17:21:44 -0700 Subject: binutils, glibc, gcc: support TLS copy relocations This allows the local-exec model to be used for any non-PIC TLS reference, even if it cannot be proven at compile time that the access binds locally. It essentially obviates the need for IE -> LE relaxations. --- binutils/bfd/elfxx-riscv.c | 189 ++++++----------------------------------- binutils/gas/config/tc-riscv.c | 10 --- binutils/include/elf/riscv.h | 33 +++---- 3 files changed, 38 insertions(+), 194 deletions(-) (limited to 'binutils') diff --git a/binutils/bfd/elfxx-riscv.c b/binutils/bfd/elfxx-riscv.c index 59b78bd..1c10121 100644 --- a/binutils/bfd/elfxx-riscv.c +++ b/binutils/bfd/elfxx-riscv.c @@ -413,81 +413,6 @@ static reloc_howto_type howto_table[] = ENCODE_STYPE_IMM(-1U), /* dst_mask */ FALSE), /* pcrel_offset */ - /* High 20 bits of TLS IE GOT access in non-PIC code. */ - HOWTO (R_RISCV_TLS_IE_HI20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_RISCV_TLS_IE_HI20", /* name */ - TRUE, /* partial_inplace */ - 0, /* src_mask */ - ENCODE_UTYPE_IMM(-1U), /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* Low 12 bits of TLS IE GOT access in non-PIC code. */ - HOWTO (R_RISCV_TLS_IE_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_RISCV_TLS_IE_LO12_I",/* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - ENCODE_ITYPE_IMM(-1U), /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* TLS IE thread pointer usage. */ - HOWTO (R_RISCV_TLS_IE_ADD, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_RISCV_TLS_IE_ADD", /* name */ - TRUE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* TLS IE low-part relocation for relaxation. */ - HOWTO (R_RISCV_TLS_IE_LO12_I, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_RISCV_TLS_IE_LO12_I",/* name */ - TRUE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* TLS IE low-part relocation for relaxation. */ - HOWTO (R_RISCV_TLS_IE_LO12_S, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_RISCV_TLS_IE_LO12_S",/* name */ - TRUE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ - /* High 20 bits of TLS LE thread pointer offset. */ HOWTO (R_RISCV_TPREL_HI20, /* type */ 0, /* rightshift */ @@ -741,11 +666,6 @@ static const struct elf_reloc_map riscv_reloc_map[] = { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD }, { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S }, { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I }, - { BFD_RELOC_RISCV_TLS_IE_HI20, R_RISCV_TLS_IE_HI20 }, - { BFD_RELOC_RISCV_TLS_IE_LO12, R_RISCV_TLS_IE_LO12 }, - { BFD_RELOC_RISCV_TLS_IE_ADD, R_RISCV_TLS_IE_ADD }, - { BFD_RELOC_RISCV_TLS_IE_LO12_S, R_RISCV_TLS_IE_LO12_S }, - { BFD_RELOC_RISCV_TLS_IE_LO12_I, R_RISCV_TLS_IE_LO12_I }, { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 }, { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 }, }; @@ -815,6 +735,7 @@ struct riscv_elf_link_hash_entry #define GOT_NORMAL 1 #define GOT_TLS_GD 2 #define GOT_TLS_IE 4 +#define GOT_TLS_LE 8 char tls_type; }; @@ -854,6 +775,7 @@ struct riscv_elf_link_hash_table /* Short-cuts to get to dynamic linker sections. */ asection *sdynbss; asection *srelbss; + asection *sdyntdata; /* Small local sym to section mapping cache. */ struct sym_cache sym_cache; @@ -1140,10 +1062,15 @@ riscv_elf_create_dynamic_sections (bfd *dynobj, htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); if (!info->shared) - htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); + { + htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); + htab->sdyntdata = + bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn", + SEC_ALLOC | SEC_THREAD_LOCAL); + } if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) + || (!info->shared && (!htab->srelbss || !htab->sdyntdata))) abort (); return TRUE; @@ -1312,14 +1239,6 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, return FALSE; break; - case R_RISCV_TLS_IE_HI20: - if (info->shared) - goto illegal_static_reloc; - if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx) - || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_IE)) - return FALSE; - break; - case R_RISCV_TLS_GOT_HI20: if (info->shared) info->flags |= DF_STATIC_TLS; @@ -1348,11 +1267,15 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } break; + case R_RISCV_TPREL_HI20: + if (h != NULL) + riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_LE); + /* Fall through. */ + case R_RISCV_HI20: if (info->shared && (h == NULL || strcmp (h->root.root.string, "_DYNAMIC") != 0)) { - illegal_static_reloc: /* Absolute relocs don't ordinarily belong in shared libs, but we make an exception for _DYNAMIC for ld.so's purpose. */ (*_bfd_error_handler) @@ -1563,7 +1486,6 @@ riscv_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, case R_RISCV_GOT_HI20: case R_RISCV_TLS_GOT_HI20: case R_RISCV_TLS_GD_HI20: - case R_RISCV_TLS_IE_HI20: if (h != NULL) { if (h->got.refcount > 0) @@ -1729,6 +1651,9 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info, h->needs_copy = 1; } + if (eh->tls_type & ~GOT_NORMAL) + return _bfd_elf_adjust_dynamic_copy (h, htab->sdyntdata); + return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss); } @@ -2241,14 +2166,12 @@ perform_relocation (const reloc_howto_type *howto, case R_RISCV_GOT_HI20: case R_RISCV_TLS_GOT_HI20: case R_RISCV_TLS_GD_HI20: - case R_RISCV_TLS_IE_HI20: value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)); break; case R_RISCV_LO12_I: case R_RISCV_TPREL_LO12_I: case R_RISCV_PCREL_LO12_I: - case R_RISCV_TLS_IE_LO12: value = ENCODE_ITYPE_IMM (value); break; @@ -2541,9 +2464,6 @@ riscv_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, { case R_RISCV_NONE: case R_RISCV_TPREL_ADD: - case R_RISCV_TLS_IE_ADD: - case R_RISCV_TLS_IE_LO12_I: - case R_RISCV_TLS_IE_LO12_S: case R_RISCV_COPY: case R_RISCV_JUMP_SLOT: case R_RISCV_RELATIVE: @@ -2775,8 +2695,6 @@ riscv_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } break; - case R_RISCV_TLS_IE_HI20: - case R_RISCV_TLS_IE_LO12: case R_RISCV_TLS_GOT_HI20: is_ie = TRUE; /* Fall through. */ @@ -3493,6 +3411,8 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count) return TRUE; } +/* Relax AUIPC + JALR into JAL. */ + static bfd_boolean _bfd_riscv_relax_call (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_byte *contents, @@ -3547,6 +3467,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, return TRUE; } +/* Relax non-PIC global variable references. */ + static bfd_boolean _bfd_riscv_relax_lui (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_byte *contents, @@ -3577,6 +3499,8 @@ _bfd_riscv_relax_lui (bfd *abfd, asection *sec, return TRUE; } +/* Relax non-PIC TLS references. */ + static bfd_boolean _bfd_riscv_relax_tls_le (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_byte *contents, @@ -3605,66 +3529,6 @@ _bfd_riscv_relax_tls_le (bfd *abfd, asection *sec, return TRUE; } -/* Relax TLS IE to TLS LE. */ -static bfd_boolean -_bfd_riscv_relax_tls_ie (bfd *abfd, asection *sec, - bfd_byte *contents, - Elf_Internal_Shdr *symtab_hdr, - Elf_Internal_Sym *isymbuf, - Elf_Internal_Rela *internal_relocs, - Elf_Internal_Rela *irel, - bfd_boolean *again) -{ - bfd_vma insn; - - elf_section_data (sec)->relocs = internal_relocs; - elf_section_data (sec)->this_hdr.contents = contents; - symtab_hdr->contents = (unsigned char *) isymbuf; - - switch (ELF_R_TYPE (irel->r_info)) - { - case R_RISCV_TLS_IE_HI20: - /* Replace with R_RISCV_TPREL_HI20. */ - irel->r_info = ELF_R_INFO (abfd, ELF_R_SYM (abfd, irel->r_info), R_RISCV_TPREL_HI20); - /* Overwrite AUIPC with LUI. */ - BFD_ASSERT (irel->r_offset + 4 <= sec->size); - insn = bfd_get_32 (abfd, contents + irel->r_offset); - insn = (insn & ~MASK_LUI) | MATCH_LUI; - bfd_put_32 (abfd, insn, contents + irel->r_offset); - break; - - case R_RISCV_TLS_IE_LO12: - /* Just delete the reloc. */ - irel->r_info = ELF_R_INFO (abfd, ELF_R_SYM (abfd, irel->r_info), R_RISCV_NONE); - if (! riscv_relax_delete_bytes (abfd, sec, irel->r_offset, 4)) - return FALSE; - break; - - case R_RISCV_TLS_IE_ADD: - /* Replace with R_RISCV_TPREL_ADD. */ - irel->r_info = ELF_R_INFO (abfd, ELF_R_SYM (abfd, irel->r_info), R_RISCV_TPREL_ADD); - break; - - case R_RISCV_TLS_IE_LO12_I: - /* Replace with R_RISCV_TPREL_LO12_I. */ - irel->r_info = ELF_R_INFO (abfd, ELF_R_SYM (abfd, irel->r_info), R_RISCV_TPREL_LO12_I); - break; - - case R_RISCV_TLS_IE_LO12_S: - /* Replace with R_RISCV_TPREL_LO12_S. */ - irel->r_info = ELF_R_INFO (abfd, ELF_R_SYM (abfd, irel->r_info), R_RISCV_TPREL_LO12_S); - break; - - default: - abort(); - } - - *again = TRUE; - return TRUE; -} - -/* Relax AUIPC/JALR into JAL. */ - bfd_boolean _bfd_riscv_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again) @@ -3701,9 +3565,8 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, bfd_boolean call = type == R_RISCV_CALL || type == R_RISCV_CALL_PLT; bfd_boolean lui = type == R_RISCV_HI20; bfd_boolean tls_le = type == R_RISCV_TPREL_HI20 || type == R_RISCV_TPREL_ADD; - bfd_boolean tls_ie = type == R_RISCV_TLS_IE_HI20 || type == R_RISCV_TLS_IE_LO12 || type == R_RISCV_TLS_IE_ADD || type == R_RISCV_TLS_IE_LO12_I || type == R_RISCV_TLS_IE_LO12_S; - if (!(call || lui || tls_le || tls_ie)) + if (!(call || lui || tls_le)) continue; /* Get the section contents. */ @@ -3782,10 +3645,6 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, symtab_hdr, isymbuf, internal_relocs, irel, symval, again)) goto error_return; - if (tls_ie && !_bfd_riscv_relax_tls_ie (abfd, sec, contents, symtab_hdr, - isymbuf, internal_relocs, irel, - again)) - goto error_return; } if (isymbuf != NULL diff --git a/binutils/gas/config/tc-riscv.c b/binutils/gas/config/tc-riscv.c index e117542..1016819 100644 --- a/binutils/gas/config/tc-riscv.c +++ b/binutils/gas/config/tc-riscv.c @@ -1311,7 +1311,6 @@ do_call: static const struct percent_op_match percent_op_utype[] = { {"%tprel_hi", BFD_RELOC_RISCV_TPREL_HI20}, - {"%tls_ie_hi", BFD_RELOC_RISCV_TLS_IE_HI20}, {"%pcrel_hi", BFD_RELOC_RISCV_PCREL_HI20}, {"%tls_ie_pcrel_hi", BFD_RELOC_RISCV_TLS_GOT_HI20}, {"%tls_gd_pcrel_hi", BFD_RELOC_RISCV_TLS_GD_HI20}, @@ -1323,8 +1322,6 @@ static const struct percent_op_match percent_op_itype[] = { {"%lo", BFD_RELOC_RISCV_LO12_I}, {"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_I}, - {"%tls_ie_lo", BFD_RELOC_RISCV_TLS_IE_LO12}, - {"%tls_ie_off", BFD_RELOC_RISCV_TLS_IE_LO12_I}, {"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_I}, {0, 0} }; @@ -1333,7 +1330,6 @@ static const struct percent_op_match percent_op_stype[] = { {"%lo", BFD_RELOC_RISCV_LO12_S}, {"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_S}, - {"%tls_ie_off", BFD_RELOC_RISCV_TLS_IE_LO12_S}, {"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_S}, {0, 0} }; @@ -1341,7 +1337,6 @@ static const struct percent_op_match percent_op_stype[] = static const struct percent_op_match percent_op_rtype[] = { {"%tprel_add", BFD_RELOC_RISCV_TPREL_ADD}, - {"%tls_ie_add", BFD_RELOC_RISCV_TLS_IE_ADD}, {0, 0} }; @@ -2046,11 +2041,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_RISCV_TPREL_LO12_I: case BFD_RELOC_RISCV_TPREL_LO12_S: case BFD_RELOC_RISCV_TPREL_ADD: - case BFD_RELOC_RISCV_TLS_IE_HI20: - case BFD_RELOC_RISCV_TLS_IE_LO12: - case BFD_RELOC_RISCV_TLS_IE_ADD: - case BFD_RELOC_RISCV_TLS_IE_LO12_I: - case BFD_RELOC_RISCV_TLS_IE_LO12_S: S_SET_THREAD_LOCAL (fixP->fx_addsy); /* fall through */ diff --git a/binutils/include/elf/riscv.h b/binutils/include/elf/riscv.h index da2f2fc..607269e 100644 --- a/binutils/include/elf/riscv.h +++ b/binutils/include/elf/riscv.h @@ -59,25 +59,20 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type) RELOC_NUMBER (R_RISCV_HI20, 26) RELOC_NUMBER (R_RISCV_LO12_I, 27) RELOC_NUMBER (R_RISCV_LO12_S, 28) - RELOC_NUMBER (R_RISCV_TLS_IE_HI20, 29) - RELOC_NUMBER (R_RISCV_TLS_IE_LO12, 30) - RELOC_NUMBER (R_RISCV_TLS_IE_ADD, 31) - RELOC_NUMBER (R_RISCV_TLS_IE_LO12_I, 32) - RELOC_NUMBER (R_RISCV_TLS_IE_LO12_S, 33) - RELOC_NUMBER (R_RISCV_TPREL_HI20, 34) - RELOC_NUMBER (R_RISCV_TPREL_LO12_I, 35) - RELOC_NUMBER (R_RISCV_TPREL_LO12_S, 36) - RELOC_NUMBER (R_RISCV_TPREL_ADD, 37) - RELOC_NUMBER (R_RISCV_ADD8, 38) - RELOC_NUMBER (R_RISCV_ADD16, 39) - RELOC_NUMBER (R_RISCV_ADD32, 40) - RELOC_NUMBER (R_RISCV_ADD64, 41) - RELOC_NUMBER (R_RISCV_SUB8, 42) - RELOC_NUMBER (R_RISCV_SUB16, 43) - RELOC_NUMBER (R_RISCV_SUB32, 44) - RELOC_NUMBER (R_RISCV_SUB64, 45) - RELOC_NUMBER (R_RISCV_GNU_VTINHERIT, 46) - RELOC_NUMBER (R_RISCV_GNU_VTENTRY, 47) + RELOC_NUMBER (R_RISCV_TPREL_HI20, 29) + RELOC_NUMBER (R_RISCV_TPREL_LO12_I, 30) + RELOC_NUMBER (R_RISCV_TPREL_LO12_S, 31) + RELOC_NUMBER (R_RISCV_TPREL_ADD, 32) + RELOC_NUMBER (R_RISCV_ADD8, 33) + RELOC_NUMBER (R_RISCV_ADD16, 34) + RELOC_NUMBER (R_RISCV_ADD32, 35) + RELOC_NUMBER (R_RISCV_ADD64, 36) + RELOC_NUMBER (R_RISCV_SUB8, 37) + RELOC_NUMBER (R_RISCV_SUB16, 38) + RELOC_NUMBER (R_RISCV_SUB32, 39) + RELOC_NUMBER (R_RISCV_SUB64, 40) + RELOC_NUMBER (R_RISCV_GNU_VTINHERIT, 41) + RELOC_NUMBER (R_RISCV_GNU_VTENTRY, 42) END_RELOC_NUMBERS (R_RISCV_max) /* Processor specific flags for the ELF header e_flags field. */ -- cgit v1.1