aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/dynarmic/CMakeLists.txt86
-rw-r--r--src/dynarmic/backend/exception_handler_macos.cpp (renamed from src/dynarmic/backend/x64/exception_handler_macos.cpp)83
-rw-r--r--src/dynarmic/backend/exception_handler_macos_mig.c14
-rw-r--r--src/dynarmic/backend/exception_handler_windows.cpp14
5 files changed, 139 insertions, 59 deletions
diff --git a/.gitignore b/.gitignore
index 3621caac..d735e662 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ cmake-build-*/
.idea/
docs/Doxygen/
# Generated files
+src/dynarmic/backend/arm64/mig/
src/dynarmic/backend/x64/mig/
# System files
.DS_Store
diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt
index 85a118cf..6312af19 100644
--- a/src/dynarmic/CMakeLists.txt
+++ b/src/dynarmic/CMakeLists.txt
@@ -330,41 +330,6 @@ if (ARCHITECTURE STREQUAL "x86_64")
)
endif()
- if (WIN32)
- target_sources(dynarmic PRIVATE backend/x64/exception_handler_windows.cpp)
- elseif (APPLE)
- find_path(MACH_EXC_DEFS_DIR "mach/mach_exc.defs")
- if (NOT MACH_EXC_DEFS_DIR)
- message(WARNING "macOS fastmem disabled: unable to find mach/mach_exc.defs")
- target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp)
- else()
- message(STATUS "mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}")
- execute_process(
- COMMAND
- mkdir -p "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig"
- COMMAND
- mig
- -arch x86_64
- -user "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_user.c"
- -header "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_user.h"
- -server "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_server.c"
- -sheader "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_server.h"
- "${MACH_EXC_DEFS_DIR}/mach/mach_exc.defs"
- )
- target_sources(dynarmic PRIVATE
- backend/x64/exception_handler_macos.cpp
- backend/x64/mig/mach_exc_server.c
- backend/x64/mig/mach_exc_server.h
- )
- endif()
- elseif (UNIX)
- if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
- target_link_libraries(dynarmic PRIVATE rt)
- endif()
- target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp)
- else()
- target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp)
- endif()
elseif(ARCHITECTURE STREQUAL "arm64")
target_link_libraries(dynarmic PRIVATE merry::oaknut)
@@ -423,17 +388,54 @@ elseif(ARCHITECTURE STREQUAL "arm64")
backend/arm64/a64_interface.cpp
)
endif()
+endif()
- if (UNIX)
- if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
- target_link_libraries(dynarmic PRIVATE rt)
- endif()
- target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp)
- else()
+if (WIN32)
+ target_sources(dynarmic PRIVATE backend/exception_handler_windows.cpp)
+elseif (APPLE)
+ find_path(MACH_EXC_DEFS_DIR "mach/mach_exc.defs")
+ if (NOT MACH_EXC_DEFS_DIR)
+ message(WARNING "macOS fastmem disabled: unable to find mach/mach_exc.defs")
target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp)
+ else()
+ message(STATUS "mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}")
+ execute_process(
+ COMMAND
+ mkdir -p "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig"
+ COMMAND
+ mig
+ -arch x86_64
+ -user "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_user.c"
+ -header "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_user.h"
+ -server "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_server.c"
+ -sheader "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig/mach_exc_server.h"
+ "${MACH_EXC_DEFS_DIR}/mach/mach_exc.defs"
+ )
+ message(STATUS "mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}")
+ execute_process(
+ COMMAND
+ mkdir -p "${CMAKE_CURRENT_SOURCE_DIR}/backend/arm64/mig"
+ COMMAND
+ mig
+ -arch arm64
+ -user "${CMAKE_CURRENT_SOURCE_DIR}/backend/arm64/mig/mach_exc_user.c"
+ -header "${CMAKE_CURRENT_SOURCE_DIR}/backend/arm64/mig/mach_exc_user.h"
+ -server "${CMAKE_CURRENT_SOURCE_DIR}/backend/arm64/mig/mach_exc_server.c"
+ -sheader "${CMAKE_CURRENT_SOURCE_DIR}/backend/arm64/mig/mach_exc_server.h"
+ "${MACH_EXC_DEFS_DIR}/mach/mach_exc.defs"
+ )
+ target_sources(dynarmic PRIVATE
+ backend/exception_handler_macos.cpp
+ backend/exception_handler_macos_mig.c
+ )
+ endif()
+elseif (UNIX)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ target_link_libraries(dynarmic PRIVATE rt)
endif()
+ target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp)
else()
- message(FATAL_ERROR "Unsupported architecture")
+ target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp)
endif()
include(CreateDirectoryGroups)
diff --git a/src/dynarmic/backend/x64/exception_handler_macos.cpp b/src/dynarmic/backend/exception_handler_macos.cpp
index 763ced7d..201c7584 100644
--- a/src/dynarmic/backend/x64/exception_handler_macos.cpp
+++ b/src/dynarmic/backend/exception_handler_macos.cpp
@@ -16,17 +16,36 @@
#include <fmt/format.h>
#include <mcl/assert.hpp>
#include <mcl/bit_cast.hpp>
+#include <mcl/macro/architecture.hpp>
#include <mcl/stdint.hpp>
#include "dynarmic/backend/exception_handler.h"
-#include "dynarmic/backend/x64/block_of_code.h"
-#define mig_external extern "C"
-#include "dynarmic/backend/x64/mig/mach_exc_server.h"
+#if defined(MCL_ARCHITECTURE_X86_64)
-namespace Dynarmic::Backend {
+# include "dynarmic/backend/x64/block_of_code.h"
+# define mig_external extern "C"
+# include "dynarmic/backend/x64/mig/mach_exc_server.h"
+
+# define THREAD_STATE x86_THREAD_STATE64
+# define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
+
+using dynarmic_thread_state_t = x86_thread_state64_t;
+
+#elif defined(MCL_ARCHITECTURE_ARM64)
+
+# include <oaknut/code_block.hpp>
+# define mig_external extern "C"
+# include "dynarmic/backend/arm64/mig/mach_exc_server.h"
+
+# define THREAD_STATE ARM_THREAD_STATE64
+# define THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT
-using namespace Dynarmic::Backend::X64;
+using dynarmic_thread_state_t = arm_thread_state64_t;
+
+#endif
+
+namespace Dynarmic::Backend {
namespace {
@@ -45,7 +64,7 @@ public:
MachHandler();
~MachHandler();
- kern_return_t HandleRequest(x86_thread_state64_t* thread_state);
+ kern_return_t HandleRequest(dynarmic_thread_state_t* thread_state);
void AddCodeBlock(CodeBlockInfo info);
void RemoveCodeBlock(u64 rip);
@@ -69,7 +88,7 @@ MachHandler::MachHandler() {
KCHECK(mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &server_port));
KCHECK(mach_port_insert_right(mach_task_self(), server_port, server_port, MACH_MSG_TYPE_MAKE_SEND));
- KCHECK(task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, server_port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, x86_THREAD_STATE64));
+ KCHECK(task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, server_port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, THREAD_STATE));
// The below doesn't actually work, and I'm not sure why; since this doesn't work we'll have a spurious error message upon shutdown.
mach_port_t prev;
@@ -110,6 +129,7 @@ void MachHandler::MessagePump() {
}
}
+#if defined(MCL_ARCHITECTURE_X86_64)
kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) {
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
@@ -127,6 +147,24 @@ kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) {
return KERN_SUCCESS;
}
+#elif defined(MCL_ARCHITECTURE_ARM64)
+kern_return_t MachHandler::HandleRequest(arm_thread_state64_t* ts) {
+ std::lock_guard<std::mutex> guard(code_block_infos_mutex);
+
+ const auto iter = FindCodeBlockInfo(ts->__pc);
+ if (iter == code_block_infos.end()) {
+ fmt::print(stderr, "Unhandled EXC_BAD_ACCESS at pc {:#016x}\n", ts->__pc);
+ return KERN_FAILURE;
+ }
+
+ FakeCall fc = iter->cb(ts->__pc);
+
+ // TODO: Sign with ptrauth_sign_unauthenticated if pointer authentication is enabled.
+ ts->__pc = fc.call_pc;
+
+ return KERN_SUCCESS;
+}
+#endif
void MachHandler::AddCodeBlock(CodeBlockInfo cbi) {
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
@@ -173,7 +211,7 @@ mig_external kern_return_t catch_mach_exception_raise_state(
fmt::print(stderr, "dynarmic: catch_mach_exception_raise_state: Invalid arguments.\n");
return KERN_INVALID_ARGUMENT;
}
- if (*flavor != x86_THREAD_STATE64 || old_stateCnt != x86_THREAD_STATE64_COUNT || *new_stateCnt < x86_THREAD_STATE64_COUNT) {
+ if (*flavor != THREAD_STATE || old_stateCnt != THREAD_STATE_COUNT || *new_stateCnt < THREAD_STATE_COUNT) {
fmt::print(stderr, "dynarmic: catch_mach_exception_raise_state: Unexpected flavor.\n");
return KERN_INVALID_ARGUMENT;
}
@@ -182,17 +220,17 @@ mig_external kern_return_t catch_mach_exception_raise_state(
return KERN_FAILURE;
}
- x86_thread_state64_t* ts = reinterpret_cast<x86_thread_state64_t*>(new_state);
- std::memcpy(ts, reinterpret_cast<const x86_thread_state64_t*>(old_state), sizeof(x86_thread_state64_t));
- *new_stateCnt = x86_THREAD_STATE64_COUNT;
+ dynarmic_thread_state_t* ts = reinterpret_cast<dynarmic_thread_state_t*>(new_state);
+ std::memcpy(ts, reinterpret_cast<const dynarmic_thread_state_t*>(old_state), sizeof(dynarmic_thread_state_t));
+ *new_stateCnt = THREAD_STATE_COUNT;
return mach_handler.HandleRequest(ts);
}
struct ExceptionHandler::Impl final {
- Impl(BlockOfCode& code)
- : code_begin(mcl::bit_cast<u64>(code.getCode()))
- , code_end(code_begin + code.GetTotalCodeSize()) {}
+ Impl(u64 code_begin_, u64 code_end_)
+ : code_begin(code_begin_)
+ , code_end(code_end_) {}
void SetCallback(std::function<FakeCall(u64)> cb) {
CodeBlockInfo cbi;
@@ -211,12 +249,23 @@ private:
};
ExceptionHandler::ExceptionHandler() = default;
-
ExceptionHandler::~ExceptionHandler() = default;
-void ExceptionHandler::Register(BlockOfCode& code) {
- impl = std::make_unique<Impl>(code);
+#if defined(MCL_ARCHITECTURE_X86_64)
+void ExceptionHandler::Register(X64::BlockOfCode& code) {
+ const u64 code_begin = mcl::bit_cast<u64>(code.getCode());
+ const u64 code_end = code_begin + code.GetTotalCodeSize();
+ impl = std::make_unique<Impl>(code_begin, code_end);
+}
+#elif defined(MCL_ARCHITECTURE_ARM64)
+void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
+ const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
+ const u64 code_end = code_begin + size;
+ impl = std::make_unique<Impl>(code_begin, code_end);
}
+#else
+# error "Invalid architecture"
+#endif
bool ExceptionHandler::SupportsFastmem() const noexcept {
return static_cast<bool>(impl);
diff --git a/src/dynarmic/backend/exception_handler_macos_mig.c b/src/dynarmic/backend/exception_handler_macos_mig.c
new file mode 100644
index 00000000..762a80ca
--- /dev/null
+++ b/src/dynarmic/backend/exception_handler_macos_mig.c
@@ -0,0 +1,14 @@
+/* This file is part of the dynarmic project.
+ * Copyright (c) 2023 MerryMage
+ * SPDX-License-Identifier: 0BSD
+ */
+
+#include <mcl/macro/architecture.hpp>
+
+#if defined(MCL_ARCHITECTURE_X86_64)
+# include "dynarmic/backend/x64/mig/mach_exc_server.c"
+#elif defined(MCL_ARCHITECTURE_ARM64)
+# include "dynarmic/backend/arm64/mig/mach_exc_server.c"
+#else
+# error "Invalid architecture"
+#endif
diff --git a/src/dynarmic/backend/exception_handler_windows.cpp b/src/dynarmic/backend/exception_handler_windows.cpp
new file mode 100644
index 00000000..719c0075
--- /dev/null
+++ b/src/dynarmic/backend/exception_handler_windows.cpp
@@ -0,0 +1,14 @@
+/* This file is part of the dynarmic project.
+ * Copyright (c) 2023 MerryMage
+ * SPDX-License-Identifier: 0BSD
+ */
+
+#include <mcl/macro/architecture.hpp>
+
+#if defined(MCL_ARCHITECTURE_X86_64)
+# include "dynarmic/backend/x64/exception_handler_windows.cpp"
+#elif defined(MCL_ARCHITECTURE_ARM64)
+# include "dynarmic/backend/exception_handler_generic.cpp"
+#else
+# error "Invalid architecture"
+#endif