mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-03-26 20:58:32 -06:00
Improve signal emulation (#4108)
* improve signal emulation * make the sce function use the new posix ones * ifdefing away the issues * fix me being very tired yesterday night * let macOS handle SIGRT signals with the native sigaction call instead of an early error return * windows still has no clue what the fuck is going on * the loathsome clang-formatter * fix oact * return the guest handler, not the host one * Clear any existing signal mask for game threads. * don't rely on implementation specific things * Fix Windows support and sceKernelRaiseException bug * Review suggestions @kalaposfos13 suggested I push these. --------- Co-authored-by: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com>
This commit is contained in:
parent
cc6af03adf
commit
0579569f13
@ -788,14 +788,11 @@ static bool PatchesIllegalInstructionHandler(void* context) {
|
||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||
const auto status =
|
||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
|
||||
[[unlikely]] {
|
||||
UNREACHABLE_MSG("ud2 at code address {:#x}", reinterpret_cast<u64>(code_address));
|
||||
}
|
||||
UNREACHABLE_MSG("Failed to patch address {:x} -- mnemonic: {}",
|
||||
reinterpret_cast<u64>(code_address),
|
||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||
: "Failed to decode");
|
||||
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}",
|
||||
reinterpret_cast<u64>(code_address),
|
||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||
: "Failed to decode");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/kernel/posix_error.h"
|
||||
#include "core/libraries/kernel/threads/exception.h"
|
||||
#include "core/libraries/kernel/threads/pthread.h"
|
||||
#include "core/libraries/libs.h"
|
||||
@ -13,23 +15,24 @@
|
||||
#else
|
||||
#include <csignal>
|
||||
#endif
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Windows doesn't have native versions of these, and we don't need to use them either.
|
||||
static s32 NativeToOrbisSignal(s32 s) {
|
||||
s32 NativeToOrbisSignal(s32 s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static s32 OrbisToNativeSignal(s32 s) {
|
||||
s32 OrbisToNativeSignal(s32 s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static s32 NativeToOrbisSignal(s32 s) {
|
||||
s32 NativeToOrbisSignal(s32 s) {
|
||||
switch (s) {
|
||||
case SIGHUP:
|
||||
return POSIX_SIGHUP;
|
||||
@ -89,12 +92,21 @@ static s32 NativeToOrbisSignal(s32 s) {
|
||||
return POSIX_SIGUSR1;
|
||||
case SIGUSR2:
|
||||
return POSIX_SIGUSR2;
|
||||
case _SIGEMT:
|
||||
return POSIX_SIGEMT;
|
||||
case _SIGINFO:
|
||||
return POSIX_SIGINFO;
|
||||
case 0:
|
||||
return 128;
|
||||
default:
|
||||
if (s > 0 && s < 128) {
|
||||
return s;
|
||||
}
|
||||
UNREACHABLE_MSG("Unknown signal {}", s);
|
||||
}
|
||||
}
|
||||
|
||||
static s32 OrbisToNativeSignal(s32 s) {
|
||||
s32 OrbisToNativeSignal(s32 s) {
|
||||
switch (s) {
|
||||
case POSIX_SIGHUP:
|
||||
return SIGHUP;
|
||||
@ -108,6 +120,8 @@ static s32 OrbisToNativeSignal(s32 s) {
|
||||
return SIGTRAP;
|
||||
case POSIX_SIGABRT:
|
||||
return SIGABRT;
|
||||
case POSIX_SIGEMT:
|
||||
return _SIGEMT;
|
||||
case POSIX_SIGFPE:
|
||||
return SIGFPE;
|
||||
case POSIX_SIGKILL:
|
||||
@ -150,22 +164,33 @@ static s32 OrbisToNativeSignal(s32 s) {
|
||||
return SIGPROF;
|
||||
case POSIX_SIGWINCH:
|
||||
return SIGWINCH;
|
||||
case POSIX_SIGINFO:
|
||||
return _SIGINFO;
|
||||
case POSIX_SIGUSR1:
|
||||
return SIGUSR1;
|
||||
case POSIX_SIGUSR2:
|
||||
return SIGUSR2;
|
||||
case 128:
|
||||
return 0;
|
||||
default:
|
||||
if (s > 0 && s < 128) {
|
||||
return s;
|
||||
}
|
||||
UNREACHABLE_MSG("Unknown signal {}", s);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
std::array<SceKernelExceptionHandler, 32> Handlers{};
|
||||
#ifdef __APPLE__
|
||||
#define sigisemptyset(x) (*(x) == 0)
|
||||
#endif
|
||||
|
||||
std::array<OrbisKernelExceptionHandler, 130> Handlers{};
|
||||
|
||||
#ifndef _WIN64
|
||||
void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context) {
|
||||
const auto handler = Handlers[native_signum];
|
||||
const auto handler = Handlers[NativeToOrbisSignal(native_signum)];
|
||||
if (handler) {
|
||||
auto ctx = Ucontext{};
|
||||
#ifdef __APPLE__
|
||||
@ -214,6 +239,8 @@ void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context
|
||||
ctx.uc_mcontext.mc_addr = reinterpret_cast<uint64_t>(inf->si_addr);
|
||||
#endif
|
||||
handler(NativeToOrbisSignal(native_signum), &ctx);
|
||||
} else {
|
||||
UNREACHABLE_MSG("Unhandled exception");
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -221,7 +248,7 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
|
||||
const char* thrName = (char*)arg1;
|
||||
int native_signum = reinterpret_cast<uintptr_t>(arg2);
|
||||
LOG_INFO(Lib_Kernel, "Exception raised successfully on thread '{}'", thrName);
|
||||
const auto handler = Handlers[native_signum];
|
||||
const auto handler = Handlers[NativeToOrbisSignal(native_signum)];
|
||||
if (handler) {
|
||||
auto ctx = Ucontext{};
|
||||
ctx.uc_mcontext.mc_r8 = context->R8;
|
||||
@ -243,76 +270,105 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
|
||||
ctx.uc_mcontext.mc_fs = context->SegFs;
|
||||
ctx.uc_mcontext.mc_gs = context->SegGs;
|
||||
handler(NativeToOrbisSignal(native_signum), &ctx);
|
||||
} else {
|
||||
UNREACHABLE_MSG("Unhandled exception");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelExceptionHandler handler) {
|
||||
if (signum > POSIX_SIGUSR2) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) {
|
||||
s->bits[0] = 0;
|
||||
s->bits[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PS4_SYSV_ABI posix_sigisemptyset(Sigset* s) {
|
||||
return s->bits[0] == 0 && s->bits[1] == 0;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI posix_sigaction(s32 sig, Sigaction* act, Sigaction* oact) {
|
||||
if (sig < 1 || sig > 128 || sig == POSIX_SIGTHR || sig == POSIX_SIGKILL ||
|
||||
sig == POSIX_SIGSTOP) {
|
||||
*__Error() = POSIX_EINVAL;
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
LOG_ERROR(Lib_Kernel, "(STUBBED) called, sig: {}", sig);
|
||||
Handlers[sig] = reinterpret_cast<OrbisKernelExceptionHandler>(
|
||||
act ? act->__sigaction_handler.sigaction : nullptr);
|
||||
#else
|
||||
s32 native_sig = OrbisToNativeSignal(sig);
|
||||
if (native_sig == SIGVTALRM) {
|
||||
LOG_ERROR(Lib_Kernel, "Guest is attempting to use the HLE-reserved signal {}!", sig);
|
||||
*__Error() = POSIX_EINVAL;
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
if (native_sig >= __SIGRTMIN && native_sig < SIGRTMIN) {
|
||||
LOG_ERROR(Lib_Kernel, "Guest is attempting to use the HLE libc-reserved signal {}!", sig);
|
||||
*__Error() = POSIX_EINVAL;
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#else
|
||||
if (native_sig > SIGUSR2) {
|
||||
LOG_ERROR(Lib_Kernel,
|
||||
"Guest is attempting to use SIGRT signals, which aren't available on this "
|
||||
"platform (signal: {})!",
|
||||
sig);
|
||||
}
|
||||
LOG_INFO(Lib_Kernel, "Installing signal handler for {}", signum);
|
||||
int const native_signum = OrbisToNativeSignal(signum);
|
||||
#ifdef __APPLE__
|
||||
ASSERT_MSG(native_signum != SIGVTALRM, "SIGVTALRM is HLE-reserved on macOS!");
|
||||
#endif
|
||||
ASSERT_MSG(!Handlers[native_signum], "Invalid parameters");
|
||||
Handlers[native_signum] = handler;
|
||||
#ifndef _WIN64
|
||||
if (native_signum == SIGSEGV || native_signum == SIGBUS || native_signum == SIGILL) {
|
||||
LOG_INFO(Lib_Kernel, "called, sig: {}, native sig: {}", sig, native_sig);
|
||||
struct sigaction native_act{};
|
||||
if (act) {
|
||||
native_act.sa_flags = act->sa_flags; // todo check compatibility, on Linux it seems fine
|
||||
native_act.sa_sigaction =
|
||||
reinterpret_cast<decltype(native_act.sa_sigaction)>(SigactionHandler);
|
||||
if (!posix_sigisemptyset(&act->sa_mask)) {
|
||||
LOG_ERROR(Lib_Kernel, "Unhandled sa_mask: {:x}", act->sa_mask.bits[0]);
|
||||
}
|
||||
}
|
||||
auto const prev_handler = Handlers[sig];
|
||||
Handlers[sig] = reinterpret_cast<OrbisKernelExceptionHandler>(
|
||||
act ? act->__sigaction_handler.sigaction : nullptr);
|
||||
|
||||
if (native_sig == SIGSEGV || native_sig == SIGBUS || native_sig == SIGILL) {
|
||||
return ORBIS_OK; // These are handled in Core::SignalHandler
|
||||
}
|
||||
struct sigaction act = {};
|
||||
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
act.sa_sigaction = reinterpret_cast<decltype(act.sa_sigaction)>(SigactionHandler);
|
||||
sigemptyset(&act.sa_mask);
|
||||
sigaction(native_signum, &act, nullptr);
|
||||
#endif
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
|
||||
if (signum > POSIX_SIGUSR2) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
if (native_sig > 127) {
|
||||
LOG_WARNING(Lib_Kernel, "We can't install a handler for native signal {}!", native_sig);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
int const native_signum = OrbisToNativeSignal(signum);
|
||||
if (!Handlers[native_signum]) {
|
||||
LOG_WARNING(Lib_Kernel, "removing non-installed handler for signum {}", signum);
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
struct sigaction native_oact{};
|
||||
s32 ret = sigaction(native_sig, act ? &native_act : nullptr, oact ? &native_oact : nullptr);
|
||||
if (oact) {
|
||||
oact->sa_flags = native_oact.sa_flags;
|
||||
oact->__sigaction_handler.sigaction =
|
||||
reinterpret_cast<decltype(oact->__sigaction_handler.sigaction)>(prev_handler);
|
||||
if (!sigisemptyset(&native_oact.sa_mask)) {
|
||||
LOG_ERROR(Lib_Kernel, "Unhandled sa_mask");
|
||||
}
|
||||
}
|
||||
Handlers[native_signum] = nullptr;
|
||||
#ifndef _WIN64
|
||||
if (native_signum == SIGSEGV || native_signum == SIGBUS || native_signum == SIGILL) {
|
||||
struct sigaction action{};
|
||||
action.sa_sigaction = Core::SignalHandler;
|
||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
sigemptyset(&action.sa_mask);
|
||||
|
||||
ASSERT_MSG(sigaction(native_signum, &action, nullptr) == 0,
|
||||
"Failed to reinstate original signal handler for signal {}", native_signum);
|
||||
} else {
|
||||
struct sigaction act = {};
|
||||
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
act.sa_sigaction = nullptr;
|
||||
sigemptyset(&act.sa_mask);
|
||||
sigaction(native_signum, &act, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Lib_Kernel, "sigaction failed: {}", strerror(errno));
|
||||
*__Error() = ErrnoToSceKernelError(errno);
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#endif
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
||||
if (signum != POSIX_SIGUSR1) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) {
|
||||
if (sig < 1 || sig > 128) { // off-by-one error?
|
||||
return POSIX_EINVAL;
|
||||
}
|
||||
LOG_WARNING(Lib_Kernel, "Raising exception on thread '{}'", thread->name);
|
||||
int const native_signum = OrbisToNativeSignal(signum);
|
||||
LOG_WARNING(Lib_Kernel, "Raising signal {} on thread '{}'", sig, thread->name);
|
||||
int const native_signum = OrbisToNativeSignal(sig);
|
||||
#ifndef _WIN64
|
||||
const auto pthr = reinterpret_cast<pthread_t>(thread->native_thr.GetHandle());
|
||||
const auto ret = pthread_kill(pthr, native_signum);
|
||||
if (ret != 0) {
|
||||
LOG_ERROR(Kernel, "Failed to send exception signal to thread '{}': {}", thread->name,
|
||||
strerror(ret));
|
||||
strerror(errno));
|
||||
}
|
||||
#else
|
||||
USER_APC_OPTION option;
|
||||
@ -326,6 +382,67 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// libkernel has a check in sceKernelInstallExceptionHandler and sceKernelRemoveExceptionHandler for
|
||||
// validating if the application requested a handler for an allowed signal or not. However, that is
|
||||
// just a wrapper for sigaction, which itself does not have any such restrictions, and therefore
|
||||
// this check is ridiculously trivial to go around. This, however, means that we need to support all
|
||||
// 127 - 3 possible signals, even if realistically, only homebrew will use most of them.
|
||||
static std::unordered_set<s32> orbis_allowed_signals{
|
||||
POSIX_SIGHUP, POSIX_SIGILL, POSIX_SIGFPE, POSIX_SIGBUS, POSIX_SIGSEGV, POSIX_SIGUSR1,
|
||||
};
|
||||
|
||||
int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, OrbisKernelExceptionHandler handler) {
|
||||
if (!orbis_allowed_signals.contains(signum)) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (Handlers[signum] != nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EAGAIN;
|
||||
}
|
||||
LOG_INFO(Lib_Kernel, "Installing signal handler for {}", signum);
|
||||
Sigaction act = {};
|
||||
act.sa_flags = POSIX_SA_SIGINFO | POSIX_SA_RESTART;
|
||||
act.__sigaction_handler.sigaction =
|
||||
reinterpret_cast<decltype(act.__sigaction_handler.sigaction)>(handler);
|
||||
posix_sigemptyset(&act.sa_mask);
|
||||
s32 ret = posix_sigaction(signum, &act, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Lib_Kernel, "Failed to add handler for signal {}: {}", signum,
|
||||
strerror(*__Error()));
|
||||
return ErrnoToSceKernelError(*__Error());
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
|
||||
if (!orbis_allowed_signals.contains(signum)) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int const native_signum = OrbisToNativeSignal(signum);
|
||||
Handlers[signum] = nullptr;
|
||||
Sigaction act = {};
|
||||
act.sa_flags = POSIX_SA_SIGINFO;
|
||||
act.__sigaction_handler.sigaction = nullptr;
|
||||
posix_sigemptyset(&act.sa_mask);
|
||||
s32 ret = posix_sigaction(signum, &act, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Lib_Kernel, "Failed to remove handler for signal {}: {}", signum,
|
||||
strerror(*__Error()));
|
||||
return ErrnoToSceKernelError(*__Error());
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
||||
if (signum != POSIX_SIGUSR1) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
s32 ret = posix_pthread_kill(thread, signum);
|
||||
if (ret < 0) {
|
||||
return ErrnoToSceKernelError(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
|
||||
if (unk != 0) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
@ -352,6 +469,13 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
|
||||
sceKernelDebugRaiseExceptionOnReleaseMode);
|
||||
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel", 1, "libkernel", sceKernelInstallExceptionHandler);
|
||||
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler);
|
||||
|
||||
LIB_FUNCTION("KiJEPEWRyUY", "libkernel", 1, "libkernel", posix_sigaction);
|
||||
LIB_FUNCTION("+F7C-hdk7+E", "libkernel", 1, "libkernel", posix_sigemptyset);
|
||||
LIB_FUNCTION("yH-uQW3LbX0", "libkernel", 1, "libkernel", posix_pthread_kill);
|
||||
LIB_FUNCTION("KiJEPEWRyUY", "libScePosix", 1, "libkernel", posix_sigaction);
|
||||
LIB_FUNCTION("+F7C-hdk7+E", "libScePosix", 1, "libkernel", posix_sigemptyset);
|
||||
LIB_FUNCTION("yH-uQW3LbX0", "libScePosix", 1, "libkernel", posix_pthread_kill);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
@ -11,7 +11,7 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
using SceKernelExceptionHandler = PS4_SYSV_ABI void (*)(int, void*);
|
||||
using OrbisKernelExceptionHandler = PS4_SYSV_ABI void (*)(int, void*);
|
||||
|
||||
constexpr s32 POSIX_SIGHUP = 1;
|
||||
constexpr s32 POSIX_SIGINT = 2;
|
||||
@ -47,6 +47,23 @@ constexpr s32 POSIX_SIGUSR2 = 31;
|
||||
constexpr s32 POSIX_SIGTHR = 32;
|
||||
constexpr s32 POSIX_SIGLIBRT = 33;
|
||||
|
||||
#ifdef __linux__
|
||||
constexpr s32 _SIGEMT = 128;
|
||||
constexpr s32 _SIGINFO = 129;
|
||||
#elif !defined(_WIN32)
|
||||
constexpr s32 _SIGEMT = SIGEMT;
|
||||
constexpr s32 _SIGINFO = SIGINFO;
|
||||
#endif
|
||||
|
||||
constexpr s32 POSIX_SA_NOCLDSTOP = 1;
|
||||
constexpr s32 POSIX_SA_NOCLDWAIT = 2;
|
||||
constexpr s32 POSIX_SA_SIGINFO = 4;
|
||||
constexpr s32 POSIX_SA_ONSTACK = 0x08000000;
|
||||
constexpr s32 POSIX_SA_RESTART = 0x10000000;
|
||||
constexpr s32 POSIX_SA_NODEFER = 0x40000000;
|
||||
constexpr s32 POSIX_SA_RESETHAND = 0x80000000;
|
||||
constexpr s32 POSIX_SA_RESTORER = 0x04000000;
|
||||
|
||||
struct Mcontext {
|
||||
u64 mc_onstack;
|
||||
u64 mc_rdi;
|
||||
@ -101,17 +118,74 @@ struct Sigset {
|
||||
u64 bits[2];
|
||||
};
|
||||
|
||||
union Sigval {
|
||||
/* Members as suggested by Annex C of POSIX 1003.1b. */
|
||||
int sival_int;
|
||||
void* sival_ptr;
|
||||
/* 6.0 compatibility */
|
||||
int sigval_int;
|
||||
void* sigval_ptr;
|
||||
};
|
||||
|
||||
struct Siginfo {
|
||||
int _si_signo; /* signal number */
|
||||
int _si_errno; /* errno association */
|
||||
/*
|
||||
* Cause of signal, one of the SI_ macros or signal-specific
|
||||
* values, i.e. one of the FPE_... values for SIGFPE. This
|
||||
* value is equivalent to the second argument to an old-style
|
||||
* FreeBSD signal handler.
|
||||
*/
|
||||
int _si_code; /* signal code */
|
||||
s32 _si_pid; /* sending process */
|
||||
u32 _si_uid; /* sender's ruid */
|
||||
int _si_status; /* exit value */
|
||||
void* _si_addr; /* faulting instruction */
|
||||
union Sigval _si_value; /* signal value */
|
||||
union {
|
||||
struct {
|
||||
int _trapno; /* machine specific trap code */
|
||||
} _fault;
|
||||
struct {
|
||||
int _timerid;
|
||||
int _overrun;
|
||||
} _timer;
|
||||
struct {
|
||||
int _mqd;
|
||||
} _mesgq;
|
||||
struct {
|
||||
long _band; /* band event for SIGPOLL */
|
||||
} _poll; /* was this ever used ? */
|
||||
struct {
|
||||
long __spare1__;
|
||||
int __spare2__[7];
|
||||
} __spare__;
|
||||
} _reason;
|
||||
};
|
||||
|
||||
struct Sigaction {
|
||||
union {
|
||||
void (*handler)(int);
|
||||
void (*sigaction)(int, struct Siginfo*, void*);
|
||||
} __sigaction_handler;
|
||||
int sa_flags;
|
||||
Sigset sa_mask;
|
||||
};
|
||||
|
||||
struct Ucontext {
|
||||
struct Sigset uc_sigmask;
|
||||
int field1_0x10[12];
|
||||
struct Mcontext uc_mcontext;
|
||||
struct Ucontext* uc_link;
|
||||
struct ExStack uc_stack;
|
||||
Mcontext uc_mcontext;
|
||||
Ucontext* uc_link;
|
||||
ExStack uc_stack;
|
||||
int uc_flags;
|
||||
int __spare[4];
|
||||
int field7_0x4f4[3];
|
||||
};
|
||||
|
||||
s32 NativeToOrbisSignal(s32 s);
|
||||
s32 OrbisToNativeSignal(s32 s);
|
||||
|
||||
void RegisterException(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
@ -665,6 +665,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", posix_pthread_once);
|
||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", posix_pthread_self);
|
||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", posix_pthread_create);
|
||||
LIB_FUNCTION("Jmi+9w9u0E4", "libkernel", 1, "libkernel", posix_pthread_create_name_np);
|
||||
LIB_FUNCTION("lZzFeSxPl08", "libkernel", 1, "libkernel", posix_pthread_setcancelstate);
|
||||
LIB_FUNCTION("CBNtXOoef-E", "libkernel", 1, "libkernel", posix_sched_get_priority_max);
|
||||
LIB_FUNCTION("m0iS6jNsXds", "libkernel", 1, "libkernel", posix_sched_get_priority_min);
|
||||
|
||||
@ -22,6 +22,10 @@
|
||||
#include "core/tls.h"
|
||||
#include "ipc/ipc.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
|
||||
static PS4_SYSV_ABI void ProgramExitFunc() {
|
||||
@ -107,6 +111,11 @@ void Linker::Execute(const std::vector<std::string>& args) {
|
||||
|
||||
main_thread.Run([this, module, &args](std::stop_token) {
|
||||
Common::SetCurrentThreadName("Game:Main");
|
||||
#ifndef _WIN32 // Clear any existing signal mask for game threads.
|
||||
sigset_t emptyset;
|
||||
sigemptyset(&emptyset);
|
||||
pthread_sigmask(SIG_SETMASK, &emptyset, nullptr);
|
||||
#endif
|
||||
if (auto& ipc = IPC::Instance()) {
|
||||
ipc.WaitForStart();
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
#ifndef _WIN32
|
||||
namespace Libraries::Kernel {
|
||||
void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context);
|
||||
extern std::array<SceKernelExceptionHandler, 32> Handlers;
|
||||
extern std::array<OrbisKernelExceptionHandler, 32> Handlers;
|
||||
} // namespace Libraries::Kernel
|
||||
#endif
|
||||
|
||||
@ -86,7 +86,7 @@ void SignalHandler(int sig, siginfo_t* info, void* raw_context) {
|
||||
if (!signals->DispatchAccessViolation(raw_context, info->si_addr)) {
|
||||
// If the guest has installed a custom signal handler, and the access violation didn't
|
||||
// come from HLE memory tracking, pass the signal on
|
||||
if (Libraries::Kernel::Handlers[sig]) {
|
||||
if (Libraries::Kernel::Handlers[Libraries::Kernel::NativeToOrbisSignal(sig)]) {
|
||||
Libraries::Kernel::SigactionHandler(sig, info,
|
||||
reinterpret_cast<ucontext_t*>(raw_context));
|
||||
return;
|
||||
@ -99,7 +99,7 @@ void SignalHandler(int sig, siginfo_t* info, void* raw_context) {
|
||||
}
|
||||
case SIGILL:
|
||||
if (!signals->DispatchIllegalInstruction(raw_context)) {
|
||||
if (Libraries::Kernel::Handlers[sig]) {
|
||||
if (Libraries::Kernel::Handlers[Libraries::Kernel::NativeToOrbisSignal(sig)]) {
|
||||
Libraries::Kernel::SigactionHandler(sig, info,
|
||||
reinterpret_cast<ucontext_t*>(raw_context));
|
||||
return;
|
||||
|
||||
@ -10,10 +10,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SIGSLEEP -1
|
||||
#elif defined(__APPLE__)
|
||||
#define SIGSLEEP SIGVTALRM
|
||||
#else
|
||||
#define SIGSLEEP SIGRTMAX
|
||||
#define SIGSLEEP SIGVTALRM
|
||||
#endif
|
||||
namespace Core {
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user