// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include "common/elf_info.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/orbis_error.h" #include "core/libraries/kernel/process.h" #include "core/libraries/libs.h" #include "core/libraries/sysmodule/sysmodule.h" #include "core/libraries/sysmodule/sysmodule_error.h" #include "core/libraries/sysmodule/sysmodule_internal.h" #include "core/linker.h" namespace Libraries::SysModule { static std::mutex g_mutex{}; s32 PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal(OrbisSysModuleInternal id, s32* handle) { LOG_INFO(Lib_SysModule, "called"); if ((id & 0x7fffffff) == 0) { return ORBIS_SYSMODULE_INVALID_ID; } std::scoped_lock lk{g_mutex}; return getModuleHandle(id, handle); } s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, Kernel::OrbisModuleInfoForUnwind* info) { LOG_TRACE(Lib_SysModule, "sceSysmoduleGetModuleInfoForUnwind called"); s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, info); if (res != ORBIS_OK) { return res; } if (shouldHideName(info->name.data())) { std::ranges::fill(info->name, '\0'); } return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id) { if (id == 0) { return ORBIS_SYSMODULE_INVALID_ID; } std::scoped_lock lk{g_mutex}; return getModuleHandle(id, nullptr); } s32 PS4_SYSV_ABI sceSysmoduleIsLoadedInternal(OrbisSysModuleInternal id) { if ((id & 0x7fffffff) == 0) { return ORBIS_SYSMODULE_INVALID_ID; } std::scoped_lock lk{g_mutex}; return getModuleHandle(id, nullptr); } s32 PS4_SYSV_ABI sceSysmoduleLoadModule(OrbisSysModule id) { LOG_INFO(Lib_SysModule, "called, id = {:#x}", id); s32 result = validateModuleId(id); if (result < ORBIS_OK) { return result; } // Only locks for internal loadModule call. { std::scoped_lock lk{g_mutex}; result = loadModule(id, 0, nullptr, nullptr); } if (result == ORBIS_KERNEL_ERROR_ESTART) { s32 sdk_ver = 0; result = Kernel::sceKernelGetCompiledSdkVersion(&sdk_ver); if (sdk_ver < Common::ElfInfo::FW_115 || result != ORBIS_OK) { return ORBIS_KERNEL_ERROR_EINVAL; } else { return ORBIS_KERNEL_ERROR_ESTART; } } // The real library has some weird workaround for CUSA01478 and CUSA01495 here. // Unless this is proven necessary, I don't plan to handle this. return result; } s32 PS4_SYSV_ABI sceSysmoduleLoadModuleByNameInternal() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleLoadModuleInternal(OrbisSysModuleInternal id) { LOG_INFO(Lib_SysModule, "called, id = {:#x}", id); s32 result = validateModuleId(id); if (result < ORBIS_OK) { return result; } // This specific module ID is loaded unlocked. if (id == 0x80000039) { return loadModule(id, 0, nullptr, nullptr); } std::scoped_lock lk{g_mutex}; return loadModule(id, 0, nullptr, nullptr); } s32 PS4_SYSV_ABI sceSysmoduleLoadModuleInternalWithArg(OrbisSysModuleInternal id, s32 argc, const void* argv, u64 unk, s32* res_out) { LOG_INFO(Lib_SysModule, "called, id = {:#x}", id); s32 result = validateModuleId(id); if (result < ORBIS_OK) { return result; } if (unk != 0) { return ORBIS_SYSMODULE_INVALID_ID; } std::scoped_lock lk{g_mutex}; return loadModule(id, argc, argv, res_out); } s32 PS4_SYSV_ABI sceSysmoduleMapLibcForLibkernel() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmodulePreloadModuleForLibkernel() { LOG_DEBUG(Lib_SysModule, "called"); return preloadModulesForLibkernel(); } s32 PS4_SYSV_ABI sceSysmoduleUnloadModule(OrbisSysModule id) { LOG_ERROR(Lib_SysModule, "(STUBBED) called, id = {:#x}", id); if (id == 0) { return ORBIS_SYSMODULE_INVALID_ID; } std::scoped_lock lk{g_mutex}; return unloadModule(id, 0, nullptr, nullptr, false); } s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleByNameInternal() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleInternal() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleInternalWithArg() { LOG_ERROR(Lib_SysModule, "(STUBBED) called"); return ORBIS_OK; } void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("D8cuU4d72xM", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleGetModuleHandleInternal); LIB_FUNCTION("4fU5yvOkVG4", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleGetModuleInfoForUnwind); LIB_FUNCTION("ctfO7dQ7geg", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleIsCalledFromSysModule); LIB_FUNCTION("no6T3EfiS3E", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleIsCameraPreloaded); LIB_FUNCTION("fMP5NHUOaMk", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleIsLoaded); LIB_FUNCTION("ynFKQ5bfGks", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleIsLoadedInternal); LIB_FUNCTION("g8cM39EUZ6o", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleLoadModule); LIB_FUNCTION("CU8m+Qs+HN4", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleLoadModuleByNameInternal); LIB_FUNCTION("39iV5E1HoCk", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleLoadModuleInternal); LIB_FUNCTION("hHrGoGoNf+s", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleLoadModuleInternalWithArg); LIB_FUNCTION("lZ6RvVl0vo0", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleMapLibcForLibkernel); LIB_FUNCTION("DOO+zuW1lrE", "libSceSysmodule", 1, "libSceSysmodule", sceSysmodulePreloadModuleForLibkernel); LIB_FUNCTION("eR2bZFAAU0Q", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleUnloadModule); LIB_FUNCTION("vpTHmA6Knvg", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleUnloadModuleByNameInternal); LIB_FUNCTION("vXZhrtJxkGc", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleUnloadModuleInternal); LIB_FUNCTION("aKa6YfBKZs4", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleUnloadModuleInternalWithArg); }; } // namespace Libraries::SysModule