// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
// in dependency order.
if ldr.SymValue(rs) != 0 {
- // r.Add is the instruction
- // low 24-bit encodes the target address
- t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
+ // Workaround for issue #58425: it appears that the
+ // external linker doesn't always take into account the
+ // relocation addend when doing reachability checks. This
+ // means that if you have a call from function XYZ at
+ // offset 8 to runtime.duffzero with addend 800 (for
+ // example), where the distance between the start of XYZ
+ // and the start of runtime.duffzero is just over the
+ // limit (by 100 bytes, say), you can get "relocation
+ // doesn't fit" errors from the external linker. To deal
+ // with this, ignore the addend when performing the
+ // distance calculation (this assumes that we're only
+ // handling backward jumps; ideally we might want to check
+ // both with and without the addend).
+ if ctxt.IsExternal() {
+ t = (ldr.SymValue(rs) - (ldr.SymValue(s) + int64(r.Off()))) / 4
+ } else {
+ // r.Add is the instruction
+ // low 24-bit encodes the target address
+ t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
+ }
}
if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
// direct call too far, need to insert trampoline.