diff --git a/rpcsx/iodev/dce.cpp b/rpcsx/iodev/dce.cpp index 80ccf04ce..74e4a3734 100644 --- a/rpcsx/iodev/dce.cpp +++ b/rpcsx/iodev/dce.cpp @@ -426,6 +426,18 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request, return {}; } + if (request == 0x80308217) { + ORBIS_LOG_ERROR(__FUNCTION__, request); + thread->where(); + return{}; + } + + if (request == 0x80208218) { + ORBIS_LOG_ERROR(__FUNCTION__, request); + thread->where(); + return{}; + } + if (request == 0x80088209) { // deallocate? auto arg = *reinterpret_cast(argp); ORBIS_LOG_ERROR("dce: 0x80088209", arg); diff --git a/rpcsx/linker.cpp b/rpcsx/linker.cpp index 7d71b24d6..39576519a 100644 --- a/rpcsx/linker.cpp +++ b/rpcsx/linker.cpp @@ -152,7 +152,7 @@ enum OrbisElfDynamicType { kElfDynamicTypeSymbolic = 16, kElfDynamicTypeRel = 17, kElfDynamicTypeRelSize = 18, - kElfDynamicTypeRelEent = 19, + kElfDynamicTypeRelEnt = 19, kElfDynamicTypePltRel = 20, kElfDynamicTypeDebug = 21, kElfDynamicTypeTextRel = 22, @@ -191,6 +191,7 @@ enum OrbisElfDynamicType { kElfDynamicTypeSceOriginalFilename1 = 0x61000041, kElfDynamicTypeSceModuleInfo1 = 0x61000043, kElfDynamicTypeSceNeededModule1 = 0x61000045, + kElfDynamicTypeSceExportLib1 = 0x61000047, kElfDynamicTypeSceImportLib1 = 0x61000049, kElfDynamicTypeSceSymTabSize = 0x6100003f, kElfDynamicTypeRelaCount = 0x6ffffff9 @@ -236,8 +237,8 @@ inline const char *toString(OrbisElfDynamicType dynType) { return "Rel"; case kElfDynamicTypeRelSize: return "RelSize"; - case kElfDynamicTypeRelEent: - return "RelEent"; + case kElfDynamicTypeRelEnt: + return "RelEnt"; case kElfDynamicTypePltRel: return "PltRel"; case kElfDynamicTypeDebug: @@ -320,6 +321,8 @@ inline const char *toString(OrbisElfDynamicType dynType) { return "SceSymTabSize"; case kElfDynamicTypeRelaCount: return "RelaCount"; + case kElfDynamicTypeSceExportLib1: + return "SceExportLib1"; } return ""; @@ -457,9 +460,9 @@ Ref rx::linker::loadModule(std::span image, auto imageBase = reinterpret_cast( vm::map(reinterpret_cast(baseAddress), - rx::alignUp(imageSize, vm::kPageSize), 0, - vm::kMapFlagPrivate | vm::kMapFlagAnonymous | - (baseAddress ? vm::kMapFlagFixed : 0))); + rx::alignUp(imageSize, vm::kPageSize), 0, + vm::kMapFlagPrivate | vm::kMapFlagAnonymous | + (baseAddress ? vm::kMapFlagFixed : 0))); if (imageBase == MAP_FAILED) { std::abort(); @@ -566,6 +569,11 @@ Ref rx::linker::loadModule(std::span image, result->ehFrameSize = dataBufferIt - dataBuffer; } + orbis::Relocation *pltRelocations = nullptr; + std::size_t pltRelocationCount = 0; + orbis::Relocation *nonPltRelocations = nullptr; + std::size_t nonPltRelocationCount = 0; + if (dynamicPhdrIndex >= 0 && phdrs[dynamicPhdrIndex].p_filesz > 0) { auto &dynPhdr = phdrs[dynamicPhdrIndex]; std::vector dyns(dynPhdr.p_filesz / sizeof(Elf64_Dyn)); @@ -655,15 +663,11 @@ Ref rx::linker::loadModule(std::span image, std::unordered_map idToModuleIndex; std::unordered_map idToLibraryIndex; - orbis::Relocation *pltRelocations = nullptr; - std::size_t pltRelocationCount = 0; - orbis::Relocation *nonPltRelocations = nullptr; - std::size_t nonPltRelocationCount = 0; - for (auto dyn : dyns) { - if (dyn.d_tag == kElfDynamicTypeSceModuleInfo) { + if (dyn.d_tag == kElfDynamicTypeSceModuleInfo || + dyn.d_tag == kElfDynamicTypeSceModuleInfo1) { std::strncpy(result->moduleName, - sceStrtab + static_cast(dyn.d_un.d_val), + strtab + static_cast(dyn.d_un.d_val), sizeof(result->moduleName)); } else if (dyn.d_tag == kElfDynamicTypeSceModuleAttr) { result->attributes = dyn.d_un.d_val; @@ -675,11 +679,13 @@ Ref rx::linker::loadModule(std::span image, sizeof(result->soName)); } - if (dyn.d_tag == kElfDynamicTypeSceModuleInfo) { + if (dyn.d_tag == kElfDynamicTypeSceModuleInfo || + dyn.d_tag == kElfDynamicTypeSceModuleInfo1) { idToModuleIndex[dyn.d_un.d_val >> 48] = -1; } - if (dyn.d_tag == kElfDynamicTypeSceNeededModule) { + if (dyn.d_tag == kElfDynamicTypeSceNeededModule || + dyn.d_tag == kElfDynamicTypeSceNeededModule1) { auto [it, inserted] = idToModuleIndex.try_emplace( dyn.d_un.d_val >> 48, result->neededModules.size()); @@ -692,7 +698,9 @@ Ref rx::linker::loadModule(std::span image, mod.attr = static_cast(dyn.d_un.d_val >> 32); mod.isExport = false; } else if (dyn.d_tag == kElfDynamicTypeSceImportLib || - dyn.d_tag == kElfDynamicTypeSceExportLib) { + dyn.d_tag == kElfDynamicTypeSceImportLib1 || + dyn.d_tag == kElfDynamicTypeSceExportLib || + dyn.d_tag == kElfDynamicTypeSceExportLib1) { auto [it, inserted] = idToLibraryIndex.try_emplace( dyn.d_un.d_val >> 48, result->neededLibraries.size()); @@ -703,7 +711,8 @@ Ref rx::linker::loadModule(std::span image, auto &lib = result->neededLibraries[it->second]; lib.name = strtab + static_cast(dyn.d_un.d_val); - lib.isExport = dyn.d_tag == kElfDynamicTypeSceExportLib; + lib.isExport = dyn.d_tag == kElfDynamicTypeSceExportLib || + dyn.d_tag == kElfDynamicTypeSceExportLib1; } else if (dyn.d_tag == kElfDynamicTypeSceExportLibAttr || dyn.d_tag == kElfDynamicTypeSceImportLibAttr) { auto [it, inserted] = idToLibraryIndex.try_emplace( @@ -719,6 +728,7 @@ Ref rx::linker::loadModule(std::span image, } switch (dyn.d_tag) { + case kElfDynamicTypePltGot: case kElfDynamicTypeScePltGot: result->pltGot = dyn.d_un.d_ptr ? reinterpret_cast( @@ -726,6 +736,11 @@ Ref rx::linker::loadModule(std::span image, : nullptr; break; + case kElfDynamicTypeJmpRel: + pltRelocations = reinterpret_cast( + imageBase - baseAddress + dyn.d_un.d_ptr); + break; + case kElfDynamicTypeSceJmpRel: if (sceDynlibData != nullptr) { pltRelocations = reinterpret_cast( @@ -737,9 +752,16 @@ Ref rx::linker::loadModule(std::span image, break; case kElfDynamicTypeScePltRel: break; + case kElfDynamicTypePltRelSize: case kElfDynamicTypeScePltRelSize: pltRelocationCount = dyn.d_un.d_val / sizeof(orbis::Relocation); break; + + case kElfDynamicTypeRela: + nonPltRelocations = reinterpret_cast( + imageBase - baseAddress + dyn.d_un.d_ptr); + break; + case kElfDynamicTypeSceRela: if (sceDynlibData != nullptr) { nonPltRelocations = reinterpret_cast( @@ -749,6 +771,7 @@ Ref rx::linker::loadModule(std::span image, image.data() + dyn.d_un.d_ptr); } break; + case kElfDynamicTypeRelaSize: case kElfDynamicTypeSceRelaSize: nonPltRelocationCount = dyn.d_un.d_val / sizeof(orbis::Relocation); break; @@ -831,25 +854,12 @@ Ref rx::linker::loadModule(std::span image, result->symbols.push_back(symbol); } } - - if (pltRelocations != nullptr && pltRelocationCount > 0) { - result->pltRelocations.reserve(pltRelocationCount); - for (auto rel : std::span(pltRelocations, pltRelocationCount)) { - result->pltRelocations.push_back(rel); - } - } - - if (nonPltRelocations != nullptr && nonPltRelocationCount > 0) { - result->nonPltRelocations.reserve(nonPltRelocationCount); - for (auto rel : std::span(nonPltRelocations, nonPltRelocationCount)) { - result->nonPltRelocations.push_back(rel); - } - } } for (auto phdr : phdrs) { if (phdr.p_type == kElfProgramTypeLoad || - phdr.p_type == kElfProgramTypeSceRelRo) { + phdr.p_type == kElfProgramTypeSceRelRo || + phdr.p_type == kElfProgramTypeGnuRelRo) { auto segmentEnd = rx::alignUp(phdr.p_vaddr + phdr.p_memsz, vm::kPageSize); auto segmentBegin = rx::alignDown(phdr.p_vaddr - baseAddress, phdr.p_align); @@ -858,7 +868,8 @@ Ref rx::linker::loadModule(std::span image, std::memcpy(imageBase + phdr.p_vaddr - baseAddress, image.data() + phdr.p_offset, phdr.p_filesz); - if (phdr.p_type == kElfProgramTypeSceRelRo) { + if (phdr.p_type == kElfProgramTypeSceRelRo || + phdr.p_type == kElfProgramTypeGnuRelRo) { phdr.p_flags |= vm::kMapProtCpuWrite; // TODO: reprotect on relocations } @@ -874,6 +885,10 @@ Ref rx::linker::loadModule(std::span image, mapFlags |= vm::kMapProtCpuRead; } + if (mapFlags == 0) { + mapFlags = vm::kMapProtCpuWrite; + } + vm::protect(imageBase + segmentBegin, segmentSize, mapFlags); if (phdr.p_type == kElfProgramTypeLoad) { @@ -889,6 +904,20 @@ Ref rx::linker::loadModule(std::span image, } } + if (pltRelocations != nullptr && pltRelocationCount > 0) { + result->pltRelocations.reserve(pltRelocationCount); + for (auto rel : std::span(pltRelocations, pltRelocationCount)) { + result->pltRelocations.push_back(rel); + } + } + + if (nonPltRelocations != nullptr && nonPltRelocationCount > 0) { + result->nonPltRelocations.reserve(nonPltRelocationCount); + for (auto rel : std::span(nonPltRelocations, nonPltRelocationCount)) { + result->nonPltRelocations.push_back(rel); + } + } + result->base = imageBase - baseAddress; result->size = imageSize + baseAddress; result->phdrAddress = phdrPhdrIndex >= 0 ? phdrs[phdrPhdrIndex].p_vaddr @@ -899,12 +928,12 @@ Ref rx::linker::loadModule(std::span image, std::printf("Loaded module '%s' (%lx) from object '%s', address: %p - %p\n", result->moduleName, (unsigned long)result->attributes, result->soName, imageBase, (char *)imageBase + result->size); - for (auto mod : result->neededModules) { + for (const auto &mod : result->neededModules) { std::printf(" needed module '%s' (%lx)\n", mod.name.c_str(), (unsigned long)mod.attr); } - for (auto lib : result->neededLibraries) { + for (const auto &lib : result->neededLibraries) { std::printf(" needed library '%s' (%lx), kind %s\n", lib.name.c_str(), (unsigned long)lib.attr, lib.isExport ? "export" : "import"); } diff --git a/rpcsx/main.cpp b/rpcsx/main.cpp index 79767c8ca..95a4346f4 100644 --- a/rpcsx/main.cpp +++ b/rpcsx/main.cpp @@ -604,11 +604,13 @@ ExecEnv ps4CreateExecEnv(orbis::Thread *mainThread, mainThread->tproc->sdkVersion = orbis::g_context.sdkVersion; } - if (executableModule->interp.empty()) { + if (executableModule->type == rx::linker::kElfTypeExec || + executableModule->type == rx::linker::kElfTypeSceExec) { return {.entryPoint = entryPoint, .interpBase = interpBase}; } - if (vfs::exists(executableModule->interp, mainThread)) { + if (!executableModule->interp.empty() && + vfs::exists(executableModule->interp, mainThread)) { auto loader = rx::linker::loadModuleFile(executableModule->interp, mainThread); loader->id = mainThread->tproc->modulesMap.insert(loader);