]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, cmd/link, runtime: handle TLS more like a platform linker on ppc64
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 29 Oct 2015 21:13:13 +0000 (10:13 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 29 Oct 2015 22:24:29 +0000 (22:24 +0000)
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/14233
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/internal/obj/link.go
src/cmd/internal/obj/ppc64/a.out.go
src/cmd/internal/obj/ppc64/anames9.go
src/cmd/internal/obj/ppc64/asm9.go
src/cmd/link/internal/ppc64/asm.go
src/runtime/tls_ppc64x.s

index 6ca34f28d3d05596b01b6af15a61a199dd5aa4b1..ef63a7047b2c7fc441d22f30a168be7ec67d9aeb 100644 (file)
@@ -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 {
index 3028b6cac8d41850d8221825636251f4fbd80e4a..ea868fdb5f94d2077bc70cf329a0d7da5a6e769b 100644 (file)
@@ -220,6 +220,7 @@ const (
        C_ANY
        C_GOK
        C_ADDR
+       C_TLS_LE
        C_TEXTSIZE
 
        C_NCLASS /* must be the last */
index b48e5162b01a6b84ffb26cdaa7642d66d713a6b7..62125a4e5234843a4ada93772ef9820a08db1a37 100644 (file)
@@ -35,6 +35,7 @@ var cnames9 = []string{
        "ANY",
        "GOK",
        "ADDR",
+       "TLS_LE",
        "TEXTSIZE",
        "NCLASS",
 }
index 993cf178cdeeb89b245d82ed6d5f7ba510dfe5d5..22ec99db048be7f2ec2502b7a67394282c9b01ce 100644 (file)
@@ -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
index 3798b24f214d41bceffe040fa58e0e6e6d8f5819..b8ab53446168b35011c9bbd31d95791c0b52d545 100644 (file)
@@ -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
index d930718c3ed1b85a37cf2dd5039c90face90d536..1b030fd36adec410c6708cc84b670eb01e02b805 100644 (file)
@@ -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