mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-16 12:09:07 +00:00
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
* Earlier initialization of elf info. Everything used for elf info initialization comes from the param.sfo, so we can initialize this earlier to have this information accessible during memory init. * Extract compiled SDK version from pubtoolinfo string Up until now, we've been using the game's reported "firmware version" as our compiled SDK version. This behavior is inaccurate, and is something that has come up in my hardware tests before. For the actual compiled SDK version, we should use the SDK version in the PUBTOOLINFO string of the param.sfo, only falling back on the firmware version when that the sdk_ver component isn't present. * Store compiled SDK version in ElfInfo * Limit address space for compiled SDK version at or above FW 3 Sony placed a hard cap at 0xfc00000000, with a slight extension for stack mappings. For now, though stack mappings aren't implemented, there's no harm in keeping a slightly extended address space (since this cap is lower than our old user max). Limiting the max through address space is necessary for Windows due to performance issues, in the future I plan to properly implement checks in memory manager code to properly handle this behavior for all platforms. * Use compiled SDK version for sceKernelGetCompiledSdkVersion I think this is pretty self explanatory. * Log SDK version Since this value is what most internal firmware version checks are against, logging the value will help with debugging. * Update address_space.cpp * Update emulator.cpp * Backwards compatible logging Because that's apparently an issue now
246 lines
8.4 KiB
C++
246 lines
8.4 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/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 Config::isNeoModeConsole() &&
|
|
Common::ElfInfo::Instance().GetPSFAttributes().support_neo_mode;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceKernelHasNeoMode() {
|
|
return Config::isNeoModeConsole();
|
|
}
|
|
|
|
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 (Config::isNeoModeConsole()) {
|
|
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() {
|
|
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
|