From fdac55a5ef350e3534f7e5bf25dfdf0dd489ad47 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 4 Oct 2026 20:28:22 +0400 Subject: [PATCH] loader: load libc automatically at startup --- src/loader/runtimeLinker.cpp | 162 ++--------------------------------- src/loader/runtimeLinker.h | 11 +-- 2 files changed, 11 insertions(+), 162 deletions(-) diff --git a/src/loader/runtimeLinker.cpp b/src/loader/runtimeLinker.cpp index 721382a82..3114f2392 100644 --- a/src/loader/runtimeLinker.cpp +++ b/src/loader/runtimeLinker.cpp @@ -13,6 +13,7 @@ #include "common/threads.h" #include "common/virtualMemory.h" #include "graphics/host_gpu/pageManager.h" +#include "kernel/fileSystem.h" #include "kernel/memory.h" #include "kernel/pthread.h" #include "loader/elf.h" @@ -1264,7 +1265,9 @@ void RuntimeLinker::Execute(const std::filesystem::path& game_patch) { } #endif - PreloadAdjacentPrograms(); + // The runtime automatically loads libc; other PRXs are requested by the application. + const auto libc_path = Libs::LibKernel::FileSystem::GetRealFilename("/app0/sce_module/libc.prx"); + auto* libc = Common::File::IsFileExisting(libc_path) ? LoadProgram(libc_path) : nullptr; RelocateAll(); if (!game_patch.empty()) { @@ -1273,7 +1276,9 @@ void RuntimeLinker::Execute(const std::filesystem::path& game_patch) { EXIT("Failed to apply game cheat\n"); } } - StartAllModules(); + if (libc != nullptr && libc->dynamic_info->init_vaddr != 0) { + StartModule(libc, 0, nullptr, nullptr); + } LOGF_COLOR(Log::Color::BrightYellow, "---\n--- Execute: %s\n---\n", "Main"); @@ -1526,84 +1531,6 @@ void RuntimeLinker::StackTrace(uint64_t frame_ptr, uint64_t stack_ptr) { } } -static std::string GetProgramModuleName(const Program* program) { - EXIT_IF(program == nullptr); - - if (program->dynamic_info != nullptr && program->dynamic_info->so_name != nullptr && - program->dynamic_info->so_name[0] != '\0') { - return std::string(program->dynamic_info->so_name); - } - - return Common::FilenameWithoutDirectory(Common::PathToGenericString(program->file_name)); -} - -static bool ModuleStartDependenciesSatisfied(const Program* program, - const std::vector& programs, - const std::vector& started) { - EXIT_IF(program == nullptr); - EXIT_IF(program->dynamic_info == nullptr); - - for (const auto* needed: program->dynamic_info->needed) { - if (needed == nullptr || needed[0] == '\0') { - continue; - } - - const auto needed_name = std::string(needed); - - for (auto* dependency: programs) { - if (dependency == nullptr || dependency == program || dependency->elf == nullptr || - !dependency->elf->IsShared()) { - continue; - } - - const auto dependency_name = GetProgramModuleName(dependency); - if (Common::EqualNoCase(dependency_name, needed_name) || - Common::EqualNoCase(Common::FilenameWithoutDirectory( - Common::PathToGenericString(dependency->file_name)), - needed_name)) { - if (std::find(started.begin(), started.end(), dependency) == started.end()) { - return false; - } - break; - } - } - } - - return true; -} - -void RuntimeLinker::StartAllModules() { - Common::LockGuard lock(m_mutex); - - std::vector started; - - for (;;) { - bool progressed = false; - - for (auto* p: m_programs) { - if (p->elf->IsShared() && p->dynamic_info->init_vaddr != 0 && - std::find(started.begin(), started.end(), p) == started.end() && - ModuleStartDependenciesSatisfied(p, m_programs, started)) { - StartModule(p, 0, nullptr, nullptr); - started.push_back(p); - progressed = true; - } - } - - if (!progressed) { - break; - } - } - - for (auto* p: m_programs) { - if (p->elf->IsShared() && p->dynamic_info->init_vaddr != 0 && - std::find(started.begin(), started.end(), p) == started.end()) { - StartModule(p, 0, nullptr, nullptr); - started.push_back(p); - } - } -} - void RuntimeLinker::StopAllModules() { Common::LockGuard lock(m_mutex); @@ -1614,75 +1541,6 @@ void RuntimeLinker::StopAllModules() { } } -static bool IsAdjacentModuleFile(const std::string& name) { - auto lower = Common::ToLower(name); - return lower.ends_with(".prx") || lower.ends_with(".sprx"); -} - -static bool SkipAdjacentModuleFile(const std::string& name) { - auto lower = Common::ToLower(name); - return lower == "eboot.bin" || lower == "libkernel.prx" || lower == "libkernel_sys.prx"; -} - -void RuntimeLinker::PreloadAdjacentPrograms() { - if (m_programs.empty()) { - return; - } - - std::vector module_paths; - - auto is_loaded = [this](const std::filesystem::path& path) { - auto fixed_path = Common::FixFilenameSlash(Common::PathToGenericString(path)); - for (auto* program: m_programs) { - if (Common::EqualNoCase( - Common::FixFilenameSlash(Common::PathToGenericString(program->file_name)), - fixed_path)) { - return true; - } - } - return false; - }; - - auto add_path = [&module_paths, &is_loaded](const std::filesystem::path& path) { - if (is_loaded(path)) { - return; - } - for (const auto& p: module_paths) { - if (Common::EqualNoCase(Common::PathToGenericString(p), - Common::PathToGenericString(path))) { - return; - } - } - module_paths.push_back(path); - }; - - auto add_dir = [&add_path](const std::filesystem::path& dir) { - if (!Common::File::IsDirectoryExisting(dir)) { - return; - } - for (const auto& entry: Common::File::GetDirEntries(dir)) { - if (entry.is_file && IsAdjacentModuleFile(entry.name) && - !SkipAdjacentModuleFile(entry.name)) { - add_path(dir / entry.name); - } - } - }; - - auto root = m_programs.at(0)->file_name.parent_path(); - if (root.empty()) { - return; - } - - add_dir(root); - add_dir(root / "sce_module"); - add_dir(root / "sce_modules"); - - for (const auto& path: module_paths) { - auto* program = LoadProgram(path); - program->fail_if_global_not_resolved = false; - } -} - int RuntimeLinker::StartModule(Program* program, size_t args, const void* argp, module_func_t func) { EXIT_IF(program == nullptr); @@ -2099,12 +1957,6 @@ void RuntimeLinker::ParseProgramDynamicInfo(Program* program) { EXIT_NOT_IMPLEMENTED(program->dynamic_info->debug != 0); EXIT_NOT_IMPLEMENTED(program->dynamic_info->textrel != 0); - std::vector needed; - GetDynValues(elf, &needed, DT_NEEDED); - for (auto need: needed) { - program->dynamic_info->needed.push_back(program->dynamic_info->str_table + need); - } - uint64_t so_name = 0; GetDynValue(elf, &so_name, DT_SONAME); program->dynamic_info->so_name = program->dynamic_info->str_table + so_name; diff --git a/src/loader/runtimeLinker.h b/src/loader/runtimeLinker.h index 7be2aaeb0..151f9b44d 100644 --- a/src/loader/runtimeLinker.h +++ b/src/loader/runtimeLinker.h @@ -102,11 +102,10 @@ struct DynamicInfo { const char* so_name = nullptr; - std::vector needed; - std::vector export_modules; - std::vector import_modules; - std::vector export_libs; - std::vector import_libs; + std::vector export_modules; + std::vector import_modules; + std::vector export_libs; + std::vector import_libs; }; struct Program { @@ -157,7 +156,6 @@ public: void Execute(const std::filesystem::path& game_patch = {}); int StartModule(Program* program, size_t args, const void* argp, module_func_t func); int StopModule(Program* program, size_t args, const void* argp, module_func_t func); - void StartAllModules(); void StopAllModules(); void DeleteTlss(int thread_id); void SetApplicationHeapApi(void* const api[10]); @@ -186,7 +184,6 @@ private: static void Relocate(Program* program); static void DeleteProgram(Program* program); static void SetupTlsHandler(Program* program); - void PreloadAdjacentPrograms(); static const ModuleId* FindModule(const Program& program, const std::string& id); static const LibraryId* FindLibrary(const Program& program, const std::string& id);