using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using AsmResolver.Collections; using AsmResolver.IO; using AsmResolver.PE.Builder; using AsmResolver.PE.Code; using AsmResolver.PE.Debug; using AsmResolver.PE.Debug.Builder; using AsmResolver.PE.Debug.CodeView; using AsmResolver.PE.DotNet; using AsmResolver.PE.DotNet.Cil; using AsmResolver.PE.DotNet.Metadata; using AsmResolver.PE.DotNet.Metadata.Blob; using AsmResolver.PE.DotNet.Metadata.Guid; using AsmResolver.PE.DotNet.Metadata.Pdb; using AsmResolver.PE.DotNet.Metadata.Strings; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.Metadata.Tables.Rows; using AsmResolver.PE.DotNet.Metadata.UserStrings; using AsmResolver.PE.DotNet.Resources; using AsmResolver.PE.DotNet.VTableFixups; using AsmResolver.PE.Exceptions; using AsmResolver.PE.Exceptions.X64; using AsmResolver.PE.Exports; using AsmResolver.PE.Exports.Builder; using AsmResolver.PE.File; using AsmResolver.PE.File.Headers; using AsmResolver.PE.Imports; using AsmResolver.PE.Imports.Builder; using AsmResolver.PE.Platforms; using AsmResolver.PE.Relocations; using AsmResolver.PE.Relocations.Builder; using AsmResolver.PE.Tls; using AsmResolver.PE.Win32Resources; using AsmResolver.PE.Win32Resources.Builder; using AsmResolver.Patching; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: AssemblyCompany("AsmResolver.PE")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Washi 2016-2022")] [assembly: AssemblyDescription("PE image models for the AsmResolver executable file inspection toolsuite.")] [assembly: AssemblyFileVersion("5.1.0.0")] [assembly: AssemblyInformationalVersion("5.1.0")] [assembly: AssemblyProduct("AsmResolver.PE")] [assembly: AssemblyTitle("AsmResolver.PE")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Washi1337/AsmResolver")] [assembly: AssemblyVersion("5.1.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace AsmResolver.PE { public interface IPEImage { string? FilePath { get; } MachineType MachineType { get; set; } Characteristics Characteristics { get; set; } DateTime TimeDateStamp { get; set; } OptionalHeaderMagic PEKind { get; set; } SubSystem SubSystem { get; set; } DllCharacteristics DllCharacteristics { get; set; } ulong ImageBase { get; set; } IList Imports { get; } IExportDirectory? Exports { get; set; } IResourceDirectory? Resources { get; set; } IExceptionDirectory? Exceptions { get; set; } IList Relocations { get; } IDotNetDirectory? DotNetDirectory { get; set; } IList DebugData { get; } ITlsDirectory? TlsDirectory { get; set; } } public class PEImage : IPEImage { private IList? _imports; private readonly LazyVariable _exports; private readonly LazyVariable _resources; private readonly LazyVariable _exceptions; private IList? _relocations; private readonly LazyVariable _dotNetDirectory; private IList? _debugData; private readonly LazyVariable _tlsDirectory; public string? FilePath { get; protected set; } public MachineType MachineType { get; set; } = (MachineType)332; public Characteristics Characteristics { get; set; } = (Characteristics)34; public DateTime TimeDateStamp { get; set; } = new DateTime(1970, 1, 1); public OptionalHeaderMagic PEKind { get; set; } = (OptionalHeaderMagic)267; public SubSystem SubSystem { get; set; } = (SubSystem)3; public DllCharacteristics DllCharacteristics { get; set; } = (DllCharacteristics)34112; public ulong ImageBase { get; set; } = 4194304uL; public IList Imports { get { if (_imports == null) { Interlocked.CompareExchange(ref _imports, GetImports(), null); } return _imports; } } public IExportDirectory? Exports { get { return _exports.Value; } set { _exports.Value = value; } } public IResourceDirectory? Resources { get { return _resources.Value; } set { _resources.Value = value; } } public IExceptionDirectory? Exceptions { get { return _exceptions.Value; } set { _exceptions.Value = value; } } public IList Relocations { get { if (_relocations == null) { Interlocked.CompareExchange(ref _relocations, GetRelocations(), null); } return _relocations; } } public IDotNetDirectory? DotNetDirectory { get { return _dotNetDirectory.Value; } set { _dotNetDirectory.Value = value; } } public IList DebugData { get { if (_debugData == null) { Interlocked.CompareExchange(ref _debugData, GetDebugData(), null); } return _debugData; } } public ITlsDirectory? TlsDirectory { get { return _tlsDirectory.Value; } set { _tlsDirectory.Value = value; } } public static IPEImage FromFile(string filePath) { return FromFile((IPEFile)(object)PEFile.FromFile(filePath)); } public static IPEImage FromFile(string filePath, PEReaderParameters readerParameters) { return FromFile((IPEFile)(object)PEFile.FromFile(readerParameters.FileService.OpenFile(filePath)), readerParameters); } public static IPEImage FromBytes(byte[] bytes) { return FromFile((IPEFile)(object)PEFile.FromBytes(bytes)); } public static IPEImage FromBytes(byte[] bytes, PEReaderParameters readerParameters) { return FromFile((IPEFile)(object)PEFile.FromBytes(bytes), readerParameters); } public static IPEImage FromModuleBaseAddress(IntPtr hInstance) { return FromModuleBaseAddress(hInstance, (PEMappingMode)1, new PEReaderParameters()); } public static IPEImage FromModuleBaseAddress(IntPtr hInstance, PEReaderParameters readerParameters) { return FromFile((IPEFile)(object)PEFile.FromModuleBaseAddress(hInstance), readerParameters); } public static IPEImage FromModuleBaseAddress(IntPtr hInstance, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile((IPEFile)(object)PEFile.FromModuleBaseAddress(hInstance, mode), readerParameters); } public static IPEImage FromDataSource(IDataSource dataSource, PEMappingMode mode = 0) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(dataSource, dataSource.BaseAddress, 0u, (uint)dataSource.Length); return FromReader(in reader, mode); } public static IPEImage FromDataSource(IDataSource dataSource, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(dataSource, dataSource.BaseAddress, 0u, (uint)dataSource.Length); return FromReader(in reader, mode, readerParameters); } public static IPEImage FromReader(in BinaryStreamReader reader, PEMappingMode mode = 0) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile((IPEFile)(object)PEFile.FromReader(ref reader, mode)); } public static IPEImage FromReader(in BinaryStreamReader reader, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile((IPEFile)(object)PEFile.FromReader(ref reader, mode), readerParameters); } public static IPEImage FromFile(IInputFile inputFile) { return FromFile((IPEFile)(object)PEFile.FromFile(inputFile), new PEReaderParameters()); } public static IPEImage FromFile(IPEFile peFile) { return FromFile(peFile, new PEReaderParameters()); } public static IPEImage FromFile(IPEFile peFile, PEReaderParameters readerParameters) { return new SerializedPEImage(peFile, readerParameters); } public PEImage() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) _exports = new LazyVariable((Func)GetExports); _resources = new LazyVariable((Func)GetResources); _exceptions = new LazyVariable((Func)GetExceptions); _dotNetDirectory = new LazyVariable((Func)GetDotNetDirectory); _tlsDirectory = new LazyVariable((Func)GetTlsDirectory); } protected virtual IList GetImports() { return new List(); } protected virtual IExportDirectory? GetExports() { return null; } protected virtual IResourceDirectory? GetResources() { return null; } protected virtual IExceptionDirectory? GetExceptions() { return null; } protected virtual IList GetRelocations() { return new List(); } protected virtual IDotNetDirectory? GetDotNetDirectory() { return null; } protected virtual IList GetDebugData() { return new List(); } protected virtual ITlsDirectory? GetTlsDirectory() { return null; } } public class PEReaderContext : IErrorListener { public IPEFile File { get; } public PEReaderParameters Parameters { get; } public PEReaderContext(IPEFile file) : this(file, new PEReaderParameters()) { } public PEReaderContext(IPEFile file, PEReaderParameters parameters) { File = file; Parameters = parameters; } public RelocationParameters GetRelocation(ulong offset, uint rva) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) return new RelocationParameters(File.OptionalHeader.ImageBase, offset, rva, (int)File.OptionalHeader.Magic == 267); } public void MarkAsFatal() { Parameters.ErrorListener.MarkAsFatal(); } public void RegisterException(Exception exception) { Parameters.ErrorListener.RegisterException(exception); } } public class PEReaderParameters { public IErrorListener ErrorListener { get; set; } public IMetadataStreamReader MetadataStreamReader { get; set; } public IDebugDataReader DebugDataReader { get; set; } public IFileService FileService { get; set; } = (IFileService)(object)UncachedFileService.Instance; public PEReaderParameters() : this((IErrorListener)(object)ThrowErrorListener.Instance) { } public PEReaderParameters(IErrorListener errorListener) { MetadataStreamReader = new DefaultMetadataStreamReader(); DebugDataReader = new DefaultDebugDataReader(); ErrorListener = errorListener ?? throw new ArgumentNullException("errorListener"); } } public class SerializedPEImage : PEImage { private readonly MachineType _originalArchitecture; public IPEFile PEFile { get; } public PEReaderContext ReaderContext { get; } public SerializedPEImage(IPEFile peFile, PEReaderParameters readerParameters) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) PEFile = peFile ?? throw new ArgumentNullException("peFile"); ReaderContext = new PEReaderContext(peFile, readerParameters); base.FilePath = peFile.FilePath; base.MachineType = PEFile.FileHeader.Machine; base.Characteristics = PEFile.FileHeader.Characteristics; base.TimeDateStamp = new DateTime(1970, 1, 1) + TimeSpan.FromSeconds(peFile.FileHeader.TimeDateStamp); base.PEKind = PEFile.OptionalHeader.Magic; base.SubSystem = PEFile.OptionalHeader.SubSystem; base.DllCharacteristics = PEFile.OptionalHeader.DllCharacteristics; base.ImageBase = PEFile.OptionalHeader.ImageBase; _originalArchitecture = base.MachineType; } protected override IList GetImports() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)1); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE) { return new List(); } return (IList)new SerializedImportedModuleList(ReaderContext, in dataDirectory); } protected override IExportDirectory? GetExports() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)0); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedExportDirectory(ReaderContext, ref reader); } protected override IResourceDirectory? GetResources() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); BinaryStreamReader directoryReader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref directoryReader)) { return null; } return new SerializedResourceDirectory(ReaderContext, null, ref directoryReader); } protected override IExceptionDirectory? GetExceptions() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)3); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } if ((int)_originalArchitecture == 34404) { return new X64ExceptionDirectory(ReaderContext, in reader); } return ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)ReaderContext); } protected override IList GetRelocations() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) DataDirectory relocDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)5); if (!((DataDirectory)(ref relocDirectory)).IsPresentInPE) { return new List(); } return (IList)new SerializedRelocationList(ReaderContext, in relocDirectory); } protected override IDotNetDirectory? GetDotNetDirectory() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)14); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedDotNetDirectory(ReaderContext, ref reader); } protected override IList GetDebugData() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)6); List list = new List(); BinaryStreamReader directoryReader = default(BinaryStreamReader); if (((DataDirectory)(ref dataDirectory)).IsPresentInPE && PEFile.TryCreateDataDirectoryReader(dataDirectory, ref directoryReader)) { uint num = ((DataDirectory)(ref dataDirectory)).Size / 28; for (int i = 0; i < num; i++) { list.Add(new SerializedDebugDataEntry(ReaderContext, ref directoryReader)); } } return list; } protected override ITlsDirectory? GetTlsDirectory() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)9); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedTlsDirectory(ReaderContext, ref reader); } } } namespace AsmResolver.PE.Win32Resources { public interface IResourceData : IResourceEntry, IOwnedCollectionElement { ISegment? Contents { get; set; } uint CodePage { get; set; } [MemberNotNullWhen(true, "Contents")] bool CanRead { [MemberNotNullWhen(true, "Contents")] get; } BinaryStreamReader CreateReader(); } public interface IResourceDirectory : IResourceEntry, IOwnedCollectionElement { ResourceType Type { get; } uint Characteristics { get; set; } uint TimeDateStamp { get; set; } ushort MajorVersion { get; set; } ushort MinorVersion { get; set; } IList Entries { get; } IResourceEntry GetEntry(uint id); IResourceDirectory GetDirectory(uint id); IResourceDirectory GetDirectory(ResourceType type); IResourceData GetData(uint id); bool TryGetEntry(uint id, [NotNullWhen(true)] out IResourceEntry? entry); bool TryGetDirectory(uint id, [NotNullWhen(true)] out IResourceDirectory? directory); bool TryGetDirectory(ResourceType type, [NotNullWhen(true)] out IResourceDirectory? directory); bool TryGetData(uint id, [NotNullWhen(true)] out IResourceData? data); void AddOrReplaceEntry(IResourceEntry entry); bool RemoveEntry(uint id); bool RemoveEntry(ResourceType type); } public interface IResourceEntry : IOwnedCollectionElement { IResourceDirectory? ParentDirectory { get; } string? Name { get; set; } uint Id { get; set; } bool IsDirectory { get; } bool IsData { get; } } public class ResourceData : IResourceData, IResourceEntry, IOwnedCollectionElement { private readonly LazyVariable _contents; public IResourceDirectory? ParentDirectory { get; private set; } IResourceDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } public string? Name { get; set; } public uint Id { get; set; } bool IResourceEntry.IsDirectory => false; bool IResourceEntry.IsData => true; public ISegment? Contents { get { return _contents.Value; } set { _contents.Value = value; } } public uint CodePage { get; set; } public bool CanRead => Contents is IReadableSegment; protected ResourceData() { _contents = new LazyVariable((Func)GetContents); } public ResourceData(string name, ISegment contents) : this() { Name = name ?? throw new ArgumentNullException("name"); Contents = contents ?? throw new ArgumentNullException("contents"); } public ResourceData(uint id, ISegment contents) : this() { Id = id; Contents = contents ?? throw new ArgumentNullException("contents"); } public BinaryStreamReader CreateReader() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) ISegment? contents = Contents; IReadableSegment val = (IReadableSegment)(object)((contents is IReadableSegment) ? contents : null); if (val == null) { throw new InvalidOperationException("Resource file is not readable."); } return Extensions.CreateReader(val); } protected virtual ISegment? GetContents() { return null; } public override string ToString() { return "Data (" + (Name ?? Id.ToString()) + ")"; } } public class ResourceDirectory : IResourceDirectory, IResourceEntry, IOwnedCollectionElement { private IList? _entries; public IResourceDirectory? ParentDirectory { get; private set; } IResourceDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } public string? Name { get; set; } public uint Id { get; set; } bool IResourceEntry.IsDirectory => true; bool IResourceEntry.IsData => false; public ResourceType Type { get { return (ResourceType)Id; } set { Id = (uint)value; } } public uint Characteristics { get; set; } public uint TimeDateStamp { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public IList Entries { get { if (_entries == null) { Interlocked.CompareExchange(ref _entries, GetEntries(), null); } return _entries; } } protected ResourceDirectory() { } public ResourceDirectory(string name) { Name = name ?? throw new ArgumentNullException("name"); } public ResourceDirectory(uint id) { Id = id; } public ResourceDirectory(ResourceType type) { Type = type; } private int GetEntryIndex(uint id) { for (int i = 0; i < Entries.Count; i++) { if (Entries[i].Id == id) { return i; } } return -1; } public IResourceEntry GetEntry(uint id) { if (!TryGetEntry(id, out IResourceEntry entry)) { throw new KeyNotFoundException($"Directory does not contain an entry with id {id}."); } return entry; } public IResourceDirectory GetDirectory(uint id) { if (!TryGetDirectory(id, out IResourceDirectory directory)) { throw new KeyNotFoundException($"Directory does not contain a directory with id {id}."); } return directory; } public IResourceDirectory GetDirectory(ResourceType type) { if (!TryGetDirectory(type, out IResourceDirectory directory)) { throw new KeyNotFoundException($"Directory does not contain a directory of type {type}."); } return directory; } public IResourceData GetData(uint id) { if (!TryGetData(id, out IResourceData data)) { throw new KeyNotFoundException($"Directory does not contain a data entry with id {id}."); } return data; } public bool TryGetEntry(uint id, [NotNullWhen(true)] out IResourceEntry? entry) { int entryIndex = GetEntryIndex(id); if (entryIndex != -1) { entry = Entries[entryIndex]; return true; } entry = null; return false; } public bool TryGetDirectory(uint id, [NotNullWhen(true)] out IResourceDirectory? directory) { if (TryGetEntry(id, out IResourceEntry entry) && entry.IsDirectory) { directory = (IResourceDirectory)entry; return true; } directory = null; return false; } public bool TryGetDirectory(ResourceType type, [NotNullWhen(true)] out IResourceDirectory? directory) { return TryGetDirectory((uint)type, out directory); } public bool TryGetData(uint id, [NotNullWhen(true)] out IResourceData? data) { if (TryGetEntry(id, out IResourceEntry entry) && entry.IsData) { data = (IResourceData)entry; return true; } data = null; return false; } public void AddOrReplaceEntry(IResourceEntry entry) { int entryIndex = GetEntryIndex(entry.Id); if (entryIndex == -1) { Entries.Add(entry); } else { Entries[entryIndex] = entry; } } public bool RemoveEntry(uint id) { int entryIndex = GetEntryIndex(id); if (entryIndex == -1) { return false; } Entries.RemoveAt(entryIndex); return true; } public bool RemoveEntry(ResourceType type) { return RemoveEntry((uint)type); } protected virtual IList GetEntries() { return (IList)new OwnedCollection((IResourceDirectory)this); } public override string ToString() { return "Directory (" + (Name ?? Id.ToString()) + ")"; } } public readonly struct ResourceDirectoryEntry { public const int EntrySize = 8; private readonly uint _idOrNameOffset; private readonly uint _dataOrSubDirOffset; public string? Name { get; } public uint IdOrNameOffset => _idOrNameOffset & 0x7FFFFFFFu; public bool IsByName => (_idOrNameOffset & 0x80000000u) != 0; public uint DataOrSubDirOffset => _dataOrSubDirOffset & 0x7FFFFFFFu; public bool IsData => (_dataOrSubDirOffset & 0x80000000u) == 0; public bool IsSubDirectory => (_dataOrSubDirOffset & 0x80000000u) != 0; public ResourceDirectoryEntry(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _idOrNameOffset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _dataOrSubDirOffset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); Name = null; if (IsByName) { DataDirectory dataDirectory = context.File.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); uint virtualAddress = ((DataDirectory)(ref dataDirectory)).VirtualAddress; BinaryStreamReader val = default(BinaryStreamReader); if (!context.File.TryCreateReaderAtRva(virtualAddress + IdOrNameOffset, ref val)) { ErrorListenerExtensions.BadImage(context.Parameters.ErrorListener, "Resource directory entry contains an invalid name RVA."); return; } int num = ((BinaryStreamReader)(ref val)).ReadUInt16() * 2; byte[] array = new byte[num]; num = ((BinaryStreamReader)(ref val)).ReadBytes(array, 0, num); Name = Encoding.Unicode.GetString(array, 0, num); } } public override string ToString() { return $"Entry: {(IsByName ? Name : IdOrNameOffset.ToString())}, Offset: {DataOrSubDirOffset:X8}"; } } public enum ResourceType { Cursor = 1, Bitmap = 2, Icon = 3, Menu = 4, Dialog = 5, String = 6, FontDirectory = 7, Font = 8, Accelerator = 9, RcData = 10, MessageTable = 11, GroupCursor = 12, GroupIcon = 14, Version = 16, DialogInclude = 17, PlugPlay = 18, Vxd = 20, AniCursor = 21, AniIcon = 22, Html = 23, Manifest = 24 } public class SerializedResourceData : ResourceData { public const uint ResourceDataEntrySize = 16u; private readonly PEReaderContext _context; private readonly uint _contentsRva; private readonly uint _contentsSize; public SerializedResourceData(PEReaderContext context, ResourceDirectoryEntry entry, ref BinaryStreamReader entryReader) { _context = context ?? throw new ArgumentNullException("context"); if (entry.IsByName) { base.Name = entry.Name; } else { base.Id = entry.IdOrNameOffset; } _contentsRva = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); _contentsSize = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); base.CodePage = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); } protected override ISegment? GetContents() { BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_contentsRva, _contentsSize, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource data entry contains an invalid RVA and/or size."); return null; } return (ISegment?)(object)DataSegment.FromReader(ref val); } } public class SerializedResourceDirectory : ResourceDirectory { public const uint ResourceDirectorySize = 16u; public const int MaxDepth = 10; private readonly PEReaderContext _context; private readonly ushort _namedEntries; private readonly ushort _idEntries; private readonly uint _entriesRva; private readonly int _depth; public SerializedResourceDirectory(PEReaderContext context, ResourceDirectoryEntry? entry, ref BinaryStreamReader directoryReader, int depth = 0) { _context = context ?? throw new ArgumentNullException("context"); _depth = depth; if (entry.HasValue) { ResourceDirectoryEntry value = entry.Value; if (value.IsByName) { base.Name = value.Name; } else { base.Id = value.IdOrNameOffset; } } if (((BinaryStreamReader)(ref directoryReader)).IsValid) { base.Characteristics = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _namedEntries = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _idEntries = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _entriesRva = ((BinaryStreamReader)(ref directoryReader)).Rva; ((BinaryStreamReader)(ref directoryReader)).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset + (ulong)((_namedEntries + _idEntries) * 8); } } protected override IList GetEntries() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) OwnedCollection val = new OwnedCollection((IResourceDirectory)this); if (_namedEntries + _idEntries == 0 || _depth >= 10) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Reached maximum recursion depth of {_depth} sub resource directories."); return (IList)val; } DataDirectory dataDirectory = _context.File.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); uint virtualAddress = ((DataDirectory)(ref dataDirectory)).VirtualAddress; uint num = (uint)((_namedEntries + _idEntries) * 8); BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_entriesRva, num, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource directory contains an invalid entry table RVA and/or entry count."); return (IList)val; } BinaryStreamReader entryReader = default(BinaryStreamReader); for (int i = 0; i < _namedEntries + _idEntries; i++) { ResourceDirectoryEntry resourceDirectoryEntry = new ResourceDirectoryEntry(_context, ref reader); if (!_context.File.TryCreateReaderAtRva(virtualAddress + resourceDirectoryEntry.DataOrSubDirOffset, ref entryReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource directory entry " + i + " has an invalid data offset."); } IResourceEntry resourceEntry2; if (!resourceDirectoryEntry.IsSubDirectory) { IResourceEntry resourceEntry = new SerializedResourceData(_context, resourceDirectoryEntry, ref entryReader); resourceEntry2 = resourceEntry; } else { IResourceEntry resourceEntry = new SerializedResourceDirectory(_context, resourceDirectoryEntry, ref entryReader, _depth + 1); resourceEntry2 = resourceEntry; } ((LazyList)(object)val).Add(resourceEntry2); } return (IList)val; } } } namespace AsmResolver.PE.Win32Resources.Builder { public class ResourceDataTableBuffer : ResourceTableBuffer { public ResourceDataTableBuffer(ISegment parentBuffer) : base(parentBuffer) { } public override uint GetEntrySize(IResourceData entry) { return 16u; } public override void Write(IBinaryStreamWriter writer) { for (int i = 0; i < base.Entries.Count; i++) { WriteDataEntry(writer, base.Entries[i]); } } private static void WriteDataEntry(IBinaryStreamWriter writer, IResourceData entry) { if (entry.Contents == null) { writer.WriteUInt64(0uL); } else { writer.WriteUInt32(((IOffsetProvider)entry.Contents).Rva); writer.WriteUInt32(((IWritable)entry.Contents).GetPhysicalSize()); } writer.WriteUInt32(entry.CodePage); writer.WriteUInt32(0u); } } public class ResourceDirectoryBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _segments; public ulong Offset => _segments.Offset; public uint Rva => _segments.Rva; public bool CanUpdateOffsets => true; public ResourceTableBuffer DirectoryTable { get; } public ResourceTableBuffer DataEntryTable { get; } public ResourceTableBuffer NameTable { get; } public SegmentBuilder DataTable { get; } public ResourceDirectoryBuffer() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown NameTable = new ResourceNameTableBuffer((ISegment)(object)this); DataEntryTable = new ResourceDataTableBuffer((ISegment)(object)this); DirectoryTable = new ResourceDirectoryTableBuffer((ISegment)(object)this, NameTable, DataEntryTable); DataTable = new SegmentBuilder(); SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(object)DirectoryTable); val.Add((ISegment)(object)NameTable); val.Add((ISegment)(object)DataEntryTable); val.Add((ISegment)(object)DataTable); _segments = val; } public void AddDirectory(IResourceDirectory directory) { DirectoryTable.AddEntry(directory); if (directory.Name != null) { NameTable.AddEntry(directory.Name); } foreach (IResourceEntry entry in directory.Entries) { AddEntry(entry); } } private void AddEntry(IResourceEntry entry) { if (entry.IsDirectory) { AddDirectory((IResourceDirectory)entry); return; } if (entry.IsData) { AddDataEntry(entry); return; } throw new NotSupportedException(); } private void AddDataEntry(IResourceEntry entry) { IResourceData resourceData = (IResourceData)entry; DataEntryTable.AddEntry(resourceData); if (resourceData.Contents != null) { DataTable.Add(resourceData.Contents, 4u); } } public void UpdateOffsets(in RelocationParameters parameters) { _segments.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _segments.GetPhysicalSize(); } public uint GetVirtualSize() { return _segments.GetVirtualSize(); } public void Write(IBinaryStreamWriter writer) { _segments.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class ResourceDirectoryTableBuffer : ResourceTableBuffer { private readonly ResourceTableBuffer _nameTable; private readonly ResourceTableBuffer _dataEntryTable; public ResourceDirectoryTableBuffer(ISegment parentBuffer, ResourceTableBuffer nameTable, ResourceTableBuffer dataEntryTable) : base(parentBuffer) { _nameTable = nameTable ?? throw new ArgumentNullException("nameTable"); _dataEntryTable = dataEntryTable ?? throw new ArgumentNullException("dataEntryTable"); } public override uint GetEntrySize(IResourceDirectory entry) { return (uint)(16 + entry.Entries.Count * 8); } public override void Write(IBinaryStreamWriter writer) { foreach (IResourceDirectory entry in base.Entries) { if (entry.IsDirectory) { WriteDirectory(writer, entry); continue; } throw new ArgumentException("Directory table contains a data entry."); } } private void WriteDirectory(IBinaryStreamWriter writer, IResourceDirectory directory) { ushort num = (ushort)directory.Entries.Count((IResourceEntry e) => e.Name != null); ushort num2 = (ushort)(directory.Entries.Count - num); writer.WriteUInt32(directory.Characteristics); writer.WriteUInt32(directory.TimeDateStamp); writer.WriteUInt16(directory.MajorVersion); writer.WriteUInt16(directory.MinorVersion); writer.WriteUInt16(num); writer.WriteUInt16(num2); foreach (IResourceEntry entry in directory.Entries) { WriteEntry(writer, entry); } } private void WriteEntry(IBinaryStreamWriter writer, IResourceEntry entry) { writer.WriteUInt32((entry.Name != null) ? (_nameTable.GetEntryOffset(entry.Name) | 0x80000000u) : entry.Id); writer.WriteUInt32(entry.IsDirectory ? (GetEntryOffset((IResourceDirectory)entry) | 0x80000000u) : _dataEntryTable.GetEntryOffset((IResourceData)entry)); } } public class ResourceNameTableBuffer : ResourceTableBuffer { public ResourceNameTableBuffer(ISegment parentBuffer) : base(parentBuffer) { } public override uint GetEntrySize(string entry) { return (uint)(2 + Encoding.Unicode.GetByteCount(entry)); } public override void Write(IBinaryStreamWriter writer) { foreach (string entry in base.Entries) { writer.WriteUInt16((ushort)entry.Length); byte[] bytes = Encoding.Unicode.GetBytes(entry); writer.WriteBytes(bytes, 0, bytes.Length); } } } public abstract class ResourceTableBuffer : SegmentBase where TEntry : notnull { private readonly Dictionary _entryOffsets = new Dictionary(); private readonly ISegment _parentBuffer; private uint _length; public uint RelativeOffset => ((SegmentBase)this).Rva - ((IOffsetProvider)_parentBuffer).Rva; protected IList Entries { get; } = new List(); protected ResourceTableBuffer(ISegment parentBuffer) { _parentBuffer = parentBuffer ?? throw new ArgumentNullException("parentBuffer"); } public void AddEntry(TEntry entry) { if (!_entryOffsets.ContainsKey(entry)) { Entries.Add(entry); _entryOffsets[entry] = _length; _length += GetEntrySize(entry); } } public abstract uint GetEntrySize(TEntry entry); public uint GetEntryOffset(TEntry entry) { return RelativeOffset + _entryOffsets[entry]; } public override uint GetPhysicalSize() { return _length; } } } namespace AsmResolver.PE.Tls { public interface ITlsDirectory : ISegment, IOffsetProvider, IWritable { IReadableSegment? TemplateData { get; set; } ISegmentReference Index { get; set; } TlsCallbackCollection CallbackFunctions { get; } uint SizeOfZeroFill { get; set; } TlsCharacteristics Characteristics { get; set; } IEnumerable GetRequiredBaseRelocations(); } public class SerializedTlsDirectory : TlsDirectory { private readonly PEReaderContext _context; private readonly ulong _templateStart; private readonly ulong _templateEnd; private readonly ulong _addressOfCallbacks; public SerializedTlsDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) _context = context; RelocationParameters relocation = context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); _templateStart = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); _templateEnd = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); base.Index = ((ISegmentReferenceFactory)context.File).GetReferenceToRva((uint)(((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit) - ((RelocationParameters)(ref relocation)).ImageBase)); _addressOfCallbacks = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); base.SizeOfZeroFill = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.Characteristics = (TlsCharacteristics)((BinaryStreamReader)(ref reader)).ReadUInt32(); ((SegmentBase)this).UpdateOffsets(ref relocation); } protected override IReadableSegment? GetTemplateData() { if (_templateEnd < _templateStart) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, "End address of TLS template data is smaller than the start address."); } ulong imageBase = _context.File.OptionalHeader.ImageBase; BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva((uint)(_templateStart - imageBase), ref val)) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, $"TLS template data start address 0x{_templateStart:X8} is invalid."); } uint num = (uint)(_templateEnd - _templateStart); if (!((BinaryStreamReader)(ref val)).CanRead(num)) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, $"TLS template data end address 0x{_templateEnd:X8} is invalid."); } return ((BinaryStreamReader)(ref val)).ReadSegment(num); } protected override TlsCallbackCollection GetCallbackFunctions() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 TlsCallbackCollection tlsCallbackCollection = new TlsCallbackCollection(this); IPEFile file = _context.File; OptionalHeader optionalHeader = file.OptionalHeader; ulong imageBase = optionalHeader.ImageBase; bool flag = (int)optionalHeader.Magic == 267; BinaryStreamReader val = default(BinaryStreamReader); if (!file.TryCreateReaderAtRva((uint)(_addressOfCallbacks - imageBase), ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"TLS callback function table start address 0x{_addressOfCallbacks:X8} is invalid."); return tlsCallbackCollection; } while (true) { if (!((BinaryStreamReader)(ref val)).CanRead(flag ? 4u : 8u)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "TLS callback function table does not end with a zero entry."); break; } ulong num = ((BinaryStreamReader)(ref val)).ReadNativeInt(flag); if (num == 0L) { break; } tlsCallbackCollection.Add(((ISegmentReferenceFactory)file).GetReferenceToRva((uint)(num - imageBase))); } return tlsCallbackCollection; } } public class TlsCallbackCollection : Collection, ISegment, IOffsetProvider, IWritable { private readonly ITlsDirectory _owner; private ulong _imageBase = 4194304uL; private bool _is32Bit = true; public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; internal TlsCallbackCollection(ITlsDirectory owner) { _owner = owner; } public void UpdateOffsets(in RelocationParameters parameters) { Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; _imageBase = ((RelocationParameters)(ref parameters)).ImageBase; _is32Bit = ((RelocationParameters)(ref parameters)).Is32Bit; } public uint GetPhysicalSize() { return (uint)((uint)(_is32Bit ? 4 : 8) * (base.Count + 1)); } public uint GetVirtualSize() { return GetPhysicalSize(); } public void Write(IBinaryStreamWriter writer) { ulong imageBase = _imageBase; bool is32Bit = _is32Bit; for (int i = 0; i < base.Items.Count; i++) { IOExtensions.WriteNativeInt(writer, imageBase + ((IOffsetProvider)base.Items[i]).Rva, is32Bit); } IOExtensions.WriteNativeInt(writer, 0uL, is32Bit); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public enum TlsCharacteristics { Align1Bytes = 1048576, Align2Bytes = 2097152, Align4Bytes = 3145728, Align8Bytes = 4194304, Align16Bytes = 5242880, Align32Bytes = 6291456, Align64Bytes = 7340032, Align128Bytes = 8388608, Align256Bytes = 9437184, Align512Bytes = 10485760, Align1024Bytes = 11534336, Align2048Bytes = 12582912, Align4096Bytes = 13631488, Align8192Bytes = 14680064 } public class TlsDirectory : SegmentBase, ITlsDirectory, ISegment, IOffsetProvider, IWritable { private readonly LazyVariable _templateData; private TlsCallbackCollection? _callbackFunctions; private ulong _imageBase = 4194304uL; private bool _is32Bit = true; public IReadableSegment? TemplateData { get { return _templateData.Value; } set { _templateData.Value = value; } } public ISegmentReference Index { get; set; } public TlsCallbackCollection CallbackFunctions { get { if (_callbackFunctions == null) { Interlocked.CompareExchange(ref _callbackFunctions, GetCallbackFunctions(), null); } return _callbackFunctions; } } public uint SizeOfZeroFill { get; set; } public TlsCharacteristics Characteristics { get; set; } public TlsDirectory() { _templateData = new LazyVariable((Func)GetTemplateData); Index = SegmentReference.Null; } public override void UpdateOffsets(in RelocationParameters parameters) { _imageBase = ((RelocationParameters)(ref parameters)).ImageBase; _is32Bit = ((RelocationParameters)(ref parameters)).Is32Bit; ((SegmentBase)this).UpdateOffsets(ref parameters); } protected virtual IReadableSegment? GetTemplateData() { return null; } protected virtual TlsCallbackCollection GetCallbackFunctions() { return new TlsCallbackCollection(this); } public IEnumerable GetRequiredBaseRelocations() { int num = (_is32Bit ? 4 : 8); RelocationType type = (_is32Bit ? RelocationType.HighLow : RelocationType.Dir64); List list = new List(4 + CallbackFunctions.Count); for (int i = 0; i < 4; i++) { list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)this, i * num))); } for (int j = 0; j < CallbackFunctions.Count; j++) { list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)CallbackFunctions, j * num))); } return list; } public override uint GetPhysicalSize() { return (uint)((_is32Bit ? 4 : 8) * 4 + 8); } public override void Write(IBinaryStreamWriter writer) { ulong imageBase = _imageBase; bool is32Bit = _is32Bit; IReadableSegment templateData = TemplateData; if (templateData != null) { IOExtensions.WriteNativeInt(writer, imageBase + ((IOffsetProvider)templateData).Rva, is32Bit); IOExtensions.WriteNativeInt(writer, imageBase + ((IOffsetProvider)templateData).Rva + ((IWritable)templateData).GetPhysicalSize(), is32Bit); } else { IOExtensions.WriteNativeInt(writer, 0uL, is32Bit); IOExtensions.WriteNativeInt(writer, 0uL, is32Bit); } IOExtensions.WriteNativeInt(writer, imageBase + ((IOffsetProvider)Index).Rva, is32Bit); IOExtensions.WriteNativeInt(writer, imageBase + CallbackFunctions.Rva, is32Bit); writer.WriteUInt32(SizeOfZeroFill); writer.WriteUInt32((uint)Characteristics); } } } namespace AsmResolver.PE.Relocations { public readonly struct BaseRelocation { public RelocationType Type { get; } public ISegmentReference Location { get; } public BaseRelocation(RelocationType type, ISegmentReference location) { Type = type; Location = location ?? throw new ArgumentNullException("location"); } public override string ToString() { return $"{((IOffsetProvider)Location).Rva:X8} ({Type})"; } public bool Equals(BaseRelocation other) { if (Type == other.Type) { return ((IOffsetProvider)Location).Rva == ((IOffsetProvider)other.Location).Rva; } return false; } public override bool Equals(object? obj) { if (obj is BaseRelocation other) { return Equals(other); } return false; } public override int GetHashCode() { return ((int)Type * 397) ^ (int)((IOffsetProvider)Location).Rva; } } public readonly struct RelocatableSegment { public ISegment Segment { get; } public IReadOnlyList Relocations { get; } public RelocatableSegment(ISegment segment, IReadOnlyList relocations) { Segment = segment; Relocations = relocations; } } public enum RelocationType { Absolute = 0, High = 1, Low = 2, HighLow = 3, HighAdj = 4, MipsJmpAddr = 5, ArmMov32 = 5, RiscVHigh20 = 5, ThumbMov32 = 7, RiscVLow12I = 7, RiscVLow12S = 8, MipsJmpAddr16 = 9, Dir64 = 10 } [DebuggerDisplay("Count = {Count}")] public class SerializedRelocationList : LazyList { private readonly PEReaderContext _context; private readonly DataDirectory _relocDirectory; public SerializedRelocationList(PEReaderContext context, in DataDirectory relocDirectory) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _relocDirectory = relocDirectory; } protected override void Initialize() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_relocDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid base relocation data directory RVA and/or size."); return; } while (((BinaryStreamReader)(ref reader)).Offset < ((BinaryStreamReader)(ref reader)).StartOffset + ((BinaryStreamReader)(ref reader)).Length) { ReadBlock(ref reader); } } private void ReadBlock(ref BinaryStreamReader reader) { uint pageRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); int num = (int)((((BinaryStreamReader)(ref reader)).ReadUInt32() - 8) / 2); for (int i = 0; i < num; i++) { ReadRelocationEntry(ref reader, pageRva); } } private void ReadRelocationEntry(ref BinaryStreamReader reader, uint pageRva) { ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); RelocationType type = (RelocationType)(num >> 12); int num2 = num & 0xFFF; base.Items.Add(new BaseRelocation(type, ((ISegmentReferenceFactory)_context.File).GetReferenceToRva((uint)(pageRva + num2)))); } } } namespace AsmResolver.PE.Relocations.Builder { public sealed class RelocationBlock : SegmentBase { public uint PageRva { get; } public IList Entries { get; } public RelocationBlock(uint pageRva) { PageRva = pageRva; Entries = new List(); } public override uint GetPhysicalSize() { return (uint)((Entries.Count + 1) * 2 + 8); } public override void Write(IBinaryStreamWriter writer) { writer.WriteUInt32(PageRva); writer.WriteUInt32(((SegmentBase)this).GetPhysicalSize()); for (int i = 0; i < Entries.Count; i++) { Entries[i].Write(writer); } default(RelocationEntry).Write(writer); } } public readonly struct RelocationEntry : IWritable { private readonly ushort _value; public RelocationType RelocationType => (RelocationType)(_value >> 12); public int Offset => _value & 0xFFF; public RelocationEntry(ushort value) { _value = value; } public RelocationEntry(RelocationType type, int offset) { if (offset >= 0) { if (offset > 4095) { throw new ArgumentOutOfRangeException("offset", "Offset cannot be larger than 0xFFF."); } ushort value = (ushort)((uint)((byte)type << 12) | ((uint)offset & 0xFFFu)); _value = value; return; } throw new ArgumentOutOfRangeException("offset", "Offset cannot be negative."); } public uint GetPhysicalSize() { return 2u; } public void Write(IBinaryStreamWriter writer) { writer.WriteUInt16(_value); } } public class RelocationsDirectoryBuffer : SegmentBase { private readonly List _relocations = new List(); private List? _blocks = new List(); public void Add(BaseRelocation relocation) { _relocations.Add(relocation); _blocks = null; } private void EnsureBlocksCreated() { if (_blocks == null) { _blocks = CreateBlocks(); } } private List CreateBlocks() { Dictionary dictionary = new Dictionary(); for (int i = 0; i < _relocations.Count; i++) { BaseRelocation relocation = _relocations[i]; uint pageRva = GetPageRva(relocation); GetOrCreateBlock(dictionary, pageRva).Entries.Add(CreateEntry(relocation)); } return (from x in dictionary orderby x.Key select x.Value).ToList(); } private static uint GetPageRva(BaseRelocation relocation) { return (uint)(((IOffsetProvider)relocation.Location).Rva & -4096); } private static RelocationEntry CreateEntry(BaseRelocation relocation) { return new RelocationEntry(relocation.Type, (int)(((IOffsetProvider)relocation.Location).Rva & 0xFFF)); } private static RelocationBlock GetOrCreateBlock(IDictionary blocks, uint pageRva) { if (!blocks.TryGetValue(pageRva, out RelocationBlock value)) { value = new RelocationBlock(pageRva); blocks.Add(pageRva, value); } return value; } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); _blocks = null; } public override uint GetPhysicalSize() { EnsureBlocksCreated(); return (uint)_blocks.Sum((RelocationBlock b) => ((SegmentBase)b).GetPhysicalSize()); } public override void Write(IBinaryStreamWriter writer) { EnsureBlocksCreated(); for (int i = 0; i < _blocks.Count; i++) { ((SegmentBase)_blocks[i]).Write(writer); } } } } namespace AsmResolver.PE.Platforms { public class Amd64Platform : Platform { public static Amd64Platform Instance { get; } = new Amd64Platform(); public override MachineType TargetMachine => (MachineType)34404; public override bool IsClrBootstrapperRequired => false; public override RelocatableSegment CreateThunkStub(ISymbol entryPoint) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[12] { 72, 161, 0, 0, 0, 0, 0, 0, 0, 0, 255, 224 })).Patch(2u, AddressFixupType.Absolute64BitAddress, entryPoint); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[1] { new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 2)) }); } public override bool TryExtractThunkAddress(IPEImage image, BinaryStreamReader reader, out uint rva) { if (((BinaryStreamReader)(ref reader)).ReadUInt16() != 41288) { rva = 0u; return false; } rva = (uint)(((BinaryStreamReader)(ref reader)).ReadUInt64() - image.ImageBase); return ((BinaryStreamReader)(ref reader)).ReadUInt16() == 57599; } } public class I386Platform : Platform { public static I386Platform Instance { get; } = new I386Platform(); public override MachineType TargetMachine => (MachineType)332; public override bool IsClrBootstrapperRequired => true; public override RelocatableSegment CreateThunkStub(ISymbol entryPoint) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[6] { 255, 37, 0, 0, 0, 0 })).Patch(2u, AddressFixupType.Absolute32BitAddress, entryPoint); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[1] { new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 2)) }); } public override bool TryExtractThunkAddress(IPEImage image, BinaryStreamReader reader, out uint rva) { if (((BinaryStreamReader)(ref reader)).ReadUInt16() != 9727) { rva = 0u; return false; } rva = (uint)(((BinaryStreamReader)(ref reader)).ReadUInt32() - image.ImageBase); return true; } } public abstract class Platform { public abstract MachineType TargetMachine { get; } public abstract bool IsClrBootstrapperRequired { get; } public static Platform Get(MachineType machineType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!TryGet(machineType, out Platform platform)) { throw new NotSupportedException($"Unsupported machine type {machineType}."); } return platform; } public static bool TryGet(MachineType machineType, [NotNullWhen(true)] out Platform? platform) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 if ((int)machineType <= 31285) { if ((int)machineType <= 6367) { if ((int)machineType == 332 || machineType - 6366 <= 1) { goto IL_0074; } } else { if ((int)machineType == 11168) { goto IL_007c; } if ((int)machineType == 18184 || (int)machineType == 31285) { goto IL_0074; } } } else if ((int)machineType <= 40951) { if ((int)machineType == 34404 || machineType - 40950 <= 1) { goto IL_007c; } } else { if ((int)machineType == 44168) { goto IL_0074; } if ((int)machineType == 49184 || (int)machineType == 64797) { goto IL_007c; } } Platform platform2 = null; goto IL_0086; IL_0086: platform = platform2; return platform != null; IL_0074: platform2 = I386Platform.Instance; goto IL_0086; IL_007c: platform2 = Amd64Platform.Instance; goto IL_0086; } public abstract RelocatableSegment CreateThunkStub(ISymbol entryPoint); public abstract bool TryExtractThunkAddress(IPEImage image, BinaryStreamReader reader, out uint rva); } } namespace AsmResolver.PE.Imports { public sealed class DefaultSymbolResolver : ISymbolResolver { private static readonly Dictionary _ws2_32OrdinalMapping = new Dictionary { [1u] = "accept", [2u] = "bind", [3u] = "closesocket", [4u] = "connect", [5u] = "getpeername", [6u] = "getsockname", [7u] = "getsockopt", [8u] = "htonl", [9u] = "htons", [10u] = "ioctlsocket", [11u] = "inet_addr", [12u] = "inet_ntoa", [13u] = "listen", [14u] = "ntohl", [15u] = "ntohs", [16u] = "recv", [17u] = "recvfrom", [18u] = "select", [19u] = "send", [20u] = "sendto", [21u] = "setsockopt", [22u] = "shutdown", [23u] = "socket", [24u] = "WSApSetPostRoutine", [25u] = "FreeAddrInfoEx", [26u] = "FreeAddrInfoExW", [27u] = "FreeAddrInfoW", [28u] = "GetAddrInfoExA", [29u] = "GetAddrInfoExCancel", [30u] = "GetAddrInfoExOverlappedResult", [31u] = "GetAddrInfoExW", [32u] = "GetAddrInfoW", [33u] = "GetHostNameW", [34u] = "GetNameInfoW", [35u] = "InetNtopW", [36u] = "InetPtonW", [37u] = "SetAddrInfoExA", [38u] = "SetAddrInfoExW", [39u] = "WPUCompleteOverlappedRequest", [40u] = "WPUGetProviderPathEx", [41u] = "WSAAccept", [42u] = "WSAAddressToStringA", [43u] = "WSAAddressToStringW", [44u] = "WSAAdvertiseProvider", [45u] = "WSACloseEvent", [46u] = "WSAConnect", [47u] = "WSAConnectByList", [48u] = "WSAConnectByNameA", [49u] = "WSAConnectByNameW", [50u] = "WSACreateEvent", [51u] = "gethostbyaddr", [52u] = "gethostbyname", [53u] = "getprotobyname", [54u] = "getprotobynumber", [55u] = "getservbyname", [56u] = "getservbyport", [57u] = "gethostname", [58u] = "WSADuplicateSocketA", [59u] = "WSADuplicateSocketW", [60u] = "WSAEnumNameSpaceProvidersA", [61u] = "WSAEnumNameSpaceProvidersExA", [62u] = "WSAEnumNameSpaceProvidersExW", [63u] = "WSAEnumNameSpaceProvidersW", [64u] = "WSAEnumNetworkEvents", [65u] = "WSAEnumProtocolsA", [66u] = "WSAEnumProtocolsW", [67u] = "WSAEventSelect", [68u] = "WSAGetOverlappedResult", [69u] = "WSAGetQOSByName", [70u] = "WSAGetServiceClassInfoA", [71u] = "WSAGetServiceClassInfoW", [72u] = "WSAGetServiceClassNameByClassIdA", [73u] = "WSAGetServiceClassNameByClassIdW", [74u] = "WSAHtonl", [75u] = "WSAHtons", [76u] = "WSAInstallServiceClassA", [77u] = "WSAInstallServiceClassW", [78u] = "WSAIoctl", [79u] = "WSAJoinLeaf", [80u] = "WSALookupServiceBeginA", [81u] = "WSALookupServiceBeginW", [82u] = "WSALookupServiceEnd", [83u] = "WSALookupServiceNextA", [84u] = "WSALookupServiceNextW", [85u] = "WSANSPIoctl", [86u] = "WSANtohl", [87u] = "WSANtohs", [88u] = "WSAPoll", [89u] = "WSAProviderCompleteAsyncCall", [90u] = "WSAProviderConfigChange", [91u] = "WSARecv", [92u] = "WSARecvDisconnect", [93u] = "WSARecvFrom", [94u] = "WSARemoveServiceClass", [95u] = "WSAResetEvent", [96u] = "WSASend", [97u] = "WSASendDisconnect", [98u] = "WSASendMsg", [99u] = "WSASendTo", [100u] = "WSASetEvent", [101u] = "WSAAsyncSelect", [102u] = "WSAAsyncGetHostByAddr", [103u] = "WSAAsyncGetHostByName", [104u] = "WSAAsyncGetProtoByNumber", [105u] = "WSAAsyncGetProtoByName", [106u] = "WSAAsyncGetServByPort", [107u] = "WSAAsyncGetServByName", [108u] = "WSACancelAsyncRequest", [109u] = "WSASetBlockingHook", [110u] = "WSAUnhookBlockingHook", [111u] = "WSAGetLastError", [112u] = "WSASetLastError", [113u] = "WSACancelBlockingCall", [114u] = "WSAIsBlocking", [115u] = "WSAStartup", [116u] = "WSACleanup", [117u] = "WSASetServiceA", [118u] = "WSASetServiceW", [119u] = "WSASocketA", [120u] = "WSASocketW", [121u] = "WSAStringToAddressA", [122u] = "WSAStringToAddressW", [123u] = "WSAUnadvertiseProvider", [124u] = "WSAWaitForMultipleEvents", [125u] = "WSCDeinstallProvider", [126u] = "WSCDeinstallProvider32", [127u] = "WSCDeinstallProviderEx", [128u] = "WSCEnableNSProvider", [129u] = "WSCEnableNSProvider32", [130u] = "WSCEnumNameSpaceProviders32", [131u] = "WSCEnumNameSpaceProvidersEx32", [132u] = "WSCEnumProtocols", [133u] = "WSCEnumProtocols32", [134u] = "WSCEnumProtocolsEx", [135u] = "WSCGetApplicationCategory", [136u] = "WSCGetApplicationCategoryEx", [137u] = "WSCGetProviderInfo", [138u] = "WSCGetProviderInfo32", [139u] = "WSCGetProviderPath", [140u] = "WSCGetProviderPath32", [141u] = "WSCInstallNameSpace", [142u] = "WSCInstallNameSpace32", [143u] = "WSCInstallNameSpaceEx", [144u] = "WSCInstallNameSpaceEx2", [145u] = "WSCInstallNameSpaceEx32", [146u] = "WSCInstallProvider", [147u] = "WSCInstallProvider64_32", [148u] = "WSCInstallProviderAndChains64_32", [149u] = "WSCInstallProviderEx", [150u] = "WSCSetApplicationCategory", [151u] = "__WSAFDIsSet", [152u] = "WSCSetApplicationCategoryEx", [153u] = "WSCSetProviderInfo", [154u] = "WSCSetProviderInfo32", [155u] = "WSCUnInstallNameSpace", [156u] = "WSCUnInstallNameSpace32", [157u] = "WSCUnInstallNameSpaceEx2", [158u] = "WSCUpdateProvider", [159u] = "WSCUpdateProvider32", [160u] = "WSCUpdateProviderEx", [161u] = "WSCWriteNameSpaceOrder", [162u] = "WSCWriteNameSpaceOrder32", [163u] = "WSCWriteProviderOrder", [164u] = "WSCWriteProviderOrder32", [165u] = "WSCWriteProviderOrderEx", [166u] = "WahCloseApcHelper", [167u] = "WahCloseHandleHelper", [168u] = "WahCloseNotificationHandleHelper", [169u] = "WahCloseSocketHandle", [170u] = "WahCloseThread", [171u] = "WahCompleteRequest", [172u] = "WahCreateHandleContextTable", [173u] = "WahCreateNotificationHandle", [174u] = "WahCreateSocketHandle", [175u] = "WahDestroyHandleContextTable", [176u] = "WahDisableNonIFSHandleSupport", [177u] = "WahEnableNonIFSHandleSupport", [178u] = "WahEnumerateHandleContexts", [179u] = "WahInsertHandleContext", [180u] = "WahNotifyAllProcesses", [181u] = "WahOpenApcHelper", [182u] = "WahOpenCurrentThread", [183u] = "WahOpenHandleHelper", [184u] = "WahOpenNotificationHandleHelper", [185u] = "WahQueueUserApc", [186u] = "WahReferenceContextByHandle", [187u] = "WahRemoveHandleContext", [188u] = "WahWaitForNotification", [189u] = "WahWriteLSPEvent", [190u] = "freeaddrinfo", [191u] = "getaddrinfo", [192u] = "getnameinfo", [193u] = "inet_ntop", [194u] = "inet_pton", [500u] = "WEP" }; private static readonly Dictionary _oleaut32OrdinalMapping = new Dictionary { [2u] = "SysAllocString", [3u] = "SysReAllocString", [4u] = "SysAllocStringLen", [5u] = "SysReAllocStringLen", [6u] = "SysFreeString", [7u] = "SysStringLen", [8u] = "VariantInit", [9u] = "VariantClear", [10u] = "VariantCopy", [11u] = "VariantCopyInd", [12u] = "VariantChangeType", [13u] = "VariantTimeToDosDateTime", [14u] = "DosDateTimeToVariantTime", [15u] = "SafeArrayCreate", [16u] = "SafeArrayDestroy", [17u] = "SafeArrayGetDim", [18u] = "SafeArrayGetElemsize", [19u] = "SafeArrayGetUBound", [20u] = "SafeArrayGetLBound", [21u] = "SafeArrayLock", [22u] = "SafeArrayUnlock", [23u] = "SafeArrayAccessData", [24u] = "SafeArrayUnaccessData", [25u] = "SafeArrayGetElement", [26u] = "SafeArrayPutElement", [27u] = "SafeArrayCopy", [28u] = "DispGetParam", [29u] = "DispGetIDsOfNames", [30u] = "DispInvoke", [31u] = "CreateDispTypeInfo", [32u] = "CreateStdDispatch", [33u] = "RegisterActiveObject", [34u] = "RevokeActiveObject", [35u] = "GetActiveObject", [36u] = "SafeArrayAllocDescriptor", [37u] = "SafeArrayAllocData", [38u] = "SafeArrayDestroyDescriptor", [39u] = "SafeArrayDestroyData", [40u] = "SafeArrayRedim", [41u] = "SafeArrayAllocDescriptorEx", [42u] = "SafeArrayCreateEx", [43u] = "SafeArrayCreateVectorEx", [44u] = "SafeArraySetRecordInfo", [45u] = "SafeArrayGetRecordInfo", [46u] = "VarParseNumFromStr", [47u] = "VarNumFromParseNum", [48u] = "VarI2FromUI1", [49u] = "VarI2FromI4", [50u] = "VarI2FromR4", [51u] = "VarI2FromR8", [52u] = "VarI2FromCy", [53u] = "VarI2FromDate", [54u] = "VarI2FromStr", [55u] = "VarI2FromDisp", [56u] = "VarI2FromBool", [57u] = "SafeArraySetIID", [58u] = "VarI4FromUI1", [59u] = "VarI4FromI2", [60u] = "VarI4FromR4", [61u] = "VarI4FromR8", [62u] = "VarI4FromCy", [63u] = "VarI4FromDate", [64u] = "VarI4FromStr", [65u] = "VarI4FromDisp", [66u] = "VarI4FromBool", [67u] = "SafeArrayGetIID", [68u] = "VarR4FromUI1", [69u] = "VarR4FromI2", [70u] = "VarR4FromI4", [71u] = "VarR4FromR8", [72u] = "VarR4FromCy", [73u] = "VarR4FromDate", [74u] = "VarR4FromStr", [75u] = "VarR4FromDisp", [76u] = "VarR4FromBool", [77u] = "SafeArrayGetVartype", [78u] = "VarR8FromUI1", [79u] = "VarR8FromI2", [80u] = "VarR8FromI4", [81u] = "VarR8FromR4", [82u] = "VarR8FromCy", [83u] = "VarR8FromDate", [84u] = "VarR8FromStr", [85u] = "VarR8FromDisp", [86u] = "VarR8FromBool", [87u] = "VarFormat", [88u] = "VarDateFromUI1", [89u] = "VarDateFromI2", [90u] = "VarDateFromI4", [91u] = "VarDateFromR4", [92u] = "VarDateFromR8", [93u] = "VarDateFromCy", [94u] = "VarDateFromStr", [95u] = "VarDateFromDisp", [96u] = "VarDateFromBool", [97u] = "VarFormatDateTime", [98u] = "VarCyFromUI1", [99u] = "VarCyFromI2", [100u] = "VarCyFromI4", [101u] = "VarCyFromR4", [102u] = "VarCyFromR8", [103u] = "VarCyFromDate", [104u] = "VarCyFromStr", [105u] = "VarCyFromDisp", [106u] = "VarCyFromBool", [107u] = "VarFormatNumber", [108u] = "VarBstrFromUI1", [109u] = "VarBstrFromI2", [110u] = "VarBstrFromI4", [111u] = "VarBstrFromR4", [112u] = "VarBstrFromR8", [113u] = "VarBstrFromCy", [114u] = "VarBstrFromDate", [115u] = "VarBstrFromDisp", [116u] = "VarBstrFromBool", [117u] = "VarFormatPercent", [118u] = "VarBoolFromUI1", [119u] = "VarBoolFromI2", [120u] = "VarBoolFromI4", [121u] = "VarBoolFromR4", [122u] = "VarBoolFromR8", [123u] = "VarBoolFromDate", [124u] = "VarBoolFromCy", [125u] = "VarBoolFromStr", [126u] = "VarBoolFromDisp", [127u] = "VarFormatCurrency", [128u] = "VarWeekdayName", [129u] = "VarMonthName", [130u] = "VarUI1FromI2", [131u] = "VarUI1FromI4", [132u] = "VarUI1FromR4", [133u] = "VarUI1FromR8", [134u] = "VarUI1FromCy", [135u] = "VarUI1FromDate", [136u] = "VarUI1FromStr", [137u] = "VarUI1FromDisp", [138u] = "VarUI1FromBool", [139u] = "VarFormatFromTokens", [140u] = "VarTokenizeFormatString", [141u] = "VarAdd", [142u] = "VarAnd", [143u] = "VarDiv", [144u] = "BSTR_UserFree64", [145u] = "BSTR_UserMarshal64", [146u] = "DispCallFunc", [147u] = "VariantChangeTypeEx", [148u] = "SafeArrayPtrOfIndex", [149u] = "SysStringByteLen", [150u] = "SysAllocStringByteLen", [151u] = "BSTR_UserSize64", [152u] = "VarEqv", [153u] = "VarIdiv", [154u] = "VarImp", [155u] = "VarMod", [156u] = "VarMul", [157u] = "VarOr", [158u] = "VarPow", [159u] = "VarSub", [160u] = "CreateTypeLib", [161u] = "LoadTypeLib", [162u] = "LoadRegTypeLib", [163u] = "RegisterTypeLib", [164u] = "QueryPathOfRegTypeLib", [165u] = "LHashValOfNameSys", [166u] = "LHashValOfNameSysA", [167u] = "VarXor", [168u] = "VarAbs", [169u] = "VarFix", [170u] = "OaBuildVersion", [171u] = "ClearCustData", [172u] = "VarInt", [173u] = "VarNeg", [174u] = "VarNot", [175u] = "VarRound", [176u] = "VarCmp", [177u] = "VarDecAdd", [178u] = "VarDecDiv", [179u] = "VarDecMul", [180u] = "CreateTypeLib2", [181u] = "VarDecSub", [182u] = "VarDecAbs", [183u] = "LoadTypeLibEx", [184u] = "SystemTimeToVariantTime", [185u] = "VariantTimeToSystemTime", [186u] = "UnRegisterTypeLib", [187u] = "VarDecFix", [188u] = "VarDecInt", [189u] = "VarDecNeg", [190u] = "VarDecFromUI1", [191u] = "VarDecFromI2", [192u] = "VarDecFromI4", [193u] = "VarDecFromR4", [194u] = "VarDecFromR8", [195u] = "VarDecFromDate", [196u] = "VarDecFromCy", [197u] = "VarDecFromStr", [198u] = "VarDecFromDisp", [199u] = "VarDecFromBool", [200u] = "GetErrorInfo", [201u] = "SetErrorInfo", [202u] = "CreateErrorInfo", [203u] = "VarDecRound", [204u] = "VarDecCmp", [205u] = "VarI2FromI1", [206u] = "VarI2FromUI2", [207u] = "VarI2FromUI4", [208u] = "VarI2FromDec", [209u] = "VarI4FromI1", [210u] = "VarI4FromUI2", [211u] = "VarI4FromUI4", [212u] = "VarI4FromDec", [213u] = "VarR4FromI1", [214u] = "VarR4FromUI2", [215u] = "VarR4FromUI4", [216u] = "VarR4FromDec", [217u] = "VarR8FromI1", [218u] = "VarR8FromUI2", [219u] = "VarR8FromUI4", [220u] = "VarR8FromDec", [221u] = "VarDateFromI1", [222u] = "VarDateFromUI2", [223u] = "VarDateFromUI4", [224u] = "VarDateFromDec", [225u] = "VarCyFromI1", [226u] = "VarCyFromUI2", [227u] = "VarCyFromUI4", [228u] = "VarCyFromDec", [229u] = "VarBstrFromI1", [230u] = "VarBstrFromUI2", [231u] = "VarBstrFromUI4", [232u] = "VarBstrFromDec", [233u] = "VarBoolFromI1", [234u] = "VarBoolFromUI2", [235u] = "VarBoolFromUI4", [236u] = "VarBoolFromDec", [237u] = "VarUI1FromI1", [238u] = "VarUI1FromUI2", [239u] = "VarUI1FromUI4", [240u] = "VarUI1FromDec", [241u] = "VarDecFromI1", [242u] = "VarDecFromUI2", [243u] = "VarDecFromUI4", [244u] = "VarI1FromUI1", [245u] = "VarI1FromI2", [246u] = "VarI1FromI4", [247u] = "VarI1FromR4", [248u] = "VarI1FromR8", [249u] = "VarI1FromDate", [250u] = "VarI1FromCy", [251u] = "VarI1FromStr", [252u] = "VarI1FromDisp", [253u] = "VarI1FromBool", [254u] = "VarI1FromUI2", [255u] = "VarI1FromUI4", [256u] = "VarI1FromDec", [257u] = "VarUI2FromUI1", [258u] = "VarUI2FromI2", [259u] = "VarUI2FromI4", [260u] = "VarUI2FromR4", [261u] = "VarUI2FromR8", [262u] = "VarUI2FromDate", [263u] = "VarUI2FromCy", [264u] = "VarUI2FromStr", [265u] = "VarUI2FromDisp", [266u] = "VarUI2FromBool", [267u] = "VarUI2FromI1", [268u] = "VarUI2FromUI4", [269u] = "VarUI2FromDec", [270u] = "VarUI4FromUI1", [271u] = "VarUI4FromI2", [272u] = "VarUI4FromI4", [273u] = "VarUI4FromR4", [274u] = "VarUI4FromR8", [275u] = "VarUI4FromDate", [276u] = "VarUI4FromCy", [277u] = "VarUI4FromStr", [278u] = "VarUI4FromDisp", [279u] = "VarUI4FromBool", [280u] = "VarUI4FromI1", [281u] = "VarUI4FromUI2", [282u] = "VarUI4FromDec", [283u] = "BSTR_UserSize", [284u] = "BSTR_UserMarshal", [285u] = "BSTR_UserUnmarshal", [286u] = "BSTR_UserFree", [287u] = "VARIANT_UserSize", [288u] = "VARIANT_UserMarshal", [289u] = "VARIANT_UserUnmarshal", [290u] = "VARIANT_UserFree", [291u] = "LPSAFEARRAY_UserSize", [292u] = "LPSAFEARRAY_UserMarshal", [293u] = "LPSAFEARRAY_UserUnmarshal", [294u] = "LPSAFEARRAY_UserFree", [295u] = "LPSAFEARRAY_Size", [296u] = "LPSAFEARRAY_Marshal", [297u] = "LPSAFEARRAY_Unmarshal", [298u] = "VarDecCmpR8", [299u] = "VarCyAdd", [300u] = "BSTR_UserUnmarshal64", [301u] = "DllCanUnloadNow", [302u] = "DllGetClassObject", [303u] = "VarCyMul", [304u] = "VarCyMulI4", [305u] = "VarCySub", [306u] = "VarCyAbs", [307u] = "VarCyFix", [308u] = "VarCyInt", [309u] = "VarCyNeg", [310u] = "VarCyRound", [311u] = "VarCyCmp", [312u] = "VarCyCmpR8", [313u] = "VarBstrCat", [314u] = "VarBstrCmp", [315u] = "VarR8Pow", [316u] = "VarR4CmpR8", [317u] = "VarR8Round", [318u] = "VarCat", [319u] = "VarDateFromUdateEx", [320u] = "DllRegisterServer", [321u] = "DllUnregisterServer", [322u] = "GetRecordInfoFromGuids", [323u] = "GetRecordInfoFromTypeInfo", [324u] = "LPSAFEARRAY_UserFree64", [325u] = "SetVarConversionLocaleSetting", [326u] = "GetVarConversionLocaleSetting", [327u] = "SetOaNoCache", [328u] = "LPSAFEARRAY_UserMarshal64", [329u] = "VarCyMulI8", [330u] = "VarDateFromUdate", [331u] = "VarUdateFromDate", [332u] = "GetAltMonthNames", [333u] = "VarI8FromUI1", [334u] = "VarI8FromI2", [335u] = "VarI8FromR4", [336u] = "VarI8FromR8", [337u] = "VarI8FromCy", [338u] = "VarI8FromDate", [339u] = "VarI8FromStr", [340u] = "VarI8FromDisp", [341u] = "VarI8FromBool", [342u] = "VarI8FromI1", [343u] = "VarI8FromUI2", [344u] = "VarI8FromUI4", [345u] = "VarI8FromDec", [346u] = "VarI2FromI8", [347u] = "VarI2FromUI8", [348u] = "VarI4FromI8", [349u] = "VarI4FromUI8", [350u] = "LPSAFEARRAY_UserSize64", [351u] = "LPSAFEARRAY_UserUnmarshal64", [352u] = "OACreateTypeLib2", [353u] = "SafeArrayAddRef", [354u] = "SafeArrayReleaseData", [355u] = "SafeArrayReleaseDescriptor", [356u] = "SysAddRefString", [357u] = "SysReleaseString", [358u] = "VARIANT_UserFree64", [359u] = "VARIANT_UserMarshal64", [360u] = "VarR4FromI8", [361u] = "VarR4FromUI8", [362u] = "VarR8FromI8", [363u] = "VarR8FromUI8", [364u] = "VarDateFromI8", [365u] = "VarDateFromUI8", [366u] = "VarCyFromI8", [367u] = "VarCyFromUI8", [368u] = "VarBstrFromI8", [369u] = "VarBstrFromUI8", [370u] = "VarBoolFromI8", [371u] = "VarBoolFromUI8", [372u] = "VarUI1FromI8", [373u] = "VarUI1FromUI8", [374u] = "VarDecFromI8", [375u] = "VarDecFromUI8", [376u] = "VarI1FromI8", [377u] = "VarI1FromUI8", [378u] = "VarUI2FromI8", [379u] = "VarUI2FromUI8", [380u] = "VARIANT_UserSize64", [381u] = "VARIANT_UserUnmarshal64", [401u] = "OleLoadPictureEx", [402u] = "OleLoadPictureFileEx", [411u] = "SafeArrayCreateVector", [412u] = "SafeArrayCopyData", [413u] = "VectorFromBstr", [414u] = "BstrFromVector", [415u] = "OleIconToCursor", [416u] = "OleCreatePropertyFrameIndirect", [417u] = "OleCreatePropertyFrame", [418u] = "OleLoadPicture", [419u] = "OleCreatePictureIndirect", [420u] = "OleCreateFontIndirect", [421u] = "OleTranslateColor", [422u] = "OleLoadPictureFile", [423u] = "OleSavePictureFile", [424u] = "OleLoadPicturePath", [425u] = "VarUI4FromI8", [426u] = "VarUI4FromUI8", [427u] = "VarI8FromUI8", [428u] = "VarUI8FromI8", [429u] = "VarUI8FromUI1", [430u] = "VarUI8FromI2", [431u] = "VarUI8FromR4", [432u] = "VarUI8FromR8", [433u] = "VarUI8FromCy", [434u] = "VarUI8FromDate", [435u] = "VarUI8FromStr", [436u] = "VarUI8FromDisp", [437u] = "VarUI8FromBool", [438u] = "VarUI8FromI1", [439u] = "VarUI8FromUI2", [440u] = "VarUI8FromUI4", [441u] = "VarUI8FromDec", [442u] = "RegisterTypeLibForUser", [443u] = "UnRegisterTypeLibForUser", [444u] = "OaEnablePerUserTLibRegistration", [445u] = "HWND_UserFree", [446u] = "HWND_UserMarshal", [447u] = "HWND_UserSize", [448u] = "HWND_UserUnmarshal", [449u] = "HWND_UserFree64", [450u] = "HWND_UserMarshal64", [451u] = "HWND_UserSize64", [452u] = "HWND_UserUnmarshal64", [500u] = "OACleanup" }; private static readonly Dictionary> _staticMappings = new Dictionary> { ["ws2_32"] = _ws2_32OrdinalMapping, ["oleaut32"] = _oleaut32OrdinalMapping }; public static DefaultSymbolResolver Instance { get; } = new DefaultSymbolResolver(); private DefaultSymbolResolver() { } public ExportedSymbol? Resolve(ImportedSymbol symbol) { if (symbol.DeclaringModule?.Name == null) { return null; } string text = symbol.DeclaringModule.Name; if (text.EndsWith(".dll")) { text = text.Remove(text.Length - 4); } if (!_staticMappings.TryGetValue(text, out Dictionary value)) { return null; } if (!value.TryGetValue(symbol.Ordinal, out var value2)) { return null; } return new ExportedSymbol(SegmentReference.Null, value2); } } public sealed class EmptySymbolResolver : ISymbolResolver { public static EmptySymbolResolver Instance { get; } = new EmptySymbolResolver(); private EmptySymbolResolver() { } public ExportedSymbol? Resolve(ImportedSymbol symbol) { return null; } } public interface IImportedModule { string? Name { get; set; } uint TimeDateStamp { get; set; } uint ForwarderChain { get; set; } IList Symbols { get; } } public class ImportedModule : IImportedModule { private IList? _members; public string? Name { get; set; } public uint TimeDateStamp { get; set; } public uint ForwarderChain { get; set; } public IList Symbols { get { if (_members == null) { Interlocked.CompareExchange(ref _members, GetSymbols(), null); } return _members; } } protected ImportedModule() { } public ImportedModule(string name) { Name = name ?? throw new ArgumentNullException("name"); } public static IImportedModule? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { SerializedImportedModule serializedImportedModule = new SerializedImportedModule(context, ref reader); if (!serializedImportedModule.IsEmpty) { return serializedImportedModule; } return null; } protected virtual IList GetSymbols() { return (IList)new OwnedCollection((IImportedModule)this); } public override string ToString() { return Name + " (" + Symbols.Count + " symbols)"; } } public class ImportedSymbol : IOwnedCollectionElement, ISymbol { private ushort _ordinalOrHint; public IImportedModule? DeclaringModule { get; private set; } IImportedModule? IOwnedCollectionElement.Owner { get { return DeclaringModule; } set { DeclaringModule = value; } } public ushort Ordinal { get { return _ordinalOrHint; } set { _ordinalOrHint = value; Name = null; } } public ushort Hint { get { return _ordinalOrHint; } set { _ordinalOrHint = value; } } public string? Name { get; set; } public ISegmentReference? AddressTableEntry { get; set; } public bool IsImportByOrdinal => Name == null; [MemberNotNullWhen(true, "Name")] public bool IsImportByName { [MemberNotNullWhen(true, "Name")] get { return Name != null; } } public ImportedSymbol(ushort ordinal) { Ordinal = ordinal; } public ImportedSymbol(ushort hint, string name) { Hint = hint; Name = name ?? throw new ArgumentNullException("name"); } public override string ToString() { string value = ((DeclaringModule == null) ? string.Empty : (DeclaringModule.Name + "!")); string value2 = ((AddressTableEntry == null) ? "???" : ((IOffsetProvider)AddressTableEntry).Rva.ToString("X8")); if (IsImportByOrdinal) { return $"{value}#{Ordinal.ToString()} ({value2})"; } return $"{value}{Name} ({value2})"; } public ISegmentReference? GetReference() { return AddressTableEntry; } } public static class ImportHash { private static readonly string[] Extensions = new string[3] { ".dll", ".sys", ".ocx" }; public static byte[] GetImportHash(this IPEImage image) { return image.GetImportHash(DefaultSymbolResolver.Instance); } public static byte[] GetImportHash(this IPEImage image, ISymbolResolver symbolResolver) { List list = new List(); for (int i = 0; i < image.Imports.Count; i++) { IImportedModule importedModule = image.Imports[i]; string text = FormatModuleName(importedModule); for (int j = 0; j < importedModule.Symbols.Count; j++) { list.Add(text + "." + FormatSymbolName(importedModule.Symbols[j], symbolResolver)); } } using MD5 mD = MD5.Create(); return mD.ComputeHash(Encoding.ASCII.GetBytes(string.Join(",", list))); } private static string FormatModuleName(IImportedModule module) { string text = module.Name; if (string.IsNullOrEmpty(text)) { return text; } string[] extensions = Extensions; foreach (string text2 in extensions) { if (text.EndsWith(text2)) { text = text.Remove(text.Length - text2.Length); break; } } return text.ToLowerInvariant(); } private static string FormatSymbolName(ImportedSymbol symbol, ISymbolResolver symbolResolver) { if (symbol.IsImportByName) { return symbol.Name.ToLowerInvariant(); } ExportedSymbol? obj = symbolResolver.Resolve(symbol) ?? throw new ArgumentException($"Failed to resolve {symbol}."); if (!obj.IsByName) { throw new ArgumentException($"Resolved export for {symbol} has no name."); } return obj.Name.ToLowerInvariant(); } } public interface ISymbolResolver { ExportedSymbol? Resolve(ImportedSymbol symbol); } public class SerializedImportedModule : ImportedModule { public const uint ModuleImportSize = 20u; private readonly PEReaderContext _context; private readonly uint _lookupRva; private readonly uint _addressRva; public bool IsEmpty { get { if (_lookupRva == 0 && base.TimeDateStamp == 0 && base.ForwarderChain == 0 && base.Name == null) { return _addressRva == 0; } return false; } } public SerializedImportedModule(PEReaderContext context, ref BinaryStreamReader reader) { if (!((BinaryStreamReader)(ref reader)).IsValid) { throw new ArgumentNullException("reader"); } _context = context ?? throw new ArgumentNullException("context"); _lookupRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.ForwarderChain = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _addressRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); if (num != 0) { BinaryStreamReader val = default(BinaryStreamReader); if (_context.File.TryCreateReaderAtRva(num, ref val)) { base.Name = ((BinaryStreamReader)(ref val)).ReadAsciiString(); } else { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Import module contains an invalid name RVA."); } } } protected override IList GetSymbols() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 OwnedCollection val = new OwnedCollection((IImportedModule)this); if (IsEmpty) { return (IList)val; } bool flag = (int)_context.File.OptionalHeader.Magic == 267; ulong num; int num2; if (!flag) { num = 9223372036854775808uL; num2 = 8; } else { num = 2147483648uL; num2 = 4; } BinaryStreamReader val2 = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_lookupRva, ref val2)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Imported module \"" + base.Name + "\" has an invalid import lookup thunk table RVA."); return (IList)val; } BinaryStreamReader val3 = default(BinaryStreamReader); while (true) { ulong num3 = ((BinaryStreamReader)(ref val2)).ReadNativeInt(flag); if (num3 == 0L) { break; } ImportedSymbol importedSymbol; if ((num3 & num) != 0L) { importedSymbol = new ImportedSymbol((ushort)(num3 & 0xFFFF)); } else { uint num4 = (uint)(num3 & 0xFFFFFFFFu); if (!_context.File.TryCreateReaderAtRva(num4, ref val3)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid Hint-Name RVA for import {base.Name}!#{((LazyList)(object)val).Count.ToString()}."); importedSymbol = new ImportedSymbol(0, "<<>>"); } else { importedSymbol = new ImportedSymbol(((BinaryStreamReader)(ref val3)).ReadUInt16(), ((BinaryStreamReader)(ref val3)).ReadAsciiString()); } } importedSymbol.AddressTableEntry = ((ISegmentReferenceFactory)_context.File).GetReferenceToRva((uint)(_addressRva + ((LazyList)(object)val).Count * num2)); ((LazyList)(object)val).Add(importedSymbol); } return (IList)val; } } [DebuggerDisplay("Count = {Count}")] public class SerializedImportedModuleList : LazyList { private readonly PEReaderContext _context; private readonly DataDirectory _dataDirectory; public SerializedImportedModuleList(PEReaderContext context, in DataDirectory dataDirectory) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _dataDirectory = dataDirectory; } protected override void Initialize() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_dataDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid import data directory RVA and/or size."); return; } while (true) { IImportedModule importedModule = ImportedModule.FromReader(_context, ref reader); if (importedModule != null) { base.Items.Add(importedModule); continue; } break; } } } } namespace AsmResolver.PE.Imports.Builder { public class HintNameTableBuffer : SegmentBase { private readonly List _modules = new List(); private readonly Dictionary _moduleNameOffsets = new Dictionary(); private readonly Dictionary _hintNameOffsets = new Dictionary(); private uint _length; public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); ulong num = ((RelocationParameters)(ref parameters)).Offset; foreach (IImportedModule module in _modules) { foreach (ImportedSymbol symbol in module.Symbols) { if (symbol.IsImportByName) { _hintNameOffsets[symbol] = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); num += (uint)(2 + Encoding.ASCII.GetByteCount(symbol.Name) + 1); num = Extensions.Align(num, 2uL); } } _moduleNameOffsets[module] = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); if (module.Name != null) { num += (uint)Encoding.ASCII.GetByteCount(module.Name); } num++; } _length = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); } public void AddModule(IImportedModule module) { _modules.Add(module); } public uint GetModuleNameRva(IImportedModule module) { return ((SegmentBase)this).Rva + _moduleNameOffsets[module]; } public uint GetHintNameRva(ImportedSymbol member) { return ((SegmentBase)this).Rva + _hintNameOffsets[member]; } public override uint GetPhysicalSize() { return _length; } public override void Write(IBinaryStreamWriter writer) { foreach (IImportedModule module in _modules) { foreach (ImportedSymbol symbol in module.Symbols) { if (symbol.IsImportByName) { WriteHintName(writer, symbol.Hint, symbol.Name); } } WriteModuleName(writer, module); } } private static void WriteHintName(IBinaryStreamWriter writer, ushort hint, string name) { writer.WriteUInt16(hint); IOExtensions.WriteAsciiString(writer, name); writer.WriteByte((byte)0); IOExtensions.Align(writer, 2u); } private static void WriteModuleName(IBinaryStreamWriter writer, IImportedModule module) { IOExtensions.WriteAsciiString(writer, module.Name ?? string.Empty); writer.WriteByte((byte)0); } } public interface IImportAddressProvider { uint GetThunkRva(string module, string member); } public class ImportAddressDirectoryBuffer : ImportDirectoryBufferBase { public ImportAddressDirectoryBuffer(HintNameTableBuffer hintNameTable, bool is32Bit) : base(hintNameTable, is32Bit) { } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = parameters; for (int i = 0; i < base.Modules.Count; i++) { IImportedModule module = base.Modules[i]; ThunkTableBuffer moduleThunkTable = GetModuleThunkTable(module); uint physicalSize = ((SegmentBase)moduleThunkTable).GetPhysicalSize(); ((SegmentBase)moduleThunkTable).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(physicalSize); } } protected override ThunkTableBuffer CreateThunkTable() { return new ThunkTableBuffer(base.HintNameTable, base.Is32Bit, isIat: true); } } public class ImportDirectoryBuffer : ImportDirectoryBufferBase { private uint _entriesLength; public ImportAddressDirectoryBuffer ImportAddressDirectory { get; } public ImportDirectoryBuffer(bool is32Bit) : base(new HintNameTableBuffer(), is32Bit) { ImportAddressDirectory = new ImportAddressDirectoryBuffer(base.HintNameTable, is32Bit); } public override void AddModule(IImportedModule module) { if (_entriesLength == 0) { _entriesLength = 20u; } _entriesLength += 20u; ImportAddressDirectory.AddModule(module); base.AddModule(module); base.HintNameTable.AddModule(module); } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(_entriesLength); foreach (IImportedModule module in base.Modules) { ThunkTableBuffer moduleThunkTable = GetModuleThunkTable(module); uint physicalSize = ((SegmentBase)moduleThunkTable).GetPhysicalSize(); ((SegmentBase)moduleThunkTable).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(physicalSize); } ((SegmentBase)base.HintNameTable).UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return _entriesLength + base.GetPhysicalSize() + ((SegmentBase)base.HintNameTable).GetPhysicalSize(); } public override void Write(IBinaryStreamWriter writer) { WriteModuleImportEntries(writer); base.Write(writer); ((SegmentBase)base.HintNameTable).Write(writer); } private void WriteModuleImportEntries(IBinaryStreamWriter writer) { foreach (IImportedModule module in base.Modules) { WriteModuleImportEntry(writer, module); } WriteModuleImportEntry(writer, 0u, 0u, 0u, 0u, 0u); } private void WriteModuleImportEntry(IBinaryStreamWriter writer, IImportedModule module) { WriteModuleImportEntry(writer, ((SegmentBase)GetModuleThunkTable(module)).Rva, module.TimeDateStamp, module.ForwarderChain, base.HintNameTable.GetModuleNameRva(module), ((SegmentBase)ImportAddressDirectory.GetModuleThunkTable(module)).Rva); } private static void WriteModuleImportEntry(IBinaryStreamWriter writer, uint oft, uint timeDateStamp, uint forwarderChain, uint moduleNameRva, uint ft) { writer.WriteUInt32(oft); writer.WriteUInt32(timeDateStamp); writer.WriteUInt32(forwarderChain); writer.WriteUInt32(moduleNameRva); writer.WriteUInt32(ft); } } public abstract class ImportDirectoryBufferBase : SegmentBase, IImportAddressProvider { private readonly Dictionary _lookupTables = new Dictionary(); private uint _lookupTablesLength; public bool Is32Bit { get; } public int Count => Modules.Count; protected IList Modules { get; } = new List(); public HintNameTableBuffer HintNameTable { get; } protected ImportDirectoryBufferBase(HintNameTableBuffer hintNameTable, bool is32Bit) { HintNameTable = hintNameTable ?? throw new ArgumentNullException("hintNameTable"); Is32Bit = is32Bit; } public virtual void AddModule(IImportedModule module) { Modules.Add(module); AddLookupTable(module); } public ThunkTableBuffer GetModuleThunkTable(IImportedModule module) { return _lookupTables[module]; } public uint GetThunkRva(string moduleName, string memberName) { string moduleName2 = moduleName; string memberName2 = memberName; IImportedModule importedModule = Modules.FirstOrDefault((IImportedModule x) => x.Name == moduleName2); if (importedModule == null) { throw new ArgumentException("Module " + moduleName2 + " is not imported.", "moduleName"); } ImportedSymbol importedSymbol = importedModule.Symbols.FirstOrDefault((ImportedSymbol x) => x.Name == memberName2); if (importedSymbol == null) { throw new ArgumentException($"Member {moduleName2}!{memberName2} is not imported.", "memberName"); } return GetModuleThunkTable(importedModule).GetMemberThunkRva(importedSymbol); } private void AddLookupTable(IImportedModule module) { ThunkTableBuffer thunkTableBuffer = CreateThunkTable(); foreach (ImportedSymbol symbol in module.Symbols) { thunkTableBuffer.AddMember(symbol); } _lookupTables.Add(module, thunkTableBuffer); _lookupTablesLength += ((SegmentBase)thunkTableBuffer).GetPhysicalSize(); } protected virtual ThunkTableBuffer CreateThunkTable() { return new ThunkTableBuffer(HintNameTable, Is32Bit, isIat: false); } public override uint GetPhysicalSize() { return _lookupTablesLength; } public override void Write(IBinaryStreamWriter writer) { foreach (IImportedModule module in Modules) { ((SegmentBase)_lookupTables[module]).Write(writer); } } } public class ThunkTableBuffer : SegmentBase { private readonly List _members = new List(); private readonly Dictionary _memberOffsets = new Dictionary(); private readonly HintNameTableBuffer _hintNameTable; private readonly bool _isIat; private uint _length; public bool Is32Bit { get; } public uint ThunkSize { get { if (!Is32Bit) { return 8u; } return 4u; } } public ThunkTableBuffer(HintNameTableBuffer hintNameTable, bool is32Bit, bool isIat) { _hintNameTable = hintNameTable ?? throw new ArgumentNullException("hintNameTable"); _isIat = isIat; Is32Bit = is32Bit; _length = ThunkSize; } public void AddMember(ImportedSymbol entry) { uint num = _length - ThunkSize; if (_isIat) { entry.AddressTableEntry = Extensions.ToReference((ISegment)(object)this, (int)num); } _memberOffsets.Add(entry, num); _members.Add(entry); _length += ThunkSize; } public uint GetMemberThunkRva(ImportedSymbol member) { return ((SegmentBase)this).Rva + _memberOffsets[member]; } public override uint GetPhysicalSize() { return _length; } public override void Write(IBinaryStreamWriter writer) { foreach (ImportedSymbol member in _members) { ulong num = (ulong)(member.IsImportByName ? _hintNameTable.GetHintNameRva(member) : (member.Ordinal | (1L << (Is32Bit ? 31 : 63)))); if (Is32Bit) { writer.WriteUInt32((uint)num); } else { writer.WriteUInt64(num); } } if (Is32Bit) { writer.WriteUInt32(0u); } else { writer.WriteUInt64(0uL); } } } } namespace AsmResolver.PE.Exports { public class ExportDirectory : IExportDirectory { private readonly LazyVariable _name; private IList? _exports; public uint ExportFlags { get; set; } public uint TimeDateStamp { get; set; } = uint.MaxValue; public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public string? Name { get { return _name.Value; } set { _name.Value = value; } } public uint BaseOrdinal { get; set; } = 1u; public IList Entries { get { if (_exports == null) { Interlocked.CompareExchange(ref _exports, GetExports(), null); } return _exports; } } protected ExportDirectory() { _name = new LazyVariable((Func)GetName); } public ExportDirectory(string name) { _name = new LazyVariable(name ?? throw new ArgumentNullException("name")); } protected virtual string? GetName() { return null; } protected virtual IList GetExports() { return (IList)new ExportedSymbolCollection(this); } } public class ExportedSymbol : IOwnedCollectionElement, ISymbol { public IExportDirectory? ParentDirectory { get; private set; } IExportDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } internal int Index { get; set; } public uint Ordinal { get { if (Index != -1) { return (uint)Index + (ParentDirectory?.BaseOrdinal ?? 0); } return 0u; } } [MemberNotNullWhen(false, "Name")] public bool IsByOrdinal { [MemberNotNullWhen(false, "Name")] get { return Name == null; } } [MemberNotNullWhen(true, "Name")] public bool IsByName { [MemberNotNullWhen(true, "Name")] get { return Name != null; } } public string? Name { get; set; } public ISegmentReference Address { get; set; } public ExportedSymbol(ISegmentReference address) { Name = null; Address = address; } public ExportedSymbol(ISegmentReference address, string? name) { Name = name; Address = address; } public override string ToString() { string text = Name ?? ("#" + Ordinal); if (ParentDirectory != null) { return ParentDirectory.Name + "!" + text; } return text; } public ISegmentReference GetReference() { return Address; } } public class ExportedSymbolCollection : OwnedCollection { public ExportedSymbolCollection(IExportDirectory owner) : base(owner) { } private void UpdateIndicesAfterIndex(int index) { for (int i = index; i < ((LazyList)(object)this).Count; i++) { ((LazyList)(object)this).Items[i].Index = i; } } protected override void OnClearItems() { lock (((LazyList)(object)this).Items) { foreach (ExportedSymbol item in ((LazyList)(object)this).Items) { item.Index = -1; } base.OnClearItems(); } } protected override void OnInsertItem(int index, ExportedSymbol item) { lock (((LazyList)(object)this).Items) { base.OnInsertItem(index, item); UpdateIndicesAfterIndex(index); } } protected override void OnInsertRange(int index, IEnumerable items) { lock (((LazyList)(object)this).Items) { ExportedSymbol[] array = (items as ExportedSymbol[]) ?? items.ToArray(); base.OnInsertRange(index, (IEnumerable)array); for (int i = index; i < ((LazyList)(object)this).Count; i++) { ((LazyList)(object)this).Items[i].Index = i; } } } protected override void OnRemoveItem(int index) { lock (((LazyList)(object)this).Items) { ((LazyList)(object)this).Items[index].Index = -1; base.OnRemoveItem(index); UpdateIndicesAfterIndex(index); } } protected override void OnSetItem(int index, ExportedSymbol item) { lock (((LazyList)(object)this).Items) { base.AssertNotNullAndHasNoOwner(item); ((LazyList)(object)this).Items[index].Index = -1; base.OnSetItem(index, item); item.Index = index; } } } public interface IExportDirectory { uint ExportFlags { get; set; } uint TimeDateStamp { get; set; } ushort MajorVersion { get; set; } ushort MinorVersion { get; set; } string? Name { get; set; } uint BaseOrdinal { get; set; } IList Entries { get; } } public class SerializedExportDirectory : ExportDirectory { private readonly PEReaderContext _context; private readonly uint _nameRva; private readonly uint _numberOfFunctions; private readonly uint _numberOfNames; private readonly uint _addressTableRva; private readonly uint _namePointerRva; private readonly uint _ordinalTableRva; public SerializedExportDirectory(PEReaderContext context, ref BinaryStreamReader reader) { if (!((BinaryStreamReader)(ref reader)).IsValid) { throw new ArgumentNullException("reader"); } _context = context ?? throw new ArgumentNullException("context"); base.ExportFlags = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); _nameRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.BaseOrdinal = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _numberOfFunctions = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _numberOfNames = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _addressTableRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _namePointerRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _ordinalTableRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); } protected override string? GetName() { BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_nameRva, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid name RVA."); return null; } return ((BinaryStreamReader)(ref val)).ReadAsciiString(); } protected override IList GetExports() { ExportedSymbolCollection exportedSymbolCollection = new ExportedSymbolCollection(this); if (_numberOfFunctions == 0) { return (IList)exportedSymbolCollection; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_addressTableRva, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid address table RVA."); return (IList)exportedSymbolCollection; } IDictionary dictionary = null; if (_namePointerRva != 0 || _ordinalTableRva != 0) { BinaryStreamReader namePointerReader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_namePointerRva, ref namePointerReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid name pointer table RVA."); } BinaryStreamReader ordinalReader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_ordinalTableRva, ref ordinalReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid ordinal table RVA."); } if (((BinaryStreamReader)(ref namePointerReader)).IsValid || ((BinaryStreamReader)(ref ordinalReader)).IsValid) { dictionary = ReadOrdinalNameTable(ref namePointerReader, ref ordinalReader); } } for (uint num = 0u; num < _numberOfFunctions; num++) { uint num2 = ((BinaryStreamReader)(ref val)).ReadUInt32(); string value = null; dictionary?.TryGetValue(num, out value); ((LazyList)(object)exportedSymbolCollection).Add(new ExportedSymbol(((ISegmentReferenceFactory)_context.File).GetReferenceToRva(num2), value)); } return (IList)exportedSymbolCollection; } private Dictionary ReadOrdinalNameTable(ref BinaryStreamReader namePointerReader, ref BinaryStreamReader ordinalReader) { Dictionary dictionary = new Dictionary(); BinaryStreamReader val = default(BinaryStreamReader); for (int i = 0; i < _numberOfNames; i++) { uint key = ((BinaryStreamReader)(ref ordinalReader)).ReadUInt16(); uint num = ((BinaryStreamReader)(ref namePointerReader)).ReadUInt32(); if (_context.File.TryCreateReaderAtRva(num, ref val)) { dictionary[key] = ((BinaryStreamReader)(ref val)).ReadAsciiString(); } } return dictionary; } } } namespace AsmResolver.PE.Exports.Builder { public class ExportAddressTableBuffer : SegmentBase { private readonly List _entries = new List(); public void AddSymbol(ExportedSymbol symbol) { _entries.Add(symbol); } public override uint GetPhysicalSize() { return (uint)(_entries.Count * 4); } public override void Write(IBinaryStreamWriter writer) { foreach (ExportedSymbol entry in _entries) { writer.WriteUInt32(((IOffsetProvider)entry.Address).Rva); } } } public class ExportDirectoryBuffer : SegmentBase { public const uint ExportDirectoryHeaderSize = 40u; private readonly SegmentBuilder _contentsBuilder; private readonly ExportAddressTableBuffer _addressTableBuffer; private readonly OrdinalNamePointerTableBuffer _ordinalNamePointerTable; private readonly NameTableBuffer _nameTableBuffer; private IExportDirectory? _exportDirectory; [MemberNotNullWhen(false, "_exportDirectory")] public bool IsEmpty { [MemberNotNullWhen(false, "_exportDirectory")] get { return _exportDirectory == null; } } public ExportDirectoryBuffer() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown _addressTableBuffer = new ExportAddressTableBuffer(); _nameTableBuffer = new NameTableBuffer(); _ordinalNamePointerTable = new OrdinalNamePointerTableBuffer(_nameTableBuffer); SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(object)_addressTableBuffer); val.Add((ISegment)(object)_ordinalNamePointerTable); val.Add((ISegment)(object)_nameTableBuffer); _contentsBuilder = val; } public void AddDirectory(IExportDirectory exportDirectory) { if (!IsEmpty) { throw new InvalidProgramException("Cannot add a secondary export directory to the buffer."); } _exportDirectory = exportDirectory; _nameTableBuffer.AddName(exportDirectory.Name); foreach (ExportedSymbol entry in exportDirectory.Entries) { _addressTableBuffer.AddSymbol(entry); _ordinalNamePointerTable.AddSymbol(entry); if (entry.IsByName) { _nameTableBuffer.AddName(entry.Name); } } } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); SegmentBuilder contentsBuilder = _contentsBuilder; RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(40u); contentsBuilder.UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return 40 + _contentsBuilder.GetPhysicalSize(); } public override void Write(IBinaryStreamWriter writer) { WriteExportDirectoryHeader(writer); _contentsBuilder.Write(writer); } private void WriteExportDirectoryHeader(IBinaryStreamWriter writer) { if (_exportDirectory == null) { _exportDirectory = new ExportDirectory(string.Empty); } writer.WriteUInt32(_exportDirectory.ExportFlags); writer.WriteUInt32(_exportDirectory.TimeDateStamp); writer.WriteUInt16(_exportDirectory.MajorVersion); writer.WriteUInt16(_exportDirectory.MinorVersion); writer.WriteUInt32(_nameTableBuffer.GetNameRva(_exportDirectory.Name)); writer.WriteUInt32(_exportDirectory.BaseOrdinal); writer.WriteUInt32((uint)_exportDirectory.Entries.Count); writer.WriteUInt32((uint)_exportDirectory.Entries.Count((ExportedSymbol e) => e.IsByName)); writer.WriteUInt32(((SegmentBase)_addressTableBuffer).Rva); writer.WriteUInt32(_ordinalNamePointerTable.NamePointerTableRva); writer.WriteUInt32(_ordinalNamePointerTable.OrdinalTableRva); } } public class NameTableBuffer : SegmentBase { private readonly List _entries = new List(); private readonly Dictionary _nameOffsets = new Dictionary(); private uint _length; public void AddName(string? name) { if (!string.IsNullOrEmpty(name) && !_nameOffsets.ContainsKey(name)) { _entries.Add(name); _nameOffsets.Add(name, _length); _length += (uint)(Encoding.ASCII.GetByteCount(name) + 1); } } public uint GetNameRva(string? name) { if (name == null) { return 0u; } return ((SegmentBase)this).Rva + _nameOffsets[name]; } public override uint GetPhysicalSize() { return _length; } public override void Write(IBinaryStreamWriter writer) { foreach (string entry in _entries) { IOExtensions.WriteAsciiString(writer, entry); writer.WriteByte((byte)0); } } } public class OrdinalNamePointerTableBuffer : SegmentBase { private readonly NameTableBuffer _nameTableBuffer; private readonly List _ordinals = new List(); private readonly List _namedEntries = new List(); public uint OrdinalTableRva => ((SegmentBase)this).Rva; public uint OrdinalTableSize => (uint)(_ordinals.Count * 2); public uint NamePointerTableRva => ((SegmentBase)this).Rva + OrdinalTableSize; public uint NamePointerTableSize => (uint)(_namedEntries.Count * 4); public OrdinalNamePointerTableBuffer(NameTableBuffer nameTableBuffer) { _nameTableBuffer = nameTableBuffer ?? throw new ArgumentNullException("nameTableBuffer"); } public void AddSymbol(ExportedSymbol symbol) { if (symbol.ParentDirectory == null) { throw new ArgumentException("Symbol was not added to an export directory."); } if (symbol.IsByName) { _namedEntries.Add(symbol); _ordinals.Add((ushort)(symbol.Ordinal - symbol.ParentDirectory.BaseOrdinal)); } } public override uint GetPhysicalSize() { return OrdinalTableSize + NamePointerTableSize; } public override void Write(IBinaryStreamWriter writer) { WriteOrdinalTable(writer); WriteNamePointerTable(writer); } private void WriteNamePointerTable(IBinaryStreamWriter writer) { foreach (ExportedSymbol namedEntry in _namedEntries) { writer.WriteUInt32(_nameTableBuffer.GetNameRva(namedEntry.Name)); } } private void WriteOrdinalTable(IBinaryStreamWriter writer) { foreach (ushort ordinal in _ordinals) { writer.WriteUInt16(ordinal); } } } } namespace AsmResolver.PE.Exceptions { public class ExceptionDirectory : IExceptionDirectory where TFunction : IRuntimeFunction { private IList? _entries; public IList Entries { get { if (_entries == null) { Interlocked.CompareExchange(ref _entries, GetEntries(), null); } return _entries; } } protected virtual IList GetEntries() { return new List(); } IEnumerable IExceptionDirectory.GetEntries() { return (IEnumerable)Entries; } } public interface IExceptionDirectory { IEnumerable GetEntries(); } public interface IRuntimeFunction { ISegmentReference Begin { get; } ISegmentReference End { get; } } } namespace AsmResolver.PE.Exceptions.X64 { internal class X64ExceptionDirectory : ExceptionDirectory { private readonly PEReaderContext _context; private readonly BinaryStreamReader _reader; public X64ExceptionDirectory(PEReaderContext context, in BinaryStreamReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _reader = reader; } protected override IList GetEntries() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); List list = new List(); while (((BinaryStreamReader)(ref reader)).CanRead(12u)) { X64RuntimeFunction x64RuntimeFunction = X64RuntimeFunction.FromReader(_context, ref reader); if (x64RuntimeFunction == null) { break; } list.Add(x64RuntimeFunction); } return list; } } public class X64RuntimeFunction : IRuntimeFunction, IWritable { public const int EntrySize = 12; public ISegmentReference Begin { get; set; } public ISegmentReference End { get; set; } public X64UnwindInfo? UnwindInfo { get; set; } public X64RuntimeFunction(ISegmentReference begin, ISegmentReference end, X64UnwindInfo? unwindInfo) { Begin = begin; End = end; UnwindInfo = unwindInfo; } public static X64RuntimeFunction FromReader(PEReaderContext context, ref BinaryStreamReader reader) { uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num2 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num3 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); BinaryStreamReader reader2 = default(BinaryStreamReader); X64UnwindInfo unwindInfo = (context.File.TryCreateReaderAtRva(num3, ref reader2) ? X64UnwindInfo.FromReader(context, ref reader2) : ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)context, $"Invalid UnwindInfo RVA {num3:X8}.")); return new X64RuntimeFunction(((ISegmentReferenceFactory)context.File).GetReferenceToRva(num), ((ISegmentReferenceFactory)context.File).GetReferenceToRva(num2), unwindInfo); } public uint GetPhysicalSize() { return 12u; } public void Write(IBinaryStreamWriter writer) { writer.WriteUInt32(((IOffsetProvider)Begin).Rva); writer.WriteUInt32(((IOffsetProvider)End).Rva); X64UnwindInfo? unwindInfo = UnwindInfo; writer.WriteUInt32((unwindInfo != null) ? ((SegmentBase)unwindInfo).Rva : 0u); } } [Flags] public enum X64UnwindFlags : byte { NoHandler = 0, ExceptionHandler = 1, TerminationHandler = 2, ChainedUnwindInfo = 4 } public class X64UnwindInfo : SegmentBase { private byte _firstByte; private byte _frameByte; public byte Version { get { return (byte)(_firstByte & 7u); } set { _firstByte = (byte)((_firstByte & 0xF8u) | (value & 7u)); } } public X64UnwindFlags Flags { get { return (X64UnwindFlags)(_firstByte >> 3); } set { _firstByte = (byte)((_firstByte & 7u) | ((uint)value << 3)); } } public bool IsExceptionHandler { get { return (Flags & X64UnwindFlags.ExceptionHandler) != 0; } set { Flags = (Flags & ~X64UnwindFlags.ExceptionHandler) | (value ? X64UnwindFlags.ExceptionHandler : X64UnwindFlags.NoHandler); } } public bool IsTerminationHandler { get { return (Flags & X64UnwindFlags.TerminationHandler) != 0; } set { Flags = (Flags & ~X64UnwindFlags.TerminationHandler) | (value ? X64UnwindFlags.TerminationHandler : X64UnwindFlags.NoHandler); } } public bool IsChained { get { return (Flags & X64UnwindFlags.ChainedUnwindInfo) != 0; } set { Flags = (Flags & ~X64UnwindFlags.ChainedUnwindInfo) | (value ? X64UnwindFlags.ChainedUnwindInfo : X64UnwindFlags.NoHandler); } } public byte SizeOfProlog { get; set; } public byte FrameRegister { get { return (byte)(_frameByte & 0xFu); } set { _frameByte = (byte)((_frameByte & 0xF0u) | (value & 0xFu)); } } public byte FrameRegisterOffset { get { return (byte)(_frameByte >> 4); } set { _frameByte = (byte)((_frameByte & 0xFu) | (uint)(value << 4)); } } public ushort[] UnwindCodes { get; set; } public ISegmentReference ExceptionHandler { get; set; } public ISegmentReference ExceptionHandlerData { get; set; } public X64RuntimeFunction? ChainedFunction { get; set; } public X64UnwindInfo() { Version = 1; UnwindCodes = Array.Empty(); ExceptionHandler = SegmentReference.Null; ExceptionHandlerData = SegmentReference.Null; } public static X64UnwindInfo FromReader(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) X64UnwindInfo x64UnwindInfo = new X64UnwindInfo(); RelocationParameters relocation = context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); ((SegmentBase)x64UnwindInfo).UpdateOffsets(ref relocation); x64UnwindInfo._firstByte = ((BinaryStreamReader)(ref reader)).ReadByte(); x64UnwindInfo.SizeOfProlog = ((BinaryStreamReader)(ref reader)).ReadByte(); byte b = ((BinaryStreamReader)(ref reader)).ReadByte(); x64UnwindInfo._frameByte = ((BinaryStreamReader)(ref reader)).ReadByte(); ushort[] array = new ushort[b]; for (int i = 0; i < b; i++) { array[i] = ((BinaryStreamReader)(ref reader)).ReadUInt16(); } x64UnwindInfo.UnwindCodes = array; if (x64UnwindInfo.IsExceptionHandler || x64UnwindInfo.IsTerminationHandler) { x64UnwindInfo.ExceptionHandler = ((ISegmentReferenceFactory)context.File).GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()); x64UnwindInfo.ExceptionHandlerData = ((ISegmentReferenceFactory)context.File).GetReferenceToRva(((BinaryStreamReader)(ref reader)).Rva); } else if (x64UnwindInfo.IsChained) { x64UnwindInfo.ChainedFunction = X64RuntimeFunction.FromReader(context, ref reader); } return x64UnwindInfo; } public override uint GetPhysicalSize() { uint num = (uint)(4 + UnwindCodes.Length * 2); if (IsExceptionHandler) { num += 4; } else if (IsChained) { num += 12; } return num; } public override void Write(IBinaryStreamWriter writer) { writer.WriteByte(_firstByte); writer.WriteByte(SizeOfProlog); writer.WriteByte((byte)UnwindCodes.Length); writer.WriteByte(_frameByte); ushort[] unwindCodes = UnwindCodes; foreach (ushort num in unwindCodes) { writer.WriteUInt16(num); } if (IsExceptionHandler || IsTerminationHandler) { writer.WriteUInt32(((IOffsetProvider)ExceptionHandler).Rva); } else if (IsChained && ChainedFunction != null) { ChainedFunction.Write(writer); } } } } namespace AsmResolver.PE.DotNet { public class DotNetDirectory : SegmentBase, IDotNetDirectory, ISegment, IOffsetProvider, IWritable { private readonly LazyVariable _metadata; private readonly LazyVariable _resources; private readonly LazyVariable _strongName; private readonly LazyVariable _codeManagerTable; private readonly LazyVariable _exportAddressTable; private readonly LazyVariable _vtableFixups; private readonly LazyVariable _managedNativeHeader; public ushort MajorRuntimeVersion { get; set; } = 2; public ushort MinorRuntimeVersion { get; set; } = 5; public IMetadata? Metadata { get { return _metadata.Value; } set { _metadata.Value = value; } } public DotNetDirectoryFlags Flags { get; set; } public uint EntryPoint { get; set; } public DotNetResourcesDirectory? DotNetResources { get { return _resources.Value; } set { _resources.Value = value; } } public IReadableSegment? StrongName { get { return _strongName.Value; } set { _strongName.Value = value; } } public IReadableSegment? CodeManagerTable { get { return _codeManagerTable.Value; } set { _codeManagerTable.Value = value; } } public VTableFixupsDirectory? VTableFixups { get { return _vtableFixups.Value; } set { _vtableFixups.Value = value; } } public IReadableSegment? ExportAddressTable { get { return _exportAddressTable.Value; } set { _exportAddressTable.Value = value; } } public IReadableSegment? ManagedNativeHeader { get { return _managedNativeHeader.Value; } set { _managedNativeHeader.Value = value; } } public DotNetDirectory() { _metadata = new LazyVariable((Func)GetMetadata); _resources = new LazyVariable((Func)GetResources); _strongName = new LazyVariable((Func)GetStrongName); _codeManagerTable = new LazyVariable((Func)GetCodeManagerTable); _exportAddressTable = new LazyVariable((Func)GetExportAddressTable); _vtableFixups = new LazyVariable((Func)GetVTableFixups); _managedNativeHeader = new LazyVariable((Func)GetManagedNativeHeader); } public override uint GetPhysicalSize() { return 72u; } public override void Write(IBinaryStreamWriter writer) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) writer.WriteUInt32(((SegmentBase)this).GetPhysicalSize()); writer.WriteUInt16(MajorRuntimeVersion); writer.WriteUInt16(MinorRuntimeVersion); DataDirectory val = CreateDataDirectoryHeader((ISegment?)Metadata); ((DataDirectory)(ref val)).Write(writer); writer.WriteUInt32((uint)Flags); writer.WriteUInt32(EntryPoint); val = CreateDataDirectoryHeader((ISegment?)(object)DotNetResources); ((DataDirectory)(ref val)).Write(writer); val = CreateDataDirectoryHeader((ISegment?)(object)StrongName); ((DataDirectory)(ref val)).Write(writer); val = CreateDataDirectoryHeader((ISegment?)(object)CodeManagerTable); ((DataDirectory)(ref val)).Write(writer); val = CreateDataDirectoryHeader((ISegment?)(object)VTableFixups); ((DataDirectory)(ref val)).Write(writer); val = CreateDataDirectoryHeader((ISegment?)(object)ExportAddressTable); ((DataDirectory)(ref val)).Write(writer); val = CreateDataDirectoryHeader((ISegment?)(object)ManagedNativeHeader); ((DataDirectory)(ref val)).Write(writer); } private static DataDirectory CreateDataDirectoryHeader(ISegment? directoryContents) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (directoryContents == null) { return new DataDirectory(0u, 0u); } return new DataDirectory(((IOffsetProvider)directoryContents).Rva, ((IWritable)directoryContents).GetPhysicalSize()); } protected virtual IMetadata? GetMetadata() { return null; } protected virtual DotNetResourcesDirectory? GetResources() { return null; } protected virtual IReadableSegment? GetStrongName() { return null; } protected virtual IReadableSegment? GetCodeManagerTable() { return null; } protected virtual IReadableSegment? GetExportAddressTable() { return null; } protected virtual VTableFixupsDirectory? GetVTableFixups() { return null; } protected virtual IReadableSegment? GetManagedNativeHeader() { return null; } } [Flags] public enum DotNetDirectoryFlags { ILOnly = 1, Bit32Required = 2, ILLibrary = 4, StrongNameSigned = 8, NativeEntryPoint = 0x10, TrackDebugData = 0x10000, Bit32Preferred = 0x20000 } public interface IDotNetDirectory : ISegment, IOffsetProvider, IWritable { ushort MajorRuntimeVersion { get; set; } ushort MinorRuntimeVersion { get; set; } IMetadata? Metadata { get; set; } DotNetDirectoryFlags Flags { get; set; } uint EntryPoint { get; set; } DotNetResourcesDirectory? DotNetResources { get; set; } IReadableSegment? StrongName { get; set; } IReadableSegment? CodeManagerTable { get; set; } VTableFixupsDirectory? VTableFixups { get; set; } IReadableSegment? ExportAddressTable { get; set; } IReadableSegment? ManagedNativeHeader { get; set; } } public class SerializedDotNetDirectory : DotNetDirectory { private readonly PEReaderContext _context; private readonly DataDirectory _metadataDirectory; private readonly DataDirectory _resourcesDirectory; private readonly DataDirectory _strongNameDirectory; private readonly DataDirectory _codeManagerDirectory; private readonly DataDirectory _vtableFixupsDirectory; private readonly DataDirectory _exportsDirectory; private readonly DataDirectory _nativeHeaderDirectory; public SerializedDotNetDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.MajorRuntimeVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.MinorRuntimeVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); _metadataDirectory = DataDirectory.FromReader(ref reader); base.Flags = (DotNetDirectoryFlags)((BinaryStreamReader)(ref reader)).ReadUInt32(); base.EntryPoint = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _resourcesDirectory = DataDirectory.FromReader(ref reader); _strongNameDirectory = DataDirectory.FromReader(ref reader); _codeManagerDirectory = DataDirectory.FromReader(ref reader); _vtableFixupsDirectory = DataDirectory.FromReader(ref reader); _exportsDirectory = DataDirectory.FromReader(ref reader); _nativeHeaderDirectory = DataDirectory.FromReader(ref reader); } protected override IMetadata? GetMetadata() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _metadataDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_metadataDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid metadata directory RVA and/or size."); return null; } return AsmResolver.PE.DotNet.Metadata.Metadata.FromReader(reader, MetadataReaderContext.FromReaderContext(_context)); } protected override DotNetResourcesDirectory? GetResources() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _resourcesDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_resourcesDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid resources directory RVA and/or size."); return null; } return new SerializedDotNetResourcesDirectory(in reader); } protected override IReadableSegment? GetStrongName() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _strongNameDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_strongNameDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid strong name directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override IReadableSegment? GetCodeManagerTable() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _codeManagerDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_codeManagerDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid code manager directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override VTableFixupsDirectory? GetVTableFixups() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _vtableFixupsDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_vtableFixupsDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid VTable fixups directory RVA and/or size."); return null; } VTableFixupsDirectory vTableFixupsDirectory = new VTableFixupsDirectory(); RelocationParameters parameters = _context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); vTableFixupsDirectory.UpdateOffsets(in parameters); for (int i = 0; i < ((BinaryStreamReader)(ref reader)).Length / 8; i++) { VTableFixup vTableFixup = VTableFixup.FromReader(_context, ref reader); if (vTableFixup == null) { break; } vTableFixupsDirectory.Add(vTableFixup); } return vTableFixupsDirectory; } protected override IReadableSegment? GetExportAddressTable() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _exportsDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_exportsDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid export address directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override IReadableSegment? GetManagedNativeHeader() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _nativeHeaderDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_nativeHeaderDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid native header directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } } } namespace AsmResolver.PE.DotNet.VTableFixups { public class VTableFixup : SegmentBase { public VTableTokenCollection Tokens { get; } = new VTableTokenCollection(); public VTableFixup(VTableType type) { Tokens.Type = type; } public static VTableFixup? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; BinaryStreamReader val = default(BinaryStreamReader); if (!context.File.TryCreateReaderAtRva(((BinaryStreamReader)(ref reader)).ReadUInt32(), ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)context, "VTable fixups directory contains an invalid RVA for the entries of a vtable."); return null; } ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); VTableFixup vTableFixup = new VTableFixup((VTableType)((BinaryStreamReader)(ref reader)).ReadUInt16()); RelocationParameters relocation = context.GetRelocation(offset, rva); ((SegmentBase)vTableFixup).UpdateOffsets(ref relocation); VTableTokenCollection tokens = vTableFixup.Tokens; relocation = context.GetRelocation(((BinaryStreamReader)(ref val)).Offset, ((BinaryStreamReader)(ref val)).Rva); tokens.UpdateOffsets(in relocation); for (int i = 0; i < num; i++) { vTableFixup.Tokens.Add(((vTableFixup.Tokens.Type & VTableType.VTable32Bit) != 0) ? new MetadataToken(((BinaryStreamReader)(ref val)).ReadUInt32()) : new MetadataToken((uint)((BinaryStreamReader)(ref val)).ReadInt64())); } return vTableFixup; } public override uint GetPhysicalSize() { return 8u; } public override void Write(IBinaryStreamWriter writer) { writer.WriteUInt32(Tokens.Rva); writer.WriteUInt16((ushort)Tokens.Count); writer.WriteUInt16((ushort)Tokens.Type); } } public class VTableFixupsDirectory : Collection, ISegment, IOffsetProvider, IWritable { public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; public void UpdateOffsets(in RelocationParameters parameters) { Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; } public uint GetPhysicalSize() { return (uint)this.Sum((VTableFixup v) => ((SegmentBase)v).GetPhysicalSize()); } public void Write(IBinaryStreamWriter writer) { for (int i = 0; i < base.Count; i++) { ((SegmentBase)base[i]).Write(writer); } } public uint GetVirtualSize() { return (uint)this.Sum((VTableFixup v) => ((SegmentBase)v).GetVirtualSize()); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class VTableTokenCollection : Collection, ISegment, IOffsetProvider, IWritable { public VTableType Type { get; set; } public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; protected override void InsertItem(int index, MetadataToken item) { if (base.Count >= 65535) { throw new InvalidOperationException("Number of VTable tokens exceeds the maximum of 65535."); } base.InsertItem(index, item); } public void UpdateOffsets(in RelocationParameters parameters) { Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; } public uint GetPhysicalSize() { return (uint)(base.Count * (((Type & VTableType.VTable32Bit) != 0) ? 4 : 8)); } public void Write(IBinaryStreamWriter writer) { for (int i = 0; i < base.Items.Count; i++) { MetadataToken metadataToken = base.Items[i]; if ((Type & VTableType.VTable32Bit) != 0) { writer.WriteUInt32(metadataToken.ToUInt32()); } else { writer.WriteUInt64((ulong)metadataToken.ToUInt32()); } } } public uint GetVirtualSize() { return GetPhysicalSize(); } public ISegmentReference GetReferenceToIndex(int index) { return Extensions.ToReference((ISegment)(object)this, (int)GetOffsetToIndex(index)); } public uint GetOffsetToIndex(int index) { int num = (((Type & VTableType.VTable32Bit) != 0) ? 4 : 8); return (uint)(index * num); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } [Flags] public enum VTableType : ushort { VTable32Bit = 1, VTable64Bit = 2, VTableFromUnmanaged = 4, VTableCallMostDerived = 0x10 } } namespace AsmResolver.PE.DotNet.StrongName { public enum RsaPublicKeyMagic { Rsa1 = 826364754, Rsa2 = 843141970 } public enum SignatureAlgorithm : uint { RsaSign = 9216u } internal class StrongNameDataHashBuilder { private readonly Stream _imageStream; private readonly AssemblyHashAlgorithm _hashAlgorithm; private readonly List _includedRanges = new List(); private readonly List _zeroRanges = new List(); public StrongNameDataHashBuilder(Stream imageStream, AssemblyHashAlgorithm hashAlgorithm) { _imageStream = imageStream ?? throw new ArgumentNullException("imageStream"); _hashAlgorithm = hashAlgorithm; } public void IncludeRange(OffsetRange range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _includedRanges.Add(range); } public void ExcludeRange(OffsetRange range) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _includedRanges.Count; i++) { OffsetRange val = _includedRanges[i]; var (value, val2) = ((OffsetRange)(ref val)).Exclude(range); if (((OffsetRange)(ref value)).IsEmpty) { _includedRanges[i] = val2; continue; } if (((OffsetRange)(ref val2)).IsEmpty) { _includedRanges[i] = value; continue; } _includedRanges[i] = value; _includedRanges.Insert(i + 1, val2); i++; } } public void ZeroRange(OffsetRange range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _zeroRanges.Add(range); } public byte[] ComputeHash() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) using HashAlgorithm hashAlgorithm = _hashAlgorithm switch { AssemblyHashAlgorithm.Md5 => MD5.Create(), AssemblyHashAlgorithm.Sha1 => SHA1.Create(), AssemblyHashAlgorithm.Sha256 => SHA256.Create(), AssemblyHashAlgorithm.Sha384 => SHA384.Create(), AssemblyHashAlgorithm.Sha512 => SHA512.Create(), _ => throw new NotSupportedException($"Invalid or unsupported hashing algorithm {_hashAlgorithm}."), }; byte[] array = new byte[4096]; OffsetRange currentRange = default(OffsetRange); foreach (OffsetRange includedRange in _includedRanges) { OffsetRange current = includedRange; _imageStream.Position = (long)((OffsetRange)(ref current)).Start; while ((ulong)_imageStream.Position < ((OffsetRange)(ref current)).End) { int num = Math.Min(array.Length, (int)((long)((OffsetRange)(ref current)).End - _imageStream.Position)); ((OffsetRange)(ref currentRange))..ctor((ulong)(uint)_imageStream.Position, (ulong)(uint)(_imageStream.Position + num)); _imageStream.Read(array, 0, num); ZeroRangesIfApplicable(array, currentRange); hashAlgorithm.TransformBlock(array, 0, num, array, 0); } } hashAlgorithm.TransformFinalBlock(Array.Empty(), 0, 0); return hashAlgorithm.Hash; } private void ZeroRangesIfApplicable(byte[] buffer, OffsetRange currentRange) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) foreach (OffsetRange zeroRange in _zeroRanges) { if (((OffsetRange)(ref currentRange)).Intersects(zeroRange)) { OffsetRange val = ((OffsetRange)(ref currentRange)).Intersect(zeroRange); for (ulong num = ((OffsetRange)(ref val)).Start; num < ((OffsetRange)(ref val)).End; num++) { buffer[num] = 0; } } } } } public abstract class StrongNameKeyStructure : SegmentBase { public abstract StrongNameKeyStructureType Type { get; } public abstract byte Version { get; } public abstract SignatureAlgorithm SignatureAlgorithm { get; } protected static void ReadBlobHeader(ref BinaryStreamReader reader, StrongNameKeyStructureType expectedType, byte expectedVersion, SignatureAlgorithm expectedAlgorithm) { if ((uint)((BinaryStreamReader)(ref reader)).ReadByte() != (uint)expectedType) { throw new FormatException("Input stream does not contain the expected structure type."); } if (((BinaryStreamReader)(ref reader)).ReadByte() != expectedVersion) { throw new NotSupportedException("Invalid or unsupported public/private key pair structure version number."); } ((BinaryStreamReader)(ref reader)).ReadUInt16(); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != (uint)expectedAlgorithm) { throw new NotSupportedException("Invalid or unsupported public key algorithm."); } } public override uint GetPhysicalSize() { return 8u; } public override void Write(IBinaryStreamWriter writer) { writer.WriteByte((byte)Type); writer.WriteByte(Version); writer.WriteUInt16((ushort)0); writer.WriteUInt32((uint)SignatureAlgorithm); } } public enum StrongNameKeyStructureType : byte { SimpleBlob = 1, PublicKeyBlob = 6, PrivateKeyBlob = 7, PlainTextKeyBlob = 8, OpaqueKeyBlob = 9, PublicKeyBlobEx = 10, SymmetricWrapKeyBlob = 11, KeyStateBlob = 12 } public class StrongNamePrivateKey : StrongNamePublicKey { public override StrongNameKeyStructureType Type => StrongNameKeyStructureType.PrivateKeyBlob; public override byte Version => 2; public override RsaPublicKeyMagic Magic => RsaPublicKeyMagic.Rsa2; public byte[] P { get; set; } public byte[] Q { get; set; } public byte[] DP { get; set; } public byte[] DQ { get; set; } public byte[] InverseQ { get; set; } public byte[] PrivateExponent { get; set; } public new static StrongNamePrivateKey FromFile(string path) { BinaryStreamReader reader = default(BinaryStreamReader); ((BinaryStreamReader)(ref reader))..ctor(File.ReadAllBytes(path)); return FromReader(ref reader); } public new static StrongNamePrivateKey FromReader(ref BinaryStreamReader reader) { StrongNameKeyStructure.ReadBlobHeader(ref reader, StrongNameKeyStructureType.PrivateKeyBlob, 2, SignatureAlgorithm.RsaSign); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != 843141970) { throw new FormatException("Input stream does not contain a valid RSA private key header magic."); } StrongNamePrivateKey strongNamePrivateKey = new StrongNamePrivateKey(((BinaryStreamReader)(ref reader)).ReadUInt32()) { PublicExponent = ((BinaryStreamReader)(ref reader)).ReadUInt32() }; ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.Modulus, 0, strongNamePrivateKey.Modulus.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.P, 0, strongNamePrivateKey.P.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.Q, 0, strongNamePrivateKey.Q.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.DP, 0, strongNamePrivateKey.DP.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.DQ, 0, strongNamePrivateKey.DQ.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.InverseQ, 0, strongNamePrivateKey.InverseQ.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.PrivateExponent, 0, strongNamePrivateKey.PrivateExponent.Length); Array.Reverse(strongNamePrivateKey.Modulus); Array.Reverse(strongNamePrivateKey.P); Array.Reverse(strongNamePrivateKey.Q); Array.Reverse(strongNamePrivateKey.DP); Array.Reverse(strongNamePrivateKey.DQ); Array.Reverse(strongNamePrivateKey.InverseQ); Array.Reverse(strongNamePrivateKey.PrivateExponent); return strongNamePrivateKey; } public StrongNamePrivateKey(uint bitLength) : base(new byte[bitLength / 8], 65537u) { uint num = bitLength / 8; uint num2 = bitLength / 16; P = new byte[num2]; Q = new byte[num2]; DP = new byte[num2]; DQ = new byte[num2]; InverseQ = new byte[num2]; PrivateExponent = new byte[num]; } public StrongNamePrivateKey(in RSAParameters parameters) : base(parameters.Modulus ?? throw new ArgumentException("The provided RSA parameters do not define a modulus."), ByteSwap(parameters)) { base.Modulus = parameters.Modulus; P = parameters.P ?? throw new ArgumentException("The provided RSA parameters do not define prime P."); Q = parameters.Q ?? throw new ArgumentException("The provided RSA parameters do not define prime Q."); DP = parameters.DP ?? throw new ArgumentException("The provided RSA parameters do not define DP."); DQ = parameters.DQ ?? throw new ArgumentException("The provided RSA parameters do not define DQ."); InverseQ = parameters.InverseQ ?? throw new ArgumentException("The provided RSA parameters do not define InverseQ."); PrivateExponent = parameters.D ?? throw new ArgumentException("The provided RSA parameters do not define D."); } public override RSAParameters ToRsaParameters() { List list = new List(4) { (byte)(base.PublicExponent & 0xFFu), (byte)((base.PublicExponent >> 8) & 0xFFu), (byte)((base.PublicExponent >> 16) & 0xFFu), (byte)((base.PublicExponent >> 24) & 0xFFu) }; int num = list.Count - 1; while (num >= 0 && list[num] == 0) { list.RemoveAt(num); num--; } RSAParameters result = default(RSAParameters); result.Modulus = base.Modulus; result.Exponent = list.ToArray(); result.P = P; result.Q = Q; result.DP = DP; result.DQ = DQ; result.D = PrivateExponent; result.InverseQ = InverseQ; return result; } public override uint GetPhysicalSize() { uint num = (uint)(base.BitLength / 8); uint num2 = (uint)(base.BitLength / 16); return base.GetPhysicalSize() + num2 + num2 + num2 + num2 + num2 + num; } public override void Write(IBinaryStreamWriter writer) { base.Write(writer); IOExtensions.WriteBytes(writer, P); IOExtensions.WriteBytes(writer, Q); IOExtensions.WriteBytes(writer, DP); IOExtensions.WriteBytes(writer, DQ); IOExtensions.WriteBytes(writer, InverseQ); IOExtensions.WriteBytes(writer, PrivateExponent); } private static uint ByteSwap(RSAParameters parameters) { if (parameters.Exponent == null) { throw new ArgumentException("The provided RSA parameters do not define an exponent."); } uint num = 0u; for (int i = 0; i < Math.Min(4, parameters.Exponent.Length); i++) { num |= (uint)(parameters.Exponent[i] << 8 * i); } return num; } } public class StrongNamePublicKey : StrongNameKeyStructure { public override StrongNameKeyStructureType Type => StrongNameKeyStructureType.PublicKeyBlob; public override byte Version => 2; public override SignatureAlgorithm SignatureAlgorithm => SignatureAlgorithm.RsaSign; public virtual RsaPublicKeyMagic Magic => RsaPublicKeyMagic.Rsa1; public int BitLength => Modulus.Length * 8; public uint PublicExponent { get; set; } public byte[] Modulus { get; set; } public static StrongNamePublicKey FromFile(string path) { BinaryStreamReader reader = default(BinaryStreamReader); ((BinaryStreamReader)(ref reader))..ctor(File.ReadAllBytes(path)); return FromReader(ref reader); } public static StrongNamePublicKey FromReader(ref BinaryStreamReader reader) { StrongNameKeyStructure.ReadBlobHeader(ref reader, StrongNameKeyStructureType.PublicKeyBlob, 2, SignatureAlgorithm.RsaSign); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != 826364754) { throw new FormatException("Input stream does not contain a valid RSA public key header magic."); } StrongNamePublicKey strongNamePublicKey = new StrongNamePublicKey(new byte[((BinaryStreamReader)(ref reader)).ReadUInt32() / 8], ((BinaryStreamReader)(ref reader)).ReadUInt32()); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePublicKey.Modulus, 0, strongNamePublicKey.Modulus.Length); return strongNamePublicKey; } private byte[] CopyReversed(byte[] data) { byte[] array = new byte[data.Length]; for (int i = 0; i < data.Length; i++) { array[array.Length - i - 1] = data[i]; } return array; } public StrongNamePublicKey(byte[] modulus, uint publicExponent) { Modulus = modulus ?? throw new ArgumentNullException("modulus"); PublicExponent = publicExponent; } public StrongNamePublicKey(in RSAParameters parameters) { if (parameters.Modulus == null) { throw new ArgumentException("RSA parameters does not define a modulus."); } if (parameters.Exponent == null) { throw new ArgumentException("RSA parameters does not define an exponent."); } Modulus = CopyReversed(parameters.Modulus); uint num = 0u; for (int i = 0; i < Math.Min(4, parameters.Exponent.Length); i++) { num |= (uint)(parameters.Exponent[i] << 8 * i); } PublicExponent = num; } public byte[] CreatePublicKeyBlob(AssemblyHashAlgorithm hashAlgorithm) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown using MemoryStream memoryStream = new MemoryStream(); BinaryStreamWriter val = new BinaryStreamWriter((Stream)memoryStream); val.WriteUInt32((uint)SignatureAlgorithm); val.WriteUInt32((uint)hashAlgorithm); val.WriteUInt32((uint)(20 + Modulus.Length)); val.WriteByte((byte)6); val.WriteByte((byte)2); val.WriteUInt16((ushort)0); val.WriteUInt32((uint)SignatureAlgorithm); val.WriteUInt32(826364754u); val.WriteUInt32((uint)BitLength); val.WriteUInt32(PublicExponent); IOExtensions.WriteBytes((IBinaryStreamWriter)val, CopyReversed(Modulus)); return memoryStream.ToArray(); } public virtual RSAParameters ToRsaParameters() { RSAParameters result = default(RSAParameters); result.Modulus = Modulus; result.Exponent = BitConverter.GetBytes(PublicExponent); return result; } public override uint GetPhysicalSize() { return base.GetPhysicalSize() + 4 + 4 + 4 + (uint)Modulus.Length / 8u; } public override void Write(IBinaryStreamWriter writer) { base.Write(writer); writer.WriteUInt32((uint)Magic); writer.WriteUInt32((uint)BitLength); writer.WriteUInt32(PublicExponent); IOExtensions.WriteBytes(writer, Modulus); } } public class StrongNameSigner { public StrongNamePrivateKey PrivateKey { get; } public StrongNameSigner(StrongNamePrivateKey privateKey) { PrivateKey = privateKey ?? throw new ArgumentNullException("privateKey"); } public void SignImage(Stream imageStream, AssemblyHashAlgorithm hashAlgorithm) { imageStream.Position = 0L; using MemoryStream memoryStream = new MemoryStream(); imageStream.CopyTo(memoryStream); memoryStream.Position = 0L; PEFile val = PEFile.FromBytes(memoryStream.ToArray()); IPEImage iPEImage = PEImage.FromFile((IPEFile)(object)val); if (iPEImage.DotNetDirectory == null) { throw new BadImageFormatException("Input image is not a .NET assembly."); } IReadableSegment strongName = iPEImage.DotNetDirectory.StrongName; if (strongName == null) { throw new ArgumentException("Cannot sign an image without a strong name directory."); } if (PrivateKey.Modulus.Length != ((IWritable)strongName).GetPhysicalSize()) { throw new ArgumentException("The strong name signature directory size does not match the size of the strong signature."); } byte[] hashToSign = GetHashToSign(memoryStream, (IPEFile)(object)val, iPEImage, hashAlgorithm); byte[] array = ComputeSignature(hashAlgorithm, hashToSign); imageStream.Position = (long)((IOffsetProvider)strongName).Offset; imageStream.Write(array, 0, array.Length); } private byte[] GetHashToSign(Stream imageStream, IPEFile file, IPEImage image, AssemblyHashAlgorithm hashAlgorithm) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Invalid comparison between Unknown and I4 //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) StrongNameDataHashBuilder strongNameDataHashBuilder = new StrongNameDataHashBuilder(imageStream, hashAlgorithm); strongNameDataHashBuilder.IncludeRange(new OffsetRange(0uL, (ulong)(uint)(((SegmentBase)file.DosHeader).GetPhysicalSize() + 4 + ((SegmentBase)file.FileHeader).GetPhysicalSize() + ((SegmentBase)file.OptionalHeader).GetPhysicalSize() + (long)file.Sections.Count * 40L))); foreach (PESection section in file.Sections) { strongNameDataHashBuilder.IncludeRange(new OffsetRange(section.Offset, section.Offset + section.GetPhysicalSize())); } ulong num = ((SegmentBase)file.OptionalHeader).Offset + 64; strongNameDataHashBuilder.ZeroRange(new OffsetRange(num, num + 4)); uint num2 = (((int)file.OptionalHeader.Magic == 267) ? 96u : 112u); ulong num3 = ((SegmentBase)file.OptionalHeader).Offset + num2 + 32; strongNameDataHashBuilder.ZeroRange(new OffsetRange(num3, num3 + 8)); DataDirectory dataDirectory = file.OptionalHeader.GetDataDirectory((DataDirectoryIndex)4); if (((DataDirectory)(ref dataDirectory)).IsPresentInPE) { ulong num4 = ((IOffsetConverter)file).RvaToFileOffset(((DataDirectory)(ref dataDirectory)).VirtualAddress); strongNameDataHashBuilder.ExcludeRange(new OffsetRange(num4, num4 + ((DataDirectory)(ref dataDirectory)).Size)); } IReadableSegment val = image.DotNetDirectory?.StrongName; if (val == null) { throw new ArgumentException("PE image does not contain a strong name directory."); } strongNameDataHashBuilder.ExcludeRange(new OffsetRange(((IOffsetProvider)val).Offset, ((IOffsetProvider)val).Offset + ((IWritable)val).GetPhysicalSize())); return strongNameDataHashBuilder.ComputeHash(); } private byte[] ComputeSignature(AssemblyHashAlgorithm hashAlgorithm, byte[] hash) { using RSA rSA = RSA.Create(); RSAParameters parameters = PrivateKey.ToRsaParameters(); rSA.ImportParameters(parameters); RSAPKCS1SignatureFormatter rSAPKCS1SignatureFormatter = new RSAPKCS1SignatureFormatter(rSA); rSAPKCS1SignatureFormatter.SetHashAlgorithm(hashAlgorithm.ToString().ToUpperInvariant()); byte[] array = rSAPKCS1SignatureFormatter.CreateSignature(hash); Array.Reverse(array); return array; } } } namespace AsmResolver.PE.DotNet.Resources { public abstract class DotNetResourcesDirectory : SegmentBase { public abstract byte[]? GetManifestResourceData(uint offset); public abstract bool TryCreateManifestResourceReader(uint offset, out BinaryStreamReader reader); } public class SerializedDotNetResourcesDirectory : DotNetResourcesDirectory { private readonly BinaryStreamReader _reader; public SerializedDotNetResourcesDirectory(in BinaryStreamReader reader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = reader; if (!((BinaryStreamReader)(ref val)).IsValid) { throw new ArgumentNullException("reader"); } _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public SerializedDotNetResourcesDirectory(IReadableSegment contents) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = Extensions.CreateReader(contents); this..ctor(in reader); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override byte[]? GetManifestResourceData(uint offset) { if (!TryCreateManifestResourceReader(offset, out var reader)) { return null; } byte[] array = new byte[((BinaryStreamReader)(ref reader)).Length]; ((BinaryStreamReader)(ref reader)).ReadBytes(array, 0, array.Length); return array; } public override bool TryCreateManifestResourceReader(uint offset, out BinaryStreamReader reader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (offset >= ((BinaryStreamReader)(ref _reader)).Length - 4) { reader = default(BinaryStreamReader); return false; } reader = ((BinaryStreamReader)(ref _reader)).ForkRelative(offset); uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); reader = ((BinaryStreamReader)(ref reader)).ForkAbsolute(((BinaryStreamReader)(ref reader)).Offset, num); return true; } } } namespace AsmResolver.PE.DotNet.Metadata { public class CustomMetadataStream : IMetadataStream, ISegment, IOffsetProvider, IWritable { public ulong Offset => ((IOffsetProvider)Contents).Offset; public uint Rva => ((IOffsetProvider)Contents).Rva; public bool CanUpdateOffsets => true; public string Name { get; set; } [MemberNotNullWhen(true, "Contents")] public bool CanRead { [MemberNotNullWhen(true, "Contents")] get { return Contents is IReadableSegment; } } public ISegment Contents { get; set; } public CustomMetadataStream(string name, byte[] data) : this(name, (ISegment)new DataSegment(data)) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown public CustomMetadataStream(string name, ISegment contents) { Name = name; Contents = contents; } public BinaryStreamReader CreateReader() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!CanRead) { throw new InvalidOperationException("Contents of the metadata stream is not readable."); } return Extensions.CreateReader((IReadableSegment)Contents); } public void UpdateOffsets(in RelocationParameters parameters) { Contents.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return ((IWritable)Contents).GetPhysicalSize(); } public uint GetVirtualSize() { return GetPhysicalSize(); } public void Write(IBinaryStreamWriter writer) { ((IWritable)Contents).Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class DefaultMetadataStreamReader : IMetadataStreamReader { public static DefaultMetadataStreamReader Instance { get; } = new DefaultMetadataStreamReader(); public IMetadataStream ReadStream(MetadataReaderContext context, MetadataStreamHeader header, ref BinaryStreamReader reader) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) switch (header.Name) { case "#~": case "#-": return new SerializedTableStream(context, header.Name, in reader); case "#Strings": return new SerializedStringsStream(header.Name, in reader); case "#US": return new SerializedUserStringsStream(header.Name, reader); case "#Blob": return new SerializedBlobStream(header.Name, in reader); case "#GUID": return new SerializedGuidStream(header.Name, in reader); case "#Pdb": return new SerializedPdbStream(header.Name, in reader); default: return new CustomMetadataStream(header.Name, (ISegment)(object)DataSegment.FromReader(ref reader)); } } } public class FieldRvaDataReader : IFieldRvaDataReader { public ISegment? ResolveFieldData(IErrorListener listener, IMetadata metadata, in FieldRvaRow fieldRvaRow) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (fieldRvaRow.Data.IsBounded) { return fieldRvaRow.Data.GetSegment(); } if (fieldRvaRow.Data.CanRead) { if (!metadata.TryGetStream(out TablesStream stream)) { ErrorListenerExtensions.BadImage(listener, "Metadata does not contain a tables stream."); return null; } MetadataTable table = stream.GetTable(TableIndex.Field); if (fieldRvaRow.Field > table.Count) { ErrorListenerExtensions.BadImage(listener, "FieldRva row has an invalid Field column value."); return null; } FieldDefinitionRow field = table.GetByRid(fieldRvaRow.Field); int num = DetermineFieldSize(metadata, in field); BinaryStreamReader val = fieldRvaRow.Data.CreateReader(); return (ISegment?)(object)DataSegment.FromReader(ref val, num); } ErrorListenerExtensions.NotSupported(listener, "FieldRva row has an invalid or unsupported data column."); return null; } private int DetermineFieldSize(IMetadata metadata, in FieldDefinitionRow field) { if (!metadata.TryGetStream(out BlobStream stream) || !stream.TryGetBlobReaderByIndex(field.Signature, out var reader)) { return 0; } ((BinaryStreamReader)(ref reader)).ReadByte(); return (ElementType)((BinaryStreamReader)(ref reader)).ReadByte() switch { ElementType.Boolean => 1, ElementType.Char => 2, ElementType.I1 => 1, ElementType.U1 => 1, ElementType.I2 => 2, ElementType.U2 => 2, ElementType.I4 => 4, ElementType.U4 => 4, ElementType.I8 => 8, ElementType.U8 => 8, ElementType.R4 => 4, ElementType.R8 => 8, ElementType.ValueType => GetCustomTypeSize(metadata, ref reader), ElementType.Class => GetCustomTypeSize(metadata, ref reader), _ => throw new ArgumentOutOfRangeException(), }; } private int GetCustomTypeSize(IMetadata metadata, ref BinaryStreamReader reader) { uint codedIndex = default(uint); if (!((BinaryStreamReader)(ref reader)).TryReadCompressedUInt32(ref codedIndex) || !metadata.TryGetStream(out TablesStream stream)) { return 0; } MetadataToken metadataToken = stream.GetIndexEncoder(CodedIndex.TypeDefOrRef).DecodeIndex(codedIndex); if (metadataToken.Table == TableIndex.TypeDef && stream.GetTable(TableIndex.ClassLayout).TryGetRowByKey(2, metadataToken.Rid, out var row)) { return (int)row.ClassSize; } return 0; } ISegment? IFieldRvaDataReader.ResolveFieldData(IErrorListener listener, IMetadata metadata, in FieldRvaRow fieldRvaRow) { return ResolveFieldData(listener, metadata, in fieldRvaRow); } } public interface IFieldRvaDataReader { ISegment? ResolveFieldData(IErrorListener listener, IMetadata metadata, in FieldRvaRow fieldRvaRow); } public interface ILazyMetadataStream : IMetadataStream, ISegment, IOffsetProvider, IWritable { void Initialize(IMetadata parentMetadata); } public interface IMetadata : ISegment, IOffsetProvider, IWritable { ushort MajorVersion { get; set; } ushort MinorVersion { get; set; } uint Reserved { get; set; } string VersionString { get; set; } ushort Flags { get; set; } bool IsEncMetadata { get; } IList Streams { get; } IMetadataStream GetStream(string name); TStream GetStream() where TStream : class, IMetadataStream; bool TryGetStream(string name, [NotNullWhen(true)] out IMetadataStream? stream); bool TryGetStream([NotNullWhen(true)] out TStream? stream) where TStream : class, IMetadataStream; } public interface IMetadataStream : ISegment, IOffsetProvider, IWritable { string Name { get; set; } bool CanRead { get; } BinaryStreamReader CreateReader(); } public interface IMetadataStreamReader { IMetadataStream ReadStream(MetadataReaderContext context, MetadataStreamHeader header, ref BinaryStreamReader reader); } public class Metadata : SegmentBase, IMetadata, ISegment, IOffsetProvider, IWritable { private IList? _streams; public ushort MajorVersion { get; set; } = 1; public ushort MinorVersion { get; set; } = 1; public uint Reserved { get; set; } public string VersionString { get; set; } = "v4.0.30319"; public ushort Flags { get; set; } public bool IsEncMetadata { get; set; } public IList Streams { get { if (_streams == null) { Interlocked.CompareExchange(ref _streams, GetStreams(), null); } return _streams; } } public static Metadata FromFile(string path) { return FromBytes(File.ReadAllBytes(path)); } public static Metadata FromBytes(byte[] data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromReader(new BinaryStreamReader(data)); } public static Metadata FromFile(IInputFile file) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromReader(IOExtensions.CreateReader(file)); } public static Metadata FromReader(BinaryStreamReader reader) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FromReader(reader, new MetadataReaderContext((ISegmentReferenceFactory)(object)VirtualAddressFactory.Instance)); } public static Metadata FromReader(BinaryStreamReader reader, MetadataReaderContext context) { return new SerializedMetadata(context, ref reader); } public override uint GetPhysicalSize() { return (uint)(16 + Extensions.Align((uint)VersionString.Length, 4u) + 2 + 2 + GetSizeOfStreamHeaders() + Streams.Sum((IMetadataStream s) => ((IWritable)s).GetPhysicalSize())); } public override void Write(IBinaryStreamWriter writer) { ulong offset = writer.Offset; writer.WriteUInt32(1112167234u); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt32(Reserved); byte[] array = new byte[Extensions.Align((uint)VersionString.Length, 4u)]; Encoding.UTF8.GetBytes(VersionString, 0, VersionString.Length, array, 0); writer.WriteInt32(array.Length); IOExtensions.WriteBytes(writer, array); writer.WriteUInt16(Flags); writer.WriteUInt16((ushort)Streams.Count); ulong offset2 = writer.Offset; WriteStreamHeaders(writer, GetStreamHeaders((uint)(offset2 - offset))); WriteStreams(writer); } protected virtual MetadataStreamHeader[] GetStreamHeaders(uint offset) { uint sizeOfStreamHeaders = GetSizeOfStreamHeaders(); offset += sizeOfStreamHeaders; MetadataStreamHeader[] array = new MetadataStreamHeader[Streams.Count]; for (int i = 0; i < array.Length; i++) { uint physicalSize = ((IWritable)Streams[i]).GetPhysicalSize(); array[i] = new MetadataStreamHeader(offset, physicalSize, Streams[i].Name); offset += physicalSize; } return array; } private uint GetSizeOfStreamHeaders() { return (uint)(Streams.Count * 2 * 4 + Streams.Sum((IMetadataStream s) => Extensions.Align((uint)(s.Name.Length + 1), 4u))); } protected virtual void WriteStreamHeaders(IBinaryStreamWriter writer, MetadataStreamHeader[] headers) { for (int i = 0; i < headers.Length; i++) { MetadataStreamHeader metadataStreamHeader = headers[i]; writer.WriteUInt32(metadataStreamHeader.Offset); writer.WriteUInt32(metadataStreamHeader.Size); IOExtensions.WriteAsciiString(writer, metadataStreamHeader.Name); writer.WriteByte((byte)0); IOExtensions.Align(writer, 4u); } } protected virtual void WriteStreams(IBinaryStreamWriter writer) { for (int i = 0; i < Streams.Count; i++) { ((IWritable)Streams[i]).Write(writer); } } public virtual IMetadataStream GetStream(string name) { if (!TryGetStream(name, out IMetadataStream stream)) { throw new KeyNotFoundException("Metadata directory does not contain a stream called " + name + "."); } return stream; } public TStream GetStream() where TStream : class, IMetadataStream { if (!TryGetStream(out TStream stream)) { throw new KeyNotFoundException("Metadata directory does not contain a stream of type " + typeof(TStream).FullName + "."); } return stream; } public bool TryGetStream(string name, [NotNullWhen(true)] out IMetadataStream? stream) { bool heapRequested = !(name == "#~") && !(name == "#-") && !(name == "#Schema"); return TryFindStream((IMetadataStream c, object? s) => c.Name == s as string, name, heapRequested, out stream); } public bool TryGetStream([NotNullWhen(true)] out TStream? stream) where TStream : class, IMetadataStream { bool heapRequested = !typeof(TablesStream).IsAssignableFrom(typeof(TStream)); if (TryFindStream((IMetadataStream c, object? _) => c is TStream, null, heapRequested, out IMetadataStream stream2)) { stream = (TStream)stream2; return true; } stream = null; return false; } private bool TryFindStream(Func condition, object? state, bool heapRequested, [NotNullWhen(true)] out IMetadataStream? stream) { IList streams = Streams; if (heapRequested && !IsEncMetadata) { for (int num = streams.Count - 1; num >= 0; num--) { if (condition(streams[num], state)) { stream = streams[num]; return true; } } } else { for (int i = 0; i < streams.Count; i++) { if (condition(streams[i], state)) { stream = streams[i]; return true; } } } stream = null; return false; } protected virtual IList GetStreams() { return new List(); } } public abstract class MetadataHeap : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public string Name { get; set; } public virtual bool CanRead => false; public IndexSize IndexSize { get { if (((SegmentBase)this).GetPhysicalSize() > 65535) { return (IndexSize)4; } return (IndexSize)2; } } protected MetadataHeap(string name) { Name = name ?? throw new ArgumentNullException("name"); } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } } public class MetadataReaderContext : IErrorListener { public ISegmentReferenceFactory ReferenceFactory { get; } public IErrorListener ErrorListener { get; } public IMetadataStreamReader MetadataStreamReader { get; } public MetadataReaderContext(ISegmentReferenceFactory factory) : this(factory, (IErrorListener)(object)ThrowErrorListener.Instance, DefaultMetadataStreamReader.Instance) { } public MetadataReaderContext(ISegmentReferenceFactory referenceFactory, IErrorListener errorListener, IMetadataStreamReader metadataStreamReader) { ReferenceFactory = referenceFactory; ErrorListener = errorListener; MetadataStreamReader = metadataStreamReader; } public static MetadataReaderContext FromReaderContext(PEReaderContext context) { return new MetadataReaderContext((ISegmentReferenceFactory)(object)context.File, context.Parameters.ErrorListener, context.Parameters.MetadataStreamReader); } public void MarkAsFatal() { ErrorListener.MarkAsFatal(); } public void RegisterException(Exception exception) { ErrorListener.RegisterException(exception); } } public enum MetadataSignature { Bsjb = 1112167234, ComPlus = 726486851 } public readonly struct MetadataStreamHeader { public uint Offset { get; } public uint Size { get; } public string Name { get; } public MetadataStreamHeader(uint offset, uint size, string name) { Offset = offset; Size = size; Name = name ?? throw new ArgumentNullException("name"); if (name.Length > 32) { throw new ArgumentOutOfRangeException("name", "Name can be no longer than 32 bytes."); } } public static MetadataStreamHeader FromReader(ref BinaryStreamReader reader) { uint offset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint size = ((BinaryStreamReader)(ref reader)).ReadUInt32(); string name = ((BinaryStreamReader)(ref reader)).ReadAsciiString(); ((BinaryStreamReader)(ref reader)).Align(4u); return new MetadataStreamHeader(offset, size, name); } public override string ToString() { return $"{"Offset"}: {Offset:X8}, {"Size"}: {Size:X8}, {"Name"}: {Name}"; } } public class MetadataStreamList : LazyList { private readonly MetadataReaderContext _context; private readonly MetadataStreamHeader[] _streamHeaders; private readonly IMetadata _owner; private readonly BinaryStreamReader _directoryReader; public override int Count { get { if (!base.IsInitialized) { return _streamHeaders.Length; } return base.Items.Count; } } public MetadataStreamList(IMetadata owner, MetadataReaderContext context, MetadataStreamHeader[] streamHeaders, in BinaryStreamReader directoryReader) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _streamHeaders = streamHeaders; _owner = owner; _directoryReader = directoryReader; } protected override void Initialize() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) MetadataStreamHeader[] streamHeaders = _streamHeaders; for (int i = 0; i < streamHeaders.Length; i++) { MetadataStreamHeader header = streamHeaders[i]; BinaryStreamReader reader = ((BinaryStreamReader)(ref _directoryReader)).ForkAbsolute(((BinaryStreamReader)(ref _directoryReader)).Offset + header.Offset, header.Size); IMetadataStream item = _context.MetadataStreamReader.ReadStream(_context, header, ref reader); base.Items.Add(item); } } protected override void PostInitialize() { for (int i = 0; i < base.Items.Count; i++) { if (base.Items[i] is ILazyMetadataStream lazyMetadataStream) { lazyMetadataStream.Initialize(_owner); } } } } public class SerializedMetadata : Metadata { private readonly MetadataReaderContext _context; private readonly BinaryStreamReader _streamContentsReader; private readonly MetadataStreamHeader[] _streamHeaders; public SerializedMetadata(MetadataReaderContext context, ref BinaryStreamReader directoryReader) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!((BinaryStreamReader)(ref directoryReader)).IsValid) { throw new ArgumentNullException("directoryReader"); } _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref directoryReader)).Rva; _streamContentsReader = ((BinaryStreamReader)(ref directoryReader)).Fork(); _streamHeaders = Array.Empty(); MetadataSignature metadataSignature = (MetadataSignature)((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); switch (metadataSignature) { case MetadataSignature.ComPlus: ErrorListenerExtensions.NotSupported((IErrorListener)(object)_context, "Old COM+ metadata header format is not supported."); break; default: ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid metadata header ({metadataSignature:X8})."); break; case MetadataSignature.Bsjb: { base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.Reserved = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); uint num = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); if (!((BinaryStreamReader)(ref directoryReader)).CanRead(num)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid version length in metadata header (" + num + " characters)."); break; } byte[] array = new byte[num]; ((BinaryStreamReader)(ref directoryReader)).ReadBytes(array, 0, array.Length); base.VersionString = Encoding.ASCII.GetString(array); base.Flags = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); int num2 = ((BinaryStreamReader)(ref directoryReader)).ReadInt16(); _streamHeaders = new MetadataStreamHeader[num2]; for (int i = 0; i < num2; i++) { _streamHeaders[i] = MetadataStreamHeader.FromReader(ref directoryReader); if (_streamHeaders[i].Name == "#-") { base.IsEncMetadata = true; } } break; } } } protected override IList GetStreams() { if (_streamHeaders.Length == 0) { return base.GetStreams(); } return (IList)new MetadataStreamList(this, _context, _streamHeaders, in _streamContentsReader); } } } namespace AsmResolver.PE.DotNet.Metadata.UserStrings { public class SerializedUserStringsStream : UserStringsStream { private readonly Dictionary _cachedStrings = new Dictionary(); private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedUserStringsStream(byte[] rawData) : this("#US", new BinaryStreamReader(rawData)) { }//IL_0007: Unknown result type (might be due to invalid IL or missing references) public SerializedUserStringsStream(string name, byte[] rawData) : this(name, new BinaryStreamReader(rawData)) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public SerializedUserStringsStream(string name, BinaryStreamReader reader) : base(name) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override string? GetStringByIndex(uint index) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) index &= 0xFFFFFFu; if (!_cachedStrings.TryGetValue(index, out string value) && index < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); uint num = default(uint); if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num)) { if (num == 0) { return string.Empty; } byte[] array = new byte[num]; int num2 = ((BinaryStreamReader)(ref val)).ReadBytes(array, 0, (int)num); value = Encoding.Unicode.GetString(array, 0, num2 - 1); } _cachedStrings[index] = value; } return value; } public override bool TryFindStringIndex(string value, out uint index) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (value == string.Empty) { index = 0u; return true; } uint num = (uint)(value.Length * 2 + 1); uint num2 = Extensions.GetCompressedSize(num) + num; BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); uint num3 = default(uint); while (((BinaryStreamReader)(ref val)).CanRead(num2)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num3) && num3 == num && ((BinaryStreamReader)(ref val)).CanRead(num3)) { int i; for (i = 0; i < value.Length && value[i] == ((BinaryStreamReader)(ref val)).ReadUInt16(); i++) { } if (i == value.Length && ((BinaryStreamReader)(ref val)).CanRead(1u)) { byte b = ((BinaryStreamReader)(ref val)).ReadByte(); if (b == 0 || b == 1) { return true; } } } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } public abstract class UserStringsStream : MetadataHeap { public const string DefaultName = "#US"; protected UserStringsStream() : base("#US") { } protected UserStringsStream(string name) : base(name) { } public abstract string? GetStringByIndex(uint index); public abstract bool TryFindStringIndex(string value, out uint index); public bool TryFindStringToken(string value, out MetadataToken token) { if (TryFindStringIndex(value, out var index)) { token = new MetadataToken(TableIndex.String, index); return true; } token = MetadataToken.Zero; return false; } } } namespace AsmResolver.PE.DotNet.Metadata.Tables { public enum CodedIndex { TypeDefOrRef = 56, HasConstant, HasCustomAttribute, HasFieldMarshal, HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, MemberForwarded, Implementation, CustomAttributeType, ResolutionScope, TypeOrMethodDef, HasCustomDebugInformation } public readonly struct ColumnLayout { public string Name { get; } public ColumnType Type { get; } public uint Size { get; } public ColumnLayout(string name, ColumnType type) { Name = name; Type = type; if (type < ColumnType.Byte) { throw new ArgumentException("Size was not explicitly defined."); } Size = (uint)(type & (ColumnType)255); } public ColumnLayout(string name, ColumnType type, IndexSize size) : this(name, type, (uint)(int)size) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected I4, but got Unknown public ColumnLayout(string name, ColumnType type, uint size) { Name = name; Type = type; Size = size; } public override string ToString() { return $"{Name} : {Type} ({Size} bytes)"; } } public enum ColumnType { Module = 0, TypeRef = 1, TypeDef = 2, FieldPtr = 3, Field = 4, MethodPtr = 5, Method = 6, ParamPtr = 7, Param = 8, InterfaceImpl = 9, MemberRef = 10, Constant = 11, CustomAttribute = 12, FieldMarshal = 13, DeclSecurity = 14, ClassLayout = 15, FieldLayout = 16, StandAloneSig = 17, EventMap = 18, EventPtr = 19, Event = 20, PropertyMap = 21, PropertyPtr = 22, Property = 23, MethodSemantics = 24, MethodImpl = 25, ModuleRef = 26, TypeSpec = 27, ImplMap = 28, FieldRva = 29, EncLog = 30, EncMap = 31, Assembly = 32, AssemblyProcessor = 33, AssemblyOS = 34, AssemblyRef = 35, AssemblyRefProcessor = 36, AssemblyRefOS = 37, File = 38, ExportedType = 39, ManifestResource = 40, NestedClass = 41, GenericParam = 42, MethodSpec = 43, GenericParamConstraint = 44, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55, TypeDefOrRef = 56, HasConstant = 57, HasCustomAttribute = 58, HasFieldMarshal = 59, HasDeclSecurity = 60, MemberRefParent = 61, HasSemantics = 62, MethodDefOrRef = 63, MemberForwarded = 64, Implementation = 65, CustomAttributeType = 66, ResolutionScope = 67, TypeOrMethodDef = 68, HasCustomDebugInformation = 69, String = 70, Blob = 71, Guid = 72, Byte = 134217729, UInt16 = 134217730, UInt32 = 134217732 } public interface IMetadataTable : ICollection, IEnumerable { TableLayout Layout { get; } IndexSize IndexSize { get; } IMetadataRow this[int index] { get; set; } bool IsSorted { get; set; } IMetadataRow GetByRid(uint rid); bool TryGetCell(uint rid, int column, out uint value); bool TryGetByRid(uint rid, out IMetadataRow row); bool TryGetRowByKey(int keyColumnIndex, uint key, out IMetadataRow row); void SetByRid(uint rid, IMetadataRow row); void UpdateTableLayout(TableLayout layout); void Write(IBinaryStreamWriter writer); } public class IndexEncoder { private readonly TablesStream _tableStream; private readonly TableIndex[] _tables; private readonly int _tableIndexBitCount; private readonly int _tableIndexBitMask; private readonly int _maxSmallTableMemberCount; public IndexSize IndexSize { get { uint num = 0u; TableIndex[] tables = _tables; foreach (TableIndex table in tables) { num = Math.Max(num, _tableStream.GetTableRowCount(table)); } if (num > _maxSmallTableMemberCount) { return (IndexSize)4; } return (IndexSize)2; } } public IndexEncoder(TablesStream tableStream, params TableIndex[] tables) { _tableStream = tableStream ?? throw new ArgumentNullException("tableStream"); _tables = tables ?? throw new ArgumentNullException("tables"); _tableIndexBitCount = (int)Math.Ceiling(Math.Log(tables.Length, 2.0)); _tableIndexBitMask = (int)(Math.Pow(2.0, _tableIndexBitCount) - 1.0); _maxSmallTableMemberCount = 65535 >> _tableIndexBitCount; } public uint EncodeToken(MetadataToken token) { int num = Array.IndexOf(_tables, token.Table); if (num == -1) { throw new ArgumentException("Table is not supported by this encoder.", "token"); } return (token.Rid << _tableIndexBitCount) | (uint)num; } public MetadataToken DecodeIndex(uint codedIndex) { long num = codedIndex & _tableIndexBitMask; uint rid = codedIndex >> _tableIndexBitCount; return new MetadataToken((num < _tables.Length) ? _tables[num] : TableIndex.Module, rid); } } public readonly struct MetadataRange : IEnumerable, IEnumerable, IEquatable { public struct Enumerator : IEnumerator, IEnumerator, IDisposable { private readonly MetadataRange _range; private uint _currentRid; public MetadataToken Current { get { uint value; if (!_range.IsRedirected) { value = _currentRid; } else { _range.RedirectionTable.TryGetCell(_currentRid, 0, out value); } return new MetadataToken(_range.Table, value); } } object IEnumerator.Current => Current; public Enumerator(MetadataRange range) { _range = range; _currentRid = range.StartRid - 1; } public bool MoveNext() { if (_currentRid < _range.EndRid - 1) { _currentRid++; return true; } return false; } public void Reset() { _currentRid = 0u; } public void Dispose() { } } public static readonly MetadataRange Empty = new MetadataRange(TableIndex.Module, 1u, 1u); public TableIndex Table { get; } public uint StartRid { get; } public uint EndRid { get; } public int Count => (int)(EndRid - StartRid); public bool IsEmpty => EndRid == StartRid; public IMetadataTable? RedirectionTable { get; } [MemberNotNullWhen(true, "RedirectionTable")] public bool IsRedirected { [MemberNotNullWhen(true, "RedirectionTable")] get { return RedirectionTable != null; } } public MetadataRange(TableIndex table, uint startRid, uint endRid) { Table = table; StartRid = startRid; EndRid = endRid; RedirectionTable = null; } public MetadataRange(IMetadataTable redirectionTable, TableIndex table, uint startRid, uint endRid) { Table = table; StartRid = startRid; EndRid = endRid; RedirectionTable = redirectionTable; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override string ToString() { MetadataToken metadataToken = new MetadataToken(Table, StartRid); MetadataToken metadataToken2 = new MetadataToken(Table, EndRid); return $"[0x{metadataToken.ToString()}..0x{metadataToken2.ToString()})"; } public bool Equals(MetadataRange other) { if (IsEmpty && other.IsEmpty) { return true; } if (Table == other.Table && StartRid == other.StartRid && EndRid == other.EndRid) { return object.Equals(RedirectionTable, other.RedirectionTable); } return false; } public override bool Equals(object? obj) { if (obj is MetadataRange other) { return Equals(other); } return false; } public override int GetHashCode() { if (IsEmpty) { return 0; } return (int)(((((uint)((int)Table * 397) ^ StartRid) * 397) ^ EndRid) * 397) ^ ((RedirectionTable != null) ? RedirectionTable.GetHashCode() : 0); } } public class MetadataTable : IMetadataTable, ICollection, IEnumerable, ICollection, IEnumerable where TRow : struct, IMetadataRow { private RefList? _items; public TableIndex TableIndex { get; } public TableLayout Layout { get; private set; } public IndexSize IndexSize { get { if (Count > 65535) { return (IndexSize)4; } return (IndexSize)2; } } public TRow this[int index] { get { return Rows[index]; } set { Rows[index] = value; } } public bool IsSorted { get; set; } IMetadataRow IMetadataTable.this[int index] { get { return this[index]; } set { this[index] = (TRow)value; } } public int Version => Rows.Version; protected RefList Rows { get { if (_items == null) { Interlocked.CompareExchange(ref _items, GetRows(), null); } return _items; } } protected bool IsInitialized => _items != null; public virtual int Count => Rows.Count; public int Capacity { get { return Rows.Capacity; } set { Rows.Capacity = value; } } public bool IsReadOnly => false; public object SyncRoot => this; public bool IsSynchronized => false; public MetadataTable(TableIndex tableIndex, TableLayout layout) : this(tableIndex, layout, isSorted: false) { } public MetadataTable(TableIndex tableIndex, TableLayout layout, bool isSorted) { TableIndex = tableIndex; Layout = layout; IsSorted = isSorted; } public ref TRow GetRowRef(uint rid) { return ref Rows.GetElementRef((int)(rid - 1)); } public ref TRow GetRowRef(uint rid, out int version) { return ref Rows.GetElementRef((int)(rid - 1), ref version); } public void Add(TRow item) { Rows.Add(ref item); } public void Clear() { Rows.Clear(); } public bool Contains(TRow item) { return Rows.Contains(ref item); } public void CopyTo(TRow[] array, int arrayIndex) { Rows.CopyTo(array, arrayIndex); } void ICollection.CopyTo(Array array, int index) { ((ICollection)Rows).CopyTo(array, index); } public bool Remove(TRow item) { return Rows.Remove(ref item); } public IEnumerator GetEnumerator() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return (IEnumerator)(object)Rows.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } protected virtual RefList GetRows() { return new RefList(); } public TRow GetByRid(uint rid) { return this[(int)(rid - 1)]; } public bool TryGetCell(uint rid, int column, out uint value) { if (column >= 0 && column < Layout.Columns.Count && TryGetByRid(rid, out var row)) { value = row[column]; return true; } value = 0u; return false; } IMetadataRow IMetadataTable.GetByRid(uint rid) { return GetByRid(rid); } public bool TryGetByRid(uint rid, out TRow row) { if (rid >= 1 && rid <= Count) { row = GetByRid(rid); return true; } row = default(TRow); return false; } bool IMetadataTable.TryGetByRid(uint rid, out IMetadataRow row) { TRow row2; bool result = TryGetByRid(rid, out row2); row = row2; return result; } public bool TryGetRowByKey(int keyColumnIndex, uint key, out TRow row) { row = default(TRow); if (Count == 0) { return false; } int num = 0; int num2 = Count - 1; while (num <= num2) { int num3 = (num + num2) / 2; TRow val = Rows[num3]; uint num4 = val[keyColumnIndex]; if (num4 > key) { num2 = num3 - 1; continue; } if (num4 < key) { num = num3 + 1; continue; } row = val; return true; } return false; } bool IMetadataTable.TryGetRowByKey(int keyColumnIndex, uint key, out IMetadataRow row) { TRow row2; bool result = TryGetRowByKey(keyColumnIndex, key, out row2); row = row2; return result; } public void SetByRid(uint rid, TRow row) { this[(int)(rid - 1)] = row; } void IMetadataTable.SetByRid(uint rid, IMetadataRow row) { SetByRid(rid, (TRow)row); } public virtual void UpdateTableLayout(TableLayout layout) { for (int i = 0; i < Layout.Columns.Count; i++) { if (Layout.Columns[i].Name != layout.Columns[i].Name || Layout.Columns[i].Type != layout.Columns[i].Type) { throw new ArgumentException("New table layout does not match the original one."); } } Layout = layout; } public void Write(IBinaryStreamWriter writer) { for (int i = 0; i < Rows.Count; i++) { Rows[i].Write(writer, Layout); } } } public readonly struct MetadataToken : IComparable { public static readonly MetadataToken Zero = new MetadataToken(0u); private readonly uint _value; public TableIndex Table => (TableIndex)(_value >> 24); public uint Rid => _value & 0xFFFFFFu; public static implicit operator MetadataToken(int token) { return new MetadataToken((uint)token); } public static implicit operator MetadataToken(uint token) { return new MetadataToken(token); } public static bool operator ==(MetadataToken a, MetadataToken b) { return a.Equals(b); } public static bool operator !=(MetadataToken a, MetadataToken b) { return !(a == b); } public MetadataToken(uint value) { _value = value; } public MetadataToken(TableIndex table, uint rid) : this(((uint)table << 24) | (rid & 0xFFFFFFu)) { if (rid > 16777215) { throw new ArgumentOutOfRangeException("rid"); } } public uint ToUInt32() { return _value; } public int ToInt32() { return (int)_value; } public override string ToString() { return _value.ToString("X8"); } public bool Equals(MetadataToken other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is MetadataToken other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)_value; } public int CompareTo(MetadataToken other) { return _value.CompareTo(other._value); } } public class SerializedMetadataTable : MetadataTable where TRow : struct, IMetadataRow { public delegate TRow ReadRowDelegate(ref BinaryStreamReader reader, TableLayout layout); public delegate TRow ReadRowExtendedDelegate(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout); private readonly BinaryStreamReader _reader; private readonly TableLayout _originalLayout; private readonly int _rowCount; private readonly ReadRowDelegate _readRow; public override int Count { get { if (!base.IsInitialized) { return _rowCount; } return base.Rows.Count; } } public SerializedMetadataTable(in BinaryStreamReader reader, TableIndex tableIndex, TableLayout originalLayout, bool isSorted, ReadRowDelegate readRow) : base(tableIndex, originalLayout, isSorted) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _originalLayout = originalLayout; _rowCount = (int)(((BinaryStreamReader)(ref reader)).Length / originalLayout.RowSize); _readRow = readRow ?? throw new ArgumentNullException("readRow"); } public SerializedMetadataTable(MetadataReaderContext context, in BinaryStreamReader reader, TableIndex tableIndex, TableLayout originalLayout, bool isSorted, ReadRowExtendedDelegate readRow) { ReadRowExtendedDelegate readRow2 = readRow; MetadataReaderContext context2 = context; this..ctor(in reader, tableIndex, originalLayout, isSorted, (ReadRowDelegate)delegate(ref BinaryStreamReader r, TableLayout l) { return readRow2(context2, ref r, l); }); } protected override RefList GetRows() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) RefList val = new RefList(_rowCount); BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); for (int i = 0; i < _rowCount; i++) { TRow val2 = _readRow(ref reader, _originalLayout); val.Add(ref val2); } return val; } } public class SerializedTableStream : TablesStream, ILazyMetadataStream, IMetadataStream, ISegment, IOffsetProvider, IWritable { private readonly MetadataReaderContext _context; private readonly BinaryStreamReader _reader; private readonly ulong _validMask; private readonly ulong _sortedMask; private readonly uint[] _rowCounts; private readonly uint _headerSize; private bool _tablesInitialized; private uint[]? _combinedRowCounts; private IndexSize[]? _indexSizes; public override bool CanRead => true; public SerializedTableStream(MetadataReaderContext context, string name, byte[] rawData) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(context, name, in reader); } public SerializedTableStream(MetadataReaderContext context, string name, in BinaryStreamReader reader) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) base.Name = name ?? throw new ArgumentNullException("name"); _context = context ?? throw new ArgumentNullException("context"); _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; BinaryStreamReader reader2 = ((BinaryStreamReader)(ref _reader)).Fork(); base.Reserved = ((BinaryStreamReader)(ref reader2)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref reader2)).ReadByte(); base.MinorVersion = ((BinaryStreamReader)(ref reader2)).ReadByte(); base.Flags = (TablesStreamFlags)((BinaryStreamReader)(ref reader2)).ReadByte(); base.Log2LargestRid = ((BinaryStreamReader)(ref reader2)).ReadByte(); _validMask = ((BinaryStreamReader)(ref reader2)).ReadUInt64(); _sortedMask = ((BinaryStreamReader)(ref reader2)).ReadUInt64(); _rowCounts = ReadRowCounts(ref reader2); if (base.HasExtraData) { base.ExtraData = ((BinaryStreamReader)(ref reader2)).ReadUInt32(); } _headerSize = ((BinaryStreamReader)(ref reader2)).RelativeOffset; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } private uint[] ReadRowCounts(ref BinaryStreamReader reader) { uint[] array = new uint[56]; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 56) { array[(uint)tableIndex] = (TablesStream.HasTable(_validMask, tableIndex) ? ((BinaryStreamReader)(ref reader)).ReadUInt32() : 0u); tableIndex++; } return array; } public void Initialize(IMetadata parentMetadata) { if (parentMetadata.TryGetStream(out PdbStream stream)) { _combinedRowCounts = new uint[_rowCounts.Length]; base.ExternalRowCounts = new uint[48]; for (int i = 0; i < 48; i++) { _combinedRowCounts[i] = stream.TypeSystemRowCounts[i]; base.ExternalRowCounts[i] = stream.TypeSystemRowCounts[i]; } for (int j = 48; j < 56; j++) { _combinedRowCounts[j] = _rowCounts[j]; } } else { _combinedRowCounts = _rowCounts; } _indexSizes = InitializeIndexSizes(); } protected override uint GetColumnSize(ColumnType columnType) { if (_tablesInitialized) { return base.GetColumnSize(columnType); } if (_indexSizes == null) { throw new InvalidOperationException("Serialized tables stream is not fully initialized yet."); } if ((int)columnType >= _indexSizes.Length) { return base.GetColumnSize(columnType); } return (uint)_indexSizes[(int)columnType]; } private IndexSize[] InitializeIndexSizes() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected I4, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected I4, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected I4, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected I4, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected I4, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected I4, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected I4, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected I4, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected I4, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected I4, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected I4, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected I4, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected I4, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected I4, but got Unknown List list = new List(70); uint[] rowCounts = _rowCounts; foreach (uint num in rowCounts) { list.Add((IndexSize)((num > 65535) ? 4 : 2)); } list.AddRange((IEnumerable)(object)new IndexSize[14] { (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Param, TableIndex.Property), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Param), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.Method, TableIndex.Assembly), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.Method, TableIndex.TypeSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Event, TableIndex.Property), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.MemberRef), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Method), (IndexSize)(int)GetCodedIndexSize(TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType), (IndexSize)(int)GetCodedIndexSize(TableIndex.Module, TableIndex.Module, TableIndex.Method, TableIndex.MemberRef, TableIndex.Module), (IndexSize)(int)GetCodedIndexSize(TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.Method), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec, TableIndex.Document, TableIndex.LocalScope, TableIndex.LocalVariable, TableIndex.LocalConstant, TableIndex.ImportScope) }); return list.ToArray(); } private IndexSize GetCodedIndexSize(params TableIndex[] tables) { if (_combinedRowCounts == null) { throw new InvalidOperationException("Serialized tables stream is not fully initialized yet."); } int num = (int)Math.Ceiling(Math.Log(tables.Length, 2.0)); int maxSmallTableMemberCount = 65535 >> num; if (tables.Select((TableIndex t) => _combinedRowCounts[(uint)t]).All((uint c) => c < maxSmallTableMemberCount)) { return (IndexSize)2; } return (IndexSize)4; } protected override IList GetTables() { uint offset = _headerSize; IMetadataTable[] result = new IMetadataTable[56] { CreateNextTable(TableIndex.Module, ref offset, ModuleDefinitionRow.FromReader), CreateNextTable(TableIndex.TypeRef, ref offset, TypeReferenceRow.FromReader), CreateNextTable(TableIndex.TypeDef, ref offset, TypeDefinitionRow.FromReader), CreateNextTable(TableIndex.FieldPtr, ref offset, FieldPointerRow.FromReader), CreateNextTable(TableIndex.Field, ref offset, FieldDefinitionRow.FromReader), CreateNextTable(TableIndex.MethodPtr, ref offset, MethodPointerRow.FromReader), CreateNextTable(TableIndex.Method, ref offset, MethodDefinitionRow.FromReader), CreateNextTable(TableIndex.ParamPtr, ref offset, ParameterPointerRow.FromReader), CreateNextTable(TableIndex.Param, ref offset, ParameterDefinitionRow.FromReader), CreateNextTable(TableIndex.InterfaceImpl, ref offset, InterfaceImplementationRow.FromReader), CreateNextTable(TableIndex.MemberRef, ref offset, MemberReferenceRow.FromReader), CreateNextTable(TableIndex.Constant, ref offset, ConstantRow.FromReader), CreateNextTable(TableIndex.CustomAttribute, ref offset, CustomAttributeRow.FromReader), CreateNextTable(TableIndex.FieldMarshal, ref offset, FieldMarshalRow.FromReader), CreateNextTable(TableIndex.DeclSecurity, ref offset, SecurityDeclarationRow.FromReader), CreateNextTable(TableIndex.ClassLayout, ref offset, ClassLayoutRow.FromReader), CreateNextTable(TableIndex.FieldLayout, ref offset, FieldLayoutRow.FromReader), CreateNextTable(TableIndex.StandAloneSig, ref offset, StandAloneSignatureRow.FromReader), CreateNextTable(TableIndex.EventMap, ref offset, EventMapRow.FromReader), CreateNextTable(TableIndex.EventPtr, ref offset, EventPointerRow.FromReader), CreateNextTable(TableIndex.Event, ref offset, EventDefinitionRow.FromReader), CreateNextTable(TableIndex.PropertyMap, ref offset, PropertyMapRow.FromReader), CreateNextTable(TableIndex.PropertyPtr, ref offset, PropertyPointerRow.FromReader), CreateNextTable(TableIndex.Property, ref offset, PropertyDefinitionRow.FromReader), CreateNextTable(TableIndex.MethodSemantics, ref offset, MethodSemanticsRow.FromReader), CreateNextTable(TableIndex.MethodImpl, ref offset, MethodImplementationRow.FromReader), CreateNextTable(TableIndex.ModuleRef, ref offset, ModuleReferenceRow.FromReader), CreateNextTable(TableIndex.TypeSpec, ref offset, TypeSpecificationRow.FromReader), CreateNextTable(TableIndex.ImplMap, ref offset, ImplementationMapRow.FromReader), CreateNextTable(TableIndex.FieldRva, ref offset, FieldRvaRow.FromReader), CreateNextTable(TableIndex.EncLog, ref offset, EncLogRow.FromReader), CreateNextTable(TableIndex.EncMap, ref offset, EncMapRow.FromReader), CreateNextTable(TableIndex.Assembly, ref offset, AssemblyDefinitionRow.FromReader), CreateNextTable(TableIndex.AssemblyProcessor, ref offset, AssemblyProcessorRow.FromReader), CreateNextTable(TableIndex.AssemblyOS, ref offset, AssemblyOSRow.FromReader), CreateNextTable(TableIndex.AssemblyRef, ref offset, AssemblyReferenceRow.FromReader), CreateNextTable(TableIndex.AssemblyRefProcessor, ref offset, AssemblyRefProcessorRow.FromReader), CreateNextTable(TableIndex.AssemblyRefOS, ref offset, AssemblyRefOSRow.FromReader), CreateNextTable(TableIndex.File, ref offset, FileReferenceRow.FromReader), CreateNextTable(TableIndex.ExportedType, ref offset, ExportedTypeRow.FromReader), CreateNextTable(TableIndex.ManifestResource, ref offset, ManifestResourceRow.FromReader), CreateNextTable(TableIndex.NestedClass, ref offset, NestedClassRow.FromReader), CreateNextTable(TableIndex.GenericParam, ref offset, GenericParameterRow.FromReader), CreateNextTable(TableIndex.MethodSpec, ref offset, MethodSpecificationRow.FromReader), CreateNextTable(TableIndex.GenericParamConstraint, ref offset, GenericParameterConstraintRow.FromReader), null, null, null, CreateNextTable(TableIndex.Document, ref offset, DocumentRow.FromReader), CreateNextTable(TableIndex.MethodDebugInformation, ref offset, MethodDebugInformationRow.FromReader), CreateNextTable(TableIndex.LocalScope, ref offset, LocalScopeRow.FromReader), CreateNextTable(TableIndex.LocalVariable, ref offset, LocalVariableRow.FromReader), CreateNextTable(TableIndex.LocalConstant, ref offset, LocalConstantRow.FromReader), CreateNextTable(TableIndex.ImportScope, ref offset, ImportScopeRow.FromReader), CreateNextTable(TableIndex.StateMachineMethod, ref offset, StateMachineMethodRow.FromReader), CreateNextTable(TableIndex.CustomDebugInformation, ref offset, CustomDebugInformationRow.FromReader) }; _tablesInitialized = true; return result; } private BinaryStreamReader CreateNextRawTableReader(TableIndex currentIndex, ref uint currentOffset) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) uint num = base.TableLayouts[(int)currentIndex].RowSize * _rowCounts[(uint)currentIndex]; BinaryStreamReader result = ((BinaryStreamReader)(ref _reader)).ForkRelative(currentOffset, num); currentOffset += num; return result; } private SerializedMetadataTable CreateNextTable(TableIndex index, ref uint offset, SerializedMetadataTable.ReadRowDelegate readRow) where TRow : struct, IMetadataRow { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = CreateNextRawTableReader(index, ref offset); return new SerializedMetadataTable(in reader, index, base.TableLayouts[(int)index], TablesStream.IsSorted(_sortedMask, index), readRow); } private SerializedMetadataTable CreateNextTable(TableIndex index, ref uint offset, SerializedMetadataTable.ReadRowExtendedDelegate readRow) where TRow : struct, IMetadataRow { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) MetadataReaderContext context = _context; BinaryStreamReader reader = CreateNextRawTableReader(index, ref offset); return new SerializedMetadataTable(context, in reader, index, base.TableLayouts[(int)index], TablesStream.IsSorted(_sortedMask, index), readRow); } } public enum TableIndex : byte { Module = 0, TypeRef = 1, TypeDef = 2, FieldPtr = 3, Field = 4, MethodPtr = 5, Method = 6, ParamPtr = 7, Param = 8, InterfaceImpl = 9, MemberRef = 10, Constant = 11, CustomAttribute = 12, FieldMarshal = 13, DeclSecurity = 14, ClassLayout = 15, FieldLayout = 16, StandAloneSig = 17, EventMap = 18, EventPtr = 19, Event = 20, PropertyMap = 21, PropertyPtr = 22, Property = 23, MethodSemantics = 24, MethodImpl = 25, ModuleRef = 26, TypeSpec = 27, ImplMap = 28, FieldRva = 29, EncLog = 30, EncMap = 31, Assembly = 32, AssemblyProcessor = 33, AssemblyOS = 34, AssemblyRef = 35, AssemblyRefProcessor = 36, AssemblyRefOS = 37, File = 38, ExportedType = 39, ManifestResource = 40, NestedClass = 41, GenericParam = 42, MethodSpec = 43, GenericParamConstraint = 44, MaxTypeSystemTableIndex = 44, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55, Max = 56, String = 112 } public static class TableIndexExtensions { public static bool IsValidTableIndex(this TableIndex index) { if ((int)index >= 48) { if ((int)index <= 55 || index == TableIndex.String) { goto IL_0016; } } else if ((int)index <= 44) { goto IL_0016; } return false; IL_0016: return true; } } public readonly struct TableLayout { public IReadOnlyList Columns { get; } public uint RowSize { get; } public TableLayout(params ColumnLayout[] columns) { Columns = columns; RowSize = (uint)columns.Sum((ColumnLayout c) => c.Size); } public override string ToString() { return "(" + string.Join(", ", Columns.Select((ColumnLayout c) => c.Name)) + ")"; } } public class TablesStream : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public const string CompressedStreamName = "#~"; public const string EncStreamName = "#-"; public const string MinimalStreamName = "#JTD"; public const string UncompressedStreamName = "#Schema"; private readonly Dictionary _indexEncoders; private readonly LazyVariable> _tables; private readonly LazyVariable> _layouts; public string Name { get; set; } = "#~"; public virtual bool CanRead => false; public uint Reserved { get; set; } public byte MajorVersion { get; set; } = 2; public byte MinorVersion { get; set; } public TablesStreamFlags Flags { get; set; } public IndexSize StringIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(0); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(0, value); } } public IndexSize GuidIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(1); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(1, value); } } public IndexSize BlobIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(2); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(2, value); } } public bool HasPaddingBit { get { return (Flags & TablesStreamFlags.LongBlobIndices) != 0; } set { Flags = (Flags & ~TablesStreamFlags.LongBlobIndices) | (value ? TablesStreamFlags.LongBlobIndices : ((TablesStreamFlags)0)); } } public bool HasDeltaOnly { get { return (Flags & TablesStreamFlags.DeltaOnly) != 0; } set { Flags = (Flags & ~TablesStreamFlags.DeltaOnly) | (value ? TablesStreamFlags.DeltaOnly : ((TablesStreamFlags)0)); } } public bool HasExtraData { get { return (Flags & TablesStreamFlags.ExtraData) != 0; } set { Flags = (Flags & ~TablesStreamFlags.ExtraData) | (value ? TablesStreamFlags.ExtraData : ((TablesStreamFlags)0)); } } public bool HasDeletedTokens { get { return (Flags & TablesStreamFlags.HasDelete) != 0; } set { Flags = (Flags & ~TablesStreamFlags.HasDelete) | (value ? TablesStreamFlags.HasDelete : ((TablesStreamFlags)0)); } } public byte Log2LargestRid { get; protected set; } = 1; public uint ExtraData { get; set; } [MemberNotNullWhen(true, "ExternalRowCounts")] public bool HasExternalRowCounts { [MemberNotNullWhen(true, "ExternalRowCounts")] get { return ExternalRowCounts != null; } } public uint[]? ExternalRowCounts { get; set; } protected IList Tables => _tables.Value; protected IList TableLayouts => _layouts.Value; public TablesStream() { _layouts = new LazyVariable>((Func>)GetTableLayouts); _tables = new LazyVariable>((Func>)GetTables); _indexEncoders = CreateIndexEncoders(); } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } public uint GetTableRowCount(TableIndex table) { if (!HasExternalRowCounts || (int)table >= ExternalRowCounts.Length) { return (uint)GetTable(table).Count; } return ExternalRowCounts[(uint)table]; } public IndexSize GetTableIndexSize(TableIndex table) { if (GetTableRowCount(table) > 65535) { return (IndexSize)4; } return (IndexSize)2; } protected void SynchronizeTableLayoutsWithFlags() { TableLayout[] tableLayouts = GetTableLayouts(); for (int i = 0; i < Tables.Count; i++) { Tables[i]?.UpdateTableLayout(tableLayouts[i]); } } public override uint GetPhysicalSize() { SynchronizeTableLayoutsWithFlags(); ulong validBitmask = ComputeValidBitmask(); return (uint)((int)(24 + GetTablesCount(validBitmask) * 4 + (HasExtraData ? 8 : 0) + GetTablesSize(validBitmask)) + 4); } public override void Write(IBinaryStreamWriter writer) { SynchronizeTableLayoutsWithFlags(); writer.WriteUInt32(Reserved); writer.WriteByte(MajorVersion); writer.WriteByte(MinorVersion); writer.WriteByte((byte)Flags); writer.WriteByte(Log2LargestRid); ulong num = ComputeValidBitmask(); writer.WriteUInt64(num); writer.WriteUInt64(ComputeSortedBitmask()); WriteRowCounts(writer, num); if (HasExtraData) { writer.WriteUInt32(ExtraData); } WriteTables(writer, num); writer.WriteUInt32(0u); } protected virtual ulong ComputeValidBitmask() { ulong num = 0uL; for (int i = 0; i < Tables.Count; i++) { IMetadataTable? metadataTable = Tables[i]; if (metadataTable != null && metadataTable.Count > 0) { num |= (ulong)(1L << i); } } return num; } protected virtual ulong ComputeSortedBitmask() { ulong num = 0uL; bool flag = false; bool flag2 = false; for (int i = 0; i < Tables.Count; i++) { IMetadataTable metadataTable = Tables[i]; if (metadataTable == null) { continue; } if (metadataTable.IsSorted) { num |= (ulong)(1L << i); } if (metadataTable.Count > 0) { if (i <= 44) { flag = true; } else { flag2 = true; } } } if (!flag) { num &= 0xFFFFE00000000000uL; } if (!flag2) { num &= 0xFF001FFFFFFFFFFFuL; } return num; } protected virtual int GetTablesCount(ulong validBitmask) { int num = 0; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 56) { if (HasTable(validBitmask, tableIndex)) { num++; } tableIndex++; } return num; } protected virtual uint GetTablesSize(ulong validBitmask) { long num = 0L; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < (int)(byte)Tables.Count) { if (HasTable(validBitmask, tableIndex)) { IMetadataTable table = GetTable(tableIndex); num += table.Count * table.Layout.RowSize; } tableIndex++; } return (uint)num; } protected virtual void WriteRowCounts(IBinaryStreamWriter writer, ulong validBitmask) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex <= 56) { if (HasTable(validBitmask, tableIndex)) { writer.WriteInt32(GetTable(tableIndex).Count); } tableIndex++; } } protected virtual void WriteTables(IBinaryStreamWriter writer, ulong validBitmask) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < (int)(byte)Tables.Count) { if (HasTable(validBitmask, tableIndex)) { GetTable(tableIndex).Write(writer); } tableIndex++; } } protected static bool HasTable(ulong validMask, TableIndex table) { return ((validMask >> (int)table) & 1) != 0; } protected static bool IsSorted(ulong sortedMask, TableIndex table) { return ((sortedMask >> (int)table) & 1) != 0; } public virtual IMetadataTable GetTable(TableIndex index) { return Tables[(int)index] ?? throw new ArgumentOutOfRangeException("index"); } public virtual MetadataTable GetTable() where TRow : struct, IMetadataRow { return Tables.OfType>().First(); } public virtual MetadataTable GetTable(TableIndex index) where TRow : struct, IMetadataRow { return (MetadataTable)(Tables[(int)index] ?? throw new ArgumentOutOfRangeException("index")); } private IndexSize GetStreamIndexSize(int bitIndex) { return (IndexSize)(((((int)Flags >> bitIndex) & 1) + 1) * 2); } private void SetStreamIndexSize(int bitIndex, IndexSize newSize) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 Flags = (TablesStreamFlags)(((uint)Flags & (uint)(~(1 << bitIndex))) | (((int)newSize == 4) ? ((uint)(1 << bitIndex)) : 0u)); } protected virtual uint GetColumnSize(ColumnType columnType) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected I4, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected I4, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected I4, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown if (_layouts.IsInitialized) { if (columnType <= ColumnType.CustomDebugInformation) { return (uint)(int)GetTableIndexSize((TableIndex)columnType); } if (columnType <= ColumnType.HasCustomDebugInformation) { return (uint)(int)GetIndexEncoder((CodedIndex)columnType).IndexSize; } } return columnType switch { ColumnType.Blob => (uint)(int)BlobIndexSize, ColumnType.String => (uint)(int)StringIndexSize, ColumnType.Guid => (uint)(int)GuidIndexSize, ColumnType.Byte => 1u, ColumnType.UInt16 => 2u, ColumnType.UInt32 => 4u, _ => 4u, }; } public IndexEncoder GetIndexEncoder(CodedIndex index) { return _indexEncoders[index]; } public MetadataRange GetFieldRange(uint typeDefRid) { return GetMemberRange(TableIndex.TypeDef, typeDefRid, 4, TableIndex.Field, TableIndex.FieldPtr); } public MetadataRange GetMethodRange(uint typeDefRid) { return GetMemberRange(TableIndex.TypeDef, typeDefRid, 5, TableIndex.Method, TableIndex.MethodPtr); } public MetadataRange GetParameterRange(uint methodDefRid) { return GetMemberRange(TableIndex.Method, methodDefRid, 5, TableIndex.Param, TableIndex.ParamPtr); } public MetadataRange GetPropertyRange(uint propertyMapRid) { return GetMemberRange(TableIndex.PropertyMap, propertyMapRid, 1, TableIndex.Property, TableIndex.PropertyPtr); } public MetadataRange GetEventRange(uint eventMapRid) { return GetMemberRange(TableIndex.EventMap, eventMapRid, 1, TableIndex.Event, TableIndex.EventPtr); } private MetadataRange GetMemberRange(TableIndex ownerTableIndex, uint ownerRid, int ownerColumnIndex, TableIndex memberTableIndex, TableIndex redirectTableIndex) where TOwnerRow : struct, IMetadataRow { int num = (int)(ownerRid - 1); MetadataTable table = GetTable(ownerTableIndex); if (num < 0 || num >= table.Count) { return MetadataRange.Empty; } uint startRid = table[num][ownerColumnIndex]; uint endRid = ((num < table.Count - 1) ? table[num + 1][ownerColumnIndex] : ((uint)(GetTable(memberTableIndex).Count + 1))); IMetadataTable table2 = GetTable(redirectTableIndex); if (table2.Count > 0) { return new MetadataRange(table2, memberTableIndex, startRid, endRid); } return new MetadataRange(memberTableIndex, startRid, endRid); } protected virtual IList GetTables() { IList tableLayouts = TableLayouts; return new IMetadataTable[56] { new MetadataTable(TableIndex.Module, tableLayouts[0]), new MetadataTable(TableIndex.TypeRef, tableLayouts[1]), new MetadataTable(TableIndex.TypeDef, tableLayouts[2]), new MetadataTable(TableIndex.FieldPtr, tableLayouts[3]), new MetadataTable(TableIndex.Field, tableLayouts[4]), new MetadataTable(TableIndex.Method, tableLayouts[5]), new MetadataTable(TableIndex.Method, tableLayouts[6]), new MetadataTable(TableIndex.ParamPtr, tableLayouts[7]), new MetadataTable(TableIndex.Param, tableLayouts[8]), new MetadataTable(TableIndex.InterfaceImpl, tableLayouts[9], isSorted: true), new MetadataTable(TableIndex.MemberRef, tableLayouts[10]), new MetadataTable(TableIndex.Constant, tableLayouts[11], isSorted: true), new MetadataTable(TableIndex.CustomAttribute, tableLayouts[12], isSorted: true), new MetadataTable(TableIndex.FieldMarshal, tableLayouts[13], isSorted: true), new MetadataTable(TableIndex.DeclSecurity, tableLayouts[14], isSorted: true), new MetadataTable(TableIndex.ClassLayout, tableLayouts[15], isSorted: true), new MetadataTable(TableIndex.FieldLayout, tableLayouts[16], isSorted: true), new MetadataTable(TableIndex.StandAloneSig, tableLayouts[17]), new MetadataTable(TableIndex.EventMap, tableLayouts[18]), new MetadataTable(TableIndex.EventPtr, tableLayouts[19]), new MetadataTable(TableIndex.Event, tableLayouts[20]), new MetadataTable(TableIndex.PropertyMap, tableLayouts[21]), new MetadataTable(TableIndex.PropertyPtr, tableLayouts[22]), new MetadataTable(TableIndex.Property, tableLayouts[23]), new MetadataTable(TableIndex.MethodSemantics, tableLayouts[24], isSorted: true), new MetadataTable(TableIndex.MethodImpl, tableLayouts[25], isSorted: true), new MetadataTable(TableIndex.ModuleRef, tableLayouts[26]), new MetadataTable(TableIndex.TypeSpec, tableLayouts[27]), new MetadataTable(TableIndex.ImplMap, tableLayouts[28], isSorted: true), new MetadataTable(TableIndex.FieldRva, tableLayouts[29], isSorted: true), new MetadataTable(TableIndex.EncLog, tableLayouts[30]), new MetadataTable(TableIndex.EncMap, tableLayouts[31]), new MetadataTable(TableIndex.Assembly, tableLayouts[32]), new MetadataTable(TableIndex.AssemblyProcessor, tableLayouts[33]), new MetadataTable(TableIndex.AssemblyOS, tableLayouts[34]), new MetadataTable(TableIndex.AssemblyRef, tableLayouts[35]), new MetadataTable(TableIndex.AssemblyRefProcessor, tableLayouts[36]), new MetadataTable(TableIndex.AssemblyRefProcessor, tableLayouts[37]), new MetadataTable(TableIndex.File, tableLayouts[38]), new MetadataTable(TableIndex.ExportedType, tableLayouts[39]), new MetadataTable(TableIndex.ManifestResource, tableLayouts[40]), new MetadataTable(TableIndex.NestedClass, tableLayouts[41], isSorted: true), new MetadataTable(TableIndex.GenericParam, tableLayouts[42], isSorted: true), new MetadataTable(TableIndex.MethodSpec, tableLayouts[43]), new MetadataTable(TableIndex.GenericParamConstraint, tableLayouts[44], isSorted: true), null, null, null, new MetadataTable(TableIndex.Document, tableLayouts[48]), new MetadataTable(TableIndex.MethodDebugInformation, tableLayouts[49]), new MetadataTable(TableIndex.LocalScope, tableLayouts[50], isSorted: true), new MetadataTable(TableIndex.LocalVariable, tableLayouts[51]), new MetadataTable(TableIndex.LocalConstant, tableLayouts[52]), new MetadataTable(TableIndex.ImportScope, tableLayouts[53]), new MetadataTable(TableIndex.StateMachineMethod, tableLayouts[54]), new MetadataTable(TableIndex.CustomDebugInformation, tableLayouts[55], isSorted: true) }; } private Dictionary CreateIndexEncoders() { Dictionary dictionary = new Dictionary(); dictionary[CodedIndex.TypeDefOrRef] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec); dictionary[CodedIndex.HasConstant] = new IndexEncoder(this, TableIndex.Field, TableIndex.Param, TableIndex.Property); dictionary[CodedIndex.HasCustomAttribute] = new IndexEncoder(this, TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec); dictionary[CodedIndex.HasFieldMarshal] = new IndexEncoder(this, TableIndex.Field, TableIndex.Param); dictionary[CodedIndex.HasDeclSecurity] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.Method, TableIndex.Assembly); dictionary[CodedIndex.MemberRefParent] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.Method, TableIndex.TypeSpec); dictionary[CodedIndex.HasSemantics] = new IndexEncoder(this, TableIndex.Event, TableIndex.Property); dictionary[CodedIndex.MethodDefOrRef] = new IndexEncoder(this, TableIndex.Method, TableIndex.MemberRef); dictionary[CodedIndex.MemberForwarded] = new IndexEncoder(this, TableIndex.Field, TableIndex.Method); dictionary[CodedIndex.Implementation] = new IndexEncoder(this, TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType); dictionary[CodedIndex.CustomAttributeType] = new IndexEncoder(this, TableIndex.Module, TableIndex.Module, TableIndex.Method, TableIndex.MemberRef, TableIndex.Module); dictionary[CodedIndex.ResolutionScope] = new IndexEncoder(this, TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef); dictionary[CodedIndex.TypeOrMethodDef] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.Method); dictionary[CodedIndex.HasCustomDebugInformation] = new IndexEncoder(this, TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec, TableIndex.Document, TableIndex.LocalScope, TableIndex.LocalVariable, TableIndex.LocalConstant, TableIndex.ImportScope); return dictionary; } protected TableLayout[] GetTableLayouts() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07d9: Unknown result type (might be due to invalid IL or missing references) //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_08f0: Unknown result type (might be due to invalid IL or missing references) //IL_094d: Unknown result type (might be due to invalid IL or missing references) //IL_0ac3: Unknown result type (might be due to invalid IL or missing references) //IL_0adc: Unknown result type (might be due to invalid IL or missing references) //IL_0af5: Unknown result type (might be due to invalid IL or missing references) //IL_0c0e: Unknown result type (might be due to invalid IL or missing references) //IL_0c27: Unknown result type (might be due to invalid IL or missing references) //IL_0c40: Unknown result type (might be due to invalid IL or missing references) //IL_0c59: Unknown result type (might be due to invalid IL or missing references) //IL_0d4f: Unknown result type (might be due to invalid IL or missing references) //IL_0d68: Unknown result type (might be due to invalid IL or missing references) //IL_0dc0: Unknown result type (might be due to invalid IL or missing references) //IL_0dd9: Unknown result type (might be due to invalid IL or missing references) //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_0f1f: Unknown result type (might be due to invalid IL or missing references) //IL_0f65: Unknown result type (might be due to invalid IL or missing references) //IL_0fda: Unknown result type (might be due to invalid IL or missing references) //IL_0ff3: Unknown result type (might be due to invalid IL or missing references) //IL_100c: Unknown result type (might be due to invalid IL or missing references) //IL_1025: Unknown result type (might be due to invalid IL or missing references) //IL_106c: Unknown result type (might be due to invalid IL or missing references) //IL_116d: Unknown result type (might be due to invalid IL or missing references) //IL_1199: Unknown result type (might be due to invalid IL or missing references) //IL_11b2: Unknown result type (might be due to invalid IL or missing references) //IL_11f9: Unknown result type (might be due to invalid IL or missing references) //IL_1285: Unknown result type (might be due to invalid IL or missing references) //IL_129e: Unknown result type (might be due to invalid IL or missing references) return new TableLayout[56] { new TableLayout(new ColumnLayout("Generation", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Mvid", ColumnType.Guid, GuidIndexSize), new ColumnLayout("EncId", ColumnType.Guid, GuidIndexSize), new ColumnLayout("EncBaseId", ColumnType.Guid, GuidIndexSize)), new TableLayout(new ColumnLayout("ResolutionScope", ColumnType.ResolutionScope, GetColumnSize(ColumnType.ResolutionScope)), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.Guid, StringIndexSize)), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.String, StringIndexSize), new ColumnLayout("Extends", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef)), new ColumnLayout("FieldList", ColumnType.Field, GetColumnSize(ColumnType.Field)), new ColumnLayout("MethodList", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("Field", ColumnType.Field, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("RVA", ColumnType.UInt32), new ColumnLayout("ImplFlags", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize), new ColumnLayout("ParamList", ColumnType.Param, GetColumnSize(ColumnType.Param))), new TableLayout(new ColumnLayout("Parameter", ColumnType.Param, GetColumnSize(ColumnType.Param))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Sequence", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Class", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("Interface", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), new TableLayout(new ColumnLayout("Parent", ColumnType.MemberRefParent, GetColumnSize(ColumnType.MemberRefParent)), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Type", ColumnType.Byte), new ColumnLayout("Padding", ColumnType.Byte), new ColumnLayout("Parent", ColumnType.HasConstant, GetColumnSize(ColumnType.HasConstant)), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.HasCustomAttribute, GetColumnSize(ColumnType.HasCustomAttribute)), new ColumnLayout("Type", ColumnType.CustomAttributeType, GetColumnSize(ColumnType.CustomAttributeType)), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.HasFieldMarshal, GetColumnSize(ColumnType.HasFieldMarshal)), new ColumnLayout("NativeType", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Action", ColumnType.UInt16), new ColumnLayout("Parent", ColumnType.HasDeclSecurity, GetColumnSize(ColumnType.HasDeclSecurity)), new ColumnLayout("PermissionSet", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("PackingSize", ColumnType.UInt16), new ColumnLayout("ClassSize", ColumnType.UInt32), new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef))), new TableLayout(new ColumnLayout("Offset", ColumnType.UInt32), new ColumnLayout("Field", ColumnType.TypeDef, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("EventList", ColumnType.Event, GetColumnSize(ColumnType.Event))), new TableLayout(new ColumnLayout("Event", ColumnType.Event, GetColumnSize(ColumnType.Event))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("EventType", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), new TableLayout(new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("PropertyList", ColumnType.Event, GetColumnSize(ColumnType.Property))), new TableLayout(new ColumnLayout("Property", ColumnType.Property, GetColumnSize(ColumnType.Property))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("PropertyType", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Semantic", ColumnType.UInt16), new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("Association", ColumnType.HasSemantics, GetColumnSize(ColumnType.HasSemantics))), new TableLayout(new ColumnLayout("Class", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("MethodBody", ColumnType.MethodDefOrRef, GetColumnSize(ColumnType.MethodDefOrRef)), new ColumnLayout("MethodDeclaration", ColumnType.MethodDefOrRef, GetColumnSize(ColumnType.MethodDefOrRef))), new TableLayout(new ColumnLayout("Name", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("MappingFlags", ColumnType.UInt16), new ColumnLayout("MemberForwarded", ColumnType.MemberForwarded, GetColumnSize(ColumnType.MemberForwarded)), new ColumnLayout("ImportName", ColumnType.String, StringIndexSize), new ColumnLayout("ImportScope", ColumnType.ModuleRef, GetColumnSize(ColumnType.ModuleRef))), new TableLayout(new ColumnLayout("RVA", ColumnType.UInt32), new ColumnLayout("Field", ColumnType.Field, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Token", ColumnType.UInt32), new ColumnLayout("FuncCode", ColumnType.UInt32)), new TableLayout(new ColumnLayout("Token", ColumnType.UInt32)), new TableLayout(new ColumnLayout("HashAlgId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt16), new ColumnLayout("MinorVersion", ColumnType.UInt16), new ColumnLayout("BuildNumber", ColumnType.UInt16), new ColumnLayout("RevisionNumber", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("PublicKey", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Culture", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Processor", ColumnType.UInt32)), new TableLayout(new ColumnLayout("PlatformId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt32), new ColumnLayout("MinorVersion", ColumnType.UInt32)), new TableLayout(new ColumnLayout("MajorVersion", ColumnType.UInt16), new ColumnLayout("MinorVersion", ColumnType.UInt16), new ColumnLayout("BuildNumber", ColumnType.UInt16), new ColumnLayout("RevisionNumber", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("PublicKeyOrToken", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Culture", ColumnType.String, StringIndexSize), new ColumnLayout("HashValue", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Processor", ColumnType.UInt32), new ColumnLayout("AssemblyRef", ColumnType.AssemblyRef, GetColumnSize(ColumnType.AssemblyRef))), new TableLayout(new ColumnLayout("PlatformId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt32), new ColumnLayout("MinorVersion", ColumnType.UInt32), new ColumnLayout("AssemblyRef", ColumnType.AssemblyRef, GetColumnSize(ColumnType.AssemblyRef))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("HashValue", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("TypeDefId", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.String, StringIndexSize), new ColumnLayout("Implementation", ColumnType.Implementation, GetColumnSize(ColumnType.Implementation))), new TableLayout(new ColumnLayout("Offset", ColumnType.UInt32), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Implementation", ColumnType.Implementation, GetColumnSize(ColumnType.Implementation))), new TableLayout(new ColumnLayout("NestedClass", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("EnclosingClass", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef))), new TableLayout(new ColumnLayout("Number", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Owner", ColumnType.TypeOrMethodDef, GetColumnSize(ColumnType.TypeOrMethodDef)), new ColumnLayout("EnclosingClass", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.MethodDefOrRef)), new ColumnLayout("Instantiation", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Owner", ColumnType.GenericParam, GetColumnSize(ColumnType.GenericParam)), new ColumnLayout("Constraint", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), default(TableLayout), default(TableLayout), default(TableLayout), new TableLayout(new ColumnLayout("Name", ColumnType.Blob, BlobIndexSize), new ColumnLayout("HashAlgorithm", ColumnType.Guid, GuidIndexSize), new ColumnLayout("Hash", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Language", ColumnType.Guid, GuidIndexSize)), new TableLayout(new ColumnLayout("Document", ColumnType.Document, GetColumnSize(ColumnType.Document)), new ColumnLayout("SequencePoints", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("ImportScope", ColumnType.ImportScope, GetColumnSize(ColumnType.ImportScope)), new ColumnLayout("VariableList", ColumnType.LocalVariable, GetColumnSize(ColumnType.LocalVariable)), new ColumnLayout("ConstantList", ColumnType.LocalConstant, GetColumnSize(ColumnType.LocalConstant)), new ColumnLayout("StartOffset", ColumnType.UInt32), new ColumnLayout("Length", ColumnType.UInt32)), new TableLayout(new ColumnLayout("Attributes", ColumnType.UInt16), new ColumnLayout("Index", ColumnType.UInt16), new ColumnLayout("VariableList", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.ImportScope, GetColumnSize(ColumnType.ImportScope)), new ColumnLayout("Imports", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("MoveNextMethod", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("KickoffMethod", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("Parent", ColumnType.HasCustomDebugInformation, GetColumnSize(ColumnType.HasCustomDebugInformation)), new ColumnLayout("Kind", ColumnType.Guid, GuidIndexSize), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)) }; } } [Flags] public enum TablesStreamFlags : byte { LongStringIndices = 1, LongGuidIndices = 2, LongBlobIndices = 4, PaddingBit = 8, DeltaOnly = 0x20, ExtraData = 0x40, HasDelete = 0x80 } public static class TypeReferenceHash { public static byte[] GetTypeReferenceHash(this IPEImage image) { return (image.DotNetDirectory?.Metadata ?? throw new ArgumentException("Portable executable does not contain a .NET image.")).GetTypeReferenceHash(); } public static byte[] GetTypeReferenceHash(this IMetadata metadata) { TablesStream stream = metadata.GetStream(); StringsStream stringsStream = metadata.GetStream(); IEnumerable values = from row in stream.GetTable(TableIndex.TypeRef) orderby stringsStream.GetStringByIndex(row.Namespace), stringsStream.GetStringByIndex(row.Name) select $"{stringsStream.GetStringByIndex(row.Namespace)}-{stringsStream.GetStringByIndex(row.Name)}"; string s = string.Join(",", values); using SHA256 sHA = SHA256.Create(); return sHA.ComputeHash(Encoding.UTF8.GetBytes(s)); } } } namespace AsmResolver.PE.DotNet.Metadata.Tables.Rows { [Flags] public enum AssemblyAttributes : uint { PublicKey = 1u, ArchitectureNone = 0u, ArchitectureMsil = 0x10u, ArchitectureX86 = 0x20u, ArchitectureIa64 = 0x30u, ArchitectureAmd64 = 0x40u, ArchitectureMask = 0x70u, Specified = 0x80u, FullMask = 0xF0u, EnableJitCompileTracking = 0x8000u, DisableJitCompileOptimizer = 0x4000u, Retargetable = 0x100u, ContentDefault = 0u, ContentWindowsRuntime = 0x200u, ContentMask = 0xE00u } public struct AssemblyDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Assembly; public int Count => 9; public uint this[int index] => index switch { 0 => (uint)HashAlgorithm, 1 => MajorVersion, 2 => MinorVersion, 3 => BuildNumber, 4 => RevisionNumber, 5 => (uint)Attributes, 6 => PublicKey, 7 => Name, 8 => Culture, _ => throw new IndexOutOfRangeException(), }; public AssemblyHashAlgorithm HashAlgorithm { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public ushort BuildNumber { get; set; } public ushort RevisionNumber { get; set; } public AssemblyAttributes Attributes { get; set; } public uint PublicKey { get; set; } public uint Name { get; set; } public uint Culture { get; set; } public static AssemblyDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyDefinitionRow((AssemblyHashAlgorithm)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), (AssemblyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[6].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[7].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[8].Size)); } public AssemblyDefinitionRow(AssemblyHashAlgorithm hashAlgorithm, ushort majorVersion, ushort minorVersion, ushort buildNumber, ushort revisionNumber, AssemblyAttributes attributes, uint publicKey, uint name, uint culture) { HashAlgorithm = hashAlgorithm; MajorVersion = majorVersion; MinorVersion = minorVersion; BuildNumber = buildNumber; RevisionNumber = revisionNumber; Attributes = attributes; PublicKey = publicKey; Name = name; Culture = culture; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)HashAlgorithm); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt16(BuildNumber); writer.WriteUInt16(RevisionNumber); writer.WriteUInt32((uint)Attributes); IOExtensions.WriteIndex(writer, PublicKey, (IndexSize)layout.Columns[6].Size); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[7].Size); IOExtensions.WriteIndex(writer, Culture, (IndexSize)layout.Columns[8].Size); } public bool Equals(AssemblyDefinitionRow other) { if (HashAlgorithm == other.HashAlgorithm && MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion && BuildNumber == other.BuildNumber && RevisionNumber == other.RevisionNumber && Attributes == other.Attributes && PublicKey == other.PublicKey && Name == other.Name) { return Culture == other.Culture; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)((((((((((int)HashAlgorithm * 397) ^ MajorVersion.GetHashCode()) * 397) ^ MinorVersion.GetHashCode()) * 397) ^ BuildNumber.GetHashCode()) * 397) ^ RevisionNumber.GetHashCode()) * 397) ^ (uint)Attributes) * 397) ^ PublicKey) * 397) ^ Name) * 397) ^ Culture); } public override string ToString() { return $"({HashAlgorithm:X8}, {MajorVersion:X4}, {MinorVersion:X4}, {BuildNumber:X4}, {RevisionNumber:X4}, {Attributes:X8}, {PublicKey:X8}, {Name:X8}, {Culture:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum AssemblyHashAlgorithm : uint { None = 0u, Md2 = 32769u, Md4 = 32770u, Md5 = 32771u, Sha1 = 32772u, Mac = 32773u, Ripemd = 32774u, Ripemd160 = 32775u, Ssl3Shamd5 = 32776u, Hmac = 32777u, Tls1Prf = 32778u, HashReplaceOwf = 32779u, Sha256 = 32780u, Sha384 = 32781u, Sha512 = 32782u } public struct AssemblyOSRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyOS; public int Count => 3; public uint this[int index] => index switch { 0 => PlatformId, 1 => MajorVersion, 2 => MinorVersion, _ => throw new IndexOutOfRangeException(), }; public uint PlatformId { get; set; } public uint MajorVersion { get; set; } public uint MinorVersion { get; set; } public static AssemblyOSRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyOSRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32()); } public AssemblyOSRow(uint platformId, uint majorVersion, uint minorVersion) { PlatformId = platformId; MajorVersion = majorVersion; MinorVersion = minorVersion; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(PlatformId); writer.WriteUInt32(MajorVersion); writer.WriteUInt32(MinorVersion); } public bool Equals(AssemblyOSRow other) { if (PlatformId == other.PlatformId && MajorVersion == other.MajorVersion) { return MinorVersion == other.MinorVersion; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyOSRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((PlatformId * 397) ^ MajorVersion) * 397) ^ MinorVersion); } public override string ToString() { return $"({PlatformId:X8}, {MajorVersion:X8}, {MinorVersion:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyProcessorRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyProcessor; public int Count => 1; public uint this[int index] { get { if (index == 0) { return ProcessorId; } throw new IndexOutOfRangeException(); } } public uint ProcessorId { get; set; } public static AssemblyProcessorRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyProcessorRow(((BinaryStreamReader)(ref reader)).ReadUInt32()); } public AssemblyProcessorRow(uint processorId) { ProcessorId = processorId; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(ProcessorId); } public bool Equals(AssemblyProcessorRow other) { return ProcessorId == other.ProcessorId; } public override bool Equals(object? obj) { if (obj is AssemblyProcessorRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)ProcessorId; } public override string ToString() { return $"({ProcessorId:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Assembly; public int Count => 9; public uint this[int index] => index switch { 0 => MajorVersion, 1 => MinorVersion, 2 => BuildNumber, 3 => RevisionNumber, 4 => (uint)Attributes, 5 => PublicKeyOrToken, 6 => Name, 7 => Culture, 8 => HashValue, _ => throw new IndexOutOfRangeException(), }; public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public ushort BuildNumber { get; set; } public ushort RevisionNumber { get; set; } public AssemblyAttributes Attributes { get; set; } public uint PublicKeyOrToken { get; set; } public uint Name { get; set; } public uint Culture { get; set; } public uint HashValue { get; set; } public static AssemblyReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyReferenceRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), (AssemblyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[6].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[7].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[8].Size)); } public AssemblyReferenceRow(ushort majorVersion, ushort minorVersion, ushort buildNumber, ushort revisionNumber, AssemblyAttributes attributes, uint publicKeyOrToken, uint name, uint culture, uint hashValue) { MajorVersion = majorVersion; MinorVersion = minorVersion; BuildNumber = buildNumber; RevisionNumber = revisionNumber; Attributes = attributes; PublicKeyOrToken = publicKeyOrToken; Name = name; Culture = culture; HashValue = hashValue; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt16(BuildNumber); writer.WriteUInt16(RevisionNumber); writer.WriteUInt32((uint)Attributes); IOExtensions.WriteIndex(writer, PublicKeyOrToken, (IndexSize)layout.Columns[5].Size); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[6].Size); IOExtensions.WriteIndex(writer, Culture, (IndexSize)layout.Columns[7].Size); IOExtensions.WriteIndex(writer, HashValue, (IndexSize)layout.Columns[8].Size); } public bool Equals(AssemblyReferenceRow other) { if (MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion && BuildNumber == other.BuildNumber && RevisionNumber == other.RevisionNumber && Attributes == other.Attributes && PublicKeyOrToken == other.PublicKeyOrToken && Name == other.Name && Culture == other.Culture) { return HashValue == other.HashValue; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((uint)(((((((MajorVersion.GetHashCode() * 397) ^ MinorVersion.GetHashCode()) * 397) ^ BuildNumber.GetHashCode()) * 397) ^ RevisionNumber.GetHashCode()) * 397) ^ (uint)Attributes) * 397) ^ PublicKeyOrToken) * 397) ^ Name) * 397) ^ Culture) * 397) ^ HashValue); } public override string ToString() { return $"({MajorVersion:X4}, {MinorVersion:X4}, {BuildNumber:X4}, {RevisionNumber:X4}, {Attributes:X8}, {PublicKeyOrToken:X8}, {Name:X8}, {Culture:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyRefOSRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyRefOS; public int Count => 4; public uint this[int index] => index switch { 0 => PlatformId, 1 => MajorVersion, 2 => MinorVersion, 3 => AssemblyReference, _ => throw new IndexOutOfRangeException(), }; public uint PlatformId { get; set; } public uint MajorVersion { get; set; } public uint MinorVersion { get; set; } public uint AssemblyReference { get; set; } public static AssemblyRefOSRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyRefOSRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public AssemblyRefOSRow(uint platformId, uint majorVersion, uint minorVersion, uint assemblyReference) { PlatformId = platformId; MajorVersion = majorVersion; MinorVersion = minorVersion; AssemblyReference = assemblyReference; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(PlatformId); writer.WriteUInt32(MajorVersion); writer.WriteUInt32(MinorVersion); IOExtensions.WriteIndex(writer, AssemblyReference, (IndexSize)layout.Columns[3].Size); } public bool Equals(AssemblyRefOSRow other) { if (PlatformId == other.PlatformId && MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion) { return AssemblyReference == other.AssemblyReference; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyRefOSRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((PlatformId * 397) ^ MajorVersion) * 397) ^ MinorVersion) * 397) ^ AssemblyReference); } public override string ToString() { return $"({PlatformId:X8}, {MajorVersion:X8}, {MinorVersion:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyRefProcessorRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyRefProcessor; public int Count => 2; public uint this[int index] => index switch { 0 => ProcessorId, 1 => AssemblyReference, _ => throw new IndexOutOfRangeException(), }; public uint ProcessorId { get; set; } public uint AssemblyReference { get; set; } public static AssemblyRefProcessorRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyRefProcessorRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public AssemblyRefProcessorRow(uint processorId, uint assemblyReference) { ProcessorId = processorId; AssemblyReference = assemblyReference; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(ProcessorId); IOExtensions.WriteIndex(writer, AssemblyReference, (IndexSize)layout.Columns[1].Size); } public bool Equals(AssemblyRefProcessorRow other) { if (ProcessorId == other.ProcessorId) { return AssemblyReference == other.AssemblyReference; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyRefProcessorRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((ProcessorId * 397) ^ AssemblyReference); } public override string ToString() { return $"({ProcessorId:X8}, {AssemblyReference:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ClassLayoutRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ClassLayout; public int Count => 3; public uint this[int index] => index switch { 0 => PackingSize, 1 => ClassSize, 2 => Parent, _ => throw new IndexOutOfRangeException(), }; public ushort PackingSize { get; set; } public uint ClassSize { get; set; } public uint Parent { get; set; } public static ClassLayoutRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ClassLayoutRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public ClassLayoutRow(ushort packingSize, uint classSize, uint parent) { PackingSize = packingSize; ClassSize = classSize; Parent = parent; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(PackingSize); writer.WriteUInt32(ClassSize); IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[2].Size); } public bool Equals(ClassLayoutRow other) { if (PackingSize == other.PackingSize && ClassSize == other.ClassSize) { return Parent == other.Parent; } return false; } public override bool Equals(object? obj) { if (obj is ClassLayoutRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)(PackingSize.GetHashCode() * 397) ^ ClassSize) * 397) ^ Parent); } public override string ToString() { return $"({PackingSize:X4}, {ClassSize:X8}, {Parent:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ConstantRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Constant; public int Count => 4; public uint this[int index] => index switch { 0 => (uint)Type, 1 => Padding, 2 => Parent, 3 => Value, _ => throw new IndexOutOfRangeException(), }; public ElementType Type { get; } public byte Padding { get; set; } public uint Parent { get; set; } public uint Value { get; set; } public static ConstantRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ConstantRow((ElementType)((BinaryStreamReader)(ref reader)).ReadByte(), ((BinaryStreamReader)(ref reader)).ReadByte(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ConstantRow(ElementType type, uint parent, uint value) { Type = type; Padding = 0; Parent = parent; Value = value; } public ConstantRow(ElementType type, byte padding, uint parent, uint value) { Type = type; Padding = padding; Parent = parent; Value = value; } public bool Equals(ConstantRow other) { if (Type == other.Type && Padding == other.Padding && Parent == other.Parent) { return Value == other.Value; } return false; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteByte((byte)Type); writer.WriteByte(Padding); IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Value, (IndexSize)layout.Columns[3].Size); } public override bool Equals(object? obj) { if (obj is ConstantRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((((int)Type * 397) ^ Padding.GetHashCode()) * 397) ^ Parent) * 397) ^ Value); } public override string ToString() { return $"({Type:X2}, {Padding:X2}, {Parent:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct CustomAttributeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.CustomAttribute; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Type, 2 => Value, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Type { get; set; } public uint Value { get; set; } public static CustomAttributeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new CustomAttributeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public CustomAttributeRow(uint parent, uint type, uint value) { Parent = parent; Type = type; Value = value; } public bool Equals(CustomAttributeRow other) { if (Parent == other.Parent && Type == other.Type) { return Value == other.Value; } return false; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Type, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Value, (IndexSize)layout.Columns[2].Size); } public override bool Equals(object? obj) { if (obj is CustomAttributeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Type) * 397) ^ Value); } public override string ToString() { return $"({Parent:X8}, {Type:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct CustomDebugInformationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.CustomDebugInformation; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Kind, 2 => Value, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Kind { get; set; } public uint Value { get; set; } public CustomDebugInformationRow(uint parent, uint kind, uint value) { Parent = parent; Kind = kind; Value = value; } public static CustomDebugInformationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new CustomDebugInformationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Kind, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Value, (IndexSize)layout.Columns[2].Size); } public bool Equals(CustomDebugInformationRow other) { if (Parent == other.Parent && Kind == other.Kind) { return Value == other.Value; } return false; } public override bool Equals(object? obj) { if (obj is CustomDebugInformationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Kind) * 397) ^ Value); } public override string ToString() { return $"({Parent:X8}, {Kind:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum DeltaFunctionCode : uint { FuncDefault, MethodCreate, FieldCreate, ParamCreate, PropertyCreate, EventCreate } public struct DocumentRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 4; public uint this[int index] => index switch { 0 => Name, 1 => HashAlgorithm, 2 => Hash, 3 => Language, _ => throw new IndexOutOfRangeException(), }; public uint Name { get; set; } public uint HashAlgorithm { get; set; } public uint Hash { get; set; } public uint Language { get; set; } public DocumentRow(uint name, uint hashAlgorithm, uint hash, uint language) { Name = name; HashAlgorithm = hashAlgorithm; Hash = hash; Language = language; } public static DocumentRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new DocumentRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, HashAlgorithm, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Hash, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Language, (IndexSize)layout.Columns[3].Size); } public bool Equals(DocumentRow other) { if (Name == other.Name && HashAlgorithm == other.HashAlgorithm && Hash == other.Hash) { return Language == other.Language; } return false; } public override bool Equals(object? obj) { if (obj is DocumentRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((Name * 397) ^ HashAlgorithm) * 397) ^ Hash) * 397) ^ Language); } public override string ToString() { return $"({Name:X8}, {HashAlgorithm:X8}, {Hash:X8}, {Language:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum ElementType : byte { None = 0, Void = 1, Boolean = 2, Char = 3, I1 = 4, U1 = 5, I2 = 6, U2 = 7, I4 = 8, U4 = 9, I8 = 10, U8 = 11, R4 = 12, R8 = 13, String = 14, Ptr = 15, ByRef = 16, ValueType = 17, Class = 18, Var = 19, Array = 20, GenericInst = 21, TypedByRef = 22, I = 24, U = 25, FnPtr = 27, Object = 28, SzArray = 29, MVar = 30, CModReqD = 31, CModOpt = 32, Internal = 33, Modifier = 64, Sentinel = 65, Pinned = 69, Type = 80, Boxed = 81, Enum = 85 } public struct EncLogRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EncLog; public int Count => 2; public uint this[int index] => index switch { 0 => Token.ToUInt32(), 1 => (uint)FuncCode, _ => throw new IndexOutOfRangeException(), }; public MetadataToken Token { get; set; } public DeltaFunctionCode FuncCode { get; set; } public static EncLogRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EncLogRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), (DeltaFunctionCode)((BinaryStreamReader)(ref reader)).ReadUInt32()); } public EncLogRow(MetadataToken token, DeltaFunctionCode funcCode) { Token = token; FuncCode = funcCode; } public bool Equals(EncLogRow other) { if (Token.Equals(other.Token)) { return FuncCode == other.FuncCode; } return false; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Token.ToUInt32()); writer.WriteUInt32((uint)FuncCode); } public override bool Equals(object? obj) { if (obj is EncLogRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (Token.GetHashCode() * 397) ^ (int)FuncCode; } public override string ToString() { return $"({Token}, {FuncCode:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EncMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EncMap; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Token.ToUInt32(); } throw new IndexOutOfRangeException(); } } public MetadataToken Token { get; set; } public static EncMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EncMapRow(((BinaryStreamReader)(ref reader)).ReadUInt32()); } public EncMapRow(MetadataToken token) { Token = token; } public bool Equals(EncMapRow other) { return Token.Equals(other.Token); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Token.ToUInt32()); } public override bool Equals(object? obj) { if (obj is EncMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return Token.GetHashCode(); } public override string ToString() { return $"({Token})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum EventAttributes : ushort { SpecialName = 0x200, RtSpecialName = 0x400 } public struct EventDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Event; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => EventType, _ => throw new IndexOutOfRangeException(), }; public EventAttributes Attributes { get; set; } public uint Name { get; set; } public uint EventType { get; set; } public static EventDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventDefinitionRow((EventAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public EventDefinitionRow(EventAttributes attributes, uint name, uint eventType) { Attributes = attributes; Name = name; EventType = eventType; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, EventType, (IndexSize)layout.Columns[2].Size); } public bool Equals(EventDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return EventType == other.EventType; } return false; } public override bool Equals(object? obj) { if (obj is EventDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ EventType); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {EventType:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EventMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EventMap; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => EventList, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint EventList { get; set; } public static EventMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventMapRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public EventMapRow(uint parent, uint eventList) { Parent = parent; EventList = eventList; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, EventList, (IndexSize)layout.Columns[1].Size); } public bool Equals(EventMapRow other) { if (Parent == other.Parent) { return EventList == other.EventList; } return false; } public override bool Equals(object? obj) { if (obj is EventMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ EventList); } public override string ToString() { return $"({Parent:X8}, {EventList:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EventPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EventPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Event; } throw new IndexOutOfRangeException(); } } public uint Event { get; set; } public static EventPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public EventPointerRow(uint @event) { Event = @event; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Event, (IndexSize)layout.Columns[0].Size); } public bool Equals(EventPointerRow other) { return Event == other.Event; } public override bool Equals(object? obj) { if (obj is EventPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Event; } public override string ToString() { return $"({Event:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ExportedTypeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ExportedType; public int Count => 5; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => TypeDefinitionId, 2 => Name, 3 => Namespace, 4 => Implementation, _ => throw new IndexOutOfRangeException(), }; public TypeAttributes Attributes { get; set; } public uint TypeDefinitionId { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public uint Implementation { get; set; } public static ExportedTypeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ExportedTypeRow((TypeAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size)); } public ExportedTypeRow(TypeAttributes attributes, uint typeDefinitionId, uint name, uint ns, uint implementation) { Attributes = attributes; TypeDefinitionId = typeDefinitionId; Name = name; Namespace = ns; Implementation = implementation; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); writer.WriteUInt32(TypeDefinitionId); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Namespace, (IndexSize)layout.Columns[3].Size); IOExtensions.WriteIndex(writer, Implementation, (IndexSize)layout.Columns[4].Size); } public bool Equals(ExportedTypeRow other) { if (Attributes == other.Attributes && TypeDefinitionId == other.TypeDefinitionId && Name == other.Name && Namespace == other.Namespace) { return Implementation == other.Implementation; } return false; } public override bool Equals(object? obj) { if (obj is ExportedTypeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)((int)Attributes * 397) ^ TypeDefinitionId) * 397) ^ Name) * 397) ^ Namespace) * 397) ^ Implementation); } public override string ToString() { return $"({Attributes:X8}, {TypeDefinitionId:X8}, {Name:X8}, {Namespace:X8}, {Implementation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum FieldAttributes : ushort { FieldAccessMask = 7, PrivateScope = 0, Private = 1, FamilyAndAssembly = 2, Assembly = 3, Family = 4, FamilyOrAssembly = 5, Public = 6, Static = 0x10, InitOnly = 0x20, Literal = 0x40, NotSerialized = 0x80, SpecialName = 0x200, PInvokeImpl = 0x2000, ReservedMask = 0x9500, RuntimeSpecialName = 0x400, HasFieldMarshal = 0x1000, HasDefault = 0x8000, HasFieldRva = 0x100 } public struct FieldDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Field; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Signature, _ => throw new IndexOutOfRangeException(), }; public FieldAttributes Attributes { get; set; } public uint Name { get; set; } public uint Signature { get; } public static FieldDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldDefinitionRow((FieldAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public FieldDefinitionRow(FieldAttributes attributes, uint name, uint signature) { Attributes = attributes; Name = name; Signature = signature; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[2].Size); } public bool Equals(FieldDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is FieldDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Signature); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldLayoutRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldLayout; public int Count => 2; public uint this[int index] => index switch { 0 => Offset, 1 => Field, _ => throw new IndexOutOfRangeException(), }; public uint Offset { get; set; } public uint Field { get; set; } public static FieldLayoutRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldLayoutRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldLayoutRow(uint offset, uint field) { Offset = offset; Field = field; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Offset); IOExtensions.WriteIndex(writer, Field, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldLayoutRow other) { if (Offset == other.Offset) { return Field == other.Field; } return false; } public override bool Equals(object? obj) { if (obj is FieldLayoutRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Offset * 397) ^ Field); } public override string ToString() { return $"({Offset:X8}, {Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldMarshalRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldMarshal; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => NativeType, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint NativeType { get; set; } public static FieldMarshalRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldMarshalRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldMarshalRow(uint parent, uint nativeType) { Parent = parent; NativeType = nativeType; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, NativeType, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldMarshalRow other) { if (Parent == other.Parent) { return NativeType == other.NativeType; } return false; } public override bool Equals(object? obj) { if (obj is FieldMarshalRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ NativeType); } public override string ToString() { return $"({Parent:X8}, {NativeType:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Field; } throw new IndexOutOfRangeException(); } } public uint Field { get; set; } public static FieldPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public FieldPointerRow(uint field) { Field = field; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Field, (IndexSize)layout.Columns[0].Size); } public bool Equals(FieldPointerRow other) { return Field == other.Field; } public override bool Equals(object? obj) { if (obj is FieldPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Field; } public override string ToString() { return $"({Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldRvaRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldRva; public int Count => 2; public uint this[int index] { get { switch (index) { case 0: { ISegmentReference data = Data; return (data != null) ? ((IOffsetProvider)data).Rva : 0u; } case 1: return Field; default: throw new IndexOutOfRangeException(); } } } public ISegmentReference Data { get; set; } public uint Field { get; set; } public static FieldRvaRow FromReader(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout) { return new FieldRvaRow(context.ReferenceFactory.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldRvaRow(ISegmentReference data, uint field) { Data = data; Field = field; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(((IOffsetProvider)Data).Rva); IOExtensions.WriteIndex(writer, Field, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldRvaRow other) { ISegmentReference data = Data; uint? num = ((data != null) ? new uint?(((IOffsetProvider)data).Rva) : null); ISegmentReference data2 = other.Data; if (num == ((data2 != null) ? new uint?(((IOffsetProvider)data2).Rva) : null)) { return Field == other.Field; } return false; } public override bool Equals(object? obj) { if (obj is FieldRvaRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((IOffsetProvider)Data).Rva * 397) ^ Field); } public override string ToString() { return $"({((IOffsetProvider)Data).Rva:X8}, {Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum FileAttributes : uint { ContainsMetadata, ContainsNoMetadata } public struct FileReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.File; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => HashValue, _ => throw new IndexOutOfRangeException(), }; public FileAttributes Attributes { get; set; } public uint Name { get; set; } public uint HashValue { get; set; } public static FileReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FileReferenceRow((FileAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public FileReferenceRow(FileAttributes attributes, uint name, uint hashValue) { Attributes = attributes; Name = name; HashValue = hashValue; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, HashValue, (IndexSize)layout.Columns[2].Size); } public bool Equals(FileReferenceRow other) { if (Attributes == other.Attributes && Name == other.Name) { return HashValue == other.HashValue; } return false; } public override bool Equals(object? obj) { if (obj is FileReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ HashValue); } public override string ToString() { return $"({Attributes:X8}, {Name:X8}, {HashValue:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum GenericParameterAttributes : ushort { NonVariant = 0, Covariant = 1, Contravariant = 2, VarianceMask = 3, SpecialConstraintMask = 0x1C, ReferenceTypeConstraint = 4, NotNullableValueTypeConstraint = 8, DefaultConstructorConstraint = 0x10 } public struct GenericParameterConstraintRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.GenericParamConstraint; public int Count => 2; public uint this[int index] => index switch { 0 => Owner, 1 => Constraint, _ => throw new IndexOutOfRangeException(), }; public uint Owner { get; set; } public uint Constraint { get; set; } public static GenericParameterConstraintRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new GenericParameterConstraintRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public GenericParameterConstraintRow(uint owner, uint constraint) { Owner = owner; Constraint = constraint; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Owner, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Constraint, (IndexSize)layout.Columns[1].Size); } public bool Equals(GenericParameterConstraintRow other) { if (Owner == other.Owner) { return Constraint == other.Constraint; } return false; } public override bool Equals(object? obj) { if (obj is GenericParameterConstraintRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Owner * 397) ^ Constraint); } public override string ToString() { return $"({Owner:X8}, {Constraint:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct GenericParameterRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.GenericParam; public int Count => 4; public uint this[int index] => index switch { 0 => Number, 1 => (uint)Attributes, 2 => Owner, 3 => Name, _ => throw new IndexOutOfRangeException(), }; public ushort Number { get; set; } public GenericParameterAttributes Attributes { get; set; } public uint Owner { get; set; } public uint Name { get; set; } public static GenericParameterRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new GenericParameterRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), (GenericParameterAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public GenericParameterRow(ushort number, GenericParameterAttributes attributes, uint owner, uint name) { Number = number; Attributes = attributes; Owner = owner; Name = name; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(Number); writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Owner, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[3].Size); } public bool Equals(GenericParameterRow other) { if (Number == other.Number && Attributes == other.Attributes && Owner == other.Owner) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is GenericParameterRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((uint)(Number.GetHashCode() * 397) ^ (uint)Attributes) * 397) ^ Owner) * 397) ^ Name); } public override string ToString() { return $"({Number:X4}, {Attributes:X4}, {Owner:X8}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public interface IMetadataRow : IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { TableIndex TableIndex { get; } void Write(IBinaryStreamWriter writer, TableLayout layout); } [Flags] public enum ImplementationMapAttributes : ushort { NoMangle = 1, CharSetNotSpec = 0, CharSetAnsi = 2, CharSetUnicode = 4, CharSetAuto = 6, CharSetMask = 6, BestFitUseAssem = 0, BestFitEnabled = 0x10, BestFitDisabled = 0x20, BestFitMask = 0x30, ThrowOnUnmappableCharUseAssem = 0, ThrowOnUnmappableCharEnabled = 0x1000, ThrowOnUnmappableCharDisabled = 0x2000, ThrowOnUnmappableCharMask = 0x3000, SupportsLastError = 0x40, CallConvWinapi = 0x100, CallConvCdecl = 0x200, CallConvStdcall = 0x300, CallConvThiscall = 0x400, CallConvFastcall = 0x500, CallConvMask = 0x700 } public struct ImplementationMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ImplMap; public int Count => 4; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => MemberForwarded, 2 => ImportName, 3 => ImportScope, _ => throw new IndexOutOfRangeException(), }; public ImplementationMapAttributes Attributes { get; } public uint MemberForwarded { get; set; } public uint ImportName { get; set; } public uint ImportScope { get; set; } public static ImplementationMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ImplementationMapRow((ImplementationMapAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ImplementationMapRow(ImplementationMapAttributes attributes, uint memberForwarded, uint importName, uint importScope) { Attributes = attributes; MemberForwarded = memberForwarded; ImportName = importName; ImportScope = importScope; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, MemberForwarded, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, ImportName, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, ImportScope, (IndexSize)layout.Columns[3].Size); } public bool Equals(ImplementationMapRow other) { if (Attributes == other.Attributes && MemberForwarded == other.MemberForwarded && ImportName == other.ImportName) { return ImportScope == other.ImportScope; } return false; } public override bool Equals(object? obj) { if (obj is ImplementationMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((uint)((int)Attributes * 397) ^ MemberForwarded) * 397) ^ ImportName) * 397) ^ ImportScope); } public override string ToString() { return $"({Attributes:X4}, {MemberForwarded:X8}, {ImportName:X8}, {ImportScope:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ImportScopeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ImportScope; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => Imports, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Imports { get; set; } public ImportScopeRow(uint parent, uint imports) { Parent = parent; Imports = imports; } public static ImportScopeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ImportScopeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Imports, (IndexSize)layout.Columns[1].Size); } public bool Equals(ImportScopeRow other) { if (Parent == other.Parent) { return Imports == other.Imports; } return false; } public override bool Equals(object? obj) { if (obj is ImportScopeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ Imports); } public override string ToString() { return $"({Parent:X8}, {Imports:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct InterfaceImplementationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.InterfaceImpl; public int Count => 2; public uint this[int index] => index switch { 0 => Class, 1 => Interface, _ => throw new IndexOutOfRangeException(), }; public uint Class { get; set; } public uint Interface { get; set; } public static InterfaceImplementationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new InterfaceImplementationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public InterfaceImplementationRow(uint @class, uint @interface) { Class = @class; Interface = @interface; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Class, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Interface, (IndexSize)layout.Columns[1].Size); } public bool Equals(InterfaceImplementationRow other) { if (Class == other.Class) { return Interface == other.Interface; } return false; } public override bool Equals(object? obj) { if (obj is InterfaceImplementationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Class * 397) ^ Interface); } public override string ToString() { return $"({Class:X8}, {Interface:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct LocalConstantRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.LocalConstant; public int Count => 2; public uint this[int index] => index switch { 0 => Name, 1 => Signature, _ => throw new IndexOutOfRangeException(), }; public uint Name { get; set; } public uint Signature { get; set; } public LocalConstantRow(uint name, uint signature) { Name = name; Signature = signature; } public static LocalConstantRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalConstantRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[1].Size); } public bool Equals(LocalConstantRow other) { if (Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is LocalConstantRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Name * 397) ^ Signature); } public override string ToString() { return $"({Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct LocalScopeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 6; public uint this[int index] => index switch { 0 => Method, 1 => ImportScope, 2 => VariableList, 3 => ConstantList, 4 => StartOffset, 5 => Length, _ => throw new IndexOutOfRangeException(), }; public uint Method { get; set; } public uint ImportScope { get; set; } public uint VariableList { get; set; } public uint ConstantList { get; set; } public uint StartOffset { get; set; } public uint Length { get; set; } public LocalScopeRow(uint method, uint importScope, uint variableList, uint constantList, uint startOffset, uint length) { Method = method; ImportScope = importScope; VariableList = variableList; ConstantList = constantList; StartOffset = startOffset; Length = length; } public static LocalScopeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalScopeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32()); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Method, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, ImportScope, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, VariableList, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, ConstantList, (IndexSize)layout.Columns[3].Size); writer.WriteUInt32(StartOffset); writer.WriteUInt32(Length); } public bool Equals(LocalScopeRow other) { if (Method == other.Method && ImportScope == other.ImportScope && VariableList == other.VariableList && ConstantList == other.ConstantList && StartOffset == other.StartOffset) { return Length == other.Length; } return false; } public override bool Equals(object? obj) { if (obj is LocalScopeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((Method * 397) ^ ImportScope) * 397) ^ VariableList) * 397) ^ ConstantList) * 397) ^ StartOffset) * 397) ^ Length); } public override string ToString() { return $"({Method:X8}, {ImportScope:X8}, {VariableList:X8}, {ConstantList:X8}, {StartOffset:X8}, {Length:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum LocalVariableAttributes : ushort { DebuggerHidden = 1 } public struct LocalVariableRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.LocalVariable; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Index, 2 => Name, _ => throw new IndexOutOfRangeException(), }; public LocalVariableAttributes Attributes { get; set; } public ushort Index { get; set; } public uint Name { get; set; } public LocalVariableRow(LocalVariableAttributes attributes, ushort index, uint name) { Attributes = attributes; Index = index; Name = name; } public static LocalVariableRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalVariableRow((LocalVariableAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteUInt16(Index); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[2].Size); } public bool Equals(LocalVariableRow other) { if (Attributes == other.Attributes && Index == other.Index) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is LocalScopeRow localScopeRow) { return Equals(localScopeRow); } return false; } public override int GetHashCode() { return ((((int)Attributes * 397) ^ Index) * 397) ^ (int)Name; } public override string ToString() { return $"({Attributes:X4}, {Index:X4}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum ManifestResourceAttributes : uint { Public = 1u, Private } public struct ManifestResourceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ManifestResource; public int Count => 4; public uint this[int index] => index switch { 0 => Offset, 1 => (uint)Attributes, 2 => Name, 3 => Implementation, _ => throw new IndexOutOfRangeException(), }; public uint Offset { get; set; } public ManifestResourceAttributes Attributes { get; set; } public uint Name { get; set; } public uint Implementation { get; set; } public static ManifestResourceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ManifestResourceRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), (ManifestResourceAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ManifestResourceRow(uint offset, ManifestResourceAttributes attributes, uint name, uint implementation) { Offset = offset; Attributes = attributes; Name = name; Implementation = implementation; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Offset); writer.WriteUInt32((uint)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Implementation, (IndexSize)layout.Columns[3].Size); } public bool Equals(ManifestResourceRow other) { if (Offset == other.Offset && Attributes == other.Attributes && Name == other.Name) { return Implementation == other.Implementation; } return false; } public override bool Equals(object? obj) { if (obj is ManifestResourceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((Offset * 397) ^ (uint)Attributes) * 397) ^ Name) * 397) ^ Implementation); } public override string ToString() { return $"({Offset:X8}, {Attributes:X8}, {Name:X8}, {Implementation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MemberReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MemberRef; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Name, 2 => Signature, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Name { get; set; } public uint Signature { get; set; } public static MemberReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MemberReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MemberReferenceRow(uint parent, uint name, uint signature) { Parent = parent; Name = name; Signature = signature; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[2].Size); } public bool Equals(MemberReferenceRow other) { if (Parent == other.Parent && Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is MemberReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Name) * 397) ^ Signature); } public override string ToString() { return $"({Parent:X8}, {Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MetadataRowColumnEnumerator : IEnumerator, IEnumerator, IDisposable { private readonly IMetadataRow _row; private int _index; public uint Current { get { if (_index < 0 || _index >= _row.Count) { return 0u; } return _row[_index]; } } object IEnumerator.Current => Current; public MetadataRowColumnEnumerator(IMetadataRow row) { _row = row; _index = -1; } public bool MoveNext() { if (_index < _row.Count - 1) { _index++; return true; } return false; } public void Reset() { _index = 0; } public void Dispose() { } } [Flags] public enum MethodAttributes : ushort { CompilerControlled = 0, Private = 1, FamilyAndAssembly = 2, Assembly = 3, Family = 4, FamilyOrAssembly = 5, Public = 6, MemberAccessMask = 7, UnmanagedExport = 8, Static = 0x10, Final = 0x20, Virtual = 0x40, HideBySig = 0x80, ReuseSlot = 0, NewSlot = 0x100, VtableLayoutMask = 0x100, CheckAccessOnOverride = 0x200, Abstract = 0x400, SpecialName = 0x800, RuntimeSpecialName = 0x1000, PInvokeImpl = 0x2000, HasSecurity = 0x4000, RequireSecObject = 0x8000 } public struct MethodDebugInformationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 2; public uint this[int index] => index switch { 0 => Document, 1 => SequencePoints, _ => throw new IndexOutOfRangeException(), }; public uint Document { get; set; } public uint SequencePoints { get; set; } public MethodDebugInformationRow(uint document, uint sequencePoints) { Document = document; SequencePoints = sequencePoints; } public static MethodDebugInformationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodDebugInformationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Document, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, SequencePoints, (IndexSize)layout.Columns[1].Size); } public bool Equals(MethodDebugInformationRow other) { if (Document == other.Document) { return SequencePoints == other.SequencePoints; } return false; } public override bool Equals(object? obj) { if (obj is MethodDebugInformationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Document * 397) ^ SequencePoints); } public override string ToString() { return $"({Document:X8}, {SequencePoints:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Method; public int Count => 6; public uint this[int index] { get { switch (index) { case 0: { ISegmentReference body = Body; return (body != null) ? ((IOffsetProvider)body).Rva : 0u; } case 1: return (uint)ImplAttributes; case 2: return (uint)Attributes; case 3: return Name; case 4: return Signature; case 5: return ParameterList; default: throw new IndexOutOfRangeException(); } } } public ISegmentReference Body { get; set; } public MethodImplAttributes ImplAttributes { get; set; } public MethodAttributes Attributes { get; set; } public uint Name { get; set; } public uint Signature { get; set; } public uint ParameterList { get; set; } public static MethodDefinitionRow FromReader(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout) { return new MethodDefinitionRow(context.ReferenceFactory.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()), (MethodImplAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), (MethodAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size)); } public MethodDefinitionRow(ISegmentReference body, MethodImplAttributes implAttributes, MethodAttributes attributes, uint name, uint signature, uint parameterList) { Body = body; ImplAttributes = implAttributes; Attributes = attributes; Name = name; Signature = signature; ParameterList = parameterList; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { ISegmentReference body = Body; writer.WriteUInt32((body != null) ? ((IOffsetProvider)body).Rva : 0u); writer.WriteUInt16((ushort)ImplAttributes); writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[3].Size); IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[4].Size); IOExtensions.WriteIndex(writer, ParameterList, (IndexSize)layout.Columns[5].Size); } public bool Equals(MethodDefinitionRow other) { ISegmentReference body = Body; uint? num = ((body != null) ? new uint?(((IOffsetProvider)body).Rva) : null); ISegmentReference body2 = other.Body; if (num == ((body2 != null) ? new uint?(((IOffsetProvider)body2).Rva) : null) && ImplAttributes == other.ImplAttributes && Attributes == other.Attributes && Name == other.Name && Signature == other.Signature) { return ParameterList == other.ParameterList; } return false; } public override bool Equals(object? obj) { if (obj is MethodDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { ISegmentReference body = Body; return (int)((((((((((((body != null) ? ((IOffsetProvider)body).Rva : 0) * 397) ^ (uint)ImplAttributes) * 397) ^ (uint)Attributes) * 397) ^ Name) * 397) ^ Signature) * 397) ^ ParameterList); } public override string ToString() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 6); defaultInterpolatedStringHandler.AppendLiteral("("); ISegmentReference body = Body; defaultInterpolatedStringHandler.AppendFormatted((body != null) ? ((IOffsetProvider)body).Rva : 0u, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted((int)ImplAttributes, "X4"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted((int)Attributes, "X4"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(Name, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(Signature, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(ParameterList, "X8"); defaultInterpolatedStringHandler.AppendLiteral(")"); return defaultInterpolatedStringHandler.ToStringAndClear(); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum MethodImplAttributes : ushort { IL = 0, Native = 1, OPTIL = 2, Runtime = 3, CodeTypeMask = 3, Unmanaged = 4, Managed = 0, ManagedMask = 4, ForwardRef = 0x10, NoOptimization = 0x40, PreserveSig = 0x80, InternalCall = 0x1000, Synchronized = 0x20, NoInlining = 8 } public struct MethodImplementationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodImpl; public int Count => 3; public uint this[int index] => index switch { 0 => Class, 1 => MethodBody, 2 => MethodDeclaration, _ => throw new IndexOutOfRangeException(), }; public uint Class { get; set; } public uint MethodBody { get; set; } public uint MethodDeclaration { get; set; } public static MethodImplementationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodImplementationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MethodImplementationRow(uint @class, uint methodBody, uint methodDeclaration) { Class = @class; MethodBody = methodBody; MethodDeclaration = methodDeclaration; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Class, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, MethodBody, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, MethodDeclaration, (IndexSize)layout.Columns[2].Size); } public bool Equals(MethodImplementationRow other) { if (Class == other.Class && MethodBody == other.MethodBody) { return MethodDeclaration == other.MethodDeclaration; } return false; } public override bool Equals(object? obj) { if (obj is MethodImplementationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Class * 397) ^ MethodBody) * 397) ^ MethodDeclaration); } public override string ToString() { return $"({Class:X8}, {MethodBody:X8}, {MethodDeclaration:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Method; } throw new IndexOutOfRangeException(); } } public uint Method { get; set; } public static MethodPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public MethodPointerRow(uint method) { Method = method; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Method, (IndexSize)layout.Columns[0].Size); } public bool Equals(MethodPointerRow other) { return Method == other.Method; } public override bool Equals(object? obj) { if (obj is MethodPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Method; } public override string ToString() { return $"({Method:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum MethodSemanticsAttributes : ushort { Setter = 1, Getter = 2, Other = 4, AddOn = 8, RemoveOn = 0x10, Fire = 0x20 } public struct MethodSemanticsRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodSemantics; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Method, 2 => Association, _ => throw new IndexOutOfRangeException(), }; public MethodSemanticsAttributes Attributes { get; set; } public uint Method { get; set; } public uint Association { get; set; } public static MethodSemanticsRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodSemanticsRow((MethodSemanticsAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MethodSemanticsRow(MethodSemanticsAttributes attributes, uint method, uint association) { Attributes = attributes; Method = method; Association = association; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Method, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Association, (IndexSize)layout.Columns[2].Size); } public bool Equals(MethodSemanticsRow other) { if (Attributes == other.Attributes && Method == other.Method) { return Association == other.Association; } return false; } public override bool Equals(object? obj) { if (obj is MethodSemanticsRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Method) * 397) ^ Association); } public override string ToString() { return $"({Attributes:X4}, {Method:X8}, {Association:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodSpecificationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodSpec; public int Count => 2; public uint this[int index] => index switch { 0 => Method, 1 => Instantiation, _ => throw new IndexOutOfRangeException(), }; public uint Method { get; set; } public uint Instantiation { get; set; } public static MethodSpecificationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodSpecificationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public MethodSpecificationRow(uint method, uint instantiation) { Method = method; Instantiation = instantiation; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Method, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Instantiation, (IndexSize)layout.Columns[1].Size); } public bool Equals(MethodSpecificationRow other) { if (Method == other.Method) { return Instantiation == other.Instantiation; } return false; } public override bool Equals(object? obj) { if (obj is MethodSpecificationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Method * 397) ^ Instantiation); } public override string ToString() { return $"({Method:X8}, {Instantiation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ModuleDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Module; public int Count => 5; public uint this[int index] => index switch { 0 => Generation, 1 => Name, 2 => Mvid, 3 => EncId, 4 => EncBaseId, _ => throw new IndexOutOfRangeException(), }; public ushort Generation { get; set; } public uint Name { get; set; } public uint Mvid { get; set; } public uint EncId { get; set; } public uint EncBaseId { get; set; } public static ModuleDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ModuleDefinitionRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size)); } public ModuleDefinitionRow(ushort generation, uint name, uint mvid, uint encId, uint encBaseId) { Generation = generation; Name = name; Mvid = mvid; EncId = encId; EncBaseId = encBaseId; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(Generation); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Mvid, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, EncId, (IndexSize)layout.Columns[3].Size); IOExtensions.WriteIndex(writer, EncBaseId, (IndexSize)layout.Columns[4].Size); } public override string ToString() { return $"({Generation:X4}, {Name:X8}, {Mvid:X8}, {EncId:X8}, {EncBaseId:X8})"; } public bool Equals(ModuleDefinitionRow other) { if (Generation == other.Generation && Name == other.Name && Mvid == other.Mvid && EncId == other.EncId) { return EncBaseId == other.EncBaseId; } return false; } public override bool Equals(object? obj) { if (obj is ModuleDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)(Generation.GetHashCode() * 397) ^ Name) * 397) ^ Mvid) * 397) ^ EncId) * 397) ^ EncBaseId); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ModuleReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ModuleRef; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Name; } throw new IndexOutOfRangeException(); } } public uint Name { get; set; } public static ModuleReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ModuleReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public ModuleReferenceRow(uint name) { Name = name; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[0].Size); } public bool Equals(ModuleReferenceRow other) { return Name == other.Name; } public override bool Equals(object? obj) { if (obj is ModuleReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Name; } public override string ToString() { return $"({Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct NestedClassRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.NestedClass; public int Count => 2; public uint this[int index] => index switch { 0 => NestedClass, 1 => EnclosingClass, _ => throw new IndexOutOfRangeException(), }; public uint NestedClass { get; set; } public uint EnclosingClass { get; set; } public static NestedClassRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new NestedClassRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public NestedClassRow(uint nestedClass, uint enclosingClass) { NestedClass = nestedClass; EnclosingClass = enclosingClass; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, NestedClass, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, EnclosingClass, (IndexSize)layout.Columns[1].Size); } public bool Equals(NestedClassRow other) { if (NestedClass == other.NestedClass) { return EnclosingClass == other.EnclosingClass; } return false; } public override bool Equals(object? obj) { if (obj is NestedClassRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((NestedClass * 397) ^ EnclosingClass); } public override string ToString() { return $"({NestedClass:X8}, {EnclosingClass:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum ParameterAttributes : ushort { In = 1, Out = 2, Optional = 0x10, HasDefault = 0x1000, HasFieldMarshal = 0x2000 } public struct ParameterDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Param; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Sequence, 2 => Name, _ => throw new IndexOutOfRangeException(), }; public ParameterAttributes Attributes { get; set; } public ushort Sequence { get; set; } public uint Name { get; set; } public static ParameterDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ParameterDefinitionRow((ParameterAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public ParameterDefinitionRow(ParameterAttributes attributes, ushort sequence, uint name) { Attributes = attributes; Sequence = sequence; Name = name; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteUInt16(Sequence); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[2].Size); } public bool Equals(ParameterDefinitionRow other) { if (Attributes == other.Attributes && Sequence == other.Sequence) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is ParameterDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return ((((int)Attributes * 397) ^ Sequence.GetHashCode()) * 397) ^ (int)Name; } public override string ToString() { return $"({Attributes:X4}, {Sequence:X4}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ParameterPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ParamPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Parameter; } throw new IndexOutOfRangeException(); } } public uint Parameter { get; set; } public static ParameterPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ParameterPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public ParameterPointerRow(uint parameter) { Parameter = parameter; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parameter, (IndexSize)layout.Columns[0].Size); } public bool Equals(ParameterPointerRow other) { return Parameter == other.Parameter; } public override bool Equals(object? obj) { if (obj is ParameterPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Parameter; } public override string ToString() { return $"({Parameter:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum PropertyAttributes : ushort { None = 0, SpecialName = 0x200, RuntimeSpecialName = 0x400, HasDefault = 0x1000 } public struct PropertyDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Property; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Type, _ => throw new IndexOutOfRangeException(), }; public PropertyAttributes Attributes { get; set; } public uint Name { get; set; } public uint Type { get; set; } public static PropertyDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyDefinitionRow((PropertyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public PropertyDefinitionRow(PropertyAttributes attributes, uint name, uint type) { Attributes = attributes; Name = name; Type = type; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Type, (IndexSize)layout.Columns[2].Size); } public bool Equals(PropertyDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return Type == other.Type; } return false; } public override bool Equals(object? obj) { if (obj is PropertyDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Type); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {Type:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct PropertyMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.PropertyMap; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => PropertyList, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint PropertyList { get; set; } public static PropertyMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyMapRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public PropertyMapRow(uint parent, uint propertyList) { Parent = parent; PropertyList = propertyList; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, PropertyList, (IndexSize)layout.Columns[1].Size); } public bool Equals(PropertyMapRow other) { if (Parent == other.Parent) { return PropertyList == other.PropertyList; } return false; } public override bool Equals(object? obj) { if (obj is PropertyMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ PropertyList); } public override string ToString() { return $"({Parent:X8}, {PropertyList:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct PropertyPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.PropertyPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Property; } throw new IndexOutOfRangeException(); } } public uint Property { get; set; } public static PropertyPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public PropertyPointerRow(uint property) { Property = property; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Property, (IndexSize)layout.Columns[0].Size); } public bool Equals(PropertyPointerRow other) { return Property == other.Property; } public override bool Equals(object? obj) { if (obj is PropertyPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Property; } public override string ToString() { return $"({Property:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum SecurityAction : ushort { Demand = 2, Assert, Deny, PermitOnly, LinkDemand, InheritanceDemand, RequestMinimum, RequestOptional, RequestRefuse } public struct SecurityDeclarationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.DeclSecurity; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Action, 1 => Parent, 2 => PermissionSet, _ => throw new IndexOutOfRangeException(), }; public SecurityAction Action { get; set; } public uint Parent { get; set; } public uint PermissionSet { get; set; } public static SecurityDeclarationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new SecurityDeclarationRow((SecurityAction)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public SecurityDeclarationRow(SecurityAction action, uint parent, uint permissionSet) { Action = action; Parent = parent; PermissionSet = permissionSet; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Action); IOExtensions.WriteIndex(writer, Parent, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, PermissionSet, (IndexSize)layout.Columns[2].Size); } public bool Equals(SecurityDeclarationRow other) { if (Action == other.Action && Parent == other.Parent) { return PermissionSet == other.PermissionSet; } return false; } public override bool Equals(object? obj) { if (obj is SecurityDeclarationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Action * 397) ^ Parent) * 397) ^ PermissionSet); } public override string ToString() { return $"({Action:X4}, {Parent:X8}, {PermissionSet:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct StandAloneSignatureRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.StandAloneSig; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Signature; } throw new IndexOutOfRangeException(); } } public uint Signature { get; set; } public static StandAloneSignatureRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new StandAloneSignatureRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public StandAloneSignatureRow(uint signature) { Signature = signature; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[0].Size); } public bool Equals(StandAloneSignatureRow other) { return Signature == other.Signature; } public override bool Equals(object? obj) { if (obj is StandAloneSignatureRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Signature; } public override string ToString() { return $"({Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct StateMachineMethodRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.StateMachineMethod; public int Count => 2; public uint this[int index] => index switch { 0 => MoveNextMethod, 1 => KickoffMethod, _ => throw new IndexOutOfRangeException(), }; public uint MoveNextMethod { get; set; } public uint KickoffMethod { get; set; } public StateMachineMethodRow(uint moveNextMethod, uint kickoffMethod) { MoveNextMethod = moveNextMethod; KickoffMethod = kickoffMethod; } public static StateMachineMethodRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new StateMachineMethodRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, MoveNextMethod, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, KickoffMethod, (IndexSize)layout.Columns[1].Size); } public bool Equals(StateMachineMethodRow other) { if (MoveNextMethod == other.MoveNextMethod) { return KickoffMethod == other.KickoffMethod; } return false; } public override bool Equals(object? obj) { if (obj is StateMachineMethodRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((MoveNextMethod * 397) ^ KickoffMethod); } public override string ToString() { return $"({MoveNextMethod:X8}, {KickoffMethod:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum TypeAttributes : uint { NotPublic = 0u, Public = 1u, NestedPublic = 2u, NestedPrivate = 3u, NestedFamily = 4u, NestedAssembly = 5u, NestedFamilyAndAssembly = 6u, NestedFamilyOrAssembly = 7u, VisibilityMask = 7u, AutoLayout = 0u, SequentialLayout = 8u, ExplicitLayout = 0x10u, LayoutMask = 0x18u, Class = 0u, Interface = 0x20u, ClassSemanticsMask = 0x60u, Abstract = 0x80u, Sealed = 0x100u, SpecialName = 0x400u, RuntimeSpecialName = 0x800u, Import = 0x1000u, Serializable = 0x2000u, AnsiClass = 0u, UnicodeClass = 0x10000u, AutoClass = 0x20000u, CustomFormatClass = 0x30000u, StringFormatMask = 0x30000u, BeforeFieldInit = 0x100000u, Forwarder = 0x200000u, HasSecurity = 0x40000u } public struct TypeDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.TypeDef; public int Count => 6; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Namespace, 3 => Extends, 4 => FieldList, 5 => MethodList, _ => throw new IndexOutOfRangeException(), }; public TypeAttributes Attributes { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public uint Extends { get; set; } public uint FieldList { get; set; } public uint MethodList { get; set; } public static TypeDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeDefinitionRow((TypeAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size)); } public TypeDefinitionRow(TypeAttributes attributes, uint name, uint ns, uint extends, uint fieldList, uint methodList) { Attributes = attributes; Name = name; Namespace = ns; Extends = extends; FieldList = fieldList; MethodList = methodList; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Namespace, (IndexSize)layout.Columns[2].Size); IOExtensions.WriteIndex(writer, Extends, (IndexSize)layout.Columns[3].Size); IOExtensions.WriteIndex(writer, FieldList, (IndexSize)layout.Columns[4].Size); IOExtensions.WriteIndex(writer, MethodList, (IndexSize)layout.Columns[5].Size); } public override string ToString() { return $"({Attributes:X8}, {Name:X8}, {Namespace:X8}, {Extends:X8}, {FieldList:X8}, {MethodList:X8})"; } public bool Equals(TypeDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name && Namespace == other.Namespace && Extends == other.Extends && FieldList == other.FieldList) { return MethodList == other.MethodList; } return false; } public override bool Equals(object? obj) { if (obj is TypeDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Namespace) * 397) ^ Extends) * 397) ^ FieldList) * 397) ^ MethodList); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct TypeReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.TypeRef; public int Count => 3; public uint this[int index] => index switch { 0 => ResolutionScope, 1 => Name, 2 => Namespace, _ => throw new IndexOutOfRangeException(), }; public uint ResolutionScope { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public static TypeReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public TypeReferenceRow(uint resolutionScope, uint name, uint ns) { ResolutionScope = resolutionScope; Name = name; Namespace = ns; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, ResolutionScope, (IndexSize)layout.Columns[0].Size); IOExtensions.WriteIndex(writer, Name, (IndexSize)layout.Columns[1].Size); IOExtensions.WriteIndex(writer, Namespace, (IndexSize)layout.Columns[2].Size); } public override string ToString() { return $"({ResolutionScope:X8}, {Name:X8}, {Namespace:X8})"; } public bool Equals(TypeReferenceRow other) { if (ResolutionScope == other.ResolutionScope && Name == other.Name) { return Namespace == other.Namespace; } return false; } public override bool Equals(object? obj) { if (obj is TypeReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((ResolutionScope * 397) ^ Name) * 397) ^ Namespace); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct TypeSpecificationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ModuleRef; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Signature; } throw new IndexOutOfRangeException(); } } public uint Signature { get; set; } public static TypeSpecificationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeSpecificationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public TypeSpecificationRow(uint signature) { Signature = signature; } public void Write(IBinaryStreamWriter writer, TableLayout layout) { IOExtensions.WriteIndex(writer, Signature, (IndexSize)layout.Columns[0].Size); } public bool Equals(TypeSpecificationRow other) { return Signature == other.Signature; } public override bool Equals(object? obj) { if (obj is TypeSpecificationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Signature; } public override string ToString() { return $"({Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } namespace AsmResolver.PE.DotNet.Metadata.Strings { public class SerializedStringsStream : StringsStream { private readonly Dictionary _cachedStrings; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedStringsStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Strings", in reader); } public SerializedStringsStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedStringsStream(string name, in BinaryStreamReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) _cachedStrings = new Dictionary(); base..ctor(name); _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override Utf8String? GetStringByIndex(uint index) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (index == 0) { return null; } if (!_cachedStrings.TryGetValue(index, out Utf8String value) && index < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); value = ((BinaryStreamReader)(ref val)).ReadUtf8String(); _cachedStrings[index] = value; } return value; } public override bool TryFindStringIndex(Utf8String? value, out uint index) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (value == null) { index = 0u; return true; } byte[] bytesUnsafe = value.GetBytesUnsafe(); BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref val)).CanRead((uint)value.ByteCount)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; int i; for (i = 0; i < bytesUnsafe.Length && bytesUnsafe[i] == ((BinaryStreamReader)(ref val)).ReadByte(); i++) { } if (i == value.Length && ((BinaryStreamReader)(ref val)).CanRead(1u) && ((BinaryStreamReader)(ref val)).ReadByte() == 0) { return true; } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } public abstract class StringsStream : MetadataHeap { public const string DefaultName = "#Strings"; protected StringsStream() : base("#Strings") { } protected StringsStream(string name) : base(name) { } public abstract Utf8String? GetStringByIndex(uint index); public abstract bool TryFindStringIndex(Utf8String? value, out uint index); } } namespace AsmResolver.PE.DotNet.Metadata.Pdb { public class PdbStream : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public const string DefaultName = "#Pdb"; public string Name { get; set; } = "#Pdb"; public virtual bool CanRead => false; public byte[] Id { get; } = new byte[20]; public MetadataToken EntryPoint { get; set; } public uint[] TypeSystemRowCounts { get; } = new uint[56]; public void UpdateRowCounts(TablesStream stream) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 44) { if (tableIndex.IsValidTableIndex()) { TypeSystemRowCounts[(uint)tableIndex] = (uint)stream.GetTable(tableIndex).Count; } tableIndex++; } } public void UpdateRowCounts(uint[] rowCounts) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 44 && (int)tableIndex < rowCounts.Length) { if (tableIndex.IsValidTableIndex()) { TypeSystemRowCounts[(uint)tableIndex] = rowCounts[(uint)tableIndex]; } tableIndex++; } } public ulong ComputeReferencedTypeSystemTables() { ulong num = 0uL; for (int i = 0; i < TypeSystemRowCounts.Length; i++) { if (TypeSystemRowCounts[i] != 0) { num |= (ulong)(1L << i); } } return num; } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } public override uint GetPhysicalSize() { return (uint)(32 + 4 * TypeSystemRowCounts.Count((uint c) => c != 0)); } public override void Write(IBinaryStreamWriter writer) { IOExtensions.WriteBytes(writer, Id); writer.WriteUInt32(EntryPoint.ToUInt32()); writer.WriteUInt64(ComputeReferencedTypeSystemTables()); uint[] typeSystemRowCounts = TypeSystemRowCounts; foreach (uint num in typeSystemRowCounts) { if (num != 0) { writer.WriteUInt32(num); } } } } public class SerializedPdbStream : PdbStream { private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedPdbStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Pdb", in reader); } public SerializedPdbStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedPdbStream(string name, in BinaryStreamReader reader) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) _reader = reader; base.Name = name; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; BinaryStreamReader val2 = ((BinaryStreamReader)(ref reader)).Fork(); ((BinaryStreamReader)(ref val2)).ReadBytes(base.Id, 0, base.Id.Length); base.EntryPoint = ((BinaryStreamReader)(ref val2)).ReadUInt32(); ulong num = ((BinaryStreamReader)(ref val2)).ReadUInt64(); for (int i = 0; i < 64; i++) { if (((num >> i) & 1) != 0L) { base.TypeSystemRowCounts[i] = ((BinaryStreamReader)(ref val2)).ReadUInt32(); } } } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } } } namespace AsmResolver.PE.DotNet.Metadata.Guid { public abstract class GuidStream : MetadataHeap { public const int GuidSize = 16; public const string DefaultName = "#GUID"; protected GuidStream() : base("#GUID") { } protected GuidStream(string name) : base(name) { } public abstract System.Guid GetGuidByIndex(uint index); public abstract bool TryFindGuidIndex(System.Guid guid, out uint index); } public class SerializedGuidStream : GuidStream { [ThreadStatic] private static byte[]? _readBuffer; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedGuidStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#GUID", in reader); } public SerializedGuidStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedGuidStream(string name, in BinaryStreamReader reader) : base(name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override System.Guid GetGuidByIndex(uint index) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (index == 0) { return System.Guid.Empty; } if (_readBuffer == null) { _readBuffer = new byte[16]; } uint num = (index - 1) * 16; if (num < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(num); ((BinaryStreamReader)(ref val)).ReadBytes(_readBuffer, 0, _readBuffer.Length); return new System.Guid(_readBuffer); } return System.Guid.Empty; } public override bool TryFindGuidIndex(System.Guid guid, out uint index) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (_readBuffer == null) { _readBuffer = new byte[16]; } index = 1u; BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref val)).CanRead(16u)) { if (((BinaryStreamReader)(ref val)).ReadBytes(_readBuffer, 0, _readBuffer.Length) == 16 && new System.Guid(_readBuffer) == guid) { return true; } index++; } index = 0u; return false; } } } namespace AsmResolver.PE.DotNet.Metadata.Blob { public abstract class BlobStream : MetadataHeap { public const string DefaultName = "#Blob"; protected BlobStream() : base("#Blob") { } protected BlobStream(string name) : base(name) { } public abstract byte[]? GetBlobByIndex(uint index); public abstract bool TryGetBlobReaderByIndex(uint index, out BinaryStreamReader reader); public abstract bool TryFindBlobIndex(byte[]? blob, out uint index); } public class SerializedBlobStream : BlobStream { private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedBlobStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Blob", in reader); } public SerializedBlobStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedBlobStream(string name, in BinaryStreamReader reader) : base(name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override byte[]? GetBlobByIndex(uint index) { if (!TryGetBlobReaderByIndex(index, out var reader)) { return null; } return ((BinaryStreamReader)(ref reader)).ReadToEnd(); } public override bool TryGetBlobReaderByIndex(uint index, out BinaryStreamReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (index == 0 || index >= ((BinaryStreamReader)(ref _reader)).Length) { reader = default(BinaryStreamReader); return false; } reader = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); uint num = default(uint); if (((BinaryStreamReader)(ref reader)).TryReadCompressedUInt32(ref num)) { uint num2 = (uint)(((BinaryStreamReader)(ref reader)).Offset - ((BinaryStreamReader)(ref reader)).StartOffset); ((BinaryStreamReader)(ref reader)).ChangeSize(Math.Min(num + num2, ((BinaryStreamReader)(ref reader)).Length)); return true; } return false; } public override bool TryFindBlobIndex(byte[]? blob, out uint index) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (blob == null) { index = 0u; return true; } uint num = (uint)blob.Length + Extensions.GetCompressedSize((uint)blob.Length); BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); uint num2 = default(uint); while (((BinaryStreamReader)(ref val)).CanRead(num)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num2) && num2 == blob.Length && ((BinaryStreamReader)(ref val)).CanRead(num2)) { int i; for (i = 0; i < blob.Length && blob[i] == ((BinaryStreamReader)(ref val)).ReadByte(); i++) { } if (i == blob.Length) { return true; } } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } } namespace AsmResolver.PE.DotNet.Cil { public class CilAssembler { private readonly IBinaryStreamWriter _writer; private readonly ICilOperandBuilder _operandBuilder; private readonly Func? _getMethodBodyName; private readonly IErrorListener _errorListener; private string? _diagnosticPrefix; private string? DiagnosticPrefix { get { if (_diagnosticPrefix == null && _getMethodBodyName != null) { string text = _getMethodBodyName(); if (!string.IsNullOrEmpty(text)) { _diagnosticPrefix = "[In " + text + "]: "; } } return _diagnosticPrefix; } } public CilAssembler(IBinaryStreamWriter writer, ICilOperandBuilder operandBuilder) : this(writer, operandBuilder, (string?)null, (IErrorListener)(object)ThrowErrorListener.Instance) { } public CilAssembler(IBinaryStreamWriter writer, ICilOperandBuilder operandBuilder, string? methodBodyName, IErrorListener errorListener) { _writer = writer ?? throw new ArgumentNullException("writer"); _errorListener = errorListener ?? throw new ArgumentNullException("errorListener"); _operandBuilder = operandBuilder ?? throw new ArgumentNullException("operandBuilder"); _diagnosticPrefix = ((!string.IsNullOrEmpty(methodBodyName)) ? ("[In " + methodBodyName + "]: ") : null); } public CilAssembler(IBinaryStreamWriter writer, ICilOperandBuilder operandBuilder, Func? getMethodBodyName, IErrorListener errorListener) { _writer = writer ?? throw new ArgumentNullException("writer"); _errorListener = errorListener ?? throw new ArgumentNullException("errorListener"); _operandBuilder = operandBuilder ?? throw new ArgumentNullException("operandBuilder"); _getMethodBodyName = getMethodBodyName; } public void WriteInstructions(IList instructions) { for (int i = 0; i < instructions.Count; i++) { WriteInstruction(instructions[i]); } } public void WriteInstruction(CilInstruction instruction) { WriteOpCode(instruction.OpCode); WriteOperand(instruction); } private void WriteOpCode(CilOpCode opCode) { _writer.WriteByte(opCode.Byte1); if (opCode.IsLarge) { _writer.WriteByte(opCode.Byte2); } } private void WriteOperand(CilInstruction instruction) { switch (instruction.OpCode.OperandType) { case CilOperandType.ShortInlineI: _writer.WriteSByte(OperandToSByte(instruction)); break; case CilOperandType.InlineI: _writer.WriteInt32(OperandToInt32(instruction)); break; case CilOperandType.InlineI8: _writer.WriteInt64(OperandToInt64(instruction)); break; case CilOperandType.ShortInlineR: _writer.WriteSingle(OperandToFloat32(instruction)); break; case CilOperandType.InlineR: _writer.WriteDouble(OperandToFloat64(instruction)); break; case CilOperandType.ShortInlineVar: _writer.WriteByte((byte)OperandToLocalIndex(instruction)); break; case CilOperandType.InlineVar: _writer.WriteUInt16(OperandToLocalIndex(instruction)); break; case CilOperandType.ShortInlineArgument: _writer.WriteByte((byte)OperandToArgumentIndex(instruction)); break; case CilOperandType.InlineArgument: _writer.WriteUInt16(OperandToArgumentIndex(instruction)); break; case CilOperandType.ShortInlineBrTarget: _writer.WriteSByte((sbyte)OperandToBranchDelta(instruction)); break; case CilOperandType.InlineBrTarget: _writer.WriteInt32(OperandToBranchDelta(instruction)); break; case CilOperandType.InlineSwitch: { IList list = (instruction.Operand as IList) ?? Array.Empty(); _writer.WriteInt32(list.Count); int num = (int)_writer.Offset + list.Count * 4; for (int i = 0; i < list.Count; i++) { _writer.WriteInt32(list[i].Offset - num); } break; } case CilOperandType.InlineString: _writer.WriteUInt32(_operandBuilder.GetStringToken(instruction.Operand)); break; case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: _writer.WriteUInt32(_operandBuilder.GetMemberToken(instruction.Operand).ToUInt32()); break; default: throw new ArgumentOutOfRangeException(); case CilOperandType.InlineNone: break; } } private int OperandToBranchDelta(CilInstruction instruction) { bool flag = instruction.OpCode.OperandType == CilOperandType.ShortInlineBrTarget; object operand = instruction.Operand; int num3; if (!(operand is sbyte b)) { if (!(operand is int num)) { if (!(operand is ICilLabel cilLabel)) { return ThrowInvalidOperandType(instruction, new Type[2] { typeof(ICilLabel), typeof(sbyte) }); } int num2 = (flag ? 1 : 4); num3 = cilLabel.Offset - (int)((long)_writer.Offset + (long)num2); } else { num3 = num; } } else { num3 = b; } if (flag && (num3 < -128 || num3 > 127)) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Branch target at IL_{instruction.Offset:X4} is too far away for a ShortInlineBr instruction.")); } return num3; } private ushort OperandToLocalIndex(CilInstruction instruction) { int variableIndex = _operandBuilder.GetVariableIndex(instruction.Operand); if (instruction.OpCode.OperandType == CilOperandType.ShortInlineVar && variableIndex > 255) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Local index at IL_{instruction.Offset:X4} is too large for a ShortInlineVar instruction.")); } return (ushort)variableIndex; } private ushort OperandToArgumentIndex(CilInstruction instruction) { int argumentIndex = _operandBuilder.GetArgumentIndex(instruction.Operand); if (instruction.OpCode.OperandType == CilOperandType.ShortInlineArgument && argumentIndex > 255) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Argument index at IL_{instruction.Offset:X4} is too large for a ShortInlineArgument instruction.")); } return (ushort)argumentIndex; } private sbyte OperandToSByte(CilInstruction instruction) { object operand = instruction.Operand; if (operand is sbyte) { return (sbyte)operand; } return ThrowInvalidOperandType(instruction, typeof(sbyte)); } private int OperandToInt32(CilInstruction instruction) { object operand = instruction.Operand; if (operand is int) { return (int)operand; } return ThrowInvalidOperandType(instruction, typeof(int)); } private long OperandToInt64(CilInstruction instruction) { object operand = instruction.Operand; if (operand is long) { return (long)operand; } return ThrowInvalidOperandType(instruction, typeof(long)); } private float OperandToFloat32(CilInstruction instruction) { object operand = instruction.Operand; if (operand is float) { return (float)operand; } return ThrowInvalidOperandType(instruction, typeof(float)); } private double OperandToFloat64(CilInstruction instruction) { object operand = instruction.Operand; if (operand is double) { return (double)operand; } return ThrowInvalidOperandType(instruction, typeof(double)); } private T? ThrowInvalidOperandType(CilInstruction instruction, Type expectedOperand) { string value = instruction.Operand?.GetType().Name ?? "null"; _errorListener.RegisterException((Exception)new ArgumentOutOfRangeException($"{DiagnosticPrefix}Expected a {expectedOperand.Name} operand at IL_{instruction.Offset:X4}, but found {value}.")); return default(T); } private T? ThrowInvalidOperandType(CilInstruction instruction, params Type[] expectedOperands) { string[] array = expectedOperands.Select((Type o) => o.Name).ToArray(); string value = ((expectedOperands.Length > 1) ? (string.Join(", ", array.Take(array.Length - 1)) + " or " + array[^1]) : array[0]); string value2 = instruction.Operand?.GetType().Name ?? "null"; _errorListener.RegisterException((Exception)new ArgumentOutOfRangeException($"{DiagnosticPrefix}Expected a {value} operand at IL_{instruction.Offset:X4}, but found {value2}.")); return default(T); } } public enum CilCode : ushort { Nop = 0, Break = 1, Ldarg_0 = 2, Ldarg_1 = 3, Ldarg_2 = 4, Ldarg_3 = 5, Ldloc_0 = 6, Ldloc_1 = 7, Ldloc_2 = 8, Ldloc_3 = 9, Stloc_0 = 10, Stloc_1 = 11, Stloc_2 = 12, Stloc_3 = 13, Ldarg_S = 14, Ldarga_S = 15, Starg_S = 16, Ldloc_S = 17, Ldloca_S = 18, Stloc_S = 19, Ldnull = 20, Ldc_I4_M1 = 21, Ldc_I4_0 = 22, Ldc_I4_1 = 23, Ldc_I4_2 = 24, Ldc_I4_3 = 25, Ldc_I4_4 = 26, Ldc_I4_5 = 27, Ldc_I4_6 = 28, Ldc_I4_7 = 29, Ldc_I4_8 = 30, Ldc_I4_S = 31, Ldc_I4 = 32, Ldc_I8 = 33, Ldc_R4 = 34, Ldc_R8 = 35, Dup = 37, Pop = 38, Jmp = 39, Call = 40, Calli = 41, Ret = 42, Br_S = 43, Brfalse_S = 44, Brtrue_S = 45, Beq_S = 46, Bge_S = 47, Bgt_S = 48, Ble_S = 49, Blt_S = 50, Bne_Un_S = 51, Bge_Un_S = 52, Bgt_Un_S = 53, Ble_Un_S = 54, Blt_Un_S = 55, Br = 56, Brfalse = 57, Brtrue = 58, Beq = 59, Bge = 60, Bgt = 61, Ble = 62, Blt = 63, Bne_Un = 64, Bge_Un = 65, Bgt_Un = 66, Ble_Un = 67, Blt_Un = 68, Switch = 69, Ldind_I1 = 70, Ldind_U1 = 71, Ldind_I2 = 72, Ldind_U2 = 73, Ldind_I4 = 74, Ldind_U4 = 75, Ldind_I8 = 76, Ldind_I = 77, Ldind_R4 = 78, Ldind_R8 = 79, Ldind_Ref = 80, Stind_Ref = 81, Stind_I1 = 82, Stind_I2 = 83, Stind_I4 = 84, Stind_I8 = 85, Stind_R4 = 86, Stind_R8 = 87, Add = 88, Sub = 89, Mul = 90, Div = 91, Div_Un = 92, Rem = 93, Rem_Un = 94, And = 95, Or = 96, Xor = 97, Shl = 98, Shr = 99, Shr_Un = 100, Neg = 101, Not = 102, Conv_I1 = 103, Conv_I2 = 104, Conv_I4 = 105, Conv_I8 = 106, Conv_R4 = 107, Conv_R8 = 108, Conv_U4 = 109, Conv_U8 = 110, Callvirt = 111, Cpobj = 112, Ldobj = 113, Ldstr = 114, Newobj = 115, Castclass = 116, Isinst = 117, Conv_R_Un = 118, Unbox = 121, Throw = 122, Ldfld = 123, Ldflda = 124, Stfld = 125, Ldsfld = 126, Ldsflda = 127, Stsfld = 128, Stobj = 129, Conv_Ovf_I1_Un = 130, Conv_Ovf_I2_Un = 131, Conv_Ovf_I4_Un = 132, Conv_Ovf_I8_Un = 133, Conv_Ovf_U1_Un = 134, Conv_Ovf_U2_Un = 135, Conv_Ovf_U4_Un = 136, Conv_Ovf_U8_Un = 137, Conv_Ovf_I_Un = 138, Conv_Ovf_U_Un = 139, Box = 140, Newarr = 141, Ldlen = 142, Ldelema = 143, Ldelem_I1 = 144, Ldelem_U1 = 145, Ldelem_I2 = 146, Ldelem_U2 = 147, Ldelem_I4 = 148, Ldelem_U4 = 149, Ldelem_I8 = 150, Ldelem_I = 151, Ldelem_R4 = 152, Ldelem_R8 = 153, Ldelem_Ref = 154, Stelem_I = 155, Stelem_I1 = 156, Stelem_I2 = 157, Stelem_I4 = 158, Stelem_I8 = 159, Stelem_R4 = 160, Stelem_R8 = 161, Stelem_Ref = 162, Ldelem = 163, Stelem = 164, Unbox_Any = 165, Conv_Ovf_I1 = 179, Conv_Ovf_U1 = 180, Conv_Ovf_I2 = 181, Conv_Ovf_U2 = 182, Conv_Ovf_I4 = 183, Conv_Ovf_U4 = 184, Conv_Ovf_I8 = 185, Conv_Ovf_U8 = 186, Refanyval = 194, Ckfinite = 195, Mkrefany = 198, Ldtoken = 208, Conv_U2 = 209, Conv_U1 = 210, Conv_I = 211, Conv_Ovf_I = 212, Conv_Ovf_U = 213, Add_Ovf = 214, Add_Ovf_Un = 215, Mul_Ovf = 216, Mul_Ovf_Un = 217, Sub_Ovf = 218, Sub_Ovf_Un = 219, Endfinally = 220, Leave = 221, Leave_S = 222, Stind_I = 223, Conv_U = 224, Prefix7 = 248, Prefix6 = 249, Prefix5 = 250, Prefix4 = 251, Prefix3 = 252, Prefix2 = 253, Prefix1 = 254, Prefixref = 255, Arglist = 65024, Ceq = 65025, Cgt = 65026, Cgt_Un = 65027, Clt = 65028, Clt_Un = 65029, Ldftn = 65030, Ldvirtftn = 65031, Ldarg = 65033, Ldarga = 65034, Starg = 65035, Ldloc = 65036, Ldloca = 65037, Stloc = 65038, Localloc = 65039, Endfilter = 65041, Unaligned = 65042, Volatile = 65043, Tailcall = 65044, Initobj = 65045, Constrained = 65046, Cpblk = 65047, Initblk = 65048, Rethrow = 65050, Sizeof = 65052, Refanytype = 65053, Readonly = 65054 } public static class CilCodeExtensions { public static CilOpCode ToOpCode(this CilCode code) { if ((int)code < 256) { return CilOpCodes.SingleByteOpCodes[(uint)code]; } return CilOpCodes.MultiByteOpCodes[(uint)(code - 65024)]; } } public class CilDisassembler { private readonly ICilOperandResolver _operandResolver; private BinaryStreamReader _reader; public bool ResolveBranchTargets { get; set; } = true; public CilDisassembler(in BinaryStreamReader reader) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _operandResolver = EmptyOperandResolver.Instance; } public CilDisassembler(in BinaryStreamReader reader, ICilOperandResolver operandResolver) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _operandResolver = operandResolver ?? throw new ArgumentNullException("operandResolver"); } public IList ReadInstructions() { List list = null; List list2 = null; List list3 = new List(); while (((BinaryStreamReader)(ref _reader)).Offset < ((BinaryStreamReader)(ref _reader)).StartOffset + ((BinaryStreamReader)(ref _reader)).Length) { CilInstruction cilInstruction = ReadInstruction(); list3.Add(cilInstruction); if (!ResolveBranchTargets) { continue; } switch (cilInstruction.OpCode.OperandType) { case CilOperandType.InlineBrTarget: case CilOperandType.ShortInlineBrTarget: if (list == null) { list = new List(); } list.Add(cilInstruction); break; case CilOperandType.InlineSwitch: if (list2 == null) { list2 = new List(); } list2.Add(cilInstruction); break; } } if (ResolveBranchTargets) { if (list != null) { foreach (CilInstruction item in list) { item.Operand = TryResolveLabel(list3, (ICilLabel)item.Operand); } } if (list2 != null) { foreach (CilInstruction item2 in list2) { IList list4 = (IList)item2.Operand; for (int i = 0; i < list4.Count; i++) { list4[i] = TryResolveLabel(list3, list4[i]); } } } } return list3; } private static ICilLabel TryResolveLabel(IList instructions, ICilLabel label) { int indexByOffset = instructions.GetIndexByOffset(label.Offset); if (indexByOffset != -1) { label = instructions[indexByOffset].CreateLabel(); } return label; } private CilInstruction ReadInstruction() { uint relativeOffset = ((BinaryStreamReader)(ref _reader)).RelativeOffset; CilOpCode opCode = ReadOpCode(); return new CilInstruction(operand: ReadOperand(opCode.OperandType), offset: (int)relativeOffset, opCode: opCode); } private CilOpCode ReadOpCode() { byte b = ((BinaryStreamReader)(ref _reader)).ReadByte(); if (b != 254) { return CilOpCodes.SingleByteOpCodes[b]; } return CilOpCodes.MultiByteOpCodes[((BinaryStreamReader)(ref _reader)).ReadByte()]; } private object? ReadOperand(CilOperandType operandType) { switch (operandType) { case CilOperandType.InlineNone: return null; case CilOperandType.ShortInlineI: return ((BinaryStreamReader)(ref _reader)).ReadSByte(); case CilOperandType.ShortInlineBrTarget: return new CilOffsetLabel((int)((BinaryStreamReader)(ref _reader)).ReadSByte() + (int)((BinaryStreamReader)(ref _reader)).RelativeOffset); case CilOperandType.ShortInlineVar: { byte b2 = ((BinaryStreamReader)(ref _reader)).ReadByte(); return _operandResolver.ResolveLocalVariable(b2) ?? ((object)b2); } case CilOperandType.ShortInlineArgument: { byte b = ((BinaryStreamReader)(ref _reader)).ReadByte(); return _operandResolver.ResolveParameter(b) ?? ((object)b); } case CilOperandType.InlineVar: { ushort num = ((BinaryStreamReader)(ref _reader)).ReadUInt16(); return _operandResolver.ResolveLocalVariable(num) ?? ((object)num); } case CilOperandType.InlineArgument: { ushort num2 = ((BinaryStreamReader)(ref _reader)).ReadUInt16(); return _operandResolver.ResolveParameter(num2) ?? ((object)num2); } case CilOperandType.InlineI: return ((BinaryStreamReader)(ref _reader)).ReadInt32(); case CilOperandType.InlineBrTarget: return new CilOffsetLabel(((BinaryStreamReader)(ref _reader)).ReadInt32() + (int)((BinaryStreamReader)(ref _reader)).RelativeOffset); case CilOperandType.ShortInlineR: return ((BinaryStreamReader)(ref _reader)).ReadSingle(); case CilOperandType.InlineI8: return ((BinaryStreamReader)(ref _reader)).ReadInt64(); case CilOperandType.InlineR: return ((BinaryStreamReader)(ref _reader)).ReadDouble(); case CilOperandType.InlineString: { MetadataToken metadataToken2 = new MetadataToken(((BinaryStreamReader)(ref _reader)).ReadUInt32()); return _operandResolver.ResolveString(metadataToken2) ?? ((object)metadataToken2); } case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: { MetadataToken metadataToken = new MetadataToken(((BinaryStreamReader)(ref _reader)).ReadUInt32()); return _operandResolver.ResolveMember(metadataToken) ?? ((object)metadataToken); } case CilOperandType.InlinePhi: throw new NotSupportedException(); case CilOperandType.InlineSwitch: return ReadSwitchTable(); default: throw new ArgumentOutOfRangeException("operandType", operandType, null); } } private IList ReadSwitchTable() { int num = ((BinaryStreamReader)(ref _reader)).ReadInt32(); int num2 = (int)((BinaryStreamReader)(ref _reader)).RelativeOffset + num * 4; List list = new List(num); for (int i = 0; i < num; i++) { list.Add(new CilOffsetLabel(num2 + ((BinaryStreamReader)(ref _reader)).ReadInt32())); } return list; } } public class CilExtraSection : SegmentBase { public CilExtraSectionAttributes Attributes { get; set; } public bool IsEHTable { get { return (Attributes & CilExtraSectionAttributes.EHTable) == CilExtraSectionAttributes.EHTable; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.EHTable) | (value ? CilExtraSectionAttributes.EHTable : ((CilExtraSectionAttributes)0)); } } public bool IsOptILTable { get { return (Attributes & CilExtraSectionAttributes.OptILTable) == CilExtraSectionAttributes.OptILTable; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.OptILTable) | (value ? CilExtraSectionAttributes.OptILTable : ((CilExtraSectionAttributes)0)); } } public bool IsFat { get { return (Attributes & CilExtraSectionAttributes.FatFormat) == CilExtraSectionAttributes.FatFormat; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.FatFormat) | (value ? CilExtraSectionAttributes.FatFormat : ((CilExtraSectionAttributes)0)); } } public bool HasMoreSections { get { return (Attributes & CilExtraSectionAttributes.MoreSections) == CilExtraSectionAttributes.MoreSections; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.MoreSections) | (value ? CilExtraSectionAttributes.MoreSections : ((CilExtraSectionAttributes)0)); } } public byte[] Data { get; set; } private CilExtraSection() { Data = Array.Empty(); } public CilExtraSection(CilExtraSectionAttributes attributes, byte[] data) { Attributes = attributes; Data = data ?? throw new ArgumentNullException("data"); } public static CilExtraSection FromReader(ref BinaryStreamReader reader) { CilExtraSection cilExtraSection = new CilExtraSection(); ((SegmentBase)cilExtraSection).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)cilExtraSection).Rva = ((BinaryStreamReader)(ref reader)).Rva; cilExtraSection.Attributes = (CilExtraSectionAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); CilExtraSection cilExtraSection2 = cilExtraSection; int num; if (cilExtraSection2.IsFat) { num = ((BinaryStreamReader)(ref reader)).ReadByte() | (((BinaryStreamReader)(ref reader)).ReadByte() << 8) | (((BinaryStreamReader)(ref reader)).ReadByte() << 16); } else { num = ((BinaryStreamReader)(ref reader)).ReadByte(); ((BinaryStreamReader)(ref reader)).ReadUInt16(); } cilExtraSection2.Data = new byte[num]; ((BinaryStreamReader)(ref reader)).ReadBytes(cilExtraSection2.Data, 0, num); return cilExtraSection2; } public override uint GetPhysicalSize() { return (uint)(Data.Length + 4); } public override void Write(IBinaryStreamWriter writer) { writer.WriteByte((byte)Attributes); if (IsFat) { writer.WriteByte((byte)((uint)Data.Length & 0xFFu)); writer.WriteByte((byte)((Data.Length & 0xFF00) >> 8)); writer.WriteByte((byte)((Data.Length & 0xFF0000) >> 16)); } else { writer.WriteByte((byte)Data.Length); writer.WriteUInt16((ushort)0); } IOExtensions.WriteBytes(writer, Data); } } [Flags] public enum CilExtraSectionAttributes : byte { EHTable = 1, OptILTable = 2, FatFormat = 0x40, MoreSections = 0x80 } public enum CilFlowControl { Branch, Break, Call, ConditionalBranch, Meta, Next, Phi, Return, Throw } public class CilInstruction { public int Offset { get; set; } public CilOpCode OpCode { get; set; } public object? Operand { get; set; } public int Size => OpCode.Size + GetOperandSize(); public CilInstruction(CilOpCode opCode) : this(0, opCode, null) { } public CilInstruction(int offset, CilOpCode opCode) : this(offset, opCode, null) { } public CilInstruction(CilOpCode opCode, object? operand) : this(0, opCode, operand) { } public CilInstruction(int offset, CilOpCode opCode, object? operand) { Offset = offset; OpCode = opCode; Operand = operand; } public static CilInstruction CreateLdcI4(int value) { var (opCode, operand) = GetLdcI4OpCodeOperand(value); return new CilInstruction(opCode, operand); } public static (CilOpCode code, object? operand) GetLdcI4OpCodeOperand(int value) { object item = null; CilOpCode item2; if (value <= 127 && value >= -128) { switch (value) { case -1: item2 = CilOpCodes.Ldc_I4_M1; break; case 0: item2 = CilOpCodes.Ldc_I4_0; break; case 1: item2 = CilOpCodes.Ldc_I4_1; break; case 2: item2 = CilOpCodes.Ldc_I4_2; break; case 3: item2 = CilOpCodes.Ldc_I4_3; break; case 4: item2 = CilOpCodes.Ldc_I4_4; break; case 5: item2 = CilOpCodes.Ldc_I4_5; break; case 6: item2 = CilOpCodes.Ldc_I4_6; break; case 7: item2 = CilOpCodes.Ldc_I4_7; break; case 8: item2 = CilOpCodes.Ldc_I4_8; break; default: item2 = CilOpCodes.Ldc_I4_S; item = (sbyte)value; break; } } else { item2 = CilOpCodes.Ldc_I4; item = value; } return (item2, item); } private int GetOperandSize() { switch (OpCode.OperandType) { case CilOperandType.InlineNone: return 0; case CilOperandType.ShortInlineI: return 1; case CilOperandType.ShortInlineArgument: return 1; case CilOperandType.ShortInlineBrTarget: return 1; case CilOperandType.ShortInlineVar: return 1; case CilOperandType.InlineVar: return 2; case CilOperandType.InlineArgument: return 2; case CilOperandType.InlineBrTarget: return 4; case CilOperandType.InlineI: return 4; case CilOperandType.InlineField: return 4; case CilOperandType.InlineMethod: return 4; case CilOperandType.InlineSig: return 4; case CilOperandType.InlineString: return 4; case CilOperandType.InlineTok: return 4; case CilOperandType.InlineType: return 4; case CilOperandType.InlineI8: return 8; case CilOperandType.ShortInlineR: return 4; case CilOperandType.InlineR: return 8; case CilOperandType.InlineSwitch: if (Operand is IList list) { return (list.Count + 1) * 4; } return 4; case CilOperandType.InlinePhi: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(); } } public override string ToString() { return CilInstructionFormatter.Instance.FormatInstruction(this); } protected bool Equals(CilInstruction other) { if (Offset != other.Offset || !OpCode.Equals(other.OpCode)) { return false; } if (OpCode.Code == CilCode.Switch && Operand is IEnumerable first && other.Operand is IEnumerable second) { return first.SequenceEqual(second); } return object.Equals(Operand, other.Operand); } public override bool Equals(object? obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((CilInstruction)obj); } public override int GetHashCode() { return (((Offset * 397) ^ OpCode.GetHashCode()) * 397) ^ ((Operand != null) ? Operand.GetHashCode() : 0); } public ICilLabel CreateLabel() { return new CilInstructionLabel(this); } public bool IsLdloc() { CilCode code = OpCode.Code; if (code - 6 <= CilCode.Ldarg_1 || code == CilCode.Ldloc_S || code == CilCode.Ldloc) { return true; } return false; } public bool IsStloc() { CilCode code = OpCode.Code; if (code - 10 <= CilCode.Ldarg_1 || code == CilCode.Stloc_S || code == CilCode.Stloc) { return true; } return false; } public bool IsLdarg() { CilCode code = OpCode.Code; if (code - 2 <= CilCode.Ldarg_1 || code == CilCode.Ldarg_S || code == CilCode.Ldarg) { return true; } return false; } public bool IsStarg() { CilCode code = OpCode.Code; if (code == CilCode.Starg_S || code == CilCode.Starg) { return true; } return false; } public bool IsBranch() { CilFlowControl flowControl = OpCode.FlowControl; return flowControl == CilFlowControl.Branch || flowControl == CilFlowControl.ConditionalBranch; } public bool IsUnconditionalBranch() { return OpCode.FlowControl == CilFlowControl.Branch; } public bool IsConditionalBranch() { return OpCode.FlowControl == CilFlowControl.ConditionalBranch; } public bool IsLdcI4() { CilCode code = OpCode.Code; if (code - 21 <= CilCode.Stloc_1) { return true; } return false; } public int GetLdcI4Constant() { return OpCode.Code switch { CilCode.Ldc_I4 => (int)(Operand ?? ((object)0)), CilCode.Ldc_I4_S => (sbyte)(Operand ?? ((object)(sbyte)0)), CilCode.Ldc_I4_0 => 0, CilCode.Ldc_I4_1 => 1, CilCode.Ldc_I4_2 => 2, CilCode.Ldc_I4_3 => 3, CilCode.Ldc_I4_4 => 4, CilCode.Ldc_I4_5 => 5, CilCode.Ldc_I4_6 => 6, CilCode.Ldc_I4_7 => 7, CilCode.Ldc_I4_8 => 8, CilCode.Ldc_I4_M1 => -1, _ => throw new ArgumentOutOfRangeException(), }; } public void ReplaceWith(CilOpCode opCode) { ReplaceWith(opCode, null); } public void ReplaceWith(CilOpCode opCode, object? operand) { OpCode = opCode; Operand = operand; } public void ReplaceWithNop() { ReplaceWith(CilOpCodes.Nop); } } public static class CilInstructionCollectionExtensions { public static int GetIndexByOffset(this IList self, int offset) { int num = 0; int num2 = self.Count - 1; while (num <= num2) { int num3 = (num + num2) / 2; int offset2 = self[num3].Offset; if (offset2 > offset) { num2 = num3 - 1; continue; } if (offset2 < offset) { num = num3 + 1; continue; } return num3; } return -1; } public static CilInstruction? GetByOffset(this IList self, int offset) { int indexByOffset = self.GetIndexByOffset(offset); if (indexByOffset == -1) { return null; } return self[indexByOffset]; } } public class CilInstructionFormatter : ICilInstructionFormatter { private const string InvalidOperandString = "<<>>"; public static CilInstructionFormatter Instance { get; } = new CilInstructionFormatter(); public string FormatInstruction(CilInstruction instruction) { string text = FormatLabel(instruction.Offset) + ": " + FormatOpCode(instruction.OpCode); if (instruction.Operand != null) { return text + " " + FormatOperand(instruction.OpCode.OperandType, instruction.Operand); } return text; } public virtual string FormatLabel(int offset) { return $"IL_{offset:X4}"; } public virtual string FormatOpCode(CilOpCode opcode) { return opcode.Mnemonic.ToLowerInvariant(); } public virtual string FormatOperand(CilOperandType operandType, object? operand) { return operandType switch { CilOperandType.InlineNone => string.Empty, CilOperandType.ShortInlineBrTarget => FormatBranchTarget(operand), CilOperandType.InlineBrTarget => FormatBranchTarget(operand), CilOperandType.InlineType => FormatMember(operand), CilOperandType.InlineField => FormatMember(operand), CilOperandType.InlineMethod => FormatMember(operand), CilOperandType.InlineTok => FormatMember(operand), CilOperandType.InlineSig => FormatSignature(operand), CilOperandType.ShortInlineI => FormatInteger(operand), CilOperandType.InlineI => FormatInteger(operand), CilOperandType.InlineI8 => FormatInteger(operand), CilOperandType.InlineR => FormatFloat(operand), CilOperandType.ShortInlineR => FormatFloat(operand), CilOperandType.InlineString => FormatString(operand), CilOperandType.InlineSwitch => FormatSwitch(operand), CilOperandType.InlineVar => FormatVariable(operand), CilOperandType.ShortInlineVar => FormatVariable(operand), CilOperandType.InlineArgument => FormatArgument(operand), CilOperandType.ShortInlineArgument => FormatArgument(operand), _ => throw new ArgumentOutOfRangeException("operandType", operandType, null), }; } protected virtual string FormatArgument(object? operand) { if (!(operand is short num)) { if (!(operand is byte b)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "A_" + b; } return "A_" + num; } protected virtual string FormatVariable(object? operand) { if (!(operand is short num)) { if (!(operand is byte b)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "V_" + b; } return "V_" + num; } protected virtual string FormatInteger(object? operand) { return Convert.ToString(operand, CultureInfo.InvariantCulture) ?? "<<>>"; } protected virtual string FormatFloat(object? operand) { return Convert.ToString(operand, CultureInfo.InvariantCulture) ?? "<<>>"; } protected virtual string FormatSignature(object? operand) { if (!(operand is MetadataToken token)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatToken(token); } protected virtual string FormatToken(MetadataToken token) { return "TOKEN<0x" + token.ToString() + ">"; } protected virtual string FormatSwitch(object? operand) { if (!(operand is IEnumerable source)) { if (!(operand is IEnumerable source2)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "(" + string.Join(", ", source2.Select((int x) => FormatBranchTarget(x))) + ")"; } return "(" + string.Join(", ", source.Select(FormatBranchTarget)) + ")"; } protected virtual string FormatString(object? operand) { if (!(operand is string text)) { if (operand is MetadataToken token) { return FormatToken(token); } return "<<>>"; } return Extensions.CreateEscapedString(text); } protected virtual string FormatBranchTarget(object? operand) { if (!(operand is ICilLabel cilLabel)) { if (!(operand is int offset)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatLabel(offset); } return FormatLabel(cilLabel.Offset); } protected virtual string FormatMember(object? operand) { if (!(operand is MetadataToken token)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatToken(token); } } public class CilInstructionLabel : ICilLabel, IEquatable { public CilInstruction? Instruction { get; set; } public int Offset => Instruction?.Offset ?? (-1); public CilInstructionLabel() { } public CilInstructionLabel(CilInstruction instruction) { Instruction = instruction ?? throw new ArgumentNullException("instruction"); } public bool Equals(ICilLabel? other) { if (other != null) { return Offset == other.Offset; } return false; } public override bool Equals(object? obj) { return Equals(obj as ICilLabel); } public override int GetHashCode() { return Offset; } public override string ToString() { if (Instruction != null) { return $"IL_{Offset:X4}"; } return "IL_????"; } } [Flags] public enum CilMethodBodyAttributes : ushort { Tiny = 2, Fat = 3, MoreSections = 8, InitLocals = 0x10 } public class CilOffsetLabel : ICilLabel, IEquatable { public int Offset { get; } public CilOffsetLabel(int offset) { Offset = offset; } public override string ToString() { return $"IL_{Offset:X4}"; } public bool Equals(ICilLabel? other) { if (other != null) { return Offset == other.Offset; } return false; } public override bool Equals(object? obj) { return Equals(obj as ICilLabel); } public override int GetHashCode() { return Offset; } } public readonly struct CilOpCode { internal const int ValueBitLength = 8; internal const int ValueOffset = 0; internal const int TwoBytesBitLength = 1; internal const int TwoBytesOffset = 8; internal const int StackBehaviourBitLength = 5; internal const int StackBehaviourPushOffset = 9; internal const int StackBehaviourPopOffset = 14; internal const int OpCodeTypeBitLength = 3; internal const int OpCodeTypeOffset = 19; internal const int OperandTypeBitLength = 5; internal const int OperandTypeOffset = 22; internal const int FlowControlBitLength = 4; internal const int FlowControlOffset = 27; private readonly uint _value; public string Mnemonic => CilOpCodeNames.Names[IsLarge ? (Byte2 + 256) : Byte1]; public CilCode Code => (CilCode)((ushort)(_value & 0xFFu) | (IsLarge ? 65024u : 0u)); public bool IsLarge => ((_value >> 8) & 1) == 1; public int Size { get { if (!IsLarge) { return 1; } return 2; } } public byte Byte1 => (byte)(IsLarge ? 254u : (_value & 0xFFu)); public byte Byte2 => (byte)(IsLarge ? (_value & 0xFFu) : 0u); public CilStackBehaviour StackBehaviourPush => (CilStackBehaviour)((_value >> 9) & 0x1Fu); public CilStackBehaviour StackBehaviourPop => (CilStackBehaviour)((_value >> 14) & 0x1Fu); public CilOpCodeType OpCodeType => (CilOpCodeType)((_value >> 19) & 7u); public CilOperandType OperandType => (CilOperandType)((int)(_value >> 22) & 0x1F); public CilFlowControl FlowControl => (CilFlowControl)((int)(_value >> 27) & 0xF); public static bool operator ==(CilOpCode a, CilOpCode b) { return a.Equals(b); } public static bool operator !=(CilOpCode a, CilOpCode b) { return !(a == b); } internal CilOpCode(uint value) { _value = value; if (IsLarge) { CilOpCodes.MultiByteOpCodes[Byte2] = this; } else { CilOpCodes.SingleByteOpCodes[Byte1] = this; } } public override string ToString() { return Mnemonic; } public bool Equals(CilOpCode other) { return Code == other.Code; } public override bool Equals(object? obj) { if (obj is CilOpCode other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Code; } } internal static class CilOpCodeNames { internal static readonly string[] Names = new string[291] { "nop", "break", "ldarg.0", "ldarg.1", "ldarg.2", "ldarg.3", "ldloc.0", "ldloc.1", "ldloc.2", "ldloc.3", "stloc.0", "stloc.1", "stloc.2", "stloc.3", "ldarg.s", "ldarga.s", "starg.s", "ldloc.s", "ldloca.s", "stloc.s", "ldnull", "ldc.i4.m1", "ldc.i4.0", "ldc.i4.1", "ldc.i4.2", "ldc.i4.3", "ldc.i4.4", "ldc.i4.5", "ldc.i4.6", "ldc.i4.7", "ldc.i4.8", "ldc.i4.s", "ldc.i4", "ldc.i8", "ldc.r4", "ldc.r8", "unused", "dup", "pop", "jmp", "call", "calli", "ret", "br.s", "brfalse.s", "brtrue.s", "beq.s", "bge.s", "bgt.s", "ble.s", "blt.s", "bne.un.s", "bge.un.s", "bgt.un.s", "ble.un.s", "blt.un.s", "br", "brfalse", "brtrue", "beq", "bge", "bgt", "ble", "blt", "bne.un", "bge.un", "bgt.un", "ble.un", "blt.un", "switch", "ldind.i1", "ldind.u1", "ldind.i2", "ldind.u2", "ldind.i4", "ldind.u4", "ldind.i8", "ldind.i", "ldind.r4", "ldind.r8", "ldind.ref", "stind.ref", "stind.i1", "stind.i2", "stind.i4", "stind.i8", "stind.r4", "stind.r8", "add", "sub", "mul", "div", "div.un", "rem", "rem.un", "and", "or", "xor", "shl", "shr", "shr.un", "neg", "not", "conv.i1", "conv.i2", "conv.i4", "conv.i8", "conv.r4", "conv.r8", "conv.u4", "conv.u8", "callvirt", "cpobj", "ldobj", "ldstr", "newobj", "castclass", "isinst", "conv.r.un", "unused", "unused", "unbox", "throw", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda", "stsfld", "stobj", "conv.ovf.i1.un", "conv.ovf.i2.un", "conv.ovf.i4.un", "conv.ovf.i8.un", "conv.ovf.u1.un", "conv.ovf.u2.un", "conv.ovf.u4.un", "conv.ovf.u8.un", "conv.ovf.i.un", "conv.ovf.u.un", "box", "newarr", "ldlen", "ldelema", "ldelem.i1", "ldelem.u1", "ldelem.i2", "ldelem.u2", "ldelem.i4", "ldelem.u4", "ldelem.i8", "ldelem.i", "ldelem.r4", "ldelem.r8", "ldelem.ref", "stelem.i", "stelem.i1", "stelem.i2", "stelem.i4", "stelem.i8", "stelem.r4", "stelem.r8", "stelem.ref", "ldelem", "stelem", "unbox.any", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "conv.ovf.i1", "conv.ovf.u1", "conv.ovf.i2", "conv.ovf.u2", "conv.ovf.i4", "conv.ovf.u4", "conv.ovf.i8", "conv.ovf.u8", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "refanyval", "ckfinite", "unused", "unused", "mkrefany", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "ldtoken", "conv.u2", "conv.u1", "conv.i", "conv.ovf.i", "conv.ovf.u", "add.ovf", "add.ovf.un", "mul.ovf", "mul.ovf.un", "sub.ovf", "sub.ovf.un", "endfinally", "leave", "leave.s", "stind.i", "conv.u", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "prefix7", "prefix6", "prefix5", "prefix4", "prefix3", "prefix2", "prefix1", "prefixref", "arglist", "ceq", "cgt", "cgt.un", "clt", "clt.un", "ldftn", "ldvirtftn", "unused", "ldarg", "ldarga", "starg", "ldloc", "ldloca", "stloc", "localloc", "unused", "endfilter", "unaligned.", "volatile.", "tail.", "initobj", "constrained.", "cpblk", "initblk", "unused", "rethrow", "unused", "sizeof", "refanytype", "readonly.", "unused", "unused", "unused", "unused" }; } public static class CilOpCodes { public static readonly CilOpCode[] SingleByteOpCodes = new CilOpCode[256]; public static readonly CilOpCode[] MultiByteOpCodes = new CilOpCode[256]; public static readonly CilOpCode Nop = new CilOpCode(694691840u); public static readonly CilOpCode Break = new CilOpCode(157820929u); public static readonly CilOpCode Ldarg_0 = new CilOpCode(692595202u); public static readonly CilOpCode Ldarg_1 = new CilOpCode(692595203u); public static readonly CilOpCode Ldarg_2 = new CilOpCode(692595204u); public static readonly CilOpCode Ldarg_3 = new CilOpCode(692595205u); public static readonly CilOpCode Ldloc_0 = new CilOpCode(692595206u); public static readonly CilOpCode Ldloc_1 = new CilOpCode(692595207u); public static readonly CilOpCode Ldloc_2 = new CilOpCode(692595208u); public static readonly CilOpCode Ldloc_3 = new CilOpCode(692595209u); public static readonly CilOpCode Stloc_0 = new CilOpCode(692611082u); public static readonly CilOpCode Stloc_1 = new CilOpCode(692611083u); public static readonly CilOpCode Stloc_2 = new CilOpCode(692611084u); public static readonly CilOpCode Stloc_3 = new CilOpCode(692611085u); public static readonly CilOpCode Ldarg_S = new CilOpCode(755509774u); public static readonly CilOpCode Ldarga_S = new CilOpCode(755510799u); public static readonly CilOpCode Starg_S = new CilOpCode(755525648u); public static readonly CilOpCode Ldloc_S = new CilOpCode(747121169u); public static readonly CilOpCode Ldloca_S = new CilOpCode(747122194u); public static readonly CilOpCode Stloc_S = new CilOpCode(747137043u); public static readonly CilOpCode Ldnull = new CilOpCode(694695444u); public static readonly CilOpCode Ldc_I4_M1 = new CilOpCode(692596245u); public static readonly CilOpCode Ldc_I4_0 = new CilOpCode(692596246u); public static readonly CilOpCode Ldc_I4_1 = new CilOpCode(692596247u); public static readonly CilOpCode Ldc_I4_2 = new CilOpCode(692596248u); public static readonly CilOpCode Ldc_I4_3 = new CilOpCode(692596249u); public static readonly CilOpCode Ldc_I4_4 = new CilOpCode(692596250u); public static readonly CilOpCode Ldc_I4_5 = new CilOpCode(692596251u); public static readonly CilOpCode Ldc_I4_6 = new CilOpCode(692596252u); public static readonly CilOpCode Ldc_I4_7 = new CilOpCode(692596253u); public static readonly CilOpCode Ldc_I4_8 = new CilOpCode(692596254u); public static readonly CilOpCode Ldc_I4_S = new CilOpCode(738733599u); public static readonly CilOpCode Ldc_I4 = new CilOpCode(682110496u); public static readonly CilOpCode Ldc_I8 = new CilOpCode(686305313u); public static readonly CilOpCode Ldc_R4 = new CilOpCode(745026082u); public static readonly CilOpCode Ldc_R8 = new CilOpCode(703083555u); public static readonly CilOpCode Dup = new CilOpCode(694709285u); public static readonly CilOpCode Pop = new CilOpCode(694708262u); public static readonly CilOpCode Jmp = new CilOpCode(287844391u); public static readonly CilOpCode Call = new CilOpCode(288307752u); public static readonly CilOpCode Calli = new CilOpCode(309279273u); public static readonly CilOpCode Ret = new CilOpCode(963586090u); public static readonly CilOpCode Br_S = new CilOpCode(63449131u); public static readonly CilOpCode Brfalse_S = new CilOpCode(466151468u); public static readonly CilOpCode Brtrue_S = new CilOpCode(466151469u); public static readonly CilOpCode Beq_S = new CilOpCode(466135086u); public static readonly CilOpCode Bge_S = new CilOpCode(466135087u); public static readonly CilOpCode Bgt_S = new CilOpCode(466135088u); public static readonly CilOpCode Ble_S = new CilOpCode(466135089u); public static readonly CilOpCode Blt_S = new CilOpCode(466135090u); public static readonly CilOpCode Bne_Un_S = new CilOpCode(466135091u); public static readonly CilOpCode Bge_Un_S = new CilOpCode(466135092u); public static readonly CilOpCode Bgt_Un_S = new CilOpCode(466135093u); public static readonly CilOpCode Ble_Un_S = new CilOpCode(466135094u); public static readonly CilOpCode Blt_Un_S = new CilOpCode(466135095u); public static readonly CilOpCode Br = new CilOpCode(2631736u); public static readonly CilOpCode Brfalse = new CilOpCode(405334073u); public static readonly CilOpCode Brtrue = new CilOpCode(405334074u); public static readonly CilOpCode Beq = new CilOpCode(403220539u); public static readonly CilOpCode Bge = new CilOpCode(403220540u); public static readonly CilOpCode Bgt = new CilOpCode(403220541u); public static readonly CilOpCode Ble = new CilOpCode(403220542u); public static readonly CilOpCode Blt = new CilOpCode(403220543u); public static readonly CilOpCode Bne_Un = new CilOpCode(403220544u); public static readonly CilOpCode Bge_Un = new CilOpCode(403220545u); public static readonly CilOpCode Bgt_Un = new CilOpCode(403220546u); public static readonly CilOpCode Ble_Un = new CilOpCode(403220547u); public static readonly CilOpCode Blt_Un = new CilOpCode(403220548u); public static readonly CilOpCode Switch = new CilOpCode(451471429u); public static readonly CilOpCode Ldind_I1 = new CilOpCode(694742598u); public static readonly CilOpCode Ldind_U1 = new CilOpCode(694742599u); public static readonly CilOpCode Ldind_I2 = new CilOpCode(694742600u); public static readonly CilOpCode Ldind_U2 = new CilOpCode(694742601u); public static readonly CilOpCode Ldind_I4 = new CilOpCode(694742602u); public static readonly CilOpCode Ldind_U4 = new CilOpCode(694742603u); public static readonly CilOpCode Ldind_I8 = new CilOpCode(694743116u); public static readonly CilOpCode Ldind_I = new CilOpCode(694742605u); public static readonly CilOpCode Ldind_R4 = new CilOpCode(694743630u); public static readonly CilOpCode Ldind_R8 = new CilOpCode(694744143u); public static readonly CilOpCode Ldind_Ref = new CilOpCode(694744656u); public static readonly CilOpCode Stind_Ref = new CilOpCode(694773841u); public static readonly CilOpCode Stind_I1 = new CilOpCode(694773842u); public static readonly CilOpCode Stind_I2 = new CilOpCode(694773843u); public static readonly CilOpCode Stind_I4 = new CilOpCode(694773844u); public static readonly CilOpCode Stind_I8 = new CilOpCode(694790229u); public static readonly CilOpCode Stind_R4 = new CilOpCode(694822998u); public static readonly CilOpCode Stind_R8 = new CilOpCode(694839383u); public static readonly CilOpCode Add = new CilOpCode(694725208u); public static readonly CilOpCode Sub = new CilOpCode(694725209u); public static readonly CilOpCode Mul = new CilOpCode(694725210u); public static readonly CilOpCode Div = new CilOpCode(694725211u); public static readonly CilOpCode Div_Un = new CilOpCode(694725212u); public static readonly CilOpCode Rem = new CilOpCode(694725213u); public static readonly CilOpCode Rem_Un = new CilOpCode(694725214u); public static readonly CilOpCode And = new CilOpCode(694725215u); public static readonly CilOpCode Or = new CilOpCode(694725216u); public static readonly CilOpCode Xor = new CilOpCode(694725217u); public static readonly CilOpCode Shl = new CilOpCode(694725218u); public static readonly CilOpCode Shr = new CilOpCode(694725219u); public static readonly CilOpCode Shr_Un = new CilOpCode(694725220u); public static readonly CilOpCode Neg = new CilOpCode(694708837u); public static readonly CilOpCode Not = new CilOpCode(694708838u); public static readonly CilOpCode Conv_I1 = new CilOpCode(694709863u); public static readonly CilOpCode Conv_I2 = new CilOpCode(694709864u); public static readonly CilOpCode Conv_I4 = new CilOpCode(694709865u); public static readonly CilOpCode Conv_I8 = new CilOpCode(694710378u); public static readonly CilOpCode Conv_R4 = new CilOpCode(694710891u); public static readonly CilOpCode Conv_R8 = new CilOpCode(694711404u); public static readonly CilOpCode Conv_U4 = new CilOpCode(694709869u); public static readonly CilOpCode Conv_U8 = new CilOpCode(694710382u); public static readonly CilOpCode Callvirt = new CilOpCode(287259247u); public static readonly CilOpCode Cpobj = new CilOpCode(727279728u); public static readonly CilOpCode Ldobj = new CilOpCode(727247473u); public static readonly CilOpCode Ldstr = new CilOpCode(714618482u); public static readonly CilOpCode Newobj = new CilOpCode(287258227u); public static readonly CilOpCode Castclass = new CilOpCode(727365236u); public static readonly CilOpCode Isinst = new CilOpCode(727363189u); public static readonly CilOpCode Conv_R_Un = new CilOpCode(694711414u); public static readonly CilOpCode Unbox = new CilOpCode(728411769u); public static readonly CilOpCode Throw = new CilOpCode(1096460410u); public static readonly CilOpCode Ldfld = new CilOpCode(677030523u); public static readonly CilOpCode Ldflda = new CilOpCode(677031548u); public static readonly CilOpCode Stfld = new CilOpCode(677046397u); public static readonly CilOpCode Ldsfld = new CilOpCode(676866686u); public static readonly CilOpCode Ldsflda = new CilOpCode(676867711u); public static readonly CilOpCode Stsfld = new CilOpCode(676882560u); public static readonly CilOpCode Stobj = new CilOpCode(728311937u); public static readonly CilOpCode Conv_Ovf_I1_Un = new CilOpCode(694709890u); public static readonly CilOpCode Conv_Ovf_I2_Un = new CilOpCode(694709891u); public static readonly CilOpCode Conv_Ovf_I4_Un = new CilOpCode(694709892u); public static readonly CilOpCode Conv_Ovf_I8_Un = new CilOpCode(694710405u); public static readonly CilOpCode Conv_Ovf_U1_Un = new CilOpCode(694709894u); public static readonly CilOpCode Conv_Ovf_U2_Un = new CilOpCode(694709895u); public static readonly CilOpCode Conv_Ovf_U4_Un = new CilOpCode(694709896u); public static readonly CilOpCode Conv_Ovf_U8_Un = new CilOpCode(694710409u); public static readonly CilOpCode Conv_Ovf_I_Un = new CilOpCode(694709898u); public static readonly CilOpCode Conv_Ovf_U_Un = new CilOpCode(694709899u); public static readonly CilOpCode Box = new CilOpCode(728266380u); public static readonly CilOpCode Newarr = new CilOpCode(727250573u); public static readonly CilOpCode Ldlen = new CilOpCode(693808782u); public static readonly CilOpCode Ldelema = new CilOpCode(727395983u); public static readonly CilOpCode Ldelem_I1 = new CilOpCode(693841552u); public static readonly CilOpCode Ldelem_U1 = new CilOpCode(693841553u); public static readonly CilOpCode Ldelem_I2 = new CilOpCode(693841554u); public static readonly CilOpCode Ldelem_U2 = new CilOpCode(693841555u); public static readonly CilOpCode Ldelem_I4 = new CilOpCode(693841556u); public static readonly CilOpCode Ldelem_U4 = new CilOpCode(693841557u); public static readonly CilOpCode Ldelem_I8 = new CilOpCode(693842070u); public static readonly CilOpCode Ldelem_I = new CilOpCode(693841559u); public static readonly CilOpCode Ldelem_R4 = new CilOpCode(693842584u); public static readonly CilOpCode Ldelem_R8 = new CilOpCode(693843097u); public static readonly CilOpCode Ldelem_Ref = new CilOpCode(693843610u); public static readonly CilOpCode Stelem_I = new CilOpCode(693856411u); public static readonly CilOpCode Stelem_I1 = new CilOpCode(693856412u); public static readonly CilOpCode Stelem_I2 = new CilOpCode(693856413u); public static readonly CilOpCode Stelem_I4 = new CilOpCode(693856414u); public static readonly CilOpCode Stelem_I8 = new CilOpCode(693872799u); public static readonly CilOpCode Stelem_R4 = new CilOpCode(693889184u); public static readonly CilOpCode Stelem_R8 = new CilOpCode(693905569u); public static readonly CilOpCode Stelem_Ref = new CilOpCode(693921954u); public static readonly CilOpCode Ldelem = new CilOpCode(727394979u); public static readonly CilOpCode Stelem = new CilOpCode(727492772u); public static readonly CilOpCode Unbox_Any = new CilOpCode(727362213u); public static readonly CilOpCode Conv_Ovf_I1 = new CilOpCode(694709939u); public static readonly CilOpCode Conv_Ovf_U1 = new CilOpCode(694709940u); public static readonly CilOpCode Conv_Ovf_I2 = new CilOpCode(694709941u); public static readonly CilOpCode Conv_Ovf_U2 = new CilOpCode(694709942u); public static readonly CilOpCode Conv_Ovf_I4 = new CilOpCode(694709943u); public static readonly CilOpCode Conv_Ovf_U4 = new CilOpCode(694709944u); public static readonly CilOpCode Conv_Ovf_I8 = new CilOpCode(694710457u); public static readonly CilOpCode Conv_Ovf_U8 = new CilOpCode(694710458u); public static readonly CilOpCode Refanyval = new CilOpCode(728264386u); public static readonly CilOpCode Ckfinite = new CilOpCode(694711491u); public static readonly CilOpCode Mkrefany = new CilOpCode(728296134u); public static readonly CilOpCode Ldtoken = new CilOpCode(724053712u); public static readonly CilOpCode Conv_U2 = new CilOpCode(694709969u); public static readonly CilOpCode Conv_U1 = new CilOpCode(694709970u); public static readonly CilOpCode Conv_I = new CilOpCode(694709971u); public static readonly CilOpCode Conv_Ovf_I = new CilOpCode(694709972u); public static readonly CilOpCode Conv_Ovf_U = new CilOpCode(694709973u); public static readonly CilOpCode Add_Ovf = new CilOpCode(694725334u); public static readonly CilOpCode Add_Ovf_Un = new CilOpCode(694725335u); public static readonly CilOpCode Mul_Ovf = new CilOpCode(694725336u); public static readonly CilOpCode Mul_Ovf_Un = new CilOpCode(694725337u); public static readonly CilOpCode Sub_Ovf = new CilOpCode(694725338u); public static readonly CilOpCode Sub_Ovf_Un = new CilOpCode(694725339u); public static readonly CilOpCode Endfinally = new CilOpCode(963438812u); public static readonly CilOpCode Leave = new CilOpCode(2943197u); public static readonly CilOpCode Leave_S = new CilOpCode(65857758u); public static readonly CilOpCode Stind_I = new CilOpCode(694773983u); public static readonly CilOpCode Conv_U = new CilOpCode(694709984u); public static readonly CilOpCode Prefix7 = new CilOpCode(558901496u); public static readonly CilOpCode Prefix6 = new CilOpCode(558901497u); public static readonly CilOpCode Prefix5 = new CilOpCode(558901498u); public static readonly CilOpCode Prefix4 = new CilOpCode(558901499u); public static readonly CilOpCode Prefix3 = new CilOpCode(558901500u); public static readonly CilOpCode Prefix2 = new CilOpCode(558901501u); public static readonly CilOpCode Prefix1 = new CilOpCode(558901502u); public static readonly CilOpCode Prefixref = new CilOpCode(558901503u); public static readonly CilOpCode Arglist = new CilOpCode(694693632u); public static readonly CilOpCode Ceq = new CilOpCode(694726401u); public static readonly CilOpCode Cgt = new CilOpCode(694726402u); public static readonly CilOpCode Cgt_Un = new CilOpCode(694726403u); public static readonly CilOpCode Clt = new CilOpCode(694726404u); public static readonly CilOpCode Clt_Un = new CilOpCode(694726405u); public static readonly CilOpCode Ldftn = new CilOpCode(690499334u); public static readonly CilOpCode Ldvirtftn = new CilOpCode(690663175u); public static readonly CilOpCode Ldarg = new CilOpCode(753412873u); public static readonly CilOpCode Ldarga = new CilOpCode(753413898u); public static readonly CilOpCode Starg = new CilOpCode(753428747u); public static readonly CilOpCode Ldloc = new CilOpCode(732441356u); public static readonly CilOpCode Ldloca = new CilOpCode(732442381u); public static readonly CilOpCode Stloc = new CilOpCode(732457230u); public static readonly CilOpCode Localloc = new CilOpCode(694742799u); public static readonly CilOpCode Endfilter = new CilOpCode(963176721u); public static readonly CilOpCode Unaligned = new CilOpCode(606087442u); public static readonly CilOpCode Volatile = new CilOpCode(559950099u); public static readonly CilOpCode Tailcall = new CilOpCode(559950100u); public static readonly CilOpCode Initobj = new CilOpCode(727247125u); public static readonly CilOpCode Constrained = new CilOpCode(593504534u); public static readonly CilOpCode Cpblk = new CilOpCode(694806807u); public static readonly CilOpCode Initblk = new CilOpCode(694806808u); public static readonly CilOpCode Rethrow = new CilOpCode(1096296730u); public static readonly CilOpCode Sizeof = new CilOpCode(728248092u); public static readonly CilOpCode Refanytype = new CilOpCode(694710045u); public static readonly CilOpCode Readonly = new CilOpCode(559950110u); } public enum CilOpCodeType : byte { Annotation, Macro, Internal, ObjModel, Prefix, Primitive } public enum CilOperandType { InlineBrTarget = 0, InlineField = 1, InlineI = 2, InlineI8 = 3, InlineMethod = 4, InlineNone = 5, InlinePhi = 6, InlineR = 7, InlineSig = 9, InlineString = 10, InlineSwitch = 11, InlineTok = 12, InlineType = 13, InlineVar = 14, ShortInlineBrTarget = 15, ShortInlineI = 16, ShortInlineR = 17, ShortInlineVar = 18, InlineArgument = 19, ShortInlineArgument = 20 } public class CilRawFatMethodBody : CilRawMethodBody { private CilMethodBodyAttributes _attributes; public override bool IsFat => true; public CilMethodBodyAttributes Attributes { get { return _attributes; } set { _attributes = value | CilMethodBodyAttributes.Fat; } } public bool HasSections { get { return (Attributes & CilMethodBodyAttributes.MoreSections) != 0; } set { Attributes = (Attributes & ~CilMethodBodyAttributes.MoreSections) | (value ? CilMethodBodyAttributes.MoreSections : ((CilMethodBodyAttributes)0)); } } public bool InitLocals { get { return (Attributes & CilMethodBodyAttributes.InitLocals) != 0; } set { Attributes = (Attributes & ~CilMethodBodyAttributes.InitLocals) | (value ? CilMethodBodyAttributes.InitLocals : ((CilMethodBodyAttributes)0)); } } public ushort MaxStack { get; set; } public MetadataToken LocalVarSigToken { get; set; } public IList ExtraSections { get; } = new List(); public CilRawFatMethodBody(CilMethodBodyAttributes attributes, ushort maxStack, MetadataToken localVarSigToken, IReadableSegment code) : base(code) { Attributes = attributes; MaxStack = maxStack; LocalVarSigToken = localVarSigToken; } public new static CilRawFatMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)(num & 0xFFFu); int num2 = (num >> 12) * 4; if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Fat) != CilMethodBodyAttributes.Fat) { ErrorListenerExtensions.BadImage(errorListener, "Invalid fat CIL method body header."); return null; } ushort maxStack = ((BinaryStreamReader)(ref reader)).ReadUInt16(); uint num3 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num4 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); ((BinaryStreamReader)(ref reader)).Offset = offset + (ulong)num2; if (((BinaryStreamReader)(ref reader)).Offset + num3 > ((BinaryStreamReader)(ref reader)).StartOffset + ((BinaryStreamReader)(ref reader)).Length) { ErrorListenerExtensions.BadImage(errorListener, "Invalid fat CIL method body code size."); return null; } IReadableSegment code = ((BinaryStreamReader)(ref reader)).ReadSegment(num3); CilRawFatMethodBody cilRawFatMethodBody = new CilRawFatMethodBody(cilMethodBodyAttributes, maxStack, num4, code); RelocationParameters val = new RelocationParameters(offset, rva); ((SegmentBase)cilRawFatMethodBody).UpdateOffsets(ref val); if (cilRawFatMethodBody.HasSections) { ((BinaryStreamReader)(ref reader)).Align(4u); CilExtraSection cilExtraSection; do { cilExtraSection = CilExtraSection.FromReader(ref reader); cilRawFatMethodBody.ExtraSections.Add(cilExtraSection); } while (cilExtraSection.HasMoreSections); } return cilRawFatMethodBody; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(12u); ((ISegment)base.Code).UpdateOffsets(ref val); if (HasSections) { uint physicalSize = ((IWritable)base.Code).GetPhysicalSize(); ((RelocationParameters)(ref val)).Advance(physicalSize); ((RelocationParameters)(ref val)).Align(4u); for (int i = 0; i < ExtraSections.Count; i++) { ((SegmentBase)ExtraSections[i]).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(((SegmentBase)ExtraSections[i]).GetPhysicalSize()); } } } public override uint GetPhysicalSize() { uint num = 12 + ((IWritable)base.Code).GetPhysicalSize(); ulong num2 = ((SegmentBase)this).Offset + num; if (HasSections) { ulong num3 = Extensions.Align(num2, 4uL); num += (uint)(int)(num3 - num2); for (int i = 0; i < ExtraSections.Count; i++) { num += ((SegmentBase)ExtraSections[i]).GetPhysicalSize(); } } return num; } public override void Write(IBinaryStreamWriter writer) { writer.WriteUInt16((ushort)(_attributes | (CilMethodBodyAttributes)12288)); writer.WriteUInt16(MaxStack); writer.WriteUInt32(((IWritable)base.Code).GetPhysicalSize()); writer.WriteUInt32(LocalVarSigToken.ToUInt32()); ((IWritable)base.Code).Write(writer); if (HasSections) { IOExtensions.Align(writer, 4u); for (int i = 0; i < ExtraSections.Count; i++) { ((SegmentBase)ExtraSections[i]).Write(writer); } } } } public abstract class CilRawMethodBody : SegmentBase { public abstract bool IsFat { get; } public IReadableSegment Code { get; set; } protected CilRawMethodBody(IReadableSegment code) { Code = code; } public static CilRawMethodBody? FromReader(ref BinaryStreamReader reader) { return FromReader((IErrorListener)(object)ThrowErrorListener.Instance, ref reader); } public static CilRawMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); ulong offset = ((BinaryStreamReader)(ref reader)).Offset; ((BinaryStreamReader)(ref reader)).Offset = offset - 1; if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Fat) == CilMethodBodyAttributes.Fat) { return CilRawFatMethodBody.FromReader(errorListener, ref reader); } if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Tiny) == CilMethodBodyAttributes.Tiny) { return CilRawTinyMethodBody.FromReader(errorListener, ref reader); } throw new NotSupportedException("Invalid or unsupported method body format."); } } public class CilRawTinyMethodBody : CilRawMethodBody { public override bool IsFat => false; public CilRawTinyMethodBody(byte[] code) : base((IReadableSegment)new DataSegment(code)) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown public CilRawTinyMethodBody(IReadableSegment code) : base(code) { } public new static CilRawTinyMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Tiny) != CilMethodBodyAttributes.Tiny) { ErrorListenerExtensions.BadImage(errorListener, "Invalid tiny CIL method body header."); return null; } uint num = (uint)cilMethodBodyAttributes >> 2; CilRawTinyMethodBody cilRawTinyMethodBody = new CilRawTinyMethodBody(((BinaryStreamReader)(ref reader)).ReadSegment(num)); RelocationParameters val = new RelocationParameters(offset, rva); ((SegmentBase)cilRawTinyMethodBody).UpdateOffsets(ref val); return cilRawTinyMethodBody; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); IReadableSegment code = base.Code; RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(1u); ((ISegment)code).UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return 1 + ((IWritable)base.Code).GetPhysicalSize(); } public override void Write(IBinaryStreamWriter writer) { uint physicalSize = ((IWritable)base.Code).GetPhysicalSize(); if (physicalSize > 63) { throw new ArgumentException("Code of a tiny method body cannot be 64 bytes or larger."); } byte b = (byte)(2u | (physicalSize << 2)); writer.WriteByte(b); IReadableSegment code = base.Code; if (code != null) { ((IWritable)code).Write(writer); } } } public enum CilStackBehaviour : byte { Pop0, Pop1, Pop1_Pop1, PopI, PopI_Pop1, PopI_PopI, PopI_PopI8, PopI_PopI_PopI, PopI_PopR4, PopI_PopR8, PopRef, PopRef_Pop1, PopRef_PopI, PopRef_PopI_PopI, PopRef_PopI_PopI8, PopRef_PopI_PopR4, PopRef_PopI_PopR8, PopRef_PopI_PopRef, PopRef_PopI_Pop1, PopAll, Push0, Push1, Push1_Push1, PushI, PushI8, PushR4, PushR8, PushRef, VarPop, VarPush } public sealed class EmptyOperandResolver : ICilOperandResolver { public static EmptyOperandResolver Instance { get; } = new EmptyOperandResolver(); private EmptyOperandResolver() { } public object? ResolveMember(MetadataToken token) { return null; } public object? ResolveString(MetadataToken token) { return null; } public object? ResolveLocalVariable(int index) { return null; } public object? ResolveParameter(int index) { return null; } } public interface ICilInstructionFormatter { string FormatInstruction(CilInstruction instruction); } public interface ICilLabel : IEquatable { int Offset { get; } } public interface ICilOperandBuilder { int GetVariableIndex(object? operand); int GetArgumentIndex(object? operand); uint GetStringToken(object? operand); MetadataToken GetMemberToken(object? operand); } public interface ICilOperandResolver { object? ResolveMember(MetadataToken token); object? ResolveString(MetadataToken token); object? ResolveLocalVariable(int index); object? ResolveParameter(int index); } } namespace AsmResolver.PE.DotNet.Builder { public class DotNetSegmentBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _segments; public ulong Offset => _segments.Offset; public uint Rva => _segments.Rva; public bool CanUpdateOffsets => _segments.CanUpdateOffsets; public IDotNetDirectory DotNetDirectory { get; } public SegmentBuilder FieldRvaTable { get; } public MethodBodyTableBuffer MethodBodyTable { get; } public DotNetSegmentBuffer(IDotNetDirectory dotNetDirectory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_002a: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(DotNetDirectory = dotNetDirectory)); SegmentBuilder val2 = new SegmentBuilder(); SegmentBuilder val3 = val2; FieldRvaTable = val2; val.Add((ISegment)(object)val3); val.Add((ISegment)(object)(MethodBodyTable = new MethodBodyTableBuffer())); _segments = val; AddIfPresent((ISegment?)dotNetDirectory.Metadata); AddIfPresent((ISegment?)(object)dotNetDirectory.DotNetResources); AddIfPresent((ISegment?)(object)dotNetDirectory.StrongName); VTableFixupsDirectory? vTableFixups = dotNetDirectory.VTableFixups; if (vTableFixups != null && vTableFixups.Count > 0) { _segments.Add((ISegment)(object)dotNetDirectory.VTableFixups); } AddIfPresent((ISegment?)(object)dotNetDirectory.ExportAddressTable); AddIfPresent((ISegment?)(object)dotNetDirectory.ManagedNativeHeader); } private void AddIfPresent(ISegment? segment) { if (segment != null) { _segments.Add(segment, 4u); } } public void UpdateOffsets(in RelocationParameters parameters) { _segments.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _segments.GetPhysicalSize(); } public uint GetVirtualSize() { return _segments.GetVirtualSize(); } public void Write(IBinaryStreamWriter writer) { _segments.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class ManagedPEFileBuilder : PEFileBuilderBase { public class ManagedPEBuilderContext { public ImportDirectoryBuffer ImportDirectory { get; } public ExportDirectoryBuffer ExportDirectory { get; } public DebugDirectoryBuffer DebugDirectory { get; } public DotNetSegmentBuffer DotNetSegment { get; } public ResourceDirectoryBuffer ResourceDirectory { get; } public RelocationsDirectoryBuffer RelocationsDirectory { get; } public Platform Platform { get; } public RelocatableSegment? Bootstrapper { get; set; } public IFieldRvaDataReader FieldRvaDataReader { get; } public ManagedPEBuilderContext(IPEImage image) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (image.DotNetDirectory == null) { throw new ArgumentException("Image does not contain a .NET directory."); } ImportDirectory = new ImportDirectoryBuffer((int)image.PEKind == 267); ExportDirectory = new ExportDirectoryBuffer(); DotNetSegment = new DotNetSegmentBuffer(image.DotNetDirectory); ResourceDirectory = new ResourceDirectoryBuffer(); RelocationsDirectory = new RelocationsDirectoryBuffer(); FieldRvaDataReader = new FieldRvaDataReader(); DebugDirectory = new DebugDirectoryBuffer(); Platform = AsmResolver.PE.Platforms.Platform.Get(image.MachineType); } } protected override ManagedPEBuilderContext CreateContext(IPEImage image) { return new ManagedPEBuilderContext(image); } protected override IEnumerable CreateSections(IPEImage image, ManagedPEBuilderContext context) { List list = new List { CreateTextSection(image, context) }; if (image.Exports != null || image.DotNetDirectory?.VTableFixups != null) { list.Add(CreateSDataSection(image, context)); } if (image.Resources != null && image.Resources.Entries.Count > 0) { list.Add(CreateRsrcSection(image, context)); } List list2 = image.Relocations.Where((BaseRelocation r) => !(r.Location is PESegmentReference)).ToList(); if (context.Bootstrapper.HasValue) { list2.AddRange(context.Bootstrapper.Value.Relocations); } if (list2.Count > 0) { list.Add(CreateRelocSection(context, list2)); } return list; } protected virtual PESection CreateTextSection(IPEImage image, ManagedPEBuilderContext context) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown CreateImportDirectory(image, context); CreateDebugDirectory(image, context); ProcessRvasInMetadataTables(context); SegmentBuilder val = new SegmentBuilder(); if (context.ImportDirectory.Count > 0) { val.Add((ISegment)(object)context.ImportDirectory.ImportAddressDirectory); } val.Add((ISegment)(object)context.DotNetSegment); if (context.ImportDirectory.Count > 0) { val.Add((ISegment)(object)context.ImportDirectory); } if (!context.ExportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ExportDirectory); } if (!context.DebugDirectory.IsEmpty) { val.Add((ISegment)(object)context.DebugDirectory); val.Add(context.DebugDirectory.ContentsTable); } if (context.Bootstrapper.HasValue) { val.Add(context.Bootstrapper.Value.Segment); } IExportDirectory exports = image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { for (int i = 0; i < entries.Count; i++) { ExportedSymbol exportedSymbol = entries[i]; if (exportedSymbol.Address.IsBounded) { ISegment segment = exportedSymbol.Address.GetSegment(); if (segment != null) { val.Add(segment, 4u); } } } } } return new PESection(".text", (SectionFlags)1610612768) { Contents = (ISegment)(object)val }; } private static void CreateImportDirectory(IPEImage image, ManagedPEBuilderContext context) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) bool flag = context.Platform.IsClrBootstrapperRequired || (image.DotNetDirectory.Flags & DotNetDirectoryFlags.ILOnly) == 0; string mscoreeEntryName = (((image.Characteristics & 0x2000) != 0) ? "_CorDllMain" : "_CorExeMain"); ImportedSymbol entryPointSymbol; foreach (IImportedModule item in CollectImportedModules(image, flag, mscoreeEntryName, out entryPointSymbol)) { context.ImportDirectory.AddModule(item); } if (flag) { if (entryPointSymbol == null) { throw new InvalidOperationException("Entry point symbol was required but not imported."); } context.Bootstrapper = context.Platform.CreateThunkStub((ISymbol)(object)entryPointSymbol); } } private static List CollectImportedModules(IPEImage image, bool entryRequired, string mscoreeEntryName, out ImportedSymbol? entryPointSymbol) { string mscoreeEntryName2 = mscoreeEntryName; List list = new List(); IImportedModule importedModule = null; entryPointSymbol = null; foreach (IImportedModule import in image.Imports) { if (import.Name == "mscoree.dll") { importedModule = import; if (entryRequired) { entryPointSymbol = importedModule.Symbols.FirstOrDefault((ImportedSymbol s) => s.Name == mscoreeEntryName2); } if (entryRequired || import.Symbols.Count > 1) { list.Add(import); } } else { list.Add(import); } } if (entryRequired) { if (importedModule == null) { importedModule = new ImportedModule("mscoree.dll"); list.Add(importedModule); } if (entryPointSymbol == null) { entryPointSymbol = new ImportedSymbol(0, mscoreeEntryName2); importedModule.Symbols.Add(entryPointSymbol); } } return list; } private static void CreateDebugDirectory(IPEImage image, ManagedPEBuilderContext context) { for (int i = 0; i < image.DebugData.Count; i++) { context.DebugDirectory.AddEntry(image.DebugData[i]); } } protected virtual PESection CreateSDataSection(IPEImage image, ManagedPEBuilderContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown SegmentBuilder val = new SegmentBuilder(); VTableFixupsDirectory vTableFixupsDirectory = image.DotNetDirectory?.VTableFixups; if (vTableFixupsDirectory != null) { for (int i = 0; i < vTableFixupsDirectory.Count; i++) { val.Add((ISegment)(object)vTableFixupsDirectory[i].Tokens); } } IExportDirectory exports = image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { context.ExportDirectory.AddDirectory(exports); val.Add((ISegment)(object)context.ExportDirectory, 4u); } } return new PESection(".sdata", (SectionFlags)(-1073741760), (ISegment)(object)val); } protected virtual PESection CreateRsrcSection(IPEImage image, ManagedPEBuilderContext context) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown context.ResourceDirectory.AddDirectory(image.Resources); return new PESection(".rsrc", (SectionFlags)1073741888, (ISegment)(object)context.ResourceDirectory); } protected virtual PESection CreateRelocSection(ManagedPEBuilderContext context, IReadOnlyList relocations) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown for (int i = 0; i < relocations.Count; i++) { context.RelocationsDirectory.Add(relocations[i]); } return new PESection(".reloc", (SectionFlags)1073741888) { Contents = (ISegment)(object)context.RelocationsDirectory }; } protected override IEnumerable CreateDataDirectories(PEFile peFile, IPEImage image, ManagedPEBuilderContext context) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) ImportDirectoryBuffer importDirectory = context.ImportDirectory; ResourceDirectoryBuffer resourceDirectory = context.ResourceDirectory; RelocationsDirectoryBuffer relocationsDirectory = context.RelocationsDirectory; ImportAddressDirectoryBuffer importAddressDirectory = importDirectory.ImportAddressDirectory; IDotNetDirectory dotNetDirectory = context.DotNetSegment.DotNetDirectory; DataDirectory val = ((!context.ExportDirectory.IsEmpty) ? new DataDirectory(((SegmentBase)context.ExportDirectory).Rva, ((SegmentBase)context.ExportDirectory).GetPhysicalSize()) : default(DataDirectory)); DataDirectory val2 = ((!context.DebugDirectory.IsEmpty) ? new DataDirectory(context.DebugDirectory.Rva, context.DebugDirectory.GetPhysicalSize()) : default(DataDirectory)); return (IEnumerable)(object)new DataDirectory[15] { val, new DataDirectory(((SegmentBase)importDirectory).Rva, ((SegmentBase)importDirectory).GetPhysicalSize()), new DataDirectory(resourceDirectory.Rva, resourceDirectory.GetPhysicalSize()), default(DataDirectory), default(DataDirectory), new DataDirectory(((SegmentBase)relocationsDirectory).Rva, ((SegmentBase)relocationsDirectory).GetPhysicalSize()), val2, default(DataDirectory), default(DataDirectory), default(DataDirectory), default(DataDirectory), default(DataDirectory), new DataDirectory(((SegmentBase)importAddressDirectory).Rva, ((SegmentBase)importAddressDirectory).GetPhysicalSize()), default(DataDirectory), new DataDirectory(((IOffsetProvider)dotNetDirectory).Rva, ((IWritable)dotNetDirectory).GetPhysicalSize()) }; } protected override uint GetEntryPointAddress(PEFile peFile, IPEImage image, ManagedPEBuilderContext context) { RelocatableSegment? bootstrapper = context.Bootstrapper; if (!bootstrapper.HasValue) { return 0u; } return ((IOffsetProvider)bootstrapper.GetValueOrDefault().Segment).Rva; } protected override uint GetFileAlignment(PEFile peFile, IPEImage image, ManagedPEBuilderContext context) { return 512u; } protected override uint GetSectionAlignment(PEFile peFile, IPEImage image, ManagedPEBuilderContext context) { return 8192u; } protected override uint GetImageBase(PEFile peFile, IPEImage image, ManagedPEBuilderContext context) { return (uint)image.ImageBase; } private static void ProcessRvasInMetadataTables(ManagedPEBuilderContext context) { DotNetSegmentBuffer dotNetSegment = context.DotNetSegment; TablesStream tablesStream = dotNetSegment.DotNetDirectory.Metadata?.GetStream(); if (tablesStream == null) { throw new ArgumentException("Image does not have a .NET metadata tables stream."); } AddMethodBodiesToTable(dotNetSegment.MethodBodyTable, tablesStream); AddFieldRvasToTable(context); } private static void AddMethodBodiesToTable(MethodBodyTableBuffer table, TablesStream tablesStream) { MetadataTable table2 = tablesStream.GetTable(); for (int i = 0; i < table2.Count; i++) { MethodDefinitionRow methodRow = table2[i]; ISegment methodBodySegment = GetMethodBodySegment(methodRow); if (methodBodySegment is CilRawMethodBody body) { table.AddCilBody(body); } else { if (methodBodySegment == null) { continue; } table.AddNativeBody(methodBodySegment, 4u); } table2[i] = new MethodDefinitionRow(Extensions.ToReference(methodBodySegment), methodRow.ImplAttributes, methodRow.Attributes, methodRow.Name, methodRow.Signature, methodRow.ParameterList); } } private static ISegment? GetMethodBodySegment(MethodDefinitionRow methodRow) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (methodRow.Body.IsBounded) { return methodRow.Body.GetSegment(); } if (methodRow.Body.CanRead) { if ((methodRow.ImplAttributes & AsmResolver.PE.DotNet.Metadata.Tables.Rows.MethodImplAttributes.Runtime) == 0) { BinaryStreamReader reader = methodRow.Body.CreateReader(); return (ISegment?)(object)CilRawMethodBody.FromReader((IErrorListener)(object)ThrowErrorListener.Instance, ref reader); } throw new NotImplementedException("Native unbounded method bodies cannot be reassembled yet."); } return null; } private static void AddFieldRvasToTable(ManagedPEBuilderContext context) { IMetadata metadata = context.DotNetSegment.DotNetDirectory.Metadata; MetadataTable table = metadata.GetStream().GetTable(TableIndex.FieldRva); if (table.Count == 0) { return; } SegmentBuilder fieldRvaTable = context.DotNetSegment.FieldRvaTable; IFieldRvaDataReader fieldRvaDataReader = context.FieldRvaDataReader; for (int i = 0; i < table.Count; i++) { ThrowErrorListener instance = ThrowErrorListener.Instance; FieldRvaRow fieldRvaRow = table[i]; ISegment val = fieldRvaDataReader.ResolveFieldData((IErrorListener)(object)instance, metadata, in fieldRvaRow); if (val != null) { fieldRvaTable.Add(val); } } } } public class MethodBodyTableBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _tinyBodies = new SegmentBuilder(); private readonly SegmentBuilder _fatBodies = new SegmentBuilder(); private readonly SegmentBuilder _nativeBodies = new SegmentBuilder(); private readonly SegmentBuilder _segments = new SegmentBuilder(); public ulong Offset => _segments.Offset; public uint Rva => _segments.Rva; public bool CanUpdateOffsets => _segments.CanUpdateOffsets; public MethodBodyTableBuffer() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown _segments.Add((ISegment)(object)_tinyBodies); _segments.Add((ISegment)(object)_fatBodies); _segments.Add((ISegment)(object)_nativeBodies); } public void AddCilBody(CilRawMethodBody body) { if (body.IsFat) { _fatBodies.Add((ISegment)(object)body, 4u); } else { _tinyBodies.Add((ISegment)(object)body); } } public void AddNativeBody(ISegment body, uint alignment) { _nativeBodies.Add(body, alignment); } public void UpdateOffsets(in RelocationParameters parameters) { _segments.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _segments.GetPhysicalSize(); } public uint GetVirtualSize() { return _segments.GetVirtualSize(); } public void Write(IBinaryStreamWriter writer) { _segments.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } } namespace AsmResolver.PE.Debug { public class CustomDebugDataSegment : IDebugDataSegment, ISegment, IOffsetProvider, IWritable { public DebugDataType Type { get; } public ISegment? Contents { get; set; } public ulong Offset { get { ISegment? contents = Contents; if (contents == null) { return 0uL; } return ((IOffsetProvider)contents).Offset; } } public uint Rva { get { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IOffsetProvider)contents).Rva; } } public bool CanUpdateOffsets { get { ISegment? contents = Contents; if (contents == null) { return false; } return contents.CanUpdateOffsets; } } public CustomDebugDataSegment(DebugDataType type, ISegment contents) { Type = type; Contents = contents ?? throw new ArgumentNullException("contents"); } public void UpdateOffsets(in RelocationParameters parameters) { if (Contents != null) { Contents.UpdateOffsets(ref parameters); return; } throw new ArgumentNullException("Contents"); } public uint GetPhysicalSize() { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IWritable)contents).GetPhysicalSize(); } public uint GetVirtualSize() { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IWritable)contents).GetPhysicalSize(); } public void Write(IBinaryStreamWriter writer) { ISegment? contents = Contents; if (contents != null) { ((IWritable)contents).Write(writer); } } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class DebugDataEntry : SegmentBase { public const uint DebugDataEntryHeaderSize = 28u; private readonly LazyVariable _contents; public uint Characteristics { get; set; } public uint TimeDateStamp { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public IDebugDataSegment? Contents { get { return _contents.Value; } set { _contents.Value = value; } } protected DebugDataEntry() { _contents = new LazyVariable((Func)GetContents); } public DebugDataEntry(IDebugDataSegment contents) { _contents = new LazyVariable(contents); } protected virtual IDebugDataSegment? GetContents() { return null; } public override uint GetPhysicalSize() { return 28u; } public override void Write(IBinaryStreamWriter writer) { writer.WriteUInt32(Characteristics); writer.WriteUInt32(TimeDateStamp); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt32((uint)(Contents?.Type ?? DebugDataType.Unknown)); IDebugDataSegment? contents = Contents; writer.WriteUInt32((contents != null) ? ((IWritable)contents).GetPhysicalSize() : 0u); IDebugDataSegment? contents2 = Contents; writer.WriteUInt32((contents2 != null) ? ((IOffsetProvider)contents2).Rva : 0u); IDebugDataSegment? contents3 = Contents; writer.WriteUInt32((uint)((contents3 != null) ? ((IOffsetProvider)contents3).Offset : 0)); } } public enum DebugDataType : uint { Unknown = 0u, Coff = 1u, CodeView = 2u, Fpo = 0u, Misc = 4u, Exception = 5u, FixUp = 6u, OMapToSrc = 7u, OMapFromSrc = 8u, Borland = 9u, Reserved10 = 10u, ClsId = 11u, VcFeature = 12u, Pogo = 13u, Iltcg = 14u, Mpx = 15u, Repro = 16u, ExDllCharacteristics = 20u } public class DefaultDebugDataReader : IDebugDataReader { public IDebugDataSegment? ReadDebugData(PEReaderContext context, DebugDataType type, ref BinaryStreamReader reader) { if (type == DebugDataType.CodeView) { return CodeViewDataSegment.FromReader(context, ref reader); } return new CustomDebugDataSegment(type, (ISegment)(object)DataSegment.FromReader(ref reader)); } } public interface IDebugDataReader { IDebugDataSegment? ReadDebugData(PEReaderContext context, DebugDataType type, ref BinaryStreamReader reader); } public interface IDebugDataSegment : ISegment, IOffsetProvider, IWritable { DebugDataType Type { get; } } public class SerializedDebugDataEntry : DebugDataEntry { private readonly PEReaderContext _context; private readonly DebugDataType _type; private readonly uint _sizeOfData; private readonly uint _addressOfRawData; private readonly uint _pointerToRawData; public SerializedDebugDataEntry(PEReaderContext context, ref BinaryStreamReader directoryReader) { if (!((BinaryStreamReader)(ref directoryReader)).IsValid) { throw new ArgumentNullException("directoryReader"); } _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref directoryReader)).Rva; base.Characteristics = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _type = (DebugDataType)((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _sizeOfData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _addressOfRawData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _pointerToRawData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); } protected override IDebugDataSegment? GetContents() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (_sizeOfData == 0) { return null; } ISegmentReference referenceToRva = ((ISegmentReferenceFactory)_context.File).GetReferenceToRva(_addressOfRawData); if (!referenceToRva.CanRead) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Debug data entry contains an invalid RVA."); return null; } BinaryStreamReader reader = referenceToRva.CreateReader(); if (_sizeOfData > ((BinaryStreamReader)(ref reader)).Length) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Debug data entry contains a too large size."); return null; } ((BinaryStreamReader)(ref reader)).ChangeSize(_sizeOfData); return _context.Parameters.DebugDataReader.ReadDebugData(_context, _type, ref reader); } } } namespace AsmResolver.PE.Debug.CodeView { public abstract class CodeViewDataSegment : SegmentBase, IDebugDataSegment, ISegment, IOffsetProvider, IWritable { public abstract CodeViewSignature Signature { get; } public DebugDataType Type => DebugDataType.CodeView; public static CodeViewDataSegment? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { return (CodeViewSignature)((BinaryStreamReader)(ref reader)).ReadUInt32() switch { CodeViewSignature.Rsds => RsdsDataSegment.FromReader(context, ref reader), CodeViewSignature.Nb05 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb09 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb10 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb11 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), _ => ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)context, "Invalid code view debug data signature."), }; } } public enum CodeViewSignature { Rsds = 1396986706, Nb05 = 892355150, Nb09 = 959464014, Nb10 = 808534606, Nb11 = 825311822 } public class RsdsDataSegment : CodeViewDataSegment { private const uint RsdsExpectedDataSize = 25u; public override CodeViewSignature Signature => CodeViewSignature.Rsds; public Guid Guid { get; set; } public uint Age { get; set; } public string? Path { get; set; } public new static RsdsDataSegment? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { if (((BinaryStreamReader)(ref reader)).Length < 25) { ErrorListenerExtensions.BadImage((IErrorListener)(object)context, "RSDS Data was shorter than the minimal expected length"); return null; } RsdsDataSegment rsdsDataSegment = new RsdsDataSegment(); byte[] array = new byte[16]; ((BinaryStreamReader)(ref reader)).ReadBytes(array, 0, 16); rsdsDataSegment.Guid = new Guid(array); rsdsDataSegment.Age = ((BinaryStreamReader)(ref reader)).ReadUInt32(); rsdsDataSegment.Path = Encoding.UTF8.GetString(((BinaryStreamReader)(ref reader)).ReadBytesUntil((byte)0)); return rsdsDataSegment; } public override uint GetPhysicalSize() { return (uint)(24 + (Path?.Length ?? 0) + 1); } public override void Write(IBinaryStreamWriter writer) { writer.WriteUInt32((uint)Signature); IOExtensions.WriteBytes(writer, Guid.ToByteArray()); writer.WriteUInt32(Age); IOExtensions.WriteBytes(writer, Encoding.UTF8.GetBytes(Path ?? string.Empty)); writer.WriteByte((byte)0); } } } namespace AsmResolver.PE.Debug.Builder { public class DebugDirectoryBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _headers = new SegmentBuilder(); private readonly SegmentBuilder _streamsTable = new SegmentBuilder(); public ISegment ContentsTable => (ISegment)(object)_streamsTable; public bool IsEmpty => _headers.Count == 0; public ulong Offset => _headers.Offset; public uint Rva => _headers.Rva; public bool CanUpdateOffsets => true; public void AddEntry(DebugDataEntry entry) { _headers.Add((ISegment)(object)entry); if (entry.Contents != null) { _streamsTable.Add((ISegment)entry.Contents, 4u); } } public void UpdateOffsets(in RelocationParameters parameters) { _headers.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _headers.GetPhysicalSize(); } public void Write(IBinaryStreamWriter writer) { _headers.Write(writer); } public uint GetVirtualSize() { return _headers.GetVirtualSize(); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } } namespace AsmResolver.PE.Code { [DebuggerDisplay("Patch {Offset} with &{Symbol} as {Type}")] public readonly struct AddressFixup { public uint Offset { get; } public AddressFixupType Type { get; } public ISymbol Symbol { get; } public AddressFixup(uint offset, AddressFixupType type, ISymbol referencedObject) { Offset = offset; Symbol = referencedObject ?? throw new ArgumentNullException("referencedObject"); Type = type; } public override string ToString() { return $"+{Offset:X8} <{Symbol}> ({Type})"; } } public static class AddressFixupExtensions { public static PatchedSegment Patch(this PatchedSegment segment, uint relativeOffset, AddressFixupType type, ISymbol referencedObject) { AddressFixup fixup = new AddressFixup(relativeOffset, type, referencedObject); return segment.Patch(in fixup); } public static PatchedSegment Patch(this PatchedSegment segment, uint relativeOffset, AddressFixupType type, uint symbolOffset) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown AddressFixup fixup = new AddressFixup(relativeOffset, type, (ISymbol)new Symbol(Extensions.ToReference((ISegment)(object)segment, (int)symbolOffset))); return segment.Patch(in fixup); } public static PatchedSegment Patch(this PatchedSegment segment, in AddressFixup fixup) { segment.Patches.Add((IPatch)(object)new AddressFixupPatch(fixup)); return segment; } } [DebuggerDisplay("{Fixup}")] public class AddressFixupPatch : IPatch { public AddressFixup Fixup { get; } public AddressFixupPatch(AddressFixup fixup) { Fixup = fixup; } public void Apply(in PatchContext context) { ((PatchContext)(ref context)).Writer.Offset = ((IOffsetProvider)((PatchContext)(ref context)).Segment).Offset + Fixup.Offset; uint num = ((IOffsetProvider)((PatchContext)(ref context)).Segment).Rva + Fixup.Offset; ISegmentReference reference = Fixup.Symbol.GetReference(); uint num2 = ((reference != null) ? ((IOffsetProvider)reference).Rva : 0u); switch (Fixup.Type) { case AddressFixupType.Absolute32BitAddress: ((PatchContext)(ref context)).Writer.WriteUInt32((uint)(((PatchContext)(ref context)).ImageBase + num2)); break; case AddressFixupType.Relative32BitAddress: ((PatchContext)(ref context)).Writer.WriteInt32((int)(num2 - (num + 4))); break; case AddressFixupType.Absolute64BitAddress: ((PatchContext)(ref context)).Writer.WriteUInt64(((PatchContext)(ref context)).ImageBase + num2); break; default: throw new ArgumentOutOfRangeException(); } } void IPatch.Apply(in PatchContext context) { Apply(in context); } } public enum AddressFixupType { Absolute32BitAddress, Absolute64BitAddress, Relative32BitAddress } [Obsolete("This class has been superseded by AsmResolver.Patching.PatchedSegment.")] public class CodeSegment : SegmentBase { public ulong ImageBase { get; set; } public byte[] Code { get; set; } public IList AddressFixups { get; } = new List(); public CodeSegment(byte[] code) { Code = code; } public CodeSegment(ulong imageBase, byte[] code) { ImageBase = imageBase; Code = code ?? throw new ArgumentNullException("code"); } public override void UpdateOffsets(in RelocationParameters parameters) { ImageBase = ((RelocationParameters)(ref parameters)).ImageBase; ((SegmentBase)this).UpdateOffsets(ref parameters); } public override uint GetPhysicalSize() { return (uint)Code.Length; } public override void Write(IBinaryStreamWriter writer) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) IOExtensions.WriteBytes(writer, Code); for (int i = 0; i < AddressFixups.Count; i++) { AddressFixupPatch addressFixupPatch = new AddressFixupPatch(AddressFixups[i]); PatchContext context = new PatchContext((ISegment)(object)this, ImageBase, writer); addressFixupPatch.Apply(in context); } writer.Offset = ((SegmentBase)this).Offset + ((SegmentBase)this).GetPhysicalSize(); } } } namespace AsmResolver.PE.Builder { public interface IPEFileBuilder { PEFile CreateFile(IPEImage image); } public abstract class PEFileBuilderBase : IPEFileBuilder { public virtual PEFile CreateFile(IPEImage image) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown PEFile val = new PEFile(); TContext context = CreateContext(image); foreach (PESection item in CreateSections(image, context)) { val.Sections.Add(item); } ComputeHeaderFields(val, image, context); return val; } protected abstract TContext CreateContext(IPEImage image); protected abstract IEnumerable CreateSections(IPEImage image, TContext context); protected abstract IEnumerable CreateDataDirectories(PEFile peFile, IPEImage image, TContext context); protected abstract uint GetEntryPointAddress(PEFile peFile, IPEImage image, TContext context); protected abstract uint GetFileAlignment(PEFile peFile, IPEImage image, TContext context); protected abstract uint GetSectionAlignment(PEFile peFile, IPEImage image, TContext context); protected abstract uint GetImageBase(PEFile peFile, IPEImage image, TContext context); protected virtual void ComputeHeaderFields(PEFile peFile, IPEImage image, TContext context) { ComputeOptionalHeaderFields(peFile, image, context); ComputeFileHeaderFields(peFile, image, context); peFile.DosHeader.NextHeaderOffset = ((SegmentBase)peFile.DosHeader).GetPhysicalSize(); } protected virtual void ComputeOptionalHeaderFields(PEFile peFile, IPEImage image, TContext context) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) OptionalHeader optionalHeader = peFile.OptionalHeader; optionalHeader.ImageBase = GetImageBase(peFile, image, context); optionalHeader.SectionAlignment = GetSectionAlignment(peFile, image, context); optionalHeader.FileAlignment = GetFileAlignment(peFile, image, context); if (optionalHeader.SectionAlignment < optionalHeader.FileAlignment) { throw new ArgumentException("File alignment cannot be larger than the section alignment."); } peFile.UpdateHeaders(); optionalHeader.Magic = image.PEKind; optionalHeader.MajorLinkerVersion = 48; optionalHeader.MinorLinkerVersion = 0; optionalHeader.SizeOfCode = 0u; optionalHeader.SizeOfInitializedData = 0u; optionalHeader.SizeOfUninitializedData = 0u; optionalHeader.SizeOfImage = 0u; for (int i = 0; i < peFile.Sections.Count; i++) { PESection val = peFile.Sections[i]; uint physicalSize = val.GetPhysicalSize(); if (val.IsContentCode) { optionalHeader.SizeOfCode += physicalSize; } if (val.IsContentInitializedData) { optionalHeader.SizeOfInitializedData += physicalSize; } if (val.IsContentUninitializedData) { optionalHeader.SizeOfUninitializedData += physicalSize; } optionalHeader.SizeOfImage += val.GetVirtualSize(); } optionalHeader.AddressOfEntryPoint = GetEntryPointAddress(peFile, image, context); PESection? obj = ((IEnumerable)peFile.Sections).FirstOrDefault((Func)((PESection s) => s.IsContentCode)); optionalHeader.BaseOfCode = ((obj != null) ? obj.Rva : 0u); PESection? obj2 = ((IEnumerable)peFile.Sections).FirstOrDefault((Func)((PESection s) => s.IsContentInitializedData)); optionalHeader.BaseOfData = ((obj2 != null) ? obj2.Rva : 0u); optionalHeader.MajorOperatingSystemVersion = 4; optionalHeader.MinorOperatingSystemVersion = 0; optionalHeader.MajorImageVersion = 0; optionalHeader.MinorImageVersion = 0; optionalHeader.MajorSubsystemVersion = 4; optionalHeader.MinorSubsystemVersion = 0; optionalHeader.Win32VersionValue = 0u; optionalHeader.SizeOfImage = Extensions.Align(optionalHeader.SizeOfImage, optionalHeader.SectionAlignment); optionalHeader.SizeOfHeaders = Extensions.Align(((SegmentBase)peFile.DosHeader).GetPhysicalSize() + ((SegmentBase)peFile.FileHeader).GetPhysicalSize() + ((SegmentBase)peFile.OptionalHeader).GetPhysicalSize() + (uint)(peFile.Sections.Count * 40), optionalHeader.FileAlignment); optionalHeader.CheckSum = 0u; optionalHeader.SubSystem = image.SubSystem; optionalHeader.DllCharacteristics = image.DllCharacteristics; optionalHeader.SizeOfStackReserve = 1048576uL; optionalHeader.SizeOfStackCommit = 4096uL; optionalHeader.SizeOfHeapReserve = 1048576uL; optionalHeader.SizeOfHeapCommit = 4096uL; optionalHeader.LoaderFlags = 0u; List list = CreateDataDirectories(peFile, image, context).ToList(); optionalHeader.DataDirectories.Clear(); for (int j = 0; j < 16; j++) { optionalHeader.DataDirectories.Add((DataDirectory)((j < list.Count) ? list[j] : new DataDirectory(0u, 0u))); } optionalHeader.NumberOfRvaAndSizes = 16u; } protected virtual void ComputeFileHeaderFields(PEFile peFile, IPEImage image, TContext context) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) FileHeader fileHeader = peFile.FileHeader; fileHeader.Machine = image.MachineType; fileHeader.NumberOfSections = (ushort)peFile.Sections.Count; fileHeader.TimeDateStamp = (uint)(image.TimeDateStamp - new DateTime(1970, 1, 1)).TotalSeconds; fileHeader.NumberOfSymbols = 0u; fileHeader.PointerToSymbolTable = 0u; fileHeader.SizeOfOptionalHeader = (ushort)((SegmentBase)peFile.OptionalHeader).GetPhysicalSize(); fileHeader.Characteristics = image.Characteristics; } } }