]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, cmd/link: support inital-exec TLS on arm64
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 28 Oct 2015 02:27:51 +0000 (15:27 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 28 Oct 2015 19:51:28 +0000 (19:51 +0000)
Change-Id: Iaf9159a68fa395245bc20ccb4a2a377f89371a7e
Reviewed-on: https://go-review.googlesource.com/13996
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/cmd/internal/obj/arm64/a.out.go
src/cmd/internal/obj/arm64/anames7.go
src/cmd/internal/obj/arm64/asm7.go
src/cmd/internal/obj/link.go
src/cmd/link/internal/arm64/asm.go
src/cmd/link/internal/ld/elf.go

index 534a6d0a6df4f99be3a7a70debe70697d7b3ecd8..06c4ea552d36aeff2de9ea97c3c6d726d3b70f65 100644 (file)
@@ -321,7 +321,16 @@ const (
        C_LOREG
 
        C_ADDR // TODO(aram): explain difference from C_VCONADDR
-       C_TLS  // TLS var, i.e. memory address containing offset for the var
+
+       // 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_ROFF // register offset (including register extended)
 
        C_GOK
index 8ea42fd5b66d869cb5765b53b9f185216aaa3b2b..f9df74ff89807189901dbb1a0699d7d294cac594 100644 (file)
@@ -55,7 +55,8 @@ var cnames7 = []string{
        "UOREG64K",
        "LOREG",
        "ADDR",
-       "TLS",
+       "TLS_LE",
+       "TLS_IE",
        "ROFF",
        "GOK",
        "TEXTSIZE",
index 49060600ea4adf23ad3627bb7225df8348f9493d..1fd8982a988cef419bedc76b22ccb84928fa5841 100644 (file)
@@ -270,7 +270,8 @@ var optab = []Optab{
        {AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
        {AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
        {AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
-       {AMOVD, C_TLS, C_NONE, C_REG, 69, 4, 0, 0, 0},
+       {AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
+       {AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
        {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
        {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
        {AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
@@ -970,7 +971,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
+                                       if ctxt.Flag_shared != 0 {
+                                               return C_TLS_IE
+                                       } else {
+                                               return C_TLS_LE
+                                       }
                                }
                                return C_ADDR
                        }
@@ -1045,10 +1050,12 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 
                case obj.NAME_EXTERN,
                        obj.NAME_STATIC:
-                       s := a.Sym
-                       if s == nil {
+                       if a.Sym == nil {
                                break
                        }
+                       if a.Sym.Type == obj.STLSBSS {
+                               ctxt.Diag("taking address of TLS variable is not supported")
+                       }
                        ctxt.Instoffset = a.Offset
                        return C_VCONADDR
 
@@ -2757,7 +2764,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel.Add = p.From.Offset
                rel.Type = obj.R_ADDRARM64
 
-       case 69: /* movd $tlsvar, reg -> movz reg, 0 + reloc */
+       case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
                o1 = opirr(ctxt, AMOVZ)
                o1 |= uint32(p.To.Reg & 31)
                rel := obj.Addrel(ctxt.Cursym)
@@ -2769,6 +2776,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        ctxt.Diag("invalid offset on MOVW $tlsvar")
                }
 
+       case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
+               o1 = ADR(1, 0, REGTMP)
+               o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc)
+               rel.Siz = 8
+               rel.Sym = p.From.Sym
+               rel.Add = 0
+               rel.Type = obj.R_ARM64_TLS_IE
+               if p.From.Offset != 0 {
+                       ctxt.Diag("invalid offset on MOVW $tlsvar")
+               }
+
        // This is supposed to be something that stops execution.
        // It's not supposed to be reached, ever, but if it is, we'd
        // like to be able to tell how we got there.  Assemble as
index cddcdcef3be822c0bef60001f6e47e3d9b3a8cc1..6ca34f28d3d05596b01b6af15a61a199dd5aa4b1 100644 (file)
@@ -446,6 +446,11 @@ const (
        // local base to the thread local variable defined by the referenced (thread
        // local) symbol. Error if the offset does not fit into 16 bits.
        R_ARM64_TLS_LE
+
+       // Relocates an ADRP; LD64 instruction sequence to load the offset between
+       // the thread local base and the thread local variable defined by the
+       // referenced (thread local) symbol from the GOT.
+       R_ARM64_TLS_IE
 )
 
 type Auto struct {
index 3d4d8c623d19ec649e33efb4038e6153e84df1c2..58d5236398a53b178f393fdfe04abf8afcba2fff 100644 (file)
@@ -76,6 +76,12 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
        case obj.R_ARM64_TLS_LE:
                ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32)
 
+       case obj.R_ARM64_TLS_IE:
+               ld.Thearch.Vput(ld.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 | uint64(elfsym)<<32)
+               ld.Thearch.Vput(uint64(r.Xadd))
+               ld.Thearch.Vput(uint64(sectoff + 4))
+               ld.Thearch.Vput(ld.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC | uint64(elfsym)<<32)
+
        case obj.R_CALLARM64:
                if r.Siz != 4 {
                        return -1
@@ -229,7 +235,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
                        return 0
 
                case obj.R_CALLARM64,
-                       obj.R_ARM64_TLS_LE:
+                       obj.R_ARM64_TLS_LE,
+                       obj.R_ARM64_TLS_IE:
                        r.Done = 0
                        r.Xsym = r.Sym
                        r.Xadd = r.Add
index d3baf05d371e0dc51e09a633630df5d26f088451..16c669e806455f6976bd14804e78e04160d5ee27 100644 (file)
@@ -351,12 +351,14 @@ const (
        R_X86_64_TPOFF32  = 23
        R_X86_64_COUNT    = 24
 
-       R_AARCH64_ABS64               = 257
-       R_AARCH64_ABS32               = 258
-       R_AARCH64_CALL26              = 283
-       R_AARCH64_ADR_PREL_PG_HI21    = 275
-       R_AARCH64_ADD_ABS_LO12_NC     = 277
-       R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
+       R_AARCH64_ABS64                       = 257
+       R_AARCH64_ABS32                       = 258
+       R_AARCH64_CALL26                      = 283
+       R_AARCH64_ADR_PREL_PG_HI21            = 275
+       R_AARCH64_ADD_ABS_LO12_NC             = 277
+       R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21   = 541
+       R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
+       R_AARCH64_TLSLE_MOVW_TPREL_G0         = 547
 
        R_ALPHA_NONE           = 0
        R_ALPHA_REFLONG        = 1