Browse Source

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.
pull/6/head
Andrew Waterman 12 years ago
parent
commit
1726740bae
  1. 189
      binutils/bfd/elfxx-riscv.c
  2. 10
      binutils/gas/config/tc-riscv.c
  3. 33
      binutils/include/elf/riscv.h
  4. 5
      gcc/gcc/config/riscv/riscv-protos.h
  5. 56
      gcc/gcc/config/riscv/riscv.c
  6. 33
      gcc/gcc/config/riscv/riscv.md
  7. 49
      glibc/sysdeps/riscv/dl-machine.h
  8. 7
      patches/binutils

189
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

10
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 */

33
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. */

5
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);

56
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(";
}
}

33
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" "<MODE>")])
(define_insn "tls_add_tp_ie<mode>"
[(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" "<MODE>")])
(define_insn "got_load_tls_gd<mode>"
[(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" "<MODE>")])
(define_insn "got_load_tls_ie_hi<mode>"
[(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" "<MODE>")])
(define_insn "got_load_tls_ie_lo<mode>"
[(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"
"<load>\t%0,%%tls_ie_lo(%2)(%1)"
[(set_attr "type" "load")
(set_attr "mode" "<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.

49
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;

7
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,

Loading…
Cancel
Save