diff --git a/README.md b/README.md index 251df51..d108bf2 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed | WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive | | GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files | | ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format | +| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable | ### Scripts diff --git a/patterns/coff.hexpat b/patterns/coff.hexpat new file mode 100644 index 0000000..ac4a534 --- /dev/null +++ b/patterns/coff.hexpat @@ -0,0 +1,209 @@ +#pragma MIME application/x-coff + +#include +#include + +enum Machine : u16 { + Unknown = 0x0000, + AM33 = 0x01D3, + AMD64 = 0x8664, + ARM = 0x01C0, + ARM64 = 0xAA64, + ARMNT = 0x01C4, + EBC = 0x0EBC, + I386 = 0x014C, + IA64 = 0x0200, + LOONGARCH32 = 0x6232, + LOONGARCH64 = 0x6264, + M32R = 0x9041, + MIPS16 = 0x0226, + MIPSFPU = 0x0366, + MIPSFPU16 = 0x0466, + POWERPC = 0x01F0, + POWERPCFP = 0x01F0, + R4000 = 0x0166, + RISCV32 = 0x5032, + RISCV64 = 0x5064, + RISCV128 = 0x5128, + SH3 = 0x01A2, + SH3DSP = 0x01A3, + SH4 = 0x01A6, + SH5 = 0x01A8, + THUMB = 0x01C2, + WCEMIPSV2 = 0x0169 +}; + +bitfield Characteristics { + relocsStripped : 1; + executableImage : 1; + lineNumsStripped : 1; + localSymsStripped : 1; + aggressiveWsTrim : 1; + largeAddressAware : 1; + padding : 1; + bytesReversedLo : 1; + _32BitMachine : 1; + debugStripped : 1; + removableRunFromSwap : 1; + netRunFromSwap : 1; + system : 1; + dll : 1; + upSystemOnly : 1; + bytesReversedHi : 1; +} [[right_to_left]]; + +enum Type : u16 { + Null = 0, + Void = 1, + Char = 2, + Short = 3, + Int = 4, + Long = 5, + Float = 6, + Double = 7, + Struct = 8, + Union = 9, + Enum = 10, + MOE = 11, + Byte = 12, + Word = 13, + UInt = 14, + DWord = 15 +}; + +enum StorageClass : u8 { + EndOfFunction = 0xFF, + Null = 0, + Automatic = 1, + External = 2, + Static = 3, + Register = 4, + ExternalDef = 5, + Label = 6, + UndefinedLabel = 7, + MemberOfStruct = 8, + Argument = 9, + StructTag = 10, + MemberOfUnion = 11, + UnionTag = 12, + TypeDefinition = 13, + UndefinedStatic = 14, + EnumTag = 15, + MemberOfEnum = 16, + RegisterParam = 17, + BitField = 18, + Block = 100, + Function = 101, + EndOfStruct = 102, + File = 103, + Section = 104, + WeakExternal = 105, + CLRToken = 107 +}; + +struct AuxSymbol { + u8 data[18]; +}; + +u32 countedSymbols = 0; +struct SymbolTable { + char name[8]; + u32 value; + u16 sectionNumber; + Type type; + StorageClass storageClass; + u8 numberOfAuxSymbols; + + countedSymbols += 1 + numberOfAuxSymbols; + + AuxSymbol auxSymbols[numberOfAuxSymbols]; + + if (countedSymbols >= parent.header.numberOfSymbols) + break; +}; + +struct String { + char value[]; +}; + +struct StringTable { + u32 size; + String strings[while($ < addressof(size) + size)]; +}; + +bitfield SectionFlags { + padding : 3; + typeNoPad : 1; + padding : 1; + cntCode : 1; + initializedData : 1; + uninitializedData : 1; + lnkOther : 1; + lnkInfo : 1; + padding : 1; + lnkRemove : 1; + lnkCOMDAT : 1; + padding : 2; + gprel : 1; + padding : 1; + memPurgeable : 1; + memLocked : 1; + memPreload : 1; + alignment : 4 [[format("format_alignment")]]; + lnkNrelocOvfl : 1; + memDiscardable : 1; + memNotCached : 1; + memNotPaged : 1; + memShared : 1; + memExecute : 1; + memRead : 1; + memWrite : 1; +} [[right_to_left]]; + +fn format_alignment(u8 alignment) { + return 1 << alignment; +}; + +struct Relocations { + u32 virtualAddress; + u32 symbolTableIndex; + Type type; +}; + +struct Section { + char name[8]; + type::Size virtualSize; + u32 virtualAddress; + type::Size sizeOfRawData; + u32 pointerToRawData; + u32 pointerToRelocations; + u32 pointerToLineNumbers; + u16 numberOfRelocations; + u16 numberOfLineNumbers; + SectionFlags characteristics; + + u8 rawData[sizeOfRawData] @ pointerToRawData [[sealed]]; + Relocations relocations[numberOfRelocations] @ pointerToRelocations; +}; + +struct Header { + Machine machine; + u16 numberOfSections; + type::time32_t timeDateStamp; + u32 pointerToSymbolTable; + u32 numberOfSymbols; + u16 sizeOfOptionalHeader; + Characteristics characteristics; +}; + + +struct COFF { + Header header; + + Section sectionTable[header.numberOfSections]; + + SymbolTable symbolTable[header.numberOfSymbols] @ header.pointerToSymbolTable; + StringTable stringTable @ addressof(symbolTable) + sizeof(symbolTable); +}; + +COFF coff @ 0x00; diff --git a/tests/patterns/test_data/coff.hexpat.obj b/tests/patterns/test_data/coff.hexpat.obj new file mode 100644 index 0000000..26ae2e9 Binary files /dev/null and b/tests/patterns/test_data/coff.hexpat.obj differ