]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: add external linking support for GOARCH=mips{,le}
authorVladimir Stefanovic <vladimir.stefanovic@imgtec.com>
Tue, 13 Dec 2016 20:23:39 +0000 (21:23 +0100)
committerIan Lance Taylor <iant@golang.org>
Wed, 14 Dec 2016 23:51:55 +0000 (23:51 +0000)
Fixes #17792.

Change-Id: If4f24455eec0edb3b221aef6777a681f6c768866
Reviewed-on: https://go-review.googlesource.com/34313
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/link/internal/ld/config.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/mips/asm.go

index c9ee8847ad2bf0dfca86c53c3d7c944827de0201..7d00ff167553d860096bc65a54617c7948d55195 100644 (file)
@@ -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"
        }
 
index ef9f253414e2f9e3a41ae50d199aee12186e3007..1d8a5dd35e6dc21881ef7c581749372e6eca8359 100644 (file)
@@ -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:
index a2700d9698271c9b8ce2a478c322348450f3eac6..74d79d394c641fa59bf174825f5a3514b3a085fe 100644 (file)
@@ -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
 }
index b2c72893a114833cf8016246ff2b2e2a53851a0b..a591b06dfa02828770268f21c03af692732957f4 100644 (file)
@@ -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
        }