diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index cb61bbda9..ed833068c 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -32,44 +32,33 @@ void* PS4_SYSV_ABI sceKernelGetProcParam() { return linker->GetProcParam(); } -s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t args, const void* argp, +s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, u64 args, const void* argp, u32 flags, const void* pOpt, int* pRes) { LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args); - - if (flags != 0) { - return ORBIS_KERNEL_ERROR_EINVAL; - } + ASSERT(flags == 0); auto* mnt = Common::Singleton::Instance(); - const auto path = mnt->GetHostPath(moduleFileName); - - // Load PRX module and relocate any modules that import it. auto* linker = Common::Singleton::Instance(); - u32 handle = linker->FindByName(path); - if (handle != -1) { + + std::filesystem::path path; + std::string guest_path(moduleFileName); + + const bool is_root = guest_path[0] == '/'; + if (is_root || guest_path.contains('/')) { + path = mnt->GetHostPath(guest_path); + } else if (!guest_path.contains('/')) { + path = mnt->GetHostPath("/app0/" + guest_path); + } + + if (const s32 handle = linker->LoadAndStartModule(path, args, argp, pRes); handle != -1) { return handle; } - handle = linker->LoadModule(path, true); - if (handle == -1) { - return ORBIS_KERNEL_ERROR_ESRCH; - } - auto* module = linker->GetModule(handle); - linker->RelocateAnyImports(module); - // If the new module has a TLS image, trigger its load when TlsGetAddr is called. - if (module->tls.image_size != 0) { - linker->AdvanceGenerationCounter(); + if (is_root) { + UNREACHABLE(); } - // Retrieve and verify proc param according to libkernel. - u64* param = module->GetProcParam(); - ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]); - s32 ret = module->Start(args, argp, param); - if (pRes) { - *pRes = ret; - } - - return handle; + return ORBIS_KERNEL_ERROR_ENOENT; } s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 2461edcb2..18ae62f4b 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -139,6 +139,35 @@ s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) { return m_modules.size() - 1; } +s32 Linker::LoadAndStartModule(const std::filesystem::path& path, u64 args, const void* argp, + int* pRes) { + u32 handle = FindByName(path); + if (handle != -1) { + return handle; + } + handle = LoadModule(path, true); + if (handle == -1) { + return -1; + } + auto* module = GetModule(handle); + RelocateAnyImports(module); + + // If the new module has a TLS image, trigger its load when TlsGetAddr is called. + if (module->tls.image_size != 0) { + AdvanceGenerationCounter(); + } + + // Retrieve and verify proc param according to libkernel. + u64* param = module->GetProcParam(); + ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]); + s32 ret = module->Start(args, argp, param); + if (pRes) { + *pRes = ret; + } + + return handle; +} + Module* Linker::FindByAddress(VAddr address) { for (auto& module : m_modules) { const VAddr base = module->GetBaseAddress(); diff --git a/src/core/linker.h b/src/core/linker.h index 9c07400c4..63dfc37e8 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -144,6 +144,8 @@ public: void FreeTlsForNonPrimaryThread(void* pointer); s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false); + s32 LoadAndStartModule(const std::filesystem::path& path, u64 args, const void* argp, + int* pRes); Module* FindByAddress(VAddr address); void Relocate(Module* module); diff --git a/src/core/module.cpp b/src/core/module.cpp index 70afb932c..a18c1141a 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -94,7 +94,7 @@ Module::Module(Core::MemoryManager* memory_, const std::filesystem::path& file_, Module::~Module() = default; -s32 Module::Start(size_t args, const void* argp, void* param) { +s32 Module::Start(u64 args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", name); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); return ExecuteGuest(reinterpret_cast(addr), args, argp, param); diff --git a/src/core/module.h b/src/core/module.h index 630c5d583..320680485 100644 --- a/src/core/module.h +++ b/src/core/module.h @@ -203,7 +203,7 @@ public: return (rela_bits[index >> 3] >> (index & 7)) & 1; } - s32 Start(size_t args, const void* argp, void* param); + s32 Start(u64 args, const void* argp, void* param); void LoadModuleToMemory(u32& max_tls_index); void LoadDynamicInfo(); void LoadSymbols();