From bbc65391a17ff761dede4762f132b958333acdfe Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 8 Nov 2022 10:09:23 -0800 Subject: [PATCH] Add NE entry table to builder --- BurnOutSharp.Builder/NewExecutable.cs | 128 +++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 5 deletions(-) diff --git a/BurnOutSharp.Builder/NewExecutable.cs b/BurnOutSharp.Builder/NewExecutable.cs index 158a12bd..b3f5d113 100644 --- a/BurnOutSharp.Builder/NewExecutable.cs +++ b/BurnOutSharp.Builder/NewExecutable.cs @@ -143,7 +143,7 @@ namespace BurnOutSharp.Builder // Try to parse the imported-name table var importedNameTable = ParseImportedNameTable(data, tableAddress, executableHeader.EntryTableOffset); - if (moduleReferenceTable == null) + if (importedNameTable == null) return null; // Set the imported-name table @@ -151,6 +151,25 @@ namespace BurnOutSharp.Builder #endregion + #region Entry Table + + // If the offset for the entry table doesn't exist + tableAddress = initialOffset + + (int)stub.Header.NewExeHeaderAddr + + executableHeader.EntryTableOffset; + if (tableAddress >= data.Length) + return executable; + + // Try to parse the entry table + var entryTable = ParseEntryTable(data, tableAddress, (ushort)(executableHeader.EntryTableOffset + executableHeader.EntryTableSize)); + if (entryTable == null) + return null; + + // Set the entry table + executable.EntryTable = entryTable; + + #endregion + // TODO: Complete NE parsing return executable; } @@ -365,6 +384,46 @@ namespace BurnOutSharp.Builder return importedNameTable; } + /// + /// Parse a byte array into an entry table + /// + /// Byte array to parse + /// Offset into the byte array + /// First address not part of the entry table + /// Filled entry table on success, null on error + private static EntryTableBundle[] ParseEntryTable(byte[] data, int offset, ushort endOffset) + { + // TODO: Use marshalling here instead of building + var entryTable = new List(); + + while (offset < endOffset) + { + var entry = new EntryTableBundle(); + entry.EntryCount = data.ReadByte(ref offset); + entry.SegmentIndicator = data.ReadByte(ref offset); + switch (entry.GetEntryType()) + { + case SegmentEntryType.Unused: + break; + + case SegmentEntryType.FixedSegment: + entry.FixedFlagWord = (FixedSegmentEntryFlag)data.ReadByte(ref offset); + entry.FixedOffset = data.ReadUInt16(ref offset); + break; + + case SegmentEntryType.MoveableSegment: + entry.MoveableFlagWord = (MoveableSegmentEntryFlag)data.ReadByte(ref offset); + entry.MoveableReserved = data.ReadUInt16(ref offset); + entry.MoveableSegmentNumber = data.ReadByte(ref offset); + entry.MoveableOffset = data.ReadUInt16(ref offset); + break; + } + entryTable.Add(entry); + } + + return entryTable.ToArray(); + } + #endregion #region Stream Data @@ -499,7 +558,7 @@ namespace BurnOutSharp.Builder // If the offset for the imported-name table doesn't exist tableAddress = initialOffset + (int)stub.Header.NewExeHeaderAddr - + executableHeader.ResidentNameTableOffset; + + executableHeader.ImportedNamesTableOffset; if (tableAddress >= data.Length) return executable; @@ -514,6 +573,26 @@ namespace BurnOutSharp.Builder #endregion + #region Entry Table + + // If the offset for the imported-name table doesn't exist + tableAddress = initialOffset + + (int)stub.Header.NewExeHeaderAddr + + executableHeader.EntryTableOffset; + if (tableAddress >= data.Length) + return executable; + + // Try to parse the imported-name table + data.Seek(tableAddress, SeekOrigin.Begin); + var entryTable = ParseEntryTable(data, (ushort)(executableHeader.EntryTableOffset + executableHeader.EntryTableSize)); + if (entryTable == null) + return null; + + // Set the entry table + executable.EntryTable = entryTable; + + #endregion + // TODO: Complete NE parsing return executable; } @@ -657,7 +736,7 @@ namespace BurnOutSharp.Builder } /// - /// Parse a byte array into a resident-name table + /// Parse a Stream into a resident-name table /// /// Stream to parse /// First address not part of the resident-name table @@ -680,7 +759,7 @@ namespace BurnOutSharp.Builder } /// - /// Parse a byte array into a module-reference table + /// Parse a Stream into a module-reference table /// /// Stream to parse /// Number of module-reference table entries to read @@ -701,7 +780,7 @@ namespace BurnOutSharp.Builder } /// - /// Parse a byte array into an imported-name table + /// Parse a Stream into an imported-name table /// /// Stream to parse /// First address not part of the imported-name table @@ -723,6 +802,45 @@ namespace BurnOutSharp.Builder return importedNameTable; } + /// + /// Parse a Stream into an entry table + /// + /// Stream to parse + /// First address not part of the entry table + /// Filled entry table on success, null on error + private static EntryTableBundle[] ParseEntryTable(Stream data, ushort endOffset) + { + // TODO: Use marshalling here instead of building + var entryTable = new List(); + + while (data.Position < endOffset) + { + var entry = new EntryTableBundle(); + entry.EntryCount = data.ReadByteValue(); + entry.SegmentIndicator = data.ReadByteValue(); + switch (entry.GetEntryType()) + { + case SegmentEntryType.Unused: + break; + + case SegmentEntryType.FixedSegment: + entry.FixedFlagWord = (FixedSegmentEntryFlag)data.ReadByteValue(); + entry.FixedOffset = data.ReadUInt16(); + break; + + case SegmentEntryType.MoveableSegment: + entry.MoveableFlagWord = (MoveableSegmentEntryFlag)data.ReadByteValue(); + entry.MoveableReserved = data.ReadUInt16(); + entry.MoveableSegmentNumber = data.ReadByteValue(); + entry.MoveableOffset = data.ReadUInt16(); + break; + } + entryTable.Add(entry); + } + + return entryTable.ToArray(); + } + #endregion } } \ No newline at end of file