r2.SetOff(r.Off() + 4)
r2.SetSym(syms.GOT)
r2.SetAdd(int64(ldr.SymGot(targ)))
+ return true
}
return false
}
func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
relocs := ldr.Relocs(s)
r := relocs.At(ri)
+ const pcrel = 1
switch r.Type() {
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26),
+ objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
+ // Host object relocations that will be turned into a PLT call.
+ // The PLT may be too far. Insert a trampoline for them.
+ fallthrough
case objabi.R_CALLARM64:
var t int64
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
if ldr.SymValue(rs) != 0 {
t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
}
- if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
+ if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
// direct call too far, need to insert trampoline.
// look up existing trampolines first. if we found one within the range
// of direct call, we can reuse it. otherwise create a new one.
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"compress/zlib"
+ "debug/elf"
"encoding/binary"
"fmt"
"log"
relocs := ldr.Relocs(s)
for ri := 0; ri < relocs.Count(); ri++ {
r := relocs.At(ri)
- if !r.Type().IsDirectCallOrJump() {
+ rt := r.Type()
+ if !rt.IsDirectCallOrJump() && !isPLTCall(rt) {
continue
}
rs := r.Sym()
}
rs = ldr.ResolveABIAlias(rs)
if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) {
- if ldr.SymPkg(rs) == ldr.SymPkg(s) {
- continue // symbols in the same package are laid out together
+ if ldr.SymPkg(s) != "" && ldr.SymPkg(rs) == ldr.SymPkg(s) {
+ // Symbols in the same package are laid out together.
+ // Except that if SymPkg(s) == "", it is a host object symbol
+ // which may call an external symbol via PLT.
+ continue
}
if isRuntimeDepPkg(ldr.SymPkg(s)) && isRuntimeDepPkg(ldr.SymPkg(rs)) {
continue // runtime packages are laid out together
}
}
+// whether rt is a (host object) relocation that will be turned into
+// a call to PLT.
+func isPLTCall(rt objabi.RelocType) bool {
+ const pcrel = 1
+ switch rt {
+ // ARM64
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26),
+ objabi.MachoRelocOffset + MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
+ return true
+ }
+ // TODO: other architectures.
+ return false
+}
+
// FoldSubSymbolOffset computes the offset of symbol s to its top-level outer
// symbol. Returns the top-level symbol and the offset.
// This is used in generating external relocations.