Blame SOURCES/do-not-reuse-far-trampolines.patch

6d0f59
From 63dd776220bb3a443e6b5c0766a389ec33dc4b69 Mon Sep 17 00:00:00 2001
6d0f59
From: "Paul E. Murphy" <murp@ibm.com>
6d0f59
Date: Wed, 16 Nov 2022 14:53:39 -0600
6d0f59
Subject: [PATCH] [release-branch.go1.18] cmd/link/internal/ppc64: fix
6d0f59
 trampoline reuse distance calculation
6d0f59
6d0f59
If a compatible trampoline has been inserted by a previously laid
6d0f59
function in the same section, and is known to be sufficiently close,
6d0f59
it can be reused.
6d0f59
6d0f59
When testing if the trampoline can be reused, the addend of the direct
6d0f59
call should be ignored. It is already encoded in the trampoline. If the
6d0f59
addend is non-zero, and the target sufficiently far away, and just
6d0f59
beyond direct call reach, this may cause the trampoline to be
6d0f59
incorrectly reused.
6d0f59
6d0f59
This was observed on go1.17.13 and openshift-installer commit f3c53b382
6d0f59
building in release mode with the following error:
6d0f59
6d0f59
github.com/aliyun/alibaba-cloud-sdk-go/services/cms.(*Client).DescribeMonitoringAgentAccessKeyWithChan.func1: direct call too far: runtime.duffzero+1f0-tramp0-1 -2000078
6d0f59
6d0f59
Fixes #56833
6d0f59
6d0f59
Change-Id: I54af957302506d4e3cd5d3121542c83fe980e912
6d0f59
Reviewed-on: https://go-review.googlesource.com/c/go/+/451415
6d0f59
Reviewed-by: Cherry Mui <cherryyz@google.com>
6d0f59
Run-TryBot: Paul Murphy <murp@ibm.com>
6d0f59
TryBot-Result: Gopher Robot <gobot@golang.org>
6d0f59
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
6d0f59
Reviewed-by: Than McIntosh <thanm@google.com>
6d0f59
Reviewed-on: https://go-review.googlesource.com/c/go/+/451916
6d0f59
Reviewed-by: Joedian Reid <joedian@golang.org>
6d0f59
---
6d0f59
 .../testdata/script/trampoline_reuse_test.txt | 100 ++++++++++++++++++
6d0f59
 src/cmd/link/internal/ppc64/asm.go            |   5 +-
6d0f59
 2 files changed, 103 insertions(+), 2 deletions(-)
6d0f59
 create mode 100644 src/cmd/go/testdata/script/trampoline_reuse_test.txt
