mirror of
https://github.com/golang/go
synced 2024-09-30 10:18:32 -06:00
cmd/internal/obj, cmd/link: support inital-exec TLS on arm64
Change-Id: Iaf9159a68fa395245bc20ccb4a2a377f89371a7e Reviewed-on: https://go-review.googlesource.com/13996 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
72180c3b82
commit
80d9106487
@ -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
|
||||
|
@ -55,7 +55,8 @@ var cnames7 = []string{
|
||||
"UOREG64K",
|
||||
"LOREG",
|
||||
"ADDR",
|
||||
"TLS",
|
||||
"TLS_LE",
|
||||
"TLS_IE",
|
||||
"ROFF",
|
||||
"GOK",
|
||||
"TEXTSIZE",
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user