From 86a64fb980df612cb91b65aec705059828c2ac12 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Mon, 25 May 2026 02:27:55 -0500 Subject: [PATCH] Lib.Kernel: Various (mostly signal-related) fixes (#4463) * sigaddset, sigdelset, sigismember * Some define fixups Based on decomp, PS4 sigset is defined as a u32[4]. This doesn't change any behavior, but makes my decomp-based sigaddset and sigdelset implementations function appropriately. Additionally, define handler and sigaction functions as PS4_SYSV_ABI. * Fix returns * Implement signal, export _sigintr In libkernel, signal just uses sigaction. No harm in implementing it, since we've got our own implementations for everything except sigaction (and sigaction is implemented for Unix platforms). * Fix and cleanup posix_select defines Swaps use of defines for just having static functions, and fixes the pd_set_posix struct to match FreeBSD/Orbis properly (sizeof(long) == 4 on Windows, which does not match Orbis). * Fix siginfo struct Again, sizeof(long) differs on different platforms. Need to use our proper typedef to ensure accuracy. * Clang, the bane of my existance. * Oops --- src/core/libraries/kernel/file_system.cpp | 25 +++---- .../libraries/kernel/threads/exception.cpp | 66 ++++++++++++++++++- src/core/libraries/kernel/threads/exception.h | 32 ++++----- 3 files changed, 93 insertions(+), 30 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 7ee076636..1336973f7 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -1223,25 +1223,26 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) { } #ifdef _WIN32 -#define __FD_SETSIZE 1024 typedef struct { - unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(unsigned long))]; + u64 fds_bits[16]; } fd_set_posix; -#define FD_SET_POSIX(fd, set) \ - ((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] |= \ - (1UL << ((fd) % (8 * sizeof(unsigned long))))) +static void FD_SET_POSIX(s32 fd, fd_set_posix* set) { + set->fds_bits[fd / (8 * sizeof(u64))] |= (1ULL << (fd % (8 * sizeof(u64)))); +} -#define FD_CLR_POSIX(fd, set) \ - ((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] &= \ - ~(1UL << ((fd) % (8 * sizeof(unsigned long))))) +static void FD_CLR_POSIX(s32 fd, fd_set_posix* set) { + set->fds_bits[fd / (8 * sizeof(u64))] &= ~(1ULL << (fd % (8 * sizeof(u64)))); +} -#define FD_ISSET_POSIX(fd, set) \ - (((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] & \ - (1UL << ((fd) % (8 * sizeof(unsigned long))))) != 0) +static bool FD_ISSET_POSIX(s32 fd, fd_set_posix* set) { + return (set->fds_bits[fd / (8 * sizeof(u64))] & (1ULL << (fd % (8 * sizeof(u64))))) != 0; +} -#define FD_ZERO_POSIX(set) memset((set), 0, sizeof(fd_set_posix)) +static void FD_ZERO_POSIX(fd_set_posix* set) { + std::memset(set, 0, sizeof(fd_set_posix)); +} s32 PS4_SYSV_ABI posix_select(s32 nfds, fd_set_posix* readfds, fd_set_posix* writefds, fd_set_posix* exceptfds, OrbisKernelTimeval* timeout) { diff --git a/src/core/libraries/kernel/threads/exception.cpp b/src/core/libraries/kernel/threads/exception.cpp index dc8607124..fc32ee705 100644 --- a/src/core/libraries/kernel/threads/exception.cpp +++ b/src/core/libraries/kernel/threads/exception.cpp @@ -187,6 +187,7 @@ s32 OrbisToNativeSignal(s32 s) { #endif std::array Handlers{}; +Sigset g_sigintr{}; #ifndef _WIN64 void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context) { @@ -301,17 +302,50 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) { s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) { s->bits[0] = 0; s->bits[1] = 0; - return 0; + s->bits[2] = 0; + s->bits[3] = 0; + return ORBIS_OK; } s32 PS4_SYSV_ABI posix_sigfillset(Sigset* s) { s->bits[0] = ~0U; s->bits[1] = ~0U; - return 0; + s->bits[2] = ~0U; + s->bits[3] = ~0U; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI posix_sigaddset(Sigset* s, s32 sig) { + s32 val = sig - 1; + if (val >= 0x80) { + *Libraries::Kernel::__Error() = POSIX_EINVAL; + return ORBIS_FAIL; + } + s->bits[val >> 5] |= 1 << (val & 0x1f); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI posix_sigdelset(Sigset* s, s32 sig) { + s32 val = sig - 1; + if (val >= 0x80) { + *Libraries::Kernel::__Error() = POSIX_EINVAL; + return ORBIS_FAIL; + } + s->bits[val >> 5] &= ~(1 << (val & 0x1f)); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI posix_sigismember(Sigset* s, s32 sig) { + s32 val = sig - 1; + if (val >= 0x80) { + *Libraries::Kernel::__Error() = POSIX_EINVAL; + return ORBIS_FAIL; + } + return ((s->bits[val >> 5] >> (val & 0x1f)) & 1) != 0; } bool PS4_SYSV_ABI posix_sigisemptyset(Sigset* s) { - return s->bits[0] == 0 && s->bits[1] == 0; + return s->bits[0] == 0 && s->bits[1] == 0 && s->bits[2] == 0 && s->bits[3] == 0; } s32 PS4_SYSV_ABI posix_sigprocmask(s32 how, const Sigset* set, Sigset* oset) { @@ -412,6 +446,22 @@ s32 PS4_SYSV_ABI posix_sigaction(s32 sig, Sigaction* act, Sigaction* oact) { return ORBIS_OK; } +SigHandler PS4_SYSV_ABI posix_signal(s32 sig, SigHandler func) { + Sigaction act{}; + act.__sigaction_handler.handler = func; + posix_sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (posix_sigismember(&g_sigintr, sig) == 0) { + act.sa_flags |= POSIX_SA_RESTART; + } + Sigaction oact{}; + s32 result = posix_sigaction(sig, &act, &oact); + if (result >= ORBIS_OK) { + return oact.__sigaction_handler.handler; + } + return reinterpret_cast(-1); +} + s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) { if (sig < 1 || sig > 128) { // off-by-one error? return POSIX_EINVAL; @@ -515,6 +565,8 @@ s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) { } void RegisterException(Core::Loader::SymbolsResolver* sym) { + LIB_OBJ("nQVWJEGHObc", "libkernel", 1, "libkernel", &g_sigintr); + LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", sceKernelRaiseException); LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", sceKernelInstallExceptionHandler); @@ -526,15 +578,23 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler); LIB_FUNCTION("KiJEPEWRyUY", "libkernel", 1, "libkernel", posix_sigaction); + LIB_FUNCTION("VADc3MNQ3cM", "libkernel", 1, "libkernel", posix_signal); LIB_FUNCTION("+F7C-hdk7+E", "libkernel", 1, "libkernel", posix_sigemptyset); LIB_FUNCTION("VkTAsrZDcJ0", "libkernel", 1, "libkernel", posix_sigfillset); + LIB_FUNCTION("JUimFtKe0Kc", "libkernel", 1, "libkernel", posix_sigaddset); + LIB_FUNCTION("Nd-u09VFSCA", "libkernel", 1, "libkernel", posix_sigdelset); + LIB_FUNCTION("JnNl8Xr-z4Y", "libkernel", 1, "libkernel", posix_sigismember); LIB_FUNCTION("aPcyptbOiZs", "libkernel", 1, "libkernel", posix_sigprocmask); LIB_FUNCTION("yH-uQW3LbX0", "libkernel", 1, "libkernel", posix_pthread_kill); LIB_FUNCTION("sHziAegVp74", "libkernel", 1, "libkernel", posix_sigalstack); LIB_FUNCTION("KiJEPEWRyUY", "libScePosix", 1, "libkernel", posix_sigaction); + LIB_FUNCTION("VADc3MNQ3cM", "libScePosix", 1, "libkernel", posix_signal); LIB_FUNCTION("+F7C-hdk7+E", "libScePosix", 1, "libkernel", posix_sigemptyset); LIB_FUNCTION("VkTAsrZDcJ0", "libScePosix", 1, "libkernel", posix_sigfillset); + LIB_FUNCTION("JUimFtKe0Kc", "libScePosix", 1, "libkernel", posix_sigaddset); + LIB_FUNCTION("Nd-u09VFSCA", "libScePosix", 1, "libkernel", posix_sigdelset); + LIB_FUNCTION("JnNl8Xr-z4Y", "libScePosix", 1, "libkernel", posix_sigismember); LIB_FUNCTION("aPcyptbOiZs", "libScePosix", 1, "libkernel", posix_sigprocmask); LIB_FUNCTION("yH-uQW3LbX0", "libScePosix", 1, "libkernel", posix_pthread_kill); LIB_FUNCTION("sHziAegVp74", "libScePosix", 1, "libkernel", posix_sigalstack); diff --git a/src/core/libraries/kernel/threads/exception.h b/src/core/libraries/kernel/threads/exception.h index f9655404a..1b5156cbe 100644 --- a/src/core/libraries/kernel/threads/exception.h +++ b/src/core/libraries/kernel/threads/exception.h @@ -120,7 +120,7 @@ struct ExStack { }; struct Sigset { - u64 bits[2]; + u32 bits[4]; }; union Sigval { @@ -133,45 +133,47 @@ union Sigval { }; struct Siginfo { - int _si_signo; /* signal number */ - int _si_errno; /* errno association */ + s32 _si_signo; /* signal number */ + s32 _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_code; /* signal code */ s32 _si_pid; /* sending process */ u32 _si_uid; /* sender's ruid */ - int _si_status; /* exit value */ + s32 _si_status; /* exit value */ void* _si_addr; /* faulting instruction */ union Sigval _si_value; /* signal value */ union { struct { - int _trapno; /* machine specific trap code */ + s32 _trapno; /* machine specific trap code */ } _fault; struct { - int _timerid; - int _overrun; + s32 _timerid; + s32 _overrun; } _timer; struct { - int _mqd; + s32 _mqd; } _mesgq; struct { - long _band; /* band event for SIGPOLL */ - } _poll; /* was this ever used ? */ + s64 _band; /* band event for SIGPOLL */ + } _poll; /* was this ever used ? */ struct { - long __spare1__; - int __spare2__[7]; + s64 __spare1__; + s32 __spare2__[7]; } __spare__; } _reason; }; +using SigHandler = void PS4_SYSV_ABI (*)(int); + struct Sigaction { union { - void (*handler)(int); - void (*sigaction)(int, struct Siginfo*, void*); + void PS4_SYSV_ABI (*handler)(int); + void PS4_SYSV_ABI (*sigaction)(int, struct Siginfo*, void*); } __sigaction_handler; int sa_flags; Sigset sa_mask;