From: Michael Hudson-Doyle Date: Mon, 3 Aug 2015 02:08:17 +0000 (+1200) Subject: cmd/link: pass value being relocated to archreloc X-Git-Tag: go1.6beta1~1223 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=af799d94f9a913b1c6411cbd100ccbb544a70655;p=gostls13.git cmd/link: pass value being relocated to archreloc And clean up the mess on arm64 (the mess on arm is too confusing). See issue #10050 Change-Id: I2ce813fe8646d4e818eb660612a7e4b2bb04de4c Reviewed-on: https://go-review.googlesource.com/13884 Reviewed-by: Ian Lance Taylor --- diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index ab0f7aebdb..ce0d3c1a2b 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -1899,7 +1899,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { rel.Off = int32(ctxt.Pc) rel.Siz = 4 rel.Sym = p.To.Sym - rel.Add = int64(o1) | (p.To.Offset>>2)&0x3ffffff + rel.Add = p.To.Offset rel.Type = obj.R_CALLARM64 case 6: /* b ,O(R); bl ,O(R) */ diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index 3aebd8a223..5888101531 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -191,17 +191,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { } r.Xsym = rs - // the first instruction is always at the lower address, this is endian neutral; - // but note that o0 and o1 should still use the target endian. - o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4]) - o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8]) - // Note: ld64 currently has a bug that any non-zero addend for BR26 relocation // will make the linking fail because it thinks the code is not PIC even though // the BR26 relocation should be fully resolved at link time. // That is the reason why the next if block is disabled. When the bug in ld64 // is fixed, we can enable this block and also enable duff's device in cmd/7g. if false && ld.HEADTYPE == obj.Hdarwin { + var o0, o1 uint32 + + if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { + o0 = uint32(*val >> 32) + o1 = uint32(*val) + } else { + o0 = uint32(*val) + o1 = uint32(*val >> 32) + } // Mach-O wants the addend to be encoded in the instruction // Note that although Mach-O supports ARM64_RELOC_ADDEND, it // can only encode 24-bit of signed addend, but the instructions @@ -210,13 +214,13 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5) o1 |= uint32(r.Xadd&0xfff) << 10 r.Xadd = 0 - } - // when laid out, the instruction order must always be o1, o2. - if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { - *val = int64(o0)<<32 | int64(o1) - } else { - *val = int64(o1)<<32 | int64(o0) + // when laid out, the instruction order must always be o1, o2. + if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { + *val = int64(o0)<<32 | int64(o1) + } else { + *val = int64(o1)<<32 | int64(o0) + } } return 0 @@ -224,9 +228,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { case obj.R_CALLARM64: r.Done = 0 r.Xsym = r.Sym - *val = int64(0xfc000000 & uint32(r.Add)) - r.Xadd = int64((uint32(r.Add) &^ 0xfc000000) * 4) - r.Add = 0 + r.Xadd = r.Add return 0 } } @@ -246,10 +248,15 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ld.Diag("program too large, address relocation distance = %d", t) } - // the first instruction is always at the lower address, this is endian neutral; - // but note that o0 and o1 should still use the target endian. - o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4]) - o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8]) + var o0, o1 uint32 + + if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { + o0 = uint32(*val >> 32) + o1 = uint32(*val) + } else { + o0 = uint32(*val) + o1 = uint32(*val >> 32) + } o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5) o1 |= uint32(t&0xfff) << 10 @@ -263,7 +270,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { return 0 case obj.R_CALLARM64: - *val = int64((0xfc000000 & uint32(r.Add)) | uint32((ld.Symaddr(r.Sym)+r.Add*4-(s.Value+int64(r.Off)))/4)) + t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off)) + if t >= 1<<27 || t < -1<<27 { + ld.Diag("program too large, call relocation distance = %d", t) + } + *val |= (t >> 2) & 0x03ffffff return 0 } diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 55b12e5ece..91a5edd376 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -369,7 +369,18 @@ func relocsym(s *LSym) { switch r.Type { default: - o = 0 + switch siz { + default: + Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name) + case 1: + o = int64(s.P[off]) + case 2: + o = int64(Ctxt.Arch.ByteOrder.Uint16(s.P[off:])) + case 4: + o = int64(Ctxt.Arch.ByteOrder.Uint32(s.P[off:])) + case 8: + o = int64(Ctxt.Arch.ByteOrder.Uint64(s.P[off:])) + } if Thearch.Archreloc(r, s, &o) < 0 { Diag("unknown reloc %d", r.Type) }