commit
c3d26e92c6
|
@ -15,7 +15,11 @@ u32 screenHeight = 720;
|
|||
std::string logFilter;
|
||||
std::string logType = "sync";
|
||||
bool isDebugDump = false;
|
||||
bool isLibc = true;
|
||||
|
||||
bool isLleLibc() {
|
||||
return isLibc;
|
||||
}
|
||||
bool isNeoMode() {
|
||||
return isNeo;
|
||||
}
|
||||
|
@ -84,6 +88,14 @@ void load(const std::filesystem::path& path) {
|
|||
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) {
|
||||
toml::basic_value<toml::preserve_comments> data;
|
||||
|
@ -110,6 +122,7 @@ void save(const std::filesystem::path& path) {
|
|||
data["GPU"]["screenWidth"] = screenWidth;
|
||||
data["GPU"]["screenHeight"] = screenHeight;
|
||||
data["Debug"]["DebugDump"] = isDebugDump;
|
||||
data["LLE"]["libc"] = isLibc;
|
||||
|
||||
std::ofstream file(path, std::ios::out);
|
||||
file << data;
|
||||
|
|
|
@ -18,5 +18,6 @@ u32 getScreenWidth();
|
|||
u32 getScreenHeight();
|
||||
|
||||
bool debugDump();
|
||||
bool isLleLibc();
|
||||
|
||||
}; // 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;
|
||||
|
||||
switch (prot) {
|
||||
case 0x03:
|
||||
cpu_mode = VirtualMemory::MemoryMode::ReadWrite;
|
||||
break;
|
||||
case 0x32:
|
||||
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;
|
||||
|
|
|
@ -19,11 +19,18 @@
|
|||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <common/singleton.h>
|
||||
#include <core/linker.h>
|
||||
|
||||
namespace Core::Libraries::LibKernel {
|
||||
|
||||
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) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
@ -117,6 +124,23 @@ PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd,
|
|||
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) {
|
||||
// obj
|
||||
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("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
||||
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::timeSymbolsRegister(sym);
|
||||
Core::Libraries::LibKernel::pthreadSymbolsRegister(sym);
|
||||
|
||||
// temp
|
||||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||
sceLibcHeapGetTraceInfo);
|
||||
}
|
||||
|
||||
} // namespace Core::Libraries::LibKernel
|
||||
|
|
|
@ -187,7 +187,6 @@ void* createMutex(void* addr) {
|
|||
|
||||
int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr,
|
||||
const char* name) {
|
||||
LOG_INFO(Kernel_Pthread, "called");
|
||||
if (mutex == nullptr) {
|
||||
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) {
|
||||
if (addr == nullptr || *static_cast<ScePthreadCond*>(addr) != nullptr) {
|
||||
return addr;
|
||||
|
@ -470,6 +486,7 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) {
|
|||
// mutex calls
|
||||
LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit);
|
||||
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("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol);
|
||||
LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <common/config.h>
|
||||
#include "core/PS4/HLE/Graphics/video_out.h"
|
||||
#include "core/hle/libraries/libc/libc.h"
|
||||
#include "core/hle/libraries/libkernel/libkernel.h"
|
||||
|
@ -20,7 +21,9 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||
HLE::Libs::Graphics::VideoOut::videoOutRegisterLib(sym);
|
||||
Core::Libraries::LibSceGnmDriver::LibSceGnmDriver_Register(sym);
|
||||
OldLibraries::LibPad::padSymbolsRegister(sym);
|
||||
if (!Config::isLleLibc()) {
|
||||
Core::Libraries::LibC::libcSymbolsRegister(sym);
|
||||
}
|
||||
|
||||
// new libraries folder from autogen
|
||||
Libraries::UserService::RegisterlibSceUserService(sym);
|
||||
|
|
|
@ -1883,7 +1883,7 @@ int PS4_SYSV_ABI sceSystemServiceNavigateToGoHome() {
|
|||
|
||||
s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(int param_id, int* value) {
|
||||
// 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) {
|
||||
LOG_ERROR(Lib_SystemService, "value is null");
|
||||
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) {
|
||||
// TODO fix me better
|
||||
LOG_INFO(Lib_UserService, "called");
|
||||
LOG_INFO(Lib_UserService, "called user_id = {}", user_id);
|
||||
if (color == nullptr) {
|
||||
LOG_ERROR(Lib_UserService, "color is null");
|
||||
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) {
|
||||
LOG_INFO(Lib_UserService, "called user_id = {} ,size = {} ", user_id, size);
|
||||
if (user_name == nullptr) {
|
||||
LOG_ERROR(Lib_UserService, "user_name is null");
|
||||
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
|
@ -1110,7 +1111,7 @@ int PS4_SYSV_ABI sceUserServiceGetVolumeForSidetone() {
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceUserServiceInitialize(const OrbisUserServiceInitializeParams* initParams) {
|
||||
LOG_ERROR(Lib_UserService, "(STUBBED) called");
|
||||
LOG_WARNING(Lib_UserService, "(dummy) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <Zydis/Zydis.h>
|
||||
#include <common/assert.h>
|
||||
#include "common/config.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/path_util.h"
|
||||
|
@ -15,7 +16,8 @@
|
|||
|
||||
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) {
|
||||
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());
|
||||
LoadDynamicInfo(m.get());
|
||||
LoadSymbols(m.get());
|
||||
Relocate(m.get());
|
||||
} else {
|
||||
m_modules.pop_back();
|
||||
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();
|
||||
}
|
||||
|
||||
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) {
|
||||
// get elf header, program header
|
||||
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,
|
||||
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, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr);
|
||||
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 image size ={}", m->tls.image_size);
|
||||
break;
|
||||
case PT_SCE_PROCPARAM:
|
||||
m->proc_param_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Core_Linker, "Unimplemented 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) {
|
||||
|
||||
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 ||
|
||||
m->dynamic_info.symbol_table_total_size == 0) {
|
||||
LOG_INFO(Core_Linker, "Symbol table not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto* sym = m->dynamic_info.symbol_table;
|
||||
reinterpret_cast<uint8_t*>(sym) <
|
||||
reinterpret_cast<uint8_t*>(m->dynamic_info.symbol_table) +
|
||||
reinterpret_cast<u8*>(sym) < reinterpret_cast<u8*>(m->dynamic_info.symbol_table) +
|
||||
m->dynamic_info.symbol_table_total_size;
|
||||
sym++) {
|
||||
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 type = sym->GetType();
|
||||
auto visibility = sym->GetVisibility();
|
||||
if (library != nullptr || module != nullptr) {
|
||||
switch (bind) {
|
||||
case STB_GLOBAL:
|
||||
case STB_WEAK:
|
||||
break;
|
||||
default:
|
||||
LOG_INFO(Core_Linker, "Unsupported bind {} for name symbol {}", bind,
|
||||
ids.at(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;
|
||||
const auto ids = Common::SplitString(id, '#');
|
||||
if (ids.size() == 3) {
|
||||
const auto* library = FindLibrary(*m, ids.at(1));
|
||||
const auto* module = FindModule(*m, ids.at(2));
|
||||
ASSERT_MSG(library && module, "Unable to find library and module");
|
||||
if ((bind == STB_GLOBAL || bind == STB_WEAK) &&
|
||||
(type == STT_FUN || type == STT_OBJECT) &&
|
||||
export_func == (sym->st_value != 0)) {
|
||||
std::string nidName = "";
|
||||
|
||||
auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
|
||||
|
||||
if (aeronid != nullptr) {
|
||||
nidName = aeronid->name;
|
||||
} else {
|
||||
nidName = "UNK";
|
||||
}
|
||||
|
||||
Loader::SymbolResolver sym_r{};
|
||||
sym_r.name = ids.at(0);
|
||||
sym_r.nidName = nidName;
|
||||
|
@ -459,20 +429,14 @@ void Linker::LoadSymbols(Module* m) {
|
|||
sym_r.type = Loader::SymbolType::Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_sym_export) {
|
||||
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->AddSymbol(sym_r,
|
||||
(export_func ? sym->st_value + m->base_virtual_addr : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
symbol_database(m, &m->export_sym, true);
|
||||
symbol_database(m, &m->import_sym, false);
|
||||
}
|
||||
|
||||
void Linker::Relocate(Module* m) {
|
||||
|
@ -492,17 +456,18 @@ void Linker::Relocate(Module* m) {
|
|||
|
||||
switch (type) {
|
||||
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_isResolved = true;
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
case R_X86_64_JUMP_SLOT: // similar but addend is not take into account
|
||||
{
|
||||
case R_X86_64_DTPMOD64:
|
||||
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_bind = sym.GetBind();
|
||||
auto sym_type = sym.GetType();
|
||||
|
@ -516,36 +481,32 @@ void Linker::Relocate(Module* m) {
|
|||
case STT_OBJECT:
|
||||
rel_sym_type = Loader::SymbolType::Object;
|
||||
break;
|
||||
case STT_NOTYPE:
|
||||
rel_sym_type = Loader::SymbolType::NoType;
|
||||
break;
|
||||
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
|
||||
{
|
||||
LOG_INFO(Core_Linker, "symbol visilibity !=0");
|
||||
}
|
||||
switch (sym_bind) {
|
||||
case STB_LOCAL:
|
||||
symbol_vitrual_addr = rel_base_virtual_addr + sym.st_value;
|
||||
break;
|
||||
case STB_GLOBAL:
|
||||
case STB_WEAK: {
|
||||
rel_name = namesTlb + sym.st_name;
|
||||
Resolve(rel_name, rel_sym_type, m, &symrec);
|
||||
symbol_vitrual_addr = symrec.virtual_address;
|
||||
rel_isResolved = (symbol_vitrual_addr != 0);
|
||||
|
||||
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;
|
||||
} break;
|
||||
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;
|
||||
default:
|
||||
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) {
|
||||
// std::scoped_lock lock{m_mutex};
|
||||
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* module = FindModule(*m, ids.at(2));
|
||||
ASSERT_MSG(library && module, "Unable to find library and module");
|
||||
|
||||
if (library != nullptr && module != nullptr) {
|
||||
Loader::SymbolResolver sr{};
|
||||
sr.name = ids.at(0);
|
||||
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_version_major = module->version_major;
|
||||
sr.module_version_minor = module->version_minor;
|
||||
sr.type = Symtype;
|
||||
sr.type = sym_type;
|
||||
|
||||
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) {
|
||||
*return_info = *rec;
|
||||
} 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,
|
||||
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 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() {
|
||||
fmt::print("exit function called\n");
|
||||
|
@ -653,12 +667,20 @@ void Linker::Execute() {
|
|||
}
|
||||
|
||||
Core::Libraries::LibKernel::pthreadInitSelfMainThread();
|
||||
// relocate all modules
|
||||
for (const auto& m : m_modules) {
|
||||
Relocate(m.get());
|
||||
}
|
||||
StartAllModules();
|
||||
EntryParams p{};
|
||||
p.argc = 1;
|
||||
p.argv[0] = "eboot.bin"; // hmm should be ok?
|
||||
|
||||
const auto& module = m_modules.at(0);
|
||||
RunMainEntry(module->elf.GetElfEntry() + module->base_virtual_addr, &p, ProgramExitFunc);
|
||||
for (auto& m : m_modules) {
|
||||
if (!m->elf.IsSharedLib()) {
|
||||
RunMainEntry(m->elf.GetElfEntry() + m->base_virtual_addr, &p, ProgramExitFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Linker::DebugDump() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "core/loader/symbols_resolver.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
using module_func_t = int (*)(size_t args, const void* argp);
|
||||
struct DynamicModuleInfo;
|
||||
class Linker;
|
||||
|
||||
|
@ -20,6 +20,10 @@ struct EntryParams {
|
|||
};
|
||||
|
||||
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;
|
||||
union {
|
||||
u64 value;
|
||||
|
@ -34,6 +38,9 @@ struct ModuleInfo {
|
|||
};
|
||||
|
||||
struct LibraryInfo {
|
||||
bool operator==(const LibraryInfo& other) const {
|
||||
return version == other.version && name == other.name;
|
||||
}
|
||||
std::string name;
|
||||
union {
|
||||
u64 value;
|
||||
|
@ -99,6 +106,7 @@ struct Module {
|
|||
Loader::Elf elf;
|
||||
u64 aligned_base_size = 0;
|
||||
u64 base_virtual_addr = 0;
|
||||
u64 proc_param_virtual_addr = 0;
|
||||
|
||||
std::string file_name;
|
||||
|
||||
|
@ -118,7 +126,6 @@ public:
|
|||
virtual ~Linker();
|
||||
|
||||
Module* LoadModule(const std::filesystem::path& elf_name);
|
||||
Module* FindModule(u32 id = 0);
|
||||
void LoadModuleToMemory(Module* m);
|
||||
void LoadDynamicInfo(Module* m);
|
||||
void LoadSymbols(Module* m);
|
||||
|
@ -130,10 +137,14 @@ public:
|
|||
Loader::SymbolRecord* return_info);
|
||||
void Execute();
|
||||
void DebugDump();
|
||||
u64 GetProcParam();
|
||||
|
||||
private:
|
||||
const ModuleInfo* FindModule(const Module& m, 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;
|
||||
Loader::SymbolsResolver m_hle_symbols{};
|
||||
|
|
|
@ -538,4 +538,8 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) {
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
bool Elf::IsSharedLib() {
|
||||
return m_elf_header.e_type == ET_SCE_DYNAMIC;
|
||||
}
|
||||
|
||||
} // namespace Core::Loader
|
||||
|
|
|
@ -490,6 +490,7 @@ public:
|
|||
std::string ElfPheaderFlagsStr(u32 flags);
|
||||
|
||||
void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size);
|
||||
bool IsSharedLib();
|
||||
|
||||
private:
|
||||
Common::FS::IOFile m_f{};
|
||||
|
|
|
@ -11,10 +11,9 @@
|
|||
namespace Core::Loader {
|
||||
|
||||
void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) {
|
||||
SymbolRecord r{};
|
||||
SymbolRecord& r = m_symbols.emplace_back();
|
||||
r.name = GenerateName(s);
|
||||
r.virtual_address = virtual_addr;
|
||||
m_symbols.push_back(r);
|
||||
}
|
||||
|
||||
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 std::string name = GenerateName(s);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO(Core_Linker, "Unresolved! {}", name);
|
||||
// LOG_INFO(Core_Linker, "Unresolved! {}", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -46,10 +45,15 @@ void SymbolsResolver::DebugDump(const std::filesystem::path& file_name) {
|
|||
} else {
|
||||
nidName = "UNK";
|
||||
}
|
||||
f.WriteString(fmt::format("{:<20} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n",
|
||||
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)));
|
||||
f.WriteString(
|
||||
fmt::format("0x{:<20x} {:<16} {:<60} {:<30} {:<2} {:<30} {:<2} {:<2} {:<10}\n",
|
||||
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
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
}
|
||||
|
||||
void DebugDump(const std::filesystem::path& file_name);
|
||||
int GetSize();
|
||||
|
||||
private:
|
||||
std::vector<SymbolRecord> m_symbols;
|
||||
|
|
21
src/main.cpp
21
src/main.cpp
|
@ -9,6 +9,8 @@
|
|||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#include <common/logging/log.h>
|
||||
#include <core/hle/libraries/libc/libc.h>
|
||||
#include <core/hle/libraries/libkernel/thread_management.h>
|
||||
#include "common/config.h"
|
||||
#include "common/discord.h"
|
||||
|
@ -49,6 +51,25 @@ int main(int argc, char* argv[]) {
|
|||
OldLibraries::InitHLELibs(&linker->getHLESymbols());
|
||||
Core::InstallTlsHandler();
|
||||
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(); },
|
||||
nullptr);
|
||||
Discord::RPC discordRPC;
|
||||
|
|
Loading…
Reference in New Issue