Skip to content

Commit 9c7463c

Browse files
cherrymuitoothrot
authored andcommitted
[release-branch.go1.16] 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 #44640. 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/+/296909 Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent ac59d7a commit 9c7463c

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
@@ -370,10 +370,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
370370
r := relocs.At(ri)
371371
switch r.Type() {
372372
case objabi.R_CALLARM:
373-
// r.Add is the instruction
374-
// low 24-bit encodes the target address
375-
t := (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
376-
if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
373+
var t int64
374+
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
375+
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
376+
// in dependency order.
377+
if ldr.SymValue(rs) != 0 {
378+
// r.Add is the instruction
379+
// low 24-bit encodes the target address
380+
t = (ldr.SymValue(rs) + int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4
381+
}
382+
if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
377383
// direct call too far, need to insert trampoline.
378384
// look up existing trampolines first. if we found one within the range
379385
// of direct call, we can reuse it. otherwise create a new one.
@@ -445,7 +451,7 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *l
445451
arch.ByteOrder.PutUint32(P[8:], o3)
446452
tramp.SetData(P)
447453

448-
if linkmode == ld.LinkExternal {
454+
if linkmode == ld.LinkExternal || ldr.SymValue(target) == 0 {
449455
r, _ := tramp.AddRel(objabi.R_ADDR)
450456
r.SetOff(8)
451457
r.SetSiz(4)

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

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

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

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

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

657657
relocs := ldr.Relocs(s)
658658
r := relocs.At(ri)
659-
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
659+
var t int64
660+
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
661+
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
662+
// in dependency order.
663+
if ldr.SymValue(rs) != 0 {
664+
t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
665+
}
660666
switch r.Type() {
661667
case objabi.R_CALLPOWER:
662668

663669
// If branch offset is too far then create a trampoline.
664670

665-
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)) {
671+
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)) {
666672
var tramp loader.Sym
667673
for i := 0; ; i++ {
668674

@@ -749,7 +755,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta
749755

750756
// With external linking, the target address must be
751757
// relocated using LO and HA
752-
if ctxt.IsExternal() {
758+
if ctxt.IsExternal() || ldr.SymValue(target) == 0 {
753759
r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
754760
r.SetOff(0)
755761
r.SetSiz(8) // generates 2 relocations: HA + LO

0 commit comments

Comments
 (0)