shadPS4/src/core/libraries/kernel/process.cpp
georgemoralis cfa6317836
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions
Merge branch 'main' into user_and_settings
2025-12-01 11:17:21 +02:00

257 lines
8.8 KiB
C++

// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/config.h"
#include "common/elf_info.h"
#include "common/logging/log.h"
#include "core/emulator_settings.h"
#include "core/file_sys/fs.h"
#include "core/libraries/kernel/orbis_error.h"
#include "core/libraries/kernel/process.h"
#include "core/libraries/libs.h"
#include "core/linker.h"
namespace Libraries::Kernel {
s32 PS4_SYSV_ABI sceKernelIsInSandbox() {
return 1;
}
s32 PS4_SYSV_ABI sceKernelIsNeoMode() {
return EmulatorSettings::GetInstance()->IsNeo() &&
Common::ElfInfo::Instance().GetPSFAttributes().support_neo_mode;
}
s32 PS4_SYSV_ABI sceKernelHasNeoMode() {
return EmulatorSettings::GetInstance()->IsNeo();
}
s32 PS4_SYSV_ABI sceKernelGetMainSocId() {
// These hardcoded values are based on hardware observations.
// Different models of PS4/PS4 Pro likely return slightly different values.
LOG_DEBUG(Lib_Kernel, "called");
if (EmulatorSettings::GetInstance()->IsNeo()) {
return 0x740f30;
}
return 0x710f10;
}
s32 PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(s32* ver) {
s32 version = Common::ElfInfo::Instance().CompiledSdkVer();
*ver = version;
return (version >= 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL;
}
s32 PS4_SYSV_ABI sceKernelGetCpumode() {
LOG_DEBUG(Lib_Kernel, "called");
auto& attrs = Common::ElfInfo::Instance().GetPSFAttributes();
u32 is_cpu6 = attrs.six_cpu_mode.Value();
u32 is_cpu7 = attrs.seven_cpu_mode.Value();
if (is_cpu6 == 1 && is_cpu7 == 1) {
return 2;
}
if (is_cpu7 == 1) {
return 5;
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelGetCurrentCpu() {
LOG_DEBUG(Lib_Kernel, "called");
return 0;
}
void* PS4_SYSV_ABI sceKernelGetProcParam() {
auto* linker = Common::Singleton<Core::Linker>::Instance();
return linker->GetProcParam();
}
s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, u64 args, const void* argp,
u32 flags, const void* pOpt, s32* pRes) {
LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args);
ASSERT(flags == 0);
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
auto* linker = Common::Singleton<Core::Linker>::Instance();
std::filesystem::path path;
std::string guest_path(moduleFileName);
s32 handle = -1;
if (guest_path[0] == '/') {
// try load /system/common/lib/ +path
// try load /system/priv/lib/ +path
path = mnt->GetHostPath(guest_path);
handle = linker->LoadAndStartModule(path, args, argp, pRes);
if (handle != -1)
return handle;
} else {
if (!guest_path.contains('/')) {
path = mnt->GetHostPath("/app0/" + guest_path);
handle = linker->LoadAndStartModule(path, args, argp, pRes);
if (handle != -1)
return handle;
// if ((flags & 0x10000) != 0)
// try load /system/priv/lib/ +basename
// try load /system/common/lib/ +basename
} else {
path = mnt->GetHostPath(guest_path);
handle = linker->LoadAndStartModule(path, args, argp, pRes);
if (handle != -1)
return handle;
}
}
return ORBIS_KERNEL_ERROR_ENOENT;
}
s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) {
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
if (module == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*addrp = module->FindByName(symbol);
if (*addrp == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, s32 flags,
OrbisModuleInfoForUnwind* info) {
if (flags >= 3) {
std::memset(info, 0, sizeof(OrbisModuleInfoForUnwind));
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (!info) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (info->st_size < sizeof(OrbisModuleInfoForUnwind)) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
// Find module that contains specified address.
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->FindByAddress(addr);
if (!module) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
const auto mod_info = module->GetModuleInfoEx();
// Fill in module info.
std::memset(info, 0, sizeof(OrbisModuleInfoForUnwind));
info->name = mod_info.name;
info->eh_frame_hdr_addr = mod_info.eh_frame_hdr_addr;
info->eh_frame_addr = mod_info.eh_frame_addr;
info->eh_frame_size = mod_info.eh_frame_size;
info->seg0_addr = mod_info.segments[0].address;
info->seg0_size = mod_info.segments[0].size;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, s32 flags,
Core::OrbisKernelModuleInfoEx* info) {
if (flags >= 3) {
std::memset(info, 0, sizeof(Core::OrbisKernelModuleInfoEx));
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (info == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->FindByAddress(addr);
if (!module) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*info = module->GetModuleInfoEx();
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfo(s32 handle, Core::OrbisKernelModuleInfo* info) {
if (info == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (info->st_size != sizeof(Core::OrbisKernelModuleInfo)) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
if (module == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*info = module->GetModuleInfo();
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfoInternal(s32 handle, Core::OrbisKernelModuleInfoEx* info) {
if (info == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (info->st_size != sizeof(Core::OrbisKernelModuleInfoEx)) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
if (module == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*info = module->GetModuleInfoEx();
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleList(s32* handles, u64 num_array, u64* out_count) {
if (handles == nullptr || out_count == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
u64 count = 0;
auto* module = linker->GetModule(count);
while (module != nullptr && count < num_array) {
handles[count] = count;
count++;
module = linker->GetModule(count);
}
if (count == num_array && module != nullptr) {
return ORBIS_KERNEL_ERROR_ENOMEM;
}
*out_count = count;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI exit(s32 status) {
UNREACHABLE_MSG("Exiting with status code {}", status);
return 0;
}
void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("xeu-pV8wkKs", "libkernel", 1, "libkernel", sceKernelIsInSandbox);
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", sceKernelGetCompiledSdkVersion);
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", sceKernelIsNeoMode);
LIB_FUNCTION("rNRtm1uioyY", "libkernel", 1, "libkernel", sceKernelHasNeoMode);
LIB_FUNCTION("0vTn5IDMU9A", "libkernel", 1, "libkernel", sceKernelGetMainSocId);
LIB_FUNCTION("VOx8NGmHXTs", "libkernel", 1, "libkernel", sceKernelGetCpumode);
LIB_FUNCTION("g0VTBxfJyu0", "libkernel", 1, "libkernel", sceKernelGetCurrentCpu);
LIB_FUNCTION("959qrazPIrg", "libkernel", 1, "libkernel", sceKernelGetProcParam);
LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", sceKernelLoadStartModule);
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", sceKernelDlsym);
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", sceKernelGetModuleInfoForUnwind);
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", sceKernelGetModuleInfoFromAddr);
LIB_FUNCTION("kUpgrXIrz7Q", "libkernel", 1, "libkernel", sceKernelGetModuleInfo);
LIB_FUNCTION("HZO7xOos4xc", "libkernel", 1, "libkernel", sceKernelGetModuleInfoInternal);
LIB_FUNCTION("IuxnUuXk6Bg", "libkernel", 1, "libkernel", sceKernelGetModuleList);
LIB_FUNCTION("6Z83sYWFlA8", "libkernel", 1, "libkernel", exit);
}
} // namespace Libraries::Kernel