diff --git a/BurnOutSharp.Models/LinearExecutable/Enums.cs b/BurnOutSharp.Models/LinearExecutable/Enums.cs index 56940955..0b9a4c4d 100644 --- a/BurnOutSharp.Models/LinearExecutable/Enums.cs +++ b/BurnOutSharp.Models/LinearExecutable/Enums.cs @@ -65,49 +65,263 @@ namespace BurnOutSharp.Models.LinearExecutable } [Flags] - public enum InformationBlockFlag : uint + public enum ModuleFlags : uint { /// - /// Initialization (Only for DLL): - /// 0 Global - /// 1 Per-Process + /// Reserved for system use. /// - Initialization = 1 << 2, + Reserved0 = 0x00000001, /// - /// No internal fixup in exe image + /// Reserved for system use. /// - NoInternalFixup = 1 << 4, + Reserved1 = 0x00000002, /// - /// No internal fixup in exe image + /// Per-Process Library Initialization. /// - NoExternalFixup = 1 << 5, - - // TODO: Figure out this block of flags - // 8, 9, 10 all have the same note: - // 0 Unknown - // 1 Incompatible with PM windowing - // 2 Compatible with PM windowing - // 3 Uses PM windowing API + /// + /// The setting of this bit requires the EIP Object # and EIP fields + /// to have valid values. If the EIP Object # and EIP fields are + /// valid and this bit is NOT set, then Global Library Initialization + /// is assumed. Setting this bit for an EXE file is invalid. + /// + Initialization = 0x00000004, /// - /// Module not loadable + /// Reserved for system use. /// - ModuleNotLoadable = 1 << 13, + Reserved3 = 0x00000008, /// - /// Module is DLL rather then program + /// Internal fixups for the module have been applied. /// - IsDLL = 1 << 15, + /// + /// The setting of this bit in a Linear Executable Module indicates that + /// each object of the module has a preferred load address specified in + /// the Object Table Reloc Base Addr. If the module's objects can not be + /// loaded at these preferred addresses, then the relocation records that + /// have been retained in the file data will be applied. + /// + InternalFixupsApplied = 0x00000010, - // Bits 16-31 are all reserved + /// + /// External fixups for the module have been applied. + /// + ExternalFixupsApplied = 0x00000020, + + /// + /// Reserved for system use. + /// + Reserved6 = 0x00000040, + + /// + /// Reserved for system use. + /// + Reserved7 = 0x00000080, + + /// + /// Incompatible with PM windowing. + /// + IncompatibleWithPMWindowing = 0x00000100, + + /// + /// Incompatible with PM windowing. + /// + CompatibleWithPMWindowing = 0x00000200, + + /// + /// Uses PM windowing API. + /// + UsesPMWindowing = 0x00000300, + + /// + /// Reserved for system use. + /// + Reserved10 = 0x00000400, + + /// + /// Reserved for system use. + /// + Reserved11 = 0x00000800, + + /// + /// Reserved for system use. + /// + Reserved12 = 0x00001000, + + /// + /// Module is not loadable. + /// + /// + /// When the 'Module is not loadable' flag is set, it indicates that + /// either errors were detected at link time or that the module is + /// being incrementally linked and therefore can't be loaded. + /// + ModuleNotLoadable = 0x00002000, + + /// + /// Reserved for system use. + /// + Reserved14 = 0x00004000, + + /// + /// Module type mask. + /// + ModuleTypeMask = 0x00038000, + + /// + /// Program module. + /// + /// + /// A module can not contain dynamic links to other modules that have + /// the 'program module' type. + /// + ProgramModule = 0x00000000, + + /// + /// Library module. + /// + LibraryModule = 0x00008000, + + /// + /// Protected Memory Library module. + /// + ProtectedMemoryLibraryModule = 0x00018000, + + /// + /// Physical Device Driver module. + /// + PhysicalDeviceDriverModule = 0x00020000, + + /// + /// Virtual Device Driver module. + /// + VirtualDeviceDriverModule = 0x00028000, + + /// + /// Per-process Library Termination. + /// + /// + /// The setting of this bit requires the EIP Object # and EIP fields + /// to have valid values. If the EIP Object # and EIP fields are + /// valid and this bit is NOT set, then Global Library Termination + /// is assumed. Setting this bit for an EXE file is invalid. + /// + PerProcessLibraryTermination = 0x40000000, + } + + [Flags] + public enum ObjectFlags : ushort + { + /// + /// Readable Object. + /// + ReadableObject = 0x0001, + + /// + /// Writable Object. + /// + WritableObject = 0x0002, + + /// + /// Executable Object. + /// + ExecutableObject = 0x0004, + + // The readable, writable and executable flags provide support for all possible + // protections. In systems where all of these protections are not supported, + // the loader will be responsible for making the appropriate protection match + // for the system. + + /// + /// Resource Object. + /// + ResourceObject = 0x0008, + + /// + /// Discardable Object. + /// + DiscardableObject = 0x0010, + + /// + /// Object is Shared. + /// + Shared = 0x0020, + + /// + /// Object has Preload Pages. + /// + HasPreloadPages = 0x0040, + + /// + /// Object has Invalid Pages. + /// + HasInvalidPages = 0x0080, + + /// + /// Object has Zero Filled Pages. + /// + HasZeroFilledPages = 0x0100, + + /// + /// Object is Resident (valid for VDDs, PDDs only). + /// + Resident = 0x0200, + + /// + /// Object is Resident & Contiguous (VDDs, PDDs only). + /// + ResidentAndContiguous = 0x0300, + + /// + /// Object is Resident & 'long-lockable' (VDDs, PDDs only). + /// + ResidentAndLongLockable = 0x0400, + + /// + /// Reserved for system use. + /// + Reserved = 0x0800, + + /// + /// 16:16 Alias Required (80x86 Specific). + /// + AliasRequired = 0x1000, + + /// + /// Big/Default Bit Setting (80x86 Specific). + /// + BitSetting = 0x2000, + + // The 'big/default' bit, for data segments, controls the setting of the + // Big bit in the segment descriptor. (The Big bit, or B-bit, determines + // whether ESP or SP is used as the stack pointer.) For code segments, + // this bit controls the setting of the Default bit in the segment + // descriptor. (The Default bit, or D-bit, determines whether the default + // word size is 32-bits or 16-bits. It also affects the interpretation of + // the instruction stream.) + + /// + /// Object is conforming for code (80x86 Specific). + /// + Conforming = 0x4000, + + /// + /// Object I/O privilege level (80x86 Specific). Only used for 16:16 Alias Objects. + /// + PrivilegeLevel = 0x8000, } public enum OperatingSystem : ushort { /// - /// OS/2 + /// Unknown (any "new-format" OS) + /// + Unknown = 0x00, + + /// + /// OS/2 (default) /// OS2 = 0x01, diff --git a/BurnOutSharp.Models/LinearExecutable/InformationBlock.cs b/BurnOutSharp.Models/LinearExecutable/InformationBlock.cs index 88e41ebf..97266977 100644 --- a/BurnOutSharp.Models/LinearExecutable/InformationBlock.cs +++ b/BurnOutSharp.Models/LinearExecutable/InformationBlock.cs @@ -11,242 +11,416 @@ namespace BurnOutSharp.Models.LinearExecutable /// the beginning of the block): /// /// + /// [StructLayout(LayoutKind.Sequential)] public class InformationBlock { /// - /// Specifies the signature word 'LE' (4Ch 45H) + /// Specifies the signature word + /// 'LE' (4Ch 45H) + /// 'LX' (4Ch 58H) /// + /// + /// The signature word is used by the loader to identify the EXE + /// file as a valid 32-bit Linear Executable Module Format. + /// public char[] Signature; /// - /// Byte order + /// Byte Ordering. /// + /// + /// This byte specifies the byte ordering for the linear EXE format. + /// public ByteOrder ByteOrder; /// - /// Word order + /// Word Ordering. /// + /// + /// This byte specifies the Word ordering for the linear EXE format. + /// public WordOrder WordOrder; /// - /// Executable format level + /// Linear EXE Format Level. /// + /// + /// The Linear EXE Format Level is set to 0 for the initial version of the + /// 32-bit linear EXE format. Each incompatible change to the linear EXE + /// format must increment this value. This allows the system to recognized + /// future EXE file versions so that an appropriate error message may be + /// displayed if an attempt is made to load them. + /// public uint ExecutableFormatLevel; /// - /// CPU type + /// Module CPU Type. /// + /// + /// This field specifies the type of CPU required by this module to run. + /// public CPUType CPUType; /// - /// Target operating system + /// Module OS Type. /// - public OperatingSystem TargetOperatingSystem; + /// + /// This field specifies the type of Operating system required to run this module. + /// + public OperatingSystem ModuleOS; /// /// Module version /// + /// + /// This is useful for differentiating between revisions of dynamic linked modules. + /// This value is specified at link time by the user. + /// public uint ModuleVersion; /// /// Module type flags /// - public InformationBlockFlag ModuleTypeFlags; + public ModuleFlags ModuleTypeFlags; /// - /// Number of memory pages + /// Number of pages in module. /// - public uint MemoryPageCount; + /// + /// This field specifies the number of pages physically contained in this module. + /// In other words, pages containing either enumerated or iterated data, or + /// zero-fill pages that have relocations, not invalid or zero-fill pages implied + /// by the Virtual Size in the Object Table being larger than the number of pages + /// actually in the linear EXE file. These pages are contained in the 'preload + /// pages', 'demand load pages' and 'iterated data pages' sections of the linear + /// EXE module. This is used to determine the size of the page information tables + /// in the linear EXE module. + /// + public uint ModuleNumberPages; /// - /// Initial object CS number + /// The Object number to which the Entry Address is relative. /// + /// + /// This specifies the object to which the Entry Address is relative. This must be + /// a nonzero value for a program module to be correctly loaded. A zero value for + /// a library module indicates that no library entry routine exists. If this value + /// is zero, then both the Per-process Library Initialization bit and the Per-process + /// Library Termination bit must be clear in the module flags, or else the loader + /// will fail to load the module. Further, if the Per-process Library Termination bit + /// is set, then the object to which this field refers must be a 32-bit object (i.e., + /// the Big/Default bit must be set in the object flags; see below). + /// public uint InitialObjectCS; /// - /// Initial EIP + /// Entry Address of module. /// + /// + /// The Entry Address is the starting address for program modules and the library + /// initialization and Library termination address for library modules. + /// public uint InitialEIP; /// - /// Initial object SS number + /// The Object number to which the ESP is relative. /// + /// + /// This specifies the object to which the starting ESP is relative. This must be a + /// nonzero value for a program module to be correctly loaded. This field is ignored + /// for a library module. + /// public uint InitialObjectSS; /// - /// Initial ESP + /// Starting stack address of module. /// + /// + /// The ESP defines the starting stack pointer address for program modules. A zero + /// value in this field indicates that the stack pointer is to be initialized to the + /// highest address/offset in the object. This field is ignored for a library module. + /// public uint InitialESP; /// - /// Memory page size + /// The size of one page for this system. /// + /// + /// This field specifies the page size used by the linear EXE format and the system. + /// For the initial version of this linear EXE format the page size is 4Kbytes. + /// (The 4K page size is specified by a value of 4096 in this field.) + /// public uint MemoryPageSize; /// - /// Bytes on last page + /// The shift left bits for page offsets. /// + /// + /// This field gives the number of bit positions to shift left when interpreting + /// the Object Page Table entries' page offset field. This determines the alignment + /// of the page information in the file. For example, a value of 4 in this field + /// would align all pages in the Data Pages and Iterated Pages sections on 16 byte + /// (paragraph) boundaries. A Page Offset Shift of 9 would align all pages on a + /// 512 byte (disk sector) basis. The default value for this field is 12 (decimal), + /// which give a 4096 byte alignment. All other offsets are byte aligned. + /// public uint BytesOnLastPage; /// - /// Fix-up section size + /// Total size of the fixup information in bytes. /// + /// + /// This includes the following 4 tables: + /// - Fixup Page Table + /// - Fixup Record Table + /// - Import Module name Table + /// - Import Procedure Name Table + /// public uint FixupSectionSize; /// - /// Fix-up section checksum + /// Checksum for fixup information. /// + /// + /// This is a cryptographic checksum covering all of the fixup information. The + /// checksum for the fixup information is kept separate because the fixup data is + /// not always loaded into main memory with the 'loader section'. If the checksum + /// feature is not implemented, then the linker will set these fields to zero. + /// public uint FixupSectionChecksum; /// - /// Loader section size + /// Size of memory resident tables. /// + /// + /// This is the total size in bytes of the tables required to be memory resident + /// for the module, while the module is in use. This total size includes all + /// tables from the Object Table down to and including the Per-Page Checksum Table. + /// public uint LoaderSectionSize; /// - /// Loader section checksum + /// Checksum for loader section. /// + /// + /// This is a cryptographic checksum covering all of the loader section information. + /// If the checksum feature is not implemented, then the linker will set these fields + /// to zero. + /// public uint LoaderSectionChecksum; /// - /// Offset of object table + /// Object Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ObjectTableOffset; /// - /// Object table entries + /// Object Table Count. /// + /// + /// This defines the number of entries in Object Table. + /// public uint ObjectTableCount; /// - /// Object page map offset + /// Object Page Table offset /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ObjectPageMapOffset; /// - /// Object iterate data map offset + /// Object Iterated Pages offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ObjectIterateDataMapOffset; /// - /// Resource table offset + /// Resource Table offset /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ResourceTableOffset; /// - /// Resource table entries + /// Number of entries in Resource Table. /// public uint ResourceTableCount; /// - /// Resident names table offset + /// Resident Name Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ResidentNamesTableOffset; /// - /// Entry table offset + /// Entry Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint EntryTableOffset; /// - /// Module directives table offset + /// Module Format Directives Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ModuleDirectivesTableOffset; /// - /// Module directives entries + /// Number of Module Format Directives in the Table. /// + /// + /// This field specifies the number of entries in the + /// Module Format Directives Table. + /// public uint ModuleDirectivesCount; /// - /// Fix-up page table offset + /// Fixup Page Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint FixupPageTableOffset; /// - /// Fix-up record table offset + /// Fixup Record Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint FixupRecordTableOffset; /// - /// Imported modules name table offset + /// Import Module Name Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint ImportedModulesNameTableOffset; /// - /// Imported modules count + /// The number of entries in the Import Module Name Table. /// public uint ImportedModulesCount; /// - /// Imported procedure name table offset + /// Import Procedure Name Table offset. /// - public uint ImportedProcedureNameTableOffset; + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ImportProcedureNameTableOffset; /// - /// Per-page checksum table offset + /// Per-page Checksum Table offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint PerPageChecksumTableOffset; /// - /// Data pages offset from top of file + /// Data Pages Offset. /// + /// + /// This offset is relative to the beginning of the EXE file. + /// public uint DataPagesOffset; /// - /// Preload page count + /// Number of Preload pages for this module. /// + /// + /// Note that OS/2 2.0 does not respect the preload of pages as specified + /// in the executable file for performance reasons. + /// public uint PreloadPageCount; /// - /// Non-resident names table offset from top of file + /// Non-Resident Name Table offset. /// - public uint NonresidentNamesTableOffset; + /// + /// This offset is relative to the beginning of the EXE file. + /// + public uint NonResidentNamesTableOffset; /// - /// Non-resident names table length + /// Number of bytes in the Non-resident name table. /// - public uint NonresidentNamesTableLength; + public uint NonResidentNamesTableLength; /// - /// Non-resident names table checksum + /// Non-Resident Name Table Checksum. /// - public uint NonresidentNamesTableChecksum; + /// + /// This is a cryptographic checksum of the Non-Resident Name Table. + /// + public uint NonResidentNamesTableChecksum; /// - /// Automatic data object + /// The Auto Data Segment Object number. /// + /// + /// This is the object number for the Auto Data Segment used by 16-bit modules. + /// This field is supported for 16-bit compatibility only and is not used by + /// 32-bit modules. + /// public uint AutomaticDataObject; /// - /// Debug information offset + /// Debug Information offset. /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// public uint DebugInformationOffset; /// - /// Debug information length + /// Debug Information length. /// + /// + /// The length of the debug information in bytes. + /// public uint DebugInformationLength; /// - /// Preload instance pages number + /// Instance pages in preload section. /// + /// + /// The number of instance data pages found in the preload section. + /// public uint PreloadInstancePagesNumber; /// - /// Demand instance pages number + /// Instance pages in demand section. /// + /// + /// The number of instance data pages found in the demand section. + /// public uint DemandInstancePagesNumber; /// - /// Extra heap allocation + /// Heap size added to the Auto DS Object. /// + /// + /// The heap size is the number of bytes added to the Auto Data Segment + /// by the loader. This field is supported for 16-bit compatibility only and + /// is not used by 32-bit modules. + /// public uint ExtraHeapAllocation; - - /// - /// ??? - /// - public uint Reserved; } } diff --git a/BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs b/BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs index 68602efb..d67b1869 100644 --- a/BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs +++ b/BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs @@ -9,38 +9,73 @@ namespace BurnOutSharp.Models.LinearExecutable /// values found in in the segment table (the locations are relative to /// the beginning of each entry): /// + /// + /// Entries in the Object Table are numbered starting from one. + /// /// + /// [StructLayout(LayoutKind.Sequential)] public class ObjectTableEntry { /// - /// Virtual segment size in bytes + /// Virtual memory size. /// + /// + /// This is the size of the object that will be allocated when the object + /// is loaded. The object's virtual size (rounded up to the page size value) + /// must be greater than or equal to the total size of the pages in the EXE + /// file for the object. This memory size must also be large enough to + /// contain all of the iterated data and uninitialized data in the EXE file. + /// public uint VirtualSegmentSize; /// - /// Relocation base address + /// Relocation Base Address. /// + /// + /// The relocation base address the object is currently relocated to. If the + /// internal relocation fixups for the module have been removed, this is the + /// address the object will be allocated at by the loader. + /// public uint RelocationBaseAddress; /// - /// Object flags + /// Flag bits for the object. /// - /// No flags are documented properly - public uint ObjectFlags; + public ObjectFlags ObjectFlags; /// - /// Page map index + /// Object Page Table Index. /// - public uint PageMapIndex; + /// + /// This specifies the number of the first object page table entry for this object. + /// The object page table specifies where in the EXE file a page can be found for + /// a given object and specifies per-page attributes. + /// + /// The object table entries are ordered by logical page in the object table. In + /// other words the object table entries are sorted based on the object page table + /// index value. + /// + public uint PageTableIndex; /// - /// Page map entries + /// # of object page table entries for this object. /// - public uint PageMapEntries; + /// + /// Any logical pages at the end of an object that do not have an entry in the object + /// page table associated with them are handled as zero filled or invalid pages by + /// the loader. + /// + /// When the last logical pages of an object are not specified with an object page + /// table entry, they are treated as either zero filled pages or invalid pages based + /// on the last entry in the object page table for that object. If the last entry + /// was neither a zero filled or invalid page, then the additional pages are treated + /// as zero filled pages. + /// + public uint PageTableEntries; /// - /// ??? + /// Reserved for future use. Must be set to zero. /// public uint Reserved; }