aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2014-10-22 17:21:44 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2014-10-22 20:18:30 -0700
commit1726740baee385b3e744e40bfe51e6debd5436ba (patch)
treebe98f5bf69d1d57899b606588ec8e1651495941c /binutils
parentc4276840c8e41dc39c4e0b24807d882e68d89f32 (diff)
downloadriscv-gnu-toolchain-1726740baee385b3e744e40bfe51e6debd5436ba.zip
riscv-gnu-toolchain-1726740baee385b3e744e40bfe51e6debd5436ba.tar.gz
riscv-gnu-toolchain-1726740baee385b3e744e40bfe51e6debd5436ba.tar.bz2
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.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/bfd/elfxx-riscv.c189
-rw-r--r--binutils/gas/config/tc-riscv.c10
-rw-r--r--binutils/include/elf/riscv.h33
3 files changed, 38 insertions, 194 deletions
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. */