Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Unified Diff: src/trusted/service_runtime/osx/mach_exception_handler.c

Issue 12207165: Mac x86_64: Mach exception support (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/trusted/service_runtime/osx/mach_exception_handler.c
===================================================================
--- src/trusted/service_runtime/osx/mach_exception_handler.c (revision 10790)
+++ src/trusted/service_runtime/osx/mach_exception_handler.c (working copy)
@@ -26,11 +26,13 @@
#include "native_client/src/trusted/service_runtime/nacl_exception.h"
#include "native_client/src/trusted/service_runtime/nacl_globals.h"
#include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
+#include "native_client/src/trusted/service_runtime/nacl_tls.h"
+#include "native_client/src/trusted/service_runtime/osx/mach_thread_map.h"
+#include "native_client/src/trusted/service_runtime/osx/mach_thread_trusted_state.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"
#include "native_client/src/trusted/service_runtime/sel_rt.h"
-/* Only handle x86_32 for now. */
-#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
+#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
/*
@@ -87,31 +89,64 @@
}
}
+#if NACL_BUILD_SUBARCH == 32
+
+#define NATIVE_x86_THREAD_STATE x86_THREAD_STATE32
+#define TSx ts32
+
+#define TS_xCX TSx.__ecx
Mark Seaborn 2013/02/14 23:55:02 I'm not overly keen on adding macros for accessing
+#define TS_xBP TSx.__ebp
+#define TS_xSP TSx.__esp
+#define TS_SS TSx.__ss
+#define TS_xFLAGS TSx.__eflags
+#define TS_xIP TSx.__eip
+#define TS_CS TSx.__cs
+#define TS_DS TSx.__ds
+#define TS_ES TSx.__es
+#define TS_GS TSx.__gs
+
+#elif NACL_BUILD_SUBARCH == 64
+
+#define NATIVE_x86_THREAD_STATE x86_THREAD_STATE64
+#define TSx ts64
+
+#define TS_xDI TSx.__rdi
+#define TS_xBP TSx.__rbp
+#define TS_xSP TSx.__rsp
+#define TS_xIP TSx.__rip
+#define TS_xFLAGS TSx.__rflags
+
+#endif /* NACL_BUILD_SUBARCH */
+
static int HandleException(mach_port_t thread_port,
exception_type_t exception, int *is_untrusted) {
mach_msg_type_number_t size;
x86_thread_state_t regs;
kern_return_t result;
- uint16_t trusted_cs = NaClGetGlobalCs();
- uint16_t trusted_ds = NaClGetGlobalDs();
uint32_t nacl_thread_index;
struct NaClApp *nap;
struct NaClAppThread *natp;
struct NaClExceptionFrame frame;
- uintptr_t frame_addr_user;
+ uint32_t frame_addr_user;
uintptr_t frame_addr_sys;
+#if NACL_BUILD_SUBARCH == 32
+ uint16_t trusted_cs = NaClGetGlobalCs();
+ uint16_t trusted_ds = NaClGetGlobalDs();
+#endif
/* Assume untrusted crash until we know otherwise. */
*is_untrusted = TRUE;
/* Capture the register state of the 'excepting' thread. */
- size = sizeof(regs) / sizeof(natural_t);
+ size = x86_THREAD_STATE_COUNT;
result = thread_get_state(thread_port, x86_THREAD_STATE,
- (void *) &regs, &size);
+ (thread_state_t) &regs, &size);
if (result != KERN_SUCCESS) {
return 0;
}
+ CHECK(regs.tsh.flavor == NATIVE_x86_THREAD_STATE);
+#if NACL_BUILD_SUBARCH == 32
/*
* If trusted_cs is 0 (which is not a usable segment selector), the
* sandbox has not been initialised yet, so there can be no untrusted
@@ -129,15 +164,15 @@
* the last thing to change when switching into untrusted code. We need
* tests to vet this.
*/
- if (regs.uts.ts32.__cs == trusted_cs) {
+ if (regs.uts.TS_CS == trusted_cs) {
/*
* If we are single-stepping, allow NaClSwitchRemainingRegsViaECX()
* to continue in order to restore control to untrusted code.
*/
if (exception == EXC_BREAKPOINT &&
- (regs.uts.ts32.__eflags & NACL_X86_TRAP_FLAG) != 0 &&
- regs.uts.ts32.__eip >= (uintptr_t) NaClSwitchRemainingRegsViaECX &&
- regs.uts.ts32.__eip < (uintptr_t) NaClSwitchRemainingRegsAsmEnd) {
+ (regs.uts.TS_xFLAGS & NACL_X86_TRAP_FLAG) != 0 &&
+ regs.uts.TS_xIP >= (uintptr_t) NaClSwitchRemainingRegsViaECX &&
+ regs.uts.TS_xIP < (uintptr_t) NaClSwitchRemainingRegsAsmEnd) {
return 1;
}
*is_untrusted = FALSE;
@@ -149,28 +184,53 @@
* from %gs >> 3.
* TODO(bradnelson): Migrate that knowledge to a single shared location.
*/
- nacl_thread_index = regs.uts.ts32.__gs >> 3;
+ nacl_thread_index = regs.uts.TS_GS >> 3;
+#elif NACL_BUILD_SUBARCH == 64
+ nacl_thread_index = NaClGetThreadIndexForMachThread(thread_port);
+ if (nacl_thread_index == NACL_TLS_INDEX_INVALID) {
+ *is_untrusted = FALSE;
+ return 0;
+ }
+#endif
+
natp = NaClAppThreadGetFromIndex(nacl_thread_index);
nap = natp->nap;
+#if NACL_BUILD_SUBARCH == 64
Mark Seaborn 2013/02/14 23:55:02 It looks like you don't need this #if, and your in
+ *is_untrusted = NaClMachThreadStateIsInUntrusted(&regs, nacl_thread_index);
+ /*
+ * If trusted code accidentally jumped to untrusted code, don't let the
+ * untrusted exception handler take over.
+ */
+ if (*is_untrusted &&
+ (natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) == 0) {
+ *is_untrusted = 0;
+ }
+ if (!*is_untrusted) {
+ return 0;
+ }
+#endif
+
if (nap->enable_faulted_thread_queue) {
+#if NACL_BUILD_SUBARCH == 32
/*
* If we are single-stepping, step through until we reach untrusted code.
*/
if (exception == EXC_BREAKPOINT &&
- (regs.uts.ts32.__eflags & NACL_X86_TRAP_FLAG) != 0) {
- if (regs.uts.ts32.__eip >= nap->all_regs_springboard.start_addr &&
- regs.uts.ts32.__eip < nap->all_regs_springboard.end_addr) {
+ (regs.uts.TS_xFLAGS & NACL_X86_TRAP_FLAG) != 0) {
+ if (regs.uts.TS_xIP >= nap->all_regs_springboard.start_addr &&
+ regs.uts.TS_xIP < nap->all_regs_springboard.end_addr) {
return 1;
}
/*
* Step through the instruction we have been asked to restore
* control to.
*/
- if (regs.uts.ts32.__eip == natp->user.gs_segment.new_prog_ctr) {
+ if (regs.uts.TS_xIP == natp->user.gs_segment.new_prog_ctr) {
return 1;
}
}
+#endif
/*
* Increment the kernel's thread suspension count so that the
@@ -192,35 +252,12 @@
return 1;
}
- /*
- * Ignore all but bad accesses for now.
- * TODO(bradnelson): eventually consider these too:
- * EXC_BAD_INSTRUCTION
- * EXC_ARITHMETIC
- * EXC_BREAKPOINT
- */
- if (exception != EXC_BAD_ACCESS) {
- return 0;
- }
-
- /* Don't handle it if the exception flag is set. */
- if (natp->exception_flag) {
- return 0;
- }
- /* Set the flag. */
- natp->exception_flag = 1;
-
- /* Don't handle if no exception handler is set. */
- if (nap->exception_handler == 0) {
- return 0;
- }
-
/* Get location of exception stack frame. */
if (natp->exception_stack) {
frame_addr_user = natp->exception_stack;
} else {
/* If not set default to user stack. */
- frame_addr_user = regs.uts.ts32.__esp;
+ frame_addr_user = regs.uts.TS_xSP - NACL_STACK_RED_ZONE;
}
/* Align stack frame properly. */
@@ -236,13 +273,38 @@
return 0;
}
+ /*
+ * Ignore all but bad accesses for now.
+ * TODO(bradnelson): eventually consider these too:
+ * EXC_BAD_INSTRUCTION
+ * EXC_ARITHMETIC
+ * EXC_BREAKPOINT
+ */
+ if (exception != EXC_BAD_ACCESS) {
+ return 0;
+ }
+
+ /* Don't handle if no exception handler is set. */
+ if (nap->exception_handler == 0) {
Mark Seaborn 2013/02/14 23:55:02 I can see why you reordered this before checking e
Mark Mentovai 2013/02/15 17:36:42 Mark Seaborn wrote:
+ return 0;
+ }
+
+ /* Don't handle it if the exception flag is set. */
+ if (natp->exception_flag) {
+ return 0;
+ }
+ /* Set the flag. */
+ natp->exception_flag = 1;
+
/* Set up the stack frame for the handler invocation. */
frame.return_addr = 0;
+ frame.context.prog_ctr = regs.uts.TS_xIP;
+ frame.context.stack_ptr = regs.uts.TS_xSP;
+ frame.context.frame_ptr = regs.uts.TS_xBP;
+#if NACL_BUILD_SUBARCH == 32
frame.context_ptr = frame_addr_user +
offsetof(struct NaClExceptionFrame, context);
- frame.context.prog_ctr = regs.uts.ts32.__eip;
- frame.context.stack_ptr = regs.uts.ts32.__esp;
- frame.context.frame_ptr = regs.uts.ts32.__ebp;
+#endif
/*
* Write the stack frame into untrusted address space. We do not
@@ -259,10 +321,8 @@
}
/* Set up thread context to resume at handler. */
- natp->user.new_prog_ctr = nap->exception_handler;
- natp->user.stack_ptr = frame_addr_user;
/* TODO(bradnelson): put all registers in some default state. */
-
+#if NACL_BUILD_SUBARCH == 32
/*
* Put registers in right place to land at NaClSwitchNoSSEViaECX
* This is required because:
@@ -276,15 +336,26 @@
* Instead we call a variant of NaClSwitchNoSSE which takes a pointer
* to the thread user context in %ecx.
*/
- regs.uts.ts32.__eip = (uint32_t) &NaClSwitchNoSSEViaECX;
- regs.uts.ts32.__cs = trusted_cs;
- regs.uts.ts32.__ecx = (uint32_t) &natp->user;
- regs.uts.ts32.__ds = trusted_ds;
- regs.uts.ts32.__es = trusted_ds; /* just for good measure */
- regs.uts.ts32.__ss = trusted_ds; /* just for good measure */
- regs.uts.ts32.__eflags &= ~NACL_X86_DIRECTION_FLAG;
+ natp->user.new_prog_ctr = nap->exception_handler;
+ natp->user.stack_ptr = frame_addr_user;
+ regs.uts.TS_xIP = (uint32_t) &NaClSwitchNoSSEViaECX;
+ regs.uts.TS_CS = trusted_cs;
+ regs.uts.TS_xCX = (uint32_t) &natp->user;
+ regs.uts.TS_DS = trusted_ds;
+ regs.uts.TS_ES = trusted_ds; /* just for good measure */
+ regs.uts.TS_SS = trusted_ds; /* just for good measure */
+#elif NACL_BUILD_SUBARCH == 64
+ regs.uts.TS_xIP = NaClUserToSys(nap, nap->exception_handler);
+ regs.uts.TS_xSP = frame_addr_sys;
+ regs.uts.TS_xBP = nap->mem_start;
+
+ /* Argument 1 */
+ regs.uts.TS_xDI = frame_addr_user +
+ offsetof(struct NaClExceptionFrame, context);
+#endif
+ regs.uts.TS_xFLAGS &= ~NACL_X86_DIRECTION_FLAG;
result = thread_set_state(thread_port, x86_THREAD_STATE,
- (void *) &regs, size);
+ (thread_state_t) &regs, size);
if (result != KERN_SUCCESS) {
return 0;
}
@@ -570,10 +641,4 @@
return FALSE;
}
-#else /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 */
-
-int NaClInterceptMachExceptions(void) {
- return FALSE;
-}
-
-#endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 */
+#endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */

Powered by Google App Engine
This is Rietveld 408576698