Commit 80d91064 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj, cmd/link: support inital-exec TLS on arm64

Change-Id: Iaf9159a68fa395245bc20ccb4a2a377f89371a7e
Reviewed-on: https://go-review.googlesource.com/13996Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent 72180c3b
...@@ -321,7 +321,16 @@ const ( ...@@ -321,7 +321,16 @@ const (
C_LOREG C_LOREG
C_ADDR // TODO(aram): explain difference from C_VCONADDR C_ADDR // TODO(aram): explain difference from C_VCONADDR
C_TLS // TLS var, i.e. memory address containing offset for the var
// TLS "var" in local exec mode: will become a constant offset from
// thread local base that is ultimately chosen by the program linker.
C_TLS_LE
// TLS "var" in initial exec mode: will become a memory address (chosen
// by the program linker) that the dynamic linker will fill with the
// offset from the thread local base.
C_TLS_IE
C_ROFF // register offset (including register extended) C_ROFF // register offset (including register extended)
C_GOK C_GOK
......
...@@ -55,7 +55,8 @@ var cnames7 = []string{ ...@@ -55,7 +55,8 @@ var cnames7 = []string{
"UOREG64K", "UOREG64K",
"LOREG", "LOREG",
"ADDR", "ADDR",
"TLS", "TLS_LE",
"TLS_IE",
"ROFF", "ROFF",
"GOK", "GOK",
"TEXTSIZE", "TEXTSIZE",
......
...@@ -270,7 +270,8 @@ var optab = []Optab{ ...@@ -270,7 +270,8 @@ var optab = []Optab{
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0}, {AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVW, 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_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
{AMOVD, C_TLS, C_NONE, C_REG, 69, 4, 0, 0, 0}, {AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
{AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
{AMUL, C_REG, C_REG, C_REG, 15, 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}, {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, {AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
...@@ -970,7 +971,11 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -970,7 +971,11 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
ctxt.Instoffset = a.Offset ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation if a.Sym != nil { // use relocation
if a.Sym.Type == obj.STLSBSS { if a.Sym.Type == obj.STLSBSS {
return C_TLS if ctxt.Flag_shared != 0 {
return C_TLS_IE
} else {
return C_TLS_LE
}
} }
return C_ADDR return C_ADDR
} }
...@@ -1045,10 +1050,12 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -1045,10 +1050,12 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
case obj.NAME_EXTERN, case obj.NAME_EXTERN,
obj.NAME_STATIC: obj.NAME_STATIC:
s := a.Sym if a.Sym == nil {
if s == nil {
break break
} }
if a.Sym.Type == obj.STLSBSS {
ctxt.Diag("taking address of TLS variable is not supported")
}
ctxt.Instoffset = a.Offset ctxt.Instoffset = a.Offset
return C_VCONADDR return C_VCONADDR
...@@ -2757,7 +2764,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2757,7 +2764,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
rel.Add = p.From.Offset rel.Add = p.From.Offset
rel.Type = obj.R_ADDRARM64 rel.Type = obj.R_ADDRARM64
case 69: /* movd $tlsvar, reg -> movz reg, 0 + reloc */ case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
o1 = opirr(ctxt, AMOVZ) o1 = opirr(ctxt, AMOVZ)
o1 |= uint32(p.To.Reg & 31) o1 |= uint32(p.To.Reg & 31)
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(ctxt.Cursym)
...@@ -2769,6 +2776,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2769,6 +2776,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
ctxt.Diag("invalid offset on MOVW $tlsvar") ctxt.Diag("invalid offset on MOVW $tlsvar")
} }
case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
o1 = ADR(1, 0, REGTMP)
o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = p.From.Sym
rel.Add = 0
rel.Type = obj.R_ARM64_TLS_IE
if p.From.Offset != 0 {
ctxt.Diag("invalid offset on MOVW $tlsvar")
}
// This is supposed to be something that stops execution. // This is supposed to be something that stops execution.
// It's not supposed to be reached, ever, but if it is, we'd // 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 // like to be able to tell how we got there. Assemble as
......
...@@ -446,6 +446,11 @@ const ( ...@@ -446,6 +446,11 @@ const (
// local base to the thread local variable defined by the referenced (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. // local) symbol. Error if the offset does not fit into 16 bits.
R_ARM64_TLS_LE R_ARM64_TLS_LE
// Relocates an ADRP; LD64 instruction sequence to load the offset between
// the thread local base and the thread local variable defined by the
// referenced (thread local) symbol from the GOT.
R_ARM64_TLS_IE
) )
type Auto struct { type Auto struct {
......
...@@ -76,6 +76,12 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int { ...@@ -76,6 +76,12 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
case obj.R_ARM64_TLS_LE: case obj.R_ARM64_TLS_LE:
ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32) ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32)
case obj.R_ARM64_TLS_IE:
ld.Thearch.Vput(ld.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 | uint64(elfsym)<<32)
ld.Thearch.Vput(uint64(r.Xadd))
ld.Thearch.Vput(uint64(sectoff + 4))
ld.Thearch.Vput(ld.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC | uint64(elfsym)<<32)
case obj.R_CALLARM64: case obj.R_CALLARM64:
if r.Siz != 4 { if r.Siz != 4 {
return -1 return -1
...@@ -229,7 +235,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -229,7 +235,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
return 0 return 0
case obj.R_CALLARM64, case obj.R_CALLARM64,
obj.R_ARM64_TLS_LE: obj.R_ARM64_TLS_LE,
obj.R_ARM64_TLS_IE:
r.Done = 0 r.Done = 0
r.Xsym = r.Sym r.Xsym = r.Sym
r.Xadd = r.Add r.Xadd = r.Add
......
...@@ -351,12 +351,14 @@ const ( ...@@ -351,12 +351,14 @@ const (
R_X86_64_TPOFF32 = 23 R_X86_64_TPOFF32 = 23
R_X86_64_COUNT = 24 R_X86_64_COUNT = 24
R_AARCH64_ABS64 = 257 R_AARCH64_ABS64 = 257
R_AARCH64_ABS32 = 258 R_AARCH64_ABS32 = 258
R_AARCH64_CALL26 = 283 R_AARCH64_CALL26 = 283
R_AARCH64_ADR_PREL_PG_HI21 = 275 R_AARCH64_ADR_PREL_PG_HI21 = 275
R_AARCH64_ADD_ABS_LO12_NC = 277 R_AARCH64_ADD_ABS_LO12_NC = 277
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
R_ALPHA_NONE = 0 R_ALPHA_NONE = 0
R_ALPHA_REFLONG = 1 R_ALPHA_REFLONG = 1
......
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