summaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-05-02 07:10:18 +0000
committerMoonchild <moonchild@palemoon.org>2021-05-02 07:10:18 +0000
commit3d671e4275c73a1484c72713304c6e04ec4ffc7c (patch)
tree98c4e605f3ce273f65fdf208275c433ee4566d4c /js/src
parent56da7e27477d0d4669980d2ce17f3b877ea0c36c (diff)
downloaduxp-3d671e4275c73a1484c72713304c6e04ec4ffc7c.tar.gz
Issue #1751 -- Remove XP_DARWIN
Diffstat (limited to 'js/src')
-rw-r--r--js/src/ds/MemoryProtectionExceptionHandler.cpp466
-rw-r--r--js/src/jsmath.cpp2
-rw-r--r--js/src/jsnativestack.cpp7
-rw-r--r--js/src/jsstr.cpp2
-rw-r--r--js/src/threading/posix/Thread.cpp4
-rw-r--r--js/src/vm/Runtime.cpp6
-rw-r--r--js/src/vm/Runtime.h7
-rw-r--r--js/src/wasm/WasmSignalHandlers.cpp367
-rw-r--r--js/src/wasm/WasmSignalHandlers.h29
9 files changed, 13 insertions, 877 deletions
diff --git a/js/src/ds/MemoryProtectionExceptionHandler.cpp b/js/src/ds/MemoryProtectionExceptionHandler.cpp
index 06fabb5301..77df1f0d92 100644
--- a/js/src/ds/MemoryProtectionExceptionHandler.cpp
+++ b/js/src/ds/MemoryProtectionExceptionHandler.cpp
@@ -10,13 +10,10 @@
#if defined(XP_WIN)
# include "jswin.h"
-#elif defined(XP_UNIX) && !defined(XP_DARWIN)
+#elif defined(XP_UNIX)
# include <signal.h>
# include <sys/types.h>
# include <unistd.h>
-#elif defined(XP_DARWIN)
-# include <mach/mach.h>
-# include <unistd.h>
#endif
#ifdef ANDROID
@@ -210,7 +207,7 @@ MemoryProtectionExceptionHandler::uninstall()
}
}
-#elif defined(XP_UNIX) && !defined(XP_DARWIN)
+#elif defined(XP_UNIX)
static struct sigaction sPrevSEGVHandler = {};
@@ -291,465 +288,6 @@ MemoryProtectionExceptionHandler::uninstall()
}
}
-#elif defined(XP_DARWIN)
-
-/*
- * The fact that we need to be able to forward to other exception handlers
- * makes this code much more complicated. The forwarding logic and the
- * structures required to make it work are heavily based on the code at
- * www.ravenbrook.com/project/mps/prototype/2013-06-24/machtest/machtest/main.c
- */
-
-/* -------------------------------------------------------------------------- */
-/* Begin Mach definitions and helper functions */
-/* -------------------------------------------------------------------------- */
-
-/*
- * These are the message IDs associated with each exception type.
- * We'll be using sIDRequest64, but we need the others for forwarding.
- */
-static const mach_msg_id_t sIDRequest32 = 2401;
-static const mach_msg_id_t sIDRequestState32 = 2402;
-static const mach_msg_id_t sIDRequestStateIdentity32 = 2403;
-
-static const mach_msg_id_t sIDRequest64 = 2405;
-static const mach_msg_id_t sIDRequestState64 = 2406;
-static const mach_msg_id_t sIDRequestStateIdentity64 = 2407;
-
-/*
- * Each message ID has an associated Mach message structure.
- * We use the preprocessor to make defining them a little less arduous.
- */
-# define REQUEST_HEADER_FIELDS\
- mach_msg_header_t header;
-
-# define REQUEST_IDENTITY_FIELDS\
- mach_msg_body_t msgh_body;\
- mach_msg_port_descriptor_t thread;\
- mach_msg_port_descriptor_t task;
-
-# define REQUEST_GENERAL_FIELDS(bits)\
- NDR_record_t NDR;\
- exception_type_t exception;\
- mach_msg_type_number_t code_count;\
- int##bits##_t code[2];
-
-# define REQUEST_STATE_FIELDS\
- int flavor;\
- mach_msg_type_number_t old_state_count;\
- natural_t old_state[THREAD_STATE_MAX];
-
-# define REQUEST_TRAILER_FIELDS\
- mach_msg_trailer_t trailer;
-
-# define EXCEPTION_REQUEST(bits)\
- struct ExceptionRequest##bits\
- {\
- REQUEST_HEADER_FIELDS\
- REQUEST_IDENTITY_FIELDS\
- REQUEST_GENERAL_FIELDS(bits)\
- REQUEST_TRAILER_FIELDS\
- };\
-
-# define EXCEPTION_REQUEST_STATE(bits)\
- struct ExceptionRequestState##bits\
- {\
- REQUEST_HEADER_FIELDS\
- REQUEST_GENERAL_FIELDS(bits)\
- REQUEST_STATE_FIELDS\
- REQUEST_TRAILER_FIELDS\
- };\
-
-# define EXCEPTION_REQUEST_STATE_IDENTITY(bits)\
- struct ExceptionRequestStateIdentity##bits\
- {\
- REQUEST_HEADER_FIELDS\
- REQUEST_IDENTITY_FIELDS\
- REQUEST_GENERAL_FIELDS(bits)\
- REQUEST_STATE_FIELDS\
- REQUEST_TRAILER_FIELDS\
- };\
-
-/* This is needed because not all fields are naturally aligned on 64-bit. */
-# ifdef __MigPackStructs
-# pragma pack(4)
-# endif
-
-EXCEPTION_REQUEST(32)
-EXCEPTION_REQUEST(64)
-EXCEPTION_REQUEST_STATE(32)
-EXCEPTION_REQUEST_STATE(64)
-EXCEPTION_REQUEST_STATE_IDENTITY(32)
-EXCEPTION_REQUEST_STATE_IDENTITY(64)
-
-/* We use this as a common base when forwarding to the previous handler. */
-union ExceptionRequestUnion {
- mach_msg_header_t header;
- ExceptionRequest32 r32;
- ExceptionRequest64 r64;
- ExceptionRequestState32 rs32;
- ExceptionRequestState64 rs64;
- ExceptionRequestStateIdentity32 rsi32;
- ExceptionRequestStateIdentity64 rsi64;
-};
-
-/* This isn't really a full Mach message, but it's all we need to send. */
-struct ExceptionReply
-{
- mach_msg_header_t header;
- NDR_record_t NDR;
- kern_return_t RetCode;
-};
-
-# ifdef __MigPackStructs
-# pragma pack()
-# endif
-
-# undef EXCEPTION_REQUEST_STATE_IDENTITY
-# undef EXCEPTION_REQUEST_STATE
-# undef EXCEPTION_REQUEST
-# undef REQUEST_STATE_FIELDS
-# undef REQUEST_GENERAL_FIELDS
-# undef REQUEST_IDENTITY_FIELDS
-# undef REQUEST_HEADER_FIELDS
-
-/*
- * The exception handler we're forwarding to may not have the same behavior
- * or thread state flavor as what we're using. These macros help populate
- * the fields of the message we're about to send to the previous handler.
- */
-# define COPY_REQUEST_COMMON(bits, id)\
- dst.header = src.header;\
- dst.header.msgh_id = id;\
- dst.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(dst) - sizeof(dst.trailer));\
- dst.NDR = src.NDR;\
- dst.exception = src.exception;\
- dst.code_count = src.code_count;\
- dst.code[0] = int##bits##_t(src.code[0]);\
- dst.code[1] = int##bits##_t(src.code[1]);
-
-# define COPY_REQUEST_IDENTITY\
- dst.msgh_body = src.msgh_body;\
- dst.thread = src.thread;\
- dst.task = src.task;
-
-# define COPY_REQUEST_STATE(flavor, stateCount, state)\
- mach_msg_size_t stateSize = stateCount * sizeof(natural_t);\
- dst.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(dst) - sizeof(dst.trailer) -\
- sizeof(dst.old_state) + stateSize);\
- dst.flavor = flavor;\
- dst.old_state_count = stateCount;\
- memcpy(dst.old_state, state, stateSize);
-
-# define COPY_EXCEPTION_REQUEST(bits)\
- static void\
- CopyExceptionRequest##bits(ExceptionRequest64& src,\
- ExceptionRequest##bits& dst)\
- {\
- COPY_REQUEST_COMMON(bits, sIDRequest##bits)\
- COPY_REQUEST_IDENTITY\
- }
-
-# define COPY_EXCEPTION_REQUEST_STATE(bits)\
- static void\
- CopyExceptionRequestState##bits(ExceptionRequest64& src,\
- ExceptionRequestState##bits& dst,\
- thread_state_flavor_t flavor,\
- mach_msg_type_number_t stateCount,\
- thread_state_t state)\
- {\
- COPY_REQUEST_COMMON(bits, sIDRequestState##bits)\
- COPY_REQUEST_STATE(flavor, stateCount, state)\
- }
-
-# define COPY_EXCEPTION_REQUEST_STATE_IDENTITY(bits)\
- static void\
- CopyExceptionRequestStateIdentity##bits(ExceptionRequest64& src,\
- ExceptionRequestStateIdentity##bits& dst,\
- thread_state_flavor_t flavor,\
- mach_msg_type_number_t stateCount,\
- thread_state_t state)\
- {\
- COPY_REQUEST_COMMON(bits, sIDRequestStateIdentity##bits)\
- COPY_REQUEST_IDENTITY\
- COPY_REQUEST_STATE(flavor, stateCount, state)\
- }
-
-COPY_EXCEPTION_REQUEST(32)
-COPY_EXCEPTION_REQUEST_STATE(32)
-COPY_EXCEPTION_REQUEST_STATE_IDENTITY(32)
-COPY_EXCEPTION_REQUEST(64)
-COPY_EXCEPTION_REQUEST_STATE(64)
-COPY_EXCEPTION_REQUEST_STATE_IDENTITY(64)
-
-# undef COPY_EXCEPTION_REQUEST_STATE_IDENTITY
-# undef COPY_EXCEPTION_REQUEST_STATE
-# undef COPY_EXCEPTION_REQUEST
-# undef COPY_REQUEST_STATE
-# undef COPY_REQUEST_IDENTITY
-# undef COPY_REQUEST_COMMON
-
-/* -------------------------------------------------------------------------- */
-/* End Mach definitions and helper functions */
-/* -------------------------------------------------------------------------- */
-
-/* Every Mach exception handler is parameterized by these four properties. */
-struct MachExceptionParameters
-{
- exception_mask_t mask;
- mach_port_t port;
- exception_behavior_t behavior;
- thread_state_flavor_t flavor;
-};
-
-struct ExceptionHandlerState
-{
- MachExceptionParameters current;
- MachExceptionParameters previous;
-
- /* Each Mach exception handler runs in its own thread. */
- Thread handlerThread;
-};
-
-/* This choice of ID is arbitrary, but must not match our exception ID. */
-static const mach_msg_id_t sIDQuit = 42;
-
-static ExceptionHandlerState sMachExceptionState;
-
-/*
- * The meat of our exception handler. This thread waits for an exception
- * message, annotates the exception if needed, then forwards it to the
- * previously installed handler (which will likely terminate the process).
- */
-static void
-MachExceptionHandler()
-{
- kern_return_t ret;
- MachExceptionParameters& current = sMachExceptionState.current;
- MachExceptionParameters& previous = sMachExceptionState.previous;
-
- // We use the simplest kind of 64-bit exception message here.
- ExceptionRequest64 request = {};
- request.header.msgh_local_port = current.port;
- request.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(request));
- ret = mach_msg(&request.header, MACH_RCV_MSG, 0, request.header.msgh_size,
- current.port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-
- // Restore the previous handler. We're going to forward to it
- // anyway, and if we crash while doing so we don't want to hang.
- task_set_exception_ports(mach_task_self(), previous.mask, previous.port,
- previous.behavior, previous.flavor);
-
- // If we failed even receiving the message, just give up.
- if (ret != MACH_MSG_SUCCESS)
- MOZ_CRASH("MachExceptionHandler: mach_msg failed to receive a message!");
-
- // Terminate the thread if we're shutting down.
- if (request.header.msgh_id == sIDQuit)
- return;
-
- // The only other valid message ID is the one associated with the
- // EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES behavior we chose.
- if (request.header.msgh_id != sIDRequest64)
- MOZ_CRASH("MachExceptionHandler: Unexpected Message ID!");
-
- // Make sure we can understand the exception we received.
- if (request.exception != EXC_BAD_ACCESS || request.code_count != 2)
- MOZ_CRASH("MachExceptionHandler: Unexpected exception type!");
-
- // Get the address that the offending code tried to access.
- uintptr_t address = uintptr_t(request.code[1]);
-
- // If the faulting address is inside one of our protected regions, we
- // want to annotate the crash to make it stand out from the crowd.
- if (sProtectedRegions.isProtected(address)) {
- ReportCrashIfDebug("Hit MOZ_CRASH(Tried to access a protected region!)\n");
- MOZ_CRASH_ANNOTATE("MOZ_CRASH(Tried to access a protected region!)");
- }
-
- // Forward to the previous handler which may be a debugger, the unix
- // signal handler, the crash reporter or something else entirely.
- if (previous.port != MACH_PORT_NULL) {
- mach_msg_type_number_t stateCount;
- thread_state_data_t state;
- if ((uint32_t(previous.behavior) & ~MACH_EXCEPTION_CODES) != EXCEPTION_DEFAULT) {
- // If the previous handler requested thread state, get it here.
- stateCount = THREAD_STATE_MAX;
- ret = thread_get_state(request.thread.name, previous.flavor, state, &stateCount);
- if (ret != KERN_SUCCESS)
- MOZ_CRASH("MachExceptionHandler: Could not get the thread state to forward!");
- }
-
- // Depending on the behavior of the previous handler, the forwarded
- // exception message will have a different set of fields.
- // Of particular note is that exception handlers that lack
- // MACH_EXCEPTION_CODES will get 32-bit fields even on 64-bit
- // systems. It appears that OSX simply truncates these fields.
- ExceptionRequestUnion forward;
- switch (uint32_t(previous.behavior)) {
- case EXCEPTION_DEFAULT:
- CopyExceptionRequest32(request, forward.r32);
- break;
- case EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES:
- CopyExceptionRequest64(request, forward.r64);
- break;
- case EXCEPTION_STATE:
- CopyExceptionRequestState32(request, forward.rs32,
- previous.flavor, stateCount, state);
- break;
- case EXCEPTION_STATE | MACH_EXCEPTION_CODES:
- CopyExceptionRequestState64(request, forward.rs64,
- previous.flavor, stateCount, state);
- break;
- case EXCEPTION_STATE_IDENTITY:
- CopyExceptionRequestStateIdentity32(request, forward.rsi32,
- previous.flavor, stateCount, state);
- break;
- case EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES:
- CopyExceptionRequestStateIdentity64(request, forward.rsi64,
- previous.flavor, stateCount, state);
- break;
- default:
- MOZ_CRASH("MachExceptionHandler: Unknown previous handler behavior!");
- }
-
- // Forward the generated message to the old port. The local and remote
- // port fields *and their rights* are swapped on arrival, so we need to
- // swap them back first.
- forward.header.msgh_bits = (request.header.msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
- MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(request.header.msgh_bits),
- MACH_MSGH_BITS_REMOTE(request.header.msgh_bits));
- forward.header.msgh_local_port = forward.header.msgh_remote_port;
- forward.header.msgh_remote_port = previous.port;
- ret = mach_msg(&forward.header, MACH_SEND_MSG, forward.header.msgh_size, 0,
- MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (ret != MACH_MSG_SUCCESS)
- MOZ_CRASH("MachExceptionHandler: Failed to forward to the previous handler!");
- } else {
- // There was no previous task-level exception handler, so defer to the
- // host level one instead. We set the return code to KERN_FAILURE to
- // indicate that we did not handle the exception.
- // The reply message ID is always the request ID + 100.
- ExceptionReply reply = {};
- reply.header.msgh_bits =
- MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.header.msgh_bits), 0);
- reply.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(reply));
- reply.header.msgh_remote_port = request.header.msgh_remote_port;
- reply.header.msgh_local_port = MACH_PORT_NULL;
- reply.header.msgh_id = request.header.msgh_id + 100;
- reply.NDR = request.NDR;
- reply.RetCode = KERN_FAILURE;
- ret = mach_msg(&reply.header, MACH_SEND_MSG, reply.header.msgh_size, 0,
- MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (ret != MACH_MSG_SUCCESS)
- MOZ_CRASH("MachExceptionHandler: Failed to forward to the host level!");
- }
-}
-
-static void
-TerminateMachExceptionHandlerThread()
-{
- // Send a simple quit message to the exception handler thread.
- mach_msg_header_t msg;
- msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
- msg.msgh_size = static_cast<mach_msg_size_t>(sizeof(msg));
- msg.msgh_remote_port = sMachExceptionState.current.port;
- msg.msgh_local_port = MACH_PORT_NULL;
- msg.msgh_reserved = 0;
- msg.msgh_id = sIDQuit;
- kern_return_t ret = mach_msg(&msg, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
- MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-
- if (ret == MACH_MSG_SUCCESS)
- sMachExceptionState.handlerThread.join();
- else
- MOZ_CRASH("MachExceptionHandler: Handler thread failed to terminate!");
-}
-
-bool
-MemoryProtectionExceptionHandler::install()
-{
- MOZ_ASSERT(!sExceptionHandlerInstalled);
-
- // If the exception handler is disabled, report success anyway.
- if (MemoryProtectionExceptionHandler::isDisabled())
- return true;
-
- kern_return_t ret;
- mach_port_t task = mach_task_self();
-
- // Allocate a new exception port with receive rights.
- sMachExceptionState.current = {};
- MachExceptionParameters& current = sMachExceptionState.current;
- ret = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &current.port);
- if (ret != KERN_SUCCESS)
- return false;
-
- // Give the new port send rights as well.
- ret = mach_port_insert_right(task, current.port, current.port, MACH_MSG_TYPE_MAKE_SEND);
- if (ret != KERN_SUCCESS) {
- mach_port_deallocate(task, current.port);
- current = {};
- return false;
- }
-
- // Start the thread that will receive the messages from our exception port.
- if (!sMachExceptionState.handlerThread.init(MachExceptionHandler)) {
- mach_port_deallocate(task, current.port);
- current = {};
- return false;
- }
-
- // Set the other properties of our new exception handler.
- current.mask = EXC_MASK_BAD_ACCESS;
- current.behavior = exception_behavior_t(EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES);
- current.flavor = THREAD_STATE_NONE;
-
- // Tell the task to use our exception handler, and save the previous one.
- sMachExceptionState.previous = {};
- MachExceptionParameters& previous = sMachExceptionState.previous;
- mach_msg_type_number_t previousCount = 1;
- ret = task_swap_exception_ports(task, current.mask, current.port, current.behavior,
- current.flavor, &previous.mask, &previousCount,
- &previous.port, &previous.behavior, &previous.flavor);
- if (ret != KERN_SUCCESS) {
- TerminateMachExceptionHandlerThread();
- mach_port_deallocate(task, current.port);
- previous = {};
- current = {};
- return false;
- }
-
- // We should have info on the previous exception handler, even if it's null.
- MOZ_ASSERT(previousCount == 1);
-
- sExceptionHandlerInstalled = true;
- return sExceptionHandlerInstalled;
-}
-
-void
-MemoryProtectionExceptionHandler::uninstall()
-{
- if (sExceptionHandlerInstalled) {
- mach_port_t task = mach_task_self();
-
- // Restore the previous exception handler.
- MachExceptionParameters& previous = sMachExceptionState.previous;
- task_set_exception_ports(task, previous.mask, previous.port,
- previous.behavior, previous.flavor);
-
- TerminateMachExceptionHandlerThread();
-
- // Release the Mach IPC port we used.
- mach_port_deallocate(task, sMachExceptionState.current.port);
-
- sMachExceptionState.current = {};
- sMachExceptionState.previous = {};
-
- sExceptionHandlerInstalled = false;
- }
-}
-
#else
#error "This platform is not supported!"
diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp
index ba1d29de0f..78760583db 100644
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -49,7 +49,7 @@
# undef SystemFunction036
#endif
-#if defined(ANDROID) || defined(XP_DARWIN) || defined(__DragonFly__) || \
+#if defined(ANDROID) || defined(__DragonFly__) || \
defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <stdlib.h>
# define HAVE_ARC4RANDOM
diff --git a/js/src/jsnativestack.cpp b/js/src/jsnativestack.cpp
index d83e06c241..99c2f6654a 100644
--- a/js/src/jsnativestack.cpp
+++ b/js/src/jsnativestack.cpp
@@ -8,7 +8,7 @@
#ifdef XP_WIN
# include "jswin.h"
-#elif defined(XP_DARWIN) || defined(DARWIN) || defined(XP_UNIX)
+#elif defined(XP_UNIX)
# include <pthread.h>
# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
@@ -132,10 +132,6 @@ void*
js::GetNativeStackBaseImpl()
{
pthread_t thread = pthread_self();
-# if defined(XP_DARWIN) || defined(DARWIN)
- return pthread_get_stackaddr_np(thread);
-
-# else
pthread_attr_t sattr;
pthread_attr_init(&sattr);
# if defined(__OpenBSD__)
@@ -210,7 +206,6 @@ js::GetNativeStackBaseImpl()
# else
return static_cast<char*>(stackBase) + stackSize;
# endif
-# endif
}
#endif /* !XP_WIN */
diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
index 6eb11b1cc1..b44fbdebca 100644
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1177,7 +1177,7 @@ FirstCharMatcher8bit(const char* text, uint32_t n, const char pat)
static const char16_t*
FirstCharMatcher16bit(const char16_t* text, uint32_t n, const char16_t pat)
{
-#if defined(XP_DARWIN) || defined(XP_WIN)
+#if defined(XP_WIN)
/*
* Performance of memchr is horrible in OSX. Windows is better,
* but it is still better to use UnrolledMatcher.
diff --git a/js/src/threading/posix/Thread.cpp b/js/src/threading/posix/Thread.cpp
index faca05c24d..a5c2d2eacb 100644
--- a/js/src/threading/posix/Thread.cpp
+++ b/js/src/threading/posix/Thread.cpp
@@ -151,9 +151,7 @@ js::ThisThread::SetName(const char* name)
#endif
int rv;
-#ifdef XP_DARWIN
- rv = pthread_setname_np(name);
-#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
pthread_set_name_np(pthread_self(), name);
rv = 0;
#elif defined(__NetBSD__)
diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
index 251c8258cf..23c50814fc 100644
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -10,14 +10,12 @@
#include "mozilla/ThreadLocal.h"
#include "mozilla/Unused.h"
-#if defined(XP_DARWIN)
-#include <mach/mach.h>
-#elif defined(XP_UNIX)
+#if defined(XP_UNIX)
#include <sys/resource.h>
#elif defined(XP_WIN)
#include <processthreadsapi.h>
#include <windows.h>
-#endif // defined(XP_DARWIN) || defined(XP_UNIX) || defined(XP_WIN)
+#endif // defined(XP_UNIX) || defined(XP_WIN)
#include <locale.h>
#include <string.h>
diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
index f1f2e07094..eefc90cb4c 100644
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -21,9 +21,6 @@
#include "jsclist.h"
#include "jsscript.h"
-#ifdef XP_DARWIN
-# include "wasm/WasmSignalHandlers.h"
-#endif
#include "builtin/AtomicsObject.h"
#include "builtin/Intl.h"
#include "builtin/Promise.h"
@@ -932,10 +929,6 @@ struct JSRuntime : public JS::shadow::Runtime,
*/
JSCList onNewGlobalObjectWatchers;
-#if defined(XP_DARWIN)
- js::wasm::MachExceptionHandler wasmMachExceptionHandler;
-#endif
-
private:
js::FreeOp* defaultFreeOp_;
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);