// Portable Executable definitions
// Copyright (C) Florian Negele

// This file is part of the Eigen Compiler Suite.

// The ECS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The ECS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of the GNU General Public License version 3,
// the copyright holder grants you additional permissions to use
// this file as described in the ECS Runtime Support Exception.

// You should have received a copy of the GNU General Public License
// and a copy of the ECS Runtime Support Exception along with
// the ECS.  If not, see <https://www.gnu.org/licenses/>.

#ifndef ECS_DEF_PE_HEADER_INCLUDED
#define ECS_DEF_PE_HEADER_INCLUDED

#include "assembly"

#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_I386 0x14c
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define IMAGE_SCN_CNT_CODE 0x00000020
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define IMAGE_SUBSYSTEM_EFI_ROM 13
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2

#define DWORD(value) QBYTE(value)
#define LONG(value) QBYTE(value)
#define WORD(value) DBYTE(value)
#define ULONGLONG(value) OBYTE (value)

#define IMAGE_DOS_HEADER(e_cblp, e_cp, e_crlc, e_cparhdr, e_minalloc, e_maxalloc, e_ss, e_sp, e_csum, e_ip, e_cs, e_lfarlc, e_ovno, e_lfanew) \
	BYTE ("MZ") WORD (e_cblp) WORD (e_cp) WORD (e_crlc) WORD (e_cparhdr) WORD (e_minalloc) WORD (e_maxalloc) WORD (e_ss) \
	WORD (e_sp) WORD (e_csum) WORD (e_ip) WORD (e_cs) WORD (e_lfarlc) WORD (e_ovno) RESERVE (32) LONG (e_lfanew)

#define PE_HEADER \
	BYTE ("PE", 0, 0)

#define IMAGE_FILE_HEADER(Machine, NumberOfSections, TimeDateStamp, PointerToSymbolTable, NumberOfSymbols, SizeOfOptionalHeader, Characteristics) \
	WORD (Machine) WORD (NumberOfSections) DWORD (TimeDateStamp) DWORD (PointerToSymbolTable) DWORD (NumberOfSymbols) WORD (SizeOfOptionalHeader) WORD (Characteristics)

#define IMAGE_DATA_DIRECTORY(VirtualAddress, Size) \
	DWORD (VirtualAddress) DWORD (Size)

#define IMAGE_SECTION_HEADER(Name, VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData, PointerToRelocations, PointerToLinenumbers, NumberOfRelocations, NumberOfLinenumbers, Characteristics) \
	BYTE (Name) ALIGN (8) DWORD (VirtualSize) DWORD (VirtualAddress) DWORD (SizeOfRawData) DWORD (PointerToRawData) DWORD (PointerToRelocations) DWORD (PointerToLinenumbers) WORD (NumberOfRelocations) WORD (NumberOfLinenumbers) DWORD (Characteristics)

#define IMAGE_IMPORT_DESCRIPTOR(OriginalFirstThunk, TimeDateStamp, ForwarderChain, Name, FirstThunk) \
	DWORD (OriginalFirstThunk) DWORD (TimeDateStamp) DWORD (ForwarderChain) DWORD (Name) DWORD (FirstThunk)

#define IMAGE_IMPORT_BY_NAME(Hint, Name) \
	WORD (Hint) BYTE (Name, 0)

#if defined __amd32__

	#define IMAGE_THUNK_DATA_SIZE 4

	#define IMAGE_OPTIONAL_HEADER(MajorLinkerVersion, MinorLinkerVersion, SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData, AddressOfEntryPoint, BaseOfCode, BaseOfData, ImageBase, \
		SectionAlignment, FileAlignment, MajorOperatingSystemVersion, MinorOperatingSystemVersion, MajorImageVersion, MinorImageVersion, MajorSubsystemVersion, MinorSubsystemVersion, Win32VersionValue, \
		SizeOfImage, SizeOfHeaders, CheckSum, Subsystem, DllCharacteristics, SizeOfStackReserve, SizeOfStackCommit, SizeOfHeapReserve, SizeOfHeapCommit, LoaderFlags, NumberOfRvaAndSizes) \
		WORD (IMAGE_NT_OPTIONAL_HDR32_MAGIC) BYTE (MajorLinkerVersion) BYTE (MinorLinkerVersion) DWORD (SizeOfCode) DWORD (SizeOfInitializedData) DWORD (SizeOfUninitializedData) DWORD (AddressOfEntryPoint) DWORD (BaseOfCode) \
		DWORD (BaseOfData) DWORD (ImageBase) DWORD (SectionAlignment) DWORD (FileAlignment) WORD (MajorOperatingSystemVersion) WORD (MinorOperatingSystemVersion) WORD (MajorImageVersion) \
		WORD (MinorImageVersion) WORD (MajorSubsystemVersion) WORD (MinorSubsystemVersion) DWORD (Win32VersionValue) DWORD (SizeOfImage) DWORD (SizeOfHeaders) DWORD (CheckSum) WORD (Subsystem) \
		WORD (DllCharacteristics) DWORD (SizeOfStackReserve) DWORD (SizeOfStackCommit) DWORD (SizeOfHeapReserve) DWORD (SizeOfHeapCommit) DWORD (LoaderFlags) DWORD (NumberOfRvaAndSizes)

	#define IMAGE_THUNK_DATA(AddressOfData) \
		QBYTE (AddressOfData)

#elif defined __amd64__

	#define IMAGE_THUNK_DATA_SIZE 8

	#define IMAGE_OPTIONAL_HEADER(MajorLinkerVersion, MinorLinkerVersion, SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData, AddressOfEntryPoint, BaseOfCode, BaseOfData, ImageBase, \
		SectionAlignment, FileAlignment, MajorOperatingSystemVersion, MinorOperatingSystemVersion, MajorImageVersion, MinorImageVersion, MajorSubsystemVersion, MinorSubsystemVersion, Win32VersionValue, \
		SizeOfImage, SizeOfHeaders, CheckSum, Subsystem, DllCharacteristics, SizeOfStackReserve, SizeOfStackCommit, SizeOfHeapReserve, SizeOfHeapCommit, LoaderFlags, NumberOfRvaAndSizes) \
		WORD (IMAGE_NT_OPTIONAL_HDR64_MAGIC) BYTE (MajorLinkerVersion) BYTE (MinorLinkerVersion) DWORD (SizeOfCode) DWORD (SizeOfInitializedData) DWORD (SizeOfUninitializedData) DWORD (AddressOfEntryPoint) DWORD (BaseOfCode) \
		ULONGLONG (ImageBase) DWORD (SectionAlignment) DWORD (FileAlignment) WORD (MajorOperatingSystemVersion) WORD (MinorOperatingSystemVersion) WORD (MajorImageVersion) \
		WORD (MinorImageVersion) WORD (MajorSubsystemVersion) WORD (MinorSubsystemVersion) DWORD (Win32VersionValue) DWORD (SizeOfImage) DWORD (SizeOfHeaders) DWORD (CheckSum) WORD (Subsystem) \
		WORD (DllCharacteristics) ULONGLONG (SizeOfStackReserve) ULONGLONG (SizeOfStackCommit) ULONGLONG (SizeOfHeapReserve) ULONGLONG (SizeOfHeapCommit) DWORD (LoaderFlags) DWORD (NumberOfRvaAndSizes)

	#define IMAGE_THUNK_DATA(AddressOfData) \
		OBYTE (AddressOfData)
#else

	#error PE format not supported

#endif

#endif // ECS_DEF_PE_HEADER_INCLUDED
