mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-01 12:15:43 -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];
|
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||||
const auto status =
|
const auto status =
|
||||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||||
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
|
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}",
|
||||||
[[unlikely]] {
|
reinterpret_cast<u64>(code_address),
|
||||||
UNREACHABLE_MSG("ud2 at code address {:#x}", reinterpret_cast<u64>(code_address));
|
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||||
}
|
: "Failed to decode");
|
||||||
UNREACHABLE_MSG("Failed to patch address {:x} -- mnemonic: {}",
|
return false;
|
||||||
reinterpret_cast<u64>(code_address),
|
|
||||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
|
||||||
: "Failed to decode");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "core/libraries/kernel/kernel.h"
|
||||||
#include "core/libraries/kernel/orbis_error.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/exception.h"
|
||||||
#include "core/libraries/kernel/threads/pthread.h"
|
#include "core/libraries/kernel/threads/pthread.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
@ -13,23 +15,24 @@
|
|||||||
#else
|
#else
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#endif
|
#endif
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
// Windows doesn't have native versions of these, and we don't need to use them either.
|
// 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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 OrbisToNativeSignal(s32 s) {
|
s32 OrbisToNativeSignal(s32 s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static s32 NativeToOrbisSignal(s32 s) {
|
s32 NativeToOrbisSignal(s32 s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
return POSIX_SIGHUP;
|
return POSIX_SIGHUP;
|
||||||
@ -89,12 +92,21 @@ static s32 NativeToOrbisSignal(s32 s) {
|
|||||||
return POSIX_SIGUSR1;
|
return POSIX_SIGUSR1;
|
||||||
case SIGUSR2:
|
case SIGUSR2:
|
||||||
return POSIX_SIGUSR2;
|
return POSIX_SIGUSR2;
|
||||||
|
case _SIGEMT:
|
||||||
|
return POSIX_SIGEMT;
|
||||||
|
case _SIGINFO:
|
||||||
|
return POSIX_SIGINFO;
|
||||||
|
case 0:
|
||||||
|
return 128;
|
||||||
default:
|
default:
|
||||||
|
if (s > 0 && s < 128) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
UNREACHABLE_MSG("Unknown signal {}", s);
|
UNREACHABLE_MSG("Unknown signal {}", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 OrbisToNativeSignal(s32 s) {
|
s32 OrbisToNativeSignal(s32 s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case POSIX_SIGHUP:
|
case POSIX_SIGHUP:
|
||||||
return SIGHUP;
|
return SIGHUP;
|
||||||
@ -108,6 +120,8 @@ static s32 OrbisToNativeSignal(s32 s) {
|
|||||||
return SIGTRAP;
|
return SIGTRAP;
|
||||||
case POSIX_SIGABRT:
|
case POSIX_SIGABRT:
|
||||||
return SIGABRT;
|
return SIGABRT;
|
||||||
|
case POSIX_SIGEMT:
|
||||||
|
return _SIGEMT;
|
||||||
case POSIX_SIGFPE:
|
case POSIX_SIGFPE:
|
||||||
return SIGFPE;
|
return SIGFPE;
|
||||||
case POSIX_SIGKILL:
|
case POSIX_SIGKILL:
|
||||||
@ -150,22 +164,33 @@ static s32 OrbisToNativeSignal(s32 s) {
|
|||||||
return SIGPROF;
|
return SIGPROF;
|
||||||
case POSIX_SIGWINCH:
|
case POSIX_SIGWINCH:
|
||||||
return SIGWINCH;
|
return SIGWINCH;
|
||||||
|
case POSIX_SIGINFO:
|
||||||
|
return _SIGINFO;
|
||||||
case POSIX_SIGUSR1:
|
case POSIX_SIGUSR1:
|
||||||
return SIGUSR1;
|
return SIGUSR1;
|
||||||
case POSIX_SIGUSR2:
|
case POSIX_SIGUSR2:
|
||||||
return SIGUSR2;
|
return SIGUSR2;
|
||||||
|
case 128:
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
|
if (s > 0 && s < 128) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
UNREACHABLE_MSG("Unknown signal {}", s);
|
UNREACHABLE_MSG("Unknown signal {}", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::array<SceKernelExceptionHandler, 32> Handlers{};
|
#ifdef __APPLE__
|
||||||
|
#define sigisemptyset(x) (*(x) == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::array<OrbisKernelExceptionHandler, 130> Handlers{};
|
||||||
|
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context) {
|
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) {
|
if (handler) {
|
||||||
auto ctx = Ucontext{};
|
auto ctx = Ucontext{};
|
||||||
#ifdef __APPLE__
|
#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);
|
ctx.uc_mcontext.mc_addr = reinterpret_cast<uint64_t>(inf->si_addr);
|
||||||
#endif
|
#endif
|
||||||
handler(NativeToOrbisSignal(native_signum), &ctx);
|
handler(NativeToOrbisSignal(native_signum), &ctx);
|
||||||
|
} else {
|
||||||
|
UNREACHABLE_MSG("Unhandled exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -221,7 +248,7 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
|
|||||||
const char* thrName = (char*)arg1;
|
const char* thrName = (char*)arg1;
|
||||||
int native_signum = reinterpret_cast<uintptr_t>(arg2);
|
int native_signum = reinterpret_cast<uintptr_t>(arg2);
|
||||||
LOG_INFO(Lib_Kernel, "Exception raised successfully on thread '{}'", thrName);
|
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) {
|
if (handler) {
|
||||||
auto ctx = Ucontext{};
|
auto ctx = Ucontext{};
|
||||||
ctx.uc_mcontext.mc_r8 = context->R8;
|
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_fs = context->SegFs;
|
||||||
ctx.uc_mcontext.mc_gs = context->SegGs;
|
ctx.uc_mcontext.mc_gs = context->SegGs;
|
||||||
handler(NativeToOrbisSignal(native_signum), &ctx);
|
handler(NativeToOrbisSignal(native_signum), &ctx);
|
||||||
|
} else {
|
||||||
|
UNREACHABLE_MSG("Unhandled exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelExceptionHandler handler) {
|
s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) {
|
||||||
if (signum > POSIX_SIGUSR2) {
|
s->bits[0] = 0;
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
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
|
#endif
|
||||||
ASSERT_MSG(!Handlers[native_signum], "Invalid parameters");
|
LOG_INFO(Lib_Kernel, "called, sig: {}, native sig: {}", sig, native_sig);
|
||||||
Handlers[native_signum] = handler;
|
struct sigaction native_act{};
|
||||||
#ifndef _WIN64
|
if (act) {
|
||||||
if (native_signum == SIGSEGV || native_signum == SIGBUS || native_signum == SIGILL) {
|
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
|
return ORBIS_OK; // These are handled in Core::SignalHandler
|
||||||
}
|
}
|
||||||
struct sigaction act = {};
|
if (native_sig > 127) {
|
||||||
act.sa_flags = SA_SIGINFO | SA_RESTART;
|
LOG_WARNING(Lib_Kernel, "We can't install a handler for native signal {}!", native_sig);
|
||||||
act.sa_sigaction = reinterpret_cast<decltype(act.sa_sigaction)>(SigactionHandler);
|
return ORBIS_OK;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
int const native_signum = OrbisToNativeSignal(signum);
|
struct sigaction native_oact{};
|
||||||
if (!Handlers[native_signum]) {
|
s32 ret = sigaction(native_sig, act ? &native_act : nullptr, oact ? &native_oact : nullptr);
|
||||||
LOG_WARNING(Lib_Kernel, "removing non-installed handler for signum {}", signum);
|
if (oact) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
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;
|
if (ret < 0) {
|
||||||
#ifndef _WIN64
|
LOG_ERROR(Lib_Kernel, "sigaction failed: {}", strerror(errno));
|
||||||
if (native_signum == SIGSEGV || native_signum == SIGBUS || native_signum == SIGILL) {
|
*__Error() = ErrnoToSceKernelError(errno);
|
||||||
struct sigaction action{};
|
return ORBIS_FAIL;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) {
|
||||||
if (signum != POSIX_SIGUSR1) {
|
if (sig < 1 || sig > 128) { // off-by-one error?
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return POSIX_EINVAL;
|
||||||
}
|
}
|
||||||
LOG_WARNING(Lib_Kernel, "Raising exception on thread '{}'", thread->name);
|
LOG_WARNING(Lib_Kernel, "Raising signal {} on thread '{}'", sig, thread->name);
|
||||||
int const native_signum = OrbisToNativeSignal(signum);
|
int const native_signum = OrbisToNativeSignal(sig);
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
const auto pthr = reinterpret_cast<pthread_t>(thread->native_thr.GetHandle());
|
const auto pthr = reinterpret_cast<pthread_t>(thread->native_thr.GetHandle());
|
||||||
const auto ret = pthread_kill(pthr, native_signum);
|
const auto ret = pthread_kill(pthr, native_signum);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
LOG_ERROR(Kernel, "Failed to send exception signal to thread '{}': {}", thread->name,
|
LOG_ERROR(Kernel, "Failed to send exception signal to thread '{}': {}", thread->name,
|
||||||
strerror(ret));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
USER_APC_OPTION option;
|
USER_APC_OPTION option;
|
||||||
@ -326,6 +382,67 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
|||||||
return ORBIS_OK;
|
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) {
|
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
|
||||||
if (unk != 0) {
|
if (unk != 0) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
@ -352,6 +469,13 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
|
|||||||
sceKernelDebugRaiseExceptionOnReleaseMode);
|
sceKernelDebugRaiseExceptionOnReleaseMode);
|
||||||
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel", 1, "libkernel", sceKernelInstallExceptionHandler);
|
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel", 1, "libkernel", sceKernelInstallExceptionHandler);
|
||||||
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler);
|
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
|
} // namespace Libraries::Kernel
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::Kernel {
|
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_SIGHUP = 1;
|
||||||
constexpr s32 POSIX_SIGINT = 2;
|
constexpr s32 POSIX_SIGINT = 2;
|
||||||
@ -47,6 +47,23 @@ constexpr s32 POSIX_SIGUSR2 = 31;
|
|||||||
constexpr s32 POSIX_SIGTHR = 32;
|
constexpr s32 POSIX_SIGTHR = 32;
|
||||||
constexpr s32 POSIX_SIGLIBRT = 33;
|
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 {
|
struct Mcontext {
|
||||||
u64 mc_onstack;
|
u64 mc_onstack;
|
||||||
u64 mc_rdi;
|
u64 mc_rdi;
|
||||||
@ -101,17 +118,74 @@ struct Sigset {
|
|||||||
u64 bits[2];
|
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 Ucontext {
|
||||||
struct Sigset uc_sigmask;
|
struct Sigset uc_sigmask;
|
||||||
int field1_0x10[12];
|
int field1_0x10[12];
|
||||||
struct Mcontext uc_mcontext;
|
Mcontext uc_mcontext;
|
||||||
struct Ucontext* uc_link;
|
Ucontext* uc_link;
|
||||||
struct ExStack uc_stack;
|
ExStack uc_stack;
|
||||||
int uc_flags;
|
int uc_flags;
|
||||||
int __spare[4];
|
int __spare[4];
|
||||||
int field7_0x4f4[3];
|
int field7_0x4f4[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
s32 NativeToOrbisSignal(s32 s);
|
||||||
|
s32 OrbisToNativeSignal(s32 s);
|
||||||
|
|
||||||
void RegisterException(Core::Loader::SymbolsResolver* sym);
|
void RegisterException(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|||||||
@ -665,6 +665,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", posix_pthread_once);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", posix_pthread_self);
|
||||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", posix_pthread_create);
|
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("lZzFeSxPl08", "libkernel", 1, "libkernel", posix_pthread_setcancelstate);
|
||||||
LIB_FUNCTION("CBNtXOoef-E", "libkernel", 1, "libkernel", posix_sched_get_priority_max);
|
LIB_FUNCTION("CBNtXOoef-E", "libkernel", 1, "libkernel", posix_sched_get_priority_max);
|
||||||
LIB_FUNCTION("m0iS6jNsXds", "libkernel", 1, "libkernel", posix_sched_get_priority_min);
|
LIB_FUNCTION("m0iS6jNsXds", "libkernel", 1, "libkernel", posix_sched_get_priority_min);
|
||||||
|
|||||||
@ -22,6 +22,10 @@
|
|||||||
#include "core/tls.h"
|
#include "core/tls.h"
|
||||||
#include "ipc/ipc.h"
|
#include "ipc/ipc.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
static PS4_SYSV_ABI void ProgramExitFunc() {
|
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) {
|
main_thread.Run([this, module, &args](std::stop_token) {
|
||||||
Common::SetCurrentThreadName("Game:Main");
|
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()) {
|
if (auto& ipc = IPC::Instance()) {
|
||||||
ipc.WaitForStart();
|
ipc.WaitForStart();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context);
|
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
|
} // namespace Libraries::Kernel
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ void SignalHandler(int sig, siginfo_t* info, void* raw_context) {
|
|||||||
if (!signals->DispatchAccessViolation(raw_context, info->si_addr)) {
|
if (!signals->DispatchAccessViolation(raw_context, info->si_addr)) {
|
||||||
// If the guest has installed a custom signal handler, and the access violation didn't
|
// If the guest has installed a custom signal handler, and the access violation didn't
|
||||||
// come from HLE memory tracking, pass the signal on
|
// 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,
|
Libraries::Kernel::SigactionHandler(sig, info,
|
||||||
reinterpret_cast<ucontext_t*>(raw_context));
|
reinterpret_cast<ucontext_t*>(raw_context));
|
||||||
return;
|
return;
|
||||||
@ -99,7 +99,7 @@ void SignalHandler(int sig, siginfo_t* info, void* raw_context) {
|
|||||||
}
|
}
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
if (!signals->DispatchIllegalInstruction(raw_context)) {
|
if (!signals->DispatchIllegalInstruction(raw_context)) {
|
||||||
if (Libraries::Kernel::Handlers[sig]) {
|
if (Libraries::Kernel::Handlers[Libraries::Kernel::NativeToOrbisSignal(sig)]) {
|
||||||
Libraries::Kernel::SigactionHandler(sig, info,
|
Libraries::Kernel::SigactionHandler(sig, info,
|
||||||
reinterpret_cast<ucontext_t*>(raw_context));
|
reinterpret_cast<ucontext_t*>(raw_context));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -10,10 +10,8 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define SIGSLEEP -1
|
#define SIGSLEEP -1
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#define SIGSLEEP SIGVTALRM
|
|
||||||
#else
|
#else
|
||||||
#define SIGSLEEP SIGRTMAX
|
#define SIGSLEEP SIGVTALRM
|
||||||
#endif
|
#endif
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user