diff --git a/CMakeLists.txt b/CMakeLists.txt index 7853b91a..9810ff92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,10 @@ add_executable(shadps4 src/core/PS4/GPU/tile_manager.cpp src/core/PS4/GPU/tile_manager.h src/core/hle/libraries/libkernel/time_management.cpp - src/core/hle/libraries/libkernel/time_management.h) + src/core/hle/libraries/libkernel/time_management.h + src/core/tls.cpp + src/core/tls.h +) create_target_directory_groups(shadps4) diff --git a/src/common/io_file.h b/src/common/io_file.h index bd544a39..11fafbec 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -105,7 +105,6 @@ public: FileShareFlag flag = FileShareFlag::ShareReadOnly); void Close(); - bool Flush() const; bool Commit() const; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 49e246a0..078baa89 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -60,8 +60,8 @@ private: */ class FileBackend { public: - explicit FileBackend(const std::filesystem::path& filename) : file{filename, FS::FileAccessMode::Write, - FS::FileType::TextFile} {} + explicit FileBackend(const std::filesystem::path& filename) + : file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {} ~FileBackend() = default; diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp index 98b55e5a..5a797548 100644 --- a/src/core/aerolib/stubs.cpp +++ b/src/core/aerolib/stubs.cpp @@ -38,8 +38,8 @@ template static u64 CommonStub() { auto entry = stub_nids[stub_index]; if (entry) { - LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}", entry->name, - entry->nid, __builtin_return_address(0)); + LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}", entry->name, entry->nid, + __builtin_return_address(0)); } else { LOG_ERROR(Core, "Stub: Unknown (nid: {}) called, returning zero to {}", stub_nids_unknown[stub_index], __builtin_return_address(0)); diff --git a/src/core/tls.cpp b/src/core/tls.cpp new file mode 100644 index 00000000..f08985ed --- /dev/null +++ b/src/core/tls.cpp @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/types.h" +#include "core/tls.h" + +namespace Core { + +thread_local u8 TLS[1024]; + +uintptr_t GetGuestTls(s64 tls_offset) { + if (tls_offset == 0) { + return reinterpret_cast(TLS); + } + UNREACHABLE_MSG("Unimplemented offset info tls"); +} + +#ifdef _WIN64 +static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { + auto orig_rip = pExp->ContextRecord->Rip; + while (*(u8*)pExp->ContextRecord->Rip == 0x66) { + pExp->ContextRecord->Rip++; + } + + if (*(u8*)pExp->ContextRecord->Rip == 0xcd) { + int reg = *(u8*)(pExp->ContextRecord->Rip + 1) - 0x80; + int sizes = *(u8*)(pExp->ContextRecord->Rip + 2); + int pattern_size = sizes & 0xF; + int imm_size = sizes >> 4; + + int64_t tls_offset; + if (imm_size == 4) { + tls_offset = *(s32*)(pExp->ContextRecord->Rip + pattern_size); + } else { + tls_offset = *(s64*)(pExp->ContextRecord->Rip + pattern_size); + } + + (&pExp->ContextRecord->Rax)[reg] = GetGuestTls(tls_offset); /* GetGuestTls */ + pExp->ContextRecord->Rip += pattern_size + imm_size; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + pExp->ContextRecord->Rip = orig_rip; + const u32 ec = pExp->ExceptionRecord->ExceptionCode; + switch (ec) { + case EXCEPTION_ACCESS_VIOLATION: { + LOG_CRITICAL(Core, "Exception EXCEPTION_ACCESS_VIOLATION ({:#x})", ec); + const auto info = pExp->ExceptionRecord->ExceptionInformation; + switch (info[0]) { + case 0: + LOG_CRITICAL(Core, "Read violation at address {:#x}", info[1]); + break; + case 1: + LOG_CRITICAL(Core, "Write violation at address {:#x}", info[1]); + break; + case 8: + LOG_CRITICAL(Core, "DEP violation at address {:#x}", info[1]); + break; + default: + break; + } + break; + } + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + LOG_CRITICAL(Core, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED ({:#x})", ec); + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + LOG_CRITICAL(Core, "Exception EXCEPTION_DATATYPE_MISALIGNMENT ({:#x})", ec); + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + LOG_CRITICAL(Core, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO ({:#x})", ec); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + LOG_CRITICAL(Core, "Exception EXCEPTION_ILLEGAL_INSTRUCTION ({:#x})", ec); + break; + case EXCEPTION_IN_PAGE_ERROR: + LOG_CRITICAL(Core, "Exception EXCEPTION_IN_PAGE_ERROR ({:#x})", ec); + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + LOG_CRITICAL(Core, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO ({:#x})", ec); + break; + case EXCEPTION_PRIV_INSTRUCTION: + LOG_CRITICAL(Core, "Exception EXCEPTION_PRIV_INSTRUCTION ({:#x})", ec); + break; + case EXCEPTION_STACK_OVERFLOW: + LOG_CRITICAL(Core, "Exception EXCEPTION_STACK_OVERFLOW ({:#x})", ec); + break; + default: + return EXCEPTION_CONTINUE_SEARCH; + } + Flush(); + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +void InstallTlsHandler() { +#ifdef _WIN64 + if (!AddVectoredExceptionHandler(0, ExceptionHandler)) { + LOG_CRITICAL(Core, "Failed to register an exception handler"); + } +#endif +} + +} // namespace Core diff --git a/src/core/tls.h b/src/core/tls.h new file mode 100644 index 00000000..2a3c8775 --- /dev/null +++ b/src/core/tls.h @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +namespace Core { + +void InstallTlsHandler(); + +} // namespace Core diff --git a/src/core/virtual_memory.cpp b/src/core/virtual_memory.cpp index ae90f2c3..3c9c2e20 100644 --- a/src/core/virtual_memory.cpp +++ b/src/core/virtual_memory.cpp @@ -125,7 +125,7 @@ bool memory_flush(u64 address, u64 size) { } bool memory_patch(u64 vaddr, u64 value) { MemoryMode old_mode{}; - //memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); + // memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); auto* ptr = reinterpret_cast(vaddr); @@ -133,7 +133,7 @@ bool memory_patch(u64 vaddr, u64 value) { *ptr = value; - //memory_protect(vaddr, 8, old_mode, nullptr); + // memory_protect(vaddr, 8, old_mode, nullptr); // if mode is executable flush it so insure that cpu finds it if (containsExecuteMode(old_mode)) { diff --git a/src/main.cpp b/src/main.cpp index 81ac1537..0ed5d400 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include "core/file_sys/fs.h" #include "core/hle/libraries/libs.h" #include "core/linker.h" +#include "core/tls.h" #include "emulator.h" int main(int argc, char* argv[]) { @@ -46,6 +47,7 @@ int main(int argc, char* argv[]) { auto linker = Common::Singleton::Instance(); Core::Libraries::InitHLELibs(&linker->getHLESymbols()); + Core::InstallTlsHandler(); linker->LoadModule(path); std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); }, nullptr);