diff options
author | Cherry Zhang <cherryyz@google.com> | 2021-02-16 10:20:58 -0500 |
---|---|---|
committer | Alexander Rakoczy <alex@golang.org> | 2021-03-25 18:34:16 +0000 |
commit | 7c88ae4117c16c1e5b80189b81d67845e1c40d9d (patch) | |
tree | e9f9e701a4aeaf9440d24f1fc55354648b2b9610 /src/cmd/link/internal/ppc64/asm.go | |
parent | 7038a380bcd0183842471c1984da491e044d3d34 (diff) | |
download | go-7c88ae4117c16c1e5b80189b81d67845e1c40d9d.tar.gz go-7c88ae4117c16c1e5b80189b81d67845e1c40d9d.zip |
[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 <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit 098504c73ff6ece19566a1ac811ceed73be7c81d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/298030
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/cmd/link/internal/ppc64/asm.go')
-rw-r--r-- | src/cmd/link/internal/ppc64/asm.go | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index b1c0873d7a6..a3ecd43f891 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -672,13 +672,19 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { relocs := ldr.Relocs(s) r := relocs.At2(ri) - t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + var t int64 + // ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet + // laid out. Conservatively use a trampoline. This should be rare, as we lay out packages + // in dependency order. + if ldr.SymValue(rs) != 0 { + t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + } switch r.Type() { case objabi.R_CALLPOWER: // If branch offset is too far then create a trampoline. - 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)) { + 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)) { var tramp loader.Sym for i := 0; ; i++ { @@ -769,7 +775,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta // With external linking, the target address must be // relocated using LO and HA - if ctxt.IsExternal() { + if ctxt.IsExternal() || ldr.SymValue(target) == 0 { r := loader.Reloc{ Off: 0, Type: objabi.R_ADDRPOWER, |