forked from WerWolv/ImHex-Patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
patterns/ne: Adding pattern file for NE executables (WerWolv#58)
* Update pe.hexpat Implementing a number of things and fixing others * Update pe.hexpat Adding the readonlyData pattern * Update pe.hexpat Testing putting the number of tabs on Github to 4 instead of 8 (so that comments on the code for the Sections don't break) * Update pe.hexpat Reverting change that turned out to be needless * Update pe.hexpat Actually sending the `products[while($ != richHeaderEndPosition)]` to `products[while($ < richHeaderEndPosition)]` change * Add files via upload Adding NE test file * Add files via upload Adding NE pattern file * Update ne.hexpat Fixing the error with the entry table assignment * Update README.md Added the NE pattern file to the list of patterns
- Loading branch information
1 parent
01a1bd0
commit 9887da7
Showing
3 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
#include <std/mem.pat> | ||
|
||
#pragma bitfield_order right_to_left | ||
|
||
struct DOSHeader { | ||
char signature[2]; | ||
u16 lastPageSize; | ||
u16 numberOfPages; | ||
u16 relocations; | ||
u16 headerSizeInParagraphs; | ||
u16 minimumAllocatedParagraphs; | ||
u16 maximumAllocatedParagraphs; | ||
u16 initialSSValue; | ||
u16 initialRelativeSPValue; | ||
u16 checksum; | ||
u16 initialRelativeIPValue; | ||
u16 initialCSValue; | ||
u16 relocationsTablePointer; | ||
u16 overlayNumber; | ||
u8 overlayInformation[0x20]; | ||
u32 neHeaderPointer; | ||
}; | ||
|
||
u16 dosMessageOffset; | ||
u16 pointedCodeOffset; | ||
|
||
fn finddosmessage() { | ||
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) { | ||
if (std::mem::read_unsigned($+i, 1) == 0xBA) { // MOV instruction | ||
dosMessageOffset = std::mem::read_unsigned($+i+1, 2); | ||
break; | ||
} | ||
} | ||
}; | ||
|
||
fn findpointingcode() { | ||
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) { | ||
if (std::mem::read_unsigned($+i, 1) == 0xE8) { // CALL instruction | ||
pointedCodeOffset = std::mem::read_unsigned($+i+1, 2); | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
|
||
fn isdosdata(char c) { | ||
return c == 0x0D || c == '$'; | ||
}; | ||
|
||
struct DOSStub { | ||
if (findpointingcode()) { | ||
u8 pointingCode[3]; | ||
u8 code[while(std::mem::read_unsigned($, 1) != 0x00)] @ addressof(this) + pointedCodeOffset + 3; | ||
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))]; | ||
char data[while(std::mem::read_string($-1, 1) != "$")]; | ||
} | ||
else { | ||
finddosmessage(); | ||
if (dosMessageOffset > 0) { | ||
u8 code[while($ != addressof(this) + dosMessageOffset)]; | ||
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))]; | ||
char data[while(std::mem::read_string($-1, 1) != "$")]; | ||
} | ||
else { | ||
char code[while(std::mem::read_unsigned($, 1) != 0x00)]; | ||
} | ||
} | ||
}; | ||
|
||
struct FileHeader { | ||
DOSHeader dosHeader; | ||
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16; | ||
}; | ||
|
||
FileHeader fileHeader @ 0x00; | ||
|
||
enum DGroupType : u8 { | ||
NoAutoData, | ||
SingleData, | ||
MultipleData, | ||
Null | ||
}; | ||
|
||
fn formatDGroupType(u8 value) { | ||
DGroupType dgroup = value; | ||
|
||
return dgroup; | ||
}; | ||
|
||
enum AppType : u8 { | ||
None, | ||
Fullscreen, | ||
WinPMCompatible, | ||
UsesWinPM | ||
}; | ||
|
||
fn formatAppType(u8 value) { | ||
AppType app = value; | ||
|
||
return app; | ||
}; | ||
|
||
bitfield ProgramFlags { | ||
dGroupType : 2 [[format("formatDGroupType")]]; | ||
globalInitialization : 1; | ||
protectedModeOnly : 1; | ||
instructions86 : 1; | ||
instructions286 : 1; | ||
instructions386 : 1; | ||
instructionsX87 : 1; | ||
}; | ||
|
||
bitfield ApplicationFlags { | ||
applicationType : 2 [[format("formatAppType")]]; | ||
padding : 1; | ||
os2Application : 1; | ||
reserved : 1; | ||
imageError : 1; | ||
nonConforming : 1; | ||
dll : 1; | ||
}; | ||
|
||
enum OSType : u8 { | ||
Unknown = 0x00, | ||
OS2 = 0x01, | ||
Win16 = 0x02, | ||
DOS4 = 0x03, | ||
Win32 = 0x04, | ||
BorlandOSServices = 0x05, | ||
PharlapDOSExtenderOS2 = 0x81, | ||
PharlapDOSExtenderWindows = 0x82 | ||
}; | ||
|
||
bitfield OS2EXEFlags { | ||
longFilename : 1; | ||
protectedMode : 1; | ||
proportionalFonts : 1; | ||
gangloadArea : 1; | ||
}; | ||
|
||
struct NEHeader { | ||
char signature[2]; | ||
u8 majorLinkerVersion; | ||
u8 minorLinkerVersion; | ||
u16 entryTableOffset; | ||
u16 entryTableLength; | ||
u32 fileCRC; | ||
ProgramFlags programFlags; | ||
ApplicationFlags appFlags; | ||
u16 autoDataSegmentIndex; | ||
u16 initHeapSize; | ||
u16 initStackSize; | ||
u32 entryPoint; | ||
u32 initialStackPointer; | ||
u16 segmentCount; | ||
u16 moduleReferenceCount; | ||
u16 nonResidentNamesTableSize; | ||
u16 segmentTableOffset; | ||
u16 resourceTableOffset; | ||
u16 residentNamesTableOffset; | ||
u16 moduleReferenceTableOffset; | ||
u16 importedNamesTableOffset; | ||
u8 *nonResidentNamesTablePointer[nonResidentNamesTableSize] : u32; | ||
u16 moveableEntryCount; | ||
u16 fileAlignmentSizeShiftCount; | ||
u16 resourceCount; | ||
OSType targetOS; | ||
OS2EXEFlags os2ExeFlags; | ||
u16 thunksReturnOffset; | ||
u16 segmentReferenceThunksOffset; | ||
u16 minimumCodeSwapAreaSize; | ||
u8 expectedMinorWindowsVersion; | ||
u8 expectedMajorWindowsVersion; | ||
}; | ||
|
||
NEHeader neHeader @ fileHeader.dosHeader.neHeaderPointer; | ||
|
||
bitfield SegmentTableFlags { | ||
dataSegment : 1; | ||
typeMask : 2; | ||
padding : 1; | ||
moveable : 1; | ||
padding : 1; | ||
preloaded : 1; | ||
padding : 1; | ||
containsRelocationInfo : 1; | ||
padding : 1; | ||
discardPriority : 4; | ||
} [[right_to_left]]; | ||
|
||
struct SegmentTable { | ||
u16 segmentDataPointer; | ||
u16 segmentLength; | ||
SegmentTableFlags segmentTableFlags; | ||
u16 minimumAllocationSize; | ||
}; | ||
|
||
SegmentTable segmentTable[neHeader.segmentCount] @ addressof(neHeader) + neHeader.segmentTableOffset; | ||
|
||
bitfield BlockFlags { | ||
padding : 4; | ||
moveable : 1; | ||
shared : 1; | ||
preload : 1; | ||
padding : 9; | ||
}; | ||
|
||
struct ResourceTypeInformationBlock { | ||
u8 *resourcePointer : u16; | ||
u16 resourceLength; | ||
BlockFlags flags; | ||
u16 resourceID; | ||
u32 reserved; | ||
}; | ||
|
||
struct ResourceRecord { | ||
u16 typeID; | ||
u16 numberOfResources; | ||
u32 reserved; | ||
ResourceTypeInformationBlock blocks[numberOfResources]; | ||
}; | ||
|
||
struct ResourceTable { | ||
u16 alignmentShiftCount; | ||
ResourceRecord records[neHeader.resourceTableEntryCount]; | ||
u8 stringLength; | ||
char string[stringLength]; | ||
}; | ||
|
||
ResourceTable resourceTable[neHeader.resourceCount] @ addressof(neHeader) + neHeader.resourceTableOffset; | ||
|
||
struct ResidentName { | ||
u8 stringLength; | ||
char string[stringLength]; | ||
u16 ordinalNumber; | ||
}; | ||
|
||
ResidentName residentNameTable[while($+1 < addressof(neHeader) + neHeader.moduleReferenceTableOffset)] @ addressof(neHeader) + neHeader.residentNamesTableOffset; | ||
|
||
struct ModuleReference { | ||
u16 moduleNameOffset; | ||
}; | ||
|
||
ModuleReference moduleReferenceTable[neHeader.moduleReferenceCount] @ addressof(neHeader) + neHeader.moduleReferenceTableOffset; | ||
|
||
struct ImportedNameTable { | ||
u8 stringLength; | ||
char string[stringLength]; | ||
}; | ||
|
||
ImportedNameTable importedNameTable[while($ < addressof(neHeader) + neHeader.entryTableOffset)] @ addressof(neHeader) + neHeader.importedNamesTableOffset; | ||
|
||
enum EntryDataType : u8 { | ||
Unused, | ||
Fixed = 0x01 ... 0xFE, | ||
Moveable | ||
}; | ||
|
||
struct EntryTable { | ||
u8 entryCount; | ||
EntryDataType segmentIndicator; | ||
}; | ||
|
||
EntryTable entryTable[neHeader.entryTableLength/2] @ addressof(neHeader) + neHeader.entryTableOffset; |
Binary file not shown.