From 772891bfa7127c2113735c908d4987ffe0fdb16d Mon Sep 17 00:00:00 2001 From: raphaelthegreat <47210458+raphaelthegreat@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:37:40 +0300 Subject: [PATCH] linker: Reduce code nesting --- src/core/address_space.cpp | 4 +- src/core/address_space.h | 2 +- src/core/file_sys/fs.cpp | 4 + src/core/libraries/kernel/file_system.cpp | 13 +++ src/core/libraries/kernel/libkernel.cpp | 1 + .../libraries/kernel/memory_management.cpp | 6 +- src/core/libraries/kernel/memory_management.h | 1 + .../libraries/kernel/thread_management.cpp | 95 ++++++++++++++++ src/core/libraries/kernel/time_management.cpp | 61 ++++++++++ src/core/libraries/kernel/time_management.h | 6 + src/core/linker.cpp | 105 +++++++++--------- src/core/linker.h | 21 ++-- src/core/loader/symbols_resolver.cpp | 5 - src/core/loader/symbols_resolver.h | 7 +- src/core/memory.cpp | 2 +- src/core/memory.h | 4 +- src/core/tls.cpp | 14 ++- src/core/tls.h | 7 +- 18 files changed, 274 insertions(+), 84 deletions(-) diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index f10527b9..77579495 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -102,14 +102,14 @@ struct AddressSpace::Impl { // Perform the map. void* ptr = nullptr; - if (phys_addr) { + if (phys_addr != -1) { ptr = MapViewOfFile3(backing_handle, process, reinterpret_cast(virtual_addr), phys_addr, size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0); } else { ptr = VirtualAlloc2(process, reinterpret_cast(virtual_addr), size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0); } - ASSERT(ptr); + ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg()); return ptr; } diff --git a/src/core/address_space.h b/src/core/address_space.h index 963e9afa..322ab9c7 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -42,7 +42,7 @@ public: * If zero is provided the mapping is considered as private. * @return A pointer to the mapped memory. */ - void* Map(VAddr virtual_addr, size_t size, u64 alignment = 0, PAddr phys_addr = 0); + void* Map(VAddr virtual_addr, size_t size, u64 alignment = 0, PAddr phys_addr = -1); /// Unmaps specified virtual memory area. void Unmap(VAddr virtual_addr, size_t size); diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 6a99a808..dd580e04 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include "common/assert.h" #include "core/file_sys/fs.h" namespace Core::FileSys { @@ -51,9 +53,11 @@ std::string MntPoints::GetHostFile(const std::string& guest_file) { if (find == 0) { std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1); std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); + fmt::print("GetHostFile: {}\n", pair.host_path + npath); return pair.host_path + npath; } } + UNREACHABLE(); return ""; } diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index a2dfcbc1..f0fec319 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -197,12 +197,23 @@ int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) { int PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) { int result = sceKernelStat(path, sb); + return result; if (result < 0) { UNREACHABLE(); // TODO } return ORBIS_OK; } +int PS4_SYSV_ABI sceKernelCheckReachability(const char *path) { + LOG_INFO(Lib_Kernel, "path = {}", path); + auto* mnt = Common::Singleton::Instance(); + std::string path_name = mnt->GetHostFile(path); + if (!std::filesystem::exists(path_name)) { + return SCE_KERNEL_ERROR_ENOENT; + } + return ORBIS_OK; +} + void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); @@ -215,6 +226,8 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("Cg4srZ6TKbU", "libkernel", 1, "libkernel", 1, 1, sceKernelRead); LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir); LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat); + LIB_FUNCTION("uWyW3v98sU4", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckReachability); + LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat); // openOrbis (to check if it is valid out of OpenOrbis diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index a8c3975e..406ae626 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -204,6 +204,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); // memory LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateDirectMemory); + LIB_FUNCTION("B+vc2AO2Zrc", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateMainDirectMemory); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize); LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory); LIB_FUNCTION("WFcfL2lzido", "libkernel", 1, "libkernel", 1, 1, sceKernelQueryMemoryProtection); diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 9e540107..8d839c5a 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -22,7 +22,7 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); return SCE_KERNEL_ERROR_EINVAL; } - const bool is_in_range = (searchStart < len && searchEnd > len); + const bool is_in_range = searchEnd - searchStart >= len; if (len <= 0 || !Common::is16KBAligned(len) || !is_in_range) { LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); return SCE_KERNEL_ERROR_EINVAL; @@ -48,6 +48,10 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u return SCE_OK; } +s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, s64 *physAddrOut) { + return sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, len, alignment, memoryType, physAddrOut); +} + int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) { LOG_INFO( diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index be0d8514..8cb83986 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -39,6 +39,7 @@ struct OrbisQueryInfo { u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut); +s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, s64 *physAddrOut); int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment); s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot, diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 32f179a5..bdeee180 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -9,6 +9,7 @@ #include "core/libraries/error_codes.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/libs.h" +#include "core/tls.h" #ifdef _WIN64 #include #endif @@ -82,6 +83,18 @@ int PS4_SYSV_ABI scePthreadAttrDestroy(ScePthreadAttr* attr) { return SCE_KERNEL_ERROR_EINVAL; } +int PS4_SYSV_ABI pthread_attr_destroy(ScePthreadAttr* attr) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutexattr_init redirect to scePthreadMutexattrInit"); + int result = scePthreadAttrDestroy(attr); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + int PS4_SYSV_ABI scePthreadAttrSetguardsize(ScePthreadAttr* attr, size_t guard_size) { if (attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -664,6 +677,66 @@ int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex* } } +int PS4_SYSV_ABI pthread_attr_init(ScePthreadAttr* attr) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutexattr_init redirect to scePthreadMutexattrInit"); + int result = scePthreadAttrInit(attr); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + +int PS4_SYSV_ABI pthread_attr_setstacksize(ScePthreadAttr* attr, size_t stacksize) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutexattr_init redirect to scePthreadMutexattrInit"); + int result = scePthreadAttrSetstacksize(attr, stacksize); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + +int PS4_SYSV_ABI pthread_attr_setdetachstate(ScePthreadAttr *attr, int detachstate) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutexattr_init redirect to scePthreadMutexattrInit"); + int result = scePthreadAttrSetdetachstate(attr, detachstate); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + +int PS4_SYSV_ABI pthread_mutexattr_init(ScePthreadMutexattr *attr) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutexattr_init redirect to scePthreadMutexattrInit"); + int result = scePthreadMutexattrInit(attr); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + +int PS4_SYSV_ABI pthread_mutexattr_settype(ScePthreadMutexattr *attr, int type) { + // LOG_INFO(Kernel_Pthread, "posix pthread_mutex_init redirect to scePthreadMutexInit"); + int result = scePthreadMutexattrSettype(attr, type); + if (result < 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr) { // LOG_INFO(Kernel_Pthread, "posix pthread_mutex_init redirect to scePthreadMutexInit"); int result = scePthreadMutexInit(mutex, attr, nullptr); @@ -829,6 +902,7 @@ static void cleanup_thread(void* arg) { static void* run_thread(void* arg) { auto* thread = static_cast(arg); Common::SetCurrentThreadName(thread->name.c_str()); + Core::SetTLSStorage(0, 0); void* ret = nullptr; g_pthread_self = thread; pthread_cleanup_push(cleanup_thread, thread); @@ -898,6 +972,19 @@ int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr } } +int PS4_SYSV_ABI pthread_create(ScePthread* thread, const ScePthreadAttr* attr, + pthreadEntryFunc start_routine, void* arg) { + LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate"); + int result = scePthreadCreate(thread, attr, start_routine, arg, "PS4_Thread"); + if (result != 0) { + int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP + ? result + -SCE_KERNEL_ERROR_UNKNOWN + : POSIX_EOTHER; + return rt; + } + return result; +} + ScePthread PThreadPool::Create() { std::scoped_lock lock{m_mutex}; @@ -1062,6 +1149,14 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("kDh-NfxgMtE", "libkernel", 1, "libkernel", 1, 1, scePthreadCondSignal); LIB_FUNCTION("BmMjYxmew1w", "libkernel", 1, "libkernel", 1, 1, scePthreadCondTimedwait); // posix calls + LIB_FUNCTION("wtkt-teR1so", "libScePosix", 1, "libkernel", 1, 1, pthread_attr_init); + LIB_FUNCTION("2Q0z6rnBrTE", "libScePosix", 1, "libkernel", 1, 1, pthread_attr_setstacksize); + LIB_FUNCTION("E+tyo3lp5Lw", "libScePosix", 1, "libkernel", 1, 1, pthread_attr_setdetachstate); + LIB_FUNCTION("OxhIB8LB-PQ", "libScePosix", 1, "libkernel", 1, 1, pthread_create); + LIB_FUNCTION("zHchY8ft5pk", "libScePosix", 1, "libkernel", 1, 1, pthread_attr_destroy); + + LIB_FUNCTION("dQHWEsJtoE4", "libScePosix", 1, "libkernel", 1, 1, pthread_mutexattr_init); + LIB_FUNCTION("mDmgMOGVUqg", "libScePosix", 1, "libkernel", 1, 1, pthread_mutexattr_settype); LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init); LIB_FUNCTION("7H0iTOciTLo", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_lock); LIB_FUNCTION("2Z+PpY6CaJg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_unlock); diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index f32e2b8e..462cea17 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -1,10 +1,17 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include #include "common/native_clock.h" #include "core/libraries/kernel/time_management.h" #include "core/libraries/libs.h" +#ifdef _WIN64 +#include +#endif + namespace Libraries::Kernel { static u64 initial_ptc; @@ -30,6 +37,57 @@ u64 PS4_SYSV_ABI sceKernelReadTsc() { return clock->GetUptime(); } +int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval *tp) { + +} + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +struct timeval { + long tv_sec; + long tv_usec; +}; + +/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */ +static const unsigned __int64 epoch = 116444736000000000ULL; + +/* + * FILETIME represents the number of 100-nanosecond intervals since + * January 1, 1601 (UTC). + */ +#define FILETIME_UNITS_PER_SEC 10000000L +#define FILETIME_UNITS_PER_USEC 10 + +int PS4_SYSV_ABI gettimeofday(struct timeval * tp, struct timezone * tzp) { + FILETIME file_time; + ULARGE_INTEGER ularge; + + GetSystemTimePreciseAsFileTime(&file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC); + tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC) + / FILETIME_UNITS_PER_USEC); + + return 0; +} + +int PS4_SYSV_ABI usleep(u64 microseconds) { + std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); + return 0; +} + void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) { clock = std::make_unique(); initial_ptc = clock->GetUptime(); @@ -39,6 +97,9 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) { sceKernelGetProcessTimeCounterFrequency); LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc); LIB_FUNCTION("1j3S3n-tTW4", "libkernel", 1, "libkernel", 1, 1, sceKernelGetTscFrequency); + LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday); + LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday); + LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, usleep); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/time_management.h b/src/core/libraries/kernel/time_management.h index ad420f7c..f754921a 100644 --- a/src/core/libraries/kernel/time_management.h +++ b/src/core/libraries/kernel/time_management.h @@ -11,11 +11,17 @@ class SymbolsResolver; namespace Libraries::Kernel { +struct SceKernelTimeval { + time_t tv_sec; + s64 tv_usec; +}; + u64 PS4_SYSV_ABI sceKernelGetTscFrequency(); u64 PS4_SYSV_ABI sceKernelGetProcessTime(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency(); u64 PS4_SYSV_ABI sceKernelReadTsc(); +int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval *tp); void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 81248072..444c0f8e 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -87,7 +87,7 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) { } void Linker::LoadModuleToMemory(Module* m) { - // get elf header, program header + // Retrieve elf header and program header const auto elf_header = m->elf.GetElfHeader(); const auto elf_pheader = m->elf.GetProgramHeader(); @@ -383,9 +383,7 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) { } void Linker::LoadSymbols(Module* m) { - - const auto symbol_database = [this](Module* m, Loader::SymbolsResolver* symbol, - bool export_func) { + const auto symbol_database = [this, m](Loader::SymbolsResolver* symbol, bool export_func) { if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr || m->dynamic_info.symbol_table_total_size == 0) { LOG_INFO(Core_Linker, "Symbol table not found!"); @@ -442,8 +440,8 @@ void Linker::LoadSymbols(Module* m) { } } }; - symbol_database(m, &m->export_sym, true); - symbol_database(m, &m->import_sym, false); + symbol_database(&m->export_sym, true); + symbol_database(&m->import_sym, false); } void Linker::Relocate(Module* m) { @@ -550,7 +548,6 @@ bool contains(const std::vector& vecObj, const T& element) { Module* Linker::FindExportedModule(const ModuleInfo& module, const LibraryInfo& library) { // std::scoped_lock lock{m_mutex}; - for (auto& m : m_modules) { const auto& export_libs = m->dynamic_info.export_libs; const auto& export_modules = m->dynamic_info.export_modules; @@ -564,56 +561,53 @@ Module* Linker::FindExportedModule(const ModuleInfo& module, const LibraryInfo& void Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Module* m, Loader::SymbolRecord* return_info) { - // std::scoped_lock lock{m_mutex}; const auto ids = Common::SplitString(name, '#'); - if (ids.size() == 3) { - const auto* library = FindLibrary(*m, ids.at(1)); - const auto* module = FindModule(*m, ids.at(2)); - ASSERT_MSG(library && module, "Unable to find library and module"); - - Loader::SymbolResolver sr{}; - sr.name = ids.at(0); - sr.library = library->name; - sr.library_version = library->version; - sr.module = module->name; - sr.module_version_major = module->version_major; - sr.module_version_minor = module->version_minor; - sr.type = sym_type; - - const Loader::SymbolRecord* rec = nullptr; - - rec = m_hle_symbols.FindSymbol(sr); - if (rec == nullptr) { - // check if it an export function - if (auto* p = FindExportedModule(*module, *library); - p != nullptr && p->export_sym.GetSize() > 0) { - rec = p->export_sym.FindSymbol(sr); - } - } - if (rec != nullptr) { - *return_info = *rec; - } else { - auto aeronid = AeroLib::FindByNid(sr.name.c_str()); - if (aeronid) { - return_info->name = aeronid->name; - return_info->virtual_address = AeroLib::GetStub(aeronid->nid); - } else { - return_info->virtual_address = AeroLib::GetStub(sr.name.c_str()); - return_info->name = "Unknown !!!"; - } - LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name, - return_info->name, library->name, module->name); - } - } else { + if (ids.size() != 3) { return_info->virtual_address = 0; return_info->name = name; LOG_ERROR(Core_Linker, "Not Resolved {}", name); + return; } + + const auto* library = FindLibrary(*m, ids.at(1)); + const auto* module = FindModule(*m, ids.at(2)); + ASSERT_MSG(library && module, "Unable to find library and module"); + + Loader::SymbolResolver sr{}; + sr.name = ids.at(0); + sr.library = library->name; + sr.library_version = library->version; + sr.module = module->name; + sr.module_version_major = module->version_major; + sr.module_version_minor = module->version_minor; + sr.type = sym_type; + + const auto* record = m_hle_symbols.FindSymbol(sr); + if (!record) { + // Check if it an export function + if (auto* p = FindExportedModule(*module, *library); + p && p->export_sym.GetSize() > 0) { + record = p->export_sym.FindSymbol(sr); + } + } + if (record) { + *return_info = *record; + return; + } + + const auto aeronid = AeroLib::FindByNid(sr.name.c_str()); + if (aeronid) { + return_info->name = aeronid->name; + return_info->virtual_address = AeroLib::GetStub(aeronid->nid); + } else { + return_info->virtual_address = AeroLib::GetStub(sr.name.c_str()); + return_info->name = "Unknown !!!"; + } + LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name, + return_info->name, library->name, module->name); } u64 Linker::GetProcParam() { - // std::scoped_lock lock{m_mutex}; - for (auto& m : m_modules) { if (!m->elf.IsSharedLib()) { return m->proc_param_virtual_addr; @@ -621,18 +615,19 @@ u64 Linker::GetProcParam() { } return 0; } + using exit_func_t = PS4_SYSV_ABI void (*)(); using entry_func_t = PS4_SYSV_ABI void (*)(EntryParams* params, exit_func_t atexit_func); -using module_ini_func_t = PS4_SYSV_ABI int (*)(size_t args, const void* argp, module_func_t func); +using module_ini_func_t = PS4_SYSV_ABI int (*)(size_t args, const void* argp, ModuleFunc func); -static PS4_SYSV_ABI int run_module(uint64_t addr, size_t args, const void* argp, - module_func_t func) { +static PS4_SYSV_ABI int RunModule(uint64_t addr, size_t args, const void* argp, + ModuleFunc func) { return reinterpret_cast(addr)(args, argp, func); } -int Linker::StartModule(Module* m, size_t args, const void* argp, module_func_t func) { +int Linker::StartModule(Module* m, size_t args, const void* argp, ModuleFunc func) { LOG_INFO(Core_Linker, "Module started : {}", m->file_name); - return run_module(m->dynamic_info.init_virtual_addr + m->base_virtual_addr, args, argp, func); + return RunModule(m->dynamic_info.init_virtual_addr + m->base_virtual_addr, args, argp, func); } void Linker::StartAllModules() { @@ -694,7 +689,7 @@ void Linker::Execute() { continue; } if (m->tls.image_virtual_addr != 0) { - SetTLSStorage(m->tls.image_virtual_addr); + SetTLSStorage(m->tls.image_virtual_addr, m->tls.image_size); } RunMainEntry(m->elf.GetElfEntry() + m->base_virtual_addr, &p, ProgramExitFunc); } diff --git a/src/core/linker.h b/src/core/linker.h index ae730878..cd6065de 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -9,7 +9,7 @@ #include "core/loader/symbols_resolver.h" namespace Core { -using module_func_t = int (*)(size_t args, const void* argp); + struct DynamicModuleInfo; class Linker; @@ -56,7 +56,6 @@ struct LibraryInfo { struct PS4ThreadLocal { u64 image_virtual_addr = 0; u64 image_size = 0; - u64 handler_virtual_addr = 0; }; struct DynamicModuleInfo { @@ -103,27 +102,25 @@ struct DynamicModuleInfo { // This struct keeps neccesary info about loaded modules. Main executeable is included too as well struct Module { - Loader::Elf elf; u64 aligned_base_size = 0; - u64 base_virtual_addr = 0; - u64 proc_param_virtual_addr = 0; - + VAddr base_virtual_addr = 0; + VAddr proc_param_virtual_addr = 0; std::string file_name; - + Loader::Elf elf; std::vector m_dynamic; std::vector m_dynamic_data; DynamicModuleInfo dynamic_info{}; - Loader::SymbolsResolver export_sym; Loader::SymbolsResolver import_sym; - PS4ThreadLocal tls; }; +using ModuleFunc = int (*)(size_t, const void*); + class Linker { public: - Linker(); - virtual ~Linker(); + explicit Linker(); + ~Linker(); Module* LoadModule(const std::filesystem::path& elf_name); void LoadModuleToMemory(Module* m); @@ -143,7 +140,7 @@ private: const ModuleInfo* FindModule(const Module& m, const std::string& id); const LibraryInfo* FindLibrary(const Module& program, const std::string& id); Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); - int StartModule(Module* m, size_t args, const void* argp, module_func_t func); + int StartModule(Module* m, size_t args, const void* argp, ModuleFunc func); void StartAllModules(); std::vector> m_modules; diff --git a/src/core/loader/symbols_resolver.cpp b/src/core/loader/symbols_resolver.cpp index d573fc37..86537208 100644 --- a/src/core/loader/symbols_resolver.cpp +++ b/src/core/loader/symbols_resolver.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/io_file.h" -#include "common/logging/log.h" #include "common/string_util.h" #include "common/types.h" #include "core/aerolib/aerolib.h" @@ -52,8 +51,4 @@ void SymbolsResolver::DebugDump(const std::filesystem::path& file_name) { } } -int SymbolsResolver::GetSize() { - return m_symbols.size(); -} - } // namespace Core::Loader diff --git a/src/core/loader/symbols_resolver.h b/src/core/loader/symbols_resolver.h index e02e9e8b..afd4bddb 100644 --- a/src/core/loader/symbols_resolver.h +++ b/src/core/loader/symbols_resolver.h @@ -3,8 +3,8 @@ #pragma once +#include #include -#include #include #include "common/types.h" @@ -42,6 +42,10 @@ public: void AddSymbol(const SymbolResolver& s, u64 virtual_addr); const SymbolRecord* FindSymbol(const SymbolResolver& s) const; + size_t GetSize() const noexcept { + return m_symbols.size(); + } + static std::string GenerateName(const SymbolResolver& s); static std::string_view SymbolTypeToS(SymbolType sym_type) { @@ -60,7 +64,6 @@ public: } void DebugDump(const std::filesystem::path& file_name); - int GetSize(); private: std::vector m_symbols; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 06fde132..18d8f1a3 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -99,7 +99,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M } // Perform the mapping. - *out_addr = impl.Map(mapped_addr, size); + *out_addr = impl.Map(mapped_addr, size, alignment, phys_addr); return ORBIS_OK; } diff --git a/src/core/memory.h b/src/core/memory.h index ab9006a4..7a623db7 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -107,7 +107,7 @@ public: int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name = "", - PAddr phys_addr = 0, u64 alignment = 0); + PAddr phys_addr = -1, u64 alignment = 0); void UnmapMemory(VAddr virtual_addr, size_t size); @@ -121,7 +121,7 @@ private: VMAHandle FindVMA(VAddr target) { // Return first the VMA with base >= target. const auto it = vma_map.lower_bound(target); - if (it->first == target) { + if (it != vma_map.end() && it->first == target) { return it; } return std::prev(it); diff --git a/src/core/tls.cpp b/src/core/tls.cpp index b945baef..a524970f 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -43,11 +43,20 @@ constexpr static TLSPattern TlsPatterns[] = { #ifdef _WIN32 static DWORD slot = 0; +u8* tls_memory{}; +u64 tls_image{}; +u32 tls_image_size{}; -void SetTLSStorage(u64 image_address) { +void SetTLSStorage(u64 image_address, u32 image_size) { // Guest apps will use both positive and negative offsets to the TLS pointer. // User data at probably in negative offsets, while pthread data at positive offset. - const BOOL result = TlsSetValue(slot, reinterpret_cast(image_address)); + if (tls_image == 0) { + tls_image = image_address; + tls_image_size = image_size; + } + tls_memory = (u8*)std::malloc(tls_image_size + 8192); + std::memcpy(tls_memory, reinterpret_cast(tls_image), tls_image_size); + const BOOL result = TlsSetValue(slot, tls_memory + tls_image_size); ASSERT(result != 0); } @@ -81,6 +90,7 @@ void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) { std::memcpy(&offset, code + tls_pattern.pattern_size, sizeof(u64)); LOG_INFO(Core_Linker, "PATTERN64 FOUND at {}, reg: {} offset: {:#x}", fmt::ptr(code), tls_pattern.target_reg, offset); + continue; } ASSERT(offset == 0); diff --git a/src/core/tls.h b/src/core/tls.h index e9825bf6..5b2487fc 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -12,9 +12,14 @@ class CodeGenerator; namespace Core { /// Sets the data pointer that contains the TLS image. -void SetTLSStorage(u64 image_address); +void SetTLSStorage(u64 image_address, u32 image_size); /// Patches any instructions that access guest TLS to use provided storage. void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c); +class ThreadLocalStorage { +public: + +}; + } // namespace Core