Blame SOURCES/ppc64le-internal-linker-fix.patch

aae78f
diff --git a/src/cmd/go/testdata/script/trampoline_reuse_test.txt b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
aae78f
new file mode 100644
aae78f
index 0000000000000..bca897c16d054
aae78f
--- /dev/null
aae78f
+++ b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
aae78f
@@ -0,0 +1,100 @@
aae78f
+# Verify PPC64 does not reuse a trampoline which is too far away.
aae78f
+# This tests an edge case where the direct call relocation addend should
aae78f
+# be ignored when computing the distance from the direct call to the
aae78f
+# already placed trampoline
aae78f
+[short] skip
aae78f
+[!ppc64] [!ppc64le] skip
aae78f
+[aix] skip
aae78f
+
aae78f
+# Note, this program does not run. Presumably, 'DWORD $0' is simpler to
aae78f
+# assembly 2^26 or so times.
aae78f
+#
aae78f
+# We build something which should be laid out as such:
aae78f
+#
aae78f
+# bar.Bar
aae78f
+# main.Func1
aae78f
+# bar.Bar+400-tramp0
aae78f
+# main.BigAsm
aae78f
+# main.Func2
aae78f
+# bar.Bar+400-tramp1
aae78f
+#
aae78f
+# bar.Bar needs to be placed far enough away to generate relocations
aae78f
+# from main package calls. and main.Func1 and main.Func2 are placed
aae78f
+# a bit more than the direct call limit apart, but not more than 0x400
aae78f
+# bytes beyond it (to verify the reloc calc).
aae78f
+
aae78f
+go build
aae78f
+
aae78f
+-- go.mod --
aae78f
+
aae78f
+module foo
aae78f
+
aae78f
+go 1.19
aae78f
+
aae78f
+-- main.go --
aae78f
+
aae78f
+package main
aae78f
+
aae78f
+import "foo/bar"
aae78f
+
aae78f
+func Func1()
aae78f
+
aae78f
+func main() {
aae78f
+        Func1()
aae78f
+        bar.Bar2()
aae78f
+}
aae78f
+
aae78f
+-- foo.s --
aae78f
+
aae78f
+TEXT main·Func1(SB),0,$0-0
aae78f
+        CALL bar·Bar+0x400(SB)
aae78f
+        CALL main·BigAsm(SB)
aae78f
+// A trampoline will be placed here to bar.Bar
aae78f
+
aae78f
+// This creates a gap sufficiently large to prevent trampoline reuse
aae78f
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
aae78f
+#define NOP256 NOP64 NOP64 NOP64 NOP64
aae78f
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
aae78f
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
aae78f
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
aae78f
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
aae78f
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
aae78f
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
aae78f
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
aae78f
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
aae78f
+#define BIGNOP NOP2S24 NOP2S24
aae78f
+TEXT main·BigAsm(SB),0,$0-0
aae78f
+        // Fill to the direct call limit so Func2 must generate a new trampoline.
aae78f
+        // As the implicit trampoline above is just barely unreachable.
aae78f
+        BIGNOP
aae78f
+        MOVD $main·Func2(SB), R3
aae78f
+
aae78f
+TEXT main·Func2(SB),0,$0-0
aae78f
+        CALL bar·Bar+0x400(SB)
aae78f
+// Another trampoline should be placed here.
aae78f
+
aae78f
+-- bar/bar.s --
aae78f
+
aae78f
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
aae78f
+#define NOP256 NOP64 NOP64 NOP64 NOP64
aae78f
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
aae78f
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
aae78f
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
aae78f
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
aae78f
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
aae78f
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
aae78f
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
aae78f
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
aae78f
+#define BIGNOP NOP2S24 NOP2S24 NOP2S10
aae78f
+// A very big not very interesting function.
aae78f
+TEXT bar·Bar(SB),0,$0-0
aae78f
+        BIGNOP
aae78f
+
aae78f
+-- bar/bar.go --
aae78f
+
aae78f
+package bar
aae78f
+
aae78f
+func Bar()
aae78f
+
aae78f
+func Bar2() {
aae78f
+}
aae78f
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
aae78f
index 5d5fbe2a97735..6313879da083c 100644
aae78f
--- a/src/cmd/link/internal/ppc64/asm.go
aae78f
+++ b/src/cmd/link/internal/ppc64/asm.go
aae78f
@@ -900,8 +900,9 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
aae78f
 				if ldr.SymValue(tramp) == 0 {
aae78f
 					break
aae78f
 				}
aae78f
-
aae78f
-				t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
aae78f
+				// Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the
aae78f
+				// trampoline itself.
aae78f
+				t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
aae78f
 
aae78f
 				// With internal linking, the trampoline can be used if it is not too far.
aae78f
 				// With external linking, the trampoline must be in this section for it to be reused.