]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, cmd/link, runtime: a saner model for TLS on arm
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Tue, 1 Sep 2015 22:35:54 +0000 (10:35 +1200)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 10 Sep 2015 19:49:13 +0000 (19:49 +0000)
this leaves lots of cruft behind, will delete that soon

Change-Id: I12d6b6192f89bcdd89b2b0873774bd3458373b8a
Reviewed-on: https://go-review.googlesource.com/14196
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/internal/obj/arm/a.out.go
src/cmd/internal/obj/arm/anames5.go
src/cmd/internal/obj/arm/asm5.go
src/cmd/link/internal/arm/asm.go
src/cmd/link/internal/ld/data.go
src/runtime/tls_arm.s

index 6c9cfd52d160975bcf7497519084d5178c443ccf..ca166e1317728b36e48f9af140d11d2880d22758 100644 (file)
@@ -155,6 +155,16 @@ const (
        C_HREG
 
        C_ADDR /* reference to relocatable address */
+
+       // 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_TEXTSIZE
 
        C_GOK
index 2e3a1f92dd8bd1745d8bd92cb27b694ec1a0c322..e3f98ce83199413c4127017325f05fe1b55ae91c 100644 (file)
@@ -41,6 +41,8 @@ var cnames5 = []string{
        "SP",
        "HREG",
        "ADDR",
+       "C_TLS_LE",
+       "C_TLS_IE",
        "TEXTSIZE",
        "GOK",
        "NCLASS",
index 12012965b1f940884edc10c82eb1ff6a3b484003..60baa8d1d539b0d37bb22bc6a26f790bbd89c385 100644 (file)
@@ -104,6 +104,8 @@ var optab = []Optab{
        Optab{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
        Optab{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
        Optab{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
+       Optab{AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0},
+       Optab{AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0},
        Optab{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
        Optab{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
        Optab{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
@@ -151,6 +153,8 @@ var optab = []Optab{
        Optab{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
        Optab{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
        Optab{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0},
+       Optab{AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0},
        Optab{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
        Optab{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
        Optab{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
@@ -1016,6 +1020,14 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        }
 
                        ctxt.Instoffset = 0 // s.b. unused but just in case
+                       if a.Sym.Type == obj.STLSBSS {
+                               if ctxt.Flag_shared != 0 {
+                                       return C_TLS_IE
+                               } else {
+                                       return C_TLS_LE
+                               }
+                       }
+
                        return C_ADDR
 
                case obj.NAME_AUTO:
@@ -2037,6 +2049,50 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
                }
 
+       case 101: /* movw tlsvar,R, local exec*/
+               if p.Scond&C_SCOND != C_SCOND_NONE {
+                       ctxt.Diag("conditional tls")
+               }
+               o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+
+       case 102: /* movw tlsvar,R, initial exec*/
+               if p.Scond&C_SCOND != C_SCOND_NONE {
+                       ctxt.Diag("conditional tls")
+               }
+               o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+               o2 = olrr(ctxt, int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
+
+       case 103: /* word tlsvar, local exec */
+               if p.To.Sym == nil {
+                       ctxt.Diag("nil sym in tls %v", p)
+               }
+               if p.To.Offset != 0 {
+                       ctxt.Diag("offset against tls var in %v", p)
+               }
+               // This case happens with words generated in the PC stream as part of
+               // the literal pool.
+               rel := obj.Addrel(ctxt.Cursym)
+
+               rel.Off = int32(ctxt.Pc)
+               rel.Siz = 4
+               rel.Sym = p.To.Sym
+               rel.Type = obj.R_TLS_LE
+               o1 = 0
+
+       case 104: /* word tlsvar, initial exec */
+               if p.To.Sym == nil {
+                       ctxt.Diag("nil sym in tls %v", p)
+               }
+               if p.To.Offset != 0 {
+                       ctxt.Diag("offset against tls var in %v", p)
+               }
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc)
+               rel.Siz = 4
+               rel.Sym = p.To.Sym
+               rel.Type = obj.R_TLS_IE
+               rel.Add = ctxt.Pc - p.Rel.Pc - 8 - int64(rel.Siz)
+
        case 68: /* floating point store -> ADDR */
                o1 = omvl(ctxt, p, &p.To, REGTMP)
 
index a0e31a3c49c77b51829def5c04f873987c6d1cc6..848d0963cef1c95a8cc21336217a32499f943bf5 100644 (file)
@@ -233,6 +233,12 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
                } else {
                        return -1
                }
+
+       case obj.R_TLS_LE:
+               ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8)
+
+       case obj.R_TLS_IE:
+               ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8)
        }
 
        return 0
index 4263e8cf2693ceb6b9c2e7ec0f2bfd152b56c733..b8cf5b9fc24760a0efc10cdd0e6f65404f7af5a5 100644 (file)
@@ -395,15 +395,7 @@ func relocsym(s *LSym) {
                                break
                        }
                        if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' {
-                               // On ELF ARM, the thread pointer is 8 bytes before
-                               // the start of the thread-local data block, so add 8
-                               // to the actual TLS offset (r->sym->value).
-                               // This 8 seems to be a fundamental constant of
-                               // ELF on ARM (or maybe Glibc on ARM); it is not
-                               // related to the fact that our own TLS storage happens
-                               // to take up 8 bytes.
-                               o = 8 + r.Sym.Value
-
+                               panic("should no longer get here")
                                break
                        }
 
@@ -416,8 +408,10 @@ func relocsym(s *LSym) {
                case obj.R_TLS_LE:
                        if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
                                r.Done = 0
-                               r.Sym = Ctxt.Tlsg
-                               r.Xsym = Ctxt.Tlsg
+                               if r.Sym == nil {
+                                       r.Sym = Ctxt.Tlsg
+                               }
+                               r.Xsym = r.Sym
                                r.Xadd = r.Add
                                o = 0
                                if Thearch.Thechar != '6' {
@@ -426,7 +420,16 @@ func relocsym(s *LSym) {
                                break
                        }
 
-                       if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
+                       if Iself && Thearch.Thechar == '5' {
+                               // On ELF ARM, the thread pointer is 8 bytes before
+                               // the start of the thread-local data block, so add 8
+                               // to the actual TLS offset (r->sym->value).
+                               // This 8 seems to be a fundamental constant of
+                               // ELF on ARM (or maybe Glibc on ARM); it is not
+                               // related to the fact that our own TLS storage happens
+                               // to take up 8 bytes.
+                               o = 8 + r.Sym.Value
+                       } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
                                o = int64(Ctxt.Tlsoffset) + r.Add
                        } else if Ctxt.Headtype == obj.Hwindows {
                                o = r.Add
@@ -437,8 +440,10 @@ func relocsym(s *LSym) {
                case obj.R_TLS_IE:
                        if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
                                r.Done = 0
-                               r.Sym = Ctxt.Tlsg
-                               r.Xsym = Ctxt.Tlsg
+                               if r.Sym == nil {
+                                       r.Sym = Ctxt.Tlsg
+                               }
+                               r.Xsym = r.Sym
                                r.Xadd = r.Add
                                o = 0
                                if Thearch.Thechar != '6' {
index d37970e1f831e6ac46a646ce8b5722ba7d856e8f..4ff0ae4ccc6660a41ab4a4e026a008dfca1c58c4 100644 (file)
@@ -15,7 +15,7 @@
 // Note: both functions will clobber R0 and R11 and
 // can be called from 5c ABI code.
 
-// On android and darwin, runtime.tlsg is a normal variable.
+// On android and darwin, runtime.tls_g is a normal variable.
 // TLS offset is computed in x_cgo_inittls.
 #ifdef GOOS_android
 #define TLSG_IS_VARIABLE
@@ -41,14 +41,7 @@ TEXT runtime·save_g(SB),NOSPLIT,$-4
        // The replacement function saves LR in R11 over the call to read_tls_fallback.
        MRC     15, 0, R0, C13, C0, 3 // fetch TLS base pointer
        BIC $3, R0 // Darwin/ARM might return unaligned pointer
-       // $runtime.tlsg(SB) is a special linker symbol.
-       // It is the offset from the TLS base pointer to our
-       // thread-local storage for g.
-#ifdef TLSG_IS_VARIABLE
-       MOVW    runtime·tlsg(SB), R11
-#else
-       MOVW    $runtime·tlsg(SB), R11
-#endif
+       MOVW    runtime·tls_g(SB), R11
        ADD     R11, R0
        MOVW    g, 0(R0)
        MOVW    g, R0 // preserve R0 across call to setg<>
@@ -68,11 +61,7 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
        // $runtime.tlsg(SB) is a special linker symbol.
        // It is the offset from the TLS base pointer to our
        // thread-local storage for g.
-#ifdef TLSG_IS_VARIABLE
-       MOVW    runtime·tlsg(SB), R11
-#else
-       MOVW    $runtime·tlsg(SB), R11
-#endif
+       MOVW    runtime·tls_g(SB), R11
        ADD     R11, R0
        MOVW    0(R0), g
        RET
@@ -95,7 +84,11 @@ TEXT runtime·_initcgo(SB),NOSPLIT,$4
        B.EQ    nocgo
        MRC     15, 0, R0, C13, C0, 3   // load TLS base pointer
        MOVW    R0, R3                  // arg 3: TLS base pointer
-       MOVW    $runtime·tlsg(SB), R2  // arg 2: tlsg
+#ifdef TLSG_IS_VARIABLE
+       MOVW    $runtime·tls_g(SB), R2         // arg 2: &tls_g
+#else
+        MOVW   $0, R2                  // arg 2: not used when using platform tls
+#endif
        MOVW    $setg_gcc<>(SB), R1     // arg 1: setg
        MOVW    g, R0                   // arg 0: G
        BL      (R4) // will clobber R0-R3
@@ -109,5 +102,7 @@ TEXT setg_gcc<>(SB),NOSPLIT,$0
        B               runtime·save_g(SB)
 
 #ifdef TLSG_IS_VARIABLE
-GLOBL runtime·tlsg+0(SB), NOPTR, $4
+GLOBL runtime·tls_g+0(SB), NOPTR, $4
+#else
+GLOBL runtime·tls_g+0(SB), TLSBSS, $4
 #endif