6d0f59
6d0f59
diff --git a/src/cmd/go/testdata/script/trampoline_reuse_test.txt b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
6d0f59
new file mode 100644
6d0f59
index 0000000000000..bca897c16d054
6d0f59
--- /dev/null
6d0f59
+++ b/src/cmd/go/testdata/script/trampoline_reuse_test.txt
6d0f59
@@ -0,0 +1,100 @@
6d0f59
+# Verify PPC64 does not reuse a trampoline which is too far away.
6d0f59
+# This tests an edge case where the direct call relocation addend should
6d0f59
+# be ignored when computing the distance from the direct call to the
6d0f59
+# already placed trampoline
6d0f59
+[short] skip
6d0f59
+[!ppc64] [!ppc64le] skip
6d0f59
+[aix] skip
6d0f59
+
6d0f59
+# Note, this program does not run. Presumably, 'DWORD $0' is simpler to
6d0f59
+# assembly 2^26 or so times.
6d0f59
+#
6d0f59
+# We build something which should be laid out as such:
6d0f59
+#
6d0f59
+# bar.Bar
6d0f59
+# main.Func1
6d0f59
+# bar.Bar+400-tramp0
6d0f59
+# main.BigAsm
6d0f59
+# main.Func2
6d0f59
+# bar.Bar+400-tramp1
6d0f59
+#
6d0f59
+# bar.Bar needs to be placed far enough away to generate relocations
6d0f59
+# from main package calls. and main.Func1 and main.Func2 are placed
6d0f59
+# a bit more than the direct call limit apart, but not more than 0x400
6d0f59
+# bytes beyond it (to verify the reloc calc).
6d0f59
+
6d0f59
+go build
6d0f59
+
6d0f59
+-- go.mod --
6d0f59
+
6d0f59
+module foo
6d0f59
+
6d0f59
+go 1.19
6d0f59
+
6d0f59
+-- main.go --
6d0f59
+
6d0f59
+package main
6d0f59
+
6d0f59
+import "foo/bar"
6d0f59
+
6d0f59
+func Func1()
6d0f59
+
6d0f59
+func main() {
6d0f59
+        Func1()
6d0f59
+        bar.Bar2()
6d0f59
+}
6d0f59
+
6d0f59
+-- foo.s --
6d0f59
+
6d0f59
+TEXT main·Func1(SB),0,$0-0
6d0f59
+        CALL bar·Bar+0x400(SB)
6d0f59
+        CALL main·BigAsm(SB)
6d0f59
+// A trampoline will be placed here to bar.Bar
6d0f59
+
6d0f59
+// This creates a gap sufficiently large to prevent trampoline reuse
6d0f59
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
6d0f59
+#define NOP256 NOP64 NOP64 NOP64 NOP64
6d0f59
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
6d0f59
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
6d0f59
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
6d0f59
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
6d0f59
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
6d0f59
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
6d0f59
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
6d0f59
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
6d0f59
+#define BIGNOP NOP2S24 NOP2S24
6d0f59
+TEXT main·BigAsm(SB),0,$0-0
6d0f59
+        // Fill to the direct call limit so Func2 must generate a new trampoline.
6d0f59
+        // As the implicit trampoline above is just barely unreachable.
6d0f59
+        BIGNOP
6d0f59
+        MOVD $main·Func2(SB), R3
6d0f59
+
6d0f59
+TEXT main·Func2(SB),0,$0-0
6d0f59
+        CALL bar·Bar+0x400(SB)
6d0f59
+// Another trampoline should be placed here.
6d0f59
+
6d0f59
+-- bar/bar.s --
6d0f59
+
6d0f59
+#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0;
6d0f59
+#define NOP256 NOP64 NOP64 NOP64 NOP64
6d0f59
+#define NOP2S10 NOP256 NOP256 NOP256 NOP256
6d0f59
+#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10
6d0f59
+#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12
6d0f59
+#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14
6d0f59
+#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16
6d0f59
+#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18
6d0f59
+#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20
6d0f59
+#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22
6d0f59
+#define BIGNOP NOP2S24 NOP2S24 NOP2S10
6d0f59
+// A very big not very interesting function.
6d0f59
+TEXT bar·Bar(SB),0,$0-0
6d0f59
+        BIGNOP
6d0f59
+
6d0f59
+-- bar/bar.go --
6d0f59
+
6d0f59
+package bar
6d0f59
+
6d0f59
+func Bar()
6d0f59
+
6d0f59
+func Bar2() {
6d0f59
+}
6d0f59
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
6d0f59
index 73c2718a3369f..879adaa965050 100644
6d0f59
--- a/src/cmd/link/internal/ppc64/asm.go
6d0f59
+++ b/src/cmd/link/internal/ppc64/asm.go
6d0f59
@@ -809,8 +809,9 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
6d0f59
 				if ldr.SymValue(tramp) == 0 {
6d0f59
 					break
6d0f59
 				}
6d0f59
-
6d0f59
-				t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
6d0f59
+				// Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the
6d0f59
+				// trampoline itself.
6d0f59
+				t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
6d0f59
 
6d0f59
 				// With internal linking, the trampoline can be used if it is not too far.
6d0f59
 				// With external linking, the trampoline must be in this section for it to be reused.