commit
c3d26e92c6
|
@ -15,7 +15,11 @@ u32 screenHeight = 720;
|
||||||
std::string logFilter;
|
std::string logFilter;
|
||||||
std::string logType = "sync";
|
std::string logType = "sync";
|
||||||
bool isDebugDump = false;
|
bool isDebugDump = false;
|
||||||
|
bool isLibc = true;
|
||||||
|
|
||||||
|
bool isLleLibc() {
|
||||||
|
return isLibc;
|
||||||
|
}
|
||||||
bool isNeoMode() {
|
bool isNeoMode() {
|
||||||
return isNeo;
|
return isNeo;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +88,14 @@ void load(const std::filesystem::path& path) {
|
||||||
isDebugDump = toml::find_or<toml::boolean>(debug, "DebugDump", false);
|
isDebugDump = toml::find_or<toml::boolean>(debug, "DebugDump", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (data.contains("LLE")) {
|
||||||
|
auto lleResult = toml::expect<toml::value>(data.at("LLE"));
|
||||||
|
if (lleResult.is_ok()) {
|
||||||
|
auto lle = lleResult.unwrap();
|
||||||
|
|
||||||
|
isLibc = toml::find_or<toml::boolean>(lle, "libc", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void save(const std::filesystem::path& path) {
|
void save(const std::filesystem::path& path) {
|
||||||
toml::basic_value<toml::preserve_comments> data;
|
toml::basic_value<toml::preserve_comments> data;
|
||||||
|
@ -110,6 +122,7 @@ void save(const std::filesystem::path& path) {
|
||||||
data["GPU"]["screenWidth"] = screenWidth;
|
data["GPU"]["screenWidth"] = screenWidth;
|
||||||
data["GPU"]["screenHeight"] = screenHeight;
|
data["GPU"]["screenHeight"] = screenHeight;
|
||||||
data["Debug"]["DebugDump"] = isDebugDump;
|
data["Debug"]["DebugDump"] = isDebugDump;
|
||||||
|
data["LLE"]["libc"] = isLibc;
|
||||||
|
|
||||||
std::ofstream file(path, std::ios::out);
|
std::ofstream file(path, std::ios::out);
|
||||||
file << data;
|
file << data;
|
||||||
|
|
|
@ -18,5 +18,6 @@ u32 getScreenWidth();
|
||||||
u32 getScreenHeight();
|
u32 getScreenHeight();
|
||||||
|
|
||||||
bool debugDump();
|
bool debugDump();
|
||||||
|
bool isLleLibc();
|
||||||
|
|
||||||
}; // namespace Config
|
}; // namespace Config
|
||||||
|
|
|
@ -85,6 +85,9 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl
|
||||||
GPU::MemoryMode gpu_mode = GPU::MemoryMode::NoAccess;
|
GPU::MemoryMode gpu_mode = GPU::MemoryMode::NoAccess;
|
||||||
|
|
||||||
switch (prot) {
|
switch (prot) {
|
||||||
|
case 0x03:
|
||||||
|
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||||
|
break;
|
||||||
case 0x32:
|
case 0x32:
|
||||||
case 0x33: // SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL
|
case 0x33: // SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL
|
||||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||||
|
|
|
@ -19,11 +19,18 @@
|
||||||
#else
|
#else
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <common/singleton.h>
|
||||||
|
#include <core/linker.h>
|
||||||
|
|
||||||
namespace Core::Libraries::LibKernel {
|
namespace Core::Libraries::LibKernel {
|
||||||
|
|
||||||
static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return
|
static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return
|
||||||
|
|
||||||
|
static void* PS4_SYSV_ABI sceKernelGetProcParam() {
|
||||||
|
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||||
|
return reinterpret_cast<void*>(linker->GetProcParam());
|
||||||
|
}
|
||||||
|
|
||||||
int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) {
|
int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -117,6 +124,23 @@ PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd,
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t g_mspace_atomic_id_mask = 0;
|
||||||
|
static uint64_t g_mstate_table[64] = {0};
|
||||||
|
|
||||||
|
struct HeapInfoInfo {
|
||||||
|
uint64_t size = sizeof(HeapInfoInfo);
|
||||||
|
uint32_t flag;
|
||||||
|
uint32_t getSegmentInfo;
|
||||||
|
uint64_t* mspace_atomic_id_mask;
|
||||||
|
uint64_t* mstate_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) {
|
||||||
|
info->mspace_atomic_id_mask = &g_mspace_atomic_id_mask;
|
||||||
|
info->mstate_table = g_mstate_table;
|
||||||
|
info->getSegmentInfo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void LibKernel_Register(Loader::SymbolsResolver* sym) {
|
void LibKernel_Register(Loader::SymbolsResolver* sym) {
|
||||||
// obj
|
// obj
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||||
|
@ -139,10 +163,15 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap);
|
LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap);
|
||||||
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
||||||
LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev);
|
LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev);
|
||||||
|
LIB_FUNCTION("959qrazPIrg", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcParam);
|
||||||
|
|
||||||
Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym);
|
Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym);
|
||||||
Core::Libraries::LibKernel::timeSymbolsRegister(sym);
|
Core::Libraries::LibKernel::timeSymbolsRegister(sym);
|
||||||
Core::Libraries::LibKernel::pthreadSymbolsRegister(sym);
|
Core::Libraries::LibKernel::pthreadSymbolsRegister(sym);
|
||||||
|
|
||||||
|
// temp
|
||||||
|
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||||
|
sceLibcHeapGetTraceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Libraries::LibKernel
|
} // namespace Core::Libraries::LibKernel
|
||||||
|
|
|
@ -187,7 +187,6 @@ void* createMutex(void* addr) {
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr,
|
int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
LOG_INFO(Kernel_Pthread, "called");
|
|
||||||
if (mutex == nullptr) {
|
if (mutex == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +328,23 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
||||||
|
|
||||||
|
int result = pthread_mutexattr_destroy(&(*attr)->pth_mutex_attr);
|
||||||
|
|
||||||
|
delete *attr;
|
||||||
|
*attr = nullptr;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case 0:
|
||||||
|
return SCE_OK;
|
||||||
|
case ENOMEM:
|
||||||
|
return SCE_KERNEL_ERROR_ENOMEM;
|
||||||
|
default:
|
||||||
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* createCond(void* addr) {
|
void* createCond(void* addr) {
|
||||||
if (addr == nullptr || *static_cast<ScePthreadCond*>(addr) != nullptr) {
|
if (addr == nullptr || *static_cast<ScePthreadCond*>(addr) != nullptr) {
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -470,6 +486,7 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) {
|
||||||
// mutex calls
|
// mutex calls
|
||||||
LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit);
|
LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit);
|
||||||
LIB_FUNCTION("F8bUHwAG284", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrInit);
|
LIB_FUNCTION("F8bUHwAG284", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrInit);
|
||||||
|
LIB_FUNCTION("smWEktiyyG0", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrDestroy);
|
||||||
LIB_FUNCTION("iMp8QpE+XO4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSettype);
|
LIB_FUNCTION("iMp8QpE+XO4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSettype);
|
||||||
LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol);
|
LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol);
|
||||||
LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock);
|
LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <common/config.h>
|
||||||
#include "core/PS4/HLE/Graphics/video_out.h"
|
#include "core/PS4/HLE/Graphics/video_out.h"
|
||||||
#include "core/hle/libraries/libc/libc.h"
|
#include "core/hle/libraries/libc/libc.h"
|
||||||
#include "core/hle/libraries/libkernel/libkernel.h"
|
#include "core/hle/libraries/libkernel/libkernel.h"
|
||||||
|
@ -20,7 +21,9 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
||||||
HLE::Libs::Graphics::VideoOut::videoOutRegisterLib(sym);
|
HLE::Libs::Graphics::VideoOut::videoOutRegisterLib(sym);
|
||||||
Core::Libraries::LibSceGnmDriver::LibSceGnmDriver_Register(sym);
|
Core::Libraries::LibSceGnmDriver::LibSceGnmDriver_Register(sym);
|
||||||
OldLibraries::LibPad::padSymbolsRegister(sym);
|
OldLibraries::LibPad::padSymbolsRegister(sym);
|
||||||
|
if (!Config::isLleLibc()) {
|
||||||
Core::Libraries::LibC::libcSymbolsRegister(sym);
|
Core::Libraries::LibC::libcSymbolsRegister(sym);
|
||||||
|
}
|
||||||
|
|
||||||
// new libraries folder from autogen
|
// new libraries folder from autogen
|
||||||
Libraries::UserService::RegisterlibSceUserService(sym);
|
Libraries::UserService::RegisterlibSceUserService(sym);
|
||||||
|
|
|
@ -1883,7 +1883,7 @@ int PS4_SYSV_ABI sceSystemServiceNavigateToGoHome() {
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(int param_id, int* value) {
|
s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(int param_id, int* value) {
|
||||||
// TODO this probably should be stored in config for UI configuration
|
// TODO this probably should be stored in config for UI configuration
|
||||||
LOG_INFO(Lib_SystemService, "called");
|
LOG_INFO(Lib_SystemService, "called param_id {}", param_id);
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
LOG_ERROR(Lib_SystemService, "value is null");
|
LOG_ERROR(Lib_SystemService, "value is null");
|
||||||
return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER;
|
return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ int PS4_SYSV_ABI sceUserServiceGetTraditionalChineseInputType() {
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUserServiceGetUserColor(int user_id, int* color) {
|
s32 PS4_SYSV_ABI sceUserServiceGetUserColor(int user_id, int* color) {
|
||||||
// TODO fix me better
|
// TODO fix me better
|
||||||
LOG_INFO(Lib_UserService, "called");
|
LOG_INFO(Lib_UserService, "called user_id = {}", user_id);
|
||||||
if (color == nullptr) {
|
if (color == nullptr) {
|
||||||
LOG_ERROR(Lib_UserService, "color is null");
|
LOG_ERROR(Lib_UserService, "color is null");
|
||||||
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||||
|
@ -1056,6 +1056,7 @@ int PS4_SYSV_ABI sceUserServiceGetUserGroupNum() {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::size_t size) {
|
s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::size_t size) {
|
||||||
|
LOG_INFO(Lib_UserService, "called user_id = {} ,size = {} ", user_id, size);
|
||||||
if (user_name == nullptr) {
|
if (user_name == nullptr) {
|
||||||
LOG_ERROR(Lib_UserService, "user_name is null");
|
LOG_ERROR(Lib_UserService, "user_name is null");
|
||||||
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||||
|
@ -1110,7 +1111,7 @@ int PS4_SYSV_ABI sceUserServiceGetVolumeForSidetone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUserServiceInitialize(const OrbisUserServiceInitializeParams* initParams) {
|
s32 PS4_SYSV_ABI sceUserServiceInitialize(const OrbisUserServiceInitializeParams* initParams) {
|
||||||
LOG_ERROR(Lib_UserService, "(STUBBED) called");
|
LOG_WARNING(Lib_UserService, "(dummy) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <Zydis/Zydis.h>
|
#include <Zydis/Zydis.h>
|
||||||
|
#include <common/assert.h>
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
|
@ -15,7 +16,8 @@
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
static constexpr u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
static u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
||||||
|
static constexpr u64 CODE_BASE_INCR = 0x010000000u;
|
||||||
|
|
||||||
static u64 GetAlignedSize(const elf_program_header& phdr) {
|
static u64 GetAlignedSize(const elf_program_header& phdr) {
|
||||||
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
|
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
|
||||||
|
@ -74,7 +76,6 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) {
|
||||||
LoadModuleToMemory(m.get());
|
LoadModuleToMemory(m.get());
|
||||||
LoadDynamicInfo(m.get());
|
LoadDynamicInfo(m.get());
|
||||||
LoadSymbols(m.get());
|
LoadSymbols(m.get());
|
||||||
Relocate(m.get());
|
|
||||||
} else {
|
} else {
|
||||||
m_modules.pop_back();
|
m_modules.pop_back();
|
||||||
return nullptr; // It is not a valid elf file //TODO check it why!
|
return nullptr; // It is not a valid elf file //TODO check it why!
|
||||||
|
@ -83,14 +84,6 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) {
|
||||||
return m.get();
|
return m.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Module* Linker::FindModule(u32 id) {
|
|
||||||
// TODO atm we only have 1 module so we don't need to iterate on vector
|
|
||||||
if (m_modules.empty()) [[unlikely]] {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return m_modules[0].get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Linker::LoadModuleToMemory(Module* m) {
|
void Linker::LoadModuleToMemory(Module* m) {
|
||||||
// get elf header, program header
|
// get elf header, program header
|
||||||
const auto elf_header = m->elf.GetElfHeader();
|
const auto elf_header = m->elf.GetElfHeader();
|
||||||
|
@ -104,6 +97,8 @@ void Linker::LoadModuleToMemory(Module* m) {
|
||||||
m->base_virtual_addr = VirtualMemory::memory_alloc(LoadAddress, m->aligned_base_size,
|
m->base_virtual_addr = VirtualMemory::memory_alloc(LoadAddress, m->aligned_base_size,
|
||||||
VirtualMemory::MemoryMode::ExecuteReadWrite);
|
VirtualMemory::MemoryMode::ExecuteReadWrite);
|
||||||
|
|
||||||
|
LoadAddress += CODE_BASE_INCR * (1 + m->aligned_base_size / CODE_BASE_INCR);
|
||||||
|
|
||||||
LOG_INFO(Core_Linker, "====Load Module to Memory ========");
|
LOG_INFO(Core_Linker, "====Load Module to Memory ========");
|
||||||
LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr);
|
LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr);
|
||||||
LOG_INFO(Core_Linker, "base_size ..............: {:#018x}", base_size);
|
LOG_INFO(Core_Linker, "base_size ..............: {:#018x}", base_size);
|
||||||
|
@ -161,6 +156,9 @@ void Linker::LoadModuleToMemory(Module* m) {
|
||||||
LOG_INFO(Core_Linker, "tls virtual address ={:#x}", m->tls.image_virtual_addr);
|
LOG_INFO(Core_Linker, "tls virtual address ={:#x}", m->tls.image_virtual_addr);
|
||||||
LOG_INFO(Core_Linker, "tls image size ={}", m->tls.image_size);
|
LOG_INFO(Core_Linker, "tls image size ={}", m->tls.image_size);
|
||||||
break;
|
break;
|
||||||
|
case PT_SCE_PROCPARAM:
|
||||||
|
m->proc_param_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Core_Linker, "Unimplemented type {}",
|
LOG_ERROR(Core_Linker, "Unimplemented type {}",
|
||||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||||
|
@ -378,65 +376,37 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Linker::LoadSymbols(Module* m) {
|
void Linker::LoadSymbols(Module* m) {
|
||||||
|
|
||||||
|
const auto symbol_database = [this](Module* m, Loader::SymbolsResolver* symbol,
|
||||||
|
bool export_func) {
|
||||||
if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr ||
|
if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr ||
|
||||||
m->dynamic_info.symbol_table_total_size == 0) {
|
m->dynamic_info.symbol_table_total_size == 0) {
|
||||||
LOG_INFO(Core_Linker, "Symbol table not found!");
|
LOG_INFO(Core_Linker, "Symbol table not found!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* sym = m->dynamic_info.symbol_table;
|
for (auto* sym = m->dynamic_info.symbol_table;
|
||||||
reinterpret_cast<uint8_t*>(sym) <
|
reinterpret_cast<u8*>(sym) < reinterpret_cast<u8*>(m->dynamic_info.symbol_table) +
|
||||||
reinterpret_cast<uint8_t*>(m->dynamic_info.symbol_table) +
|
|
||||||
m->dynamic_info.symbol_table_total_size;
|
m->dynamic_info.symbol_table_total_size;
|
||||||
sym++) {
|
sym++) {
|
||||||
std::string id = std::string(m->dynamic_info.str_table + sym->st_name);
|
std::string id = std::string(m->dynamic_info.str_table + sym->st_name);
|
||||||
const auto ids = Common::SplitString(id, '#');
|
|
||||||
if (ids.size() == 3) // symbols are 3 parts name , library , module
|
|
||||||
{
|
|
||||||
const auto* library = FindLibrary(*m, ids.at(1));
|
|
||||||
const auto* module = FindModule(*m, ids.at(2));
|
|
||||||
auto bind = sym->GetBind();
|
auto bind = sym->GetBind();
|
||||||
auto type = sym->GetType();
|
auto type = sym->GetType();
|
||||||
auto visibility = sym->GetVisibility();
|
auto visibility = sym->GetVisibility();
|
||||||
if (library != nullptr || module != nullptr) {
|
const auto ids = Common::SplitString(id, '#');
|
||||||
switch (bind) {
|
if (ids.size() == 3) {
|
||||||
case STB_GLOBAL:
|
const auto* library = FindLibrary(*m, ids.at(1));
|
||||||
case STB_WEAK:
|
const auto* module = FindModule(*m, ids.at(2));
|
||||||
break;
|
ASSERT_MSG(library && module, "Unable to find library and module");
|
||||||
default:
|
if ((bind == STB_GLOBAL || bind == STB_WEAK) &&
|
||||||
LOG_INFO(Core_Linker, "Unsupported bind {} for name symbol {}", bind,
|
(type == STT_FUN || type == STT_OBJECT) &&
|
||||||
ids.at(0));
|
export_func == (sym->st_value != 0)) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (type) {
|
|
||||||
case STT_OBJECT:
|
|
||||||
case STT_FUN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_INFO(Core_Linker, "Unsupported type {} for name symbol {}", type,
|
|
||||||
ids.at(0));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (visibility) {
|
|
||||||
case STV_DEFAULT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_INFO(Core_Linker, "Unsupported visibility {} for name symbol {}",
|
|
||||||
visibility, ids.at(0));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// if st_value!=0 then it's export symbol
|
|
||||||
bool is_sym_export = sym->st_value != 0;
|
|
||||||
std::string nidName = "";
|
std::string nidName = "";
|
||||||
|
|
||||||
auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
|
auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
|
||||||
|
|
||||||
if (aeronid != nullptr) {
|
if (aeronid != nullptr) {
|
||||||
nidName = aeronid->name;
|
nidName = aeronid->name;
|
||||||
} else {
|
} else {
|
||||||
nidName = "UNK";
|
nidName = "UNK";
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader::SymbolResolver sym_r{};
|
Loader::SymbolResolver sym_r{};
|
||||||
sym_r.name = ids.at(0);
|
sym_r.name = ids.at(0);
|
||||||
sym_r.nidName = nidName;
|
sym_r.nidName = nidName;
|
||||||
|
@ -459,20 +429,14 @@ void Linker::LoadSymbols(Module* m) {
|
||||||
sym_r.type = Loader::SymbolType::Unknown;
|
sym_r.type = Loader::SymbolType::Unknown;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
symbol->AddSymbol(sym_r,
|
||||||
if (is_sym_export) {
|
(export_func ? sym->st_value + m->base_virtual_addr : 0));
|
||||||
m->export_sym.AddSymbol(sym_r, sym->st_value + m->base_virtual_addr);
|
|
||||||
} else {
|
|
||||||
m->import_sym.AddSymbol(sym_r, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO(Core_Linker,
|
|
||||||
"name = {}, function = {}, library = {}, module = {}, bind = {}, type = "
|
|
||||||
"{}, visibility = {}",
|
|
||||||
ids.at(0), nidName, library->name, module->name, bind, type, visibility);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
symbol_database(m, &m->export_sym, true);
|
||||||
|
symbol_database(m, &m->import_sym, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Linker::Relocate(Module* m) {
|
void Linker::Relocate(Module* m) {
|
||||||
|
@ -492,17 +456,18 @@ void Linker::Relocate(Module* m) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_X86_64_RELATIVE:
|
case R_X86_64_RELATIVE:
|
||||||
if (symbol != 0) // should be always zero
|
|
||||||
{
|
|
||||||
// LOG_INFO(Core_Linker, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type,
|
|
||||||
// symbol);//found it openorbis but i am not sure it worth logging
|
|
||||||
}
|
|
||||||
rel_value = rel_base_virtual_addr + addend;
|
rel_value = rel_base_virtual_addr + addend;
|
||||||
rel_isResolved = true;
|
rel_isResolved = true;
|
||||||
break;
|
break;
|
||||||
case R_X86_64_64:
|
case R_X86_64_DTPMOD64:
|
||||||
case R_X86_64_JUMP_SLOT: // similar but addend is not take into account
|
rel_value = reinterpret_cast<uint64_t>(m);
|
||||||
{
|
rel_isResolved = true;
|
||||||
|
rel_sym_type = Loader::SymbolType::Tls;
|
||||||
|
break;
|
||||||
|
case R_X86_64_GLOB_DAT:
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
addend = 0;
|
||||||
|
case R_X86_64_64: {
|
||||||
auto sym = symbolsTlb[symbol];
|
auto sym = symbolsTlb[symbol];
|
||||||
auto sym_bind = sym.GetBind();
|
auto sym_bind = sym.GetBind();
|
||||||
auto sym_type = sym.GetType();
|
auto sym_type = sym.GetType();
|
||||||
|
@ -516,36 +481,32 @@ void Linker::Relocate(Module* m) {
|
||||||
case STT_OBJECT:
|
case STT_OBJECT:
|
||||||
rel_sym_type = Loader::SymbolType::Object;
|
rel_sym_type = Loader::SymbolType::Object;
|
||||||
break;
|
break;
|
||||||
|
case STT_NOTYPE:
|
||||||
|
rel_sym_type = Loader::SymbolType::NoType;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_INFO(Core_Linker, "unknown symbol type {}", sym_type);
|
ASSERT_MSG(0, "unknown symbol type {}", sym_type);
|
||||||
}
|
}
|
||||||
if (sym_visibility != 0) // should be zero log if else
|
if (sym_visibility != 0) // should be zero log if else
|
||||||
{
|
{
|
||||||
LOG_INFO(Core_Linker, "symbol visilibity !=0");
|
LOG_INFO(Core_Linker, "symbol visilibity !=0");
|
||||||
}
|
}
|
||||||
switch (sym_bind) {
|
switch (sym_bind) {
|
||||||
|
case STB_LOCAL:
|
||||||
|
symbol_vitrual_addr = rel_base_virtual_addr + sym.st_value;
|
||||||
|
break;
|
||||||
case STB_GLOBAL:
|
case STB_GLOBAL:
|
||||||
|
case STB_WEAK: {
|
||||||
rel_name = namesTlb + sym.st_name;
|
rel_name = namesTlb + sym.st_name;
|
||||||
Resolve(rel_name, rel_sym_type, m, &symrec);
|
Resolve(rel_name, rel_sym_type, m, &symrec);
|
||||||
symbol_vitrual_addr = symrec.virtual_address;
|
symbol_vitrual_addr = symrec.virtual_address;
|
||||||
rel_isResolved = (symbol_vitrual_addr != 0);
|
} break;
|
||||||
|
|
||||||
rel_name = symrec.name;
|
|
||||||
if (type == R_X86_64_JUMP_SLOT) {
|
|
||||||
addend = 0;
|
|
||||||
}
|
|
||||||
rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0);
|
|
||||||
if (!rel_isResolved) {
|
|
||||||
LOG_INFO(Core_Linker,
|
|
||||||
"R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : "
|
|
||||||
"{:#010x}",
|
|
||||||
sym_type, symbol);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
LOG_INFO(Core_Linker, "UNK bind {}", sym_bind);
|
ASSERT_MSG(0, "unknown bind type {}", sym_bind);
|
||||||
}
|
}
|
||||||
|
rel_isResolved = (symbol_vitrual_addr != 0);
|
||||||
|
rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0);
|
||||||
|
rel_name = symrec.name;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
LOG_INFO(Core_Linker, "UNK type {:#010x} rel symbol : {:#010x}", type, symbol);
|
LOG_INFO(Core_Linker, "UNK type {:#010x} rel symbol : {:#010x}", type, symbol);
|
||||||
|
@ -574,15 +535,36 @@ void Linker::Relocate(Module* m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Linker::Resolve(const std::string& name, Loader::SymbolType Symtype, Module* m,
|
template <typename T>
|
||||||
|
bool contains(const std::vector<T>& vecObj, const T& element) {
|
||||||
|
auto it = std::find(vecObj.begin(), vecObj.end(), element);
|
||||||
|
return it != vecObj.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
Module* Linker::FindExportedModule(const ModuleInfo& module, const LibraryInfo& library) {
|
||||||
|
// std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
|
for (auto& m : m_modules) {
|
||||||
|
const auto& export_libs = m->dynamic_info.export_libs;
|
||||||
|
const auto& export_modules = m->dynamic_info.export_modules;
|
||||||
|
|
||||||
|
if (contains(export_libs, library) && contains(export_modules, module)) {
|
||||||
|
return m.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Module* m,
|
||||||
Loader::SymbolRecord* return_info) {
|
Loader::SymbolRecord* return_info) {
|
||||||
|
// std::scoped_lock lock{m_mutex};
|
||||||
const auto ids = Common::SplitString(name, '#');
|
const auto ids = Common::SplitString(name, '#');
|
||||||
if (ids.size() == 3) // symbols are 3 parts name , library , module
|
ASSERT_MSG(ids.size() == 3, "Symbols must be 3 parts name, library, module");
|
||||||
{
|
|
||||||
const auto* library = FindLibrary(*m, ids.at(1));
|
const auto* library = FindLibrary(*m, ids.at(1));
|
||||||
const auto* module = FindModule(*m, ids.at(2));
|
const auto* module = FindModule(*m, ids.at(2));
|
||||||
|
ASSERT_MSG(library && module, "Unable to find library and module");
|
||||||
|
|
||||||
if (library != nullptr && module != nullptr) {
|
|
||||||
Loader::SymbolResolver sr{};
|
Loader::SymbolResolver sr{};
|
||||||
sr.name = ids.at(0);
|
sr.name = ids.at(0);
|
||||||
sr.library = library->name;
|
sr.library = library->name;
|
||||||
|
@ -590,11 +572,18 @@ void Linker::Resolve(const std::string& name, Loader::SymbolType Symtype, Module
|
||||||
sr.module = module->name;
|
sr.module = module->name;
|
||||||
sr.module_version_major = module->version_major;
|
sr.module_version_major = module->version_major;
|
||||||
sr.module_version_minor = module->version_minor;
|
sr.module_version_minor = module->version_minor;
|
||||||
sr.type = Symtype;
|
sr.type = sym_type;
|
||||||
|
|
||||||
const Loader::SymbolRecord* rec = nullptr;
|
const Loader::SymbolRecord* rec = nullptr;
|
||||||
rec = m_hle_symbols.FindSymbol(sr);
|
|
||||||
|
|
||||||
|
rec = m_hle_symbols.FindSymbol(sr);
|
||||||
|
if (rec == nullptr) {
|
||||||
|
// check if it an export function
|
||||||
|
if (auto* p = FindExportedModule(*module, *library);
|
||||||
|
p != nullptr && p->export_sym.GetSize() > 0) {
|
||||||
|
rec = p->export_sym.FindSymbol(sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (rec != nullptr) {
|
if (rec != nullptr) {
|
||||||
*return_info = *rec;
|
*return_info = *rec;
|
||||||
} else {
|
} else {
|
||||||
|
@ -609,16 +598,41 @@ void Linker::Resolve(const std::string& name, Loader::SymbolType Symtype, Module
|
||||||
LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name,
|
LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name,
|
||||||
return_info->name, library->name, module->name);
|
return_info->name, library->name, module->name);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//__debugbreak();//den tha prepei na ftasoume edo
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//__debugbreak();//oute edo mallon
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 Linker::GetProcParam() {
|
||||||
|
// std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
|
for (auto& m : m_modules) {
|
||||||
|
if (!m->elf.IsSharedLib()) {
|
||||||
|
return m->proc_param_virtual_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
using exit_func_t = PS4_SYSV_ABI void (*)();
|
using exit_func_t = PS4_SYSV_ABI void (*)();
|
||||||
using entry_func_t = PS4_SYSV_ABI void (*)(EntryParams* params, exit_func_t atexit_func);
|
using entry_func_t = PS4_SYSV_ABI void (*)(EntryParams* params, exit_func_t atexit_func);
|
||||||
|
using module_ini_func_t = PS4_SYSV_ABI int (*)(size_t args, const void* argp, module_func_t func);
|
||||||
|
|
||||||
|
static PS4_SYSV_ABI int run_module(uint64_t addr, size_t args, const void* argp,
|
||||||
|
module_func_t func) {
|
||||||
|
return reinterpret_cast<module_ini_func_t>(addr)(args, argp, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Linker::StartModule(Module* m, size_t args, const void* argp, module_func_t func) {
|
||||||
|
LOG_INFO(Core_Linker, "Module started : {}", m->file_name);
|
||||||
|
return run_module(m->dynamic_info.init_virtual_addr + m->base_virtual_addr, args, argp, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Linker::StartAllModules() {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
|
for (auto& m : m_modules) {
|
||||||
|
if (m->elf.IsSharedLib()) {
|
||||||
|
StartModule(m.get(), 0, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PS4_SYSV_ABI void ProgramExitFunc() {
|
static PS4_SYSV_ABI void ProgramExitFunc() {
|
||||||
fmt::print("exit function called\n");
|
fmt::print("exit function called\n");
|
||||||
|
@ -653,12 +667,20 @@ void Linker::Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Libraries::LibKernel::pthreadInitSelfMainThread();
|
Core::Libraries::LibKernel::pthreadInitSelfMainThread();
|
||||||
|
// relocate all modules
|
||||||
|
for (const auto& m : m_modules) {
|
||||||
|
Relocate(m.get());
|
||||||
|
}
|
||||||
|
StartAllModules();
|
||||||
EntryParams p{};
|
EntryParams p{};
|
||||||
p.argc = 1;
|
p.argc = 1;
|
||||||
p.argv[0] = "eboot.bin"; // hmm should be ok?
|
p.argv[0] = "eboot.bin"; // hmm should be ok?
|
||||||
|
|
||||||
const auto& module = m_modules.at(0);
|
for (auto& m : m_modules) {
|
||||||
RunMainEntry(module->elf.GetElfEntry() + module->base_virtual_addr, &p, ProgramExitFunc);
|
if (!m->elf.IsSharedLib()) {
|
||||||
|
RunMainEntry(m->elf.GetElfEntry() + m->base_virtual_addr, &p, ProgramExitFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Linker::DebugDump() {
|
void Linker::DebugDump() {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "core/loader/symbols_resolver.h"
|
#include "core/loader/symbols_resolver.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
using module_func_t = int (*)(size_t args, const void* argp);
|
||||||
struct DynamicModuleInfo;
|
struct DynamicModuleInfo;
|
||||||
class Linker;
|
class Linker;
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ struct EntryParams {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModuleInfo {
|
struct ModuleInfo {
|
||||||
|
bool operator==(const ModuleInfo& other) const {
|
||||||
|
return version_major == other.version_major && version_minor == other.version_minor &&
|
||||||
|
name == other.name;
|
||||||
|
}
|
||||||
std::string name;
|
std::string name;
|
||||||
union {
|
union {
|
||||||
u64 value;
|
u64 value;
|
||||||
|
@ -34,6 +38,9 @@ struct ModuleInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LibraryInfo {
|
struct LibraryInfo {
|
||||||
|
bool operator==(const LibraryInfo& other) const {
|
||||||
|
return version == other.version && name == other.name;
|
||||||
|
}
|
||||||
std::string name;
|
std::string name;
|
||||||
union {
|
union {
|
||||||
u64 value;
|
u64 value;
|
||||||
|
@ -99,6 +106,7 @@ struct Module {
|
||||||
Loader::Elf elf;
|
Loader::Elf elf;
|
||||||
u64 aligned_base_size = 0;
|
u64 aligned_base_size = 0;
|
||||||
u64 base_virtual_addr = 0;
|
u64 base_virtual_addr = 0;
|
||||||
|
u64 proc_param_virtual_addr = 0;
|
||||||
|
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
|
|
||||||
|
@ -118,7 +126,6 @@ public:
|
||||||
virtual ~Linker();
|
virtual ~Linker();
|
||||||
|
|
||||||
Module* LoadModule(const std::filesystem::path& elf_name);
|
Module* LoadModule(const std::filesystem::path& elf_name);
|
||||||
Module* FindModule(u32 id = 0);
|
|
||||||
void LoadModuleToMemory(Module* m);
|
void LoadModuleToMemory(Module* m);
|
||||||
void LoadDynamicInfo(Module* m);
|
void LoadDynamicInfo(Module* m);
|
||||||
void LoadSymbols(Module* m);
|
void LoadSymbols(Module* m);
|
||||||
|
@ -130,10 +137,14 @@ public:
|
||||||
Loader::SymbolRecord* return_info);
|
Loader::SymbolRecord* return_info);
|
||||||
void Execute();
|
void Execute();
|
||||||
void DebugDump();
|
void DebugDump();
|
||||||
|
u64 GetProcParam();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ModuleInfo* FindModule(const Module& m, const std::string& id);
|
const ModuleInfo* FindModule(const Module& m, const std::string& id);
|
||||||
const LibraryInfo* FindLibrary(const Module& program, const std::string& id);
|
const LibraryInfo* FindLibrary(const Module& program, const std::string& id);
|
||||||
|
Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l);
|
||||||
|
int StartModule(Module* m, size_t args, const void* argp, module_func_t func);
|
||||||
|
void StartAllModules();
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Module>> m_modules;
|
std::vector<std::unique_ptr<Module>> m_modules;
|
||||||
Loader::SymbolsResolver m_hle_symbols{};
|
Loader::SymbolsResolver m_hle_symbols{};
|
||||||
|
|
|
@ -538,4 +538,8 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Elf::IsSharedLib() {
|
||||||
|
return m_elf_header.e_type == ET_SCE_DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core::Loader
|
} // namespace Core::Loader
|
||||||
|
|
|
@ -490,6 +490,7 @@ public:
|
||||||
std::string ElfPheaderFlagsStr(u32 flags);
|
std::string ElfPheaderFlagsStr(u32 flags);
|
||||||
|
|
||||||
void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size);
|
void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size);
|
||||||
|
bool IsSharedLib();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Common::FS::IOFile m_f{};
|
Common::FS::IOFile m_f{};
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
namespace Core::Loader {
|
namespace Core::Loader {
|
||||||
|
|
||||||
void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) {
|
void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) {
|
||||||
SymbolRecord r{};
|
SymbolRecord& r = m_symbols.emplace_back();
|
||||||
r.name = GenerateName(s);
|
r.name = GenerateName(s);
|
||||||
r.virtual_address = virtual_addr;
|
r.virtual_address = virtual_addr;
|
||||||
m_symbols.push_back(r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SymbolsResolver::GenerateName(const SymbolResolver& s) {
|
std::string SymbolsResolver::GenerateName(const SymbolResolver& s) {
|
||||||
|
@ -25,12 +24,12 @@ std::string SymbolsResolver::GenerateName(const SymbolResolver& s) {
|
||||||
const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolResolver& s) const {
|
const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolResolver& s) const {
|
||||||
const std::string name = GenerateName(s);
|
const std::string name = GenerateName(s);
|
||||||
for (u32 i = 0; i < m_symbols.size(); i++) {
|
for (u32 i = 0; i < m_symbols.size(); i++) {
|
||||||
if (m_symbols[i].name.compare(name) == 0) {
|
if (m_symbols[i].name == name) {
|
||||||
return &m_symbols[i];
|
return &m_symbols[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(Core_Linker, "Unresolved! {}", name);
|
// LOG_INFO(Core_Linker, "Unresolved! {}", name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +45,15 @@ void SymbolsResolver::DebugDump(const std::filesystem::path& file_name) {
|
||||||
} else {
|
} else {
|
||||||
nidName = "UNK";
|
nidName = "UNK";
|
||||||
}
|
}
|
||||||
f.WriteString(fmt::format("{:<20} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n",
|
f.WriteString(
|
||||||
symbol.virtual_address, ids.at(0), nidName, ids.at(1), ids.at(2),
|
fmt::format("0x{:<20x} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n",
|
||||||
ids.at(3), ids.at(4), ids.at(5), ids.at(6)));
|
symbol.virtual_address, ids.at(0), nidName, ids.at(1), ids.at(2), ids.at(3),
|
||||||
|
ids.at(4), ids.at(5), ids.at(6)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SymbolsResolver::GetSize() {
|
||||||
|
return m_symbols.size();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core::Loader
|
} // namespace Core::Loader
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDump(const std::filesystem::path& file_name);
|
void DebugDump(const std::filesystem::path& file_name);
|
||||||
|
int GetSize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<SymbolRecord> m_symbols;
|
std::vector<SymbolRecord> m_symbols;
|
||||||
|
|
21
src/main.cpp
21
src/main.cpp
|
@ -9,6 +9,8 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include <common/logging/log.h>
|
||||||
|
#include <core/hle/libraries/libc/libc.h>
|
||||||
#include <core/hle/libraries/libkernel/thread_management.h>
|
#include <core/hle/libraries/libkernel/thread_management.h>
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/discord.h"
|
#include "common/discord.h"
|
||||||
|
@ -49,6 +51,25 @@ int main(int argc, char* argv[]) {
|
||||||
OldLibraries::InitHLELibs(&linker->getHLESymbols());
|
OldLibraries::InitHLELibs(&linker->getHLESymbols());
|
||||||
Core::InstallTlsHandler();
|
Core::InstallTlsHandler();
|
||||||
linker->LoadModule(path);
|
linker->LoadModule(path);
|
||||||
|
// check if there is a libc.prx in sce_module folder
|
||||||
|
bool found = false;
|
||||||
|
if (Config::isLleLibc()) {
|
||||||
|
std::filesystem::path sce_module_folder = p.parent_path() / "sce_module";
|
||||||
|
if (std::filesystem::is_directory(sce_module_folder)) {
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
||||||
|
if (entry.path().filename() == "libc.prx" ||
|
||||||
|
entry.path().filename() == "libSceFios2.prx") {
|
||||||
|
found = true;
|
||||||
|
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||||
|
linker->LoadModule(entry.path().string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) // load HLE libc
|
||||||
|
{
|
||||||
|
Core::Libraries::LibC::libcSymbolsRegister(&linker->getHLESymbols());
|
||||||
|
}
|
||||||
std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); },
|
std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); },
|
||||||
nullptr);
|
nullptr);
|
||||||
Discord::RPC discordRPC;
|
Discord::RPC discordRPC;
|
||||||
|
|
Loading…
Reference in New Issue