[Misc] Moved pe_image to base from 3pp and cut unnecessary parts

This commit is contained in:
Gliniak 2025-05-29 21:06:00 +02:00 committed by Radosław Gliński
parent 31ce3e0c71
commit 50492a951e
4 changed files with 213 additions and 1066 deletions

193
src/xenia/base/pe_image.h Normal file
View file

@ -0,0 +1,193 @@
/* Xenia: minor tweaks to bring up to date with winnt.h */
#include <cstdint>
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* NT image format (to be used when the Win32 SDK version of WINNT.H cannot) */
#define XIMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
#define XIMAGE_OS2_SIGNATURE 0x454E /* NE */
#define XIMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
#define XIMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
typedef struct _XIMAGE_DOS_HEADER { /* DOS .EXE header */
uint16_t e_magic; /* Magic number */
uint16_t e_cblp; /* Bytes on last page of file */
uint16_t e_cp; /* Pages in file */
uint16_t e_crlc; /* Relocations */
uint16_t e_cparhdr; /* Size of header in paragraphs */
uint16_t e_minalloc; /* Minimum extra paragraphs needed */
uint16_t e_maxalloc; /* Maximum extra paragraphs needed */
uint16_t e_ss; /* Initial (relative) SS value */
uint16_t e_sp; /* Initial SP value */
uint16_t e_csum; /* Checksum */
uint16_t e_ip; /* Initial IP value */
uint16_t e_cs; /* Initial (relative) CS value */
uint16_t e_lfarlc; /* File address of relocation table */
uint16_t e_ovno; /* Overlay number */
uint16_t e_res[4]; /* Reserved words */
uint16_t e_oemid; /* OEM identifier (for e_oeminfo) */
uint16_t e_oeminfo; /* OEM information; e_oemid specific */
uint16_t e_res2[10]; /* Reserved words */
int32_t e_lfanew; /* File address of new exe header */
} XIMAGE_DOS_HEADER, *PXIMAGE_DOS_HEADER;
typedef struct _XIMAGE_OS2_HEADER { /* OS/2 .EXE header */
uint16_t ne_magic; /* Magic number */
int8_t ne_ver; /* Version number */
int8_t ne_rev; /* Revision number */
uint16_t ne_enttab; /* Offset of Entry Table */
uint16_t ne_cbenttab; /* Number of bytes in Entry Table */
int32_t ne_crc; /* Checksum of whole file */
uint16_t ne_flags; /* Flag word */
uint16_t ne_autodata; /* Automatic data segment number */
uint16_t ne_heap; /* Initial heap allocation */
uint16_t ne_stack; /* Initial stack allocation */
int32_t ne_csip; /* Initial CS:IP setting */
int32_t ne_sssp; /* Initial SS:SP setting */
uint16_t ne_cseg; /* Count of file segments */
uint16_t ne_cmod; /* Entries in Module Reference Table */
uint16_t ne_cbnrestab; /* Size of non-resident name table */
uint16_t ne_segtab; /* Offset of Segment Table */
uint16_t ne_rsrctab; /* Offset of Resource Table */
uint16_t ne_restab; /* Offset of resident name table */
uint16_t ne_modtab; /* Offset of Module Reference Table */
uint16_t ne_imptab; /* Offset of Imported Names Table */
int32_t ne_nrestab; /* Offset of Non-resident Names Table */
uint16_t ne_cmovent; /* Count of movable entries */
uint16_t ne_align; /* Segment alignment shift count */
uint16_t ne_cres; /* Count of resource segments */
uint8_t ne_exetyp; /* Target Operating system */
uint8_t ne_flagsothers; /* Other .EXE flags */
uint16_t ne_pretthunks; /* offset to return thunks */
uint16_t ne_psegrefbytes; /* offset to segment ref. bytes */
uint16_t ne_swaparea; /* Minimum code swap area size */
uint16_t ne_expver; /* Expected Windows version number */
} XIMAGE_OS2_HEADER, *PXIMAGE_OS2_HEADER;
typedef struct _XIMAGE_FILE_HEADER {
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
} XIMAGE_FILE_HEADER, *PXIMAGE_FILE_HEADER;
#define XIMAGE_FILE_32BIT_MACHINE 0x0100 /* 32 bit word machine. */
#define XIMAGE_FILE_MACHINE_POWERPCBE 0x01F2 // IBM PowerPC Big-Endian
typedef struct _XIMAGE_DATA_DIRECTORY {
uint32_t VirtualAddress;
uint32_t Size;
} XIMAGE_DATA_DIRECTORY, *PXIMAGE_DATA_DIRECTORY;
#define XIMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
/*
* Optional header format.
*/
typedef struct _XIMAGE_OPTIONAL_HEADER {
/*
* Standard fields.
*/
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint32_t BaseOfData;
/*
* NT additional fields.
*/
uint32_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Reserved1;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
XIMAGE_DATA_DIRECTORY DataDirectory[XIMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} XIMAGE_OPTIONAL_HEADER, *PXIMAGE_OPTIONAL_HEADER;
typedef XIMAGE_OPTIONAL_HEADER XIMAGE_OPTIONAL_HEADER32;
#define XIMAGE_SIZEOF_NT_OPTIONAL_HEADER 224
#define XIMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
typedef struct _XIMAGE_NT_HEADERS {
uint32_t Signature;
XIMAGE_FILE_HEADER FileHeader;
XIMAGE_OPTIONAL_HEADER OptionalHeader;
} XIMAGE_NT_HEADERS, *PXIMAGE_NT_HEADERS;
typedef XIMAGE_NT_HEADERS XIMAGE_NT_HEADERS32;
#define XIMAGE_FIRST_SECTION(ntheader) \
((PXIMAGE_SECTION_HEADER)((uint8_t*)ntheader + \
offsetof(XIMAGE_NT_HEADERS, OptionalHeader) + \
((PXIMAGE_NT_HEADERS)(ntheader)) \
->FileHeader.SizeOfOptionalHeader))
#define XIMAGE_SUBSYSTEM_XBOX 14
/*
* Section header format.
*/
#define XIMAGE_SIZEOF_SHORT_NAME 8
typedef struct _XIMAGE_SECTION_HEADER {
uint8_t Name[XIMAGE_SIZEOF_SHORT_NAME];
union {
uint32_t PhysicalAddress;
uint32_t VirtualSize;
} Misc;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t Characteristics;
} XIMAGE_SECTION_HEADER, *PXIMAGE_SECTION_HEADER;
#define XIMAGE_SIZEOF_SECTION_HEADER 40
typedef struct _XIMAGE_EXPORT_DIRECTORY {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
uint16_t MinorVersion;
uint32_t Name;
uint32_t Base;
uint32_t NumberOfFunctions;
uint32_t NumberOfNames;
uint32_t** AddressOfFunctions;
uint32_t** AddressOfNames;
uint16_t** AddressOfNameOrdinals;
} XIMAGE_EXPORT_DIRECTORY, *PXIMAGE_EXPORT_DIRECTORY;

View file

@ -18,6 +18,7 @@
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
#include "xenia/base/pe_image.h"
#include "xenia/cpu/cpu_flags.h"
#include "xenia/cpu/export_resolver.h"
@ -30,7 +31,6 @@
#include "third_party/crypto/TinySHA1.hpp"
#include "third_party/crypto/rijndael-alg-fst.c"
#include "third_party/crypto/rijndael-alg-fst.h"
#include "third_party/pe/pe_image.h"
#include "xenia/cpu/ppc/ppc_decode_data.h"
#include "xenia/cpu/ppc/ppc_instr.h"
DEFINE_bool(disable_instruction_infocache, false,
@ -818,8 +818,8 @@ int XexModule::ReadPEHeaders() {
const uint8_t* p = memory()->TranslateVirtual(base_address_);
// Verify DOS signature (MZ).
auto doshdr = reinterpret_cast<const IMAGE_DOS_HEADER*>(p);
if (doshdr->e_magic != IMAGE_DOS_SIGNATURE) {
auto doshdr = reinterpret_cast<const XIMAGE_DOS_HEADER*>(p);
if (doshdr->e_magic != XIMAGE_DOS_SIGNATURE) {
XELOGE("PE signature mismatch; likely bad decryption/decompression");
return 1;
}
@ -828,59 +828,35 @@ int XexModule::ReadPEHeaders() {
p += doshdr->e_lfanew;
// Verify NT signature (PE\0\0).
auto nthdr = reinterpret_cast<const IMAGE_NT_HEADERS32*>(p);
if (nthdr->Signature != IMAGE_NT_SIGNATURE) {
auto nthdr = reinterpret_cast<const XIMAGE_NT_HEADERS32*>(p);
if (nthdr->Signature != XIMAGE_NT_SIGNATURE) {
return 1;
}
// Verify matches an Xbox PE.
const IMAGE_FILE_HEADER* filehdr = &nthdr->FileHeader;
if ((filehdr->Machine != IMAGE_FILE_MACHINE_POWERPCBE) ||
!(filehdr->Characteristics & IMAGE_FILE_32BIT_MACHINE)) {
const XIMAGE_FILE_HEADER* filehdr = &nthdr->FileHeader;
if ((filehdr->Machine != XIMAGE_FILE_MACHINE_POWERPCBE) ||
!(filehdr->Characteristics & XIMAGE_FILE_32BIT_MACHINE)) {
return 1;
}
// Verify the expected size.
if (filehdr->SizeOfOptionalHeader != IMAGE_SIZEOF_NT_OPTIONAL_HEADER) {
if (filehdr->SizeOfOptionalHeader != XIMAGE_SIZEOF_NT_OPTIONAL_HEADER) {
return 1;
}
// Verify optional header is 32bit.
const IMAGE_OPTIONAL_HEADER32* opthdr = &nthdr->OptionalHeader;
if (opthdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
const XIMAGE_OPTIONAL_HEADER32* opthdr = &nthdr->OptionalHeader;
if (opthdr->Magic != XIMAGE_NT_OPTIONAL_HDR32_MAGIC) {
return 1;
}
// Verify subsystem.
if (opthdr->Subsystem != IMAGE_SUBSYSTEM_XBOX) {
if (opthdr->Subsystem != XIMAGE_SUBSYSTEM_XBOX) {
return 1;
}
// Linker version - likely 8+
// Could be useful for recognizing certain patterns
// opthdr->MajorLinkerVersion; opthdr->MinorLinkerVersion;
// Data directories of interest:
// EXPORT IMAGE_EXPORT_DIRECTORY
// IMPORT IMAGE_IMPORT_DESCRIPTOR[]
// EXCEPTION IMAGE_CE_RUNTIME_FUNCTION_ENTRY[]
// BASERELOC
// DEBUG IMAGE_DEBUG_DIRECTORY[]
// ARCHITECTURE /IMAGE_ARCHITECTURE_HEADER/ ----- import thunks!
// TLS IMAGE_TLS_DIRECTORY
// IAT Import Address Table ptr
// opthdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_X].VirtualAddress / .Size
// The macros in pe_image.h don't work with clang, for some reason.
// offsetof seems to be unable to find OptionalHeader.
#define offsetof1(type, member) ((std::size_t) & (((type*)0)->member))
#define IMAGE_FIRST_SECTION1(ntheader) \
((PIMAGE_SECTION_HEADER)((uint8_t*)ntheader + \
offsetof1(IMAGE_NT_HEADERS, OptionalHeader) + \
((PIMAGE_NT_HEADERS)(ntheader)) \
->FileHeader.SizeOfOptionalHeader))
// Quick scan to determine bounds of sections.
size_t upper_address = 0;
const IMAGE_SECTION_HEADER* sechdr = IMAGE_FIRST_SECTION1(nthdr);
const XIMAGE_SECTION_HEADER* sechdr = XIMAGE_FIRST_SECTION(nthdr);
for (size_t n = 0; n < filehdr->NumberOfSections; n++, sechdr++) {
const size_t physical_address = opthdr->ImageBase + sechdr->VirtualAddress;
upper_address =
@ -888,7 +864,7 @@ int XexModule::ReadPEHeaders() {
}
// Setup/load sections.
sechdr = IMAGE_FIRST_SECTION1(nthdr);
sechdr = XIMAGE_FIRST_SECTION(nthdr);
for (size_t n = 0; n < filehdr->NumberOfSections; n++, sechdr++) {
PESection section;
memcpy(section.name, sechdr->Name, sizeof(sechdr->Name));

View file

@ -12,10 +12,10 @@
#include <algorithm>
#include <string>
#include "third_party/pe/pe_image.h"
#include "xenia/base/atomic.h"
#include "xenia/base/chrono.h"
#include "xenia/base/logging.h"
#include "xenia/base/pe_image.h"
#include "xenia/base/string.h"
#include "xenia/base/threading.h"
#include "xenia/kernel/kernel_state.h"
@ -400,7 +400,7 @@ DECLARE_XBOXKRNL_EXPORT3(RtlUnicodeToMultiByteN, kNone, kImplemented,
kHighFrequency, kSketchy);
// https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlImageNtHeader.html
static IMAGE_NT_HEADERS32* ImageNtHeader(uint8_t* module) {
static XIMAGE_NT_HEADERS32* ImageNtHeader(uint8_t* module) {
if (!module) {
return 0;
}
@ -419,7 +419,7 @@ static IMAGE_NT_HEADERS32* ImageNtHeader(uint8_t* module) {
if (nt_magic != 0x4550) { // 'PE'
return 0;
}
return reinterpret_cast<IMAGE_NT_HEADERS32*>(nt_header);
return reinterpret_cast<XIMAGE_NT_HEADERS32*>(nt_header);
}
pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) {
@ -443,13 +443,13 @@ dword_result_t RtlImageDirectoryEntryToData_entry(dword_t Base,
aligned_base = Base & 0xFFFFFFFE;
MappedAsImage = false;
}
IMAGE_NT_HEADERS32* nt_header =
XIMAGE_NT_HEADERS32* nt_header =
ImageNtHeader(ctx->TranslateVirtual<uint8_t*>(aligned_base));
if (!nt_header) {
return 0;
}
if (nt_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
if (nt_header->OptionalHeader.Magic != XIMAGE_NT_OPTIONAL_HDR32_MAGIC) {
return 0;
}
if (DirectoryEntry >= nt_header->OptionalHeader.NumberOfRvaAndSizes) {
@ -468,7 +468,7 @@ dword_result_t RtlImageDirectoryEntryToData_entry(dword_t Base,
}
uint32_t n_sections = nt_header->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER* v8 = reinterpret_cast<IMAGE_SECTION_HEADER*>(
XIMAGE_SECTION_HEADER* v8 = reinterpret_cast<XIMAGE_SECTION_HEADER*>(
reinterpret_cast<char*>(&nt_header->OptionalHeader) +
nt_header->FileHeader.SizeOfOptionalHeader);
if (!n_sections) {

File diff suppressed because it is too large Load diff