mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-05-26 13:50:37 +00:00
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:
@@ -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) {
|
||||
|
||||
@@ -187,6 +187,7 @@ s32 OrbisToNativeSignal(s32 s) {
|
||||
#endif
|
||||
|
||||
std::array<OrbisKernelExceptionHandler, 130> 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<SigHandler>(-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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user