exception_handler: connect installation to instance lifetime
This commit is contained in:
parent
ac643f1bee
commit
0df09e2f6b
2 changed files with 39 additions and 17 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -183,7 +184,15 @@ void MachHandler::RemoveCodeBlock(u64 rip) {
|
||||||
code_block_infos.erase(iter);
|
code_block_infos.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
MachHandler mach_handler;
|
std::mutex handler_lock;
|
||||||
|
std::optional<MachHandler> mach_handler;
|
||||||
|
|
||||||
|
void RegisterHandler() {
|
||||||
|
std::lock_guard<std::mutex> guard(handler_lock);
|
||||||
|
if (!mach_handler) {
|
||||||
|
mach_handler.emplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
@ -224,7 +233,7 @@ mig_external kern_return_t catch_mach_exception_raise_state(
|
||||||
dynarmic_thread_state_t ts;
|
dynarmic_thread_state_t ts;
|
||||||
std::memcpy(&ts, old_state, sizeof(ts));
|
std::memcpy(&ts, old_state, sizeof(ts));
|
||||||
|
|
||||||
kern_return_t ret = mach_handler.HandleRequest(&ts);
|
kern_return_t ret = mach_handler->HandleRequest(&ts);
|
||||||
|
|
||||||
std::memcpy(new_state, &ts, sizeof(ts));
|
std::memcpy(new_state, &ts, sizeof(ts));
|
||||||
*new_stateCnt = THREAD_STATE_COUNT;
|
*new_stateCnt = THREAD_STATE_COUNT;
|
||||||
|
@ -234,18 +243,20 @@ mig_external kern_return_t catch_mach_exception_raise_state(
|
||||||
struct ExceptionHandler::Impl final {
|
struct ExceptionHandler::Impl final {
|
||||||
Impl(u64 code_begin_, u64 code_end_)
|
Impl(u64 code_begin_, u64 code_end_)
|
||||||
: code_begin(code_begin_)
|
: code_begin(code_begin_)
|
||||||
, code_end(code_end_) {}
|
, code_end(code_end_) {
|
||||||
|
RegisterHandler();
|
||||||
|
}
|
||||||
|
|
||||||
void SetCallback(std::function<FakeCall(u64)> cb) {
|
void SetCallback(std::function<FakeCall(u64)> cb) {
|
||||||
CodeBlockInfo cbi;
|
CodeBlockInfo cbi;
|
||||||
cbi.code_begin = code_begin;
|
cbi.code_begin = code_begin;
|
||||||
cbi.code_end = code_end;
|
cbi.code_end = code_end;
|
||||||
cbi.cb = cb;
|
cbi.cb = cb;
|
||||||
mach_handler.AddCodeBlock(cbi);
|
mach_handler->AddCodeBlock(cbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl() {
|
~Impl() {
|
||||||
mach_handler.RemoveCodeBlock(code_begin);
|
mach_handler->RemoveCodeBlock(code_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <mcl/assert.hpp>
|
#include <mcl/assert.hpp>
|
||||||
|
@ -72,7 +73,15 @@ private:
|
||||||
static void SigAction(int sig, siginfo_t* info, void* raw_context);
|
static void SigAction(int sig, siginfo_t* info, void* raw_context);
|
||||||
};
|
};
|
||||||
|
|
||||||
SigHandler sig_handler;
|
std::mutex handler_lock;
|
||||||
|
std::optional<SigHandler> sig_handler;
|
||||||
|
|
||||||
|
void RegisterHandler() {
|
||||||
|
std::lock_guard<std::mutex> guard(handler_lock);
|
||||||
|
if (!sig_handler) {
|
||||||
|
sig_handler.emplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SigHandler::SigHandler() {
|
SigHandler::SigHandler() {
|
||||||
const size_t signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
|
const size_t signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
|
||||||
|
@ -159,10 +168,10 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(sig_handler.code_block_infos_mutex);
|
std::lock_guard<std::mutex> guard(sig_handler->code_block_infos_mutex);
|
||||||
|
|
||||||
const auto iter = sig_handler.FindCodeBlockInfo(CTX_RIP);
|
const auto iter = sig_handler->FindCodeBlockInfo(CTX_RIP);
|
||||||
if (iter != sig_handler.code_block_infos.end()) {
|
if (iter != sig_handler->code_block_infos.end()) {
|
||||||
FakeCall fc = iter->cb(CTX_RIP);
|
FakeCall fc = iter->cb(CTX_RIP);
|
||||||
|
|
||||||
CTX_RSP -= sizeof(u64);
|
CTX_RSP -= sizeof(u64);
|
||||||
|
@ -220,10 +229,10 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(sig_handler.code_block_infos_mutex);
|
std::lock_guard<std::mutex> guard(sig_handler->code_block_infos_mutex);
|
||||||
|
|
||||||
const auto iter = sig_handler.FindCodeBlockInfo(CTX_PC);
|
const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC);
|
||||||
if (iter != sig_handler.code_block_infos.end()) {
|
if (iter != sig_handler->code_block_infos.end()) {
|
||||||
FakeCall fc = iter->cb(CTX_PC);
|
FakeCall fc = iter->cb(CTX_PC);
|
||||||
|
|
||||||
CTX_PC = fc.call_pc;
|
CTX_PC = fc.call_pc;
|
||||||
|
@ -240,7 +249,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler.old_sa_segv : &sig_handler.old_sa_bus;
|
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus;
|
||||||
if (retry_sa->sa_flags & SA_SIGINFO) {
|
if (retry_sa->sa_flags & SA_SIGINFO) {
|
||||||
retry_sa->sa_sigaction(sig, info, raw_context);
|
retry_sa->sa_sigaction(sig, info, raw_context);
|
||||||
return;
|
return;
|
||||||
|
@ -260,18 +269,20 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
struct ExceptionHandler::Impl final {
|
struct ExceptionHandler::Impl final {
|
||||||
Impl(u64 code_begin_, u64 code_end_)
|
Impl(u64 code_begin_, u64 code_end_)
|
||||||
: code_begin(code_begin_)
|
: code_begin(code_begin_)
|
||||||
, code_end(code_end_) {}
|
, code_end(code_end_) {
|
||||||
|
RegisterHandler();
|
||||||
|
}
|
||||||
|
|
||||||
void SetCallback(std::function<FakeCall(u64)> cb) {
|
void SetCallback(std::function<FakeCall(u64)> cb) {
|
||||||
CodeBlockInfo cbi;
|
CodeBlockInfo cbi;
|
||||||
cbi.code_begin = code_begin;
|
cbi.code_begin = code_begin;
|
||||||
cbi.code_end = code_end;
|
cbi.code_end = code_end;
|
||||||
cbi.cb = cb;
|
cbi.cb = cb;
|
||||||
sig_handler.AddCodeBlock(cbi);
|
sig_handler->AddCodeBlock(cbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl() {
|
~Impl() {
|
||||||
sig_handler.RemoveCodeBlock(code_begin);
|
sig_handler->RemoveCodeBlock(code_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -298,7 +309,7 @@ void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ExceptionHandler::SupportsFastmem() const noexcept {
|
bool ExceptionHandler::SupportsFastmem() const noexcept {
|
||||||
return static_cast<bool>(impl) && sig_handler.SupportsFastmem();
|
return static_cast<bool>(impl) && sig_handler->SupportsFastmem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExceptionHandler::SetFastmemCallback(std::function<FakeCall(u64)> cb) {
|
void ExceptionHandler::SetFastmemCallback(std::function<FakeCall(u64)> cb) {
|
||||||
|
|
Loading…
Reference in a new issue