Commit c9b8cab1 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj, cmd/link, runtime: handle TLS more like a platform linker on ppc64

On ppc64x, the thread pointer, held in R13, points 0x7000 bytes past where
thread-local storage begins (presumably to maximize the amount of storage that
can be accessed with a 16-bit signed displacement). The relocations used to
indicate thread-local storage to the platform linker account for this, so to be
able to support external linking we need to change things so the linker applies
this offset instead of the runtime assembly.

Change-Id: I2556c249ab2d802cae62c44b2b4c5b44787d7059
Reviewed-on: https://go-review.googlesource.com/14233Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Reviewed-by: 's avatarAustin Clements <austin@google.com>
parent a59a2756
...@@ -451,6 +451,14 @@ const ( ...@@ -451,6 +451,14 @@ const (
// the thread local base and the thread local variable defined by the // the thread local base and the thread local variable defined by the
// referenced (thread local) symbol from the GOT. // referenced (thread local) symbol from the GOT.
R_ARM64_TLS_IE R_ARM64_TLS_IE
// PPC64.
// R_POWER_TLS_LE is used to implement the "local exec" model for tls
// access. It resolves to the offset of the thread-local symbol from the
// thread pointer (R13) and inserts this value into the low 16 bits of an
// instruction word.
R_POWER_TLS_LE
) )
type Auto struct { type Auto struct {
......
...@@ -220,6 +220,7 @@ const ( ...@@ -220,6 +220,7 @@ const (
C_ANY C_ANY
C_GOK C_GOK
C_ADDR C_ADDR
C_TLS_LE
C_TEXTSIZE C_TEXTSIZE
C_NCLASS /* must be the last */ C_NCLASS /* must be the last */
......
...@@ -35,6 +35,7 @@ var cnames9 = []string{ ...@@ -35,6 +35,7 @@ var cnames9 = []string{
"ANY", "ANY",
"GOK", "GOK",
"ADDR", "ADDR",
"TLS_LE",
"TEXTSIZE", "TEXTSIZE",
"NCLASS", "NCLASS",
} }
...@@ -245,6 +245,8 @@ var optab = []Optab{ ...@@ -245,6 +245,8 @@ var optab = []Optab{
{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0}, {AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0}, {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 79, 4, 0},
/* load constant */ /* load constant */
{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, {AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP}, {AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
...@@ -583,6 +585,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -583,6 +585,9 @@ 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 {
return C_TLS_LE
}
return C_ADDR return C_ADDR
} }
return C_LEXT return C_LEXT
...@@ -2396,6 +2401,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2396,6 +2401,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
//if(dlm) reloc(&p->from, p->pc, 1); //if(dlm) reloc(&p->from, p->pc, 1);
case 79:
if p.From.Offset != 0 {
ctxt.Diag("invalid offset against tls var %v", p)
}
o1 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGZERO, 0)
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 4
rel.Sym = p.From.Sym
rel.Type = obj.R_POWER_TLS_LE
} }
out[0] = o1 out[0] = o1
......
...@@ -408,6 +408,18 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -408,6 +408,18 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
*val = ld.Symaddr(r.Sym) + r.Add - symtoc(s) *val = ld.Symaddr(r.Sym) + r.Add - symtoc(s)
return 0 return 0
case obj.R_POWER_TLS_LE:
// The thread pointer points 0x7000 bytes after the start of the the
// thread local storage area as documented in section "3.7.2 TLS
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
// Specification".
v := r.Sym.Value - 0x7000
if int64(int16(v)) != v {
ld.Diag("TLS offset out of range %d", v)
}
*val = (*val &^ 0xffff) | (v & 0xffff)
return 0
} }
return -1 return -1
......
...@@ -26,16 +26,8 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0 ...@@ -26,16 +26,8 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
MOVB runtime·iscgo(SB), R31 MOVB runtime·iscgo(SB), R31
CMP R31, $0 CMP R31, $0
BEQ nocgo BEQ nocgo
MOVD runtime·tls_g(SB), R31
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the start of TLS to our
// thread-local storage for g.
MOVD $runtime·tls_g(SB), R31
ADD R13, R31 ADD R13, R31
// The actual TLS base is 0x7000 below R13
SUB $0x7000, R31
// Store g in TLS
MOVD g, 0(R31) MOVD g, 0(R31)
nocgo: nocgo:
...@@ -51,11 +43,8 @@ nocgo: ...@@ -51,11 +43,8 @@ nocgo:
// //
// NOTE: _cgo_topofstack assumes this only clobbers g (R30), and R31. // NOTE: _cgo_topofstack assumes this only clobbers g (R30), and R31.
TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0 TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
MOVD $runtime·tls_g(SB), R31 MOVD runtime·tls_g(SB), R31
// R13 is the C ABI TLS base pointer + 0x7000
ADD R13, R31 ADD R13, R31
SUB $0x7000, R31
MOVD 0(R31), g MOVD 0(R31), g
RET RET
......
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