Commit a3b670e3 authored by Vladimir Stefanovic's avatar Vladimir Stefanovic Committed by Ian Lance Taylor

cmd/link: add external linking support for GOARCH=mips{,le}

Fixes #17792.

Change-Id: If4f24455eec0edb3b221aef6777a681f6c768866
Reviewed-on: https://go-review.googlesource.com/34313Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 96414ca3
......@@ -184,7 +184,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
// Internally linking cgo is incomplete on some architectures.
// https://golang.org/issue/10373
// https://golang.org/issue/14449
if iscgo && SysArch.InFamily(sys.ARM64, sys.MIPS64) {
if iscgo && SysArch.InFamily(sys.ARM64, sys.MIPS64, sys.MIPS) {
return true, obj.GOARCH + " does not support internal cgo"
}
......
......@@ -962,7 +962,7 @@ func Elfinit(ctxt *Link) {
ehdr.flags = 0x5000002 // has entry point, Version5 EABI
}
} else if SysArch.Family == sys.MIPS {
ehdr.flags = 0x50000000 /* MIPS 32 */
ehdr.flags = 0x50001004 /* MIPS 32 CPIC O32*/
}
fallthrough
default:
......
......@@ -1257,6 +1257,8 @@ func hostlinkArchArgs() []string {
// nothing needed
case sys.MIPS64:
return []string{"-mabi=64"}
case sys.MIPS:
return []string{"-mabi=32"}
}
return nil
}
......
......@@ -47,7 +47,33 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
}
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int {
return -1
ld.Thearch.Lput(uint32(sectoff))
elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
case obj.R_ADDR:
if r.Siz != 4 {
return -1
}
ld.Thearch.Lput(ld.R_MIPS_32 | uint32(elfsym)<<8)
case obj.R_ADDRMIPS:
ld.Thearch.Lput(ld.R_MIPS_LO16 | uint32(elfsym)<<8)
case obj.R_ADDRMIPSU:
ld.Thearch.Lput(ld.R_MIPS_HI16 | uint32(elfsym)<<8)
case obj.R_ADDRMIPSTLS:
ld.Thearch.Lput(ld.R_MIPS_TLS_TPREL_LO16 | uint32(elfsym)<<8)
case obj.R_CALLMIPS, obj.R_JMPMIPS:
ld.Thearch.Lput(ld.R_MIPS_26 | uint32(elfsym)<<8)
}
return 0
}
func elfsetupplt(ctxt *ld.Link) {
......@@ -58,9 +84,50 @@ func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
return -1
}
func applyrel(r *ld.Reloc, s *ld.Symbol, val *int64, t int64) {
o := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
switch r.Type {
case obj.R_ADDRMIPS, obj.R_ADDRMIPSTLS:
*val = int64(o&0xffff0000 | uint32(t)&0xffff)
case obj.R_ADDRMIPSU:
*val = int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
case obj.R_CALLMIPS, obj.R_JMPMIPS:
*val = int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
}
}
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
if ld.Linkmode == ld.LinkExternal {
return -1
switch r.Type {
default:
return -1
case obj.R_ADDRMIPS, obj.R_ADDRMIPSU:
r.Done = 0
// set up addend for eventual relocation via outer symbol.
rs := r.Sym
r.Xadd = r.Add
for rs.Outer != nil {
r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
rs = rs.Outer
}
if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name)
}
r.Xsym = rs
applyrel(r, s, val, r.Xadd)
return 0
case obj.R_ADDRMIPSTLS, obj.R_CALLMIPS, obj.R_JMPMIPS:
r.Done = 0
r.Xsym = r.Sym
r.Xadd = r.Add
applyrel(r, s, val, r.Add)
return 0
}
}
switch r.Type {
......@@ -72,23 +139,33 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
return 0
case obj.R_ADDRMIPS,
obj.R_ADDRMIPSU:
case obj.R_ADDRMIPS, obj.R_ADDRMIPSU:
t := ld.Symaddr(r.Sym) + r.Add
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
if r.Type == obj.R_ADDRMIPS {
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
} else {
*val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
}
applyrel(r, s, val, t)
return 0
case obj.R_CALLMIPS,
obj.R_JMPMIPS:
// Low 26 bits = (S + A) >> 2
case obj.R_CALLMIPS, obj.R_JMPMIPS:
t := ld.Symaddr(r.Sym) + r.Add
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
if t&3 != 0 {
ld.Errorf(s, "direct call is not aligned: %s %x", r.Sym.Name, t)
}
// check if target address is in the same 256 MB region as the next instruction
if (s.Value+int64(r.Off)+4)&0xf0000000 != (t & 0xf0000000) {
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
}
applyrel(r, s, val, t)
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.Errorf(s, "TLS offset out of range %d", t)
}
applyrel(r, s, val, t)
return 0
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment