Skip to content

Commit 7c88ae4

Browse files
cherrymuitoothrot
authored andcommitted
[release-branch.go1.15] cmd/link: generate trampoline for inter-dependent packages
Currently, in the trampoline generation pass we expect packages are laid out in dependency order, so a cross-package jump always has a known target address so we can check if a trampoline is needed. With linknames, there can be cycles in the package dependency graph, making this algorithm no longer work. For them, as the target address is unkown we conservatively generate a trampoline. This may generate unnecessary trampolines (if the packages turn out laid together), but package cycles are extremely rare so this is fine. Updates #44639. Fixes #44748. Change-Id: I2dc2998edacbda27d726fc79452313a21d07787a Reviewed-on: https://go-review.googlesource.com/c/go/+/292490 Trust: Cherry Zhang <[email protected]> Reviewed-by: Than McIntosh <[email protected]> (cherry picked from commit 098504c) Reviewed-on: https://go-review.googlesource.com/c/go/+/298030 Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 7038a38 commit 7c88ae4

File tree

3 files changed

+25
-15
lines changed

3 files changed

+25
-15
lines changed

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
373373
r := relocs.At2(ri)
374374
switch r.Type() {
375375
case objabi.R_CALLARM:
376-
// r.Add is the instruction
377-
// low 24-bit encodes the target address
378-
t := (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
379-
if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
376+
var t int64
377+
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
378+
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
379+
// in dependency order.
380+
if ldr.SymValue(rs) != 0 {
381+
// r.Add is the instruction
382+
// low 24-bit encodes the target address
383+
t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
384+
}
385+
if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
380386
// direct call too far, need to insert trampoline.
381387
// look up existing trampolines first. if we found one within the range
382388
// of direct call, we can reuse it. otherwise create a new one.
@@ -447,7 +453,7 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *l
447453
arch.ByteOrder.PutUint32(P[8:], o3)
448454
tramp.SetData(P)
449455

450-
if linkmode == ld.LinkExternal {
456+
if linkmode == ld.LinkExternal || ldr.SymValue(target) == 0 {
451457
r := loader.Reloc{
452458
Off: 8,
453459
Type: objabi.R_ADDR,

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

+5-7
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,12 @@ func trampoline(ctxt *Link, s loader.Sym) {
105105
}
106106
rs = ldr.ResolveABIAlias(rs)
107107
if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) {
108-
if ldr.SymPkg(rs) != ldr.SymPkg(s) {
109-
if !isRuntimeDepPkg(ldr.SymPkg(s)) || !isRuntimeDepPkg(ldr.SymPkg(rs)) {
110-
ctxt.Errorf(s, "unresolved inter-package jump to %s(%s) from %s", ldr.SymName(rs), ldr.SymPkg(rs), ldr.SymPkg(s))
111-
}
112-
// runtime and its dependent packages may call to each other.
113-
// they are fine, as they will be laid down together.
108+
if ldr.SymPkg(rs) == ldr.SymPkg(s) {
109+
continue // symbols in the same package are laid out together
110+
}
111+
if isRuntimeDepPkg(ldr.SymPkg(s)) && isRuntimeDepPkg(ldr.SymPkg(rs)) {
112+
continue // runtime packages are laid out together
114113
}
115-
continue
116114
}
117115

118116
thearch.Trampoline(ctxt, ldr, ri, rs, s)

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -672,13 +672,19 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
672672

673673
relocs := ldr.Relocs(s)
674674
r := relocs.At2(ri)
675-
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
675+
var t int64
676+
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
677+
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
678+
// in dependency order.
679+
if ldr.SymValue(rs) != 0 {
680+
t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
681+
}
676682
switch r.Type() {
677683
case objabi.R_CALLPOWER:
678684

679685
// If branch offset is too far then create a trampoline.
680686

681-
if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
687+
if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
682688
var tramp loader.Sym
683689
for i := 0; ; i++ {
684690

@@ -769,7 +775,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta
769775

770776
// With external linking, the target address must be
771777
// relocated using LO and HA
772-
if ctxt.IsExternal() {
778+
if ctxt.IsExternal() || ldr.SymValue(target) == 0 {
773779
r := loader.Reloc{
774780
Off: 0,
775781
Type: objabi.R_ADDRPOWER,

0 commit comments

Comments
 (0)