mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-23 06:34:03 +00:00
Fill out LE/LX builder
This commit is contained in:
@@ -86,29 +86,365 @@ namespace BurnOutSharp.Builders
|
||||
#region Object Table
|
||||
|
||||
// Get the object table offset
|
||||
long objectTableOffset = informationBlock.ObjectTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (objectTableOffset < 0 || objectTableOffset >= data.Length)
|
||||
return null;
|
||||
|
||||
// Seek to the object table
|
||||
data.Seek(objectTableOffset, SeekOrigin.Begin);
|
||||
|
||||
// Create the object table
|
||||
executable.ObjectTable = new ObjectTableEntry[informationBlock.ObjectTableCount];
|
||||
|
||||
// Try to parse the object table
|
||||
for (int i = 0; i < executable.ObjectTable.Length; i++)
|
||||
long offset = informationBlock.ObjectTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
var objectTableEntry = ParseObjectTableEntry(data);
|
||||
if (objectTableEntry == null)
|
||||
return null;
|
||||
// Seek to the object table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
executable.ObjectTable[i] = objectTableEntry;
|
||||
// Create the object table
|
||||
executable.ObjectTable = new ObjectTableEntry[informationBlock.ObjectTableCount];
|
||||
|
||||
// Try to parse the object table
|
||||
for (int i = 0; i < executable.ObjectTable.Length; i++)
|
||||
{
|
||||
var entry = ParseObjectTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.ObjectTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Implement LE/LX parsing
|
||||
#region Object Page Map
|
||||
|
||||
// Get the object page map offset
|
||||
offset = informationBlock.ObjectPageMapOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the object page map
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the object page map
|
||||
executable.ObjectPageMap = new ObjectPageMapEntry[informationBlock.ObjectTableCount];
|
||||
|
||||
// Try to parse the object page map
|
||||
for (int i = 0; i < executable.ObjectPageMap.Length; i++)
|
||||
{
|
||||
var entry = ParseObjectPageMapEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.ObjectPageMap[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Object Iterate Data Map
|
||||
|
||||
offset = informationBlock.ObjectIterateDataMapOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the object page map
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// TODO: Implement when model found
|
||||
// No model has been found in the documentation about what
|
||||
// each of the entries looks like for this map.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resource Table
|
||||
|
||||
// Get the resource table offset
|
||||
offset = informationBlock.ResourceTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the resource table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the resource table
|
||||
executable.ResourceTable = new ResourceTableEntry[informationBlock.ResourceTableCount];
|
||||
|
||||
// Try to parse the resource table
|
||||
for (int i = 0; i < executable.ResourceTable.Length; i++)
|
||||
{
|
||||
var entry = ParseResourceTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.ResourceTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resident Names Table
|
||||
|
||||
// Get the resident names table offset
|
||||
offset = informationBlock.ResidentNamesTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the resident names table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the resident names table
|
||||
var residentNamesTable = new List<ResidentNamesTableEntry>();
|
||||
|
||||
// Try to parse the resident names table
|
||||
while (true)
|
||||
{
|
||||
var entry = ParseResidentNamesTableEntry(data);
|
||||
residentNamesTable.Add(entry);
|
||||
|
||||
// If we have a 0-length entry
|
||||
if (entry.Length == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Assign the resident names table
|
||||
executable.ResidentNamesTable = residentNamesTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Entry Table
|
||||
|
||||
// Get the entry table offset
|
||||
offset = informationBlock.EntryTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the entry table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the entry table
|
||||
var entryTable = new List<EntryTableBundle>();
|
||||
|
||||
// Try to parse the entry table
|
||||
while (true)
|
||||
{
|
||||
var bundle = ParseEntryTableBundle(data);
|
||||
entryTable.Add(bundle);
|
||||
|
||||
// If we have a 0-length entry
|
||||
if (bundle.Entries == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Assign the entry table
|
||||
executable.EntryTable = entryTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Module Format Directives Table
|
||||
|
||||
// Get the module format directives table offset
|
||||
offset = informationBlock.ModuleDirectivesTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the module format directives table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the module format directives table
|
||||
executable.ModuleFormatDirectivesTable = new ModuleFormatDirectivesTableEntry[informationBlock.ModuleDirectivesCount];
|
||||
|
||||
// Try to parse the module format directives table
|
||||
for (int i = 0; i < executable.ModuleFormatDirectivesTable.Length; i++)
|
||||
{
|
||||
var entry = ParseModuleFormatDirectivesTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.ModuleFormatDirectivesTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Verify Record Directive Table
|
||||
|
||||
// TODO: Figure out where the offset to this table is stored
|
||||
// The documentation suggests it's either part of or immediately following
|
||||
// the Module Format Directives Table
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fix-up Page Table
|
||||
|
||||
// Get the fix-up page table offset
|
||||
offset = informationBlock.FixupPageTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the fix-up page table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the fix-up page table
|
||||
executable.FixupPageTable = new FixupPageTableEntry[executable.ObjectPageMap.Length + 1];
|
||||
|
||||
// Try to parse the fix-up page table
|
||||
for (int i = 0; i < executable.FixupPageTable.Length; i++)
|
||||
{
|
||||
var entry = ParseFixupPageTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.FixupPageTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fix-up Record Table
|
||||
|
||||
// Get the fix-up record table offset
|
||||
offset = informationBlock.FixupRecordTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the fix-up record table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the fix-up record table
|
||||
executable.FixupRecordTable = new FixupRecordTableEntry[executable.ObjectPageMap.Length + 1];
|
||||
|
||||
// Try to parse the fix-up record table
|
||||
for (int i = 0; i < executable.FixupRecordTable.Length; i++)
|
||||
{
|
||||
var entry = ParseFixupRecordTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.FixupRecordTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imported Module Name Table
|
||||
|
||||
// Get the imported module name table offset
|
||||
offset = informationBlock.ImportedModulesNameTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the imported module name table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the imported module name table
|
||||
executable.ImportModuleNameTable = new ImportModuleNameTableEntry[informationBlock.ImportedModulesCount];
|
||||
|
||||
// Try to parse the imported module name table
|
||||
for (int i = 0; i < executable.ImportModuleNameTable.Length; i++)
|
||||
{
|
||||
var entry = ParseImportModuleNameTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.ImportModuleNameTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imported Module Procedure Name Table
|
||||
|
||||
// Get the imported module procedure name table offset
|
||||
offset = informationBlock.ImportProcedureNameTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the imported module procedure name table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Get the size of the imported module procedure name table
|
||||
long tableSize = informationBlock.FixupPageTableOffset
|
||||
+ informationBlock.FixupSectionSize
|
||||
- informationBlock.ImportProcedureNameTableOffset;
|
||||
|
||||
// Create the imported module procedure name table
|
||||
var importModuleProcedureNameTable = new List<ImportModuleProcedureNameTableEntry>();
|
||||
|
||||
// Try to parse the imported module procedure name table
|
||||
while (data.Position < offset + tableSize)
|
||||
{
|
||||
var entry = ParseImportModuleProcedureNameTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
importModuleProcedureNameTable.Add(entry);
|
||||
}
|
||||
|
||||
// Assign the resident names table
|
||||
executable.ImportModuleProcedureNameTable = importModuleProcedureNameTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Per-Page Checksum Table
|
||||
|
||||
// Get the per-page checksum table offset
|
||||
offset = informationBlock.PerPageChecksumTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the per-page checksum name table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the per-page checksum name table
|
||||
executable.PerPageChecksumTable = new PerPageChecksumTableEntry[informationBlock.ModuleNumberPages];
|
||||
|
||||
// Try to parse the per-page checksum name table
|
||||
for (int i = 0; i < executable.PerPageChecksumTable.Length; i++)
|
||||
{
|
||||
var entry = ParsePerPageChecksumTableEntry(data);
|
||||
if (entry == null)
|
||||
return null;
|
||||
|
||||
executable.PerPageChecksumTable[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Non-Resident Names Table
|
||||
|
||||
// Get the non-resident names table offset
|
||||
offset = informationBlock.NonResidentNamesTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the non-resident names table
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Create the non-resident names table
|
||||
var nonResidentNamesTable = new List<NonResidentNamesTableEntry>();
|
||||
|
||||
// Try to parse the non-resident names table
|
||||
while (true)
|
||||
{
|
||||
var entry = ParseNonResidentNameTableEntry(data);
|
||||
nonResidentNamesTable.Add(entry);
|
||||
|
||||
// If we have a 0-length entry
|
||||
if (entry.Length == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Assign the non-resident names table
|
||||
executable.NonResidentNamesTable = nonResidentNamesTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Debug Information
|
||||
|
||||
// Get the debug information offset
|
||||
offset = informationBlock.NonResidentNamesTableOffset + stub.Header.NewExeHeaderAddr;
|
||||
if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length)
|
||||
{
|
||||
// Seek to the debug information
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Try to parse the debug information
|
||||
var debugInformation = ParseDebugInformation(data, informationBlock.DebugInformationLength);
|
||||
if (debugInformation == null)
|
||||
return null;
|
||||
|
||||
// Set the debug information
|
||||
executable.DebugInformation = debugInformation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return executable;
|
||||
}
|
||||
@@ -121,7 +457,7 @@ namespace BurnOutSharp.Builders
|
||||
private static InformationBlock ParseInformationBlock(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
InformationBlock informationBlock = new InformationBlock();
|
||||
var informationBlock = new InformationBlock();
|
||||
|
||||
byte[] magic = data.ReadBytes(2);
|
||||
informationBlock.Signature = Encoding.ASCII.GetString(magic);
|
||||
@@ -185,16 +521,423 @@ namespace BurnOutSharp.Builders
|
||||
private static ObjectTableEntry ParseObjectTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
ObjectTableEntry objectTableEntry = new ObjectTableEntry();
|
||||
var entry = new ObjectTableEntry();
|
||||
|
||||
objectTableEntry.VirtualSegmentSize = data.ReadUInt32();
|
||||
objectTableEntry.RelocationBaseAddress = data.ReadUInt32();
|
||||
objectTableEntry.ObjectFlags = (ObjectFlags)data.ReadUInt16();
|
||||
objectTableEntry.PageTableIndex = data.ReadUInt32();
|
||||
objectTableEntry.PageTableEntries = data.ReadUInt32();
|
||||
objectTableEntry.Reserved = data.ReadUInt32();
|
||||
entry.VirtualSegmentSize = data.ReadUInt32();
|
||||
entry.RelocationBaseAddress = data.ReadUInt32();
|
||||
entry.ObjectFlags = (ObjectFlags)data.ReadUInt16();
|
||||
entry.PageTableIndex = data.ReadUInt32();
|
||||
entry.PageTableEntries = data.ReadUInt32();
|
||||
entry.Reserved = data.ReadUInt32();
|
||||
|
||||
return objectTableEntry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an object page map entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled object page map entry on success, null on error</returns>
|
||||
private static ObjectPageMapEntry ParseObjectPageMapEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ObjectPageMapEntry();
|
||||
|
||||
entry.PageDataOffset = data.ReadUInt32();
|
||||
entry.DataSize = data.ReadUInt16();
|
||||
entry.Flags = (ObjectPageFlags)data.ReadUInt16();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a resource table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled resource table entry on success, null on error</returns>
|
||||
private static ResourceTableEntry ParseResourceTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ResourceTableEntry();
|
||||
|
||||
entry.TypeID = (ResourceTableEntryType)data.ReadUInt32();
|
||||
entry.NameID = data.ReadUInt16();
|
||||
entry.ResourceSize = data.ReadUInt32();
|
||||
entry.ObjectNumber = data.ReadUInt16();
|
||||
entry.Offset = data.ReadUInt32();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a resident names table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled resident names table entry on success, null on error</returns>
|
||||
private static ResidentNamesTableEntry ParseResidentNamesTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ResidentNamesTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
{
|
||||
byte[] name = data.ReadBytes(entry.Length);
|
||||
entry.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
|
||||
}
|
||||
entry.OrdinalNumber = data.ReadUInt16();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an entry table bundle
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled entry table bundle on success, null on error</returns>
|
||||
private static EntryTableBundle ParseEntryTableBundle(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var bundle = new EntryTableBundle();
|
||||
|
||||
bundle.Entries = data.ReadByteValue();
|
||||
if (bundle.Entries == 0)
|
||||
return bundle;
|
||||
|
||||
bundle.BundleType = (BundleType)data.ReadByteValue();
|
||||
bundle.TableEntries = new EntryTableEntry[bundle.Entries];
|
||||
for (int i = 0; i < bundle.Entries; i++)
|
||||
{
|
||||
var entry = new EntryTableEntry();
|
||||
|
||||
switch (bundle.BundleType & ~BundleType.ParameterTypingInformationPresent)
|
||||
{
|
||||
case BundleType.UnusedEntry:
|
||||
// Empty entry with no information
|
||||
break;
|
||||
|
||||
case BundleType.SixteenBitEntry:
|
||||
entry.SixteenBitObjectNumber = data.ReadUInt16();
|
||||
entry.SixteenBitEntryFlags = (EntryFlags)data.ReadByteValue();
|
||||
entry.SixteenBitOffset = data.ReadUInt16();
|
||||
break;
|
||||
|
||||
case BundleType.TwoEightySixCallGateEntry:
|
||||
entry.TwoEightySixObjectNumber = data.ReadUInt16();
|
||||
entry.TwoEightySixEntryFlags = (EntryFlags)data.ReadByteValue();
|
||||
entry.TwoEightySixOffset = data.ReadUInt16();
|
||||
entry.TwoEightySixCallgate = data.ReadUInt16();
|
||||
break;
|
||||
|
||||
case BundleType.ThirtyTwoBitEntry:
|
||||
entry.ThirtyTwoBitObjectNumber = data.ReadUInt16();
|
||||
entry.ThirtyTwoBitEntryFlags = (EntryFlags)data.ReadByteValue();
|
||||
entry.ThirtyTwoBitOffset = data.ReadUInt32();
|
||||
break;
|
||||
|
||||
case BundleType.ForwarderEntry:
|
||||
entry.ForwarderReserved = data.ReadUInt16();
|
||||
entry.ForwarderFlags = (ForwarderFlags)data.ReadByteValue();
|
||||
entry.ForwarderModuleOrdinalNumber = data.ReadUInt16();
|
||||
entry.ProcedureNameOffset = data.ReadUInt32();
|
||||
entry.ImportOrdinalNumber = data.ReadUInt32();
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
bundle.TableEntries[i] = entry;
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a module format directives table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled module format directives table entry on success, null on error</returns>
|
||||
private static ModuleFormatDirectivesTableEntry ParseModuleFormatDirectivesTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ModuleFormatDirectivesTableEntry();
|
||||
|
||||
entry.DirectiveNumber = (DirectiveNumber)data.ReadUInt16();
|
||||
entry.DirectiveDataLength = data.ReadUInt16();
|
||||
entry.DirectiveDataOffset = data.ReadUInt32();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a verify record directive table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled verify record directive table entry on success, null on error</returns>
|
||||
private static VerifyRecordDirectiveTableEntry ParseVerifyRecordDirectiveTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new VerifyRecordDirectiveTableEntry();
|
||||
|
||||
entry.EntryCount = data.ReadUInt16();
|
||||
entry.OrdinalIndex = data.ReadUInt16();
|
||||
entry.Version = data.ReadUInt16();
|
||||
entry.ObjectEntriesCount = data.ReadUInt16();
|
||||
entry.ObjectNumberInModule = data.ReadUInt16();
|
||||
entry.ObjectLoadBaseAddress = data.ReadUInt16();
|
||||
entry.ObjectVirtualAddressSize = data.ReadUInt16();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a fix-up page table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled fix-up page table entry on success, null on error</returns>
|
||||
private static FixupPageTableEntry ParseFixupPageTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new FixupPageTableEntry();
|
||||
|
||||
entry.Offset = data.ReadUInt32();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a fix-up record table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled fix-up record table entry on success, null on error</returns>
|
||||
private static FixupRecordTableEntry ParseFixupRecordTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new FixupRecordTableEntry();
|
||||
|
||||
entry.SourceType = (FixupRecordSourceType)data.ReadByteValue();
|
||||
entry.TargetFlags = (FixupRecordTargetFlags)data.ReadByteValue();
|
||||
|
||||
// Source list flag
|
||||
if (entry.SourceType.HasFlag(FixupRecordSourceType.SourceListFlag))
|
||||
entry.SourceOffsetListCount = data.ReadByteValue();
|
||||
else
|
||||
entry.SourceOffset = data.ReadUInt16();
|
||||
|
||||
switch (entry.TargetFlags & FixupRecordTargetFlags.FixupTargetTypeMask)
|
||||
{
|
||||
// OBJECT / TRGOFF
|
||||
case FixupRecordTargetFlags.InternalReference:
|
||||
|
||||
// 16-bit Object Number/Module Ordinal Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
|
||||
entry.TargetObjectNumberWORD = data.ReadUInt16();
|
||||
else
|
||||
entry.TargetObjectNumberByte = data.ReadByteValue();
|
||||
|
||||
// 16-bit Selector fixup
|
||||
if (!entry.SourceType.HasFlag(FixupRecordSourceType.SixteenBitSelectorFixup))
|
||||
{
|
||||
// 32-bit Target Offset Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
|
||||
entry.TargetOffsetDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.TargetOffsetWORD = data.ReadUInt16();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// MOD ORD# / IMPORT ORD / ADDITIVE
|
||||
case FixupRecordTargetFlags.ImportedReferenceByOrdinal:
|
||||
|
||||
// 16-bit Object Number/Module Ordinal Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
|
||||
entry.OrdinalIndexImportModuleNameTableWORD = data.ReadUInt16();
|
||||
else
|
||||
entry.OrdinalIndexImportModuleNameTableByte = data.ReadByteValue();
|
||||
|
||||
// 8-bit Ordinal Flag & 32-bit Target Offset Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.EightBitOrdinalFlag))
|
||||
entry.ImportedOrdinalNumberByte = data.ReadByteValue();
|
||||
else if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
|
||||
entry.ImportedOrdinalNumberDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.ImportedOrdinalNumberWORD = data.ReadUInt16();
|
||||
|
||||
// Additive Fixup Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
|
||||
{
|
||||
// 32-bit Additive Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
|
||||
entry.AdditiveFixupValueDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.AdditiveFixupValueWORD = data.ReadUInt16();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// MOD ORD# / PROCEDURE NAME OFFSET / ADDITIVE
|
||||
case FixupRecordTargetFlags.ImportedReferenceByName:
|
||||
|
||||
// 16-bit Object Number/Module Ordinal Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
|
||||
entry.OrdinalIndexImportModuleNameTableWORD = data.ReadUInt16();
|
||||
else
|
||||
entry.OrdinalIndexImportModuleNameTableByte = data.ReadByteValue();
|
||||
|
||||
// 32-bit Target Offset Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
|
||||
entry.OffsetImportProcedureNameTableDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.OffsetImportProcedureNameTableWORD = data.ReadUInt16();
|
||||
|
||||
// Additive Fixup Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
|
||||
{
|
||||
// 32-bit Additive Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
|
||||
entry.AdditiveFixupValueDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.AdditiveFixupValueWORD = data.ReadUInt16();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// ORD # / ADDITIVE
|
||||
case FixupRecordTargetFlags.InternalReferenceViaEntryTable:
|
||||
|
||||
// 16-bit Object Number/Module Ordinal Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
|
||||
entry.OrdinalIndexImportModuleNameTableWORD = data.ReadUInt16();
|
||||
else
|
||||
entry.OrdinalIndexImportModuleNameTableByte = data.ReadByteValue();
|
||||
|
||||
// Additive Fixup Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
|
||||
{
|
||||
// 32-bit Additive Flag
|
||||
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
|
||||
entry.AdditiveFixupValueDWORD = data.ReadUInt32();
|
||||
else
|
||||
entry.AdditiveFixupValueWORD = data.ReadUInt16();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#region SCROFFn
|
||||
|
||||
if (entry.SourceType.HasFlag(FixupRecordSourceType.SourceListFlag))
|
||||
{
|
||||
entry.SourceOffsetList = new ushort[entry.SourceOffsetListCount];
|
||||
for (int i = 0; i < entry.SourceOffsetList.Length; i++)
|
||||
{
|
||||
entry.SourceOffsetList[i] = data.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a import module name table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled import module name table entry on success, null on error</returns>
|
||||
private static ImportModuleNameTableEntry ParseImportModuleNameTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ImportModuleNameTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
{
|
||||
byte[] name = data.ReadBytes(entry.Length);
|
||||
entry.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a import module name table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled import module name table entry on success, null on error</returns>
|
||||
private static ImportModuleProcedureNameTableEntry ParseImportModuleProcedureNameTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new ImportModuleProcedureNameTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
{
|
||||
byte[] name = data.ReadBytes(entry.Length);
|
||||
entry.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a per-page checksum table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled per-page checksum table entry on success, null on error</returns>
|
||||
private static PerPageChecksumTableEntry ParsePerPageChecksumTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new PerPageChecksumTableEntry();
|
||||
|
||||
entry.Checksum = data.ReadUInt32();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a non-resident names table entry
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled non-resident names table entry on success, null on error</returns>
|
||||
private static NonResidentNamesTableEntry ParseNonResidentNameTableEntry(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entry = new NonResidentNamesTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
{
|
||||
byte[] name = data.ReadBytes(entry.Length);
|
||||
entry.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
|
||||
}
|
||||
entry.OrdinalNumber = data.ReadUInt16();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a debug information
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="size">Total size of the debug information</param>
|
||||
/// <returns>Filled debug information on success, null on error</returns>
|
||||
private static DebugInformation ParseDebugInformation(Stream data, long size)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var debugInformation = new DebugInformation();
|
||||
|
||||
byte[] signature = data.ReadBytes(3);
|
||||
debugInformation.Signature = Encoding.ASCII.GetString(signature);
|
||||
if (debugInformation.Signature != DebugInformationSignatureString)
|
||||
return null;
|
||||
|
||||
debugInformation.FormatType = (DebugFormatType)data.ReadByteValue();
|
||||
debugInformation.DebuggerData = data.ReadBytes((int)(size - 4));
|
||||
|
||||
return debugInformation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -27,10 +27,12 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// </summary>
|
||||
public DebugFormatType FormatType;
|
||||
|
||||
// DEBUGGER DATA = Debugger specific data.
|
||||
// The format of the debugger data is defined by the debugger that is being used.
|
||||
// The values defined for the type field are not enforced by the system. It is
|
||||
// the responsibility of the linker or debugging tools to follow the convention
|
||||
// for the type field that is defined here.
|
||||
/// <summary>
|
||||
/// The format of the debugger data is defined by the debugger that is being used.
|
||||
/// The values defined for the type field are not enforced by the system. It is
|
||||
/// the responsibility of the linker or debugging tools to follow the convention
|
||||
/// for the type field that is defined here.
|
||||
/// </summary>
|
||||
public byte[] DebuggerData;
|
||||
}
|
||||
}
|
||||
|
||||
59
BurnOutSharp.Models/LinearExecutable/EntryTableBundle.cs
Normal file
59
BurnOutSharp.Models/LinearExecutable/EntryTableBundle.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry table contains object and offset information that is used to resolve
|
||||
/// fixup references to the entry points within this module. Not all entry points
|
||||
/// in the entry table will be exported, some entry points will only be used
|
||||
/// within the module. An ordinal number is used to index into the entry table.
|
||||
/// The entry table entries are numbered starting from one.
|
||||
///
|
||||
/// The list of entries are compressed into 'bundles', where possible. The entries
|
||||
/// within each bundle are all the same size. A bundle starts with a count field
|
||||
/// which indicates the number of entries in the bundle. The count is followed by
|
||||
/// a type field which identifies the bundle format. This provides both a means
|
||||
/// for saving space as well as a mechanism for extending the bundle types.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class EntryTableBundle
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of entries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the number of entries in this bundle.
|
||||
///
|
||||
/// A zero value for the number of entries identifies the end of the
|
||||
/// entry table. There is no further bundle information when the number
|
||||
/// of entries is zero. In other words the entry table is terminated by
|
||||
/// a single zero byte.
|
||||
///
|
||||
/// For <see cref="BundleType.UnusedEntry"/>, this is the number of unused
|
||||
/// entries to skip.
|
||||
/// For <see cref="BundleType.SixteenBitEntry"/>, this is the number of 16-bit
|
||||
/// entries in this bundle. The flags and offset value are repeated this
|
||||
/// number of times.
|
||||
/// For <see cref="BundleType.TwoEightySixCallGateEntry"/>, this is the number
|
||||
/// of 286 call gate entries in this bundle. The flags, callgate, and offset
|
||||
/// value are repeated this number of times.
|
||||
/// For <see cref="BundleType.ThirtyTwoBitEntry"/>, this is the number
|
||||
/// of 32-bit entries in this bundle. The flags and offset value are repeated
|
||||
/// this number of times.
|
||||
/// For <see cref="BundleType.ForwarderEntry"/>, this field is reserved for future use.
|
||||
/// </remarks>
|
||||
public byte Entries;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the bundle type which determines the contents of the BUNDLE INFO.
|
||||
/// </summary>
|
||||
public BundleType BundleType;
|
||||
|
||||
/// <summary>
|
||||
/// Table entries in the bundle
|
||||
/// </summary>
|
||||
public EntryTableEntry[] TableEntries;
|
||||
}
|
||||
}
|
||||
@@ -2,55 +2,11 @@
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry table contains object and offset information that is used to resolve
|
||||
/// fixup references to the entry points within this module. Not all entry points
|
||||
/// in the entry table will be exported, some entry points will only be used
|
||||
/// within the module. An ordinal number is used to index into the entry table.
|
||||
/// The entry table entries are numbered starting from one.
|
||||
///
|
||||
/// The list of entries are compressed into 'bundles', where possible. The entries
|
||||
/// within each bundle are all the same size. A bundle starts with a count field
|
||||
/// which indicates the number of entries in the bundle. The count is followed by
|
||||
/// a type field which identifies the bundle format. This provides both a means
|
||||
/// for saving space as well as a mechanism for extending the bundle types.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public sealed class EntryTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of entries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the number of entries in this bundle.
|
||||
///
|
||||
/// A zero value for the number of entries identifies the end of the
|
||||
/// entry table. There is no further bundle information when the number
|
||||
/// of entries is zero. In other words the entry table is terminated by
|
||||
/// a single zero byte.
|
||||
///
|
||||
/// For <see cref="BundleType.UnusedEntry"/>, this is the number of unused
|
||||
/// entries to skip.
|
||||
/// For <see cref="BundleType.SixteenBitEntry"/>, this is the number of 16-bit
|
||||
/// entries in this bundle. The flags and offset value are repeated this
|
||||
/// number of times.
|
||||
/// For <see cref="BundleType.TwoEightySixCallGateEntry"/>, this is the number
|
||||
/// of 286 call gate entries in this bundle. The flags, callgate, and offset
|
||||
/// value are repeated this number of times.
|
||||
/// For <see cref="BundleType.ThirtyTwoBitEntry"/>, this is the number
|
||||
/// of 32-bit entries in this bundle. The flags and offset value are repeated
|
||||
/// this number of times.
|
||||
/// For <see cref="BundleType.ForwarderEntry"/>, this field is reserved for future use.
|
||||
/// </remarks>
|
||||
[FieldOffset(0)] public byte Entries;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the bundle type which determines the contents of the BUNDLE INFO.
|
||||
/// </summary>
|
||||
[FieldOffset(1)] public BundleType BundleType;
|
||||
|
||||
#region 16-bit Entry
|
||||
|
||||
/// <summary>
|
||||
@@ -59,7 +15,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort SixteenBitObjectNumber;
|
||||
[FieldOffset(0)] public ushort SixteenBitObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
@@ -67,7 +23,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags SixteenBitEntryFlags;
|
||||
[FieldOffset(2)] public EntryFlags SixteenBitEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
@@ -75,7 +31,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort SixteenBitOffset;
|
||||
[FieldOffset(3)] public ushort SixteenBitOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -87,7 +43,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort TwoEightySixObjectNumber;
|
||||
[FieldOffset(0)] public ushort TwoEightySixObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
@@ -95,7 +51,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags TwoEightySixEntryFlags;
|
||||
[FieldOffset(2)] public EntryFlags TwoEightySixEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
@@ -103,7 +59,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort TwoEightySixOffset;
|
||||
[FieldOffset(3)] public ushort TwoEightySixOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Callgate selector.
|
||||
@@ -115,7 +71,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// offset is place in the relocation fixup address. The segment number and offset
|
||||
/// in segment is placed in the LDT callgate.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public ushort TwoEightySixCallgate;
|
||||
[FieldOffset(5)] public ushort TwoEightySixCallgate;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -127,7 +83,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort ThirtyTwoBitObjectNumber;
|
||||
[FieldOffset(0)] public ushort ThirtyTwoBitObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
@@ -135,7 +91,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags ThirtyTwoBitEntryFlags;
|
||||
[FieldOffset(2)] public EntryFlags ThirtyTwoBitEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
@@ -143,7 +99,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public uint ThirtyTwoBitOffset;
|
||||
[FieldOffset(3)] public uint ThirtyTwoBitOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -155,7 +111,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This field is reserved for future use.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort ForwarderReserved;
|
||||
[FieldOffset(0)] public ushort ForwarderReserved;
|
||||
|
||||
/// <summary>
|
||||
/// Forwarder flags.
|
||||
@@ -163,7 +119,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public ForwarderFlags ForwarderFlags;
|
||||
[FieldOffset(2)] public ForwarderFlags ForwarderFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Module Ordinal Number
|
||||
@@ -171,7 +127,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <remarks>
|
||||
/// This is the index into the Import Module Name Table for this forwarder.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort ForwarderModuleOrdinalNumber;
|
||||
[FieldOffset(3)] public ushort ForwarderModuleOrdinalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Procedure Name Offset
|
||||
@@ -199,7 +155,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// single libraries, one could provide entry points for the three libraries
|
||||
/// that are forwarders pointing to the common implementation.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public uint ProcedureNameOffset;
|
||||
[FieldOffset(5)] public uint ProcedureNameOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Import Ordinal Number
|
||||
@@ -227,8 +183,8 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// single libraries, one could provide entry points for the three libraries
|
||||
/// that are forwarders pointing to the common implementation.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public uint ImportOrdinalNumber;
|
||||
[FieldOffset(5)] public uint ImportOrdinalNumber;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,11 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
public ObjectTableEntry[] ObjectTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Object page table
|
||||
/// Object page map
|
||||
/// </summary>
|
||||
public ObjectPageTableEntry[] ObjectPageTable { get; set; }
|
||||
public ObjectPageMapEntry[] ObjectPageMap { get; set; }
|
||||
|
||||
// TODO: Object iterate data map table [Does this exist?]
|
||||
// TODO: Object iterate data map table (Undefined)
|
||||
|
||||
/// <summary>
|
||||
/// Resource table
|
||||
@@ -40,12 +40,12 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <summary>
|
||||
/// Resident Name table
|
||||
/// </summary>
|
||||
public ResidentNameTableEntry[] ResidentNameTable { get; set; }
|
||||
public ResidentNamesTableEntry[] ResidentNamesTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry table
|
||||
/// </summary>
|
||||
public EntryTableEntry[] EntryTable { get; set; }
|
||||
public EntryTableBundle[] EntryTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Module format directives table (optional)
|
||||
@@ -57,11 +57,6 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// </summary>
|
||||
public VerifyRecordDirectiveTableEntry[] VerifyRecordDirectiveTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Per-Page checksum table
|
||||
/// </summary>
|
||||
public PerPageChecksumTableEntry[] PerPageChecksumTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fix-up page table
|
||||
/// </summary>
|
||||
@@ -82,14 +77,15 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// </summary>
|
||||
public ImportModuleProcedureNameTableEntry[] ImportModuleProcedureNameTable { get; set; }
|
||||
|
||||
// TODO: Preload Pages
|
||||
// TODO: Demand Load Pages
|
||||
// TODO: Iterated Pages
|
||||
/// <summary>
|
||||
/// Per-Page checksum table
|
||||
/// </summary>
|
||||
public PerPageChecksumTableEntry[] PerPageChecksumTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Non-Resident Name table
|
||||
/// </summary>
|
||||
public NonResidentNameTableEntry[] NonResidentNameTable { get; set; }
|
||||
public NonResidentNamesTableEntry[] NonResidentNamesTable { get; set; }
|
||||
|
||||
// TODO: Non-resident directives data (Undefined)
|
||||
|
||||
|
||||
@@ -36,6 +36,6 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// This is a variable length string with it's length defined in bytes by
|
||||
/// the LEN field. The string is case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
public string Name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,6 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// This is a variable length string with it's length defined in bytes by
|
||||
/// the LEN field. The string is case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
public string Name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class NonResidentNameTableEntry
|
||||
public sealed class NonResidentNamesTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
@@ -51,7 +51,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// This is a variable length string with it's length defined in bytes by the LEN field.
|
||||
/// The string is case case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number.
|
||||
@@ -16,7 +16,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class ObjectPageTableEntry
|
||||
public sealed class ObjectPageMapEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset to the page data in the EXE file.
|
||||
@@ -11,12 +11,12 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// information in the entry table.
|
||||
///
|
||||
/// The resident name table is kept resident in system memory while the module is
|
||||
/// loaded.It is intended to contain the exported entry point names that are
|
||||
/// frequently dynamically linked to by name.Non-resident names are not kept in
|
||||
/// loaded. It is intended to contain the exported entry point names that are
|
||||
/// frequently dynamically linked to by name. Non-resident names are not kept in
|
||||
/// memory and are read from the EXE file when a dynamic link reference is made.
|
||||
/// Exported entry point names that are infrequently dynamically linked to by name
|
||||
/// or are commonly referenced by ordinal number should be placed in the
|
||||
/// non-resident name table.The trade off made for references by name is performance
|
||||
/// non-resident name table. The trade off made for references by name is performance
|
||||
/// vs memory usage.
|
||||
///
|
||||
/// Import references by name require these tables to be searched to obtain the entry
|
||||
@@ -28,7 +28,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public sealed class ResidentNameTableEntry
|
||||
public sealed class ResidentNamesTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
@@ -51,7 +51,7 @@ namespace BurnOutSharp.Models.LinearExecutable
|
||||
/// This is a variable length string with it's length defined in bytes by the LEN field.
|
||||
/// The string is case case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number.
|
||||
@@ -223,7 +223,7 @@ namespace BurnOutSharp.Wrappers
|
||||
public Models.LinearExecutable.ObjectTableEntry[] ObjectTable => _executable.ObjectTable;
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.ObjectTable"/>
|
||||
public Models.LinearExecutable.ObjectPageTableEntry[] ObjectPageTable => _executable.ObjectPageTable;
|
||||
public Models.LinearExecutable.ObjectPageMapEntry[] ObjectPageTable => _executable.ObjectPageMap;
|
||||
|
||||
// TODO: Object iterate data map table [Does this exist?]
|
||||
|
||||
@@ -231,10 +231,10 @@ namespace BurnOutSharp.Wrappers
|
||||
public Models.LinearExecutable.ResourceTableEntry[] ResourceTable => _executable.ResourceTable;
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.ResidentNameTable"/>
|
||||
public Models.LinearExecutable.ResidentNameTableEntry[] ResidentNameTable => _executable.ResidentNameTable;
|
||||
public Models.LinearExecutable.ResidentNamesTableEntry[] ResidentNameTable => _executable.ResidentNamesTable;
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.EntryTable"/>
|
||||
public Models.LinearExecutable.EntryTableEntry[] EntryTable => _executable.EntryTable;
|
||||
public Models.LinearExecutable.EntryTableBundle[] EntryTable => _executable.EntryTable;
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.ModuleFormatDirectivesTable"/>
|
||||
public Models.LinearExecutable.ModuleFormatDirectivesTableEntry[] ModuleFormatDirectivesTable => _executable.ModuleFormatDirectivesTable;
|
||||
@@ -262,7 +262,7 @@ namespace BurnOutSharp.Wrappers
|
||||
// TODO: Iterated Pages
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.NonResidentNameTable"/>
|
||||
public Models.LinearExecutable.NonResidentNameTableEntry[] NonResidentNameTable => _executable.NonResidentNameTable;
|
||||
public Models.LinearExecutable.NonResidentNamesTableEntry[] NonResidentNameTable => _executable.NonResidentNamesTable;
|
||||
|
||||
/// <inheritdoc cref="Models.LinearExecutable.DebugInformation"/>
|
||||
public Models.LinearExecutable.DebugInformation DebugInformation => _executable.DebugInformation;
|
||||
|
||||
Reference in New Issue
Block a user