From 8c2900bb9f01043cc3a61bc86424fd814812c21e Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Thu, 23 Mar 2023 10:41:31 -0500 Subject: [PATCH] runtime: consolidate function descriptor definitions on PPC64 This is a cleanup to allow a consistent definitions of a function descriptor on code shared between AIX and Linux. They need to be declared in slightly different ways, but we can hide that in one macro. And, update all usage. Change-Id: I10f3580473db555b4fb4d2597b856f3a67d01a53 Reviewed-on: https://go-review.googlesource.com/c/go/+/478917 Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Paul Murphy --- src/runtime/asm_ppc64x.h | 20 ++++++++++++++++++-- src/runtime/asm_ppc64x.s | 21 +++------------------ src/runtime/cgo/asm_ppc64x.s | 25 ++++++++++++------------- src/runtime/rt0_aix_ppc64.s | 17 ++++------------- src/runtime/rt0_linux_ppc64.s | 13 +++---------- src/runtime/sys_linux_ppc64x.s | 23 ++++++----------------- 6 files changed, 46 insertions(+), 73 deletions(-) diff --git a/src/runtime/asm_ppc64x.h b/src/runtime/asm_ppc64x.h index cce5537a9c..65870fe020 100644 --- a/src/runtime/asm_ppc64x.h +++ b/src/runtime/asm_ppc64x.h @@ -24,16 +24,32 @@ #define FIXED_FRAME 32 -// aix/ppc64 uses XCOFF which has function descriptors. +// aix/ppc64 uses XCOFF which uses function descriptors. +// AIX cannot perform the TOC relocation in a text section. +// Therefore, these descriptors must live in a data section. #ifdef GOOS_aix #ifdef GOARCH_ppc64 #define GO_PPC64X_HAS_FUNCDESC +#define DEFINE_PPC64X_FUNCDESC(funcname, localfuncname) \ + DATA funcname+0(SB)/8, $localfuncname(SB) \ + DATA funcname+8(SB)/8, $TOC(SB) \ + DATA funcname+16(SB)/8, $0 \ + GLOBL funcname(SB), NOPTR, $24 #endif #endif -// linux/ppc64 uses ELFv1 which has function descriptors. +// linux/ppc64 uses ELFv1 which uses function descriptors. +// These must also look like ABI0 functions on linux/ppc64 +// to work with abi.FuncPCABI0(sigtramp) in os_linux.go. +// Only static codegen is supported on linux/ppc64, so TOC +// is not needed. #ifdef GOOS_linux #ifdef GOARCH_ppc64 #define GO_PPC64X_HAS_FUNCDESC +#define DEFINE_PPC64X_FUNCDESC(funcname, localfuncname) \ + TEXT funcname(SB),NOSPLIT|NOFRAME,$0 \ + DWORD $localfuncname(SB) \ + DWORD $0 \ + DWORD $0 #endif #endif diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 7c866b4bc3..293683f419 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -771,26 +771,11 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8 BL runtime·save_g(SB) RET -#ifdef GOARCH_ppc64 -#ifdef GOOS_aix -DATA setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB) -DATA setg_gcc<>+8(SB)/8, $TOC(SB) -DATA setg_gcc<>+16(SB)/8, $0 -GLOBL setg_gcc<>(SB), NOPTR, $24 +#ifdef GO_PPC64X_HAS_FUNCDESC +DEFINE_PPC64X_FUNCDESC(setg_gcc<>, _setg_gcc<>) +TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 #else TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 - DWORD $_setg_gcc<>(SB) - DWORD $0 - DWORD $0 -#endif -#endif - -// void setg_gcc(G*); set g in C TLS. -// Must obey the gcc calling convention. -#ifdef GOARCH_ppc64le -TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 -#else -TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 #endif // The standard prologue clobbers R31, which is callee-save in // the C ABI, so we have to use $-8-0 and save LR ourselves. diff --git a/src/runtime/cgo/asm_ppc64x.s b/src/runtime/cgo/asm_ppc64x.s index 8eb4a42157..7752feb650 100644 --- a/src/runtime/cgo/asm_ppc64x.s +++ b/src/runtime/cgo/asm_ppc64x.s @@ -7,26 +7,25 @@ #include "textflag.h" #include "asm_ppc64x.h" +#ifdef GO_PPC64X_HAS_FUNCDESC +// crosscall2 is marked with go:cgo_export_static. On AIX, this creates and exports +// the symbol name and descriptor as the AIX linker expects, but does not work if +// referenced from within Go. Create and use an aliased descriptor of crosscall2 +// to workaround this. +DEFINE_PPC64X_FUNCDESC(_crosscall2<>, crosscall2) +#define CROSSCALL2_FPTR $_crosscall2<>(SB) +#else +#define CROSSCALL2_FPTR $crosscall2(SB) +#endif + // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVD _crosscall2_ptr(SB), R5 -#ifdef GOARCH_ppc64 - MOVD $_crosscall2<>(SB), R6 -#else - MOVD $crosscall2(SB), R6 -#endif + MOVD CROSSCALL2_FPTR, R6 MOVD R6, (R5) RET -#ifdef GO_PPC64X_HAS_FUNCDESC -// _crosscall2<> is a function descriptor to the real crosscall2. -DATA _crosscall2<>+0(SB)/8, $crosscall2(SB) -DATA _crosscall2<>+8(SB)/8, $TOC(SB) -DATA _crosscall2<>+16(SB)/8, $0 -GLOBL _crosscall2<>(SB), NOPTR, $24 -#endif - // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. diff --git a/src/runtime/rt0_aix_ppc64.s b/src/runtime/rt0_aix_ppc64.s index 86fda56899..1670a80986 100644 --- a/src/runtime/rt0_aix_ppc64.s +++ b/src/runtime/rt0_aix_ppc64.s @@ -3,13 +3,11 @@ // license that can be found in the LICENSE file. #include "textflag.h" +#include "asm_ppc64x.h" // _rt0_ppc64_aix is a function descriptor of the entrypoint function // __start. This name is needed by cmd/link. -DATA _rt0_ppc64_aix+0(SB)/8, $__start<>(SB) -DATA _rt0_ppc64_aix+8(SB)/8, $TOC(SB) -GLOBL _rt0_ppc64_aix(SB), NOPTR, $16 - +DEFINE_PPC64X_FUNCDESC(_rt0_ppc64_aix, __start<>) // The starting function must return in the loader to // initialise some libraries, especially libthread which @@ -37,11 +35,7 @@ TEXT __start<>(SB),NOSPLIT,$-8 BL _main(SB) -DATA main+0(SB)/8, $_main(SB) -DATA main+8(SB)/8, $TOC(SB) -DATA main+16(SB)/8, $0 -GLOBL main(SB), NOPTR, $24 - +DEFINE_PPC64X_FUNCDESC(main, _main) TEXT _main(SB),NOSPLIT,$-8 MOVD $runtime·rt0_go(SB), R12 MOVD R12, CTR @@ -181,10 +175,7 @@ done: MOVD R0, LR RET -DATA _rt0_ppc64_aix_lib_go+0(SB)/8, $__rt0_ppc64_aix_lib_go(SB) -DATA _rt0_ppc64_aix_lib_go+8(SB)/8, $TOC(SB) -DATA _rt0_ppc64_aix_lib_go+16(SB)/8, $0 -GLOBL _rt0_ppc64_aix_lib_go(SB), NOPTR, $24 +DEFINE_PPC64X_FUNCDESC(_rt0_ppc64_aix_lib_go, __rt0_ppc64_aix_lib_go) TEXT __rt0_ppc64_aix_lib_go(SB),NOSPLIT,$0 MOVD _rt0_ppc64_aix_lib_argc<>(SB), R3 diff --git a/src/runtime/rt0_linux_ppc64.s b/src/runtime/rt0_linux_ppc64.s index c9300a9caf..f527170ed2 100644 --- a/src/runtime/rt0_linux_ppc64.s +++ b/src/runtime/rt0_linux_ppc64.s @@ -3,17 +3,10 @@ // license that can be found in the LICENSE file. #include "textflag.h" +#include "asm_ppc64x.h" -// actually a function descriptor for _main<>(SB) -TEXT _rt0_ppc64_linux(SB),NOSPLIT,$0 - DWORD $_main<>(SB) - DWORD $0 - DWORD $0 - -TEXT main(SB),NOSPLIT,$0 - DWORD $_main<>(SB) - DWORD $0 - DWORD $0 +DEFINE_PPC64X_FUNCDESC(_rt0_ppc64_linux, _main<>) +DEFINE_PPC64X_FUNCDESC(main, _main<>) TEXT _main<>(SB),NOSPLIT,$-8 // In a statically linked binary, the stack contains argc, diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index ec9b966c8c..44cd0e7b3e 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -447,18 +447,16 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 MOVD 24(R1), R2 RET -#ifdef GOARCH_ppc64le +#ifdef GO_PPC64X_HAS_FUNCDESC +DEFINE_PPC64X_FUNCDESC(runtime·sigtramp, sigtramp<>) +// cgo isn't supported on ppc64, but we need to supply a cgoSigTramp function. +DEFINE_PPC64X_FUNCDESC(runtime·cgoSigtramp, sigtramp<>) +TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 +#else // ppc64le doesn't need function descriptors // Save callee-save registers in the case of signal forwarding. // Same as on ARM64 https://golang.org/issue/31827 . TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0 -#else -// function descriptor for the real sigtramp -TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0 - DWORD $sigtramp<>(SB) - DWORD $0 - DWORD $0 -TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 #endif // Start with standard C stack frame layout and linkage. MOVD LR, R0 @@ -627,7 +625,6 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 RET #ifdef GOARCH_ppc64le -// ppc64le doesn't need function descriptors TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 // The stack unwinder, presumably written in C, may not be able to // handle Go frame correctly. So, this function is NOFRAME, and we @@ -722,14 +719,6 @@ sigtrampnog: MOVD R12, CTR MOVD R10, LR // restore LR JMP (CTR) -#else -// function descriptor for the real sigtramp -TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 - DWORD $cgoSigtramp<>(SB) - DWORD $0 - DWORD $0 -TEXT cgoSigtramp<>(SB),NOSPLIT,$0 - JMP sigtramp<>(SB) #endif // Used by cgoSigtramp to inspect without clobbering R30/R31 via runtime.load_g. -- 2.48.1