diff options
| author | qmuntal <quimmuntal@gmail.com> | 2026-03-19 10:44:39 +0100 |
|---|---|---|
| committer | Quim Muntal <quimmuntal@gmail.com> | 2026-03-31 12:52:46 -0700 |
| commit | fdd485c5f1701dfadb3a74d95c606329ec6463aa (patch) | |
| tree | 13ee000266f676cbfa0b148cbf24f737f1d67442 /src/runtime | |
| parent | 14a6bf0e90c0e22dcbf6dcf367604ac1ec627121 (diff) | |
| download | go-fdd485c5f1701dfadb3a74d95c606329ec6463aa.tar.xz | |
runtime/cgo: remove SIGSEGV emulation on iOS
The misc/ios exec wrapper doesn't support lldb since https://go.dev/cl/573175.
This means that the SIGSEGV emulation code in the cgo signal handling on
iOS is no longer needed, and can be removed.
Cq-Include-Trybots: luci.golang.try:gotip-darwin-arm64_26
Change-Id: I39827cb20756e4730352d87cb3514bb6a3f1cee8
Reviewed-on: https://go-review.googlesource.com/c/go/+/756800
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/cgo/gcc_ios_arm64.c | 21 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_signal2_ios_arm64.c | 11 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_signal_ios_arm64.c | 213 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_signal_ios_nolldb.c | 10 | ||||
| -rw-r--r-- | src/runtime/cgo/libcgo.h | 10 | ||||
| -rw-r--r-- | src/runtime/cgo/signal_ios_arm64.go | 10 | ||||
| -rw-r--r-- | src/runtime/cgo/signal_ios_arm64.s | 56 |
7 files changed, 0 insertions, 331 deletions
diff --git a/src/runtime/cgo/gcc_ios_arm64.c b/src/runtime/cgo/gcc_ios_arm64.c index 32f517d464..bef2750cd1 100644 --- a/src/runtime/cgo/gcc_ios_arm64.c +++ b/src/runtime/cgo/gcc_ios_arm64.c @@ -10,22 +10,8 @@ #include "libcgo.h" -#include <TargetConditionals.h> - -#if TARGET_OS_IPHONE #include <CoreFoundation/CFBundle.h> #include <CoreFoundation/CFString.h> -#endif - -#if TARGET_OS_IPHONE - -static void -threadentry_platform(void) -{ -#if TARGET_OS_IPHONE - darwin_arm_init_thread_exception_port(); -#endif -} // init_working_dir sets the current working directory to the app root. // By default ios/arm64 processes start in "/". @@ -87,17 +73,10 @@ init_working_dir() } } -#endif // TARGET_OS_IPHONE - static void init_platform() { -#if TARGET_OS_IPHONE - darwin_arm_init_mach_exception_handler(); - darwin_arm_init_thread_exception_port(); init_working_dir(); -#endif } void (*x_cgo_init_platform)(void) = init_platform; -void (*x_cgo_threadentry_platform)(void) = threadentry_platform; diff --git a/src/runtime/cgo/gcc_signal2_ios_arm64.c b/src/runtime/cgo/gcc_signal2_ios_arm64.c deleted file mode 100644 index f8cef54f6a..0000000000 --- a/src/runtime/cgo/gcc_signal2_ios_arm64.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build lldb - -// Used by gcc_signal_darwin_arm64.c when doing the test build during cgo. -// We hope that for real binaries the definition provided by Go will take precedence -// and the linker will drop this .o file altogether, which is why this definition -// is all by itself in its own file. -void __attribute__((weak)) xx_cgo_panicmem(void) {} diff --git a/src/runtime/cgo/gcc_signal_ios_arm64.c b/src/runtime/cgo/gcc_signal_ios_arm64.c deleted file mode 100644 index 3872f62de1..0000000000 --- a/src/runtime/cgo/gcc_signal_ios_arm64.c +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Emulation of the Unix signal SIGSEGV. -// -// On iOS, Go tests and apps under development are run by lldb. -// The debugger uses a task-level exception handler to intercept signals. -// Despite having a 'handle' mechanism like gdb, lldb will not allow a -// SIGSEGV to pass to the running program. For Go, this means we cannot -// generate a panic, which cannot be recovered, and so tests fail. -// -// We work around this by registering a thread-level mach exception handler -// and intercepting EXC_BAD_ACCESS. The kernel offers thread handlers a -// chance to resolve exceptions before the task handler, so we can generate -// the panic and avoid lldb's SIGSEGV handler. -// -// The dist tool enables this by build flag when testing. - -//go:build lldb - -#include <limits.h> -#include <pthread.h> -#include <stdio.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> - -#include <mach/arm/thread_status.h> -#include <mach/exception_types.h> -#include <mach/mach.h> -#include <mach/mach_init.h> -#include <mach/mach_port.h> -#include <mach/thread_act.h> -#include <mach/thread_status.h> - -#include "libcgo.h" -#include "libcgo_unix.h" - -void xx_cgo_panicmem(void); -uintptr_t x_cgo_panicmem = (uintptr_t)xx_cgo_panicmem; - -static pthread_mutex_t mach_exception_handler_port_set_mu; -static mach_port_t mach_exception_handler_port_set = MACH_PORT_NULL; - -kern_return_t -catch_exception_raise( - mach_port_t exception_port, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - exception_data_t code_vector, - mach_msg_type_number_t code_count) -{ - kern_return_t ret; - arm_unified_thread_state_t thread_state; - mach_msg_type_number_t state_count = ARM_UNIFIED_THREAD_STATE_COUNT; - - // Returning KERN_SUCCESS intercepts the exception. - // - // Returning KERN_FAILURE lets the exception fall through to the - // next handler, which is the standard signal emulation code - // registered on the task port. - - if (exception != EXC_BAD_ACCESS) { - return KERN_FAILURE; - } - - ret = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE, (thread_state_t)&thread_state, &state_count); - if (ret) { - fprintf(stderr, "runtime/cgo: thread_get_state failed: %d\n", ret); - abort(); - } - - // Bounce call to sigpanic through asm that makes it look like - // we call sigpanic directly from the faulting code. -#ifdef __arm64__ - thread_state.ts_64.__x[1] = thread_state.ts_64.__lr; - thread_state.ts_64.__x[2] = thread_state.ts_64.__pc; - thread_state.ts_64.__pc = x_cgo_panicmem; -#else - thread_state.ts_32.__r[1] = thread_state.ts_32.__lr; - thread_state.ts_32.__r[2] = thread_state.ts_32.__pc; - thread_state.ts_32.__pc = x_cgo_panicmem; -#endif - - if (0) { - // Useful debugging logic when panicmem is broken. - // - // Sends the first SIGSEGV and lets lldb catch the - // second one, avoiding a loop that locks up iOS - // devices requiring a hard reboot. - fprintf(stderr, "runtime/cgo: caught exc_bad_access\n"); - fprintf(stderr, "__lr = %llx\n", thread_state.ts_64.__lr); - fprintf(stderr, "__pc = %llx\n", thread_state.ts_64.__pc); - static int pass1 = 0; - if (pass1) { - return KERN_FAILURE; - } - pass1 = 1; - } - - ret = thread_set_state(thread, ARM_UNIFIED_THREAD_STATE, (thread_state_t)&thread_state, state_count); - if (ret) { - fprintf(stderr, "runtime/cgo: thread_set_state failed: %d\n", ret); - abort(); - } - - return KERN_SUCCESS; -} - -void -darwin_arm_init_thread_exception_port() -{ - // Called by each new OS thread to bind its EXC_BAD_ACCESS exception - // to mach_exception_handler_port_set. - int ret; - mach_port_t port = MACH_PORT_NULL; - - ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); - if (ret) { - fprintf(stderr, "runtime/cgo: mach_port_allocate failed: %d\n", ret); - abort(); - } - ret = mach_port_insert_right( - mach_task_self(), - port, - port, - MACH_MSG_TYPE_MAKE_SEND); - if (ret) { - fprintf(stderr, "runtime/cgo: mach_port_insert_right failed: %d\n", ret); - abort(); - } - - ret = thread_set_exception_ports( - mach_thread_self(), - EXC_MASK_BAD_ACCESS, - port, - EXCEPTION_DEFAULT, - THREAD_STATE_NONE); - if (ret) { - fprintf(stderr, "runtime/cgo: thread_set_exception_ports failed: %d\n", ret); - abort(); - } - - ret = pthread_mutex_lock(&mach_exception_handler_port_set_mu); - if (ret) { - fprintf(stderr, "runtime/cgo: pthread_mutex_lock failed: %d\n", ret); - abort(); - } - ret = mach_port_move_member( - mach_task_self(), - port, - mach_exception_handler_port_set); - if (ret) { - fprintf(stderr, "runtime/cgo: mach_port_move_member failed: %d\n", ret); - abort(); - } - ret = pthread_mutex_unlock(&mach_exception_handler_port_set_mu); - if (ret) { - fprintf(stderr, "runtime/cgo: pthread_mutex_unlock failed: %d\n", ret); - abort(); - } -} - -static void* -mach_exception_handler(void *port) -{ - // Calls catch_exception_raise. - extern boolean_t exc_server(); - mach_msg_server(exc_server, 2048, (mach_port_t)(uintptr_t)port, 0); - abort(); // never returns -} - -void -darwin_arm_init_mach_exception_handler() -{ - pthread_mutex_init(&mach_exception_handler_port_set_mu, NULL); - - // Called once per process to initialize a mach port server, listening - // for EXC_BAD_ACCESS thread exceptions. - int ret; - pthread_t thr = NULL; - pthread_attr_t attr; - sigset_t ign, oset; - - ret = mach_port_allocate( - mach_task_self(), - MACH_PORT_RIGHT_PORT_SET, - &mach_exception_handler_port_set); - if (ret) { - fprintf(stderr, "runtime/cgo: mach_port_allocate failed for port_set: %d\n", ret); - abort(); - } - - // Block all signals to the exception handler thread - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - // Start a thread to handle exceptions. - uintptr_t port_set = (uintptr_t)mach_exception_handler_port_set; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ret = _cgo_try_pthread_create(&thr, &attr, mach_exception_handler, (void*)port_set); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (ret) { - fprintf(stderr, "runtime/cgo: pthread_create failed: %d\n", ret); - abort(); - } - pthread_attr_destroy(&attr); -} diff --git a/src/runtime/cgo/gcc_signal_ios_nolldb.c b/src/runtime/cgo/gcc_signal_ios_nolldb.c deleted file mode 100644 index 9ddc37a013..0000000000 --- a/src/runtime/cgo/gcc_signal_ios_nolldb.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !lldb && ios && arm64 - -#include <stdint.h> - -void darwin_arm_init_thread_exception_port() {} -void darwin_arm_init_mach_exception_handler() {} diff --git a/src/runtime/cgo/libcgo.h b/src/runtime/cgo/libcgo.h index ae0542df36..24475b7c43 100644 --- a/src/runtime/cgo/libcgo.h +++ b/src/runtime/cgo/libcgo.h @@ -86,16 +86,6 @@ void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); void fatalf(const char* format, ...) __attribute__ ((noreturn)); /* - * Registers the current mach thread port for EXC_BAD_ACCESS processing. - */ -void darwin_arm_init_thread_exception_port(void); - -/* - * Starts a mach message server processing EXC_BAD_ACCESS. - */ -void darwin_arm_init_mach_exception_handler(void); - -/* * The cgo traceback callback. See runtime.SetCgoTraceback. */ struct cgoTracebackArg { diff --git a/src/runtime/cgo/signal_ios_arm64.go b/src/runtime/cgo/signal_ios_arm64.go deleted file mode 100644 index 3425c448c4..0000000000 --- a/src/runtime/cgo/signal_ios_arm64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cgo - -import _ "unsafe" - -//go:cgo_export_static xx_cgo_panicmem xx_cgo_panicmem -func xx_cgo_panicmem() diff --git a/src/runtime/cgo/signal_ios_arm64.s b/src/runtime/cgo/signal_ios_arm64.s deleted file mode 100644 index 1ae00d13f3..0000000000 --- a/src/runtime/cgo/signal_ios_arm64.s +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -// xx_cgo_panicmem is the entrypoint for SIGSEGV as intercepted via a -// mach thread port as EXC_BAD_ACCESS. As the segfault may have happened -// in C code, we first need to load_g then call xx_cgo_panicmem. -// -// R1 - LR at moment of fault -// R2 - PC at moment of fault -TEXT xx_cgo_panicmem(SB),NOSPLIT|NOFRAME,$0 - // If in external C code, we need to load the g register. - BL runtime·load_g(SB) - CMP $0, g - BNE ongothread - - // On a foreign thread. - // TODO(crawshaw): call badsignal - MOVD.W $0, -16(RSP) - MOVW $139, R1 - MOVW R1, 8(RSP) - B runtime·exit(SB) - -ongothread: - // Trigger a SIGSEGV panic. - // - // The goal is to arrange the stack so it looks like the runtime - // function sigpanic was called from the PC that faulted. It has - // to be sigpanic, as the stack unwinding code in traceback.go - // looks explicitly for it. - // - // To do this we call into runtime·setsigsegv, which sets the - // appropriate state inside the g object. We give it the faulting - // PC on the stack, then put it in the LR before calling sigpanic. - - // Build a 32-byte stack frame for us for this call. - // Saved LR (none available) is at the bottom, - // then the PC argument for setsigsegv, - // then a copy of the LR for us to restore. - MOVD.W $0, -32(RSP) - MOVD R1, 8(RSP) - MOVD R2, 16(RSP) - BL runtime·setsigsegv(SB) - MOVD 8(RSP), R1 - MOVD 16(RSP), R2 - - // Build a 16-byte stack frame for the simulated - // call to sigpanic, by taking 16 bytes away from the - // 32-byte stack frame above. - // The saved LR in this frame is the LR at time of fault, - // and the LR on entry to sigpanic is the PC at time of fault. - MOVD.W R1, 16(RSP) - MOVD R2, R30 - B runtime·sigpanic(SB) |
