diff --git a/rpcsx-os/linker.cpp b/rpcsx-os/linker.cpp index 8f75133ef..97e867d48 100644 --- a/rpcsx-os/linker.cpp +++ b/rpcsx-os/linker.cpp @@ -376,7 +376,7 @@ Ref rx::linker::loadModule(std::span image, auto imageBase = reinterpret_cast( rx::vm::map(reinterpret_cast(baseAddress), utils::alignUp(imageSize, rx::vm::kPageSize), - rx::vm::kMapProtCpuRead | rx::vm::kMapProtCpuWrite, + 0, rx::vm::kMapFlagPrivate | rx::vm::kMapFlagAnonymous)); if (imageBase == MAP_FAILED) { @@ -484,27 +484,6 @@ Ref rx::linker::loadModule(std::span image, result->ehFrameSize = dataBufferIt - dataBuffer; } - for (auto &phdr : phdrs) { - if (phdr.p_type == kElfProgramTypeLoad || - phdr.p_type == kElfProgramTypeSceRelRo) { - std::memcpy(imageBase + phdr.p_vaddr, image.data() + phdr.p_offset, - phdr.p_filesz); - std::memset(imageBase + phdr.p_vaddr + phdr.p_filesz, 0, - phdr.p_memsz - phdr.p_filesz); - - if (phdr.p_type == kElfProgramTypeLoad) { - if (result->segmentCount >= std::size(result->segments)) { - std::abort(); - } - - auto &segment = result->segments[result->segmentCount++]; - segment.addr = imageBase + phdr.p_vaddr; - segment.size = phdr.p_memsz; - segment.prot = phdr.p_flags; - } - } - } - if (dynamicPhdrIndex >= 0 && phdrs[dynamicPhdrIndex].p_filesz > 0) { auto &dynPhdr = phdrs[dynamicPhdrIndex]; std::vector dyns(dynPhdr.p_filesz / sizeof(Elf64_Dyn)); @@ -701,18 +680,24 @@ Ref rx::linker::loadModule(std::span image, library = moduleLibary.substr(0, hashPos); module = moduleLibary.substr(hashPos + 1); - auto libaryNid = decodeNid(library); - auto moduleNid = decodeNid(module); + auto libaryNid = *decodeNid(library); + auto moduleNid = *decodeNid(module); symbol.libraryIndex = idToLibraryIndex.at(libaryNid); symbol.moduleIndex = idToModuleIndex.at(moduleNid); - symbol.id = decodeNid(name); + symbol.id = *decodeNid(name); + } else if (auto nid = decodeNid(fullName)) { + symbol.id = *nid; + symbol.libraryIndex = -1; + symbol.moduleIndex = -1; } else { - // std::printf("ignored: (%s) - %lx\n", - // sceStrtab ? sceStrtab + - // static_cast(sym.st_name) - // : "", - // sym.st_value); + std::printf("ignored: (%s) - %lx\n", + sceStrtab ? sceStrtab + + static_cast(sym.st_name) + : "", + sym.st_value); + + continue; } } @@ -735,6 +720,35 @@ Ref rx::linker::loadModule(std::span 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, segmentSize, PROT_WRITE); + std::memcpy(imageBase + phdr.p_vaddr, image.data() + phdr.p_offset, + phdr.p_filesz); + std::memset(imageBase + phdr.p_vaddr + phdr.p_filesz, 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, segmentSize, phdr.p_flags); + + if (phdr.p_type == kElfProgramTypeLoad) { + if (result->segmentCount >= std::size(result->segments)) { + std::abort(); + } + + auto &segment = result->segments[result->segmentCount++]; + segment.addr = imageBase + phdr.p_vaddr; + segment.size = phdr.p_memsz; + segment.prot = phdr.p_flags; + } + } + } + result->base = imageBase; result->size = imageSize; // std::printf("Needed modules: [");