mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 13:26:52 +01:00
ci: fix the Linux build and the macOS SRT walker test crashes (#1922)
* graphics: give InlinePageOwnerList's const_iterator iterator traits The Linux build failed in textureCache.cpp: std::any_of over the image owners of a page needs std::iterator_traits, which libstdc++ only fills from the iterator's own member types. MSVC's STL and libc++ don't consult them there, so Windows and macOS built. Declare the five member types. The category is input, not forward, because operator* returns a copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tests: assert InlinePageOwnerList's const_iterator has an input category Only libstdc++ needs the iterator traits for std::any_of, so removing them would compile on Windows and macOS and break only the Linux build. The assert fails the build on every platform instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tests: serve SRT walker test loads on macOS too FakeGuestMemory only installed its fault handler on Linux and Windows, so on macOS the walker's deliberately faulting loads crashed scalar_provenance, resource_materialization and resource_tracking. Share the Linux sigaction path with macOS, read the registers from the macOS thread state, and catch SIGBUS as well as SIGSEGV there, like the emulator's own handler. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -118,6 +119,13 @@ public:
|
||||
|
||||
class const_iterator final {
|
||||
public:
|
||||
// libstdc++'s algorithms need these. Input, not forward, because operator* returns a copy.
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = OwnerT;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = void;
|
||||
using reference = OwnerT;
|
||||
|
||||
[[nodiscard]] OwnerT operator*() const noexcept { return m_owners->At(m_index); }
|
||||
const_iterator& operator++() noexcept {
|
||||
++m_index;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -13,6 +15,11 @@ using Table = Libs::Graphics::MultiLevelPageTable<Owners, 20, 44, 14>;
|
||||
using PageOwners = Libs::Graphics::InlinePageOwnerList<uint32_t, 16>;
|
||||
using OwnerTable = Libs::Graphics::MultiLevelPageTable<PageOwners, 20, 44, 14>;
|
||||
|
||||
// MSVC's STL and libc++ don't need these traits for std::any_of, but libstdc++ does, so only a
|
||||
// Linux build would notice them missing.
|
||||
static_assert(std::is_same_v<std::iterator_traits<PageOwners::const_iterator>::iterator_category,
|
||||
std::input_iterator_tag>);
|
||||
|
||||
void Check(bool value, const char* text) {
|
||||
if (!value) {
|
||||
std::fprintf(stderr, "ImagePageTableTests: failed: %s\n", text);
|
||||
|
||||
+31
-11
@@ -6,12 +6,16 @@
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <ucontext.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/ucontext.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@@ -23,18 +27,20 @@ public:
|
||||
explicit FakeGuestMemory(Libs::Graphics::ShaderRecompiler::IR::SrtMemoryReader reader = nullptr,
|
||||
void *userdata = nullptr) {
|
||||
Current() = {reader, userdata};
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
struct sigaction action {};
|
||||
action.sa_sigaction = Handle;
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGSEGV, &action, &m_previous);
|
||||
for (size_t index = 0; index < std::size(kSignals); ++index)
|
||||
sigaction(kSignals[index], &action, &m_previous[index]);
|
||||
#elif defined(_WIN32)
|
||||
m_handler = AddVectoredExceptionHandler(1, Handle);
|
||||
#endif
|
||||
}
|
||||
~FakeGuestMemory() {
|
||||
#if defined(__linux__)
|
||||
sigaction(SIGSEGV, &m_previous, nullptr);
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
for (size_t index = 0; index < std::size(kSignals); ++index)
|
||||
sigaction(kSignals[index], &m_previous[index], nullptr);
|
||||
#elif defined(_WIN32)
|
||||
RemoveVectoredExceptionHandler(m_handler);
|
||||
#endif
|
||||
@@ -54,16 +60,30 @@ private:
|
||||
const auto [reader, userdata] = Current();
|
||||
return reader != nullptr && reader(userdata, address, {&word, 1}) ? word : 0u;
|
||||
}
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#if defined(__APPLE__)
|
||||
// macOS raises SIGBUS for some protection faults and SIGSEGV for others.
|
||||
static constexpr int kSignals[] = {SIGSEGV, SIGBUS};
|
||||
#else
|
||||
static constexpr int kSignals[] = {SIGSEGV};
|
||||
#endif
|
||||
static void Handle(int, siginfo_t *, void *context) {
|
||||
auto ®isters = static_cast<ucontext_t *>(context)->uc_mcontext.gregs;
|
||||
const auto length =
|
||||
Libs::Graphics::ShaderRecompiler::IR::SrtWalkerLoadLength(registers[REG_RIP]);
|
||||
auto *native = static_cast<ucontext_t *>(context);
|
||||
#if defined(__APPLE__)
|
||||
auto &rip = native->uc_mcontext->__ss.__rip;
|
||||
auto &rax = native->uc_mcontext->__ss.__rax;
|
||||
const auto r10 = native->uc_mcontext->__ss.__r10;
|
||||
#else
|
||||
auto &rip = native->uc_mcontext.gregs[REG_RIP];
|
||||
auto &rax = native->uc_mcontext.gregs[REG_RAX];
|
||||
const auto r10 = native->uc_mcontext.gregs[REG_R10];
|
||||
#endif
|
||||
const auto length = Libs::Graphics::ShaderRecompiler::IR::SrtWalkerLoadLength(rip);
|
||||
if (length == 0) std::abort();
|
||||
registers[REG_RAX] = Read(registers[REG_R10]);
|
||||
registers[REG_RIP] += length;
|
||||
rax = Read(r10);
|
||||
rip += length;
|
||||
}
|
||||
struct sigaction m_previous {};
|
||||
struct sigaction m_previous[std::size(kSignals)] {};
|
||||
#elif defined(_WIN32)
|
||||
static LONG CALLBACK Handle(EXCEPTION_POINTERS *info) {
|
||||
auto &context = *info->ContextRecord;
|
||||
|
||||
Reference in New Issue
Block a user