Merge pull request #100 from shadps4-emu/libc_part2

Libc LLE
This commit is contained in:
georgemoralis 2024-03-28 07:24:06 +02:00 committed by GitHub
commit c3d26e92c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 305 additions and 174 deletions

View File

@ -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;

View File

@ -18,5 +18,6 @@ u32 getScreenWidth();
u32 getScreenHeight(); u32 getScreenHeight();
bool debugDump(); bool debugDump();
bool isLleLibc();
}; // namespace Config }; // namespace Config

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }

View File

@ -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() {

View File

@ -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{};

View File

@ -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

View File

@ -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{};

View File

@ -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

View File

@ -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;

View File

@ -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;