loader: load libc automatically at startup

This commit is contained in:
nmzik
2026-10-04 20:28:22 +04:00
parent 719e02574a
commit fdac55a5ef
2 changed files with 11 additions and 162 deletions
+7 -155
View File
@@ -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<Program*>& programs,
const std::vector<Program*>& 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<Program*> 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<std::filesystem::path> 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<uint64_t> 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;
+4 -7
View File
@@ -102,11 +102,10 @@ struct DynamicInfo {
const char* so_name = nullptr;
std::vector<const char*> needed;
std::vector<ModuleId> export_modules;
std::vector<ModuleId> import_modules;
std::vector<LibraryId> export_libs;
std::vector<LibraryId> import_libs;
std::vector<ModuleId> export_modules;
std::vector<ModuleId> import_modules;
std::vector<LibraryId> export_libs;
std::vector<LibraryId> 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);