From 1726740baee385b3e744e40bfe51e6debd5436ba Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 22 Oct 2014 17:21:44 -0700 Subject: [PATCH] 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 +++-- gcc/gcc/config/riscv/riscv-protos.h | 5 +- gcc/gcc/config/riscv/riscv.c | 56 ++------- gcc/gcc/config/riscv/riscv.md | 33 ----- glibc/sysdeps/riscv/dl-machine.h | 49 +++++--- patches/binutils | 7 +- 8 files changed, 83 insertions(+), 299 deletions(-) diff --git a/binutils/bfd/elfxx-riscv.c b/binutils/bfd/elfxx-riscv.c index 59b78bd1..1c10121d 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 e1175428..1016819c 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 da2f2fca..607269e0 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. */ diff --git a/gcc/gcc/config/riscv/riscv-protos.h b/gcc/gcc/config/riscv/riscv-protos.h index 429da71e..5120cb1c 100644 --- a/gcc/gcc/config/riscv/riscv-protos.h +++ b/gcc/gcc/config/riscv/riscv-protos.h @@ -26,10 +26,9 @@ enum mips_symbol_type { SYMBOL_ABSOLUTE, SYMBOL_GOT_DISP, SYMBOL_TLS, - SYMBOL_TLS_LE, - SYMBOL_TLS_IE + SYMBOL_TLS_LE }; -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_IE + 1) +#define NUM_SYMBOL_TYPES (SYMBOL_TLS_LE + 1) extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *); extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool); diff --git a/gcc/gcc/config/riscv/riscv.c b/gcc/gcc/config/riscv/riscv.c index 8492b38a..f108c42b 100644 --- a/gcc/gcc/config/riscv/riscv.c +++ b/gcc/gcc/config/riscv/riscv.c @@ -586,11 +586,10 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) switch (*symbol_type) { case SYMBOL_ABSOLUTE: + case SYMBOL_TLS_LE: return (int32_t) INTVAL (offset) == INTVAL (offset); case SYMBOL_TLS: - case SYMBOL_TLS_LE: - case SYMBOL_TLS_IE: case SYMBOL_GOT_DISP: return false; } @@ -606,7 +605,6 @@ static int riscv_symbol_insns (enum mips_symbol_type type) case SYMBOL_TLS: return 0; /* Depends on the TLS model. */ case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference itself */ case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference itself */ - case SYMBOL_TLS_IE: return 4; /* LUI + LD + ADD TP + the reference itself */ case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference itself */ default: gcc_unreachable(); } @@ -1065,22 +1063,6 @@ static rtx riscv_got_load_tls_ie(rtx dest, rtx sym) return (Pmode == DImode ? gen_got_load_tls_iedi(dest, sym) : gen_got_load_tls_iesi(dest, sym)); } -static rtx riscv_got_load_tls_ie_hi(rtx dest, rtx sym) -{ - return (Pmode == DImode ? gen_got_load_tls_ie_hidi(dest, sym) : gen_got_load_tls_ie_hisi(dest, sym)); -} - -static rtx riscv_got_load_tls_ie_lo(rtx dest, rtx base, rtx sym) -{ - return (Pmode == DImode ? gen_got_load_tls_ie_lodi(dest, base, sym) : gen_got_load_tls_ie_losi(dest, base, sym)); -} - -static rtx riscv_tls_add_tp_ie(rtx dest, rtx base, rtx sym) -{ - rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); - return (Pmode == DImode ? gen_tls_add_tp_iedi(dest, base, tp, sym) : gen_tls_add_tp_iesi(dest, base, tp, sym)); -} - static rtx riscv_tls_add_tp_le(rtx dest, rtx base, rtx sym) { rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); @@ -1191,8 +1173,13 @@ static rtx mips_legitimize_tls_address (rtx loc) { rtx dest, insn, v0, tp, tmp1; + enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); - switch (SYMBOL_REF_TLS_MODEL (loc)) + /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE. */ + if (!flag_pic) + model = TLS_MODEL_LOCAL_EXEC; + + switch (model) { case TLS_MODEL_LOCAL_DYNAMIC: /* Rely on section anchors for the optimization that LDM TLS @@ -1205,27 +1192,12 @@ mips_legitimize_tls_address (rtx loc) break; case TLS_MODEL_INITIAL_EXEC: - if (flag_pic) - { - /* la.tls.ie; tp-relative add */ - tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); - tmp1 = gen_reg_rtx (Pmode); - emit_insn (riscv_got_load_tls_ie (tmp1, loc)); - dest = gen_reg_rtx (Pmode); - emit_insn (gen_add3_insn (dest, tmp1, tp)); - } - else - { - /* lui %tls_ie_hi; ld %tls_le_lo; tp-relative add */ - tmp1 = gen_reg_rtx (Pmode); - emit_insn (riscv_got_load_tls_ie_hi (tmp1, loc)); - dest = gen_reg_rtx (Pmode); - emit_insn (riscv_got_load_tls_ie_lo (dest, tmp1, loc)); - tmp1 = gen_reg_rtx (Pmode); - emit_insn (riscv_tls_add_tp_ie (tmp1, dest, loc)); - dest = gen_rtx_LO_SUM (Pmode, tmp1, - mips_unspec_address (loc, SYMBOL_TLS_IE)); - } + /* la.tls.ie; tp-relative add */ + tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); + tmp1 = gen_reg_rtx (Pmode); + emit_insn (riscv_got_load_tls_ie (tmp1, loc)); + dest = gen_reg_rtx (Pmode); + emit_insn (gen_add3_insn (dest, tmp1, tp)); break; case TLS_MODEL_LOCAL_EXEC: @@ -2904,8 +2876,6 @@ mips_init_relocs (void) riscv_hi_relocs[SYMBOL_TLS_LE] = "%tprel_hi("; riscv_lo_relocs[SYMBOL_TLS_LE] = "%tprel_lo("; - - riscv_lo_relocs[SYMBOL_TLS_IE] = "%tls_ie_off("; } } diff --git a/gcc/gcc/config/riscv/riscv.md b/gcc/gcc/config/riscv/riscv.md index 0e3d5077..f28269e9 100644 --- a/gcc/gcc/config/riscv/riscv.md +++ b/gcc/gcc/config/riscv/riscv.md @@ -35,11 +35,8 @@ ;; Symbolic accesses. UNSPEC_LOAD_GOT UNSPEC_TLS_LE_ADD - UNSPEC_TLS_IE_ADD UNSPEC_TLS_GD UNSPEC_TLS_IE - UNSPEC_TLS_IE_HI - UNSPEC_TLS_IE_LO ;; Blockage and synchronisation. UNSPEC_BLOCKAGE @@ -1450,17 +1447,6 @@ [(set_attr "type" "arith") (set_attr "mode" "")]) -(define_insn "tls_add_tp_ie" - [(set (match_operand:P 0 "register_operand" "=r") - (unspec:P [(match_operand:P 1 "register_operand" "r") - (match_operand:P 2 "register_operand" "r") - (match_operand:P 3 "symbolic_operand" "")] - UNSPEC_TLS_IE_ADD))] - "!flag_pic" - "add\t%0,%1,%2,%%tls_ie_add(%3)" - [(set_attr "type" "arith") - (set_attr "mode" "")]) - (define_insn "got_load_tls_gd" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(match_operand:P 1 "symbolic_operand" "")] @@ -1479,25 +1465,6 @@ [(set_attr "got" "load") (set_attr "mode" "")]) -(define_insn "got_load_tls_ie_hi" - [(set (match_operand:P 0 "register_operand" "=r") - (unspec:P [(match_operand:P 1 "symbolic_operand" "")] - UNSPEC_TLS_IE_HI))] - "!flag_pic" - "lui\t%0,%%tls_ie_hi(%1)" - [(set_attr "type" "arith") - (set_attr "mode" "")]) - -(define_insn "got_load_tls_ie_lo" - [(set (match_operand:P 0 "register_operand" "=r") - (unspec:P [(match_operand:P 1 "register_operand" "r") - (match_operand:P 2 "symbolic_operand" "")] - UNSPEC_TLS_IE_LO))] - "!flag_pic" - "\t%0,%%tls_ie_lo(%2)(%1)" - [(set_attr "type" "load") - (set_attr "mode" "")]) - ;; Instructions for adding the low 16 bits of an address to a register. ;; Operand 2 is the address: mips_print_operand works out which relocation ;; should be applied. diff --git a/glibc/sysdeps/riscv/dl-machine.h b/glibc/sysdeps/riscv/dl-machine.h index fa8bba8f..d92c3ac8 100644 --- a/glibc/sysdeps/riscv/dl-machine.h +++ b/glibc/sysdeps/riscv/dl-machine.h @@ -186,26 +186,6 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, if (sym_map != NULL) value = sym_map->l_addr + sym->st_value + reloc->r_addend; -#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC - if (__builtin_expect (r_type == R_RISCV_RELATIVE, 0)) - { -# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC - /* This is defined in rtld.c, but nowhere in the static libc.a; - make the reference weak so static programs can still link. - This declaration cannot be done when compiling rtld.c - (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the - common defn for _dl_rtld_map, which is incompatible with a - weak decl in the same file. */ -# ifndef SHARED - weak_extern (GL(dl_rtld_map)); -# endif - if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -# endif - *addr_field = map->l_addr + reloc->r_addend; - return; - } -#endif - switch (r_type) { #ifndef RTLD_BOOTSTRAP @@ -234,6 +214,15 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, found. */ break; + /* Handle TLS copy relocations. */ + if (__glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_TLS)) + { + /* There's nothing to do if the symbol is in .tbss. */ + if (__glibc_likely (sym->st_value >= sym_map->l_tls_initimage_size)) + break; + value += sym_map->l_tls_initimage - sym_map->l_addr; + } + size_t size = sym->st_size; if (__builtin_expect (sym->st_size != refsym->st_size, 0)) { @@ -252,6 +241,26 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, } #endif +#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC + case R_RISCV_RELATIVE: + { +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC + /* This is defined in rtld.c, but nowhere in the static libc.a; + make the reference weak so static programs can still link. + This declaration cannot be done when compiling rtld.c + (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the + common defn for _dl_rtld_map, which is incompatible with a + weak decl in the same file. */ +# ifndef SHARED + weak_extern (GL(dl_rtld_map)); +# endif + if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ +# endif + *addr_field = map->l_addr + reloc->r_addend; + break; + } +#endif + case R_RISCV_JUMP_SLOT: case _RISCV_SIM == _ABI64 ? R_RISCV_64 : R_RISCV_32: *addr_field = value + reloc->r_addend; diff --git a/patches/binutils b/patches/binutils index 3d2a3237..d5f402a7 100644 --- a/patches/binutils +++ b/patches/binutils @@ -28,7 +28,7 @@ bfd_arch_rs6000, /* IBM RS/6000 */ #define bfd_mach_rs6k 6000 #define bfd_mach_rs6k_rs1 6001 -@@ -5227,6 +5230,45 @@ relative offset from _GLOBAL_OFFSET_TABL +@@ -5227,6 +5230,40 @@ relative offset from _GLOBAL_OFFSET_TABL value in a word. The relocation is relative offset from */ BFD_RELOC_MICROBLAZE_32_GOTOFF, @@ -57,11 +57,6 @@ + BFD_RELOC_RISCV_SUB64, + BFD_RELOC_RISCV_GOT_HI20, + BFD_RELOC_RISCV_TLS_GOT_HI20, -+ BFD_RELOC_RISCV_TLS_IE_HI20, -+ BFD_RELOC_RISCV_TLS_IE_LO12, -+ BFD_RELOC_RISCV_TLS_IE_ADD, -+ BFD_RELOC_RISCV_TLS_IE_LO12_I, -+ BFD_RELOC_RISCV_TLS_IE_LO12_S, + BFD_RELOC_RISCV_TLS_GD_HI20, + BFD_RELOC_RISCV_JMP, + BFD_RELOC_RISCV_TLS_DTPMOD32,