mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
loader: use interpreter if possible
fixed end address alignment fixed loading elfs without sceDynlibData pass phdr address to interpreter cleanup
This commit is contained in:
parent
797f70268f
commit
f09d3151ff
|
|
@ -103,6 +103,7 @@ struct Module final {
|
|||
|
||||
bool isTlsDone = false;
|
||||
|
||||
utils::kstring interp;
|
||||
utils::kvector<Symbol> symbols;
|
||||
utils::kvector<Relocation> pltRelocations;
|
||||
utils::kvector<Relocation> nonPltRelocations;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include <crypto/sha1.h>
|
||||
#include <elf.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <orbis/thread/Process.hpp>
|
||||
#include <sys/mman.h>
|
||||
|
|
@ -404,7 +403,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
std::min(baseAddress, utils::alignDown(phdr.p_vaddr, phdr.p_align));
|
||||
endAddress =
|
||||
std::max(endAddress,
|
||||
utils::alignUp(phdr.p_vaddr + phdr.p_memsz, phdr.p_align));
|
||||
utils::alignUp(phdr.p_vaddr + phdr.p_memsz, vm::kPageSize));
|
||||
break;
|
||||
case kElfProgramTypeDynamic:
|
||||
dynamicPhdrIndex = index;
|
||||
|
|
@ -439,7 +438,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
std::min(baseAddress, utils::alignDown(phdr.p_vaddr, phdr.p_align));
|
||||
endAddress =
|
||||
std::max(endAddress,
|
||||
utils::alignUp(phdr.p_vaddr + phdr.p_memsz, phdr.p_align));
|
||||
utils::alignUp(phdr.p_vaddr + phdr.p_memsz, vm::kPageSize));
|
||||
break;
|
||||
case kElfProgramTypeGnuEhFrame:
|
||||
gnuEhFramePhdrIndex = index;
|
||||
|
|
@ -473,6 +472,11 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
imageBase - baseAddress + header.e_entry)
|
||||
: 0;
|
||||
|
||||
if (interpPhdrIndex >= 0) {
|
||||
result->interp = reinterpret_cast<const char *>(
|
||||
image.data() + phdrs[interpPhdrIndex].p_offset);
|
||||
}
|
||||
|
||||
if (sceProcParamIndex >= 0) {
|
||||
result->processParam =
|
||||
phdrs[sceProcParamIndex].p_vaddr
|
||||
|
|
@ -489,13 +493,6 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
phdrs[sceModuleParamIndex].p_vaddr)
|
||||
: nullptr;
|
||||
result->moduleParamSize = phdrs[sceModuleParamIndex].p_memsz;
|
||||
|
||||
// std::printf("sce_module_param: ");
|
||||
// for (auto elem : image.subspan(phdrs[sceModuleParamIndex].p_offset,
|
||||
// phdrs[sceModuleParamIndex].p_filesz)) {
|
||||
// std::printf(" %02x", (unsigned)elem);
|
||||
// }
|
||||
// std::printf("\n");
|
||||
}
|
||||
|
||||
if (tlsPhdrIndex >= 0) {
|
||||
|
|
@ -579,22 +576,53 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
|
||||
int sceStrtabIndex = -1;
|
||||
int sceSymtabIndex = -1;
|
||||
std::size_t sceSymtabSize = 0;
|
||||
int strtabIndex = -1;
|
||||
int symtabIndex = -1;
|
||||
int hashIndex = -1;
|
||||
int sceSymtabSizeIndex = -1;
|
||||
for (auto &dyn : dyns) {
|
||||
if (dyn.d_tag == kElfDynamicTypeSceStrTab) {
|
||||
sceStrtabIndex = &dyn - dyns.data();
|
||||
} else if (dyn.d_tag == kElfDynamicTypeSceSymTab) {
|
||||
sceSymtabIndex = &dyn - dyns.data();
|
||||
} else if (dyn.d_tag == kElfDynamicTypeSceSymTabSize) {
|
||||
sceSymtabSize = dyn.d_un.d_val;
|
||||
sceSymtabSizeIndex = &dyn - dyns.data();
|
||||
} else if (dyn.d_tag == kElfDynamicTypeStrTab) {
|
||||
strtabIndex = &dyn - dyns.data();
|
||||
} else if (dyn.d_tag == kElfDynamicTypeSymTab) {
|
||||
symtabIndex = &dyn - dyns.data();
|
||||
} else if (dyn.d_tag == kElfDynamicTypeHash) {
|
||||
hashIndex = &dyn - dyns.data();
|
||||
}
|
||||
}
|
||||
|
||||
auto sceStrtab = sceStrtabIndex >= 0 && sceDynlibDataPhdrIndex >= 0
|
||||
? reinterpret_cast<const char *>(
|
||||
image.data() + dyns[sceStrtabIndex].d_un.d_val +
|
||||
phdrs[sceDynlibDataPhdrIndex].p_offset)
|
||||
: nullptr;
|
||||
auto dynTabOffsetGet = [&](std::uint64_t address) {
|
||||
if (sceSymtabIndex < 0 || sceStrtabIndex < 0) {
|
||||
for (auto &phdr : phdrs) {
|
||||
if (phdr.p_vaddr <= address &&
|
||||
address < phdr.p_vaddr + phdr.p_memsz) {
|
||||
return phdr.p_offset + address - phdr.p_vaddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return address;
|
||||
};
|
||||
|
||||
auto sceStrtab =
|
||||
sceStrtabIndex >= 0 && sceDynlibDataPhdrIndex >= 0
|
||||
? reinterpret_cast<const char *>(
|
||||
image.data() +
|
||||
dynTabOffsetGet(dyns[sceStrtabIndex].d_un.d_val) +
|
||||
phdrs[sceDynlibDataPhdrIndex].p_offset)
|
||||
: nullptr;
|
||||
|
||||
auto strtab = sceStrtab;
|
||||
|
||||
if (strtab == nullptr && strtabIndex >= 0) {
|
||||
strtab = reinterpret_cast<const char *>(
|
||||
image.data() + dynTabOffsetGet(dyns[strtabIndex].d_un.d_val));
|
||||
}
|
||||
|
||||
auto sceDynlibData =
|
||||
sceDynlibDataPhdrIndex >= 0
|
||||
|
|
@ -607,6 +635,25 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
sceDynlibData + dyns[sceSymtabIndex].d_un.d_val)
|
||||
: nullptr;
|
||||
|
||||
auto symtab = sceSymtabData;
|
||||
auto symtabSize =
|
||||
sceSymtabSizeIndex >= 0
|
||||
? dyns[sceSymtabSizeIndex].d_un.d_val / sizeof(Elf64_Sym)
|
||||
: 0;
|
||||
|
||||
if (symtab == nullptr && symtabIndex >= 0) {
|
||||
if (hashIndex < 0) {
|
||||
std::fprintf(stderr, "SYMTAB without HASH!\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
symtab = reinterpret_cast<const Elf64_Sym *>(
|
||||
image.data() + dynTabOffsetGet(dyns[symtabIndex].d_un.d_val));
|
||||
symtabSize = *reinterpret_cast<const std::uint32_t *>(
|
||||
image.data() + dynTabOffsetGet(dyns[hashIndex].d_un.d_val) +
|
||||
sizeof(std::uint32_t));
|
||||
}
|
||||
|
||||
std::unordered_map<std::uint64_t, std::size_t> idToModuleIndex;
|
||||
std::unordered_map<std::uint64_t, std::size_t> idToLibraryIndex;
|
||||
|
||||
|
|
@ -615,45 +662,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
orbis::Relocation *nonPltRelocations = nullptr;
|
||||
std::size_t nonPltRelocationCount = 0;
|
||||
|
||||
auto patchSoName = [](std::string_view name) {
|
||||
if (name.ends_with(".prx")) {
|
||||
name.remove_suffix(4);
|
||||
}
|
||||
if (name.ends_with("-PRX")) {
|
||||
name.remove_suffix(4); // TODO: implement lib scan
|
||||
}
|
||||
if (name.ends_with("-module")) {
|
||||
name.remove_suffix(7); // TODO: implement lib scan
|
||||
}
|
||||
if (name.ends_with("_padebug")) {
|
||||
name.remove_suffix(8);
|
||||
}
|
||||
if (name.ends_with("_sys")) {
|
||||
name.remove_suffix(4);
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
for (auto dyn : dyns) {
|
||||
// std::printf("%s: %lx", toString((OrbisElfDynamicType)dyn.d_tag),
|
||||
// dyn.d_un.d_val);
|
||||
|
||||
// if (dyn.d_tag == kElfDynamicTypeSceNeededModule ||
|
||||
// dyn.d_tag == kElfDynamicTypeNeeded ||
|
||||
// dyn.d_tag == kElfDynamicTypeSceOriginalFilename ||
|
||||
// dyn.d_tag == kElfDynamicTypeSceImportLib ||
|
||||
// dyn.d_tag == kElfDynamicTypeSceExportLib ||
|
||||
// dyn.d_tag == kElfDynamicTypeSceModuleInfo) {
|
||||
// std::printf(" ('%s')",
|
||||
// sceStrtab
|
||||
// ? sceStrtab +
|
||||
// static_cast<std::uint32_t>(dyn.d_un.d_val) : "<no
|
||||
// strtab>");
|
||||
// }
|
||||
|
||||
// std::printf("\n");
|
||||
|
||||
if (dyn.d_tag == kElfDynamicTypeSceModuleInfo) {
|
||||
std::strncpy(result->moduleName,
|
||||
sceStrtab + static_cast<std::uint32_t>(dyn.d_un.d_val),
|
||||
|
|
@ -663,27 +672,11 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
}
|
||||
|
||||
if (dyn.d_tag == kElfDynamicTypeSoName) {
|
||||
auto name =
|
||||
patchSoName(sceStrtab + static_cast<std::uint32_t>(dyn.d_un.d_val));
|
||||
std::memcpy(result->soName, name.data(), name.size());
|
||||
std::memcpy(result->soName + name.size(), ".prx", sizeof(".prx"));
|
||||
std::strncpy(result->soName,
|
||||
strtab + static_cast<std::uint32_t>(dyn.d_un.d_val),
|
||||
sizeof(result->soName));
|
||||
}
|
||||
|
||||
// if (dyn.d_tag == kElfDynamicTypeNeeded) {
|
||||
// auto name = std::string_view(
|
||||
// sceStrtab + static_cast<std::uint32_t>(dyn.d_un.d_val));
|
||||
// if (name == "STREQUAL") {
|
||||
// // HACK for broken FWs
|
||||
// result->needed.push_back("libSceDolbyVision.prx");
|
||||
// } else {
|
||||
// name = patchSoName(name);
|
||||
// if (name != "libSceFreeTypeOptBm") { // TODO
|
||||
// result->needed.emplace_back(name);
|
||||
// result->needed.back() += ".prx";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (dyn.d_tag == kElfDynamicTypeSceModuleInfo) {
|
||||
idToModuleIndex[dyn.d_un.d_val >> 48] = -1;
|
||||
}
|
||||
|
|
@ -697,7 +690,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
}
|
||||
|
||||
auto &mod = result->neededModules[it->second];
|
||||
mod.name = sceStrtab + static_cast<std::uint32_t>(dyn.d_un.d_val);
|
||||
mod.name = strtab + static_cast<std::uint32_t>(dyn.d_un.d_val);
|
||||
mod.attr = static_cast<std::uint16_t>(dyn.d_un.d_val >> 32);
|
||||
mod.isExport = false;
|
||||
} else if (dyn.d_tag == kElfDynamicTypeSceImportLib ||
|
||||
|
|
@ -711,7 +704,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
|
||||
auto &lib = result->neededLibraries[it->second];
|
||||
|
||||
lib.name = sceStrtab + static_cast<std::uint32_t>(dyn.d_un.d_val);
|
||||
lib.name = strtab + static_cast<std::uint32_t>(dyn.d_un.d_val);
|
||||
lib.isExport = dyn.d_tag == kElfDynamicTypeSceExportLib;
|
||||
} else if (dyn.d_tag == kElfDynamicTypeSceExportLibAttr ||
|
||||
dyn.d_tag == kElfDynamicTypeSceImportLibAttr) {
|
||||
|
|
@ -739,6 +732,9 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
if (sceDynlibData != nullptr) {
|
||||
pltRelocations = reinterpret_cast<orbis::Relocation *>(
|
||||
sceDynlibData + dyn.d_un.d_ptr);
|
||||
} else {
|
||||
pltRelocations = reinterpret_cast<orbis::Relocation *>(
|
||||
image.data() + dyn.d_un.d_ptr);
|
||||
}
|
||||
break;
|
||||
case kElfDynamicTypeScePltRel:
|
||||
|
|
@ -750,6 +746,9 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
if (sceDynlibData != nullptr) {
|
||||
nonPltRelocations = reinterpret_cast<orbis::Relocation *>(
|
||||
sceDynlibData + dyn.d_un.d_ptr);
|
||||
} else {
|
||||
nonPltRelocations = reinterpret_cast<orbis::Relocation *>(
|
||||
image.data() + dyn.d_un.d_ptr);
|
||||
}
|
||||
break;
|
||||
case kElfDynamicTypeSceRelaSize:
|
||||
|
|
@ -767,9 +766,8 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
}
|
||||
}
|
||||
|
||||
if (sceSymtabData != nullptr && sceSymtabSize / sizeof(Elf64_Sym) > 0) {
|
||||
auto sceSymtab =
|
||||
std::span(sceSymtabData, sceSymtabSize / sizeof(Elf64_Sym));
|
||||
if (symtab != nullptr && symtabSize > 0) {
|
||||
auto sceSymtab = std::span(symtab, symtabSize);
|
||||
|
||||
result->symbols.reserve(sceSymtab.size());
|
||||
|
||||
|
|
@ -789,8 +787,8 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
symbol.address -= baseAddress;
|
||||
}
|
||||
|
||||
if (sceStrtab != nullptr && sym.st_name != 0) {
|
||||
auto fullName = std::string_view(sceStrtab + sym.st_name);
|
||||
if (strtab != nullptr && sym.st_name != 0) {
|
||||
auto fullName = std::string_view(strtab + sym.st_name);
|
||||
if (auto hashPos = fullName.find('#');
|
||||
hashPos != std::string_view::npos) {
|
||||
std::string_view module;
|
||||
|
|
@ -817,7 +815,8 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
symbol.id = *decodeNid(name);
|
||||
if (name == "5JrIq4tzVIo") {
|
||||
monoPimpAddress = symbol.address + (std::uint64_t)imageBase;
|
||||
std::fprintf(stderr, "mono_pimp address = %lx\n", monoPimpAddress);
|
||||
std::fprintf(stderr, "mono_pimp address = %lx\n",
|
||||
monoPimpAddress);
|
||||
}
|
||||
} else if (auto nid = decodeNid(fullName)) {
|
||||
symbol.id = *nid;
|
||||
|
|
@ -825,7 +824,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
symbol.moduleIndex = -1;
|
||||
} else {
|
||||
symbol.id =
|
||||
encodeFid(sceStrtab + static_cast<std::uint32_t>(sym.st_name));
|
||||
encodeFid(strtab + static_cast<std::uint32_t>(sym.st_name));
|
||||
symbol.libraryIndex = -1;
|
||||
symbol.moduleIndex = -1;
|
||||
}
|
||||
|
|
@ -853,20 +852,20 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
for (auto phdr : phdrs) {
|
||||
if (phdr.p_type == kElfProgramTypeLoad ||
|
||||
phdr.p_type == kElfProgramTypeSceRelRo) {
|
||||
auto segmentSize = utils::alignUp(phdr.p_memsz, phdr.p_align);
|
||||
::mprotect(imageBase + phdr.p_vaddr - baseAddress, segmentSize,
|
||||
PROT_WRITE);
|
||||
auto segmentEnd =
|
||||
utils::alignUp(phdr.p_vaddr + phdr.p_memsz, vm::kPageSize);
|
||||
auto segmentBegin =
|
||||
utils::alignDown(phdr.p_vaddr - baseAddress, phdr.p_align);
|
||||
auto segmentSize = segmentEnd - segmentBegin;
|
||||
::mprotect(imageBase + segmentBegin, segmentSize, PROT_WRITE);
|
||||
std::memcpy(imageBase + phdr.p_vaddr - baseAddress,
|
||||
image.data() + phdr.p_offset, phdr.p_filesz);
|
||||
std::memset(imageBase + phdr.p_vaddr + phdr.p_filesz - baseAddress, 0,
|
||||
phdr.p_memsz - phdr.p_filesz);
|
||||
|
||||
if (phdr.p_type == kElfProgramTypeSceRelRo) {
|
||||
phdr.p_flags |= vm::kMapProtCpuWrite; // TODO: reprotect on relocations
|
||||
}
|
||||
|
||||
vm::protect(imageBase + phdr.p_vaddr - baseAddress, segmentSize,
|
||||
phdr.p_flags);
|
||||
vm::protect(imageBase + segmentBegin, segmentSize, phdr.p_flags);
|
||||
|
||||
if (phdr.p_type == kElfProgramTypeLoad) {
|
||||
if (result->segmentCount >= std::size(result->segments)) {
|
||||
|
|
@ -874,7 +873,7 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
}
|
||||
|
||||
auto &segment = result->segments[result->segmentCount++];
|
||||
segment.addr = imageBase + phdr.p_vaddr - baseAddress;
|
||||
segment.addr = imageBase + segmentBegin;
|
||||
segment.size = phdr.p_memsz;
|
||||
segment.prot = phdr.p_flags;
|
||||
}
|
||||
|
|
@ -883,29 +882,9 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
|
||||
result->base = imageBase - baseAddress;
|
||||
result->size = imageSize + baseAddress;
|
||||
// std::printf("Needed modules: [");
|
||||
// for (bool isFirst = true; auto &module : result->neededModules) {
|
||||
// if (isFirst) {
|
||||
// isFirst = false;
|
||||
// } else {
|
||||
// std::printf(", ");
|
||||
// }
|
||||
|
||||
// std::printf("'%s'", module.name.c_str());
|
||||
// }
|
||||
// std::printf("]\n");
|
||||
// std::printf("Needed libraries: [");
|
||||
// for (bool isFirst = true; auto &library : result->neededLibraries) {
|
||||
// if (isFirst) {
|
||||
// isFirst = false;
|
||||
// } else {
|
||||
// std::printf(", ");
|
||||
// }
|
||||
|
||||
// std::printf("'%s'", library.name.c_str());
|
||||
// }
|
||||
// std::printf("]\n");
|
||||
|
||||
result->phdrAddress = phdrPhdrIndex >= 0 ? phdrs[phdrPhdrIndex].p_vaddr
|
||||
: baseAddress + header.e_phoff;
|
||||
result->phNum = header.e_phnum;
|
||||
result->proc = process;
|
||||
|
||||
std::printf("Loaded module '%s' (%lx) from object '%s', address: %p - %p\n",
|
||||
|
|
@ -928,14 +907,10 @@ Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image,
|
|||
return result;
|
||||
}
|
||||
|
||||
Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
|
||||
orbis::Thread *thread) {
|
||||
if (!path.contains('/')) {
|
||||
return loadModuleByName(path, thread);
|
||||
}
|
||||
|
||||
static Ref<orbis::Module> loadModuleFileImpl(std::string_view path,
|
||||
orbis::Thread *thread) {
|
||||
orbis::Ref<orbis::File> instance;
|
||||
if (vfs::open(path, kOpenFlagReadOnly, 0, &instance, thread).isError()) {
|
||||
if (rx::vfs::open(path, kOpenFlagReadOnly, 0, &instance, thread).isError()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -985,95 +960,34 @@ Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
|
|||
// .write((const char *)image.data(), image.size());
|
||||
}
|
||||
|
||||
return loadModule(image, thread->tproc);
|
||||
return rx::linker::loadModule(image, thread->tproc);
|
||||
}
|
||||
|
||||
static Ref<orbis::Module> createSceFreeTypeFull(orbis::Thread *thread) {
|
||||
auto result = orbis::knew<orbis::Module>();
|
||||
|
||||
std::strncpy(result->soName, "libSceFreeTypeFull.prx",
|
||||
sizeof(result->soName) - 1);
|
||||
std::strncpy(result->moduleName, "libSceFreeType",
|
||||
sizeof(result->moduleName) - 1);
|
||||
|
||||
result->neededLibraries.push_back(
|
||||
{.name = "libSceFreeType", .isExport = true});
|
||||
|
||||
for (auto dep :
|
||||
{"libSceFreeTypeSubFunc", "libSceFreeTypeOl", "libSceFreeTypeOt",
|
||||
"libSceFreeTypeOptOl", "libSceFreeTypeHinter"}) {
|
||||
result->needed.push_back(dep);
|
||||
result->needed.back() += ".prx";
|
||||
Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
|
||||
orbis::Thread *thread) {
|
||||
if (auto result = loadModuleFileImpl(path, thread)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (auto needed : result->needed) {
|
||||
auto neededMod = rx::linker::loadModuleByName(needed, thread);
|
||||
if (path.ends_with(".sprx")) {
|
||||
path.remove_suffix(4);
|
||||
|
||||
if (neededMod == nullptr) {
|
||||
std::fprintf(stderr, "Failed to load needed '%s' for FreeType\n",
|
||||
needed.c_str());
|
||||
std::abort();
|
||||
if (auto result = loadModuleFileImpl(std::string(path) + "prx", thread)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result->namespaceModules.push_back(neededMod);
|
||||
}
|
||||
|
||||
// TODO: load native library with module_start and module_stop
|
||||
result->initProc = reinterpret_cast<void *>(+[] {});
|
||||
result->finiProc = reinterpret_cast<void *>(+[] {});
|
||||
|
||||
result->proc = thread->tproc;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Ref<orbis::Module> rx::linker::loadModuleByName(std::string_view name,
|
||||
orbis::Thread *thread) {
|
||||
if (name.ends_with(".prx")) {
|
||||
name.remove_suffix(4);
|
||||
}
|
||||
|
||||
if (auto it = g_moduleOverrideTable.find(name);
|
||||
it != g_moduleOverrideTable.end()) {
|
||||
return loadModuleFile(it->second.c_str(), thread);
|
||||
}
|
||||
|
||||
if (name == "libSceAbstractTwitch") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (name == "libSceFreeTypeFull") {
|
||||
return createSceFreeTypeFull(thread);
|
||||
if (path.ends_with(".prx")) {
|
||||
path.remove_suffix(3);
|
||||
|
||||
if (auto result = loadModuleFileImpl(std::string(path) + "sprx", thread)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
std::string filePath = "/app0/sce_module/";
|
||||
filePath += name;
|
||||
filePath += ".elf";
|
||||
if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) {
|
||||
return result;
|
||||
}
|
||||
filePath.resize(filePath.size() - 4);
|
||||
filePath += ".sprx";
|
||||
if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) {
|
||||
return result;
|
||||
}
|
||||
filePath.resize(filePath.size() - 5);
|
||||
filePath += ".prx";
|
||||
if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto path : {"/system/common/lib/", "/system/priv/lib/"}) {
|
||||
auto filePath = std::string(path);
|
||||
filePath += name;
|
||||
filePath += ".sprx";
|
||||
|
||||
if (auto result = rx::linker::loadModuleFile(filePath.c_str(), thread)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,4 @@ orbis::Ref<orbis::Module> loadModule(std::span<std::byte> image,
|
|||
orbis::Process *process);
|
||||
orbis::Ref<orbis::Module> loadModuleFile(std::string_view path,
|
||||
orbis::Thread *thread);
|
||||
orbis::Ref<orbis::Module> loadModuleByName(std::string_view name,
|
||||
orbis::Thread *thread);
|
||||
} // namespace rx::linker
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
}
|
||||
}
|
||||
|
||||
struct sigaction act {};
|
||||
struct sigaction act{};
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
|
||||
|
|
@ -243,7 +243,7 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
void setupSigHandlers() {
|
||||
rx::thread::setupSignalStack();
|
||||
|
||||
struct sigaction act {};
|
||||
struct sigaction act{};
|
||||
act.sa_sigaction = handle_signal;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
|
||||
|
||||
|
|
@ -553,6 +553,9 @@ int ps4Exec(orbis::Thread *mainThread, ExecEnv execEnv,
|
|||
std::uint64_t auxv[] = {
|
||||
AT_ENTRY, executableModule->entryPoint,
|
||||
AT_BASE, execEnv.interpBase,
|
||||
AT_PHDR, executableModule->phdrAddress,
|
||||
AT_PHENT, sizeof(Elf64_Phdr),
|
||||
AT_PHNUM, executableModule->phNum,
|
||||
AT_NULL, 0
|
||||
};
|
||||
// clang-format on
|
||||
|
|
@ -593,13 +596,27 @@ int ps4Exec(orbis::Thread *mainThread, ExecEnv execEnv,
|
|||
std::abort();
|
||||
}
|
||||
|
||||
struct Ps4ProcessParam {
|
||||
orbis::size_t size;
|
||||
orbis::uint32_t magic;
|
||||
orbis::uint32_t version;
|
||||
orbis::uint32_t sdkVersion;
|
||||
orbis::uint32_t reserved;
|
||||
orbis::ptr<char> processName;
|
||||
orbis::ptr<char> userMainThreadName;
|
||||
orbis::ptr<orbis::uint> userMainThreadPriority;
|
||||
orbis::ptr<orbis::uint> userMainThreadStackSize;
|
||||
orbis::ptr<void> libcParam;
|
||||
};
|
||||
|
||||
ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
||||
orbis::Ref<orbis::Module> executableModule,
|
||||
bool isSystem) {
|
||||
std::uint64_t interpBase = 0;
|
||||
std::uint64_t entryPoint = executableModule->entryPoint;
|
||||
|
||||
if (mainThread->tproc->processParam != nullptr) {
|
||||
if (mainThread->tproc->processParam != nullptr &&
|
||||
mainThread->tproc->processParamSize <= sizeof(Ps4ProcessParam)) {
|
||||
auto processParam =
|
||||
reinterpret_cast<std::byte *>(mainThread->tproc->processParam);
|
||||
|
||||
|
|
@ -618,63 +635,75 @@ ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread,
|
|||
mainThread->tproc->sdkVersion = orbis::g_context.sdkVersion;
|
||||
}
|
||||
|
||||
if (executableModule->type != rx::linker::kElfTypeExec) {
|
||||
auto libSceLibcInternal = rx::linker::loadModuleFile(
|
||||
"/system/common/lib/libSceLibcInternal.sprx", mainThread);
|
||||
|
||||
if (libSceLibcInternal == nullptr) {
|
||||
std::fprintf(stderr, "libSceLibcInternal not found\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
libSceLibcInternal->id =
|
||||
mainThread->tproc->modulesMap.insert(libSceLibcInternal);
|
||||
|
||||
auto libkernel = rx::linker::loadModuleFile(
|
||||
(isSystem ? "/system/common/lib/libkernel_sys.sprx"
|
||||
: "/system/common/lib/libkernel.sprx"),
|
||||
mainThread);
|
||||
|
||||
if (libkernel == nullptr) {
|
||||
std::fprintf(stderr, "libkernel not found\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
for (auto sym : libkernel->symbols) {
|
||||
if (sym.id == 0xd2f4e7e480cc53d0) {
|
||||
auto address = (uint64_t)libkernel->base + sym.address;
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000),
|
||||
utils::alignUp(sym.size + sym.address, 0x1000), PROT_WRITE);
|
||||
std::printf("patching sceKernelGetMainSocId\n");
|
||||
struct GetMainSocId : Xbyak::CodeGenerator {
|
||||
GetMainSocId(std::uint64_t address, std::uint64_t size)
|
||||
: Xbyak::CodeGenerator(size, (void *)address) {
|
||||
mov(eax, 0x710f00);
|
||||
ret();
|
||||
}
|
||||
} gen{address, sym.size};
|
||||
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000),
|
||||
utils::alignUp(sym.size + sym.address, 0x1000),
|
||||
PROT_READ | PROT_EXEC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (orbis::g_context.fwSdkVersion == 0) {
|
||||
auto moduleParam = reinterpret_cast<std::byte *>(libkernel->moduleParam);
|
||||
auto fwSdkVersion = moduleParam //
|
||||
+ sizeof(uint64_t) // size
|
||||
+ sizeof(uint64_t); // magic
|
||||
orbis::g_context.fwSdkVersion = *(uint32_t *)fwSdkVersion;
|
||||
std::printf("fw sdk version: %x\n", orbis::g_context.fwSdkVersion);
|
||||
}
|
||||
|
||||
libkernel->id = mainThread->tproc->modulesMap.insert(libkernel);
|
||||
interpBase = reinterpret_cast<std::uint64_t>(libkernel->base);
|
||||
entryPoint = libkernel->entryPoint;
|
||||
if (executableModule->interp.empty()) {
|
||||
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
||||
}
|
||||
|
||||
if (rx::vfs::exists(executableModule->interp, mainThread)) {
|
||||
auto loader =
|
||||
rx::linker::loadModuleFile(executableModule->interp, mainThread);
|
||||
loader->id = mainThread->tproc->modulesMap.insert(loader);
|
||||
interpBase = reinterpret_cast<std::uint64_t>(loader->base);
|
||||
entryPoint = loader->entryPoint;
|
||||
|
||||
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
||||
}
|
||||
|
||||
auto libSceLibcInternal = rx::linker::loadModuleFile(
|
||||
"/system/common/lib/libSceLibcInternal.sprx", mainThread);
|
||||
|
||||
if (libSceLibcInternal == nullptr) {
|
||||
std::fprintf(stderr, "libSceLibcInternal not found\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
libSceLibcInternal->id =
|
||||
mainThread->tproc->modulesMap.insert(libSceLibcInternal);
|
||||
|
||||
auto libkernel = rx::linker::loadModuleFile(
|
||||
(isSystem ? "/system/common/lib/libkernel_sys.sprx"
|
||||
: "/system/common/lib/libkernel.sprx"),
|
||||
mainThread);
|
||||
|
||||
if (libkernel == nullptr) {
|
||||
std::fprintf(stderr, "libkernel not found\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
for (auto sym : libkernel->symbols) {
|
||||
if (sym.id == 0xd2f4e7e480cc53d0) {
|
||||
auto address = (uint64_t)libkernel->base + sym.address;
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000),
|
||||
utils::alignUp(sym.size + sym.address, 0x1000), PROT_WRITE);
|
||||
std::printf("patching sceKernelGetMainSocId\n");
|
||||
struct GetMainSocId : Xbyak::CodeGenerator {
|
||||
GetMainSocId(std::uint64_t address, std::uint64_t size)
|
||||
: Xbyak::CodeGenerator(size, (void *)address) {
|
||||
mov(eax, 0x710f00);
|
||||
ret();
|
||||
}
|
||||
} gen{address, sym.size};
|
||||
|
||||
::mprotect((void *)utils::alignDown(address, 0x1000),
|
||||
utils::alignUp(sym.size + sym.address, 0x1000),
|
||||
PROT_READ | PROT_EXEC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (orbis::g_context.fwSdkVersion == 0) {
|
||||
auto moduleParam = reinterpret_cast<std::byte *>(libkernel->moduleParam);
|
||||
auto fwSdkVersion = moduleParam //
|
||||
+ sizeof(uint64_t) // size
|
||||
+ sizeof(uint64_t); // magic
|
||||
orbis::g_context.fwSdkVersion = *(uint32_t *)fwSdkVersion;
|
||||
std::printf("fw sdk version: %x\n", orbis::g_context.fwSdkVersion);
|
||||
}
|
||||
|
||||
libkernel->id = mainThread->tproc->modulesMap.insert(libkernel);
|
||||
interpBase = reinterpret_cast<std::uint64_t>(libkernel->base);
|
||||
entryPoint = libkernel->entryPoint;
|
||||
|
||||
return {.entryPoint = entryPoint, .interpBase = interpBase};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue