From ed0c722ff0e18e97952da2850c2e691afa697768 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 Aug 2024 15:54:56 +0200 Subject: [PATCH] Speedup relocation handling --- src/windows_emulator/module_mapper.cpp | 56 ++++++++++---------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/src/windows_emulator/module_mapper.cpp b/src/windows_emulator/module_mapper.cpp index 053fde73..d5642f30 100644 --- a/src/windows_emulator/module_mapper.cpp +++ b/src/windows_emulator/module_mapper.cpp @@ -49,33 +49,34 @@ namespace return; } + std::vector memory{}; + memory.resize(binary.size_of_image); + emu.read_memory(binary.image_base, memory.data(), memory.size()); - emulator_object relocation_object{emu, binary.image_base + directory->VirtualAddress}; - const auto end_address = relocation_object.value() + directory->Size; + const auto start = memory.data() + directory->VirtualAddress; + const auto end = start + directory->Size; - std::vector relocations{}; + const auto* relocation = reinterpret_cast(start); - while (relocation_object.value() < end_address) + while (reinterpret_cast(relocation) < end) { - const auto relocation = relocation_object.read(); - if (relocation.VirtualAddress <= 0 || relocation.SizeOfBlock <= 0) + if (relocation->VirtualAddress <= 0 || relocation->SizeOfBlock <= 0) { break; } - const auto dest = binary.image_base + relocation.VirtualAddress; + const auto dest = memory.data() + relocation->VirtualAddress; - const auto data_size = relocation.SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION); + const auto data_size = relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION); const auto entry_count = data_size / sizeof(uint16_t); - if (relocations.size() < entry_count) - { - relocations.resize(entry_count); - } + printf("Applying relocations %lX - %lX - %lld\n", relocation->VirtualAddress, relocation->SizeOfBlock, + entry_count); - emu.read_memory(relocation_object.value() + relocation_object.size(), relocations.data(), data_size); + const auto entry_start = offset_pointer(relocation, sizeof(IMAGE_BASE_RELOCATION)); + const auto entries = std::span(entry_start, entry_count); - for (const auto entry : std::span(relocations.data(), entry_count)) + for (const auto entry : entries) { const int type = entry >> 12; const int offset = entry & 0xfff; @@ -86,35 +87,22 @@ namespace break; case IMAGE_REL_BASED_HIGHLOW: - { - emulator_object relocatable_object{emu, dest + offset}; - relocatable_object.access([&](DWORD& obj) - { - obj += static_cast(delta); - }); - break; - } + *reinterpret_cast(dest + offset) += static_cast(delta); + break; case IMAGE_REL_BASED_DIR64: - { - emulator_object relocatable_object{emu, dest + offset}; - relocatable_object.access([&](ULONGLONG& obj) - { - obj += delta; - }); - - break; - } + *reinterpret_cast(dest + offset) += delta; + break; default: throw std::runtime_error("Unknown relocation type: " + std::to_string(type)); } } - relocation_object = emulator_object{ - emu, relocation_object.value() + relocation.SizeOfBlock - }; + relocation = offset_pointer(relocation, relocation->SizeOfBlock); } + + emu.write_memory(binary.image_base, memory.data(), memory.size()); } void map_sections(x64_emulator& emu, const mapped_binary& binary, const unsigned char* ptr,