1
0
mirror of https://github.com/golang/go synced 2024-11-12 09:10:21 -07:00

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 <iant@golang.org>
This commit is contained in:
Michael Hudson-Doyle 2015-08-03 14:08:17 +12:00 committed by Ian Lance Taylor
parent 5f2c420eb6
commit af799d94f9
3 changed files with 43 additions and 21 deletions

View File

@ -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) */

View File

@ -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
}

View File

@ -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)
}