diff options
author | Moonchild <moonchild@palemoon.org> | 2021-05-02 07:10:18 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2021-05-02 07:10:18 +0000 |
commit | 3d671e4275c73a1484c72713304c6e04ec4ffc7c (patch) | |
tree | 98c4e605f3ce273f65fdf208275c433ee4566d4c /js/src/wasm | |
parent | 56da7e27477d0d4669980d2ce17f3b877ea0c36c (diff) | |
download | uxp-3d671e4275c73a1484c72713304c6e04ec4ffc7c.tar.gz |
Issue #1751 -- Remove XP_DARWIN
Diffstat (limited to 'js/src/wasm')
-rw-r--r-- | js/src/wasm/WasmSignalHandlers.cpp | 367 | ||||
-rw-r--r-- | js/src/wasm/WasmSignalHandlers.h | 29 |
2 files changed, 5 insertions, 391 deletions
diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp index b7bb024bca..b45d05ebd2 100644 --- a/js/src/wasm/WasmSignalHandlers.cpp +++ b/js/src/wasm/WasmSignalHandlers.cpp @@ -1,6 +1,7 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * Copyright 2014 Mozilla Foundation + * Copyright 2021 Moonchild Productions * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -235,10 +236,6 @@ class AutoSetHandlingSegFault # define EPC_sig(p) ((p)->uc_mcontext.mc_pc) # define RFP_sig(p) ((p)->uc_mcontext.mc_regs[30]) # endif -#elif defined(XP_DARWIN) -# define EIP_sig(p) ((p)->uc_mcontext->__ss.__eip) -# define RIP_sig(p) ((p)->uc_mcontext->__ss.__rip) -# define R15_sig(p) ((p)->uc_mcontext->__ss.__pc) #else # error "Don't know how to read/write to the thread state via the mcontext_t." #endif @@ -348,34 +345,8 @@ enum { REG_EIP = 14 }; #endif // Define a context type for use in the emulator code. This is usually just -// the same as CONTEXT, but on Mac we use a different structure since we call -// into the emulator code from a Mach exception handler rather than a -// sigaction-style signal handler. -#if defined(XP_DARWIN) -# if defined(JS_CPU_X64) -struct macos_x64_context { - x86_thread_state64_t thread; - x86_float_state64_t float_; -}; -# define EMULATOR_CONTEXT macos_x64_context -# elif defined(JS_CPU_X86) -struct macos_x86_context { - x86_thread_state_t thread; - x86_float_state_t float_; -}; -# define EMULATOR_CONTEXT macos_x86_context -# elif defined(JS_CPU_ARM) -struct macos_arm_context { - arm_thread_state_t thread; - arm_neon_state_t float_; -}; -# define EMULATOR_CONTEXT macos_arm_context -# else -# error Unsupported architecture -# endif -#else +// the same as CONTEXT. # define EMULATOR_CONTEXT CONTEXT -#endif #if defined(JS_CPU_X64) # define PC_sig(p) RIP_sig(p) @@ -467,7 +438,6 @@ StoreValueFromGPImm(SharedMem<void*> addr, size_t size, int32_t imm) AtomicOperations::memcpySafeWhenRacy(addr, static_cast<void*>(&imm), size); } -# if !defined(XP_DARWIN) MOZ_COLD static void* AddressOfFPRegisterSlot(CONTEXT* context, FloatRegisters::Encoding encoding) { @@ -517,57 +487,6 @@ AddressOfGPRegisterSlot(EMULATOR_CONTEXT* context, Registers::Code code) } MOZ_CRASH(); } -# else -MOZ_COLD static void* -AddressOfFPRegisterSlot(EMULATOR_CONTEXT* context, FloatRegisters::Encoding encoding) -{ - switch (encoding) { - case X86Encoding::xmm0: return &context->float_.__fpu_xmm0; - case X86Encoding::xmm1: return &context->float_.__fpu_xmm1; - case X86Encoding::xmm2: return &context->float_.__fpu_xmm2; - case X86Encoding::xmm3: return &context->float_.__fpu_xmm3; - case X86Encoding::xmm4: return &context->float_.__fpu_xmm4; - case X86Encoding::xmm5: return &context->float_.__fpu_xmm5; - case X86Encoding::xmm6: return &context->float_.__fpu_xmm6; - case X86Encoding::xmm7: return &context->float_.__fpu_xmm7; - case X86Encoding::xmm8: return &context->float_.__fpu_xmm8; - case X86Encoding::xmm9: return &context->float_.__fpu_xmm9; - case X86Encoding::xmm10: return &context->float_.__fpu_xmm10; - case X86Encoding::xmm11: return &context->float_.__fpu_xmm11; - case X86Encoding::xmm12: return &context->float_.__fpu_xmm12; - case X86Encoding::xmm13: return &context->float_.__fpu_xmm13; - case X86Encoding::xmm14: return &context->float_.__fpu_xmm14; - case X86Encoding::xmm15: return &context->float_.__fpu_xmm15; - default: break; - } - MOZ_CRASH(); -} - -MOZ_COLD static void* -AddressOfGPRegisterSlot(EMULATOR_CONTEXT* context, Registers::Code code) -{ - switch (code) { - case X86Encoding::rax: return &context->thread.__rax; - case X86Encoding::rcx: return &context->thread.__rcx; - case X86Encoding::rdx: return &context->thread.__rdx; - case X86Encoding::rbx: return &context->thread.__rbx; - case X86Encoding::rsp: return &context->thread.__rsp; - case X86Encoding::rbp: return &context->thread.__rbp; - case X86Encoding::rsi: return &context->thread.__rsi; - case X86Encoding::rdi: return &context->thread.__rdi; - case X86Encoding::r8: return &context->thread.__r8; - case X86Encoding::r9: return &context->thread.__r9; - case X86Encoding::r10: return &context->thread.__r10; - case X86Encoding::r11: return &context->thread.__r11; - case X86Encoding::r12: return &context->thread.__r12; - case X86Encoding::r13: return &context->thread.__r13; - case X86Encoding::r14: return &context->thread.__r14; - case X86Encoding::r15: return &context->thread.__r15; - default: break; - } - MOZ_CRASH(); -} -# endif // !XP_DARWIN MOZ_COLD static void SetRegisterToCoercedUndefined(EMULATOR_CONTEXT* context, size_t size, @@ -873,276 +792,7 @@ WasmFaultHandler(LPEXCEPTION_POINTERS exception) return EXCEPTION_CONTINUE_SEARCH; } -#elif defined(XP_DARWIN) -# include <mach/exc.h> - -static uint8_t** -ContextToPC(EMULATOR_CONTEXT* context) -{ -# if defined(JS_CPU_X64) - static_assert(sizeof(context->thread.__rip) == sizeof(void*), - "stored IP should be compile-time pointer-sized"); - return reinterpret_cast<uint8_t**>(&context->thread.__rip); -# elif defined(JS_CPU_X86) - static_assert(sizeof(context->thread.uts.ts32.__eip) == sizeof(void*), - "stored IP should be compile-time pointer-sized"); - return reinterpret_cast<uint8_t**>(&context->thread.uts.ts32.__eip); -# elif defined(JS_CPU_ARM) - static_assert(sizeof(context->thread.__pc) == sizeof(void*), - "stored IP should be compile-time pointer-sized"); - return reinterpret_cast<uint8_t**>(&context->thread.__pc); -# else -# error Unsupported architecture -# endif -} - -// This definition was generated by mig (the Mach Interface Generator) for the -// routine 'exception_raise' (exc.defs). -#pragma pack(4) -typedef struct { - mach_msg_header_t Head; - /* start of the kernel processed data */ - mach_msg_body_t msgh_body; - mach_msg_port_descriptor_t thread; - mach_msg_port_descriptor_t task; - /* end of the kernel processed data */ - NDR_record_t NDR; - exception_type_t exception; - mach_msg_type_number_t codeCnt; - int64_t code[2]; -} Request__mach_exception_raise_t; -#pragma pack() - -// The full Mach message also includes a trailer. -struct ExceptionRequest -{ - Request__mach_exception_raise_t body; - mach_msg_trailer_t trailer; -}; - -static bool -HandleMachException(JSRuntime* rt, const ExceptionRequest& request) -{ - // Don't allow recursive handling of signals, see AutoSetHandlingSegFault. - if (rt->handlingSegFault) - return false; - AutoSetHandlingSegFault handling(rt); - - // Get the port of the JSRuntime's thread from the message. - mach_port_t rtThread = request.body.thread.name; - - // Read out the JSRuntime thread's register state. - EMULATOR_CONTEXT context; -# if defined(JS_CPU_X64) - unsigned int thread_state_count = x86_THREAD_STATE64_COUNT; - unsigned int float_state_count = x86_FLOAT_STATE64_COUNT; - int thread_state = x86_THREAD_STATE64; - int float_state = x86_FLOAT_STATE64; -# elif defined(JS_CPU_X86) - unsigned int thread_state_count = x86_THREAD_STATE_COUNT; - unsigned int float_state_count = x86_FLOAT_STATE_COUNT; - int thread_state = x86_THREAD_STATE; - int float_state = x86_FLOAT_STATE; -# elif defined(JS_CPU_ARM) - unsigned int thread_state_count = ARM_THREAD_STATE_COUNT; - unsigned int float_state_count = ARM_NEON_STATE_COUNT; - int thread_state = ARM_THREAD_STATE; - int float_state = ARM_NEON_STATE; -# else -# error Unsupported architecture -# endif - kern_return_t kret; - kret = thread_get_state(rtThread, thread_state, - (thread_state_t)&context.thread, &thread_state_count); - if (kret != KERN_SUCCESS) - return false; - kret = thread_get_state(rtThread, float_state, - (thread_state_t)&context.float_, &float_state_count); - if (kret != KERN_SUCCESS) - return false; - - uint8_t** ppc = ContextToPC(&context); - uint8_t* pc = *ppc; - - if (request.body.exception != EXC_BAD_ACCESS || request.body.codeCnt != 2) - return false; - - WasmActivation* activation = rt->wasmActivationStack(); - if (!activation) - return false; - - const Instance* instance = activation->compartment()->wasm.lookupInstanceDeprecated(pc); - if (!instance || !instance->codeSegment().containsFunctionPC(pc)) - return false; - - uint8_t* faultingAddress = reinterpret_cast<uint8_t*>(request.body.code[1]); - - // This check isn't necessary, but, since we can, check anyway to make - // sure we aren't covering up a real bug. - if (!IsHeapAccessAddress(*instance, faultingAddress)) - return false; - - HandleMemoryAccess(&context, pc, faultingAddress, *instance, ppc); - - // Update the thread state with the new pc and register values. - kret = thread_set_state(rtThread, float_state, (thread_state_t)&context.float_, float_state_count); - if (kret != KERN_SUCCESS) - return false; - kret = thread_set_state(rtThread, thread_state, (thread_state_t)&context.thread, thread_state_count); - if (kret != KERN_SUCCESS) - return false; - - return true; -} - -// Taken from mach_exc in /usr/include/mach/mach_exc.defs. -static const mach_msg_id_t sExceptionId = 2405; - -// The choice of id here is arbitrary, the only constraint is that sQuitId != sExceptionId. -static const mach_msg_id_t sQuitId = 42; - -static void -MachExceptionHandlerThread(JSRuntime* rt) -{ - mach_port_t port = rt->wasmMachExceptionHandler.port(); - kern_return_t kret; - - while(true) { - ExceptionRequest request; - kret = mach_msg(&request.body.Head, MACH_RCV_MSG, 0, sizeof(request), - port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - - // If we fail even receiving the message, we can't even send a reply! - // Rather than hanging the faulting thread (hanging the browser), crash. - if (kret != KERN_SUCCESS) { - fprintf(stderr, "MachExceptionHandlerThread: mach_msg failed with %d\n", (int)kret); - MOZ_CRASH(); - } - - // There are only two messages we should be receiving: an exception - // message that occurs when the runtime's thread faults and the quit - // message sent when the runtime is shutting down. - if (request.body.Head.msgh_id == sQuitId) - break; - if (request.body.Head.msgh_id != sExceptionId) { - fprintf(stderr, "Unexpected msg header id %d\n", (int)request.body.Head.msgh_bits); - MOZ_CRASH(); - } - - // Some thread just commited an EXC_BAD_ACCESS and has been suspended by - // the kernel. The kernel is waiting for us to reply with instructions. - // Our default is the "not handled" reply (by setting the RetCode field - // of the reply to KERN_FAILURE) which tells the kernel to continue - // searching at the process and system level. If this is an asm.js - // expected exception, we handle it and return KERN_SUCCESS. - bool handled = HandleMachException(rt, request); - kern_return_t replyCode = handled ? KERN_SUCCESS : KERN_FAILURE; - - // This magic incantation to send a reply back to the kernel was derived - // from the exc_server generated by 'mig -v /usr/include/mach/mach_exc.defs'. - __Reply__exception_raise_t reply; - reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.body.Head.msgh_bits), 0); - reply.Head.msgh_size = sizeof(reply); - reply.Head.msgh_remote_port = request.body.Head.msgh_remote_port; - reply.Head.msgh_local_port = MACH_PORT_NULL; - reply.Head.msgh_id = request.body.Head.msgh_id + 100; - reply.NDR = NDR_record; - reply.RetCode = replyCode; - mach_msg(&reply.Head, MACH_SEND_MSG, sizeof(reply), 0, MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - } -} - -MachExceptionHandler::MachExceptionHandler() - : installed_(false), - thread_(), - port_(MACH_PORT_NULL) -{} - -void -MachExceptionHandler::uninstall() -{ - if (installed_) { - thread_port_t thread = mach_thread_self(); - kern_return_t kret = thread_set_exception_ports(thread, - EXC_MASK_BAD_ACCESS, - MACH_PORT_NULL, - EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, - THREAD_STATE_NONE); - mach_port_deallocate(mach_task_self(), thread); - if (kret != KERN_SUCCESS) - MOZ_CRASH(); - installed_ = false; - } - if (thread_.joinable()) { - // Break the handler thread out of the mach_msg loop. - mach_msg_header_t msg; - msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); - msg.msgh_size = sizeof(msg); - msg.msgh_remote_port = port_; - msg.msgh_local_port = MACH_PORT_NULL; - msg.msgh_reserved = 0; - msg.msgh_id = sQuitId; - kern_return_t kret = mach_msg(&msg, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (kret != KERN_SUCCESS) { - fprintf(stderr, "MachExceptionHandler: failed to send quit message: %d\n", (int)kret); - MOZ_CRASH(); - } - - // Wait for the handler thread to complete before deallocating the port. - thread_.join(); - } - if (port_ != MACH_PORT_NULL) { - DebugOnly<kern_return_t> kret = mach_port_destroy(mach_task_self(), port_); - MOZ_ASSERT(kret == KERN_SUCCESS); - port_ = MACH_PORT_NULL; - } -} - -bool -MachExceptionHandler::install(JSRuntime* rt) -{ - MOZ_ASSERT(!installed()); - kern_return_t kret; - mach_port_t thread; - - // Get a port which can send and receive data. - kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port_); - if (kret != KERN_SUCCESS) - goto error; - kret = mach_port_insert_right(mach_task_self(), port_, port_, MACH_MSG_TYPE_MAKE_SEND); - if (kret != KERN_SUCCESS) - goto error; - - // Create a thread to block on reading port_. - if (!thread_.init(MachExceptionHandlerThread, rt)) - goto error; - - // Direct exceptions on this thread to port_ (and thus our handler thread). - // Note: we are totally clobbering any existing *thread* exception ports and - // not even attempting to forward. Breakpad and gdb both use the *process* - // exception ports which are only called if the thread doesn't handle the - // exception, so we should be fine. - thread = mach_thread_self(); - kret = thread_set_exception_ports(thread, - EXC_MASK_BAD_ACCESS, - port_, - EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, - THREAD_STATE_NONE); - mach_port_deallocate(mach_task_self(), thread); - if (kret != KERN_SUCCESS) - goto error; - - installed_ = true; - return true; - - error: - uninstall(); - return false; -} - -#else // If not Windows or Mac, assume Unix +#else // If not Windows, assume Unix-like enum class Signal { SegFault, @@ -1246,7 +896,7 @@ WasmFaultHandler(int signum, siginfo_t* info, void* context) else previousSignal->sa_handler(signum); } -# endif // XP_WIN || XP_DARWIN || assume unix +# endif // XP_WIN || assume Unix-like static void RedirectIonBackedgesToInterruptCheck(JSRuntime* rt) @@ -1374,9 +1024,6 @@ ProcessHasSignalHandlers() # if defined(XP_WIN) if (!AddVectoredExceptionHandler(/* FirstHandler = */ true, WasmFaultHandler)) return false; -# elif defined(XP_DARWIN) - // OSX handles seg faults via the Mach exception handler above, so don't - // install WasmFaultHandler. # else // SA_NODEFER allows us to reenter the signal handler if we crash while // handling the signal, and fall through to the Breakpad handler by testing @@ -1412,12 +1059,6 @@ wasm::EnsureSignalHandlers(JSRuntime* rt) if (!ProcessHasSignalHandlers()) return true; -#if defined(XP_DARWIN) - // On OSX, each JSRuntime gets its own handler thread. - if (!rt->wasmMachExceptionHandler.installed() && !rt->wasmMachExceptionHandler.install(rt)) - return false; -#endif - return true; } diff --git a/js/src/wasm/WasmSignalHandlers.h b/js/src/wasm/WasmSignalHandlers.h index 87faa15025..7fe3dd86e6 100644 --- a/js/src/wasm/WasmSignalHandlers.h +++ b/js/src/wasm/WasmSignalHandlers.h @@ -1,6 +1,7 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * Copyright 2014 Mozilla Foundation + * Copyright 2021 Moonchild Productions * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +20,6 @@ #define wasm_signal_handlers_h #include "mozilla/Attributes.h" - -#if defined(XP_DARWIN) -# include <mach/mach.h> -#endif #include "threading/Thread.h" struct JSRuntime; @@ -46,30 +43,6 @@ EnsureSignalHandlers(JSRuntime* rt); bool HaveSignalHandlers(); -#if defined(XP_DARWIN) -// On OSX we are forced to use the lower-level Mach exception mechanism instead -// of Unix signals. Mach exceptions are not handled on the victim's stack but -// rather require an extra thread. For simplicity, we create one such thread -// per JSRuntime (upon the first use of asm.js in the JSRuntime). This thread -// and related resources are owned by AsmJSMachExceptionHandler which is owned -// by JSRuntime. -class MachExceptionHandler -{ - bool installed_; - js::Thread thread_; - mach_port_t port_; - - void uninstall(); - - public: - MachExceptionHandler(); - ~MachExceptionHandler() { uninstall(); } - mach_port_t port() const { return port_; } - bool installed() const { return installed_; } - bool install(JSRuntime* rt); -}; -#endif - // Test whether the given PC is within the innermost wasm activation. Return // false if it is not, or it cannot be determined. bool IsPCInWasmCode(void *pc); |