mirror of
https://github.com/golang/go
synced 2024-11-24 06:30:22 -07:00
cmd/internal/obj/mips, cmd/link: add support TLS relocation for mips64x
a new relocation R_ADDRMIPSTLS is added, which resolves to 16-bit offset of a TLS address on mips64x. Change-Id: Ic60d0e1ba49ff1c433cead242f5884677ab227a5 Reviewed-on: https://go-review.googlesource.com/19804 Reviewed-by: Minux Ma <minux@golang.org>
This commit is contained in:
parent
77c7f12438
commit
3b0b30727c
@ -585,6 +585,9 @@ const (
|
|||||||
// R_ADDRMIPSU (only used on mips64) resolves to the sign-adjusted "upper" 16
|
// R_ADDRMIPSU (only used on mips64) resolves to the sign-adjusted "upper" 16
|
||||||
// bits (bit 16-31) of an external address, by encoding it into the instruction.
|
// bits (bit 16-31) of an external address, by encoding it into the instruction.
|
||||||
R_ADDRMIPSU
|
R_ADDRMIPSU
|
||||||
|
// R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
|
||||||
|
// address (offset from thread pointer), by encoding it into the instruction.
|
||||||
|
R_ADDRMIPSTLS
|
||||||
)
|
)
|
||||||
|
|
||||||
type Auto struct {
|
type Auto struct {
|
||||||
|
@ -243,6 +243,7 @@ const (
|
|||||||
C_LACON /* $n(REG) where int16 < n <= int32 */
|
C_LACON /* $n(REG) where int16 < n <= int32 */
|
||||||
C_LECON
|
C_LECON
|
||||||
C_DACON /* $n(REG) where int32 < n */
|
C_DACON /* $n(REG) where int32 < n */
|
||||||
|
C_STCON /* $tlsvar */
|
||||||
C_SBRA
|
C_SBRA
|
||||||
C_LBRA
|
C_LBRA
|
||||||
C_SAUTO
|
C_SAUTO
|
||||||
@ -254,6 +255,7 @@ const (
|
|||||||
C_LOREG
|
C_LOREG
|
||||||
C_GOK
|
C_GOK
|
||||||
C_ADDR
|
C_ADDR
|
||||||
|
C_TLS
|
||||||
C_TEXTSIZE
|
C_TEXTSIZE
|
||||||
|
|
||||||
C_NCLASS /* must be the last */
|
C_NCLASS /* must be the last */
|
||||||
|
@ -26,6 +26,7 @@ var cnames0 = []string{
|
|||||||
"LACON",
|
"LACON",
|
||||||
"LECON",
|
"LECON",
|
||||||
"DACON",
|
"DACON",
|
||||||
|
"STCON",
|
||||||
"SBRA",
|
"SBRA",
|
||||||
"LBRA",
|
"LBRA",
|
||||||
"SAUTO",
|
"SAUTO",
|
||||||
@ -37,6 +38,7 @@ var cnames0 = []string{
|
|||||||
"LOREG",
|
"LOREG",
|
||||||
"GOK",
|
"GOK",
|
||||||
"ADDR",
|
"ADDR",
|
||||||
|
"TLS",
|
||||||
"TEXTSIZE",
|
"TEXTSIZE",
|
||||||
"NCLASS",
|
"NCLASS",
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,11 @@ var optab = []Optab{
|
|||||||
{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
||||||
{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
||||||
{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
|
||||||
|
{AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0},
|
||||||
|
{AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0},
|
||||||
|
{AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0},
|
||||||
|
{AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0},
|
||||||
|
{AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0},
|
||||||
|
|
||||||
{AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
|
{AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
|
||||||
{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
|
{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
|
||||||
@ -162,6 +167,11 @@ var optab = []Optab{
|
|||||||
{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
||||||
{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
||||||
{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
|
||||||
|
{AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0},
|
||||||
|
{AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0},
|
||||||
|
{AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0},
|
||||||
|
{AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0},
|
||||||
|
{AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0},
|
||||||
|
|
||||||
{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
|
{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
|
||||||
{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
|
{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
|
||||||
@ -175,6 +185,8 @@ var optab = []Optab{
|
|||||||
{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
||||||
{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
||||||
{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
|
||||||
|
{AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0},
|
||||||
|
{AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0},
|
||||||
|
|
||||||
{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
|
{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
|
||||||
{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
|
{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
|
||||||
@ -476,6 +488,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
|
|||||||
}
|
}
|
||||||
ctxt.Instoffset = a.Offset
|
ctxt.Instoffset = a.Offset
|
||||||
if a.Sym != nil { // use relocation
|
if a.Sym != nil { // use relocation
|
||||||
|
if a.Sym.Type == obj.STLSBSS {
|
||||||
|
return C_TLS
|
||||||
|
}
|
||||||
return C_ADDR
|
return C_ADDR
|
||||||
}
|
}
|
||||||
return C_LEXT
|
return C_LEXT
|
||||||
@ -539,6 +554,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctxt.Instoffset = a.Offset
|
ctxt.Instoffset = a.Offset
|
||||||
|
if s.Type == obj.STLSBSS {
|
||||||
|
return C_STCON // address of TLS variable
|
||||||
|
}
|
||||||
return C_LECON
|
return C_LECON
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
@ -1387,6 +1405,40 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
rel2.Sym = p.From.Sym
|
rel2.Sym = p.From.Sym
|
||||||
rel2.Add = p.From.Offset
|
rel2.Add = p.From.Offset
|
||||||
rel2.Type = obj.R_ADDRMIPS
|
rel2.Type = obj.R_ADDRMIPS
|
||||||
|
|
||||||
|
case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
|
||||||
|
// clobbers R3 !
|
||||||
|
// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
|
||||||
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
||||||
|
o2 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
|
||||||
|
rel := obj.Addrel(ctxt.Cursym)
|
||||||
|
rel.Off = int32(ctxt.Pc + 4)
|
||||||
|
rel.Siz = 4
|
||||||
|
rel.Sym = p.To.Sym
|
||||||
|
rel.Add = p.To.Offset
|
||||||
|
rel.Type = obj.R_ADDRMIPSTLS
|
||||||
|
|
||||||
|
case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
|
||||||
|
// clobbers R3 !
|
||||||
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
||||||
|
o2 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
|
||||||
|
rel := obj.Addrel(ctxt.Cursym)
|
||||||
|
rel.Off = int32(ctxt.Pc + 4)
|
||||||
|
rel.Siz = 4
|
||||||
|
rel.Sym = p.From.Sym
|
||||||
|
rel.Add = p.From.Offset
|
||||||
|
rel.Type = obj.R_ADDRMIPSTLS
|
||||||
|
|
||||||
|
case 55: /* mov $tlsvar, r ==> rdhwr + add */
|
||||||
|
// clobbers R3 !
|
||||||
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
||||||
|
o2 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
|
||||||
|
rel := obj.Addrel(ctxt.Cursym)
|
||||||
|
rel.Off = int32(ctxt.Pc + 4)
|
||||||
|
rel.Siz = 4
|
||||||
|
rel.Sym = p.From.Sym
|
||||||
|
rel.Add = p.From.Offset
|
||||||
|
rel.Type = obj.R_ADDRMIPSTLS
|
||||||
}
|
}
|
||||||
|
|
||||||
out[0] = o1
|
out[0] = o1
|
||||||
|
@ -81,6 +81,9 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
|
|||||||
case obj.R_ADDRMIPSU:
|
case obj.R_ADDRMIPSU:
|
||||||
ld.Cput(ld.R_MIPS_HI16)
|
ld.Cput(ld.R_MIPS_HI16)
|
||||||
|
|
||||||
|
case obj.R_ADDRMIPSTLS:
|
||||||
|
ld.Cput(ld.R_MIPS_TLS_TPREL_LO16)
|
||||||
|
|
||||||
case obj.R_CALLMIPS,
|
case obj.R_CALLMIPS,
|
||||||
obj.R_JMPMIPS:
|
obj.R_JMPMIPS:
|
||||||
ld.Cput(ld.R_MIPS_26)
|
ld.Cput(ld.R_MIPS_26)
|
||||||
@ -123,7 +126,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
case obj.R_CALLMIPS,
|
case obj.R_ADDRMIPSTLS,
|
||||||
|
obj.R_CALLMIPS,
|
||||||
obj.R_JMPMIPS:
|
obj.R_JMPMIPS:
|
||||||
r.Done = 0
|
r.Done = 0
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
@ -152,6 +156,16 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
case obj.R_ADDRMIPSTLS:
|
||||||
|
// thread pointer is at 0x7000 offset from the start of TLS data area
|
||||||
|
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
|
||||||
|
if t < -32768 || t >= 32678 {
|
||||||
|
ld.Diag("TLS offset out of range %d", t)
|
||||||
|
}
|
||||||
|
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
|
||||||
|
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
|
||||||
|
return 0
|
||||||
|
|
||||||
case obj.R_CALLMIPS,
|
case obj.R_CALLMIPS,
|
||||||
obj.R_JMPMIPS:
|
obj.R_JMPMIPS:
|
||||||
// Low 26 bits = (S + A) >> 2
|
// Low 26 bits = (S + A) >> 2
|
||||||
|
Loading…
Reference in New Issue
Block a user