From bade680867c9b1eecc7b5d177ed94c455a72e50a Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Wed, 12 May 2021 12:11:03 -0500 Subject: [PATCH] runtime/cgo: fix crosscall2 on ppc64x Some uses of crosscall2 did not work on ppc64le and probably aix-ppc64. In particular, if there was a main program compiled with -buildmode=pie and used a plugin which invoked crosscall2, then failures could occur due to R2 getting set incorrectly along the way. The problem was due to R2 being saved on the caller's stack; it is now saved on the crosscall2 stack. More details can be found in the issue. This adds a testcase where the main program is built with pie and the plugin invokes crosscall2. This also changes the save of the CR bits from MOVD to MOVW as it should be. Fixes #43228 Change-Id: Ib5673e25a2ec5ee46bf9a1ffb0cb1f3ef5449086 Reviewed-on: https://go-review.googlesource.com/c/go/+/319489 Run-TryBot: Lynn Boger Reviewed-by: Cherry Mui Trust: Heschi Kreinick --- misc/cgo/testplugin/plugin_test.go | 7 +++++++ src/runtime/cgo/asm_ppc64x.s | 12 ++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go index 28a8c669c07..a6accc1dfbb 100644 --- a/misc/cgo/testplugin/plugin_test.go +++ b/misc/cgo/testplugin/plugin_test.go @@ -263,6 +263,13 @@ func TestIssue25756(t *testing.T) { } } +// Test with main using -buildmode=pie with plugin for issue #43228 +func TestIssue25756pie(t *testing.T) { + goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin") + goCmd(t, "build", "-buildmode=pie", "-o", "issue25756pie.exe", "./issue25756/main.go") + run(t, "./issue25756pie.exe") +} + func TestMethod(t *testing.T) { // Exported symbol's method must be live. goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go") diff --git a/src/runtime/cgo/asm_ppc64x.s b/src/runtime/cgo/asm_ppc64x.s index 9dec8d04ce1..187b2d42f63 100644 --- a/src/runtime/cgo/asm_ppc64x.s +++ b/src/runtime/cgo/asm_ppc64x.s @@ -12,17 +12,20 @@ // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. // fn is the PC of a func(a unsafe.Pointer) function. +// The value of R2 is saved on the new stack frame, and not +// the caller's frame due to issue #43228. TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 // Start with standard C stack frame layout and linkage MOVD LR, R0 MOVD R0, 16(R1) // Save LR in caller's frame MOVW CR, R0 // Save CR in caller's frame - MOVD R0, 8(R1) - MOVD R2, 24(R1) // Save TOC in caller's frame + MOVW R0, 8(R1) BL saveregs2<>(SB) MOVDU R1, (-288-3*8-FIXED_FRAME)(R1) + // Save the caller's R2 + MOVD R2, 24(R1) // Initialize Go ABI environment BL runtime·reginit(SB) @@ -41,12 +44,13 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 MOVD R6, FIXED_FRAME+16(R1) // ctxt uintptr BL runtime·cgocallback(SB) + // Restore the caller's R2 + MOVD 24(R1), R2 ADD $(288+3*8+FIXED_FRAME), R1 BL restoreregs2<>(SB) - MOVD 24(R1), R2 - MOVD 8(R1), R0 + MOVW 8(R1), R0 MOVFL R0, $0xff MOVD 16(R1), R0 MOVD R0, LR