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
This commit is contained in:
Stephen Miller 2026-05-25 02:27:55 -05:00 committed by GitHub
parent 9dada49956
commit 86a64fb980
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 93 additions and 30 deletions

View File

@ -1223,25 +1223,26 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) {
} }
#ifdef _WIN32 #ifdef _WIN32
#define __FD_SETSIZE 1024
typedef struct { typedef struct {
unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(unsigned long))]; u64 fds_bits[16];
} fd_set_posix; } fd_set_posix;
#define FD_SET_POSIX(fd, set) \ static void FD_SET_POSIX(s32 fd, fd_set_posix* set) {
((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] |= \ set->fds_bits[fd / (8 * sizeof(u64))] |= (1ULL << (fd % (8 * sizeof(u64))));
(1UL << ((fd) % (8 * sizeof(unsigned long))))) }
#define FD_CLR_POSIX(fd, set) \ static void FD_CLR_POSIX(s32 fd, fd_set_posix* set) {
((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] &= \ set->fds_bits[fd / (8 * sizeof(u64))] &= ~(1ULL << (fd % (8 * sizeof(u64))));
~(1UL << ((fd) % (8 * sizeof(unsigned long))))) }
#define FD_ISSET_POSIX(fd, set) \ static bool FD_ISSET_POSIX(s32 fd, fd_set_posix* set) {
(((set)->fds_bits[(fd) / (8 * sizeof(unsigned long))] & \ return (set->fds_bits[fd / (8 * sizeof(u64))] & (1ULL << (fd % (8 * sizeof(u64))))) != 0;
(1UL << ((fd) % (8 * sizeof(unsigned long))))) != 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, s32 PS4_SYSV_ABI posix_select(s32 nfds, fd_set_posix* readfds, fd_set_posix* writefds,
fd_set_posix* exceptfds, OrbisKernelTimeval* timeout) { fd_set_posix* exceptfds, OrbisKernelTimeval* timeout) {

View File

@ -187,6 +187,7 @@ s32 OrbisToNativeSignal(s32 s) {
#endif #endif
std::array<OrbisKernelExceptionHandler, 130> Handlers{}; std::array<OrbisKernelExceptionHandler, 130> Handlers{};
Sigset g_sigintr{};
#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) {
@ -301,17 +302,50 @@ void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) { s32 PS4_SYSV_ABI posix_sigemptyset(Sigset* s) {
s->bits[0] = 0; s->bits[0] = 0;
s->bits[1] = 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) { s32 PS4_SYSV_ABI posix_sigfillset(Sigset* s) {
s->bits[0] = ~0U; s->bits[0] = ~0U;
s->bits[1] = ~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) { 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) { 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; 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<SigHandler>(-1);
}
s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) { s32 PS4_SYSV_ABI posix_pthread_kill(PthreadT thread, s32 sig) {
if (sig < 1 || sig > 128) { // off-by-one error? if (sig < 1 || sig > 128) { // off-by-one error?
return POSIX_EINVAL; return POSIX_EINVAL;
@ -515,6 +565,8 @@ s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
} }
void RegisterException(Core::Loader::SymbolsResolver* sym) { void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_OBJ("nQVWJEGHObc", "libkernel", 1, "libkernel", &g_sigintr);
LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", sceKernelRaiseException); LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", sceKernelRaiseException);
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel",
sceKernelInstallExceptionHandler); sceKernelInstallExceptionHandler);
@ -526,15 +578,23 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler); LIB_FUNCTION("Qhv5ARAoOEc", "libkernel", 1, "libkernel", sceKernelRemoveExceptionHandler);
LIB_FUNCTION("KiJEPEWRyUY", "libkernel", 1, "libkernel", posix_sigaction); 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("+F7C-hdk7+E", "libkernel", 1, "libkernel", posix_sigemptyset);
LIB_FUNCTION("VkTAsrZDcJ0", "libkernel", 1, "libkernel", posix_sigfillset); 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("aPcyptbOiZs", "libkernel", 1, "libkernel", posix_sigprocmask);
LIB_FUNCTION("yH-uQW3LbX0", "libkernel", 1, "libkernel", posix_pthread_kill); LIB_FUNCTION("yH-uQW3LbX0", "libkernel", 1, "libkernel", posix_pthread_kill);
LIB_FUNCTION("sHziAegVp74", "libkernel", 1, "libkernel", posix_sigalstack); LIB_FUNCTION("sHziAegVp74", "libkernel", 1, "libkernel", posix_sigalstack);
LIB_FUNCTION("KiJEPEWRyUY", "libScePosix", 1, "libkernel", posix_sigaction); 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("+F7C-hdk7+E", "libScePosix", 1, "libkernel", posix_sigemptyset);
LIB_FUNCTION("VkTAsrZDcJ0", "libScePosix", 1, "libkernel", posix_sigfillset); 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("aPcyptbOiZs", "libScePosix", 1, "libkernel", posix_sigprocmask);
LIB_FUNCTION("yH-uQW3LbX0", "libScePosix", 1, "libkernel", posix_pthread_kill); LIB_FUNCTION("yH-uQW3LbX0", "libScePosix", 1, "libkernel", posix_pthread_kill);
LIB_FUNCTION("sHziAegVp74", "libScePosix", 1, "libkernel", posix_sigalstack); LIB_FUNCTION("sHziAegVp74", "libScePosix", 1, "libkernel", posix_sigalstack);

View File

@ -120,7 +120,7 @@ struct ExStack {
}; };
struct Sigset { struct Sigset {
u64 bits[2]; u32 bits[4];
}; };
union Sigval { union Sigval {
@ -133,45 +133,47 @@ union Sigval {
}; };
struct Siginfo { struct Siginfo {
int _si_signo; /* signal number */ s32 _si_signo; /* signal number */
int _si_errno; /* errno association */ s32 _si_errno; /* errno association */
/* /*
* Cause of signal, one of the SI_ macros or signal-specific * Cause of signal, one of the SI_ macros or signal-specific
* values, i.e. one of the FPE_... values for SIGFPE. This * values, i.e. one of the FPE_... values for SIGFPE. This
* value is equivalent to the second argument to an old-style * value is equivalent to the second argument to an old-style
* FreeBSD signal handler. * FreeBSD signal handler.
*/ */
int _si_code; /* signal code */ s32 _si_code; /* signal code */
s32 _si_pid; /* sending process */ s32 _si_pid; /* sending process */
u32 _si_uid; /* sender's ruid */ u32 _si_uid; /* sender's ruid */
int _si_status; /* exit value */ s32 _si_status; /* exit value */
void* _si_addr; /* faulting instruction */ void* _si_addr; /* faulting instruction */
union Sigval _si_value; /* signal value */ union Sigval _si_value; /* signal value */
union { union {
struct { struct {
int _trapno; /* machine specific trap code */ s32 _trapno; /* machine specific trap code */
} _fault; } _fault;
struct { struct {
int _timerid; s32 _timerid;
int _overrun; s32 _overrun;
} _timer; } _timer;
struct { struct {
int _mqd; s32 _mqd;
} _mesgq; } _mesgq;
struct { struct {
long _band; /* band event for SIGPOLL */ s64 _band; /* band event for SIGPOLL */
} _poll; /* was this ever used ? */ } _poll; /* was this ever used ? */
struct { struct {
long __spare1__; s64 __spare1__;
int __spare2__[7]; s32 __spare2__[7];
} __spare__; } __spare__;
} _reason; } _reason;
}; };
using SigHandler = void PS4_SYSV_ABI (*)(int);
struct Sigaction { struct Sigaction {
union { union {
void (*handler)(int); void PS4_SYSV_ABI (*handler)(int);
void (*sigaction)(int, struct Siginfo*, void*); void PS4_SYSV_ABI (*sigaction)(int, struct Siginfo*, void*);
} __sigaction_handler; } __sigaction_handler;
int sa_flags; int sa_flags;
Sigset sa_mask; Sigset sa_mask;