1
0
mirror of https://github.com/golang/go synced 2024-11-19 23:04:40 -07:00

runtime/cgo: EXC_BAD_ACCESS handler for arm64

Change-Id: Ia9ff9c0d381fad43fc5d3e5972dd6e66503733a5
Reviewed-on: https://go-review.googlesource.com/8815
Reviewed-by: Minux Ma <minux@golang.org>
This commit is contained in:
David Crawshaw 2015-04-11 19:14:02 -04:00
parent 4c1ee3ea88
commit 989f0ee80a
2 changed files with 69 additions and 4 deletions

View File

@ -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 <limits.h>
#include <pthread.h>
@ -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();

View File

@ -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)