diff --git a/src/common/config.cpp b/src/common/config.cpp index 96c71c4f..6040df53 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -15,7 +15,11 @@ u32 screenHeight = 720; std::string logFilter; std::string logType = "sync"; bool isDebugDump = false; +bool isLibc = true; +bool isLleLibc() { + return isLibc; +} bool isNeoMode() { return isNeo; } @@ -84,6 +88,14 @@ void load(const std::filesystem::path& path) { isDebugDump = toml::find_or(debug, "DebugDump", false); } } + if (data.contains("LLE")) { + auto lleResult = toml::expect(data.at("LLE")); + if (lleResult.is_ok()) { + auto lle = lleResult.unwrap(); + + isLibc = toml::find_or(lle, "libc", true); + } + } } void save(const std::filesystem::path& path) { toml::basic_value data; @@ -110,6 +122,7 @@ void save(const std::filesystem::path& path) { data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; data["Debug"]["DebugDump"] = isDebugDump; + data["LLE"]["libc"] = isLibc; std::ofstream file(path, std::ios::out); file << data; diff --git a/src/common/config.h b/src/common/config.h index 114ef55f..b69c43b4 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -18,5 +18,6 @@ u32 getScreenWidth(); u32 getScreenHeight(); bool debugDump(); +bool isLleLibc(); }; // namespace Config diff --git a/src/core/hle/kernel/memory_management.cpp b/src/core/hle/kernel/memory_management.cpp index 9491b4a3..d6aa8cdb 100644 --- a/src/core/hle/kernel/memory_management.cpp +++ b/src/core/hle/kernel/memory_management.cpp @@ -85,6 +85,9 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl GPU::MemoryMode gpu_mode = GPU::MemoryMode::NoAccess; switch (prot) { + case 0x03: + cpu_mode = VirtualMemory::MemoryMode::ReadWrite; + break; case 0x32: case 0x33: // SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL cpu_mode = VirtualMemory::MemoryMode::ReadWrite; diff --git a/src/core/hle/libraries/libkernel/libkernel.cpp b/src/core/hle/libraries/libkernel/libkernel.cpp index 8fbeb2d0..e666d6a3 100644 --- a/src/core/hle/libraries/libkernel/libkernel.cpp +++ b/src/core/hle/libraries/libkernel/libkernel.cpp @@ -19,11 +19,18 @@ #else #include #endif +#include +#include namespace Core::Libraries::LibKernel { static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return +static void* PS4_SYSV_ABI sceKernelGetProcParam() { + auto* linker = Common::Singleton::Instance(); + return reinterpret_cast(linker->GetProcParam()); +} + int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) { UNREACHABLE(); return 0; @@ -117,6 +124,23 @@ PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, return ptr; } +static uint64_t g_mspace_atomic_id_mask = 0; +static uint64_t g_mstate_table[64] = {0}; + +struct HeapInfoInfo { + uint64_t size = sizeof(HeapInfoInfo); + uint32_t flag; + uint32_t getSegmentInfo; + uint64_t* mspace_atomic_id_mask; + uint64_t* mstate_table; +}; + +void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) { + info->mspace_atomic_id_mask = &g_mspace_atomic_id_mask; + info->mstate_table = g_mstate_table; + info->getSegmentInfo = 0; +} + void LibKernel_Register(Loader::SymbolsResolver* sym) { // obj LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); @@ -139,10 +163,15 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) { LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap); LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep); LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev); + LIB_FUNCTION("959qrazPIrg", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcParam); Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym); Core::Libraries::LibKernel::timeSymbolsRegister(sym); Core::Libraries::LibKernel::pthreadSymbolsRegister(sym); + + // temp + LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1, + sceLibcHeapGetTraceInfo); } } // namespace Core::Libraries::LibKernel diff --git a/src/core/hle/libraries/libkernel/thread_management.cpp b/src/core/hle/libraries/libkernel/thread_management.cpp index 343a64a8..771391d5 100644 --- a/src/core/hle/libraries/libkernel/thread_management.cpp +++ b/src/core/hle/libraries/libkernel/thread_management.cpp @@ -187,7 +187,6 @@ void* createMutex(void* addr) { int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, const char* name) { - LOG_INFO(Kernel_Pthread, "called"); if (mutex == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -329,6 +328,23 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { } } +int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) { + + int result = pthread_mutexattr_destroy(&(*attr)->pth_mutex_attr); + + delete *attr; + *attr = nullptr; + + switch (result) { + case 0: + return SCE_OK; + case ENOMEM: + return SCE_KERNEL_ERROR_ENOMEM; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + void* createCond(void* addr) { if (addr == nullptr || *static_cast(addr) != nullptr) { return addr; @@ -470,6 +486,7 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) { // mutex calls LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit); LIB_FUNCTION("F8bUHwAG284", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrInit); + LIB_FUNCTION("smWEktiyyG0", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrDestroy); LIB_FUNCTION("iMp8QpE+XO4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSettype); LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol); LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock); diff --git a/src/core/hle/libraries/libs.cpp b/src/core/hle/libraries/libs.cpp index 28594471..88184fe9 100644 --- a/src/core/hle/libraries/libs.cpp +++ b/src/core/hle/libraries/libs.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "core/PS4/HLE/Graphics/video_out.h" #include "core/hle/libraries/libc/libc.h" #include "core/hle/libraries/libkernel/libkernel.h" @@ -20,7 +21,9 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { HLE::Libs::Graphics::VideoOut::videoOutRegisterLib(sym); Core::Libraries::LibSceGnmDriver::LibSceGnmDriver_Register(sym); OldLibraries::LibPad::padSymbolsRegister(sym); - Core::Libraries::LibC::libcSymbolsRegister(sym); + if (!Config::isLleLibc()) { + Core::Libraries::LibC::libcSymbolsRegister(sym); + } // new libraries folder from autogen Libraries::UserService::RegisterlibSceUserService(sym); diff --git a/src/core/libraries/libscesystemservice.cpp b/src/core/libraries/libscesystemservice.cpp index becee8a2..67490951 100644 --- a/src/core/libraries/libscesystemservice.cpp +++ b/src/core/libraries/libscesystemservice.cpp @@ -1883,7 +1883,7 @@ int PS4_SYSV_ABI sceSystemServiceNavigateToGoHome() { s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(int param_id, int* value) { // TODO this probably should be stored in config for UI configuration - LOG_INFO(Lib_SystemService, "called"); + LOG_INFO(Lib_SystemService, "called param_id {}", param_id); if (value == nullptr) { LOG_ERROR(Lib_SystemService, "value is null"); return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER; diff --git a/src/core/libraries/libsceuserservice.cpp b/src/core/libraries/libsceuserservice.cpp index 9a9adbbd..f3966756 100644 --- a/src/core/libraries/libsceuserservice.cpp +++ b/src/core/libraries/libsceuserservice.cpp @@ -1031,7 +1031,7 @@ int PS4_SYSV_ABI sceUserServiceGetTraditionalChineseInputType() { s32 PS4_SYSV_ABI sceUserServiceGetUserColor(int user_id, int* color) { // TODO fix me better - LOG_INFO(Lib_UserService, "called"); + LOG_INFO(Lib_UserService, "called user_id = {}", user_id); if (color == nullptr) { LOG_ERROR(Lib_UserService, "color is null"); return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; @@ -1056,6 +1056,7 @@ int PS4_SYSV_ABI sceUserServiceGetUserGroupNum() { } s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::size_t size) { + LOG_INFO(Lib_UserService, "called user_id = {} ,size = {} ", user_id, size); if (user_name == nullptr) { LOG_ERROR(Lib_UserService, "user_name is null"); return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; @@ -1110,7 +1111,7 @@ int PS4_SYSV_ABI sceUserServiceGetVolumeForSidetone() { } s32 PS4_SYSV_ABI sceUserServiceInitialize(const OrbisUserServiceInitializeParams* initParams) { - LOG_ERROR(Lib_UserService, "(STUBBED) called"); + LOG_WARNING(Lib_UserService, "(dummy) called"); return ORBIS_OK; } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 58baf966..ba38d412 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/config.h" #include "common/logging/log.h" #include "common/path_util.h" @@ -15,7 +16,8 @@ namespace Core { -static constexpr u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET; +static u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET; +static constexpr u64 CODE_BASE_INCR = 0x010000000u; static u64 GetAlignedSize(const elf_program_header& phdr) { return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1) @@ -74,7 +76,6 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) { LoadModuleToMemory(m.get()); LoadDynamicInfo(m.get()); LoadSymbols(m.get()); - Relocate(m.get()); } else { m_modules.pop_back(); return nullptr; // It is not a valid elf file //TODO check it why! @@ -83,14 +84,6 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) { return m.get(); } -Module* Linker::FindModule(u32 id) { - // TODO atm we only have 1 module so we don't need to iterate on vector - if (m_modules.empty()) [[unlikely]] { - return nullptr; - } - return m_modules[0].get(); -} - void Linker::LoadModuleToMemory(Module* m) { // get elf header, program header const auto elf_header = m->elf.GetElfHeader(); @@ -104,6 +97,8 @@ void Linker::LoadModuleToMemory(Module* m) { m->base_virtual_addr = VirtualMemory::memory_alloc(LoadAddress, m->aligned_base_size, VirtualMemory::MemoryMode::ExecuteReadWrite); + LoadAddress += CODE_BASE_INCR * (1 + m->aligned_base_size / CODE_BASE_INCR); + LOG_INFO(Core_Linker, "====Load Module to Memory ========"); LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr); LOG_INFO(Core_Linker, "base_size ..............: {:#018x}", base_size); @@ -161,6 +156,9 @@ void Linker::LoadModuleToMemory(Module* m) { LOG_INFO(Core_Linker, "tls virtual address ={:#x}", m->tls.image_virtual_addr); LOG_INFO(Core_Linker, "tls image size ={}", m->tls.image_size); break; + case PT_SCE_PROCPARAM: + m->proc_param_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr; + break; default: LOG_ERROR(Core_Linker, "Unimplemented type {}", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); @@ -378,101 +376,67 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) { } void Linker::LoadSymbols(Module* m) { - 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!"); - return; - } - for (auto* sym = m->dynamic_info.symbol_table; - reinterpret_cast(sym) < - reinterpret_cast(m->dynamic_info.symbol_table) + - m->dynamic_info.symbol_table_total_size; - sym++) { - std::string id = std::string(m->dynamic_info.str_table + sym->st_name); - const auto ids = Common::SplitString(id, '#'); - if (ids.size() == 3) // symbols are 3 parts name , library , module - { - const auto* library = FindLibrary(*m, ids.at(1)); - const auto* module = FindModule(*m, ids.at(2)); + const auto symbol_database = [this](Module* 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!"); + return; + } + for (auto* sym = m->dynamic_info.symbol_table; + reinterpret_cast(sym) < reinterpret_cast(m->dynamic_info.symbol_table) + + m->dynamic_info.symbol_table_total_size; + sym++) { + std::string id = std::string(m->dynamic_info.str_table + sym->st_name); auto bind = sym->GetBind(); auto type = sym->GetType(); auto visibility = sym->GetVisibility(); - if (library != nullptr || module != nullptr) { - switch (bind) { - case STB_GLOBAL: - case STB_WEAK: - break; - default: - LOG_INFO(Core_Linker, "Unsupported bind {} for name symbol {}", bind, - ids.at(0)); - continue; + const auto ids = Common::SplitString(id, '#'); + 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"); + if ((bind == STB_GLOBAL || bind == STB_WEAK) && + (type == STT_FUN || type == STT_OBJECT) && + export_func == (sym->st_value != 0)) { + std::string nidName = ""; + auto aeronid = AeroLib::FindByNid(ids.at(0).c_str()); + if (aeronid != nullptr) { + nidName = aeronid->name; + } else { + nidName = "UNK"; + } + Loader::SymbolResolver sym_r{}; + sym_r.name = ids.at(0); + sym_r.nidName = nidName; + sym_r.library = library->name; + sym_r.library_version = library->version; + sym_r.module = module->name; + sym_r.module_version_major = module->version_major; + sym_r.module_version_minor = module->version_minor; + switch (type) { + case STT_NOTYPE: + sym_r.type = Loader::SymbolType::NoType; + break; + case STT_FUN: + sym_r.type = Loader::SymbolType::Function; + break; + case STT_OBJECT: + sym_r.type = Loader::SymbolType::Object; + break; + default: + sym_r.type = Loader::SymbolType::Unknown; + break; + } + symbol->AddSymbol(sym_r, + (export_func ? sym->st_value + m->base_virtual_addr : 0)); } - switch (type) { - case STT_OBJECT: - case STT_FUN: - break; - default: - LOG_INFO(Core_Linker, "Unsupported type {} for name symbol {}", type, - ids.at(0)); - continue; - } - switch (visibility) { - case STV_DEFAULT: - break; - default: - LOG_INFO(Core_Linker, "Unsupported visibility {} for name symbol {}", - visibility, ids.at(0)); - continue; - } - // if st_value!=0 then it's export symbol - bool is_sym_export = sym->st_value != 0; - std::string nidName = ""; - - auto aeronid = AeroLib::FindByNid(ids.at(0).c_str()); - - if (aeronid != nullptr) { - nidName = aeronid->name; - } else { - nidName = "UNK"; - } - - Loader::SymbolResolver sym_r{}; - sym_r.name = ids.at(0); - sym_r.nidName = nidName; - sym_r.library = library->name; - sym_r.library_version = library->version; - sym_r.module = module->name; - sym_r.module_version_major = module->version_major; - sym_r.module_version_minor = module->version_minor; - switch (type) { - case STT_NOTYPE: - sym_r.type = Loader::SymbolType::NoType; - break; - case STT_FUN: - sym_r.type = Loader::SymbolType::Function; - break; - case STT_OBJECT: - sym_r.type = Loader::SymbolType::Object; - break; - default: - sym_r.type = Loader::SymbolType::Unknown; - break; - } - - if (is_sym_export) { - m->export_sym.AddSymbol(sym_r, sym->st_value + m->base_virtual_addr); - } else { - m->import_sym.AddSymbol(sym_r, 0); - } - - LOG_INFO(Core_Linker, - "name = {}, function = {}, library = {}, module = {}, bind = {}, type = " - "{}, visibility = {}", - ids.at(0), nidName, library->name, module->name, bind, type, visibility); } } - } + }; + symbol_database(m, &m->export_sym, true); + symbol_database(m, &m->import_sym, false); } void Linker::Relocate(Module* m) { @@ -492,17 +456,18 @@ void Linker::Relocate(Module* m) { switch (type) { case R_X86_64_RELATIVE: - if (symbol != 0) // should be always zero - { - // LOG_INFO(Core_Linker, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, - // symbol);//found it openorbis but i am not sure it worth logging - } rel_value = rel_base_virtual_addr + addend; rel_isResolved = true; break; - case R_X86_64_64: - case R_X86_64_JUMP_SLOT: // similar but addend is not take into account - { + case R_X86_64_DTPMOD64: + rel_value = reinterpret_cast(m); + rel_isResolved = true; + rel_sym_type = Loader::SymbolType::Tls; + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + addend = 0; + case R_X86_64_64: { auto sym = symbolsTlb[symbol]; auto sym_bind = sym.GetBind(); auto sym_type = sym.GetType(); @@ -516,36 +481,32 @@ void Linker::Relocate(Module* m) { case STT_OBJECT: rel_sym_type = Loader::SymbolType::Object; break; + case STT_NOTYPE: + rel_sym_type = Loader::SymbolType::NoType; + break; default: - LOG_INFO(Core_Linker, "unknown symbol type {}", sym_type); + ASSERT_MSG(0, "unknown symbol type {}", sym_type); } if (sym_visibility != 0) // should be zero log if else { LOG_INFO(Core_Linker, "symbol visilibity !=0"); } switch (sym_bind) { + case STB_LOCAL: + symbol_vitrual_addr = rel_base_virtual_addr + sym.st_value; + break; case STB_GLOBAL: + case STB_WEAK: { rel_name = namesTlb + sym.st_name; Resolve(rel_name, rel_sym_type, m, &symrec); symbol_vitrual_addr = symrec.virtual_address; - rel_isResolved = (symbol_vitrual_addr != 0); - - rel_name = symrec.name; - if (type == R_X86_64_JUMP_SLOT) { - addend = 0; - } - rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); - if (!rel_isResolved) { - LOG_INFO(Core_Linker, - "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : " - "{:#010x}", - sym_type, symbol); - } - break; + } break; default: - LOG_INFO(Core_Linker, "UNK bind {}", sym_bind); + ASSERT_MSG(0, "unknown bind type {}", sym_bind); } - + rel_isResolved = (symbol_vitrual_addr != 0); + rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); + rel_name = symrec.name; } break; default: LOG_INFO(Core_Linker, "UNK type {:#010x} rel symbol : {:#010x}", type, symbol); @@ -574,51 +535,104 @@ void Linker::Relocate(Module* m) { } } -void Linker::Resolve(const std::string& name, Loader::SymbolType Symtype, Module* m, - Loader::SymbolRecord* return_info) { - const auto ids = Common::SplitString(name, '#'); - if (ids.size() == 3) // symbols are 3 parts name , library , module - { - const auto* library = FindLibrary(*m, ids.at(1)); - const auto* module = FindModule(*m, ids.at(2)); +template +bool contains(const std::vector& vecObj, const T& element) { + auto it = std::find(vecObj.begin(), vecObj.end(), element); + return it != vecObj.end(); +} - if (library != nullptr && module != nullptr) { - 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 = Symtype; +Module* Linker::FindExportedModule(const ModuleInfo& module, const LibraryInfo& library) { + // std::scoped_lock lock{m_mutex}; - const Loader::SymbolRecord* rec = nullptr; - rec = m_hle_symbols.FindSymbol(sr); + for (auto& m : m_modules) { + const auto& export_libs = m->dynamic_info.export_libs; + const auto& export_modules = m->dynamic_info.export_modules; - 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 { - //__debugbreak();//den tha prepei na ftasoume edo + if (contains(export_libs, library) && contains(export_modules, module)) { + return m.get(); } + } + return nullptr; +} + +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, '#'); + ASSERT_MSG(ids.size() == 3, "Symbols must be 3 parts name, library, module"); + + 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 { - //__debugbreak();//oute edo mallon + 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; + } + } + 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); + +static PS4_SYSV_ABI int run_module(uint64_t addr, size_t args, const void* argp, + module_func_t func) { + return reinterpret_cast(addr)(args, argp, func); +} + +int Linker::StartModule(Module* m, size_t args, const void* argp, module_func_t 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); +} + +void Linker::StartAllModules() { + std::scoped_lock lock{m_mutex}; + + for (auto& m : m_modules) { + if (m->elf.IsSharedLib()) { + StartModule(m.get(), 0, nullptr, nullptr); + } + } +} static PS4_SYSV_ABI void ProgramExitFunc() { fmt::print("exit function called\n"); @@ -653,12 +667,20 @@ void Linker::Execute() { } Core::Libraries::LibKernel::pthreadInitSelfMainThread(); + // relocate all modules + for (const auto& m : m_modules) { + Relocate(m.get()); + } + StartAllModules(); EntryParams p{}; p.argc = 1; p.argv[0] = "eboot.bin"; // hmm should be ok? - const auto& module = m_modules.at(0); - RunMainEntry(module->elf.GetElfEntry() + module->base_virtual_addr, &p, ProgramExitFunc); + for (auto& m : m_modules) { + if (!m->elf.IsSharedLib()) { + RunMainEntry(m->elf.GetElfEntry() + m->base_virtual_addr, &p, ProgramExitFunc); + } + } } void Linker::DebugDump() { diff --git a/src/core/linker.h b/src/core/linker.h index 9d97648a..ae730878 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; @@ -20,6 +20,10 @@ struct EntryParams { }; struct ModuleInfo { + bool operator==(const ModuleInfo& other) const { + return version_major == other.version_major && version_minor == other.version_minor && + name == other.name; + } std::string name; union { u64 value; @@ -34,6 +38,9 @@ struct ModuleInfo { }; struct LibraryInfo { + bool operator==(const LibraryInfo& other) const { + return version == other.version && name == other.name; + } std::string name; union { u64 value; @@ -99,6 +106,7 @@ struct Module { Loader::Elf elf; u64 aligned_base_size = 0; u64 base_virtual_addr = 0; + u64 proc_param_virtual_addr = 0; std::string file_name; @@ -118,7 +126,6 @@ public: virtual ~Linker(); Module* LoadModule(const std::filesystem::path& elf_name); - Module* FindModule(u32 id = 0); void LoadModuleToMemory(Module* m); void LoadDynamicInfo(Module* m); void LoadSymbols(Module* m); @@ -130,10 +137,14 @@ public: Loader::SymbolRecord* return_info); void Execute(); void DebugDump(); + u64 GetProcParam(); 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); + void StartAllModules(); std::vector> m_modules; Loader::SymbolsResolver m_hle_symbols{}; diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 2e6dd60d..0b58880a 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -538,4 +538,8 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) { UNREACHABLE(); } +bool Elf::IsSharedLib() { + return m_elf_header.e_type == ET_SCE_DYNAMIC; +} + } // namespace Core::Loader diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 3a8df6be..b2d2ea59 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -490,6 +490,7 @@ public: std::string ElfPheaderFlagsStr(u32 flags); void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size); + bool IsSharedLib(); private: Common::FS::IOFile m_f{}; diff --git a/src/core/loader/symbols_resolver.cpp b/src/core/loader/symbols_resolver.cpp index 085e061c..d573fc37 100644 --- a/src/core/loader/symbols_resolver.cpp +++ b/src/core/loader/symbols_resolver.cpp @@ -11,10 +11,9 @@ namespace Core::Loader { void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) { - SymbolRecord r{}; + SymbolRecord& r = m_symbols.emplace_back(); r.name = GenerateName(s); r.virtual_address = virtual_addr; - m_symbols.push_back(r); } std::string SymbolsResolver::GenerateName(const SymbolResolver& s) { @@ -25,12 +24,12 @@ std::string SymbolsResolver::GenerateName(const SymbolResolver& s) { const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolResolver& s) const { const std::string name = GenerateName(s); for (u32 i = 0; i < m_symbols.size(); i++) { - if (m_symbols[i].name.compare(name) == 0) { + if (m_symbols[i].name == name) { return &m_symbols[i]; } } - LOG_INFO(Core_Linker, "Unresolved! {}", name); + // LOG_INFO(Core_Linker, "Unresolved! {}", name); return nullptr; } @@ -46,10 +45,15 @@ void SymbolsResolver::DebugDump(const std::filesystem::path& file_name) { } else { nidName = "UNK"; } - f.WriteString(fmt::format("{:<20} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n", - symbol.virtual_address, ids.at(0), nidName, ids.at(1), ids.at(2), - ids.at(3), ids.at(4), ids.at(5), ids.at(6))); + f.WriteString( + fmt::format("0x{:<20x} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n", + symbol.virtual_address, ids.at(0), nidName, ids.at(1), ids.at(2), ids.at(3), + ids.at(4), ids.at(5), ids.at(6))); } } +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 09428daf..e02e9e8b 100644 --- a/src/core/loader/symbols_resolver.h +++ b/src/core/loader/symbols_resolver.h @@ -60,6 +60,7 @@ public: } void DebugDump(const std::filesystem::path& file_name); + int GetSize(); private: std::vector m_symbols; diff --git a/src/main.cpp b/src/main.cpp index ec236bd3..92058541 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include "common/config.h" #include "common/discord.h" @@ -49,6 +51,25 @@ int main(int argc, char* argv[]) { OldLibraries::InitHLELibs(&linker->getHLESymbols()); Core::InstallTlsHandler(); linker->LoadModule(path); + // check if there is a libc.prx in sce_module folder + bool found = false; + if (Config::isLleLibc()) { + std::filesystem::path sce_module_folder = p.parent_path() / "sce_module"; + if (std::filesystem::is_directory(sce_module_folder)) { + for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) { + if (entry.path().filename() == "libc.prx" || + entry.path().filename() == "libSceFios2.prx") { + found = true; + LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); + linker->LoadModule(entry.path().string().c_str()); + } + } + } + } + if (!found) // load HLE libc + { + Core::Libraries::LibC::libcSymbolsRegister(&linker->getHLESymbols()); + } std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); }, nullptr); Discord::RPC discordRPC;