mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
[rpcsx-os] linker: implement fake unself
This commit is contained in:
parent
1b15ef4d13
commit
9fcee39dd3
|
|
@ -7,8 +7,10 @@
|
||||||
#include "orbis/uio.hpp"
|
#include "orbis/uio.hpp"
|
||||||
#include "vfs.hpp"
|
#include "vfs.hpp"
|
||||||
#include "vm.hpp"
|
#include "vm.hpp"
|
||||||
|
#include <bit>
|
||||||
#include <crypto/sha1.h>
|
#include <crypto/sha1.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
#include <fstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <orbis/thread/Process.hpp>
|
#include <orbis/thread/Process.hpp>
|
||||||
|
|
@ -17,6 +19,76 @@
|
||||||
|
|
||||||
using orbis::utils::Ref;
|
using orbis::utils::Ref;
|
||||||
|
|
||||||
|
static std::vector<std::byte> unself(const std::byte *image, std::size_t size) {
|
||||||
|
struct [[gnu::packed]] Header {
|
||||||
|
std::uint32_t magic;
|
||||||
|
std::uint32_t unk;
|
||||||
|
std::uint8_t category;
|
||||||
|
std::uint8_t programType;
|
||||||
|
std::uint16_t padding;
|
||||||
|
std::uint16_t headerSize;
|
||||||
|
std::uint16_t signSize;
|
||||||
|
std::uint32_t fileSize;
|
||||||
|
std::uint32_t padding2;
|
||||||
|
std::uint16_t segmentCount;
|
||||||
|
std::uint16_t unk1;
|
||||||
|
std::uint32_t padding3;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(0x18 == 24);
|
||||||
|
|
||||||
|
static_assert(sizeof(Header) == 0x20);
|
||||||
|
struct [[gnu::packed]] Segment {
|
||||||
|
std::uint64_t flags;
|
||||||
|
std::uint64_t offset;
|
||||||
|
std::uint64_t encryptedSize;
|
||||||
|
std::uint64_t decryptedSize;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Segment) == 0x20);
|
||||||
|
|
||||||
|
auto header = std::bit_cast<Header *>(image);
|
||||||
|
auto segments = std::bit_cast<Segment *>(image + sizeof(Header));
|
||||||
|
|
||||||
|
auto elfOffset = sizeof(Header) + sizeof(Segment) * header->segmentCount;
|
||||||
|
std::vector<std::byte> result;
|
||||||
|
result.reserve(header->fileSize);
|
||||||
|
result.resize(sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
auto ehdr = std::bit_cast<Elf64_Ehdr *>(image + elfOffset);
|
||||||
|
auto phdrs = std::bit_cast<Elf64_Phdr *>(image + elfOffset + ehdr->e_phoff);
|
||||||
|
std::memcpy(result.data(), ehdr, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
auto phdrEndOffset = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum;
|
||||||
|
if (result.size() < phdrEndOffset) {
|
||||||
|
result.resize(phdrEndOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < ehdr->e_phnum; ++i) {
|
||||||
|
std::memcpy(result.data() + ehdr->e_phoff + ehdr->e_phentsize * i,
|
||||||
|
image + elfOffset + ehdr->e_phoff + ehdr->e_phentsize * i,
|
||||||
|
sizeof(Elf64_Phdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < header->segmentCount; ++i) {
|
||||||
|
auto &segment = segments[i];
|
||||||
|
if (~segment.flags & 0x800) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &phdr = phdrs[segment.flags >> 20];
|
||||||
|
|
||||||
|
auto endOffset = phdr.p_offset + segment.decryptedSize;
|
||||||
|
if (result.size() < endOffset) {
|
||||||
|
result.resize(endOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(result.data() + phdr.p_offset, image + segment.offset,
|
||||||
|
segment.decryptedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::uint64_t rx::linker::encodeFid(std::string_view fid) {
|
std::uint64_t rx::linker::encodeFid(std::string_view fid) {
|
||||||
static const char suffix[] =
|
static const char suffix[] =
|
||||||
"\x51\x8D\x64\xA6\x35\xDE\xD8\xC1\xE6\xB0\x39\xB1\xC3\xE5\x52\x30";
|
"\x51\x8D\x64\xA6\x35\xDE\xD8\xC1\xE6\xB0\x39\xB1\xC3\xE5\x52\x30";
|
||||||
|
|
@ -882,6 +954,11 @@ Ref<orbis::Module> rx::linker::loadModuleFile(std::string_view path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (image[0] != std::byte{'\x7f'} || image[1] != std::byte{'E'} ||
|
||||||
|
image[2] != std::byte{'L'} || image[3] != std::byte{'F'}) {
|
||||||
|
image = unself(image.data(), image.size());
|
||||||
|
}
|
||||||
|
|
||||||
return loadModule(image, thread->tproc);
|
return loadModule(image, thread->tproc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue