]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, runtime: implement IE model TLS on ppc64le
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Fri, 16 Oct 2015 08:15:18 +0000 (21:15 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 12 Nov 2015 23:50:27 +0000 (23:50 +0000)
This requires changing the tls access code to match the patterns documented in
the ABI documentation or the system linker will "optimize" it into ridiculousness.

With this change, -buildmode=pie works, although as it is tested in testshared,
the tests are not run yet.

Change-Id: I1efa6687af0a5b8db3385b10f6542a49056b2eb3
Reviewed-on: https://go-review.googlesource.com/15971
Reviewed-by: Russ Cox <rsc@golang.org>
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/ld/elf.go
src/cmd/link/internal/ppc64/asm.go
src/runtime/tls_ppc64x.s

index ab1de2447b76e85367d9df5f60d3b74993bf54f8..a7e0c2f863abb34e8e5b89e4d27b652d400511ac 100644 (file)
@@ -480,6 +480,19 @@ const (
        // instruction word.
        R_POWER_TLS_LE
 
+       // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
+       // relocates a D-form, DS-form instruction sequence like R_ADDRPOWER_DS. It
+       // inserts to the offset of GOT slot for the thread-local symbol from the TOC (the
+       // GOT slot is filled by the dynamic linker with the offset of the thread-local
+       // symbol from the thread pointer (R13)).
+       R_POWER_TLS_IE
+
+       // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
+       // accessing a particular thread-local symbol. It does not affect code generation
+       // but is used by the system linker when relaxing "initial exec" model code to
+       // "local exec" model code.
+       R_POWER_TLS
+
        // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
        // instruction is a "DS-form" instruction, which has an immediate field occupying
        // bits [15:2] of the instruction word. Bits [15:2] of the address of the
index 3fd4685769fe8d880bbccc28ec4d3d1402fb3e36..d28e1e895e5a4ac7d5c0d689a34860fb2aa0344a 100644 (file)
@@ -222,6 +222,7 @@ const (
        C_GOK
        C_ADDR
        C_TLS_LE
+       C_TLS_IE
        C_TEXTSIZE
 
        C_NCLASS /* must be the last */
index 62125a4e5234843a4ada93772ef9820a08db1a37..1b5d564dfecf9fa31d007632ebef7e1e1c84ca91 100644 (file)
@@ -36,6 +36,7 @@ var cnames9 = []string{
        "GOK",
        "ADDR",
        "TLS_LE",
+       "TLS_IE",
        "TEXTSIZE",
        "NCLASS",
 }
index c226ed540db125312af6b844ba0f8b8be5717c4a..25b9aef83000c5e375ebda5372bed8e05b9799b3 100644 (file)
@@ -246,6 +246,7 @@ var optab = []Optab{
        {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},
+       {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 80, 8, 0},
 
        /* load constant */
        {AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
@@ -587,7 +588,11 @@ 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
+                                       if ctxt.Flag_shared != 0 {
+                                               return C_TLS_IE
+                                       } else {
+                                               return C_TLS_LE
+                                       }
                                }
                                return C_ADDR
                        }
@@ -1652,6 +1657,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        if v != 0 {
                                ctxt.Diag("illegal indexed instruction\n%v", p)
                        }
+                       if ctxt.Flag_shared != 0 && r == REG_R13 {
+                               rel := obj.Addrel(ctxt.Cursym)
+                               rel.Off = int32(ctxt.Pc)
+                               rel.Siz = 4
+                               // This (and the matching part in the load case
+                               // below) are the only places in the ppc64 toolchain
+                               // that knows the name of the tls variable. Possibly
+                               // we could add some assembly syntax so that the name
+                               // of the variable does not have to be assumed.
+                               rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+                               rel.Type = obj.R_POWER_TLS
+                       }
                        o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
                } else {
                        if int32(int16(v)) != v {
@@ -1671,6 +1688,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        if v != 0 {
                                ctxt.Diag("illegal indexed instruction\n%v", p)
                        }
+                       if ctxt.Flag_shared != 0 && r == REG_R13 {
+                               rel := obj.Addrel(ctxt.Cursym)
+                               rel.Off = int32(ctxt.Pc)
+                               rel.Siz = 4
+                               rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+                               rel.Type = obj.R_POWER_TLS
+                       }
                        o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
                } else {
                        if int32(int16(v)) != v {
@@ -2467,6 +2491,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel.Sym = p.From.Sym
                rel.Type = obj.R_POWER_TLS_LE
 
+       case 80:
+               if p.From.Offset != 0 {
+                       ctxt.Diag("invalid offset against tls var %v", p)
+               }
+               o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
+               o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0)
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc)
+               rel.Siz = 8
+               rel.Sym = p.From.Sym
+               rel.Type = obj.R_POWER_TLS_IE
+
        }
 
        out[0] = o1
index 51552e3c152f92b5b860d13f5092e9d9b9f54b2e..505cbcdbb1ab3d1bf39d7fd8f81ccdea4953682e 100644 (file)
@@ -564,23 +564,28 @@ const (
        R_PPC_EMB_BIT_FLD     = 115
        R_PPC_EMB_RELSDA      = 116
 
-       R_PPC64_ADDR32       = R_PPC_ADDR32
-       R_PPC64_ADDR16_LO    = R_PPC_ADDR16_LO
-       R_PPC64_ADDR16_HA    = R_PPC_ADDR16_HA
-       R_PPC64_REL24        = R_PPC_REL24
-       R_PPC64_JMP_SLOT     = R_PPC_JMP_SLOT
-       R_PPC64_TPREL16      = R_PPC_TPREL16
-       R_PPC64_ADDR64       = 38
-       R_PPC64_TOC16        = 47
-       R_PPC64_TOC16_LO     = 48
-       R_PPC64_TOC16_HI     = 49
-       R_PPC64_TOC16_HA     = 50
-       R_PPC64_ADDR16_LO_DS = 57
-       R_PPC64_TOC16_DS     = 63
-       R_PPC64_TOC16_LO_DS  = 64
-       R_PPC64_REL16_LO     = 250
-       R_PPC64_REL16_HI     = 251
-       R_PPC64_REL16_HA     = 252
+       R_PPC64_ADDR32            = R_PPC_ADDR32
+       R_PPC64_ADDR16_LO         = R_PPC_ADDR16_LO
+       R_PPC64_ADDR16_HA         = R_PPC_ADDR16_HA
+       R_PPC64_REL24             = R_PPC_REL24
+       R_PPC64_GOT16_HA          = R_PPC_GOT16_HA
+       R_PPC64_JMP_SLOT          = R_PPC_JMP_SLOT
+       R_PPC64_TPREL16           = R_PPC_TPREL16
+       R_PPC64_ADDR64            = 38
+       R_PPC64_TOC16             = 47
+       R_PPC64_TOC16_LO          = 48
+       R_PPC64_TOC16_HI          = 49
+       R_PPC64_TOC16_HA          = 50
+       R_PPC64_ADDR16_LO_DS      = 57
+       R_PPC64_GOT16_LO_DS       = 59
+       R_PPC64_TOC16_DS          = 63
+       R_PPC64_TOC16_LO_DS       = 64
+       R_PPC64_TLS               = 67
+       R_PPC64_GOT_TPREL16_LO_DS = 88
+       R_PPC64_GOT_TPREL16_HA    = 90
+       R_PPC64_REL16_LO          = 250
+       R_PPC64_REL16_HI          = 251
+       R_PPC64_REL16_HA          = 252
 
        R_SPARC_NONE     = 0
        R_SPARC_8        = 1
index 97efe7d354f06f0e6cecd425ba26e01e984ce11c..706160d0fb0340322164878aa94b037e4f9e104e 100644 (file)
@@ -310,9 +310,18 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
                        return -1
                }
 
+       case obj.R_POWER_TLS:
+               ld.Thearch.Vput(ld.R_PPC64_TLS | uint64(elfsym)<<32)
+
        case obj.R_POWER_TLS_LE:
                ld.Thearch.Vput(ld.R_PPC64_TPREL16 | uint64(elfsym)<<32)
 
+       case obj.R_POWER_TLS_IE:
+               ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_HA | uint64(elfsym)<<32)
+               ld.Thearch.Vput(uint64(r.Xadd))
+               ld.Thearch.Vput(uint64(sectoff + 4))
+               ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_LO_DS | uint64(elfsym)<<32)
+
        case obj.R_ADDRPOWER:
                ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
                ld.Thearch.Vput(uint64(r.Xadd))
@@ -444,7 +453,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
                default:
                        return -1
 
-               case obj.R_POWER_TLS_LE:
+               case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE:
                        r.Done = 0
                        // check Outer is nil, Type is TLSBSS?
                        r.Xadd = r.Add
index 1b030fd36adec410c6708cc84b670eb01e02b805..c79c97dae3f5704259f314efab5fc5f85527afaf 100644 (file)
@@ -27,8 +27,7 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
        CMP     R31, $0
        BEQ     nocgo
        MOVD    runtime·tls_g(SB), R31
-       ADD     R13, R31
-       MOVD    g, 0(R31)
+       MOVD    g, 0(R13)(R31*1)
 
 nocgo:
        RET
@@ -44,8 +43,7 @@ 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
-       ADD     R13, R31
-       MOVD    0(R31), g
+       MOVD    0(R13)(R31*1), g
        RET
 
 GLOBL runtime·tls_g+0(SB), TLSBSS, $8