mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 04:03:57 +00:00
support mapping 32bit files
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <system_error>
|
||||
#include <variant>
|
||||
|
||||
// NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
@@ -342,4 +346,63 @@ struct SECTION_IMAGE_INFORMATION
|
||||
ULONG CheckSum;
|
||||
};
|
||||
|
||||
namespace winpe
|
||||
{
|
||||
|
||||
enum class pe_arch
|
||||
{
|
||||
pe32,
|
||||
pe64
|
||||
};
|
||||
|
||||
inline std::variant<pe_arch, std::error_code> get_pe_arch(const std::filesystem::path& file)
|
||||
{
|
||||
std::ifstream f(file, std::ios::binary);
|
||||
if (!f)
|
||||
{
|
||||
return std::make_error_code(std::errc::no_such_file_or_directory);
|
||||
}
|
||||
|
||||
PEDosHeader_t dos{};
|
||||
f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
|
||||
if (!f || dos.e_magic != PEDosHeader_t::k_Magic)
|
||||
{
|
||||
return std::make_error_code(std::errc::executable_format_error);
|
||||
}
|
||||
|
||||
f.seekg(dos.e_lfanew, std::ios::beg);
|
||||
uint32_t nt_signature = 0;
|
||||
f.read(reinterpret_cast<char*>(&nt_signature), sizeof(nt_signature));
|
||||
if (!f || nt_signature != PENTHeaders_t<std::uint32_t>::k_Signature)
|
||||
{
|
||||
return std::make_error_code(std::errc::executable_format_error);
|
||||
}
|
||||
|
||||
PEFileHeader_t file_header{};
|
||||
f.read(reinterpret_cast<char*>(&file_header), sizeof(file_header));
|
||||
if (!f)
|
||||
{
|
||||
return std::make_error_code(std::errc::executable_format_error);
|
||||
}
|
||||
|
||||
uint16_t magic = 0;
|
||||
f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
|
||||
if (!f)
|
||||
{
|
||||
return std::make_error_code(std::errc::executable_format_error);
|
||||
}
|
||||
|
||||
if (magic == PEOptionalHeader_t<std::uint32_t>::k_Magic)
|
||||
{
|
||||
return pe_arch::pe32;
|
||||
}
|
||||
if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
|
||||
{
|
||||
return pe_arch::pe64;
|
||||
}
|
||||
|
||||
return std::make_error_code(std::errc::executable_format_error);
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../std_include.hpp"
|
||||
#include "module_manager.hpp"
|
||||
#include "module_mapping.hpp"
|
||||
#include "platform/win_pefile.hpp"
|
||||
#include "windows-emulator/logger.hpp"
|
||||
|
||||
#include <serialization_helper.hpp>
|
||||
@@ -119,7 +120,28 @@ mapped_module* module_manager::map_local_module(const std::filesystem::path& fil
|
||||
|
||||
try
|
||||
{
|
||||
auto mod = map_module_from_file(*this->memory_, std::move(local_file));
|
||||
mapped_module mod;
|
||||
auto petype_result = winpe::get_pe_arch(file);
|
||||
if (std::holds_alternative<winpe::pe_arch>(petype_result))
|
||||
{
|
||||
if (std::get<winpe::pe_arch>(petype_result) == winpe::pe_arch::pe32)
|
||||
{
|
||||
mod = map_module_from_file<std::uint32_t>(*this->memory_, std::move(local_file));
|
||||
}
|
||||
else if (std::get<winpe::pe_arch>(petype_result) == winpe::pe_arch::pe64)
|
||||
{
|
||||
mod = map_module_from_file<std::uint64_t>(*this->memory_, std::move(local_file));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Unknown PE architecture");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Unknown PE architecture");
|
||||
}
|
||||
|
||||
mod.is_static = is_static;
|
||||
|
||||
logger.log("Mapped %s at 0x%" PRIx64 "\n", mod.path.generic_string().c_str(), mod.image_base);
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
uint64_t get_first_section_offset(const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
|
||||
template <typename T>
|
||||
uint64_t get_first_section_offset(const PENTHeaders_t<T>& nt_headers, const uint64_t nt_headers_offset)
|
||||
{
|
||||
const auto* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
|
||||
const size_t optional_header_offset =
|
||||
@@ -29,8 +30,9 @@ namespace
|
||||
return mem;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void collect_exports(mapped_module& binary, const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
const PEOptionalHeader_t<std::uint64_t>& optional_header)
|
||||
const PEOptionalHeader_t<T>& optional_header)
|
||||
{
|
||||
const auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0)
|
||||
@@ -79,8 +81,9 @@ namespace
|
||||
obj.set(new_value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void apply_relocations(const mapped_module& binary, const utils::safe_buffer_accessor<std::byte> buffer,
|
||||
const PEOptionalHeader_t<std::uint64_t>& optional_header)
|
||||
const PEOptionalHeader_t<T>& optional_header)
|
||||
{
|
||||
const auto delta = binary.image_base - optional_header.ImageBase;
|
||||
if (delta == 0)
|
||||
@@ -141,9 +144,10 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void map_sections(memory_manager& memory, mapped_module& binary,
|
||||
const utils::safe_buffer_accessor<const std::byte> buffer,
|
||||
const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
|
||||
const utils::safe_buffer_accessor<const std::byte> buffer, const PENTHeaders_t<T>& nt_headers,
|
||||
const uint64_t nt_headers_offset)
|
||||
{
|
||||
const auto first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset);
|
||||
const auto sections = buffer.as<IMAGE_SECTION_HEADER>(static_cast<size_t>(first_section_offset));
|
||||
@@ -196,6 +200,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
mapped_module map_module_from_data(memory_manager& memory, const std::span<const std::byte> data,
|
||||
std::filesystem::path file)
|
||||
{
|
||||
@@ -208,10 +213,10 @@ mapped_module map_module_from_data(memory_manager& memory, const std::span<const
|
||||
const auto dos_header = buffer.as<PEDosHeader_t>(0).get();
|
||||
const auto nt_headers_offset = dos_header.e_lfanew;
|
||||
|
||||
const auto nt_headers = buffer.as<PENTHeaders_t<std::uint64_t>>(nt_headers_offset).get();
|
||||
const auto nt_headers = buffer.as<PENTHeaders_t<T>>(nt_headers_offset).get();
|
||||
const auto& optional_header = nt_headers.OptionalHeader;
|
||||
|
||||
if (nt_headers.FileHeader.Machine != PEMachineType::AMD64)
|
||||
if (nt_headers.FileHeader.Machine != PEMachineType::I386 && nt_headers.FileHeader.Machine != PEMachineType::AMD64)
|
||||
{
|
||||
throw std::runtime_error("Unsupported architecture!");
|
||||
}
|
||||
@@ -254,6 +259,7 @@ mapped_module map_module_from_data(memory_manager& memory, const std::span<const
|
||||
return binary;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path file)
|
||||
{
|
||||
const auto data = utils::io::read_file(file);
|
||||
@@ -262,10 +268,19 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path
|
||||
throw std::runtime_error("Bad file data: " + file.string());
|
||||
}
|
||||
|
||||
return map_module_from_data(memory, data, std::move(file));
|
||||
return map_module_from_data<T>(memory, data, std::move(file));
|
||||
}
|
||||
|
||||
bool unmap_module(memory_manager& memory, const mapped_module& mod)
|
||||
{
|
||||
return memory.release_memory(mod.image_base, static_cast<size_t>(mod.size_of_image));
|
||||
}
|
||||
|
||||
template mapped_module map_module_from_data<std::uint32_t>(memory_manager& memory,
|
||||
const std::span<const std::byte> data,
|
||||
std::filesystem::path file);
|
||||
template mapped_module map_module_from_data<std::uint64_t>(memory_manager& memory,
|
||||
const std::span<const std::byte> data,
|
||||
std::filesystem::path file);
|
||||
template mapped_module map_module_from_file<std::uint32_t>(memory_manager& memory, std::filesystem::path file);
|
||||
template mapped_module map_module_from_file<std::uint64_t>(memory_manager& memory, std::filesystem::path file);
|
||||
@@ -4,6 +4,6 @@
|
||||
#include "../memory_manager.hpp"
|
||||
|
||||
mapped_module map_module_from_data(memory_manager& memory, std::span<const uint8_t> data, std::filesystem::path file);
|
||||
template <typename T>
|
||||
mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path file);
|
||||
|
||||
bool unmap_module(memory_manager& memory, const mapped_module& mod);
|
||||
|
||||
Reference in New Issue
Block a user