diff --git a/src/Workshell.PE.Testbed/Program.cs b/src/Workshell.PE.Testbed/Program.cs index 323bc4a..6949c40 100644 --- a/src/Workshell.PE.Testbed/Program.cs +++ b/src/Workshell.PE.Testbed/Program.cs @@ -20,8 +20,8 @@ static async Task RunAsync(string[] args) var dataDirectory = image.NTHeaders.DataDirectories[DataDirectoryType.DelayImportDescriptor]; var content = await dataDirectory.GetContentAsync().ConfigureAwait(false); - var table = await ImportHintNameTable.LoadAsync(image).ConfigureAwait(false); - var entries = table.ToArray(); + //var table = await ImportHintNameTable.LoadAsync(image).ConfigureAwait(false); + //var entries = table.ToArray(); } } } diff --git a/src/Workshell.PE/Content/Imports/DelayedImportAddressTable.cs b/src/Workshell.PE/Content/Imports/DelayedImportAddressTable.cs deleted file mode 100644 index b5d0997..0000000 --- a/src/Workshell.PE/Content/Imports/DelayedImportAddressTable.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Workshell.PE.Content -{ - public sealed class DelayedImportAddressTable : ImportAddressTableBase - { - internal DelayedImportAddressTable(PortableExecutableImage image, DelayedImportDirectoryEntry directoryEntry, uint tableRVA, ulong[] tableEntries) : base(image, directoryEntry, tableRVA, tableEntries, false) - { - } - } -} diff --git a/src/Workshell.PE/Content/Imports/DelayedImportAddressTableEntry.cs b/src/Workshell.PE/Content/Imports/DelayedImportAddressTableEntry.cs deleted file mode 100644 index d535ac3..0000000 --- a/src/Workshell.PE/Content/Imports/DelayedImportAddressTableEntry.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using Workshell.PE.Extensions; - -namespace Workshell.PE.Content -{ - public sealed class DelayedImportAddressTableEntry : ImportAddressTableEntryBase - { - internal DelayedImportAddressTableEntry(PortableExecutableImage image, ulong offset, ulong value, uint address, ushort ordinal, bool isOrdinal) : base(image, offset, value, address, ordinal, isOrdinal, true) - { - } - } -} diff --git a/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs b/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs deleted file mode 100644 index 86ea83a..0000000 --- a/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Workshell.PE.Content -{ - public sealed class DelayedImportAddressTables : ImportAddressTablesBase - { - internal DelayedImportAddressTables(PortableExecutableImage image, DataDirectory directory, Location location, Tuple[] tables) : base(image, directory, location, tables) - { - } - - #region Static Methods - - public static async Task GetLookupTableAsync(PortableExecutableImage image, DelayedImportDirectory directory = null) - { - if (directory == null) - directory = await DelayedImportDirectory.LoadAsync(image).ConfigureAwait(false); - - var tables = await LoadAsync( - image, - directory, - entry => entry.DelayNameTable - ).ConfigureAwait(false); - - return tables; - } - - public static async Task GetAddressTableAsync(PortableExecutableImage image, DelayedImportDirectory directory = null) - { - if (directory == null) - directory = await DelayedImportDirectory.LoadAsync(image).ConfigureAwait(false); - - var tables = await LoadAsync( - image, - directory, - entry => entry.DelayAddressTable - ).ConfigureAwait(false); - - return tables; - } - - #endregion - } -} diff --git a/src/Workshell.PE/Content/Imports/DelayedImportHintNameEntry.cs b/src/Workshell.PE/Content/Imports/DelayedImportHintNameEntry.cs deleted file mode 100644 index 9e1249c..0000000 --- a/src/Workshell.PE/Content/Imports/DelayedImportHintNameEntry.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Workshell.PE.Content -{ - public sealed class DelayedImportHintNameEntry : ImportHintNameEntryBase - { - internal DelayedImportHintNameEntry(PortableExecutableImage image, ulong offset, uint size, ushort hint, string name, bool isPadded) : base(image, offset, size, hint, name, isPadded, true) - { - } - } -} diff --git a/src/Workshell.PE/Content/Imports/DelayedImportHintNameTable.cs b/src/Workshell.PE/Content/Imports/DelayedImportHintNameTable.cs deleted file mode 100644 index 4fe9220..0000000 --- a/src/Workshell.PE/Content/Imports/DelayedImportHintNameTable.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Workshell.PE.Content -{ - public sealed class DelayedImportHintNameTable : ImportHintNameTableBase - { - internal DelayedImportHintNameTable(PortableExecutableImage image, DataDirectory directory, Location location, IEnumerable> entries) : base(image, directory, location, entries, true) - { - } - - #region Static Methods - - public static async Task LoadAsync(PortableExecutableImage image) - { - var ilt = await DelayedImportAddressTables.GetLookupTableAsync(image).ConfigureAwait(false); - - return await LoadAsync(image, ilt).ConfigureAwait(false); - } - - #endregion - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTable.cs b/src/Workshell.PE/Content/Imports/ImportAddressTable.cs index 2fc0394..7c81bf8 100644 --- a/src/Workshell.PE/Content/Imports/ImportAddressTable.cs +++ b/src/Workshell.PE/Content/Imports/ImportAddressTable.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; using System.Text; -using System.Threading.Tasks; -namespace Workshell.PE.Content +namespace Workshell.PE.Content.Imports { - public sealed class ImportAddressTable : ImportAddressTableBase + public sealed class ImportAddressTable : ImportAddressTableBase { - internal ImportAddressTable(PortableExecutableImage image, ImportDirectoryEntry directoryEntry, uint tableRVA, ulong[] tableEntries) : base(image, directoryEntry, tableRVA, tableEntries, false) + internal ImportAddressTable(PortableExecutableImage image, uint rva, ulong[] entries) : base(image, rva, entries, false) { } } diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTableBase.cs b/src/Workshell.PE/Content/Imports/ImportAddressTableBase.cs index e5a49f4..807d7cf 100644 --- a/src/Workshell.PE/Content/Imports/ImportAddressTableBase.cs +++ b/src/Workshell.PE/Content/Imports/ImportAddressTableBase.cs @@ -10,32 +10,42 @@ namespace Workshell.PE.Content { - public abstract class ImportAddressTableBase : ISupportsLocation, ISupportsBytes, IEnumerable + public abstract class ImportAddressTableBase : IEnumerable, ISupportsLocation, ISupportsBytes where TEntry : ImportAddressTableEntryBase - where TDirectoryEntry : ImportDirectoryEntryBase { private readonly PortableExecutableImage _image; private readonly TEntry[] _entries; - protected internal ImportAddressTableBase(PortableExecutableImage image, TDirectoryEntry directoryEntry, uint rva, ulong[] entries, bool isDelayed) + protected internal ImportAddressTableBase(PortableExecutableImage image, uint rva, ulong[] entries, bool isDelayed) { - _image = image; - _entries = BuildEntries(image, rva, entries); - var calc = image.GetCalculator(); var imageBase = image.NTHeaders.OptionalHeader.ImageBase; var va = imageBase + rva; var offset = calc.RVAToOffset(rva); var size = (entries.Length * (image.Is64Bit ? sizeof(ulong) : sizeof(uint))).ToUInt64(); + var section = calc.RVAToSection(rva); + + _image = image; + _entries = BuildEntries(image, offset, entries); - DirectoryEntry = directoryEntry; - Location = new Location(calc, offset, rva, va, size, size); + Location = new Location(offset, rva, va, size, size, section); Count = _entries.Length; IsDelayed = isDelayed; } #region Methods + public IEnumerator GetEnumerator() + { + foreach (var entry in _entries) + yield return entry; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + public byte[] GetBytes() { return GetBytesAsync().GetAwaiter().GetResult(); @@ -49,28 +59,14 @@ public async Task GetBytesAsync() return buffer; } - public IEnumerator GetEnumerator() - { - foreach (var entry in _entries) - yield return entry; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - private TEntry[] BuildEntries(PortableExecutableImage image, uint rva, ulong[] entries) + private TEntry[] BuildEntries(PortableExecutableImage image, ulong tableOffset, ulong[] entries) { var results = new TEntry[entries.Length]; - var calc = image.GetCalculator(); - var offset = calc.RVAToOffset(rva); - - var entryType = typeof(TEntry); - var ctors = entryType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - var ctor = ctors.First(); // TODO: Should probably match it better somehow + var ctors = typeof(TEntry).GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + var ctor = ctors.First(); + var offset = tableOffset; - for (var i = 0; i < entries.Length; i++) + for(var i = 0; i < entries.Length; i++) { var addrOrOrd = entries[i]; ushort ordinal = 0; @@ -84,7 +80,7 @@ private TEntry[] BuildEntries(PortableExecutableImage image, uint rva, ulong[] e { value &= 0x7fffffff; - ordinal = Convert.ToUInt16(value); + ordinal = value.ToUInt16(); isOrdinal = true; } } @@ -96,7 +92,7 @@ private TEntry[] BuildEntries(PortableExecutableImage image, uint rva, ulong[] e { value &= 0x7fffffffffffffff; - ordinal = Convert.ToUInt16(value); + ordinal = value.ToUInt16(); isOrdinal = true; } } @@ -123,7 +119,6 @@ private TEntry[] BuildEntries(PortableExecutableImage image, uint rva, ulong[] e #region Properties - public TDirectoryEntry DirectoryEntry { get; } public Location Location { get; } public int Count { get; } public TEntry this[int index] => _entries[index]; diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTableEntry.cs b/src/Workshell.PE/Content/Imports/ImportAddressTableEntry.cs index 9be3af1..4ed0cf6 100644 --- a/src/Workshell.PE/Content/Imports/ImportAddressTableEntry.cs +++ b/src/Workshell.PE/Content/Imports/ImportAddressTableEntry.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; using System.Text; -using System.Threading.Tasks; -using Workshell.PE.Extensions; namespace Workshell.PE.Content { public sealed class ImportAddressTableEntry : ImportAddressTableEntryBase { - internal ImportAddressTableEntry(PortableExecutableImage image, ulong offset, ulong value, uint address, ushort ordinal, bool isOrdinal) : base(image, offset, value, address, ordinal, isOrdinal, false) + internal ImportAddressTableEntry(PortableExecutableImage image, ulong entryOffset, ulong entryValue, uint entryAddress, ushort entryOrdinal, bool isOrdinal) : base(image, entryOffset, entryValue, entryAddress, entryOrdinal, isOrdinal, false) { } } diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTableEntryBase.cs b/src/Workshell.PE/Content/Imports/ImportAddressTableEntryBase.cs index e9e0392..fbae04c 100644 --- a/src/Workshell.PE/Content/Imports/ImportAddressTableEntryBase.cs +++ b/src/Workshell.PE/Content/Imports/ImportAddressTableEntryBase.cs @@ -10,20 +10,20 @@ public abstract class ImportAddressTableEntryBase : ISupportsLocation, ISupports { private readonly PortableExecutableImage _image; - protected ImportAddressTableEntryBase(PortableExecutableImage image, ulong offset, ulong value, uint address, ushort ordinal, - bool isOrdinal, bool isDelayed) + protected internal ImportAddressTableEntryBase(PortableExecutableImage image, ulong entryOffset, ulong entryValue, uint entryAddress, ushort entryOrdinal, bool isOrdinal, bool isDelayed) { _image = image; var calc = image.GetCalculator(); - var rva = calc.OffsetToRVA(offset); - var va = image.NTHeaders.OptionalHeader.ImageBase + rva; + var rva = calc.OffsetToRVA(entryOffset); + var imageBase = image.NTHeaders.OptionalHeader.ImageBase; + var va = imageBase + rva; var size = (image.Is64Bit ? sizeof(ulong) : sizeof(uint)).ToUInt64(); - Location = new Location(calc, offset, rva, va, size, size); - Value = value; - Address = address; - Ordinal = ordinal; + Location = new Location(calc, entryOffset, rva, va, size, size); + Value = entryValue; + Address = entryAddress; + Ordinal = entryOrdinal; IsOrdinal = isOrdinal; IsDelayed = isDelayed; } diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTables.cs b/src/Workshell.PE/Content/Imports/ImportAddressTables.cs deleted file mode 100644 index 7786167..0000000 --- a/src/Workshell.PE/Content/Imports/ImportAddressTables.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Workshell.PE.Content -{ - public sealed class ImportAddressTables : ImportAddressTablesBase - { - internal ImportAddressTables(PortableExecutableImage image, DataDirectory directory, Location location, Tuple[] tables) : base(image, directory, location, tables) - { - } - - #region Static Methods - - public static async Task GetLookupTableAsync(PortableExecutableImage image, ImportDirectory directory = null) - { - if (directory == null) - directory = await ImportDirectory.LoadAsync(image).ConfigureAwait(false); - - var tables = await LoadAsync( - image, - directory, - entry => entry.OriginalFirstThunk - ).ConfigureAwait(false); - - return tables; - } - - public static async Task GetAddressTableAsync(PortableExecutableImage image, ImportDirectory directory = null) - { - if (directory == null) - directory = await ImportDirectory.LoadAsync(image).ConfigureAwait(false); - - var tables = await LoadAsync( - image, - directory, - entry => entry.FirstThunk - ).ConfigureAwait(false); - - return tables; - } - - #endregion - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTablesBase.cs b/src/Workshell.PE/Content/Imports/ImportAddressTablesBase.cs deleted file mode 100644 index edc4ffe..0000000 --- a/src/Workshell.PE/Content/Imports/ImportAddressTablesBase.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Workshell.PE.Extensions; - -namespace Workshell.PE.Content -{ - public abstract class ImportAddressTablesBase : DataContent, IEnumerable - where TTable : ImportAddressTableBase - where TEntry : ImportAddressTableEntryBase - where TDirectoryEntry : ImportDirectoryEntryBase - { - private readonly TTable[] _tables; - - protected internal ImportAddressTablesBase(PortableExecutableImage image, DataDirectory directory, Location location, Tuple[] tables) : base(image, directory, location) - { - _tables = new TTable[tables.Length]; - - var tableType = typeof(TTable); - var ctors = tableType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - var ctor = ctors.First(); // TODO: Should probably match it better somehow - - for (var i = 0; i < tables.Length; i++) - _tables[i] = (TTable)ctor.Invoke(new object[] {image, tables[i].Item2, tables[i].Item1, tables[i].Item3}); - - Count = _tables.Length; - } - - #region Static Methods - - internal static async Task LoadAsync(PortableExecutableImage image, ImportDirectoryBase directory, Func thunkRVA) - where TStaticTable : ImportAddressTableBase - where TStaticEntry : ImportAddressTableEntryBase - where TStaticDirectoryEntry : ImportDirectoryEntryBase - where TTables : ImportAddressTablesBase - { - if (directory == null) - return null; - - var calc = image.GetCalculator(); - var stream = image.GetStream(); - var tuples = new List>(); - - foreach (var directoryEntry in directory) - { - var thunk = thunkRVA(directoryEntry); - - if (thunk == 0) - continue; - - var entries = new List(); - var offset = calc.RVAToOffset(thunk); - - stream.Seek(offset.ToInt64(), SeekOrigin.Begin); - - while (true) - { - ulong entry; - - if (!image.Is64Bit) - { - entry = await stream.ReadUInt32Async().ConfigureAwait(false); - } - else - { - entry = await stream.ReadUInt64Async().ConfigureAwait(false); - } - - entries.Add(entry); - - if (entry == 0) - break; - } - - var table = new Tuple(thunk, directoryEntry, entries.ToArray()); - - tuples.Add(table); - } - - var rva = 0u; - - if (tuples.Count > 0) - rva = tuples.MinBy(table => table.Item1).Item1; - - var imageBase = image.NTHeaders.OptionalHeader.ImageBase; - var va = imageBase + rva; - var fileOffset = calc.RVAToOffset(rva); - ulong fileSize = 0; - - foreach (var table in tuples) - { - var size = (table.Item3.Length * (!image.Is64Bit ? sizeof(uint) : sizeof(ulong))).ToUInt32(); - - fileSize += size; - } - - var section = calc.RVAToSection(rva); - var location = new Location(fileOffset, rva, va, fileSize, fileSize, section); - var tableType = typeof(TTables); - var ctors = tableType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - var ctor = ctors.First(); // TODO: Should probably match it better somehow - var result = (TTables)ctor.Invoke(new object[] {image, directory.Directory, location, tuples.ToArray()}); - - return result; - } - - #endregion - - #region Methods - - public IEnumerator GetEnumerator() - { - foreach (var table in _tables) - yield return table; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - #endregion - - #region Properties - - public int Count { get; } - public TTable this[int index] => _tables[index]; - - #endregion - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportHintNameEntry.cs b/src/Workshell.PE/Content/Imports/ImportHintNameEntry.cs deleted file mode 100644 index ccabe66..0000000 --- a/src/Workshell.PE/Content/Imports/ImportHintNameEntry.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Workshell.PE.Content -{ - public sealed class ImportHintNameEntry : ImportHintNameEntryBase - { - internal ImportHintNameEntry(PortableExecutableImage image, ulong offset, uint size, ushort hint, string name, bool isPadded) : base(image, offset, size, hint, name, isPadded, false) - { - } - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportHintNameEntryBase.cs b/src/Workshell.PE/Content/Imports/ImportHintNameEntryBase.cs deleted file mode 100644 index 72504d0..0000000 --- a/src/Workshell.PE/Content/Imports/ImportHintNameEntryBase.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading.Tasks; - -using Workshell.PE.Extensions; - -namespace Workshell.PE.Content -{ - public abstract class ImportHintNameEntryBase : ISupportsLocation, ISupportsBytes - { - private readonly PortableExecutableImage _image; - - protected internal ImportHintNameEntryBase(PortableExecutableImage image, ulong offset, uint size, ushort hint, string name, bool isPadded, bool isDelayed) - { - _image = image; - - var calc = image.GetCalculator(); - var rva = calc.OffsetToRVA(offset); - var va = calc.OffsetToVA(offset); - - Location = new Location(calc, offset, rva, va, size, size); - Hint = hint; - Name = name; - IsPadded = isPadded; - IsDelayed = isDelayed; - } - - #region Methods - - public override string ToString() - { - return $"0x{Hint:X4} {Name}"; - } - - public byte[] GetBytes() - { - return GetBytesAsync().GetAwaiter().GetResult(); - } - - public async Task GetBytesAsync() - { - var stream = _image.GetStream(); - var buffer = await stream.ReadBytesAsync(Location).ConfigureAwait(false); - - return buffer; - } - - #endregion - - #region Properties - - public Location Location { get; } - public ushort Hint { get; } - public string Name { get; } - public bool IsPadded { get; } - public bool IsDelayed { get; } - - #endregion - - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportHintNameTable.cs b/src/Workshell.PE/Content/Imports/ImportHintNameTable.cs deleted file mode 100644 index ebe779c..0000000 --- a/src/Workshell.PE/Content/Imports/ImportHintNameTable.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - -namespace Workshell.PE.Content -{ - public sealed class ImportHintNameTable : ImportHintNameTableBase - { - internal ImportHintNameTable(PortableExecutableImage image, DataDirectory directory, Location location, IEnumerable> entries) : base(image, directory, location, entries, false) - { - } - - #region Static Methods - - public static async Task LoadAsync(PortableExecutableImage image) - { - var ilt = await ImportAddressTables.GetLookupTableAsync(image).ConfigureAwait(false); - - return await LoadAsync(image, ilt).ConfigureAwait(false); - } - - #endregion - } -} diff --git a/src/Workshell.PE/Content/Imports/ImportHintNameTableBase.cs b/src/Workshell.PE/Content/Imports/ImportHintNameTableBase.cs deleted file mode 100644 index 58a0d5f..0000000 --- a/src/Workshell.PE/Content/Imports/ImportHintNameTableBase.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -using Workshell.PE.Extensions; - -namespace Workshell.PE.Content -{ - public abstract class ImportHintNameTableBase : DataContent, IEnumerable - where TEntry : ImportHintNameEntryBase - { - private readonly TEntry[] _entries; - - protected internal ImportHintNameTableBase(PortableExecutableImage image, DataDirectory directory, Location location, IEnumerable> entries, bool isDelayed) : base(image, directory, location) - { - _entries = BuildEntries(image, entries); - - Count = _entries.Length; - IsDelayed = isDelayed; - } - - #region Static Methods - - internal static async Task LoadAsync(PortableExecutableImage image, TAddressTable tables) - where TStaticTable : ImportHintNameTableBase - where TStaticEntry : ImportHintNameEntryBase - where TAddressTable : ImportAddressTablesBase, ImportAddressTableEntryBase, ImportDirectoryEntryBase> - { - var entries = new Dictionary>(); - //var ilt = await ImportAddressTables.GetLookupTableAsync(image).ConfigureAwait(false); - var calc = image.GetCalculator(); - var stream = image.GetStream(); - - foreach (var table in tables) - { - foreach (var entry in table) - { - if (entry.Address == 0) - continue; - - if (entries.ContainsKey(entry.Address)) - continue; - - if (!entry.IsOrdinal) - { - var offset = calc.RVAToOffset(entry.Address); - var size = 0u; - var isPadded = false; - ushort hint = 0; - var name = new StringBuilder(256); - - stream.Seek(offset.ToInt64(), SeekOrigin.Begin); - - hint = await stream.ReadUInt16Async().ConfigureAwait(false); - size += sizeof(ushort); - - while (true) - { - var b = await stream.ReadByteAsync(); - - size++; - - if (b <= 0) - break; - - name.Append((char) b); - } - - if ((size % 2) != 0) - { - isPadded = true; - size++; - } - - var tuple = new Tuple(offset, size, hint, name.ToString(), isPadded); - - entries.Add(entry.Address, tuple); - } - } - } - - Location location; - - if (entries.Count > 0) - { - var firstEntry = entries.Values.MinBy(tuple => tuple.Item1); - var lastEntry = entries.Values.MaxBy(tuple => tuple.Item1); - var tableOffset = firstEntry.Item1; - var tableSize = ((lastEntry.Item1 + lastEntry.Item2) - tableOffset).ToUInt32(); - var rva = calc.OffsetToRVA(tableOffset); - var imageBase = image.NTHeaders.OptionalHeader.ImageBase; - var va = imageBase + rva; - - location = new Location(calc, tableOffset, rva, va, tableSize, tableSize); - } - else - { - location = new Location(0, 0, 0, 0, 0, null); - } - - var dataDirectory = tables.Directory; - var tableType = typeof(TStaticTable); - var ctors = tableType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - var ctor = ctors.First(); // TODO: Should probably match it better somehow - var result = (TStaticTable)ctor.Invoke(new object[] { image, dataDirectory, location, entries.Values }); - - return result; - } - - #endregion - - #region Methods - - public override string ToString() - { - return $"File Offset: 0x{Location.FileOffset:X8}, Name Count: {_entries.Length}"; - } - - public IEnumerator GetEnumerator() - { - foreach (var entry in _entries) - yield return entry; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - private TEntry[] BuildEntries(PortableExecutableImage image, IEnumerable> entries) - { - var results = new List(); - var entryType = typeof(TEntry); - var ctors = entryType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - var ctor = ctors.First(); // TODO: Should probably match it better somehow - - foreach (var tuple in entries) - { - var entry = (TEntry)ctor.Invoke(new object[] { image, tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5 }); - - results.Add(entry); - } - - return results.OrderBy(entry => entry.Location.FileOffset).ToArray(); - } - - #endregion - - #region Properties - - public int Count { get; } - public TEntry this[int index] => _entries[index]; - public bool IsDelayed { get; } - - #endregion - } -}