mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
99 lines
5.1 KiB
C++
99 lines
5.1 KiB
C++
#include "SceTypes.hpp"
|
|
#include "prx/libkernel/include/Api.hpp"
|
|
#include "prx/libc/include/Api.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <initializer_list>
|
|
#include <limits>
|
|
|
|
using Handler = void (APS5_VABI *)(int);
|
|
|
|
static_assert(sizeof(GuestSignalSet) == 16 && alignof(GuestSignalSet) == 4);
|
|
static_assert(sizeof(GuestSigaction) == 32 && offsetof(GuestSigaction, flags) == 8 && offsetof(GuestSigaction, mask) == 12);
|
|
|
|
extern "C" {
|
|
extern GuestSignalSet _sigintr_nid_postfix;
|
|
}
|
|
|
|
namespace {
|
|
|
|
void Require(bool condition, const char* message) {
|
|
if (condition) return;
|
|
std::fprintf(stderr, "%s\n", message);
|
|
std::abort();
|
|
}
|
|
|
|
bool Same(const GuestSigaction& first, const GuestSigaction& second) {
|
|
return first.handler == second.handler && first.flags == second.flags &&
|
|
std::memcmp(&first.mask, &second.mask, sizeof(first.mask)) == 0;
|
|
}
|
|
|
|
void APS5_VABI HandlerFunction(int) {}
|
|
|
|
}
|
|
|
|
int main() {
|
|
const GuestSignalSet initial = _sigintr_nid_postfix;
|
|
Require(initial.bits[0] == 0 && initial.bits[1] == 0 && initial.bits[2] == 0 && initial.bits[3] == 0, "initial interrupt set");
|
|
for (int guest : {1, 32, 33, 64, 65, 96, 97, 128}) {
|
|
GuestSigaction original{};
|
|
Require(sigaction_nid_postfix(guest, nullptr, &original) == 0, "read original disposition");
|
|
GuestSigaction custom{reinterpret_cast<std::uintptr_t>(HandlerFunction), 0x42,
|
|
{{0x11111111, 0x22222222, 0x33333333, 0x44444444}}};
|
|
Require(sigaction_nid_postfix(guest, &custom, nullptr) == 0, "install custom disposition");
|
|
Require(sigaction_nid_postfix(guest, nullptr, &custom) == 0, "read installed disposition");
|
|
const auto word = static_cast<unsigned>(guest - 1) / 32;
|
|
const auto bit = std::uint32_t{1} << (static_cast<unsigned>(guest - 1) % 32);
|
|
GuestSignalSet expected{{0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa}};
|
|
expected.bits[word] &= ~bit;
|
|
_sigintr_nid_postfix = expected;
|
|
for (int flag : {1, -1, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()}) {
|
|
*__error_nid_postfix() = 12345;
|
|
Require(siginterrupt_nid_postfix(guest, flag) == 0, "nonzero flag");
|
|
Require(*__error_nid_postfix() == 12345, "successful errno preservation");
|
|
expected.bits[word] |= bit;
|
|
Require(std::memcmp(&_sigintr_nid_postfix, &expected, sizeof(expected)) == 0, "set bit without changing neighboring bits");
|
|
GuestSigaction actual{};
|
|
Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0, "read interrupted disposition");
|
|
auto interrupted = custom;
|
|
interrupted.flags &= ~0x2;
|
|
Require(Same(actual, interrupted), "preserve handler, mask and other flags");
|
|
}
|
|
for (int repeat = 0; repeat < 2; ++repeat) {
|
|
*__error_nid_postfix() = 23456;
|
|
Require(siginterrupt_nid_postfix(guest, 0) == 0, "clear interrupt bit");
|
|
Require(*__error_nid_postfix() == 23456, "zero flag errno preservation");
|
|
expected.bits[word] &= ~bit;
|
|
Require(std::memcmp(&_sigintr_nid_postfix, &expected, sizeof(expected)) == 0, "clear bit without changing neighboring bits");
|
|
GuestSigaction actual{};
|
|
Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && Same(actual, custom), "restore restart without changing disposition");
|
|
}
|
|
Require(siginterrupt_nid_postfix(guest, -1) == 0, "make later signal interruptible");
|
|
Require(signal_nid_postfix(guest, HandlerFunction) == HandlerFunction, "subsequent signal preserves previous handler");
|
|
GuestSigaction actual{};
|
|
Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && actual.flags == 0, "signal consults shared interrupt set");
|
|
Require(siginterrupt_nid_postfix(guest, 0) == 0, "make later signal restartable");
|
|
Require(signal_nid_postfix(guest, HandlerFunction) == HandlerFunction, "repeat signal registration");
|
|
Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && actual.flags == 0x2, "signal restores restart");
|
|
Require(sigaction_nid_postfix(guest, &original, nullptr) == 0, "restore original disposition");
|
|
_sigintr_nid_postfix = initial;
|
|
}
|
|
const GuestSignalSet sentinels{{0x12345678, 0xabcdef01, 0x23456789, 0xbcdef012}};
|
|
_sigintr_nid_postfix = sentinels;
|
|
GuestSigaction before{};
|
|
Require(sigaction_nid_postfix(30, nullptr, &before) == 0, "read invalid-call control");
|
|
for (int guest : {0, -1, 129, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()}) {
|
|
for (int flag : {0, 1, -1}) {
|
|
*__error_nid_postfix() = 34567;
|
|
Require(siginterrupt_nid_postfix(guest, flag) == -1 && *__error_nid_postfix() == 22, "invalid signal reports EINVAL");
|
|
Require(std::memcmp(&_sigintr_nid_postfix, &sentinels, sizeof(sentinels)) == 0, "invalid signal leaves all words unchanged");
|
|
}
|
|
}
|
|
GuestSigaction after{};
|
|
Require(sigaction_nid_postfix(30, nullptr, &after) == 0 && Same(before, after), "invalid calls preserve dispositions");
|
|
_sigintr_nid_postfix = initial;
|
|
}
|