Commit 72180c3b authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj, cmd/link, runtime: native-ish support for tls on arm64

Fixes #10560

Change-Id: Iedffd9c236c4fbb386c3afc52c5a1457f96ef122
Reviewed-on: https://go-review.googlesource.com/13991Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 492a62e9
......@@ -321,6 +321,7 @@ const (
C_LOREG
C_ADDR // TODO(aram): explain difference from C_VCONADDR
C_TLS // TLS var, i.e. memory address containing offset for the var
C_ROFF // register offset (including register extended)
C_GOK
......
......@@ -55,6 +55,7 @@ var cnames7 = []string{
"UOREG64K",
"LOREG",
"ADDR",
"TLS",
"ROFF",
"GOK",
"TEXTSIZE",
......
......@@ -270,6 +270,7 @@ var optab = []Optab{
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVD, C_TLS, C_NONE, C_REG, 69, 4, 0, 0, 0},
{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
......@@ -968,6 +969,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
}
ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation
if a.Sym.Type == obj.STLSBSS {
return C_TLS
}
return C_ADDR
}
return C_LEXT
......@@ -2753,6 +2757,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
rel.Add = p.From.Offset
rel.Type = obj.R_ADDRARM64
case 69: /* movd $tlsvar, reg -> movz reg, 0 + reloc */
o1 = opirr(ctxt, AMOVZ)
o1 |= uint32(p.To.Reg & 31)
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 4
rel.Sym = p.From.Sym
rel.Type = obj.R_ARM64_TLS_LE
if p.From.Offset != 0 {
ctxt.Diag("invalid offset on MOVW $tlsvar")
}
// This is supposed to be something that stops execution.
// It's not supposed to be reached, ever, but if it is, we'd
// like to be able to tell how we got there. Assemble as
......
......@@ -432,6 +432,20 @@ const (
R_USEFIELD
R_POWER_TOC
R_GOTPCREL
// Platform dependent relocations. Architectures with fixed width instructions
// have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
// stuffed into a 32-bit instruction, so an address needs to be spread across
// several instructions, and in turn this requires a sequence of relocations, each
// updating a part of an instruction. This leads to relocation codes that are
// inherently processor specific.
// Arm64.
// Set a MOV[NZ] immediate field to bits [15:0] of the offset from the thread
// local base to the thread local variable defined by the referenced (thread
// local) symbol. Error if the offset does not fit into 16 bits.
R_ARM64_TLS_LE
)
type Auto struct {
......
......@@ -73,6 +73,9 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff + 4))
ld.Thearch.Vput(ld.R_AARCH64_ADD_ABS_LO12_NC | uint64(elfsym)<<32)
case obj.R_ARM64_TLS_LE:
ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32)
case obj.R_CALLARM64:
if r.Siz != 4 {
return -1
......@@ -225,7 +228,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
return 0
case obj.R_CALLARM64:
case obj.R_CALLARM64,
obj.R_ARM64_TLS_LE:
r.Done = 0
r.Xsym = r.Sym
r.Xadd = r.Add
......@@ -269,6 +273,20 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
}
return 0
case obj.R_ARM64_TLS_LE:
r.Done = 0
if ld.HEADTYPE != obj.Hlinux {
ld.Diag("TLS reloc on unsupported OS %s", ld.Headstr(int(ld.HEADTYPE)))
}
// The TCB is two pointers. This is not documented anywhere, but is
// de facto part of the ABI.
v := r.Sym.Value + int64(2*ld.Thearch.Ptrsize)
if v < 0 || v >= 32678 {
ld.Diag("TLS offset out of range %d", v)
}
*val |= v << 5
return 0
case obj.R_CALLARM64:
t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
if t >= 1<<27 || t < -1<<27 {
......
......@@ -350,11 +350,14 @@ const (
R_X86_64_GOTTPOFF = 22
R_X86_64_TPOFF32 = 23
R_X86_64_COUNT = 24
R_AARCH64_ABS64 = 257
R_AARCH64_ABS32 = 258
R_AARCH64_CALL26 = 283
R_AARCH64_ADR_PREL_PG_HI21 = 275
R_AARCH64_ADD_ABS_LO12_NC = 277
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
R_ALPHA_NONE = 0
R_ALPHA_REFLONG = 1
R_ALPHA_REFQUAD = 2
......@@ -384,6 +387,7 @@ const (
R_ALPHA_JMP_SLOT = 26
R_ALPHA_RELATIVE = 27
R_ALPHA_COUNT = 28
R_ARM_NONE = 0
R_ARM_PC24 = 1
R_ARM_ABS32 = 2
......@@ -424,6 +428,7 @@ const (
R_ARM_RPC24 = 254
R_ARM_RBASE = 255
R_ARM_COUNT = 38
R_386_NONE = 0
R_386_32 = 1
R_386_PC32 = 2
......@@ -456,6 +461,7 @@ const (
R_386_TLS_DTPOFF32 = 36
R_386_TLS_TPOFF32 = 37
R_386_COUNT = 38
R_PPC_NONE = 0
R_PPC_ADDR32 = 1
R_PPC_ADDR24 = 2
......@@ -535,6 +541,7 @@ const (
R_PPC_EMB_BIT_FLD = 115
R_PPC_EMB_RELSDA = 116
R_PPC_EMB_COUNT = R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1
R_PPC64_REL24 = R_PPC_REL24
R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT
R_PPC64_ADDR64 = 38
......@@ -547,6 +554,7 @@ const (
R_PPC64_REL16_LO = 250
R_PPC64_REL16_HI = 251
R_PPC64_REL16_HA = 252
R_SPARC_NONE = 0
R_SPARC_8 = 1
R_SPARC_16 = 2
......@@ -603,6 +611,7 @@ const (
R_SPARC_REGISTER = 53
R_SPARC_UA64 = 54
R_SPARC_UA16 = 55
ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
)
......
......@@ -38,7 +38,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
#ifdef TLSG_IS_VARIABLE
MOVD $runtime·tls_g(SB), R2 // arg 2: &tls_g
#else
MOVD 0, R2 // arg 2: not used when using platform's TLS
MOVD $0, R2 // arg 2: not used when using platform's TLS
#endif
MOVD $setg_gcc<>(SB), R1 // arg 1: setg
MOVD g, R0 // arg 0: G
......
......@@ -18,13 +18,8 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
// Darwin sometimes returns unaligned pointers
AND $0xfffffffffffffff8, R0
#endif
#ifdef TLSG_IS_VARIABLE
MOVD runtime·tls_g(SB), R27
ADD R27, R0
#else
// TODO(minux): use real TLS relocation, instead of hard-code for Linux
ADD $0x10, R0
#endif
MOVD 0(R0), g
nocgo:
......@@ -40,13 +35,8 @@ TEXT runtime·save_g(SB),NOSPLIT,$0
// Darwin sometimes returns unaligned pointers
AND $0xfffffffffffffff8, R0
#endif
#ifdef TLSG_IS_VARIABLE
MOVD runtime·tls_g(SB), R27
ADD R27, R0
#else
// TODO(minux): use real TLS relocation, instead of hard-code for Linux
ADD $0x10, R0
#endif
MOVD g, 0(R0)
nocgo:
......@@ -54,4 +44,6 @@ nocgo:
#ifdef TLSG_IS_VARIABLE
GLOBL runtime·tls_g+0(SB), NOPTR, $8
#else
GLOBL runtime·tls_g+0(SB), TLSBSS, $8
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment