Index: components/nacl/loader/nonsfi/irt_exception_handling.cc |
diff --git a/components/nacl/loader/nonsfi/irt_exception_handling.cc b/components/nacl/loader/nonsfi/irt_exception_handling.cc |
index cdd33aff3f6164caa9d7a2d0f7d01ba23e80765e..d310e19bd5687b929a52c55f9be659f45abb8fb6 100644 |
--- a/components/nacl/loader/nonsfi/irt_exception_handling.cc |
+++ b/components/nacl/loader/nonsfi/irt_exception_handling.cc |
@@ -1,15 +1,15 @@ |
// Copyright 2014 The Chromium 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 <elf.h> |
#include <errno.h> |
#include <signal.h> |
+#include <sys/ucontext.h> |
-#include <map> |
- |
+#include "base/logging.h" |
#include "components/nacl/loader/nonsfi/irt_interfaces.h" |
+#include "native_client/src/include/nacl/nacl_exception.h" |
#include "native_client/src/include/nacl_macros.h" |
-#include "native_client/src/trusted/service_runtime/nacl_exception.h" |
-#include "native_client/src/trusted/service_runtime/nacl_signal.h" |
namespace nacl { |
namespace nonsfi { |
@@ -33,18 +33,91 @@ static const int kSignals[] = { |
NaClExceptionHandler signal_handler_function_pointer = NULL; |
+struct NonSfiExceptionFrame { |
+ struct NaClExceptionContext context; |
+ struct NaClExceptionPortableContext portable; |
+}; |
+ |
+// Convert context reported by signal to NaClExceptionContext format. |
+void MachineContextToRegister(const mcontext_t *mctx, |
+ // what is volatile about it? |
+ NaClUserRegisterState *dest) { |
+ |
+#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 |
+ dest->eax = mctx->gregs[REG_EAX]; |
+ dest->ecx = mctx->gregs[REG_ECX]; |
+ dest->edx = mctx->gregs[REG_EDX]; |
+ dest->ebx = mctx->gregs[REG_EBX]; |
+ dest->stack_ptr = mctx->gregs[REG_ESP]; |
+ dest->ebp = mctx->gregs[REG_EBP]; |
+ dest->esi = mctx->gregs[REG_ESI]; |
+ dest->edi = mctx->gregs[REG_EDI]; |
+ dest->prog_ctr = mctx->gregs[REG_EIP]; |
+ dest->flags = mctx->gregs[REG_EFL]; |
+ |
+#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm |
+ dest->r0 = mctx->arm_r0; |
+ dest->r1 = mctx->arm_r1; |
+ dest->r2 = mctx->arm_r2; |
+ dest->r3 = mctx->arm_r3; |
+ dest->r4 = mctx->arm_r4; |
+ dest->r5 = mctx->arm_r5; |
+ dest->r6 = mctx->arm_r6; |
+ dest->r7 = mctx->arm_r7; |
+ dest->r8 = mctx->arm_r8; |
+ // TODO(uekawa): We don't really use r9 for trusted thread pointer |
+ // for Non-SFI NaCl, do we? |
+ dest->r9 = mctx->arm_r9; |
+ dest->r10 = mctx->arm_r10; |
+ dest->r11 = mctx->arm_fp; |
+ dest->r12 = mctx->arm_ip; |
+ dest->stack_ptr = mctx->arm_sp; |
+ dest->lr = mctx->arm_lr; |
+ dest->prog_ctr = mctx->arm_pc; |
+ dest->cpsr = mctx->arm_cpsr; |
+#else |
+# error Unsupported architecture |
+#endif |
+} |
+ |
+void ExceptionFrameFromSignalContext(NonSfiExceptionFrame* frame, |
+ const void* raw_ctx) { |
+ const ucontext_t *uctx = (ucontext_t *) raw_ctx; |
+ // mcontext_t is sigcontext in ARM. |
+ const mcontext_t *mctx = &uctx->uc_mcontext; |
+ frame->context.size = (((uintptr_t)&frame->portable + 1) |
+ - (uintptr_t)&frame->context); |
+ frame->context.portable_context_offset = ((uintptr_t)&frame->portable |
+ - (uintptr_t)&frame->context); |
+ frame->context.portable_context_size = sizeof(frame->portable); |
+ frame->context.regs_size = sizeof(frame->context.regs); |
+ |
+ for (size_t i = 0; i < NACL_ARRAY_SIZE(frame->context.reserved); i++) { |
+ frame->context.reserved[i] = 0; |
+ } |
+ |
+ MachineContextToRegister(mctx, &frame->context.regs); |
+ |
+ frame->portable.prog_ctr = frame->context.regs.prog_ctr; |
+ frame->portable.stack_ptr = frame->context.regs.stack_ptr; |
+ |
+#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 |
+ frame->context.arch = EM_386; |
+ frame->portable.frame_ptr = frame->context.regs.ebp; |
+#elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm |
+ frame->context.arch = EM_ARM; |
+ // R11 is frame pointer in ARM mode, R8 is frame pointer in thumb mode. |
+ frame->portable.frame_ptr = frame->context.regs.r11; |
+#else |
+# error Unsupported architecture |
+#endif |
+} |
+ |
// Signal handler, responsible for calling the registered handlers. |
static void SignalCatch(int sig, siginfo_t *info, void *uc) { |
if (signal_handler_function_pointer) { |
- // TODO(uekawa): Whether to add dependency or copy the implementation? |
- NaClSignalContext signal_context; |
- NaClSignalContextFromHandler(&signal_context, uc); |
- // Is this safe to allocate this on stack ? |
- NaClExceptionFrame exception_frame; |
- NaClSignalSetUpExceptionFrame(&exception_frame, |
- &signal_context, |
- 0 /* context_user_addr, what is this? */); |
- |
+ NonSfiExceptionFrame exception_frame; |
+ ExceptionFrameFromSignalContext(&exception_frame, uc); |
signal_handler_function_pointer(&exception_frame.context); |
} |
// TODO(uekawa): Only exit on crash signals? |
@@ -104,7 +177,7 @@ void InitializeSignalHandler(void) { |
/* Install all handlers */ |
for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) { |
if (sigaction(kSignals[a], &sa, NULL) != 0) { |
- perror("sigaction"); |
+ PLOG(FATAL) << "Registering signal handlers failed"; |
} |
} |
} |