Skip to content

Commit

Permalink
Move .patch to start of executable (Pre-Patching)
Browse files Browse the repository at this point in the history
  • Loading branch information
PixelyIon committed Nov 22, 2020
1 parent 369bd46 commit 6f2cd41
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 131 deletions.
19 changes: 15 additions & 4 deletions app/src/main/cpp/skyline/kernel/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
namespace skyline::kernel {
MemoryManager::MemoryManager(const DeviceState &state) : state(state) {}

constexpr size_t RegionAlignment{1ULL << 21}; //!< The minimum alignment of a HOS memory region

void MemoryManager::InitializeVmm(memory::AddressSpaceType type) {
switch (type) {
case memory::AddressSpaceType::AddressSpace32Bit:
Expand All @@ -22,7 +24,7 @@ namespace skyline::kernel {
case memory::AddressSpaceType::AddressSpace39Bit: {
addressSpace.address = 0;
addressSpace.size = 1UL << 39;
base.size = 0x78000000 + 0x1000000000 + 0x180000000 + 0x80000000 + 0x1000000000;
base.size = 0x78000000 + 0x1000000000 + 0x180000000 + 0x80000000 + 0x1000000000; // Code region size is an assumed maximum here
break;
}

Expand All @@ -41,15 +43,15 @@ namespace skyline::kernel {
}

start = util::HexStringToInt<u64>(std::string_view(maps.data() + maps.find_first_of('-', line) + 1, sizeof(u64) * 2));
alignedStart = util::AlignUp(start, 1ULL << 21);
alignedStart = util::AlignUp(start, RegionAlignment);
if (alignedStart + base.size > addressSpace.size)
break;
} while ((line = maps.find_first_of('\n', line)) != std::string::npos && line++);

if (!base.address)
throw exception("Cannot find a suitable carveout for the guest address space");

mmap(reinterpret_cast<void*>(base.address), base.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
mmap(reinterpret_cast<void *>(base.address), base.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

chunks = {ChunkDescriptor{
.ptr = reinterpret_cast<u8 *>(addressSpace.address),
Expand All @@ -60,6 +62,9 @@ namespace skyline::kernel {

void MemoryManager::InitializeRegions(u8 *codeStart, u64 size) {
u64 address{reinterpret_cast<u64>(codeStart)};
if (!util::IsAligned(address, RegionAlignment))
throw exception("Non-aligned code region was used to initialize regions: 0x{:X} - 0x{:X}", codeStart, codeStart + size);

switch (addressSpace.size) {
case 1UL << 36: {
code.address = base.address;
Expand All @@ -79,7 +84,7 @@ namespace skyline::kernel {

case 1UL << 39: {
code.address = base.address;
code.size = 0x78000000;
code.size = util::AlignUp(size, RegionAlignment);
alias.address = code.address + code.size;
alias.size = 0x1000000000;
heap.address = alias.address + alias.size;
Expand All @@ -95,6 +100,12 @@ namespace skyline::kernel {
throw exception("Regions initialized without VMM initialization");
}

auto newSize{code.size + alias.size + stack.size + heap.size + tlsIo.size};
if (newSize > base.size)
throw exception("Region size has exceeded pre-allocated area: 0x{:X}/0x{:X}", newSize, base.size);
if (newSize != base.size)
munmap(reinterpret_cast<u8 *>(base.address) + base.size, newSize - base.size);

if (size > code.size)
throw exception("Code region ({}) is smaller than mapped code size ({})", code.size, size);

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/skyline/kernel/svc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,11 +678,11 @@ namespace skyline::kernel::svc {
break;

case constant::infoState::AddressSpaceBaseAddr:
out = state.process->memory.addressSpace.address;
out = state.process->memory.base.address;
break;

case constant::infoState::AddressSpaceSize:
out = state.process->memory.addressSpace.size;
out = state.process->memory.base.size;
break;

case constant::infoState::StackRegionBaseAddr:
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace skyline::kernel::type {
if (ptr && !util::PageAligned(ptr))
throw exception("KSharedMemory was mapped to a non-page-aligned address: 0x{:X}", ptr);

guest.ptr = reinterpret_cast<u8 *>(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | (ptr ? MAP_FIXED_NOREPLACE : 0), fd, 0));
guest.ptr = reinterpret_cast<u8 *>(mmap(ptr, size, permission.Get(), MAP_SHARED | (ptr ? MAP_FIXED : 0), fd, 0));
if (guest.ptr == MAP_FAILED)
throw exception("An error occurred while mapping shared memory in guest");
guest.size = size;
Expand Down
33 changes: 14 additions & 19 deletions app/src/main/cpp/skyline/loader/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,25 @@ namespace skyline::loader {
if (!util::PageAligned(executable.text.offset) || !util::PageAligned(executable.ro.offset) || !util::PageAligned(executable.data.offset))
throw exception("LoadProcessData: Section offsets are not aligned with page size: 0x{:X}, 0x{:X}, 0x{:X}", executable.text.offset, executable.ro.offset, executable.data.offset);

// The data section will always be the last section in memory, so put the patch section after it
u64 patchOffset{executable.data.offset + dataSize};
std::vector<u32> patch = state.nce->PatchCode(executable.text.contents, reinterpret_cast<u64>(base), patchOffset);
auto patch{state.nce->GetPatchData(executable.text.contents)};

u64 patchSize{patch.size() * sizeof(u32)};
u64 padding{util::AlignUp(patchSize, PAGE_SIZE) - patchSize};
process->NewHandle<kernel::type::KPrivateMemory>(base, patch.size, memory::Permission{false, false, false}, memory::states::Reserved); // ---
state.logger->Debug("Successfully mapped section .patch @ 0x{:X}, Size = 0x{:X}", base, patch.size);

process->NewHandle<kernel::type::KPrivateMemory>(base + executable.text.offset, textSize, memory::Permission{true, false, true}, memory::states::CodeStatic); // R-X
state.logger->Debug("Successfully mapped section .text @ {}, Size = 0x{:X}", base + executable.text.offset, textSize);
process->NewHandle<kernel::type::KPrivateMemory>(base + patch.size + executable.text.offset, textSize, memory::Permission{true, false, true}, memory::states::CodeStatic); // R-X
state.logger->Debug("Successfully mapped section .text @ 0x{:X}, Size = 0x{:X}", base + patch.size + executable.text.offset, textSize);

process->NewHandle<kernel::type::KPrivateMemory>(base + executable.ro.offset, roSize, memory::Permission{true, false, false}, memory::states::CodeReadOnly); // R--
state.logger->Debug("Successfully mapped section .rodata @ {}, Size = 0x{:X}", base + executable.ro.offset, roSize);
process->NewHandle<kernel::type::KPrivateMemory>(base + patch.size + executable.ro.offset, roSize, memory::Permission{true, false, false}, memory::states::CodeReadOnly); // R--
state.logger->Debug("Successfully mapped section .rodata @ 0x{:X}, Size = 0x{:X}", base + patch.size + executable.ro.offset, roSize);

process->NewHandle<kernel::type::KPrivateMemory>(base + executable.data.offset, dataSize, memory::Permission{true, true, false}, memory::states::CodeMutable); // RW-
state.logger->Debug("Successfully mapped section .data @ {}, Size = 0x{:X}", base + executable.data.offset, dataSize);
process->NewHandle<kernel::type::KPrivateMemory>(base + patch.size + executable.data.offset, dataSize, memory::Permission{true, true, false}, memory::states::CodeMutable); // RW-
state.logger->Debug("Successfully mapped section .data + .bss @ 0x{:X}, Size = 0x{:X}", base + patch.size + executable.data.offset, dataSize);

process->NewHandle<kernel::type::KPrivateMemory>(base + patchOffset, patchSize + padding, memory::Permission{true, true, true}, memory::states::CodeMutable); // RWX
state.logger->Debug("Successfully mapped section .patch @ {}, Size = 0x{:X}", base + patchOffset, patchSize + padding);
state.nce->PatchCode(executable.text.contents, reinterpret_cast<u32*>(base), patch.size, patch.offsets);
std::memcpy(base + patch.size + executable.text.offset, executable.text.contents.data(), textSize);
std::memcpy(base + patch.size + executable.ro.offset, executable.ro.contents.data(), roSize);
std::memcpy(base + patch.size + executable.data.offset, executable.data.contents.data(), dataSize - executable.bssSize);

std::memcpy(base + executable.text.offset, executable.text.contents.data(), textSize);
std::memcpy(base + executable.ro.offset, executable.ro.contents.data(), roSize);
std::memcpy(base + executable.data.offset, executable.data.contents.data(), dataSize - executable.bssSize);
std::memcpy(base + patchOffset, patch.data(), patchSize);

return {base, patchOffset + patchSize + padding, base};
return {base, patch.size + textSize + roSize + dataSize, base + patch.size};
}
}
Loading

0 comments on commit 6f2cd41

Please sign in to comment.