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: default avatarRuss Cox <rsc@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
parent a59a2756
......@@ -451,6 +451,14 @@ const (
// the thread local base and the thread local variable defined by the
// referenced (thread local) symbol from the GOT.
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 {
......
......@@ -220,6 +220,7 @@ const (
C_ANY
C_GOK
C_ADDR
C_TLS_LE
C_TEXTSIZE
C_NCLASS /* must be the last */
......
......@@ -35,6 +35,7 @@ var cnames9 = []string{
"ANY",
"GOK",
"ADDR",
"TLS_LE",
"TEXTSIZE",
"NCLASS",
}
......@@ -245,6 +245,8 @@ var optab = []Optab{
{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 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 */
{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
{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 {
}
ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation
if a.Sym.Type == obj.STLSBSS {
return C_TLS_LE
}
return C_ADDR
}
return C_LEXT
......@@ -2396,6 +2401,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
//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
......
......@@ -408,6 +408,18 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
*val = ld.Symaddr(r.Sym) + r.Add - symtoc(s)
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
......
......@@ -26,16 +26,8 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
MOVB runtime·iscgo(SB), R31
CMP R31, $0
BEQ nocgo
// $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
MOVD runtime·tls_g(SB), R31
ADD R13, R31
// The actual TLS base is 0x7000 below R13
SUB $0x7000, R31
// Store g in TLS
MOVD g, 0(R31)
nocgo:
......@@ -51,11 +43,8 @@ nocgo:
//
// NOTE: _cgo_topofstack assumes this only clobbers g (R30), and R31.
TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
MOVD $runtime·tls_g(SB), R31
// R13 is the C ABI TLS base pointer + 0x7000
MOVD runtime·tls_g(SB), R31
ADD R13, R31
SUB $0x7000, R31
MOVD 0(R31), g
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