Commit af799d94 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle Committed by Ian Lance Taylor

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/13884Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 5f2c420e
...@@ -1899,7 +1899,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1899,7 +1899,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
rel.Off = int32(ctxt.Pc) rel.Off = int32(ctxt.Pc)
rel.Siz = 4 rel.Siz = 4
rel.Sym = p.To.Sym rel.Sym = p.To.Sym
rel.Add = int64(o1) | (p.To.Offset>>2)&0x3ffffff rel.Add = p.To.Offset
rel.Type = obj.R_CALLARM64 rel.Type = obj.R_CALLARM64
case 6: /* b ,O(R); bl ,O(R) */ case 6: /* b ,O(R); bl ,O(R) */
......
...@@ -191,17 +191,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -191,17 +191,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
} }
r.Xsym = rs 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 // 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 // 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. // 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 // 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. // is fixed, we can enable this block and also enable duff's device in cmd/7g.
if false && ld.HEADTYPE == obj.Hdarwin { 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 // Mach-O wants the addend to be encoded in the instruction
// Note that although Mach-O supports ARM64_RELOC_ADDEND, it // Note that although Mach-O supports ARM64_RELOC_ADDEND, it
// can only encode 24-bit of signed addend, but the instructions // 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 { ...@@ -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) o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
o1 |= uint32(r.Xadd&0xfff) << 10 o1 |= uint32(r.Xadd&0xfff) << 10
r.Xadd = 0 r.Xadd = 0
}
// when laid out, the instruction order must always be o1, o2. // when laid out, the instruction order must always be o1, o2.
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
*val = int64(o0)<<32 | int64(o1) *val = int64(o0)<<32 | int64(o1)
} else { } else {
*val = int64(o1)<<32 | int64(o0) *val = int64(o1)<<32 | int64(o0)
}
} }
return 0 return 0
...@@ -224,9 +228,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -224,9 +228,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
case obj.R_CALLARM64: case obj.R_CALLARM64:
r.Done = 0 r.Done = 0
r.Xsym = r.Sym r.Xsym = r.Sym
*val = int64(0xfc000000 & uint32(r.Add)) r.Xadd = r.Add
r.Xadd = int64((uint32(r.Add) &^ 0xfc000000) * 4)
r.Add = 0
return 0 return 0
} }
} }
...@@ -246,10 +248,15 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -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) ld.Diag("program too large, address relocation distance = %d", t)
} }
// the first instruction is always at the lower address, this is endian neutral; var o0, o1 uint32
// but note that o0 and o1 should still use the target endian.
o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4]) if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8]) 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) o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
o1 |= uint32(t&0xfff) << 10 o1 |= uint32(t&0xfff) << 10
...@@ -263,7 +270,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { ...@@ -263,7 +270,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
return 0 return 0
case obj.R_CALLARM64: 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 return 0
} }
......
...@@ -369,7 +369,18 @@ func relocsym(s *LSym) { ...@@ -369,7 +369,18 @@ func relocsym(s *LSym) {
switch r.Type { switch r.Type {
default: 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 { if Thearch.Archreloc(r, s, &o) < 0 {
Diag("unknown reloc %d", r.Type) Diag("unknown reloc %d", r.Type)
} }
......
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