Files
FEX-Emu--FEX/Source/Tests/LinuxSyscalls/x32/Signals.cpp
T
Lioncash 75b2f226f6 General: Migrate over to fmt where possible
Migrates lingering instances of the old logger over to fmt where
applicable. This allows removing some of the old defines and functions.

The only remaining usages of the printf-based variant of the logger is
in Tests/LinuxSyscalls/Syscalls.cpp for the strace handling.
2021-11-23 12:51:57 -05:00

149 lines
5.3 KiB
C++

/*
$info$
tags: LinuxSyscalls|syscalls-x86-32
$end_info$
*/
#include "Tests/LinuxSyscalls/SignalDelegator.h"
#include "Tests/LinuxSyscalls/Syscalls.h"
#include "Tests/LinuxSyscalls/x32/Syscalls.h"
#include "Tests/LinuxSyscalls/x32/Types.h"
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Core/UContext.h>
#include <errno.h>
#include <bits/types/siginfo_t.h>
#include <stdint.h>
#include <time.h>
namespace FEXCore::Core {
struct CpuStateFrame;
}
ARG_TO_STR(FEX::HLE::x32::compat_ptr<FEXCore::x86::siginfo_t>, "%lx")
namespace FEX::HLE::x32 {
void CopySigInfo(FEXCore::x86::siginfo_t *Info, siginfo_t const &Host) {
// Copy the basic things first
Info->si_signo = Host.si_signo;
Info->si_errno = Host.si_errno;
Info->si_code = Host.si_code;
// Check si_code to determine how we need to interpret this
if (Info->si_code == SI_TIMER) {
// SI_TIMER means pid, uid, value
Info->_sifields._timer.tid = Host.si_timerid;
Info->_sifields._timer.overrun = Host.si_overrun;
Info->_sifields._timer.sigval.sival_int = Host.si_value.sival_int;
}
else {
// Now we need to copy over the more complex things
switch (Info->si_signo) {
case SIGSEGV:
case SIGBUS:
// This is the address trying to be accessed, not the RIP
Info->_sifields._sigfault.addr = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(Host.si_addr));
break;
case SIGFPE:
case SIGILL:
// Can't really give a real result here. This is the RIP causing a sigill or sigfpe
// Claim at RIP 0 for now
Info->_sifields._sigfault.addr = 0;
break;
case SIGCHLD:
Info->_sifields._sigchld.pid = Host.si_pid;
Info->_sifields._sigchld.uid = Host.si_uid;
Info->_sifields._sigchld.status = Host.si_status;
Info->_sifields._sigchld.utime = Host.si_utime;
Info->_sifields._sigchld.stime = Host.si_stime;
break;
case SIGALRM:
case SIGVTALRM:
Info->_sifields._timer.tid = Host.si_timerid;
Info->_sifields._timer.overrun = Host.si_overrun;
Info->_sifields._timer.sigval.sival_int = Host.si_int;
break;
default:
LogMan::Msg::EFmt("Unhandled siginfo_t for sigtimedwait: {}", Info->si_signo);
break;
}
}
}
void RegisterSignals() {
REGISTER_SYSCALL_IMPL_X32(sigpending, [](FEXCore::Core::CpuStateFrame *Frame, compat_old_sigset_t *set) -> uint64_t {
uint64_t HostSet{};
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigPending(&HostSet, 8);
if (Result == 0) {
// This old interface only returns the lower signals
*set = HostSet & ~0U;
}
return Result;
});
REGISTER_SYSCALL_IMPL_X32(signal, [](FEXCore::Core::CpuStateFrame *Frame, int signum, uint32_t handler) -> uint64_t {
FEXCore::GuestSigAction newact{};
FEXCore::GuestSigAction oldact{};
newact.sigaction_handler.handler = reinterpret_cast<decltype(newact.sigaction_handler.handler)>(handler);
FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSignalHandler(signum, &newact, &oldact);
return static_cast<uint32_t>(reinterpret_cast<uint64_t>(oldact.sigaction_handler.handler));
});
REGISTER_SYSCALL_IMPL_X32(rt_sigaction, [](FEXCore::Core::CpuStateFrame *Frame, int signum, const GuestSigAction_32 *act, GuestSigAction_32 *oldact, size_t sigsetsize) -> uint64_t {
if (sigsetsize != 8) {
return -EINVAL;
}
FEXCore::GuestSigAction *act64_p{};
FEXCore::GuestSigAction *old64_p{};
FEXCore::GuestSigAction act64{};
if (act) {
act64 = *act;
act64_p = &act64;
}
FEXCore::GuestSigAction old64{};
if (oldact) {
old64_p = &old64;
}
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSignalHandler(signum, act64_p, old64_p);
if (Result == 0 && oldact) {
*oldact = old64;
}
return Result;
});
REGISTER_SYSCALL_IMPL_X32(rt_sigtimedwait, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, compat_ptr<FEXCore::x86::siginfo_t> info, const struct timespec32* timeout, size_t sigsetsize) -> uint64_t {
struct timespec* timeout_ptr{};
struct timespec tp64{};
if (timeout) {
tp64 = *timeout;
timeout_ptr = &tp64;
}
siginfo_t HostInfo{};
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, &HostInfo, timeout_ptr, sigsetsize);
if (Result != -1) {
// We need to translate the 64-bit siginfo_t to 32-bit siginfo_t
CopySigInfo(info, HostInfo);
}
return Result;
});
REGISTER_SYSCALL_IMPL_X32(rt_sigtimedwait_time64, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, compat_ptr<FEXCore::x86::siginfo_t> info, const struct timespec* timeout, size_t sigsetsize) -> uint64_t {
siginfo_t HostInfo{};
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, &HostInfo, timeout, sigsetsize);
if (Result != -1) {
// We need to translate the 64-bit siginfo_t to 32-bit siginfo_t
CopySigInfo(info, HostInfo);
}
return Result;
});
}
}