From: David Crawshaw Date: Sat, 11 Apr 2015 23:14:02 +0000 (-0400) Subject: runtime/cgo: EXC_BAD_ACCESS handler for arm64 X-Git-Tag: go1.5beta1~1145 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=989f0ee80a57c7c57fe4ae238d14cbffe8f9fd87;p=gostls13.git runtime/cgo: EXC_BAD_ACCESS handler for arm64 Change-Id: Ia9ff9c0d381fad43fc5d3e5972dd6e66503733a5 Reviewed-on: https://go-review.googlesource.com/8815 Reviewed-by: Minux Ma --- diff --git a/src/runtime/cgo/gcc_signal_darwin_armx.c b/src/runtime/cgo/gcc_signal_darwin_armx.c index cb32898e43..9d572acce3 100644 --- a/src/runtime/cgo/gcc_signal_darwin_armx.c +++ b/src/runtime/cgo/gcc_signal_darwin_armx.c @@ -20,9 +20,9 @@ // // go test -tags lldb -installsuffix lldb -// +build darwin,arm,!lldb - -// TODO(crawshaw): darwin,arm64,!lldb +// +build !lldb +// +build darwin +// +build arm arm64 #include #include @@ -77,9 +77,31 @@ catch_exception_raise( // 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) { @@ -174,9 +196,10 @@ darwin_arm_init_mach_exception_handler() } // 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 = pthread_create(&thr, &attr, mach_exception_handler, (void*)mach_exception_handler_port_set); + ret = pthread_create(&thr, &attr, mach_exception_handler, (void*)port_set); if (ret) { fprintf(stderr, "runtime/cgo: pthread_create failed: %d\n", ret); abort(); diff --git a/src/runtime/cgo/signal_darwin_arm64.s b/src/runtime/cgo/signal_darwin_arm64.s new file mode 100644 index 0000000000..83062d4c75 --- /dev/null +++ b/src/runtime/cgo/signal_darwin_arm64.s @@ -0,0 +1,42 @@ +// 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" + +// 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 panicmem. +// +// R1 - LR at moment of fault +// R2 - PC at moment of fault +TEXT ·panicmem(SB),NOSPLIT,$-8 + // 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 + MOVW $139, R1 + MOVW R1, (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. + STP.W (R1, R2), -16(RSP) + BL runtime·setsigsegv(SB) + LDP.P 16(RSP), (R1, R2) + + MOVD R1, 8(RSP) + MOVD R2, R30 // link register + B runtime·sigpanic(SB)