Skip to content

Commit af799d9

Browse files
mwhudsonianlancetaylor
authored andcommitted
cmd/link: pass value being relocated to archreloc
And clean up the mess on arm64 (the mess on arm is too confusing). See issue golang#10050 Change-Id: I2ce813fe8646d4e818eb660612a7e4b2bb04de4c Reviewed-on: https://go-review.googlesource.com/13884 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 5f2c420 commit af799d9

3 files changed

Lines changed: 43 additions & 21 deletions

File tree

src/cmd/internal/obj/arm64/asm7.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
18991899
rel.Off = int32(ctxt.Pc)
19001900
rel.Siz = 4
19011901
rel.Sym = p.To.Sym
1902-
rel.Add = int64(o1) | (p.To.Offset>>2)&0x3ffffff
1902+
rel.Add = p.To.Offset
19031903
rel.Type = obj.R_CALLARM64
19041904

19051905
case 6: /* b ,O(R); bl ,O(R) */

src/cmd/link/internal/arm64/asm.go

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
191191
}
192192
r.Xsym = rs
193193

194-
// the first instruction is always at the lower address, this is endian neutral;
195-
// but note that o0 and o1 should still use the target endian.
196-
o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
197-
o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
198-
199194
// Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
200195
// will make the linking fail because it thinks the code is not PIC even though
201196
// the BR26 relocation should be fully resolved at link time.
202197
// That is the reason why the next if block is disabled. When the bug in ld64
203198
// is fixed, we can enable this block and also enable duff's device in cmd/7g.
204199
if false && ld.HEADTYPE == obj.Hdarwin {
200+
var o0, o1 uint32
201+
202+
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
203+
o0 = uint32(*val >> 32)
204+
o1 = uint32(*val)
205+
} else {
206+
o0 = uint32(*val)
207+
o1 = uint32(*val >> 32)
208+
}
205209
// Mach-O wants the addend to be encoded in the instruction
206210
// Note that although Mach-O supports ARM64_RELOC_ADDEND, it
207211
// can only encode 24-bit of signed addend, but the instructions
@@ -210,23 +214,21 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
210214
o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
211215
o1 |= uint32(r.Xadd&0xfff) << 10
212216
r.Xadd = 0
213-
}
214217

215-
// when laid out, the instruction order must always be o1, o2.
216-
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
217-
*val = int64(o0)<<32 | int64(o1)
218-
} else {
219-
*val = int64(o1)<<32 | int64(o0)
218+
// when laid out, the instruction order must always be o1, o2.
219+
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
220+
*val = int64(o0)<<32 | int64(o1)
221+
} else {
222+
*val = int64(o1)<<32 | int64(o0)
223+
}
220224
}
221225

222226
return 0
223227

224228
case obj.R_CALLARM64:
225229
r.Done = 0
226230
r.Xsym = r.Sym
227-
*val = int64(0xfc000000 & uint32(r.Add))
228-
r.Xadd = int64((uint32(r.Add) &^ 0xfc000000) * 4)
229-
r.Add = 0
231+
r.Xadd = r.Add
230232
return 0
231233
}
232234
}
@@ -246,10 +248,15 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
246248
ld.Diag("program too large, address relocation distance = %d", t)
247249
}
248250

249-
// the first instruction is always at the lower address, this is endian neutral;
250-
// but note that o0 and o1 should still use the target endian.
251-
o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
252-
o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
251+
var o0, o1 uint32
252+
253+
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
254+
o0 = uint32(*val >> 32)
255+
o1 = uint32(*val)
256+
} else {
257+
o0 = uint32(*val)
258+
o1 = uint32(*val >> 32)
259+
}
253260

254261
o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
255262
o1 |= uint32(t&0xfff) << 10
@@ -263,7 +270,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
263270
return 0
264271

265272
case obj.R_CALLARM64:
266-
*val = int64((0xfc000000 & uint32(r.Add)) | uint32((ld.Symaddr(r.Sym)+r.Add*4-(s.Value+int64(r.Off)))/4))
273+
t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
274+
if t >= 1<<27 || t < -1<<27 {
275+
ld.Diag("program too large, call relocation distance = %d", t)
276+
}
277+
*val |= (t >> 2) & 0x03ffffff
267278
return 0
268279
}
269280

src/cmd/link/internal/ld/data.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,18 @@ func relocsym(s *LSym) {
369369

370370
switch r.Type {
371371
default:
372-
o = 0
372+
switch siz {
373+
default:
374+
Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
375+
case 1:
376+
o = int64(s.P[off])
377+
case 2:
378+
o = int64(Ctxt.Arch.ByteOrder.Uint16(s.P[off:]))
379+
case 4:
380+
o = int64(Ctxt.Arch.ByteOrder.Uint32(s.P[off:]))
381+
case 8:
382+
o = int64(Ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
383+
}
373384
if Thearch.Archreloc(r, s, &o) < 0 {
374385
Diag("unknown reloc %d", r.Type)
375386
}

0 commit comments

Comments
 (0)