using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.SymbolStore; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Xml; using Microsoft.CodeAnalysis; using Microsoft.Win32.SafeHandles; using dnlib.DotNet; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.DotNet.Pdb.Dss; using dnlib.DotNet.Pdb.Managed; using dnlib.DotNet.Pdb.Portable; using dnlib.DotNet.Pdb.Symbols; using dnlib.DotNet.Pdb.WindowsPdb; using dnlib.DotNet.Writer; using dnlib.IO; using dnlib.PE; using dnlib.Threading; using dnlib.Utils; using dnlib.W32Resources; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("0xd4d")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2012-2019 de4dot@gmail.com")] [assembly: AssemblyDescription("Reads and writes .NET assemblies and modules")] [assembly: AssemblyFileVersion("4.5.0.0")] [assembly: AssemblyInformationalVersion("4.5.0+c78d296c522aae0520df2afd825d48266321cf36")] [assembly: AssemblyProduct("dnlib")] [assembly: AssemblyTitle("dnlib (thread safe)")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/0xd4d/dnlib")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(System.Security.Permissions.SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace System { internal static class Array2 { private static class EmptyClass { public static readonly T[] Empty = new T[0]; } public static T[] Empty() { return EmptyClass.Empty; } } } namespace dnlib { public static class Settings { public static bool IsThreadSafe => true; } } namespace dnlib.W32Resources { public sealed class ResourceData : ResourceDirectoryEntry { private readonly DataReaderFactory dataReaderFactory; private readonly uint resourceStartOffset; private readonly uint resourceLength; private uint codePage; private uint reserved; public uint CodePage { get { return codePage; } set { codePage = value; } } public uint Reserved { get { return reserved; } set { reserved = value; } } public DataReader CreateReader() { return dataReaderFactory.CreateReader(resourceStartOffset, resourceLength); } public ResourceData(ResourceName name) : this(name, ByteArrayDataReaderFactory.Create(Array2.Empty(), null), 0u, 0u) { } public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length) : this(name, dataReaderFactory, offset, length, 0u, 0u) { } public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length, uint codePage, uint reserved) : base(name) { this.dataReaderFactory = dataReaderFactory ?? throw new ArgumentNullException("dataReaderFactory"); resourceStartOffset = offset; resourceLength = length; this.codePage = codePage; this.reserved = reserved; } } public abstract class ResourceDirectory : ResourceDirectoryEntry { protected uint characteristics; protected uint timeDateStamp; protected ushort majorVersion; protected ushort minorVersion; private protected LazyList directories; private protected LazyList data; public uint Characteristics { get { return characteristics; } set { characteristics = value; } } public uint TimeDateStamp { get { return timeDateStamp; } set { timeDateStamp = value; } } public ushort MajorVersion { get { return majorVersion; } set { majorVersion = value; } } public ushort MinorVersion { get { return minorVersion; } set { minorVersion = value; } } public IList Directories => directories; public IList Data => data; protected ResourceDirectory(ResourceName name) : base(name) { } public ResourceDirectory FindDirectory(ResourceName name) { foreach (ResourceDirectory directory in directories) { if (directory.Name == name) { return directory; } } return null; } public ResourceData FindData(ResourceName name) { foreach (ResourceData datum in data) { if (datum.Name == name) { return datum; } } return null; } } public class ResourceDirectoryUser : ResourceDirectory { public ResourceDirectoryUser(ResourceName name) : base(name) { directories = new LazyList(); data = new LazyList(); } } public sealed class ResourceDirectoryPE : ResourceDirectory { private readonly struct EntryInfo { public readonly ResourceName name; public readonly uint offset; public EntryInfo(ResourceName name, uint offset) { this.name = name; this.offset = offset; } public override string ToString() { return $"{offset:X8} {name}"; } } private const uint MAX_DIR_DEPTH = 10u; private readonly Win32ResourcesPE resources; private uint depth; private List dataInfos; private List dirInfos; public ResourceDirectoryPE(uint depth, ResourceName name, Win32ResourcesPE resources, ref DataReader reader) : base(name) { this.resources = resources; this.depth = depth; Initialize(ref reader); } private void Initialize(ref DataReader reader) { if (depth > 10 || !reader.CanRead(16u)) { InitializeDefault(); return; } characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); ushort num = reader.ReadUInt16(); ushort num2 = reader.ReadUInt16(); int num3 = num + num2; if (!reader.CanRead((uint)(num3 * 8))) { InitializeDefault(); return; } dataInfos = new List(); dirInfos = new List(); uint num4 = reader.Position; int num5 = 0; while (num5 < num3) { reader.Position = num4; uint num6 = reader.ReadUInt32(); uint num7 = reader.ReadUInt32(); ResourceName resourceName = (((num6 & 0x80000000u) == 0) ? new ResourceName((int)num6) : new ResourceName(ReadString(ref reader, num6 & 0x7FFFFFFF) ?? string.Empty)); if ((num7 & 0x80000000u) == 0) { dataInfos.Add(new EntryInfo(resourceName, num7)); } else { dirInfos.Add(new EntryInfo(resourceName, num7 & 0x7FFFFFFF)); } num5++; num4 += 8; } directories = new LazyList(dirInfos.Count, null, (object ctx, int i) => ReadResourceDirectory(i)); data = new LazyList(dataInfos.Count, null, (object ctx, int i) => ReadResourceData(i)); } private static string ReadString(ref DataReader reader, uint offset) { reader.Position = offset; if (!reader.CanRead(2u)) { return null; } int num = reader.ReadUInt16() * 2; if (!reader.CanRead((uint)num)) { return null; } try { return reader.ReadUtf16String(num / 2); } catch { return null; } } private ResourceDirectory ReadResourceDirectory(int i) { EntryInfo entryInfo = dirInfos[i]; DataReader reader = resources.GetResourceReader(); reader.Position = Math.Min(reader.Length, entryInfo.offset); return new ResourceDirectoryPE(depth + 1, entryInfo.name, resources, ref reader); } private ResourceData ReadResourceData(int i) { EntryInfo entryInfo = dataInfos[i]; DataReader resourceReader = resources.GetResourceReader(); resourceReader.Position = Math.Min(resourceReader.Length, entryInfo.offset); if (resourceReader.CanRead(16u)) { RVA rva = (RVA)resourceReader.ReadUInt32(); uint size = resourceReader.ReadUInt32(); uint codePage = resourceReader.ReadUInt32(); uint reserved = resourceReader.ReadUInt32(); resources.GetDataReaderInfo(rva, size, out var dataReaderFactory, out var dataOffset, out var dataLength); return new ResourceData(entryInfo.name, dataReaderFactory, dataOffset, dataLength, codePage, reserved); } return new ResourceData(entryInfo.name); } private void InitializeDefault() { directories = new LazyList(); data = new LazyList(); } } public abstract class ResourceDirectoryEntry { private ResourceName name; public ResourceName Name { get { return name; } set { name = value; } } protected ResourceDirectoryEntry(ResourceName name) { this.name = name; } public override string ToString() { return name.ToString(); } } public readonly struct ResourceName : IComparable, IEquatable { private readonly int id; private readonly string name; public bool HasId => name == null; public bool HasName => name != null; public int Id => id; public string Name => name; public ResourceName(int id) { this.id = id; name = null; } public ResourceName(string name) { id = 0; this.name = name; } public static implicit operator ResourceName(int id) { return new ResourceName(id); } public static implicit operator ResourceName(string name) { return new ResourceName(name); } public static bool operator <(ResourceName left, ResourceName right) { return left.CompareTo(right) < 0; } public static bool operator <=(ResourceName left, ResourceName right) { return left.CompareTo(right) <= 0; } public static bool operator >(ResourceName left, ResourceName right) { return left.CompareTo(right) > 0; } public static bool operator >=(ResourceName left, ResourceName right) { return left.CompareTo(right) >= 0; } public static bool operator ==(ResourceName left, ResourceName right) { return left.Equals(right); } public static bool operator !=(ResourceName left, ResourceName right) { return !left.Equals(right); } public int CompareTo(ResourceName other) { if (HasId != other.HasId) { if (!HasName) { return 1; } return -1; } if (HasId) { return id.CompareTo(other.id); } return name.ToUpperInvariant().CompareTo(other.name.ToUpperInvariant()); } public bool Equals(ResourceName other) { return CompareTo(other) == 0; } public override bool Equals(object obj) { if (!(obj is ResourceName)) { return false; } return Equals((ResourceName)obj); } public override int GetHashCode() { if (HasId) { return id; } return name.GetHashCode(); } public override string ToString() { if (!HasId) { return name; } return id.ToString(); } } public abstract class Win32Resources : IDisposable { public abstract ResourceDirectory Root { get; set; } public ResourceDirectory Find(ResourceName type) { return Root?.FindDirectory(type); } public ResourceDirectory Find(ResourceName type, ResourceName name) { return Find(type)?.FindDirectory(name); } public ResourceData Find(ResourceName type, ResourceName name, ResourceName langId) { return Find(type, name)?.FindData(langId); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { Root = null; } } } public class Win32ResourcesUser : Win32Resources { private ResourceDirectory root = new ResourceDirectoryUser(new ResourceName("root")); public override ResourceDirectory Root { get { return root; } set { Interlocked.Exchange(ref root, value); } } } public sealed class Win32ResourcesPE : Win32Resources { private readonly IRvaFileOffsetConverter rvaConverter; private DataReaderFactory dataReader_factory; private uint dataReader_offset; private uint dataReader_length; private bool owns_dataReader_factory; private DataReaderFactory rsrcReader_factory; private uint rsrcReader_offset; private uint rsrcReader_length; private bool owns_rsrcReader_factory; private UserValue root; private readonly Lock theLock = Lock.Create(); public override ResourceDirectory Root { get { return root.Value; } set { if (!root.IsValueInitialized || root.Value != value) { root.Value = value; } } } internal DataReader GetResourceReader() { return rsrcReader_factory.CreateReader(rsrcReader_offset, rsrcReader_length); } public Win32ResourcesPE(IRvaFileOffsetConverter rvaConverter, DataReaderFactory rsrcReader_factory, uint rsrcReader_offset, uint rsrcReader_length, bool owns_rsrcReader_factory, DataReaderFactory dataReader_factory, uint dataReader_offset, uint dataReader_length, bool owns_dataReader_factory) { this.rvaConverter = rvaConverter ?? throw new ArgumentNullException("rvaConverter"); this.rsrcReader_factory = rsrcReader_factory ?? throw new ArgumentNullException("rsrcReader_factory"); this.rsrcReader_offset = rsrcReader_offset; this.rsrcReader_length = rsrcReader_length; this.owns_rsrcReader_factory = owns_rsrcReader_factory; this.dataReader_factory = dataReader_factory ?? throw new ArgumentNullException("dataReader_factory"); this.dataReader_offset = dataReader_offset; this.dataReader_length = dataReader_length; this.owns_dataReader_factory = owns_dataReader_factory; Initialize(); } public Win32ResourcesPE(IPEImage peImage) : this(peImage, null, 0u, 0u, owns_rsrcReader_factory: false) { } public Win32ResourcesPE(IPEImage peImage, DataReaderFactory rsrcReader_factory, uint rsrcReader_offset, uint rsrcReader_length, bool owns_rsrcReader_factory) { rvaConverter = peImage ?? throw new ArgumentNullException("peImage"); dataReader_factory = peImage.DataReaderFactory; dataReader_offset = 0u; dataReader_length = dataReader_factory.Length; if (rsrcReader_factory != null) { this.rsrcReader_factory = rsrcReader_factory; this.rsrcReader_offset = rsrcReader_offset; this.rsrcReader_length = rsrcReader_length; this.owns_rsrcReader_factory = owns_rsrcReader_factory; } else { ImageDataDirectory imageDataDirectory = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[2]; if (imageDataDirectory.VirtualAddress != 0 && imageDataDirectory.Size != 0) { DataReader dataReader = peImage.CreateReader(imageDataDirectory.VirtualAddress, imageDataDirectory.Size); this.rsrcReader_factory = peImage.DataReaderFactory; this.rsrcReader_offset = dataReader.StartOffset; this.rsrcReader_length = dataReader.Length; } else { this.rsrcReader_factory = ByteArrayDataReaderFactory.Create(Array2.Empty(), null); this.rsrcReader_offset = 0u; this.rsrcReader_length = 0u; } } Initialize(); } private void Initialize() { root.ReadOriginalValue = delegate { DataReaderFactory dataReaderFactory = rsrcReader_factory; if (dataReaderFactory == null) { return (ResourceDirectory)null; } DataReader reader = dataReaderFactory.CreateReader(rsrcReader_offset, rsrcReader_length); return new ResourceDirectoryPE(0u, new ResourceName("root"), this, ref reader); }; root.Lock = theLock; } public DataReader CreateReader(RVA rva, uint size) { GetDataReaderInfo(rva, size, out var dataReaderFactory, out var dataOffset, out var dataLength); return dataReaderFactory.CreateReader(dataOffset, dataLength); } internal void GetDataReaderInfo(RVA rva, uint size, out DataReaderFactory dataReaderFactory, out uint dataOffset, out uint dataLength) { dataOffset = (uint)rvaConverter.ToFileOffset(rva); if ((ulong)((long)dataOffset + (long)size) <= (ulong)dataReader_factory.Length) { dataReaderFactory = dataReader_factory; dataLength = size; } else { dataReaderFactory = ByteArrayDataReaderFactory.Create(Array2.Empty(), null); dataOffset = 0u; dataLength = 0u; } } protected override void Dispose(bool disposing) { if (disposing) { if (owns_dataReader_factory) { dataReader_factory?.Dispose(); } if (owns_rsrcReader_factory) { rsrcReader_factory?.Dispose(); } dataReader_factory = null; rsrcReader_factory = null; base.Dispose(disposing); } } } } namespace dnlib.Utils { internal class CollectionDebugView { private readonly ICollection list; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public TValue[] Items { get { TValue[] array = new TValue[list.Count]; list.CopyTo(array, 0); return array; } } public CollectionDebugView(ICollection list) { this.list = list ?? throw new ArgumentNullException("list"); } } internal class CollectionDebugView : CollectionDebugView { public CollectionDebugView(ICollection list) : base(list) { } } internal sealed class LocalList_CollectionDebugView : CollectionDebugView { public LocalList_CollectionDebugView(LocalList list) : base((ICollection)list) { } } internal sealed class ParameterList_CollectionDebugView : CollectionDebugView { public ParameterList_CollectionDebugView(ParameterList list) : base((ICollection)list) { } } internal interface ILazyList : IList, ICollection, IEnumerable, IEnumerable { } public interface IListListener { void OnLazyAdd(int index, ref TListValue value); void OnAdd(int index, TListValue value); void OnRemove(int index, TListValue value); void OnResize(int index); void OnClear(); } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(CollectionDebugView<>))] public class LazyList : ILazyList, IList, ICollection, IEnumerable, IEnumerable where TValue : class { private protected class Element { protected TValue value; public virtual bool IsInitialized_NoLock => true; protected Element() { } public Element(TValue data) { value = data; } public virtual TValue GetValue_NoLock(int index) { return value; } public virtual void SetValue_NoLock(int index, TValue value) { this.value = value; } public override string ToString() { return value?.ToString() ?? string.Empty; } } public struct Enumerator : IEnumerator, IEnumerator, IDisposable { private readonly LazyList list; private readonly int id; private int index; private TValue current; public TValue Current => current; object IEnumerator.Current => current; internal Enumerator(LazyList list) { this.list = list; index = 0; current = null; list.theLock.EnterReadLock(); try { id = list.id; } finally { list.theLock.ExitReadLock(); } } public bool MoveNext() { list.theLock.EnterWriteLock(); try { if (list.id == id && index < list.Count_NoLock) { current = list.list[index].GetValue_NoLock(index); index++; return true; } return MoveNextDoneOrThrow_NoLock(); } finally { list.theLock.ExitWriteLock(); } } private bool MoveNextDoneOrThrow_NoLock() { if (list.id != id) { throw new InvalidOperationException("List was modified"); } current = null; return false; } public void Dispose() { } void IEnumerator.Reset() { throw new NotSupportedException(); } } private protected readonly List list; private int id; private protected readonly IListListener listener; private readonly Lock theLock = Lock.Create(); public int Count { get { theLock.EnterReadLock(); try { return Count_NoLock; } finally { theLock.ExitReadLock(); } } } internal int Count_NoLock => list.Count; public bool IsReadOnly => false; public TValue this[int index] { get { theLock.EnterWriteLock(); try { return Get_NoLock(index); } finally { theLock.ExitWriteLock(); } } set { theLock.EnterWriteLock(); try { Set_NoLock(index, value); } finally { theLock.ExitWriteLock(); } } } internal TValue Get_NoLock(int index) { return list[index].GetValue_NoLock(index); } private void Set_NoLock(int index, TValue value) { if (listener != null) { listener.OnRemove(index, list[index].GetValue_NoLock(index)); listener.OnAdd(index, value); } list[index].SetValue_NoLock(index, value); id++; } public LazyList() : this((IListListener)null) { } public LazyList(IListListener listener) { this.listener = listener; list = new List(); } private protected LazyList(int length, IListListener listener) { this.listener = listener; list = new List(length); } public int IndexOf(TValue item) { theLock.EnterWriteLock(); try { return IndexOf_NoLock(item); } finally { theLock.ExitWriteLock(); } } private int IndexOf_NoLock(TValue item) { for (int i = 0; i < list.Count; i++) { if (list[i].GetValue_NoLock(i) == item) { return i; } } return -1; } public void Insert(int index, TValue item) { theLock.EnterWriteLock(); try { Insert_NoLock(index, item); } finally { theLock.ExitWriteLock(); } } private void Insert_NoLock(int index, TValue item) { if (listener != null) { listener.OnAdd(index, item); } list.Insert(index, new Element(item)); if (listener != null) { listener.OnResize(index); } id++; } public void RemoveAt(int index) { theLock.EnterWriteLock(); try { RemoveAt_NoLock(index); } finally { theLock.ExitWriteLock(); } } private void RemoveAt_NoLock(int index) { if (listener != null) { listener.OnRemove(index, list[index].GetValue_NoLock(index)); } list.RemoveAt(index); if (listener != null) { listener.OnResize(index); } id++; } public void Add(TValue item) { theLock.EnterWriteLock(); try { Add_NoLock(item); } finally { theLock.ExitWriteLock(); } } private void Add_NoLock(TValue item) { int count = list.Count; if (listener != null) { listener.OnAdd(count, item); } list.Add(new Element(item)); if (listener != null) { listener.OnResize(count); } id++; } public void Clear() { theLock.EnterWriteLock(); try { Clear_NoLock(); } finally { theLock.ExitWriteLock(); } } private void Clear_NoLock() { if (listener != null) { listener.OnClear(); } list.Clear(); if (listener != null) { listener.OnResize(0); } id++; } public bool Contains(TValue item) { return IndexOf(item) >= 0; } public void CopyTo(TValue[] array, int arrayIndex) { theLock.EnterWriteLock(); try { CopyTo_NoLock(array, arrayIndex); } finally { theLock.ExitWriteLock(); } } private void CopyTo_NoLock(TValue[] array, int arrayIndex) { for (int i = 0; i < list.Count; i++) { array[arrayIndex + i] = list[i].GetValue_NoLock(i); } } public bool Remove(TValue item) { theLock.EnterWriteLock(); try { return Remove_NoLock(item); } finally { theLock.ExitWriteLock(); } } private bool Remove_NoLock(TValue item) { int num = IndexOf_NoLock(item); if (num < 0) { return false; } RemoveAt_NoLock(num); return true; } internal bool IsInitialized(int index) { theLock.EnterReadLock(); try { return IsInitialized_NoLock(index); } finally { theLock.ExitReadLock(); } } private bool IsInitialized_NoLock(int index) { if ((uint)index >= (uint)list.Count) { return false; } return list[index].IsInitialized_NoLock; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } internal IEnumerable GetEnumerable_NoLock() { int id2 = id; for (int i = 0; i < list.Count; i++) { if (id != id2) { throw new InvalidOperationException("List was modified"); } yield return list[i].GetValue_NoLock(i); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(CollectionDebugView<, >))] public class LazyList : LazyList, ILazyList, IList, ICollection, IEnumerable, IEnumerable where TValue : class { private sealed class LazyElement : Element { internal readonly int origIndex; private LazyList lazyList; public override bool IsInitialized_NoLock => lazyList == null; public override TValue GetValue_NoLock(int index) { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(index, origIndex); lazyList = null; } return value; } public override void SetValue_NoLock(int index, TValue value) { base.value = value; lazyList = null; } public LazyElement(int origIndex, LazyList lazyList) { this.origIndex = origIndex; this.lazyList = lazyList; } public override string ToString() { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(this); lazyList = null; } if (value != null) { return value.ToString(); } return string.Empty; } } private TContext context; private readonly Func readOriginalValue; public LazyList() : this((IListListener)null) { } public LazyList(IListListener listener) : base(listener) { } public LazyList(int length, TContext context, Func readOriginalValue) : this(length, (IListListener)null, context, readOriginalValue) { } public LazyList(int length, IListListener listener, TContext context, Func readOriginalValue) : base(length, listener) { this.context = context; this.readOriginalValue = readOriginalValue; for (int i = 0; i < length; i++) { list.Add(new LazyElement(i, this)); } } private TValue ReadOriginalValue_NoLock(LazyElement elem) { return ReadOriginalValue_NoLock(list.IndexOf(elem), elem.origIndex); } private TValue ReadOriginalValue_NoLock(int index, int origIndex) { TValue value = readOriginalValue(context, origIndex); listener?.OnLazyAdd(index, ref value); return value; } } [DebuggerDisplay("Count = {Length}")] internal sealed class SimpleLazyList where T : class { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] private readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Func readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly uint length; public uint Length => length; public T this[uint index] { get { if (index >= length) { return null; } if (elements[index] == null) { Interlocked.CompareExchange(ref elements[index], readElementByRID(index + 1), null); } return elements[index]; } } public SimpleLazyList(uint length, Func readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; elements = new T[length]; } } [DebuggerDisplay("Count = {Length}")] internal sealed class SimpleLazyList2 where T : class, IContainsGenericParameter2 { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] private readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Func readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly uint length; public uint Length => length; public T this[uint index, GenericParamContext gpContext] { get { if (index >= length) { return null; } if (elements[index] == null) { T val = readElementByRID(index + 1, gpContext); if (val.ContainsGenericParameter) { return val; } Interlocked.CompareExchange(ref elements[index], val, null); } return elements[index]; } } public SimpleLazyList2(uint length, Func readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; elements = new T[length]; } } [DebuggerDisplay("{value}")] internal struct UserValue { private Lock theLock; private Func readOriginalValue; private TValue value; private bool isUserValue; private bool isValueInitialized; public Lock Lock { set { theLock = value; } } public Func ReadOriginalValue { set { readOriginalValue = value; } } public TValue Value { get { theLock?.EnterWriteLock(); try { if (!isValueInitialized) { value = readOriginalValue(); readOriginalValue = null; isValueInitialized = true; } return value; } finally { theLock?.ExitWriteLock(); } } set { theLock?.EnterWriteLock(); try { this.value = value; readOriginalValue = null; isUserValue = true; isValueInitialized = true; } finally { theLock?.ExitWriteLock(); } } } public bool IsValueInitialized { get { theLock?.EnterReadLock(); try { return isValueInitialized; } finally { theLock?.ExitReadLock(); } } } public bool IsUserValue { get { theLock?.EnterReadLock(); try { return isUserValue; } finally { theLock?.ExitReadLock(); } } } } } namespace dnlib.Threading { public interface ICancellationToken { void ThrowIfCancellationRequested(); } [Serializable] internal class LockException : Exception { public LockException() { } public LockException(string msg) : base(msg) { } protected LockException(SerializationInfo info, StreamingContext context) : base(info, context) { } } internal class Lock { private readonly object lockObj; private int recurseCount; public static Lock Create() { return new Lock(); } private Lock() { lockObj = new object(); recurseCount = 0; } public void EnterReadLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount++; } public void ExitReadLock() { if (recurseCount <= 0) { throw new LockException("Too many exit lock method calls"); } recurseCount--; Monitor.Exit(lockObj); } public void EnterWriteLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount--; } public void ExitWriteLock() { if (recurseCount >= 0) { throw new LockException("Too many exit lock method calls"); } recurseCount++; Monitor.Exit(lockObj); } } } namespace dnlib.PE { [Flags] public enum Characteristics : ushort { RelocsStripped = 1, ExecutableImage = 2, LineNumsStripped = 4, LocalSymsStripped = 8, AggressiveWsTrim = 0x10, LargeAddressAware = 0x20, Reserved1 = 0x40, BytesReversedLo = 0x80, Bit32Machine = 0x100, DebugStripped = 0x200, RemovableRunFromSwap = 0x400, NetRunFromSwap = 0x800, System = 0x1000, Dll = 0x2000, UpSystemOnly = 0x4000, BytesReversedHi = 0x8000 } [Flags] public enum DllCharacteristics : ushort { Reserved1 = 1, Reserved2 = 2, Reserved3 = 4, Reserved4 = 8, Reserved5 = 0x10, HighEntropyVA = 0x20, DynamicBase = 0x40, ForceIntegrity = 0x80, NxCompat = 0x100, NoIsolation = 0x200, NoSeh = 0x400, NoBind = 0x800, AppContainer = 0x1000, WdmDriver = 0x2000, GuardCf = 0x4000, TerminalServerAware = 0x8000 } public interface IImageOptionalHeader : IFileSection { ushort Magic { get; } byte MajorLinkerVersion { get; } byte MinorLinkerVersion { get; } uint SizeOfCode { get; } uint SizeOfInitializedData { get; } uint SizeOfUninitializedData { get; } RVA AddressOfEntryPoint { get; } RVA BaseOfCode { get; } RVA BaseOfData { get; } ulong ImageBase { get; } uint SectionAlignment { get; } uint FileAlignment { get; } ushort MajorOperatingSystemVersion { get; } ushort MinorOperatingSystemVersion { get; } ushort MajorImageVersion { get; } ushort MinorImageVersion { get; } ushort MajorSubsystemVersion { get; } ushort MinorSubsystemVersion { get; } uint Win32VersionValue { get; } uint SizeOfImage { get; } uint SizeOfHeaders { get; } uint CheckSum { get; } Subsystem Subsystem { get; } DllCharacteristics DllCharacteristics { get; } ulong SizeOfStackReserve { get; } ulong SizeOfStackCommit { get; } ulong SizeOfHeapReserve { get; } ulong SizeOfHeapCommit { get; } uint LoaderFlags { get; } uint NumberOfRvaAndSizes { get; } ImageDataDirectory[] DataDirectories { get; } } [DebuggerDisplay("{virtualAddress} {dataSize}")] public sealed class ImageDataDirectory : FileSection { private readonly RVA virtualAddress; private readonly uint dataSize; public RVA VirtualAddress => virtualAddress; public uint Size => dataSize; public ImageDataDirectory() { } public ImageDataDirectory(ref DataReader reader, bool verify) { SetStartOffset(ref reader); virtualAddress = (RVA)reader.ReadUInt32(); dataSize = reader.ReadUInt32(); SetEndoffset(ref reader); } } [DebuggerDisplay("{type}: TS:{timeDateStamp,h} V:{majorVersion,d}.{minorVersion,d} SZ:{sizeOfData} RVA:{addressOfRawData,h} FO:{pointerToRawData,h}")] public sealed class ImageDebugDirectory : FileSection { private readonly uint characteristics; private readonly uint timeDateStamp; private readonly ushort majorVersion; private readonly ushort minorVersion; private readonly ImageDebugType type; private readonly uint sizeOfData; private readonly uint addressOfRawData; private readonly uint pointerToRawData; public uint Characteristics => characteristics; public uint TimeDateStamp => timeDateStamp; public ushort MajorVersion => majorVersion; public ushort MinorVersion => minorVersion; public ImageDebugType Type => type; public uint SizeOfData => sizeOfData; public RVA AddressOfRawData => (RVA)addressOfRawData; public FileOffset PointerToRawData => (FileOffset)pointerToRawData; public ImageDebugDirectory(ref DataReader reader, bool verify) { SetStartOffset(ref reader); characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); type = (ImageDebugType)reader.ReadUInt32(); sizeOfData = reader.ReadUInt32(); addressOfRawData = reader.ReadUInt32(); pointerToRawData = reader.ReadUInt32(); SetEndoffset(ref reader); } } public enum ImageDebugType : uint { Unknown = 0u, Coff = 1u, CodeView = 2u, FPO = 3u, Misc = 4u, Exception = 5u, Fixup = 6u, OmapToSrc = 7u, OmapFromSrc = 8u, Borland = 9u, Reserved10 = 10u, CLSID = 11u, VcFeature = 12u, POGO = 13u, ILTCG = 14u, MPX = 15u, Reproducible = 16u, EmbeddedPortablePdb = 17u, PdbChecksum = 19u } public sealed class ImageDosHeader : FileSection { private readonly uint ntHeadersOffset; public uint NTHeadersOffset => ntHeadersOffset; public ImageDosHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); ushort num = reader.ReadUInt16(); if (verify && num != 23117) { throw new BadImageFormatException("Invalid DOS signature"); } reader.Position = (uint)(startOffset + 60); ntHeadersOffset = reader.ReadUInt32(); SetEndoffset(ref reader); } } public sealed class ImageFileHeader : FileSection { private readonly Machine machine; private readonly ushort numberOfSections; private readonly uint timeDateStamp; private readonly uint pointerToSymbolTable; private readonly uint numberOfSymbols; private readonly ushort sizeOfOptionalHeader; private readonly Characteristics characteristics; public Machine Machine => machine; public int NumberOfSections => numberOfSections; public uint TimeDateStamp => timeDateStamp; public uint PointerToSymbolTable => pointerToSymbolTable; public uint NumberOfSymbols => numberOfSymbols; public uint SizeOfOptionalHeader => sizeOfOptionalHeader; public Characteristics Characteristics => characteristics; public ImageFileHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); machine = (Machine)reader.ReadUInt16(); numberOfSections = reader.ReadUInt16(); timeDateStamp = reader.ReadUInt32(); pointerToSymbolTable = reader.ReadUInt32(); numberOfSymbols = reader.ReadUInt32(); sizeOfOptionalHeader = reader.ReadUInt16(); characteristics = (Characteristics)reader.ReadUInt16(); SetEndoffset(ref reader); if (verify && sizeOfOptionalHeader == 0) { throw new BadImageFormatException("Invalid SizeOfOptionalHeader"); } } } public sealed class ImageNTHeaders : FileSection { private readonly uint signature; private readonly ImageFileHeader imageFileHeader; private readonly IImageOptionalHeader imageOptionalHeader; public uint Signature => signature; public ImageFileHeader FileHeader => imageFileHeader; public IImageOptionalHeader OptionalHeader => imageOptionalHeader; public ImageNTHeaders(ref DataReader reader, bool verify) { SetStartOffset(ref reader); signature = reader.ReadUInt32(); if (verify && (ushort)signature != 17744) { throw new BadImageFormatException("Invalid NT headers signature"); } imageFileHeader = new ImageFileHeader(ref reader, verify); imageOptionalHeader = CreateImageOptionalHeader(ref reader, verify); SetEndoffset(ref reader); } private IImageOptionalHeader CreateImageOptionalHeader(ref DataReader reader, bool verify) { ushort num = reader.ReadUInt16(); reader.Position -= 2u; return num switch { 267 => new ImageOptionalHeader32(ref reader, imageFileHeader.SizeOfOptionalHeader, verify), 523 => new ImageOptionalHeader64(ref reader, imageFileHeader.SizeOfOptionalHeader, verify), _ => throw new BadImageFormatException("Invalid optional header magic"), }; } } public sealed class ImageOptionalHeader32 : FileSection, IImageOptionalHeader, IFileSection { private readonly ushort magic; private readonly byte majorLinkerVersion; private readonly byte minorLinkerVersion; private readonly uint sizeOfCode; private readonly uint sizeOfInitializedData; private readonly uint sizeOfUninitializedData; private readonly RVA addressOfEntryPoint; private readonly RVA baseOfCode; private readonly RVA baseOfData; private readonly uint imageBase; private readonly uint sectionAlignment; private readonly uint fileAlignment; private readonly ushort majorOperatingSystemVersion; private readonly ushort minorOperatingSystemVersion; private readonly ushort majorImageVersion; private readonly ushort minorImageVersion; private readonly ushort majorSubsystemVersion; private readonly ushort minorSubsystemVersion; private readonly uint win32VersionValue; private readonly uint sizeOfImage; private readonly uint sizeOfHeaders; private readonly uint checkSum; private readonly Subsystem subsystem; private readonly DllCharacteristics dllCharacteristics; private readonly uint sizeOfStackReserve; private readonly uint sizeOfStackCommit; private readonly uint sizeOfHeapReserve; private readonly uint sizeOfHeapCommit; private readonly uint loaderFlags; private readonly uint numberOfRvaAndSizes; private readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; public ushort Magic => magic; public byte MajorLinkerVersion => majorLinkerVersion; public byte MinorLinkerVersion => minorLinkerVersion; public uint SizeOfCode => sizeOfCode; public uint SizeOfInitializedData => sizeOfInitializedData; public uint SizeOfUninitializedData => sizeOfUninitializedData; public RVA AddressOfEntryPoint => addressOfEntryPoint; public RVA BaseOfCode => baseOfCode; public RVA BaseOfData => baseOfData; public ulong ImageBase => imageBase; public uint SectionAlignment => sectionAlignment; public uint FileAlignment => fileAlignment; public ushort MajorOperatingSystemVersion => majorOperatingSystemVersion; public ushort MinorOperatingSystemVersion => minorOperatingSystemVersion; public ushort MajorImageVersion => majorImageVersion; public ushort MinorImageVersion => minorImageVersion; public ushort MajorSubsystemVersion => majorSubsystemVersion; public ushort MinorSubsystemVersion => minorSubsystemVersion; public uint Win32VersionValue => win32VersionValue; public uint SizeOfImage => sizeOfImage; public uint SizeOfHeaders => sizeOfHeaders; public uint CheckSum => checkSum; public Subsystem Subsystem => subsystem; public DllCharacteristics DllCharacteristics => dllCharacteristics; public ulong SizeOfStackReserve => sizeOfStackReserve; public ulong SizeOfStackCommit => sizeOfStackCommit; public ulong SizeOfHeapReserve => sizeOfHeapReserve; public ulong SizeOfHeapCommit => sizeOfHeapCommit; public uint LoaderFlags => loaderFlags; public uint NumberOfRvaAndSizes => numberOfRvaAndSizes; public ImageDataDirectory[] DataDirectories => dataDirectories; public ImageOptionalHeader32(ref DataReader reader, uint totalSize, bool verify) { if (totalSize < 96) { throw new BadImageFormatException("Invalid optional header size"); } if (verify && (ulong)((long)reader.Position + (long)totalSize) > (ulong)reader.Length) { throw new BadImageFormatException("Invalid optional header size"); } SetStartOffset(ref reader); magic = reader.ReadUInt16(); majorLinkerVersion = reader.ReadByte(); minorLinkerVersion = reader.ReadByte(); sizeOfCode = reader.ReadUInt32(); sizeOfInitializedData = reader.ReadUInt32(); sizeOfUninitializedData = reader.ReadUInt32(); addressOfEntryPoint = (RVA)reader.ReadUInt32(); baseOfCode = (RVA)reader.ReadUInt32(); baseOfData = (RVA)reader.ReadUInt32(); imageBase = reader.ReadUInt32(); sectionAlignment = reader.ReadUInt32(); fileAlignment = reader.ReadUInt32(); majorOperatingSystemVersion = reader.ReadUInt16(); minorOperatingSystemVersion = reader.ReadUInt16(); majorImageVersion = reader.ReadUInt16(); minorImageVersion = reader.ReadUInt16(); majorSubsystemVersion = reader.ReadUInt16(); minorSubsystemVersion = reader.ReadUInt16(); win32VersionValue = reader.ReadUInt32(); sizeOfImage = reader.ReadUInt32(); sizeOfHeaders = reader.ReadUInt32(); checkSum = reader.ReadUInt32(); subsystem = (Subsystem)reader.ReadUInt16(); dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); sizeOfStackReserve = reader.ReadUInt32(); sizeOfStackCommit = reader.ReadUInt32(); sizeOfHeapReserve = reader.ReadUInt32(); sizeOfHeapCommit = reader.ReadUInt32(); loaderFlags = reader.ReadUInt32(); numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { if ((uint)(reader.Position - startOffset + 8) <= totalSize) { dataDirectories[i] = new ImageDataDirectory(ref reader, verify); } else { dataDirectories[i] = new ImageDataDirectory(); } } reader.Position = (uint)(startOffset + totalSize); SetEndoffset(ref reader); } } public sealed class ImageOptionalHeader64 : FileSection, IImageOptionalHeader, IFileSection { private readonly ushort magic; private readonly byte majorLinkerVersion; private readonly byte minorLinkerVersion; private readonly uint sizeOfCode; private readonly uint sizeOfInitializedData; private readonly uint sizeOfUninitializedData; private readonly RVA addressOfEntryPoint; private readonly RVA baseOfCode; private readonly ulong imageBase; private readonly uint sectionAlignment; private readonly uint fileAlignment; private readonly ushort majorOperatingSystemVersion; private readonly ushort minorOperatingSystemVersion; private readonly ushort majorImageVersion; private readonly ushort minorImageVersion; private readonly ushort majorSubsystemVersion; private readonly ushort minorSubsystemVersion; private readonly uint win32VersionValue; private readonly uint sizeOfImage; private readonly uint sizeOfHeaders; private readonly uint checkSum; private readonly Subsystem subsystem; private readonly DllCharacteristics dllCharacteristics; private readonly ulong sizeOfStackReserve; private readonly ulong sizeOfStackCommit; private readonly ulong sizeOfHeapReserve; private readonly ulong sizeOfHeapCommit; private readonly uint loaderFlags; private readonly uint numberOfRvaAndSizes; private readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; public ushort Magic => magic; public byte MajorLinkerVersion => majorLinkerVersion; public byte MinorLinkerVersion => minorLinkerVersion; public uint SizeOfCode => sizeOfCode; public uint SizeOfInitializedData => sizeOfInitializedData; public uint SizeOfUninitializedData => sizeOfUninitializedData; public RVA AddressOfEntryPoint => addressOfEntryPoint; public RVA BaseOfCode => baseOfCode; public RVA BaseOfData => (RVA)0u; public ulong ImageBase => imageBase; public uint SectionAlignment => sectionAlignment; public uint FileAlignment => fileAlignment; public ushort MajorOperatingSystemVersion => majorOperatingSystemVersion; public ushort MinorOperatingSystemVersion => minorOperatingSystemVersion; public ushort MajorImageVersion => majorImageVersion; public ushort MinorImageVersion => minorImageVersion; public ushort MajorSubsystemVersion => majorSubsystemVersion; public ushort MinorSubsystemVersion => minorSubsystemVersion; public uint Win32VersionValue => win32VersionValue; public uint SizeOfImage => sizeOfImage; public uint SizeOfHeaders => sizeOfHeaders; public uint CheckSum => checkSum; public Subsystem Subsystem => subsystem; public DllCharacteristics DllCharacteristics => dllCharacteristics; public ulong SizeOfStackReserve => sizeOfStackReserve; public ulong SizeOfStackCommit => sizeOfStackCommit; public ulong SizeOfHeapReserve => sizeOfHeapReserve; public ulong SizeOfHeapCommit => sizeOfHeapCommit; public uint LoaderFlags => loaderFlags; public uint NumberOfRvaAndSizes => numberOfRvaAndSizes; public ImageDataDirectory[] DataDirectories => dataDirectories; public ImageOptionalHeader64(ref DataReader reader, uint totalSize, bool verify) { if (totalSize < 112) { throw new BadImageFormatException("Invalid optional header size"); } if (verify && (ulong)((long)reader.Position + (long)totalSize) > (ulong)reader.Length) { throw new BadImageFormatException("Invalid optional header size"); } SetStartOffset(ref reader); magic = reader.ReadUInt16(); majorLinkerVersion = reader.ReadByte(); minorLinkerVersion = reader.ReadByte(); sizeOfCode = reader.ReadUInt32(); sizeOfInitializedData = reader.ReadUInt32(); sizeOfUninitializedData = reader.ReadUInt32(); addressOfEntryPoint = (RVA)reader.ReadUInt32(); baseOfCode = (RVA)reader.ReadUInt32(); imageBase = reader.ReadUInt64(); sectionAlignment = reader.ReadUInt32(); fileAlignment = reader.ReadUInt32(); majorOperatingSystemVersion = reader.ReadUInt16(); minorOperatingSystemVersion = reader.ReadUInt16(); majorImageVersion = reader.ReadUInt16(); minorImageVersion = reader.ReadUInt16(); majorSubsystemVersion = reader.ReadUInt16(); minorSubsystemVersion = reader.ReadUInt16(); win32VersionValue = reader.ReadUInt32(); sizeOfImage = reader.ReadUInt32(); sizeOfHeaders = reader.ReadUInt32(); checkSum = reader.ReadUInt32(); subsystem = (Subsystem)reader.ReadUInt16(); dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); sizeOfStackReserve = reader.ReadUInt64(); sizeOfStackCommit = reader.ReadUInt64(); sizeOfHeapReserve = reader.ReadUInt64(); sizeOfHeapCommit = reader.ReadUInt64(); loaderFlags = reader.ReadUInt32(); numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { if ((uint)(reader.Position - startOffset + 8) <= totalSize) { dataDirectories[i] = new ImageDataDirectory(ref reader, verify); } else { dataDirectories[i] = new ImageDataDirectory(); } } reader.Position = (uint)(startOffset + totalSize); SetEndoffset(ref reader); } } [DebuggerDisplay("RVA:{virtualAddress} VS:{virtualSize} FO:{pointerToRawData} FS:{sizeOfRawData} {displayName}")] public sealed class ImageSectionHeader : FileSection { private readonly string displayName; private readonly byte[] name; private readonly uint virtualSize; private readonly RVA virtualAddress; private readonly uint sizeOfRawData; private readonly uint pointerToRawData; private readonly uint pointerToRelocations; private readonly uint pointerToLinenumbers; private readonly ushort numberOfRelocations; private readonly ushort numberOfLinenumbers; private readonly uint characteristics; public string DisplayName => displayName; public byte[] Name => name; public uint VirtualSize => virtualSize; public RVA VirtualAddress => virtualAddress; public uint SizeOfRawData => sizeOfRawData; public uint PointerToRawData => pointerToRawData; public uint PointerToRelocations => pointerToRelocations; public uint PointerToLinenumbers => pointerToLinenumbers; public ushort NumberOfRelocations => numberOfRelocations; public ushort NumberOfLinenumbers => numberOfLinenumbers; public uint Characteristics => characteristics; public ImageSectionHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); name = reader.ReadBytes(8); virtualSize = reader.ReadUInt32(); virtualAddress = (RVA)reader.ReadUInt32(); sizeOfRawData = reader.ReadUInt32(); pointerToRawData = reader.ReadUInt32(); pointerToRelocations = reader.ReadUInt32(); pointerToLinenumbers = reader.ReadUInt32(); numberOfRelocations = reader.ReadUInt16(); numberOfLinenumbers = reader.ReadUInt16(); characteristics = reader.ReadUInt32(); SetEndoffset(ref reader); displayName = ToString(name); } private static string ToString(byte[] name) { StringBuilder stringBuilder = new StringBuilder(name.Length); foreach (byte b in name) { if (b == 0) { break; } stringBuilder.Append((char)b); } return stringBuilder.ToString(); } } public interface IRvaFileOffsetConverter { RVA ToRVA(FileOffset offset); FileOffset ToFileOffset(RVA rva); } public interface IPEImage : IRvaFileOffsetConverter, IDisposable { bool IsFileImageLayout { get; } bool MayHaveInvalidAddresses { get; } string Filename { get; } ImageDosHeader ImageDosHeader { get; } ImageNTHeaders ImageNTHeaders { get; } IList ImageSectionHeaders { get; } IList ImageDebugDirectories { get; } Win32Resources Win32Resources { get; set; } DataReaderFactory DataReaderFactory { get; } DataReader CreateReader(FileOffset offset); DataReader CreateReader(FileOffset offset, uint length); DataReader CreateReader(RVA rva); DataReader CreateReader(RVA rva, uint length); DataReader CreateReader(); } public interface IInternalPEImage : IPEImage, IRvaFileOffsetConverter, IDisposable { bool IsMemoryMappedIO { get; } void UnsafeDisableMemoryMappedIO(); } public static class PEExtensions { public static ResourceData FindWin32ResourceData(this IPEImage self, ResourceName type, ResourceName name, ResourceName langId) { return self.Win32Resources?.Find(type, name, langId); } internal static uint CalculatePECheckSum(this Stream stream, long length, long checkSumOffset) { if ((length & 1) != 0L) { ThrowInvalidOperationException("Invalid PE length"); } byte[] buffer = new byte[(int)Math.Min(length, 8192L)]; uint checkSum = 0u; checkSum = CalculatePECheckSum(stream, checkSumOffset, checkSum, buffer); stream.Position += 4L; checkSum = CalculatePECheckSum(stream, length - checkSumOffset - 4, checkSum, buffer); ulong num = (ulong)(checkSum + length); return (uint)((int)num + (int)(num >> 32)); } private static uint CalculatePECheckSum(Stream stream, long length, uint checkSum, byte[] buffer) { int num3; for (long num = 0L; num < length; num += num3) { int num2 = (int)Math.Min(length - num, buffer.Length); num3 = stream.Read(buffer, 0, num2); if (num3 != num2) { ThrowInvalidOperationException("Couldn't read all bytes"); } int num4 = 0; while (num4 < num3) { checkSum += (uint)(buffer[num4++] | (buffer[num4++] << 8)); checkSum = (ushort)(checkSum + (checkSum >> 16)); } } return checkSum; } private static void ThrowInvalidOperationException(string message) { throw new InvalidOperationException(message); } public static RVA AlignUp(this RVA rva, uint alignment) { return (RVA)((uint)(rva + alignment - 1) & ~(alignment - 1)); } public static RVA AlignUp(this RVA rva, int alignment) { return (RVA)(((long)rva + (long)alignment - 1) & ~(alignment - 1)); } } internal interface IPEType { RVA ToRVA(PEInfo peInfo, FileOffset offset); FileOffset ToFileOffset(PEInfo peInfo, RVA rva); } public enum Machine : ushort { Unknown = 0, I386 = 332, R3000 = 354, R4000 = 358, R10000 = 360, WCEMIPSV2 = 361, ALPHA = 388, SH3 = 418, SH3DSP = 419, SH3E = 420, SH4 = 422, SH5 = 424, ARM = 448, THUMB = 450, ARMNT = 452, AM33 = 467, POWERPC = 496, POWERPCFP = 497, IA64 = 512, MIPS16 = 614, ALPHA64 = 644, MIPSFPU = 870, MIPSFPU16 = 1126, TRICORE = 1312, CEF = 3311, EBC = 3772, AMD64 = 34404, M32R = 36929, ARM64 = 43620, CEE = 49390, I386_Native_Apple = 18184, AMD64_Native_Apple = 49184, ARMNT_Native_Apple = 18304, ARM64_Native_Apple = 60448, S390X_Native_Apple = 17988, I386_Native_FreeBSD = 44168, AMD64_Native_FreeBSD = 11168, ARMNT_Native_FreeBSD = 44032, ARM64_Native_FreeBSD = 1952, S390X_Native_FreeBSD = 44484, I386_Native_Linux = 31285, AMD64_Native_Linux = 64797, ARMNT_Native_Linux = 31421, ARM64_Native_Linux = 53533, S390X_Native_Linux = 31609, I386_Native_NetBSD = 6367, AMD64_Native_NetBSD = 40951, ARMNT_Native_NetBSD = 6231, ARM64_Native_NetBSD = 46071, S390X_Native_NetBSD = 6547, I386_Native_Sun = 6366, AMD64_Native_Sun = 40950, ARMNT_Native_Sun = 6230, ARM64_Native_Sun = 46070, S390X_Native_Sun = 6546 } public static class MachineExtensions { public static bool Is64Bit(this Machine machine) { switch (machine) { case Machine.IA64: case Machine.ARM64_Native_FreeBSD: case Machine.AMD64_Native_FreeBSD: case Machine.AMD64: case Machine.AMD64_Native_Sun: case Machine.AMD64_Native_NetBSD: case Machine.ARM64: case Machine.ARM64_Native_Sun: case Machine.ARM64_Native_NetBSD: case Machine.AMD64_Native_Apple: case Machine.ARM64_Native_Linux: case Machine.ARM64_Native_Apple: case Machine.AMD64_Native_Linux: return true; case Machine.S390X_Native_Sun: case Machine.S390X_Native_NetBSD: case Machine.S390X_Native_Apple: case Machine.S390X_Native_Linux: case Machine.S390X_Native_FreeBSD: return true; default: return false; } } public static bool IsI386(this Machine machine) { switch (machine) { case Machine.I386: case Machine.I386_Native_Sun: case Machine.I386_Native_NetBSD: case Machine.I386_Native_Apple: case Machine.I386_Native_Linux: case Machine.I386_Native_FreeBSD: return true; default: return false; } } public static bool IsAMD64(this Machine machine) { switch (machine) { case Machine.AMD64_Native_FreeBSD: case Machine.AMD64: case Machine.AMD64_Native_Sun: case Machine.AMD64_Native_NetBSD: case Machine.AMD64_Native_Apple: case Machine.AMD64_Native_Linux: return true; default: return false; } } public static bool IsARMNT(this Machine machine) { switch (machine) { case Machine.ARMNT: case Machine.ARMNT_Native_Sun: case Machine.ARMNT_Native_NetBSD: case Machine.ARMNT_Native_Apple: case Machine.ARMNT_Native_Linux: case Machine.ARMNT_Native_FreeBSD: return true; default: return false; } } public static bool IsARM64(this Machine machine) { switch (machine) { case Machine.ARM64_Native_FreeBSD: case Machine.ARM64: case Machine.ARM64_Native_Sun: case Machine.ARM64_Native_NetBSD: case Machine.ARM64_Native_Linux: case Machine.ARM64_Native_Apple: return true; default: return false; } } public static bool IsS390x(this Machine machine) { switch (machine) { case Machine.S390X_Native_Sun: case Machine.S390X_Native_NetBSD: case Machine.S390X_Native_Apple: case Machine.S390X_Native_Linux: case Machine.S390X_Native_FreeBSD: return true; default: return false; } } } public enum ImageLayout { File, Memory } public sealed class PEImage : IInternalPEImage, IPEImage, IRvaFileOffsetConverter, IDisposable { private sealed class FilePEType : IPEType { public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return peInfo.ToRVA(offset); } public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return peInfo.ToFileOffset(rva); } } private sealed class MemoryPEType : IPEType { public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return (RVA)offset; } public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return (FileOffset)rva; } } private const bool USE_MEMORY_LAYOUT_WITH_MAPPED_FILES = false; private static readonly IPEType MemoryLayout = new MemoryPEType(); private static readonly IPEType FileLayout = new FilePEType(); private DataReaderFactory dataReaderFactory; private IPEType peType; private PEInfo peInfo; private UserValue win32Resources; private readonly Lock theLock = Lock.Create(); private ImageDebugDirectory[] imageDebugDirectories; public bool IsFileImageLayout => peType is FilePEType; public bool MayHaveInvalidAddresses => !IsFileImageLayout; public string Filename => dataReaderFactory.Filename; public ImageDosHeader ImageDosHeader => peInfo.ImageDosHeader; public ImageNTHeaders ImageNTHeaders => peInfo.ImageNTHeaders; public IList ImageSectionHeaders => peInfo.ImageSectionHeaders; public IList ImageDebugDirectories { get { if (imageDebugDirectories == null) { imageDebugDirectories = ReadImageDebugDirectories(); } return imageDebugDirectories; } } public DataReaderFactory DataReaderFactory => dataReaderFactory; public Win32Resources Win32Resources { get { return win32Resources.Value; } set { IDisposable disposable = null; if (win32Resources.IsValueInitialized) { disposable = win32Resources.Value; if (disposable == value) { return; } } win32Resources.Value = value; disposable?.Dispose(); } } bool IInternalPEImage.IsMemoryMappedIO { get { if (dataReaderFactory is MemoryMappedDataReaderFactory memoryMappedDataReaderFactory) { return memoryMappedDataReaderFactory.IsMemoryMappedIO; } return false; } } public PEImage(DataReaderFactory dataReaderFactory, ImageLayout imageLayout, bool verify) { try { this.dataReaderFactory = dataReaderFactory; peType = ConvertImageLayout(imageLayout); DataReader reader = dataReaderFactory.CreateReader(); peInfo = new PEInfo(ref reader, verify); Initialize(); } catch { Dispose(); throw; } } private void Initialize() { win32Resources.ReadOriginalValue = delegate { ImageDataDirectory imageDataDirectory = peInfo.ImageNTHeaders.OptionalHeader.DataDirectories[2]; return (imageDataDirectory.VirtualAddress == (RVA)0u || imageDataDirectory.Size == 0) ? null : new Win32ResourcesPE(this); }; win32Resources.Lock = theLock; } private static IPEType ConvertImageLayout(ImageLayout imageLayout) { return imageLayout switch { ImageLayout.File => FileLayout, ImageLayout.Memory => MemoryLayout, _ => throw new ArgumentException("imageLayout"), }; } internal PEImage(string filename, bool mapAsImage, bool verify) : this(DataReaderFactoryFactory.Create(filename, mapAsImage), mapAsImage ? ImageLayout.Memory : ImageLayout.File, verify) { try { if (mapAsImage && dataReaderFactory is MemoryMappedDataReaderFactory) { ((MemoryMappedDataReaderFactory)dataReaderFactory).SetLength(peInfo.GetImageSize()); } } catch { Dispose(); throw; } } public PEImage(string filename, bool verify) : this(filename, mapAsImage: false, verify) { } public PEImage(string filename) : this(filename, verify: true) { } public PEImage(byte[] data, string filename, ImageLayout imageLayout, bool verify) : this(ByteArrayDataReaderFactory.Create(data, filename), imageLayout, verify) { } public PEImage(byte[] data, ImageLayout imageLayout, bool verify) : this(data, null, imageLayout, verify) { } public PEImage(byte[] data, bool verify) : this(data, null, ImageLayout.File, verify) { } public PEImage(byte[] data, string filename, bool verify) : this(data, filename, ImageLayout.File, verify) { } public PEImage(byte[] data) : this(data, null, verify: true) { } public PEImage(byte[] data, string filename) : this(data, filename, verify: true) { } public unsafe PEImage(IntPtr baseAddr, uint length, ImageLayout imageLayout, bool verify) : this(NativeMemoryDataReaderFactory.Create((byte*)(void*)baseAddr, length, null), imageLayout, verify) { } public PEImage(IntPtr baseAddr, uint length, bool verify) : this(baseAddr, length, ImageLayout.Memory, verify) { } public PEImage(IntPtr baseAddr, uint length) : this(baseAddr, length, verify: true) { } public unsafe PEImage(IntPtr baseAddr, ImageLayout imageLayout, bool verify) : this(NativeMemoryDataReaderFactory.Create((byte*)(void*)baseAddr, 65536u, null), imageLayout, verify) { try { ((NativeMemoryDataReaderFactory)dataReaderFactory).SetLength(peInfo.GetImageSize()); } catch { Dispose(); throw; } } public PEImage(IntPtr baseAddr, bool verify) : this(baseAddr, ImageLayout.Memory, verify) { } public PEImage(IntPtr baseAddr) : this(baseAddr, verify: true) { } public RVA ToRVA(FileOffset offset) { return peType.ToRVA(peInfo, offset); } public FileOffset ToFileOffset(RVA rva) { return peType.ToFileOffset(peInfo, rva); } public void Dispose() { IDisposable value; if (win32Resources.IsValueInitialized && (value = win32Resources.Value) != null) { value.Dispose(); } dataReaderFactory?.Dispose(); win32Resources.Value = null; dataReaderFactory = null; peType = null; peInfo = null; } public DataReader CreateReader(FileOffset offset) { return DataReaderFactory.CreateReader((uint)offset, (uint)(DataReaderFactory.Length - offset)); } public DataReader CreateReader(FileOffset offset, uint length) { return DataReaderFactory.CreateReader((uint)offset, length); } public DataReader CreateReader(RVA rva) { return CreateReader(ToFileOffset(rva)); } public DataReader CreateReader(RVA rva, uint length) { return CreateReader(ToFileOffset(rva), length); } public DataReader CreateReader() { return DataReaderFactory.CreateReader(); } void IInternalPEImage.UnsafeDisableMemoryMappedIO() { if (dataReaderFactory is MemoryMappedDataReaderFactory memoryMappedDataReaderFactory) { memoryMappedDataReaderFactory.UnsafeDisableMemoryMappedIO(); } } private ImageDebugDirectory[] ReadImageDebugDirectories() { try { ImageDataDirectory imageDataDirectory = ImageNTHeaders.OptionalHeader.DataDirectories[6]; if (imageDataDirectory.VirtualAddress == (RVA)0u) { return Array2.Empty(); } DataReader reader = DataReaderFactory.CreateReader(); if (imageDataDirectory.Size > reader.Length) { return Array2.Empty(); } int num = (int)(imageDataDirectory.Size / 28); if (num == 0) { return Array2.Empty(); } reader.CurrentOffset = (uint)ToFileOffset(imageDataDirectory.VirtualAddress); if ((ulong)((long)reader.CurrentOffset + (long)imageDataDirectory.Size) > (ulong)reader.Length) { return Array2.Empty(); } ImageDebugDirectory[] array = new ImageDebugDirectory[num]; for (int i = 0; i < array.Length; i++) { array[i] = new ImageDebugDirectory(ref reader, verify: true); } return array; } catch (IOException) { } return Array2.Empty(); } } internal sealed class PEInfo { private readonly ImageDosHeader imageDosHeader; private readonly ImageNTHeaders imageNTHeaders; private readonly ImageSectionHeader[] imageSectionHeaders; public ImageDosHeader ImageDosHeader => imageDosHeader; public ImageNTHeaders ImageNTHeaders => imageNTHeaders; public ImageSectionHeader[] ImageSectionHeaders => imageSectionHeaders; public PEInfo(ref DataReader reader, bool verify) { reader.Position = 0u; imageDosHeader = new ImageDosHeader(ref reader, verify); if (verify && imageDosHeader.NTHeadersOffset == 0) { throw new BadImageFormatException("Invalid NT headers offset"); } reader.Position = imageDosHeader.NTHeadersOffset; imageNTHeaders = new ImageNTHeaders(ref reader, verify); reader.Position = (uint)(imageNTHeaders.OptionalHeader.StartOffset + imageNTHeaders.FileHeader.SizeOfOptionalHeader); int num = imageNTHeaders.FileHeader.NumberOfSections; if (num > 0) { DataReader dataReader = reader; dataReader.Position += 20u; uint num2 = dataReader.ReadUInt32(); num = Math.Min(num, (int)((num2 - reader.Position) / 40)); } imageSectionHeaders = new ImageSectionHeader[num]; for (int i = 0; i < imageSectionHeaders.Length; i++) { imageSectionHeaders[i] = new ImageSectionHeader(ref reader, verify); } } public ImageSectionHeader ToImageSectionHeader(FileOffset offset) { ImageSectionHeader[] array = imageSectionHeaders; foreach (ImageSectionHeader imageSectionHeader in array) { if ((uint)offset >= imageSectionHeader.PointerToRawData && (uint)offset < imageSectionHeader.PointerToRawData + imageSectionHeader.SizeOfRawData) { return imageSectionHeader; } } return null; } public ImageSectionHeader ToImageSectionHeader(RVA rva) { uint sectionAlignment = imageNTHeaders.OptionalHeader.SectionAlignment; ImageSectionHeader[] array = imageSectionHeaders; foreach (ImageSectionHeader imageSectionHeader in array) { if (rva >= imageSectionHeader.VirtualAddress && rva < imageSectionHeader.VirtualAddress + dnlib.DotNet.Utils.AlignUp(imageSectionHeader.VirtualSize, sectionAlignment)) { return imageSectionHeader; } } return null; } public RVA ToRVA(FileOffset offset) { if (imageSectionHeaders.Length == 0) { return (RVA)offset; } ImageSectionHeader imageSectionHeader = imageSectionHeaders[imageSectionHeaders.Length - 1]; if ((uint)offset > imageSectionHeader.PointerToRawData + imageSectionHeader.SizeOfRawData) { return (RVA)0u; } ImageSectionHeader imageSectionHeader2 = ToImageSectionHeader(offset); if (imageSectionHeader2 != null) { return (RVA)((uint)(offset - imageSectionHeader2.PointerToRawData) + (uint)imageSectionHeader2.VirtualAddress); } return (RVA)offset; } public FileOffset ToFileOffset(RVA rva) { if ((uint)rva >= imageNTHeaders.OptionalHeader.SizeOfImage) { return (FileOffset)0u; } ImageSectionHeader imageSectionHeader = ToImageSectionHeader(rva); if (imageSectionHeader != null) { uint num = rva - imageSectionHeader.VirtualAddress; if (num < imageSectionHeader.SizeOfRawData) { return (FileOffset)(num + imageSectionHeader.PointerToRawData); } return (FileOffset)0u; } return (FileOffset)rva; } private static ulong AlignUp(ulong val, uint alignment) { return (val + alignment - 1) & ~(ulong)(alignment - 1); } public uint GetImageSize() { IImageOptionalHeader optionalHeader = ImageNTHeaders.OptionalHeader; uint sectionAlignment = optionalHeader.SectionAlignment; if (imageSectionHeaders.Length == 0) { return (uint)AlignUp(optionalHeader.SizeOfHeaders, sectionAlignment); } ImageSectionHeader imageSectionHeader = imageSectionHeaders[imageSectionHeaders.Length - 1]; return (uint)Math.Min(AlignUp((ulong)imageSectionHeader.VirtualAddress + (ulong)imageSectionHeader.VirtualSize, sectionAlignment), 4294967295uL); } } internal static class ProcessorArchUtils { private static class RuntimeInformationUtils { public static bool TryGet_RuntimeInformation_Architecture(out Machine machine) { return TryGetArchitecture((int)RuntimeInformation.ProcessArchitecture, out machine); } private static bool TryGetArchitecture(int architecture, out Machine machine) { switch (architecture) { case 0: machine = Machine.I386; return true; case 1: machine = Machine.AMD64; return true; case 2: machine = Machine.ARMNT; return true; case 3: machine = Machine.ARM64; return true; default: machine = Machine.Unknown; return false; } } } private static class WindowsUtils { private struct SYSTEM_INFO { public ushort wProcessorArchitecture; public ushort wReserved; public uint dwPageSize; public IntPtr lpMinimumApplicationAddress; public IntPtr lpMaximumApplicationAddress; public IntPtr dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public ushort wProcessorLevel; public ushort wProcessorRevision; } private enum ProcessorArchitecture : ushort { INTEL = 0, ARM = 5, IA64 = 6, AMD64 = 9, ARM64 = 12, UNKNOWN = ushort.MaxValue } private static bool canTryGetSystemInfo = true; [DllImport("kernel32")] private static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); public static bool TryGetProcessCpuArchitecture(out Machine machine) { if (canTryGetSystemInfo) { try { GetSystemInfo(out var lpSystemInfo); switch ((ProcessorArchitecture)lpSystemInfo.wProcessorArchitecture) { case ProcessorArchitecture.INTEL: machine = Machine.I386; return true; case ProcessorArchitecture.ARM: machine = Machine.ARMNT; return true; case ProcessorArchitecture.IA64: machine = Machine.IA64; return true; case ProcessorArchitecture.AMD64: machine = Machine.AMD64; return true; case ProcessorArchitecture.ARM64: machine = Machine.ARM64; return true; } } catch (EntryPointNotFoundException) { canTryGetSystemInfo = false; } catch (DllNotFoundException) { canTryGetSystemInfo = false; } } machine = Machine.Unknown; return false; } } private static Machine cachedMachine; public static Machine GetProcessCpuArchitecture() { if (cachedMachine == Machine.Unknown) { cachedMachine = GetProcessCpuArchitectureCore(); } return cachedMachine; } private static Machine GetProcessCpuArchitectureCore() { if (WindowsUtils.TryGetProcessCpuArchitecture(out var machine)) { return machine; } try { if (RuntimeInformationUtils.TryGet_RuntimeInformation_Architecture(out machine)) { return machine; } } catch (PlatformNotSupportedException) { } if (IntPtr.Size != 4) { return Machine.AMD64; } return Machine.I386; } } public enum RVA : uint { } public enum Subsystem : ushort { Unknown = 0, Native = 1, WindowsGui = 2, WindowsCui = 3, Os2Cui = 5, PosixCui = 7, NativeWindows = 8, WindowsCeGui = 9, EfiApplication = 10, EfiBootServiceDriver = 11, EfiRuntimeDriver = 12, EfiRom = 13, Xbox = 14, WindowsBootApplication = 16 } } namespace dnlib.IO { internal sealed class AlignedByteArrayDataStream : DataStream { private readonly byte[] data; public AlignedByteArrayDataStream(byte[] data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { Marshal.Copy(data, (int)offset, (IntPtr)destination, length); } public override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Array.Copy(data, (int)offset, destination, destinationIndex, length); } public override byte ReadByte(uint offset) { return data[offset]; } public override ushort ReadUInt16(uint offset) { int num = (int)offset; byte[] array = data; return (ushort)(array[num++] | (array[num] << 8)); } public override uint ReadUInt32(uint offset) { int num = (int)offset; byte[] array = data; return (uint)(array[num++] | (array[num++] << 8) | (array[num++] << 16) | (array[num] << 24)); } public override ulong ReadUInt64(uint offset) { int num = (int)offset; byte[] array = data; return array[num++] | ((ulong)array[num++] << 8) | ((ulong)array[num++] << 16) | ((ulong)array[num++] << 24) | ((ulong)array[num++] << 32) | ((ulong)array[num++] << 40) | ((ulong)array[num++] << 48) | ((ulong)array[num] << 56); } public unsafe override float ReadSingle(uint offset) { int num = (int)offset; byte[] array = data; uint num2 = (uint)(array[num++] | (array[num++] << 8) | (array[num++] << 16) | (array[num] << 24)); return *(float*)(&num2); } public unsafe override double ReadDouble(uint offset) { int num = (int)offset; byte[] array = data; ulong num2 = array[num++] | ((ulong)array[num++] << 8) | ((ulong)array[num++] << 16) | ((ulong)array[num++] << 24) | ((ulong)array[num++] << 32) | ((ulong)array[num++] << 40) | ((ulong)array[num++] << 48) | ((ulong)array[num] << 56); return *(double*)(&num2); } public unsafe override string ReadUtf16String(uint offset, int chars) { fixed (byte* ptr = data) { return new string((char*)(ptr + offset), 0, chars); } } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { fixed (byte* ptr = data) { return new string((sbyte*)(ptr + offset), 0, length, encoding); } } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { fixed (byte* ptr = data) { byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } } internal sealed class AlignedNativeMemoryDataStream : DataStream { private unsafe readonly byte* data; public unsafe AlignedNativeMemoryDataStream(byte* data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { byte* ptr = data + offset; byte* ptr2 = (byte*)destination; int num = length / 4; length %= 4; for (int i = 0; i < num; i++) { *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; } int num2 = 0; while (num2 < length) { *ptr2 = *ptr; num2++; ptr++; ptr2++; } } public unsafe override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Marshal.Copy((IntPtr)(data + offset), destination, destinationIndex, length); } public unsafe override byte ReadByte(uint offset) { return data[offset]; } public unsafe override ushort ReadUInt16(uint offset) { byte* ptr = data + offset; return (ushort)(*(ptr++) | (*ptr << 8)); } public unsafe override uint ReadUInt32(uint offset) { byte* ptr = data + offset; return (uint)(*(ptr++) | (*(ptr++) << 8) | (*(ptr++) << 16) | (*ptr << 24)); } public unsafe override ulong ReadUInt64(uint offset) { byte* ptr = data + offset; return *(ptr++) | ((ulong)(*(ptr++)) << 8) | ((ulong)(*(ptr++)) << 16) | ((ulong)(*(ptr++)) << 24) | ((ulong)(*(ptr++)) << 32) | ((ulong)(*(ptr++)) << 40) | ((ulong)(*(ptr++)) << 48) | ((ulong)(*ptr) << 56); } public unsafe override float ReadSingle(uint offset) { byte* ptr = data + offset; uint num = (uint)(*(ptr++) | (*(ptr++) << 8) | (*(ptr++) << 16) | (*ptr << 24)); return *(float*)(&num); } public unsafe override double ReadDouble(uint offset) { byte* ptr = data + offset; ulong num = *(ptr++) | ((ulong)(*(ptr++)) << 8) | ((ulong)(*(ptr++)) << 16) | ((ulong)(*(ptr++)) << 24) | ((ulong)(*(ptr++)) << 32) | ((ulong)(*(ptr++)) << 40) | ((ulong)(*(ptr++)) << 48) | ((ulong)(*ptr) << 56); return *(double*)(&num); } public unsafe override string ReadUtf16String(uint offset, int chars) { return new string((char*)(data + offset), 0, chars); } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { return new string((sbyte*)(data + offset), 0, length, encoding); } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { byte* ptr = data; byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } public sealed class ByteArrayDataReaderFactory : DataReaderFactory { private DataStream stream; private string filename; private uint length; private byte[] data; public override string Filename => filename; public override uint Length => length; internal byte[] DataArray => data; internal uint DataOffset => 0u; private ByteArrayDataReaderFactory(byte[] data, string filename) { this.filename = filename; length = (uint)data.Length; stream = DataStreamFactory.Create(data); this.data = data; } public static ByteArrayDataReaderFactory Create(byte[] data, string filename) { if (data == null) { throw new ArgumentNullException("data"); } return new ByteArrayDataReaderFactory(data, filename); } public static DataReader CreateReader(byte[] data) { return Create(data, null).CreateReader(); } public override DataReader CreateReader(uint offset, uint length) { return CreateReader(stream, offset, length); } public override void Dispose() { stream = EmptyDataStream.Instance; length = 0u; filename = null; data = null; } } [Serializable] public sealed class DataReaderException : IOException { internal DataReaderException(string message) : base(message) { } internal DataReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [DebuggerDisplay("{StartOffset,h}-{EndOffset,h} Length={Length} BytesLeft={BytesLeft}")] public struct DataReader { private readonly DataStream stream; private readonly uint startOffset; private readonly uint endOffset; private uint currentOffset; public readonly uint StartOffset => startOffset; public readonly uint EndOffset => endOffset; public readonly uint Length => endOffset - startOffset; public uint CurrentOffset { readonly get { return currentOffset; } set { if (value < startOffset || value > endOffset) { ThrowDataReaderException("Invalid new CurrentOffset"); } currentOffset = value; } } public uint Position { readonly get { return currentOffset - startOffset; } set { if (value > Length) { ThrowDataReaderException("Invalid new Position"); } currentOffset = startOffset + value; } } public readonly uint BytesLeft => endOffset - currentOffset; public DataReader(DataStream stream, uint offset, uint length) { this.stream = stream; startOffset = offset; endOffset = offset + length; currentOffset = offset; } [Conditional("DEBUG")] private readonly void VerifyState() { } private static void ThrowNoMoreBytesLeft() { throw new DataReaderException("There's not enough bytes left to read"); } private static void ThrowDataReaderException(string message) { throw new DataReaderException(message); } private static void ThrowInvalidOperationException() { throw new InvalidOperationException(); } private static void ThrowArgumentNullException(string paramName) { throw new ArgumentNullException(paramName); } private static void ThrowInvalidArgument(string paramName) { throw new DataReaderException("Invalid argument value"); } public void Reset() { currentOffset = startOffset; } public readonly DataReader Slice(uint start, uint length) { if ((ulong)((long)start + (long)length) > (ulong)Length) { ThrowInvalidArgument("length"); } return new DataReader(stream, startOffset + start, length); } public readonly DataReader Slice(uint start) { if (start > Length) { ThrowInvalidArgument("start"); } return Slice(start, Length - start); } public readonly DataReader Slice(int start, int length) { if (start < 0) { ThrowInvalidArgument("start"); } if (length < 0) { ThrowInvalidArgument("length"); } return Slice((uint)start, (uint)length); } public readonly DataReader Slice(int start) { if (start < 0) { ThrowInvalidArgument("start"); } if ((uint)start > Length) { ThrowInvalidArgument("start"); } return Slice((uint)start, Length - (uint)start); } public readonly bool CanRead(int length) { if (length >= 0) { return (uint)length <= BytesLeft; } return false; } public readonly bool CanRead(uint length) { return length <= BytesLeft; } public bool ReadBoolean() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } bool result = stream.ReadBoolean(num); currentOffset = num + 1; return result; } public char ReadChar() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } char result = stream.ReadChar(num); currentOffset = num + 2; return result; } public sbyte ReadSByte() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } sbyte result = stream.ReadSByte(num); currentOffset = num + 1; return result; } public byte ReadByte() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } byte result = stream.ReadByte(num); currentOffset = num + 1; return result; } public short ReadInt16() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } short result = stream.ReadInt16(num); currentOffset = num + 2; return result; } public ushort ReadUInt16() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } ushort result = stream.ReadUInt16(num); currentOffset = num + 2; return result; } public int ReadInt32() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } int result = stream.ReadInt32(num); currentOffset = num + 4; return result; } public uint ReadUInt32() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } uint result = stream.ReadUInt32(num); currentOffset = num + 4; return result; } internal byte Unsafe_ReadByte() { uint num = currentOffset; byte result = stream.ReadByte(num); currentOffset = num + 1; return result; } internal ushort Unsafe_ReadUInt16() { uint num = currentOffset; ushort result = stream.ReadUInt16(num); currentOffset = num + 2; return result; } internal uint Unsafe_ReadUInt32() { uint num = currentOffset; uint result = stream.ReadUInt32(num); currentOffset = num + 4; return result; } public long ReadInt64() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } long result = stream.ReadInt64(num); currentOffset = num + 8; return result; } public ulong ReadUInt64() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } ulong result = stream.ReadUInt64(num); currentOffset = num + 8; return result; } public float ReadSingle() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } float result = stream.ReadSingle(num); currentOffset = num + 4; return result; } public double ReadDouble() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } double result = stream.ReadDouble(num); currentOffset = num + 8; return result; } public Guid ReadGuid() { uint num = currentOffset; if (endOffset - num < 16) { ThrowNoMoreBytesLeft(); } Guid result = stream.ReadGuid(num); currentOffset = num + 16; return result; } public decimal ReadDecimal() { uint num = currentOffset; if (endOffset - num < 16) { ThrowNoMoreBytesLeft(); } decimal result = stream.ReadDecimal(num); currentOffset = num + 16; return result; } public string ReadUtf16String(int chars) { if (chars < 0) { ThrowInvalidArgument("chars"); } if (chars == 0) { return string.Empty; } uint num = (uint)(chars * 2); uint num2 = currentOffset; if (endOffset - num2 < num) { ThrowNoMoreBytesLeft(); } string result = ((num == 0) ? string.Empty : stream.ReadUtf16String(num2, chars)); currentOffset = num2 + num; return result; } public unsafe void ReadBytes(void* destination, int length) { if (destination == null && length != 0) { ThrowArgumentNullException("destination"); } if (length < 0) { ThrowInvalidArgument("length"); } if (length != 0) { uint num = currentOffset; if (endOffset - num < (uint)length) { ThrowNoMoreBytesLeft(); } stream.ReadBytes(num, destination, length); currentOffset = num + (uint)length; } } public void ReadBytes(byte[] destination, int destinationIndex, int length) { if (destination == null) { ThrowArgumentNullException("destination"); } if (destinationIndex < 0) { ThrowInvalidArgument("destinationIndex"); } if (length < 0) { ThrowInvalidArgument("length"); } if (length != 0) { uint num = currentOffset; if (endOffset - num < (uint)length) { ThrowNoMoreBytesLeft(); } stream.ReadBytes(num, destination, destinationIndex, length); currentOffset = num + (uint)length; } } public byte[] ReadBytes(int length) { if (length < 0) { ThrowInvalidArgument("length"); } if (length == 0) { return Array2.Empty(); } byte[] array = new byte[length]; ReadBytes(array, 0, length); return array; } public bool TryReadCompressedUInt32(out uint value) { uint num = currentOffset; uint num2 = endOffset - num; if (num2 == 0) { value = 0u; return false; } DataStream dataStream = stream; byte b = dataStream.ReadByte(num++); if ((b & 0x80) == 0) { value = b; currentOffset = num; return true; } if ((b & 0xC0) == 128) { if (num2 < 2) { value = 0u; return false; } value = (uint)(((b & 0x3F) << 8) | dataStream.ReadByte(num++)); currentOffset = num; return true; } if (num2 < 4) { value = 0u; return false; } value = (uint)(((b & 0x1F) << 24) | (dataStream.ReadByte(num++) << 16) | (dataStream.ReadByte(num++) << 8) | dataStream.ReadByte(num++)); currentOffset = num; return true; } public uint ReadCompressedUInt32() { if (!TryReadCompressedUInt32(out var value)) { ThrowNoMoreBytesLeft(); } return value; } public bool TryReadCompressedInt32(out int value) { uint num = currentOffset; uint num2 = endOffset - num; if (num2 == 0) { value = 0; return false; } DataStream dataStream = stream; byte b = dataStream.ReadByte(num++); if ((b & 0x80) == 0) { if ((b & 1) != 0) { value = -64 | (b >> 1); } else { value = b >> 1; } currentOffset = num; return true; } if ((b & 0xC0) == 128) { if (num2 < 2) { value = 0; return false; } uint num3 = (uint)(((b & 0x3F) << 8) | dataStream.ReadByte(num++)); if ((num3 & 1) != 0) { value = -8192 | (int)(num3 >> 1); } else { value = (int)(num3 >> 1); } currentOffset = num; return true; } if ((b & 0xE0) == 192) { if (num2 < 4) { value = 0; return false; } uint num4 = (uint)(((b & 0x1F) << 24) | (dataStream.ReadByte(num++) << 16) | (dataStream.ReadByte(num++) << 8) | dataStream.ReadByte(num++)); if ((num4 & 1) != 0) { value = -268435456 | (int)(num4 >> 1); } else { value = (int)(num4 >> 1); } currentOffset = num; return true; } value = 0; return false; } public int ReadCompressedInt32() { if (!TryReadCompressedInt32(out var value)) { ThrowNoMoreBytesLeft(); } return value; } public uint Read7BitEncodedUInt32() { uint num = 0u; int num2 = 0; for (int i = 0; i < 5; i++) { byte b = ReadByte(); num |= (uint)((b & 0x7F) << num2); if ((b & 0x80) == 0) { return num; } num2 += 7; } ThrowDataReaderException("Invalid encoded UInt32"); return 0u; } public int Read7BitEncodedInt32() { return (int)Read7BitEncodedUInt32(); } public string ReadSerializedString() { return ReadSerializedString(Encoding.UTF8); } public string ReadSerializedString(Encoding encoding) { if (encoding == null) { ThrowArgumentNullException("encoding"); } int num = Read7BitEncodedInt32(); if (num < 0) { ThrowNoMoreBytesLeft(); } if (num == 0) { return string.Empty; } return ReadString(num, encoding); } public readonly byte[] ToArray() { int length = (int)Length; if (length < 0) { ThrowInvalidOperationException(); } if (length == 0) { return Array2.Empty(); } byte[] array = new byte[length]; stream.ReadBytes(startOffset, array, 0, array.Length); return array; } public byte[] ReadRemainingBytes() { int bytesLeft = (int)BytesLeft; if (bytesLeft < 0) { ThrowInvalidOperationException(); } return ReadBytes(bytesLeft); } public byte[] TryReadBytesUntil(byte value) { uint num = currentOffset; uint num2 = endOffset; if (num == num2) { return null; } if (!stream.TryGetOffsetOf(num, num2, value, out var valueOffset)) { return null; } int num3 = (int)(valueOffset - num); if (num3 < 0) { return null; } return ReadBytes(num3); } public string TryReadZeroTerminatedUtf8String() { return TryReadZeroTerminatedString(Encoding.UTF8); } public string TryReadZeroTerminatedString(Encoding encoding) { if (encoding == null) { ThrowArgumentNullException("encoding"); } uint num = currentOffset; uint num2 = endOffset; if (num == num2) { return null; } if (!stream.TryGetOffsetOf(num, num2, 0, out var valueOffset)) { return null; } int num3 = (int)(valueOffset - num); if (num3 < 0) { return null; } string result = ((num3 == 0) ? string.Empty : stream.ReadString(num, num3, encoding)); currentOffset = valueOffset + 1; return result; } public string ReadUtf8String(int byteCount) { return ReadString(byteCount, Encoding.UTF8); } public string ReadString(int byteCount, Encoding encoding) { if (byteCount < 0) { ThrowInvalidArgument("byteCount"); } if (encoding == null) { ThrowArgumentNullException("encoding"); } if (byteCount == 0) { return string.Empty; } if ((uint)byteCount > Length) { ThrowInvalidArgument("byteCount"); } uint num = currentOffset; string result = stream.ReadString(num, byteCount, encoding); currentOffset = num + (uint)byteCount; return result; } public readonly Stream AsStream() { return new DataReaderStream(in this); } private readonly byte[] AllocTempBuffer() { return new byte[Math.Min(8192u, BytesLeft)]; } public void CopyTo(DataWriter destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination.InternalStream, AllocTempBuffer()); } } public void CopyTo(DataWriter destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } CopyTo(destination.InternalStream, dataBuffer); } public void CopyTo(BinaryWriter destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination.BaseStream, AllocTempBuffer()); } } public void CopyTo(BinaryWriter destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } CopyTo(destination.BaseStream, dataBuffer); } public void CopyTo(Stream destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination, AllocTempBuffer()); } } public void CopyTo(Stream destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } if (dataBuffer == null) { ThrowArgumentNullException("dataBuffer"); } if (Position < Length) { if (dataBuffer.Length == 0) { ThrowInvalidArgument("dataBuffer"); } uint num = BytesLeft; while (num != 0) { int num2 = (int)Math.Min((uint)dataBuffer.Length, num); num -= (uint)num2; ReadBytes(dataBuffer, 0, num2); destination.Write(dataBuffer, 0, num2); } } } } public abstract class DataReaderFactory : IDisposable { public abstract string Filename { get; } public abstract uint Length { get; } public virtual event EventHandler DataReaderInvalidated { add { } remove { } } public DataReader CreateReader() { return CreateReader(0u, Length); } public abstract DataReader CreateReader(uint offset, uint length); private static void ThrowArgumentOutOfRangeException(string paramName) { throw new ArgumentOutOfRangeException(paramName); } private static void Throw_CreateReader_2(int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } throw new ArgumentOutOfRangeException("length"); } public DataReader CreateReader(uint offset, int length) { if (length < 0) { ThrowArgumentOutOfRangeException("length"); } return CreateReader(offset, (uint)length); } public DataReader CreateReader(int offset, uint length) { if (offset < 0) { ThrowArgumentOutOfRangeException("offset"); } return CreateReader((uint)offset, length); } public DataReader CreateReader(int offset, int length) { if (offset < 0 || length < 0) { Throw_CreateReader_2(offset, length); } return CreateReader((uint)offset, (uint)length); } protected DataReader CreateReader(DataStream stream, uint offset, uint length) { uint length2 = Length; if (offset > length2) { offset = length2; } if ((ulong)((long)offset + (long)length) > (ulong)length2) { length = length2 - offset; } return new DataReader(stream, offset, length); } public abstract void Dispose(); } internal static class DataReaderFactoryFactory { private static readonly bool isUnix; static DataReaderFactoryFactory() { int platform = (int)Environment.OSVersion.Platform; if (platform == 4 || platform == 6 || platform == 128) { isUnix = true; } if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { isUnix = true; } } public static DataReaderFactory Create(string fileName, bool mapAsImage) { DataReaderFactory dataReaderFactory = CreateDataReaderFactory(fileName, mapAsImage); if (dataReaderFactory != null) { return dataReaderFactory; } return ByteArrayDataReaderFactory.Create(File.ReadAllBytes(fileName), fileName); } private static DataReaderFactory CreateDataReaderFactory(string fileName, bool mapAsImage) { if (!isUnix) { return MemoryMappedDataReaderFactory.CreateWindows(fileName, mapAsImage); } return MemoryMappedDataReaderFactory.CreateUnix(fileName, mapAsImage); } } internal sealed class DataReaderStream : Stream { private DataReader reader; private long position; public override bool CanRead => true; public override bool CanSeek => true; public override bool CanWrite => false; public override long Length => reader.Length; public override long Position { get { return position; } set { position = value; } } public DataReaderStream(in DataReader reader) { this.reader = reader; position = reader.Position; } public override void Flush() { } private bool CheckAndSetPosition() { if ((ulong)position > (ulong)reader.Length) { return false; } reader.Position = (uint)position; return true; } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current: Position += offset; break; case SeekOrigin.End: Position = Length + offset; break; } return Position; } public override int Read(byte[] buffer, int offset, int count) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (!CheckAndSetPosition()) { return 0; } int num = (int)Math.Min((uint)count, reader.BytesLeft); reader.ReadBytes(buffer, offset, num); Position += num; return num; } public override int ReadByte() { if (!CheckAndSetPosition() || !reader.CanRead(1u)) { return -1; } Position++; return reader.ReadByte(); } public override void SetLength(long value) { throw new NotSupportedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } } public abstract class DataStream { public unsafe abstract void ReadBytes(uint offset, void* destination, int length); public abstract void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length); public abstract byte ReadByte(uint offset); public virtual sbyte ReadSByte(uint offset) { return (sbyte)ReadByte(offset); } public virtual bool ReadBoolean(uint offset) { return ReadByte(offset) != 0; } public abstract ushort ReadUInt16(uint offset); public virtual short ReadInt16(uint offset) { return (short)ReadUInt16(offset); } public virtual char ReadChar(uint offset) { return (char)ReadUInt16(offset); } public abstract uint ReadUInt32(uint offset); public virtual int ReadInt32(uint offset) { return (int)ReadUInt32(offset); } public abstract ulong ReadUInt64(uint offset); public virtual long ReadInt64(uint offset) { return (long)ReadUInt64(offset); } public abstract float ReadSingle(uint offset); public abstract double ReadDouble(uint offset); public virtual Guid ReadGuid(uint offset) { return new Guid(ReadUInt32(offset), ReadUInt16(offset + 4), ReadUInt16(offset + 6), ReadByte(offset + 8), ReadByte(offset + 9), ReadByte(offset + 10), ReadByte(offset + 11), ReadByte(offset + 12), ReadByte(offset + 13), ReadByte(offset + 14), ReadByte(offset + 15)); } public virtual decimal ReadDecimal(uint offset) { int lo = ReadInt32(offset); int mid = ReadInt32(offset + 4); int hi = ReadInt32(offset + 8); int num = ReadInt32(offset + 12); byte scale = (byte)(num >> 16); bool isNegative = (num & 0x80000000u) != 0; return new decimal(lo, mid, hi, isNegative, scale); } public abstract string ReadUtf16String(uint offset, int chars); public abstract string ReadString(uint offset, int length, Encoding encoding); public abstract bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset); } public static class DataStreamFactory { private static bool supportsUnalignedAccesses = CalculateSupportsUnalignedAccesses(); private static bool CalculateSupportsUnalignedAccesses() { switch (ProcessorArchUtils.GetProcessCpuArchitecture()) { case Machine.I386: case Machine.AMD64: return true; case Machine.ARMNT: case Machine.ARM64: return false; default: return true; } } public unsafe static DataStream Create(byte* data) { if (data == null) { throw new ArgumentNullException("data"); } if (supportsUnalignedAccesses) { return new UnalignedNativeMemoryDataStream(data); } return new AlignedNativeMemoryDataStream(data); } public static DataStream Create(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (supportsUnalignedAccesses) { return new UnalignedByteArrayDataStream(data); } return new AlignedByteArrayDataStream(data); } } internal sealed class EmptyDataStream : DataStream { public static readonly DataStream Instance = new EmptyDataStream(); private EmptyDataStream() { } public unsafe override void ReadBytes(uint offset, void* destination, int length) { for (int i = 0; i < length; i++) { *(sbyte*)destination = 0; } } public override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { for (int i = 0; i < length; i++) { destination[destinationIndex + i] = 0; } } public override byte ReadByte(uint offset) { return 0; } public override ushort ReadUInt16(uint offset) { return 0; } public override uint ReadUInt32(uint offset) { return 0u; } public override ulong ReadUInt64(uint offset) { return 0uL; } public override float ReadSingle(uint offset) { return 0f; } public override double ReadDouble(uint offset) { return 0.0; } public override string ReadUtf16String(uint offset, int chars) { return string.Empty; } public override string ReadString(uint offset, int length, Encoding encoding) { return string.Empty; } public override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { valueOffset = 0u; return false; } } public enum FileOffset : uint { } public static class IOExtensions { public static FileOffset AlignUp(this FileOffset offset, uint alignment) { return (FileOffset)((uint)(offset + alignment - 1) & ~(alignment - 1)); } public static FileOffset AlignUp(this FileOffset offset, int alignment) { return (FileOffset)(((long)offset + (long)alignment - 1) & ~(alignment - 1)); } } [DebuggerDisplay("O:{startOffset} L:{size} {GetType().Name}")] public class FileSection : IFileSection { protected FileOffset startOffset; protected uint size; public FileOffset StartOffset => startOffset; public FileOffset EndOffset => startOffset + size; protected void SetStartOffset(ref DataReader reader) { startOffset = (FileOffset)reader.CurrentOffset; } protected void SetEndoffset(ref DataReader reader) { size = (uint)(reader.CurrentOffset - startOffset); } } public interface IFileSection { FileOffset StartOffset { get; } FileOffset EndOffset { get; } } internal sealed class MemoryMappedDataReaderFactory : DataReaderFactory { private enum OSType : byte { Unknown, Windows, Unix } [Serializable] private sealed class MemoryMappedIONotSupportedException : IOException { public MemoryMappedIONotSupportedException(string s) : base(s) { } public MemoryMappedIONotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) { } } private static class Windows { private const uint GENERIC_READ = 2147483648u; private const uint FILE_SHARE_READ = 1u; private const uint OPEN_EXISTING = 3u; private const uint FILE_ATTRIBUTE_NORMAL = 128u; private const uint PAGE_READONLY = 2u; private const uint SEC_IMAGE = 16777216u; private const uint SECTION_MAP_READ = 4u; private const uint FILE_MAP_READ = 4u; private const uint INVALID_FILE_SIZE = uint.MaxValue; private const int NO_ERROR = 0; [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] private static extern SafeFileHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr MapViewOfFile(SafeFileHandle hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] private static extern uint GetFileSize(SafeFileHandle hFile, out uint lpFileSizeHigh); public unsafe static void Mmap(MemoryMappedDataReaderFactory creator, bool mapAsImage) { using SafeFileHandle safeFileHandle = CreateFile(creator.filename, 2147483648u, 1u, IntPtr.Zero, 3u, 128u, IntPtr.Zero); if (safeFileHandle.IsInvalid) { throw new IOException($"Could not open file {creator.filename} for reading. Error: {Marshal.GetLastWin32Error():X8}"); } uint lpFileSizeHigh; uint fileSize = GetFileSize(safeFileHandle, out lpFileSizeHigh); int lastWin32Error; if (fileSize == uint.MaxValue && (lastWin32Error = Marshal.GetLastWin32Error()) != 0) { throw new IOException($"Could not get file size. File: {creator.filename}, error: {lastWin32Error:X8}"); } long num = (long)(((ulong)lpFileSizeHigh << 32) | fileSize); using SafeFileHandle safeFileHandle2 = CreateFileMapping(safeFileHandle, IntPtr.Zero, (uint)(2 | (mapAsImage ? 16777216 : 0)), 0u, 0u, null); if (safeFileHandle2.IsInvalid) { throw new MemoryMappedIONotSupportedException($"Could not create a file mapping object. File: {creator.filename}, error: {Marshal.GetLastWin32Error():X8}"); } creator.data = MapViewOfFile(safeFileHandle2, 4u, 0u, 0u, UIntPtr.Zero); if (creator.data == IntPtr.Zero) { throw new MemoryMappedIONotSupportedException($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error():X8}"); } creator.length = (uint)num; creator.osType = OSType.Windows; creator.stream = DataStreamFactory.Create((byte*)(void*)creator.data); } public static void Dispose(IntPtr addr) { if (addr != IntPtr.Zero) { UnmapViewOfFile(addr); } } } private static class Unix { private const int O_RDONLY = 0; private const int SEEK_END = 2; private const int PROT_READ = 1; private const int MAP_PRIVATE = 2; [DllImport("libc")] private static extern int open(string pathname, int flags); [DllImport("libc")] private static extern int close(int fd); [DllImport("libc", EntryPoint = "lseek", SetLastError = true)] private static extern int lseek32(int fd, int offset, int whence); [DllImport("libc", EntryPoint = "lseek", SetLastError = true)] private static extern long lseek64(int fd, long offset, int whence); [DllImport("libc", EntryPoint = "mmap", SetLastError = true)] private static extern IntPtr mmap32(IntPtr addr, IntPtr length, int prot, int flags, int fd, int offset); [DllImport("libc", EntryPoint = "mmap", SetLastError = true)] private static extern IntPtr mmap64(IntPtr addr, IntPtr length, int prot, int flags, int fd, long offset); [DllImport("libc")] private static extern int munmap(IntPtr addr, IntPtr length); public unsafe static void Mmap(MemoryMappedDataReaderFactory creator, bool mapAsImage) { int num = open(creator.filename, 0); try { if (num < 0) { throw new IOException($"Could not open file {creator.filename} for reading. Error: {num}"); } long num2; IntPtr intPtr; if (IntPtr.Size == 4) { num2 = lseek32(num, 0, 2); if (num2 == -1) { throw new MemoryMappedIONotSupportedException($"Could not get length of {creator.filename} (lseek failed): {Marshal.GetLastWin32Error()}"); } intPtr = mmap32(IntPtr.Zero, (IntPtr)num2, 1, 2, num, 0); if (intPtr == new IntPtr(-1) || intPtr == IntPtr.Zero) { throw new MemoryMappedIONotSupportedException($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error()}"); } } else { num2 = lseek64(num, 0L, 2); if (num2 == -1) { throw new MemoryMappedIONotSupportedException($"Could not get length of {creator.filename} (lseek failed): {Marshal.GetLastWin32Error()}"); } intPtr = mmap64(IntPtr.Zero, (IntPtr)num2, 1, 2, num, 0L); if (intPtr == new IntPtr(-1) || intPtr == IntPtr.Zero) { throw new MemoryMappedIONotSupportedException($"Could not map file {creator.filename}. Error: {Marshal.GetLastWin32Error()}"); } } creator.data = intPtr; creator.length = (uint)num2; creator.origDataLength = num2; creator.osType = OSType.Unix; creator.stream = DataStreamFactory.Create((byte*)(void*)creator.data); } finally { if (num >= 0) { close(num); } } } public static void Dispose(IntPtr addr, long size) { if (addr != IntPtr.Zero) { munmap(addr, new IntPtr(size)); } } } private DataStream stream; private uint length; private string filename; private GCHandle gcHandle; private byte[] dataAry; private IntPtr data; private OSType osType; private long origDataLength; private static volatile bool canTryWindows = true; private static volatile bool canTryUnix = true; public override string Filename => filename; public override uint Length => length; internal bool IsMemoryMappedIO => dataAry == null; public override event EventHandler DataReaderInvalidated; private MemoryMappedDataReaderFactory(string filename) { osType = OSType.Unknown; this.filename = filename; } ~MemoryMappedDataReaderFactory() { Dispose(disposing: false); } public override DataReader CreateReader(uint offset, uint length) { return CreateReader(stream, offset, length); } public override void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } internal void SetLength(uint length) { this.length = length; } internal static MemoryMappedDataReaderFactory CreateWindows(string filename, bool mapAsImage) { if (!canTryWindows) { return null; } MemoryMappedDataReaderFactory memoryMappedDataReaderFactory = new MemoryMappedDataReaderFactory(GetFullPath(filename)); try { Windows.Mmap(memoryMappedDataReaderFactory, mapAsImage); return memoryMappedDataReaderFactory; } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryWindows = false; return null; } internal static MemoryMappedDataReaderFactory CreateUnix(string filename, bool mapAsImage) { if (!canTryUnix) { return null; } MemoryMappedDataReaderFactory memoryMappedDataReaderFactory = new MemoryMappedDataReaderFactory(GetFullPath(filename)); try { Unix.Mmap(memoryMappedDataReaderFactory, mapAsImage); if (mapAsImage) { memoryMappedDataReaderFactory.Dispose(); throw new ArgumentException("mapAsImage == true is not supported on this OS"); } return memoryMappedDataReaderFactory; } catch (MemoryMappedIONotSupportedException) { } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryUnix = false; return null; } private static string GetFullPath(string filename) { try { return Path.GetFullPath(filename); } catch { return filename; } } private void Dispose(bool disposing) { FreeMemoryMappedIoData(); if (disposing) { length = 0u; stream = EmptyDataStream.Instance; data = IntPtr.Zero; filename = null; } } internal unsafe void UnsafeDisableMemoryMappedIO() { if (dataAry == null) { byte[] array = new byte[length]; Marshal.Copy(data, array, 0, array.Length); FreeMemoryMappedIoData(); length = (uint)array.Length; dataAry = array; gcHandle = GCHandle.Alloc(dataAry, GCHandleType.Pinned); data = gcHandle.AddrOfPinnedObject(); stream = DataStreamFactory.Create((byte*)(void*)data); DataReaderInvalidated?.Invoke(this, EventArgs.Empty); } } private void FreeMemoryMappedIoData() { if (dataAry == null) { IntPtr intPtr = Interlocked.Exchange(ref data, IntPtr.Zero); if (intPtr != IntPtr.Zero) { length = 0u; switch (osType) { case OSType.Windows: Windows.Dispose(intPtr); break; case OSType.Unix: Unix.Dispose(intPtr, origDataLength); break; default: throw new InvalidOperationException("Shouldn't be here"); } } } if (gcHandle.IsAllocated) { try { gcHandle.Free(); } catch (InvalidOperationException) { } } dataAry = null; } } public sealed class NativeMemoryDataReaderFactory : DataReaderFactory { private DataStream stream; private string filename; private uint length; public override string Filename => filename; public override uint Length => length; private unsafe NativeMemoryDataReaderFactory(byte* data, uint length, string filename) { this.filename = filename; this.length = length; stream = DataStreamFactory.Create(data); } internal void SetLength(uint length) { this.length = length; } public unsafe static NativeMemoryDataReaderFactory Create(byte* data, uint length, string filename) { if (data == null) { throw new ArgumentNullException("data"); } return new NativeMemoryDataReaderFactory(data, length, filename); } public override DataReader CreateReader(uint offset, uint length) { return CreateReader(stream, offset, length); } public override void Dispose() { stream = EmptyDataStream.Instance; length = 0u; filename = null; } } internal sealed class UnalignedByteArrayDataStream : DataStream { private readonly byte[] data; public UnalignedByteArrayDataStream(byte[] data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { Marshal.Copy(data, (int)offset, (IntPtr)destination, length); } public override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Array.Copy(data, (int)offset, destination, destinationIndex, length); } public override byte ReadByte(uint offset) { return data[offset]; } public override ushort ReadUInt16(uint offset) { int num = (int)offset; byte[] array = data; return (ushort)(array[num++] | (array[num] << 8)); } public unsafe override uint ReadUInt32(uint offset) { fixed (byte* ptr = data) { return *(uint*)(ptr + offset); } } public unsafe override ulong ReadUInt64(uint offset) { fixed (byte* ptr = data) { return *(ulong*)(ptr + offset); } } public unsafe override float ReadSingle(uint offset) { fixed (byte* ptr = data) { return *(float*)(ptr + offset); } } public unsafe override double ReadDouble(uint offset) { fixed (byte* ptr = data) { return *(double*)(ptr + offset); } } public unsafe override Guid ReadGuid(uint offset) { fixed (byte* ptr = data) { return *(Guid*)(ptr + offset); } } public unsafe override string ReadUtf16String(uint offset, int chars) { fixed (byte* ptr = data) { return new string((char*)(ptr + offset), 0, chars); } } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { fixed (byte* ptr = data) { return new string((sbyte*)(ptr + offset), 0, length, encoding); } } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { fixed (byte* ptr = data) { byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } } internal sealed class UnalignedNativeMemoryDataStream : DataStream { private unsafe readonly byte* data; public unsafe UnalignedNativeMemoryDataStream(byte* data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { byte* ptr = data + offset; byte* ptr2 = (byte*)destination; int num = length / 4; length %= 4; for (int i = 0; i < num; i++) { *(int*)ptr2 = *(int*)ptr; ptr2 += 4; ptr += 4; } int num2 = 0; while (num2 < length) { *ptr2 = *ptr; num2++; ptr++; ptr2++; } } public unsafe override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Marshal.Copy((IntPtr)(data + offset), destination, destinationIndex, length); } public unsafe override byte ReadByte(uint offset) { return data[offset]; } public unsafe override ushort ReadUInt16(uint offset) { return *(ushort*)(data + offset); } public unsafe override uint ReadUInt32(uint offset) { return *(uint*)(data + offset); } public unsafe override ulong ReadUInt64(uint offset) { return *(ulong*)(data + offset); } public unsafe override float ReadSingle(uint offset) { return *(float*)(data + offset); } public unsafe override double ReadDouble(uint offset) { return *(double*)(data + offset); } public unsafe override Guid ReadGuid(uint offset) { return *(Guid*)(data + offset); } public unsafe override string ReadUtf16String(uint offset, int chars) { return new string((char*)(data + offset), 0, chars); } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { return new string((sbyte*)(data + offset), 0, length, encoding); } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { byte* ptr = data; byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } } namespace dnlib.DotNet { [StructLayout(LayoutKind.Sequential, Size = 1)] internal readonly struct AllTypesHelper { public static IEnumerable Types(IEnumerable types) { Dictionary visited = new Dictionary(); Stack> stack = new Stack>(); if (types != null) { stack.Push(types.GetEnumerator()); } while (stack.Count > 0) { IEnumerator enumerator = stack.Pop(); while (enumerator.MoveNext()) { TypeDef type = enumerator.Current; if (!visited.ContainsKey(type)) { visited[type] = true; yield return type; if (type.NestedTypes.Count > 0) { stack.Push(enumerator); enumerator = type.NestedTypes.GetEnumerator(); } } } } } } [Flags] public enum AssemblyAttributes : uint { None = 0u, PublicKey = 1u, PA_None = 0u, PA_MSIL = 0x10u, PA_x86 = 0x20u, PA_IA64 = 0x30u, PA_AMD64 = 0x40u, PA_ARM = 0x50u, PA_ARM64 = 0x60u, PA_NoPlatform = 0x70u, PA_Specified = 0x80u, PA_Mask = 0x70u, PA_FullMask = 0xF0u, PA_Shift = 4u, EnableJITcompileTracking = 0x8000u, DisableJITcompileOptimizer = 0x4000u, Retargetable = 0x100u, ContentType_Default = 0u, ContentType_WindowsRuntime = 0x200u, ContentType_Mask = 0xE00u } public abstract class AssemblyDef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasDeclSecurity, IFullName, IHasCustomDebugInformation, IAssembly, IListListener, ITypeDefFinder, IDnlibDef { protected uint rid; protected AssemblyHashAlgorithm hashAlgorithm; protected Version version; protected int attributes; protected PublicKey publicKey; protected UTF8String name; protected UTF8String culture; protected IList declSecurities; protected LazyList modules; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.Assembly, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 14; public int HasDeclSecurityTag => 2; public AssemblyHashAlgorithm HashAlgorithm { get { return hashAlgorithm; } set { hashAlgorithm = value; } } public Version Version { get { return version; } set { version = value ?? throw new ArgumentNullException("value"); } } public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (int)value; } } public PublicKey PublicKey { get { return publicKey; } set { publicKey = value ?? new PublicKey(); } } public PublicKeyToken PublicKeyToken => publicKey.Token; public UTF8String Name { get { return name; } set { name = value; } } public UTF8String Culture { get { return culture; } set { culture = value; } } public IList DeclSecurities { get { if (declSecurities == null) { InitializeDeclSecurities(); } return declSecurities; } } public PublicKeyBase PublicKeyOrToken => publicKey; public string FullName => GetFullNameWithPublicKeyToken(); public string FullNameToken => GetFullNameWithPublicKeyToken(); public IList Modules { get { if (modules == null) { InitializeModules(); } return modules; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 14; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasDeclSecurities => DeclSecurities.Count > 0; public bool HasModules => Modules.Count > 0; public ModuleDef ManifestModule { get { if (Modules.Count != 0) { return Modules[0]; } return null; } } public bool HasPublicKey { get { return (attributes & 1) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PublicKey); } } public AssemblyAttributes ProcessorArchitecture { get { return (AssemblyAttributes)(attributes & 0x70); } set { ModifyAttributes(~AssemblyAttributes.PA_NoPlatform, value & AssemblyAttributes.PA_NoPlatform); } } public AssemblyAttributes ProcessorArchitectureFull { get { return (AssemblyAttributes)(attributes & 0xF0); } set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); } } public bool IsProcessorArchitectureNone => (attributes & 0x70) == 0; public bool IsProcessorArchitectureMSIL => (attributes & 0x70) == 16; public bool IsProcessorArchitectureX86 => (attributes & 0x70) == 32; public bool IsProcessorArchitectureIA64 => (attributes & 0x70) == 48; public bool IsProcessorArchitectureX64 => (attributes & 0x70) == 64; public bool IsProcessorArchitectureARM => (attributes & 0x70) == 80; public bool IsProcessorArchitectureNoPlatform => (attributes & 0x70) == 112; public bool IsProcessorArchitectureSpecified { get { return (attributes & 0x80) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); } } public bool EnableJITcompileTracking { get { return (attributes & 0x8000) != 0; } set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); } } public bool DisableJITcompileOptimizer { get { return (attributes & 0x4000) != 0; } set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); } } public bool IsRetargetable { get { return (attributes & 0x100) != 0; } set { ModifyAttributes(value, AssemblyAttributes.Retargetable); } } public AssemblyAttributes ContentType { get { return (AssemblyAttributes)(attributes & 0xE00); } set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); } } public bool IsContentTypeDefault => (attributes & 0xE00) == 0; public bool IsContentTypeWindowsRuntime => (attributes & 0xE00) == 512; protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, new List(), null); } protected virtual void InitializeModules() { Interlocked.CompareExchange(ref modules, new LazyList(this), null); } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, AssemblyAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~flags); } } public ModuleDef FindModule(UTF8String name) { IList list = Modules; int count = list.Count; for (int i = 0; i < count; i++) { ModuleDef moduleDef = list[i]; if (moduleDef != null && UTF8String.CaseInsensitiveEquals(moduleDef.Name, name)) { return moduleDef; } } return null; } public static AssemblyDef Load(string fileName, ModuleContext context) { return Load(fileName, new ModuleCreationOptions(context)); } public static AssemblyDef Load(string fileName, ModuleCreationOptions options = null) { if (fileName == null) { throw new ArgumentNullException("fileName"); } ModuleDef moduleDef = null; try { moduleDef = ModuleDefMD.Load(fileName, options); return moduleDef.Assembly ?? throw new BadImageFormatException(fileName + " is only a .NET module, not a .NET assembly. Use ModuleDef.Load()."); } catch { moduleDef?.Dispose(); throw; } } public static AssemblyDef Load(byte[] data, ModuleContext context) { return Load(data, new ModuleCreationOptions(context)); } public static AssemblyDef Load(byte[] data, ModuleCreationOptions options = null) { if (data == null) { throw new ArgumentNullException("data"); } ModuleDef moduleDef = null; try { moduleDef = ModuleDefMD.Load(data, options); return moduleDef.Assembly ?? throw new BadImageFormatException(moduleDef.ToString() + " is only a .NET module, not a .NET assembly. Use ModuleDef.Load()."); } catch { moduleDef?.Dispose(); throw; } } public static AssemblyDef Load(IntPtr addr, ModuleContext context) { return Load(addr, new ModuleCreationOptions(context)); } public static AssemblyDef Load(IntPtr addr, ModuleCreationOptions options = null) { if (addr == IntPtr.Zero) { throw new ArgumentNullException("addr"); } ModuleDef moduleDef = null; try { moduleDef = ModuleDefMD.Load(addr, options); return moduleDef.Assembly ?? throw new BadImageFormatException($"{moduleDef.ToString()} (addr: {addr.ToInt64():X8}) is only a .NET module, not a .NET assembly. Use ModuleDef.Load()."); } catch { moduleDef?.Dispose(); throw; } } public static AssemblyDef Load(Stream stream, ModuleContext context) { return Load(stream, new ModuleCreationOptions(context)); } public static AssemblyDef Load(Stream stream, ModuleCreationOptions options = null) { if (stream == null) { throw new ArgumentNullException("stream"); } ModuleDef moduleDef = null; try { moduleDef = ModuleDefMD.Load(stream, options); return moduleDef.Assembly ?? throw new BadImageFormatException(moduleDef.ToString() + " is only a .NET module, not a .NET assembly. Use ModuleDef.Load()."); } catch { moduleDef?.Dispose(); throw; } } public string GetFullNameWithPublicKey() { return FullNameFactory.AssemblyFullName(this, withToken: false); } public string GetFullNameWithPublicKeyToken() { return FullNameFactory.AssemblyFullName(this, withToken: true); } public TypeDef Find(string fullName, bool isReflectionName) { IList list = Modules; int count = list.Count; for (int i = 0; i < count; i++) { ModuleDef moduleDef = list[i]; if (moduleDef != null) { TypeDef typeDef = moduleDef.Find(fullName, isReflectionName); if (typeDef != null) { return typeDef; } } } return null; } public TypeDef Find(TypeRef typeRef) { IList list = Modules; int count = list.Count; for (int i = 0; i < count; i++) { ModuleDef moduleDef = list[i]; if (moduleDef != null) { TypeDef typeDef = moduleDef.Find(typeRef); if (typeDef != null) { return typeDef; } } } return null; } public void Write(string filename, ModuleWriterOptions options = null) { ManifestModule.Write(filename, options); } public void Write(Stream dest, ModuleWriterOptions options = null) { ManifestModule.Write(dest, options); } public bool IsFriendAssemblyOf(AssemblyDef targetAsm) { if (targetAsm == null) { return false; } if (this == targetAsm) { return true; } if (PublicKeyBase.IsNullOrEmpty2(publicKey) != PublicKeyBase.IsNullOrEmpty2(targetAsm.PublicKey)) { return false; } foreach (CustomAttribute item in targetAsm.CustomAttributes.FindAll("System.Runtime.CompilerServices.InternalsVisibleToAttribute")) { if (item.ConstructorArguments.Count != 1) { continue; } CAArgument cAArgument = ((item.ConstructorArguments.Count == 0) ? default(CAArgument) : item.ConstructorArguments[0]); if (cAArgument.Type.GetElementType() != ElementType.String) { continue; } UTF8String uTF8String = cAArgument.Value as UTF8String; if (UTF8String.IsNull(uTF8String)) { continue; } AssemblyNameInfo assemblyNameInfo = new AssemblyNameInfo(uTF8String); if (assemblyNameInfo.Name != name) { continue; } if (!PublicKeyBase.IsNullOrEmpty2(publicKey)) { if (!PublicKey.Equals(assemblyNameInfo.PublicKeyOrToken as PublicKey)) { continue; } } else if (!PublicKeyBase.IsNullOrEmpty2(assemblyNameInfo.PublicKeyOrToken)) { continue; } return true; } return false; } public void UpdateOrCreateAssemblySignatureKeyAttribute(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { ModuleDef manifestModule = ManifestModule; if (manifestModule == null) { return; } CustomAttribute customAttribute = null; for (int i = 0; i < CustomAttributes.Count; i++) { CustomAttribute customAttribute2 = CustomAttributes[i]; if (!(customAttribute2.TypeFullName != "System.Reflection.AssemblySignatureKeyAttribute")) { CustomAttributes.RemoveAt(i); i--; if (customAttribute == null) { customAttribute = customAttribute2; } } } if (IsValidAssemblySignatureKeyAttribute(customAttribute)) { customAttribute.NamedArguments.Clear(); } else { customAttribute = CreateAssemblySignatureKeyAttribute(); } string s = StrongNameKey.CreateCounterSignatureAsString(identityPubKey, identityKey, signaturePubKey); customAttribute.ConstructorArguments[0] = new CAArgument(manifestModule.CorLibTypes.String, new UTF8String(signaturePubKey.ToString())); customAttribute.ConstructorArguments[1] = new CAArgument(manifestModule.CorLibTypes.String, new UTF8String(s)); CustomAttributes.Add(customAttribute); } private bool IsValidAssemblySignatureKeyAttribute(CustomAttribute ca) { if (Settings.IsThreadSafe) { return false; } if (ca == null) { return false; } ICustomAttributeType constructor = ca.Constructor; if (constructor == null) { return false; } MethodSig methodSig = constructor.MethodSig; if (methodSig == null || methodSig.Params.Count != 2) { return false; } if (methodSig.Params[0].GetElementType() != ElementType.String) { return false; } if (methodSig.Params[1].GetElementType() != ElementType.String) { return false; } if (ca.ConstructorArguments.Count != 2) { return false; } return true; } private CustomAttribute CreateAssemblySignatureKeyAttribute() { ModuleDef manifestModule = ManifestModule; TypeRefUser typeRefUser = manifestModule.UpdateRowId(new TypeRefUser(manifestModule, "System.Reflection", "AssemblySignatureKeyAttribute", manifestModule.CorLibTypes.AssemblyRef)); MethodSig sig = MethodSig.CreateInstance(manifestModule.CorLibTypes.Void, manifestModule.CorLibTypes.String, manifestModule.CorLibTypes.String); return new CustomAttribute(manifestModule.UpdateRowId(new MemberRefUser(manifestModule, MethodDef.InstanceConstructorName, sig, typeRefUser))) { ConstructorArguments = { new CAArgument(manifestModule.CorLibTypes.String, UTF8String.Empty), new CAArgument(manifestModule.CorLibTypes.String, UTF8String.Empty) } }; } public virtual bool TryGetOriginalTargetFrameworkAttribute(out string framework, out Version version, out string profile) { framework = null; version = null; profile = null; return false; } void IListListener.OnLazyAdd(int index, ref ModuleDef module) { _ = module; } void IListListener.OnAdd(int index, ModuleDef module) { if (module != null) { if (module.Assembly != null) { throw new InvalidOperationException("Module already has an assembly. Remove it from that assembly before adding it to this assembly."); } module.Assembly = this; } } void IListListener.OnRemove(int index, ModuleDef module) { if (module != null) { module.Assembly = null; } } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (ModuleDef item in modules.GetEnumerable_NoLock()) { if (item != null) { item.Assembly = null; } } } public override string ToString() { return FullName; } } public class AssemblyDefUser : AssemblyDef { public AssemblyDefUser() : this(UTF8String.Empty, new Version(0, 0, 0, 0)) { } public AssemblyDefUser(UTF8String name) : this(name, new Version(0, 0, 0, 0), new PublicKey()) { } public AssemblyDefUser(UTF8String name, Version version) : this(name, version, new PublicKey()) { } public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey) : this(name, version, publicKey, UTF8String.Empty) { } public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey, UTF8String locale) { if ((object)name == null) { throw new ArgumentNullException("name"); } if ((object)locale == null) { throw new ArgumentNullException("locale"); } modules = new LazyList(this); base.name = name; base.version = version ?? throw new ArgumentNullException("version"); base.publicKey = publicKey ?? new PublicKey(); culture = locale; attributes = 0; } public AssemblyDefUser(AssemblyName asmName) : this(new AssemblyNameInfo(asmName)) { hashAlgorithm = (AssemblyHashAlgorithm)asmName.HashAlgorithm; attributes = (int)asmName.Flags; } public AssemblyDefUser(IAssembly asmName) { if (asmName == null) { throw new ArgumentNullException("asmName"); } modules = new LazyList(this); name = asmName.Name; version = asmName.Version ?? new Version(0, 0, 0, 0); publicKey = (asmName.PublicKeyOrToken as PublicKey) ?? new PublicKey(); culture = asmName.Culture; attributes = 0; hashAlgorithm = AssemblyHashAlgorithm.SHA1; } } internal sealed class AssemblyDefMD : AssemblyDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private volatile bool hasInitdTFA; private string tfaFramework; private Version tfaVersion; private string tfaProfile; private bool tfaReturnValue; private static readonly UTF8String nameSystemRuntimeVersioning = new UTF8String("System.Runtime.Versioning"); private static readonly UTF8String nameTargetFrameworkAttribute = new UTF8String("TargetFrameworkAttribute"); public uint OrigRid => origRid; protected override void InitializeDeclSecurities() { RidList declSecurityRidList = readerModule.Metadata.GetDeclSecurityRidList(Table.Assembly, origRid); LazyList value = new LazyList(declSecurityRidList.Count, declSecurityRidList, (RidList list2, int index) => readerModule.ResolveDeclSecurity(list2[index])); Interlocked.CompareExchange(ref declSecurities, value, null); } protected override void InitializeModules() { RidList moduleRidList = readerModule.GetModuleRidList(); LazyList value = new LazyList(moduleRidList.Count + 1, this, moduleRidList, delegate(RidList list2, int index) { ModuleDef moduleDef = ((index != 0) ? readerModule.ReadModule(list2[index - 1], this) : readerModule); if (moduleDef == null) { moduleDef = new ModuleDefUser("INVALID", Guid.NewGuid()); } moduleDef.Assembly = this; return moduleDef; }); Interlocked.CompareExchange(ref modules, value, null); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Assembly, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public override bool TryGetOriginalTargetFrameworkAttribute(out string framework, out Version version, out string profile) { if (!hasInitdTFA) { InitializeTargetFrameworkAttribute(); } framework = tfaFramework; version = tfaVersion; profile = tfaProfile; return tfaReturnValue; } private void InitializeTargetFrameworkAttribute() { if (hasInitdTFA) { return; } RidList customAttributeRidList = readerModule.Metadata.GetCustomAttributeRidList(Table.Assembly, origRid); GenericParamContext gpContext = default(GenericParamContext); for (int i = 0; i < customAttributeRidList.Count; i++) { uint num = customAttributeRidList[i]; if (!readerModule.TablesStream.TryReadCustomAttributeRow(num, out var row)) { continue; } ICustomAttributeType customAttributeType = readerModule.ResolveCustomAttributeType(row.Type, gpContext); if (TryGetName(customAttributeType, out var ns, out var uTF8String) && !(ns != nameSystemRuntimeVersioning) && !(uTF8String != nameTargetFrameworkAttribute)) { CustomAttribute customAttribute = CustomAttributeReader.Read(readerModule, customAttributeType, row.Value, gpContext); if (customAttribute != null && customAttribute.ConstructorArguments.Count == 1 && customAttribute.ConstructorArguments[0].Value is UTF8String uTF8String2 && TryCreateTargetFrameworkInfo(uTF8String2, out var framework, out var version, out var profile)) { tfaFramework = framework; tfaVersion = version; tfaProfile = profile; tfaReturnValue = true; break; } } } hasInitdTFA = true; } private static bool TryGetName(ICustomAttributeType caType, out UTF8String ns, out UTF8String name) { ITypeDefOrRef typeDefOrRef = ((!(caType is MemberRef memberRef)) ? (caType as MethodDef)?.DeclaringType : memberRef.DeclaringType); if (typeDefOrRef is TypeRef typeRef) { ns = typeRef.Namespace; name = typeRef.Name; return true; } if (typeDefOrRef is TypeDef typeDef) { ns = typeDef.Namespace; name = typeDef.Name; return true; } ns = null; name = null; return false; } private static bool TryCreateTargetFrameworkInfo(string attrString, out string framework, out Version version, out string profile) { framework = null; version = null; profile = null; string[] array = attrString.Split(new char[1] { ',' }); if (array.Length < 2 || array.Length > 3) { return false; } string text = array[0].Trim(); if (text.Length == 0) { return false; } Version version2 = null; string text2 = null; for (int i = 1; i < array.Length; i++) { string[] array2 = array[i].Split('='); if (array2.Length != 2) { return false; } string text3 = array2[0].Trim(); string text4 = array2[1].Trim(); if (text3.Equals("Version", StringComparison.OrdinalIgnoreCase)) { if (text4.StartsWith("v", StringComparison.OrdinalIgnoreCase)) { text4 = text4.Substring(1); } if (!TryParse(text4, out version2)) { return false; } version2 = new Version(version2.Major, version2.Minor, (version2.Build != -1) ? version2.Build : 0, 0); } else if (text3.Equals("Profile", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(text4)) { text2 = text4; } } if ((object)version2 == null) { return false; } framework = text; version = version2; profile = text2; return true; } private static int ParseInt32(string s) { if (!int.TryParse(s, out var result)) { return 0; } return result; } private static bool TryParse(string s, out Version version) { Match match = Regex.Match(s, "^(\\d+)\\.(\\d+)$"); if (match.Groups.Count == 3) { version = new Version(ParseInt32(match.Groups[1].Value), ParseInt32(match.Groups[2].Value)); return true; } match = Regex.Match(s, "^(\\d+)\\.(\\d+)\\.(\\d+)$"); if (match.Groups.Count == 4) { version = new Version(ParseInt32(match.Groups[1].Value), ParseInt32(match.Groups[2].Value), ParseInt32(match.Groups[3].Value)); return true; } match = Regex.Match(s, "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$"); if (match.Groups.Count == 5) { version = new Version(ParseInt32(match.Groups[1].Value), ParseInt32(match.Groups[2].Value), ParseInt32(match.Groups[3].Value), ParseInt32(match.Groups[4].Value)); return true; } version = null; return false; } public AssemblyDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; if (rid != 1) { modules = new LazyList(this); } readerModule.TablesStream.TryReadAssemblyRow(origRid, out var row); hashAlgorithm = (AssemblyHashAlgorithm)row.HashAlgId; version = new Version(row.MajorVersion, row.MinorVersion, row.BuildNumber, row.RevisionNumber); attributes = (int)row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); culture = readerModule.StringsStream.ReadNoNull(row.Locale); publicKey = new PublicKey(readerModule.BlobStream.Read(row.PublicKey)); } } internal readonly struct AssemblyHash : IDisposable { private readonly HashAlgorithm hasher; public AssemblyHash(AssemblyHashAlgorithm hashAlgo) { hasher = hashAlgo switch { AssemblyHashAlgorithm.MD5 => MD5.Create(), AssemblyHashAlgorithm.SHA_256 => SHA256.Create(), AssemblyHashAlgorithm.SHA_384 => SHA384.Create(), AssemblyHashAlgorithm.SHA_512 => SHA512.Create(), _ => SHA1.Create(), }; } public void Dispose() { if (hasher != null) { ((IDisposable)hasher).Dispose(); } } public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo) { if (data == null) { return null; } using AssemblyHash assemblyHash = new AssemblyHash(hashAlgo); assemblyHash.Hash(data); return assemblyHash.ComputeHash(); } public void Hash(byte[] data) { Hash(data, 0, data.Length); } public void Hash(byte[] data, int offset, int length) { if (hasher.TransformBlock(data, offset, length, data, offset) != length) { throw new IOException("Could not calculate hash"); } } public void Hash(Stream stream, uint length, byte[] buffer) { while (length != 0) { int num = ((length > (uint)buffer.Length) ? buffer.Length : ((int)length)); if (stream.Read(buffer, 0, num) != num) { throw new IOException("Could not read data"); } Hash(buffer, 0, num); length -= (uint)num; } } public byte[] ComputeHash() { hasher.TransformFinalBlock(Array2.Empty(), 0, 0); return hasher.Hash; } public static PublicKeyToken CreatePublicKeyToken(byte[] publicKeyData) { if (publicKeyData == null) { return new PublicKeyToken(); } byte[] array = Hash(publicKeyData, AssemblyHashAlgorithm.SHA1); byte[] array2 = new byte[8]; for (int i = 0; i < array2.Length && i < array.Length; i++) { array2[i] = array[array.Length - i - 1]; } return new PublicKeyToken(array2); } } public enum AssemblyHashAlgorithm : uint { None = 0u, MD2 = 32769u, MD4 = 32770u, MD5 = 32771u, SHA1 = 32772u, MAC = 32773u, SSL3_SHAMD5 = 32776u, HMAC = 32777u, TLS1PRF = 32778u, HASH_REPLACE_OWF = 32779u, SHA_256 = 32780u, SHA_384 = 32781u, SHA_512 = 32782u } public static class Extensions { internal static string GetName(this AssemblyHashAlgorithm hashAlg) { return hashAlg switch { AssemblyHashAlgorithm.MD2 => null, AssemblyHashAlgorithm.MD4 => null, AssemblyHashAlgorithm.MD5 => "MD5", AssemblyHashAlgorithm.SHA1 => "SHA1", AssemblyHashAlgorithm.MAC => null, AssemblyHashAlgorithm.SSL3_SHAMD5 => null, AssemblyHashAlgorithm.HMAC => null, AssemblyHashAlgorithm.TLS1PRF => null, AssemblyHashAlgorithm.HASH_REPLACE_OWF => null, AssemblyHashAlgorithm.SHA_256 => "SHA256", AssemblyHashAlgorithm.SHA_384 => "SHA384", AssemblyHashAlgorithm.SHA_512 => "SHA512", _ => null, }; } public static TypeSig GetFieldType(this FieldSig sig) { return sig?.Type; } public static TypeSig GetRetType(this MethodBaseSig sig) { return sig?.RetType; } public static IList GetParams(this MethodBaseSig sig) { return sig?.Params ?? new List(); } public static int GetParamCount(this MethodBaseSig sig) { return sig?.Params.Count ?? 0; } public static uint GetGenParamCount(this MethodBaseSig sig) { return sig?.GenParamCount ?? 0; } public static IList GetParamsAfterSentinel(this MethodBaseSig sig) { return sig?.ParamsAfterSentinel; } public static IList GetLocals(this LocalSig sig) { return sig?.Locals ?? new List(); } public static IList GetGenericArguments(this GenericInstMethodSig sig) { return sig?.GenericArguments ?? new List(); } public static bool GetIsDefault(this CallingConventionSig sig) { return sig?.IsDefault ?? false; } public static bool IsPrimitive(this ElementType etype) { if (etype - 2 <= ElementType.U8 || etype - 24 <= ElementType.Boolean) { return true; } return false; } public static int GetPrimitiveSize(this ElementType etype, int ptrSize = -1) { switch (etype) { case ElementType.Boolean: case ElementType.I1: case ElementType.U1: return 1; case ElementType.Char: case ElementType.I2: case ElementType.U2: return 2; case ElementType.I4: case ElementType.U4: case ElementType.R4: return 4; case ElementType.I8: case ElementType.U8: case ElementType.R8: return 8; case ElementType.Ptr: case ElementType.I: case ElementType.U: case ElementType.FnPtr: return ptrSize; default: return -1; } } public static bool IsValueType(this ElementType etype) { switch (etype) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.ValueType: case ElementType.TypedByRef: case ElementType.ValueArray: case ElementType.I: case ElementType.U: case ElementType.R: return true; case ElementType.GenericInst: return false; default: return false; } } public static AssemblyDef Resolve(this IAssemblyResolver self, AssemblyName assembly, ModuleDef sourceModule) { if (assembly == null) { return null; } return self.Resolve(new AssemblyNameInfo(assembly), sourceModule); } public static AssemblyDef Resolve(this IAssemblyResolver self, string asmFullName, ModuleDef sourceModule) { if (asmFullName == null) { return null; } return self.Resolve(new AssemblyNameInfo(asmFullName), sourceModule); } public static AssemblyDef ResolveThrow(this IAssemblyResolver self, IAssembly assembly, ModuleDef sourceModule) { if (assembly == null) { return null; } AssemblyDef assemblyDef = self.Resolve(assembly, sourceModule); if (assemblyDef != null) { return assemblyDef; } throw new AssemblyResolveException($"Could not resolve assembly: {assembly}"); } public static AssemblyDef ResolveThrow(this IAssemblyResolver self, AssemblyName assembly, ModuleDef sourceModule) { if (assembly == null) { return null; } AssemblyDef assemblyDef = self.Resolve(new AssemblyNameInfo(assembly), sourceModule); if (assemblyDef != null) { return assemblyDef; } throw new AssemblyResolveException($"Could not resolve assembly: {assembly}"); } public static AssemblyDef ResolveThrow(this IAssemblyResolver self, string asmFullName, ModuleDef sourceModule) { if (asmFullName == null) { return null; } AssemblyDef assemblyDef = self.Resolve(new AssemblyNameInfo(asmFullName), sourceModule); if (assemblyDef != null) { return assemblyDef; } throw new AssemblyResolveException("Could not resolve assembly: " + asmFullName); } public static bool IsCorLib(this IAssembly asm) { if (asm is AssemblyDef { ManifestModule: { IsCoreLibraryModule: var isCoreLibraryModule } } && isCoreLibraryModule.HasValue) { return isCoreLibraryModule.Value; } if (asm != null && UTF8String.IsNullOrEmpty(asm.Culture)) { string text; if (!(text = UTF8String.ToSystemStringOrEmpty(asm.Name)).Equals("mscorlib", StringComparison.OrdinalIgnoreCase) && !text.Equals("System.Runtime", StringComparison.OrdinalIgnoreCase) && !text.Equals("System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) && !text.Equals("netstandard", StringComparison.OrdinalIgnoreCase)) { return text.Equals("corefx", StringComparison.OrdinalIgnoreCase); } return true; } return false; } public static AssemblyRef ToAssemblyRef(this IAssembly asm) { if (asm == null) { return null; } return new AssemblyRefUser(asm.Name, asm.Version, asm.PublicKeyOrToken, asm.Culture) { Attributes = asm.Attributes }; } public static TypeSig ToTypeSig(this ITypeDefOrRef type, bool resolveToCheckValueType = true) { if (type == null) { return null; } ModuleDef module = type.Module; if (module != null) { CorLibTypeSig corLibTypeSig = module.CorLibTypes.GetCorLibTypeSig(type); if (corLibTypeSig != null) { return corLibTypeSig; } } TypeDef typeDef = type as TypeDef; if (typeDef != null) { return CreateClassOrValueType(type, typeDef.IsValueType); } if (type is TypeRef typeRef) { if (resolveToCheckValueType) { typeDef = typeRef.Resolve(); } return CreateClassOrValueType(type, typeDef?.IsValueType ?? false); } if (type is TypeSpec typeSpec) { return typeSpec.TypeSig; } return null; } private static TypeSig CreateClassOrValueType(ITypeDefOrRef type, bool isValueType) { if (isValueType) { return new ValueTypeSig(type); } return new ClassSig(type); } public static TypeDefOrRefSig TryGetTypeDefOrRefSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as TypeDefOrRefSig; } return null; } public static ClassOrValueTypeSig TryGetClassOrValueTypeSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as ClassOrValueTypeSig; } return null; } public static ValueTypeSig TryGetValueTypeSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as ValueTypeSig; } return null; } public static ClassSig TryGetClassSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as ClassSig; } return null; } public static GenericSig TryGetGenericSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as GenericSig; } return null; } public static GenericVar TryGetGenericVar(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as GenericVar; } return null; } public static GenericMVar TryGetGenericMVar(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as GenericMVar; } return null; } public static GenericInstSig TryGetGenericInstSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as GenericInstSig; } return null; } public static PtrSig TryGetPtrSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as PtrSig; } return null; } public static ByRefSig TryGetByRefSig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as ByRefSig; } return null; } public static ArraySig TryGetArraySig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as ArraySig; } return null; } public static SZArraySig TryGetSZArraySig(this ITypeDefOrRef type) { if (type is TypeSpec typeSpec) { return typeSpec.TypeSig.RemovePinnedAndModifiers() as SZArraySig; } return null; } public static ITypeDefOrRef GetBaseTypeThrow(this ITypeDefOrRef tdr) { return tdr.GetBaseType(throwOnResolveFailure: true); } public static ITypeDefOrRef GetBaseType(this ITypeDefOrRef tdr, bool throwOnResolveFailure = false) { if (tdr is TypeDef typeDef) { return typeDef.BaseType; } if (tdr is TypeRef typeRef) { return (throwOnResolveFailure ? typeRef.ResolveThrow() : typeRef.Resolve())?.BaseType; } if (!(tdr is TypeSpec typeSpec)) { return null; } GenericInstSig genericInstSig = typeSpec.TypeSig.ToGenericInstSig(); tdr = ((genericInstSig == null) ? typeSpec.TypeSig.ToTypeDefOrRefSig()?.TypeDefOrRef : genericInstSig.GenericType?.TypeDefOrRef); if (tdr is TypeDef typeDef2) { return typeDef2.BaseType; } if (tdr is TypeRef typeRef2) { return (throwOnResolveFailure ? typeRef2.ResolveThrow() : typeRef2.Resolve())?.BaseType; } return null; } public static TypeDef ResolveTypeDef(this ITypeDefOrRef tdr) { if (tdr is TypeDef result) { return result; } if (tdr is TypeRef typeRef) { return typeRef.Resolve(); } if (tdr == null) { return null; } tdr = tdr.ScopeType; if (tdr is TypeDef result2) { return result2; } if (tdr is TypeRef typeRef2) { return typeRef2.Resolve(); } return null; } public static TypeDef ResolveTypeDefThrow(this ITypeDefOrRef tdr) { if (tdr is TypeDef result) { return result; } if (tdr is TypeRef typeRef) { return typeRef.ResolveThrow(); } if (tdr == null) { throw new TypeResolveException("Can't resolve a null pointer"); } tdr = tdr.ScopeType; if (tdr is TypeDef result2) { return result2; } if (tdr is TypeRef typeRef2) { return typeRef2.ResolveThrow(); } throw new TypeResolveException($"Could not resolve type: {tdr} ({tdr?.DefinitionAssembly})"); } public static FieldDef ResolveFieldDef(this IField field) { if (field is FieldDef result) { return result; } if (field is MemberRef memberRef) { return memberRef.ResolveField(); } return null; } public static FieldDef ResolveFieldDefThrow(this IField field) { if (field is FieldDef result) { return result; } if (field is MemberRef memberRef) { return memberRef.ResolveFieldThrow(); } throw new MemberRefResolveException($"Could not resolve field: {field}"); } public static MethodDef ResolveMethodDef(this IMethod method) { if (method is MethodDef result) { return result; } if (method is MemberRef memberRef) { return memberRef.ResolveMethod(); } if (method is MethodSpec methodSpec) { if (methodSpec.Method is MethodDef result2) { return result2; } if (methodSpec.Method is MemberRef memberRef2) { return memberRef2.ResolveMethod(); } } return null; } public static MethodDef ResolveMethodDefThrow(this IMethod method) { if (method is MethodDef result) { return result; } if (method is MemberRef memberRef) { return memberRef.ResolveMethodThrow(); } if (method is MethodSpec methodSpec) { if (methodSpec.Method is MethodDef result2) { return result2; } if (methodSpec.Method is MemberRef memberRef2) { return memberRef2.ResolveMethodThrow(); } } throw new MemberRefResolveException($"Could not resolve method: {method}"); } internal static IAssembly GetDefinitionAssembly(this MemberRef mr) { if (mr == null) { return null; } IMemberRefParent memberRefParent = mr.Class; if (memberRefParent is ITypeDefOrRef typeDefOrRef) { return typeDefOrRef.DefinitionAssembly; } if (memberRefParent is ModuleRef) { return mr.Module?.Assembly; } if (memberRefParent is MethodDef methodDef) { return methodDef.DeclaringType?.DefinitionAssembly; } return null; } public static IList GetParams(this IMethod method) { return method?.MethodSig.GetParams(); } public static int GetParamCount(this IMethod method) { return method?.MethodSig.GetParamCount() ?? 0; } public static bool HasParams(this IMethod method) { return method.GetParamCount() > 0; } public static TypeSig GetParam(this IMethod method, int index) { IList list = method?.MethodSig.GetParams(); if (list == null || index < 0 || index >= list.Count) { return null; } return list[index]; } public static ITypeDefOrRef ToTypeDefOrRef(this TypeSig sig) { if (sig == null) { return null; } if (sig is TypeDefOrRefSig typeDefOrRefSig) { return typeDefOrRefSig.TypeDefOrRef; } ModuleDef module = sig.Module; if (module == null) { return new TypeSpecUser(sig); } return module.UpdateRowId(new TypeSpecUser(sig)); } internal static bool IsPrimitive(this IType tdr) { if (tdr == null) { return false; } if (!tdr.DefinitionAssembly.IsCorLib()) { return false; } switch (tdr.FullName) { case "System.Boolean": case "System.UIntPtr": case "System.Byte": case "System.Char": case "System.Int64": case "System.SByte": case "System.Int16": case "System.Int32": case "System.UInt64": case "System.Single": case "System.Double": case "System.IntPtr": case "System.UInt16": case "System.UInt32": return true; default: return false; } } public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, ITypeDefOrRef type) { CorLibTypeSig corLibTypeSig; if (type is TypeDef { DeclaringType: null } typeDef && (corLibTypeSig = self.GetCorLibTypeSig(typeDef.Namespace, typeDef.Name, typeDef.DefinitionAssembly)) != null) { return corLibTypeSig; } if (type is TypeRef typeRef && !(typeRef.ResolutionScope is TypeRef) && (corLibTypeSig = self.GetCorLibTypeSig(typeRef.Namespace, typeRef.Name, typeRef.DefinitionAssembly)) != null) { return corLibTypeSig; } return null; } public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, UTF8String @namespace, UTF8String name, IAssembly defAsm) { return self.GetCorLibTypeSig(UTF8String.ToSystemStringOrEmpty(@namespace), UTF8String.ToSystemStringOrEmpty(name), defAsm); } public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, string @namespace, string name, IAssembly defAsm) { if (@namespace != "System") { return null; } if (defAsm == null || !defAsm.IsCorLib()) { return null; } return name switch { "Void" => self.Void, "Boolean" => self.Boolean, "Char" => self.Char, "SByte" => self.SByte, "Byte" => self.Byte, "Int16" => self.Int16, "UInt16" => self.UInt16, "Int32" => self.Int32, "UInt32" => self.UInt32, "Int64" => self.Int64, "UInt64" => self.UInt64, "Single" => self.Single, "Double" => self.Double, "String" => self.String, "TypedReference" => self.TypedReference, "IntPtr" => self.IntPtr, "UIntPtr" => self.UIntPtr, "Object" => self.Object, _ => null, }; } public static void Error(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Error, "{0}", message); } public static void Error(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Error, message, arg1); } public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2); } public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3); } public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3, arg4); } public static void Error(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Error, message, args); } public static void Warning(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Warning, "{0}", message); } public static void Warning(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Warning, message, arg1); } public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2); } public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3); } public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3, arg4); } public static void Warning(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Warning, message, args); } public static void Info(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Info, "{0}", message); } public static void Info(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Info, message, arg1); } public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2); } public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3); } public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3, arg4); } public static void Info(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Info, message, args); } public static void Verbose(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Verbose, "{0}", message); } public static void Verbose(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Verbose, message, arg1); } public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2); } public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3); } public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3, arg4); } public static void Verbose(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Verbose, message, args); } public static void VeryVerbose(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.VeryVerbose, "{0}", message); } public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1); } public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2); } public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3); } public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3, arg4); } public static void VeryVerbose(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.VeryVerbose, message, args); } public static TypeDef Resolve(this ITypeResolver self, TypeRef typeRef) { return self.Resolve(typeRef, null); } public static TypeDef ResolveThrow(this ITypeResolver self, TypeRef typeRef) { return self.ResolveThrow(typeRef, null); } public static TypeDef ResolveThrow(this ITypeResolver self, TypeRef typeRef, ModuleDef sourceModule) { TypeDef typeDef = self.Resolve(typeRef, sourceModule); if (typeDef != null) { return typeDef; } throw new TypeResolveException($"Could not resolve type: {typeRef} ({typeRef?.DefinitionAssembly})"); } public static IMemberForwarded ResolveThrow(this IMemberRefResolver self, MemberRef memberRef) { IMemberForwarded memberForwarded = self.Resolve(memberRef); if (memberForwarded != null) { return memberForwarded; } throw new MemberRefResolveException($"Could not resolve method/field: {memberRef} ({memberRef?.GetDefinitionAssembly()})"); } public static FieldDef ResolveField(this IMemberRefResolver self, MemberRef memberRef) { return self.Resolve(memberRef) as FieldDef; } public static FieldDef ResolveFieldThrow(this IMemberRefResolver self, MemberRef memberRef) { if (self.Resolve(memberRef) is FieldDef result) { return result; } throw new MemberRefResolveException($"Could not resolve field: {memberRef} ({memberRef?.GetDefinitionAssembly()})"); } public static MethodDef ResolveMethod(this IMemberRefResolver self, MemberRef memberRef) { return self.Resolve(memberRef) as MethodDef; } public static MethodDef ResolveMethodThrow(this IMemberRefResolver self, MemberRef memberRef) { if (self.Resolve(memberRef) is MethodDef result) { return result; } throw new MemberRefResolveException($"Could not resolve method: {memberRef} ({memberRef?.GetDefinitionAssembly()})"); } public static IMDTokenProvider ResolveToken(this ITokenResolver self, uint token) { return self.ResolveToken(token, default(GenericParamContext)); } public static ITypeDefOrRef GetNonNestedTypeRefScope(this IType type) { if (type == null) { return null; } ITypeDefOrRef scopeType = type.ScopeType; TypeRef typeRef = scopeType as TypeRef; if (typeRef == null) { return scopeType; } for (int i = 0; i < 100; i++) { if (!(typeRef.ResolutionScope is TypeRef typeRef2)) { return typeRef; } typeRef = typeRef2; } return typeRef; } public static TypeDef FindThrow(this ITypeDefFinder self, TypeRef typeRef) { TypeDef typeDef = self.Find(typeRef); if (typeDef != null) { return typeDef; } throw new TypeResolveException($"Could not find type: {typeRef}"); } public static TypeDef FindThrow(this ITypeDefFinder self, string fullName, bool isReflectionName) { TypeDef typeDef = self.Find(fullName, isReflectionName); if (typeDef != null) { return typeDef; } throw new TypeResolveException("Could not find type: " + fullName); } public static TypeDef FindNormal(this ITypeDefFinder self, string fullName) { return self.Find(fullName, isReflectionName: false); } public static TypeDef FindNormalThrow(this ITypeDefFinder self, string fullName) { TypeDef typeDef = self.Find(fullName, isReflectionName: false); if (typeDef != null) { return typeDef; } throw new TypeResolveException("Could not find type: " + fullName); } public static TypeDef FindReflection(this ITypeDefFinder self, string fullName) { return self.Find(fullName, isReflectionName: true); } public static TypeDef FindReflectionThrow(this ITypeDefFinder self, string fullName) { TypeDef typeDef = self.Find(fullName, isReflectionName: true); if (typeDef != null) { return typeDef; } throw new TypeResolveException("Could not find type: " + fullName); } public static bool TypeExists(this ITypeDefFinder self, TypeRef typeRef) { return self.Find(typeRef) != null; } public static bool TypeExists(this ITypeDefFinder self, string fullName, bool isReflectionName) { return self.Find(fullName, isReflectionName) != null; } public static bool TypeExistsNormal(this ITypeDefFinder self, string fullName) { return self.Find(fullName, isReflectionName: false) != null; } public static bool TypeExistsReflection(this ITypeDefFinder self, string fullName) { return self.Find(fullName, isReflectionName: true) != null; } public static TypeSig RemoveModifiers(this TypeSig a) { if (a == null) { return null; } while (a is ModifierSig) { a = a.Next; } return a; } public static TypeSig RemovePinned(this TypeSig a) { if (!(a is PinnedSig pinnedSig)) { return a; } return pinnedSig.Next; } public static TypeSig RemovePinnedAndModifiers(this TypeSig a) { a = a.RemoveModifiers(); a = a.RemovePinned(); a = a.RemoveModifiers(); return a; } public static TypeDefOrRefSig ToTypeDefOrRefSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as TypeDefOrRefSig; } public static ClassOrValueTypeSig ToClassOrValueTypeSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ClassOrValueTypeSig; } public static ValueTypeSig ToValueTypeSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ValueTypeSig; } public static ClassSig ToClassSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ClassSig; } public static GenericSig ToGenericSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericSig; } public static GenericVar ToGenericVar(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericVar; } public static GenericMVar ToGenericMVar(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericMVar; } public static GenericInstSig ToGenericInstSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericInstSig; } public static PtrSig ToPtrSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as PtrSig; } public static ByRefSig ToByRefSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ByRefSig; } public static ArraySig ToArraySig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ArraySig; } public static SZArraySig ToSZArraySig(this TypeSig type) { return type.RemovePinnedAndModifiers() as SZArraySig; } public static TypeSig GetNext(this TypeSig self) { return self?.Next; } public static bool GetIsValueType(this TypeSig self) { return self?.IsValueType ?? false; } public static bool GetIsPrimitive(this TypeSig self) { return self?.IsPrimitive ?? false; } public static ElementType GetElementType(this TypeSig a) { return a?.ElementType ?? ElementType.End; } public static string GetFullName(this TypeSig a) { if (a != null) { return a.FullName; } return string.Empty; } public static string GetName(this TypeSig a) { if (a != null) { return a.TypeName; } return string.Empty; } public static string GetNamespace(this TypeSig a) { if (a != null) { return a.Namespace; } return string.Empty; } public static ITypeDefOrRef TryGetTypeDefOrRef(this TypeSig a) { return (a.RemovePinnedAndModifiers() as TypeDefOrRefSig)?.TypeDefOrRef; } public static TypeRef TryGetTypeRef(this TypeSig a) { return (a.RemovePinnedAndModifiers() as TypeDefOrRefSig)?.TypeRef; } public static TypeDef TryGetTypeDef(this TypeSig a) { return (a.RemovePinnedAndModifiers() as TypeDefOrRefSig)?.TypeDef; } public static TypeSpec TryGetTypeSpec(this TypeSig a) { return (a.RemovePinnedAndModifiers() as TypeDefOrRefSig)?.TypeSpec; } } [Flags] public enum AssemblyNameComparerFlags { Name = 1, Version = 2, PublicKeyToken = 4, Culture = 8, ContentType = 0x10, All = 0x1F } public readonly struct AssemblyNameComparer : IEqualityComparer { public static readonly AssemblyNameComparer CompareAll = new AssemblyNameComparer(AssemblyNameComparerFlags.All); public static readonly AssemblyNameComparer NameAndPublicKeyTokenOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name | AssemblyNameComparerFlags.PublicKeyToken); public static readonly AssemblyNameComparer NameOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name); private readonly AssemblyNameComparerFlags flags; public bool CompareName => (flags & AssemblyNameComparerFlags.Name) != 0; public bool CompareVersion => (flags & AssemblyNameComparerFlags.Version) != 0; public bool ComparePublicKeyToken => (flags & AssemblyNameComparerFlags.PublicKeyToken) != 0; public bool CompareCulture => (flags & AssemblyNameComparerFlags.Culture) != 0; public bool CompareContentType => (flags & AssemblyNameComparerFlags.ContentType) != 0; public AssemblyNameComparer(AssemblyNameComparerFlags flags) { this.flags = flags; } public int CompareTo(IAssembly a, IAssembly b) { if (a == b) { return 0; } if (a == null) { return -1; } if (b == null) { return 1; } int result; if (CompareName && (result = UTF8String.CaseInsensitiveCompareTo(a.Name, b.Name)) != 0) { return result; } if (CompareVersion && (result = Utils.CompareTo(a.Version, b.Version)) != 0) { return result; } if (ComparePublicKeyToken && (result = PublicKeyBase.TokenCompareTo(a.PublicKeyOrToken, b.PublicKeyOrToken)) != 0) { return result; } if (CompareCulture && (result = Utils.LocaleCompareTo(a.Culture, b.Culture)) != 0) { return result; } if (CompareContentType && (result = a.ContentType.CompareTo(b.ContentType)) != 0) { return result; } return 0; } public bool Equals(IAssembly a, IAssembly b) { return CompareTo(a, b) == 0; } public int CompareClosest(IAssembly requested, IAssembly a, IAssembly b) { if (a == b) { return 0; } if (a == null) { if (CompareName) { return UTF8String.CaseInsensitiveEquals(requested.Name, b.Name) ? 1 : 0; } return 1; } if (b == null) { if (CompareName) { return (!UTF8String.CaseInsensitiveEquals(requested.Name, a.Name)) ? 1 : 0; } return 0; } if (CompareName) { bool flag = UTF8String.CaseInsensitiveEquals(requested.Name, a.Name); bool flag2 = UTF8String.CaseInsensitiveEquals(requested.Name, b.Name); if (flag && !flag2) { return 0; } if (!flag && flag2) { return 1; } if (!flag && !flag2) { return -1; } } if (ComparePublicKeyToken) { bool flag3; bool flag4; if (PublicKeyBase.IsNullOrEmpty2(requested.PublicKeyOrToken)) { flag3 = PublicKeyBase.IsNullOrEmpty2(a.PublicKeyOrToken); flag4 = PublicKeyBase.IsNullOrEmpty2(b.PublicKeyOrToken); } else { flag3 = PublicKeyBase.TokenEquals(requested.PublicKeyOrToken, a.PublicKeyOrToken); flag4 = PublicKeyBase.TokenEquals(requested.PublicKeyOrToken, b.PublicKeyOrToken); } if (flag3 && !flag4) { return 0; } if (!flag3 && flag4) { return 1; } } if (CompareVersion && !Utils.Equals(a.Version, b.Version)) { Version version = Utils.CreateVersionWithNoUndefinedValues(requested.Version); if (version == new Version(0, 0, 0, 0)) { version = new Version(65535, 65535, 65535, 65535); } int num = Utils.CompareTo(a.Version, version); int num2 = Utils.CompareTo(b.Version, version); if (num == 0) { return 0; } if (num2 == 0) { return 1; } if (num > 0 && num2 < 0) { return 0; } if (num < 0 && num2 > 0) { return 1; } if (num > 0) { return (Utils.CompareTo(a.Version, b.Version) >= 0) ? 1 : 0; } return (Utils.CompareTo(a.Version, b.Version) <= 0) ? 1 : 0; } if (CompareCulture) { bool flag5 = Utils.LocaleEquals(requested.Culture, a.Culture); bool flag6 = Utils.LocaleEquals(requested.Culture, b.Culture); if (flag5 && !flag6) { return 0; } if (!flag5 && flag6) { return 1; } } if (CompareContentType) { bool flag7 = requested.ContentType == a.ContentType; bool flag8 = requested.ContentType == b.ContentType; if (flag7 && !flag8) { return 0; } if (!flag7 && flag8) { return 1; } } return -1; } public int GetHashCode(IAssembly a) { if (a == null) { return 0; } int num = 0; if (CompareName) { num += UTF8String.GetHashCode(a.Name); } if (CompareVersion) { num += Utils.CreateVersionWithNoUndefinedValues(a.Version).GetHashCode(); } if (ComparePublicKeyToken) { num += PublicKeyBase.GetHashCodeToken(a.PublicKeyOrToken); } if (CompareCulture) { num += Utils.GetHashCodeLocale(a.Culture); } if (CompareContentType) { num += (int)a.ContentType; } return num; } } public sealed class AssemblyNameInfo : IAssembly, IFullName { private AssemblyHashAlgorithm hashAlgId; private Version version; private AssemblyAttributes flags; private PublicKeyBase publicKeyOrToken; private UTF8String name; private UTF8String culture; public AssemblyHashAlgorithm HashAlgId { get { return hashAlgId; } set { hashAlgId = value; } } public Version Version { get { return version; } set { version = value; } } public AssemblyAttributes Attributes { get { return flags; } set { flags = value; } } public PublicKeyBase PublicKeyOrToken { get { return publicKeyOrToken; } set { publicKeyOrToken = value; } } public UTF8String Name { get { return name; } set { name = value; } } public UTF8String Culture { get { return culture; } set { culture = value; } } public string FullName => FullNameToken; public string FullNameToken => FullNameFactory.AssemblyFullName(this, withToken: true); public bool HasPublicKey { get { return (Attributes & AssemblyAttributes.PublicKey) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PublicKey); } } public AssemblyAttributes ProcessorArchitecture { get { return Attributes & AssemblyAttributes.PA_NoPlatform; } set { ModifyAttributes(~AssemblyAttributes.PA_NoPlatform, value & AssemblyAttributes.PA_NoPlatform); } } public AssemblyAttributes ProcessorArchitectureFull { get { return Attributes & AssemblyAttributes.PA_FullMask; } set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); } } public bool IsProcessorArchitectureNone => (Attributes & AssemblyAttributes.PA_NoPlatform) == 0; public bool IsProcessorArchitectureMSIL => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_MSIL; public bool IsProcessorArchitectureX86 => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_x86; public bool IsProcessorArchitectureIA64 => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_IA64; public bool IsProcessorArchitectureX64 => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_AMD64; public bool IsProcessorArchitectureARM => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_ARM; public bool IsProcessorArchitectureNoPlatform => (Attributes & AssemblyAttributes.PA_NoPlatform) == AssemblyAttributes.PA_NoPlatform; public bool IsProcessorArchitectureSpecified { get { return (Attributes & AssemblyAttributes.PA_Specified) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); } } public bool EnableJITcompileTracking { get { return (Attributes & AssemblyAttributes.EnableJITcompileTracking) != 0; } set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); } } public bool DisableJITcompileOptimizer { get { return (Attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0; } set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); } } public bool IsRetargetable { get { return (Attributes & AssemblyAttributes.Retargetable) != 0; } set { ModifyAttributes(value, AssemblyAttributes.Retargetable); } } public AssemblyAttributes ContentType { get { return Attributes & AssemblyAttributes.ContentType_Mask; } set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); } } public bool IsContentTypeDefault => (Attributes & AssemblyAttributes.ContentType_Mask) == 0; public bool IsContentTypeWindowsRuntime => (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime; private void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) { Attributes = (Attributes & andMask) | orMask; } private void ModifyAttributes(bool set, AssemblyAttributes flags) { if (set) { Attributes |= flags; } else { Attributes &= ~flags; } } public AssemblyNameInfo() { } public AssemblyNameInfo(string asmFullName) : this(ReflectionTypeNameParser.ParseAssemblyRef(asmFullName)) { } public AssemblyNameInfo(IAssembly asm) { if (asm != null) { hashAlgId = (asm as AssemblyDef)?.HashAlgorithm ?? AssemblyHashAlgorithm.None; version = asm.Version ?? new Version(0, 0, 0, 0); flags = asm.Attributes; publicKeyOrToken = asm.PublicKeyOrToken; name = (UTF8String.IsNullOrEmpty(asm.Name) ? UTF8String.Empty : asm.Name); culture = (UTF8String.IsNullOrEmpty(asm.Culture) ? UTF8String.Empty : asm.Culture); } } public AssemblyNameInfo(AssemblyName asmName) { if (asmName != null) { hashAlgId = (AssemblyHashAlgorithm)asmName.HashAlgorithm; version = asmName.Version ?? new Version(0, 0, 0, 0); flags = (AssemblyAttributes)asmName.Flags; publicKeyOrToken = (PublicKeyBase)(((object)PublicKeyBase.CreatePublicKey(asmName.GetPublicKey())) ?? ((object)PublicKeyBase.CreatePublicKeyToken(asmName.GetPublicKeyToken()))); name = asmName.Name ?? string.Empty; culture = ((asmName.CultureInfo != null && asmName.CultureInfo.Name != null) ? asmName.CultureInfo.Name : string.Empty); } } public override string ToString() { return FullName; } } public abstract class AssemblyRef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IImplementation, IFullName, IResolutionScope, IHasCustomDebugInformation, IAssembly, IScope { public static readonly AssemblyRef CurrentAssembly = new AssemblyRefUser("<<>>"); protected uint rid; protected Version version; protected int attributes; protected PublicKeyBase publicKeyOrToken; protected UTF8String name; protected UTF8String culture; protected byte[] hashValue; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.AssemblyRef, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 15; public int ImplementationTag => 1; public int ResolutionScopeTag => 2; public ScopeType ScopeType => ScopeType.AssemblyRef; public string ScopeName => FullName; public Version Version { get { return version; } set { version = value ?? throw new ArgumentNullException("value"); } } public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (int)value; } } public PublicKeyBase PublicKeyOrToken { get { return publicKeyOrToken; } set { publicKeyOrToken = value ?? throw new ArgumentNullException("value"); } } public UTF8String Name { get { return name; } set { name = value; } } public UTF8String Culture { get { return culture; } set { culture = value; } } public byte[] Hash { get { return hashValue; } set { hashValue = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 15; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public string FullName => FullNameToken; public string RealFullName => FullNameFactory.AssemblyFullName(this, withToken: false); public string FullNameToken => FullNameFactory.AssemblyFullName(this, withToken: true); public bool HasPublicKey { get { return (attributes & 1) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PublicKey); } } public AssemblyAttributes ProcessorArchitecture { get { return (AssemblyAttributes)(attributes & 0x70); } set { ModifyAttributes(~AssemblyAttributes.PA_NoPlatform, value & AssemblyAttributes.PA_NoPlatform); } } public AssemblyAttributes ProcessorArchitectureFull { get { return (AssemblyAttributes)(attributes & 0xF0); } set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); } } public bool IsProcessorArchitectureNone => (attributes & 0x70) == 0; public bool IsProcessorArchitectureMSIL => (attributes & 0x70) == 16; public bool IsProcessorArchitectureX86 => (attributes & 0x70) == 32; public bool IsProcessorArchitectureIA64 => (attributes & 0x70) == 48; public bool IsProcessorArchitectureX64 => (attributes & 0x70) == 64; public bool IsProcessorArchitectureARM => (attributes & 0x70) == 80; public bool IsProcessorArchitectureNoPlatform => (attributes & 0x70) == 112; public bool IsProcessorArchitectureSpecified { get { return (attributes & 0x80) != 0; } set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); } } public bool EnableJITcompileTracking { get { return (attributes & 0x8000) != 0; } set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); } } public bool DisableJITcompileOptimizer { get { return (attributes & 0x4000) != 0; } set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); } } public bool IsRetargetable { get { return (attributes & 0x100) != 0; } set { ModifyAttributes(value, AssemblyAttributes.Retargetable); } } public AssemblyAttributes ContentType { get { return (AssemblyAttributes)(attributes & 0xE00); } set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); } } public bool IsContentTypeDefault => (attributes & 0xE00) == 0; public bool IsContentTypeWindowsRuntime => (attributes & 0xE00) == 512; protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, AssemblyAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~flags); } } public override string ToString() { return FullName; } } public class AssemblyRefUser : AssemblyRef { public static AssemblyRefUser CreateMscorlibReferenceCLR10() { return new AssemblyRefUser("mscorlib", new Version(1, 0, 3300, 0), new PublicKeyToken("b77a5c561934e089")); } public static AssemblyRefUser CreateMscorlibReferenceCLR11() { return new AssemblyRefUser("mscorlib", new Version(1, 0, 5000, 0), new PublicKeyToken("b77a5c561934e089")); } public static AssemblyRefUser CreateMscorlibReferenceCLR20() { return new AssemblyRefUser("mscorlib", new Version(2, 0, 0, 0), new PublicKeyToken("b77a5c561934e089")); } public static AssemblyRefUser CreateMscorlibReferenceCLR40() { return new AssemblyRefUser("mscorlib", new Version(4, 0, 0, 0), new PublicKeyToken("b77a5c561934e089")); } public AssemblyRefUser() : this(UTF8String.Empty) { } public AssemblyRefUser(UTF8String name) : this(name, new Version(0, 0, 0, 0)) { } public AssemblyRefUser(UTF8String name, Version version) : this(name, version, new PublicKey()) { } public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey) : this(name, version, publicKey, UTF8String.Empty) { } public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey, UTF8String locale) { if ((object)name == null) { throw new ArgumentNullException("name"); } if ((object)locale == null) { throw new ArgumentNullException("locale"); } base.name = name; base.version = version ?? throw new ArgumentNullException("version"); publicKeyOrToken = publicKey; culture = locale; attributes = ((publicKey is PublicKey) ? 1 : 0); } public AssemblyRefUser(AssemblyName asmName) : this(new AssemblyNameInfo(asmName)) { attributes = (int)asmName.Flags; } public AssemblyRefUser(IAssembly assembly) { if (assembly == null) { throw new ArgumentNullException("asmName"); } version = assembly.Version ?? new Version(0, 0, 0, 0); publicKeyOrToken = assembly.PublicKeyOrToken; name = (UTF8String.IsNullOrEmpty(assembly.Name) ? UTF8String.Empty : assembly.Name); culture = assembly.Culture; attributes = ((publicKeyOrToken is PublicKey) ? 1 : 0) | (int)assembly.ContentType; } } internal sealed class AssemblyRefMD : AssemblyRef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.AssemblyRef, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public AssemblyRefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadAssemblyRefRow(origRid, out var row); version = new Version(row.MajorVersion, row.MinorVersion, row.BuildNumber, row.RevisionNumber); attributes = (int)row.Flags; byte[] data = readerModule.BlobStream.Read(row.PublicKeyOrToken); if (((ulong)attributes & 1uL) != 0L) { publicKeyOrToken = new PublicKey(data); } else { publicKeyOrToken = new PublicKeyToken(data); } name = readerModule.StringsStream.ReadNoNull(row.Name); culture = readerModule.StringsStream.ReadNoNull(row.Locale); hashValue = readerModule.BlobStream.Read(row.HashValue); } } public class AssemblyResolver : IAssemblyResolver { private sealed class GacInfo { public readonly int Version; public readonly string Path; public readonly string Prefix; public readonly string[] SubDirs; public GacInfo(int version, string prefix, string path, string[] subDirs) { Version = version; Prefix = prefix; Path = path; SubDirs = subDirs; } } private static readonly ModuleDef nullModule; private static readonly string[] assemblyExtensions; private static readonly string[] winMDAssemblyExtensions; private static readonly List gacInfos; private static readonly string[] extraMonoPaths; private static readonly string[] monoVerDirs; private ModuleContext defaultModuleContext; private readonly Dictionary> moduleSearchPaths = new Dictionary>(); private readonly Dictionary cachedAssemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly List preSearchPaths = new List(); private readonly List postSearchPaths = new List(); private bool findExactMatch; private bool enableFrameworkRedirect; private bool enableTypeDefCache = true; private bool useGac = true; private readonly Lock theLock = Lock.Create(); public ModuleContext DefaultModuleContext { get { return defaultModuleContext; } set { defaultModuleContext = value; } } public bool FindExactMatch { get { return findExactMatch; } set { findExactMatch = value; } } public bool EnableFrameworkRedirect { get { return enableFrameworkRedirect; } set { enableFrameworkRedirect = value; } } public bool EnableTypeDefCache { get { return enableTypeDefCache; } set { enableTypeDefCache = value; } } public bool UseGAC { get { return useGac; } set { useGac = value; } } public IList PreSearchPaths => preSearchPaths; public IList PostSearchPaths => postSearchPaths; static AssemblyResolver() { nullModule = new ModuleDefUser(); assemblyExtensions = new string[2] { ".dll", ".exe" }; winMDAssemblyExtensions = new string[1] { ".winmd" }; monoVerDirs = new string[14] { "4.5", "4.5\\Facades", "4.5-api", "4.5-api\\Facades", "4.0", "4.0-api", "3.5", "3.5-api", "3.0", "3.0-api", "2.0", "2.0-api", "1.1", "1.0" }; gacInfos = new List(); if ((object)Type.GetType("Mono.Runtime") != null) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); List list = new List(); foreach (string item in FindMonoPrefixes()) { string text = Path.Combine(Path.Combine(Path.Combine(item, "lib"), "mono"), "gac"); if (dictionary.ContainsKey(text)) { continue; } dictionary[text] = true; if (Directory.Exists(text)) { gacInfos.Add(new GacInfo(-1, "", Path.GetDirectoryName(text), new string[1] { Path.GetFileName(text) })); } text = Path.GetDirectoryName(text); string[] array = monoVerDirs; foreach (string obj in array) { string text2 = text; string[] array2 = obj.Split(new char[1] { '\\' }); foreach (string path in array2) { text2 = Path.Combine(text2, path); } if (Directory.Exists(text2)) { list.Add(text2); } } } string environmentVariable = Environment.GetEnvironmentVariable("MONO_PATH"); if (environmentVariable != null) { string[] array = environmentVariable.Split(Path.PathSeparator); for (int i = 0; i < array.Length; i++) { string text3 = array[i].Trim(); if (text3 != string.Empty && Directory.Exists(text3)) { list.Add(text3); } } } extraMonoPaths = list.ToArray(); return; } string environmentVariable2 = Environment.GetEnvironmentVariable("WINDIR"); if (!string.IsNullOrEmpty(environmentVariable2)) { string path2 = Path.Combine(environmentVariable2, "assembly"); if (Directory.Exists(path2)) { gacInfos.Add(new GacInfo(2, "", path2, new string[4] { "GAC_32", "GAC_64", "GAC_MSIL", "GAC" })); } path2 = Path.Combine(Path.Combine(environmentVariable2, "Microsoft.NET"), "assembly"); if (Directory.Exists(path2)) { gacInfos.Add(new GacInfo(4, "v4.0_", path2, new string[3] { "GAC_32", "GAC_64", "GAC_MSIL" })); } } } private static string GetCurrentMonoPrefix() { string text = typeof(object).Module.FullyQualifiedName; for (int i = 0; i < 4; i++) { text = Path.GetDirectoryName(text); } return text; } private static IEnumerable FindMonoPrefixes() { yield return GetCurrentMonoPrefix(); string environmentVariable = Environment.GetEnvironmentVariable("MONO_GAC_PREFIX"); if (string.IsNullOrEmpty(environmentVariable)) { yield break; } string[] array = environmentVariable.Split(Path.PathSeparator); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text != string.Empty) { yield return text; } } } public AssemblyResolver() : this(null) { } public AssemblyResolver(ModuleContext defaultModuleContext) { this.defaultModuleContext = defaultModuleContext; enableFrameworkRedirect = true; } public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) { if (assembly == null) { return null; } if (EnableFrameworkRedirect && !FindExactMatch) { FrameworkRedirect.ApplyFrameworkRedirect(ref assembly, sourceModule); } theLock.EnterWriteLock(); try { AssemblyDef assemblyDef = Resolve2(assembly, sourceModule); if (assemblyDef == null) { string text = UTF8String.ToSystemStringOrEmpty(assembly.Name); string text2 = text.Trim(); if (text != text2) { assembly = new AssemblyNameInfo { Name = text2, Version = assembly.Version, PublicKeyOrToken = assembly.PublicKeyOrToken, Culture = assembly.Culture }; assemblyDef = Resolve2(assembly, sourceModule); } } if (assemblyDef == null) { cachedAssemblies[GetAssemblyNameKey(assembly)] = null; return null; } string assemblyNameKey = GetAssemblyNameKey(assemblyDef); string assemblyNameKey2 = GetAssemblyNameKey(assembly); cachedAssemblies.TryGetValue(assemblyNameKey, out var value); cachedAssemblies.TryGetValue(assemblyNameKey2, out var value2); if (value != assemblyDef && value2 != assemblyDef && enableTypeDefCache) { IList modules = assemblyDef.Modules; int count = modules.Count; for (int i = 0; i < count; i++) { ModuleDef moduleDef = modules[i]; if (moduleDef != null) { moduleDef.EnableTypeDefFindCache = true; } } } bool flag = false; if (!cachedAssemblies.ContainsKey(assemblyNameKey)) { cachedAssemblies.Add(assemblyNameKey, assemblyDef); flag = true; } if (!cachedAssemblies.ContainsKey(assemblyNameKey2)) { cachedAssemblies.Add(assemblyNameKey2, assemblyDef); flag = true; } if (flag || value == assemblyDef || value2 == assemblyDef) { return assemblyDef; } assemblyDef.ManifestModule?.Dispose(); return value ?? value2; } finally { theLock.ExitWriteLock(); } } public bool AddToCache(ModuleDef module) { if (module != null) { return AddToCache(module.Assembly); } return false; } public bool AddToCache(AssemblyDef asm) { if (asm == null) { return false; } string assemblyNameKey = GetAssemblyNameKey(asm); theLock.EnterWriteLock(); try { if (cachedAssemblies.TryGetValue(assemblyNameKey, out var value) && value != null) { return asm == value; } cachedAssemblies[assemblyNameKey] = asm; return true; } finally { theLock.ExitWriteLock(); } } public bool Remove(ModuleDef module) { if (module != null) { return Remove(module.Assembly); } return false; } public bool Remove(AssemblyDef asm) { if (asm == null) { return false; } string assemblyNameKey = GetAssemblyNameKey(asm); theLock.EnterWriteLock(); try { ModuleDef manifestModule = asm.ManifestModule; if (manifestModule != null) { moduleSearchPaths.Remove(manifestModule); } return cachedAssemblies.Remove(assemblyNameKey); } finally { theLock.ExitWriteLock(); } } public void Clear() { theLock.EnterWriteLock(); List list; try { list = new List(cachedAssemblies.Values); cachedAssemblies.Clear(); moduleSearchPaths.Clear(); } finally { theLock.ExitWriteLock(); } foreach (AssemblyDef item in list) { if (item == null) { continue; } foreach (ModuleDef module in item.Modules) { module.Dispose(); } } } public IEnumerable GetCachedAssemblies() { theLock.EnterReadLock(); try { return cachedAssemblies.Values.ToArray(); } finally { theLock.ExitReadLock(); } } private static string GetAssemblyNameKey(IAssembly asmName) { return asmName.FullNameToken; } private AssemblyDef Resolve2(IAssembly assembly, ModuleDef sourceModule) { if (cachedAssemblies.TryGetValue(GetAssemblyNameKey(assembly), out var value)) { return value; } ModuleContext context = defaultModuleContext; if (context == null && sourceModule != null) { context = sourceModule.Context; } value = FindExactAssembly(assembly, PreFindAssemblies(assembly, sourceModule, matchExactly: true), context) ?? FindExactAssembly(assembly, FindAssemblies(assembly, sourceModule, matchExactly: true), context) ?? FindExactAssembly(assembly, PostFindAssemblies(assembly, sourceModule, matchExactly: true), context); if (value != null) { return value; } if (!findExactMatch) { value = FindClosestAssembly(assembly); value = FindClosestAssembly(assembly, value, PreFindAssemblies(assembly, sourceModule, matchExactly: false), context); value = FindClosestAssembly(assembly, value, FindAssemblies(assembly, sourceModule, matchExactly: false), context); value = FindClosestAssembly(assembly, value, PostFindAssemblies(assembly, sourceModule, matchExactly: false), context); } return value; } private AssemblyDef FindExactAssembly(IAssembly assembly, IEnumerable paths, ModuleContext moduleContext) { if (paths == null) { return null; } AssemblyNameComparer compareAll = AssemblyNameComparer.CompareAll; foreach (string path in paths) { ModuleDefMD moduleDefMD = null; try { moduleDefMD = ModuleDefMD.Load(path, moduleContext); AssemblyDef assembly2 = moduleDefMD.Assembly; if (assembly2 != null && compareAll.Equals(assembly, assembly2)) { moduleDefMD = null; return assembly2; } } catch { } finally { moduleDefMD?.Dispose(); } } return null; } private AssemblyDef FindClosestAssembly(IAssembly assembly) { AssemblyDef assemblyDef = null; AssemblyNameComparer compareAll = AssemblyNameComparer.CompareAll; foreach (KeyValuePair cachedAssembly in cachedAssemblies) { AssemblyDef value = cachedAssembly.Value; if (value != null && compareAll.CompareClosest(assembly, assemblyDef, value) == 1) { assemblyDef = value; } } return assemblyDef; } private AssemblyDef FindClosestAssembly(IAssembly assembly, AssemblyDef closest, IEnumerable paths, ModuleContext moduleContext) { if (paths == null) { return closest; } AssemblyNameComparer compareAll = AssemblyNameComparer.CompareAll; foreach (string path in paths) { ModuleDefMD moduleDefMD = null; try { moduleDefMD = ModuleDefMD.Load(path, moduleContext); AssemblyDef assembly2 = moduleDefMD.Assembly; if (assembly2 != null && compareAll.CompareClosest(assembly, closest, assembly2) == 1) { if (!IsCached(closest)) { closest?.ManifestModule?.Dispose(); } closest = assembly2; moduleDefMD = null; } } catch { } finally { moduleDefMD?.Dispose(); } } return closest; } private bool IsCached(AssemblyDef asm) { if (asm == null) { return false; } if (cachedAssemblies.TryGetValue(GetAssemblyNameKey(asm), out var value)) { return value == asm; } return false; } private IEnumerable FindAssemblies2(IAssembly assembly, IEnumerable paths) { if (paths == null) { yield break; } string asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name); string[] array = (assembly.IsContentTypeWindowsRuntime ? winMDAssemblyExtensions : assemblyExtensions); string[] array2 = array; foreach (string ext in array2) { foreach (string path in paths) { string text; try { text = Path.Combine(path, asmSimpleName + ext); } catch (ArgumentException) { yield break; } if (File.Exists(text)) { yield return text; } } } } protected virtual IEnumerable PreFindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { foreach (string item in FindAssemblies2(assembly, preSearchPaths)) { yield return item; } } protected virtual IEnumerable PostFindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { foreach (string item in FindAssemblies2(assembly, postSearchPaths)) { yield return item; } } protected virtual IEnumerable FindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { if (assembly.IsContentTypeWindowsRuntime) { string text; try { text = Path.Combine(Path.Combine(Environment.SystemDirectory, "WinMetadata"), string.Concat(assembly.Name, ".winmd")); } catch (ArgumentException) { text = null; } if (File.Exists(text)) { yield return text; } } else if (UseGAC) { foreach (string item in FindAssembliesGac(assembly, sourceModule, matchExactly)) { yield return item; } } foreach (string item2 in FindAssembliesModuleSearchPaths(assembly, sourceModule, matchExactly)) { yield return item2; } } private IEnumerable FindAssembliesGac(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { if (matchExactly) { return FindAssembliesGacExactly(assembly, sourceModule); } return FindAssembliesGacAny(assembly, sourceModule); } private IEnumerable GetGacInfos(ModuleDef sourceModule) { int version = ((sourceModule == null) ? int.MinValue : (sourceModule.IsClr40 ? 4 : 2)); foreach (GacInfo gacInfo in gacInfos) { if (gacInfo.Version == version) { yield return gacInfo; } } foreach (GacInfo gacInfo2 in gacInfos) { if (gacInfo2.Version != version) { yield return gacInfo2; } } } private IEnumerable FindAssembliesGacExactly(IAssembly assembly, ModuleDef sourceModule) { foreach (GacInfo gacInfo in GetGacInfos(sourceModule)) { foreach (string item in FindAssembliesGacExactly(gacInfo, assembly, sourceModule)) { yield return item; } } if (extraMonoPaths == null) { yield break; } foreach (string extraMonoPath in GetExtraMonoPaths(assembly, sourceModule)) { yield return extraMonoPath; } } private static IEnumerable GetExtraMonoPaths(IAssembly assembly, ModuleDef sourceModule) { if (extraMonoPaths == null) { yield break; } string[] array = extraMonoPaths; foreach (string path in array) { string text; try { text = Path.Combine(path, string.Concat(assembly.Name, ".dll")); } catch (ArgumentException) { break; } if (File.Exists(text)) { yield return text; } } } private IEnumerable FindAssembliesGacExactly(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) { PublicKeyToken publicKeyToken = PublicKeyBase.ToPublicKeyToken(assembly.PublicKeyOrToken); if (gacInfo == null || publicKeyToken == null) { yield break; } string pktString = publicKeyToken.ToString(); string verString = Utils.CreateVersionWithNoUndefinedValues(assembly.Version).ToString(); string cultureString = UTF8String.ToSystemStringOrEmpty(assembly.Culture); if (cultureString.Equals("neutral", StringComparison.OrdinalIgnoreCase)) { cultureString = string.Empty; } string asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name); string[] subDirs = gacInfo.SubDirs; foreach (string path in subDirs) { string path2 = Path.Combine(gacInfo.Path, path); try { path2 = Path.Combine(path2, asmSimpleName); } catch (ArgumentException) { break; } path2 = Path.Combine(path2, $"{gacInfo.Prefix}{verString}_{cultureString}_{pktString}"); string text = Path.Combine(path2, asmSimpleName + ".dll"); if (File.Exists(text)) { yield return text; } } } private IEnumerable FindAssembliesGacAny(IAssembly assembly, ModuleDef sourceModule) { foreach (GacInfo gacInfo in GetGacInfos(sourceModule)) { foreach (string item in FindAssembliesGacAny(gacInfo, assembly, sourceModule)) { yield return item; } } if (extraMonoPaths == null) { yield break; } foreach (string extraMonoPath in GetExtraMonoPaths(assembly, sourceModule)) { yield return extraMonoPath; } } private IEnumerable FindAssembliesGacAny(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) { if (gacInfo == null) { yield break; } string asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name); string[] subDirs = gacInfo.SubDirs; foreach (string path in subDirs) { string path2 = Path.Combine(gacInfo.Path, path); try { path2 = Path.Combine(path2, asmSimpleName); } catch (ArgumentException) { break; } foreach (string dir in GetDirs(path2)) { string text = Path.Combine(dir, asmSimpleName + ".dll"); if (File.Exists(text)) { yield return text; } } } } private IEnumerable GetDirs(string baseDir) { if (!Directory.Exists(baseDir)) { return Array2.Empty(); } List list = new List(); try { DirectoryInfo[] directories = new DirectoryInfo(baseDir).GetDirectories(); foreach (DirectoryInfo directoryInfo in directories) { list.Add(directoryInfo.FullName); } } catch { } return list; } private IEnumerable FindAssembliesModuleSearchPaths(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { string asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name); IEnumerable searchPaths = GetSearchPaths(sourceModule); string[] array = (assembly.IsContentTypeWindowsRuntime ? winMDAssemblyExtensions : assemblyExtensions); string[] array2 = array; foreach (string ext in array2) { foreach (string path in searchPaths) { for (int j = 0; j < 2; j++) { string text; try { text = ((j != 0) ? Path.Combine(Path.Combine(path, asmSimpleName), asmSimpleName + ext) : Path.Combine(path, asmSimpleName + ext)); } catch (ArgumentException) { yield break; } if (File.Exists(text)) { yield return text; } } } } } private IEnumerable GetSearchPaths(ModuleDef module) { ModuleDef moduleDef = module; if (moduleDef == null) { moduleDef = nullModule; } if (moduleSearchPaths.TryGetValue(moduleDef, out var value)) { return value; } return moduleSearchPaths[moduleDef] = new List(GetModuleSearchPaths(module)); } protected virtual IEnumerable GetModuleSearchPaths(ModuleDef module) { return GetModulePrivateSearchPaths(module); } protected IEnumerable GetModulePrivateSearchPaths(ModuleDef module) { if (module == null) { return Array2.Empty(); } AssemblyDef assembly = module.Assembly; if (assembly == null) { return Array2.Empty(); } module = assembly.ManifestModule; if (module == null) { return Array2.Empty(); } string text = null; try { string location = module.Location; if (location != string.Empty) { DirectoryInfo parent = Directory.GetParent(location); if (parent != null) { text = parent.FullName; string text2 = location + ".config"; if (File.Exists(text2)) { return GetPrivatePaths(text, text2); } } } } catch { } if (text != null) { return new List { text }; } return Array2.Empty(); } private IEnumerable GetPrivatePaths(string baseDir, string configFileName) { List list = new List(); try { string directoryName = Path.GetDirectoryName(Path.GetFullPath(configFileName)); list.Add(directoryName); using FileStream input = new FileStream(configFileName, FileMode.Open, FileAccess.Read, FileShare.Read); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(XmlReader.Create(input)); foreach (object item in xmlDocument.GetElementsByTagName("probing")) { if (!(item is XmlElement xmlElement)) { continue; } string attribute = xmlElement.GetAttribute("privatePath"); if (string.IsNullOrEmpty(attribute)) { continue; } string[] array = attribute.Split(';'); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!(text == "")) { string fullPath = Path.GetFullPath(Path.Combine(directoryName, text.Replace('\\', Path.DirectorySeparatorChar))); if (Directory.Exists(fullPath) && fullPath.StartsWith(baseDir + Path.DirectorySeparatorChar)) { list.Add(fullPath); } } } } } catch (ArgumentException) { } catch (IOException) { } catch (XmlException) { } return list; } } [Flags] public enum CallingConvention : byte { Default = 0, C = 1, StdCall = 2, ThisCall = 3, FastCall = 4, VarArg = 5, Field = 6, LocalSig = 7, Property = 8, Unmanaged = 9, GenericInst = 0xA, NativeVarArg = 0xB, Mask = 0xF, Generic = 0x10, HasThis = 0x20, ExplicitThis = 0x40, ReservedByCLR = 0x80 } public abstract class CallingConventionSig : IContainsGenericParameter { protected CallingConvention callingConvention; private byte[] extraData; public byte[] ExtraData { get { return extraData; } set { extraData = value; } } public bool IsDefault => (callingConvention & CallingConvention.Mask) == 0; public bool IsC => (callingConvention & CallingConvention.Mask) == CallingConvention.C; public bool IsStdCall => (callingConvention & CallingConvention.Mask) == CallingConvention.StdCall; public bool IsThisCall => (callingConvention & CallingConvention.Mask) == CallingConvention.ThisCall; public bool IsFastCall => (callingConvention & CallingConvention.Mask) == CallingConvention.FastCall; public bool IsVarArg => (callingConvention & CallingConvention.Mask) == CallingConvention.VarArg; public bool IsField => (callingConvention & CallingConvention.Mask) == CallingConvention.Field; public bool IsLocalSig => (callingConvention & CallingConvention.Mask) == CallingConvention.LocalSig; public bool IsProperty => (callingConvention & CallingConvention.Mask) == CallingConvention.Property; public bool IsUnmanaged => (callingConvention & CallingConvention.Mask) == CallingConvention.Unmanaged; public bool IsGenericInst => (callingConvention & CallingConvention.Mask) == CallingConvention.GenericInst; public bool IsNativeVarArg => (callingConvention & CallingConvention.Mask) == CallingConvention.NativeVarArg; public bool Generic { get { return (callingConvention & CallingConvention.Generic) != 0; } set { if (value) { callingConvention |= CallingConvention.Generic; } else { callingConvention &= ~CallingConvention.Generic; } } } public bool HasThis { get { return (callingConvention & CallingConvention.HasThis) != 0; } set { if (value) { callingConvention |= CallingConvention.HasThis; } else { callingConvention &= ~CallingConvention.HasThis; } } } public bool ExplicitThis { get { return (callingConvention & CallingConvention.ExplicitThis) != 0; } set { if (value) { callingConvention |= CallingConvention.ExplicitThis; } else { callingConvention &= ~CallingConvention.ExplicitThis; } } } public bool ReservedByCLR { get { return (callingConvention & CallingConvention.ReservedByCLR) != 0; } set { if (value) { callingConvention |= CallingConvention.ReservedByCLR; } else { callingConvention &= ~CallingConvention.ReservedByCLR; } } } public bool ImplicitThis { get { if (HasThis) { return !ExplicitThis; } return false; } } public bool ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected CallingConventionSig() { } protected CallingConventionSig(CallingConvention callingConvention) { this.callingConvention = callingConvention; } public CallingConvention GetCallingConvention() { return callingConvention; } } public sealed class FieldSig : CallingConventionSig { private TypeSig type; public TypeSig Type { get { return type; } set { type = value; } } public FieldSig() { callingConvention = CallingConvention.Field; } public FieldSig(TypeSig type) { callingConvention = CallingConvention.Field; this.type = type; } internal FieldSig(CallingConvention callingConvention, TypeSig type) { base.callingConvention = callingConvention; this.type = type; } public FieldSig Clone() { return new FieldSig(callingConvention, type); } public override string ToString() { return FullNameFactory.FullName(type, isReflection: false); } } public abstract class MethodBaseSig : CallingConventionSig { protected TypeSig retType; protected IList parameters; protected uint genParamCount; protected IList paramsAfterSentinel; public CallingConvention CallingConvention { get { return callingConvention; } set { callingConvention = value; } } public TypeSig RetType { get { return retType; } set { retType = value; } } public IList Params => parameters; public uint GenParamCount { get { return genParamCount; } set { genParamCount = value; } } public IList ParamsAfterSentinel { get { return paramsAfterSentinel; } set { paramsAfterSentinel = value; } } } public sealed class MethodSig : MethodBaseSig { private uint origToken; public uint OriginalToken { get { return origToken; } set { origToken = value; } } public static MethodSig CreateStatic(TypeSig retType) { return new MethodSig(CallingConvention.Default, 0u, retType); } public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1) { return new MethodSig(CallingConvention.Default, 0u, retType, argType1); } public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) { return new MethodSig(CallingConvention.Default, 0u, retType, argType1, argType2); } public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new MethodSig(CallingConvention.Default, 0u, retType, argType1, argType2, argType3); } public static MethodSig CreateStatic(TypeSig retType, params TypeSig[] argTypes) { return new MethodSig(CallingConvention.Default, 0u, retType, argTypes); } public static MethodSig CreateInstance(TypeSig retType) { return new MethodSig(CallingConvention.HasThis, 0u, retType); } public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1) { return new MethodSig(CallingConvention.HasThis, 0u, retType, argType1); } public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) { return new MethodSig(CallingConvention.HasThis, 0u, retType, argType1, argType2); } public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new MethodSig(CallingConvention.HasThis, 0u, retType, argType1, argType2, argType3); } public static MethodSig CreateInstance(TypeSig retType, params TypeSig[] argTypes) { return new MethodSig(CallingConvention.HasThis, 0u, retType, argTypes); } public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType) { return new MethodSig(CallingConvention.Generic, genParamCount, retType); } public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) { return new MethodSig(CallingConvention.Generic, genParamCount, retType, argType1); } public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) { return new MethodSig(CallingConvention.Generic, genParamCount, retType, argType1, argType2); } public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new MethodSig(CallingConvention.Generic, genParamCount, retType, argType1, argType2, argType3); } public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) { return new MethodSig(CallingConvention.Generic, genParamCount, retType, argTypes); } public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType) { return new MethodSig(CallingConvention.Generic | CallingConvention.HasThis, genParamCount, retType); } public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) { return new MethodSig(CallingConvention.Generic | CallingConvention.HasThis, genParamCount, retType, argType1); } public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) { return new MethodSig(CallingConvention.Generic | CallingConvention.HasThis, genParamCount, retType, argType1, argType2); } public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new MethodSig(CallingConvention.Generic | CallingConvention.HasThis, genParamCount, retType, argType1, argType2, argType3); } public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) { return new MethodSig(CallingConvention.Generic | CallingConvention.HasThis, genParamCount, retType, argTypes); } public MethodSig() { parameters = new List(); } public MethodSig(CallingConvention callingConvention) { base.callingConvention = callingConvention; parameters = new List(); } public MethodSig(CallingConvention callingConvention, uint genParamCount) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; parameters = new List(); } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List(); } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List { argType1 }; } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List { argType1, argType2 }; } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List { argType1, argType2, argType3 }; } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, params TypeSig[] argTypes) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List(argTypes); } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List(argTypes); } public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes, IList paramsAfterSentinel) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List(argTypes); base.paramsAfterSentinel = ((paramsAfterSentinel == null) ? null : new List(paramsAfterSentinel)); } public MethodSig Clone() { return new MethodSig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel); } public override string ToString() { return FullNameFactory.MethodBaseSigFullName(this); } } public sealed class PropertySig : MethodBaseSig { public static PropertySig CreateStatic(TypeSig retType) { return new PropertySig(hasThis: false, retType); } public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1) { return new PropertySig(hasThis: false, retType, argType1); } public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) { return new PropertySig(hasThis: false, retType, argType1, argType2); } public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new PropertySig(hasThis: false, retType, argType1, argType2, argType3); } public static PropertySig CreateStatic(TypeSig retType, params TypeSig[] argTypes) { return new PropertySig(hasThis: false, retType, argTypes); } public static PropertySig CreateInstance(TypeSig retType) { return new PropertySig(hasThis: true, retType); } public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1) { return new PropertySig(hasThis: true, retType, argType1); } public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) { return new PropertySig(hasThis: true, retType, argType1, argType2); } public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { return new PropertySig(hasThis: true, retType, argType1, argType2, argType3); } public static PropertySig CreateInstance(TypeSig retType, params TypeSig[] argTypes) { return new PropertySig(hasThis: true, retType, argTypes); } public PropertySig() { callingConvention = CallingConvention.Property; parameters = new List(); } internal PropertySig(CallingConvention callingConvention) { base.callingConvention = callingConvention; parameters = new List(); } public PropertySig(bool hasThis) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); parameters = new List(); } public PropertySig(bool hasThis, TypeSig retType) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); base.retType = retType; parameters = new List(); } public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); base.retType = retType; parameters = new List { argType1 }; } public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argType2) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); base.retType = retType; parameters = new List { argType1, argType2 }; } public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); base.retType = retType; parameters = new List { argType1, argType2, argType3 }; } public PropertySig(bool hasThis, TypeSig retType, params TypeSig[] argTypes) { callingConvention = (CallingConvention)(8 | (hasThis ? 32 : 0)); base.retType = retType; parameters = new List(argTypes); } internal PropertySig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes, IList paramsAfterSentinel) { base.callingConvention = callingConvention; base.genParamCount = genParamCount; base.retType = retType; parameters = new List(argTypes); base.paramsAfterSentinel = ((paramsAfterSentinel == null) ? null : new List(paramsAfterSentinel)); } public PropertySig Clone() { return new PropertySig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel); } public override string ToString() { return FullNameFactory.MethodBaseSigFullName(this); } } public sealed class LocalSig : CallingConventionSig { private readonly IList locals; public IList Locals => locals; public LocalSig() { callingConvention = CallingConvention.LocalSig; locals = new List(); } internal LocalSig(CallingConvention callingConvention, uint count) { base.callingConvention = callingConvention; locals = new List((int)count); } public LocalSig(TypeSig local1) { callingConvention = CallingConvention.LocalSig; locals = new List { local1 }; } public LocalSig(TypeSig local1, TypeSig local2) { callingConvention = CallingConvention.LocalSig; locals = new List { local1, local2 }; } public LocalSig(TypeSig local1, TypeSig local2, TypeSig local3) { callingConvention = CallingConvention.LocalSig; locals = new List { local1, local2, local3 }; } public LocalSig(params TypeSig[] locals) { callingConvention = CallingConvention.LocalSig; this.locals = new List(locals); } public LocalSig(IList locals) { callingConvention = CallingConvention.LocalSig; this.locals = new List(locals); } internal LocalSig(IList locals, bool dummy) { callingConvention = CallingConvention.LocalSig; this.locals = locals; } public LocalSig Clone() { return new LocalSig(locals); } } public sealed class GenericInstMethodSig : CallingConventionSig { private readonly IList genericArgs; public IList GenericArguments => genericArgs; public GenericInstMethodSig() { callingConvention = CallingConvention.GenericInst; genericArgs = new List(); } internal GenericInstMethodSig(CallingConvention callingConvention, uint size) { base.callingConvention = callingConvention; genericArgs = new List((int)size); } public GenericInstMethodSig(TypeSig arg1) { callingConvention = CallingConvention.GenericInst; genericArgs = new List { arg1 }; } public GenericInstMethodSig(TypeSig arg1, TypeSig arg2) { callingConvention = CallingConvention.GenericInst; genericArgs = new List { arg1, arg2 }; } public GenericInstMethodSig(TypeSig arg1, TypeSig arg2, TypeSig arg3) { callingConvention = CallingConvention.GenericInst; genericArgs = new List { arg1, arg2, arg3 }; } public GenericInstMethodSig(params TypeSig[] args) { callingConvention = CallingConvention.GenericInst; genericArgs = new List(args); } public GenericInstMethodSig(IList args) { callingConvention = CallingConvention.GenericInst; genericArgs = new List(args); } public GenericInstMethodSig Clone() { return new GenericInstMethodSig(genericArgs); } } public abstract class ClassLayout : IMDTokenProvider { protected uint rid; protected ushort packingSize; protected uint classSize; public MDToken MDToken => new MDToken(Table.ClassLayout, rid); public uint Rid { get { return rid; } set { rid = value; } } public ushort PackingSize { get { return packingSize; } set { packingSize = value; } } public uint ClassSize { get { return classSize; } set { classSize = value; } } } public class ClassLayoutUser : ClassLayout { public ClassLayoutUser() { } public ClassLayoutUser(ushort packingSize, uint classSize) { base.packingSize = packingSize; base.classSize = classSize; } } internal sealed class ClassLayoutMD : ClassLayout, IMDTokenProviderMD, IMDTokenProvider { private readonly uint origRid; public uint OrigRid => origRid; public ClassLayoutMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; readerModule.TablesStream.TryReadClassLayoutRow(origRid, out var row); classSize = row.ClassSize; packingSize = row.PackingSize; } } public abstract class Constant : IMDTokenProvider { protected uint rid; protected ElementType type; protected object value; public MDToken MDToken => new MDToken(Table.Constant, rid); public uint Rid { get { return rid; } set { rid = value; } } public ElementType Type { get { return type; } set { type = value; } } public object Value { get { return value; } set { this.value = value; } } } public class ConstantUser : Constant { public ConstantUser() { } public ConstantUser(object value) { type = GetElementType(value); base.value = value; } public ConstantUser(object value, ElementType type) { base.type = type; base.value = value; } private static ElementType GetElementType(object value) { if (value == null) { return ElementType.Class; } return System.Type.GetTypeCode(value.GetType()) switch { TypeCode.Boolean => ElementType.Boolean, TypeCode.Char => ElementType.Char, TypeCode.SByte => ElementType.I1, TypeCode.Byte => ElementType.U1, TypeCode.Int16 => ElementType.I2, TypeCode.UInt16 => ElementType.U2, TypeCode.Int32 => ElementType.I4, TypeCode.UInt32 => ElementType.U4, TypeCode.Int64 => ElementType.I8, TypeCode.UInt64 => ElementType.U8, TypeCode.Single => ElementType.R4, TypeCode.Double => ElementType.R8, TypeCode.String => ElementType.String, _ => ElementType.Void, }; } } internal sealed class ConstantMD : Constant, IMDTokenProviderMD, IMDTokenProvider { private readonly uint origRid; public uint OrigRid => origRid; public ConstantMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; readerModule.TablesStream.TryReadConstantRow(origRid, out var row); type = (ElementType)row.Type; DataReader reader = readerModule.BlobStream.CreateReader(row.Value); value = GetValue(type, ref reader); } private static object GetValue(ElementType etype, ref DataReader reader) { switch (etype) { case ElementType.Boolean: if (reader.Length < 1) { return false; } return reader.ReadBoolean(); case ElementType.Char: if (reader.Length < 2) { return '\0'; } return reader.ReadChar(); case ElementType.I1: if (reader.Length < 1) { return (sbyte)0; } return reader.ReadSByte(); case ElementType.U1: if (reader.Length < 1) { return (byte)0; } return reader.ReadByte(); case ElementType.I2: if (reader.Length < 2) { return (short)0; } return reader.ReadInt16(); case ElementType.U2: if (reader.Length < 2) { return (ushort)0; } return reader.ReadUInt16(); case ElementType.I4: if (reader.Length < 4) { return 0; } return reader.ReadInt32(); case ElementType.U4: if (reader.Length < 4) { return 0u; } return reader.ReadUInt32(); case ElementType.I8: if (reader.Length < 8) { return 0L; } return reader.ReadInt64(); case ElementType.U8: if (reader.Length < 8) { return 0uL; } return reader.ReadUInt64(); case ElementType.R4: if (reader.Length < 4) { return 0f; } return reader.ReadSingle(); case ElementType.R8: if (reader.Length < 8) { return 0.0; } return reader.ReadDouble(); case ElementType.String: return reader.ReadUtf16String((int)(reader.BytesLeft / 2)); case ElementType.Class: return null; default: return null; } } } public sealed class CorLibTypes : ICorLibTypes { private readonly ModuleDef module; private CorLibTypeSig typeVoid; private CorLibTypeSig typeBoolean; private CorLibTypeSig typeChar; private CorLibTypeSig typeSByte; private CorLibTypeSig typeByte; private CorLibTypeSig typeInt16; private CorLibTypeSig typeUInt16; private CorLibTypeSig typeInt32; private CorLibTypeSig typeUInt32; private CorLibTypeSig typeInt64; private CorLibTypeSig typeUInt64; private CorLibTypeSig typeSingle; private CorLibTypeSig typeDouble; private CorLibTypeSig typeString; private CorLibTypeSig typeTypedReference; private CorLibTypeSig typeIntPtr; private CorLibTypeSig typeUIntPtr; private CorLibTypeSig typeObject; private readonly AssemblyRef corLibAssemblyRef; public CorLibTypeSig Void => typeVoid; public CorLibTypeSig Boolean => typeBoolean; public CorLibTypeSig Char => typeChar; public CorLibTypeSig SByte => typeSByte; public CorLibTypeSig Byte => typeByte; public CorLibTypeSig Int16 => typeInt16; public CorLibTypeSig UInt16 => typeUInt16; public CorLibTypeSig Int32 => typeInt32; public CorLibTypeSig UInt32 => typeUInt32; public CorLibTypeSig Int64 => typeInt64; public CorLibTypeSig UInt64 => typeUInt64; public CorLibTypeSig Single => typeSingle; public CorLibTypeSig Double => typeDouble; public CorLibTypeSig String => typeString; public CorLibTypeSig TypedReference => typeTypedReference; public CorLibTypeSig IntPtr => typeIntPtr; public CorLibTypeSig UIntPtr => typeUIntPtr; public CorLibTypeSig Object => typeObject; public AssemblyRef AssemblyRef => corLibAssemblyRef; public CorLibTypes(ModuleDef module) : this(module, null) { } public CorLibTypes(ModuleDef module, AssemblyRef corLibAssemblyRef) { this.module = module; this.corLibAssemblyRef = corLibAssemblyRef ?? CreateCorLibAssemblyRef(); Initialize(); } private AssemblyRef CreateCorLibAssemblyRef() { return module.UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20()); } private void Initialize() { bool isCorLib = module.Assembly.IsCorLib(); typeVoid = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Void"), ElementType.Void); typeBoolean = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Boolean"), ElementType.Boolean); typeChar = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Char"), ElementType.Char); typeSByte = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "SByte"), ElementType.I1); typeByte = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Byte"), ElementType.U1); typeInt16 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int16"), ElementType.I2); typeUInt16 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt16"), ElementType.U2); typeInt32 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int32"), ElementType.I4); typeUInt32 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt32"), ElementType.U4); typeInt64 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int64"), ElementType.I8); typeUInt64 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt64"), ElementType.U8); typeSingle = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Single"), ElementType.R4); typeDouble = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Double"), ElementType.R8); typeString = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "String"), ElementType.String); typeTypedReference = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "TypedReference"), ElementType.TypedByRef); typeIntPtr = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "IntPtr"), ElementType.I); typeUIntPtr = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UIntPtr"), ElementType.U); typeObject = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Object"), ElementType.Object); } private ITypeDefOrRef CreateCorLibTypeRef(bool isCorLib, string name) { TypeRefUser typeRefUser = new TypeRefUser(module, "System", name, corLibAssemblyRef); if (isCorLib) { TypeDef typeDef = module.Find(typeRefUser); if (typeDef != null) { return typeDef; } } return module.UpdateRowId(typeRefUser); } public TypeRef GetTypeRef(string @namespace, string name) { return module.UpdateRowId(new TypeRefUser(module, @namespace, name, corLibAssemblyRef)); } } internal enum StubType { Export, EntryPoint } internal abstract class CpuArch { private static readonly X86CpuArch x86CpuArch = new X86CpuArch(); private static readonly X64CpuArch x64CpuArch = new X64CpuArch(); private static readonly ItaniumCpuArch itaniumCpuArch = new ItaniumCpuArch(); private static readonly ArmCpuArch armCpuArch = new ArmCpuArch(); public abstract uint GetStubAlignment(StubType stubType); public abstract uint GetStubSize(StubType stubType); public abstract uint GetStubCodeOffset(StubType stubType); public static bool TryGetCpuArch(Machine machine, out CpuArch cpuArch) { switch (machine) { case Machine.I386: case Machine.I386_Native_Sun: case Machine.I386_Native_NetBSD: case Machine.I386_Native_Apple: case Machine.I386_Native_Linux: case Machine.I386_Native_FreeBSD: cpuArch = x86CpuArch; return true; case Machine.AMD64_Native_FreeBSD: case Machine.AMD64: case Machine.AMD64_Native_Sun: case Machine.AMD64_Native_NetBSD: case Machine.AMD64_Native_Apple: case Machine.AMD64_Native_Linux: cpuArch = x64CpuArch; return true; case Machine.IA64: cpuArch = itaniumCpuArch; return true; case Machine.ARMNT: case Machine.ARMNT_Native_Sun: case Machine.ARMNT_Native_NetBSD: case Machine.ARMNT_Native_Apple: case Machine.ARMNT_Native_Linux: case Machine.ARMNT_Native_FreeBSD: cpuArch = armCpuArch; return true; default: cpuArch = null; return false; } } public bool TryGetExportedRvaFromStub(ref DataReader reader, IPEImage peImage, out uint funcRva) { return TryGetExportedRvaFromStubCore(ref reader, peImage, out funcRva); } protected abstract bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva); public abstract void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset); public abstract void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva); } internal sealed class X86CpuArch : CpuArch { public override uint GetStubAlignment(StubType stubType) { if ((uint)stubType <= 1u) { return 4u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubSize(StubType stubType) { if ((uint)stubType <= 1u) { return 8u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubCodeOffset(StubType stubType) { if ((uint)stubType <= 1u) { return 2u; } throw new ArgumentOutOfRangeException(); } protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) { funcRva = 0u; if (reader.ReadUInt16() != 9727) { return false; } funcRva = reader.ReadUInt32() - (uint)(int)peImage.ImageNTHeaders.OptionalHeader.ImageBase; return true; } public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) { if ((uint)stubType <= 1u) { relocDirectory.Add(chunk, stubOffset + 4); return; } throw new ArgumentOutOfRangeException(); } public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { if ((uint)stubType <= 1u) { writer.WriteUInt16(0); writer.WriteUInt16(9727); writer.WriteUInt32((uint)(int)imageBase + managedFuncRva); return; } throw new ArgumentOutOfRangeException(); } } internal sealed class X64CpuArch : CpuArch { public override uint GetStubAlignment(StubType stubType) { if ((uint)stubType <= 1u) { return 4u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubSize(StubType stubType) { if ((uint)stubType <= 1u) { return 14u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubCodeOffset(StubType stubType) { if ((uint)stubType <= 1u) { return 2u; } throw new ArgumentOutOfRangeException(); } protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) { funcRva = 0u; if (reader.ReadUInt16() != 41288) { return false; } ulong num = reader.ReadUInt64(); if (reader.ReadUInt16() != 57599) { return false; } ulong num2 = num - peImage.ImageNTHeaders.OptionalHeader.ImageBase; if (num2 > uint.MaxValue) { return false; } funcRva = (uint)num2; return true; } public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) { if ((uint)stubType <= 1u) { relocDirectory.Add(chunk, stubOffset + 4); return; } throw new ArgumentOutOfRangeException(); } public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { if ((uint)stubType <= 1u) { writer.WriteUInt16(0); writer.WriteUInt16(41288); writer.WriteUInt64(imageBase + managedFuncRva); writer.WriteUInt16(57599); return; } throw new ArgumentOutOfRangeException(); } } internal sealed class ItaniumCpuArch : CpuArch { public override uint GetStubAlignment(StubType stubType) { if ((uint)stubType <= 1u) { return 16u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubSize(StubType stubType) { if ((uint)stubType <= 1u) { return 48u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubCodeOffset(StubType stubType) { if ((uint)stubType <= 1u) { return 32u; } throw new ArgumentOutOfRangeException(); } protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) { funcRva = 0u; ulong num = reader.ReadUInt64(); ulong num2 = reader.ReadUInt64(); reader.Position = (uint)peImage.ToFileOffset((RVA)(num - peImage.ImageNTHeaders.OptionalHeader.ImageBase)); if (reader.ReadUInt64() != 4656739709999925259L) { return false; } if (reader.ReadUInt64() != 1125899909476388L) { return false; } if (reader.ReadUInt64() != 5791646816365709328L) { return false; } if (reader.ReadUInt64() != 36029209336053764L) { return false; } ulong num3 = num2 - peImage.ImageNTHeaders.OptionalHeader.ImageBase; if (num3 > uint.MaxValue) { return false; } funcRva = (uint)num3; return true; } public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) { if ((uint)stubType <= 1u) { relocDirectory.Add(chunk, stubOffset + 32); relocDirectory.Add(chunk, stubOffset + 40); return; } throw new ArgumentOutOfRangeException(); } public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { if ((uint)stubType <= 1u) { writer.WriteUInt64(4656739709999925259uL); writer.WriteUInt64(1125899909476388uL); writer.WriteUInt64(5791646816365709328uL); writer.WriteUInt64(36029209336053764uL); writer.WriteUInt64(imageBase + stubRva); writer.WriteUInt64(imageBase + managedFuncRva); return; } throw new ArgumentOutOfRangeException(); } } internal sealed class ArmCpuArch : CpuArch { public override uint GetStubAlignment(StubType stubType) { if ((uint)stubType <= 1u) { return 4u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubSize(StubType stubType) { if ((uint)stubType <= 1u) { return 8u; } throw new ArgumentOutOfRangeException(); } public override uint GetStubCodeOffset(StubType stubType) { if ((uint)stubType <= 1u) { return 0u; } throw new ArgumentOutOfRangeException(); } protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) { funcRva = 0u; if (reader.ReadUInt32() != 4026595551u) { return false; } funcRva = reader.ReadUInt32() - (uint)(int)peImage.ImageNTHeaders.OptionalHeader.ImageBase; return true; } public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) { if ((uint)stubType <= 1u) { relocDirectory.Add(chunk, stubOffset + 4); return; } throw new ArgumentOutOfRangeException(); } public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { if ((uint)stubType <= 1u) { writer.WriteUInt32(4026595551u); writer.WriteUInt32((uint)(int)imageBase + managedFuncRva); return; } throw new ArgumentOutOfRangeException(); } } public sealed class CustomAttribute : ICustomAttribute { private ICustomAttributeType ctor; private byte[] rawData; private readonly IList arguments; private readonly IList namedArguments; private uint caBlobOffset; public ICustomAttributeType Constructor { get { return ctor; } set { ctor = value; } } public ITypeDefOrRef AttributeType => ctor?.DeclaringType; public string TypeFullName { get { if (ctor is MemberRef memberRef) { return memberRef.GetDeclaringTypeFullName() ?? string.Empty; } if (ctor is MethodDef { DeclaringType: { } declaringType }) { return declaringType.FullName; } return string.Empty; } } internal string TypeName { get { if (ctor is MemberRef memberRef) { return memberRef.GetDeclaringTypeName() ?? string.Empty; } if (ctor is MethodDef { DeclaringType: { } declaringType }) { return declaringType.Name; } return string.Empty; } } public bool IsRawBlob => rawData != null; public byte[] RawData => rawData; public IList ConstructorArguments => arguments; public bool HasConstructorArguments => arguments.Count > 0; public IList NamedArguments => namedArguments; public bool HasNamedArguments => namedArguments.Count > 0; public IEnumerable Fields { get { IList namedArguments = this.namedArguments; int count = namedArguments.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = namedArguments[i]; if (cANamedArgument.IsField) { yield return cANamedArgument; } } } } public IEnumerable Properties { get { IList namedArguments = this.namedArguments; int count = namedArguments.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = namedArguments[i]; if (cANamedArgument.IsProperty) { yield return cANamedArgument; } } } } public uint BlobOffset => caBlobOffset; public CustomAttribute(ICustomAttributeType ctor, byte[] rawData) : this(ctor, null, null, 0u) { this.rawData = rawData; } public CustomAttribute(ICustomAttributeType ctor) : this(ctor, null, null, 0u) { } public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments) : this(ctor, arguments, null) { } public CustomAttribute(ICustomAttributeType ctor, IEnumerable namedArguments) : this(ctor, null, namedArguments) { } public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments, IEnumerable namedArguments) : this(ctor, arguments, namedArguments, 0u) { } public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments, IEnumerable namedArguments, uint caBlobOffset) { this.ctor = ctor; this.arguments = ((arguments == null) ? new List() : new List(arguments)); this.namedArguments = ((namedArguments == null) ? new List() : new List(namedArguments)); this.caBlobOffset = caBlobOffset; } internal CustomAttribute(ICustomAttributeType ctor, List arguments, List namedArguments, uint caBlobOffset) { this.ctor = ctor; this.arguments = arguments ?? new List(); this.namedArguments = namedArguments ?? new List(); this.caBlobOffset = caBlobOffset; } public CANamedArgument GetField(string name) { return GetNamedArgument(name, isField: true); } public CANamedArgument GetField(UTF8String name) { return GetNamedArgument(name, isField: true); } public CANamedArgument GetProperty(string name) { return GetNamedArgument(name, isField: false); } public CANamedArgument GetProperty(UTF8String name) { return GetNamedArgument(name, isField: false); } public CANamedArgument GetNamedArgument(string name, bool isField) { IList list = namedArguments; int count = list.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = list[i]; if (cANamedArgument.IsField == isField && UTF8String.ToSystemStringOrEmpty(cANamedArgument.Name) == name) { return cANamedArgument; } } return null; } public CANamedArgument GetNamedArgument(UTF8String name, bool isField) { IList list = namedArguments; int count = list.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = list[i]; if (cANamedArgument.IsField == isField && UTF8String.Equals(cANamedArgument.Name, name)) { return cANamedArgument; } } return null; } public override string ToString() { return TypeFullName; } } public struct CAArgument : ICloneable { private TypeSig type; private object value; public TypeSig Type { readonly get { return type; } set { type = value; } } public object Value { readonly get { return value; } set { this.value = value; } } public CAArgument(TypeSig type) { this.type = type; value = null; } public CAArgument(TypeSig type, object value) { this.type = type; this.value = value; } readonly object ICloneable.Clone() { return Clone(); } public readonly CAArgument Clone() { object obj = value; if (obj is CAArgument cAArgument) { obj = cAArgument.Clone(); } else if (obj is IList list) { List list2 = new List(list.Count); int count = list.Count; for (int i = 0; i < count; i++) { list2.Add(list[i].Clone()); } obj = list2; } return new CAArgument(type, obj); } public override readonly string ToString() { return $"{value ?? "null"} ({type})"; } } public sealed class CANamedArgument : ICloneable { private bool isField; private TypeSig type; private UTF8String name; private CAArgument argument; public bool IsField { get { return isField; } set { isField = value; } } public bool IsProperty { get { return !isField; } set { isField = !value; } } public TypeSig Type { get { return type; } set { type = value; } } public UTF8String Name { get { return name; } set { name = value; } } public CAArgument Argument { get { return argument; } set { argument = value; } } public TypeSig ArgumentType { get { return argument.Type; } set { argument.Type = value; } } public object Value { get { return argument.Value; } set { argument.Value = value; } } public CANamedArgument() { } public CANamedArgument(bool isField) { this.isField = isField; } public CANamedArgument(bool isField, TypeSig type) { this.isField = isField; this.type = type; } public CANamedArgument(bool isField, TypeSig type, UTF8String name) { this.isField = isField; this.type = type; this.name = name; } public CANamedArgument(bool isField, TypeSig type, UTF8String name, CAArgument argument) { this.isField = isField; this.type = type; this.name = name; this.argument = argument; } object ICloneable.Clone() { return Clone(); } public CANamedArgument Clone() { return new CANamedArgument(isField, type, name, argument.Clone()); } public override string ToString() { return $"({(isField ? "field" : "property")}) {type} {name} = {Value ?? "null"} ({ArgumentType})"; } } public class CustomAttributeCollection : LazyList { public CustomAttributeCollection() { } public CustomAttributeCollection(int length, object context, Func readOriginalValue) : base(length, context, readOriginalValue) { } public bool IsDefined(string fullName) { return Find(fullName) != null; } public void RemoveAll(string fullName) { if (fullName == null) { return; } for (int num = base.Count - 1; num >= 0; num--) { CustomAttribute customAttribute = base[num]; if (customAttribute != null && fullName.EndsWith(customAttribute.TypeName, StringComparison.Ordinal) && customAttribute.TypeFullName == fullName) { RemoveAt(num); } } } public CustomAttribute Find(string fullName) { if (fullName == null) { return null; } using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; if (current != null && fullName.EndsWith(current.TypeName, StringComparison.Ordinal) && current.TypeFullName == fullName) { return current; } } } return null; } public IEnumerable FindAll(string fullName) { if (fullName == null) { yield break; } using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; if (current != null && fullName.EndsWith(current.TypeName, StringComparison.Ordinal) && current.TypeFullName == fullName) { yield return current; } } } public CustomAttribute Find(IType attrType) { return Find(attrType, (SigComparerOptions)0u); } public CustomAttribute Find(IType attrType, SigComparerOptions options) { SigComparer sigComparer = new SigComparer(options); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; if (sigComparer.Equals(current.AttributeType, attrType)) { return current; } } } return null; } public IEnumerable FindAll(IType attrType) { return FindAll(attrType, (SigComparerOptions)0u); } public IEnumerable FindAll(IType attrType, SigComparerOptions options) { SigComparer comparer = new SigComparer(options); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; if (comparer.Equals(current.AttributeType, attrType)) { yield return current; } } } } internal sealed class CAAssemblyRefFinder : IAssemblyRefFinder { private readonly ModuleDef module; public CAAssemblyRefFinder(ModuleDef module) { this.module = module; } public AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef) { AssemblyDef assembly = module.Assembly; if (assembly != null) { if (assembly.Find(nonNestedTypeRef) is TypeDefMD typeDefMD && typeDefMD.ReaderModule == module) { return module.UpdateRowId(new AssemblyRefUser(assembly)); } } else if (module.Find(nonNestedTypeRef) != null) { return AssemblyRef.CurrentAssembly; } AssemblyDef assemblyDef = module.Context.AssemblyResolver.Resolve(module.CorLibTypes.AssemblyRef, module); if (assemblyDef != null && assemblyDef.Find(nonNestedTypeRef) != null) { return module.CorLibTypes.AssemblyRef; } if (assembly != null) { return module.UpdateRowId(new AssemblyRefUser(assembly)); } return AssemblyRef.CurrentAssembly; } } [Serializable] public class CABlobParserException : Exception { public CABlobParserException() { } public CABlobParserException(string message) : base(message) { } public CABlobParserException(string message, Exception innerException) : base(message, innerException) { } protected CABlobParserException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public struct CustomAttributeReader { private readonly ModuleDef module; private DataReader reader; private readonly uint caBlobOffset; private readonly GenericParamContext gpContext; private GenericArguments genericArguments; private RecursionCounter recursionCounter; private bool verifyReadAllBytes; public static CustomAttribute Read(ModuleDefMD readerModule, ICustomAttributeType ctor, uint offset) { return Read(readerModule, ctor, offset, default(GenericParamContext)); } public static CustomAttribute Read(ModuleDefMD readerModule, ICustomAttributeType ctor, uint offset, GenericParamContext gpContext) { CustomAttributeReader customAttributeReader = new CustomAttributeReader(readerModule, offset, gpContext); try { if (ctor == null) { return customAttributeReader.CreateRaw(ctor); } return customAttributeReader.Read(ctor); } catch (CABlobParserException) { return customAttributeReader.CreateRaw(ctor); } catch (IOException) { return customAttributeReader.CreateRaw(ctor); } } private CustomAttribute CreateRaw(ICustomAttributeType ctor) { return new CustomAttribute(ctor, GetRawBlob()); } public static CustomAttribute Read(ModuleDef module, byte[] caBlob, ICustomAttributeType ctor) { return Read(module, ByteArrayDataReaderFactory.CreateReader(caBlob), ctor, default(GenericParamContext)); } public static CustomAttribute Read(ModuleDef module, DataReader reader, ICustomAttributeType ctor) { return Read(module, ref reader, ctor, default(GenericParamContext)); } public static CustomAttribute Read(ModuleDef module, byte[] caBlob, ICustomAttributeType ctor, GenericParamContext gpContext) { return Read(module, ByteArrayDataReaderFactory.CreateReader(caBlob), ctor, gpContext); } public static CustomAttribute Read(ModuleDef module, DataReader reader, ICustomAttributeType ctor, GenericParamContext gpContext) { return Read(module, ref reader, ctor, gpContext); } private static CustomAttribute Read(ModuleDef module, ref DataReader reader, ICustomAttributeType ctor, GenericParamContext gpContext) { CustomAttributeReader customAttributeReader = new CustomAttributeReader(module, ref reader, gpContext); try { if (ctor == null) { return customAttributeReader.CreateRaw(ctor); } return customAttributeReader.Read(ctor); } catch (CABlobParserException) { return customAttributeReader.CreateRaw(ctor); } catch (IOException) { return customAttributeReader.CreateRaw(ctor); } } internal static List ReadNamedArguments(ModuleDef module, ref DataReader reader, int numNamedArgs, GenericParamContext gpContext) { try { CustomAttributeReader customAttributeReader = new CustomAttributeReader(module, ref reader, gpContext); List result = customAttributeReader.ReadNamedArguments(numNamedArgs); reader.CurrentOffset = customAttributeReader.reader.CurrentOffset; return result; } catch (CABlobParserException) { return null; } catch (IOException) { return null; } } private CustomAttributeReader(ModuleDefMD readerModule, uint offset, GenericParamContext gpContext) { module = readerModule; caBlobOffset = offset; reader = readerModule.BlobStream.CreateReader(offset); genericArguments = null; recursionCounter = default(RecursionCounter); verifyReadAllBytes = false; this.gpContext = gpContext; } private CustomAttributeReader(ModuleDef module, ref DataReader reader, GenericParamContext gpContext) { this.module = module; caBlobOffset = 0u; this.reader = reader; genericArguments = null; recursionCounter = default(RecursionCounter); verifyReadAllBytes = false; this.gpContext = gpContext; } private byte[] GetRawBlob() { return reader.ToArray(); } private CustomAttribute Read(ICustomAttributeType ctor) { MethodSig obj = ctor?.MethodSig ?? throw new CABlobParserException("ctor is null or not a method"); if (ctor is MemberRef { Class: TypeSpec { TypeSig: GenericInstSig typeSig } }) { genericArguments = new GenericArguments(); genericArguments.PushTypeArgs(typeSig.GenericArguments); } IList list = obj.Params; if ((list.Count != 0 || reader.Position != reader.Length) && reader.ReadUInt16() != 1) { throw new CABlobParserException("Invalid CA blob prolog"); } List list2 = new List(list.Count); int count = list.Count; for (int i = 0; i < count; i++) { list2.Add(ReadFixedArg(FixTypeSig(list[i]))); } int numNamedArgs = ((reader.Position != reader.Length) ? reader.ReadUInt16() : 0); List namedArguments = ReadNamedArguments(numNamedArgs); if (verifyReadAllBytes && reader.Position != reader.Length) { throw new CABlobParserException("Not all CA blob bytes were read"); } return new CustomAttribute(ctor, list2, namedArguments, caBlobOffset); } private List ReadNamedArguments(int numNamedArgs) { if ((uint)numNamedArgs >= 1073741824u || numNamedArgs * 4 > reader.BytesLeft) { return null; } List list = new List(numNamedArgs); for (int i = 0; i < numNamedArgs; i++) { if (reader.Position == reader.Length) { break; } list.Add(ReadNamedArgument()); } return list; } private TypeSig FixTypeSig(TypeSig type) { return SubstituteGenericParameter(type.RemoveModifiers()).RemoveModifiers(); } private TypeSig SubstituteGenericParameter(TypeSig type) { if (genericArguments == null) { return type; } return genericArguments.Resolve(type); } private CAArgument ReadFixedArg(TypeSig argType) { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } if (argType == null) { throw new CABlobParserException("null argType"); } CAArgument result = ((!(argType is SZArraySig arrayType)) ? ReadElem(argType) : ReadArrayArgument(arrayType)); recursionCounter.Decrement(); return result; } private CAArgument ReadElem(TypeSig argType) { if (argType == null) { throw new CABlobParserException("null argType"); } TypeSig realArgType; object obj = ReadValue((SerializationType)argType.ElementType, argType, out realArgType); if (realArgType == null) { throw new CABlobParserException("Invalid arg type"); } if (obj is CAArgument) { return (CAArgument)obj; } return new CAArgument(realArgType, obj); } private object ReadValue(SerializationType etype, TypeSig argType, out TypeSig realArgType) { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } object result; switch (etype) { case SerializationType.Boolean: realArgType = module.CorLibTypes.Boolean; result = reader.ReadByte() != 0; break; case SerializationType.Char: realArgType = module.CorLibTypes.Char; result = reader.ReadChar(); break; case SerializationType.I1: realArgType = module.CorLibTypes.SByte; result = reader.ReadSByte(); break; case SerializationType.U1: realArgType = module.CorLibTypes.Byte; result = reader.ReadByte(); break; case SerializationType.I2: realArgType = module.CorLibTypes.Int16; result = reader.ReadInt16(); break; case SerializationType.U2: realArgType = module.CorLibTypes.UInt16; result = reader.ReadUInt16(); break; case SerializationType.I4: realArgType = module.CorLibTypes.Int32; result = reader.ReadInt32(); break; case SerializationType.U4: realArgType = module.CorLibTypes.UInt32; result = reader.ReadUInt32(); break; case SerializationType.I8: realArgType = module.CorLibTypes.Int64; result = reader.ReadInt64(); break; case SerializationType.U8: realArgType = module.CorLibTypes.UInt64; result = reader.ReadUInt64(); break; case SerializationType.R4: realArgType = module.CorLibTypes.Single; result = reader.ReadSingle(); break; case SerializationType.R8: realArgType = module.CorLibTypes.Double; result = reader.ReadDouble(); break; case SerializationType.String: realArgType = module.CorLibTypes.String; result = ReadUTF8String(); break; case (SerializationType)17: if (argType == null) { throw new CABlobParserException("Invalid element type"); } realArgType = argType; result = ReadEnumValue(GetEnumUnderlyingType(argType)); break; case (SerializationType)28: case SerializationType.TaggedObject: { realArgType = ReadFieldOrPropType(); result = ((!(realArgType is SZArraySig arrayType)) ? ReadValue((SerializationType)realArgType.ElementType, realArgType, out var _) : ((object)ReadArrayArgument(arrayType))); break; } case (SerializationType)18: if (argType is TypeDefOrRefSig typeDefOrRefSig && typeDefOrRefSig.DefinitionAssembly.IsCorLib() && typeDefOrRefSig.Namespace == "System") { if (typeDefOrRefSig.TypeName == "Type") { result = ReadValue(SerializationType.Type, typeDefOrRefSig, out realArgType); break; } if (typeDefOrRefSig.TypeName == "String") { result = ReadValue(SerializationType.String, typeDefOrRefSig, out realArgType); break; } if (typeDefOrRefSig.TypeName == "Object") { result = ReadValue(SerializationType.TaggedObject, typeDefOrRefSig, out realArgType); break; } } realArgType = argType; result = ReadEnumValue(null); break; case SerializationType.Type: realArgType = argType; result = ReadType(canReturnNull: true); break; case SerializationType.Enum: realArgType = ReadType(canReturnNull: false); result = ReadEnumValue(GetEnumUnderlyingType(realArgType)); break; default: throw new CABlobParserException("Invalid element type"); } recursionCounter.Decrement(); return result; } private object ReadEnumValue(TypeSig underlyingType) { if (underlyingType != null) { if ((int)underlyingType.ElementType < 2 || (int)underlyingType.ElementType > 11) { throw new CABlobParserException("Invalid enum underlying type"); } TypeSig realArgType; return ReadValue((SerializationType)underlyingType.ElementType, underlyingType, out realArgType); } verifyReadAllBytes = true; return reader.ReadInt32(); } private TypeSig ReadType(bool canReturnNull) { UTF8String uTF8String = ReadUTF8String(); if (canReturnNull && (object)uTF8String == null) { return null; } CAAssemblyRefFinder typeNameParserHelper = new CAAssemblyRefFinder(module); return TypeNameParser.ParseAsTypeSigReflection(module, UTF8String.ToSystemStringOrEmpty(uTF8String), typeNameParserHelper, gpContext) ?? throw new CABlobParserException("Could not parse type"); } private static TypeSig GetEnumUnderlyingType(TypeSig type) { if (type == null) { throw new CABlobParserException("null enum type"); } TypeDef typeDef = GetTypeDef(type); if (typeDef == null) { return null; } if (!typeDef.IsEnum) { throw new CABlobParserException("Not an enum"); } return typeDef.GetEnumUnderlyingType().RemoveModifiers(); } private static TypeDef GetTypeDef(TypeSig type) { if (type is TypeDefOrRefSig { TypeDef: var typeDef } typeDefOrRefSig) { if (typeDef != null) { return typeDef; } TypeRef typeRef = typeDefOrRefSig.TypeRef; if (typeRef != null) { return typeRef.Resolve(); } } return null; } private CAArgument ReadArrayArgument(SZArraySig arrayType) { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } CAArgument result = new CAArgument(arrayType); int num = reader.ReadInt32(); if (num != -1) { if (num < 0 || num > reader.BytesLeft) { throw new CABlobParserException("Array is too big"); } List list = (List)(result.Value = new List(num)); for (int i = 0; i < num; i++) { list.Add(ReadFixedArg(FixTypeSig(arrayType.Next))); } } recursionCounter.Decrement(); return result; } private CANamedArgument ReadNamedArgument() { int isField = (SerializationType)reader.ReadByte() switch { SerializationType.Property => 0, SerializationType.Field => 1, _ => throw new CABlobParserException("Named argument is not a field/property"), }; TypeSig typeSig = ReadFieldOrPropType(); UTF8String name = ReadUTF8String(); CAArgument argument = ReadFixedArg(typeSig); return new CANamedArgument((byte)isField != 0, typeSig, name, argument); } private TypeSig ReadFieldOrPropType() { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } object result = (SerializationType)reader.ReadByte() switch { SerializationType.Boolean => module.CorLibTypes.Boolean, SerializationType.Char => module.CorLibTypes.Char, SerializationType.I1 => module.CorLibTypes.SByte, SerializationType.U1 => module.CorLibTypes.Byte, SerializationType.I2 => module.CorLibTypes.Int16, SerializationType.U2 => module.CorLibTypes.UInt16, SerializationType.I4 => module.CorLibTypes.Int32, SerializationType.U4 => module.CorLibTypes.UInt32, SerializationType.I8 => module.CorLibTypes.Int64, SerializationType.U8 => module.CorLibTypes.UInt64, SerializationType.R4 => module.CorLibTypes.Single, SerializationType.R8 => module.CorLibTypes.Double, SerializationType.String => module.CorLibTypes.String, SerializationType.SZArray => new SZArraySig(ReadFieldOrPropType()), SerializationType.Type => new ClassSig(module.CorLibTypes.GetTypeRef("System", "Type")), SerializationType.TaggedObject => module.CorLibTypes.Object, SerializationType.Enum => ReadType(canReturnNull: false), _ => throw new CABlobParserException("Invalid type"), }; recursionCounter.Decrement(); return (TypeSig)result; } private UTF8String ReadUTF8String() { if (reader.ReadByte() == byte.MaxValue) { return null; } reader.Position--; if (!reader.TryReadCompressedUInt32(out var value)) { throw new CABlobParserException("Could not read compressed UInt32"); } if (value == 0) { return UTF8String.Empty; } return new UTF8String(reader.ReadBytes((int)value)); } } [DebuggerDisplay("{Action} Count={SecurityAttributes.Count}")] public abstract class DeclSecurity : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation { protected uint rid; protected SecurityAction action; protected IList securityAttributes; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.DeclSecurity, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 8; public SecurityAction Action { get { return action; } set { action = value; } } public IList SecurityAttributes { get { if (securityAttributes == null) { InitializeSecurityAttributes(); } return securityAttributes; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 8; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasSecurityAttributes => SecurityAttributes.Count > 0; protected virtual void InitializeSecurityAttributes() { Interlocked.CompareExchange(ref securityAttributes, new List(), null); } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } public abstract byte[] GetBlob(); public string GetNet1xXmlString() { return GetNet1xXmlStringInternal(SecurityAttributes); } internal static string GetNet1xXmlStringInternal(IList secAttrs) { if (secAttrs == null || secAttrs.Count != 1) { return null; } SecurityAttribute securityAttribute = secAttrs[0]; if (securityAttribute == null || securityAttribute.TypeFullName != "System.Security.Permissions.PermissionSetAttribute") { return null; } if (securityAttribute.NamedArguments.Count != 1) { return null; } CANamedArgument cANamedArgument = securityAttribute.NamedArguments[0]; if (cANamedArgument == null || !cANamedArgument.IsProperty || cANamedArgument.Name != "XML") { return null; } if (cANamedArgument.ArgumentType.GetElementType() != ElementType.String) { return null; } CAArgument argument = cANamedArgument.Argument; if (argument.Type.GetElementType() != ElementType.String) { return null; } if (argument.Value is UTF8String uTF8String) { return uTF8String; } if (argument.Value is string result) { return result; } return null; } } public class DeclSecurityUser : DeclSecurity { public DeclSecurityUser() { } public DeclSecurityUser(SecurityAction action, IList securityAttrs) { base.action = action; securityAttributes = securityAttrs; } public override byte[] GetBlob() { return null; } } internal sealed class DeclSecurityMD : DeclSecurity, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly uint permissionSet; public uint OrigRid => origRid; protected override void InitializeSecurityAttributes() { IList value = DeclSecurityReader.Read(readerModule, permissionSet, default(GenericParamContext)); Interlocked.CompareExchange(ref securityAttributes, value, null); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.DeclSecurity, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public DeclSecurityMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadDeclSecurityRow(origRid, out var row); permissionSet = row.PermissionSet; action = (SecurityAction)row.Action; } public override byte[] GetBlob() { return readerModule.BlobStream.Read(permissionSet); } } public struct DeclSecurityReader { private DataReader reader; private readonly ModuleDef module; private readonly GenericParamContext gpContext; public static IList Read(ModuleDefMD module, uint sig) { return Read(module, module.BlobStream.CreateReader(sig), default(GenericParamContext)); } public static IList Read(ModuleDefMD module, uint sig, GenericParamContext gpContext) { return Read(module, module.BlobStream.CreateReader(sig), gpContext); } public static IList Read(ModuleDef module, byte[] blob) { return Read(module, ByteArrayDataReaderFactory.CreateReader(blob), default(GenericParamContext)); } public static IList Read(ModuleDef module, byte[] blob, GenericParamContext gpContext) { return Read(module, ByteArrayDataReaderFactory.CreateReader(blob), gpContext); } public static IList Read(ModuleDef module, DataReader signature) { return Read(module, signature, default(GenericParamContext)); } public static IList Read(ModuleDef module, DataReader signature, GenericParamContext gpContext) { return new DeclSecurityReader(module, signature, gpContext).Read(); } private DeclSecurityReader(ModuleDef module, DataReader reader, GenericParamContext gpContext) { this.reader = reader; this.module = module; this.gpContext = gpContext; } private IList Read() { try { if (reader.Position >= reader.Length) { return new List(); } if (reader.ReadByte() == 46) { return ReadBinaryFormat(); } reader.Position--; return ReadXmlFormat(); } catch { return new List(); } } private IList ReadBinaryFormat() { int num = (int)reader.ReadCompressedUInt32(); List list = new List(num); for (int i = 0; i < num; i++) { UTF8String utf = ReadUTF8String(); ITypeDefOrRef attrType = TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(utf), new CAAssemblyRefFinder(module), gpContext); reader.ReadCompressedUInt32(); int numNamedArgs = (int)reader.ReadCompressedUInt32(); List list2 = CustomAttributeReader.ReadNamedArguments(module, ref reader, numNamedArgs, gpContext); if (list2 == null) { throw new ApplicationException("Could not read named arguments"); } list.Add(new SecurityAttribute(attrType, list2)); } return list; } private IList ReadXmlFormat() { string xml = reader.ReadUtf16String((int)reader.Length / 2); SecurityAttribute item = SecurityAttribute.CreateFromXml(module, xml); return new List { item }; } private UTF8String ReadUTF8String() { uint num = reader.ReadCompressedUInt32(); if (num != 0) { return new UTF8String(reader.ReadBytes((int)num)); } return UTF8String.Empty; } } public enum ElementType : byte { End = 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, ValueArray = 23, I = 24, U = 25, R = 26, FnPtr = 27, Object = 28, SZArray = 29, MVar = 30, CModReqd = 31, CModOpt = 32, Internal = 33, Module = 63, Sentinel = 65, Pinned = 69 } [Flags] public enum EventAttributes : ushort { SpecialName = 0x200, RTSpecialName = 0x400 } public abstract class EventDef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasSemantic, IFullName, IMemberRef, IOwnerModule, IIsTypeOrMethod, IHasCustomDebugInformation, IMemberDef, IDnlibDef { protected uint rid; private readonly Lock theLock = Lock.Create(); protected int attributes; protected UTF8String name; protected ITypeDefOrRef eventType; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected MethodDef addMethod; protected MethodDef invokeMethod; protected MethodDef removeMethod; protected IList otherMethods; protected TypeDef declaringType2; public MDToken MDToken => new MDToken(Table.Event, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 10; public int HasSemanticTag => 0; public EventAttributes Attributes { get { return (EventAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public ITypeDefOrRef EventType { get { return eventType; } set { eventType = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public int HasCustomDebugInformationTag => 10; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public MethodDef AddMethod { get { if (otherMethods == null) { InitializeEventMethods(); } return addMethod; } set { if (otherMethods == null) { InitializeEventMethods(); } addMethod = value; } } public MethodDef InvokeMethod { get { if (otherMethods == null) { InitializeEventMethods(); } return invokeMethod; } set { if (otherMethods == null) { InitializeEventMethods(); } invokeMethod = value; } } public MethodDef RemoveMethod { get { if (otherMethods == null) { InitializeEventMethods(); } return removeMethod; } set { if (otherMethods == null) { InitializeEventMethods(); } removeMethod = value; } } public IList OtherMethods { get { if (otherMethods == null) { InitializeEventMethods(); } return otherMethods; } } public bool IsEmpty { get { if (AddMethod == null && removeMethod == null && invokeMethod == null) { return otherMethods.Count == 0; } return false; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public bool HasOtherMethods => OtherMethods.Count > 0; public TypeDef DeclaringType { get { return declaringType2; } set { TypeDef typeDef = DeclaringType2; if (typeDef != value) { typeDef?.Events.Remove(this); value?.Events.Add(this); } } } ITypeDefOrRef IMemberRef.DeclaringType => declaringType2; public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } public ModuleDef Module => declaringType2?.Module; public string FullName => FullNameFactory.EventFullName(declaringType2?.FullName, name, eventType); bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => true; bool IMemberRef.IsGenericParam => false; public bool IsSpecialName { get { return ((ushort)attributes & 0x200) != 0; } set { ModifyAttributes(value, EventAttributes.SpecialName); } } public bool IsRuntimeSpecialName { get { return ((ushort)attributes & 0x400) != 0; } set { ModifyAttributes(value, EventAttributes.RTSpecialName); } } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void InitializeEventMethods() { theLock.EnterWriteLock(); try { if (otherMethods == null) { InitializeEventMethods_NoLock(); } } finally { theLock.ExitWriteLock(); } } protected virtual void InitializeEventMethods_NoLock() { otherMethods = new List(); } protected void ResetMethods() { otherMethods = null; } private void ModifyAttributes(bool set, EventAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } public override string ToString() { return FullName; } } public class EventDefUser : EventDef { public EventDefUser() { } public EventDefUser(UTF8String name) : this(name, null, (EventAttributes)0) { } public EventDefUser(UTF8String name, ITypeDefOrRef type) : this(name, type, (EventAttributes)0) { } public EventDefUser(UTF8String name, ITypeDefOrRef type, EventAttributes flags) { base.name = name; eventType = type; attributes = (int)flags; } } internal sealed class EventDefMD : EventDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Event, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public EventDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadEventRow(origRid, out var row); attributes = row.EventFlags; name = readerModule.StringsStream.ReadNoNull(row.Name); declaringType2 = readerModule.GetOwnerType(this); eventType = readerModule.ResolveTypeDefOrRef(row.EventType, new GenericParamContext(declaringType2)); } internal EventDefMD InitializeAll() { MemberMDInitializer.Initialize(base.Attributes); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.EventType); MemberMDInitializer.Initialize(base.CustomAttributes); MemberMDInitializer.Initialize(base.AddMethod); MemberMDInitializer.Initialize(base.InvokeMethod); MemberMDInitializer.Initialize(base.RemoveMethod); MemberMDInitializer.Initialize(base.OtherMethods); MemberMDInitializer.Initialize(base.DeclaringType); return this; } protected override void InitializeEventMethods_NoLock() { IList list; if (!(declaringType2 is TypeDefMD typeDefMD)) { list = new List(); } else { typeDefMD.InitializeEvent(this, out addMethod, out invokeMethod, out removeMethod, out list); } otherMethods = list; } } public abstract class ExportedType : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IImplementation, IFullName, IHasCustomDebugInformation, IType, IOwnerModule, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter { protected uint rid; private readonly Lock theLock = Lock.Create(); protected ModuleDef module; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected int attributes; protected uint typeDefId; protected UTF8String typeName; protected UTF8String typeNamespace; protected IImplementation implementation; protected bool implementation_isInitialized; private const int MAX_LOOP_ITERS = 50; public MDToken MDToken => new MDToken(Table.ExportedType, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 17; public int ImplementationTag => 2; public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 17; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool IsValueType => Resolve()?.IsValueType ?? false; public bool IsPrimitive => this.IsPrimitive(); string IType.TypeName => TypeName; public UTF8String Name { get { return typeName; } set { typeName = value; } } public string ReflectionName => FullNameFactory.Name(this, isReflection: true); public string Namespace => TypeNamespace; public string ReflectionNamespace => FullNameFactory.Namespace(this, isReflection: true); public string FullName => FullNameFactory.FullName(this, isReflection: false); public string ReflectionFullName => FullNameFactory.FullName(this, isReflection: true); public string AssemblyQualifiedName => FullNameFactory.AssemblyQualifiedName(this); public IAssembly DefinitionAssembly => FullNameFactory.DefinitionAssembly(this); public IScope Scope => FullNameFactory.Scope(this); public ITypeDefOrRef ScopeType => FullNameFactory.ScopeType(this); public bool ContainsGenericParameter => false; public ModuleDef Module => module; bool IIsTypeOrMethod.IsMethod => false; bool IIsTypeOrMethod.IsType => true; int IGenericParameterProvider.NumberOfGenericParameters => 0; public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (int)value; } } public uint TypeDefId { get { return typeDefId; } set { typeDefId = value; } } public UTF8String TypeName { get { return typeName; } set { typeName = value; } } public UTF8String TypeNamespace { get { return typeNamespace; } set { typeNamespace = value; } } public IImplementation Implementation { get { if (!implementation_isInitialized) { InitializeImplementation(); } return implementation; } set { theLock.EnterWriteLock(); try { implementation = value; implementation_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public bool IsNested => DeclaringType != null; public ExportedType DeclaringType { get { if (!implementation_isInitialized) { InitializeImplementation(); } return implementation as ExportedType; } } public TypeAttributes Visibility { get { return (TypeAttributes)(attributes & 7); } set { ModifyAttributes(~TypeAttributes.VisibilityMask, value & TypeAttributes.VisibilityMask); } } public bool IsNotPublic => (attributes & 7) == 0; public bool IsPublic => (attributes & 7) == 1; public bool IsNestedPublic => (attributes & 7) == 2; public bool IsNestedPrivate => (attributes & 7) == 3; public bool IsNestedFamily => (attributes & 7) == 4; public bool IsNestedAssembly => (attributes & 7) == 5; public bool IsNestedFamilyAndAssembly => (attributes & 7) == 6; public bool IsNestedFamilyOrAssembly => (attributes & 7) == 7; public TypeAttributes Layout { get { return (TypeAttributes)(attributes & 0x18); } set { ModifyAttributes(~TypeAttributes.LayoutMask, value & TypeAttributes.LayoutMask); } } public bool IsAutoLayout => (attributes & 0x18) == 0; public bool IsSequentialLayout => (attributes & 0x18) == 8; public bool IsExplicitLayout => (attributes & 0x18) == 16; public bool IsInterface { get { return (attributes & 0x20) != 0; } set { ModifyAttributes(value, TypeAttributes.ClassSemanticsMask); } } public bool IsClass { get { return (attributes & 0x20) == 0; } set { ModifyAttributes(!value, TypeAttributes.ClassSemanticsMask); } } public bool IsAbstract { get { return (attributes & 0x80) != 0; } set { ModifyAttributes(value, TypeAttributes.Abstract); } } public bool IsSealed { get { return (attributes & 0x100) != 0; } set { ModifyAttributes(value, TypeAttributes.Sealed); } } public bool IsSpecialName { get { return (attributes & 0x400) != 0; } set { ModifyAttributes(value, TypeAttributes.SpecialName); } } public bool IsImport { get { return (attributes & 0x1000) != 0; } set { ModifyAttributes(value, TypeAttributes.Import); } } public bool IsSerializable { get { return (attributes & 0x2000) != 0; } set { ModifyAttributes(value, TypeAttributes.Serializable); } } public bool IsWindowsRuntime { get { return (attributes & 0x4000) != 0; } set { ModifyAttributes(value, TypeAttributes.WindowsRuntime); } } public TypeAttributes StringFormat { get { return (TypeAttributes)(attributes & 0x30000); } set { ModifyAttributes(~TypeAttributes.StringFormatMask, value & TypeAttributes.StringFormatMask); } } public bool IsAnsiClass => (attributes & 0x30000) == 0; public bool IsUnicodeClass => (attributes & 0x30000) == 65536; public bool IsAutoClass => (attributes & 0x30000) == 131072; public bool IsCustomFormatClass => (attributes & 0x30000) == 196608; public bool IsBeforeFieldInit { get { return (attributes & 0x100000) != 0; } set { ModifyAttributes(value, TypeAttributes.BeforeFieldInit); } } public bool IsForwarder { get { return (attributes & 0x200000) != 0; } set { ModifyAttributes(value, TypeAttributes.Forwarder); } } public bool IsRuntimeSpecialName { get { return (attributes & 0x800) != 0; } set { ModifyAttributes(value, TypeAttributes.RTSpecialName); } } public bool HasSecurity { get { return (attributes & 0x40000) != 0; } set { ModifyAttributes(value, TypeAttributes.HasSecurity); } } public bool MovedToAnotherAssembly { get { ExportedType exportedType = this; for (int i = 0; i < 50; i++) { IImplementation implementation = exportedType.Implementation; if (implementation is AssemblyRef) { return exportedType.IsForwarder; } exportedType = implementation as ExportedType; if (exportedType == null) { break; } } return false; } } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void InitializeImplementation() { theLock.EnterWriteLock(); try { if (!implementation_isInitialized) { implementation = GetImplementation_NoLock(); implementation_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual IImplementation GetImplementation_NoLock() { return null; } private void ModifyAttributes(TypeAttributes andMask, TypeAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, TypeAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~flags); } } public TypeDef Resolve() { return Resolve(null); } public TypeDef Resolve(ModuleDef sourceModule) { if (module == null) { return null; } return Resolve(sourceModule, this); } private static TypeDef Resolve(ModuleDef sourceModule, ExportedType et) { for (int i = 0; i < 50; i++) { if (et == null) { break; } if (et.module == null) { break; } AssemblyDef assemblyDef = et.module.Context.AssemblyResolver.Resolve(et.DefinitionAssembly, sourceModule ?? et.module); if (assemblyDef == null) { break; } TypeDef typeDef = assemblyDef.Find(et.FullName, isReflectionName: false); if (typeDef != null) { return typeDef; } et = FindExportedType(assemblyDef, et); } return null; } private static ExportedType FindExportedType(AssemblyDef asm, ExportedType et) { IList modules = asm.Modules; int count = modules.Count; for (int i = 0; i < count; i++) { IList exportedTypes = modules[i].ExportedTypes; int count2 = exportedTypes.Count; for (int j = 0; j < count2; j++) { ExportedType exportedType = exportedTypes[j]; if (new SigComparer(SigComparerOptions.DontCompareTypeScope).Equals(et, exportedType)) { return exportedType; } } } return null; } public TypeDef ResolveThrow() { TypeDef typeDef = Resolve(); if (typeDef != null) { return typeDef; } throw new TypeResolveException($"Could not resolve type: {this} ({DefinitionAssembly})"); } public TypeRef ToTypeRef() { TypeRef typeRef = null; TypeRef typeRef2 = null; ModuleDef moduleDef = module; IImplementation implementation = this; for (int i = 0; i < 50; i++) { if (implementation == null) { break; } if (implementation is ExportedType exportedType) { TypeRefUser typeRefUser = moduleDef.UpdateRowId(new TypeRefUser(moduleDef, exportedType.TypeNamespace, exportedType.TypeName)); if (typeRef == null) { typeRef = typeRefUser; } if (typeRef2 != null) { typeRef2.ResolutionScope = typeRefUser; } typeRef2 = typeRefUser; implementation = exportedType.Implementation; continue; } if (implementation is AssemblyRef resolutionScope) { typeRef2.ResolutionScope = resolutionScope; return typeRef; } if (!(implementation is FileDef file)) { break; } typeRef2.ResolutionScope = FindModule(moduleDef, file); return typeRef; } return typeRef; } private static ModuleDef FindModule(ModuleDef module, FileDef file) { if (module == null || file == null) { return null; } if (UTF8String.CaseInsensitiveEquals(module.Name, file.Name)) { return module; } return module.Assembly?.FindModule(file.Name); } public override string ToString() { return FullName; } } public class ExportedTypeUser : ExportedType { public ExportedTypeUser(ModuleDef module) { base.module = module; } public ExportedTypeUser(ModuleDef module, uint typeDefId, UTF8String typeNamespace, UTF8String typeName, TypeAttributes flags, IImplementation implementation) { base.module = module; base.typeDefId = typeDefId; base.typeName = typeName; base.typeNamespace = typeNamespace; attributes = (int)flags; base.implementation = implementation; implementation_isInitialized = true; } } internal sealed class ExportedTypeMD : ExportedType, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly uint implementationRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ExportedType, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } protected override IImplementation GetImplementation_NoLock() { return readerModule.ResolveImplementation(implementationRid); } public ExportedTypeMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; module = readerModule; readerModule.TablesStream.TryReadExportedTypeRow(origRid, out var row); implementationRid = row.Implementation; attributes = (int)row.Flags; typeDefId = row.TypeDefId; typeName = readerModule.StringsStream.ReadNoNull(row.TypeName); typeNamespace = readerModule.StringsStream.ReadNoNull(row.TypeNamespace); } } [Flags] public enum FieldAttributes : ushort { FieldAccessMask = 7, PrivateScope = 0, CompilerControlled = 0, Private = 1, FamANDAssem = 2, Assembly = 3, Family = 4, FamORAssem = 5, Public = 6, Static = 0x10, InitOnly = 0x20, Literal = 0x40, NotSerialized = 0x80, SpecialName = 0x200, PinvokeImpl = 0x2000, RTSpecialName = 0x400, HasFieldMarshal = 0x1000, HasDefault = 0x8000, HasFieldRVA = 0x100 } public abstract class FieldDef : IHasConstant, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName, IHasFieldMarshal, IMemberForwarded, IMemberRef, IOwnerModule, IIsTypeOrMethod, IHasCustomDebugInformation, IField, ITokenOperand, IMemberDef, IDnlibDef { protected uint rid; private readonly Lock theLock = Lock.Create(); protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected int attributes; protected UTF8String name; protected CallingConventionSig signature; protected uint? fieldOffset; protected bool fieldOffset_isInitialized; protected MarshalType marshalType; protected bool marshalType_isInitialized; protected RVA rva; protected bool rva_isInitialized; protected byte[] initialValue; protected bool initialValue_isInitialized; protected ImplMap implMap; protected bool implMap_isInitialized; protected Constant constant; protected bool constant_isInitialized; protected TypeDef declaringType2; public MDToken MDToken => new MDToken(Table.Field, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasConstantTag => 0; public int HasCustomAttributeTag => 1; public int HasFieldMarshalTag => 0; public int MemberForwardedTag => 0; public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public int HasCustomDebugInformationTag => 1; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public FieldAttributes Attributes { get { return (FieldAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public CallingConventionSig Signature { get { return signature; } set { signature = value; } } public uint? FieldOffset { get { if (!fieldOffset_isInitialized) { InitializeFieldOffset(); } return fieldOffset; } set { theLock.EnterWriteLock(); try { fieldOffset = value; fieldOffset_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public MarshalType MarshalType { get { if (!marshalType_isInitialized) { InitializeMarshalType(); } return marshalType; } set { theLock.EnterWriteLock(); try { marshalType = value; marshalType_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public RVA RVA { get { if (!rva_isInitialized) { InitializeRVA(); } return rva; } set { theLock.EnterWriteLock(); try { rva = value; rva_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public byte[] InitialValue { get { if (!initialValue_isInitialized) { InitializeInitialValue(); } return initialValue; } set { theLock.EnterWriteLock(); try { initialValue = value; initialValue_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public ImplMap ImplMap { get { if (!implMap_isInitialized) { InitializeImplMap(); } return implMap; } set { theLock.EnterWriteLock(); try { implMap = value; implMap_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public Constant Constant { get { if (!constant_isInitialized) { InitializeConstant(); } return constant; } set { theLock.EnterWriteLock(); try { constant = value; constant_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public bool HasImplMap => ImplMap != null; public TypeDef DeclaringType { get { return declaringType2; } set { TypeDef typeDef = DeclaringType2; if (typeDef != value) { typeDef?.Fields.Remove(this); value?.Fields.Add(this); } } } ITypeDefOrRef IMemberRef.DeclaringType => declaringType2; public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } public FieldSig FieldSig { get { return signature as FieldSig; } set { signature = value; } } public ModuleDef Module => declaringType2?.Module; bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => true; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => true; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public bool HasLayoutInfo => FieldOffset.HasValue; public bool HasConstant => Constant != null; public ElementType ElementType => Constant?.Type ?? ElementType.End; public bool HasMarshalType => MarshalType != null; public TypeSig FieldType { get { return FieldSig.GetFieldType(); } set { FieldSig fieldSig = FieldSig; if (fieldSig != null) { fieldSig.Type = value; } } } public FieldAttributes Access { get { return (FieldAttributes)((ushort)attributes & 7); } set { ModifyAttributes(~FieldAttributes.FieldAccessMask, value & FieldAttributes.FieldAccessMask); } } public bool IsCompilerControlled => IsPrivateScope; public bool IsPrivateScope => ((ushort)attributes & 7) == 0; public bool IsPrivate => ((ushort)attributes & 7) == 1; public bool IsFamilyAndAssembly => ((ushort)attributes & 7) == 2; public bool IsAssembly => ((ushort)attributes & 7) == 3; public bool IsFamily => ((ushort)attributes & 7) == 4; public bool IsFamilyOrAssembly => ((ushort)attributes & 7) == 5; public bool IsPublic => ((ushort)attributes & 7) == 6; public bool IsStatic { get { return ((ushort)attributes & 0x10) != 0; } set { ModifyAttributes(value, FieldAttributes.Static); } } public bool IsInitOnly { get { return ((ushort)attributes & 0x20) != 0; } set { ModifyAttributes(value, FieldAttributes.InitOnly); } } public bool IsLiteral { get { return ((ushort)attributes & 0x40) != 0; } set { ModifyAttributes(value, FieldAttributes.Literal); } } public bool IsNotSerialized { get { return ((ushort)attributes & 0x80) != 0; } set { ModifyAttributes(value, FieldAttributes.NotSerialized); } } public bool IsSpecialName { get { return ((ushort)attributes & 0x200) != 0; } set { ModifyAttributes(value, FieldAttributes.SpecialName); } } public bool IsPinvokeImpl { get { return ((ushort)attributes & 0x2000) != 0; } set { ModifyAttributes(value, FieldAttributes.PinvokeImpl); } } public bool IsRuntimeSpecialName { get { return ((ushort)attributes & 0x400) != 0; } set { ModifyAttributes(value, FieldAttributes.RTSpecialName); } } public bool HasFieldMarshal { get { return ((ushort)attributes & 0x1000) != 0; } set { ModifyAttributes(value, FieldAttributes.HasFieldMarshal); } } public bool HasDefault { get { return ((ushort)attributes & 0x8000) != 0; } set { ModifyAttributes(value, FieldAttributes.HasDefault); } } public bool HasFieldRVA { get { return ((ushort)attributes & 0x100) != 0; } set { ModifyAttributes(value, FieldAttributes.HasFieldRVA); } } public string FullName => FullNameFactory.FieldFullName(declaringType2?.FullName, name, FieldSig); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void InitializeFieldOffset() { theLock.EnterWriteLock(); try { if (!fieldOffset_isInitialized) { fieldOffset = GetFieldOffset_NoLock(); fieldOffset_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual uint? GetFieldOffset_NoLock() { return null; } private void InitializeMarshalType() { theLock.EnterWriteLock(); try { if (!marshalType_isInitialized) { marshalType = GetMarshalType_NoLock(); marshalType_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual MarshalType GetMarshalType_NoLock() { return null; } protected void ResetMarshalType() { marshalType_isInitialized = false; } private void InitializeRVA() { theLock.EnterWriteLock(); try { if (!rva_isInitialized) { rva = GetRVA_NoLock(); rva_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual RVA GetRVA_NoLock() { return (RVA)0u; } protected void ResetRVA() { rva_isInitialized = false; } private void InitializeInitialValue() { theLock.EnterWriteLock(); try { if (!initialValue_isInitialized) { initialValue = GetInitialValue_NoLock(); initialValue_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual byte[] GetInitialValue_NoLock() { return null; } protected void ResetInitialValue() { initialValue_isInitialized = false; } private void InitializeImplMap() { theLock.EnterWriteLock(); try { if (!implMap_isInitialized) { implMap = GetImplMap_NoLock(); implMap_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual ImplMap GetImplMap_NoLock() { return null; } private void InitializeConstant() { theLock.EnterWriteLock(); try { if (!constant_isInitialized) { constant = GetConstant_NoLock(); constant_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual Constant GetConstant_NoLock() { return null; } protected void ResetConstant() { constant_isInitialized = false; } private void ModifyAttributes(FieldAttributes andMask, FieldAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, FieldAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } public uint GetFieldSize() { if (!GetFieldSize(out var size)) { return 0u; } return size; } public bool GetFieldSize(out uint size) { return GetFieldSize(declaringType2, FieldSig, out size); } protected bool GetFieldSize(TypeDef declaringType, FieldSig fieldSig, out uint size) { return GetFieldSize(declaringType, fieldSig, GetPointerSize(declaringType), out size); } protected bool GetFieldSize(TypeDef declaringType, FieldSig fieldSig, int ptrSize, out uint size) { size = 0u; if (fieldSig == null) { return false; } return GetClassSize(declaringType, fieldSig.Type, ptrSize, out size); } private bool GetClassSize(TypeDef declaringType, TypeSig ts, int ptrSize, out uint size) { size = 0u; ts = ts.RemovePinnedAndModifiers(); if (ts == null) { return false; } int primitiveSize = ts.ElementType.GetPrimitiveSize(ptrSize); if (primitiveSize >= 0) { size = (uint)primitiveSize; return true; } if (!(ts is TypeDefOrRefSig { TypeDef: var typeDef } typeDefOrRefSig)) { return false; } if (typeDef != null) { return TypeDef.GetClassSize(typeDef, out size); } TypeRef typeRef = typeDefOrRefSig.TypeRef; if (typeRef != null) { return TypeDef.GetClassSize(typeRef.Resolve(), out size); } return false; } private int GetPointerSize(TypeDef declaringType) { if (declaringType == null) { return 4; } return declaringType.Module?.GetPointerSize() ?? 4; } public override string ToString() { return FullName; } } public class FieldDefUser : FieldDef { public FieldDefUser() { } public FieldDefUser(UTF8String name) : this(name, null) { } public FieldDefUser(UTF8String name, FieldSig signature) : this(name, signature, FieldAttributes.PrivateScope) { } public FieldDefUser(UTF8String name, FieldSig signature, FieldAttributes attributes) { base.name = name; base.signature = signature; base.attributes = (int)attributes; } } internal sealed class FieldDefMD : FieldDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly FieldAttributes origAttributes; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Field, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } protected override uint? GetFieldOffset_NoLock() { if (readerModule.TablesStream.TryReadFieldLayoutRow(readerModule.Metadata.GetFieldLayoutRid(origRid), out var row)) { return row.OffSet; } return null; } protected override MarshalType GetMarshalType_NoLock() { return readerModule.ReadMarshalType(Table.Field, origRid, new GenericParamContext(declaringType2)); } protected override RVA GetRVA_NoLock() { GetFieldRVA_NoLock(out var result); return result; } protected override byte[] GetInitialValue_NoLock() { if (!GetFieldRVA_NoLock(out var rVA)) { return null; } return ReadInitialValue_NoLock(rVA); } protected override ImplMap GetImplMap_NoLock() { return readerModule.ResolveImplMap(readerModule.Metadata.GetImplMapRid(Table.Field, origRid)); } protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.Metadata.GetConstantRid(Table.Field, origRid)); } public FieldDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadFieldRow(origRid, out var row); name = readerModule.StringsStream.ReadNoNull(row.Name); attributes = row.Flags; origAttributes = (FieldAttributes)attributes; declaringType2 = readerModule.GetOwnerType(this); signature = readerModule.ReadSignature(row.Signature, new GenericParamContext(declaringType2)); } internal FieldDefMD InitializeAll() { MemberMDInitializer.Initialize(base.CustomAttributes); MemberMDInitializer.Initialize(base.Attributes); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.Signature); MemberMDInitializer.Initialize(base.FieldOffset); MemberMDInitializer.Initialize(base.MarshalType); MemberMDInitializer.Initialize(base.RVA); MemberMDInitializer.Initialize(base.InitialValue); MemberMDInitializer.Initialize(base.ImplMap); MemberMDInitializer.Initialize(base.Constant); MemberMDInitializer.Initialize(base.DeclaringType); return this; } private bool GetFieldRVA_NoLock(out RVA rva) { if ((origAttributes & FieldAttributes.HasFieldRVA) == 0) { rva = (RVA)0u; return false; } if (!readerModule.TablesStream.TryReadFieldRVARow(readerModule.Metadata.GetFieldRVARid(origRid), out var row)) { rva = (RVA)0u; return false; } rva = (RVA)row.RVA; return true; } private byte[] ReadInitialValue_NoLock(RVA rva) { if (!GetFieldSize(declaringType2, signature as FieldSig, out var size)) { return null; } if (size >= int.MaxValue) { return null; } return readerModule.ReadDataAt(rva, (int)size); } } [Flags] public enum FileAttributes : uint { ContainsMetadata = 0u, ContainsNoMetadata = 1u } public abstract class FileDef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IImplementation, IFullName, IHasCustomDebugInformation, IManagedEntryPoint { protected uint rid; protected int attributes; protected UTF8String name; protected byte[] hashValue; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.File, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 16; public int ImplementationTag => 0; public FileAttributes Flags { get { return (FileAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public byte[] HashValue { get { return hashValue; } set { hashValue = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 16; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool ContainsMetadata { get { return (attributes & 1) == 0; } set { ModifyAttributes(!value, FileAttributes.ContainsNoMetadata); } } public bool ContainsNoMetadata { get { return (attributes & 1) != 0; } set { ModifyAttributes(value, FileAttributes.ContainsNoMetadata); } } public string FullName => UTF8String.ToSystemStringOrEmpty(name); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(bool set, FileAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~flags); } } public override string ToString() { return FullName; } } public class FileDefUser : FileDef { public FileDefUser() { } public FileDefUser(UTF8String name, FileAttributes flags, byte[] hashValue) { base.name = name; attributes = (int)flags; base.hashValue = hashValue; } } internal sealed class FileDefMD : FileDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.File, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public FileDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadFileRow(origRid, out var row); attributes = (int)row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); hashValue = readerModule.BlobStream.Read(row.HashValue); } } public static class FrameworkRedirect { private readonly struct FrameworkRedirectInfo { public readonly PublicKeyToken publicKeyToken; public readonly Version redirectVersion; public FrameworkRedirectInfo(string publicKeyToken, string redirectVersion) { this.publicKeyToken = new PublicKeyToken(publicKeyToken); this.redirectVersion = new Version(redirectVersion); } } private static readonly Dictionary frmRedir2; private static readonly Dictionary frmRedir4; static FrameworkRedirect() { frmRedir2 = new Dictionary(StringComparer.OrdinalIgnoreCase); frmRedir4 = new Dictionary(StringComparer.OrdinalIgnoreCase); InitFrameworkRedirectV2(); InitFrameworkRedirectV4(); } private static void InitFrameworkRedirectV2() { frmRedir2["Accessibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["cscompmgd"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["CustomMarshalers"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IEExecRemote"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IEHost"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IIEHost"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["ISymWrapper"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["Microsoft.JScript"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Compatibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Compatibility.Data"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Vsa"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.Vsa"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.Vsa.Vb.CodeDOMProcessor"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft_VsaVb"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["mscorcfg"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["mscorlib"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Configuration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Configuration.Install"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Data"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Data.OracleClient"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Data.SqlXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Deployment"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.DirectoryServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.DirectoryServices.Protocols"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Drawing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Drawing.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.EnterpriseServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Management"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Messaging"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Runtime.Remoting"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Runtime.Serialization.Formatters.Soap"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.ServiceProcess"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Transactions"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Web"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.Mobile"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.Services"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Windows.Forms"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Xml"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["vjscor"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["VJSharpCodeProvider"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjsJBC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjslib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjslibcw"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["Vjssupuilib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjsvwaux"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["VJSWfcBrowserStubLib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfccw"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfchtml"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); } private static void InitFrameworkRedirectV4() { frmRedir4["Accessibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["CustomMarshalers"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["ISymWrapper"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.JScript"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic.Compatibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic.Compatibility.Data"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["mscorlib"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Configuration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Configuration.Install"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Data"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.OracleClient"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.SqlXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Deployment"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.DirectoryServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.DirectoryServices.Protocols"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Drawing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Drawing.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.EnterpriseServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Management"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Messaging"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Remoting"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Formatters.Soap"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceProcess"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Transactions"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.Mobile"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.Services"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Windows.Forms"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["AspNetMMCExt"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["sysglobl"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Engine"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Framework"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["PresentationCFFRasterizer"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationCore"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Aero"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Classic"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Luna"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Royale"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationUI"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["ReachFramework"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Printing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Speech"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationClient"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationClientsideProviders"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationProvider"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationTypes"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["WindowsBase"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["WindowsFormsIntegration"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["SMDiagnostics"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel.Selectors"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Log"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.Install"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.WasHosting"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Workflow.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Workflow.ComponentModel"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Workflow.Runtime"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Transactions.Bridge"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Transactions.Bridge.Dtc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.AddIn"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.AddIn.Contract"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.Composition"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Core"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.DataSetExtensions"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Linq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xml.Linq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.DirectoryServices.AccountManagement"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Management.Instrumentation"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Net"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Web"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Extensions"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Extensions.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Presentation"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.WorkflowServices"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ComponentModel.DataAnnotations"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Data.Entity"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Entity.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services.Client"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Abstractions"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DynamicData"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DynamicData.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Entity"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Entity.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Routing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Build"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.CSharp"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Dynamic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Numerics"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xaml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["Microsoft.Workflow.Compiler"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Activities.Build"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Build.Conversion.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Tasks.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Utilities.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Internal.Tasks.Dataflow"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["Microsoft.VisualBasic.Activities.Compiler"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualC.STLCLR"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir4["Microsoft.Windows.ApplicationServer.Applications"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationBuildTasks"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Aero2"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.AeroLite"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework-SystemCore"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemData"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemDrawing"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemXmlLinq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.Core.Presentation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.DurableInstancing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.Presentation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ComponentModel.Composition.Registration"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Device"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel.Services"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Compression"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Compression.FileSystem"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Net.Http"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Http.WebRequest"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Context"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.Caching"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.DurableInstancing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Runtime.WindowsRuntime"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.WindowsRuntime.UI.Xaml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.Activation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Channels"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Discovery"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Internals"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Routing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.ServiceMoniker40"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.ApplicationServices"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DataVisualization"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DataVisualization.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Controls.Ribbon"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Windows.Forms.DataVisualization"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Forms.DataVisualization.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Input.Manipulations"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xaml.Hosting"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["XamlBuildTask"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["XsdBuildTask"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Collections"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Collections.Concurrent"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.Annotations"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.EventBasedAsync"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Contracts"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Debug"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Tools"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Tracing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Dynamic.Runtime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Globalization"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.IO"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Expressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Parallel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Queryable"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.NetworkInformation"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Requests"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ObjectModel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit.ILGeneration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit.Lightweight"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Resources.ResourceManager"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.InteropServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.InteropServices.WindowsRuntime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Numerics"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Json"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Xml"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Security.Principal"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Duplex"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Http"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.NetTcp"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.Encoding"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.Encoding.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Timer"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Tasks"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Tasks.Parallel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.ReaderWriter"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.XDocument"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.XmlSerializer"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Http.Rtc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Windows"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.Serialization"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); } public static void ApplyFrameworkRedirect(ref IAssembly assembly, ModuleDef sourceModule) { if (TryApplyFrameworkRedirectCore(assembly, sourceModule, out var redirectedAssembly)) { assembly = redirectedAssembly; } } public static bool TryApplyFrameworkRedirect(IAssembly assembly, ModuleDef sourceModule, out IAssembly redirectedAssembly) { return TryApplyFrameworkRedirectCore(assembly, sourceModule, out redirectedAssembly); } private static bool TryApplyFrameworkRedirectCore(IAssembly assembly, ModuleDef sourceModule, out IAssembly redirectedAssembly) { if (sourceModule != null) { if (sourceModule.IsClr40) { return TryApplyFrameworkRedirect(assembly, frmRedir4, out redirectedAssembly); } if (sourceModule.IsClr20) { return TryApplyFrameworkRedirect(assembly, frmRedir2, out redirectedAssembly); } } redirectedAssembly = null; return false; } public static void ApplyFrameworkRedirectV2(ref IAssembly assembly) { if (TryApplyFrameworkRedirect(assembly, frmRedir2, out var redirectedAssembly)) { assembly = redirectedAssembly; } } public static void ApplyFrameworkRedirectV4(ref IAssembly assembly) { if (TryApplyFrameworkRedirect(assembly, frmRedir4, out var redirectedAssembly)) { assembly = redirectedAssembly; } } public static bool TryApplyFrameworkRedirectV2(IAssembly assembly, out IAssembly redirectedAssembly) { return TryApplyFrameworkRedirect(assembly, frmRedir2, out redirectedAssembly); } public static bool TryApplyFrameworkRedirectV4(IAssembly assembly, out IAssembly redirectedAssembly) { return TryApplyFrameworkRedirect(assembly, frmRedir4, out redirectedAssembly); } private static bool TryApplyFrameworkRedirect(IAssembly assembly, Dictionary frmRedir, out IAssembly redirectedAssembly) { redirectedAssembly = null; if (!Utils.LocaleEquals(assembly.Culture, "")) { return false; } if (!frmRedir.TryGetValue(assembly.Name, out var value)) { return false; } if (PublicKeyBase.TokenCompareTo(assembly.PublicKeyOrToken, value.publicKeyToken) != 0) { return false; } if (Utils.CompareTo(assembly.Version, value.redirectVersion) == 0) { redirectedAssembly = assembly; } else { redirectedAssembly = new AssemblyNameInfo(assembly); redirectedAssembly.Version = value.redirectVersion; } return true; } } public interface IFullNameFactoryHelper { bool MustUseAssemblyName(IType type); } public struct FullNameFactory { private const uint MaxArrayRank = 100u; private const uint MaxMethodGenParamCount = 200u; private const string RECURSION_ERROR_RESULT_STRING = "<<>>"; private const string NULLVALUE = "<<>>"; private readonly StringBuilder sb; private readonly bool isReflection; private readonly IFullNameFactoryHelper helper; private GenericArguments genericArguments; private RecursionCounter recursionCounter; private const int TYPESIG_NAMESPACE = 1; private const int TYPESIG_NAME = 2; private const int TYPESIG_ONLY_NAMESPACE = 4; private string Result => sb?.ToString(); public static bool MustUseAssemblyName(ModuleDef module, IType type) { return MustUseAssemblyName(module, type, allowCorlib: true); } public static bool MustUseAssemblyName(ModuleDef module, IType type, bool allowCorlib) { if (type is TypeDef typeDef) { return typeDef.Module != module; } if (!(type is TypeRef typeRef)) { return true; } if (typeRef.ResolutionScope == AssemblyRef.CurrentAssembly) { return false; } if (allowCorlib) { if (!typeRef.DefinitionAssembly.IsCorLib()) { return true; } return module.Find(typeRef) != null; } return true; } public static string FullName(IType type, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { return FullNameSB(type, isReflection, helper, sb).ToString(); } public static StringBuilder FullNameSB(IType type, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { if (type is TypeDef typeDef) { return FullNameSB(typeDef, isReflection, helper, sb); } if (type is TypeRef typeRef) { return FullNameSB(typeRef, isReflection, helper, sb); } if (type is TypeSpec typeSpec) { return FullNameSB(typeSpec, isReflection, helper, sb); } if (type is TypeSig typeSig) { return FullNameSB(typeSig, isReflection, helper, null, null, sb); } if (type is ExportedType exportedType) { return FullNameSB(exportedType, isReflection, helper, sb); } return sb ?? new StringBuilder(); } public static string Name(IType type, bool isReflection, StringBuilder sb) { return NameSB(type, isReflection, sb).ToString(); } public static StringBuilder NameSB(IType type, bool isReflection, StringBuilder sb) { if (type is TypeDef typeDef) { return NameSB(typeDef, isReflection, sb); } if (type is TypeRef typeRef) { return NameSB(typeRef, isReflection, sb); } if (type is TypeSpec typeSpec) { return NameSB(typeSpec, isReflection, sb); } if (type is TypeSig typeSig) { return NameSB(typeSig, isReflection, sb); } if (type is ExportedType exportedType) { return NameSB(exportedType, isReflection, sb); } return sb ?? new StringBuilder(); } public static string Namespace(IType type, bool isReflection, StringBuilder sb) { return NamespaceSB(type, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(IType type, bool isReflection, StringBuilder sb) { if (type is TypeDef typeDef) { return NamespaceSB(typeDef, isReflection, sb); } if (type is TypeRef typeRef) { return NamespaceSB(typeRef, isReflection, sb); } if (type is TypeSpec typeSpec) { return NamespaceSB(typeSpec, isReflection, sb); } if (type is TypeSig typeSig) { return NamespaceSB(typeSig, isReflection, sb); } if (type is ExportedType exportedType) { return NamespaceSB(exportedType, isReflection, sb); } return sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(IType type, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(type, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(IType type, IFullNameFactoryHelper helper, StringBuilder sb) { if (type is TypeDef typeDef) { return AssemblyQualifiedNameSB(typeDef, helper, sb); } if (type is TypeRef typeRef) { return AssemblyQualifiedNameSB(typeRef, helper, sb); } if (type is TypeSpec typeSpec) { return AssemblyQualifiedNameSB(typeSpec, helper, sb); } if (type is TypeSig typeSig) { return AssemblyQualifiedNameSB(typeSig, helper, sb); } if (type is ExportedType exportedType) { return AssemblyQualifiedNameSB(exportedType, helper, sb); } return sb ?? new StringBuilder(); } public static string PropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig, IList typeGenArgs = null, StringBuilder sb = null) { return PropertyFullNameSB(declaringType, name, propertySig, typeGenArgs, sb).ToString(); } public static StringBuilder PropertyFullNameSB(string declaringType, UTF8String name, CallingConventionSig propertySig, IList typeGenArgs, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); if (typeGenArgs != null) { fullNameFactory.genericArguments = new GenericArguments(); fullNameFactory.genericArguments.PushTypeArgs(typeGenArgs); } fullNameFactory.CreatePropertyFullName(declaringType, name, propertySig); return fullNameFactory.sb ?? new StringBuilder(); } public static string EventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList typeGenArgs = null, StringBuilder sb = null) { return EventFullNameSB(declaringType, name, typeDefOrRef, typeGenArgs, sb).ToString(); } public static StringBuilder EventFullNameSB(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList typeGenArgs, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); if (typeGenArgs != null) { fullNameFactory.genericArguments = new GenericArguments(); fullNameFactory.genericArguments.PushTypeArgs(typeGenArgs); } fullNameFactory.CreateEventFullName(declaringType, name, typeDefOrRef); return fullNameFactory.sb ?? new StringBuilder(); } public static string FieldFullName(string declaringType, string name, FieldSig fieldSig, IList typeGenArgs = null, StringBuilder sb = null) { return FieldFullNameSB(declaringType, name, fieldSig, typeGenArgs, sb).ToString(); } public static StringBuilder FieldFullNameSB(string declaringType, string name, FieldSig fieldSig, IList typeGenArgs, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); if (typeGenArgs != null) { fullNameFactory.genericArguments = new GenericArguments(); fullNameFactory.genericArguments.PushTypeArgs(typeGenArgs); } fullNameFactory.CreateFieldFullName(declaringType, name, fieldSig); return fullNameFactory.sb ?? new StringBuilder(); } public static string MethodFullName(string declaringType, string name, MethodSig methodSig, IList typeGenArgs = null, IList methodGenArgs = null, MethodDef gppMethod = null, StringBuilder sb = null) { return MethodFullNameSB(declaringType, name, methodSig, typeGenArgs, methodGenArgs, gppMethod, sb).ToString(); } public static StringBuilder MethodFullNameSB(string declaringType, string name, MethodSig methodSig, IList typeGenArgs, IList methodGenArgs, MethodDef gppMethod, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); if (typeGenArgs != null || methodGenArgs != null) { fullNameFactory.genericArguments = new GenericArguments(); } if (typeGenArgs != null) { fullNameFactory.genericArguments.PushTypeArgs(typeGenArgs); } if (methodGenArgs != null) { fullNameFactory.genericArguments.PushMethodArgs(methodGenArgs); } fullNameFactory.CreateMethodFullName(declaringType, name, methodSig, gppMethod); return fullNameFactory.sb ?? new StringBuilder(); } public static string MethodBaseSigFullName(MethodBaseSig sig, StringBuilder sb = null) { return MethodBaseSigFullNameSB(sig, sb).ToString(); } public static StringBuilder MethodBaseSigFullNameSB(MethodBaseSig sig, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); fullNameFactory.CreateMethodFullName(null, null, sig, null); return fullNameFactory.sb ?? new StringBuilder(); } public static string MethodBaseSigFullName(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb = null) { return MethodBaseSigFullNameSB(declType, name, sig, gppMethod, sb).ToString(); } public static StringBuilder MethodBaseSigFullNameSB(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); fullNameFactory.CreateMethodFullName(declType, name, sig, gppMethod); return fullNameFactory.sb ?? new StringBuilder(); } public static string Namespace(TypeRef typeRef, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeRef, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(TypeRef typeRef, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateNamespace(typeRef, onlyNamespace: true); return fullNameFactory.sb ?? new StringBuilder(); } public static string Name(TypeRef typeRef, bool isReflection, StringBuilder sb = null) { return NameSB(typeRef, isReflection, sb).ToString(); } public static StringBuilder NameSB(TypeRef typeRef, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateName(typeRef); return fullNameFactory.sb ?? new StringBuilder(); } public static string FullName(TypeRef typeRef, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeRef, isReflection, helper, sb).ToString(); } public static StringBuilder FullNameSB(TypeRef typeRef, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, helper, sb); fullNameFactory.CreateFullName(typeRef); return fullNameFactory.sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(TypeRef typeRef, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeRef, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(TypeRef typeRef, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: true, helper, sb); fullNameFactory.CreateAssemblyQualifiedName(typeRef); return fullNameFactory.sb ?? new StringBuilder(); } public static IAssembly DefinitionAssembly(TypeRef typeRef) { return default(FullNameFactory).GetDefinitionAssembly(typeRef); } public static IScope Scope(TypeRef typeRef) { return default(FullNameFactory).GetScope(typeRef); } public static ModuleDef OwnerModule(TypeRef typeRef) { return default(FullNameFactory).GetOwnerModule(typeRef); } public static string Namespace(TypeDef typeDef, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeDef, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(TypeDef typeDef, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateNamespace(typeDef, onlyNamespace: true); return fullNameFactory.sb ?? new StringBuilder(); } public static string Name(TypeDef typeDef, bool isReflection, StringBuilder sb = null) { return NameSB(typeDef, isReflection, sb).ToString(); } public static StringBuilder NameSB(TypeDef typeDef, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateName(typeDef); return fullNameFactory.sb ?? new StringBuilder(); } public static string FullName(TypeDef typeDef, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeDef, isReflection, helper, sb).ToString(); } public static StringBuilder FullNameSB(TypeDef typeDef, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, helper, sb); fullNameFactory.CreateFullName(typeDef); return fullNameFactory.sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(TypeDef typeDef, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeDef, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(TypeDef typeDef, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: true, helper, sb); fullNameFactory.CreateAssemblyQualifiedName(typeDef); return fullNameFactory.sb ?? new StringBuilder(); } public static IAssembly DefinitionAssembly(TypeDef typeDef) { return default(FullNameFactory).GetDefinitionAssembly(typeDef); } public static ModuleDef OwnerModule(TypeDef typeDef) { return default(FullNameFactory).GetOwnerModule(typeDef); } public static string Namespace(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeSpec, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateNamespace(typeSpec, onlyNamespace: true); return fullNameFactory.sb ?? new StringBuilder(); } public static string Name(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) { return NameSB(typeSpec, isReflection, sb).ToString(); } public static StringBuilder NameSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateName(typeSpec); return fullNameFactory.sb ?? new StringBuilder(); } public static string FullName(TypeSpec typeSpec, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeSpec, isReflection, helper, sb).ToString(); } public static StringBuilder FullNameSB(TypeSpec typeSpec, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, helper, sb); fullNameFactory.CreateFullName(typeSpec); return fullNameFactory.sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(TypeSpec typeSpec, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeSpec, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(TypeSpec typeSpec, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: true, helper, sb); fullNameFactory.CreateAssemblyQualifiedName(typeSpec); return fullNameFactory.sb ?? new StringBuilder(); } public static IAssembly DefinitionAssembly(TypeSpec typeSpec) { return default(FullNameFactory).GetDefinitionAssembly(typeSpec); } public static ITypeDefOrRef ScopeType(TypeSpec typeSpec) { return default(FullNameFactory).GetScopeType(typeSpec); } public static IScope Scope(TypeSpec typeSpec) { return default(FullNameFactory).GetScope(typeSpec); } public static ModuleDef OwnerModule(TypeSpec typeSpec) { return default(FullNameFactory).GetOwnerModule(typeSpec); } public static string Namespace(TypeSig typeSig, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeSig, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(TypeSig typeSig, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateNamespace(typeSig, onlyNamespace: true); return fullNameFactory.sb ?? new StringBuilder(); } public static string Name(TypeSig typeSig, bool isReflection, StringBuilder sb = null) { return NameSB(typeSig, isReflection, sb).ToString(); } public static StringBuilder NameSB(TypeSig typeSig, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateName(typeSig); return fullNameFactory.sb ?? new StringBuilder(); } public static string FullName(TypeSig typeSig, bool isReflection, IFullNameFactoryHelper helper = null, IList typeGenArgs = null, IList methodGenArgs = null, StringBuilder sb = null) { return FullNameSB(typeSig, isReflection, helper, typeGenArgs, methodGenArgs, sb).ToString(); } public static StringBuilder FullNameSB(TypeSig typeSig, bool isReflection, IFullNameFactoryHelper helper, IList typeGenArgs, IList methodGenArgs, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, helper, sb); if (typeGenArgs != null || methodGenArgs != null) { fullNameFactory.genericArguments = new GenericArguments(); } if (typeGenArgs != null) { fullNameFactory.genericArguments.PushTypeArgs(typeGenArgs); } if (methodGenArgs != null) { fullNameFactory.genericArguments.PushMethodArgs(methodGenArgs); } fullNameFactory.CreateFullName(typeSig); return fullNameFactory.sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(TypeSig typeSig, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeSig, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(TypeSig typeSig, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: true, helper, sb); fullNameFactory.CreateAssemblyQualifiedName(typeSig); return fullNameFactory.sb ?? new StringBuilder(); } public static IAssembly DefinitionAssembly(TypeSig typeSig) { return default(FullNameFactory).GetDefinitionAssembly(typeSig); } public static IScope Scope(TypeSig typeSig) { return default(FullNameFactory).GetScope(typeSig); } public static ITypeDefOrRef ScopeType(TypeSig typeSig) { return default(FullNameFactory).GetScopeType(typeSig); } public static ModuleDef OwnerModule(TypeSig typeSig) { return default(FullNameFactory).GetOwnerModule(typeSig); } public static string Namespace(ExportedType exportedType, bool isReflection, StringBuilder sb = null) { return NamespaceSB(exportedType, isReflection, sb).ToString(); } public static StringBuilder NamespaceSB(ExportedType exportedType, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateNamespace(exportedType, onlyNamespace: true); return fullNameFactory.sb ?? new StringBuilder(); } public static string Name(ExportedType exportedType, bool isReflection, StringBuilder sb = null) { return NameSB(exportedType, isReflection, sb).ToString(); } public static StringBuilder NameSB(ExportedType exportedType, bool isReflection, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, null, sb); fullNameFactory.CreateName(exportedType); return fullNameFactory.sb ?? new StringBuilder(); } public static string FullName(ExportedType exportedType, bool isReflection, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return FullNameSB(exportedType, isReflection, helper, sb).ToString(); } public static StringBuilder FullNameSB(ExportedType exportedType, bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection, helper, sb); fullNameFactory.CreateFullName(exportedType); return fullNameFactory.sb ?? new StringBuilder(); } public static string AssemblyQualifiedName(ExportedType exportedType, IFullNameFactoryHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(exportedType, helper, sb).ToString(); } public static StringBuilder AssemblyQualifiedNameSB(ExportedType exportedType, IFullNameFactoryHelper helper, StringBuilder sb) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: true, helper, sb); fullNameFactory.CreateAssemblyQualifiedName(exportedType); return fullNameFactory.sb ?? new StringBuilder(); } public static IAssembly DefinitionAssembly(ExportedType exportedType) { return default(FullNameFactory).GetDefinitionAssembly(exportedType); } public static ITypeDefOrRef ScopeType(ExportedType exportedType) { return default(FullNameFactory).GetScopeType(exportedType); } public static IScope Scope(ExportedType exportedType) { return default(FullNameFactory).GetScope(exportedType); } public static ModuleDef OwnerModule(ExportedType exportedType) { return default(FullNameFactory).GetOwnerModule(exportedType); } public static string AssemblyFullName(IAssembly assembly, bool withToken, StringBuilder sb = null) { return AssemblyFullNameSB(assembly, withToken, sb).ToString(); } public static StringBuilder AssemblyFullNameSB(IAssembly assembly, bool withToken, StringBuilder sb = null) { FullNameFactory fullNameFactory = new FullNameFactory(isReflection: false, null, sb); fullNameFactory.CreateAssemblyFullName(assembly, withToken); return fullNameFactory.sb ?? new StringBuilder(); } private FullNameFactory(bool isReflection, IFullNameFactoryHelper helper, StringBuilder sb) { this.sb = sb ?? new StringBuilder(); this.isReflection = isReflection; this.helper = helper; genericArguments = null; recursionCounter = default(RecursionCounter); } private bool MustUseAssemblyName(IType type) { if (helper == null) { return true; } return helper.MustUseAssemblyName(GetDefinitionType(type)); } private IType GetDefinitionType(IType type) { if (!recursionCounter.Increment()) { return type; } if (type is TypeSpec typeSpec) { type = typeSpec.TypeSig; } if (type is TypeSig typeSig) { type = ((!(typeSig is TypeDefOrRefSig typeDefOrRefSig)) ? ((!(typeSig is GenericInstSig genericInstSig)) ? GetDefinitionType(typeSig.Next) : GetDefinitionType(genericInstSig.GenericType)) : GetDefinitionType(typeDefOrRefSig.TypeDefOrRef)); } recursionCounter.Decrement(); return type; } private void CreateFullName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) { CreateFullName((TypeRef)typeDefOrRef); } else if (typeDefOrRef is TypeDef) { CreateFullName((TypeDef)typeDefOrRef); } else if (typeDefOrRef is TypeSpec) { CreateFullName((TypeSpec)typeDefOrRef); } else { sb.Append("<<>>"); } } private void CreateNamespace(ITypeDefOrRef typeDefOrRef, bool onlyNamespace) { if (typeDefOrRef is TypeRef) { CreateNamespace((TypeRef)typeDefOrRef, onlyNamespace); } else if (typeDefOrRef is TypeDef) { CreateNamespace((TypeDef)typeDefOrRef, onlyNamespace); } else if (typeDefOrRef is TypeSpec) { CreateNamespace((TypeSpec)typeDefOrRef, onlyNamespace); } else { sb.Append("<<>>"); } } private void CreateName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) { CreateName((TypeRef)typeDefOrRef); } else if (typeDefOrRef is TypeDef) { CreateName((TypeDef)typeDefOrRef); } else if (typeDefOrRef is TypeSpec) { CreateName((TypeSpec)typeDefOrRef); } else { sb.Append("<<>>"); } } private void CreateAssemblyQualifiedName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) { CreateAssemblyQualifiedName((TypeRef)typeDefOrRef); } else if (typeDefOrRef is TypeDef) { CreateAssemblyQualifiedName((TypeDef)typeDefOrRef); } else if (typeDefOrRef is TypeSpec) { CreateAssemblyQualifiedName((TypeSpec)typeDefOrRef); } else { sb.Append("<<>>"); } } private void CreateAssemblyQualifiedName(TypeRef typeRef) { if (typeRef == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } CreateFullName(typeRef); if (MustUseAssemblyName(typeRef)) { sb.Append(", "); CreateAssemblyFullName(GetDefinitionAssembly(typeRef), useToken: true); } recursionCounter.Decrement(); } private void CreateFullName(TypeRef typeRef) { if (typeRef == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } if (typeRef.ResolutionScope is TypeRef typeRef2) { CreateFullName(typeRef2); AddNestedTypeSeparator(); } if (AddNamespace(typeRef.Namespace, onlyNamespace: false)) { sb.Append('.'); } AddName(typeRef.Name); recursionCounter.Decrement(); } private void CreateNamespace(TypeRef typeRef, bool onlyNamespace) { if (typeRef == null) { sb.Append("<<>>"); } else { AddNamespace(typeRef.Namespace, onlyNamespace); } } private void CreateName(TypeRef typeRef) { if (typeRef == null) { sb.Append("<<>>"); } else { AddName(typeRef.Name); } } private void CreateAssemblyQualifiedName(TypeDef typeDef) { if (typeDef == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } CreateFullName(typeDef); if (MustUseAssemblyName(typeDef)) { sb.Append(", "); CreateAssemblyFullName(GetDefinitionAssembly(typeDef), useToken: true); } recursionCounter.Decrement(); } private void CreateFullName(TypeDef typeDef) { if (typeDef == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } TypeDef declaringType = typeDef.DeclaringType; if (declaringType != null) { CreateFullName(declaringType); AddNestedTypeSeparator(); } if (AddNamespace(typeDef.Namespace, onlyNamespace: false)) { sb.Append('.'); } AddName(typeDef.Name); recursionCounter.Decrement(); } private void CreateNamespace(TypeDef typeDef, bool onlyNamespace) { if (typeDef == null) { sb.Append("<<>>"); } else { AddNamespace(typeDef.Namespace, onlyNamespace); } } private void CreateName(TypeDef typeDef) { if (typeDef == null) { sb.Append("<<>>"); } else { AddName(typeDef.Name); } } private void CreateAssemblyQualifiedName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append("<<>>"); } else { CreateAssemblyQualifiedName(typeSpec.TypeSig); } } private void CreateFullName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append("<<>>"); } else { CreateFullName(typeSpec.TypeSig); } } private void CreateNamespace(TypeSpec typeSpec, bool onlyNamespace) { if (typeSpec == null) { sb.Append("<<>>"); } else { CreateNamespace(typeSpec.TypeSig, onlyNamespace); } } private void CreateName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append("<<>>"); } else { CreateName(typeSpec.TypeSig); } } private void CreateAssemblyQualifiedName(TypeSig typeSig) { if (typeSig == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } CreateFullName(typeSig); if (MustUseAssemblyName(typeSig)) { sb.Append(", "); CreateAssemblyFullName(GetDefinitionAssembly(typeSig), useToken: true); } recursionCounter.Decrement(); } private void CreateFullName(TypeSig typeSig) { CreateTypeSigName(typeSig, 3); } private void CreateNamespace(TypeSig typeSig, bool onlyNamespace) { CreateTypeSigName(typeSig, 1 | (onlyNamespace ? 4 : 0)); } private void CreateName(TypeSig typeSig) { CreateTypeSigName(typeSig, 2); } private TypeSig ReplaceGenericArg(TypeSig typeSig) { if (genericArguments == null) { return typeSig; } TypeSig typeSig2 = genericArguments.Resolve(typeSig); if (typeSig2 != typeSig) { genericArguments = null; } return typeSig2; } private void CreateTypeSigName(TypeSig typeSig, int flags) { if (typeSig == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } GenericArguments genericArguments = this.genericArguments; typeSig = ReplaceGenericArg(typeSig); bool flag = (flags & 1) != 0; bool flag2 = (flags & 2) != 0; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: if (flag && flag2) { CreateFullName(((TypeDefOrRefSig)typeSig).TypeDefOrRef); } else if (flag) { CreateNamespace(((TypeDefOrRefSig)typeSig).TypeDefOrRef, (flags & 4) != 0); } else if (flag2) { CreateName(((TypeDefOrRefSig)typeSig).TypeDefOrRef); } break; case ElementType.Ptr: CreateTypeSigName(typeSig.Next, flags); if (flag2) { sb.Append('*'); } break; case ElementType.ByRef: CreateTypeSigName(typeSig.Next, flags); if (flag2) { sb.Append('&'); } break; case ElementType.Array: { CreateTypeSigName(typeSig.Next, flags); if (!flag2) { break; } ArraySig arraySig = (ArraySig)typeSig; sb.Append('['); uint num = arraySig.Rank; if (num > 100) { num = 100u; } switch (num) { case 0u: sb.Append(""); break; case 1u: sb.Append('*'); break; default: { for (int i = 0; i < (int)num; i++) { if (i != 0) { sb.Append(','); } if (isReflection) { continue; } int num2 = ((i < arraySig.LowerBounds.Count) ? arraySig.LowerBounds[i] : int.MinValue); uint num3 = ((i < arraySig.Sizes.Count) ? arraySig.Sizes[i] : uint.MaxValue); if (num2 != int.MinValue) { sb.Append(num2); sb.Append(".."); if (num3 != uint.MaxValue) { sb.Append(num2 + (int)num3 - 1); } else { sb.Append('.'); } } } break; } } sb.Append(']'); break; } case ElementType.SZArray: CreateTypeSigName(typeSig.Next, flags); if (flag2) { sb.Append("[]"); } break; case ElementType.CModReqd: CreateTypeSigName(typeSig.Next, flags); if (!isReflection && flag2) { sb.Append(" modreq("); if (flag) { CreateFullName(((ModifierSig)typeSig).Modifier); } else { CreateName(((ModifierSig)typeSig).Modifier); } sb.Append(")"); } break; case ElementType.CModOpt: CreateTypeSigName(typeSig.Next, flags); if (!isReflection && flag2) { sb.Append(" modopt("); if (flag) { CreateFullName(((ModifierSig)typeSig).Modifier); } else { CreateName(((ModifierSig)typeSig).Modifier); } sb.Append(")"); } break; case ElementType.Pinned: CreateTypeSigName(typeSig.Next, flags); break; case ElementType.ValueArray: CreateTypeSigName(typeSig.Next, flags); if (flag2) { ValueArraySig valueArraySig = (ValueArraySig)typeSig; sb.Append(" ValueArray("); sb.Append(valueArraySig.Size); sb.Append(')'); } break; case ElementType.Module: CreateTypeSigName(typeSig.Next, flags); if (flag2) { ModuleSig moduleSig = (ModuleSig)typeSig; sb.Append(" Module("); sb.Append(moduleSig.Index); sb.Append(')'); } break; case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)typeSig; IList list = genericInstSig.GenericArguments; CreateTypeSigName(genericInstSig.GenericType, flags); if (!(flag && flag2)) { break; } if (isReflection) { sb.Append('['); int num4 = -1; int count = list.Count; for (int j = 0; j < count; j++) { TypeSig typeSig2 = list[j]; num4++; if (num4 != 0) { sb.Append(','); } bool num5 = MustUseAssemblyName(typeSig2); if (num5) { sb.Append('['); } CreateFullName(typeSig2); if (num5) { sb.Append(", "); CreateAssemblyFullName(GetDefinitionAssembly(typeSig2), useToken: true, escapeClosingBracket: true); sb.Append(']'); } } sb.Append(']'); break; } sb.Append('<'); int num6 = -1; int count2 = list.Count; for (int k = 0; k < count2; k++) { TypeSig typeSig3 = list[k]; num6++; if (num6 != 0) { sb.Append(','); } CreateFullName(typeSig3); } sb.Append('>'); break; } case ElementType.Var: case ElementType.MVar: if (flag2) { GenericSig genericSig = (GenericSig)typeSig; GenericParam genericParam = genericSig.GenericParam; if (genericParam == null || !AddName(genericParam.Name)) { sb.Append(genericSig.IsMethodVar ? "!!" : "!"); sb.Append(genericSig.Number); } } break; case ElementType.FnPtr: if (flag2) { if (isReflection) { sb.Append("(fnptr)"); } else { CreateMethodFullName(null, null, ((FnPtrSig)typeSig).MethodSig, null); } } break; } this.genericArguments = genericArguments; recursionCounter.Decrement(); } private void CreateAssemblyQualifiedName(ExportedType exportedType) { if (exportedType == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } CreateFullName(exportedType); if (MustUseAssemblyName(exportedType)) { sb.Append(", "); CreateAssemblyFullName(GetDefinitionAssembly(exportedType), useToken: true); } recursionCounter.Decrement(); } private void CreateFullName(ExportedType exportedType) { if (exportedType == null) { sb.Append("<<>>"); return; } if (!recursionCounter.Increment()) { sb.Append("<<>>"); return; } if (exportedType.Implementation is ExportedType exportedType2) { CreateFullName(exportedType2); AddNestedTypeSeparator(); } if (AddNamespace(exportedType.TypeNamespace, onlyNamespace: false)) { sb.Append('.'); } AddName(exportedType.TypeName); recursionCounter.Decrement(); } private void CreateNamespace(ExportedType exportedType, bool onlyNamespace) { if (exportedType == null) { sb.Append("<<>>"); } else { AddNamespace(exportedType.TypeNamespace, onlyNamespace); } } private void CreateName(ExportedType exportedType) { if (exportedType == null) { sb.Append("<<>>"); } else { AddName(exportedType.TypeName); } } private static string EscapeAssemblyName(UTF8String asmSimpleName) { return EscapeAssemblyName(UTF8String.ToSystemString(asmSimpleName)); } private static string EscapeAssemblyName(string asmSimpleName) { if (asmSimpleName.IndexOf(']') < 0) { return asmSimpleName; } StringBuilder stringBuilder = new StringBuilder(asmSimpleName.Length); foreach (char c in asmSimpleName) { if (c == ']') { stringBuilder.Append('\\'); } stringBuilder.Append(c); } return stringBuilder.ToString(); } private void AddNestedTypeSeparator() { if (isReflection) { sb.Append('+'); } else { sb.Append('/'); } } private bool AddNamespace(UTF8String @namespace, bool onlyNamespace) { if (UTF8String.IsNullOrEmpty(@namespace)) { return false; } if (onlyNamespace && isReflection) { sb.Append(@namespace.String); } else { AddIdentifier(@namespace.String); } return true; } private bool AddName(UTF8String name) { if (UTF8String.IsNullOrEmpty(name)) { return false; } AddIdentifier(name.String); return true; } private void CreateAssemblyFullName(IAssembly assembly, bool useToken, bool escapeClosingBracket = false) { if (assembly == null) { sb.Append("<<>>"); return; } string text = UTF8String.ToSystemStringOrEmpty(assembly.Name); foreach (char c in text) { if (c == ',' || c == '=' || (escapeClosingBracket && c == ']')) { sb.Append('\\'); } sb.Append(c); } if ((object)assembly.Version != null) { sb.Append(", Version="); sb.Append(Utils.CreateVersionWithNoUndefinedValues(assembly.Version)); } if ((object)assembly.Culture != null) { sb.Append(", Culture="); if (UTF8String.IsNullOrEmpty(assembly.Culture)) { sb.Append("neutral"); } else { sb.Append(escapeClosingBracket ? EscapeAssemblyName(assembly.Culture) : assembly.Culture.String); } } PublicKeyBase publicKeyBase = assembly.PublicKeyOrToken; if (useToken) { publicKeyBase = PublicKeyBase.ToPublicKeyToken(publicKeyBase); } sb.Append(", "); sb.Append((publicKeyBase == null || publicKeyBase is PublicKeyToken) ? "PublicKeyToken=" : "PublicKey="); sb.Append((publicKeyBase == null) ? "null" : publicKeyBase.ToString()); if (assembly.IsRetargetable) { sb.Append(", Retargetable=Yes"); } if (assembly.IsContentTypeWindowsRuntime) { sb.Append(", ContentType=WindowsRuntime"); } } private void AddIdentifier(string id) { if (isReflection) { foreach (char c in id) { switch (c) { case '&': case '*': case '+': case ',': case '[': case '\\': case ']': sb.Append('\\'); break; } sb.Append(c); } } else { sb.Append(id); } } private IAssembly GetDefinitionAssembly(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef typeRef) { return GetDefinitionAssembly(typeRef); } if (typeDefOrRef is TypeDef typeDef) { return GetDefinitionAssembly(typeDef); } if (typeDefOrRef is TypeSpec typeSpec) { return GetDefinitionAssembly(typeSpec); } return null; } private IScope GetScope(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef typeRef) { return GetScope(typeRef); } if (typeDefOrRef is TypeDef typeDef) { return typeDef.Scope; } if (typeDefOrRef is TypeSpec typeSpec) { return GetScope(typeSpec); } return null; } private ITypeDefOrRef GetScopeType(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef result) { return result; } if (typeDefOrRef is TypeDef result2) { return result2; } if (typeDefOrRef is TypeSpec typeSpec) { return GetScopeType(typeSpec); } return null; } private ModuleDef GetOwnerModule(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef typeRef) { return GetOwnerModule(typeRef); } if (typeDefOrRef is TypeDef typeDef) { return GetOwnerModule(typeDef); } if (typeDefOrRef is TypeSpec typeSpec) { return GetOwnerModule(typeSpec); } return null; } private IAssembly GetDefinitionAssembly(TypeRef typeRef) { if (typeRef == null) { return null; } if (!recursionCounter.Increment()) { return null; } IResolutionScope resolutionScope = typeRef.ResolutionScope; IAssembly result = ((resolutionScope == null) ? null : ((resolutionScope is TypeRef) ? GetDefinitionAssembly((TypeRef)resolutionScope) : ((resolutionScope is AssemblyRef) ? ((IAssembly)(AssemblyRef)resolutionScope) : ((IAssembly)((resolutionScope is ModuleRef) ? GetOwnerModule(typeRef)?.Assembly : ((!(resolutionScope is ModuleDef)) ? null : ((ModuleDef)resolutionScope).Assembly)))))); recursionCounter.Decrement(); return result; } private IScope GetScope(TypeRef typeRef) { if (typeRef == null) { return null; } if (!recursionCounter.Increment()) { return null; } IResolutionScope resolutionScope = typeRef.ResolutionScope; IScope result = ((resolutionScope == null) ? null : ((!(resolutionScope is TypeRef typeRef2)) ? ((!(resolutionScope is AssemblyRef assemblyRef)) ? ((!(resolutionScope is ModuleRef moduleRef)) ? ((IScope)((!(resolutionScope is ModuleDef moduleDef)) ? null : moduleDef)) : ((IScope)moduleRef)) : assemblyRef) : GetScope(typeRef2))); recursionCounter.Decrement(); return result; } private ModuleDef GetOwnerModule(TypeRef typeRef) { return typeRef?.Module; } private IAssembly GetDefinitionAssembly(TypeDef typeDef) { return GetOwnerModule(typeDef)?.Assembly; } private ModuleDef GetOwnerModule(TypeDef typeDef) { if (typeDef == null) { return null; } ModuleDef result = null; for (int i = recursionCounter.Counter; i < 100; i++) { TypeDef declaringType = typeDef.DeclaringType; if (declaringType == null) { result = typeDef.Module2; break; } typeDef = declaringType; } return result; } private IAssembly GetDefinitionAssembly(TypeSpec typeSpec) { if (typeSpec == null) { return null; } return GetDefinitionAssembly(typeSpec.TypeSig); } private IScope GetScope(TypeSpec typeSpec) { if (typeSpec == null) { return null; } return GetScope(typeSpec.TypeSig); } private ITypeDefOrRef GetScopeType(TypeSpec typeSpec) { if (typeSpec == null) { return null; } return GetScopeType(typeSpec.TypeSig); } private ModuleDef GetOwnerModule(TypeSpec typeSpec) { if (typeSpec == null) { return null; } return GetOwnerModule(typeSpec.TypeSig); } private IAssembly GetDefinitionAssembly(TypeSig typeSig) { if (typeSig == null) { return null; } if (!recursionCounter.Increment()) { return null; } GenericArguments genericArguments = this.genericArguments; typeSig = ReplaceGenericArg(typeSig); IAssembly result; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetDefinitionAssembly(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Module: case ElementType.Pinned: result = GetDefinitionAssembly(typeSig.Next); break; case ElementType.GenericInst: result = GetDefinitionAssembly(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef); break; default: result = null; break; } this.genericArguments = genericArguments; recursionCounter.Decrement(); return result; } private ITypeDefOrRef GetScopeType(TypeSig typeSig) { if (typeSig == null) { return null; } if (!recursionCounter.Increment()) { return null; } GenericArguments genericArguments = this.genericArguments; typeSig = ReplaceGenericArg(typeSig); ITypeDefOrRef result; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetScopeType(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Module: case ElementType.Pinned: result = GetScopeType(typeSig.Next); break; case ElementType.GenericInst: result = GetScopeType(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef); break; default: result = null; break; } this.genericArguments = genericArguments; recursionCounter.Decrement(); return result; } private IScope GetScope(TypeSig typeSig) { if (typeSig == null) { return null; } if (!recursionCounter.Increment()) { return null; } GenericArguments genericArguments = this.genericArguments; typeSig = ReplaceGenericArg(typeSig); IScope result; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetScope(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Module: case ElementType.Pinned: result = GetScope(typeSig.Next); break; case ElementType.GenericInst: result = GetScope(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef); break; default: result = null; break; } this.genericArguments = genericArguments; recursionCounter.Decrement(); return result; } private ModuleDef GetOwnerModule(TypeSig typeSig) { if (typeSig == null) { return null; } if (!recursionCounter.Increment()) { return null; } GenericArguments genericArguments = this.genericArguments; typeSig = ReplaceGenericArg(typeSig); ModuleDef result; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetOwnerModule(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Module: case ElementType.Pinned: result = GetOwnerModule(typeSig.Next); break; case ElementType.GenericInst: result = GetOwnerModule(((GenericInstSig)typeSig).GenericType?.TypeDefOrRef); break; default: result = null; break; } this.genericArguments = genericArguments; recursionCounter.Decrement(); return result; } private IAssembly GetDefinitionAssembly(ExportedType exportedType) { if (exportedType == null) { return null; } if (!recursionCounter.Increment()) { return null; } IImplementation implementation = exportedType.Implementation; IAssembly result = ((!(implementation is ExportedType exportedType2)) ? ((!(implementation is AssemblyRef assemblyRef)) ? ((IAssembly)((!(implementation is FileDef)) ? null : GetOwnerModule(exportedType)?.Assembly)) : ((IAssembly)assemblyRef)) : GetDefinitionAssembly(exportedType2)); recursionCounter.Decrement(); return result; } private ITypeDefOrRef GetScopeType(ExportedType exportedType) { return null; } private IScope GetScope(ExportedType exportedType) { if (exportedType == null) { return null; } if (!recursionCounter.Increment()) { return null; } IImplementation implementation = exportedType.Implementation; IScope result; if (implementation is ExportedType exportedType2) { result = GetScope(exportedType2); } else if (implementation is AssemblyRef assemblyRef) { result = assemblyRef; } else if (implementation is FileDef fileDef) { ModuleDef ownerModule = GetOwnerModule(exportedType); ModuleRefUser moduleRefUser = new ModuleRefUser(ownerModule, fileDef.Name); ownerModule?.UpdateRowId(moduleRefUser); result = moduleRefUser; } else { result = null; } recursionCounter.Decrement(); return result; } private ModuleDef GetOwnerModule(ExportedType exportedType) { return exportedType?.Module; } private void CreateFieldFullName(string declaringType, string name, FieldSig fieldSig) { CreateFullName(fieldSig?.Type); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (name != null) { sb.Append(name); } } private void CreateMethodFullName(string declaringType, string name, MethodBaseSig methodSig, MethodDef gppMethod) { if (methodSig == null) { sb.Append("<<>>"); return; } CreateFullName(methodSig.RetType); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (name != null) { sb.Append(name); } if (methodSig.Generic) { sb.Append('<'); uint num = methodSig.GenParamCount; if (num > 200) { num = 200u; } for (uint num2 = 0u; num2 < num; num2++) { if (num2 != 0) { sb.Append(','); } CreateFullName(new GenericMVar(num2, gppMethod)); } sb.Append('>'); } sb.Append('('); int num3 = PrintMethodArgList(methodSig.Params, hasPrintedArgs: false, isAfterSentinel: false); PrintMethodArgList(methodSig.ParamsAfterSentinel, num3 > 0, isAfterSentinel: true); sb.Append(')'); } private int PrintMethodArgList(IList args, bool hasPrintedArgs, bool isAfterSentinel) { if (args == null) { return 0; } if (isAfterSentinel) { if (hasPrintedArgs) { sb.Append(','); } sb.Append("..."); hasPrintedArgs = true; } int num = 0; int count = args.Count; for (int i = 0; i < count; i++) { TypeSig typeSig = args[i]; num++; if (hasPrintedArgs) { sb.Append(','); } CreateFullName(typeSig); hasPrintedArgs = true; } return num; } private void CreatePropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig) { CreateMethodFullName(declaringType, UTF8String.ToSystemString(name), propertySig as MethodBaseSig, null); } private void CreateEventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef) { CreateFullName(typeDefOrRef); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (!UTF8String.IsNull(name)) { sb.Append(UTF8String.ToSystemString(name)); } } public override string ToString() { return Result; } } internal readonly struct GenericArgumentsStack { private readonly List> argsStack; private readonly bool isTypeVar; public GenericArgumentsStack(bool isTypeVar) { argsStack = new List>(); this.isTypeVar = isTypeVar; } public void Push(IList args) { argsStack.Add(args); } public IList Pop() { int index = argsStack.Count - 1; IList result = argsStack[index]; argsStack.RemoveAt(index); return result; } public TypeSig Resolve(uint number) { TypeSig result = null; for (int num = argsStack.Count - 1; num >= 0; num--) { IList list = argsStack[num]; if (number >= list.Count) { return null; } TypeSig typeSig = list[(int)number]; if (!(typeSig is GenericSig genericSig) || genericSig.IsTypeVar != isTypeVar) { return typeSig; } result = genericSig; number = genericSig.Number; } return result; } } internal sealed class GenericArguments { private GenericArgumentsStack typeArgsStack = new GenericArgumentsStack(isTypeVar: true); private GenericArgumentsStack methodArgsStack = new GenericArgumentsStack(isTypeVar: false); public void PushTypeArgs(IList typeArgs) { typeArgsStack.Push(typeArgs); } public IList PopTypeArgs() { return typeArgsStack.Pop(); } public void PushMethodArgs(IList methodArgs) { methodArgsStack.Push(methodArgs); } public IList PopMethodArgs() { return methodArgsStack.Pop(); } public TypeSig Resolve(TypeSig typeSig) { if (typeSig == null) { return null; } if (typeSig is GenericMVar genericMVar) { TypeSig typeSig2 = methodArgsStack.Resolve(genericMVar.Number); if (typeSig2 == null || typeSig2 == typeSig) { return typeSig; } return typeSig2; } if (!(typeSig is GenericVar genericVar)) { return typeSig; } TypeSig typeSig3 = typeArgsStack.Resolve(genericVar.Number); if (typeSig3 == null || typeSig3 == typeSig) { return typeSig; } return typeSig3; } } [DebuggerDisplay("{Name.String}")] public abstract class GenericParam : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation, IMemberDef, IDnlibDef, IFullName, IMemberRef, IOwnerModule, IIsTypeOrMethod, IListListener { protected uint rid; protected ITypeOrMethodDef owner; protected ushort number; protected int attributes; protected UTF8String name; protected ITypeDefOrRef kind; protected LazyList genericParamConstraints; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.GenericParam, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 19; public ITypeOrMethodDef Owner { get { return owner; } internal set { owner = value; } } public TypeDef DeclaringType => owner as TypeDef; ITypeDefOrRef IMemberRef.DeclaringType => owner as TypeDef; public MethodDef DeclaringMethod => owner as MethodDef; public ushort Number { get { return number; } set { number = value; } } public GenericParamAttributes Flags { get { return (GenericParamAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public ITypeDefOrRef Kind { get { return kind; } set { kind = value; } } public IList GenericParamConstraints { get { if (genericParamConstraints == null) { InitializeGenericParamConstraints(); } return genericParamConstraints; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 19; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasGenericParamConstraints => GenericParamConstraints.Count > 0; public ModuleDef Module => owner?.Module; public string FullName => UTF8String.ToSystemStringOrEmpty(name); bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => true; public GenericParamAttributes Variance { get { return (GenericParamAttributes)((ushort)attributes & 3); } set { ModifyAttributes(~GenericParamAttributes.VarianceMask, value & GenericParamAttributes.VarianceMask); } } public bool IsNonVariant => Variance == GenericParamAttributes.NonVariant; public bool IsCovariant => Variance == GenericParamAttributes.Covariant; public bool IsContravariant => Variance == GenericParamAttributes.Contravariant; public GenericParamAttributes SpecialConstraint { get { return (GenericParamAttributes)((ushort)attributes & 0x3C); } set { ModifyAttributes(~GenericParamAttributes.SpecialConstraintMask, value & GenericParamAttributes.SpecialConstraintMask); } } public bool HasNoSpecialConstraint => ((ushort)attributes & 0x3C) == 0; public bool HasReferenceTypeConstraint { get { return ((ushort)attributes & 4) != 0; } set { ModifyAttributes(value, GenericParamAttributes.ReferenceTypeConstraint); } } public bool HasNotNullableValueTypeConstraint { get { return ((ushort)attributes & 8) != 0; } set { ModifyAttributes(value, GenericParamAttributes.NotNullableValueTypeConstraint); } } public bool HasDefaultConstructorConstraint { get { return ((ushort)attributes & 0x10) != 0; } set { ModifyAttributes(value, GenericParamAttributes.DefaultConstructorConstraint); } } public bool AllowsByRefLike { get { return ((ushort)attributes & 0x20) != 0; } set { ModifyAttributes(value, GenericParamAttributes.AllowByRefLike); } } protected virtual void InitializeGenericParamConstraints() { Interlocked.CompareExchange(ref genericParamConstraints, new LazyList(this), null); } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(GenericParamAttributes andMask, GenericParamAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, GenericParamAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } void IListListener.OnLazyAdd(int index, ref GenericParamConstraint value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParamConstraint value) { } void IListListener.OnAdd(int index, GenericParamConstraint value) { if (value.Owner != null) { throw new InvalidOperationException("Generic param constraint is already owned by another generic param. Set Owner to null first."); } value.Owner = this; } void IListListener.OnRemove(int index, GenericParamConstraint value) { value.Owner = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (GenericParamConstraint item in genericParamConstraints.GetEnumerable_NoLock()) { item.Owner = null; } } public override string ToString() { ITypeOrMethodDef typeOrMethodDef = owner; if (!(typeOrMethodDef is TypeDef)) { if (!(typeOrMethodDef is MethodDef)) { return $"??{number}"; } return $"!!{number}"; } return $"!{number}"; } } public class GenericParamUser : GenericParam { public GenericParamUser() { } public GenericParamUser(ushort number) : this(number, GenericParamAttributes.NonVariant) { } public GenericParamUser(ushort number, GenericParamAttributes flags) : this(number, flags, UTF8String.Empty) { } public GenericParamUser(ushort number, GenericParamAttributes flags, UTF8String name) { genericParamConstraints = new LazyList(this); base.number = number; attributes = (int)flags; base.name = name; } } internal sealed class GenericParamMD : GenericParam, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.GenericParam, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), GetGenericParamContext(owner), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } protected override void InitializeGenericParamConstraints() { RidList genericParamConstraintRidList = readerModule.Metadata.GetGenericParamConstraintRidList(origRid); LazyList value = new LazyList(genericParamConstraintRidList.Count, this, genericParamConstraintRidList, (RidList list2, int index) => readerModule.ResolveGenericParamConstraint(list2[index], GetGenericParamContext(owner))); Interlocked.CompareExchange(ref genericParamConstraints, value, null); } private static GenericParamContext GetGenericParamContext(ITypeOrMethodDef tmOwner) { if (tmOwner is MethodDef method) { return GenericParamContext.Create(method); } return new GenericParamContext(tmOwner as TypeDef); } public GenericParamMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadGenericParamRow(origRid, out var row); number = row.Number; attributes = row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); owner = readerModule.GetOwner(this); if (row.Kind != 0) { kind = readerModule.ResolveTypeDefOrRef(row.Kind, GetGenericParamContext(owner)); } } internal GenericParamMD InitializeAll() { MemberMDInitializer.Initialize(base.Owner); MemberMDInitializer.Initialize(base.Number); MemberMDInitializer.Initialize(base.Flags); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.Kind); MemberMDInitializer.Initialize(base.CustomAttributes); MemberMDInitializer.Initialize(base.GenericParamConstraints); return this; } internal override void OnLazyAdd2(int index, ref GenericParamConstraint value) { if (value.Owner != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParamConstraint(value.Rid, GetGenericParamContext(owner)).InitializeAll()); value.Owner = this; } } } [Flags] public enum GenericParamAttributes : ushort { VarianceMask = 3, NonVariant = 0, Covariant = 1, Contravariant = 2, SpecialConstraintMask = 0x3C, NoSpecialConstraint = 0, ReferenceTypeConstraint = 4, NotNullableValueTypeConstraint = 8, DefaultConstructorConstraint = 0x10, AllowByRefLike = 0x20 } public abstract class GenericParamConstraint : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation, IContainsGenericParameter { protected uint rid; protected GenericParam owner; protected ITypeDefOrRef constraint; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.GenericParamConstraint, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 20; public GenericParam Owner { get { return owner; } internal set { owner = value; } } public ITypeDefOrRef Constraint { get { return constraint; } set { constraint = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 20; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } bool IContainsGenericParameter.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } } public class GenericParamConstraintUser : GenericParamConstraint { public GenericParamConstraintUser() { } public GenericParamConstraintUser(ITypeDefOrRef constraint) { base.constraint = constraint; } } internal sealed class GenericParamConstraintMD : GenericParamConstraint, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; public uint OrigRid => origRid; bool IContainsGenericParameter2.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.GenericParamConstraint, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public GenericParamConstraintMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; readerModule.TablesStream.TryReadGenericParamConstraintRow(origRid, out var row); constraint = readerModule.ResolveTypeDefOrRef(row.Constraint, gpContext); owner = readerModule.GetOwner(this); } internal GenericParamConstraintMD InitializeAll() { MemberMDInitializer.Initialize(base.Owner); MemberMDInitializer.Initialize(base.Constraint); MemberMDInitializer.Initialize(base.CustomAttributes); return this; } } public readonly struct GenericParamContext { public readonly TypeDef Type; public readonly MethodDef Method; public bool IsEmpty { get { if (Type == null) { return Method == null; } return false; } } public static GenericParamContext Create(MethodDef method) { if (method == null) { return default(GenericParamContext); } return new GenericParamContext(method.DeclaringType, method); } public static GenericParamContext Create(TypeDef type) { return new GenericParamContext(type); } public GenericParamContext(TypeDef type) { Type = type; Method = null; } public GenericParamContext(MethodDef method) { Type = null; Method = method; } public GenericParamContext(TypeDef type, MethodDef method) { Type = type; Method = method; } } public interface IAssemblyResolver { AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule); } public interface IMDTokenProvider { MDToken MDToken { get; } uint Rid { get; set; } } public interface IMDTokenProviderMD : IMDTokenProvider { uint OrigRid { get; } } public interface IAssembly : IFullName { Version Version { get; set; } AssemblyAttributes Attributes { get; set; } PublicKeyBase PublicKeyOrToken { get; } UTF8String Culture { get; set; } string FullNameToken { get; } bool HasPublicKey { get; set; } AssemblyAttributes ProcessorArchitecture { get; set; } AssemblyAttributes ProcessorArchitectureFull { get; set; } bool IsProcessorArchitectureNone { get; } bool IsProcessorArchitectureMSIL { get; } bool IsProcessorArchitectureX86 { get; } bool IsProcessorArchitectureIA64 { get; } bool IsProcessorArchitectureX64 { get; } bool IsProcessorArchitectureARM { get; } bool IsProcessorArchitectureNoPlatform { get; } bool IsProcessorArchitectureSpecified { get; set; } bool EnableJITcompileTracking { get; set; } bool DisableJITcompileOptimizer { get; set; } bool IsRetargetable { get; set; } AssemblyAttributes ContentType { get; set; } bool IsContentTypeDefault { get; } bool IsContentTypeWindowsRuntime { get; } } public interface IManagedEntryPoint : ICodedToken, IMDTokenProvider { } public interface IModule : IScope, IFullName { } public enum ScopeType { AssemblyRef, ModuleRef, ModuleDef } public interface IScope { ScopeType ScopeType { get; } string ScopeName { get; } } public interface IFullName { string FullName { get; } UTF8String Name { get; set; } } public interface IOwnerModule { ModuleDef Module { get; } } public interface IIsTypeOrMethod { bool IsType { get; } bool IsMethod { get; } } public interface IMemberRef : ICodedToken, IMDTokenProvider, IFullName, IOwnerModule, IIsTypeOrMethod { ITypeDefOrRef DeclaringType { get; } bool IsField { get; } bool IsTypeSpec { get; } bool IsTypeRef { get; } bool IsTypeDef { get; } bool IsMethodSpec { get; } bool IsMethodDef { get; } bool IsMemberRef { get; } bool IsFieldDef { get; } bool IsPropertyDef { get; } bool IsEventDef { get; } bool IsGenericParam { get; } } public interface IMemberDef : IDnlibDef, ICodedToken, IMDTokenProvider, IFullName, IHasCustomAttribute, IMemberRef, IOwnerModule, IIsTypeOrMethod { new TypeDef DeclaringType { get; } } public interface IDnlibDef : ICodedToken, IMDTokenProvider, IFullName, IHasCustomAttribute { } public interface IGenericParameterProvider : ICodedToken, IMDTokenProvider, IIsTypeOrMethod { int NumberOfGenericParameters { get; } } public interface IField : ICodedToken, IMDTokenProvider, ITokenOperand, IFullName, IMemberRef, IOwnerModule, IIsTypeOrMethod { FieldSig FieldSig { get; set; } } public interface IMethod : ICodedToken, IMDTokenProvider, ITokenOperand, IFullName, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule { MethodSig MethodSig { get; set; } } public interface ITokenOperand : ICodedToken, IMDTokenProvider { } public interface ICodedToken : IMDTokenProvider { } public interface ITypeDefOrRef : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IMemberRefParent, IFullName, IType, IOwnerModule, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter, ITokenOperand, IMemberRef { int TypeDefOrRefTag { get; } } public interface IHasConstant : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName { int HasConstantTag { get; } Constant Constant { get; set; } } public interface IHasCustomAttribute : ICodedToken, IMDTokenProvider { int HasCustomAttributeTag { get; } CustomAttributeCollection CustomAttributes { get; } bool HasCustomAttributes { get; } } public interface IHasFieldMarshal : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IHasConstant, IFullName { int HasFieldMarshalTag { get; } MarshalType MarshalType { get; set; } bool HasMarshalType { get; } } public interface IHasDeclSecurity : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName { int HasDeclSecurityTag { get; } IList DeclSecurities { get; } bool HasDeclSecurities { get; } } public interface IMemberRefParent : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName { int MemberRefParentTag { get; } } public interface IHasSemantic : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName, IMemberRef, IOwnerModule, IIsTypeOrMethod { int HasSemanticTag { get; } } public interface IMethodDefOrRef : ICodedToken, IMDTokenProvider, IHasCustomAttribute, ICustomAttributeType, IMethod, ITokenOperand, IFullName, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule { int MethodDefOrRefTag { get; } } public interface IMemberForwarded : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName, IMemberRef, IOwnerModule, IIsTypeOrMethod { int MemberForwardedTag { get; } ImplMap ImplMap { get; set; } bool HasImplMap { get; } } public interface IImplementation : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName { int ImplementationTag { get; } } public interface ICustomAttributeType : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IMethod, ITokenOperand, IFullName, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule { int CustomAttributeTypeTag { get; } } public interface IResolutionScope : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName { int ResolutionScopeTag { get; } } public interface ITypeOrMethodDef : ICodedToken, IMDTokenProvider, IHasCustomAttribute, IHasDeclSecurity, IFullName, IMemberRefParent, IMemberRef, IOwnerModule, IIsTypeOrMethod, IGenericParameterProvider, IMemberDef, IDnlibDef { int TypeOrMethodDefTag { get; } IList GenericParameters { get; } bool HasGenericParameters { get; } } public interface IHasCustomDebugInformation { int HasCustomDebugInformationTag { get; } IList CustomDebugInfos { get; } bool HasCustomDebugInfos { get; } } public interface ICorLibTypes { CorLibTypeSig Void { get; } CorLibTypeSig Boolean { get; } CorLibTypeSig Char { get; } CorLibTypeSig SByte { get; } CorLibTypeSig Byte { get; } CorLibTypeSig Int16 { get; } CorLibTypeSig UInt16 { get; } CorLibTypeSig Int32 { get; } CorLibTypeSig UInt32 { get; } CorLibTypeSig Int64 { get; } CorLibTypeSig UInt64 { get; } CorLibTypeSig Single { get; } CorLibTypeSig Double { get; } CorLibTypeSig String { get; } CorLibTypeSig TypedReference { get; } CorLibTypeSig IntPtr { get; } CorLibTypeSig UIntPtr { get; } CorLibTypeSig Object { get; } AssemblyRef AssemblyRef { get; } TypeRef GetTypeRef(string @namespace, string name); } public interface ICustomAttribute { ITypeDefOrRef AttributeType { get; } string TypeFullName { get; } IList NamedArguments { get; } bool HasNamedArguments { get; } IEnumerable Fields { get; } IEnumerable Properties { get; } } public interface IMethodDecrypter { bool GetMethodBody(uint rid, RVA rva, IList parameters, GenericParamContext gpContext, out dnlib.DotNet.Emit.MethodBody methodBody); } public interface IStringDecrypter { string ReadUserString(uint token); } public enum LoggerEvent { Error, Warning, Info, Verbose, VeryVerbose } public interface ILogger { void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args); bool IgnoresEvent(LoggerEvent loggerEvent); } public sealed class DummyLogger : ILogger { private ConstructorInfo ctor; public static readonly DummyLogger NoThrowInstance = new DummyLogger(); public static readonly DummyLogger ThrowModuleWriterExceptionOnErrorInstance = new DummyLogger(typeof(ModuleWriterException)); private DummyLogger() { } public DummyLogger(Type exceptionToThrow) { if ((object)exceptionToThrow != null) { if (!exceptionToThrow.IsSubclassOf(typeof(Exception))) { throw new ArgumentException($"Not a System.Exception sub class: {exceptionToThrow.GetType()}"); } ctor = exceptionToThrow.GetConstructor(new Type[1] { typeof(string) }); if ((object)ctor == null) { throw new ArgumentException($"Exception type {exceptionToThrow.GetType()} doesn't have a public constructor that takes a string as the only argument"); } } } public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { if (loggerEvent == LoggerEvent.Error && (object)ctor != null) { throw (Exception)ctor.Invoke(new object[1] { string.Format(format, args) }); } } public bool IgnoresEvent(LoggerEvent loggerEvent) { if ((object)ctor == null) { return true; } return loggerEvent != LoggerEvent.Error; } } [DebuggerDisplay("{Module} {Name}")] public abstract class ImplMap : IMDTokenProvider { protected uint rid; protected int attributes; protected UTF8String name; protected ModuleRef module; private static readonly char[] trimChars = new char[1] { ' ' }; public MDToken MDToken => new MDToken(Table.ImplMap, rid); public uint Rid { get { return rid; } set { rid = value; } } public PInvokeAttributes Attributes { get { return (PInvokeAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public ModuleRef Module { get { return module; } set { module = value; } } public bool IsNoMangle { get { return ((ushort)attributes & 1) != 0; } set { ModifyAttributes(value, PInvokeAttributes.NoMangle); } } public PInvokeAttributes CharSet { get { return (PInvokeAttributes)((ushort)attributes & 6); } set { ModifyAttributes(~PInvokeAttributes.CharSetMask, value & PInvokeAttributes.CharSetMask); } } public bool IsCharSetNotSpec => ((ushort)attributes & 6) == 0; public bool IsCharSetAnsi => ((ushort)attributes & 6) == 2; public bool IsCharSetUnicode => ((ushort)attributes & 6) == 4; public bool IsCharSetAuto => ((ushort)attributes & 6) == 6; public PInvokeAttributes BestFit { get { return (PInvokeAttributes)((ushort)attributes & 0x30); } set { ModifyAttributes(~PInvokeAttributes.BestFitMask, value & PInvokeAttributes.BestFitMask); } } public bool IsBestFitUseAssem => ((ushort)attributes & 0x30) == 0; public bool IsBestFitEnabled => ((ushort)attributes & 0x30) == 16; public bool IsBestFitDisabled => ((ushort)attributes & 0x30) == 32; public PInvokeAttributes ThrowOnUnmappableChar { get { return (PInvokeAttributes)((ushort)attributes & 0x3000); } set { ModifyAttributes(~PInvokeAttributes.ThrowOnUnmappableCharMask, value & PInvokeAttributes.ThrowOnUnmappableCharMask); } } public bool IsThrowOnUnmappableCharUseAssem => ((ushort)attributes & 0x3000) == 0; public bool IsThrowOnUnmappableCharEnabled => ((ushort)attributes & 0x3000) == 4096; public bool IsThrowOnUnmappableCharDisabled => ((ushort)attributes & 0x3000) == 8192; public bool SupportsLastError { get { return ((ushort)attributes & 0x40) != 0; } set { ModifyAttributes(value, PInvokeAttributes.SupportsLastError); } } public PInvokeAttributes CallConv { get { return (PInvokeAttributes)((ushort)attributes & 0x700); } set { ModifyAttributes(~PInvokeAttributes.CallConvMask, value & PInvokeAttributes.CallConvMask); } } public bool IsCallConvWinapi => ((ushort)attributes & 0x700) == 256; public bool IsCallConvCdecl => ((ushort)attributes & 0x700) == 512; public bool IsCallConvStdcall => ((ushort)attributes & 0x700) == 768; public bool IsCallConvThiscall => ((ushort)attributes & 0x700) == 1024; public bool IsCallConvFastcall => ((ushort)attributes & 0x700) == 1280; private void ModifyAttributes(PInvokeAttributes andMask, PInvokeAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, PInvokeAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } public bool IsPinvokeMethod(string dllName, string funcName) { return IsPinvokeMethod(dllName, funcName, IsWindows()); } public bool IsPinvokeMethod(string dllName, string funcName, bool treatAsWindows) { if (name != funcName) { return false; } ModuleRef moduleRef = module; if (moduleRef == null) { return false; } return GetDllName(dllName, treatAsWindows).Equals(GetDllName(moduleRef.Name, treatAsWindows), StringComparison.OrdinalIgnoreCase); } private static string GetDllName(string dllName, bool treatAsWindows) { if (treatAsWindows) { dllName = dllName.TrimEnd(trimChars); } if (dllName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) { return dllName.Substring(0, dllName.Length - 4); } return dllName; } private static bool IsWindows() { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); } } public class ImplMapUser : ImplMap { public ImplMapUser() { } public ImplMapUser(ModuleRef scope, UTF8String name, PInvokeAttributes flags) { module = scope; base.name = name; attributes = (int)flags; } } internal sealed class ImplMapMD : ImplMap, IMDTokenProviderMD, IMDTokenProvider { private readonly uint origRid; public uint OrigRid => origRid; public ImplMapMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; readerModule.TablesStream.TryReadImplMapRow(origRid, out var row); attributes = row.MappingFlags; name = readerModule.StringsStream.ReadNoNull(row.ImportName); module = readerModule.ResolveModuleRef(row.ImportScope); } } [Flags] public enum ImporterOptions { TryToUseTypeDefs = 1, TryToUseMethodDefs = 2, TryToUseFieldDefs = 4, TryToUseDefs = 7, TryToUseExistingAssemblyRefs = 8, FixSignature = int.MinValue } public abstract class ImportMapper { public virtual ITypeDefOrRef Map(ITypeDefOrRef source) { return null; } public virtual IField Map(FieldDef source) { return null; } public virtual IMethod Map(MethodDef source) { return null; } public virtual MemberRef Map(MemberRef source) { return null; } public virtual ITypeDefOrRef Map(Type source) { return null; } } public struct Importer { private readonly ModuleDef module; internal readonly GenericParamContext gpContext; private readonly ImportMapper mapper; private RecursionCounter recursionCounter; private ImporterOptions options; private bool TryToUseTypeDefs => (options & ImporterOptions.TryToUseTypeDefs) != 0; private bool TryToUseMethodDefs => (options & ImporterOptions.TryToUseMethodDefs) != 0; private bool TryToUseFieldDefs => (options & ImporterOptions.TryToUseFieldDefs) != 0; private bool TryToUseExistingAssemblyRefs => (options & ImporterOptions.TryToUseExistingAssemblyRefs) != 0; private bool FixSignature { get { return (options & ImporterOptions.FixSignature) != 0; } set { if (value) { options |= ImporterOptions.FixSignature; } else { options &= (ImporterOptions)2147483647; } } } public Importer(ModuleDef module) : this(module, (ImporterOptions)0, default(GenericParamContext), null) { } public Importer(ModuleDef module, GenericParamContext gpContext) : this(module, (ImporterOptions)0, gpContext, null) { } public Importer(ModuleDef module, ImporterOptions options) : this(module, options, default(GenericParamContext), null) { } public Importer(ModuleDef module, ImporterOptions options, GenericParamContext gpContext) : this(module, options, gpContext, null) { } public Importer(ModuleDef module, ImporterOptions options, GenericParamContext gpContext, ImportMapper mapper) { this.module = module; recursionCounter = default(RecursionCounter); this.options = options; this.gpContext = gpContext; this.mapper = mapper; } public ITypeDefOrRef Import(Type type) { return module.UpdateRowId(ImportAsTypeSig(type).ToTypeDefOrRef()); } [Obsolete("Use 'Import(Type)' instead.")] public ITypeDefOrRef ImportDeclaringType(Type type) { return Import(type); } public ITypeDefOrRef Import(Type type, IList requiredModifiers, IList optionalModifiers) { return module.UpdateRowId(ImportAsTypeSig(type, requiredModifiers, optionalModifiers).ToTypeDefOrRef()); } public TypeSig ImportAsTypeSig(Type type) { return ImportAsTypeSig(type, null, false); } private TypeSig ImportAsTypeSig(Type type, Type declaringType, bool? treatAsGenericInst = null) { if ((object)type == null) { return null; } switch ((treatAsGenericInst ?? declaringType.MustTreatTypeAsGenericInstType(type)) ? ElementType.GenericInst : type.GetElementType2()) { case ElementType.Void: return module.CorLibTypes.Void; case ElementType.Boolean: return module.CorLibTypes.Boolean; case ElementType.Char: return module.CorLibTypes.Char; case ElementType.I1: return module.CorLibTypes.SByte; case ElementType.U1: return module.CorLibTypes.Byte; case ElementType.I2: return module.CorLibTypes.Int16; case ElementType.U2: return module.CorLibTypes.UInt16; case ElementType.I4: return module.CorLibTypes.Int32; case ElementType.U4: return module.CorLibTypes.UInt32; case ElementType.I8: return module.CorLibTypes.Int64; case ElementType.U8: return module.CorLibTypes.UInt64; case ElementType.R4: return module.CorLibTypes.Single; case ElementType.R8: return module.CorLibTypes.Double; case ElementType.String: return module.CorLibTypes.String; case ElementType.TypedByRef: return module.CorLibTypes.TypedReference; case ElementType.U: return module.CorLibTypes.UIntPtr; case ElementType.Object: return module.CorLibTypes.Object; case ElementType.Ptr: return new PtrSig(ImportAsTypeSig(type.GetElementType(), declaringType)); case ElementType.ByRef: return new ByRefSig(ImportAsTypeSig(type.GetElementType(), declaringType)); case ElementType.SZArray: return new SZArraySig(ImportAsTypeSig(type.GetElementType(), declaringType)); case ElementType.ValueType: return new ValueTypeSig(CreateTypeDefOrRef(type)); case ElementType.Class: return new ClassSig(CreateTypeDefOrRef(type)); case ElementType.Var: return new GenericVar((uint)type.GenericParameterPosition, gpContext.Type); case ElementType.MVar: return new GenericMVar((uint)type.GenericParameterPosition, gpContext.Method); case ElementType.I: FixSignature = true; return module.CorLibTypes.IntPtr; case ElementType.Array: { int[] lowerBounds = new int[type.GetArrayRank()]; uint[] sizes = Array2.Empty(); FixSignature = true; return new ArraySig(ImportAsTypeSig(type.GetElementType(), declaringType), (uint)type.GetArrayRank(), sizes, lowerBounds); } case ElementType.GenericInst: { Type[] genericArguments = type.GetGenericArguments(); GenericInstSig genericInstSig = new GenericInstSig(ImportAsTypeSig(type.GetGenericTypeDefinition(), null, false) as ClassOrValueTypeSig, (uint)genericArguments.Length); Type[] array = genericArguments; foreach (Type type2 in array) { genericInstSig.GenericArguments.Add(ImportAsTypeSig(type2, declaringType)); } return genericInstSig; } default: return null; } } private ITypeDefOrRef TryResolve(TypeRef tr) { if (!TryToUseTypeDefs || tr == null) { return tr; } if (!IsThisModule(tr)) { return tr; } TypeDef typeDef = tr.Resolve(); if (typeDef == null || typeDef.Module != module) { return tr; } return typeDef; } private IMethodDefOrRef TryResolveMethod(IMethodDefOrRef mdr) { if (!TryToUseMethodDefs || mdr == null) { return mdr; } if (!(mdr is MemberRef memberRef)) { return mdr; } if (!memberRef.IsMethodRef) { return memberRef; } TypeDef declaringType = GetDeclaringType(memberRef); if (declaringType == null) { return memberRef; } if (declaringType.Module != module) { return memberRef; } IMethodDefOrRef methodDefOrRef = declaringType.ResolveMethod(memberRef); return methodDefOrRef ?? memberRef; } private IField TryResolveField(MemberRef mr) { if (!TryToUseFieldDefs || mr == null) { return mr; } if (!mr.IsFieldRef) { return mr; } TypeDef declaringType = GetDeclaringType(mr); if (declaringType == null) { return mr; } if (declaringType.Module != module) { return mr; } IField field = declaringType.ResolveField(mr); return field ?? mr; } private TypeDef GetDeclaringType(MemberRef mr) { if (mr == null) { return null; } if (mr.Class is TypeDef result) { return result; } if (TryResolve(mr.Class as TypeRef) is TypeDef result2) { return result2; } ModuleRef modRef = mr.Class as ModuleRef; if (IsThisModule(modRef)) { return module.GlobalType; } return null; } private bool IsThisModule(TypeRef tr) { if (tr == null) { return false; } if (!(tr.GetNonNestedTypeRefScope() is TypeRef typeRef)) { return false; } if (module == typeRef.ResolutionScope) { return true; } if (typeRef.ResolutionScope is ModuleRef modRef) { return IsThisModule(modRef); } AssemblyRef b = typeRef.ResolutionScope as AssemblyRef; return Equals(module.Assembly, b); } private bool IsThisModule(ModuleRef modRef) { if (modRef != null && module.Name == modRef.Name) { return Equals(module.Assembly, modRef.DefinitionAssembly); } return false; } private static bool Equals(IAssembly a, IAssembly b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (Utils.Equals(a.Version, b.Version) && PublicKeyBase.TokenEquals(a.PublicKeyOrToken, b.PublicKeyOrToken) && UTF8String.Equals(a.Name, b.Name)) { return UTF8String.CaseInsensitiveEquals(a.Culture, b.Culture); } return false; } private ITypeDefOrRef CreateTypeDefOrRef(Type type) { ITypeDefOrRef typeDefOrRef = mapper?.Map(type); if (typeDefOrRef is TypeSpec) { throw new InvalidOperationException(); } if (typeDefOrRef is TypeDef result) { return result; } if (typeDefOrRef is TypeRef tr) { return TryResolve(tr); } if (TryToUseTypeDefs && IsThisModule(type.Module) && module.ResolveToken(type.MetadataToken) is TypeDef result2) { return result2; } return TryResolve(CreateTypeRef(type)); } private TypeRef CreateTypeRef(Type type) { if (!type.IsNested) { return module.UpdateRowId(new TypeRefUser(module, type.Namespace ?? string.Empty, ReflectionExtensions.Unescape(type.Name) ?? string.Empty, CreateScopeReference(type))); } type.GetTypeNamespaceAndName_TypeDefOrRef(out var @namespace, out var name); return module.UpdateRowId(new TypeRefUser(module, @namespace ?? string.Empty, name ?? string.Empty, CreateTypeRef(type.DeclaringType))); } private IResolutionScope CreateScopeReference(Type type) { if ((object)type == null) { return null; } AssemblyName name = type.Assembly.GetName(); AssemblyDef assembly = module.Assembly; if (assembly != null && UTF8String.ToSystemStringOrEmpty(assembly.Name).Equals(name.Name, StringComparison.OrdinalIgnoreCase)) { if (UTF8String.ToSystemStringOrEmpty(module.Name).Equals(type.Module.ScopeName, StringComparison.OrdinalIgnoreCase)) { return module; } return module.UpdateRowId(new ModuleRefUser(module, type.Module.ScopeName)); } byte[] array = name.GetPublicKeyToken(); if (array == null || array.Length == 0) { array = null; } if (TryToUseExistingAssemblyRefs) { AssemblyRef assemblyRef = module.GetAssemblyRef(name.Name); if (assemblyRef != null) { return assemblyRef; } } return module.UpdateRowId(new AssemblyRefUser(name.Name, name.Version, PublicKeyBase.CreatePublicKeyToken(array), name.CultureInfo?.Name ?? string.Empty)); } public TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList optionalModifiers) { return ImportAsTypeSig(type, requiredModifiers, optionalModifiers, null); } private TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList optionalModifiers, Type declaringType) { if ((object)type == null) { return null; } if (IsEmpty(requiredModifiers) && IsEmpty(optionalModifiers)) { return ImportAsTypeSig(type, declaringType); } FixSignature = true; TypeSig typeSig = ImportAsTypeSig(type, declaringType); if (requiredModifiers != null) { foreach (Type requiredModifier in requiredModifiers) { typeSig = new CModReqdSig(Import(requiredModifier), typeSig); } } if (optionalModifiers != null) { foreach (Type optionalModifier in optionalModifiers) { typeSig = new CModOptSig(Import(optionalModifier), typeSig); } } return typeSig; } private static bool IsEmpty(IList list) { if (list != null) { return list.Count == 0; } return true; } public IMethod Import(MethodBase methodBase) { return Import(methodBase, forceFixSignature: false); } public IMethod Import(MethodBase methodBase, bool forceFixSignature) { FixSignature = false; return ImportInternal(methodBase, forceFixSignature); } private IMethod ImportInternal(MethodBase methodBase) { return ImportInternal(methodBase, forceFixSignature: false); } private IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) { if ((object)methodBase == null) { return null; } if (TryToUseMethodDefs && IsThisModule(methodBase.Module) && !methodBase.IsGenericMethod && ((object)methodBase.DeclaringType == null || !methodBase.DeclaringType.IsGenericType) && module.ResolveToken(methodBase.MetadataToken) is MethodDef result) { return result; } if (methodBase.IsGenericButNotGenericMethodDefinition()) { MethodBase methodBase2 = methodBase.Module.ResolveMethod(methodBase.MetadataToken); IMethodDefOrRef mdr = ((methodBase.DeclaringType.GetElementType2() != ElementType.GenericInst) ? (ImportInternal(methodBase2) as IMethodDefOrRef) : module.UpdateRowId(new MemberRefUser(module, methodBase.Name, CreateMethodSig(methodBase2), Import(methodBase.DeclaringType)))); mdr = TryResolveMethod(mdr); if (methodBase.ContainsGenericParameters) { return mdr; } GenericInstMethodSig sig = CreateGenericInstMethodSig(methodBase); MethodSpecUser result2 = module.UpdateRowId(new MethodSpecUser(mdr, sig)); if (FixSignature) { } return result2; } IMemberRefParent memberRefParent = (((object)methodBase.DeclaringType != null) ? Import(methodBase.DeclaringType) : GetModuleParent(methodBase.Module)); if (memberRefParent == null) { return null; } MethodBase mb; try { mb = methodBase.Module.ResolveMethod(methodBase.MetadataToken); } catch (ArgumentException) { mb = methodBase; } MethodSig sig2 = CreateMethodSig(mb); IMethodDefOrRef mdr2 = module.UpdateRowId(new MemberRefUser(module, methodBase.Name, sig2, memberRefParent)); mdr2 = TryResolveMethod(mdr2); if (FixSignature) { } return mdr2; } private bool IsThisModule(Module module2) { if (UTF8String.ToSystemStringOrEmpty(module.Name).Equals(module2.ScopeName, StringComparison.OrdinalIgnoreCase)) { return IsThisAssembly(module2); } return false; } private MethodSig CreateMethodSig(MethodBase mb) { MethodSig methodSig = new MethodSig(GetCallingConvention(mb)); if (mb is MethodInfo methodInfo) { methodSig.RetType = ImportAsTypeSig(methodInfo.ReturnParameter, mb.DeclaringType); } else { methodSig.RetType = module.CorLibTypes.Void; } ParameterInfo[] parameters = mb.GetParameters(); foreach (ParameterInfo p in parameters) { methodSig.Params.Add(ImportAsTypeSig(p, mb.DeclaringType)); } if (mb.IsGenericMethodDefinition) { methodSig.GenParamCount = (uint)mb.GetGenericArguments().Length; } return methodSig; } private TypeSig ImportAsTypeSig(ParameterInfo p, Type declaringType) { return ImportAsTypeSig(p.ParameterType, p.GetRequiredCustomModifiers(), p.GetOptionalCustomModifiers(), declaringType); } private CallingConvention GetCallingConvention(MethodBase mb) { CallingConvention callingConvention = CallingConvention.Default; CallingConventions callingConvention2 = mb.CallingConvention; if (mb.IsGenericMethodDefinition) { callingConvention |= CallingConvention.Generic; } if ((callingConvention2 & CallingConventions.HasThis) != 0) { callingConvention |= CallingConvention.HasThis; } if ((callingConvention2 & CallingConventions.ExplicitThis) != 0) { callingConvention |= CallingConvention.ExplicitThis; } switch (callingConvention2 & CallingConventions.Any) { case CallingConventions.Standard: return callingConvention | CallingConvention.Default; case CallingConventions.VarArgs: return callingConvention | CallingConvention.VarArg; default: FixSignature = true; return callingConvention | CallingConvention.Default; } } private GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb) { Type[] genericArguments = mb.GetGenericArguments(); GenericInstMethodSig genericInstMethodSig = new GenericInstMethodSig(CallingConvention.GenericInst, (uint)genericArguments.Length); Type[] array = genericArguments; foreach (Type type in array) { genericInstMethodSig.GenericArguments.Add(ImportAsTypeSig(type)); } return genericInstMethodSig; } private IMemberRefParent GetModuleParent(Module module2) { if (!IsThisAssembly(module2)) { return null; } return module.UpdateRowId(new ModuleRefUser(module, module.Name)); } private bool IsThisAssembly(Module module2) { AssemblyDef assembly = module.Assembly; if (assembly != null) { return UTF8String.ToSystemStringOrEmpty(assembly.Name).Equals(module2.Assembly.GetName().Name, StringComparison.OrdinalIgnoreCase); } return true; } public IField Import(FieldInfo fieldInfo) { return Import(fieldInfo, forceFixSignature: false); } public IField Import(FieldInfo fieldInfo, bool forceFixSignature) { FixSignature = false; if ((object)fieldInfo == null) { return null; } if (TryToUseFieldDefs && IsThisModule(fieldInfo.Module) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsGenericType) && module.ResolveToken(fieldInfo.MetadataToken) is FieldDef result) { return result; } IMemberRefParent memberRefParent = (((object)fieldInfo.DeclaringType != null) ? Import(fieldInfo.DeclaringType) : GetModuleParent(fieldInfo.Module)); if (memberRefParent == null) { return null; } FieldInfo fieldInfo2; try { fieldInfo2 = fieldInfo.Module.ResolveField(fieldInfo.MetadataToken); } catch (ArgumentException) { fieldInfo2 = fieldInfo; } FieldSig sig = new FieldSig(ImportAsTypeSig(fieldInfo2.FieldType, fieldInfo2.GetRequiredCustomModifiers(), fieldInfo2.GetOptionalCustomModifiers(), fieldInfo2.DeclaringType)); MemberRefUser mr = module.UpdateRowId(new MemberRefUser(module, fieldInfo.Name, sig, memberRefParent)); IField result2 = TryResolveField(mr); if (FixSignature) { } return result2; } public IType Import(IType type) { if (type == null) { return null; } if (!recursionCounter.Increment()) { return null; } IType result = ((!(type is TypeDef type2)) ? ((!(type is TypeRef type3)) ? ((!(type is TypeSpec type4)) ? ((IType)((!(type is TypeSig type5)) ? null : Import(type5))) : ((IType)Import(type4))) : Import(type3)) : Import(type2)); recursionCounter.Decrement(); return result; } public ITypeDefOrRef Import(TypeDef type) { if (type == null) { return null; } if (TryToUseTypeDefs && type.Module == module) { return type; } ITypeDefOrRef typeDefOrRef = mapper?.Map(type); if (typeDefOrRef != null) { return typeDefOrRef; } return Import2(type); } private TypeRef Import2(TypeDef type) { if (type == null) { return null; } if (!recursionCounter.Increment()) { return null; } TypeDef declaringType = type.DeclaringType; TypeRef result = ((declaringType == null) ? module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, CreateScopeReference(type.DefinitionAssembly, type.Module))) : module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, Import2(declaringType)))); recursionCounter.Decrement(); return result; } private IResolutionScope CreateScopeReference(IAssembly defAsm, ModuleDef defMod) { if (defAsm == null) { return null; } AssemblyDef assembly = module.Assembly; if (defMod != null && defAsm != null && assembly != null && UTF8String.CaseInsensitiveEquals(assembly.Name, defAsm.Name)) { if (UTF8String.CaseInsensitiveEquals(module.Name, defMod.Name)) { return module; } return module.UpdateRowId(new ModuleRefUser(module, defMod.Name)); } PublicKeyToken publicKeyToken = PublicKeyBase.ToPublicKeyToken(defAsm.PublicKeyOrToken); if (PublicKeyBase.IsNullOrEmpty2(publicKeyToken)) { publicKeyToken = null; } if (TryToUseExistingAssemblyRefs) { AssemblyRef assemblyRef = module.GetAssemblyRef(defAsm.Name); if (assemblyRef != null) { return assemblyRef; } } return module.UpdateRowId(new AssemblyRefUser(defAsm.Name, defAsm.Version, publicKeyToken, defAsm.Culture) { Attributes = (AssemblyAttributes)((uint)defAsm.Attributes & 0xFFFFFFFEu) }); } public ITypeDefOrRef Import(TypeRef type) { ITypeDefOrRef typeDefOrRef = mapper?.Map(type); if (typeDefOrRef != null) { return typeDefOrRef; } return TryResolve(Import2(type)); } private TypeRef Import2(TypeRef type) { if (type == null) { return null; } if (!recursionCounter.Increment()) { return null; } TypeRef declaringType = type.DeclaringType; TypeRef result = ((declaringType == null) ? module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, CreateScopeReference(type.DefinitionAssembly, type.Module))) : module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, Import2(declaringType)))); recursionCounter.Decrement(); return result; } public TypeSpec Import(TypeSpec type) { if (type == null) { return null; } return module.UpdateRowId(new TypeSpecUser(Import(type.TypeSig))); } public TypeSig Import(TypeSig type) { if (type == null) { return null; } if (!recursionCounter.Increment()) { return null; } TypeSig result; switch (type.ElementType) { case ElementType.Void: result = module.CorLibTypes.Void; break; case ElementType.Boolean: result = module.CorLibTypes.Boolean; break; case ElementType.Char: result = module.CorLibTypes.Char; break; case ElementType.I1: result = module.CorLibTypes.SByte; break; case ElementType.U1: result = module.CorLibTypes.Byte; break; case ElementType.I2: result = module.CorLibTypes.Int16; break; case ElementType.U2: result = module.CorLibTypes.UInt16; break; case ElementType.I4: result = module.CorLibTypes.Int32; break; case ElementType.U4: result = module.CorLibTypes.UInt32; break; case ElementType.I8: result = module.CorLibTypes.Int64; break; case ElementType.U8: result = module.CorLibTypes.UInt64; break; case ElementType.R4: result = module.CorLibTypes.Single; break; case ElementType.R8: result = module.CorLibTypes.Double; break; case ElementType.String: result = module.CorLibTypes.String; break; case ElementType.TypedByRef: result = module.CorLibTypes.TypedReference; break; case ElementType.I: result = module.CorLibTypes.IntPtr; break; case ElementType.U: result = module.CorLibTypes.UIntPtr; break; case ElementType.Object: result = module.CorLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(Import(type.Next)); break; case ElementType.ByRef: result = new ByRefSig(Import(type.Next)); break; case ElementType.ValueType: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, isValueType: true); break; case ElementType.Class: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, isValueType: false); break; case ElementType.Var: result = new GenericVar((type as GenericVar).Number, gpContext.Type); break; case ElementType.ValueArray: result = new ValueArraySig(Import(type.Next), (type as ValueArraySig).Size); break; case ElementType.FnPtr: result = new FnPtrSig(Import((type as FnPtrSig).Signature)); break; case ElementType.SZArray: result = new SZArraySig(Import(type.Next)); break; case ElementType.MVar: result = new GenericMVar((type as GenericMVar).Number, gpContext.Method); break; case ElementType.CModReqd: result = new CModReqdSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.CModOpt: result = new CModOptSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.Module: result = new ModuleSig((type as ModuleSig).Index, Import(type.Next)); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(Import(type.Next)); break; case ElementType.Array: { ArraySig arraySig = (ArraySig)type; List sizes = new List(arraySig.Sizes); List lowerBounds = new List(arraySig.LowerBounds); result = new ArraySig(Import(type.Next), arraySig.Rank, sizes, lowerBounds); break; } case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)type; List list = new List(genericInstSig.GenericArguments.Count); foreach (TypeSig genericArgument in genericInstSig.GenericArguments) { list.Add(Import(genericArgument)); } result = new GenericInstSig(Import(genericInstSig.GenericType) as ClassOrValueTypeSig, list); break; } default: result = null; break; } recursionCounter.Decrement(); return result; } public ITypeDefOrRef Import(ITypeDefOrRef type) { return (ITypeDefOrRef)Import((IType)type); } private TypeSig CreateClassOrValueType(ITypeDefOrRef type, bool isValueType) { CorLibTypeSig corLibTypeSig = module.CorLibTypes.GetCorLibTypeSig(type); if (corLibTypeSig != null) { return corLibTypeSig; } if (isValueType) { return new ValueTypeSig(Import(type)); } return new ClassSig(Import(type)); } public CallingConventionSig Import(CallingConventionSig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } Type type = sig.GetType(); CallingConventionSig result = ((type == typeof(MethodSig)) ? Import((MethodSig)sig) : ((type == typeof(FieldSig)) ? Import((FieldSig)sig) : ((type == typeof(GenericInstMethodSig)) ? Import((GenericInstMethodSig)sig) : ((type == typeof(PropertySig)) ? ((CallingConventionSig)Import((PropertySig)sig)) : ((CallingConventionSig)((!(type == typeof(LocalSig))) ? null : Import((LocalSig)sig))))))); recursionCounter.Decrement(); return result; } public FieldSig Import(FieldSig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } FieldSig result = new FieldSig(sig.GetCallingConvention(), Import(sig.Type)); recursionCounter.Decrement(); return result; } public MethodSig Import(MethodSig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } MethodSig result = Import(new MethodSig(sig.GetCallingConvention()), sig); recursionCounter.Decrement(); return result; } private T Import(T sig, T old) where T : MethodBaseSig { sig.RetType = Import(old.RetType); foreach (TypeSig item in old.Params) { sig.Params.Add(Import(item)); } sig.GenParamCount = old.GenParamCount; IList paramsAfterSentinel = sig.ParamsAfterSentinel; if (paramsAfterSentinel != null) { foreach (TypeSig item2 in old.ParamsAfterSentinel) { paramsAfterSentinel.Add(Import(item2)); } } return sig; } public PropertySig Import(PropertySig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } PropertySig result = Import(new PropertySig(sig.GetCallingConvention()), sig); recursionCounter.Decrement(); return result; } public LocalSig Import(LocalSig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } LocalSig localSig = new LocalSig(sig.GetCallingConvention(), (uint)sig.Locals.Count); foreach (TypeSig local in sig.Locals) { localSig.Locals.Add(Import(local)); } recursionCounter.Decrement(); return localSig; } public GenericInstMethodSig Import(GenericInstMethodSig sig) { if (sig == null) { return null; } if (!recursionCounter.Increment()) { return null; } GenericInstMethodSig genericInstMethodSig = new GenericInstMethodSig(sig.GetCallingConvention(), (uint)sig.GenericArguments.Count); foreach (TypeSig genericArgument in sig.GenericArguments) { genericInstMethodSig.GenericArguments.Add(Import(genericArgument)); } recursionCounter.Decrement(); return genericInstMethodSig; } public IField Import(IField field) { if (field == null) { return null; } if (!recursionCounter.Increment()) { return null; } IField result = ((!(field is FieldDef field2)) ? ((!(field is MemberRef memberRef)) ? null : Import(memberRef)) : Import(field2)); recursionCounter.Decrement(); return result; } public IMethod Import(IMethod method) { if (method == null) { return null; } if (!recursionCounter.Increment()) { return null; } IMethod result = ((!(method is MethodDef method2)) ? ((!(method is MethodSpec method3)) ? ((IMethod)((!(method is MemberRef memberRef)) ? null : Import(memberRef))) : ((IMethod)Import(method3))) : Import(method2)); recursionCounter.Decrement(); return result; } public IField Import(FieldDef field) { if (field == null) { return null; } if (TryToUseFieldDefs && field.Module == module) { return field; } if (!recursionCounter.Increment()) { return null; } IField field2 = mapper?.Map(field); if (field2 != null) { recursionCounter.Decrement(); return field2; } MemberRefUser memberRefUser = module.UpdateRowId(new MemberRefUser(module, field.Name)); memberRefUser.Signature = Import(field.Signature); memberRefUser.Class = ImportParent(field.DeclaringType); recursionCounter.Decrement(); return memberRefUser; } private IMemberRefParent ImportParent(TypeDef type) { if (type == null) { return null; } if (type.IsGlobalModuleType) { return module.UpdateRowId(new ModuleRefUser(module, type.Module?.Name)); } return Import(type); } public IMethod Import(MethodDef method) { if (method == null) { return null; } if (TryToUseMethodDefs && method.Module == module) { return method; } if (!recursionCounter.Increment()) { return null; } IMethod method2 = mapper?.Map(method); if (method2 != null) { recursionCounter.Decrement(); return method2; } MemberRefUser memberRefUser = module.UpdateRowId(new MemberRefUser(module, method.Name)); memberRefUser.Signature = Import(method.Signature); memberRefUser.Class = ImportParent(method.DeclaringType); recursionCounter.Decrement(); return memberRefUser; } public MethodSpec Import(MethodSpec method) { if (method == null) { return null; } if (!recursionCounter.Increment()) { return null; } MethodSpecUser methodSpecUser = module.UpdateRowId(new MethodSpecUser((IMethodDefOrRef)Import(method.Method))); methodSpecUser.Instantiation = Import(method.Instantiation); recursionCounter.Decrement(); return methodSpecUser; } public MemberRef Import(MemberRef memberRef) { if (memberRef == null) { return null; } if (!recursionCounter.Increment()) { return null; } MemberRef memberRef2 = mapper?.Map(memberRef); if (memberRef2 != null) { recursionCounter.Decrement(); return memberRef2; } MemberRef memberRef3 = module.UpdateRowId(new MemberRefUser(module, memberRef.Name)); memberRef3.Signature = Import(memberRef.Signature); memberRef3.Class = Import(memberRef.Class); if (memberRef3.Class == null) { memberRef3 = null; } recursionCounter.Decrement(); return memberRef3; } private IMemberRefParent Import(IMemberRefParent parent) { if (parent is ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeDef { IsGlobalModuleType: not false } typeDef) { return module.UpdateRowId(new ModuleRefUser(module, typeDef.Module?.Name)); } return Import(typeDefOrRef); } if (parent is ModuleRef moduleRef) { return module.UpdateRowId(new ModuleRefUser(module, moduleRef.Name)); } if (parent is MethodDef { DeclaringType: var declaringType } methodDef) { if (declaringType != null && declaringType.Module == module) { return methodDef; } return null; } return null; } } [DebuggerDisplay("{Interface}")] public abstract class InterfaceImpl : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IContainsGenericParameter, IHasCustomDebugInformation { protected uint rid; protected ITypeDefOrRef @interface; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.InterfaceImpl, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 5; public ITypeDefOrRef Interface { get { return @interface; } set { @interface = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 5; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } bool IContainsGenericParameter.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } } public class InterfaceImplUser : InterfaceImpl { public InterfaceImplUser() { } public InterfaceImplUser(ITypeDefOrRef @interface) { base.@interface = @interface; } } internal sealed class InterfaceImplMD : InterfaceImpl, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; public uint OrigRid => origRid; bool IContainsGenericParameter2.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.InterfaceImpl, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public InterfaceImplMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; readerModule.TablesStream.TryReadInterfaceImplRow(origRid, out var row); @interface = readerModule.ResolveTypeDefOrRef(row.Interface, gpContext); } } public interface IResolver : ITypeResolver, IMemberRefResolver { } public interface ITypeResolver { TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule); } public interface IMemberRefResolver { IMemberForwarded Resolve(MemberRef memberRef); } public interface ITokenResolver { IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext); } public interface IType : IFullName, IOwnerModule, ICodedToken, IMDTokenProvider, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter { bool IsValueType { get; } string TypeName { get; } string ReflectionName { get; } string Namespace { get; } string ReflectionNamespace { get; } string ReflectionFullName { get; } string AssemblyQualifiedName { get; } IAssembly DefinitionAssembly { get; } IScope Scope { get; } ITypeDefOrRef ScopeType { get; } bool IsPrimitive { get; } } public interface IContainsGenericParameter { bool ContainsGenericParameter { get; } } internal interface IContainsGenericParameter2 { bool ContainsGenericParameter { get; } } public interface ITypeDefFinder { TypeDef Find(string fullName, bool isReflectionName); TypeDef Find(TypeRef typeRef); } public interface IVariable { TypeSig Type { get; } int Index { get; } string Name { get; set; } } [DebuggerDisplay("{Offset} {Name.String} {Implementation}")] public abstract class ManifestResource : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation { protected uint rid; protected uint offset; protected int attributes; protected UTF8String name; protected IImplementation implementation; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.ManifestResource, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 18; public uint Offset { get { return offset; } set { offset = value; } } public ManifestResourceAttributes Flags { get { return (ManifestResourceAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public IImplementation Implementation { get { return implementation; } set { implementation = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 18; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public ManifestResourceAttributes Visibility { get { return (ManifestResourceAttributes)(attributes & 7); } set { ModifyAttributes(~ManifestResourceAttributes.VisibilityMask, value & ManifestResourceAttributes.VisibilityMask); } } public bool IsPublic => (attributes & 7) == 1; public bool IsPrivate => (attributes & 7) == 2; protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(ManifestResourceAttributes andMask, ManifestResourceAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } } public class ManifestResourceUser : ManifestResource { public ManifestResourceUser() { } public ManifestResourceUser(UTF8String name, IImplementation implementation) : this(name, implementation, (ManifestResourceAttributes)0u) { } public ManifestResourceUser(UTF8String name, IImplementation implementation, ManifestResourceAttributes flags) : this(name, implementation, flags, 0u) { } public ManifestResourceUser(UTF8String name, IImplementation implementation, ManifestResourceAttributes flags, uint offset) { base.name = name; base.implementation = implementation; attributes = (int)flags; base.offset = offset; } } internal sealed class ManifestResourceMD : ManifestResource, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ManifestResource, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public ManifestResourceMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadManifestResourceRow(origRid, out var row); offset = row.Offset; attributes = (int)row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); implementation = readerModule.ResolveImplementation(row.Implementation); } } [Flags] public enum ManifestResourceAttributes : uint { VisibilityMask = 7u, Public = 1u, Private = 2u } public struct MarshalBlobReader { private readonly ModuleDef module; private DataReader reader; private readonly GenericParamContext gpContext; public static MarshalType Read(ModuleDefMD module, uint sig) { return Read(module, module.BlobStream.CreateReader(sig), default(GenericParamContext)); } public static MarshalType Read(ModuleDefMD module, uint sig, GenericParamContext gpContext) { return Read(module, module.BlobStream.CreateReader(sig), gpContext); } public static MarshalType Read(ModuleDef module, byte[] data) { return Read(module, ByteArrayDataReaderFactory.CreateReader(data), default(GenericParamContext)); } public static MarshalType Read(ModuleDef module, byte[] data, GenericParamContext gpContext) { return Read(module, ByteArrayDataReaderFactory.CreateReader(data), gpContext); } public static MarshalType Read(ModuleDef module, DataReader reader) { return Read(module, reader, default(GenericParamContext)); } public static MarshalType Read(ModuleDef module, DataReader reader, GenericParamContext gpContext) { return new MarshalBlobReader(module, ref reader, gpContext).Read(); } private MarshalBlobReader(ModuleDef module, ref DataReader reader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.gpContext = gpContext; } private MarshalType Read() { try { NativeType nativeType = (NativeType)reader.ReadByte(); switch (nativeType) { case NativeType.FixedSysString: { int numElems = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); return new FixedSysStringMarshalType(numElems); } case NativeType.SafeArray: { int vt = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); UTF8String uTF8String = (CanRead() ? ReadUTF8String() : null); ITypeDefOrRef userDefinedSubType = (((object)uTF8String == null) ? null : TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(uTF8String), null, gpContext)); return new SafeArrayMarshalType((VariantType)vt, userDefinedSubType); } case NativeType.FixedArray: { int numElems = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); NativeType elementType = (CanRead() ? ((NativeType)reader.ReadCompressedUInt32()) : NativeType.NotInitialized); return new FixedArrayMarshalType(numElems, elementType); } case NativeType.Array: { NativeType elementType = (CanRead() ? ((NativeType)reader.ReadCompressedUInt32()) : NativeType.NotInitialized); int paramNum = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); int numElems = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); int flags = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); return new ArrayMarshalType(elementType, paramNum, numElems, flags); } case NativeType.CustomMarshaler: { UTF8String guid = ReadUTF8String(); UTF8String nativeTypeName = ReadUTF8String(); UTF8String uTF8String2 = ReadUTF8String(); ITypeDefOrRef custMarshaler = ((uTF8String2.DataLength == 0) ? null : TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(uTF8String2), new CAAssemblyRefFinder(module), gpContext)); UTF8String cookie = ReadUTF8String(); return new CustomMarshalType(guid, nativeTypeName, custMarshaler, cookie); } case NativeType.IUnknown: case NativeType.IDispatch: case NativeType.IntF: { int iidParamIndex = (CanRead() ? ((int)reader.ReadCompressedUInt32()) : (-1)); return new InterfaceMarshalType(nativeType, iidParamIndex); } default: return new MarshalType(nativeType); } } catch { return new RawMarshalType(reader.ToArray()); } } private bool CanRead() { return reader.Position < reader.Length; } private UTF8String ReadUTF8String() { uint num = reader.ReadCompressedUInt32(); if (num != 0) { return new UTF8String(reader.ReadBytes((int)num)); } return UTF8String.Empty; } } public class MarshalType { protected readonly NativeType nativeType; public NativeType NativeType => nativeType; public MarshalType(NativeType nativeType) { this.nativeType = nativeType; } public override string ToString() { return nativeType.ToString(); } } public sealed class RawMarshalType : MarshalType { private byte[] data; public byte[] Data { get { return data; } set { data = value; } } public RawMarshalType(byte[] data) : base(NativeType.RawBlob) { this.data = data; } } public sealed class FixedSysStringMarshalType : MarshalType { private int size; public int Size { get { return size; } set { size = value; } } public bool IsSizeValid => size >= 0; public FixedSysStringMarshalType() : this(-1) { } public FixedSysStringMarshalType(int size) : base(NativeType.FixedSysString) { this.size = size; } public override string ToString() { if (!IsSizeValid) { return $"{nativeType} ()"; } return $"{nativeType} ({size})"; } } public sealed class SafeArrayMarshalType : MarshalType { private VariantType vt; private ITypeDefOrRef userDefinedSubType; public VariantType VariantType { get { return vt; } set { vt = value; } } public ITypeDefOrRef UserDefinedSubType { get { return userDefinedSubType; } set { userDefinedSubType = value; } } public bool IsVariantTypeValid => vt != VariantType.NotInitialized; public bool IsUserDefinedSubTypeValid => userDefinedSubType != null; public SafeArrayMarshalType() : this(VariantType.NotInitialized, null) { } public SafeArrayMarshalType(VariantType vt) : this(vt, null) { } public SafeArrayMarshalType(ITypeDefOrRef userDefinedSubType) : this(VariantType.NotInitialized, userDefinedSubType) { } public SafeArrayMarshalType(VariantType vt, ITypeDefOrRef userDefinedSubType) : base(NativeType.SafeArray) { this.vt = vt; this.userDefinedSubType = userDefinedSubType; } public override string ToString() { ITypeDefOrRef typeDefOrRef = userDefinedSubType; if (typeDefOrRef == null) { return $"{nativeType} ({vt})"; } return $"{nativeType} ({vt}, {typeDefOrRef})"; } } public sealed class FixedArrayMarshalType : MarshalType { private int size; private NativeType elementType; public NativeType ElementType { get { return elementType; } set { elementType = value; } } public int Size { get { return size; } set { size = value; } } public bool IsElementTypeValid => elementType != NativeType.NotInitialized; public bool IsSizeValid => size >= 0; public FixedArrayMarshalType() : this(0) { } public FixedArrayMarshalType(int size) : this(size, NativeType.NotInitialized) { } public FixedArrayMarshalType(int size, NativeType elementType) : base(NativeType.FixedArray) { this.size = size; this.elementType = elementType; } public override string ToString() { return $"{nativeType} ({size}, {elementType})"; } } public sealed class ArrayMarshalType : MarshalType { private NativeType elementType; private int paramNum; private int numElems; private int flags; private const int ntaSizeParamIndexSpecified = 1; public NativeType ElementType { get { return elementType; } set { elementType = value; } } public int ParamNumber { get { return paramNum; } set { paramNum = value; } } public int Size { get { return numElems; } set { numElems = value; } } public int Flags { get { return flags; } set { flags = value; } } public bool IsElementTypeValid => elementType != NativeType.NotInitialized; public bool IsParamNumberValid => paramNum >= 0; public bool IsSizeValid => numElems >= 0; public bool IsFlagsValid => flags >= 0; public bool IsSizeParamIndexSpecified { get { if (IsFlagsValid) { return (flags & 1) != 0; } return false; } } public bool IsSizeParamIndexNotSpecified { get { if (IsFlagsValid) { return (flags & 1) == 0; } return false; } } public ArrayMarshalType() : this(NativeType.NotInitialized, -1, -1, -1) { } public ArrayMarshalType(NativeType elementType) : this(elementType, -1, -1, -1) { } public ArrayMarshalType(NativeType elementType, int paramNum) : this(elementType, paramNum, -1, -1) { } public ArrayMarshalType(NativeType elementType, int paramNum, int numElems) : this(elementType, paramNum, numElems, -1) { } public ArrayMarshalType(NativeType elementType, int paramNum, int numElems, int flags) : base(NativeType.Array) { this.elementType = elementType; this.paramNum = paramNum; this.numElems = numElems; this.flags = flags; } public override string ToString() { return $"{nativeType} ({elementType}, {paramNum}, {numElems}, {flags})"; } } public sealed class CustomMarshalType : MarshalType { private UTF8String guid; private UTF8String nativeTypeName; private ITypeDefOrRef custMarshaler; private UTF8String cookie; public UTF8String Guid { get { return guid; } set { guid = value; } } public UTF8String NativeTypeName { get { return nativeTypeName; } set { nativeTypeName = value; } } public ITypeDefOrRef CustomMarshaler { get { return custMarshaler; } set { custMarshaler = value; } } public UTF8String Cookie { get { return cookie; } set { cookie = value; } } public CustomMarshalType() : this(null, null, null, null) { } public CustomMarshalType(UTF8String guid) : this(guid, null, null, null) { } public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName) : this(guid, nativeTypeName, null, null) { } public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName, ITypeDefOrRef custMarshaler) : this(guid, nativeTypeName, custMarshaler, null) { } public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName, ITypeDefOrRef custMarshaler, UTF8String cookie) : base(NativeType.CustomMarshaler) { this.guid = guid; this.nativeTypeName = nativeTypeName; this.custMarshaler = custMarshaler; this.cookie = cookie; } public override string ToString() { return $"{nativeType} ({guid}, {nativeTypeName}, {custMarshaler}, {cookie})"; } } public sealed class InterfaceMarshalType : MarshalType { private int iidParamIndex; public int IidParamIndex { get { return iidParamIndex; } set { iidParamIndex = value; } } public bool IsIidParamIndexValid => iidParamIndex >= 0; public InterfaceMarshalType(NativeType nativeType) : this(nativeType, -1) { } public InterfaceMarshalType(NativeType nativeType, int iidParamIndex) : base(nativeType) { if (nativeType != NativeType.IUnknown && nativeType != NativeType.IDispatch && nativeType != NativeType.IntF) { throw new ArgumentException("Invalid nativeType"); } this.iidParamIndex = iidParamIndex; } public override string ToString() { return $"{nativeType} ({iidParamIndex})"; } } [DebuggerDisplay("{Table} {Rid}")] public readonly struct MDToken : IEquatable, IComparable { public const uint RID_MASK = 16777215u; public const uint RID_MAX = 16777215u; public const int TABLE_SHIFT = 24; private readonly uint token; public Table Table => ToTable(token); public uint Rid => ToRID(token); public uint Raw => token; public bool IsNull => Rid == 0; public MDToken(uint token) { this.token = token; } public MDToken(int token) : this((uint)token) { } public MDToken(Table table, uint rid) : this(((uint)table << 24) | rid) { } public MDToken(Table table, int rid) : this(((uint)table << 24) | (uint)rid) { } public static uint ToRID(uint token) { return token & 0xFFFFFF; } public static uint ToRID(int token) { return ToRID((uint)token); } public static Table ToTable(uint token) { return (Table)(token >> 24); } public static Table ToTable(int token) { return ToTable((uint)token); } public int ToInt32() { return (int)token; } public uint ToUInt32() { return token; } public static bool operator ==(MDToken left, MDToken right) { return left.CompareTo(right) == 0; } public static bool operator !=(MDToken left, MDToken right) { return left.CompareTo(right) != 0; } public static bool operator <(MDToken left, MDToken right) { return left.CompareTo(right) < 0; } public static bool operator >(MDToken left, MDToken right) { return left.CompareTo(right) > 0; } public static bool operator <=(MDToken left, MDToken right) { return left.CompareTo(right) <= 0; } public static bool operator >=(MDToken left, MDToken right) { return left.CompareTo(right) >= 0; } public int CompareTo(MDToken other) { return token.CompareTo(other.token); } public bool Equals(MDToken other) { return CompareTo(other) == 0; } public override bool Equals(object obj) { if (!(obj is MDToken)) { return false; } return Equals((MDToken)obj); } public override int GetHashCode() { return (int)token; } public override string ToString() { return token.ToString("X8"); } } public class MemberFinder { private enum ObjectType { Unknown, EventDef, FieldDef, GenericParam, MemberRef, MethodDef, MethodSpec, PropertyDef, TypeDef, TypeRef, TypeSig, TypeSpec, ExportedType } public readonly Dictionary CustomAttributes = new Dictionary(); public readonly Dictionary EventDefs = new Dictionary(); public readonly Dictionary FieldDefs = new Dictionary(); public readonly Dictionary GenericParams = new Dictionary(); public readonly Dictionary MemberRefs = new Dictionary(); public readonly Dictionary MethodDefs = new Dictionary(); public readonly Dictionary MethodSpecs = new Dictionary(); public readonly Dictionary PropertyDefs = new Dictionary(); public readonly Dictionary TypeDefs = new Dictionary(); public readonly Dictionary TypeRefs = new Dictionary(); public readonly Dictionary TypeSigs = new Dictionary(); public readonly Dictionary TypeSpecs = new Dictionary(); public readonly Dictionary ExportedTypes = new Dictionary(); private Stack objectStack; private ModuleDef validModule; private readonly Dictionary toObjectType = new Dictionary(); public MemberFinder FindAll(ModuleDef module) { validModule = module; objectStack = new Stack(4096); Add(module); ProcessAll(); objectStack = null; return this; } private void Push(object mr) { if (mr != null) { objectStack.Push(mr); } } private void ProcessAll() { while (objectStack.Count > 0) { object obj = objectStack.Pop(); switch (GetObjectType(obj)) { case ObjectType.EventDef: Add((EventDef)obj); break; case ObjectType.FieldDef: Add((FieldDef)obj); break; case ObjectType.GenericParam: Add((GenericParam)obj); break; case ObjectType.MemberRef: Add((MemberRef)obj); break; case ObjectType.MethodDef: Add((MethodDef)obj); break; case ObjectType.MethodSpec: Add((MethodSpec)obj); break; case ObjectType.PropertyDef: Add((PropertyDef)obj); break; case ObjectType.TypeDef: Add((TypeDef)obj); break; case ObjectType.TypeRef: Add((TypeRef)obj); break; case ObjectType.TypeSig: Add((TypeSig)obj); break; case ObjectType.TypeSpec: Add((TypeSpec)obj); break; case ObjectType.ExportedType: Add((ExportedType)obj); break; default: throw new InvalidOperationException($"Unknown type: {obj.GetType()}"); case ObjectType.Unknown: break; } } } private ObjectType GetObjectType(object o) { if (o == null) { return ObjectType.Unknown; } Type type = o.GetType(); if (toObjectType.TryGetValue(type, out var value)) { return value; } value = GetObjectType2(o); toObjectType[type] = value; return value; } private static ObjectType GetObjectType2(object o) { if (o is EventDef) { return ObjectType.EventDef; } if (o is FieldDef) { return ObjectType.FieldDef; } if (o is GenericParam) { return ObjectType.GenericParam; } if (o is MemberRef) { return ObjectType.MemberRef; } if (o is MethodDef) { return ObjectType.MethodDef; } if (o is MethodSpec) { return ObjectType.MethodSpec; } if (o is PropertyDef) { return ObjectType.PropertyDef; } if (o is TypeDef) { return ObjectType.TypeDef; } if (o is TypeRef) { return ObjectType.TypeRef; } if (o is TypeSig) { return ObjectType.TypeSig; } if (o is TypeSpec) { return ObjectType.TypeSpec; } if (o is ExportedType) { return ObjectType.ExportedType; } return ObjectType.Unknown; } private void Add(ModuleDef mod) { Push(mod.ManagedEntryPoint); Add(mod.CustomAttributes); Add(mod.Types); Add(mod.ExportedTypes); if (mod.IsManifestModule) { Add(mod.Assembly); } Add(mod.VTableFixups); Add(mod.Resources); } private void Add(VTableFixups fixups) { if (fixups == null) { return; } foreach (VTable fixup in fixups) { foreach (IMethod item in fixup) { Push(item); } } } private void Add(ResourceCollection resources) { foreach (Resource resource in resources) { Add(resource.CustomAttributes); } } private void Add(AssemblyDef asm) { if (asm != null) { Add(asm.DeclSecurities); Add(asm.CustomAttributes); } } private void Add(CallingConventionSig sig) { if (sig != null) { if (sig is FieldSig sig2) { Add(sig2); } else if (sig is MethodBaseSig sig3) { Add(sig3); } else if (sig is LocalSig sig4) { Add(sig4); } else if (sig is GenericInstMethodSig sig5) { Add(sig5); } } } private void Add(FieldSig sig) { if (sig != null) { Add(sig.Type); } } private void Add(MethodBaseSig sig) { if (sig != null) { Add(sig.RetType); Add(sig.Params); Add(sig.ParamsAfterSentinel); } } private void Add(LocalSig sig) { if (sig != null) { Add(sig.Locals); } } private void Add(GenericInstMethodSig sig) { if (sig != null) { Add(sig.GenericArguments); } } private void Add(IEnumerable cas) { if (cas == null) { return; } foreach (CustomAttribute ca in cas) { Add(ca); } } private void Add(CustomAttribute ca) { if (ca != null && !CustomAttributes.ContainsKey(ca)) { CustomAttributes[ca] = true; Push(ca.Constructor); Add(ca.ConstructorArguments); Add(ca.NamedArguments); } } private void Add(IEnumerable args) { if (args == null) { return; } foreach (CAArgument arg in args) { Add(arg); } } private void Add(CAArgument arg) { Add(arg.Type); if (arg.Value is TypeSig ts) { Add(ts); } else if (arg.Value is IList args) { Add(args); } else if (arg.Value is CAArgument arg2) { Add(arg2); } } private void Add(IEnumerable args) { if (args == null) { return; } foreach (CANamedArgument arg in args) { Add(arg); } } private void Add(CANamedArgument arg) { if (arg != null) { Add(arg.Type); Add(arg.Argument); } } private void Add(IEnumerable decls) { if (decls == null) { return; } foreach (DeclSecurity decl in decls) { Add(decl); } } private void Add(DeclSecurity decl) { if (decl != null) { Add(decl.SecurityAttributes); Add(decl.CustomAttributes); } } private void Add(IEnumerable secAttrs) { if (secAttrs == null) { return; } foreach (SecurityAttribute secAttr in secAttrs) { Add(secAttr); } } private void Add(SecurityAttribute secAttr) { if (secAttr != null) { Add(secAttr.AttributeType); Add(secAttr.NamedArguments); } } private void Add(ITypeDefOrRef tdr) { if (tdr is TypeDef td) { Add(td); } else if (tdr is TypeRef tr) { Add(tr); } else if (tdr is TypeSpec ts) { Add(ts); } } private void Add(IEnumerable eds) { if (eds == null) { return; } foreach (EventDef ed in eds) { Add(ed); } } private void Add(EventDef ed) { if (ed != null && !EventDefs.ContainsKey(ed) && (ed.DeclaringType == null || ed.DeclaringType.Module == validModule)) { EventDefs[ed] = true; Push(ed.EventType); Add(ed.CustomAttributes); Add(ed.AddMethod); Add(ed.InvokeMethod); Add(ed.RemoveMethod); Add(ed.OtherMethods); Add(ed.DeclaringType); } } private void Add(IEnumerable fds) { if (fds == null) { return; } foreach (FieldDef fd in fds) { Add(fd); } } private void Add(FieldDef fd) { if (fd != null && !FieldDefs.ContainsKey(fd) && (fd.DeclaringType == null || fd.DeclaringType.Module == validModule)) { FieldDefs[fd] = true; Add(fd.CustomAttributes); Add(fd.Signature); Add(fd.DeclaringType); Add(fd.MarshalType); } } private void Add(IEnumerable gps) { if (gps == null) { return; } foreach (GenericParam gp in gps) { Add(gp); } } private void Add(GenericParam gp) { if (gp != null && !GenericParams.ContainsKey(gp)) { GenericParams[gp] = true; Push(gp.Owner); Push(gp.Kind); Add(gp.GenericParamConstraints); Add(gp.CustomAttributes); } } private void Add(IEnumerable gpcs) { if (gpcs == null) { return; } foreach (GenericParamConstraint gpc in gpcs) { Add(gpc); } } private void Add(GenericParamConstraint gpc) { if (gpc != null) { Add(gpc.Owner); Push(gpc.Constraint); Add(gpc.CustomAttributes); } } private void Add(MemberRef mr) { if (mr != null && !MemberRefs.ContainsKey(mr) && mr.Module == validModule) { MemberRefs[mr] = true; Push(mr.Class); Add(mr.Signature); Add(mr.CustomAttributes); } } private void Add(IEnumerable methods) { if (methods == null) { return; } foreach (MethodDef method in methods) { Add(method); } } private void Add(MethodDef md) { if (md != null && !MethodDefs.ContainsKey(md) && (md.DeclaringType == null || md.DeclaringType.Module == validModule)) { MethodDefs[md] = true; Add(md.Signature); Add(md.ParamDefs); Add(md.GenericParameters); Add(md.DeclSecurities); Add(md.MethodBody); Add(md.CustomAttributes); Add(md.Overrides); Add(md.DeclaringType); } } private void Add(dnlib.DotNet.Emit.MethodBody mb) { if (mb is CilBody cb) { Add(cb); } } private void Add(CilBody cb) { if (cb != null) { Add(cb.Instructions); Add(cb.ExceptionHandlers); Add(cb.Variables); } } private void Add(IEnumerable instrs) { if (instrs == null) { return; } foreach (Instruction instr in instrs) { if (instr == null) { continue; } switch (instr.OpCode.OperandType) { case dnlib.DotNet.Emit.OperandType.InlineField: case dnlib.DotNet.Emit.OperandType.InlineMethod: case dnlib.DotNet.Emit.OperandType.InlineTok: case dnlib.DotNet.Emit.OperandType.InlineType: Push(instr.Operand); break; case dnlib.DotNet.Emit.OperandType.InlineSig: Add(instr.Operand as CallingConventionSig); break; case dnlib.DotNet.Emit.OperandType.InlineVar: case dnlib.DotNet.Emit.OperandType.ShortInlineVar: if (instr.Operand is Local local) { Add(local); } else if (instr.Operand is Parameter param) { Add(param); } break; } } } private void Add(IEnumerable ehs) { if (ehs == null) { return; } foreach (ExceptionHandler eh in ehs) { Push(eh.CatchType); } } private void Add(IEnumerable locals) { if (locals == null) { return; } foreach (Local local in locals) { Add(local); } } private void Add(Local local) { if (local != null) { Add(local.Type); } } private void Add(IEnumerable ps) { if (ps == null) { return; } foreach (Parameter p in ps) { Add(p); } } private void Add(Parameter param) { if (param != null) { Add(param.Type); Add(param.Method); } } private void Add(IEnumerable pds) { if (pds == null) { return; } foreach (ParamDef pd in pds) { Add(pd); } } private void Add(ParamDef pd) { if (pd != null) { Add(pd.DeclaringMethod); Add(pd.CustomAttributes); Add(pd.MarshalType); } } private void Add(MarshalType mt) { if (mt != null) { switch (mt.NativeType) { case NativeType.SafeArray: Add(((SafeArrayMarshalType)mt).UserDefinedSubType); break; case NativeType.CustomMarshaler: Add(((CustomMarshalType)mt).CustomMarshaler); break; } } } private void Add(IEnumerable mos) { if (mos == null) { return; } foreach (MethodOverride mo in mos) { Add(mo); } } private void Add(MethodOverride mo) { Push(mo.MethodBody); Push(mo.MethodDeclaration); } private void Add(MethodSpec ms) { if (ms != null && !MethodSpecs.ContainsKey(ms) && (ms.Method == null || ms.Method.DeclaringType == null || ms.Method.DeclaringType.Module == validModule)) { MethodSpecs[ms] = true; Push(ms.Method); Add(ms.Instantiation); Add(ms.CustomAttributes); } } private void Add(IEnumerable pds) { if (pds == null) { return; } foreach (PropertyDef pd in pds) { Add(pd); } } private void Add(PropertyDef pd) { if (pd != null && !PropertyDefs.ContainsKey(pd) && (pd.DeclaringType == null || pd.DeclaringType.Module == validModule)) { PropertyDefs[pd] = true; Add(pd.Type); Add(pd.CustomAttributes); Add(pd.GetMethods); Add(pd.SetMethods); Add(pd.OtherMethods); Add(pd.DeclaringType); } } private void Add(IEnumerable tds) { if (tds == null) { return; } foreach (TypeDef td in tds) { Add(td); } } private void Add(TypeDef td) { if (td != null && !TypeDefs.ContainsKey(td) && td.Module == validModule) { TypeDefs[td] = true; Push(td.BaseType); Add(td.Fields); Add(td.Methods); Add(td.GenericParameters); Add(td.Interfaces); Add(td.DeclSecurities); Add(td.DeclaringType); Add(td.Events); Add(td.Properties); Add(td.NestedTypes); Add(td.CustomAttributes); } } private void Add(IEnumerable iis) { if (iis == null) { return; } foreach (InterfaceImpl ii in iis) { Add(ii); } } private void Add(InterfaceImpl ii) { if (ii != null) { Push(ii.Interface); Add(ii.CustomAttributes); } } private void Add(TypeRef tr) { if (tr != null && !TypeRefs.ContainsKey(tr) && tr.Module == validModule) { TypeRefs[tr] = true; Push(tr.ResolutionScope); Add(tr.CustomAttributes); } } private void Add(IEnumerable tss) { if (tss == null) { return; } foreach (TypeSig item in tss) { Add(item); } } private void Add(TypeSig ts) { if (ts == null || TypeSigs.ContainsKey(ts) || ts.Module != validModule) { return; } TypeSigs[ts] = true; while (ts != null) { switch (ts.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: { TypeDefOrRefSig typeDefOrRefSig = (TypeDefOrRefSig)ts; Push(typeDefOrRefSig.TypeDefOrRef); break; } case ElementType.FnPtr: { FnPtrSig fnPtrSig = (FnPtrSig)ts; Add(fnPtrSig.Signature); break; } case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)ts; Add(genericInstSig.GenericType); Add(genericInstSig.GenericArguments); break; } case ElementType.CModReqd: case ElementType.CModOpt: { ModifierSig modifierSig = (ModifierSig)ts; Push(modifierSig.Modifier); break; } } ts = ts.Next; } } private void Add(TypeSpec ts) { if (ts != null && !TypeSpecs.ContainsKey(ts) && ts.Module == validModule) { TypeSpecs[ts] = true; Add(ts.TypeSig); Add(ts.CustomAttributes); } } private void Add(IEnumerable ets) { if (ets == null) { return; } foreach (ExportedType et in ets) { Add(et); } } private void Add(ExportedType et) { if (et != null && !ExportedTypes.ContainsKey(et) && et.Module == validModule) { ExportedTypes[et] = true; Add(et.CustomAttributes); Push(et.Implementation); } } } internal static class MemberMDInitializer { public static void Initialize(IEnumerable coll) { if (coll == null) { return; } foreach (T item in coll) { _ = item; } } public static void Initialize(object o) { } } public abstract class MemberRef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IMethodDefOrRef, ICustomAttributeType, IMethod, ITokenOperand, IFullName, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule, IField, IContainsGenericParameter, IHasCustomDebugInformation { protected uint rid; protected ModuleDef module; protected IMemberRefParent @class; protected UTF8String name; protected CallingConventionSig signature; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.MemberRef, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 6; public int MethodDefOrRefTag => 1; public int CustomAttributeTypeTag => 3; public IMemberRefParent Class { get { return @class; } set { @class = value; } } public UTF8String Name { get { return name; } set { name = value; } } public CallingConventionSig Signature { get { return signature; } set { signature = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 6; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public ITypeDefOrRef DeclaringType { get { IMemberRefParent memberRefParent = @class; if (memberRefParent is ITypeDefOrRef result) { return result; } if (memberRefParent is MethodDef methodDef) { return methodDef.DeclaringType; } if (memberRefParent is ModuleRef mr) { TypeRefUser globalTypeRef = GetGlobalTypeRef(mr); if (module != null) { return module.UpdateRowId(globalTypeRef); } return globalTypeRef; } return null; } } bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => IsMethodRef; bool IMemberRef.IsField => IsFieldRef; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => true; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public bool IsMethodRef => MethodSig != null; public bool IsFieldRef => FieldSig != null; public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } public FieldSig FieldSig { get { return signature as FieldSig; } set { signature = value; } } public ModuleDef Module => module; public bool HasThis => MethodSig?.HasThis ?? false; public bool ExplicitThis => MethodSig?.ExplicitThis ?? false; public CallingConvention CallingConvention { get { MethodSig methodSig = MethodSig; if (methodSig != null) { return methodSig.CallingConvention & CallingConvention.Mask; } return CallingConvention.Default; } } public TypeSig ReturnType { get { return MethodSig?.RetType; } set { MethodSig methodSig = MethodSig; if (methodSig != null) { methodSig.RetType = value; } } } int IGenericParameterProvider.NumberOfGenericParameters => (int)(MethodSig?.GenParamCount ?? 0); public string FullName { get { IMemberRefParent memberRefParent = @class; IList typeGenArgs = null; if (memberRefParent is TypeSpec && ((TypeSpec)memberRefParent).TypeSig is GenericInstSig genericInstSig) { typeGenArgs = genericInstSig.GenericArguments; } MethodSig methodSig = MethodSig; if (methodSig != null) { return FullNameFactory.MethodFullName(GetDeclaringTypeFullName(memberRefParent), name, methodSig, typeGenArgs); } FieldSig fieldSig = FieldSig; if (fieldSig != null) { return FullNameFactory.FieldFullName(GetDeclaringTypeFullName(memberRefParent), name, fieldSig, typeGenArgs); } return string.Empty; } } bool IContainsGenericParameter.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private TypeRefUser GetGlobalTypeRef(ModuleRef mr) { if (module == null) { return CreateDefaultGlobalTypeRef(mr); } TypeDef globalType = module.GlobalType; if (globalType != null && default(SigComparer).Equals(module, mr)) { return new TypeRefUser(module, globalType.Namespace, globalType.Name, mr); } AssemblyDef assembly = module.Assembly; if (assembly == null) { return CreateDefaultGlobalTypeRef(mr); } ModuleDef moduleDef = assembly.FindModule(mr.Name); if (moduleDef == null) { return CreateDefaultGlobalTypeRef(mr); } globalType = moduleDef.GlobalType; if (globalType == null) { return CreateDefaultGlobalTypeRef(mr); } return new TypeRefUser(module, globalType.Namespace, globalType.Name, mr); } private TypeRefUser CreateDefaultGlobalTypeRef(ModuleRef mr) { TypeRefUser typeRefUser = new TypeRefUser(module, string.Empty, "", mr); if (module != null) { module.UpdateRowId(typeRefUser); } return typeRefUser; } public string GetDeclaringTypeFullName() { return GetDeclaringTypeFullName(@class); } private string GetDeclaringTypeFullName(IMemberRefParent parent) { if (parent == null) { return null; } if (parent is ITypeDefOrRef) { return ((ITypeDefOrRef)parent).FullName; } if (parent is ModuleRef) { return "[module:" + ((ModuleRef)parent).ToString() + "]"; } if (parent is MethodDef) { return ((MethodDef)parent).DeclaringType?.FullName; } return null; } internal string GetDeclaringTypeName() { return GetDeclaringTypeName(@class); } private string GetDeclaringTypeName(IMemberRefParent parent) { if (parent == null) { return null; } if (parent is ITypeDefOrRef) { return ((ITypeDefOrRef)parent).Name; } if (parent is ModuleRef) { return ""; } if (parent is MethodDef) { return ((MethodDef)parent).DeclaringType?.Name; } return null; } public IMemberForwarded Resolve() { if (module == null) { return null; } return module.Context.Resolver.Resolve(this); } public IMemberForwarded ResolveThrow() { IMemberForwarded memberForwarded = Resolve(); if (memberForwarded != null) { return memberForwarded; } throw new MemberRefResolveException($"Could not resolve method/field: {this} ({this.GetDefinitionAssembly()})"); } public FieldDef ResolveField() { return Resolve() as FieldDef; } public FieldDef ResolveFieldThrow() { FieldDef fieldDef = ResolveField(); if (fieldDef != null) { return fieldDef; } throw new MemberRefResolveException($"Could not resolve field: {this} ({this.GetDefinitionAssembly()})"); } public MethodDef ResolveMethod() { return Resolve() as MethodDef; } public MethodDef ResolveMethodThrow() { MethodDef methodDef = ResolveMethod(); if (methodDef != null) { return methodDef; } throw new MemberRefResolveException($"Could not resolve method: {this} ({this.GetDefinitionAssembly()})"); } protected static GenericParamContext GetSignatureGenericParamContext(GenericParamContext gpContext, IMemberRefParent @class) { TypeDef type = null; MethodDef method = gpContext.Method; if (@class is TypeSpec { TypeSig: GenericInstSig typeSig }) { type = typeSig.GenericType.ToTypeDefOrRef().ResolveTypeDef(); } return new GenericParamContext(type, method); } public override string ToString() { return FullName; } } public class MemberRefUser : MemberRef { public MemberRefUser(ModuleDef module) { base.module = module; } public MemberRefUser(ModuleDef module, UTF8String name) { base.module = module; base.name = name; } public MemberRefUser(ModuleDef module, UTF8String name, FieldSig sig) : this(module, name, sig, null) { } public MemberRefUser(ModuleDef module, UTF8String name, FieldSig sig, IMemberRefParent @class) { base.module = module; base.name = name; base.@class = @class; signature = sig; } public MemberRefUser(ModuleDef module, UTF8String name, MethodSig sig) : this(module, name, sig, null) { } public MemberRefUser(ModuleDef module, UTF8String name, MethodSig sig, IMemberRefParent @class) { base.module = module; base.name = name; base.@class = @class; signature = sig; } } internal sealed class MemberRefMD : MemberRef, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; public uint OrigRid => origRid; bool IContainsGenericParameter2.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.MemberRef, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public MemberRefMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; module = readerModule; readerModule.TablesStream.TryReadMemberRefRow(origRid, out var row); name = readerModule.StringsStream.ReadNoNull(row.Name); @class = readerModule.ResolveMemberRefParent(row.Class, gpContext); signature = readerModule.ReadSignature(row.Signature, MemberRef.GetSignatureGenericParamContext(gpContext, @class)); } } [Flags] public enum MethodAttributes : ushort { MemberAccessMask = 7, PrivateScope = 0, CompilerControlled = 0, Private = 1, FamANDAssem = 2, Assembly = 3, Family = 4, FamORAssem = 5, Public = 6, Static = 0x10, Final = 0x20, Virtual = 0x40, HideBySig = 0x80, VtableLayoutMask = 0x100, ReuseSlot = 0, NewSlot = 0x100, CheckAccessOnOverride = 0x200, Abstract = 0x400, SpecialName = 0x800, PinvokeImpl = 0x2000, UnmanagedExport = 8, RTSpecialName = 0x1000, HasSecurity = 0x4000, RequireSecObject = 0x8000 } public abstract class MethodDef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasDeclSecurity, IFullName, IMemberRefParent, IMethodDefOrRef, ICustomAttributeType, IMethod, ITokenOperand, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule, IMemberForwarded, ITypeOrMethodDef, IMemberDef, IDnlibDef, IManagedEntryPoint, IHasCustomDebugInformation, IListListener, IListListener { internal static readonly UTF8String StaticConstructorName = ".cctor"; internal static readonly UTF8String InstanceConstructorName = ".ctor"; protected uint rid; private readonly Lock theLock = Lock.Create(); protected ParameterList parameterList; protected RVA rva; protected int implAttributes; protected int attributes; protected UTF8String name; protected CallingConventionSig signature; protected LazyList paramDefs; protected LazyList genericParameters; protected IList declSecurities; protected ImplMap implMap; protected bool implMap_isInitialized; protected dnlib.DotNet.Emit.MethodBody methodBody; protected bool methodBody_isInitialized; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected IList overrides; protected MethodExportInfo exportInfo; protected TypeDef declaringType2; protected internal static int SEMATTRS_INITD = int.MinValue; protected internal int semAttrs; public MDToken MDToken => new MDToken(Table.Method, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 0; public int HasDeclSecurityTag => 1; public int MemberRefParentTag => 3; public int MethodDefOrRefTag => 0; public int MemberForwardedTag => 1; public int CustomAttributeTypeTag => 2; public int TypeOrMethodDefTag => 1; public RVA RVA { get { return rva; } set { rva = value; } } public MethodImplAttributes ImplAttributes { get { return (MethodImplAttributes)implAttributes; } set { implAttributes = (int)value; } } public MethodAttributes Attributes { get { return (MethodAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public CallingConventionSig Signature { get { return signature; } set { signature = value; } } public IList ParamDefs { get { if (paramDefs == null) { InitializeParamDefs(); } return paramDefs; } } public IList GenericParameters { get { if (genericParameters == null) { InitializeGenericParameters(); } return genericParameters; } } public IList DeclSecurities { get { if (declSecurities == null) { InitializeDeclSecurities(); } return declSecurities; } } public ImplMap ImplMap { get { if (!implMap_isInitialized) { InitializeImplMap(); } return implMap; } set { theLock.EnterWriteLock(); try { implMap = value; implMap_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public dnlib.DotNet.Emit.MethodBody MethodBody { get { if (!methodBody_isInitialized) { InitializeMethodBody(); } return methodBody; } set { theLock.EnterWriteLock(); try { methodBody = value; methodBody_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } protected virtual bool CanFreeMethodBody => true; public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public int HasCustomDebugInformationTag => 0; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public IList Overrides { get { if (overrides == null) { InitializeOverrides(); } return overrides; } } public MethodExportInfo ExportInfo { get { return exportInfo; } set { exportInfo = value; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public bool HasDeclSecurities => DeclSecurities.Count > 0; public bool HasParamDefs => ParamDefs.Count > 0; public TypeDef DeclaringType { get { return declaringType2; } set { TypeDef typeDef = DeclaringType2; if (typeDef != value) { typeDef?.Methods.Remove(this); value?.Methods.Add(this); } } } ITypeDefOrRef IMemberRef.DeclaringType => declaringType2; public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } public ModuleDef Module => declaringType2?.Module; bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => true; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => true; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public CilBody Body { get { if (!methodBody_isInitialized) { InitializeMethodBody(); } return methodBody as CilBody; } set { MethodBody = value; } } public NativeMethodBody NativeBody { get { if (!methodBody_isInitialized) { InitializeMethodBody(); } return methodBody as NativeMethodBody; } set { MethodBody = value; } } public bool HasGenericParameters => GenericParameters.Count > 0; public bool HasBody => Body != null; public bool HasOverrides => Overrides.Count > 0; public bool HasImplMap => ImplMap != null; public string FullName => FullNameFactory.MethodFullName(declaringType2?.FullName, name, MethodSig, null, null, this); public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } public ParameterList Parameters => parameterList; int IGenericParameterProvider.NumberOfGenericParameters => (int)(MethodSig?.GenParamCount ?? 0); public bool HasThis => MethodSig?.HasThis ?? false; public bool ExplicitThis => MethodSig?.ExplicitThis ?? false; public CallingConvention CallingConvention { get { MethodSig methodSig = MethodSig; if (methodSig != null) { return methodSig.CallingConvention & CallingConvention.Mask; } return CallingConvention.Default; } } public TypeSig ReturnType { get { return MethodSig?.RetType; } set { parameterList.ReturnParameter.Type = value; } } public bool HasReturnType => ReturnType.RemovePinnedAndModifiers().GetElementType() != ElementType.Void; public MethodSemanticsAttributes SemanticsAttributes { get { if ((semAttrs & SEMATTRS_INITD) == 0) { InitializeSemanticsAttributes(); } return (MethodSemanticsAttributes)semAttrs; } set { semAttrs = (int)value | SEMATTRS_INITD; } } public MethodAttributes Access { get { return (MethodAttributes)((ushort)attributes & 7); } set { ModifyAttributes(~MethodAttributes.MemberAccessMask, value & MethodAttributes.MemberAccessMask); } } public bool IsCompilerControlled => IsPrivateScope; public bool IsPrivateScope => ((ushort)attributes & 7) == 0; public bool IsPrivate => ((ushort)attributes & 7) == 1; public bool IsFamilyAndAssembly => ((ushort)attributes & 7) == 2; public bool IsAssembly => ((ushort)attributes & 7) == 3; public bool IsFamily => ((ushort)attributes & 7) == 4; public bool IsFamilyOrAssembly => ((ushort)attributes & 7) == 5; public bool IsPublic => ((ushort)attributes & 7) == 6; public bool IsStatic { get { return ((ushort)attributes & 0x10) != 0; } set { ModifyAttributes(value, MethodAttributes.Static); } } public bool IsFinal { get { return ((ushort)attributes & 0x20) != 0; } set { ModifyAttributes(value, MethodAttributes.Final); } } public bool IsVirtual { get { return ((ushort)attributes & 0x40) != 0; } set { ModifyAttributes(value, MethodAttributes.Virtual); } } public bool IsHideBySig { get { return ((ushort)attributes & 0x80) != 0; } set { ModifyAttributes(value, MethodAttributes.HideBySig); } } public bool IsNewSlot { get { return ((ushort)attributes & 0x100) != 0; } set { ModifyAttributes(value, MethodAttributes.VtableLayoutMask); } } public bool IsReuseSlot { get { return ((ushort)attributes & 0x100) == 0; } set { ModifyAttributes(!value, MethodAttributes.VtableLayoutMask); } } public bool IsCheckAccessOnOverride { get { return ((ushort)attributes & 0x200) != 0; } set { ModifyAttributes(value, MethodAttributes.CheckAccessOnOverride); } } public bool IsAbstract { get { return ((ushort)attributes & 0x400) != 0; } set { ModifyAttributes(value, MethodAttributes.Abstract); } } public bool IsSpecialName { get { return ((ushort)attributes & 0x800) != 0; } set { ModifyAttributes(value, MethodAttributes.SpecialName); } } public bool IsPinvokeImpl { get { return ((ushort)attributes & 0x2000) != 0; } set { ModifyAttributes(value, MethodAttributes.PinvokeImpl); } } public bool IsUnmanagedExport { get { return ((ushort)attributes & 8) != 0; } set { ModifyAttributes(value, MethodAttributes.UnmanagedExport); } } public bool IsRuntimeSpecialName { get { return ((ushort)attributes & 0x1000) != 0; } set { ModifyAttributes(value, MethodAttributes.RTSpecialName); } } public bool HasSecurity { get { return ((ushort)attributes & 0x4000) != 0; } set { ModifyAttributes(value, MethodAttributes.HasSecurity); } } public bool IsRequireSecObject { get { return ((ushort)attributes & 0x8000) != 0; } set { ModifyAttributes(value, MethodAttributes.RequireSecObject); } } public MethodImplAttributes CodeType { get { return (MethodImplAttributes)((ushort)implAttributes & 3); } set { ModifyImplAttributes(~MethodImplAttributes.CodeTypeMask, value & MethodImplAttributes.CodeTypeMask); } } public bool IsIL => ((ushort)implAttributes & 3) == 0; public bool IsNative => ((ushort)implAttributes & 3) == 1; public bool IsOPTIL => ((ushort)implAttributes & 3) == 2; public bool IsRuntime => ((ushort)implAttributes & 3) == 3; public bool IsUnmanaged { get { return ((ushort)implAttributes & 4) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.ManagedMask); } } public bool IsManaged { get { return ((ushort)implAttributes & 4) == 0; } set { ModifyImplAttributes(!value, MethodImplAttributes.ManagedMask); } } public bool IsForwardRef { get { return ((ushort)implAttributes & 0x10) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.ForwardRef); } } public bool IsPreserveSig { get { return ((ushort)implAttributes & 0x80) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.PreserveSig); } } public bool IsInternalCall { get { return ((ushort)implAttributes & 0x1000) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.InternalCall); } } public bool IsSynchronized { get { return ((ushort)implAttributes & 0x20) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.Synchronized); } } public bool IsNoInlining { get { return ((ushort)implAttributes & 8) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.NoInlining); } } public bool IsAggressiveInlining { get { return ((ushort)implAttributes & 0x100) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.AggressiveInlining); } } public bool IsNoOptimization { get { return ((ushort)implAttributes & 0x40) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.NoOptimization); } } public bool IsAggressiveOptimization { get { return ((ushort)implAttributes & 0x200) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.AggressiveOptimization); } } public bool HasSecurityMitigations { get { return ((ushort)implAttributes & 0x400) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.SecurityMitigations); } } public bool IsSetter { get { return (SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Setter); } } public bool IsGetter { get { return (SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Getter); } } public bool IsOther { get { return (SemanticsAttributes & MethodSemanticsAttributes.Other) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Other); } } public bool IsAddOn { get { return (SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.AddOn); } } public bool IsRemoveOn { get { return (SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.RemoveOn); } } public bool IsFire { get { return (SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Fire); } } public bool IsStaticConstructor { get { if (IsRuntimeSpecialName) { return UTF8String.Equals(name, StaticConstructorName); } return false; } } public bool IsInstanceConstructor { get { if (IsRuntimeSpecialName) { return UTF8String.Equals(name, InstanceConstructorName); } return false; } } public bool IsConstructor { get { if (!IsStaticConstructor) { return IsInstanceConstructor; } return true; } } protected virtual void InitializeParamDefs() { Interlocked.CompareExchange(ref paramDefs, new LazyList(this), null); } protected virtual void InitializeGenericParameters() { Interlocked.CompareExchange(ref genericParameters, new LazyList(this), null); } protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, new List(), null); } private void InitializeImplMap() { theLock.EnterWriteLock(); try { if (!implMap_isInitialized) { implMap = GetImplMap_NoLock(); implMap_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual ImplMap GetImplMap_NoLock() { return null; } protected void ResetImplMap() { implMap_isInitialized = false; } private void InitializeMethodBody() { theLock.EnterWriteLock(); try { if (!methodBody_isInitialized) { methodBody = GetMethodBody_NoLock(); methodBody_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } public void FreeMethodBody() { if (!CanFreeMethodBody || !methodBody_isInitialized) { return; } theLock.EnterWriteLock(); try { methodBody = null; methodBody_isInitialized = false; } finally { theLock.ExitWriteLock(); } } protected virtual dnlib.DotNet.Emit.MethodBody GetMethodBody_NoLock() { return null; } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } protected virtual void InitializeOverrides() { Interlocked.CompareExchange(ref overrides, new List(), null); } protected virtual void InitializeSemanticsAttributes() { semAttrs = 0 | SEMATTRS_INITD; } private void ModifyAttributes(bool set, MethodSemanticsAttributes flags) { if ((semAttrs & SEMATTRS_INITD) == 0) { InitializeSemanticsAttributes(); } if (set) { semAttrs |= (int)flags; } else { semAttrs &= (int)(~(uint)flags); } } private void ModifyAttributes(MethodAttributes andMask, MethodAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, MethodAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } private void ModifyImplAttributes(MethodImplAttributes andMask, MethodImplAttributes orMask) { implAttributes = (int)((uint)implAttributes & (uint)andMask) | (int)orMask; } private void ModifyImplAttributes(bool set, MethodImplAttributes flags) { if (set) { implAttributes |= (int)flags; } else { implAttributes &= (int)(~(uint)flags); } } void IListListener.OnLazyAdd(int index, ref GenericParam value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParam value) { } void IListListener.OnAdd(int index, GenericParam value) { if (value.Owner != null) { throw new InvalidOperationException("Generic param is already owned by another type/method. Set Owner to null first."); } value.Owner = this; } void IListListener.OnRemove(int index, GenericParam value) { value.Owner = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (GenericParam item in genericParameters.GetEnumerable_NoLock()) { item.Owner = null; } } void IListListener.OnLazyAdd(int index, ref ParamDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref ParamDef value) { } void IListListener.OnAdd(int index, ParamDef value) { if (value.DeclaringMethod != null) { throw new InvalidOperationException("Param is already owned by another method. Set DeclaringMethod to null first."); } value.DeclaringMethod = this; } void IListListener.OnRemove(int index, ParamDef value) { value.DeclaringMethod = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (ParamDef item in paramDefs.GetEnumerable_NoLock()) { item.DeclaringMethod = null; } } public override string ToString() { return FullName; } } public class MethodDefUser : MethodDef { public MethodDefUser() { paramDefs = new LazyList(this); genericParameters = new LazyList(this); parameterList = new ParameterList(this, null); semAttrs = 0 | MethodDef.SEMATTRS_INITD; } public MethodDefUser(UTF8String name) : this(name, null, MethodImplAttributes.IL, MethodAttributes.PrivateScope) { } public MethodDefUser(UTF8String name, MethodSig methodSig) : this(name, methodSig, MethodImplAttributes.IL, MethodAttributes.PrivateScope) { } public MethodDefUser(UTF8String name, MethodSig methodSig, MethodAttributes flags) : this(name, methodSig, MethodImplAttributes.IL, flags) { } public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags) : this(name, methodSig, implFlags, MethodAttributes.PrivateScope) { } public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags, MethodAttributes flags) { base.name = name; signature = methodSig; paramDefs = new LazyList(this); genericParameters = new LazyList(this); implAttributes = (int)implFlags; attributes = (int)flags; parameterList = new ParameterList(this, null); semAttrs = 0 | MethodDef.SEMATTRS_INITD; } } internal sealed class MethodDefMD : MethodDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly RVA origRva; private readonly MethodImplAttributes origImplAttributes; public uint OrigRid => origRid; protected override void InitializeParamDefs() { RidList paramRidList = readerModule.Metadata.GetParamRidList(origRid); LazyList value = new LazyList(paramRidList.Count, this, paramRidList, (RidList list2, int index) => readerModule.ResolveParam(list2[index])); Interlocked.CompareExchange(ref paramDefs, value, null); } protected override void InitializeGenericParameters() { RidList genericParamRidList = readerModule.Metadata.GetGenericParamRidList(Table.Method, origRid); LazyList value = new LazyList(genericParamRidList.Count, this, genericParamRidList, (RidList list2, int index) => readerModule.ResolveGenericParam(list2[index])); Interlocked.CompareExchange(ref genericParameters, value, null); } protected override void InitializeDeclSecurities() { RidList declSecurityRidList = readerModule.Metadata.GetDeclSecurityRidList(Table.Method, origRid); LazyList value = new LazyList(declSecurityRidList.Count, declSecurityRidList, (RidList list2, int index) => readerModule.ResolveDeclSecurity(list2[index])); Interlocked.CompareExchange(ref declSecurities, value, null); } protected override ImplMap GetImplMap_NoLock() { return readerModule.ResolveImplMap(readerModule.Metadata.GetImplMapRid(Table.Method, origRid)); } protected override dnlib.DotNet.Emit.MethodBody GetMethodBody_NoLock() { return readerModule.ReadMethodBody(this, origRva, origImplAttributes, new GenericParamContext(declaringType2, this)); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Method, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List value = new List(); if (Interlocked.CompareExchange(ref customDebugInfos, value, null) == null) { CilBody body = base.Body; readerModule.InitializeCustomDebugInfos(this, body, value); } } protected override void InitializeOverrides() { IList list; if (declaringType2 is TypeDefMD typeDefMD) { list = typeDefMD.GetMethodOverrides(this, new GenericParamContext(declaringType2, this)); } else { IList list2 = new List(); list = list2; } IList value = list; Interlocked.CompareExchange(ref overrides, value, null); } protected override void InitializeSemanticsAttributes() { if (base.DeclaringType is TypeDefMD typeDefMD) { typeDefMD.InitializeMethodSemanticsAttributes(); } semAttrs |= MethodDef.SEMATTRS_INITD; } public MethodDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadMethodRow(origRid, out var row); rva = (RVA)row.RVA; implAttributes = row.ImplFlags; attributes = row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); origRva = rva; origImplAttributes = (MethodImplAttributes)implAttributes; declaringType2 = readerModule.GetOwnerType(this); signature = readerModule.ReadSignature(row.Signature, new GenericParamContext(declaringType2, this)); parameterList = new ParameterList(this, declaringType2); exportInfo = readerModule.GetExportInfo(rid); } internal MethodDefMD InitializeAll() { MemberMDInitializer.Initialize(base.RVA); MemberMDInitializer.Initialize(base.Attributes); MemberMDInitializer.Initialize(base.ImplAttributes); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.Signature); MemberMDInitializer.Initialize(base.ImplMap); MemberMDInitializer.Initialize(base.MethodBody); MemberMDInitializer.Initialize(base.DeclaringType); MemberMDInitializer.Initialize(base.CustomAttributes); MemberMDInitializer.Initialize(base.Overrides); MemberMDInitializer.Initialize(base.ParamDefs); MemberMDInitializer.Initialize(base.GenericParameters); MemberMDInitializer.Initialize(base.DeclSecurities); return this; } internal override void OnLazyAdd2(int index, ref GenericParam value) { if (value.Owner != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParam(value.Rid).InitializeAll()); value.Owner = this; } } internal override void OnLazyAdd2(int index, ref ParamDef value) { if (value.DeclaringMethod != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadParam(value.Rid).InitializeAll()); value.DeclaringMethod = this; } } } [DebuggerDisplay("{Ordinal} {Name} {Options}")] public sealed class MethodExportInfo { private MethodExportInfoOptions options; private ushort? ordinal; private string name; private const MethodExportInfoOptions DefaultOptions = MethodExportInfoOptions.FromUnmanaged; public ushort? Ordinal { get { return ordinal; } set { ordinal = value; } } public string Name { get { return name; } set { name = value; } } public MethodExportInfoOptions Options { get { return options; } set { options = value; } } public MethodExportInfo() { options = MethodExportInfoOptions.FromUnmanaged; } public MethodExportInfo(string name) { options = MethodExportInfoOptions.FromUnmanaged; this.name = name; } public MethodExportInfo(ushort ordinal) { options = MethodExportInfoOptions.FromUnmanaged; this.ordinal = ordinal; } public MethodExportInfo(string name, ushort? ordinal) { options = MethodExportInfoOptions.FromUnmanaged; this.name = name; this.ordinal = ordinal; } public MethodExportInfo(string name, ushort? ordinal, MethodExportInfoOptions options) { this.options = options; this.name = name; this.ordinal = ordinal; } } [Flags] public enum MethodExportInfoOptions { None = 0, FromUnmanaged = 1, FromUnmanagedRetainAppDomain = 2, CallMostDerived = 4 } internal sealed class MethodExportInfoProvider { private struct NameAndIndex { public string Name; public int Index; } private readonly Dictionary toInfo; public MethodExportInfoProvider(ModuleDefMD module) { toInfo = new Dictionary(); try { Initialize(module); } catch (OutOfMemoryException) { } catch (IOException) { } } private void Initialize(ModuleDefMD module) { ImageDataDirectory vTableFixups = module.Metadata.ImageCor20Header.VTableFixups; if (vTableFixups.VirtualAddress == (RVA)0u || vTableFixups.Size == 0) { return; } IPEImage pEImage = module.Metadata.PEImage; ImageDataDirectory imageDataDirectory = pEImage.ImageNTHeaders.OptionalHeader.DataDirectories[0]; if (imageDataDirectory.VirtualAddress == (RVA)0u || imageDataDirectory.Size < 40 || !CpuArch.TryGetCpuArch(pEImage.ImageNTHeaders.FileHeader.Machine, out var cpuArch)) { return; } DataReader reader = pEImage.CreateReader(); Dictionary offsetToExportInfoDictionary = GetOffsetToExportInfoDictionary(ref reader, pEImage, imageDataDirectory, cpuArch); reader.Position = (uint)pEImage.ToFileOffset(vTableFixups.VirtualAddress); ulong num = (ulong)reader.Position + (ulong)vTableFixups.Size; while ((ulong)((long)reader.Position + 8L) <= num && reader.CanRead(8u)) { RVA rva = (RVA)reader.ReadUInt32(); int num2 = reader.ReadUInt16(); ushort num3 = reader.ReadUInt16(); bool flag = (num3 & 2) != 0; MethodExportInfoOptions options = ToMethodExportInfoOptions((VTableFlags)num3); uint position = reader.Position; reader.Position = (uint)pEImage.ToFileOffset(rva); uint num4 = (flag ? 8u : 4u); while (num2-- > 0 && reader.CanRead(num4)) { uint position2 = reader.Position; uint key = reader.ReadUInt32(); if (offsetToExportInfoDictionary.TryGetValue(position2, out var value)) { toInfo[key] = new MethodExportInfo(value.Name, value.Ordinal, options); } if (num4 == 8) { reader.ReadUInt32(); } } reader.Position = position; } } private static MethodExportInfoOptions ToMethodExportInfoOptions(VTableFlags flags) { MethodExportInfoOptions methodExportInfoOptions = MethodExportInfoOptions.None; if ((flags & VTableFlags.FromUnmanaged) != 0) { methodExportInfoOptions |= MethodExportInfoOptions.FromUnmanaged; } if ((flags & VTableFlags.FromUnmanagedRetainAppDomain) != 0) { methodExportInfoOptions |= MethodExportInfoOptions.FromUnmanagedRetainAppDomain; } if ((flags & VTableFlags.CallMostDerived) != 0) { methodExportInfoOptions |= MethodExportInfoOptions.CallMostDerived; } return methodExportInfoOptions; } private static Dictionary GetOffsetToExportInfoDictionary(ref DataReader reader, IPEImage peImage, ImageDataDirectory exportHdr, CpuArch cpuArch) { reader.Position = (uint)peImage.ToFileOffset(exportHdr.VirtualAddress); reader.Position += 16u; uint num = reader.ReadUInt32(); int num2 = reader.ReadInt32(); int numNames = reader.ReadInt32(); uint position = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32()); uint offsetOfNames = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32()); uint offsetOfNameIndexes = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32()); NameAndIndex[] array = ReadNames(ref reader, peImage, numNames, offsetOfNames, offsetOfNameIndexes); reader.Position = position; MethodExportInfo[] array2 = new MethodExportInfo[num2]; Dictionary dictionary = new Dictionary(num2); for (int i = 0; i < array2.Length; i++) { uint position2 = reader.Position + 4; uint funcRva = 0u; RVA rVA = (RVA)reader.ReadUInt32(); reader.Position = (uint)peImage.ToFileOffset(rVA); uint num3 = (uint)((rVA != 0 && cpuArch.TryGetExportedRvaFromStub(ref reader, peImage, out funcRva)) ? peImage.ToFileOffset((RVA)funcRva) : ((FileOffset)0u)); MethodExportInfo methodExportInfo = new MethodExportInfo((ushort)(num + (uint)i)); if (num3 != 0) { dictionary[num3] = methodExportInfo; } array2[i] = methodExportInfo; reader.Position = position2; } NameAndIndex[] array3 = array; for (int j = 0; j < array3.Length; j++) { NameAndIndex nameAndIndex = array3[j]; int index = nameAndIndex.Index; if ((uint)index < (uint)num2) { array2[index].Ordinal = null; array2[index].Name = nameAndIndex.Name; } } return dictionary; } private static NameAndIndex[] ReadNames(ref DataReader reader, IPEImage peImage, int numNames, uint offsetOfNames, uint offsetOfNameIndexes) { NameAndIndex[] array = new NameAndIndex[numNames]; reader.Position = offsetOfNameIndexes; for (int i = 0; i < array.Length; i++) { array[i].Index = reader.ReadUInt16(); } uint num = offsetOfNames; int num2 = 0; while (num2 < array.Length) { reader.Position = num; uint offset = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32()); array[num2].Name = ReadMethodNameASCIIZ(ref reader, offset); num2++; num += 4; } return array; } private static string ReadMethodNameASCIIZ(ref DataReader reader, uint offset) { reader.Position = offset; return reader.TryReadZeroTerminatedUtf8String() ?? string.Empty; } public MethodExportInfo GetMethodExportInfo(uint token) { if (toInfo.Count == 0) { return null; } if (toInfo.TryGetValue(token, out var value)) { return new MethodExportInfo(value.Name, value.Ordinal, value.Options); } return null; } } [Flags] public enum MethodImplAttributes : ushort { CodeTypeMask = 3, IL = 0, Native = 1, OPTIL = 2, Runtime = 3, ManagedMask = 4, Unmanaged = 4, Managed = 0, ForwardRef = 0x10, PreserveSig = 0x80, InternalCall = 0x1000, Synchronized = 0x20, NoInlining = 8, AggressiveInlining = 0x100, NoOptimization = 0x40, AggressiveOptimization = 0x200, SecurityMitigations = 0x400 } public struct MethodOverride { public IMethodDefOrRef MethodBody; public IMethodDefOrRef MethodDeclaration; public MethodOverride(IMethodDefOrRef methodBody, IMethodDefOrRef methodDeclaration) { MethodBody = methodBody; MethodDeclaration = methodDeclaration; } } [Flags] public enum MethodSemanticsAttributes : ushort { None = 0, Setter = 1, Getter = 2, Other = 4, AddOn = 8, RemoveOn = 0x10, Fire = 0x20 } public abstract class MethodSpec : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation, IMethod, ITokenOperand, IFullName, IGenericParameterProvider, IIsTypeOrMethod, IMemberRef, IOwnerModule, IContainsGenericParameter { protected uint rid; protected IMethodDefOrRef method; protected CallingConventionSig instantiation; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.MethodSpec, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 21; public IMethodDefOrRef Method { get { return method; } set { method = value; } } public CallingConventionSig Instantiation { get { return instantiation; } set { instantiation = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 21; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } MethodSig IMethod.MethodSig { get { return method?.MethodSig; } set { IMethodDefOrRef methodDefOrRef = method; if (methodDefOrRef != null) { methodDefOrRef.MethodSig = value; } } } public UTF8String Name { get { IMethodDefOrRef methodDefOrRef = method; if (methodDefOrRef != null) { return methodDefOrRef.Name; } return UTF8String.Empty; } set { IMethodDefOrRef methodDefOrRef = method; if (methodDefOrRef != null) { methodDefOrRef.Name = value; } } } public ITypeDefOrRef DeclaringType => method?.DeclaringType; public GenericInstMethodSig GenericInstMethodSig { get { return instantiation as GenericInstMethodSig; } set { instantiation = value; } } int IGenericParameterProvider.NumberOfGenericParameters => GenericInstMethodSig?.GenericArguments.Count ?? 0; public ModuleDef Module => method?.Module; public string FullName { get { IList methodGenArgs = GenericInstMethodSig?.GenericArguments; IMethodDefOrRef methodDefOrRef = method; if (methodDefOrRef is MethodDef methodDef) { return FullNameFactory.MethodFullName(methodDef.DeclaringType?.FullName, methodDef.Name, methodDef.MethodSig, null, methodGenArgs); } if (methodDefOrRef is MemberRef { MethodSig: { } methodSig } memberRef) { IList typeGenArgs = ((memberRef.Class as TypeSpec)?.TypeSig as GenericInstSig)?.GenericArguments; return FullNameFactory.MethodFullName(memberRef.GetDeclaringTypeFullName(), memberRef.Name, methodSig, typeGenArgs, methodGenArgs); } return string.Empty; } } bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => true; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => true; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; bool IContainsGenericParameter.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } public override string ToString() { return FullName; } } public class MethodSpecUser : MethodSpec { public MethodSpecUser() { } public MethodSpecUser(IMethodDefOrRef method) : this(method, null) { } public MethodSpecUser(IMethodDefOrRef method, GenericInstMethodSig sig) { base.method = method; instantiation = sig; } } internal sealed class MethodSpecMD : MethodSpec, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; public uint OrigRid => origRid; bool IContainsGenericParameter2.ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.MethodSpec, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public MethodSpecMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; readerModule.TablesStream.TryReadMethodSpecRow(origRid, out var row); method = readerModule.ResolveMethodDefOrRef(row.Method, gpContext); instantiation = readerModule.ReadSignature(row.Instantiation, gpContext); } } public class ModuleContext { private IAssemblyResolver assemblyResolver; private IResolver resolver; private readonly dnlib.DotNet.Emit.OpCode[][] experimentalOpCodes = new dnlib.DotNet.Emit.OpCode[12][]; public IAssemblyResolver AssemblyResolver { get { if (assemblyResolver == null) { Interlocked.CompareExchange(ref assemblyResolver, NullResolver.Instance, null); } return assemblyResolver; } set { assemblyResolver = value; } } public IResolver Resolver { get { if (resolver == null) { Interlocked.CompareExchange(ref resolver, NullResolver.Instance, null); } return resolver; } set { resolver = value; } } public ModuleContext() { } public ModuleContext(IAssemblyResolver assemblyResolver) : this(assemblyResolver, new Resolver(assemblyResolver)) { } public ModuleContext(IResolver resolver) : this(null, resolver) { } public ModuleContext(IAssemblyResolver assemblyResolver, IResolver resolver) { this.assemblyResolver = assemblyResolver; this.resolver = resolver; if (resolver == null && assemblyResolver != null) { this.resolver = new Resolver(assemblyResolver); } } public void RegisterExperimentalOpCode(dnlib.DotNet.Emit.OpCode opCode) { byte num = (byte)((ushort)opCode.Value >> 8); byte b = (byte)opCode.Value; dnlib.DotNet.Emit.OpCode[][] array = experimentalOpCodes; int num2 = num - 240; (array[num2] ?? (array[num2] = new dnlib.DotNet.Emit.OpCode[256]))[b] = opCode; } public void ClearExperimentalOpCode(byte high, byte low) { dnlib.DotNet.Emit.OpCode[] array = experimentalOpCodes[high - 240]; if (array != null) { array[low] = null; } } public dnlib.DotNet.Emit.OpCode GetExperimentalOpCode(byte high, byte low) { dnlib.DotNet.Emit.OpCode[] obj = experimentalOpCodes[high - 240]; if (obj == null) { return null; } return obj[low]; } } public sealed class ModuleCreationOptions { internal static readonly ModuleCreationOptions Default = new ModuleCreationOptions(); internal const PdbReaderOptions DefaultPdbReaderOptions = PdbReaderOptions.None; public ModuleContext Context { get; set; } public PdbReaderOptions PdbOptions { get; set; } public object PdbFileOrData { get; set; } public bool TryToLoadPdbFromDisk { get; set; } = true; public AssemblyRef CorLibAssemblyRef { get; set; } public CLRRuntimeReaderKind Runtime { get; set; } public ModuleCreationOptions() { } public ModuleCreationOptions(ModuleContext context) { Context = context; } public ModuleCreationOptions(CLRRuntimeReaderKind runtime) { Runtime = runtime; } public ModuleCreationOptions(ModuleContext context, CLRRuntimeReaderKind runtime) { Context = context; Runtime = runtime; } } public enum CLRRuntimeReaderKind { CLR, Mono } public abstract class ModuleDef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation, IResolutionScope, IFullName, IDisposable, IListListener, IModule, IScope, ITypeDefFinder, IDnlibDef, ITokenResolver, ISignatureReaderHelper { protected const Characteristics DefaultCharacteristics = Characteristics.ExecutableImage | Characteristics.Bit32Machine; protected const DllCharacteristics DefaultDllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompat | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware; protected uint rid; private readonly Lock theLock = Lock.Create(); protected ICorLibTypes corLibTypes; protected PdbState pdbState; private TypeDefFinder typeDefFinder; protected readonly int[] lastUsedRids = new int[64]; protected ModuleContext context; private object tag; protected ushort generation; protected UTF8String name; protected Guid? mvid; protected Guid? encId; protected Guid? encBaseId; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected AssemblyDef assembly; protected LazyList types; protected IList exportedTypes; protected RVA nativeEntryPoint; protected IManagedEntryPoint managedEntryPoint; protected bool nativeAndManagedEntryPoint_initialized; protected ResourceCollection resources; protected VTableFixups vtableFixups; protected bool vtableFixups_isInitialized; protected string location; protected Win32Resources win32Resources; protected bool win32Resources_isInitialized; private string runtimeVersion; private WinMDStatus? cachedWinMDStatus; private string runtimeVersionWinMD; private string winMDVersion; protected int cor20HeaderFlags; public MDToken MDToken => new MDToken(Table.Module, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 7; public int ResolutionScopeTag => 0; public object Tag { get { return tag; } set { tag = value; } } public ScopeType ScopeType => ScopeType.ModuleDef; public string ScopeName => FullName; public ushort Generation { get { return generation; } set { generation = value; } } public UTF8String Name { get { return name; } set { name = value; } } public Guid? Mvid { get { return mvid; } set { mvid = value; } } public Guid? EncId { get { return encId; } set { encId = value; } } public Guid? EncBaseId { get { return encBaseId; } set { encBaseId = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public int HasCustomDebugInformationTag => 7; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public AssemblyDef Assembly { get { return assembly; } internal set { assembly = value; } } public IList Types { get { if (types == null) { InitializeTypes(); } return types; } } public IList ExportedTypes { get { if (exportedTypes == null) { InitializeExportedTypes(); } return exportedTypes; } } public RVA NativeEntryPoint { get { if (!nativeAndManagedEntryPoint_initialized) { InitializeNativeAndManagedEntryPoint(); } return nativeEntryPoint; } set { theLock.EnterWriteLock(); try { nativeEntryPoint = value; managedEntryPoint = null; Cor20HeaderFlags |= ComImageFlags.NativeEntryPoint; nativeAndManagedEntryPoint_initialized = true; } finally { theLock.ExitWriteLock(); } } } public IManagedEntryPoint ManagedEntryPoint { get { if (!nativeAndManagedEntryPoint_initialized) { InitializeNativeAndManagedEntryPoint(); } return managedEntryPoint; } set { theLock.EnterWriteLock(); try { nativeEntryPoint = (RVA)0u; managedEntryPoint = value; Cor20HeaderFlags &= ~ComImageFlags.NativeEntryPoint; nativeAndManagedEntryPoint_initialized = true; } finally { theLock.ExitWriteLock(); } } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public MethodDef EntryPoint { get { return ManagedEntryPoint as MethodDef; } set { ManagedEntryPoint = value; } } public bool IsNativeEntryPointValid => NativeEntryPoint != (RVA)0u; public bool IsManagedEntryPointValid => ManagedEntryPoint != null; public bool IsEntryPointValid => EntryPoint != null; public ResourceCollection Resources { get { if (resources == null) { InitializeResources(); } return resources; } } public VTableFixups VTableFixups { get { if (!vtableFixups_isInitialized) { InitializeVTableFixups(); } return vtableFixups; } set { theLock.EnterWriteLock(); try { vtableFixups = value; vtableFixups_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public bool HasTypes => Types.Count > 0; public bool HasExportedTypes => ExportedTypes.Count > 0; public bool HasResources => Resources.Count > 0; public string FullName => UTF8String.ToSystemStringOrEmpty(name); public string Location { get { return location; } set { location = value; } } public ICorLibTypes CorLibTypes => corLibTypes; private TypeDefFinder TypeDefFinder { get { if (typeDefFinder == null) { Interlocked.CompareExchange(ref typeDefFinder, new TypeDefFinder(Types), null); } return typeDefFinder; } } public ModuleContext Context { get { if (context == null) { Interlocked.CompareExchange(ref context, new ModuleContext(), null); } return context; } set { context = value ?? new ModuleContext(); } } public bool EnableTypeDefFindCache { get { return TypeDefFinder.IsCacheEnabled; } set { TypeDefFinder.IsCacheEnabled = value; } } public bool IsManifestModule { get { AssemblyDef assemblyDef = assembly; if (assemblyDef != null) { return assemblyDef.ManifestModule == this; } return false; } } public TypeDef GlobalType { get { if (Types.Count != 0) { return Types[0]; } return null; } } public bool? IsCoreLibraryModule { get; set; } public Win32Resources Win32Resources { get { if (!win32Resources_isInitialized) { InitializeWin32Resources(); } return win32Resources; } set { theLock.EnterWriteLock(); try { win32Resources = value; win32Resources_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public PdbState PdbState => pdbState; public ModuleKind Kind { get; set; } public Characteristics Characteristics { get; set; } public DllCharacteristics DllCharacteristics { get; set; } public string RuntimeVersion { get { return runtimeVersion; } set { if (runtimeVersion != value) { runtimeVersion = value; cachedWinMDStatus = null; runtimeVersionWinMD = null; winMDVersion = null; } } } public WinMDStatus WinMDStatus { get { WinMDStatus? winMDStatus = cachedWinMDStatus; if (winMDStatus.HasValue) { return winMDStatus.Value; } winMDStatus = (cachedWinMDStatus = CalculateWinMDStatus(RuntimeVersion)); return winMDStatus.Value; } } public bool IsWinMD => WinMDStatus != WinMDStatus.None; public bool IsManagedWinMD => WinMDStatus == WinMDStatus.Managed; public bool IsPureWinMD => WinMDStatus == WinMDStatus.Pure; public string RuntimeVersionWinMD { get { string text = runtimeVersionWinMD; if (text != null) { return text; } return runtimeVersionWinMD = CalculateRuntimeVersionWinMD(RuntimeVersion); } } public string WinMDVersion { get { string text = winMDVersion; if (text != null) { return text; } return winMDVersion = CalculateWinMDVersion(RuntimeVersion); } } public bool IsClr10 { get { string text = RuntimeVersion ?? string.Empty; if (!text.StartsWith("v1.0") && !text.StartsWith("v1.x86") && !(text == "retail")) { return text == "COMPLUS"; } return true; } } public bool IsClr10Exactly { get { if (!(RuntimeVersion == "v1.0.3705") && !(RuntimeVersion == "v1.x86ret") && !(RuntimeVersion == "retail")) { return RuntimeVersion == "COMPLUS"; } return true; } } public bool IsClr11 => (RuntimeVersion ?? string.Empty).StartsWith("v1.1"); public bool IsClr11Exactly => RuntimeVersion == "v1.1.4322"; public bool IsClr1x { get { if (!IsClr10) { return IsClr11; } return true; } } public bool IsClr1xExactly { get { if (!IsClr10Exactly) { return IsClr11Exactly; } return true; } } public bool IsClr20 => (RuntimeVersion ?? string.Empty).StartsWith("v2.0"); public bool IsClr20Exactly => RuntimeVersion == "v2.0.50727"; public bool IsClr40 => (RuntimeVersion ?? string.Empty).StartsWith("v4.0"); public bool IsClr40Exactly => RuntimeVersion == "v4.0.30319"; public bool IsEcma2002 => RuntimeVersion == "Standard CLI 2002"; public bool IsEcma2005 => RuntimeVersion == "Standard CLI 2005"; public Machine Machine { get; set; } public bool IsI386 => Machine.IsI386(); public bool IsIA64 => Machine == Machine.IA64; public bool IsAMD64 => Machine.IsAMD64(); public bool IsARM => Machine.IsARMNT(); public bool IsARM64 => Machine.IsARM64(); public bool IsS390x => Machine.IsS390x(); public ComImageFlags Cor20HeaderFlags { get { return (ComImageFlags)cor20HeaderFlags; } set { cor20HeaderFlags = (int)value; } } public uint? Cor20HeaderRuntimeVersion { get; set; } public ushort? TablesHeaderVersion { get; set; } public bool IsILOnly { get { return (cor20HeaderFlags & 1) != 0; } set { ModifyComImageFlags(value, ComImageFlags.ILOnly); } } public bool Is32BitRequired { get { return (cor20HeaderFlags & 2) != 0; } set { ModifyComImageFlags(value, ComImageFlags.Bit32Required); } } public bool IsStrongNameSigned { get { return (cor20HeaderFlags & 8) != 0; } set { ModifyComImageFlags(value, ComImageFlags.StrongNameSigned); } } public bool HasNativeEntryPoint { get { return (cor20HeaderFlags & 0x10) != 0; } set { ModifyComImageFlags(value, ComImageFlags.NativeEntryPoint); } } public bool Is32BitPreferred { get { return (cor20HeaderFlags & 0x20000) != 0; } set { ModifyComImageFlags(value, ComImageFlags.Bit32Preferred); } } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } protected virtual void InitializeTypes() { Interlocked.CompareExchange(ref types, new LazyList(this), null); } protected virtual void InitializeExportedTypes() { Interlocked.CompareExchange(ref exportedTypes, new List(), null); } private void InitializeNativeAndManagedEntryPoint() { theLock.EnterWriteLock(); try { if (!nativeAndManagedEntryPoint_initialized) { nativeEntryPoint = GetNativeEntryPoint_NoLock(); managedEntryPoint = GetManagedEntryPoint_NoLock(); nativeAndManagedEntryPoint_initialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual RVA GetNativeEntryPoint_NoLock() { return (RVA)0u; } protected virtual IManagedEntryPoint GetManagedEntryPoint_NoLock() { return null; } protected virtual void InitializeResources() { Interlocked.CompareExchange(ref resources, new ResourceCollection(), null); } private void InitializeVTableFixups() { theLock.EnterWriteLock(); try { if (!vtableFixups_isInitialized) { vtableFixups = GetVTableFixups_NoLock(); vtableFixups_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual VTableFixups GetVTableFixups_NoLock() { return null; } private void InitializeWin32Resources() { theLock.EnterWriteLock(); try { if (!win32Resources_isInitialized) { win32Resources = GetWin32Resources_NoLock(); win32Resources_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual Win32Resources GetWin32Resources_NoLock() { return null; } private static WinMDStatus CalculateWinMDStatus(string version) { if (version == null) { return WinMDStatus.None; } if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) { return WinMDStatus.None; } if (version.IndexOf(';') >= 0) { return WinMDStatus.Managed; } return WinMDStatus.Pure; } private static string CalculateRuntimeVersionWinMD(string version) { if (version == null) { return null; } if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) { return null; } int num = version.IndexOf(';'); if (num < 0) { return null; } string text = version.Substring(num + 1); if (text.StartsWith("CLR", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(3); } return text.TrimStart(' '); } private static string CalculateWinMDVersion(string version) { if (version == null) { return null; } if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) { return null; } int num = version.IndexOf(';'); if (num < 0) { return version; } return version.Substring(0, num); } private void ModifyComImageFlags(bool set, ComImageFlags flags) { int num; int value; do { num = cor20HeaderFlags; value = ((!set) ? (num & (int)(~flags)) : (num | (int)flags)); } while (Interlocked.CompareExchange(ref cor20HeaderFlags, value, num) != num); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { TypeDefFinder typeDefFinder = this.typeDefFinder; if (typeDefFinder != null) { typeDefFinder.Dispose(); this.typeDefFinder = null; } pdbState?.Dispose(); pdbState = null; } } public IEnumerable GetTypes() { return AllTypesHelper.Types(Types); } public void AddAsNonNestedType(TypeDef typeDef) { if (typeDef != null) { typeDef.DeclaringType = null; Types.Add(typeDef); } } public T UpdateRowId(T tableRow) where T : IMDTokenProvider { if (tableRow != null && tableRow.Rid == 0) { tableRow.Rid = GetNextFreeRid(tableRow.MDToken.Table); } return tableRow; } public T ForceUpdateRowId(T tableRow) where T : IMDTokenProvider { if (tableRow != null) { tableRow.Rid = GetNextFreeRid(tableRow.MDToken.Table); } return tableRow; } private uint GetNextFreeRid(Table table) { int[] array = lastUsedRids; if ((long)table >= (long)array.Length) { return 0u; } return (uint)(Interlocked.Increment(ref array[(uint)table]) & 0xFFFFFF); } public ITypeDefOrRef Import(Type type) { return new Importer(this).Import(type); } public TypeSig ImportAsTypeSig(Type type) { return new Importer(this).ImportAsTypeSig(type); } public MemberRef Import(FieldInfo fieldInfo) { return (MemberRef)new Importer(this).Import(fieldInfo); } public IMethod Import(MethodBase methodBase) { return new Importer(this).Import(methodBase); } public IType Import(IType type) { return new Importer(this).Import(type); } public TypeRef Import(TypeDef type) { return (TypeRef)new Importer(this).Import(type); } public TypeRef Import(TypeRef type) { return (TypeRef)new Importer(this).Import(type); } public TypeSpec Import(TypeSpec type) { return new Importer(this).Import(type); } public TypeSig Import(TypeSig type) { return new Importer(this).Import(type); } public MemberRef Import(IField field) { return (MemberRef)new Importer(this).Import(field); } public MemberRef Import(FieldDef field) { return (MemberRef)new Importer(this).Import(field); } public IMethod Import(IMethod method) { return new Importer(this).Import(method); } public MemberRef Import(MethodDef method) { return (MemberRef)new Importer(this).Import(method); } public MethodSpec Import(MethodSpec method) { return new Importer(this).Import(method); } public MemberRef Import(MemberRef memberRef) { return new Importer(this).Import(memberRef); } public void Write(string filename) { Write(filename, null); } public void Write(string filename, ModuleWriterOptions options) { new ModuleWriter(this, options ?? new ModuleWriterOptions(this)).Write(filename); } public void Write(Stream dest) { Write(dest, null); } public void Write(Stream dest, ModuleWriterOptions options) { new ModuleWriter(this, options ?? new ModuleWriterOptions(this)).Write(dest); } public void ResetTypeDefFindCache() { TypeDefFinder.ResetCache(); } public ResourceData FindWin32ResourceData(ResourceName type, ResourceName name, ResourceName langId) { return Win32Resources?.Find(type, name, langId); } public void CreatePdbState(PdbFileKind pdbFileKind) { SetPdbState(new PdbState(this, pdbFileKind)); } public void SetPdbState(PdbState pdbState) { if (pdbState == null) { throw new ArgumentNullException("pdbState"); } if (Interlocked.CompareExchange(ref this.pdbState, pdbState, null) != null) { throw new InvalidOperationException("PDB file has already been initialized"); } } private uint GetCor20RuntimeVersion() { uint? cor20HeaderRuntimeVersion = Cor20HeaderRuntimeVersion; if (cor20HeaderRuntimeVersion.HasValue) { return cor20HeaderRuntimeVersion.Value; } if (!IsClr1x) { return 131077u; } return 131072u; } public int GetPointerSize() { return GetPointerSize(4); } public int GetPointerSize(int defaultPointerSize) { return GetPointerSize(defaultPointerSize, defaultPointerSize); } public int GetPointerSize(int defaultPointerSize, int prefer32bitPointerSize) { Machine machine = Machine; if (machine.Is64Bit()) { return 8; } if (!machine.IsI386()) { return 4; } if (GetCor20RuntimeVersion() < 131077) { return 4; } ComImageFlags comImageFlags = (ComImageFlags)cor20HeaderFlags; if ((comImageFlags & ComImageFlags.ILOnly) == 0) { return 4; } return (comImageFlags & (ComImageFlags.Bit32Required | ComImageFlags.Bit32Preferred)) switch { ComImageFlags.Bit32Required => 4, ComImageFlags.Bit32Required | ComImageFlags.Bit32Preferred => prefer32bitPointerSize, _ => defaultPointerSize, }; } void IListListener.OnLazyAdd(int index, ref TypeDef value) { value.Module2 = this; } void IListListener.OnAdd(int index, TypeDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Nested type is already owned by another type. Set DeclaringType to null first."); } if (value.Module != null) { throw new InvalidOperationException("Type is already owned by another module. Remove it from that module's type list."); } value.Module2 = this; } void IListListener.OnRemove(int index, TypeDef value) { value.Module2 = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (TypeDef item in types.GetEnumerable_NoLock()) { item.Module2 = null; } } public TypeDef Find(string fullName, bool isReflectionName) { return TypeDefFinder.Find(fullName, isReflectionName); } public TypeDef Find(TypeRef typeRef) { return TypeDefFinder.Find(typeRef); } public TypeDef Find(ITypeDefOrRef typeRef) { if (typeRef is TypeDef typeDef) { if (typeDef.Module != this) { return null; } return typeDef; } if (typeRef is TypeRef typeRef2) { return Find(typeRef2); } if (!(typeRef is TypeSpec typeSpec)) { return null; } if (!(typeSpec.TypeSig is TypeDefOrRefSig { TypeDef: var typeDef2 } typeDefOrRefSig)) { return null; } if (typeDef2 != null) { if (typeDef2.Module != this) { return null; } return typeDef2; } TypeRef typeRef3 = typeDefOrRefSig.TypeRef; if (typeRef3 != null) { return Find(typeRef3); } return null; } public static ModuleContext CreateModuleContext() { ModuleContext moduleContext = new ModuleContext(); AssemblyResolver assemblyResolver = new AssemblyResolver(moduleContext); Resolver resolver = new Resolver(assemblyResolver); moduleContext.AssemblyResolver = assemblyResolver; moduleContext.Resolver = resolver; assemblyResolver.DefaultModuleContext = moduleContext; return moduleContext; } public virtual void LoadEverything(ICancellationToken cancellationToken = null) { ModuleLoader.LoadAll(this, cancellationToken); } public override string ToString() { return FullName; } public IMDTokenProvider ResolveToken(MDToken mdToken) { return ResolveToken(mdToken.Raw, default(GenericParamContext)); } public IMDTokenProvider ResolveToken(MDToken mdToken, GenericParamContext gpContext) { return ResolveToken(mdToken.Raw, gpContext); } public IMDTokenProvider ResolveToken(int token) { return ResolveToken((uint)token, default(GenericParamContext)); } public IMDTokenProvider ResolveToken(int token, GenericParamContext gpContext) { return ResolveToken((uint)token, gpContext); } public IMDTokenProvider ResolveToken(uint token) { return ResolveToken(token, default(GenericParamContext)); } public virtual IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext) { return null; } public IEnumerable GetAssemblyRefs() { for (uint rid = 1u; ResolveToken(new MDToken(Table.AssemblyRef, rid).Raw) is AssemblyRef assemblyRef; rid++) { yield return assemblyRef; } } public IEnumerable GetModuleRefs() { for (uint rid = 1u; ResolveToken(new MDToken(Table.ModuleRef, rid).Raw) is ModuleRef moduleRef; rid++) { yield return moduleRef; } } public IEnumerable GetMemberRefs() { return GetMemberRefs(default(GenericParamContext)); } public IEnumerable GetMemberRefs(GenericParamContext gpContext) { for (uint rid = 1u; ResolveToken(new MDToken(Table.MemberRef, rid).Raw, gpContext) is MemberRef memberRef; rid++) { yield return memberRef; } } public IEnumerable GetTypeRefs() { for (uint rid = 1u; ResolveToken(new MDToken(Table.TypeRef, rid).Raw) is TypeRef typeRef; rid++) { yield return typeRef; } } public AssemblyRef GetAssemblyRef(UTF8String simpleName) { AssemblyRef assemblyRef = null; foreach (AssemblyRef assemblyRef2 in GetAssemblyRefs()) { if (!(assemblyRef2.Name != simpleName) && IsGreaterAssemblyRefVersion(assemblyRef, assemblyRef2)) { assemblyRef = assemblyRef2; } } return assemblyRef; } protected static bool IsGreaterAssemblyRefVersion(AssemblyRef found, AssemblyRef newOne) { if (found == null) { return true; } Version version = found.Version; Version version2 = newOne.Version; if ((object)version != null) { if ((object)version2 != null) { return version2 >= version; } return false; } return true; } ITypeDefOrRef ISignatureReaderHelper.ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.TypeDefOrRef.Decode(codedToken, out uint token)) { return null; } return ResolveToken(token) as ITypeDefOrRef; } TypeSig ISignatureReaderHelper.ConvertRTInternalAddress(IntPtr address) { return null; } } public class ModuleDefUser : ModuleDef { public ModuleDefUser() : this(null, null) { } public ModuleDefUser(UTF8String name) : this(name, Guid.NewGuid()) { } public ModuleDefUser(UTF8String name, Guid? mvid) : this(name, mvid, null) { } public ModuleDefUser(UTF8String name, Guid? mvid, AssemblyRef corLibAssemblyRef) { base.Kind = ModuleKind.Windows; base.Characteristics = Characteristics.ExecutableImage | Characteristics.Bit32Machine; base.DllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompat | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware; base.RuntimeVersion = "v2.0.50727"; base.Machine = Machine.I386; cor20HeaderFlags = 1; base.Cor20HeaderRuntimeVersion = 131077u; base.TablesHeaderVersion = (ushort)512; types = new LazyList(this); exportedTypes = new LazyList(); resources = new ResourceCollection(); corLibTypes = new CorLibTypes(this, corLibAssemblyRef); types = new LazyList(this); base.name = name; base.mvid = mvid; types.Add(CreateModuleType()); UpdateRowId(this); } private TypeDef CreateModuleType() { TypeDefUser typeDefUser = UpdateRowId(new TypeDefUser(UTF8String.Empty, "", null)); typeDefUser.Attributes = TypeAttributes.NotPublic; return typeDefUser; } } public class ModuleDefMD2 : ModuleDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Module, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } protected override RVA GetNativeEntryPoint_NoLock() { return readerModule.GetNativeEntryPoint(); } protected override IManagedEntryPoint GetManagedEntryPoint_NoLock() { return readerModule.GetManagedEntryPoint(); } internal ModuleDefMD2(ModuleDefMD readerModule, uint rid) { if (rid == 1 && readerModule == null) { readerModule = (ModuleDefMD)this; } origRid = rid; base.rid = rid; this.readerModule = readerModule; if (rid != 1) { base.Kind = ModuleKind.Windows; base.Characteristics = Characteristics.ExecutableImage | Characteristics.Bit32Machine; base.DllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompat | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware; base.RuntimeVersion = "v2.0.50727"; base.Machine = Machine.I386; cor20HeaderFlags = 1; base.Cor20HeaderRuntimeVersion = 131077u; base.TablesHeaderVersion = (ushort)512; corLibTypes = new CorLibTypes(this); location = string.Empty; InitializeFromRawRow(); } } protected void InitializeFromRawRow() { readerModule.TablesStream.TryReadModuleRow(origRid, out var row); generation = row.Generation; mvid = readerModule.GuidStream.Read(row.Mvid); encId = readerModule.GuidStream.Read(row.EncId); encBaseId = readerModule.GuidStream.Read(row.EncBaseId); name = readerModule.StringsStream.ReadNoNull(row.Name); if (origRid == 1) { assembly = readerModule.ResolveAssembly(origRid); } } } public sealed class ModuleDefMD : ModuleDefMD2, IInstructionOperandResolver, ITokenResolver, IStringResolver { private MetadataBase metadata; private IMethodDecrypter methodDecrypter; private IStringDecrypter stringDecrypter; private StrongBox moduleRidList; private SimpleLazyList listModuleDefMD; private SimpleLazyList listTypeRefMD; private SimpleLazyList listTypeDefMD; private SimpleLazyList listFieldDefMD; private SimpleLazyList listMethodDefMD; private SimpleLazyList listParamDefMD; private SimpleLazyList2 listInterfaceImplMD; private SimpleLazyList2 listMemberRefMD; private SimpleLazyList listConstantMD; private SimpleLazyList listDeclSecurityMD; private SimpleLazyList listClassLayoutMD; private SimpleLazyList2 listStandAloneSigMD; private SimpleLazyList listEventDefMD; private SimpleLazyList listPropertyDefMD; private SimpleLazyList listModuleRefMD; private SimpleLazyList2 listTypeSpecMD; private SimpleLazyList listImplMapMD; private SimpleLazyList listAssemblyDefMD; private SimpleLazyList listAssemblyRefMD; private SimpleLazyList listFileDefMD; private SimpleLazyList listExportedTypeMD; private SimpleLazyList listManifestResourceMD; private SimpleLazyList listGenericParamMD; private SimpleLazyList2 listMethodSpecMD; private SimpleLazyList2 listGenericParamConstraintMD; private static readonly Dictionary preferredCorLibs = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 100 }, { "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 90 }, { "mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 60 }, { "mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 50 }, { "mscorlib, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", 80 }, { "mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", 70 }, { "mscorlib, Version=3.5.0.0, Culture=neutral, PublicKeyToken=e92a8b81eba7ceb7", 60 }, { "mscorlib, Version=3.5.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac", 60 }, { "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac", 50 } }; private static readonly string[] corlibs = new string[4] { "System.Private.CoreLib", "System.Runtime", "netstandard", "mscorlib" }; private static readonly UTF8String systemRuntimeName = new UTF8String("System.Runtime"); private static readonly UTF8String corefxName = new UTF8String("corefx"); private static readonly PublicKeyToken contractsPublicKeyToken = new PublicKeyToken("b03f5f7f11d50a3a"); private MethodExportInfoProvider methodExportInfoProvider; public IMethodDecrypter MethodDecrypter { get { return methodDecrypter; } set { methodDecrypter = value; } } public IStringDecrypter StringDecrypter { get { return stringDecrypter; } set { stringDecrypter = value; } } public dnlib.DotNet.MD.Metadata Metadata => metadata; public TablesStream TablesStream => metadata.TablesStream; public StringsStream StringsStream => metadata.StringsStream; public BlobStream BlobStream => metadata.BlobStream; public GuidStream GuidStream => metadata.GuidStream; public USStream USStream => metadata.USStream; protected override void InitializeTypes() { RidList nonNestedClassRidList = Metadata.GetNonNestedClassRidList(); LazyList value = new LazyList(nonNestedClassRidList.Count, this, nonNestedClassRidList, (RidList list2, int index) => ResolveTypeDef(list2[index])); Interlocked.CompareExchange(ref types, value, null); } protected override void InitializeExportedTypes() { RidList exportedTypeRidList = Metadata.GetExportedTypeRidList(); LazyList value = new LazyList(exportedTypeRidList.Count, exportedTypeRidList, (RidList list2, int i) => ResolveExportedType(list2[i])); Interlocked.CompareExchange(ref exportedTypes, value, null); } protected override void InitializeResources() { ResourceCollection value = new ResourceCollection((int)TablesStream.ManifestResourceTable.Rows, null, (object ctx, int i) => CreateResource((uint)(i + 1))); Interlocked.CompareExchange(ref resources, value, null); } protected override Win32Resources GetWin32Resources_NoLock() { return metadata.PEImage.Win32Resources; } protected override VTableFixups GetVTableFixups_NoLock() { ImageDataDirectory vTableFixups = metadata.ImageCor20Header.VTableFixups; if (vTableFixups.VirtualAddress == (RVA)0u || vTableFixups.Size == 0) { return null; } return new VTableFixups(this); } public static ModuleDefMD Load(string fileName, ModuleContext context) { return Load(fileName, new ModuleCreationOptions(context)); } public static ModuleDefMD Load(string fileName, ModuleCreationOptions options = null) { return Load(MetadataFactory.Load(fileName, options?.Runtime ?? CLRRuntimeReaderKind.CLR), options); } public static ModuleDefMD Load(byte[] data, ModuleContext context) { return Load(data, new ModuleCreationOptions(context)); } public static ModuleDefMD Load(byte[] data, ModuleCreationOptions options = null) { return Load(MetadataFactory.Load(data, options?.Runtime ?? CLRRuntimeReaderKind.CLR), options); } public static ModuleDefMD Load(Module mod) { return Load(mod, (ModuleCreationOptions)null, GetImageLayout(mod)); } public static ModuleDefMD Load(Module mod, ModuleContext context) { return Load(mod, new ModuleCreationOptions(context), GetImageLayout(mod)); } public static ModuleDefMD Load(Module mod, ModuleCreationOptions options) { return Load(mod, options, GetImageLayout(mod)); } private static ImageLayout GetImageLayout(Module mod) { string fullyQualifiedName = mod.FullyQualifiedName; if (fullyQualifiedName.Length > 0 && fullyQualifiedName[0] == '<' && fullyQualifiedName[fullyQualifiedName.Length - 1] == '>') { return ImageLayout.File; } return ImageLayout.Memory; } public static ModuleDefMD Load(Module mod, ModuleContext context, ImageLayout imageLayout) { return Load(mod, new ModuleCreationOptions(context), imageLayout); } private static IntPtr GetModuleHandle(Module mod) { return Marshal.GetHINSTANCE(mod); } public static ModuleDefMD Load(Module mod, ModuleCreationOptions options, ImageLayout imageLayout) { IntPtr moduleHandle = GetModuleHandle(mod); if (moduleHandle != IntPtr.Zero && moduleHandle != new IntPtr(-1)) { return Load(moduleHandle, options, imageLayout); } string fullyQualifiedName = mod.FullyQualifiedName; if (string.IsNullOrEmpty(fullyQualifiedName) || fullyQualifiedName[0] == '<') { throw new InvalidOperationException($"Module {mod} has no HINSTANCE"); } return Load(fullyQualifiedName, options); } public static ModuleDefMD Load(IntPtr addr) { return Load(MetadataFactory.Load(addr, CLRRuntimeReaderKind.CLR), null); } public static ModuleDefMD Load(IntPtr addr, ModuleContext context) { return Load(MetadataFactory.Load(addr, CLRRuntimeReaderKind.CLR), new ModuleCreationOptions(context)); } public static ModuleDefMD Load(IntPtr addr, ModuleCreationOptions options) { return Load(MetadataFactory.Load(addr, options?.Runtime ?? CLRRuntimeReaderKind.CLR), options); } public static ModuleDefMD Load(IPEImage peImage) { return Load(MetadataFactory.Load(peImage, CLRRuntimeReaderKind.CLR), null); } public static ModuleDefMD Load(IPEImage peImage, ModuleContext context) { return Load(MetadataFactory.Load(peImage, CLRRuntimeReaderKind.CLR), new ModuleCreationOptions(context)); } public static ModuleDefMD Load(IPEImage peImage, ModuleCreationOptions options) { return Load(MetadataFactory.Load(peImage, options?.Runtime ?? CLRRuntimeReaderKind.CLR), options); } public static ModuleDefMD Load(IntPtr addr, ModuleContext context, ImageLayout imageLayout) { return Load(MetadataFactory.Load(addr, imageLayout, CLRRuntimeReaderKind.CLR), new ModuleCreationOptions(context)); } public static ModuleDefMD Load(IntPtr addr, ModuleCreationOptions options, ImageLayout imageLayout) { return Load(MetadataFactory.Load(addr, imageLayout, options?.Runtime ?? CLRRuntimeReaderKind.CLR), options); } public static ModuleDefMD Load(Stream stream) { return Load(stream, (ModuleCreationOptions)null); } public static ModuleDefMD Load(Stream stream, ModuleContext context) { return Load(stream, new ModuleCreationOptions(context)); } public static ModuleDefMD Load(Stream stream, ModuleCreationOptions options) { if (stream == null) { throw new ArgumentNullException("stream"); } if (stream.Length > int.MaxValue) { throw new ArgumentException("Stream is too big"); } byte[] array = new byte[(int)stream.Length]; stream.Position = 0L; if (stream.Read(array, 0, array.Length) != array.Length) { throw new IOException("Could not read all bytes from the stream"); } return Load(array, options); } internal static ModuleDefMD Load(MetadataBase metadata, ModuleCreationOptions options) { return new ModuleDefMD(metadata, options); } private ModuleDefMD(MetadataBase metadata, ModuleCreationOptions options) : base(null, 1u) { if (options == null) { options = ModuleCreationOptions.Default; } this.metadata = metadata; context = options.Context; Initialize(); InitializeFromRawRow(); location = metadata.PEImage.Filename ?? string.Empty; base.Kind = GetKind(); base.Characteristics = Metadata.PEImage.ImageNTHeaders.FileHeader.Characteristics; base.DllCharacteristics = Metadata.PEImage.ImageNTHeaders.OptionalHeader.DllCharacteristics; base.RuntimeVersion = Metadata.VersionString; base.Machine = Metadata.PEImage.ImageNTHeaders.FileHeader.Machine; base.Cor20HeaderFlags = Metadata.ImageCor20Header.Flags; base.Cor20HeaderRuntimeVersion = (uint)((Metadata.ImageCor20Header.MajorRuntimeVersion << 16) | Metadata.ImageCor20Header.MinorRuntimeVersion); base.TablesHeaderVersion = Metadata.TablesStream.Version; corLibTypes = new CorLibTypes(this, options.CorLibAssemblyRef ?? FindCorLibAssemblyRef() ?? CreateDefaultCorLibAssemblyRef()); InitializePdb(options); } private void InitializePdb(ModuleCreationOptions options) { if (options != null) { LoadPdb(CreateSymbolReader(options)); } } private SymbolReader CreateSymbolReader(ModuleCreationOptions options) { if (options.PdbFileOrData != null) { string text = options.PdbFileOrData as string; if (!string.IsNullOrEmpty(text)) { SymbolReader symbolReader = dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options.PdbOptions, metadata, text); if (symbolReader != null) { return symbolReader; } } if (options.PdbFileOrData is byte[] pdbData) { return dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options.PdbOptions, metadata, pdbData); } if (options.PdbFileOrData is DataReaderFactory pdbStream) { return dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options.PdbOptions, metadata, pdbStream); } } if (options.TryToLoadPdbFromDisk) { return dnlib.DotNet.Pdb.SymbolReaderFactory.CreateFromAssemblyFile(options.PdbOptions, metadata, location ?? string.Empty); } return null; } public void LoadPdb(SymbolReader symbolReader) { if (symbolReader != null) { if (pdbState != null) { throw new InvalidOperationException("PDB file has already been initialized"); } if (Interlocked.CompareExchange(ref pdbState, new PdbState(symbolReader, this), null) != null) { throw new InvalidOperationException("PDB file has already been initialized"); } } } public void LoadPdb(string pdbFileName) { LoadPdb(PdbReaderOptions.None, pdbFileName); } public void LoadPdb(PdbReaderOptions options, string pdbFileName) { LoadPdb(dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options, metadata, pdbFileName)); } public void LoadPdb(byte[] pdbData) { LoadPdb(PdbReaderOptions.None, pdbData); } public void LoadPdb(PdbReaderOptions options, byte[] pdbData) { LoadPdb(dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options, metadata, pdbData)); } public void LoadPdb(DataReaderFactory pdbStream) { LoadPdb(PdbReaderOptions.None, pdbStream); } public void LoadPdb(PdbReaderOptions options, DataReaderFactory pdbStream) { LoadPdb(dnlib.DotNet.Pdb.SymbolReaderFactory.Create(options, metadata, pdbStream)); } public void LoadPdb() { LoadPdb(PdbReaderOptions.None); } public void LoadPdb(PdbReaderOptions options) { LoadPdb(dnlib.DotNet.Pdb.SymbolReaderFactory.CreateFromAssemblyFile(options, metadata, location ?? string.Empty)); } internal void InitializeCustomDebugInfos(MDToken token, GenericParamContext gpContext, IList result) { pdbState?.InitializeCustomDebugInfos(token, gpContext, result); } private ModuleKind GetKind() { if (TablesStream.AssemblyTable.Rows < 1) { return ModuleKind.NetModule; } IPEImage pEImage = Metadata.PEImage; if ((pEImage.ImageNTHeaders.FileHeader.Characteristics & Characteristics.Dll) != 0) { return ModuleKind.Dll; } if (pEImage.ImageNTHeaders.OptionalHeader.Subsystem == Subsystem.WindowsCui) { return ModuleKind.Console; } return ModuleKind.Windows; } private void Initialize() { TablesStream tablesStream = metadata.TablesStream; listModuleDefMD = new SimpleLazyList(tablesStream.ModuleTable.Rows, (uint rid2) => (rid2 != 1) ? new ModuleDefMD2(this, rid2) : this); listTypeRefMD = new SimpleLazyList(tablesStream.TypeRefTable.Rows, (uint rid2) => new TypeRefMD(this, rid2)); listTypeDefMD = new SimpleLazyList(tablesStream.TypeDefTable.Rows, (uint rid2) => new TypeDefMD(this, rid2)); listFieldDefMD = new SimpleLazyList(tablesStream.FieldTable.Rows, (uint rid2) => new FieldDefMD(this, rid2)); listMethodDefMD = new SimpleLazyList(tablesStream.MethodTable.Rows, (uint rid2) => new MethodDefMD(this, rid2)); listParamDefMD = new SimpleLazyList(tablesStream.ParamTable.Rows, (uint rid2) => new ParamDefMD(this, rid2)); listInterfaceImplMD = new SimpleLazyList2(tablesStream.InterfaceImplTable.Rows, (uint rid2, GenericParamContext gpContext) => new InterfaceImplMD(this, rid2, gpContext)); listMemberRefMD = new SimpleLazyList2(tablesStream.MemberRefTable.Rows, (uint rid2, GenericParamContext gpContext) => new MemberRefMD(this, rid2, gpContext)); listConstantMD = new SimpleLazyList(tablesStream.ConstantTable.Rows, (uint rid2) => new ConstantMD(this, rid2)); listDeclSecurityMD = new SimpleLazyList(tablesStream.DeclSecurityTable.Rows, (uint rid2) => new DeclSecurityMD(this, rid2)); listClassLayoutMD = new SimpleLazyList(tablesStream.ClassLayoutTable.Rows, (uint rid2) => new ClassLayoutMD(this, rid2)); listStandAloneSigMD = new SimpleLazyList2(tablesStream.StandAloneSigTable.Rows, (uint rid2, GenericParamContext gpContext) => new StandAloneSigMD(this, rid2, gpContext)); listEventDefMD = new SimpleLazyList(tablesStream.EventTable.Rows, (uint rid2) => new EventDefMD(this, rid2)); listPropertyDefMD = new SimpleLazyList(tablesStream.PropertyTable.Rows, (uint rid2) => new PropertyDefMD(this, rid2)); listModuleRefMD = new SimpleLazyList(tablesStream.ModuleRefTable.Rows, (uint rid2) => new ModuleRefMD(this, rid2)); listTypeSpecMD = new SimpleLazyList2(tablesStream.TypeSpecTable.Rows, (uint rid2, GenericParamContext gpContext) => new TypeSpecMD(this, rid2, gpContext)); listImplMapMD = new SimpleLazyList(tablesStream.ImplMapTable.Rows, (uint rid2) => new ImplMapMD(this, rid2)); listAssemblyDefMD = new SimpleLazyList(tablesStream.AssemblyTable.Rows, (uint rid2) => new AssemblyDefMD(this, rid2)); listFileDefMD = new SimpleLazyList(tablesStream.FileTable.Rows, (uint rid2) => new FileDefMD(this, rid2)); listAssemblyRefMD = new SimpleLazyList(tablesStream.AssemblyRefTable.Rows, (uint rid2) => new AssemblyRefMD(this, rid2)); listExportedTypeMD = new SimpleLazyList(tablesStream.ExportedTypeTable.Rows, (uint rid2) => new ExportedTypeMD(this, rid2)); listManifestResourceMD = new SimpleLazyList(tablesStream.ManifestResourceTable.Rows, (uint rid2) => new ManifestResourceMD(this, rid2)); listGenericParamMD = new SimpleLazyList(tablesStream.GenericParamTable.Rows, (uint rid2) => new GenericParamMD(this, rid2)); listMethodSpecMD = new SimpleLazyList2(tablesStream.MethodSpecTable.Rows, (uint rid2, GenericParamContext gpContext) => new MethodSpecMD(this, rid2, gpContext)); listGenericParamConstraintMD = new SimpleLazyList2(tablesStream.GenericParamConstraintTable.Rows, (uint rid2, GenericParamContext gpContext) => new GenericParamConstraintMD(this, rid2, gpContext)); for (int num = 0; num < 64; num++) { MDTable mDTable = TablesStream.Get((Table)num); lastUsedRids[num] = (int)(mDTable?.Rows ?? 0); } } private AssemblyRef FindCorLibAssemblyRef() { uint rows = TablesStream.AssemblyRefTable.Rows; AssemblyRef assemblyRef = null; int num = int.MinValue; for (uint num2 = 1u; num2 <= rows; num2++) { AssemblyRef assemblyRef2 = ResolveAssemblyRef(num2); if (preferredCorLibs.TryGetValue(assemblyRef2.FullName, out var value) && value > num) { num = value; assemblyRef = assemblyRef2; } } if (assemblyRef != null) { return assemblyRef; } string[] array = corlibs; foreach (string value2 in array) { for (uint num3 = 1u; num3 <= rows; num3++) { AssemblyRef assemblyRef3 = ResolveAssemblyRef(num3); if (UTF8String.ToSystemStringOrEmpty(assemblyRef3.Name).Equals(value2, StringComparison.OrdinalIgnoreCase) && ModuleDef.IsGreaterAssemblyRefVersion(assemblyRef, assemblyRef3)) { assemblyRef = assemblyRef3; } } if (assemblyRef != null) { return assemblyRef; } } AssemblyDef assemblyDef = base.Assembly; if (assemblyDef != null && (assemblyDef.IsCorLib() || Find("System.Object", isReflectionName: false) != null)) { base.IsCoreLibraryModule = true; return UpdateRowId(new AssemblyRefUser(assemblyDef)); } return assemblyRef; } private AssemblyRef CreateDefaultCorLibAssemblyRef() { AssemblyRef alternativeCorLibReference = GetAlternativeCorLibReference(); if (alternativeCorLibReference != null) { return UpdateRowId(alternativeCorLibReference); } if (base.IsClr40) { return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR40()); } if (base.IsClr20) { return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20()); } if (base.IsClr11) { return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR11()); } if (base.IsClr10) { return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR10()); } return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR40()); } private AssemblyRef GetAlternativeCorLibReference() { foreach (AssemblyRef assemblyRef in GetAssemblyRefs()) { if (IsAssemblyRef(assemblyRef, systemRuntimeName, contractsPublicKeyToken)) { return assemblyRef; } } foreach (AssemblyRef assemblyRef2 in GetAssemblyRefs()) { if (IsAssemblyRef(assemblyRef2, corefxName, contractsPublicKeyToken)) { return assemblyRef2; } } return null; } private static bool IsAssemblyRef(AssemblyRef asmRef, UTF8String name, PublicKeyToken token) { if (asmRef.Name != name) { return false; } PublicKeyBase publicKeyOrToken = asmRef.PublicKeyOrToken; if (publicKeyOrToken == null) { return false; } return token.Equals(publicKeyOrToken.Token); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { metadata?.Dispose(); metadata = null; } } public override IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext) { uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Module => ResolveModule(num), Table.TypeRef => ResolveTypeRef(num), Table.TypeDef => ResolveTypeDef(num), Table.Field => ResolveField(num), Table.Method => ResolveMethod(num), Table.Param => ResolveParam(num), Table.InterfaceImpl => ResolveInterfaceImpl(num, gpContext), Table.MemberRef => ResolveMemberRef(num, gpContext), Table.Constant => ResolveConstant(num), Table.DeclSecurity => ResolveDeclSecurity(num), Table.ClassLayout => ResolveClassLayout(num), Table.StandAloneSig => ResolveStandAloneSig(num, gpContext), Table.Event => ResolveEvent(num), Table.Property => ResolveProperty(num), Table.ModuleRef => ResolveModuleRef(num), Table.TypeSpec => ResolveTypeSpec(num, gpContext), Table.ImplMap => ResolveImplMap(num), Table.Assembly => ResolveAssembly(num), Table.AssemblyRef => ResolveAssemblyRef(num), Table.File => ResolveFile(num), Table.ExportedType => ResolveExportedType(num), Table.ManifestResource => ResolveManifestResource(num), Table.GenericParam => ResolveGenericParam(num), Table.MethodSpec => ResolveMethodSpec(num, gpContext), Table.GenericParamConstraint => ResolveGenericParamConstraint(num, gpContext), _ => null, }; } public ModuleDef ResolveModule(uint rid) { return listModuleDefMD[rid - 1]; } public TypeRef ResolveTypeRef(uint rid) { return listTypeRefMD[rid - 1]; } public TypeDef ResolveTypeDef(uint rid) { return listTypeDefMD[rid - 1]; } public FieldDef ResolveField(uint rid) { return listFieldDefMD[rid - 1]; } public MethodDef ResolveMethod(uint rid) { return listMethodDefMD[rid - 1]; } public ParamDef ResolveParam(uint rid) { return listParamDefMD[rid - 1]; } public InterfaceImpl ResolveInterfaceImpl(uint rid) { return listInterfaceImplMD[rid - 1, default(GenericParamContext)]; } public InterfaceImpl ResolveInterfaceImpl(uint rid, GenericParamContext gpContext) { return listInterfaceImplMD[rid - 1, gpContext]; } public MemberRef ResolveMemberRef(uint rid) { return listMemberRefMD[rid - 1, default(GenericParamContext)]; } public MemberRef ResolveMemberRef(uint rid, GenericParamContext gpContext) { return listMemberRefMD[rid - 1, gpContext]; } public Constant ResolveConstant(uint rid) { return listConstantMD[rid - 1]; } public DeclSecurity ResolveDeclSecurity(uint rid) { return listDeclSecurityMD[rid - 1]; } public ClassLayout ResolveClassLayout(uint rid) { return listClassLayoutMD[rid - 1]; } public StandAloneSig ResolveStandAloneSig(uint rid) { return listStandAloneSigMD[rid - 1, default(GenericParamContext)]; } public StandAloneSig ResolveStandAloneSig(uint rid, GenericParamContext gpContext) { return listStandAloneSigMD[rid - 1, gpContext]; } public EventDef ResolveEvent(uint rid) { return listEventDefMD[rid - 1]; } public PropertyDef ResolveProperty(uint rid) { return listPropertyDefMD[rid - 1]; } public ModuleRef ResolveModuleRef(uint rid) { return listModuleRefMD[rid - 1]; } public TypeSpec ResolveTypeSpec(uint rid) { return listTypeSpecMD[rid - 1, default(GenericParamContext)]; } public TypeSpec ResolveTypeSpec(uint rid, GenericParamContext gpContext) { return listTypeSpecMD[rid - 1, gpContext]; } public ImplMap ResolveImplMap(uint rid) { return listImplMapMD[rid - 1]; } public AssemblyDef ResolveAssembly(uint rid) { return listAssemblyDefMD[rid - 1]; } public AssemblyRef ResolveAssemblyRef(uint rid) { return listAssemblyRefMD[rid - 1]; } public FileDef ResolveFile(uint rid) { return listFileDefMD[rid - 1]; } public ExportedType ResolveExportedType(uint rid) { return listExportedTypeMD[rid - 1]; } public ManifestResource ResolveManifestResource(uint rid) { return listManifestResourceMD[rid - 1]; } public GenericParam ResolveGenericParam(uint rid) { return listGenericParamMD[rid - 1]; } public MethodSpec ResolveMethodSpec(uint rid) { return listMethodSpecMD[rid - 1, default(GenericParamContext)]; } public MethodSpec ResolveMethodSpec(uint rid, GenericParamContext gpContext) { return listMethodSpecMD[rid - 1, gpContext]; } public GenericParamConstraint ResolveGenericParamConstraint(uint rid) { return listGenericParamConstraintMD[rid - 1, default(GenericParamContext)]; } public GenericParamConstraint ResolveGenericParamConstraint(uint rid, GenericParamContext gpContext) { return listGenericParamConstraintMD[rid - 1, gpContext]; } public ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken) { return ResolveTypeDefOrRef(codedToken, default(GenericParamContext)); } public ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.TypeDefOrRef.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.TypeDef => ResolveTypeDef(num), Table.TypeRef => ResolveTypeRef(num), Table.TypeSpec => ResolveTypeSpec(num, gpContext), _ => null, }; } public IHasConstant ResolveHasConstant(uint codedToken) { if (!CodedToken.HasConstant.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Field => ResolveField(num), Table.Param => ResolveParam(num), Table.Property => ResolveProperty(num), _ => null, }; } public IHasCustomAttribute ResolveHasCustomAttribute(uint codedToken) { return ResolveHasCustomAttribute(codedToken, default(GenericParamContext)); } public IHasCustomAttribute ResolveHasCustomAttribute(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.HasCustomAttribute.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Method => ResolveMethod(num), Table.Field => ResolveField(num), Table.TypeRef => ResolveTypeRef(num), Table.TypeDef => ResolveTypeDef(num), Table.Param => ResolveParam(num), Table.InterfaceImpl => ResolveInterfaceImpl(num, gpContext), Table.MemberRef => ResolveMemberRef(num, gpContext), Table.Module => ResolveModule(num), Table.DeclSecurity => ResolveDeclSecurity(num), Table.Property => ResolveProperty(num), Table.Event => ResolveEvent(num), Table.StandAloneSig => ResolveStandAloneSig(num, gpContext), Table.ModuleRef => ResolveModuleRef(num), Table.TypeSpec => ResolveTypeSpec(num, gpContext), Table.Assembly => ResolveAssembly(num), Table.AssemblyRef => ResolveAssemblyRef(num), Table.File => ResolveFile(num), Table.ExportedType => ResolveExportedType(num), Table.ManifestResource => ResolveManifestResource(num), Table.GenericParam => ResolveGenericParam(num), Table.MethodSpec => ResolveMethodSpec(num, gpContext), Table.GenericParamConstraint => ResolveGenericParamConstraint(num, gpContext), _ => null, }; } public IHasFieldMarshal ResolveHasFieldMarshal(uint codedToken) { if (!CodedToken.HasFieldMarshal.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Field => ResolveField(num), Table.Param => ResolveParam(num), _ => null, }; } public IHasDeclSecurity ResolveHasDeclSecurity(uint codedToken) { if (!CodedToken.HasDeclSecurity.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.TypeDef => ResolveTypeDef(num), Table.Method => ResolveMethod(num), Table.Assembly => ResolveAssembly(num), _ => null, }; } public IMemberRefParent ResolveMemberRefParent(uint codedToken) { return ResolveMemberRefParent(codedToken, default(GenericParamContext)); } public IMemberRefParent ResolveMemberRefParent(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.MemberRefParent.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.TypeDef => ResolveTypeDef(num), Table.TypeRef => ResolveTypeRef(num), Table.ModuleRef => ResolveModuleRef(num), Table.Method => ResolveMethod(num), Table.TypeSpec => ResolveTypeSpec(num, gpContext), _ => null, }; } public IHasSemantic ResolveHasSemantic(uint codedToken) { if (!CodedToken.HasSemantic.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Event => ResolveEvent(num), Table.Property => ResolveProperty(num), _ => null, }; } public IMethodDefOrRef ResolveMethodDefOrRef(uint codedToken) { return ResolveMethodDefOrRef(codedToken, default(GenericParamContext)); } public IMethodDefOrRef ResolveMethodDefOrRef(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.MethodDefOrRef.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Method => ResolveMethod(num), Table.MemberRef => ResolveMemberRef(num, gpContext), _ => null, }; } public IMemberForwarded ResolveMemberForwarded(uint codedToken) { if (!CodedToken.MemberForwarded.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Field => ResolveField(num), Table.Method => ResolveMethod(num), _ => null, }; } public IImplementation ResolveImplementation(uint codedToken) { if (!CodedToken.Implementation.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.File => ResolveFile(num), Table.AssemblyRef => ResolveAssemblyRef(num), Table.ExportedType => ResolveExportedType(num), _ => null, }; } public ICustomAttributeType ResolveCustomAttributeType(uint codedToken) { return ResolveCustomAttributeType(codedToken, default(GenericParamContext)); } public ICustomAttributeType ResolveCustomAttributeType(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.CustomAttributeType.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.Method => ResolveMethod(num), Table.MemberRef => ResolveMemberRef(num, gpContext), _ => null, }; } public IResolutionScope ResolveResolutionScope(uint codedToken) { if (!CodedToken.ResolutionScope.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); Table table = MDToken.ToTable(token); switch (table) { case Table.TypeRef: if (table != Table.TypeRef) { break; } return ResolveTypeRef(num); case Table.Module: return ResolveModule(num); case Table.ModuleRef: return ResolveModuleRef(num); case Table.AssemblyRef: return ResolveAssemblyRef(num); } return null; } public ITypeOrMethodDef ResolveTypeOrMethodDef(uint codedToken) { if (!CodedToken.TypeOrMethodDef.Decode(codedToken, out uint token)) { return null; } uint num = MDToken.ToRID(token); return MDToken.ToTable(token) switch { Table.TypeDef => ResolveTypeDef(num), Table.Method => ResolveMethod(num), _ => null, }; } public CallingConventionSig ReadSignature(uint sig) { return SignatureReader.ReadSig(this, sig, default(GenericParamContext)); } public CallingConventionSig ReadSignature(uint sig, GenericParamContext gpContext) { return SignatureReader.ReadSig(this, sig, gpContext); } public TypeSig ReadTypeSignature(uint sig) { return SignatureReader.ReadTypeSig(this, sig, default(GenericParamContext)); } public TypeSig ReadTypeSignature(uint sig, GenericParamContext gpContext) { return SignatureReader.ReadTypeSig(this, sig, gpContext); } public TypeSig ReadTypeSignature(uint sig, out byte[] extraData) { return SignatureReader.ReadTypeSig(this, sig, default(GenericParamContext), out extraData); } public TypeSig ReadTypeSignature(uint sig, GenericParamContext gpContext, out byte[] extraData) { return SignatureReader.ReadTypeSig(this, sig, gpContext, out extraData); } internal MarshalType ReadMarshalType(Table table, uint rid, GenericParamContext gpContext) { if (!TablesStream.TryReadFieldMarshalRow(Metadata.GetFieldMarshalRid(table, rid), out var row)) { return null; } return MarshalBlobReader.Read(this, row.NativeType, gpContext); } public CilBody ReadCilBody(IList parameters, RVA rva) { return ReadCilBody(parameters, rva, default(GenericParamContext)); } public CilBody ReadCilBody(IList parameters, RVA rva, GenericParamContext gpContext) { if (rva == (RVA)0u) { return new CilBody(); } FileOffset fileOffset = metadata.PEImage.ToFileOffset(rva); if (fileOffset == (FileOffset)0u) { return new CilBody(); } DataReader reader = metadata.PEImage.CreateReader(); reader.Position = (uint)fileOffset; return MethodBodyReader.CreateCilBody(this, reader, parameters, gpContext, base.Context); } internal TypeDef GetOwnerType(FieldDefMD field) { return ResolveTypeDef(Metadata.GetOwnerTypeOfField(field.OrigRid)); } internal TypeDef GetOwnerType(MethodDefMD method) { return ResolveTypeDef(Metadata.GetOwnerTypeOfMethod(method.OrigRid)); } internal TypeDef GetOwnerType(EventDefMD evt) { return ResolveTypeDef(Metadata.GetOwnerTypeOfEvent(evt.OrigRid)); } internal TypeDef GetOwnerType(PropertyDefMD property) { return ResolveTypeDef(Metadata.GetOwnerTypeOfProperty(property.OrigRid)); } internal ITypeOrMethodDef GetOwner(GenericParamMD gp) { return ResolveTypeOrMethodDef(Metadata.GetOwnerOfGenericParam(gp.OrigRid)); } internal GenericParam GetOwner(GenericParamConstraintMD gpc) { return ResolveGenericParam(Metadata.GetOwnerOfGenericParamConstraint(gpc.OrigRid)); } internal MethodDef GetOwner(ParamDefMD pd) { return ResolveMethod(Metadata.GetOwnerOfParam(pd.OrigRid)); } internal ModuleDefMD ReadModule(uint fileRid, AssemblyDef owner) { FileDef fileDef = ResolveFile(fileRid); if (fileDef == null) { return null; } if (!fileDef.ContainsMetadata) { return null; } string validFilename = GetValidFilename(GetBaseDirectoryOfImage(), UTF8String.ToSystemString(fileDef.Name)); if (validFilename == null) { return null; } ModuleDefMD moduleDefMD; try { moduleDefMD = Load(validFilename); } catch { moduleDefMD = null; } if (moduleDefMD != null) { moduleDefMD.context = context; AssemblyDef assemblyDef = moduleDefMD.Assembly; if (assemblyDef != null && assemblyDef != owner) { assemblyDef.Modules.Remove(moduleDefMD); } } return moduleDefMD; } internal RidList GetModuleRidList() { if (moduleRidList == null) { InitializeModuleList(); } return moduleRidList.Value; } private void InitializeModuleList() { if (moduleRidList != null) { return; } uint rows = TablesStream.FileTable.Rows; List list = new List((int)rows); string baseDirectoryOfImage = GetBaseDirectoryOfImage(); for (uint num = 1u; num <= rows; num++) { FileDef fileDef = ResolveFile(num); if (fileDef != null && fileDef.ContainsMetadata && GetValidFilename(baseDirectoryOfImage, UTF8String.ToSystemString(fileDef.Name)) != null) { list.Add(num); } } Interlocked.CompareExchange(ref moduleRidList, new StrongBox(RidList.Create(list)), null); } private static string GetValidFilename(string baseDir, string name) { if (baseDir == null) { return null; } try { if (name.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { return null; } string text = Path.Combine(baseDir, name); if (text != Path.GetFullPath(text)) { return null; } if (!File.Exists(text)) { return null; } return text; } catch { return null; } } private string GetBaseDirectoryOfImage() { string text = base.Location; if (string.IsNullOrEmpty(text)) { return null; } try { return Path.GetDirectoryName(text); } catch (IOException) { } catch (ArgumentException) { } return null; } private Resource CreateResource(uint rid) { if (!TablesStream.TryReadManifestResourceRow(rid, out var row)) { return new EmbeddedResource(UTF8String.Empty, Array2.Empty(), (ManifestResourceAttributes)0u) { Rid = rid }; } if (!CodedToken.Implementation.Decode(row.Implementation, out MDToken token)) { return new EmbeddedResource(UTF8String.Empty, Array2.Empty(), (ManifestResourceAttributes)0u) { Rid = rid }; } ManifestResource manifestResource = ResolveManifestResource(rid); if (manifestResource == null) { return new EmbeddedResource(UTF8String.Empty, Array2.Empty(), (ManifestResourceAttributes)0u) { Rid = rid }; } if (token.Rid == 0) { if (TryCreateResourceStream(manifestResource.Offset, out var dataReaderFactory, out var resourceOffset, out var resourceLength)) { return new EmbeddedResourceMD(this, manifestResource, dataReaderFactory, resourceOffset, resourceLength); } return new EmbeddedResourceMD(this, manifestResource, Array2.Empty()); } if (manifestResource.Implementation is FileDef file) { return new LinkedResourceMD(this, manifestResource, file); } if (manifestResource.Implementation is AssemblyRef asmRef) { return new AssemblyLinkedResourceMD(this, manifestResource, asmRef); } return new EmbeddedResourceMD(this, manifestResource, Array2.Empty()); } [SecurityCritical] private bool TryCreateResourceStream(uint offset, out DataReaderFactory dataReaderFactory, out uint resourceOffset, out uint resourceLength) { dataReaderFactory = null; resourceOffset = 0u; resourceLength = 0u; try { IPEImage pEImage = metadata.PEImage; ImageDataDirectory imageDataDirectory = metadata.ImageCor20Header.Resources; if (imageDataDirectory.VirtualAddress == (RVA)0u || imageDataDirectory.Size == 0) { return false; } DataReader dataReader = pEImage.CreateReader(); uint num = (uint)pEImage.ToFileOffset(imageDataDirectory.VirtualAddress); if (num == 0 || (ulong)((long)num + (long)offset) > 4294967295uL) { return false; } if ((ulong)((long)offset + 4L) > (ulong)imageDataDirectory.Size) { return false; } if ((ulong)((long)num + (long)offset + 4) > (ulong)dataReader.Length) { return false; } dataReader.Position = num + offset; resourceLength = dataReader.ReadUInt32(); resourceOffset = dataReader.Position; if (resourceLength == 0 || (ulong)((long)dataReader.Position + (long)resourceLength) > (ulong)dataReader.Length) { return false; } if ((ulong)((long)dataReader.Position - (long)num + resourceLength - 1) >= (ulong)imageDataDirectory.Size) { return false; } if (pEImage.MayHaveInvalidAddresses) { DataReader dataReader2 = pEImage.CreateReader((FileOffset)dataReader.Position, resourceLength); while (dataReader2.Position < dataReader2.Length) { dataReader2.ReadByte(); dataReader2.Position += Math.Min(dataReader2.BytesLeft, 4096u); } dataReader2.Position = dataReader2.Length - 1; dataReader2.ReadByte(); } dataReaderFactory = pEImage.DataReaderFactory; return true; } catch (IOException) { } catch (AccessViolationException) { } return false; } public CustomAttribute ReadCustomAttribute(uint caRid) { return ReadCustomAttribute(caRid, default(GenericParamContext)); } public CustomAttribute ReadCustomAttribute(uint caRid, GenericParamContext gpContext) { if (!TablesStream.TryReadCustomAttributeRow(caRid, out var row)) { return null; } return CustomAttributeReader.Read(this, ResolveCustomAttributeType(row.Type, gpContext), row.Value, gpContext); } public byte[] ReadDataAt(RVA rva, int size) { if (size < 0) { return null; } DataReader dataReader = Metadata.PEImage.CreateReader(rva, (uint)size); if (dataReader.Length < size) { return null; } return dataReader.ReadBytes(size); } public RVA GetNativeEntryPoint() { dnlib.DotNet.MD.ImageCor20Header imageCor20Header = Metadata.ImageCor20Header; if ((imageCor20Header.Flags & ComImageFlags.NativeEntryPoint) == 0) { return (RVA)0u; } return (RVA)imageCor20Header.EntryPointToken_or_RVA; } public IManagedEntryPoint GetManagedEntryPoint() { dnlib.DotNet.MD.ImageCor20Header imageCor20Header = Metadata.ImageCor20Header; if ((imageCor20Header.Flags & ComImageFlags.NativeEntryPoint) != 0) { return null; } return ResolveToken(imageCor20Header.EntryPointToken_or_RVA) as IManagedEntryPoint; } internal FieldDefMD ReadField(uint rid) { return new FieldDefMD(this, rid); } internal MethodDefMD ReadMethod(uint rid) { return new MethodDefMD(this, rid); } internal EventDefMD ReadEvent(uint rid) { return new EventDefMD(this, rid); } internal PropertyDefMD ReadProperty(uint rid) { return new PropertyDefMD(this, rid); } internal ParamDefMD ReadParam(uint rid) { return new ParamDefMD(this, rid); } internal GenericParamMD ReadGenericParam(uint rid) { return new GenericParamMD(this, rid); } internal GenericParamConstraintMD ReadGenericParamConstraint(uint rid) { return new GenericParamConstraintMD(this, rid, default(GenericParamContext)); } internal GenericParamConstraintMD ReadGenericParamConstraint(uint rid, GenericParamContext gpContext) { return new GenericParamConstraintMD(this, rid, gpContext); } internal dnlib.DotNet.Emit.MethodBody ReadMethodBody(MethodDefMD method, RVA rva, MethodImplAttributes implAttrs, GenericParamContext gpContext) { IMethodDecrypter methodDecrypter = this.methodDecrypter; if (methodDecrypter != null && methodDecrypter.GetMethodBody(method.OrigRid, rva, method.Parameters, gpContext, out var methodBody)) { if (methodBody is CilBody body) { return InitializeBodyFromPdb(method, body); } return methodBody; } if (rva == (RVA)0u) { return null; } return (implAttrs & MethodImplAttributes.CodeTypeMask) switch { MethodImplAttributes.IL => InitializeBodyFromPdb(method, ReadCilBody(method.Parameters, rva, gpContext)), MethodImplAttributes.Native => new NativeMethodBody(rva), _ => null, }; } private CilBody InitializeBodyFromPdb(MethodDefMD method, CilBody body) { pdbState?.InitializeMethodBody(this, method, body); return body; } internal void InitializeCustomDebugInfos(MethodDefMD method, CilBody body, IList customDebugInfos) { if (body != null) { pdbState?.InitializeCustomDebugInfos(method, body, customDebugInfos); } } public string ReadUserString(uint token) { IStringDecrypter stringDecrypter = this.stringDecrypter; if (stringDecrypter != null) { string text = stringDecrypter.ReadUserString(token); if (text != null) { return text; } } return USStream.ReadNoNull(token & 0xFFFFFF); } internal MethodExportInfo GetExportInfo(uint methodRid) { if (methodExportInfoProvider == null) { InitializeMethodExportInfoProvider(); } return methodExportInfoProvider.GetMethodExportInfo(100663296 + methodRid); } private void InitializeMethodExportInfoProvider() { Interlocked.CompareExchange(ref methodExportInfoProvider, new MethodExportInfoProvider(this), null); } public void NativeWrite(string filename) { NativeWrite(filename, null); } public void NativeWrite(string filename, NativeModuleWriterOptions options) { new NativeModuleWriter(this, options ?? new NativeModuleWriterOptions(this, optimizeImageSize: true)).Write(filename); } public void NativeWrite(Stream dest) { NativeWrite(dest, null); } public void NativeWrite(Stream dest, NativeModuleWriterOptions options) { new NativeModuleWriter(this, options ?? new NativeModuleWriterOptions(this, optimizeImageSize: true)).Write(dest); } public byte[] ReadBlob(uint token) { uint num = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Field: { if (TablesStream.TryReadFieldRow(num, out var row12)) { return BlobStream.Read(row12.Signature); } break; } case Table.Method: { if (TablesStream.TryReadMethodRow(num, out var row4)) { return BlobStream.Read(row4.Signature); } break; } case Table.MemberRef: { if (TablesStream.TryReadMemberRefRow(num, out var row8)) { return BlobStream.Read(row8.Signature); } break; } case Table.Constant: { if (TablesStream.TryReadConstantRow(num, out var row14)) { return BlobStream.Read(row14.Value); } break; } case Table.CustomAttribute: { if (TablesStream.TryReadCustomAttributeRow(num, out var row10)) { return BlobStream.Read(row10.Value); } break; } case Table.FieldMarshal: { if (TablesStream.TryReadFieldMarshalRow(num, out var row6)) { return BlobStream.Read(row6.NativeType); } break; } case Table.DeclSecurity: { if (TablesStream.TryReadDeclSecurityRow(num, out var row2)) { return BlobStream.Read(row2.PermissionSet); } break; } case Table.StandAloneSig: { if (TablesStream.TryReadStandAloneSigRow(num, out var row13)) { return BlobStream.Read(row13.Signature); } break; } case Table.Property: { if (TablesStream.TryReadPropertyRow(num, out var row11)) { return BlobStream.Read(row11.Type); } break; } case Table.TypeSpec: { if (TablesStream.TryReadTypeSpecRow(num, out var row9)) { return BlobStream.Read(row9.Signature); } break; } case Table.Assembly: { if (TablesStream.TryReadAssemblyRow(num, out var row7)) { return BlobStream.Read(row7.PublicKey); } break; } case Table.AssemblyRef: { if (TablesStream.TryReadAssemblyRefRow(num, out var row5)) { return BlobStream.Read(row5.PublicKeyOrToken); } break; } case Table.File: { if (TablesStream.TryReadFileRow(num, out var row3)) { return BlobStream.Read(row3.HashValue); } break; } case Table.MethodSpec: { if (TablesStream.TryReadMethodSpecRow(num, out var row)) { return BlobStream.Read(row.Instantiation); } break; } } return null; } } public enum ModuleKind { Console, Windows, Dll, NetModule } internal readonly struct ModuleLoader { private readonly ModuleDef module; private readonly ICancellationToken cancellationToken; private readonly Dictionary seen; private readonly Stack stack; private ModuleLoader(ModuleDef module, ICancellationToken cancellationToken) { this.module = module; this.cancellationToken = cancellationToken; seen = new Dictionary(16384); stack = new Stack(16384); } public static void LoadAll(ModuleDef module, ICancellationToken cancellationToken) { new ModuleLoader(module, cancellationToken).Load(); } private void Add(UTF8String a) { } private void Add(Guid? a) { } private void Add(ushort a) { } private void Add(AssemblyHashAlgorithm a) { } private void Add(Version a) { } private void Add(AssemblyAttributes a) { } private void Add(PublicKeyBase a) { } private void Add(RVA a) { } private void Add(IManagedEntryPoint a) { } private void Add(string a) { } private void Add(WinMDStatus a) { } private void Add(TypeAttributes a) { } private void Add(FieldAttributes a) { } private void Add(uint? a) { } private void Add(byte[] a) { } private void Add(MethodImplAttributes a) { } private void Add(MethodAttributes a) { } private void Add(MethodSemanticsAttributes a) { } private void Add(ParamAttributes a) { } private void Add(ElementType a) { } private void Add(SecurityAction a) { } private void Add(EventAttributes a) { } private void Add(PropertyAttributes a) { } private void Add(PInvokeAttributes a) { } private void Add(FileAttributes a) { } private void Add(ManifestResourceAttributes a) { } private void Add(GenericParamAttributes a) { } private void Add(NativeType a) { } private void Load() { LoadAllTables(); Load(module); Process(); } private void Process() { while (stack.Count != 0) { if (cancellationToken != null) { cancellationToken.ThrowIfCancellationRequested(); } object o = stack.Pop(); LoadObj(o); } } private void LoadAllTables() { ITokenResolver tokenResolver = module; if (tokenResolver == null) { return; } Table table = Table.Module; while ((int)table <= 44) { uint num = 1u; while (true) { IMDTokenProvider iMDTokenProvider = tokenResolver.ResolveToken(new MDToken(table, num).Raw, default(GenericParamContext)); if (iMDTokenProvider == null) { break; } Add(iMDTokenProvider); Process(); num++; } table++; } } private void LoadObj(object o) { if (o is TypeSig ts) { Load(ts); } else if (o is IMDTokenProvider mdt) { Load(mdt); } else if (o is CustomAttribute obj) { Load(obj); } else if (o is SecurityAttribute obj2) { Load(obj2); } else if (o is CANamedArgument obj3) { Load(obj3); } else if (o is Parameter obj4) { Load(obj4); } else if (o is PdbMethod obj5) { Load(obj5); } else if (o is ResourceDirectory obj6) { Load(obj6); } else if (o is ResourceData obj7) { Load(obj7); } } private void Load(TypeSig ts) { if (ts != null) { Add(ts.Next); switch (ts.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: Add(((TypeDefOrRefSig)ts).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: { GenericSig genericSig = (GenericSig)ts; Add(genericSig.OwnerType); Add(genericSig.OwnerMethod); break; } case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)ts; Add(genericInstSig.GenericType); Add(genericInstSig.GenericArguments); break; } case ElementType.FnPtr: { FnPtrSig fnPtrSig = (FnPtrSig)ts; Add(fnPtrSig.Signature); break; } case ElementType.CModReqd: case ElementType.CModOpt: { ModifierSig modifierSig = (ModifierSig)ts; Add(modifierSig.Modifier); break; } case ElementType.End: case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.R: case ElementType.SZArray: case ElementType.Internal: case (ElementType)34: case (ElementType)35: case (ElementType)36: case (ElementType)37: case (ElementType)38: case (ElementType)39: case (ElementType)40: case (ElementType)41: case (ElementType)42: case (ElementType)43: case (ElementType)44: case (ElementType)45: case (ElementType)46: case (ElementType)47: case (ElementType)48: case (ElementType)49: case (ElementType)50: case (ElementType)51: case (ElementType)52: case (ElementType)53: case (ElementType)54: case (ElementType)55: case (ElementType)56: case (ElementType)57: case (ElementType)58: case (ElementType)59: case (ElementType)60: case (ElementType)61: case (ElementType)62: case ElementType.Module: case (ElementType)64: case ElementType.Sentinel: case (ElementType)66: case (ElementType)67: case (ElementType)68: case ElementType.Pinned: break; } } } private void Load(IMDTokenProvider mdt) { if (mdt == null) { return; } switch (mdt.MDToken.Table) { case Table.Module: Load((ModuleDef)mdt); break; case Table.TypeRef: Load((TypeRef)mdt); break; case Table.TypeDef: Load((TypeDef)mdt); break; case Table.Field: Load((FieldDef)mdt); break; case Table.Method: Load((MethodDef)mdt); break; case Table.Param: Load((ParamDef)mdt); break; case Table.InterfaceImpl: Load((InterfaceImpl)mdt); break; case Table.MemberRef: Load((MemberRef)mdt); break; case Table.Constant: Load((Constant)mdt); break; case Table.DeclSecurity: Load((DeclSecurity)mdt); break; case Table.ClassLayout: Load((ClassLayout)mdt); break; case Table.StandAloneSig: Load((StandAloneSig)mdt); break; case Table.Event: Load((EventDef)mdt); break; case Table.Property: Load((PropertyDef)mdt); break; case Table.ModuleRef: Load((ModuleRef)mdt); break; case Table.TypeSpec: Load((TypeSpec)mdt); break; case Table.ImplMap: Load((ImplMap)mdt); break; case Table.Assembly: Load((AssemblyDef)mdt); break; case Table.AssemblyRef: Load((AssemblyRef)mdt); break; case Table.File: Load((FileDef)mdt); break; case Table.ExportedType: Load((ExportedType)mdt); break; case Table.GenericParam: Load((GenericParam)mdt); break; case Table.MethodSpec: Load((MethodSpec)mdt); break; case Table.GenericParamConstraint: Load((GenericParamConstraint)mdt); break; case Table.ManifestResource: if (mdt is Resource obj) { Load(obj); } else if (mdt is ManifestResource obj2) { Load(obj2); } break; case Table.FieldPtr: case Table.MethodPtr: case Table.ParamPtr: case Table.CustomAttribute: case Table.FieldMarshal: case Table.FieldLayout: case Table.EventMap: case Table.EventPtr: case Table.PropertyMap: case Table.PropertyPtr: case Table.MethodSemantics: case Table.MethodImpl: case Table.FieldRVA: case Table.ENCLog: case Table.ENCMap: case Table.AssemblyProcessor: case Table.AssemblyOS: case Table.AssemblyRefProcessor: case Table.AssemblyRefOS: case Table.NestedClass: case (Table)45: case (Table)46: case (Table)47: case Table.Document: case Table.MethodDebugInformation: case Table.LocalScope: case Table.LocalVariable: case Table.LocalConstant: case Table.ImportScope: case Table.StateMachineMethod: case Table.CustomDebugInformation: break; } } private void Load(ModuleDef obj) { if (obj != null && obj == module) { Add(obj.Generation); Add(obj.Name); Add(obj.Mvid); Add(obj.EncId); Add(obj.EncBaseId); Add(obj.CustomAttributes); Add(obj.Assembly); Add(obj.Types); Add(obj.ExportedTypes); Add(obj.NativeEntryPoint); Add(obj.ManagedEntryPoint); Add(obj.Resources); Add(obj.VTableFixups); Add(obj.Location); Add(obj.Win32Resources); Add(obj.RuntimeVersion); Add(obj.WinMDStatus); Add(obj.RuntimeVersionWinMD); Add(obj.WinMDVersion); Add(obj.PdbState); } } private void Load(TypeRef obj) { if (obj != null) { Add(obj.ResolutionScope); Add(obj.Name); Add(obj.Namespace); Add(obj.CustomAttributes); } } private void Load(TypeDef obj) { if (obj != null) { Add(obj.Module2); Add(obj.Attributes); Add(obj.Name); Add(obj.Namespace); Add(obj.BaseType); Add(obj.Fields); Add(obj.Methods); Add(obj.GenericParameters); Add(obj.Interfaces); Add(obj.DeclSecurities); Add(obj.ClassLayout); Add(obj.DeclaringType); Add(obj.DeclaringType2); Add(obj.NestedTypes); Add(obj.Events); Add(obj.Properties); Add(obj.CustomAttributes); } } private void Load(FieldDef obj) { if (obj != null) { Add(obj.CustomAttributes); Add(obj.Attributes); Add(obj.Name); Add(obj.Signature); Add(obj.FieldOffset); Add(obj.MarshalType); Add(obj.RVA); Add(obj.InitialValue); Add(obj.ImplMap); Add(obj.Constant); Add(obj.DeclaringType); } } private void Load(MethodDef obj) { if (obj != null) { Add(obj.RVA); Add(obj.ImplAttributes); Add(obj.Attributes); Add(obj.Name); Add(obj.Signature); Add(obj.ParamDefs); Add(obj.GenericParameters); Add(obj.DeclSecurities); Add(obj.ImplMap); Add(obj.MethodBody); Add(obj.CustomAttributes); Add(obj.Overrides); Add(obj.DeclaringType); Add(obj.Parameters); Add(obj.SemanticsAttributes); } } private void Load(ParamDef obj) { if (obj != null) { Add(obj.DeclaringMethod); Add(obj.Attributes); Add(obj.Sequence); Add(obj.Name); Add(obj.MarshalType); Add(obj.Constant); Add(obj.CustomAttributes); } } private void Load(InterfaceImpl obj) { if (obj != null) { Add(obj.Interface); Add(obj.CustomAttributes); } } private void Load(MemberRef obj) { if (obj != null) { Add(obj.Class); Add(obj.Name); Add(obj.Signature); Add(obj.CustomAttributes); } } private void Load(Constant obj) { if (obj != null) { Add(obj.Type); _ = obj.Value; } } private void Load(DeclSecurity obj) { if (obj != null) { Add(obj.Action); Add(obj.SecurityAttributes); Add(obj.CustomAttributes); obj.GetBlob(); } } private void Load(ClassLayout obj) { if (obj != null) { Add(obj.PackingSize); Add(obj.ClassSize); } } private void Load(StandAloneSig obj) { if (obj != null) { Add(obj.Signature); Add(obj.CustomAttributes); } } private void Load(EventDef obj) { if (obj != null) { Add(obj.Attributes); Add(obj.Name); Add(obj.EventType); Add(obj.CustomAttributes); Add(obj.AddMethod); Add(obj.InvokeMethod); Add(obj.RemoveMethod); Add(obj.OtherMethods); Add(obj.DeclaringType); } } private void Load(PropertyDef obj) { if (obj != null) { Add(obj.Attributes); Add(obj.Name); Add(obj.Type); Add(obj.Constant); Add(obj.CustomAttributes); Add(obj.GetMethods); Add(obj.SetMethods); Add(obj.OtherMethods); Add(obj.DeclaringType); } } private void Load(ModuleRef obj) { if (obj != null) { Add(obj.Name); Add(obj.CustomAttributes); } } private void Load(TypeSpec obj) { if (obj != null) { Add(obj.TypeSig); Add(obj.ExtraData); Add(obj.CustomAttributes); } } private void Load(ImplMap obj) { if (obj != null) { Add(obj.Attributes); Add(obj.Name); Add(obj.Module); } } private void Load(AssemblyDef obj) { if (obj != null && obj.ManifestModule == module) { Add(obj.HashAlgorithm); Add(obj.Version); Add(obj.Attributes); Add(obj.PublicKey); Add(obj.Name); Add(obj.Culture); Add(obj.DeclSecurities); Add(obj.Modules); Add(obj.CustomAttributes); } } private void Load(AssemblyRef obj) { if (obj != null) { Add(obj.Version); Add(obj.Attributes); Add(obj.PublicKeyOrToken); Add(obj.Name); Add(obj.Culture); Add(obj.Hash); Add(obj.CustomAttributes); } } private void Load(FileDef obj) { if (obj != null) { Add(obj.Flags); Add(obj.Name); Add(obj.HashValue); Add(obj.CustomAttributes); } } private void Load(ExportedType obj) { if (obj != null) { Add(obj.CustomAttributes); Add(obj.Attributes); Add(obj.TypeDefId); Add(obj.TypeName); Add(obj.TypeNamespace); Add(obj.Implementation); } } private void Load(Resource obj) { if (obj != null) { Add(obj.Offset); Add(obj.Name); Add(obj.Attributes); Add(obj.CustomAttributes); switch (obj.ResourceType) { case ResourceType.AssemblyLinked: { AssemblyLinkedResource assemblyLinkedResource = (AssemblyLinkedResource)obj; Add(assemblyLinkedResource.Assembly); break; } case ResourceType.Linked: { LinkedResource linkedResource = (LinkedResource)obj; Add(linkedResource.File); Add(linkedResource.Hash); break; } case ResourceType.Embedded: break; } } } private void Load(ManifestResource obj) { if (obj != null) { Add(obj.Offset); Add(obj.Flags); Add(obj.Name); Add(obj.Implementation); Add(obj.CustomAttributes); } } private void Load(GenericParam obj) { if (obj != null) { Add(obj.Owner); Add(obj.Number); Add(obj.Flags); Add(obj.Name); Add(obj.Kind); Add(obj.GenericParamConstraints); Add(obj.CustomAttributes); } } private void Load(MethodSpec obj) { if (obj != null) { Add(obj.Method); Add(obj.Instantiation); Add(obj.CustomAttributes); } } private void Load(GenericParamConstraint obj) { if (obj != null) { Add(obj.Owner); Add(obj.Constraint); Add(obj.CustomAttributes); } } private void Load(CANamedArgument obj) { if (obj != null) { Add(obj.Type); Add(obj.Name); Load(obj.Argument); } } private void Load(Parameter obj) { if (obj != null) { Add(obj.Type); } } private void Load(SecurityAttribute obj) { if (obj != null) { Add(obj.AttributeType); Add(obj.NamedArguments); } } private void Load(CustomAttribute obj) { if (obj != null) { Add(obj.Constructor); Add(obj.RawData); Add(obj.ConstructorArguments); Add(obj.NamedArguments); } } private void Load(MethodOverride obj) { Add(obj.MethodBody); Add(obj.MethodDeclaration); } private void AddCAValue(object obj) { if (obj is CAArgument) { Load((CAArgument)obj); } else if (obj is IList list) { Add(list); } else if (obj is IMDTokenProvider o) { Add(o); } } private void Load(CAArgument obj) { Add(obj.Type); AddCAValue(obj.Value); } private void Load(PdbMethod obj) { } private void Load(ResourceDirectory obj) { if (obj != null) { Add(obj.Directories); Add(obj.Data); } } private void Load(ResourceData obj) { } private void AddToStack(T t) where T : class { if (t != null && !seen.ContainsKey(t)) { seen[t] = true; stack.Push(t); } } private void Add(CustomAttribute obj) { AddToStack(obj); } private void Add(SecurityAttribute obj) { AddToStack(obj); } private void Add(CANamedArgument obj) { AddToStack(obj); } private void Add(Parameter obj) { AddToStack(obj); } private void Add(IMDTokenProvider o) { AddToStack(o); } private void Add(PdbMethod pdbMethod) { } private void Add(TypeSig ts) { AddToStack(ts); } private void Add(ResourceDirectory rd) { AddToStack(rd); } private void Add(ResourceData rd) { AddToStack(rd); } private void Add(IList list) where T : IMDTokenProvider { if (list == null) { return; } foreach (T item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (TypeSig item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (CustomAttribute item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (SecurityAttribute item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (MethodOverride item in list) { Load(item); } } private void Add(IList list) { if (list == null) { return; } foreach (CAArgument item in list) { Load(item); } } private void Add(IList list) { if (list == null) { return; } foreach (CANamedArgument item in list) { Add(item); } } private void Add(ParameterList list) { if (list == null) { return; } foreach (Parameter item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (Instruction item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (ExceptionHandler item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (Local item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (ResourceDirectory item in list) { Add(item); } } private void Add(IList list) { if (list == null) { return; } foreach (ResourceData item in list) { Add(item); } } private void Add(VTableFixups vtf) { if (vtf == null) { return; } foreach (VTable item in vtf) { foreach (IMethod item2 in item) { Add(item2); } } } private void Add(Win32Resources vtf) { if (vtf != null) { Add(vtf.Root); } } private void Add(CallingConventionSig sig) { if (sig is MethodBaseSig msig) { Add(msig); } else if (sig is FieldSig fsig) { Add(fsig); } else if (sig is LocalSig lsig) { Add(lsig); } else if (sig is GenericInstMethodSig gsig) { Add(gsig); } } private void Add(MethodBaseSig msig) { if (msig != null) { Add(msig.ExtraData); Add(msig.RetType); Add(msig.Params); Add(msig.ParamsAfterSentinel); } } private void Add(FieldSig fsig) { if (fsig != null) { Add(fsig.ExtraData); Add(fsig.Type); } } private void Add(LocalSig lsig) { if (lsig != null) { Add(lsig.ExtraData); Add(lsig.Locals); } } private void Add(GenericInstMethodSig gsig) { if (gsig != null) { Add(gsig.ExtraData); Add(gsig.GenericArguments); } } private void Add(MarshalType mt) { if (mt != null) { Add(mt.NativeType); } } private void Add(dnlib.DotNet.Emit.MethodBody mb) { if (mb is CilBody body) { Add(body); } else if (mb is NativeMethodBody body2) { Add(body2); } } private void Add(NativeMethodBody body) { if (body != null) { Add(body.RVA); } } private void Add(CilBody body) { if (body != null) { Add(body.Instructions); Add(body.ExceptionHandlers); Add(body.Variables); Add(body.PdbMethod); } } private void Add(Instruction instr) { if (instr != null) { if (instr.Operand is IMDTokenProvider o) { Add(o); } else if (instr.Operand is Parameter obj) { Add(obj); } else if (instr.Operand is Local local) { Add(local); } else if (instr.Operand is CallingConventionSig sig) { Add(sig); } } } private void Add(ExceptionHandler eh) { if (eh != null) { Add(eh.CatchType); } } private void Add(Local local) { if (local != null) { Add(local.Type); } } private void Add(PdbState state) { if (state != null) { Add(state.UserEntryPoint); } } } public abstract class ModuleRef : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IMemberRefParent, IFullName, IHasCustomDebugInformation, IResolutionScope, IModule, IScope, IOwnerModule { protected uint rid; protected ModuleDef module; protected UTF8String name; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.ModuleRef, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 12; public int MemberRefParentTag => 2; public int ResolutionScopeTag => 1; public ScopeType ScopeType => ScopeType.ModuleRef; public string ScopeName => FullName; public UTF8String Name { get { return name; } set { name = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 12; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public ModuleDef Module => module; public ModuleDef DefinitionModule { get { if (module == null) { return null; } UTF8String a = name; if (UTF8String.CaseInsensitiveEquals(a, module.Name)) { return module; } return DefinitionAssembly?.FindModule(a); } } public AssemblyDef DefinitionAssembly => module?.Assembly; public string FullName => UTF8String.ToSystemStringOrEmpty(name); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } public override string ToString() { return FullName; } } public class ModuleRefUser : ModuleRef { public ModuleRefUser(ModuleDef module) : this(module, UTF8String.Empty) { } public ModuleRefUser(ModuleDef module, UTF8String name) { base.module = module; base.name = name; } } internal sealed class ModuleRefMD : ModuleRef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ModuleRef, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public ModuleRefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; module = readerModule; readerModule.TablesStream.TryReadModuleRefRow(origRid, out var row); name = readerModule.StringsStream.ReadNoNull(row.Name); } } public enum NativeType : uint { End = 0u, Void = 1u, Boolean = 2u, I1 = 3u, U1 = 4u, I2 = 5u, U2 = 6u, I4 = 7u, U4 = 8u, I8 = 9u, U8 = 10u, R4 = 11u, R8 = 12u, SysChar = 13u, Variant = 14u, Currency = 15u, Ptr = 16u, Decimal = 17u, Date = 18u, BStr = 19u, LPStr = 20u, LPWStr = 21u, LPTStr = 22u, FixedSysString = 23u, ObjectRef = 24u, IUnknown = 25u, IDispatch = 26u, Struct = 27u, IntF = 28u, SafeArray = 29u, FixedArray = 30u, Int = 31u, UInt = 32u, NestedStruct = 33u, ByValStr = 34u, ANSIBStr = 35u, TBStr = 36u, VariantBool = 37u, Func = 38u, ASAny = 40u, Array = 42u, LPStruct = 43u, CustomMarshaler = 44u, Error = 45u, IInspectable = 46u, HString = 47u, LPUTF8Str = 48u, Max = 80u, NotInitialized = 4294967294u, RawBlob = uint.MaxValue } public sealed class NullResolver : IAssemblyResolver, IResolver, ITypeResolver, IMemberRefResolver { public static readonly NullResolver Instance = new NullResolver(); private NullResolver() { } public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) { return null; } public TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule) { return null; } public IMemberForwarded Resolve(MemberRef memberRef) { return null; } } [Flags] public enum ParamAttributes : ushort { In = 1, Out = 2, Lcid = 4, Retval = 8, Optional = 0x10, HasDefault = 0x1000, HasFieldMarshal = 0x2000 } [DebuggerDisplay("{Sequence} {Name}")] public abstract class ParamDef : IHasConstant, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName, IHasFieldMarshal, IHasCustomDebugInformation { protected uint rid; private readonly Lock theLock = Lock.Create(); protected MethodDef declaringMethod; protected int attributes; protected ushort sequence; protected UTF8String name; protected MarshalType marshalType; protected bool marshalType_isInitialized; protected Constant constant; protected bool constant_isInitialized; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.Param, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasConstantTag => 1; public int HasCustomAttributeTag => 4; public int HasFieldMarshalTag => 1; public MethodDef DeclaringMethod { get { return declaringMethod; } internal set { declaringMethod = value; } } public ParamAttributes Attributes { get { return (ParamAttributes)attributes; } set { attributes = (int)value; } } public ushort Sequence { get { return sequence; } set { sequence = value; } } public UTF8String Name { get { return name; } set { name = value; } } public MarshalType MarshalType { get { if (!marshalType_isInitialized) { InitializeMarshalType(); } return marshalType; } set { theLock.EnterWriteLock(); try { marshalType = value; marshalType_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public Constant Constant { get { if (!constant_isInitialized) { InitializeConstant(); } return constant; } set { theLock.EnterWriteLock(); try { constant = value; constant_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 4; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasConstant => Constant != null; public ElementType ElementType => Constant?.Type ?? ElementType.End; public bool HasMarshalType => MarshalType != null; public string FullName { get { UTF8String uTF8String = name; if (UTF8String.IsNullOrEmpty(uTF8String)) { return $"A_{sequence}"; } return uTF8String.String; } } public bool IsIn { get { return ((ushort)attributes & 1) != 0; } set { ModifyAttributes(value, ParamAttributes.In); } } public bool IsOut { get { return ((ushort)attributes & 2) != 0; } set { ModifyAttributes(value, ParamAttributes.Out); } } public bool IsLcid { get { return ((ushort)attributes & 4) != 0; } set { ModifyAttributes(value, ParamAttributes.Lcid); } } public bool IsRetval { get { return ((ushort)attributes & 8) != 0; } set { ModifyAttributes(value, ParamAttributes.Retval); } } public bool IsOptional { get { return ((ushort)attributes & 0x10) != 0; } set { ModifyAttributes(value, ParamAttributes.Optional); } } public bool HasDefault { get { return ((ushort)attributes & 0x1000) != 0; } set { ModifyAttributes(value, ParamAttributes.HasDefault); } } public bool HasFieldMarshal { get { return ((ushort)attributes & 0x2000) != 0; } set { ModifyAttributes(value, ParamAttributes.HasFieldMarshal); } } private void InitializeMarshalType() { theLock.EnterWriteLock(); try { if (!marshalType_isInitialized) { marshalType = GetMarshalType_NoLock(); marshalType_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual MarshalType GetMarshalType_NoLock() { return null; } protected void ResetMarshalType() { marshalType_isInitialized = false; } private void InitializeConstant() { theLock.EnterWriteLock(); try { if (!constant_isInitialized) { constant = GetConstant_NoLock(); constant_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual Constant GetConstant_NoLock() { return null; } protected void ResetConstant() { constant_isInitialized = false; } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(bool set, ParamAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } } public class ParamDefUser : ParamDef { public ParamDefUser() { } public ParamDefUser(UTF8String name) : this(name, 0) { } public ParamDefUser(UTF8String name, ushort sequence) : this(name, sequence, (ParamAttributes)0) { } public ParamDefUser(UTF8String name, ushort sequence, ParamAttributes flags) { base.name = name; base.sequence = sequence; attributes = (int)flags; } } internal sealed class ParamDefMD : ParamDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override MarshalType GetMarshalType_NoLock() { return readerModule.ReadMarshalType(Table.Param, origRid, GenericParamContext.Create(declaringMethod)); } protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.Metadata.GetConstantRid(Table.Param, origRid)); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Param, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), GenericParamContext.Create(declaringMethod), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public ParamDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadParamRow(origRid, out var row); attributes = row.Flags; sequence = row.Sequence; name = readerModule.StringsStream.ReadNoNull(row.Name); declaringMethod = readerModule.GetOwner(this); } internal ParamDefMD InitializeAll() { MemberMDInitializer.Initialize(base.DeclaringMethod); MemberMDInitializer.Initialize(base.Attributes); MemberMDInitializer.Initialize(base.Sequence); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.MarshalType); MemberMDInitializer.Initialize(base.Constant); MemberMDInitializer.Initialize(base.CustomAttributes); return this; } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ParameterList_CollectionDebugView))] public sealed class ParameterList : IList, ICollection, IEnumerable, IEnumerable { public struct Enumerator : IEnumerator, IEnumerator, IDisposable { private readonly ParameterList list; private List.Enumerator listEnumerator; private Parameter current; public Parameter Current => current; Parameter IEnumerator.Current => current; object IEnumerator.Current => current; internal Enumerator(ParameterList list) { this.list = list; current = null; list.theLock.EnterReadLock(); try { listEnumerator = list.parameters.GetEnumerator(); } finally { list.theLock.ExitReadLock(); } } public bool MoveNext() { list.theLock.EnterWriteLock(); try { bool result = listEnumerator.MoveNext(); current = listEnumerator.Current; return result; } finally { list.theLock.ExitWriteLock(); } } public void Dispose() { listEnumerator.Dispose(); } void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly MethodDef method; private readonly List parameters; private readonly Parameter hiddenThisParameter; private ParamDef hiddenThisParamDef; private readonly Parameter returnParameter; private int methodSigIndexBase; private readonly Lock theLock = Lock.Create(); public MethodDef Method => method; public int Count { get { theLock.EnterReadLock(); try { return parameters.Count; } finally { theLock.ExitReadLock(); } } } public int MethodSigIndexBase { get { theLock.EnterReadLock(); try { return (methodSigIndexBase == 1) ? 1 : 0; } finally { theLock.ExitReadLock(); } } } public Parameter this[int index] { get { theLock.EnterReadLock(); try { return parameters[index]; } finally { theLock.ExitReadLock(); } } set { throw new NotSupportedException(); } } public Parameter ReturnParameter { get { theLock.EnterReadLock(); try { return returnParameter; } finally { theLock.ExitReadLock(); } } } bool ICollection.IsReadOnly => true; public ParameterList(MethodDef method, TypeDef declaringType) { this.method = method; parameters = new List(); methodSigIndexBase = -1; hiddenThisParameter = new Parameter(this, 0, -2); returnParameter = new Parameter(this, -1, -1); UpdateThisParameterType(declaringType); UpdateParameterTypes(); } internal void UpdateThisParameterType(TypeDef methodDeclaringType) { theLock.EnterWriteLock(); try { if (methodDeclaringType == null) { hiddenThisParameter.Type = null; return; } bool isValueType = methodDeclaringType.IsValueType; ClassOrValueTypeSig classOrValueTypeSig = ((!isValueType) ? ((ClassOrValueTypeSig)new ClassSig(methodDeclaringType)) : ((ClassOrValueTypeSig)new ValueTypeSig(methodDeclaringType))); TypeSig typeSig; if (methodDeclaringType.HasGenericParameters) { int count = methodDeclaringType.GenericParameters.Count; List list = new List(count); for (int i = 0; i < count; i++) { list.Add(new GenericVar(i, methodDeclaringType)); } typeSig = new GenericInstSig(classOrValueTypeSig, list); } else { typeSig = classOrValueTypeSig; } hiddenThisParameter.Type = (isValueType ? new ByRefSig(typeSig) : typeSig); } finally { theLock.ExitWriteLock(); } } public void UpdateParameterTypes() { theLock.EnterWriteLock(); try { MethodSig methodSig = method.MethodSig; if (methodSig == null) { methodSigIndexBase = -1; parameters.Clear(); return; } if (UpdateThisParameter_NoLock(methodSig)) { parameters.Clear(); } returnParameter.Type = methodSig.RetType; ResizeParameters_NoLock(methodSig.Params.Count + methodSigIndexBase); if (methodSigIndexBase > 0) { parameters[0] = hiddenThisParameter; } for (int i = 0; i < methodSig.Params.Count; i++) { parameters[i + methodSigIndexBase].Type = methodSig.Params[i]; } } finally { theLock.ExitWriteLock(); } } private bool UpdateThisParameter_NoLock(MethodSig methodSig) { int num = ((methodSig != null) ? (methodSig.ImplicitThis ? 1 : 0) : (-1)); if (methodSigIndexBase == num) { return false; } methodSigIndexBase = num; return true; } private void ResizeParameters_NoLock(int length) { if (parameters.Count == length) { return; } if (parameters.Count < length) { for (int i = parameters.Count; i < length; i++) { parameters.Add(new Parameter(this, i, i - methodSigIndexBase)); } } else { while (parameters.Count > length) { parameters.RemoveAt(parameters.Count - 1); } } } internal ParamDef FindParamDef(Parameter param) { theLock.EnterReadLock(); try { return FindParamDef_NoLock(param); } finally { theLock.ExitReadLock(); } } private ParamDef FindParamDef_NoLock(Parameter param) { int num; if (param.IsReturnTypeParameter) { num = 0; } else { if (!param.IsNormalMethodParameter) { return hiddenThisParamDef; } num = param.MethodSigIndex + 1; } IList paramDefs = method.ParamDefs; int count = paramDefs.Count; for (int i = 0; i < count; i++) { ParamDef paramDef = paramDefs[i]; if (paramDef != null && paramDef.Sequence == num) { return paramDef; } } return null; } internal void TypeUpdated(Parameter param) { MethodSig methodSig = method.MethodSig; if (methodSig != null) { int methodSigIndex = param.MethodSigIndex; if (methodSigIndex == -1) { methodSig.RetType = param.Type; } else if (methodSigIndex >= 0) { methodSig.Params[methodSigIndex] = param.Type; } } } internal void CreateParamDef(Parameter param) { theLock.EnterWriteLock(); try { ParamDef paramDef = FindParamDef_NoLock(param); if (paramDef == null) { if (param.IsHiddenThisParameter) { hiddenThisParamDef = UpdateRowId_NoLock(new ParamDefUser(UTF8String.Empty, ushort.MaxValue, (ParamAttributes)0)); return; } int num = ((!param.IsReturnTypeParameter) ? (param.MethodSigIndex + 1) : 0); paramDef = UpdateRowId_NoLock(new ParamDefUser(UTF8String.Empty, (ushort)num, (ParamAttributes)0)); method.ParamDefs.Add(paramDef); } } finally { theLock.ExitWriteLock(); } } private ParamDef UpdateRowId_NoLock(ParamDef pd) { TypeDef declaringType = method.DeclaringType; if (declaringType == null) { return pd; } ModuleDef module = declaringType.Module; if (module == null) { return pd; } return module.UpdateRowId(pd); } public int IndexOf(Parameter item) { theLock.EnterReadLock(); try { return parameters.IndexOf(item); } finally { theLock.ExitReadLock(); } } void IList.Insert(int index, Parameter item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.Add(Parameter item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(Parameter item) { theLock.EnterReadLock(); try { return parameters.Contains(item); } finally { theLock.ExitReadLock(); } } void ICollection.CopyTo(Parameter[] array, int arrayIndex) { theLock.EnterReadLock(); try { parameters.CopyTo(array, arrayIndex); } finally { theLock.ExitReadLock(); } } bool ICollection.Remove(Parameter item) { throw new NotSupportedException(); } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public sealed class Parameter : IVariable { private readonly ParameterList parameterList; private TypeSig typeSig; private readonly int paramIndex; private readonly int methodSigIndex; public const int HIDDEN_THIS_METHOD_SIG_INDEX = -2; public const int RETURN_TYPE_METHOD_SIG_INDEX = -1; public int Index => paramIndex; public int MethodSigIndex => methodSigIndex; public bool IsNormalMethodParameter => methodSigIndex >= 0; public bool IsHiddenThisParameter => methodSigIndex == -2; public bool IsReturnTypeParameter => methodSigIndex == -1; public TypeSig Type { get { return typeSig; } set { typeSig = value; if (parameterList != null) { parameterList.TypeUpdated(this); } } } public MethodDef Method => parameterList?.Method; public ParamDef ParamDef => parameterList?.FindParamDef(this); public bool HasParamDef => ParamDef != null; public string Name { get { ParamDef paramDef = ParamDef; if (paramDef != null) { return UTF8String.ToSystemStringOrEmpty(paramDef.Name); } return string.Empty; } set { ParamDef paramDef = ParamDef; if (paramDef != null) { paramDef.Name = value; } } } public Parameter(int paramIndex) { this.paramIndex = paramIndex; methodSigIndex = paramIndex; } public Parameter(int paramIndex, TypeSig type) { this.paramIndex = paramIndex; methodSigIndex = paramIndex; typeSig = type; } public Parameter(int paramIndex, int methodSigIndex) { this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; } public Parameter(int paramIndex, int methodSigIndex, TypeSig type) { this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; typeSig = type; } internal Parameter(ParameterList parameterList, int paramIndex, int methodSigIndex) { this.parameterList = parameterList; this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; } public void CreateParamDef() { if (parameterList != null) { parameterList.CreateParamDef(this); } } public override string ToString() { string name = Name; if (string.IsNullOrEmpty(name)) { if (IsReturnTypeParameter) { return "RET_PARAM"; } return $"A_{paramIndex}"; } return name; } } [Flags] public enum PInvokeAttributes : ushort { NoMangle = 1, CharSetMask = 6, CharSetNotSpec = 0, CharSetAnsi = 2, CharSetUnicode = 4, CharSetAuto = 6, BestFitUseAssem = 0, BestFitEnabled = 0x10, BestFitDisabled = 0x20, BestFitMask = 0x30, ThrowOnUnmappableCharUseAssem = 0, ThrowOnUnmappableCharEnabled = 0x1000, ThrowOnUnmappableCharDisabled = 0x2000, ThrowOnUnmappableCharMask = 0x3000, SupportsLastError = 0x40, CallConvMask = 0x700, CallConvWinapi = 0x100, CallConvCdecl = 0x200, CallConvStdcall = 0x300, CallConvStdCall = 0x300, CallConvThiscall = 0x400, CallConvFastcall = 0x500 } [Flags] public enum PropertyAttributes : ushort { SpecialName = 0x200, RTSpecialName = 0x400, HasDefault = 0x1000 } public abstract class PropertyDef : IHasConstant, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IFullName, IHasSemantic, IMemberRef, IOwnerModule, IIsTypeOrMethod, IHasCustomDebugInformation, IMemberDef, IDnlibDef { protected uint rid; private readonly Lock theLock = Lock.Create(); protected int attributes; protected UTF8String name; protected CallingConventionSig type; protected Constant constant; protected bool constant_isInitialized; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; protected IList getMethods; protected IList setMethods; protected IList otherMethods; protected TypeDef declaringType2; public MDToken MDToken => new MDToken(Table.Property, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasConstantTag => 2; public int HasCustomAttributeTag => 9; public int HasSemanticTag => 1; public PropertyAttributes Attributes { get { return (PropertyAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public CallingConventionSig Type { get { return type; } set { type = value; } } public Constant Constant { get { if (!constant_isInitialized) { InitializeConstant(); } return constant; } set { theLock.EnterWriteLock(); try { constant = value; constant_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public int HasCustomDebugInformationTag => 9; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public MethodDef GetMethod { get { if (otherMethods == null) { InitializePropertyMethods(); } if (getMethods.Count != 0) { return getMethods[0]; } return null; } set { if (otherMethods == null) { InitializePropertyMethods(); } if (value == null) { getMethods.Clear(); } else if (getMethods.Count == 0) { getMethods.Add(value); } else { getMethods[0] = value; } } } public MethodDef SetMethod { get { if (otherMethods == null) { InitializePropertyMethods(); } if (setMethods.Count != 0) { return setMethods[0]; } return null; } set { if (otherMethods == null) { InitializePropertyMethods(); } if (value == null) { setMethods.Clear(); } else if (setMethods.Count == 0) { setMethods.Add(value); } else { setMethods[0] = value; } } } public IList GetMethods { get { if (otherMethods == null) { InitializePropertyMethods(); } return getMethods; } } public IList SetMethods { get { if (otherMethods == null) { InitializePropertyMethods(); } return setMethods; } } public IList OtherMethods { get { if (otherMethods == null) { InitializePropertyMethods(); } return otherMethods; } } public bool IsEmpty { get { if (GetMethods.Count == 0 && setMethods.Count == 0) { return otherMethods.Count == 0; } return false; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public bool HasOtherMethods => OtherMethods.Count > 0; public bool HasConstant => Constant != null; public ElementType ElementType => Constant?.Type ?? ElementType.End; public PropertySig PropertySig { get { return type as PropertySig; } set { type = value; } } public TypeDef DeclaringType { get { return declaringType2; } set { TypeDef typeDef = DeclaringType2; if (typeDef != value) { typeDef?.Properties.Remove(this); value?.Properties.Add(this); } } } ITypeDefOrRef IMemberRef.DeclaringType => declaringType2; public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } public ModuleDef Module => declaringType2?.Module; public string FullName => FullNameFactory.PropertyFullName(declaringType2?.FullName, name, type); bool IIsTypeOrMethod.IsType => false; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => true; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public bool IsSpecialName { get { return ((ushort)attributes & 0x200) != 0; } set { ModifyAttributes(value, PropertyAttributes.SpecialName); } } public bool IsRuntimeSpecialName { get { return ((ushort)attributes & 0x400) != 0; } set { ModifyAttributes(value, PropertyAttributes.RTSpecialName); } } public bool HasDefault { get { return ((ushort)attributes & 0x1000) != 0; } set { ModifyAttributes(value, PropertyAttributes.HasDefault); } } private void InitializeConstant() { theLock.EnterWriteLock(); try { if (!constant_isInitialized) { constant = GetConstant_NoLock(); constant_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual Constant GetConstant_NoLock() { return null; } protected void ResetConstant() { constant_isInitialized = false; } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void InitializePropertyMethods() { theLock.EnterWriteLock(); try { if (otherMethods == null) { InitializePropertyMethods_NoLock(); } } finally { theLock.ExitWriteLock(); } } protected virtual void InitializePropertyMethods_NoLock() { getMethods = new List(); setMethods = new List(); otherMethods = new List(); } protected void ResetMethods() { otherMethods = null; } private void ModifyAttributes(bool set, PropertyAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~(uint)flags); } } public override string ToString() { return FullName; } } public class PropertyDefUser : PropertyDef { public PropertyDefUser() { } public PropertyDefUser(UTF8String name) : this(name, null) { } public PropertyDefUser(UTF8String name, PropertySig sig) : this(name, sig, (PropertyAttributes)0) { } public PropertyDefUser(UTF8String name, PropertySig sig, PropertyAttributes flags) { base.name = name; type = sig; attributes = (int)flags; } } internal sealed class PropertyDefMD : PropertyDef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.Metadata.GetConstantRid(Table.Property, origRid)); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.Property, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public PropertyDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadPropertyRow(origRid, out var row); attributes = row.PropFlags; name = readerModule.StringsStream.ReadNoNull(row.Name); declaringType2 = readerModule.GetOwnerType(this); type = readerModule.ReadSignature(row.Type, new GenericParamContext(declaringType2)); } internal PropertyDefMD InitializeAll() { MemberMDInitializer.Initialize(base.Attributes); MemberMDInitializer.Initialize(base.Name); MemberMDInitializer.Initialize(base.Type); MemberMDInitializer.Initialize(base.Constant); MemberMDInitializer.Initialize(base.CustomAttributes); MemberMDInitializer.Initialize(base.GetMethod); MemberMDInitializer.Initialize(base.SetMethod); MemberMDInitializer.Initialize(base.OtherMethods); MemberMDInitializer.Initialize(base.DeclaringType); return this; } protected override void InitializePropertyMethods_NoLock() { if (otherMethods == null) { IList list; IList list2; IList list3; if (!(declaringType2 is TypeDefMD typeDefMD)) { list = new List(); list2 = new List(); list3 = new List(); } else { typeDefMD.InitializeProperty(this, out list, out list2, out list3); } getMethods = list; setMethods = list2; otherMethods = list3; } } } public sealed class PublicKey : PublicKeyBase { private const AssemblyHashAlgorithm DEFAULT_ALGORITHM = AssemblyHashAlgorithm.SHA1; private PublicKeyToken publicKeyToken; public override PublicKeyToken Token { get { if (publicKeyToken == null && !base.IsNullOrEmpty) { Interlocked.CompareExchange(ref publicKeyToken, AssemblyHash.CreatePublicKeyToken(data), null); } return publicKeyToken; } } public override byte[] Data => data; public PublicKey() : base((byte[])null) { } public PublicKey(byte[] data) : base(data) { } public PublicKey(string hexString) : base(hexString) { } public override bool Equals(object obj) { if (this == obj) { return true; } if (!(obj is PublicKey publicKey)) { return false; } return Utils.Equals(Data, publicKey.Data); } public override int GetHashCode() { return Utils.GetHashCode(Data); } } public abstract class PublicKeyBase { protected readonly byte[] data; private static readonly byte[] EmptyByteArray = Array2.Empty(); public bool IsNullOrEmpty { get { if (data != null) { return data.Length == 0; } return true; } } public bool IsNull => Data == null; public virtual byte[] Data => data; public abstract PublicKeyToken Token { get; } protected PublicKeyBase(byte[] data) { this.data = data; } protected PublicKeyBase(string hexString) { data = Parse(hexString); } private static byte[] Parse(string hexString) { if (hexString == null || hexString == "null") { return null; } return Utils.ParseBytes(hexString); } public static bool IsNullOrEmpty2(PublicKeyBase a) { return a?.IsNullOrEmpty ?? true; } public static PublicKeyToken ToPublicKeyToken(PublicKeyBase pkb) { if (pkb is PublicKeyToken result) { return result; } if (pkb is PublicKey publicKey) { return publicKey.Token; } return null; } public static int TokenCompareTo(PublicKeyBase a, PublicKeyBase b) { if (a == b) { return 0; } return TokenCompareTo(ToPublicKeyToken(a), ToPublicKeyToken(b)); } public static bool TokenEquals(PublicKeyBase a, PublicKeyBase b) { return TokenCompareTo(a, b) == 0; } public static int TokenCompareTo(PublicKeyToken a, PublicKeyToken b) { if (a == b) { return 0; } return TokenCompareTo(a?.Data, b?.Data); } private static int TokenCompareTo(byte[] a, byte[] b) { return Utils.CompareTo(a ?? EmptyByteArray, b ?? EmptyByteArray); } public static bool TokenEquals(PublicKeyToken a, PublicKeyToken b) { return TokenCompareTo(a, b) == 0; } public static int GetHashCodeToken(PublicKeyBase a) { return GetHashCode(ToPublicKeyToken(a)); } public static int GetHashCode(PublicKeyToken a) { if (a == null) { return 0; } return Utils.GetHashCode(a.Data); } public static PublicKey CreatePublicKey(byte[] data) { if (data == null) { return null; } return new PublicKey(data); } public static PublicKeyToken CreatePublicKeyToken(byte[] data) { if (data == null) { return null; } return new PublicKeyToken(data); } public static byte[] GetRawData(PublicKeyBase pkb) { return pkb?.Data; } public override string ToString() { byte[] array = Data; if (array == null || array.Length == 0) { return "null"; } return Utils.ToHex(array, upper: false); } } public sealed class PublicKeyToken : PublicKeyBase { public override PublicKeyToken Token => this; public PublicKeyToken() : base((byte[])null) { } public PublicKeyToken(byte[] data) : base(data) { } public PublicKeyToken(string hexString) : base(hexString) { } public override bool Equals(object obj) { if (this == obj) { return true; } if (!(obj is PublicKeyToken publicKeyToken)) { return false; } return Utils.Equals(Data, publicKeyToken.Data); } public override int GetHashCode() { return Utils.GetHashCode(Data); } } internal struct RecursionCounter { public const int MAX_RECURSION_COUNT = 100; private int counter; public int Counter => counter; public bool Increment() { if (counter >= 100) { return false; } counter++; return true; } public void Decrement() { counter--; } public override string ToString() { return counter.ToString(); } } internal static class ReflectionExtensions { public static void GetTypeNamespaceAndName_TypeDefOrRef(this Type type, out string @namespace, out string name) { name = Unescape(type.Name) ?? string.Empty; if (!type.IsNested) { @namespace = type.Namespace ?? string.Empty; return; } string text = Unescape(type.DeclaringType.FullName); string text2 = Unescape(type.FullName); if (text.Length + 1 + name.Length == text2.Length) { @namespace = string.Empty; } else { @namespace = text2.Substring(text.Length + 1, text2.Length - text.Length - 1 - name.Length - 1); } } public static bool IsSZArray(this Type self) { if ((object)self == null || !self.IsArray) { return false; } PropertyInfo property = self.GetType().GetProperty("IsSzArray", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property != null) { return (bool)property.GetValue(self, Array2.Empty()); } return (self.Name ?? string.Empty).EndsWith("[]"); } public static ElementType GetElementType2(this Type a) { if ((object)a == null) { return ElementType.End; } if (a.IsArray) { if (!a.IsSZArray()) { return ElementType.Array; } return ElementType.SZArray; } if (a.IsByRef) { return ElementType.ByRef; } if (a.IsPointer) { return ElementType.Ptr; } if (a.IsGenericParameter) { if ((object)a.DeclaringMethod != null) { return ElementType.MVar; } return ElementType.Var; } if (a.IsGenericType && !a.IsGenericTypeDefinition) { return ElementType.GenericInst; } if (a == typeof(void)) { return ElementType.Void; } if (a == typeof(bool)) { return ElementType.Boolean; } if (a == typeof(char)) { return ElementType.Char; } if (a == typeof(sbyte)) { return ElementType.I1; } if (a == typeof(byte)) { return ElementType.U1; } if (a == typeof(short)) { return ElementType.I2; } if (a == typeof(ushort)) { return ElementType.U2; } if (a == typeof(int)) { return ElementType.I4; } if (a == typeof(uint)) { return ElementType.U4; } if (a == typeof(long)) { return ElementType.I8; } if (a == typeof(ulong)) { return ElementType.U8; } if (a == typeof(float)) { return ElementType.R4; } if (a == typeof(double)) { return ElementType.R8; } if (a == typeof(string)) { return ElementType.String; } if (a == typeof(TypedReference)) { return ElementType.TypedByRef; } if (a == typeof(IntPtr)) { return ElementType.I; } if (a == typeof(UIntPtr)) { return ElementType.U; } if (a == typeof(object)) { return ElementType.Object; } if (!a.IsValueType) { return ElementType.Class; } return ElementType.ValueType; } public static bool IsGenericButNotGenericTypeDefinition(this Type type) { if ((object)type != null && !type.IsGenericTypeDefinition) { return type.IsGenericType; } return false; } public static bool IsGenericButNotGenericMethodDefinition(this MethodBase mb) { if ((object)mb != null && !mb.IsGenericMethodDefinition) { return mb.IsGenericMethod; } return false; } internal static bool MustTreatTypeAsGenericInstType(this Type declaringType, Type t) { if ((object)declaringType != null && declaringType.IsGenericTypeDefinition) { return t == declaringType; } return false; } public static bool IsTypeDef(this Type type) { if ((object)type != null && !type.HasElementType) { if (type.IsGenericType) { return type.IsGenericTypeDefinition; } return true; } return false; } internal static string Unescape(string name) { if (string.IsNullOrEmpty(name) || name.IndexOf('\\') < 0) { return name; } StringBuilder stringBuilder = new StringBuilder(name.Length); for (int i = 0; i < name.Length; i++) { if (name[i] == '\\' && i < name.Length - 1 && IsReservedTypeNameChar(name[i + 1])) { stringBuilder.Append(name[++i]); } else { stringBuilder.Append(name[i]); } } return stringBuilder.ToString(); } private static bool IsReservedTypeNameChar(char c) { switch (c) { case '&': case '*': case '+': case ',': case '[': case '\\': case ']': return true; default: return false; } } } [Serializable] public class ResolveException : Exception { public ResolveException() { } public ResolveException(string message) : base(message) { } public ResolveException(string message, Exception innerException) : base(message, innerException) { } protected ResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [Serializable] public class AssemblyResolveException : ResolveException { public AssemblyResolveException() { } public AssemblyResolveException(string message) : base(message) { } public AssemblyResolveException(string message, Exception innerException) : base(message, innerException) { } protected AssemblyResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [Serializable] public class TypeResolveException : ResolveException { public TypeResolveException() { } public TypeResolveException(string message) : base(message) { } public TypeResolveException(string message, Exception innerException) : base(message, innerException) { } protected TypeResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [Serializable] public class MemberRefResolveException : ResolveException { public MemberRefResolveException() { } public MemberRefResolveException(string message) : base(message) { } public MemberRefResolveException(string message, Exception innerException) : base(message, innerException) { } protected MemberRefResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public sealed class Resolver : IResolver, ITypeResolver, IMemberRefResolver { private readonly IAssemblyResolver assemblyResolver; private bool projectWinMDRefs = true; public bool ProjectWinMDRefs { get { return projectWinMDRefs; } set { projectWinMDRefs = value; } } public Resolver(IAssemblyResolver assemblyResolver) { this.assemblyResolver = assemblyResolver ?? throw new ArgumentNullException("assemblyResolver"); } public TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule) { if (typeRef == null) { return null; } if (ProjectWinMDRefs) { typeRef = WinMDHelpers.ToCLR(typeRef.Module ?? sourceModule, typeRef) ?? typeRef; } TypeRef nonNestedTypeRef = TypeRef.GetNonNestedTypeRef(typeRef); if (nonNestedTypeRef == null) { return null; } IResolutionScope resolutionScope = nonNestedTypeRef.ResolutionScope; ModuleDef module = nonNestedTypeRef.Module; if (resolutionScope is AssemblyRef assembly) { AssemblyDef assemblyDef = assemblyResolver.Resolve(assembly, sourceModule ?? module); object obj; if (assemblyDef != null) { obj = assemblyDef.Find(typeRef); if (obj == null) { return ResolveExportedType(assemblyDef.Modules, typeRef, sourceModule); } } else { obj = null; } return (TypeDef)obj; } if (resolutionScope is ModuleDef moduleDef) { return moduleDef.Find(typeRef) ?? ResolveExportedType(new ModuleDef[1] { moduleDef }, typeRef, sourceModule); } if (resolutionScope is ModuleRef moduleRef) { if (module == null) { return null; } if (default(SigComparer).Equals(moduleRef, module)) { return module.Find(typeRef) ?? ResolveExportedType(new ModuleDef[1] { module }, typeRef, sourceModule); } AssemblyDef assembly2 = module.Assembly; if (assembly2 == null) { return null; } ModuleDef moduleDef2 = assembly2.FindModule(moduleRef.Name); object obj2; if (moduleDef2 != null) { obj2 = moduleDef2.Find(typeRef); if (obj2 == null) { return ResolveExportedType(new ModuleDef[1] { moduleDef2 }, typeRef, sourceModule); } } else { obj2 = null; } return (TypeDef)obj2; } if (resolutionScope == null) { return module.Find(typeRef) ?? ResolveExportedType(new ModuleDef[1] { module }, typeRef, sourceModule); } return null; } private TypeDef ResolveExportedType(IList modules, TypeRef typeRef, ModuleDef sourceModule) { for (int i = 0; i < 30; i++) { ExportedType exportedType = FindExportedType(modules, typeRef); if (exportedType == null) { return null; } AssemblyDef assemblyDef = modules[0].Context.AssemblyResolver.Resolve(exportedType.DefinitionAssembly, sourceModule ?? typeRef.Module); if (assemblyDef == null) { return null; } TypeDef typeDef = assemblyDef.Find(typeRef); if (typeDef != null) { return typeDef; } modules = assemblyDef.Modules; } return null; } private static ExportedType FindExportedType(IList modules, TypeRef typeRef) { if (typeRef == null) { return null; } int count = modules.Count; for (int i = 0; i < count; i++) { IList exportedTypes = modules[i].ExportedTypes; int count2 = exportedTypes.Count; for (int j = 0; j < count2; j++) { ExportedType exportedType = exportedTypes[j]; if (new SigComparer(SigComparerOptions.DontCompareTypeScope).Equals(exportedType, typeRef)) { return exportedType; } } } return null; } public IMemberForwarded Resolve(MemberRef memberRef) { if (memberRef == null) { return null; } if (ProjectWinMDRefs) { memberRef = WinMDHelpers.ToCLR(memberRef.Module, memberRef) ?? memberRef; } IMemberRefParent memberRefParent = memberRef.Class; if (memberRefParent is MethodDef result) { return result; } return GetDeclaringType(memberRef, memberRefParent)?.Resolve(memberRef); } private TypeDef GetDeclaringType(MemberRef memberRef, IMemberRefParent parent) { if (memberRef == null || parent == null) { return null; } if (parent is TypeSpec typeSpec) { parent = typeSpec.ScopeType; } if (parent is TypeDef result) { return result; } if (parent is TypeRef typeRef) { return Resolve(typeRef, memberRef.Module); } if (parent is ModuleRef moduleRef) { ModuleDef module = memberRef.Module; if (module == null) { return null; } TypeDef typeDef = null; if (default(SigComparer).Equals(module, moduleRef)) { typeDef = module.GlobalType; } AssemblyDef assembly = module.Assembly; if (typeDef == null && assembly != null) { ModuleDef moduleDef = assembly.FindModule(moduleRef.Name); if (moduleDef != null) { typeDef = moduleDef.GlobalType; } } return typeDef; } if (parent is MethodDef methodDef) { return methodDef.DeclaringType; } return null; } } public enum ResourceType { Embedded, AssemblyLinked, Linked } public abstract class Resource : IMDTokenProvider, IHasCustomAttribute, ICodedToken, IHasCustomDebugInformation { private protected uint rid; private protected uint? offset; private UTF8String name; private ManifestResourceAttributes flags; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.ManifestResource, rid); public uint Rid { get { return rid; } set { rid = value; } } public uint? Offset { get { return offset; } set { offset = value; } } public UTF8String Name { get { return name; } set { name = value; } } public ManifestResourceAttributes Attributes { get { return flags; } set { flags = value; } } public abstract ResourceType ResourceType { get; } public ManifestResourceAttributes Visibility { get { return flags & ManifestResourceAttributes.VisibilityMask; } set { flags = (ManifestResourceAttributes)(((uint)flags & 0xFFFFFFF8u) | (uint)(value & ManifestResourceAttributes.VisibilityMask)); } } public bool IsPublic => (flags & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Public; public bool IsPrivate => (flags & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Private; public int HasCustomAttributeTag => 18; public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 18; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } protected Resource(UTF8String name, ManifestResourceAttributes flags) { this.name = name; this.flags = flags; } } public class EmbeddedResource : Resource { private readonly DataReaderFactory dataReaderFactory; private readonly uint resourceStartOffset; private readonly uint resourceLength; public uint Length => resourceLength; public override ResourceType ResourceType => ResourceType.Embedded; public EmbeddedResource(UTF8String name, byte[] data, ManifestResourceAttributes flags = ManifestResourceAttributes.Private) : this(name, ByteArrayDataReaderFactory.Create(data, null), 0u, (uint)data.Length, flags) { } public EmbeddedResource(UTF8String name, DataReaderFactory dataReaderFactory, uint offset, uint length, ManifestResourceAttributes flags = ManifestResourceAttributes.Private) : base(name, flags) { this.dataReaderFactory = dataReaderFactory ?? throw new ArgumentNullException("dataReaderFactory"); resourceStartOffset = offset; resourceLength = length; } public DataReader CreateReader() { return dataReaderFactory.CreateReader(resourceStartOffset, resourceLength); } public override string ToString() { return $"{UTF8String.ToSystemStringOrEmpty(base.Name)} - size: {resourceLength}"; } } internal sealed class EmbeddedResourceMD : EmbeddedResource, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ManifestResource, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public EmbeddedResourceMD(ModuleDefMD readerModule, ManifestResource mr, byte[] data) : this(readerModule, mr, ByteArrayDataReaderFactory.Create(data, null), 0u, (uint)data.Length) { } public EmbeddedResourceMD(ModuleDefMD readerModule, ManifestResource mr, DataReaderFactory dataReaderFactory, uint offset, uint length) : base(mr.Name, dataReaderFactory, offset, length, mr.Flags) { this.readerModule = readerModule; origRid = (rid = mr.Rid); base.offset = mr.Offset; } } public class AssemblyLinkedResource : Resource { private AssemblyRef asmRef; public override ResourceType ResourceType => ResourceType.AssemblyLinked; public AssemblyRef Assembly { get { return asmRef; } set { asmRef = value ?? throw new ArgumentNullException("value"); } } public AssemblyLinkedResource(UTF8String name, AssemblyRef asmRef, ManifestResourceAttributes flags) : base(name, flags) { this.asmRef = asmRef ?? throw new ArgumentNullException("asmRef"); } public override string ToString() { return UTF8String.ToSystemStringOrEmpty(base.Name) + " - assembly: " + asmRef.FullName; } } internal sealed class AssemblyLinkedResourceMD : AssemblyLinkedResource, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ManifestResource, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public AssemblyLinkedResourceMD(ModuleDefMD readerModule, ManifestResource mr, AssemblyRef asmRef) : base(mr.Name, asmRef, mr.Flags) { this.readerModule = readerModule; origRid = (rid = mr.Rid); offset = mr.Offset; } } public class LinkedResource : Resource { private FileDef file; public override ResourceType ResourceType => ResourceType.Linked; public FileDef File { get { return file; } set { file = value ?? throw new ArgumentNullException("value"); } } public byte[] Hash { get { return file.HashValue; } set { file.HashValue = value; } } public UTF8String FileName { get { if (file != null) { return file.Name; } return UTF8String.Empty; } } public LinkedResource(UTF8String name, FileDef file, ManifestResourceAttributes flags) : base(name, flags) { this.file = file; } public override string ToString() { return UTF8String.ToSystemStringOrEmpty(base.Name) + " - file: " + UTF8String.ToSystemStringOrEmpty(FileName); } } internal sealed class LinkedResourceMD : LinkedResource, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.ManifestResource, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public LinkedResourceMD(ModuleDefMD readerModule, ManifestResource mr, FileDef file) : base(mr.Name, file, mr.Flags) { this.readerModule = readerModule; origRid = (rid = mr.Rid); offset = mr.Offset; } } public class ResourceCollection : LazyList { public ResourceCollection() { } public ResourceCollection(IListListener listener) : base(listener) { } public ResourceCollection(int length, object context, Func readOriginalValue) : base(length, context, readOriginalValue) { } public int IndexOf(UTF8String name) { int num = -1; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; num++; if (current != null && current.Name == name) { return num; } } } return -1; } public int IndexOfEmbeddedResource(UTF8String name) { int num = -1; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; num++; if (current != null && current.ResourceType == ResourceType.Embedded && current.Name == name) { return num; } } } return -1; } public int IndexOfAssemblyLinkedResource(UTF8String name) { int num = -1; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; num++; if (current != null && current.ResourceType == ResourceType.AssemblyLinked && current.Name == name) { return num; } } } return -1; } public int IndexOfLinkedResource(UTF8String name) { int num = -1; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; num++; if (current != null && current.ResourceType == ResourceType.Linked && current.Name == name) { return num; } } } return -1; } public Resource Find(UTF8String name) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; if (current != null && current.Name == name) { return current; } } } return null; } public EmbeddedResource FindEmbeddedResource(UTF8String name) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; if (current != null && current.ResourceType == ResourceType.Embedded && current.Name == name) { return (EmbeddedResource)current; } } } return null; } public AssemblyLinkedResource FindAssemblyLinkedResource(UTF8String name) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; if (current != null && current.ResourceType == ResourceType.AssemblyLinked && current.Name == name) { return (AssemblyLinkedResource)current; } } } return null; } public LinkedResource FindLinkedResource(UTF8String name) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Resource current = enumerator.Current; if (current != null && current.ResourceType == ResourceType.Linked && current.Name == name) { return (LinkedResource)current; } } } return null; } } public enum SecurityAction : short { ActionMask = 31, ActionNil = 0, Request = 1, Demand = 2, Assert = 3, Deny = 4, PermitOnly = 5, LinktimeCheck = 6, LinkDemand = 6, InheritanceCheck = 7, InheritDemand = 7, RequestMinimum = 8, RequestOptional = 9, RequestRefuse = 10, PrejitGrant = 11, PreJitGrant = 11, PrejitDenied = 12, PreJitDeny = 12, NonCasDemand = 13, NonCasLinkDemand = 14, NonCasInheritance = 15, MaximumValue = 15 } public sealed class SecurityAttribute : ICustomAttribute { private ITypeDefOrRef attrType; private readonly IList namedArguments; public ITypeDefOrRef AttributeType { get { return attrType; } set { attrType = value; } } public string TypeFullName { get { ITypeDefOrRef typeDefOrRef = attrType; if (typeDefOrRef != null) { return typeDefOrRef.FullName; } return string.Empty; } } public IList NamedArguments => namedArguments; public bool HasNamedArguments => namedArguments.Count > 0; public IEnumerable Fields { get { IList namedArguments = this.namedArguments; int count = namedArguments.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = namedArguments[i]; if (cANamedArgument.IsField) { yield return cANamedArgument; } } } } public IEnumerable Properties { get { IList namedArguments = this.namedArguments; int count = namedArguments.Count; for (int i = 0; i < count; i++) { CANamedArgument cANamedArgument = namedArguments[i]; if (cANamedArgument.IsProperty) { yield return cANamedArgument; } } } } public static SecurityAttribute CreateFromXml(ModuleDef module, string xml) { TypeRef typeRef = module.CorLibTypes.GetTypeRef("System.Security.Permissions", "PermissionSetAttribute"); UTF8String value = new UTF8String(xml); CANamedArgument item = new CANamedArgument(isField: false, module.CorLibTypes.String, "XML", new CAArgument(module.CorLibTypes.String, value)); List list = new List { item }; return new SecurityAttribute(typeRef, list); } public SecurityAttribute() : this(null, null) { } public SecurityAttribute(ITypeDefOrRef attrType) : this(attrType, null) { } public SecurityAttribute(ITypeDefOrRef attrType, IList namedArguments) { this.attrType = attrType; this.namedArguments = namedArguments ?? new List(); } public override string ToString() { return TypeFullName; } } internal enum SerializationType : byte { Undefined = 0, 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, SZArray = 29, Type = 80, TaggedObject = 81, Field = 83, Property = 84, Enum = 85 } public sealed class TypeEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { private readonly SigComparerOptions options; public static readonly TypeEqualityComparer Instance = new TypeEqualityComparer((SigComparerOptions)0u); public static readonly TypeEqualityComparer CaseInsensitive = new TypeEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public static readonly TypeEqualityComparer CompareReferenceInSameModule = new TypeEqualityComparer(SigComparerOptions.ReferenceCompareForMemberDefsInSameModule); public TypeEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(IType x, IType y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(IType obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(ITypeDefOrRef x, ITypeDefOrRef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(ITypeDefOrRef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(TypeRef x, TypeRef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(TypeRef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(TypeDef x, TypeDef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(TypeDef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(TypeSpec x, TypeSpec y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(TypeSpec obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(TypeSig x, TypeSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(TypeSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(ExportedType x, ExportedType y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(ExportedType obj) { return new SigComparer(options).GetHashCode(obj); } } public sealed class FieldEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer { private readonly SigComparerOptions options; public static readonly FieldEqualityComparer CompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType); public static readonly FieldEqualityComparer DontCompareDeclaringTypes = new FieldEqualityComparer((SigComparerOptions)0u); public static readonly FieldEqualityComparer CaseInsensitiveCompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CaseInsensitiveAll | SigComparerOptions.CompareMethodFieldDeclaringType); public static readonly FieldEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public static readonly FieldEqualityComparer CompareReferenceInSameModule = new FieldEqualityComparer(SigComparerOptions.ReferenceCompareForMemberDefsInSameModule); public FieldEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(IField x, IField y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(IField obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(FieldDef x, FieldDef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(FieldDef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MemberRef x, MemberRef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MemberRef obj) { return new SigComparer(options).GetHashCode(obj); } } public sealed class MethodEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { private readonly SigComparerOptions options; public static readonly MethodEqualityComparer CompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType); public static readonly MethodEqualityComparer DontCompareDeclaringTypes = new MethodEqualityComparer((SigComparerOptions)0u); public static readonly MethodEqualityComparer CaseInsensitiveCompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CaseInsensitiveAll | SigComparerOptions.CompareMethodFieldDeclaringType); public static readonly MethodEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public static readonly MethodEqualityComparer CompareReferenceInSameModule = new MethodEqualityComparer(SigComparerOptions.ReferenceCompareForMemberDefsInSameModule); public MethodEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(IMethod x, IMethod y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(IMethod obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(IMethodDefOrRef x, IMethodDefOrRef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(IMethodDefOrRef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MethodDef x, MethodDef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MethodDef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MemberRef x, MemberRef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MemberRef obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MethodSpec x, MethodSpec y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MethodSpec obj) { return new SigComparer(options).GetHashCode(obj); } } public sealed class PropertyEqualityComparer : IEqualityComparer { private readonly SigComparerOptions options; public static readonly PropertyEqualityComparer CompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.ComparePropertyDeclaringType); public static readonly PropertyEqualityComparer DontCompareDeclaringTypes = new PropertyEqualityComparer((SigComparerOptions)0u); public static readonly PropertyEqualityComparer CaseInsensitiveCompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.CaseInsensitiveAll | SigComparerOptions.ComparePropertyDeclaringType); public static readonly PropertyEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public static readonly PropertyEqualityComparer CompareReferenceInSameModule = new PropertyEqualityComparer(SigComparerOptions.ReferenceCompareForMemberDefsInSameModule); public PropertyEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(PropertyDef x, PropertyDef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(PropertyDef obj) { return new SigComparer(options).GetHashCode(obj); } } public sealed class EventEqualityComparer : IEqualityComparer { private readonly SigComparerOptions options; public static readonly EventEqualityComparer CompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CompareEventDeclaringType); public static readonly EventEqualityComparer DontCompareDeclaringTypes = new EventEqualityComparer((SigComparerOptions)0u); public static readonly EventEqualityComparer CaseInsensitiveCompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CaseInsensitiveAll | SigComparerOptions.CompareEventDeclaringType); public static readonly EventEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public static readonly EventEqualityComparer CompareReferenceInSameModule = new EventEqualityComparer(SigComparerOptions.ReferenceCompareForMemberDefsInSameModule); public EventEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(EventDef x, EventDef y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(EventDef obj) { return new SigComparer(options).GetHashCode(obj); } } public sealed class SignatureEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { private readonly SigComparerOptions options; public static readonly SignatureEqualityComparer Instance = new SignatureEqualityComparer((SigComparerOptions)0u); public static readonly SignatureEqualityComparer CaseInsensitive = new SignatureEqualityComparer(SigComparerOptions.CaseInsensitiveAll); public SignatureEqualityComparer(SigComparerOptions options) { this.options = options; } public bool Equals(CallingConventionSig x, CallingConventionSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(CallingConventionSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MethodBaseSig x, MethodBaseSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MethodBaseSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(MethodSig x, MethodSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(MethodSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(PropertySig x, PropertySig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(PropertySig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(FieldSig x, FieldSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(FieldSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(LocalSig x, LocalSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(LocalSig obj) { return new SigComparer(options).GetHashCode(obj); } public bool Equals(GenericInstMethodSig x, GenericInstMethodSig y) { return new SigComparer(options).Equals(x, y); } public int GetHashCode(GenericInstMethodSig obj) { return new SigComparer(options).GetHashCode(obj); } } [Flags] public enum SigComparerOptions : uint { DontCompareTypeScope = 1u, CompareMethodFieldDeclaringType = 2u, ComparePropertyDeclaringType = 4u, CompareEventDeclaringType = 8u, CompareDeclaringTypes = 0xEu, CompareSentinelParams = 0x10u, CompareAssemblyPublicKeyToken = 0x20u, CompareAssemblyVersion = 0x40u, CompareAssemblyLocale = 0x80u, TypeRefCanReferenceGlobalType = 0x100u, DontCompareReturnType = 0x200u, CaseInsensitiveTypeNamespaces = 0x800u, CaseInsensitiveTypeNames = 0x1000u, CaseInsensitiveTypes = 0x1800u, CaseInsensitiveMethodFieldNames = 0x2000u, CaseInsensitivePropertyNames = 0x4000u, CaseInsensitiveEventNames = 0x8000u, CaseInsensitiveAll = 0xF800u, PrivateScopeFieldIsComparable = 0x10000u, PrivateScopeMethodIsComparable = 0x20000u, PrivateScopeIsComparable = 0x30000u, RawSignatureCompare = 0x40000u, IgnoreModifiers = 0x80000u, MscorlibIsNotSpecial = 0x100000u, DontProjectWinMDRefs = 0x200000u, DontCheckTypeEquivalence = 0x400000u, IgnoreMultiDimensionalArrayLowerBoundsAndSizes = 0x800000u, ReferenceCompareForMemberDefsInSameModule = 0x1000000u } public struct SigComparer { private const SigComparerOptions SigComparerOptions_DontSubstituteGenericParameters = (SigComparerOptions)1024u; private const int HASHCODE_MAGIC_GLOBAL_TYPE = 1654396648; private const int HASHCODE_MAGIC_NESTED_TYPE = -1049070942; private const int HASHCODE_MAGIC_ET_MODULE = -299744851; private const int HASHCODE_MAGIC_ET_VALUEARRAY = -674970533; private const int HASHCODE_MAGIC_ET_GENERICINST = -2050514639; private const int HASHCODE_MAGIC_ET_VAR = 1288450097; private const int HASHCODE_MAGIC_ET_MVAR = -990598495; private const int HASHCODE_MAGIC_ET_ARRAY = -96331531; private const int HASHCODE_MAGIC_ET_SZARRAY = 871833535; private const int HASHCODE_MAGIC_ET_BYREF = -634749586; private const int HASHCODE_MAGIC_ET_PTR = 1976400808; private const int HASHCODE_MAGIC_ET_SENTINEL = 68439620; private RecursionCounter recursionCounter; private SigComparerOptions options; private GenericArguments genericArguments; private readonly ModuleDef sourceModule; private bool DontCompareTypeScope => (options & SigComparerOptions.DontCompareTypeScope) != 0; private bool CompareMethodFieldDeclaringType => (options & SigComparerOptions.CompareMethodFieldDeclaringType) != 0; private bool ComparePropertyDeclaringType => (options & SigComparerOptions.ComparePropertyDeclaringType) != 0; private bool CompareEventDeclaringType => (options & SigComparerOptions.CompareEventDeclaringType) != 0; private bool CompareSentinelParams => (options & SigComparerOptions.CompareSentinelParams) != 0; private bool CompareAssemblyPublicKeyToken => (options & SigComparerOptions.CompareAssemblyPublicKeyToken) != 0; private bool CompareAssemblyVersion => (options & SigComparerOptions.CompareAssemblyVersion) != 0; private bool CompareAssemblyLocale => (options & SigComparerOptions.CompareAssemblyLocale) != 0; private bool TypeRefCanReferenceGlobalType => (options & SigComparerOptions.TypeRefCanReferenceGlobalType) != 0; private bool DontCompareReturnType => (options & SigComparerOptions.DontCompareReturnType) != 0; private bool DontSubstituteGenericParameters => (options & (SigComparerOptions)1024u) != 0; private bool CaseInsensitiveTypeNamespaces => (options & SigComparerOptions.CaseInsensitiveTypeNamespaces) != 0; private bool CaseInsensitiveTypeNames => (options & SigComparerOptions.CaseInsensitiveTypeNames) != 0; private bool CaseInsensitiveMethodFieldNames => (options & SigComparerOptions.CaseInsensitiveMethodFieldNames) != 0; private bool CaseInsensitivePropertyNames => (options & SigComparerOptions.CaseInsensitivePropertyNames) != 0; private bool CaseInsensitiveEventNames => (options & SigComparerOptions.CaseInsensitiveEventNames) != 0; private bool PrivateScopeFieldIsComparable => (options & SigComparerOptions.PrivateScopeFieldIsComparable) != 0; private bool PrivateScopeMethodIsComparable => (options & SigComparerOptions.PrivateScopeMethodIsComparable) != 0; private bool RawSignatureCompare => (options & SigComparerOptions.RawSignatureCompare) != 0; private bool IgnoreModifiers => (options & SigComparerOptions.IgnoreModifiers) != 0; private bool MscorlibIsNotSpecial => (options & SigComparerOptions.MscorlibIsNotSpecial) != 0; private bool DontProjectWinMDRefs => (options & SigComparerOptions.DontProjectWinMDRefs) != 0; private bool DontCheckTypeEquivalence => (options & SigComparerOptions.DontCheckTypeEquivalence) != 0; private bool IgnoreMultiDimensionalArrayLowerBoundsAndSizes => (options & SigComparerOptions.IgnoreMultiDimensionalArrayLowerBoundsAndSizes) != 0; private bool ReferenceCompareForMemberDefsInSameModule => (options & SigComparerOptions.ReferenceCompareForMemberDefsInSameModule) != 0; public SigComparer(SigComparerOptions options) : this(options, null) { } public SigComparer(SigComparerOptions options, ModuleDef sourceModule) { recursionCounter = default(RecursionCounter); this.options = options; genericArguments = null; this.sourceModule = sourceModule; } private int GetHashCode_FnPtr_SystemIntPtr() { return GetHashCode_TypeNamespace("System") + GetHashCode_TypeName("IntPtr"); } private bool Equals_Names(bool caseInsensitive, UTF8String a, UTF8String b) { if (caseInsensitive) { return UTF8String.ToSystemStringOrEmpty(a).Equals(UTF8String.ToSystemStringOrEmpty(b), StringComparison.OrdinalIgnoreCase); } return UTF8String.Equals(a, b); } private bool Equals_Names(bool caseInsensitive, string a, string b) { if (caseInsensitive) { return (a ?? string.Empty).Equals(b ?? string.Empty, StringComparison.OrdinalIgnoreCase); } return (a ?? string.Empty) == (b ?? string.Empty); } private int GetHashCode_Name(bool caseInsensitive, string a) { if (caseInsensitive) { return (a ?? string.Empty).ToUpperInvariant().GetHashCode(); } return (a ?? string.Empty).GetHashCode(); } private bool Equals_TypeNamespaces(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveTypeNamespaces, a, b); } private bool Equals_TypeNamespaces(UTF8String a, string b) { return Equals_Names(CaseInsensitiveTypeNamespaces, UTF8String.ToSystemStringOrEmpty(a), b); } private int GetHashCode_TypeNamespace(UTF8String a) { return GetHashCode_Name(CaseInsensitiveTypeNamespaces, UTF8String.ToSystemStringOrEmpty(a)); } private int GetHashCode_TypeNamespace(string a) { return GetHashCode_Name(CaseInsensitiveTypeNamespaces, a); } private bool Equals_TypeNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveTypeNames, a, b); } private bool Equals_TypeNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveTypeNames, UTF8String.ToSystemStringOrEmpty(a), b); } private int GetHashCode_TypeName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveTypeNames, UTF8String.ToSystemStringOrEmpty(a)); } private int GetHashCode_TypeName(string a) { return GetHashCode_Name(CaseInsensitiveTypeNames, a); } private bool Equals_MethodFieldNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveMethodFieldNames, a, b); } private bool Equals_MethodFieldNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveMethodFieldNames, UTF8String.ToSystemStringOrEmpty(a), b); } private int GetHashCode_MethodFieldName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveMethodFieldNames, UTF8String.ToSystemStringOrEmpty(a)); } private int GetHashCode_MethodFieldName(string a) { return GetHashCode_Name(CaseInsensitiveMethodFieldNames, a); } private bool Equals_PropertyNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitivePropertyNames, a, b); } private bool Equals_PropertyNames(UTF8String a, string b) { return Equals_Names(CaseInsensitivePropertyNames, UTF8String.ToSystemStringOrEmpty(a), b); } private int GetHashCode_PropertyName(UTF8String a) { return GetHashCode_Name(CaseInsensitivePropertyNames, UTF8String.ToSystemStringOrEmpty(a)); } private int GetHashCode_PropertyName(string a) { return GetHashCode_Name(CaseInsensitivePropertyNames, a); } private bool Equals_EventNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveEventNames, a, b); } private bool Equals_EventNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveEventNames, UTF8String.ToSystemStringOrEmpty(a), b); } private int GetHashCode_EventName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveEventNames, UTF8String.ToSystemStringOrEmpty(a)); } private int GetHashCode_EventName(string a) { return GetHashCode_Name(CaseInsensitiveEventNames, a); } private SigComparerOptions ClearOptions(SigComparerOptions flags) { SigComparerOptions result = options; options &= ~flags; return result; } private SigComparerOptions SetOptions(SigComparerOptions flags) { SigComparerOptions result = options; options |= flags; return result; } private void RestoreOptions(SigComparerOptions oldFlags) { options = oldFlags; } private void InitializeGenericArguments() { if (genericArguments == null) { genericArguments = new GenericArguments(); } } private static GenericInstSig GetGenericInstanceType(IMemberRefParent parent) { if (!(parent is TypeSpec typeSpec)) { return null; } return typeSpec.TypeSig.RemoveModifiers() as GenericInstSig; } private bool Equals(IAssembly aAsm, IAssembly bAsm, TypeRef b) { if (Equals(aAsm, bAsm)) { return true; } TypeDef typeDef = b.Resolve(sourceModule); if (typeDef != null) { return Equals(aAsm, typeDef.Module.Assembly); } return false; } private bool Equals(IAssembly aAsm, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) { return true; } TypeDef typeDef = b.Resolve(); if (typeDef != null) { return Equals(aAsm, typeDef.Module.Assembly); } return false; } private bool Equals(IAssembly aAsm, TypeRef a, IAssembly bAsm, TypeRef b) { if (Equals(aAsm, bAsm)) { return true; } TypeDef typeDef = a.Resolve(sourceModule); TypeDef typeDef2 = b.Resolve(sourceModule); if (typeDef != null && typeDef2 != null) { return Equals(typeDef.Module.Assembly, typeDef2.Module.Assembly); } return false; } private bool Equals(IAssembly aAsm, ExportedType a, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) { return true; } TypeDef typeDef = a.Resolve(); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null) { return Equals(typeDef.Module.Assembly, typeDef2.Module.Assembly); } return false; } private bool Equals(IAssembly aAsm, TypeRef a, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) { return true; } TypeDef typeDef = a.Resolve(sourceModule); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null) { return Equals(typeDef.Module.Assembly, typeDef2.Module.Assembly); } return false; } private bool Equals(TypeDef a, IModule bMod, TypeRef b) { if (Equals(a.Module, bMod) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) { return true; } TypeDef typeDef = b.Resolve(sourceModule); if (typeDef == null) { return false; } if (!DontCheckTypeEquivalence && TIAHelper.Equivalent(a, typeDef)) { return true; } if (Equals(a.Module, typeDef.Module)) { return Equals(a.DefinitionAssembly, typeDef.DefinitionAssembly); } return false; } private bool Equals(TypeDef a, FileDef bFile, ExportedType b) { if (Equals(a.Module, bFile) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) { return true; } TypeDef typeDef = b.Resolve(); if (typeDef != null && Equals(a.Module, typeDef.Module)) { return Equals(a.DefinitionAssembly, typeDef.DefinitionAssembly); } return false; } private bool TypeDefScopeEquals(TypeDef a, TypeDef b) { if (a == null || b == null) { return false; } if (!DontCheckTypeEquivalence && TIAHelper.Equivalent(a, b)) { return true; } return Equals(a.Module, b.Module); } private bool Equals(TypeRef a, IModule ma, TypeRef b, IModule mb) { if (Equals(ma, mb) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) { return true; } TypeDef typeDef = a.Resolve(sourceModule); TypeDef typeDef2 = b.Resolve(sourceModule); if (typeDef != null && typeDef2 != null && Equals(typeDef.Module, typeDef2.Module)) { return Equals(typeDef.DefinitionAssembly, typeDef2.DefinitionAssembly); } return false; } private bool Equals(TypeRef a, IModule ma, ExportedType b, FileDef fb) { if (Equals(ma, fb) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) { return true; } TypeDef typeDef = a.Resolve(sourceModule); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null && Equals(typeDef.Module, typeDef2.Module)) { return Equals(typeDef.DefinitionAssembly, typeDef2.DefinitionAssembly); } return false; } private bool Equals(Assembly aAsm, IAssembly bAsm, TypeRef b) { if (Equals(bAsm, aAsm)) { return true; } TypeDef typeDef = b.Resolve(sourceModule); if (typeDef != null) { return Equals(typeDef.Module.Assembly, aAsm); } return false; } private bool Equals(Assembly aAsm, IAssembly bAsm, ExportedType b) { if (Equals(bAsm, aAsm)) { return true; } TypeDef typeDef = b.Resolve(); if (typeDef != null) { return Equals(typeDef.Module.Assembly, aAsm); } return false; } private bool Equals(Type a, IModule bMod, TypeRef b) { if (Equals(bMod, a.Module) && Equals(b.DefinitionAssembly, a.Assembly)) { return true; } TypeDef typeDef = b.Resolve(sourceModule); if (typeDef != null && Equals(typeDef.Module, a.Module)) { return Equals(typeDef.DefinitionAssembly, a.Assembly); } return false; } private bool Equals(Type a, FileDef bFile, ExportedType b) { if (Equals(bFile, a.Module) && Equals(b.DefinitionAssembly, a.Assembly)) { return true; } TypeDef typeDef = b.Resolve(); if (typeDef != null && Equals(typeDef.Module, a.Module)) { return Equals(typeDef.DefinitionAssembly, a.Assembly); } return false; } public bool Equals(IMemberRef a, IMemberRef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((a is IType a2 && b is IType b2) ? Equals(a2, b2) : ((a is IField field && b is IField field2 && field.IsField && field2.IsField) ? Equals(field, field2) : ((a is IMethod a3 && b is IMethod b3) ? Equals(a3, b3) : ((a is PropertyDef a4 && b is PropertyDef b4) ? Equals(a4, b4) : (a is EventDef a5 && b is EventDef b5 && Equals(a5, b5)))))); recursionCounter.Decrement(); return result; } public int GetHashCode(IMemberRef a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = ((!(a is IType a2)) ? ((!(a is IField a3)) ? ((!(a is IMethod a4)) ? ((!(a is PropertyDef a5)) ? ((a is EventDef a6) ? GetHashCode(a6) : 0) : GetHashCode(a5)) : GetHashCode(a4)) : GetHashCode(a3)) : GetHashCode(a2)); recursionCounter.Decrement(); return result; } public bool Equals(ITypeDefOrRef a, ITypeDefOrRef b) { return Equals((IType)a, (IType)b); } public int GetHashCode(ITypeDefOrRef a) { return GetHashCode((IType)a); } public bool Equals(IType a, IType b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } TypeDef typeDef; TypeDef typeDef2; TypeRef typeRef; TypeRef typeRef2; TypeSpec typeSpec; TypeSpec typeSpec2; TypeSig typeSig; TypeSig typeSig2; ExportedType exportedType; ExportedType exportedType2; bool result = ((((typeDef = a as TypeDef) != null) & ((typeDef2 = b as TypeDef) != null)) ? Equals(typeDef, typeDef2) : ((((typeRef = a as TypeRef) != null) & ((typeRef2 = b as TypeRef) != null)) ? Equals(typeRef, typeRef2) : ((((typeSpec = a as TypeSpec) != null) & ((typeSpec2 = b as TypeSpec) != null)) ? Equals(typeSpec, typeSpec2) : ((((typeSig = a as TypeSig) != null) & ((typeSig2 = b as TypeSig) != null)) ? Equals(typeSig, typeSig2) : ((((exportedType = a as ExportedType) != null) & ((exportedType2 = b as ExportedType) != null)) ? Equals(exportedType, exportedType2) : ((typeDef != null && typeRef2 != null) ? Equals(typeDef, typeRef2) : ((typeRef != null && typeDef2 != null) ? Equals(typeDef2, typeRef) : ((typeDef != null && typeSpec2 != null) ? Equals(typeDef, typeSpec2) : ((typeSpec != null && typeDef2 != null) ? Equals(typeDef2, typeSpec) : ((typeDef != null && typeSig2 != null) ? Equals(typeDef, typeSig2) : ((typeSig != null && typeDef2 != null) ? Equals(typeDef2, typeSig) : ((typeDef != null && exportedType2 != null) ? Equals(typeDef, exportedType2) : ((exportedType != null && typeDef2 != null) ? Equals(typeDef2, exportedType) : ((typeRef != null && typeSpec2 != null) ? Equals(typeRef, typeSpec2) : ((typeSpec != null && typeRef2 != null) ? Equals(typeRef2, typeSpec) : ((typeRef != null && typeSig2 != null) ? Equals(typeRef, typeSig2) : ((typeSig != null && typeRef2 != null) ? Equals(typeRef2, typeSig) : ((typeRef != null && exportedType2 != null) ? Equals(typeRef, exportedType2) : ((exportedType != null && typeRef2 != null) ? Equals(typeRef2, exportedType) : ((typeSpec != null && typeSig2 != null) ? Equals(typeSpec, typeSig2) : ((typeSig != null && typeSpec2 != null) ? Equals(typeSpec2, typeSig) : ((typeSpec != null && exportedType2 != null) ? Equals(typeSpec, exportedType2) : ((exportedType != null && typeSpec2 != null) ? Equals(typeSpec2, exportedType) : ((typeSig != null && exportedType2 != null) ? Equals(typeSig, exportedType2) : (exportedType != null && typeSig2 != null && Equals(typeSig2, exportedType)))))))))))))))))))))))))); recursionCounter.Decrement(); return result; } public int GetHashCode(IType a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = ((!(a is TypeDef a2)) ? ((!(a is TypeRef a3)) ? ((!(a is TypeSpec a4)) ? ((!(a is TypeSig a5)) ? ((a is ExportedType a6) ? GetHashCode(a6) : 0) : GetHashCode(a5)) : GetHashCode(a4)) : GetHashCode(a3)) : GetHashCode(a2)); recursionCounter.Decrement(); return result; } public bool Equals(TypeRef a, TypeDef b) { return Equals(b, a); } public bool Equals(TypeDef a, TypeRef b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag; if (!DontProjectWinMDRefs) { TypeRef typeRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (typeRef != null) { flag = Equals(typeRef, b); goto IL_014e; } } IResolutionScope resolutionScope = b.ResolutionScope; if (!Equals_TypeNames(a.Name, b.Name) || !Equals_TypeNamespaces(a.Namespace, b.Namespace)) { flag = false; } else if (resolutionScope is TypeRef b2) { flag = Equals(a.DeclaringType, b2); } else if (a.DeclaringType != null) { flag = false; } else if (DontCompareTypeScope) { flag = true; } else if (resolutionScope is IModule bMod) { flag = Equals(a, bMod, b); } else if (resolutionScope is AssemblyRef bAsm) { ModuleDef module = a.Module; flag = module != null && Equals(module.Assembly, bAsm, b); if (!flag && !DontCheckTypeEquivalence) { TypeDef b3 = b.Resolve(); flag = TypeDefScopeEquals(a, b3); } } else { flag = false; } if (flag && !TypeRefCanReferenceGlobalType && a.IsGlobalModuleType) { flag = false; } goto IL_014e; IL_014e: recursionCounter.Decrement(); return flag; } public bool Equals(ExportedType a, TypeDef b) { return Equals(b, a); } public bool Equals(TypeDef a, ExportedType b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag; if (!DontProjectWinMDRefs) { TypeRef typeRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (typeRef != null) { flag = Equals(typeRef, b); goto IL_014e; } } IImplementation implementation = b.Implementation; if (!Equals_TypeNames(a.Name, b.TypeName) || !Equals_TypeNamespaces(a.Namespace, b.TypeNamespace)) { flag = false; } else if (implementation is ExportedType b2) { flag = Equals(a.DeclaringType, b2); } else if (a.DeclaringType != null) { flag = false; } else if (DontCompareTypeScope) { flag = true; } else { if (implementation is FileDef bFile) { flag = Equals(a, bFile, b); } else if (implementation is AssemblyRef bAsm) { ModuleDef module = a.Module; flag = module != null && Equals(module.Assembly, bAsm, b); } else { flag = false; } if (!flag && !DontCheckTypeEquivalence) { TypeDef b3 = b.Resolve(); flag = TypeDefScopeEquals(a, b3); } } if (flag && !TypeRefCanReferenceGlobalType && a.IsGlobalModuleType) { flag = false; } goto IL_014e; IL_014e: recursionCounter.Decrement(); return flag; } public bool Equals(TypeSpec a, TypeDef b) { return Equals(b, a); } public bool Equals(TypeDef a, TypeSpec b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } return Equals(a, b.TypeSig); } public bool Equals(TypeSig a, TypeDef b) { return Equals(b, a); } public bool Equals(TypeDef a, TypeSig b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(b is TypeDefOrRefSig typeDefOrRefSig)) ? ((b is ModifierSig || b is PinnedSig) && Equals(a, b.Next)) : Equals((IType)a, (IType)typeDefOrRefSig.TypeDefOrRef)); recursionCounter.Decrement(); return result; } public bool Equals(TypeSpec a, TypeRef b) { return Equals(b, a); } public bool Equals(TypeRef a, TypeSpec b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } return Equals(a, b.TypeSig); } public bool Equals(ExportedType a, TypeRef b) { return Equals(b, a); } public bool Equals(TypeRef a, ExportedType b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.Name, b.TypeName) && Equals_TypeNamespaces(a.Namespace, b.TypeNamespace) && EqualsScope(a, b); recursionCounter.Decrement(); return result; } public bool Equals(TypeSig a, TypeRef b) { return Equals(b, a); } public bool Equals(TypeRef a, TypeSig b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(b is TypeDefOrRefSig typeDefOrRefSig)) ? ((b is ModifierSig || b is PinnedSig) && Equals(a, b.Next)) : Equals((IType)a, (IType)typeDefOrRefSig.TypeDefOrRef)); recursionCounter.Decrement(); return result; } public bool Equals(TypeSig a, TypeSpec b) { return Equals(b, a); } public bool Equals(TypeSpec a, TypeSig b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } return Equals(a.TypeSig, b); } public bool Equals(ExportedType a, TypeSpec b) { return Equals(b, a); } public bool Equals(TypeSpec a, ExportedType b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } return Equals(a.TypeSig, b); } public bool Equals(ExportedType a, TypeSig b) { return Equals(b, a); } public bool Equals(TypeSig a, ExportedType b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is TypeDefOrRefSig typeDefOrRefSig)) ? ((a is ModifierSig || a is PinnedSig) && Equals(a.Next, b)) : Equals(typeDefOrRefSig.TypeDefOrRef, b)); recursionCounter.Decrement(); return result; } private int GetHashCodeGlobalType() { return 1654396648; } public bool Equals(TypeRef a, TypeRef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.Name, b.Name) && Equals_TypeNamespaces(a.Namespace, b.Namespace) && EqualsResolutionScope(a, b); recursionCounter.Decrement(); return result; } public int GetHashCode(TypeRef a) { if (a == null) { if (!TypeRefCanReferenceGlobalType) { return 0; } return GetHashCodeGlobalType(); } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } int hashCode_TypeName = GetHashCode_TypeName(a.Name); if (a.ResolutionScope is TypeRef) { return hashCode_TypeName + -1049070942; } return hashCode_TypeName + GetHashCode_TypeNamespace(a.Namespace); } public bool Equals(ExportedType a, ExportedType b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.TypeName, b.TypeName) && Equals_TypeNamespaces(a.TypeNamespace, b.TypeNamespace) && EqualsImplementation(a, b); recursionCounter.Decrement(); return result; } public int GetHashCode(ExportedType a) { if (a == null) { if (!TypeRefCanReferenceGlobalType) { return 0; } return GetHashCodeGlobalType(); } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } int hashCode_TypeName = GetHashCode_TypeName(a.TypeName); if (a.Implementation is ExportedType) { return hashCode_TypeName + -1049070942; } return hashCode_TypeName + GetHashCode_TypeNamespace(a.TypeNamespace); } public bool Equals(TypeDef a, TypeDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (ReferenceCompareForMemberDefsInSameModule && InSameModule(a, b)) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (!DontProjectWinMDRefs) { TypeRef typeRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); TypeRef typeRef2 = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b); if (typeRef != null || typeRef2 != null) { IType type = typeRef; IType a2 = type ?? a; type = typeRef2; result = Equals(a2, type ?? b); goto IL_00d8; } } result = Equals_TypeNames(a.Name, b.Name) && Equals_TypeNamespaces(a.Namespace, b.Namespace) && Equals(a.DeclaringType, b.DeclaringType) && (DontCompareTypeScope || TypeDefScopeEquals(a, b)); goto IL_00d8; IL_00d8: recursionCounter.Decrement(); return result; } public int GetHashCode(TypeDef a) { if (a == null || a.IsGlobalModuleType) { return GetHashCodeGlobalType(); } if (!DontProjectWinMDRefs) { TypeRef typeRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (typeRef != null) { return GetHashCode(typeRef); } } int hashCode_TypeName = GetHashCode_TypeName(a.Name); if (a.DeclaringType != null) { return hashCode_TypeName + -1049070942; } return hashCode_TypeName + GetHashCode_TypeNamespace(a.Namespace); } public bool Equals(TypeSpec a, TypeSpec b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals(a.TypeSig, b.TypeSig); recursionCounter.Decrement(); return result; } public int GetHashCode(TypeSpec a) { if (a == null) { return 0; } return GetHashCode(a.TypeSig); } private bool EqualsResolutionScope(TypeRef a, TypeRef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } IResolutionScope resolutionScope = a.ResolutionScope; IResolutionScope resolutionScope2 = b.ResolutionScope; if (resolutionScope == resolutionScope2) { return true; } if (resolutionScope == null || resolutionScope2 == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag = true; TypeRef a2; TypeRef b2; bool flag2; IModule ma; IModule mb; AssemblyRef assemblyRef; AssemblyRef assemblyRef2; if (((a2 = resolutionScope as TypeRef) != null) | ((b2 = resolutionScope2 as TypeRef) != null)) { flag2 = Equals(a2, b2); flag = false; } else if (DontCompareTypeScope) { flag2 = true; } else if (((ma = resolutionScope as IModule) != null) & ((mb = resolutionScope2 as IModule) != null)) { flag2 = Equals(a, ma, b, mb); } else if (((assemblyRef = resolutionScope as AssemblyRef) != null) & ((assemblyRef2 = resolutionScope2 as AssemblyRef) != null)) { flag2 = Equals(assemblyRef, a, assemblyRef2, b); } else if (assemblyRef != null && resolutionScope2 is ModuleRef) { ModuleDef module = b.Module; flag2 = module != null && Equals(module.Assembly, b, assemblyRef, a); } else if (assemblyRef2 != null && resolutionScope is ModuleRef) { ModuleDef module2 = a.Module; flag2 = module2 != null && Equals(module2.Assembly, a, assemblyRef2, b); } else if (assemblyRef != null && resolutionScope2 is ModuleDef moduleDef) { flag2 = Equals(moduleDef.Assembly, assemblyRef, a); } else if (assemblyRef2 != null && resolutionScope is ModuleDef moduleDef2) { flag2 = Equals(moduleDef2.Assembly, assemblyRef2, b); } else { flag2 = false; flag = false; } if (!flag2 && flag && !DontCheckTypeEquivalence) { TypeDef typeDef = a.Resolve(); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null) { flag2 = TypeDefScopeEquals(typeDef, typeDef2); } } recursionCounter.Decrement(); return flag2; } private bool EqualsImplementation(ExportedType a, ExportedType b) { if (a == b) { return true; } if (a == null || b == null) { return false; } IImplementation implementation = a.Implementation; IImplementation implementation2 = b.Implementation; if (implementation == implementation2) { return true; } if (implementation == null || implementation2 == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag = true; ExportedType a2; ExportedType b2; bool flag2; FileDef fileDef; FileDef fileDef2; AssemblyRef assemblyRef; AssemblyRef assemblyRef2; if (((a2 = implementation as ExportedType) != null) | ((b2 = implementation2 as ExportedType) != null)) { flag2 = Equals(a2, b2); flag = false; } else if (DontCompareTypeScope) { flag2 = true; } else if (((fileDef = implementation as FileDef) != null) & ((fileDef2 = implementation2 as FileDef) != null)) { flag2 = Equals(fileDef, fileDef2); } else if (((assemblyRef = implementation as AssemblyRef) != null) & ((assemblyRef2 = implementation2 as AssemblyRef) != null)) { flag2 = Equals(assemblyRef, a, assemblyRef2, b); } else if (fileDef != null && assemblyRef2 != null) { flag2 = Equals(a.DefinitionAssembly, assemblyRef2, b); } else if (fileDef2 != null && assemblyRef != null) { flag2 = Equals(b.DefinitionAssembly, assemblyRef, a); } else { flag2 = false; flag = false; } if (!flag2 && flag && !DontCheckTypeEquivalence) { TypeDef typeDef = a.Resolve(); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null) { flag2 = TypeDefScopeEquals(typeDef, typeDef2); } } recursionCounter.Decrement(); return flag2; } private bool EqualsScope(TypeRef a, ExportedType b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } IResolutionScope resolutionScope = a.ResolutionScope; IImplementation implementation = b.Implementation; if (resolutionScope == implementation) { return true; } if (resolutionScope == null || implementation == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag = true; TypeRef a2; ExportedType b2; bool flag2; IModule module; FileDef fileDef; AssemblyRef assemblyRef; AssemblyRef assemblyRef2; if (((a2 = resolutionScope as TypeRef) != null) | ((b2 = implementation as ExportedType) != null)) { flag2 = Equals(a2, b2); flag = false; } else if (DontCompareTypeScope) { flag2 = true; } else if (((module = resolutionScope as IModule) != null) & ((fileDef = implementation as FileDef) != null)) { flag2 = Equals(a, module, b, fileDef); } else if (((assemblyRef = resolutionScope as AssemblyRef) != null) & ((assemblyRef2 = implementation as AssemblyRef) != null)) { flag2 = Equals(assemblyRef, a, assemblyRef2, b); } else if (module != null && assemblyRef2 != null) { flag2 = Equals(a.DefinitionAssembly, assemblyRef2, b); } else if (fileDef != null && assemblyRef != null) { flag2 = Equals(b.DefinitionAssembly, assemblyRef, a); } else { flag = false; flag2 = false; } if (!flag2 && flag && !DontCheckTypeEquivalence) { TypeDef typeDef = a.Resolve(); TypeDef typeDef2 = b.Resolve(); if (typeDef != null && typeDef2 != null) { flag2 = TypeDefScopeEquals(typeDef, typeDef2); } } recursionCounter.Decrement(); return flag2; } private bool Equals(FileDef a, FileDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } private bool Equals(IModule a, FileDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } internal bool Equals(IModule a, IModule b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } private static bool IsCorLib(ModuleDef a) { if (a != null && a.IsManifestModule) { return a.Assembly.IsCorLib(); } return false; } private static bool IsCorLib(IModule a) { if (a is ModuleDef { IsManifestModule: not false } moduleDef) { return moduleDef.Assembly.IsCorLib(); } return false; } private static bool IsCorLib(Module a) { if ((object)a != null && a.Assembly.ManifestModule == a) { return a.Assembly == typeof(void).Assembly; } return false; } private static bool IsCorLib(IAssembly a) { return a.IsCorLib(); } private static bool IsCorLib(Assembly a) { return a == typeof(void).Assembly; } private bool Equals(ModuleDef a, ModuleDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } if (!recursionCounter.Increment()) { return false; } bool result = Equals((IModule)a, (IModule)b) && Equals(a.Assembly, b.Assembly); recursionCounter.Decrement(); return result; } private bool Equals(IAssembly a, IAssembly b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } if (!recursionCounter.Increment()) { return false; } bool result = UTF8String.CaseInsensitiveEquals(a.Name, b.Name) && (!CompareAssemblyPublicKeyToken || PublicKeyBase.TokenEquals(a.PublicKeyOrToken, b.PublicKeyOrToken)) && (!CompareAssemblyVersion || Utils.Equals(a.Version, b.Version)) && (!CompareAssemblyLocale || Utils.LocaleEquals(a.Culture, b.Culture)); recursionCounter.Decrement(); return result; } public bool Equals(TypeSig a, TypeSig b) { if (IgnoreModifiers) { a = a.RemoveModifiers(); b = b.RemoveModifiers(); } if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result; if (a.ElementType != b.ElementType) { result = false; } else { switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.Sentinel: result = true; break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.SZArray: case ElementType.Pinned: result = Equals(a.Next, b.Next); break; case ElementType.Array: { ArraySig arraySig = a as ArraySig; ArraySig arraySig2 = b as ArraySig; result = arraySig.Rank == arraySig2.Rank && (IgnoreMultiDimensionalArrayLowerBoundsAndSizes || (Equals(arraySig.Sizes, arraySig2.Sizes) && Equals(arraySig.LowerBounds, arraySig2.LowerBounds))) && Equals(a.Next, b.Next); break; } case ElementType.ValueType: case ElementType.Class: result = ((!RawSignatureCompare) ? Equals((IType)(a as ClassOrValueTypeSig).TypeDefOrRef, (IType)(b as ClassOrValueTypeSig).TypeDefOrRef) : TokenEquals((a as ClassOrValueTypeSig).TypeDefOrRef, (b as ClassOrValueTypeSig).TypeDefOrRef)); break; case ElementType.Var: case ElementType.MVar: result = (a as GenericSig).Number == (b as GenericSig).Number; break; case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)a; GenericInstSig genericInstSig2 = (GenericInstSig)b; if (RawSignatureCompare) { ClassOrValueTypeSig genericType = genericInstSig.GenericType; result = TokenEquals(b: genericInstSig2.GenericType?.TypeDefOrRef, a: genericType?.TypeDefOrRef) && Equals(genericInstSig.GenericArguments, genericInstSig2.GenericArguments); } else { result = Equals(genericInstSig.GenericType, genericInstSig2.GenericType) && Equals(genericInstSig.GenericArguments, genericInstSig2.GenericArguments); } break; } case ElementType.FnPtr: result = Equals((a as FnPtrSig).Signature, (b as FnPtrSig).Signature); break; case ElementType.CModReqd: case ElementType.CModOpt: result = ((!RawSignatureCompare) ? (Equals((IType)(a as ModifierSig).Modifier, (IType)(b as ModifierSig).Modifier) && Equals(a.Next, b.Next)) : (TokenEquals((a as ModifierSig).Modifier, (b as ModifierSig).Modifier) && Equals(a.Next, b.Next))); break; case ElementType.ValueArray: result = (a as ValueArraySig).Size == (b as ValueArraySig).Size && Equals(a.Next, b.Next); break; case ElementType.Module: result = (a as ModuleSig).Index == (b as ModuleSig).Index && Equals(a.Next, b.Next); break; default: result = false; break; } } recursionCounter.Decrement(); return result; } private static bool TokenEquals(ITypeDefOrRef a, ITypeDefOrRef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } return a.MDToken == b.MDToken; } public int GetHashCode(TypeSig a) { return GetHashCode(a, substituteGenericParameters: true); } private int GetHashCode(TypeSig a, bool substituteGenericParameters) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } if (substituteGenericParameters && genericArguments != null) { TypeSig typeSig = a; a = genericArguments.Resolve(a); substituteGenericParameters = typeSig == a; } int result; switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetHashCode((IType)(a as TypeDefOrRefSig).TypeDefOrRef); break; case ElementType.Sentinel: result = 68439620; break; case ElementType.Ptr: result = 1976400808 + GetHashCode(a.Next, substituteGenericParameters); break; case ElementType.ByRef: result = -634749586 + GetHashCode(a.Next, substituteGenericParameters); break; case ElementType.SZArray: result = 871833535 + GetHashCode(a.Next, substituteGenericParameters); break; case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: result = GetHashCode(a.Next, substituteGenericParameters); break; case ElementType.Array: { ArraySig arraySig = (ArraySig)a; result = -96331531 + (int)arraySig.Rank + GetHashCode(arraySig.Next, substituteGenericParameters); break; } case ElementType.Var: result = (int)(1288450097 + (a as GenericVar).Number); break; case ElementType.MVar: result = -990598495 + (int)(a as GenericMVar).Number; break; case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)a; result = -2050514639; result += GetHashCode(genericInstSig.GenericType, substituteGenericParameters); result += GetHashCode(genericInstSig.GenericArguments, substituteGenericParameters); break; } case ElementType.FnPtr: result = GetHashCode_FnPtr_SystemIntPtr(); break; case ElementType.ValueArray: result = -674970533 + (int)(a as ValueArraySig).Size + GetHashCode(a.Next, substituteGenericParameters); break; case ElementType.Module: result = -299744851 + (int)(a as ModuleSig).Index + GetHashCode(a.Next, substituteGenericParameters); break; default: result = 0; break; } recursionCounter.Decrement(); return result; } public bool Equals(IList a, IList b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (a.Count != b.Count) { result = false; } else { int i; for (i = 0; i < a.Count && Equals(a[i], b[i]); i++) { } result = i == a.Count; } recursionCounter.Decrement(); return result; } public int GetHashCode(IList a) { return GetHashCode(a, substituteGenericParameters: true); } private int GetHashCode(IList a, bool substituteGenericParameters) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } uint num = 0u; for (int i = 0; i < a.Count; i++) { num += (uint)GetHashCode(a[i], substituteGenericParameters); num = (num << 13) | (num >> 19); } recursionCounter.Decrement(); return (int)num; } private bool Equals(IList a, IList b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.Count != b.Count) { return false; } for (int i = 0; i < a.Count; i++) { if (a[i] != b[i]) { return false; } } return true; } private bool Equals(IList a, IList b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.Count != b.Count) { return false; } for (int i = 0; i < a.Count; i++) { if (a[i] != b[i]) { return false; } } return true; } public bool Equals(CallingConventionSig a, CallingConventionSig b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (a.GetCallingConvention() != b.GetCallingConvention()) { result = false; } else { switch (a.GetCallingConvention() & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Property: case CallingConvention.Unmanaged: case CallingConvention.NativeVarArg: { MethodBaseSig methodBaseSig = a as MethodBaseSig; MethodBaseSig methodBaseSig2 = b as MethodBaseSig; result = methodBaseSig != null && methodBaseSig2 != null && Equals(methodBaseSig, methodBaseSig2); break; } case CallingConvention.Field: { FieldSig fieldSig = a as FieldSig; FieldSig fieldSig2 = b as FieldSig; result = fieldSig != null && fieldSig2 != null && Equals(fieldSig, fieldSig2); break; } case CallingConvention.LocalSig: { LocalSig localSig = a as LocalSig; LocalSig localSig2 = b as LocalSig; result = localSig != null && localSig2 != null && Equals(localSig, localSig2); break; } case CallingConvention.GenericInst: { GenericInstMethodSig genericInstMethodSig = a as GenericInstMethodSig; GenericInstMethodSig genericInstMethodSig2 = b as GenericInstMethodSig; result = genericInstMethodSig != null && genericInstMethodSig2 != null && Equals(genericInstMethodSig, genericInstMethodSig2); break; } default: result = false; break; } } recursionCounter.Decrement(); return result; } public int GetHashCode(CallingConventionSig a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result; switch (a.GetCallingConvention() & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Property: case CallingConvention.Unmanaged: case CallingConvention.NativeVarArg: result = ((a is MethodBaseSig a4) ? GetHashCode(a4) : 0); break; case CallingConvention.Field: result = ((a is FieldSig a3) ? GetHashCode(a3) : 0); break; case CallingConvention.LocalSig: result = ((a is LocalSig a5) ? GetHashCode(a5) : 0); break; case CallingConvention.GenericInst: result = ((a is GenericInstMethodSig a2) ? GetHashCode(a2) : 0); break; default: result = GetHashCode_CallingConvention(a); break; } recursionCounter.Decrement(); return result; } public bool Equals(MethodBaseSig a, MethodBaseSig b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = a.GetCallingConvention() == b.GetCallingConvention() && (DontCompareReturnType || Equals(a.RetType, b.RetType)) && Equals(a.Params, b.Params) && (!a.Generic || a.GenParamCount == b.GenParamCount) && (!CompareSentinelParams || Equals(a.ParamsAfterSentinel, b.ParamsAfterSentinel)); recursionCounter.Decrement(); return result; } public int GetHashCode(MethodBaseSig a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_CallingConvention(a) + GetHashCode(a.Params); if (!DontCompareReturnType) { num += GetHashCode(a.RetType); } if (a.Generic) { num += GetHashCode_ElementType_MVar((int)a.GenParamCount); } if (CompareSentinelParams) { num += GetHashCode(a.ParamsAfterSentinel); } recursionCounter.Decrement(); return num; } private int GetHashCode_CallingConvention(CallingConventionSig a) { return GetHashCode(a.GetCallingConvention()); } private int GetHashCode(CallingConvention a) { switch (a & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Field: case CallingConvention.Property: case CallingConvention.Unmanaged: case CallingConvention.GenericInst: case CallingConvention.NativeVarArg: return (int)(a & ~(CallingConvention.Mask | CallingConvention.ReservedByCLR)); default: return (int)a; } } public bool Equals(FieldSig a, FieldSig b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.Type, b.Type); recursionCounter.Decrement(); return result; } public int GetHashCode(FieldSig a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = GetHashCode_CallingConvention(a) + GetHashCode(a.Type); recursionCounter.Decrement(); return result; } public bool Equals(LocalSig a, LocalSig b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.Locals, b.Locals); recursionCounter.Decrement(); return result; } public int GetHashCode(LocalSig a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = GetHashCode_CallingConvention(a) + GetHashCode(a.Locals); recursionCounter.Decrement(); return result; } public bool Equals(GenericInstMethodSig a, GenericInstMethodSig b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.GenericArguments, b.GenericArguments); recursionCounter.Decrement(); return result; } public int GetHashCode(GenericInstMethodSig a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = GetHashCode_CallingConvention(a) + GetHashCode(a.GenericArguments); recursionCounter.Decrement(); return result; } public bool Equals(IMethod a, IMethod b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } MethodDef methodDef; MethodDef methodDef2; MemberRef memberRef; MemberRef memberRef2; bool result = ((((methodDef = a as MethodDef) != null) & ((methodDef2 = b as MethodDef) != null)) ? Equals(methodDef, methodDef2) : ((((memberRef = a as MemberRef) != null) & ((memberRef2 = b as MemberRef) != null)) ? Equals(memberRef, memberRef2) : ((a is MethodSpec a2 && b is MethodSpec b2) ? Equals(a2, b2) : ((methodDef != null && memberRef2 != null) ? Equals(methodDef, memberRef2) : (memberRef != null && methodDef2 != null && Equals(methodDef2, memberRef)))))); recursionCounter.Decrement(); return result; } public int GetHashCode(IMethod a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = ((!(a is MethodDef a2)) ? ((!(a is MemberRef a3)) ? ((a is MethodSpec a4) ? GetHashCode(a4) : 0) : GetHashCode(a3)) : GetHashCode(a2)); recursionCounter.Decrement(); return result; } public bool Equals(MemberRef a, MethodDef b) { return Equals(b, a); } public bool Equals(MethodDef a, MemberRef b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (!DontProjectWinMDRefs) { MemberRef memberRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (memberRef != null) { result = Equals(memberRef, b); goto IL_00c0; } } result = (PrivateScopeMethodIsComparable || !a.IsPrivateScope) && Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.Class)); goto IL_00c0; IL_00c0: recursionCounter.Decrement(); return result; } public bool Equals(MethodDef a, MethodDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (ReferenceCompareForMemberDefsInSameModule && InSameModule(a, b)) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (!DontProjectWinMDRefs) { MemberRef memberRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); MemberRef memberRef2 = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b); if (memberRef != null || memberRef2 != null) { IMethod method = memberRef; IMethod a2 = method ?? a; method = memberRef2; result = Equals(a2, method ?? b); goto IL_00ce; } } result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); goto IL_00ce; IL_00ce: recursionCounter.Decrement(); return result; } public int GetHashCode(MethodDef a) { if (a == null) { return 0; } if (!DontProjectWinMDRefs) { MemberRef memberRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (memberRef != null) { return GetHashCode(memberRef); } } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_MethodFieldName(a.Name) + GetHashCode(a.Signature); if (CompareMethodFieldDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } public bool Equals(MemberRef a, MemberRef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.Class)); recursionCounter.Decrement(); return result; } public int GetHashCode(MemberRef a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } int hashCode_MethodFieldName = GetHashCode_MethodFieldName(a.Name); GenericInstSig genericInstanceType; if (CompareMethodFieldDeclaringType && !DontSubstituteGenericParameters && (genericInstanceType = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(genericInstanceType.GenericArguments); hashCode_MethodFieldName += GetHashCode(a.Signature); genericArguments.PopTypeArgs(); } else { hashCode_MethodFieldName += GetHashCode(a.Signature); } if (CompareMethodFieldDeclaringType) { hashCode_MethodFieldName += GetHashCode(a.Class); } recursionCounter.Decrement(); return hashCode_MethodFieldName; } public bool Equals(MethodSpec a, MethodSpec b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals(a.Method, b.Method) && Equals(a.Instantiation, b.Instantiation); recursionCounter.Decrement(); return result; } public int GetHashCode(MethodSpec a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } GenericInstMethodSig genericInstMethodSig = a.GenericInstMethodSig; if (genericInstMethodSig != null) { InitializeGenericArguments(); genericArguments.PushMethodArgs(genericInstMethodSig.GenericArguments); } int hashCode = GetHashCode(a.Method); if (genericInstMethodSig != null) { genericArguments.PopMethodArgs(); } recursionCounter.Decrement(); return hashCode; } private bool Equals(IMemberRefParent a, IMemberRefParent b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; ModuleRef moduleRef; ModuleRef moduleRef2; if (a is ITypeDefOrRef a2 && b is ITypeDefOrRef b2) { result = Equals((IType)a2, (IType)b2); } else if (!(((moduleRef = a as ModuleRef) != null) & ((moduleRef2 = b as ModuleRef) != null))) { result = ((a is MethodDef a3 && b is MethodDef b3) ? Equals(a3, b3) : ((moduleRef2 != null && a is TypeDef a4) ? EqualsGlobal(a4, moduleRef2) : (moduleRef != null && b is TypeDef a5 && EqualsGlobal(a5, moduleRef)))); } else { ModuleDef module = moduleRef.Module; ModuleDef module2 = moduleRef2.Module; result = Equals((IModule)moduleRef, (IModule)moduleRef2) && Equals(module?.Assembly, module2?.Assembly); } recursionCounter.Decrement(); return result; } private int GetHashCode(IMemberRefParent a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = ((!(a is ITypeDefOrRef a2)) ? ((a is ModuleRef) ? GetHashCodeGlobalType() : ((a is MethodDef methodDef) ? GetHashCode(methodDef.DeclaringType) : 0)) : GetHashCode((IType)a2)); recursionCounter.Decrement(); return result; } public bool Equals(IField a, IField b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } FieldDef fieldDef; FieldDef fieldDef2; MemberRef memberRef; MemberRef memberRef2; bool result = ((((fieldDef = a as FieldDef) != null) & ((fieldDef2 = b as FieldDef) != null)) ? Equals(fieldDef, fieldDef2) : ((((memberRef = a as MemberRef) != null) & ((memberRef2 = b as MemberRef) != null)) ? Equals(memberRef, memberRef2) : ((fieldDef != null && memberRef2 != null) ? Equals(fieldDef, memberRef2) : (fieldDef2 != null && memberRef != null && Equals(fieldDef2, memberRef))))); recursionCounter.Decrement(); return result; } public int GetHashCode(IField a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int result = ((!(a is FieldDef a2)) ? ((a is MemberRef a3) ? GetHashCode(a3) : 0) : GetHashCode(a2)); recursionCounter.Decrement(); return result; } public bool Equals(MemberRef a, FieldDef b) { return Equals(b, a); } public bool Equals(FieldDef a, MemberRef b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = (PrivateScopeFieldIsComparable || !a.IsPrivateScope) && Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.Class)); recursionCounter.Decrement(); return result; } public bool Equals(FieldDef a, FieldDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (ReferenceCompareForMemberDefsInSameModule && InSameModule(a, b)) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } public int GetHashCode(FieldDef a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_MethodFieldName(a.Name) + GetHashCode(a.Signature); if (CompareMethodFieldDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } public bool Equals(PropertyDef a, PropertyDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (ReferenceCompareForMemberDefsInSameModule && InSameModule(a, b)) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_PropertyNames(a.Name, b.Name) && Equals(a.Type, b.Type) && (!ComparePropertyDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } public int GetHashCode(PropertyDef a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } PropertySig propertySig = a.PropertySig; int num = GetHashCode_PropertyName(a.Name) + GetHashCode(propertySig?.RetType); if (ComparePropertyDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } public bool Equals(EventDef a, EventDef b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (ReferenceCompareForMemberDefsInSameModule && InSameModule(a, b)) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_EventNames(a.Name, b.Name) && Equals((IType)a.EventType, (IType)b.EventType) && (!CompareEventDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } public int GetHashCode(EventDef a) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_EventName(a.Name) + GetHashCode((IType)a.EventType); if (CompareEventDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } private bool EqualsGlobal(TypeDef a, ModuleRef b) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = a.IsGlobalModuleType && Equals(a.Module, b) && Equals(a.DefinitionAssembly, GetAssembly(b.Module)); recursionCounter.Decrement(); return result; } private static AssemblyDef GetAssembly(ModuleDef module) { return module?.Assembly; } public bool Equals(Type a, IType b) { return Equals(b, a); } public bool Equals(IType a, Type b) { if (a == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is TypeDef a2)) ? ((!(a is TypeRef a3)) ? ((!(a is TypeSpec a4)) ? ((!(a is TypeSig a5)) ? (a is ExportedType a6 && Equals(a6, b)) : Equals(a5, b)) : Equals(a4, b)) : Equals(a3, b)) : Equals(a2, b)); recursionCounter.Decrement(); return result; } public bool Equals(Type a, TypeDef b) { return Equals(b, a); } public bool Equals(TypeDef a, Type b) { if (a == null) { return false; } if ((object)b == null) { return a.IsGlobalModuleType; } if (!recursionCounter.Increment()) { return false; } bool result; if (!DontProjectWinMDRefs) { TypeRef typeRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (typeRef != null) { result = Equals(typeRef, b); goto IL_00b0; } } result = !b.HasElementType && Equals_TypeNames(a.Name, ReflectionExtensions.Unescape(b.Name)) && Equals_TypeNamespaces(a.Namespace, b) && EnclosingTypeEquals(a.DeclaringType, b.DeclaringType) && (DontCompareTypeScope || Equals(a.Module, b.Module)); goto IL_00b0; IL_00b0: recursionCounter.Decrement(); return result; } private bool EnclosingTypeEquals(TypeDef a, Type b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } return Equals(a, b); } public bool Equals(Type a, TypeRef b) { return Equals(b, a); } public bool Equals(TypeRef a, Type b) { if (a == null) { return false; } if ((object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } IResolutionScope resolutionScope = a.ResolutionScope; bool result = b.IsTypeDef() && Equals_TypeNames(a.Name, ReflectionExtensions.Unescape(b.Name)) && Equals_TypeNamespaces(a.Namespace, b) && ((!(resolutionScope is TypeRef a2)) ? (!b.IsNested && (DontCompareTypeScope || ((!(resolutionScope is IModule bMod)) ? (resolutionScope is AssemblyRef bAsm && Equals(b.Assembly, bAsm, a)) : Equals(b, bMod, a)))) : Equals(a2, b.DeclaringType)); recursionCounter.Decrement(); return result; } private bool Equals_TypeNamespaces(UTF8String a, Type b) { if (b.IsNested) { return true; } return Equals_TypeNamespaces(a, b.Namespace); } public bool Equals(Type a, TypeSpec b) { return Equals(b, a); } public bool Equals(TypeSpec a, Type b) { if (a == null) { return false; } if ((object)b == null) { return false; } return Equals(a.TypeSig, b); } public bool Equals(Type a, TypeSig b) { return Equals(b, a); } public bool Equals(TypeSig a, Type b) { return Equals(a, b, null, false); } private bool Equals(ITypeDefOrRef a, Type b, Type declaringType) { if (a is TypeSpec typeSpec) { return Equals(typeSpec.TypeSig, b, declaringType); } return Equals(a, b); } private static bool IsFnPtrElementType(Type a) { if ((object)a == null || !a.HasElementType) { return false; } Type elementType = a.GetElementType(); if ((object)elementType == null || elementType.HasElementType) { return false; } if (elementType != typeof(IntPtr)) { return false; } if (!a.FullName.StartsWith("(fnptr)")) { return false; } return true; } private bool Equals(TypeSig a, Type b, Type declaringType, bool? treatAsGenericInst = null) { if (a == null) { return false; } if ((object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag = treatAsGenericInst ?? declaringType.MustTreatTypeAsGenericInstType(b); if (genericArguments != null) { a = genericArguments.Resolve(a); } bool result; switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = Equals(((TypeDefOrRefSig)a).TypeDefOrRef, b, declaringType); break; case ElementType.Ptr: if (!b.IsPointer) { result = false; } else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else { result = Equals(a.Next, b.GetElementType(), declaringType); } break; case ElementType.ByRef: if (!b.IsByRef) { result = false; } else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else { result = Equals(a.Next, b.GetElementType(), declaringType); } break; case ElementType.SZArray: if (!b.IsArray || !b.IsSZArray()) { result = false; } else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else { result = Equals(a.Next, b.GetElementType(), declaringType); } break; case ElementType.Pinned: result = Equals(a.Next, b, declaringType); break; case ElementType.Array: result = b.IsArray && !b.IsSZArray() && (a as ArraySig).Rank == b.GetArrayRank() && ((!IsFnPtrElementType(b)) ? Equals(a.Next, b.GetElementType(), declaringType) : ((a = a.Next.RemoveModifiers()) != null && a.ElementType == ElementType.FnPtr)); break; case ElementType.ValueType: case ElementType.Class: result = Equals((a as ClassOrValueTypeSig).TypeDefOrRef, b, declaringType); break; case ElementType.Var: result = b.IsGenericParameter && b.GenericParameterPosition == (a as GenericSig).Number && (object)b.DeclaringMethod == null; break; case ElementType.MVar: result = b.IsGenericParameter && b.GenericParameterPosition == (a as GenericSig).Number && (object)b.DeclaringMethod != null; break; case ElementType.GenericInst: { if ((!b.IsGenericType || b.IsGenericTypeDefinition) && !flag) { result = false; break; } GenericInstSig genericInstSig = (GenericInstSig)a; result = Equals(genericInstSig.GenericType, b.GetGenericTypeDefinition(), null, false) && Equals(genericInstSig.GenericArguments, b.GetGenericArguments(), declaringType); break; } case ElementType.CModReqd: case ElementType.CModOpt: result = Equals(a.Next, b, declaringType); break; case ElementType.FnPtr: result = b == typeof(IntPtr); break; default: result = false; break; } recursionCounter.Decrement(); return result; } public bool Equals(Type a, ExportedType b) { return Equals(b, a); } public bool Equals(ExportedType a, Type b) { if (a == null) { return false; } if ((object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } IImplementation implementation = a.Implementation; bool result = b.IsTypeDef() && Equals_TypeNames(a.TypeName, ReflectionExtensions.Unescape(b.Name)) && Equals_TypeNamespaces(a.TypeNamespace, b) && ((!(implementation is ExportedType a2)) ? (!b.IsNested && (DontCompareTypeScope || ((!(implementation is FileDef bFile)) ? (implementation is AssemblyRef bAsm && Equals(b.Assembly, bAsm, a)) : Equals(b, bFile, a)))) : Equals(a2, b.DeclaringType)); recursionCounter.Decrement(); return result; } public int GetHashCode(Type a) { return GetHashCode(a, treatAsGenericInst: false); } public int GetHashCode(Type a, bool treatAsGenericInst) { return GetHashCode(a, null, treatAsGenericInst); } private int GetHashCode(Type a, Type declaringType, bool? treatAsGenericInst = null) { if ((object)a == null) { return GetHashCode_TypeDef(a); } if (!recursionCounter.Increment()) { return 0; } int result; switch ((treatAsGenericInst ?? declaringType.MustTreatTypeAsGenericInstType(a)) ? ElementType.GenericInst : a.GetElementType2()) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = GetHashCode_TypeDef(a); break; case ElementType.FnPtr: result = GetHashCode_FnPtr_SystemIntPtr(); break; case ElementType.Sentinel: result = 68439620; break; case ElementType.Ptr: result = 1976400808 + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType(), declaringType)); break; case ElementType.ByRef: result = -634749586 + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType(), declaringType)); break; case ElementType.SZArray: result = 871833535 + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType(), declaringType)); break; case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: result = GetHashCode(a.GetElementType(), declaringType); break; case ElementType.Array: result = -96331531 + a.GetArrayRank() + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType(), declaringType)); break; case ElementType.Var: result = 1288450097 + a.GenericParameterPosition; break; case ElementType.MVar: result = -990598495 + a.GenericParameterPosition; break; case ElementType.GenericInst: result = -2050514639 + GetHashCode(a.GetGenericTypeDefinition(), treatAsGenericInst: false) + GetHashCode(a.GetGenericArguments(), declaringType); break; default: result = 0; break; } recursionCounter.Decrement(); return result; } private int GetHashCode(IList a, Type declaringType) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } uint num = 0u; for (int i = 0; i < a.Count; i++) { num += (uint)GetHashCode(a[i], declaringType); num = (num << 13) | (num >> 19); } recursionCounter.Decrement(); return (int)num; } private static int GetHashCode_ElementType_MVar(int numGenericParams) { return GetHashCode(numGenericParams, -990598495); } private static int GetHashCode(int numGenericParams, int etypeHashCode) { uint num = 0u; for (int i = 0; i < numGenericParams; i++) { num += (uint)(etypeHashCode + i); num = (num << 13) | (num >> 19); } return (int)num; } public int GetHashCode_TypeDef(Type a) { if ((object)a == null) { return GetHashCodeGlobalType(); } int hashCode_TypeName = GetHashCode_TypeName(ReflectionExtensions.Unescape(a.Name)); if (a.IsNested) { return hashCode_TypeName + -1049070942; } return hashCode_TypeName + GetHashCode_TypeNamespace(a.Namespace); } private bool Equals(IList a, IList b, Type declaringType) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (a.Count != b.Count) { result = false; } else { int i; for (i = 0; i < a.Count && Equals(a[i], b[i], declaringType); i++) { } result = i == a.Count; } recursionCounter.Decrement(); return result; } private bool Equals(ModuleDef a, Module b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } if (!recursionCounter.Increment()) { return false; } bool result = Equals((IModule)a, b) && Equals(a.Assembly, b.Assembly); recursionCounter.Decrement(); return result; } private bool Equals(FileDef a, Module b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } return UTF8String.ToSystemStringOrEmpty(a.Name).Equals(b.Name, StringComparison.OrdinalIgnoreCase); } private bool Equals(IModule a, Module b) { if (a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } return UTF8String.ToSystemStringOrEmpty(a.Name).Equals(b.ScopeName, StringComparison.OrdinalIgnoreCase); } private bool Equals(IAssembly a, Assembly b) { if (a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) { return true; } if (!recursionCounter.Increment()) { return false; } AssemblyName name = b.GetName(); bool result = UTF8String.ToSystemStringOrEmpty(a.Name).Equals(name.Name, StringComparison.OrdinalIgnoreCase) && (!CompareAssemblyPublicKeyToken || PublicKeyBase.TokenEquals(a.PublicKeyOrToken, new PublicKeyToken(name.GetPublicKeyToken()))) && (!CompareAssemblyVersion || Utils.Equals(a.Version, name.Version)) && (!CompareAssemblyLocale || Utils.LocaleEquals(a.Culture, name.CultureInfo.Name)); recursionCounter.Decrement(); return result; } private bool DeclaringTypeEquals(IMethod a, MethodBase b) { if (!CompareMethodFieldDeclaringType) { return true; } if (a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is MethodDef a2)) ? ((!(a is MemberRef a3)) ? (a is MethodSpec a4 && DeclaringTypeEquals(a4, b)) : DeclaringTypeEquals(a3, b)) : DeclaringTypeEquals(a2, b)); recursionCounter.Decrement(); return result; } private bool DeclaringTypeEquals(MethodDef a, MethodBase b) { if (!CompareMethodFieldDeclaringType) { return true; } if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } return Equals(a.DeclaringType, b.DeclaringType); } private bool DeclaringTypeEquals(MemberRef a, MethodBase b) { if (!CompareMethodFieldDeclaringType) { return true; } if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } return Equals(a.Class, b.DeclaringType, b.Module); } private bool DeclaringTypeEquals(MethodSpec a, MethodBase b) { if (!CompareMethodFieldDeclaringType) { return true; } if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } return DeclaringTypeEquals(a.Method, b); } public bool Equals(MethodBase a, IMethod b) { return Equals(b, a); } public bool Equals(IMethod a, MethodBase b) { if (a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is MethodDef a2)) ? ((!(a is MemberRef a3)) ? (a is MethodSpec a4 && Equals(a4, b)) : Equals(a3, b)) : Equals(a2, b)); recursionCounter.Decrement(); return result; } public bool Equals(MethodBase a, MethodDef b) { return Equals(b, a); } public bool Equals(MethodDef a, MethodBase b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (!DontProjectWinMDRefs) { MemberRef memberRef = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (memberRef != null) { result = Equals(memberRef, b); goto IL_00c3; } } MethodSig methodSig = a.MethodSig; result = Equals_MethodFieldNames(a.Name, b.Name) && methodSig != null && ((methodSig.Generic && b.IsGenericMethodDefinition && b.IsGenericMethod) || (!methodSig.Generic && !b.IsGenericMethodDefinition && !b.IsGenericMethod)) && Equals(methodSig, b) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); goto IL_00c3; IL_00c3: recursionCounter.Decrement(); return result; } public bool Equals(MethodBase a, MethodSig b) { return Equals(b, a); } public bool Equals(MethodSig a, MethodBase b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!CompareMethodFieldDeclaringType && b.DeclaringType.IsGenericButNotGenericTypeDefinition()) { MethodBase methodBase = b; b = b.Module.ResolveMethod(b.MetadataToken); if (b.IsGenericButNotGenericMethodDefinition()) { b = ((MethodInfo)b).MakeGenericMethod(methodBase.GetGenericArguments()); } } bool result = Equals(a.GetCallingConvention(), b) && (DontCompareReturnType || ReturnTypeEquals(a.RetType, b)) && Equals(a.Params, b.GetParameters(), b.DeclaringType) && (!a.Generic || a.GenParamCount == b.GetGenericArguments().Length); recursionCounter.Decrement(); return result; } public bool Equals(MethodBase a, MemberRef b) { return Equals(b, a); } public bool Equals(MemberRef a, MethodBase b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; } bool flag; if (b.IsGenericMethod && !b.IsGenericMethodDefinition) { flag = a.IsMethodRef && a.MethodSig.Generic; SigComparerOptions oldFlags = ClearOptions(SigComparerOptions.CompareMethodFieldDeclaringType); SetOptions((SigComparerOptions)1024u); flag = flag && Equals(a, b.Module.ResolveMethod(b.MetadataToken)); RestoreOptions(oldFlags); flag = flag && DeclaringTypeEquals(a, b) && GenericMethodArgsEquals((int)a.MethodSig.GenParamCount, b.GetGenericArguments()); } else { MethodSig methodSig = a.MethodSig; flag = Equals_MethodFieldNames(a.Name, b.Name) && methodSig != null && ((methodSig.Generic && b.IsGenericMethodDefinition && b.IsGenericMethod) || (!methodSig.Generic && !b.IsGenericMethodDefinition && !b.IsGenericMethod)); GenericInstSig genericInstanceType; if (CompareMethodFieldDeclaringType && !DontSubstituteGenericParameters && (genericInstanceType = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(genericInstanceType.GenericArguments); flag = flag && Equals(methodSig, b); genericArguments.PopTypeArgs(); } else { flag = flag && Equals(methodSig, b); } flag = flag && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.DeclaringType, b.Module)); } recursionCounter.Decrement(); return flag; } private static bool GenericMethodArgsEquals(int numMethodArgs, IList methodGenArgs) { if (numMethodArgs != methodGenArgs.Count) { return false; } for (int i = 0; i < numMethodArgs; i++) { if (methodGenArgs[i].GetElementType2() != ElementType.MVar) { return false; } } return true; } private bool Equals(IMemberRefParent a, Type b, Module bModule) { if (a == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is ITypeDefOrRef a2)) ? ((!(a is ModuleRef { Module: var module } moduleRef)) ? ((!(a is MethodDef methodDef)) ? ((object)b == null && a is TypeDef typeDef && typeDef.IsGlobalModuleType) : Equals(methodDef.DeclaringType, b)) : ((object)b == null && Equals(moduleRef, bModule) && Equals(module?.Assembly, bModule.Assembly))) : Equals(a2, b)); recursionCounter.Decrement(); return result; } public bool Equals(MethodBase a, MethodSpec b) { return Equals(b, a); } public bool Equals(MethodSpec a, MethodBase b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool num = b.IsGenericMethod && !b.IsGenericMethodDefinition; SigComparerOptions oldFlags = ClearOptions(SigComparerOptions.CompareMethodFieldDeclaringType); SetOptions((SigComparerOptions)1024u); bool num2 = num && Equals(a.Method, b.Module.ResolveMethod(b.MetadataToken)); RestoreOptions(oldFlags); bool num3 = num2 && DeclaringTypeEquals(a.Method, b); GenericInstMethodSig genericInstMethodSig = a.GenericInstMethodSig; bool result = num3 && genericInstMethodSig != null && Equals(genericInstMethodSig.GenericArguments, b.GetGenericArguments(), b.DeclaringType); recursionCounter.Decrement(); return result; } public int GetHashCode(MethodBase a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_MethodFieldName(a.Name) + GetHashCode_MethodSig(a); if (CompareMethodFieldDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } private int GetHashCode_MethodSig(MethodBase a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } if (!CompareMethodFieldDeclaringType && a.DeclaringType.IsGenericButNotGenericTypeDefinition()) { MethodBase methodBase = a; a = a.Module.ResolveMethod(a.MetadataToken); if (methodBase.IsGenericButNotGenericMethodDefinition()) { a = ((MethodInfo)a).MakeGenericMethod(methodBase.GetGenericArguments()); } } int num = GetHashCode_CallingConvention(a.CallingConvention, a.IsGenericMethod) + GetHashCode(a.GetParameters(), a.DeclaringType); if (!DontCompareReturnType) { num += GetHashCode_ReturnType(a); } if (a.IsGenericMethod) { num += GetHashCode_ElementType_MVar(a.GetGenericArguments().Length); } recursionCounter.Decrement(); return num; } private int GetHashCode(IList a, Type declaringType) { if (a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } uint num = 0u; for (int i = 0; i < a.Count; i++) { num += (uint)GetHashCode(a[i], declaringType); num = (num << 13) | (num >> 19); } recursionCounter.Decrement(); return (int)num; } private int GetHashCode_ReturnType(MethodBase a) { if (a is MethodInfo methodInfo) { return GetHashCode(methodInfo.ReturnParameter, a.DeclaringType); } return GetHashCode(typeof(void)); } private int GetHashCode(ParameterInfo a, Type declaringType) { return GetHashCode(a.ParameterType, declaringType); } private static bool Equals(CallingConvention a, MethodBase b) { CallingConventions callingConvention = b.CallingConvention; if ((a & CallingConvention.Generic) != 0 != b.IsGenericMethod) { return false; } if ((a & CallingConvention.HasThis) != 0 != ((callingConvention & CallingConventions.HasThis) != 0)) { return false; } if ((a & CallingConvention.ExplicitThis) != 0 != ((callingConvention & CallingConventions.ExplicitThis) != 0)) { return false; } CallingConvention callingConvention2 = a & CallingConvention.Mask; switch (callingConvention & CallingConventions.Any) { case CallingConventions.Standard: if (callingConvention2 == CallingConvention.VarArg || callingConvention2 == CallingConvention.NativeVarArg) { return false; } break; case CallingConventions.VarArgs: if (callingConvention2 != CallingConvention.VarArg && callingConvention2 != CallingConvention.NativeVarArg) { return false; } break; } return true; } private static int GetHashCode_CallingConvention(CallingConventions a, bool isGeneric) { CallingConvention callingConvention = CallingConvention.Default; if (isGeneric) { callingConvention |= CallingConvention.Generic; } if ((a & CallingConventions.HasThis) != 0) { callingConvention |= CallingConvention.HasThis; } if ((a & CallingConventions.ExplicitThis) != 0) { callingConvention |= CallingConvention.ExplicitThis; } return (int)callingConvention; } private bool ReturnTypeEquals(TypeSig a, MethodBase b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(b is MethodInfo methodInfo)) ? (b is ConstructorInfo && IsSystemVoid(a)) : Equals(a, methodInfo.ReturnParameter, b.DeclaringType)); recursionCounter.Decrement(); return result; } private static bool IsSystemVoid(TypeSig a) { return a.RemovePinnedAndModifiers().GetElementType() == ElementType.Void; } private bool Equals(IList a, IList b, Type declaringType) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (a.Count != b.Count) { result = false; } else { int i; for (i = 0; i < a.Count && Equals(a[i], b[i], declaringType); i++) { } result = i == a.Count; } recursionCounter.Decrement(); return result; } private bool Equals(TypeSig a, ParameterInfo b, Type declaringType) { if ((object)a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } TypeSig aAfterModifiers; bool result = ModifiersEquals(a, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out aAfterModifiers) && Equals(aAfterModifiers, b.ParameterType, declaringType); recursionCounter.Decrement(); return result; } private bool ModifiersEquals(TypeSig a, IList reqMods2, IList optMods2, out TypeSig aAfterModifiers) { aAfterModifiers = a; if (!(a is ModifierSig)) { if (reqMods2.Count == 0) { return optMods2.Count == 0; } return false; } if (!recursionCounter.Increment()) { return false; } List list = new List(reqMods2.Count); List list2 = new List(optMods2.Count); while (aAfterModifiers is ModifierSig modifierSig) { if (modifierSig is CModOptSig) { list2.Add(modifierSig.Modifier); } else { list.Add(modifierSig.Modifier); } aAfterModifiers = aAfterModifiers.Next; } list2.Reverse(); list.Reverse(); bool result = list.Count == reqMods2.Count && list2.Count == optMods2.Count && ModifiersEquals(list, reqMods2) && ModifiersEquals(list2, optMods2); recursionCounter.Decrement(); return result; } private bool ModifiersEquals(IList a, IList b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; if (a.Count != b.Count) { result = false; } else { int i; for (i = 0; i < b.Count && Equals(a[i], b[i]); i++) { } result = i == b.Count; } recursionCounter.Decrement(); return result; } public bool Equals(FieldInfo a, IField b) { return Equals(b, a); } public bool Equals(IField a, FieldInfo b) { if (a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ((!(a is FieldDef a2)) ? (a is MemberRef a3 && Equals(a3, b)) : Equals(a2, b)); recursionCounter.Decrement(); return result; } public bool Equals(FieldInfo a, FieldDef b) { return Equals(b, a); } public bool Equals(FieldDef a, FieldInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.FieldSig, b) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } private bool Equals(FieldSig a, FieldInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } if (!CompareMethodFieldDeclaringType && b.DeclaringType.IsGenericButNotGenericTypeDefinition()) { b = b.Module.ResolveField(b.MetadataToken); } TypeSig aAfterModifiers; bool result = ModifiersEquals(a.Type, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out aAfterModifiers) && Equals(aAfterModifiers, b.FieldType, b.DeclaringType); recursionCounter.Decrement(); return result; } public bool Equals(FieldInfo a, MemberRef b) { return Equals(b, a); } public bool Equals(MemberRef a, FieldInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool flag = Equals_MethodFieldNames(a.Name, b.Name); GenericInstSig genericInstanceType; if (CompareMethodFieldDeclaringType && !DontSubstituteGenericParameters && (genericInstanceType = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(genericInstanceType.GenericArguments); flag = flag && Equals(a.FieldSig, b); genericArguments.PopTypeArgs(); } else { flag = flag && Equals(a.FieldSig, b); } flag = flag && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.DeclaringType, b.Module)); recursionCounter.Decrement(); return flag; } public int GetHashCode(FieldInfo a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_MethodFieldName(a.Name) + GetHashCode_FieldSig(a); if (CompareMethodFieldDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } private int GetHashCode_FieldSig(FieldInfo a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } if (!CompareMethodFieldDeclaringType && a.DeclaringType.IsGenericButNotGenericTypeDefinition()) { a = a.Module.ResolveField(a.MetadataToken); } int result = GetHashCode_CallingConvention((CallingConventions)0, isGeneric: false) + GetHashCode(a.FieldType, a.DeclaringType); recursionCounter.Decrement(); return result; } public bool Equals(PropertyDef a, PropertyInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_PropertyNames(a.Name, b.Name) && Equals(a.PropertySig, b) && (!ComparePropertyDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } private bool Equals(PropertySig a, PropertyInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } TypeSig aAfterModifiers; bool result = ModifiersEquals(a.RetType, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out aAfterModifiers) && Equals(aAfterModifiers, b.PropertyType, b.DeclaringType); recursionCounter.Decrement(); return result; } public int GetHashCode(PropertyInfo a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_PropertyName(a.Name) + GetHashCode(a.PropertyType, a.DeclaringType); if (ComparePropertyDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } public bool Equals(EventDef a, EventInfo b) { if ((object)a == b) { return true; } if (a == null || (object)b == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = Equals_EventNames(a.Name, b.Name) && Equals(a.EventType, b.EventHandlerType, b.DeclaringType) && (!CompareEventDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } public int GetHashCode(EventInfo a) { if ((object)a == null) { return 0; } if (!recursionCounter.Increment()) { return 0; } int num = GetHashCode_EventName(a.Name) + GetHashCode(a.EventHandlerType, a.DeclaringType); if (CompareEventDeclaringType) { num += GetHashCode(a.DeclaringType); } recursionCounter.Decrement(); return num; } public override string ToString() { return $"{recursionCounter} - {options}"; } private static bool InSameModule(IOwnerModule a, IOwnerModule b) { ModuleDef module = a.Module; if (module != null) { return module == b.Module; } return false; } } public interface ISignatureReaderHelper { ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext); TypeSig ConvertRTInternalAddress(IntPtr address); } public struct SignatureReader { private const uint MaxArrayRank = 64u; private readonly ISignatureReaderHelper helper; private readonly ICorLibTypes corLibTypes; private DataReader reader; private readonly GenericParamContext gpContext; private RecursionCounter recursionCounter; public static CallingConventionSig ReadSig(ModuleDefMD readerModule, uint sig) { return ReadSig(readerModule, sig, default(GenericParamContext)); } public static CallingConventionSig ReadSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) { try { SignatureReader signatureReader = new SignatureReader(readerModule, sig, gpContext); if (signatureReader.reader.Length == 0) { return null; } CallingConventionSig callingConventionSig = signatureReader.ReadSig(); if (callingConventionSig != null) { callingConventionSig.ExtraData = signatureReader.GetExtraData(); } return callingConventionSig; } catch { return null; } } public static CallingConventionSig ReadSig(ModuleDefMD module, byte[] signature) { return ReadSig(module, module.CorLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), default(GenericParamContext)); } public static CallingConventionSig ReadSig(ModuleDefMD module, byte[] signature, GenericParamContext gpContext) { return ReadSig(module, module.CorLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), gpContext); } public static CallingConventionSig ReadSig(ModuleDefMD module, DataReader signature) { return ReadSig(module, module.CorLibTypes, signature, default(GenericParamContext)); } public static CallingConventionSig ReadSig(ModuleDefMD module, DataReader signature, GenericParamContext gpContext) { return ReadSig(module, module.CorLibTypes, signature, gpContext); } public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature) { return ReadSig(helper, corLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), default(GenericParamContext)); } public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext) { return ReadSig(helper, corLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), gpContext); } public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, DataReader signature) { return ReadSig(helper, corLibTypes, signature, default(GenericParamContext)); } public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, DataReader signature, GenericParamContext gpContext) { try { SignatureReader signatureReader = new SignatureReader(helper, corLibTypes, ref signature, gpContext); if (signatureReader.reader.Length == 0) { return null; } return signatureReader.ReadSig(); } catch { return null; } } public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig) { return ReadTypeSig(readerModule, sig, default(GenericParamContext)); } public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) { try { return new SignatureReader(readerModule, sig, gpContext).ReadType(); } catch { return null; } } public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, out byte[] extraData) { return ReadTypeSig(readerModule, sig, default(GenericParamContext), out extraData); } public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext, out byte[] extraData) { try { SignatureReader signatureReader = new SignatureReader(readerModule, sig, gpContext); TypeSig result; try { result = signatureReader.ReadType(); } catch (IOException) { signatureReader.reader.Position = 0u; result = null; } extraData = signatureReader.GetExtraData(); return result; } catch { extraData = null; return null; } } public static TypeSig ReadTypeSig(ModuleDefMD module, byte[] signature) { return ReadTypeSig(module, module.CorLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), default(GenericParamContext)); } public static TypeSig ReadTypeSig(ModuleDefMD module, byte[] signature, GenericParamContext gpContext) { return ReadTypeSig(module, module.CorLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), gpContext); } public static TypeSig ReadTypeSig(ModuleDefMD module, DataReader signature) { return ReadTypeSig(module, module.CorLibTypes, signature, default(GenericParamContext)); } public static TypeSig ReadTypeSig(ModuleDefMD module, DataReader signature, GenericParamContext gpContext) { return ReadTypeSig(module, module.CorLibTypes, signature, gpContext); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature) { return ReadTypeSig(helper, corLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), default(GenericParamContext)); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext) { return ReadTypeSig(helper, corLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), gpContext); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, DataReader signature) { return ReadTypeSig(helper, corLibTypes, signature, default(GenericParamContext)); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, DataReader signature, GenericParamContext gpContext) { byte[] extraData; return ReadTypeSig(helper, corLibTypes, signature, gpContext, out extraData); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext, out byte[] extraData) { return ReadTypeSig(helper, corLibTypes, ByteArrayDataReaderFactory.CreateReader(signature), gpContext, out extraData); } public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, DataReader signature, GenericParamContext gpContext, out byte[] extraData) { try { SignatureReader signatureReader = new SignatureReader(helper, corLibTypes, ref signature, gpContext); TypeSig result; try { result = signatureReader.ReadType(); } catch (IOException) { signatureReader.reader.Position = 0u; result = null; } extraData = signatureReader.GetExtraData(); return result; } catch { extraData = null; return null; } } private SignatureReader(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) { helper = readerModule; corLibTypes = readerModule.CorLibTypes; reader = readerModule.BlobStream.CreateReader(sig); this.gpContext = gpContext; recursionCounter = default(RecursionCounter); } private SignatureReader(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, ref DataReader reader, GenericParamContext gpContext) { this.helper = helper; this.corLibTypes = corLibTypes; this.reader = reader; this.gpContext = gpContext; recursionCounter = default(RecursionCounter); } private byte[] GetExtraData() { if (reader.Position == reader.Length) { return null; } return reader.ReadRemainingBytes(); } private CallingConventionSig ReadSig() { if (!recursionCounter.Increment()) { return null; } CallingConvention callingConvention = (CallingConvention)reader.ReadByte(); CallingConventionSig result; switch (callingConvention & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Unmanaged: case CallingConvention.NativeVarArg: result = ReadMethod(callingConvention); break; case CallingConvention.Field: result = ReadField(callingConvention); break; case CallingConvention.LocalSig: result = ReadLocalSig(callingConvention); break; case CallingConvention.Property: result = ReadProperty(callingConvention); break; case CallingConvention.GenericInst: result = ReadGenericInstMethod(callingConvention); break; default: result = null; break; } recursionCounter.Decrement(); return result; } private FieldSig ReadField(CallingConvention callingConvention) { return new FieldSig(callingConvention, ReadType()); } private MethodSig ReadMethod(CallingConvention callingConvention) { return ReadSig(new MethodSig(callingConvention)); } private PropertySig ReadProperty(CallingConvention callingConvention) { return ReadSig(new PropertySig(callingConvention)); } private T ReadSig(T methodSig) where T : MethodBaseSig { if (methodSig.Generic) { if (!reader.TryReadCompressedUInt32(out var value) || value > 65536) { return null; } methodSig.GenParamCount = value; } if (!reader.TryReadCompressedUInt32(out var value2) || value2 > 65536 || value2 > reader.BytesLeft) { return null; } methodSig.RetType = ReadType(); IList list = methodSig.Params; for (uint num = 0u; num < value2; num++) { TypeSig typeSig = ReadType(); if (typeSig is SentinelSig) { if (methodSig.ParamsAfterSentinel == null) { list = (methodSig.ParamsAfterSentinel = new List((int)(value2 - num))); } num--; } else { list.Add(typeSig); } } return methodSig; } private LocalSig ReadLocalSig(CallingConvention callingConvention) { if (!reader.TryReadCompressedUInt32(out var value) || value > 65536 || value > reader.BytesLeft) { return null; } LocalSig localSig = new LocalSig(callingConvention, value); IList locals = localSig.Locals; for (uint num = 0u; num < value; num++) { locals.Add(ReadType()); } return localSig; } private GenericInstMethodSig ReadGenericInstMethod(CallingConvention callingConvention) { if (!reader.TryReadCompressedUInt32(out var value) || value > 65536 || value > reader.BytesLeft) { return null; } GenericInstMethodSig genericInstMethodSig = new GenericInstMethodSig(callingConvention, value); IList genericArguments = genericInstMethodSig.GenericArguments; for (uint num = 0u; num < value; num++) { genericArguments.Add(ReadType()); } return genericInstMethodSig; } private TypeSig ReadType(bool allowTypeSpec = false) { if (!recursionCounter.Increment()) { return null; } TypeSig result = null; uint value2; switch ((ElementType)reader.ReadByte()) { case ElementType.Void: result = corLibTypes.Void; break; case ElementType.Boolean: result = corLibTypes.Boolean; break; case ElementType.Char: result = corLibTypes.Char; break; case ElementType.I1: result = corLibTypes.SByte; break; case ElementType.U1: result = corLibTypes.Byte; break; case ElementType.I2: result = corLibTypes.Int16; break; case ElementType.U2: result = corLibTypes.UInt16; break; case ElementType.I4: result = corLibTypes.Int32; break; case ElementType.U4: result = corLibTypes.UInt32; break; case ElementType.I8: result = corLibTypes.Int64; break; case ElementType.U8: result = corLibTypes.UInt64; break; case ElementType.R4: result = corLibTypes.Single; break; case ElementType.R8: result = corLibTypes.Double; break; case ElementType.String: result = corLibTypes.String; break; case ElementType.TypedByRef: result = corLibTypes.TypedReference; break; case ElementType.I: result = corLibTypes.IntPtr; break; case ElementType.U: result = corLibTypes.UIntPtr; break; case ElementType.Object: result = corLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(ReadType()); break; case ElementType.ByRef: result = new ByRefSig(ReadType()); break; case ElementType.ValueType: result = new ValueTypeSig(ReadTypeDefOrRef(allowTypeSpec)); break; case ElementType.Class: result = new ClassSig(ReadTypeDefOrRef(allowTypeSpec)); break; case ElementType.FnPtr: result = new FnPtrSig(ReadSig()); break; case ElementType.SZArray: result = new SZArraySig(ReadType()); break; case ElementType.CModReqd: result = new CModReqdSig(ReadTypeDefOrRef(allowTypeSpec: true), ReadType()); break; case ElementType.CModOpt: result = new CModOptSig(ReadTypeDefOrRef(allowTypeSpec: true), ReadType()); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(ReadType()); break; case ElementType.Var: if (reader.TryReadCompressedUInt32(out value2)) { result = new GenericVar(value2, gpContext.Type); } break; case ElementType.MVar: if (reader.TryReadCompressedUInt32(out value2)) { result = new GenericMVar(value2, gpContext.Method); } break; case ElementType.ValueArray: { TypeSig arrayType = ReadType(); if (reader.TryReadCompressedUInt32(out value2)) { result = new ValueArraySig(arrayType, value2); } break; } case ElementType.Module: if (reader.TryReadCompressedUInt32(out value2)) { result = new ModuleSig(value2, ReadType()); } break; case ElementType.GenericInst: { TypeSig arrayType = ReadType(); if (reader.TryReadCompressedUInt32(out value2) && value2 <= 65536 && value2 <= reader.BytesLeft) { GenericInstSig genericInstSig = new GenericInstSig(arrayType as ClassOrValueTypeSig, value2); IList genericArguments = genericInstSig.GenericArguments; for (uint num = 0u; num < value2; num++) { genericArguments.Add(ReadType()); } result = genericInstSig; } break; } case ElementType.Array: { TypeSig arrayType = ReadType(); if (!reader.TryReadCompressedUInt32(out var value)) { break; } switch (value) { case 0u: result = new ArraySig(arrayType, value); break; case 1u: case 2u: case 3u: case 4u: case 5u: case 6u: case 7u: case 8u: case 9u: case 10u: case 11u: case 12u: case 13u: case 14u: case 15u: case 16u: case 17u: case 18u: case 19u: case 20u: case 21u: case 22u: case 23u: case 24u: case 25u: case 26u: case 27u: case 28u: case 29u: case 30u: case 31u: case 32u: case 33u: case 34u: case 35u: case 36u: case 37u: case 38u: case 39u: case 40u: case 41u: case 42u: case 43u: case 44u: case 45u: case 46u: case 47u: case 48u: case 49u: case 50u: case 51u: case 52u: case 53u: case 54u: case 55u: case 56u: case 57u: case 58u: case 59u: case 60u: case 61u: case 62u: case 63u: case 64u: { if (!reader.TryReadCompressedUInt32(out value2) || value2 > value) { break; } List list = new List((int)value2); uint num = 0u; while (true) { if (num < value2) { if (!reader.TryReadCompressedUInt32(out var value3)) { break; } list.Add(value3); num++; continue; } if (!reader.TryReadCompressedUInt32(out value2) || value2 > value) { break; } List list2 = new List((int)value2); num = 0u; while (true) { if (num < value2) { if (!reader.TryReadCompressedInt32(out var value4)) { break; } list2.Add(value4); num++; continue; } result = new ArraySig(arrayType, value, list, list2); break; } break; } break; } } break; } case ElementType.Internal: { IntPtr address = ((IntPtr.Size != 4) ? new IntPtr(reader.ReadInt64()) : new IntPtr(reader.ReadInt32())); result = helper.ConvertRTInternalAddress(address); break; } default: result = null; break; } recursionCounter.Decrement(); return result; } private ITypeDefOrRef ReadTypeDefOrRef(bool allowTypeSpec) { if (!reader.TryReadCompressedUInt32(out var value)) { return null; } if (!allowTypeSpec && CodedToken.TypeDefOrRef.Decode2(value).Table == Table.TypeSpec) { return null; } return helper.ResolveTypeDefOrRef(value, default(GenericParamContext)); } } public abstract class StandAloneSig : IHasCustomAttribute, ICodedToken, IMDTokenProvider, IHasCustomDebugInformation, IContainsGenericParameter { protected uint rid; protected CallingConventionSig signature; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.StandAloneSig, rid); public uint Rid { get { return rid; } set { rid = value; } } public int HasCustomAttributeTag => 11; public CallingConventionSig Signature { get { return signature; } set { signature = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 11; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } public LocalSig LocalSig { get { return signature as LocalSig; } set { signature = value; } } public bool ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } } public class StandAloneSigUser : StandAloneSig { public StandAloneSigUser() { } public StandAloneSigUser(LocalSig localSig) { signature = localSig; } public StandAloneSigUser(MethodSig methodSig) { signature = methodSig; } } internal sealed class StandAloneSigMD : StandAloneSig, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; public uint OrigRid => origRid; protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.StandAloneSig, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public StandAloneSigMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; readerModule.TablesStream.TryReadStandAloneSigRow(origRid, out var row); signature = readerModule.ReadSignature(row.Signature, gpContext); } } [Serializable] public class InvalidKeyException : Exception { public InvalidKeyException() { } public InvalidKeyException(string message) : base(message) { } public InvalidKeyException(string message, Exception innerException) : base(message, innerException) { } protected InvalidKeyException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public enum SignatureAlgorithm : uint { CALG_RSA_SIGN = 9216u } internal static class StrongNameUtils { public static byte[] ReadBytesReverse(this BinaryReader reader, int len) { byte[] array = reader.ReadBytes(len); if (array.Length != len) { throw new InvalidKeyException("Can't read more bytes"); } Array.Reverse(array); return array; } public static void WriteReverse(this BinaryWriter writer, byte[] data) { byte[] array = (byte[])data.Clone(); Array.Reverse(array); writer.Write(array); } } public sealed class StrongNamePublicKey { private const uint RSA1_SIG = 826364754u; private readonly SignatureAlgorithm signatureAlgorithm; private readonly AssemblyHashAlgorithm hashAlgorithm; private readonly byte[] modulus; private readonly byte[] publicExponent; public SignatureAlgorithm SignatureAlgorithm => signatureAlgorithm; public AssemblyHashAlgorithm HashAlgorithm => hashAlgorithm; public byte[] Modulus => modulus; public byte[] PublicExponent => publicExponent; public StrongNamePublicKey() { } public StrongNamePublicKey(byte[] modulus, byte[] publicExponent) : this(modulus, publicExponent, AssemblyHashAlgorithm.SHA1, SignatureAlgorithm.CALG_RSA_SIGN) { } public StrongNamePublicKey(byte[] modulus, byte[] publicExponent, AssemblyHashAlgorithm hashAlgorithm) : this(modulus, publicExponent, hashAlgorithm, SignatureAlgorithm.CALG_RSA_SIGN) { } public StrongNamePublicKey(byte[] modulus, byte[] publicExponent, AssemblyHashAlgorithm hashAlgorithm, SignatureAlgorithm signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; this.hashAlgorithm = hashAlgorithm; this.modulus = modulus; this.publicExponent = publicExponent; } public StrongNamePublicKey(PublicKey pk) : this(pk.Data) { } public StrongNamePublicKey(byte[] pk) : this(new BinaryReader(new MemoryStream(pk))) { } public StrongNamePublicKey(string filename) : this(File.ReadAllBytes(filename)) { } public StrongNamePublicKey(Stream stream) : this(new BinaryReader(stream)) { } public StrongNamePublicKey(BinaryReader reader) { try { signatureAlgorithm = (SignatureAlgorithm)reader.ReadUInt32(); hashAlgorithm = (AssemblyHashAlgorithm)reader.ReadUInt32(); reader.ReadInt32(); if (reader.ReadByte() != 6) { throw new InvalidKeyException("Not a public key"); } if (reader.ReadByte() != 2) { throw new InvalidKeyException("Invalid version"); } reader.ReadUInt16(); if (reader.ReadUInt32() != 9216) { throw new InvalidKeyException("Not RSA sign"); } if (reader.ReadUInt32() != 826364754) { throw new InvalidKeyException("Invalid RSA1 magic"); } uint num = reader.ReadUInt32(); publicExponent = reader.ReadBytesReverse(4); modulus = reader.ReadBytesReverse((int)(num / 8)); } catch (IOException innerException) { throw new InvalidKeyException("Invalid public key", innerException); } } public byte[] CreatePublicKey() { return CreatePublicKey(signatureAlgorithm, hashAlgorithm, modulus, publicExponent); } internal static byte[] CreatePublicKey(SignatureAlgorithm sigAlg, AssemblyHashAlgorithm hashAlg, byte[] modulus, byte[] publicExponent) { if (sigAlg != SignatureAlgorithm.CALG_RSA_SIGN) { throw new ArgumentException("Signature algorithm must be RSA"); } MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((uint)sigAlg); binaryWriter.Write((uint)hashAlg); binaryWriter.Write(20 + modulus.Length); binaryWriter.Write((byte)6); binaryWriter.Write((byte)2); binaryWriter.Write((ushort)0); binaryWriter.Write((uint)sigAlg); binaryWriter.Write(826364754u); binaryWriter.Write(modulus.Length * 8); binaryWriter.WriteReverse(publicExponent); binaryWriter.WriteReverse(modulus); return memoryStream.ToArray(); } public override string ToString() { return Utils.ToHex(CreatePublicKey(), upper: false); } } public sealed class StrongNameKey { private const uint RSA2_SIG = 843141970u; private byte[] publicKey; private readonly AssemblyHashAlgorithm hashAlg; private readonly byte[] publicExponent; private readonly byte[] modulus; private readonly byte[] prime1; private readonly byte[] prime2; private readonly byte[] exponent1; private readonly byte[] exponent2; private readonly byte[] coefficient; private readonly byte[] privateExponent; public byte[] PublicKey { get { if (publicKey == null) { Interlocked.CompareExchange(ref publicKey, CreatePublicKey(), null); } return publicKey; } } public int SignatureSize => modulus.Length; public AssemblyHashAlgorithm HashAlgorithm => hashAlg; public byte[] PublicExponent => publicExponent; public byte[] Modulus => modulus; public byte[] Prime1 => prime1; public byte[] Prime2 => prime2; public byte[] Exponent1 => exponent1; public byte[] Exponent2 => exponent2; public byte[] Coefficient => coefficient; public byte[] PrivateExponent => privateExponent; public StrongNameKey(byte[] keyData) : this(new BinaryReader(new MemoryStream(keyData))) { } public StrongNameKey(string filename) : this(File.ReadAllBytes(filename)) { } public StrongNameKey(Stream stream) : this(new BinaryReader(stream)) { } public StrongNameKey(BinaryReader reader) { try { publicKey = null; if (reader.ReadByte() != 7) { throw new InvalidKeyException("Not a public/private key pair"); } if (reader.ReadByte() != 2) { throw new InvalidKeyException("Invalid version"); } reader.ReadUInt16(); if (reader.ReadUInt32() != 9216) { throw new InvalidKeyException("Not RSA sign"); } if (reader.ReadUInt32() != 843141970) { throw new InvalidKeyException("Invalid RSA2 magic"); } uint num = reader.ReadUInt32(); publicExponent = reader.ReadBytesReverse(4); int len = (int)(num / 8); int len2 = (int)(num / 16); modulus = reader.ReadBytesReverse(len); prime1 = reader.ReadBytesReverse(len2); prime2 = reader.ReadBytesReverse(len2); exponent1 = reader.ReadBytesReverse(len2); exponent2 = reader.ReadBytesReverse(len2); coefficient = reader.ReadBytesReverse(len2); privateExponent = reader.ReadBytesReverse(len); } catch (IOException innerException) { throw new InvalidKeyException("Couldn't read strong name key", innerException); } } private StrongNameKey(AssemblyHashAlgorithm hashAlg, byte[] publicExponent, byte[] modulus, byte[] prime1, byte[] prime2, byte[] exponent1, byte[] exponent2, byte[] coefficient, byte[] privateExponent) { this.hashAlg = hashAlg; this.publicExponent = publicExponent; this.modulus = modulus; this.prime1 = prime1; this.prime2 = prime2; this.exponent1 = exponent1; this.exponent2 = exponent2; this.coefficient = coefficient; this.privateExponent = privateExponent; } public StrongNameKey WithHashAlgorithm(AssemblyHashAlgorithm hashAlgorithm) { if (hashAlg == hashAlgorithm) { return this; } return new StrongNameKey(hashAlgorithm, publicExponent, modulus, prime1, prime2, exponent1, exponent2, coefficient, privateExponent); } private byte[] CreatePublicKey() { AssemblyHashAlgorithm assemblyHashAlgorithm = ((hashAlg == AssemblyHashAlgorithm.None) ? AssemblyHashAlgorithm.SHA1 : hashAlg); return StrongNamePublicKey.CreatePublicKey(SignatureAlgorithm.CALG_RSA_SIGN, assemblyHashAlgorithm, modulus, publicExponent); } public RSA CreateRSA() { RSAParameters parameters = new RSAParameters { Exponent = publicExponent, Modulus = modulus, P = prime1, Q = prime2, DP = exponent1, DQ = exponent2, InverseQ = coefficient, D = privateExponent }; RSA rSA = RSA.Create(); try { rSA.ImportParameters(parameters); return rSA; } catch { ((IDisposable)rSA).Dispose(); throw; } } public byte[] CreateStrongName() { MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((byte)7); binaryWriter.Write((byte)2); binaryWriter.Write((ushort)0); binaryWriter.Write(9216u); binaryWriter.Write(843141970u); binaryWriter.Write(modulus.Length * 8); binaryWriter.WriteReverse(publicExponent); binaryWriter.WriteReverse(modulus); binaryWriter.WriteReverse(prime1); binaryWriter.WriteReverse(prime2); binaryWriter.WriteReverse(exponent1); binaryWriter.WriteReverse(exponent2); binaryWriter.WriteReverse(coefficient); binaryWriter.WriteReverse(privateExponent); return memoryStream.ToArray(); } public static string CreateCounterSignatureAsString(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { return Utils.ToHex(CreateCounterSignature(identityPubKey, identityKey, signaturePubKey), upper: false); } public static byte[] CreateCounterSignature(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { byte[] rgbHash = AssemblyHash.Hash(signaturePubKey.CreatePublicKey(), identityPubKey.HashAlgorithm); using RSA key = identityKey.CreateRSA(); RSAPKCS1SignatureFormatter rSAPKCS1SignatureFormatter = new RSAPKCS1SignatureFormatter(key); string name = identityPubKey.HashAlgorithm.GetName(); rSAPKCS1SignatureFormatter.SetHashAlgorithm(name); byte[] array = rSAPKCS1SignatureFormatter.CreateSignature(rgbHash); Array.Reverse(array); return array; } } public readonly struct StrongNameSigner { private readonly Stream stream; private readonly long baseOffset; public StrongNameSigner(Stream stream) : this(stream, 0L) { } public StrongNameSigner(Stream stream, long baseOffset) { this.stream = stream; this.baseOffset = baseOffset; } public byte[] WriteSignature(StrongNameKey snk, long snSigOffset) { byte[] array = CalculateSignature(snk, snSigOffset); stream.Position = baseOffset + snSigOffset; stream.Write(array, 0, array.Length); return array; } public byte[] CalculateSignature(StrongNameKey snk, long snSigOffset) { uint signatureSize = (uint)snk.SignatureSize; AssemblyHashAlgorithm hashAlg = ((snk.HashAlgorithm == AssemblyHashAlgorithm.None) ? AssemblyHashAlgorithm.SHA1 : snk.HashAlgorithm); byte[] hash = StrongNameHashData(hashAlg, snSigOffset, signatureSize); byte[] strongNameSignature = GetStrongNameSignature(snk, hashAlg, hash); if (strongNameSignature.Length != signatureSize) { throw new InvalidOperationException("Invalid strong name signature size"); } return strongNameSignature; } private byte[] StrongNameHashData(AssemblyHashAlgorithm hashAlg, long snSigOffset, uint snSigSize) { BinaryReader binaryReader = new BinaryReader(stream); snSigOffset += baseOffset; long num = snSigOffset + snSigSize; using AssemblyHash assemblyHash = new AssemblyHash(hashAlg); byte[] array = new byte[32768]; stream.Position = baseOffset + 60; uint length = binaryReader.ReadUInt32(); stream.Position = baseOffset; assemblyHash.Hash(stream, length, array); stream.Position += 6L; int num2 = binaryReader.ReadUInt16(); stream.Position -= 8L; assemblyHash.Hash(stream, 24u, array); bool num3 = binaryReader.ReadUInt16() == 267; stream.Position -= 2L; int num4 = (num3 ? 96 : 112); if (stream.Read(array, 0, num4) != num4) { throw new IOException("Could not read data"); } for (int i = 0; i < 4; i++) { array[64 + i] = 0; } assemblyHash.Hash(array, 0, num4); if (stream.Read(array, 0, 128) != 128) { throw new IOException("Could not read data"); } for (int j = 0; j < 8; j++) { array[32 + j] = 0; } assemblyHash.Hash(array, 0, 128); long position = stream.Position; assemblyHash.Hash(stream, (uint)(num2 * 40), array); for (int k = 0; k < num2; k++) { stream.Position = position + k * 40 + 16; uint num5 = binaryReader.ReadUInt32(); uint num6 = binaryReader.ReadUInt32(); stream.Position = baseOffset + num6; while (num5 != 0) { long position2 = stream.Position; if (snSigOffset <= position2 && position2 < num) { uint num7 = (uint)(num - position2); if (num7 >= num5) { break; } num5 -= num7; stream.Position += num7; continue; } if (position2 >= num) { assemblyHash.Hash(stream, num5, array); break; } uint num8 = (uint)Math.Min(snSigOffset - position2, num5); assemblyHash.Hash(stream, num8, array); num5 -= num8; } } return assemblyHash.ComputeHash(); } private byte[] GetStrongNameSignature(StrongNameKey snk, AssemblyHashAlgorithm hashAlg, byte[] hash) { using RSA key = snk.CreateRSA(); RSAPKCS1SignatureFormatter rSAPKCS1SignatureFormatter = new RSAPKCS1SignatureFormatter(key); string hashAlgorithm = hashAlg.GetName() ?? AssemblyHashAlgorithm.SHA1.GetName(); rSAPKCS1SignatureFormatter.SetHashAlgorithm(hashAlgorithm); byte[] array = rSAPKCS1SignatureFormatter.CreateSignature(hash); Array.Reverse(array); return array; } } internal static class TIAHelper { private readonly struct Info : IEquatable { public readonly UTF8String Scope; public readonly UTF8String Identifier; public Info(UTF8String scope, UTF8String identifier) { Scope = scope; Identifier = identifier; } public bool Equals(Info other) { if (stricmp(Scope, other.Scope)) { return UTF8String.Equals(Identifier, other.Identifier); } return false; } private static bool stricmp(UTF8String a, UTF8String b) { byte[] array = a?.Data; byte[] array2 = b?.Data; if (array == array2) { return true; } if (array == null || array2 == null) { return false; } if (array.Length != array2.Length) { return false; } for (int i = 0; i < array.Length; i++) { byte b2 = array[i]; byte b3 = array2[i]; if (65 <= b2 && b2 <= 90) { b2 = (byte)(b2 - 65 + 97); } if (65 <= b3 && b3 <= 90) { b3 = (byte)(b3 - 65 + 97); } if (b2 != b3) { return false; } } return true; } } private static readonly UTF8String InvokeString = new UTF8String("Invoke"); private static Info? GetInfo(TypeDef td) { if (td == null) { return null; } if (td.IsWindowsRuntime) { return null; } UTF8String scope = null; UTF8String uTF8String = null; CustomAttribute customAttribute = td.CustomAttributes.Find("System.Runtime.InteropServices.TypeIdentifierAttribute"); if (customAttribute != null) { if (customAttribute.ConstructorArguments.Count >= 2) { if (customAttribute.ConstructorArguments[0].Type.GetElementType() != ElementType.String) { return null; } if (customAttribute.ConstructorArguments[1].Type.GetElementType() != ElementType.String) { return null; } scope = (customAttribute.ConstructorArguments[0].Value as UTF8String) ?? ((UTF8String)(customAttribute.ConstructorArguments[0].Value as string)); uTF8String = (customAttribute.ConstructorArguments[1].Value as UTF8String) ?? ((UTF8String)(customAttribute.ConstructorArguments[1].Value as string)); } } else { AssemblyDef assemblyDef = td.Module?.Assembly; if (assemblyDef == null) { return null; } if (!assemblyDef.CustomAttributes.IsDefined("System.Runtime.InteropServices.ImportedFromTypeLibAttribute") && !assemblyDef.CustomAttributes.IsDefined("System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute")) { return null; } } if (UTF8String.IsNull(uTF8String)) { CustomAttribute customAttribute2; if (td.IsInterface && td.IsImport) { customAttribute2 = td.CustomAttributes.Find("System.Runtime.InteropServices.GuidAttribute"); } else { AssemblyDef assemblyDef2 = td.Module?.Assembly; if (assemblyDef2 == null) { return null; } customAttribute2 = assemblyDef2.CustomAttributes.Find("System.Runtime.InteropServices.GuidAttribute"); } if (customAttribute2 == null) { return null; } if (customAttribute2.ConstructorArguments.Count < 1) { return null; } if (customAttribute2.ConstructorArguments[0].Type.GetElementType() != ElementType.String) { return null; } scope = (customAttribute2.ConstructorArguments[0].Value as UTF8String) ?? ((UTF8String)(customAttribute2.ConstructorArguments[0].Value as string)); UTF8String uTF8String2 = td.Namespace; UTF8String name = td.Name; uTF8String = (UTF8String.IsNullOrEmpty(uTF8String2) ? name : ((!UTF8String.IsNullOrEmpty(name)) ? new UTF8String(Concat(uTF8String2.Data, 46, name.Data)) : new UTF8String(Concat(uTF8String2.Data, 46, Array2.Empty())))); } return new Info(scope, uTF8String); } private static byte[] Concat(byte[] a, byte b, byte[] c) { byte[] array = new byte[a.Length + 1 + c.Length]; for (int i = 0; i < a.Length; i++) { array[i] = a[i]; } array[a.Length] = b; int num = 0; int num2 = a.Length + 1; while (num < c.Length) { array[num2] = c[num]; num++; num2++; } return array; } internal static bool IsTypeDefEquivalent(TypeDef td) { if (GetInfo(td).HasValue) { return CheckEquivalent(td); } return false; } private static bool CheckEquivalent(TypeDef td) { int num = 0; while (td != null && num < 1000) { if (num != 0 && !GetInfo(td).HasValue) { return false; } if (!((!td.IsInterface) ? (td.IsValueType || td.IsDelegate) : (td.IsImport || td.CustomAttributes.IsDefined("System.Runtime.InteropServices.ComEventInterfaceAttribute")))) { return false; } if (td.GenericParameters.Count > 0) { return false; } TypeDef declaringType = td.DeclaringType; if (declaringType == null) { return td.IsPublic; } if (!td.IsNestedPublic) { return false; } td = declaringType; num++; } return false; } public static bool Equivalent(TypeDef td1, TypeDef td2) { Info? info = GetInfo(td1); if (!info.HasValue) { return false; } Info? info2 = GetInfo(td2); if (!info2.HasValue) { return false; } if (!CheckEquivalent(td1) || !CheckEquivalent(td2)) { return false; } if (!info.Value.Equals(info2.Value)) { return false; } for (int i = 0; i < 1000; i++) { if (td1.IsInterface) { if (!td2.IsInterface) { return false; } } else { ITypeDefOrRef baseType = td1.BaseType; ITypeDefOrRef baseType2 = td2.BaseType; if (baseType == null || baseType2 == null) { return false; } if (td1.IsDelegate) { if (!td2.IsDelegate) { return false; } if (!DelegateEquals(td1, td2)) { return false; } } else { if (!td1.IsValueType) { return false; } if (td1.IsEnum != td2.IsEnum) { return false; } if (!td2.IsValueType) { return false; } if (!ValueTypeEquals(td1, td2, td1.IsEnum)) { return false; } } } td1 = td1.DeclaringType; td2 = td2.DeclaringType; if (td1 == null && td2 == null) { break; } if (td1 == null || td2 == null) { return false; } } return true; } private static bool DelegateEquals(TypeDef td1, TypeDef td2) { MethodDef methodDef = td1.FindMethod(InvokeString); MethodDef methodDef2 = td2.FindMethod(InvokeString); if (methodDef == null || methodDef2 == null) { return false; } return true; } private static bool ValueTypeEquals(TypeDef td1, TypeDef td2, bool isEnum) { if (td1.Methods.Count != 0 || td2.Methods.Count != 0) { return false; } return true; } } [Flags] public enum TypeAttributes : uint { VisibilityMask = 7u, NotPublic = 0u, Public = 1u, NestedPublic = 2u, NestedPrivate = 3u, NestedFamily = 4u, NestedAssembly = 5u, NestedFamANDAssem = 6u, NestedFamORAssem = 7u, LayoutMask = 0x18u, AutoLayout = 0u, SequentialLayout = 8u, ExplicitLayout = 0x10u, ClassSemanticsMask = 0x20u, ClassSemanticMask = 0x20u, Class = 0u, Interface = 0x20u, Abstract = 0x80u, Sealed = 0x100u, SpecialName = 0x400u, Import = 0x1000u, Serializable = 0x2000u, WindowsRuntime = 0x4000u, StringFormatMask = 0x30000u, AnsiClass = 0u, UnicodeClass = 0x10000u, AutoClass = 0x20000u, CustomFormatClass = 0x30000u, CustomFormatMask = 0xC00000u, BeforeFieldInit = 0x100000u, Forwarder = 0x200000u, ReservedMask = 0x40800u, RTSpecialName = 0x800u, HasSecurity = 0x40000u } public abstract class TypeDef : ITypeDefOrRef, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IMemberRefParent, IFullName, IType, IOwnerModule, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter, ITokenOperand, IMemberRef, IHasDeclSecurity, ITypeOrMethodDef, IMemberDef, IDnlibDef, IHasCustomDebugInformation, IListListener, IListListener, IListListener, IListListener, IListListener, IListListener, IMemberRefResolver { protected uint rid; private readonly Lock theLock = Lock.Create(); protected ModuleDef module2; protected bool module2_isInitialized; protected int attributes; protected UTF8String name; protected UTF8String @namespace; protected ITypeDefOrRef baseType; protected bool baseType_isInitialized; protected LazyList fields; protected LazyList methods; protected LazyList genericParameters; protected IList interfaces; protected IList declSecurities; protected ClassLayout classLayout; protected bool classLayout_isInitialized; protected TypeDef declaringType2; protected bool declaringType2_isInitialized; protected LazyList nestedTypes; protected LazyList events; protected LazyList properties; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; private static readonly UTF8String systemString = new UTF8String("System"); private static readonly UTF8String enumString = new UTF8String("Enum"); private static readonly UTF8String valueTypeString = new UTF8String("ValueType"); private static readonly UTF8String multicastDelegateString = new UTF8String("MulticastDelegate"); public MDToken MDToken => new MDToken(Table.TypeDef, rid); public uint Rid { get { return rid; } set { rid = value; } } public int TypeDefOrRefTag => 0; public int HasCustomAttributeTag => 3; public int HasDeclSecurityTag => 0; public int MemberRefParentTag => 0; public int TypeOrMethodDefTag => 0; int IGenericParameterProvider.NumberOfGenericParameters => GenericParameters.Count; string IType.TypeName => Name; public string ReflectionName => FullNameFactory.Name(this, isReflection: true); string IType.Namespace => Namespace; public string ReflectionNamespace => FullNameFactory.Namespace(this, isReflection: true); public string FullName => FullNameFactory.FullName(this, isReflection: false); public string ReflectionFullName => FullNameFactory.FullName(this, isReflection: true); public string AssemblyQualifiedName => FullNameFactory.AssemblyQualifiedName(this); public IAssembly DefinitionAssembly => FullNameFactory.DefinitionAssembly(this); public IScope Scope => Module; public ITypeDefOrRef ScopeType => this; public bool ContainsGenericParameter => false; public ModuleDef Module => FullNameFactory.OwnerModule(this); internal ModuleDef Module2 { get { if (!module2_isInitialized) { InitializeModule2(); } return module2; } set { theLock.EnterWriteLock(); try { module2 = value; module2_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } bool IIsTypeOrMethod.IsType => true; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => true; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (int)value; } } public UTF8String Name { get { return name; } set { name = value; } } public UTF8String Namespace { get { return @namespace; } set { @namespace = value; } } public ITypeDefOrRef BaseType { get { if (!baseType_isInitialized) { InitializeBaseType(); } return baseType; } set { theLock.EnterWriteLock(); try { baseType = value; baseType_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public IList Fields { get { if (fields == null) { InitializeFields(); } return fields; } } public IList Methods { get { if (methods == null) { InitializeMethods(); } return methods; } } public IList GenericParameters { get { if (genericParameters == null) { InitializeGenericParameters(); } return genericParameters; } } public IList Interfaces { get { if (interfaces == null) { InitializeInterfaces(); } return interfaces; } } public IList DeclSecurities { get { if (declSecurities == null) { InitializeDeclSecurities(); } return declSecurities; } } public ClassLayout ClassLayout { get { if (!classLayout_isInitialized) { InitializeClassLayout(); } return classLayout; } set { theLock.EnterWriteLock(); try { classLayout = value; classLayout_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public bool HasDeclSecurities => DeclSecurities.Count > 0; public TypeDef DeclaringType { get { if (!declaringType2_isInitialized) { InitializeDeclaringType2(); } return declaringType2; } set { TypeDef typeDef = DeclaringType2; if (typeDef != value) { typeDef?.NestedTypes.Remove(this); value?.NestedTypes.Add(this); Module2 = null; } } } ITypeDefOrRef IMemberRef.DeclaringType => DeclaringType; public TypeDef DeclaringType2 { get { if (!declaringType2_isInitialized) { InitializeDeclaringType2(); } return declaringType2; } set { theLock.EnterWriteLock(); try { declaringType2 = value; declaringType2_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public IList NestedTypes { get { if (nestedTypes == null) { InitializeNestedTypes(); } return nestedTypes; } } public IList Events { get { if (events == null) { InitializeEvents(); } return events; } } public IList Properties { get { if (properties == null) { InitializeProperties(); } return properties; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 3; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool HasFields => Fields.Count > 0; public bool HasMethods => Methods.Count > 0; public bool HasGenericParameters => GenericParameters.Count > 0; public bool HasEvents => Events.Count > 0; public bool HasProperties => Properties.Count > 0; public bool HasNestedTypes => NestedTypes.Count > 0; public bool HasInterfaces => Interfaces.Count > 0; public bool HasClassLayout => ClassLayout != null; public ushort PackingSize { get { return ClassLayout?.PackingSize ?? ushort.MaxValue; } set { GetOrCreateClassLayout().PackingSize = value; } } public uint ClassSize { get { return (uint)(((int?)ClassLayout?.ClassSize) ?? (-1)); } set { GetOrCreateClassLayout().ClassSize = value; } } public bool IsValueType { get { if ((Attributes & TypeAttributes.ClassSemanticsMask) != TypeAttributes.NotPublic) { return false; } ITypeDefOrRef typeDefOrRef = BaseType; if (typeDefOrRef == null) { return false; } if (!typeDefOrRef.DefinitionAssembly.IsCorLib()) { return false; } UTF8String uTF8String; UTF8String uTF8String2; if (typeDefOrRef is TypeRef typeRef) { uTF8String = typeRef.Name; uTF8String2 = typeRef.Namespace; } else { if (!(typeDefOrRef is TypeDef typeDef)) { return false; } uTF8String = typeDef.Name; uTF8String2 = typeDef.Namespace; } if (uTF8String2 != systemString) { return false; } if (uTF8String != valueTypeString && uTF8String != enumString) { return false; } if (!DefinitionAssembly.IsCorLib()) { return true; } if (Name == enumString) { return !(Namespace == systemString); } return true; } } public bool IsEnum { get { if ((Attributes & TypeAttributes.ClassSemanticsMask) != TypeAttributes.NotPublic) { return false; } ITypeDefOrRef typeDefOrRef = BaseType; if (typeDefOrRef == null) { return false; } if (!typeDefOrRef.DefinitionAssembly.IsCorLib()) { return false; } if (typeDefOrRef is TypeRef typeRef) { if (typeRef.Namespace == systemString) { return typeRef.Name == enumString; } return false; } if (typeDefOrRef is TypeDef typeDef) { if (typeDef.Namespace == systemString) { return typeDef.Name == enumString; } return false; } return false; } } public bool IsDelegate { get { if ((Attributes & (TypeAttributes.ClassSemanticsMask | TypeAttributes.Abstract)) != TypeAttributes.NotPublic) { return false; } ITypeDefOrRef typeDefOrRef = BaseType; if (typeDefOrRef == null) { return false; } if (!typeDefOrRef.DefinitionAssembly.IsCorLib()) { return false; } if (typeDefOrRef is TypeRef typeRef) { if (typeRef.Namespace == systemString) { return typeRef.Name == multicastDelegateString; } return false; } if (typeDefOrRef is TypeDef typeDef) { if (typeDef.Namespace == systemString) { return typeDef.Name == multicastDelegateString; } return false; } return false; } } public bool IsNested => DeclaringType != null; public bool IsPrimitive => this.IsPrimitive(); public bool IsEquivalent => TIAHelper.IsTypeDefEquivalent(this); public TypeAttributes Visibility { get { return (TypeAttributes)(attributes & 7); } set { ModifyAttributes(~TypeAttributes.VisibilityMask, value & TypeAttributes.VisibilityMask); } } public bool IsNotPublic => (attributes & 7) == 0; public bool IsPublic => (attributes & 7) == 1; public bool IsNestedPublic => (attributes & 7) == 2; public bool IsNestedPrivate => (attributes & 7) == 3; public bool IsNestedFamily => (attributes & 7) == 4; public bool IsNestedAssembly => (attributes & 7) == 5; public bool IsNestedFamilyAndAssembly => (attributes & 7) == 6; public bool IsNestedFamilyOrAssembly => (attributes & 7) == 7; public TypeAttributes Layout { get { return (TypeAttributes)(attributes & 0x18); } set { ModifyAttributes(~TypeAttributes.LayoutMask, value & TypeAttributes.LayoutMask); } } public bool IsAutoLayout => (attributes & 0x18) == 0; public bool IsSequentialLayout => (attributes & 0x18) == 8; public bool IsExplicitLayout => (attributes & 0x18) == 16; public bool IsInterface { get { return (attributes & 0x20) != 0; } set { ModifyAttributes(value, TypeAttributes.ClassSemanticsMask); } } public bool IsClass { get { return (attributes & 0x20) == 0; } set { ModifyAttributes(!value, TypeAttributes.ClassSemanticsMask); } } public bool IsAbstract { get { return (attributes & 0x80) != 0; } set { ModifyAttributes(value, TypeAttributes.Abstract); } } public bool IsSealed { get { return (attributes & 0x100) != 0; } set { ModifyAttributes(value, TypeAttributes.Sealed); } } public bool IsSpecialName { get { return (attributes & 0x400) != 0; } set { ModifyAttributes(value, TypeAttributes.SpecialName); } } public bool IsImport { get { return (attributes & 0x1000) != 0; } set { ModifyAttributes(value, TypeAttributes.Import); } } public bool IsSerializable { get { return (attributes & 0x2000) != 0; } set { ModifyAttributes(value, TypeAttributes.Serializable); } } public bool IsWindowsRuntime { get { return (attributes & 0x4000) != 0; } set { ModifyAttributes(value, TypeAttributes.WindowsRuntime); } } public TypeAttributes StringFormat { get { return (TypeAttributes)(attributes & 0x30000); } set { ModifyAttributes(~TypeAttributes.StringFormatMask, value & TypeAttributes.StringFormatMask); } } public bool IsAnsiClass => (attributes & 0x30000) == 0; public bool IsUnicodeClass => (attributes & 0x30000) == 65536; public bool IsAutoClass => (attributes & 0x30000) == 131072; public bool IsCustomFormatClass => (attributes & 0x30000) == 196608; public bool IsBeforeFieldInit { get { return (attributes & 0x100000) != 0; } set { ModifyAttributes(value, TypeAttributes.BeforeFieldInit); } } public bool IsForwarder { get { return (attributes & 0x200000) != 0; } set { ModifyAttributes(value, TypeAttributes.Forwarder); } } public bool IsRuntimeSpecialName { get { return (attributes & 0x800) != 0; } set { ModifyAttributes(value, TypeAttributes.RTSpecialName); } } public bool HasSecurity { get { return (attributes & 0x40000) != 0; } set { ModifyAttributes(value, TypeAttributes.HasSecurity); } } public bool IsGlobalModuleType { get { ModuleDef module = Module; if (module != null) { return module.GlobalType == this; } return false; } } private void InitializeModule2() { theLock.EnterWriteLock(); try { if (!module2_isInitialized) { module2 = GetModule2_NoLock(); module2_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual ModuleDef GetModule2_NoLock() { return null; } private void InitializeBaseType() { theLock.EnterWriteLock(); try { if (!baseType_isInitialized) { baseType = GetBaseType_NoLock(); baseType_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual ITypeDefOrRef GetBaseType_NoLock() { return null; } protected void ResetBaseType() { baseType_isInitialized = false; } protected virtual void InitializeFields() { Interlocked.CompareExchange(ref fields, new LazyList(this), null); } protected virtual void InitializeMethods() { Interlocked.CompareExchange(ref methods, new LazyList(this), null); } protected virtual void InitializeGenericParameters() { Interlocked.CompareExchange(ref genericParameters, new LazyList(this), null); } protected virtual void InitializeInterfaces() { Interlocked.CompareExchange(ref interfaces, new List(), null); } protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, new List(), null); } private void InitializeClassLayout() { theLock.EnterWriteLock(); try { if (!classLayout_isInitialized) { classLayout = GetClassLayout_NoLock(); classLayout_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } private ClassLayout GetOrCreateClassLayout() { ClassLayout classLayout = ClassLayout; if (classLayout != null) { return classLayout; } Interlocked.CompareExchange(ref this.classLayout, new ClassLayoutUser(0, 0u), null); return this.classLayout; } protected virtual ClassLayout GetClassLayout_NoLock() { return null; } private void InitializeDeclaringType2() { theLock.EnterWriteLock(); try { if (!declaringType2_isInitialized) { declaringType2 = GetDeclaringType2_NoLock(); declaringType2_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual TypeDef GetDeclaringType2_NoLock() { return null; } protected virtual void InitializeNestedTypes() { Interlocked.CompareExchange(ref nestedTypes, new LazyList(this), null); } protected virtual void InitializeEvents() { Interlocked.CompareExchange(ref events, new LazyList(this), null); } protected virtual void InitializeProperties() { Interlocked.CompareExchange(ref properties, new LazyList(this), null); } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } private void ModifyAttributes(TypeAttributes andMask, TypeAttributes orMask) { attributes = (int)((uint)attributes & (uint)andMask) | (int)orMask; } private void ModifyAttributes(bool set, TypeAttributes flags) { if (set) { attributes |= (int)flags; } else { attributes &= (int)(~flags); } } public IEnumerable GetTypes() { return AllTypesHelper.Types(NestedTypes); } public TypeSig GetEnumUnderlyingType() { IList list = Fields; int count = list.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = list[i]; if (!fieldDef.IsLiteral && !fieldDef.IsStatic) { FieldSig fieldSig = fieldDef.FieldSig; if (fieldSig != null) { return fieldSig.Type; } } } return null; } public IMemberForwarded Resolve(MemberRef memberRef) { return Resolve(memberRef, (SigComparerOptions)0u); } public IMemberForwarded Resolve(MemberRef memberRef, SigComparerOptions options) { if (memberRef == null) { return null; } MethodSig methodSig = memberRef.MethodSig; if (methodSig != null) { return FindMethodCheckBaseType(memberRef.Name, methodSig, options, memberRef.Module); } FieldSig fieldSig = memberRef.FieldSig; if (fieldSig != null) { return FindFieldCheckBaseType(memberRef.Name, fieldSig, options, memberRef.Module); } return null; } public MethodDef FindMethod(UTF8String name, MethodSig sig) { return FindMethod(name, sig, (SigComparerOptions)0u, null); } public MethodDef FindMethod(UTF8String name, MethodSig sig, SigComparerOptions options) { return FindMethod(name, sig, options, null); } public MethodDef FindMethod(UTF8String name, MethodSig sig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || sig == null) { return null; } SigComparer sigComparer = new SigComparer(options, sourceModule); bool flag = (options & SigComparerOptions.PrivateScopeMethodIsComparable) != 0; IList list = Methods; int count = list.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = list[i]; if ((flag || !methodDef.IsPrivateScope || sourceModule == Module) && UTF8String.Equals(methodDef.Name, name) && sigComparer.Equals(methodDef.MethodSig, sig)) { return methodDef; } } return null; } public MethodDef FindMethod(UTF8String name) { IList list = Methods; int count = list.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = list[i]; if (UTF8String.Equals(methodDef.Name, name)) { return methodDef; } } return null; } public IEnumerable FindMethods(UTF8String name) { IList methods = Methods; int count = methods.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = methods[i]; if (UTF8String.Equals(methodDef.Name, name)) { yield return methodDef; } } } public MethodDef FindStaticConstructor() { IList list = Methods; int count = list.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = list[i]; if (methodDef.IsStaticConstructor) { return methodDef; } } return null; } public MethodDef FindOrCreateStaticConstructor() { MethodDef methodDef = FindStaticConstructor(); if (methodDef != null) { return methodDef; } MethodImplAttributes implFlags = MethodImplAttributes.IL; MethodAttributes flags = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; ModuleDef module = Module; methodDef = module.UpdateRowId(new MethodDefUser(MethodDef.StaticConstructorName, MethodSig.CreateStatic(module.CorLibTypes.Void), implFlags, flags)); CilBody cilBody = new CilBody(); cilBody.InitLocals = true; cilBody.MaxStack = 8; cilBody.Instructions.Add(dnlib.DotNet.Emit.OpCodes.Ret.ToInstruction()); methodDef.Body = cilBody; Methods.Add(methodDef); return methodDef; } public IEnumerable FindInstanceConstructors() { IList methods = Methods; int count = methods.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = methods[i]; if (methodDef.IsInstanceConstructor) { yield return methodDef; } } } public IEnumerable FindConstructors() { IList methods = Methods; int count = methods.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = methods[i]; if (methodDef.IsConstructor) { yield return methodDef; } } } public MethodDef FindDefaultConstructor() { IList list = Methods; int count = list.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = list[i]; if (methodDef.IsInstanceConstructor) { MethodSig methodSig = methodDef.MethodSig; if (methodSig != null && methodSig.Params.Count == 0) { return methodDef; } } } return null; } public FieldDef FindField(UTF8String name, FieldSig sig) { return FindField(name, sig, (SigComparerOptions)0u, null); } public FieldDef FindField(UTF8String name, FieldSig sig, SigComparerOptions options) { return FindField(name, sig, options, null); } public FieldDef FindField(UTF8String name, FieldSig sig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || sig == null) { return null; } SigComparer sigComparer = new SigComparer(options, sourceModule); bool flag = (options & SigComparerOptions.PrivateScopeFieldIsComparable) != 0; IList list = Fields; int count = list.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = list[i]; if ((flag || !fieldDef.IsPrivateScope || sourceModule == Module) && UTF8String.Equals(fieldDef.Name, name) && sigComparer.Equals(fieldDef.FieldSig, sig)) { return fieldDef; } } return null; } public FieldDef FindField(UTF8String name) { IList list = Fields; int count = list.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = list[i]; if (UTF8String.Equals(fieldDef.Name, name)) { return fieldDef; } } return null; } public IEnumerable FindFields(UTF8String name) { IList fields = Fields; int count = fields.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = fields[i]; if (UTF8String.Equals(fieldDef.Name, name)) { yield return fieldDef; } } } public EventDef FindEvent(UTF8String name, IType type) { return FindEvent(name, type, (SigComparerOptions)0u, null); } public EventDef FindEvent(UTF8String name, IType type, SigComparerOptions options) { return FindEvent(name, type, options, null); } public EventDef FindEvent(UTF8String name, IType type, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || type == null) { return null; } SigComparer sigComparer = new SigComparer(options, sourceModule); IList list = Events; int count = list.Count; for (int i = 0; i < count; i++) { EventDef eventDef = list[i]; if (UTF8String.Equals(eventDef.Name, name) && sigComparer.Equals(eventDef.EventType, type)) { return eventDef; } } return null; } public EventDef FindEvent(UTF8String name) { IList list = Events; int count = list.Count; for (int i = 0; i < count; i++) { EventDef eventDef = list[i]; if (UTF8String.Equals(eventDef.Name, name)) { return eventDef; } } return null; } public IEnumerable FindEvents(UTF8String name) { IList events = Events; int count = events.Count; for (int i = 0; i < count; i++) { EventDef eventDef = events[i]; if (UTF8String.Equals(eventDef.Name, name)) { yield return eventDef; } } } public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig) { return FindProperty(name, propSig, (SigComparerOptions)0u, null); } public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig, SigComparerOptions options) { return FindProperty(name, propSig, options, null); } public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || propSig == null) { return null; } SigComparer sigComparer = new SigComparer(options, sourceModule); IList list = Properties; int count = list.Count; for (int i = 0; i < count; i++) { PropertyDef propertyDef = list[i]; if (UTF8String.Equals(propertyDef.Name, name) && sigComparer.Equals(propertyDef.Type, propSig)) { return propertyDef; } } return null; } public PropertyDef FindProperty(UTF8String name) { IList list = Properties; int count = list.Count; for (int i = 0; i < count; i++) { PropertyDef propertyDef = list[i]; if (UTF8String.Equals(propertyDef.Name, name)) { return propertyDef; } } return null; } public IEnumerable FindProperties(UTF8String name) { IList properties = Properties; int count = properties.Count; for (int i = 0; i < count; i++) { PropertyDef propertyDef = properties[i]; if (UTF8String.Equals(propertyDef.Name, name)) { yield return propertyDef; } } } public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig) { return FindMethodCheckBaseType(name, sig, (SigComparerOptions)0u, null); } public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig, SigComparerOptions options) { return FindMethodCheckBaseType(name, sig, options, null); } public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig, SigComparerOptions options, ModuleDef sourceModule) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { MethodDef methodDef = typeDef.FindMethod(name, sig, options, sourceModule); if (methodDef != null) { return methodDef; } } return null; } public MethodDef FindMethodCheckBaseType(UTF8String name) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { MethodDef methodDef = typeDef.FindMethod(name); if (methodDef != null) { return methodDef; } } return null; } public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig) { return FindFieldCheckBaseType(name, sig, (SigComparerOptions)0u, null); } public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig, SigComparerOptions options) { return FindFieldCheckBaseType(name, sig, options, null); } public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig, SigComparerOptions options, ModuleDef sourceModule) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { FieldDef fieldDef = typeDef.FindField(name, sig, options, sourceModule); if (fieldDef != null) { return fieldDef; } } return null; } public FieldDef FindFieldCheckBaseType(UTF8String name) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { FieldDef fieldDef = typeDef.FindField(name); if (fieldDef != null) { return fieldDef; } } return null; } public EventDef FindEventCheckBaseType(UTF8String name, ITypeDefOrRef eventType) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { EventDef eventDef = typeDef.FindEvent(name, eventType); if (eventDef != null) { return eventDef; } } return null; } public EventDef FindEventCheckBaseType(UTF8String name) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { EventDef eventDef = typeDef.FindEvent(name); if (eventDef != null) { return eventDef; } } return null; } public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig) { return FindPropertyCheckBaseType(name, sig, (SigComparerOptions)0u, null); } public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig, SigComparerOptions options) { return FindPropertyCheckBaseType(name, sig, options, null); } public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig, SigComparerOptions options, ModuleDef sourceModule) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { PropertyDef propertyDef = typeDef.FindProperty(name, sig, options, sourceModule); if (propertyDef != null) { return propertyDef; } } return null; } public PropertyDef FindPropertyCheckBaseType(UTF8String name) { for (TypeDef typeDef = this; typeDef != null; typeDef = typeDef.BaseType.ResolveTypeDef()) { PropertyDef propertyDef = typeDef.FindProperty(name); if (propertyDef != null) { return propertyDef; } } return null; } public void Remove(MethodDef method) { Remove(method, removeEmptyPropertiesEvents: false); } public void Remove(MethodDef method, bool removeEmptyPropertiesEvents) { if (method == null) { return; } IList list = Properties; int count = list.Count; for (int i = 0; i < count; i++) { PropertyDef propertyDef = list[i]; propertyDef.GetMethods.Remove(method); propertyDef.SetMethods.Remove(method); propertyDef.OtherMethods.Remove(method); } IList list2 = Events; count = list2.Count; for (int j = 0; j < count; j++) { EventDef eventDef = list2[j]; if (eventDef.AddMethod == method) { eventDef.AddMethod = null; } if (eventDef.RemoveMethod == method) { eventDef.RemoveMethod = null; } if (eventDef.InvokeMethod == method) { eventDef.InvokeMethod = null; } eventDef.OtherMethods.Remove(method); } if (removeEmptyPropertiesEvents) { RemoveEmptyProperties(); RemoveEmptyEvents(); } Methods.Remove(method); } private void RemoveEmptyProperties() { IList list = Properties; for (int num = list.Count - 1; num >= 0; num--) { if (list[num].IsEmpty) { list.RemoveAt(num); } } } private void RemoveEmptyEvents() { IList list = Events; for (int num = list.Count - 1; num >= 0; num--) { if (list[num].IsEmpty) { list.RemoveAt(num); } } } void IListListener.OnLazyAdd(int index, ref FieldDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref FieldDef value) { } void IListListener.OnAdd(int index, FieldDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Field is already owned by another type. Set DeclaringType to null first."); } value.DeclaringType2 = this; } void IListListener.OnRemove(int index, FieldDef value) { value.DeclaringType2 = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (FieldDef item in fields.GetEnumerable_NoLock()) { item.DeclaringType2 = null; } } void IListListener.OnLazyAdd(int index, ref MethodDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref MethodDef value) { } void IListListener.OnAdd(int index, MethodDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Method is already owned by another type. Set DeclaringType to null first."); } value.DeclaringType2 = this; value.Parameters.UpdateThisParameterType(this); } void IListListener.OnRemove(int index, MethodDef value) { value.DeclaringType2 = null; value.Parameters.UpdateThisParameterType(null); } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (MethodDef item in methods.GetEnumerable_NoLock()) { item.DeclaringType2 = null; item.Parameters.UpdateThisParameterType(null); } } void IListListener.OnLazyAdd(int index, ref TypeDef value) { } void IListListener.OnAdd(int index, TypeDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Nested type is already owned by another type. Set DeclaringType to null first."); } if (value.Module != null) { throw new InvalidOperationException("Type is already owned by another module. Remove it from that module's type list."); } value.DeclaringType2 = this; } void IListListener.OnRemove(int index, TypeDef value) { value.DeclaringType2 = null; value.Module2 = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (TypeDef item in nestedTypes.GetEnumerable_NoLock()) { item.DeclaringType2 = null; } } void IListListener.OnLazyAdd(int index, ref EventDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref EventDef value) { } void IListListener.OnAdd(int index, EventDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Event is already owned by another type. Set DeclaringType to null first."); } value.DeclaringType2 = this; } void IListListener.OnRemove(int index, EventDef value) { value.DeclaringType2 = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (EventDef item in events.GetEnumerable_NoLock()) { item.DeclaringType2 = null; } } void IListListener.OnLazyAdd(int index, ref PropertyDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref PropertyDef value) { } void IListListener.OnAdd(int index, PropertyDef value) { if (value.DeclaringType != null) { throw new InvalidOperationException("Property is already owned by another type. Set DeclaringType to null first."); } value.DeclaringType2 = this; } void IListListener.OnRemove(int index, PropertyDef value) { value.DeclaringType2 = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (PropertyDef item in properties.GetEnumerable_NoLock()) { item.DeclaringType2 = null; } } void IListListener.OnLazyAdd(int index, ref GenericParam value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParam value) { } void IListListener.OnAdd(int index, GenericParam value) { if (value.Owner != null) { throw new InvalidOperationException("Generic param is already owned by another type/method. Set Owner to null first."); } value.Owner = this; } void IListListener.OnRemove(int index, GenericParam value) { value.Owner = null; } void IListListener.OnResize(int index) { } void IListListener.OnClear() { foreach (GenericParam item in genericParameters.GetEnumerable_NoLock()) { item.Owner = null; } } public IList GetFields(UTF8String name) { List list = new List(); IList list2 = Fields; int count = list2.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = list2[i]; if (fieldDef.Name == name) { list.Add(fieldDef); } } return list; } public FieldDef GetField(UTF8String name) { IList list = Fields; int count = list.Count; for (int i = 0; i < count; i++) { FieldDef fieldDef = list[i]; if (fieldDef.Name == name) { return fieldDef; } } return null; } internal static bool GetClassSize(TypeDef td, out uint size) { size = 0u; if (td == null) { return false; } if (!td.IsValueType) { return false; } if (!td.IsSequentialLayout && !td.IsExplicitLayout) { if (td.Fields.Count != 1) { return false; } return td.Fields[0]?.GetFieldSize(out size) ?? false; } ClassLayout classLayout = td.ClassLayout; if (classLayout == null) { return false; } uint classSize = classLayout.ClassSize; if (classSize != 0) { size = classSize; return true; } return false; } protected MethodDef FindMethodImplMethod(IMethodDefOrRef mdr) { if (mdr is MethodDef result) { return result; } if (!(mdr is MemberRef { Class: var memberRefParent } memberRef)) { return null; } if (memberRefParent is MethodDef result2) { return result2; } for (int i = 0; i < 10; i++) { if (!(memberRefParent is TypeSpec typeSpec)) { break; } if (!(typeSpec.TypeSig is GenericInstSig { GenericType: not null } genericInstSig)) { return null; } memberRefParent = genericInstSig.GenericType.TypeDefOrRef; } TypeDef typeDef = memberRefParent as TypeDef; if (typeDef == null && memberRefParent is TypeRef typeRef && Module != null) { typeDef = Module.Find(typeRef); } return typeDef?.FindMethod(memberRef.Name, memberRef.MethodSig); } public override string ToString() { return FullName; } } public class TypeDefUser : TypeDef { public TypeDefUser(UTF8String name) : this(null, name, null) { } public TypeDefUser(UTF8String @namespace, UTF8String name) : this(@namespace, name, null) { } public TypeDefUser(UTF8String name, ITypeDefOrRef baseType) : this(null, name, baseType) { } public TypeDefUser(UTF8String @namespace, UTF8String name, ITypeDefOrRef baseType) { fields = new LazyList(this); methods = new LazyList(this); genericParameters = new LazyList(this); nestedTypes = new LazyList(this); events = new LazyList(this); properties = new LazyList(this); base.@namespace = @namespace; base.name = name; base.baseType = baseType; baseType_isInitialized = true; } } internal sealed class TypeDefMD : TypeDef, IMDTokenProviderMD, IMDTokenProvider { private readonly struct MethodOverrideTokens { public readonly uint MethodBodyToken; public readonly uint MethodDeclarationToken; public MethodOverrideTokens(uint methodBodyToken, uint methodDeclarationToken) { MethodBodyToken = methodBodyToken; MethodDeclarationToken = methodDeclarationToken; } } private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly uint extendsCodedToken; private Dictionary> methodRidToOverrides; internal ModuleDefMD ReaderModule => readerModule; public uint OrigRid => origRid; private TypeDef DeclaringType2_NoLock { get { if (!declaringType2_isInitialized) { declaringType2 = GetDeclaringType2_NoLock(); declaringType2_isInitialized = true; } return declaringType2; } } protected override ITypeDefOrRef GetBaseType_NoLock() { return readerModule.ResolveTypeDefOrRef(extendsCodedToken, new GenericParamContext(this)); } protected override void InitializeFields() { RidList fieldRidList = readerModule.Metadata.GetFieldRidList(origRid); LazyList value = new LazyList(fieldRidList.Count, this, fieldRidList, (RidList list2, int index) => readerModule.ResolveField(list2[index])); Interlocked.CompareExchange(ref fields, value, null); } protected override void InitializeMethods() { RidList methodRidList = readerModule.Metadata.GetMethodRidList(origRid); LazyList value = new LazyList(methodRidList.Count, this, methodRidList, (RidList list2, int index) => readerModule.ResolveMethod(list2[index])); Interlocked.CompareExchange(ref methods, value, null); } protected override void InitializeGenericParameters() { RidList genericParamRidList = readerModule.Metadata.GetGenericParamRidList(Table.TypeDef, origRid); LazyList value = new LazyList(genericParamRidList.Count, this, genericParamRidList, (RidList list2, int index) => readerModule.ResolveGenericParam(list2[index])); Interlocked.CompareExchange(ref genericParameters, value, null); } protected override void InitializeInterfaces() { RidList interfaceImplRidList = readerModule.Metadata.GetInterfaceImplRidList(origRid); LazyList value = new LazyList(interfaceImplRidList.Count, interfaceImplRidList, (RidList list2, int index) => readerModule.ResolveInterfaceImpl(list2[index], new GenericParamContext(this))); Interlocked.CompareExchange(ref interfaces, value, null); } protected override void InitializeDeclSecurities() { RidList declSecurityRidList = readerModule.Metadata.GetDeclSecurityRidList(Table.TypeDef, origRid); LazyList value = new LazyList(declSecurityRidList.Count, declSecurityRidList, (RidList list2, int index) => readerModule.ResolveDeclSecurity(list2[index])); Interlocked.CompareExchange(ref declSecurities, value, null); } protected override ClassLayout GetClassLayout_NoLock() { return readerModule.ResolveClassLayout(readerModule.Metadata.GetClassLayoutRid(origRid)); } protected override TypeDef GetDeclaringType2_NoLock() { if (!readerModule.TablesStream.TryReadNestedClassRow(readerModule.Metadata.GetNestedClassRid(origRid), out var row)) { return null; } return readerModule.ResolveTypeDef(row.EnclosingClass); } protected override void InitializeEvents() { uint eventMapRid = readerModule.Metadata.GetEventMapRid(origRid); RidList eventRidList = readerModule.Metadata.GetEventRidList(eventMapRid); LazyList value = new LazyList(eventRidList.Count, this, eventRidList, (RidList list2, int index) => readerModule.ResolveEvent(list2[index])); Interlocked.CompareExchange(ref events, value, null); } protected override void InitializeProperties() { uint propertyMapRid = readerModule.Metadata.GetPropertyMapRid(origRid); RidList propertyRidList = readerModule.Metadata.GetPropertyRidList(propertyMapRid); LazyList value = new LazyList(propertyRidList.Count, this, propertyRidList, (RidList list2, int index) => readerModule.ResolveProperty(list2[index])); Interlocked.CompareExchange(ref properties, value, null); } protected override void InitializeNestedTypes() { RidList nestedClassRidList = readerModule.Metadata.GetNestedClassRidList(origRid); LazyList value = new LazyList(nestedClassRidList.Count, this, nestedClassRidList, (RidList list2, int index) => readerModule.ResolveTypeDef(list2[index])); Interlocked.CompareExchange(ref nestedTypes, value, null); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.TypeDef, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), new GenericParamContext(this), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } protected override ModuleDef GetModule2_NoLock() { if (DeclaringType2_NoLock == null) { return readerModule; } return null; } public TypeDefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; readerModule.TablesStream.TryReadTypeDefRow(origRid, out var row); extendsCodedToken = row.Extends; attributes = (int)row.Flags; name = readerModule.StringsStream.ReadNoNull(row.Name); @namespace = readerModule.StringsStream.ReadNoNull(row.Namespace); } internal IList GetMethodOverrides(MethodDefMD method, GenericParamContext gpContext) { if (method == null) { return new List(); } if (methodRidToOverrides == null) { InitializeMethodOverrides(); } if (methodRidToOverrides.TryGetValue(method.OrigRid, out var value)) { List list = new List(value.Count); for (int i = 0; i < value.Count; i++) { MethodOverrideTokens methodOverrideTokens = value[i]; IMethodDefOrRef methodBody = (IMethodDefOrRef)readerModule.ResolveToken(methodOverrideTokens.MethodBodyToken, gpContext); IMethodDefOrRef methodDeclaration = (IMethodDefOrRef)readerModule.ResolveToken(methodOverrideTokens.MethodDeclarationToken, gpContext); list.Add(new MethodOverride(methodBody, methodDeclaration)); } return list; } return new List(); } private void InitializeMethodOverrides() { Dictionary> dictionary = new Dictionary>(); RidList methodImplRidList = readerModule.Metadata.GetMethodImplRidList(origRid); for (int i = 0; i < methodImplRidList.Count; i++) { if (!readerModule.TablesStream.TryReadMethodImplRow(methodImplRidList[i], out var row)) { continue; } IMethodDefOrRef methodDefOrRef = readerModule.ResolveMethodDefOrRef(row.MethodBody); IMethodDefOrRef methodDefOrRef2 = readerModule.ResolveMethodDefOrRef(row.MethodDeclaration); if (methodDefOrRef == null || methodDefOrRef2 == null) { continue; } MethodDef methodDef = FindMethodImplMethod(methodDefOrRef); if (methodDef != null && methodDef.DeclaringType == this) { uint key = methodDef.Rid; if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List()); } value.Add(new MethodOverrideTokens(methodDefOrRef.MDToken.Raw, methodDefOrRef2.MDToken.Raw)); } } Interlocked.CompareExchange(ref methodRidToOverrides, dictionary, null); } internal void InitializeMethodSemanticsAttributes() { uint propertyMapRid = readerModule.Metadata.GetPropertyMapRid(origRid); RidList propertyRidList = readerModule.Metadata.GetPropertyRidList(propertyMapRid); for (int i = 0; i < propertyRidList.Count; i++) { RidList methodSemanticsRidList = readerModule.Metadata.GetMethodSemanticsRidList(Table.Property, propertyRidList[i]); for (int j = 0; j < methodSemanticsRidList.Count; j++) { if (readerModule.TablesStream.TryReadMethodSemanticsRow(methodSemanticsRidList[j], out var row)) { MethodDef methodDef = readerModule.ResolveMethod(row.Method); if (methodDef != null) { Interlocked.CompareExchange(ref methodDef.semAttrs, row.Semantic | MethodDef.SEMATTRS_INITD, 0); } } } } propertyMapRid = readerModule.Metadata.GetEventMapRid(origRid); propertyRidList = readerModule.Metadata.GetEventRidList(propertyMapRid); for (int k = 0; k < propertyRidList.Count; k++) { RidList methodSemanticsRidList2 = readerModule.Metadata.GetMethodSemanticsRidList(Table.Event, propertyRidList[k]); for (int l = 0; l < methodSemanticsRidList2.Count; l++) { if (readerModule.TablesStream.TryReadMethodSemanticsRow(methodSemanticsRidList2[l], out var row2)) { MethodDef methodDef2 = readerModule.ResolveMethod(row2.Method); if (methodDef2 != null) { Interlocked.CompareExchange(ref methodDef2.semAttrs, row2.Semantic | MethodDef.SEMATTRS_INITD, 0); } } } } } internal void InitializeProperty(PropertyDefMD prop, out IList getMethods, out IList setMethods, out IList otherMethods) { getMethods = new List(); setMethods = new List(); otherMethods = new List(); if (prop == null) { return; } RidList methodSemanticsRidList = readerModule.Metadata.GetMethodSemanticsRidList(Table.Property, prop.OrigRid); for (int i = 0; i < methodSemanticsRidList.Count; i++) { if (!readerModule.TablesStream.TryReadMethodSemanticsRow(methodSemanticsRidList[i], out var row)) { continue; } MethodDef methodDef = readerModule.ResolveMethod(row.Method); if (methodDef == null || methodDef.DeclaringType != prop.DeclaringType) { continue; } switch ((MethodSemanticsAttributes)row.Semantic) { case MethodSemanticsAttributes.Setter: if (!setMethods.Contains(methodDef)) { setMethods.Add(methodDef); } break; case MethodSemanticsAttributes.Getter: if (!getMethods.Contains(methodDef)) { getMethods.Add(methodDef); } break; case MethodSemanticsAttributes.Other: if (!otherMethods.Contains(methodDef)) { otherMethods.Add(methodDef); } break; } } } internal void InitializeEvent(EventDefMD evt, out MethodDef addMethod, out MethodDef invokeMethod, out MethodDef removeMethod, out IList otherMethods) { addMethod = null; invokeMethod = null; removeMethod = null; otherMethods = new List(); if (evt == null) { return; } RidList methodSemanticsRidList = readerModule.Metadata.GetMethodSemanticsRidList(Table.Event, evt.OrigRid); for (int i = 0; i < methodSemanticsRidList.Count; i++) { if (!readerModule.TablesStream.TryReadMethodSemanticsRow(methodSemanticsRidList[i], out var row)) { continue; } MethodDef methodDef = readerModule.ResolveMethod(row.Method); if (methodDef == null || methodDef.DeclaringType != evt.DeclaringType) { continue; } switch ((MethodSemanticsAttributes)row.Semantic) { case MethodSemanticsAttributes.AddOn: if (addMethod == null) { addMethod = methodDef; } break; case MethodSemanticsAttributes.RemoveOn: if (removeMethod == null) { removeMethod = methodDef; } break; case MethodSemanticsAttributes.Fire: if (invokeMethod == null) { invokeMethod = methodDef; } break; case MethodSemanticsAttributes.Other: if (!otherMethods.Contains(methodDef)) { otherMethods.Add(methodDef); } break; } } } internal override void OnLazyAdd2(int index, ref FieldDef value) { if (value.DeclaringType != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadField(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } internal override void OnLazyAdd2(int index, ref MethodDef value) { if (value.DeclaringType != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadMethod(value.Rid).InitializeAll()); value.DeclaringType2 = this; value.Parameters.UpdateThisParameterType(this); } } internal override void OnLazyAdd2(int index, ref EventDef value) { if (value.DeclaringType != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadEvent(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } internal override void OnLazyAdd2(int index, ref PropertyDef value) { if (value.DeclaringType != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadProperty(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } internal override void OnLazyAdd2(int index, ref GenericParam value) { if (value.Owner != this) { value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParam(value.Rid).InitializeAll()); value.Owner = this; } } } internal sealed class TypeDefFinder : ITypeDefFinder, IDisposable { private const SigComparerOptions TypeComparerOptions = SigComparerOptions.DontCompareTypeScope | SigComparerOptions.TypeRefCanReferenceGlobalType; private bool isCacheEnabled; private readonly bool includeNestedTypes; private Dictionary typeRefCache = new Dictionary(new TypeEqualityComparer(SigComparerOptions.DontCompareTypeScope | SigComparerOptions.TypeRefCanReferenceGlobalType)); private Dictionary normalNameCache = new Dictionary(StringComparer.Ordinal); private Dictionary reflectionNameCache = new Dictionary(StringComparer.Ordinal); private readonly StringBuilder sb = new StringBuilder(); private IEnumerator typeEnumerator; private readonly IEnumerable rootTypes; private readonly Lock theLock = Lock.Create(); public bool IsCacheEnabled { get { theLock.EnterReadLock(); try { return IsCacheEnabled_NoLock; } finally { theLock.ExitReadLock(); } } set { theLock.EnterWriteLock(); try { IsCacheEnabled_NoLock = value; } finally { theLock.ExitWriteLock(); } } } private bool IsCacheEnabled_NoLock { get { return isCacheEnabled; } set { if (isCacheEnabled != value) { if (typeEnumerator != null) { typeEnumerator.Dispose(); typeEnumerator = null; } typeRefCache.Clear(); normalNameCache.Clear(); reflectionNameCache.Clear(); if (value) { InitializeTypeEnumerator(); } isCacheEnabled = value; } } } public TypeDefFinder(IEnumerable rootTypes) : this(rootTypes, includeNestedTypes: true) { } public TypeDefFinder(IEnumerable rootTypes, bool includeNestedTypes) { this.rootTypes = rootTypes ?? throw new ArgumentNullException("rootTypes"); this.includeNestedTypes = includeNestedTypes; } private void InitializeTypeEnumerator() { if (typeEnumerator != null) { typeEnumerator.Dispose(); typeEnumerator = null; } typeEnumerator = (includeNestedTypes ? AllTypesHelper.Types(rootTypes) : rootTypes).GetEnumerator(); } public void ResetCache() { theLock.EnterWriteLock(); try { bool isCacheEnabled_NoLock = IsCacheEnabled_NoLock; IsCacheEnabled_NoLock = false; IsCacheEnabled_NoLock = isCacheEnabled_NoLock; } finally { theLock.ExitWriteLock(); } } public TypeDef Find(string fullName, bool isReflectionName) { if (fullName == null) { return null; } theLock.EnterWriteLock(); try { if (isCacheEnabled) { return isReflectionName ? FindCacheReflection(fullName) : FindCacheNormal(fullName); } return isReflectionName ? FindSlowReflection(fullName) : FindSlowNormal(fullName); } finally { theLock.ExitWriteLock(); } } public TypeDef Find(TypeRef typeRef) { if (typeRef == null) { return null; } theLock.EnterWriteLock(); try { return isCacheEnabled ? FindCache(typeRef) : FindSlow(typeRef); } finally { theLock.ExitWriteLock(); } } private TypeDef FindCache(TypeRef typeRef) { if (typeRefCache.TryGetValue(typeRef, out var value)) { return value; } SigComparer sigComparer = new SigComparer(SigComparerOptions.DontCompareTypeScope | SigComparerOptions.TypeRefCanReferenceGlobalType); do { value = GetNextTypeDefCache(); } while (value != null && !sigComparer.Equals(value, typeRef)); return value; } private TypeDef FindCacheReflection(string fullName) { if (reflectionNameCache.TryGetValue(fullName, out var value)) { return value; } do { value = GetNextTypeDefCache(); if (value == null) { return value; } sb.Length = 0; } while (!(FullNameFactory.FullName(value, isReflection: true, null, sb) == fullName)); return value; } private TypeDef FindCacheNormal(string fullName) { if (normalNameCache.TryGetValue(fullName, out var value)) { return value; } do { value = GetNextTypeDefCache(); if (value == null) { return value; } sb.Length = 0; } while (!(FullNameFactory.FullName(value, isReflection: false, null, sb) == fullName)); return value; } private TypeDef FindSlow(TypeRef typeRef) { InitializeTypeEnumerator(); SigComparer sigComparer = new SigComparer(SigComparerOptions.DontCompareTypeScope | SigComparerOptions.TypeRefCanReferenceGlobalType); TypeDef nextTypeDef; do { nextTypeDef = GetNextTypeDef(); } while (nextTypeDef != null && !sigComparer.Equals(nextTypeDef, typeRef)); return nextTypeDef; } private TypeDef FindSlowReflection(string fullName) { InitializeTypeEnumerator(); TypeDef nextTypeDef; do { nextTypeDef = GetNextTypeDef(); if (nextTypeDef == null) { return nextTypeDef; } sb.Length = 0; } while (!(FullNameFactory.FullName(nextTypeDef, isReflection: true, null, sb) == fullName)); return nextTypeDef; } private TypeDef FindSlowNormal(string fullName) { InitializeTypeEnumerator(); TypeDef nextTypeDef; do { nextTypeDef = GetNextTypeDef(); if (nextTypeDef == null) { return nextTypeDef; } sb.Length = 0; } while (!(FullNameFactory.FullName(nextTypeDef, isReflection: false, null, sb) == fullName)); return nextTypeDef; } private TypeDef GetNextTypeDef() { while (typeEnumerator.MoveNext()) { TypeDef current = typeEnumerator.Current; if (current != null) { return current; } } return null; } private TypeDef GetNextTypeDefCache() { TypeDef nextTypeDef = GetNextTypeDef(); if (nextTypeDef == null) { return null; } if (!typeRefCache.ContainsKey(nextTypeDef)) { typeRefCache[nextTypeDef] = nextTypeDef; } sb.Length = 0; string key; if (!normalNameCache.ContainsKey(key = FullNameFactory.FullName(nextTypeDef, isReflection: false, null, sb))) { normalNameCache[key] = nextTypeDef; } sb.Length = 0; if (!reflectionNameCache.ContainsKey(key = FullNameFactory.FullName(nextTypeDef, isReflection: true, null, sb))) { reflectionNameCache[key] = nextTypeDef; } return nextTypeDef; } public void Dispose() { theLock.EnterWriteLock(); try { if (typeEnumerator != null) { typeEnumerator.Dispose(); } typeEnumerator = null; typeRefCache = null; normalNameCache = null; reflectionNameCache = null; } finally { theLock.ExitWriteLock(); } } } internal struct TypeHelper { private RecursionCounter recursionCounter; internal static bool ContainsGenericParameter(StandAloneSig ss) { if (ss != null) { return ContainsGenericParameter(ss.Signature); } return false; } internal static bool ContainsGenericParameter(InterfaceImpl ii) { if (ii != null) { return ContainsGenericParameter(ii.Interface); } return false; } internal static bool ContainsGenericParameter(GenericParamConstraint gpc) { if (gpc != null) { return ContainsGenericParameter(gpc.Constraint); } return false; } internal static bool ContainsGenericParameter(MethodSpec ms) { if (ms != null) { return ContainsGenericParameter(ms.GenericInstMethodSig); } return false; } internal static bool ContainsGenericParameter(MemberRef mr) { if (mr == null) { return false; } if (ContainsGenericParameter(mr.Signature)) { return true; } IMemberRefParent memberRefParent = mr.Class; if (memberRefParent is ITypeDefOrRef typeDefOrRef) { return typeDefOrRef.ContainsGenericParameter; } if (memberRefParent is MethodDef methodDef) { return ContainsGenericParameter(methodDef.Signature); } return false; } public static bool ContainsGenericParameter(CallingConventionSig callConv) { if (callConv is FieldSig fieldSig) { return ContainsGenericParameter(fieldSig); } if (callConv is MethodBaseSig methodSig) { return ContainsGenericParameter(methodSig); } if (callConv is LocalSig localSig) { return ContainsGenericParameter(localSig); } if (callConv is GenericInstMethodSig gim) { return ContainsGenericParameter(gim); } return false; } public static bool ContainsGenericParameter(FieldSig fieldSig) { return default(TypeHelper).ContainsGenericParameterInternal(fieldSig); } public static bool ContainsGenericParameter(MethodBaseSig methodSig) { return default(TypeHelper).ContainsGenericParameterInternal(methodSig); } public static bool ContainsGenericParameter(LocalSig localSig) { return default(TypeHelper).ContainsGenericParameterInternal(localSig); } public static bool ContainsGenericParameter(GenericInstMethodSig gim) { return default(TypeHelper).ContainsGenericParameterInternal(gim); } public static bool ContainsGenericParameter(IType type) { if (type is TypeDef type2) { return ContainsGenericParameter(type2); } if (type is TypeRef type3) { return ContainsGenericParameter(type3); } if (type is TypeSpec type4) { return ContainsGenericParameter(type4); } if (type is TypeSig type5) { return ContainsGenericParameter(type5); } if (type is ExportedType type6) { return ContainsGenericParameter(type6); } return false; } public static bool ContainsGenericParameter(TypeDef type) { return default(TypeHelper).ContainsGenericParameterInternal(type); } public static bool ContainsGenericParameter(TypeRef type) { return default(TypeHelper).ContainsGenericParameterInternal(type); } public static bool ContainsGenericParameter(TypeSpec type) { return default(TypeHelper).ContainsGenericParameterInternal(type); } public static bool ContainsGenericParameter(TypeSig type) { return default(TypeHelper).ContainsGenericParameterInternal(type); } public static bool ContainsGenericParameter(ExportedType type) { return default(TypeHelper).ContainsGenericParameterInternal(type); } private bool ContainsGenericParameterInternal(TypeDef type) { return false; } private bool ContainsGenericParameterInternal(TypeRef type) { return false; } private bool ContainsGenericParameterInternal(TypeSpec type) { if (type == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ContainsGenericParameterInternal(type.TypeSig); recursionCounter.Decrement(); return result; } private bool ContainsGenericParameterInternal(ITypeDefOrRef tdr) { if (tdr == null) { return false; } return ContainsGenericParameterInternal(tdr as TypeSpec); } private bool ContainsGenericParameterInternal(TypeSig type) { if (type == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result; switch (type.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = ContainsGenericParameterInternal((type as TypeDefOrRefSig).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: result = true; break; case ElementType.FnPtr: result = ContainsGenericParameterInternal((type as FnPtrSig).Signature); break; case ElementType.GenericInst: { GenericInstSig genericInstSig = (GenericInstSig)type; result = ContainsGenericParameterInternal(genericInstSig.GenericType) || ContainsGenericParameter(genericInstSig.GenericArguments); break; } case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.Module: case ElementType.Pinned: result = ContainsGenericParameterInternal((type as NonLeafSig).Next); break; case ElementType.CModReqd: case ElementType.CModOpt: result = ContainsGenericParameterInternal((type as ModifierSig).Modifier) || ContainsGenericParameterInternal((type as NonLeafSig).Next); break; default: result = false; break; } recursionCounter.Decrement(); return result; } private bool ContainsGenericParameterInternal(ExportedType type) { return false; } private bool ContainsGenericParameterInternal(CallingConventionSig callConv) { if (callConv is FieldSig fs) { return ContainsGenericParameterInternal(fs); } if (callConv is MethodBaseSig mbs) { return ContainsGenericParameterInternal(mbs); } if (callConv is LocalSig ls) { return ContainsGenericParameterInternal(ls); } if (callConv is GenericInstMethodSig gim) { return ContainsGenericParameterInternal(gim); } return false; } private bool ContainsGenericParameterInternal(FieldSig fs) { if (fs == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ContainsGenericParameterInternal(fs.Type); recursionCounter.Decrement(); return result; } private bool ContainsGenericParameterInternal(MethodBaseSig mbs) { if (mbs == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ContainsGenericParameterInternal(mbs.RetType) || ContainsGenericParameter(mbs.Params) || ContainsGenericParameter(mbs.ParamsAfterSentinel); recursionCounter.Decrement(); return result; } private bool ContainsGenericParameterInternal(LocalSig ls) { if (ls == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ContainsGenericParameter(ls.Locals); recursionCounter.Decrement(); return result; } private bool ContainsGenericParameterInternal(GenericInstMethodSig gim) { if (gim == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = ContainsGenericParameter(gim.GenericArguments); recursionCounter.Decrement(); return result; } private bool ContainsGenericParameter(IList types) { if (types == null) { return false; } if (!recursionCounter.Increment()) { return false; } bool result = false; int count = types.Count; for (int i = 0; i < count; i++) { if (ContainsGenericParameter(types[i])) { result = true; break; } } recursionCounter.Decrement(); return result; } } [Serializable] public class TypeNameParserException : Exception { public TypeNameParserException() { } public TypeNameParserException(string message) : base(message) { } public TypeNameParserException(string message, Exception innerException) : base(message, innerException) { } protected TypeNameParserException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public interface IAssemblyRefFinder { AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef); } public abstract class TypeNameParser : IDisposable { internal abstract class TSpec { public readonly ElementType etype; protected TSpec(ElementType etype) { this.etype = etype; } } internal sealed class SZArraySpec : TSpec { public static readonly SZArraySpec Instance = new SZArraySpec(); private SZArraySpec() : base(ElementType.SZArray) { } } internal sealed class ArraySpec : TSpec { public uint rank; public readonly IList sizes = new List(); public readonly IList lowerBounds = new List(); public ArraySpec() : base(ElementType.Array) { } } internal sealed class GenericInstSpec : TSpec { public readonly List args = new List(); public GenericInstSpec() : base(ElementType.GenericInst) { } } internal sealed class ByRefSpec : TSpec { public static readonly ByRefSpec Instance = new ByRefSpec(); private ByRefSpec() : base(ElementType.ByRef) { } } internal sealed class PtrSpec : TSpec { public static readonly PtrSpec Instance = new PtrSpec(); private PtrSpec() : base(ElementType.Ptr) { } } protected ModuleDef ownerModule; private readonly GenericParamContext gpContext; private StringReader reader; private readonly IAssemblyRefFinder typeNameParserHelper; private RecursionCounter recursionCounter; public static ITypeDefOrRef ParseReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)); } public static ITypeDefOrRef ParseReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { using ReflectionTypeNameParser reflectionTypeNameParser = new ReflectionTypeNameParser(ownerModule, typeFullName, typeNameParserHelper, gpContext); return reflectionTypeNameParser.Parse(); } public static ITypeDefOrRef ParseReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseReflection(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)); } public static ITypeDefOrRef ParseReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { try { return ParseReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, gpContext); } catch (TypeNameParserException) { return null; } } public static TypeSig ParseAsTypeSigReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseAsTypeSigReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)); } public static TypeSig ParseAsTypeSigReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { using ReflectionTypeNameParser reflectionTypeNameParser = new ReflectionTypeNameParser(ownerModule, typeFullName, typeNameParserHelper, gpContext); return reflectionTypeNameParser.ParseAsTypeSig(); } public static TypeSig ParseAsTypeSigReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseAsTypeSigReflection(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)); } public static TypeSig ParseAsTypeSigReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { try { return ParseAsTypeSigReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, gpContext); } catch (TypeNameParserException) { return null; } } protected TypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) : this(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)) { } protected TypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { this.ownerModule = ownerModule; reader = new StringReader(typeFullName ?? string.Empty); this.typeNameParserHelper = typeNameParserHelper; this.gpContext = gpContext; } internal ITypeDefOrRef Parse() { return ownerModule.UpdateRowId(ParseAsTypeSig().ToTypeDefOrRef()); } internal abstract TypeSig ParseAsTypeSig(); protected void RecursionIncrement() { if (!recursionCounter.Increment()) { throw new TypeNameParserException("Stack overflow"); } } protected void RecursionDecrement() { recursionCounter.Decrement(); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { if (reader != null) { reader.Dispose(); } reader = null; } } internal GenericSig ReadGenericSig() { Verify(ReadChar() == 33, "Expected '!'"); if (PeekChar() == 33) { ReadChar(); return new GenericMVar(ReadUInt32(), gpContext.Method); } return new GenericVar(ReadUInt32(), gpContext.Type); } internal TypeSig CreateTypeSig(IList tspecs, TypeSig currentSig) { int count = tspecs.Count; for (int i = 0; i < count; i++) { TSpec tSpec = tspecs[i]; switch (tSpec.etype) { case ElementType.SZArray: currentSig = new SZArraySig(currentSig); break; case ElementType.Array: { ArraySpec arraySpec = (ArraySpec)tSpec; currentSig = new ArraySig(currentSig, arraySpec.rank, arraySpec.sizes, arraySpec.lowerBounds); break; } case ElementType.GenericInst: { GenericInstSpec genericInstSpec = (GenericInstSpec)tSpec; currentSig = new GenericInstSig(currentSig as ClassOrValueTypeSig, genericInstSpec.args); break; } case ElementType.ByRef: currentSig = new ByRefSig(currentSig); break; case ElementType.Ptr: currentSig = new PtrSig(currentSig); break; default: Verify(b: false, "Unknown TSpec"); break; } } return currentSig; } protected TypeRef ReadTypeRefAndNestedNoAssembly(char nestedChar) { TypeRef typeRef = ReadTypeRefNoAssembly(); while (true) { SkipWhite(); if (PeekChar() != nestedChar) { break; } ReadChar(); TypeRef typeRef2 = ReadTypeRefNoAssembly(); typeRef2.ResolutionScope = typeRef; typeRef = typeRef2; } return typeRef; } protected TypeRef ReadTypeRefNoAssembly() { GetNamespaceAndName(ReadId(ignoreWhiteSpace: false, ignoreEqualSign: false), out var ns, out var name); return ownerModule.UpdateRowId(new TypeRefUser(ownerModule, ns, name)); } private static void GetNamespaceAndName(string fullName, out string ns, out string name) { int num = fullName.LastIndexOf('.'); if (num < 0) { ns = string.Empty; name = fullName; } else { ns = fullName.Substring(0, num); name = fullName.Substring(num + 1); } } internal TypeSig ToTypeSig(ITypeDefOrRef type) { if (type is TypeDef typeDef) { return ToTypeSig(typeDef, typeDef.IsValueType); } if (type is TypeRef typeRef) { return ToTypeSig(typeRef, IsValueType(typeRef)); } if (type is TypeSpec typeSpec) { return typeSpec.TypeSig; } Verify(b: false, "Unknown type"); return null; } private static TypeSig ToTypeSig(ITypeDefOrRef type, bool isValueType) { if (!isValueType) { return new ClassSig(type); } return new ValueTypeSig(type); } internal AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef) { AssemblyRef assemblyRef = null; if (nonNestedTypeRef != null && typeNameParserHelper != null) { assemblyRef = typeNameParserHelper.FindAssemblyRef(nonNestedTypeRef); } if (assemblyRef != null) { return assemblyRef; } AssemblyDef assembly = ownerModule.Assembly; if (assembly != null) { return ownerModule.UpdateRowId(assembly.ToAssemblyRef()); } return AssemblyRef.CurrentAssembly; } internal bool IsValueType(TypeRef typeRef) { return typeRef?.IsValueType ?? false; } internal static void Verify(bool b, string msg) { if (!b) { throw new TypeNameParserException(msg); } } internal void SkipWhite() { while (true) { int num = PeekChar(); if (num != -1 && char.IsWhiteSpace((char)num)) { ReadChar(); continue; } break; } } internal uint ReadUInt32() { SkipWhite(); bool b = false; uint num = 0u; while (true) { int num2 = PeekChar(); if (num2 == -1 || num2 < 48 || num2 > 57) { break; } ReadChar(); int num3 = (int)(num * 10) + (num2 - 48); Verify((uint)num3 >= num, "Integer overflow"); num = (uint)num3; b = true; } Verify(b, "Expected an integer"); return num; } internal int ReadInt32() { SkipWhite(); bool flag = false; if (PeekChar() == 45) { flag = true; ReadChar(); } uint num = ReadUInt32(); if (flag) { Verify(num <= 2147483648u, "Integer overflow"); return (int)(0 - num); } Verify(num <= int.MaxValue, "Integer overflow"); return (int)num; } internal string ReadId() { return ReadId(ignoreWhiteSpace: true, ignoreEqualSign: true); } internal string ReadId(bool ignoreWhiteSpace, bool ignoreEqualSign) { SkipWhite(); StringBuilder stringBuilder = new StringBuilder(); int idChar; while ((idChar = GetIdChar(ignoreWhiteSpace, ignoreEqualSign)) != -1) { stringBuilder.Append((char)idChar); } Verify(stringBuilder.Length > 0, "Expected an id"); return stringBuilder.ToString(); } protected int PeekChar() { return reader.Peek(); } protected int ReadChar() { return reader.Read(); } internal abstract int GetIdChar(bool ignoreWhiteSpace, bool ignoreEqualSign); } internal sealed class ReflectionTypeNameParser : TypeNameParser { public ReflectionTypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) : base(ownerModule, typeFullName, typeNameParserHelper, default(GenericParamContext)) { } public ReflectionTypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) : base(ownerModule, typeFullName, typeNameParserHelper, gpContext) { } public static AssemblyRef ParseAssemblyRef(string asmFullName) { return ParseAssemblyRef(asmFullName, default(GenericParamContext)); } public static AssemblyRef ParseAssemblyRef(string asmFullName, GenericParamContext gpContext) { try { using ReflectionTypeNameParser reflectionTypeNameParser = new ReflectionTypeNameParser(null, asmFullName, null, gpContext); return reflectionTypeNameParser.ReadAssemblyRef(); } catch { return null; } } internal override TypeSig ParseAsTypeSig() { try { TypeSig result = ReadType(readAssemblyReference: true); SkipWhite(); TypeNameParser.Verify(PeekChar() == -1, "Extra input after type name"); return result; } catch (TypeNameParserException) { throw; } catch (Exception innerException) { throw new TypeNameParserException("Could not parse type name", innerException); } } private TypeSig ReadType(bool readAssemblyReference) { RecursionIncrement(); SkipWhite(); TypeSig typeSig; if (PeekChar() == 33) { GenericSig currentSig = ReadGenericSig(); IList tspecs = ReadTSpecs(); ReadOptionalAssemblyRef(); typeSig = CreateTypeSig(tspecs, currentSig); } else { TypeRef typeRef = ReadTypeRefAndNestedNoAssembly('+'); IList list = ReadTSpecs(); TypeRef nonNestedTypeRef = TypeRef.GetNonNestedTypeRef(typeRef); AssemblyRef asmRef = (AssemblyRef)(nonNestedTypeRef.ResolutionScope = ((!readAssemblyReference) ? FindAssemblyRef(nonNestedTypeRef) : (ReadOptionalAssemblyRef() ?? FindAssemblyRef(nonNestedTypeRef)))); typeSig = null; if (typeRef == nonNestedTypeRef) { CorLibTypeSig corLibTypeSig = ownerModule.CorLibTypes.GetCorLibTypeSig(typeRef.Namespace, typeRef.Name, typeRef.DefinitionAssembly); if (corLibTypeSig != null) { typeSig = corLibTypeSig; } } if (typeSig == null) { TypeDef typeDef = Resolve(asmRef, typeRef); ITypeDefOrRef type; if (typeDef == null) { ITypeDefOrRef typeDefOrRef = typeRef; type = typeDefOrRef; } else { ITypeDefOrRef typeDefOrRef = typeDef; type = typeDefOrRef; } typeSig = ToTypeSig(type); } if (list.Count != 0) { typeSig = CreateTypeSig(list, typeSig); } } RecursionDecrement(); return typeSig; } private TypeDef Resolve(AssemblyRef asmRef, TypeRef typeRef) { AssemblyDef assembly = ownerModule.Assembly; if (assembly == null) { return null; } if (!AssemblyNameComparer.CompareAll.Equals(asmRef, assembly) || asmRef.IsRetargetable != assembly.IsRetargetable) { return null; } TypeDef typeDef = assembly.Find(typeRef); if (typeDef == null || typeDef.Module != ownerModule) { return null; } return typeDef; } private AssemblyRef ReadOptionalAssemblyRef() { SkipWhite(); if (PeekChar() == 44) { ReadChar(); return ReadAssemblyRef(); } return null; } private IList ReadTSpecs() { List list = new List(); while (true) { SkipWhite(); switch (PeekChar()) { case 91: { ReadChar(); SkipWhite(); int num = PeekChar(); switch (num) { case 93: TypeNameParser.Verify(ReadChar() == 93, "Expected ']'"); list.Add(SZArraySpec.Instance); break; default: if (!char.IsDigit((char)num)) { GenericInstSpec genericInstSpec = new GenericInstSpec(); while (true) { SkipWhite(); num = PeekChar(); bool flag = num == 91; if (num == 93) { break; } TypeNameParser.Verify(!flag || ReadChar() == 91, "Expected '['"); genericInstSpec.args.Add(ReadType(flag)); SkipWhite(); TypeNameParser.Verify(!flag || ReadChar() == 93, "Expected ']'"); SkipWhite(); if (PeekChar() != 44) { break; } ReadChar(); } TypeNameParser.Verify(ReadChar() == 93, "Expected ']'"); list.Add(genericInstSpec); break; } goto case 42; case 42: case 44: case 45: { ArraySpec arraySpec = new ArraySpec(); arraySpec.rank = 0u; while (true) { SkipWhite(); int num2 = PeekChar(); if (num2 == 42) { ReadChar(); } else if (num2 != 44 && num2 != 93) { if (num2 == 45 || char.IsDigit((char)num2)) { int num3 = ReadInt32(); SkipWhite(); TypeNameParser.Verify(ReadChar() == 46, "Expected '.'"); TypeNameParser.Verify(ReadChar() == 46, "Expected '.'"); uint? num4; if (PeekChar() == 46) { ReadChar(); num4 = null; } else { SkipWhite(); if (PeekChar() == 45) { int num5 = ReadInt32(); TypeNameParser.Verify(num5 >= num3, "upper < lower"); num4 = (uint)(num5 - num3 + 1); TypeNameParser.Verify(num4.Value != 0 && num4.Value <= 536870911, "Invalid size"); } else { long num6 = ReadUInt32() - num3 + 1; TypeNameParser.Verify(num6 > 0 && num6 <= 536870911, "Invalid size"); num4 = (uint)num6; } } if (arraySpec.lowerBounds.Count == arraySpec.rank) { arraySpec.lowerBounds.Add(num3); } if (num4.HasValue && arraySpec.sizes.Count == arraySpec.rank) { arraySpec.sizes.Add(num4.Value); } } else { TypeNameParser.Verify(b: false, "Unknown char"); } } arraySpec.rank++; SkipWhite(); if (PeekChar() != 44) { break; } ReadChar(); } TypeNameParser.Verify(ReadChar() == 93, "Expected ']'"); list.Add(arraySpec); break; } } break; } case 38: ReadChar(); list.Add(ByRefSpec.Instance); break; case 42: ReadChar(); list.Add(PtrSpec.Instance); break; default: return list; } } } private AssemblyRef ReadAssemblyRef() { AssemblyRefUser assemblyRefUser = new AssemblyRefUser(); if (ownerModule != null) { ownerModule.UpdateRowId(assemblyRefUser); } assemblyRefUser.Name = ReadAssemblyNameId(); SkipWhite(); if (PeekChar() != 44) { return assemblyRefUser; } ReadChar(); while (true) { SkipWhite(); switch (PeekChar()) { case 44: ReadChar(); continue; case -1: case 93: return assemblyRefUser; } string text = ReadId(); SkipWhite(); if (PeekChar() != 61) { continue; } ReadChar(); string text2 = ReadId(); switch (text.ToUpperInvariant()) { case "VERSION": assemblyRefUser.Version = Utils.ParseVersion(text2); break; case "CONTENTTYPE": if (text2.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) { assemblyRefUser.ContentType = AssemblyAttributes.ContentType_WindowsRuntime; } else { assemblyRefUser.ContentType = AssemblyAttributes.None; } break; case "RETARGETABLE": if (text2.Equals("Yes", StringComparison.OrdinalIgnoreCase)) { assemblyRefUser.IsRetargetable = true; } else { assemblyRefUser.IsRetargetable = false; } break; case "PUBLICKEY": if (text2.Equals("null", StringComparison.OrdinalIgnoreCase) || text2.Equals("neutral", StringComparison.OrdinalIgnoreCase)) { assemblyRefUser.PublicKeyOrToken = new PublicKey(); } else { assemblyRefUser.PublicKeyOrToken = PublicKeyBase.CreatePublicKey(Utils.ParseBytes(text2)); } assemblyRefUser.Attributes |= AssemblyAttributes.PublicKey; break; case "PUBLICKEYTOKEN": if (text2.Equals("null", StringComparison.OrdinalIgnoreCase) || text2.Equals("neutral", StringComparison.OrdinalIgnoreCase)) { assemblyRefUser.PublicKeyOrToken = new PublicKeyToken(); } else { assemblyRefUser.PublicKeyOrToken = PublicKeyBase.CreatePublicKeyToken(Utils.ParseBytes(text2)); } assemblyRefUser.Attributes &= ~AssemblyAttributes.PublicKey; break; case "CULTURE": case "LANGUAGE": if (text2.Equals("neutral", StringComparison.OrdinalIgnoreCase)) { assemblyRefUser.Culture = UTF8String.Empty; } else { assemblyRefUser.Culture = text2; } break; } } } private string ReadAssemblyNameId() { SkipWhite(); StringBuilder stringBuilder = new StringBuilder(); int asmNameChar; while ((asmNameChar = GetAsmNameChar()) != -1) { stringBuilder.Append((char)asmNameChar); } string text = stringBuilder.ToString().Trim(); TypeNameParser.Verify(text.Length > 0, "Expected an assembly name"); return text; } private int GetAsmNameChar() { switch (PeekChar()) { case -1: return -1; case 92: ReadChar(); return ReadChar(); case 44: case 93: return -1; default: return ReadChar(); } } internal override int GetIdChar(bool ignoreWhiteSpace, bool ignoreEqualSign) { int num = PeekChar(); if (num == -1) { return -1; } if (ignoreWhiteSpace && char.IsWhiteSpace((char)num)) { return -1; } switch (num) { case 92: ReadChar(); return ReadChar(); case 61: if (!ignoreEqualSign) { break; } goto case 38; case 38: case 42: case 43: case 44: case 91: case 93: return -1; } return ReadChar(); } } public abstract class TypeRef : ITypeDefOrRef, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IMemberRefParent, IFullName, IType, IOwnerModule, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter, ITokenOperand, IMemberRef, IHasCustomDebugInformation, IResolutionScope { protected uint rid; protected ModuleDef module; private readonly Lock theLock = Lock.Create(); protected IResolutionScope resolutionScope; protected bool resolutionScope_isInitialized; protected UTF8String name; protected UTF8String @namespace; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.TypeRef, rid); public uint Rid { get { return rid; } set { rid = value; } } public int TypeDefOrRefTag => 1; public int HasCustomAttributeTag => 2; public int MemberRefParentTag => 1; public int ResolutionScopeTag => 3; int IGenericParameterProvider.NumberOfGenericParameters => 0; string IType.TypeName => Name; public string ReflectionName => FullNameFactory.Name(this, isReflection: true); string IType.Namespace => Namespace; public string ReflectionNamespace => FullNameFactory.Namespace(this, isReflection: true); public string FullName => FullNameFactory.FullName(this, isReflection: false); public string ReflectionFullName => FullNameFactory.FullName(this, isReflection: true); public string AssemblyQualifiedName => FullNameFactory.AssemblyQualifiedName(this); public IAssembly DefinitionAssembly => FullNameFactory.DefinitionAssembly(this); public IScope Scope => FullNameFactory.Scope(this); public ITypeDefOrRef ScopeType => this; public bool ContainsGenericParameter => false; public ModuleDef Module => module; public IResolutionScope ResolutionScope { get { if (!resolutionScope_isInitialized) { InitializeResolutionScope(); } return resolutionScope; } set { theLock.EnterWriteLock(); try { resolutionScope = value; resolutionScope_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public UTF8String Name { get { return name; } set { name = value; } } public UTF8String Namespace { get { return @namespace; } set { @namespace = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 2; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } public bool IsNested => DeclaringType != null; public bool IsValueType => Resolve()?.IsValueType ?? false; public bool IsPrimitive => this.IsPrimitive(); public TypeRef DeclaringType => ResolutionScope as TypeRef; ITypeDefOrRef IMemberRef.DeclaringType => DeclaringType; bool IIsTypeOrMethod.IsType => true; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => false; bool IMemberRef.IsTypeRef => true; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; private void InitializeResolutionScope() { theLock.EnterWriteLock(); try { if (!resolutionScope_isInitialized) { resolutionScope = GetResolutionScope_NoLock(); resolutionScope_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual IResolutionScope GetResolutionScope_NoLock() { return null; } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } public TypeDef Resolve() { return Resolve(null); } public TypeDef Resolve(ModuleDef sourceModule) { if (module == null) { return null; } return module.Context.Resolver.Resolve(this, sourceModule ?? module); } public TypeDef ResolveThrow() { return ResolveThrow(null); } public TypeDef ResolveThrow(ModuleDef sourceModule) { TypeDef typeDef = Resolve(sourceModule); if (typeDef != null) { return typeDef; } throw new TypeResolveException($"Could not resolve type: {this} ({DefinitionAssembly})"); } internal static TypeRef GetNonNestedTypeRef(TypeRef typeRef) { if (typeRef == null) { return null; } for (int i = 0; i < 1000; i++) { if (!(typeRef.ResolutionScope is TypeRef typeRef2)) { return typeRef; } typeRef = typeRef2; } return null; } public override string ToString() { return FullName; } } public class TypeRefUser : TypeRef { public TypeRefUser(ModuleDef module, UTF8String name) : this(module, UTF8String.Empty, name) { } public TypeRefUser(ModuleDef module, UTF8String @namespace, UTF8String name) : this(module, @namespace, name, null) { } public TypeRefUser(ModuleDef module, UTF8String @namespace, UTF8String name, IResolutionScope resolutionScope) { base.module = module; base.resolutionScope = resolutionScope; resolutionScope_isInitialized = true; base.name = name; base.@namespace = @namespace; } } internal sealed class TypeRefMD : TypeRef, IMDTokenProviderMD, IMDTokenProvider { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly uint resolutionScopeCodedToken; public uint OrigRid => origRid; protected override IResolutionScope GetResolutionScope_NoLock() { return readerModule.ResolveResolutionScope(resolutionScopeCodedToken); } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.TypeRef, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), default(GenericParamContext), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public TypeRefMD(ModuleDefMD readerModule, uint rid) { origRid = rid; base.rid = rid; this.readerModule = readerModule; module = readerModule; readerModule.TablesStream.TryReadTypeRefRow(origRid, out var row); name = readerModule.StringsStream.ReadNoNull(row.Name); @namespace = readerModule.StringsStream.ReadNoNull(row.Namespace); resolutionScopeCodedToken = row.ResolutionScope; } } public abstract class TypeSig : IType, IFullName, IOwnerModule, ICodedToken, IMDTokenProvider, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter { private uint rid; public abstract TypeSig Next { get; } public abstract ElementType ElementType { get; } public MDToken MDToken => new MDToken(Table.TypeSpec, rid); public uint Rid { get { return rid; } set { rid = value; } } bool IIsTypeOrMethod.IsMethod => false; bool IIsTypeOrMethod.IsType => true; int IGenericParameterProvider.NumberOfGenericParameters { get { if (this.RemovePinnedAndModifiers() is GenericInstSig genericInstSig) { return genericInstSig.GenericArguments.Count; } return 0; } } public bool IsValueType { get { TypeSig typeSig = this.RemovePinnedAndModifiers(); if (typeSig == null) { return false; } if (typeSig.ElementType == ElementType.GenericInst) { typeSig = ((GenericInstSig)typeSig).GenericType; if (typeSig == null) { return false; } } return typeSig.ElementType.IsValueType(); } } public bool IsPrimitive => ElementType.IsPrimitive(); public string TypeName => FullNameFactory.Name(this, isReflection: false); UTF8String IFullName.Name { get { return new UTF8String(FullNameFactory.Name(this, isReflection: false)); } set { throw new NotSupportedException(); } } public string ReflectionName => FullNameFactory.Name(this, isReflection: true); public string Namespace => FullNameFactory.Namespace(this, isReflection: false); public string ReflectionNamespace => FullNameFactory.Namespace(this, isReflection: true); public string FullName => FullNameFactory.FullName(this, isReflection: false); public string ReflectionFullName => FullNameFactory.FullName(this, isReflection: true); public string AssemblyQualifiedName => FullNameFactory.AssemblyQualifiedName(this); public IAssembly DefinitionAssembly => FullNameFactory.DefinitionAssembly(this); public IScope Scope => FullNameFactory.Scope(this); public ITypeDefOrRef ScopeType => FullNameFactory.ScopeType(this); public ModuleDef Module => FullNameFactory.OwnerModule(this); public bool IsTypeDefOrRef => this is TypeDefOrRefSig; public bool IsCorLibType => this is CorLibTypeSig; public bool IsClassSig => this is ClassSig; public bool IsValueTypeSig => this is ValueTypeSig; public bool IsGenericParameter => this is GenericSig; public bool IsGenericTypeParameter => this is GenericVar; public bool IsGenericMethodParameter => this is GenericMVar; public bool IsSentinel => this is SentinelSig; public bool IsFunctionPointer => this is FnPtrSig; public bool IsGenericInstanceType => this is GenericInstSig; public bool IsPointer => this is PtrSig; public bool IsByRef => this is ByRefSig; public bool IsSingleOrMultiDimensionalArray => this is ArraySigBase; public bool IsArray => this is ArraySig; public bool IsSZArray => this is SZArraySig; public bool IsModifier => this is ModifierSig; public bool IsRequiredModifier => this is CModReqdSig; public bool IsOptionalModifier => this is CModOptSig; public bool IsPinned => this is PinnedSig; public bool IsValueArray => this is ValueArraySig; public bool IsModuleSig => this is ModuleSig; public bool ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); public override string ToString() { return FullName; } } public abstract class LeafSig : TypeSig { public sealed override TypeSig Next => null; } public abstract class TypeDefOrRefSig : LeafSig { private readonly ITypeDefOrRef typeDefOrRef; public ITypeDefOrRef TypeDefOrRef => typeDefOrRef; public bool IsTypeRef => TypeRef != null; public bool IsTypeDef => TypeDef != null; public bool IsTypeSpec => TypeSpec != null; public TypeRef TypeRef => typeDefOrRef as TypeRef; public TypeDef TypeDef => typeDefOrRef as TypeDef; public TypeSpec TypeSpec => typeDefOrRef as TypeSpec; protected TypeDefOrRefSig(ITypeDefOrRef typeDefOrRef) { this.typeDefOrRef = typeDefOrRef; } } public sealed class CorLibTypeSig : TypeDefOrRefSig { private readonly ElementType elementType; public override ElementType ElementType => elementType; public CorLibTypeSig(ITypeDefOrRef corType, ElementType elementType) : base(corType) { if (!(corType is TypeRef) && !(corType is TypeDef)) { throw new ArgumentException("corType must be a TypeDef or a TypeRef. null and TypeSpec are invalid inputs."); } this.elementType = elementType; } } public abstract class ClassOrValueTypeSig : TypeDefOrRefSig { protected ClassOrValueTypeSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } public sealed class ValueTypeSig : ClassOrValueTypeSig { public override ElementType ElementType => ElementType.ValueType; public ValueTypeSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } public sealed class ClassSig : ClassOrValueTypeSig { public override ElementType ElementType => ElementType.Class; public ClassSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } public abstract class GenericSig : LeafSig { private readonly bool isTypeVar; private readonly uint number; private readonly ITypeOrMethodDef genericParamProvider; public bool HasOwner => genericParamProvider != null; public bool HasOwnerType => OwnerType != null; public bool HasOwnerMethod => OwnerMethod != null; public TypeDef OwnerType => genericParamProvider as TypeDef; public MethodDef OwnerMethod => genericParamProvider as MethodDef; public uint Number => number; public GenericParam GenericParam { get { ITypeOrMethodDef typeOrMethodDef = genericParamProvider; if (typeOrMethodDef == null) { return null; } IList genericParameters = typeOrMethodDef.GenericParameters; int count = genericParameters.Count; for (int i = 0; i < count; i++) { GenericParam genericParam = genericParameters[i]; if (genericParam.Number == number) { return genericParam; } } return null; } } public bool IsMethodVar => !isTypeVar; public bool IsTypeVar => isTypeVar; protected GenericSig(bool isTypeVar, uint number) : this(isTypeVar, number, null) { } protected GenericSig(bool isTypeVar, uint number, ITypeOrMethodDef genericParamProvider) { this.isTypeVar = isTypeVar; this.number = number; this.genericParamProvider = genericParamProvider; } } public sealed class GenericVar : GenericSig { public override ElementType ElementType => ElementType.Var; public GenericVar(uint number) : base(isTypeVar: true, number) { } public GenericVar(int number) : base(isTypeVar: true, (uint)number) { } public GenericVar(uint number, TypeDef genericParamProvider) : base(isTypeVar: true, number, genericParamProvider) { } public GenericVar(int number, TypeDef genericParamProvider) : base(isTypeVar: true, (uint)number, genericParamProvider) { } } public sealed class GenericMVar : GenericSig { public override ElementType ElementType => ElementType.MVar; public GenericMVar(uint number) : base(isTypeVar: false, number) { } public GenericMVar(int number) : base(isTypeVar: false, (uint)number) { } public GenericMVar(uint number, MethodDef genericParamProvider) : base(isTypeVar: false, number, genericParamProvider) { } public GenericMVar(int number, MethodDef genericParamProvider) : base(isTypeVar: false, (uint)number, genericParamProvider) { } } public sealed class SentinelSig : LeafSig { public override ElementType ElementType => ElementType.Sentinel; } public sealed class FnPtrSig : LeafSig { private readonly CallingConventionSig signature; public override ElementType ElementType => ElementType.FnPtr; public CallingConventionSig Signature => signature; public MethodSig MethodSig => signature as MethodSig; public FnPtrSig(CallingConventionSig signature) { this.signature = signature; } } public sealed class GenericInstSig : LeafSig { private ClassOrValueTypeSig genericType; private readonly IList genericArgs; public override ElementType ElementType => ElementType.GenericInst; public ClassOrValueTypeSig GenericType { get { return genericType; } set { genericType = value; } } public IList GenericArguments => genericArgs; public GenericInstSig() { genericArgs = new List(); } public GenericInstSig(ClassOrValueTypeSig genericType) { this.genericType = genericType; genericArgs = new List(); } public GenericInstSig(ClassOrValueTypeSig genericType, uint genArgCount) { this.genericType = genericType; genericArgs = new List((int)genArgCount); } public GenericInstSig(ClassOrValueTypeSig genericType, int genArgCount) : this(genericType, (uint)genArgCount) { } public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1) { this.genericType = genericType; genericArgs = new List { genArg1 }; } public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1, TypeSig genArg2) { this.genericType = genericType; genericArgs = new List { genArg1, genArg2 }; } public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1, TypeSig genArg2, TypeSig genArg3) { this.genericType = genericType; genericArgs = new List { genArg1, genArg2, genArg3 }; } public GenericInstSig(ClassOrValueTypeSig genericType, params TypeSig[] genArgs) { this.genericType = genericType; genericArgs = new List(genArgs); } public GenericInstSig(ClassOrValueTypeSig genericType, IList genArgs) { this.genericType = genericType; genericArgs = new List(genArgs); } } public abstract class NonLeafSig : TypeSig { private readonly TypeSig nextSig; public sealed override TypeSig Next => nextSig; protected NonLeafSig(TypeSig nextSig) { this.nextSig = nextSig; } } public sealed class PtrSig : NonLeafSig { public override ElementType ElementType => ElementType.Ptr; public PtrSig(TypeSig nextSig) : base(nextSig) { } } public sealed class ByRefSig : NonLeafSig { public override ElementType ElementType => ElementType.ByRef; public ByRefSig(TypeSig nextSig) : base(nextSig) { } } public abstract class ArraySigBase : NonLeafSig { public bool IsMultiDimensional => ElementType == ElementType.Array; public bool IsSingleDimensional => ElementType == ElementType.SZArray; public abstract uint Rank { get; set; } protected ArraySigBase(TypeSig arrayType) : base(arrayType) { } public abstract IList GetSizes(); public abstract IList GetLowerBounds(); } public sealed class ArraySig : ArraySigBase { private uint rank; private readonly IList sizes; private readonly IList lowerBounds; public override ElementType ElementType => ElementType.Array; public override uint Rank { get { return rank; } set { rank = value; } } public IList Sizes => sizes; public IList LowerBounds => lowerBounds; public ArraySig(TypeSig arrayType) : base(arrayType) { sizes = new List(); lowerBounds = new List(); } public ArraySig(TypeSig arrayType, uint rank) : base(arrayType) { this.rank = rank; sizes = new List(); lowerBounds = new List(); } public ArraySig(TypeSig arrayType, int rank) : this(arrayType, (uint)rank) { } public ArraySig(TypeSig arrayType, uint rank, IEnumerable sizes, IEnumerable lowerBounds) : base(arrayType) { this.rank = rank; this.sizes = new List(sizes); this.lowerBounds = new List(lowerBounds); } public ArraySig(TypeSig arrayType, int rank, IEnumerable sizes, IEnumerable lowerBounds) : this(arrayType, (uint)rank, sizes, lowerBounds) { } internal ArraySig(TypeSig arrayType, uint rank, IList sizes, IList lowerBounds) : base(arrayType) { this.rank = rank; this.sizes = sizes; this.lowerBounds = lowerBounds; } public override IList GetSizes() { return sizes; } public override IList GetLowerBounds() { return lowerBounds; } } public sealed class SZArraySig : ArraySigBase { public override ElementType ElementType => ElementType.SZArray; public override uint Rank { get { return 1u; } set { throw new NotSupportedException(); } } public SZArraySig(TypeSig nextSig) : base(nextSig) { } public override IList GetSizes() { return Array2.Empty(); } public override IList GetLowerBounds() { return Array2.Empty(); } } public abstract class ModifierSig : NonLeafSig { private readonly ITypeDefOrRef modifier; public ITypeDefOrRef Modifier => modifier; protected ModifierSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(nextSig) { this.modifier = modifier; } } public sealed class CModReqdSig : ModifierSig { public override ElementType ElementType => ElementType.CModReqd; public CModReqdSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(modifier, nextSig) { } } public sealed class CModOptSig : ModifierSig { public override ElementType ElementType => ElementType.CModOpt; public CModOptSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(modifier, nextSig) { } } public sealed class PinnedSig : NonLeafSig { public override ElementType ElementType => ElementType.Pinned; public PinnedSig(TypeSig nextSig) : base(nextSig) { } } public sealed class ValueArraySig : NonLeafSig { private uint size; public override ElementType ElementType => ElementType.ValueArray; public uint Size { get { return size; } set { size = value; } } public ValueArraySig(TypeSig nextSig, uint size) : base(nextSig) { this.size = size; } } public sealed class ModuleSig : NonLeafSig { private uint index; public override ElementType ElementType => ElementType.Module; public uint Index { get { return index; } set { index = value; } } public ModuleSig(uint index, TypeSig nextSig) : base(nextSig) { this.index = index; } } public abstract class TypeSpec : ITypeDefOrRef, ICodedToken, IMDTokenProvider, IHasCustomAttribute, IMemberRefParent, IFullName, IType, IOwnerModule, IGenericParameterProvider, IIsTypeOrMethod, IContainsGenericParameter, ITokenOperand, IMemberRef, IHasCustomDebugInformation { protected uint rid; private readonly Lock theLock = Lock.Create(); protected TypeSig typeSig; protected byte[] extraData; protected bool typeSigAndExtraData_isInitialized; protected CustomAttributeCollection customAttributes; protected IList customDebugInfos; public MDToken MDToken => new MDToken(Table.TypeSpec, rid); public uint Rid { get { return rid; } set { rid = value; } } public int TypeDefOrRefTag => 2; public int HasCustomAttributeTag => 13; public int MemberRefParentTag => 4; int IGenericParameterProvider.NumberOfGenericParameters => ((IGenericParameterProvider)TypeSig)?.NumberOfGenericParameters ?? 0; UTF8String IFullName.Name { get { ITypeDefOrRef scopeType = ScopeType; if (scopeType != null) { return scopeType.Name; } return UTF8String.Empty; } set { ITypeDefOrRef scopeType = ScopeType; if (scopeType != null) { scopeType.Name = value; } } } ITypeDefOrRef IMemberRef.DeclaringType { get { TypeSig typeSig = TypeSig.RemovePinnedAndModifiers(); if (typeSig is GenericInstSig genericInstSig) { typeSig = genericInstSig.GenericType; } if (typeSig is TypeDefOrRefSig typeDefOrRefSig) { if (typeDefOrRefSig.IsTypeDef || typeDefOrRefSig.IsTypeRef) { return typeDefOrRefSig.TypeDefOrRef.DeclaringType; } return null; } return null; } } bool IIsTypeOrMethod.IsType => true; bool IIsTypeOrMethod.IsMethod => false; bool IMemberRef.IsField => false; bool IMemberRef.IsTypeSpec => true; bool IMemberRef.IsTypeRef => false; bool IMemberRef.IsTypeDef => false; bool IMemberRef.IsMethodSpec => false; bool IMemberRef.IsMethodDef => false; bool IMemberRef.IsMemberRef => false; bool IMemberRef.IsFieldDef => false; bool IMemberRef.IsPropertyDef => false; bool IMemberRef.IsEventDef => false; bool IMemberRef.IsGenericParam => false; public bool IsValueType => TypeSig?.IsValueType ?? false; public bool IsPrimitive => TypeSig?.IsPrimitive ?? false; public string TypeName => FullNameFactory.Name(this, isReflection: false); public string ReflectionName => FullNameFactory.Name(this, isReflection: true); string IType.Namespace => FullNameFactory.Namespace(this, isReflection: false); public string ReflectionNamespace => FullNameFactory.Namespace(this, isReflection: true); public string FullName => FullNameFactory.FullName(this, isReflection: false); public string ReflectionFullName => FullNameFactory.FullName(this, isReflection: true); public string AssemblyQualifiedName => FullNameFactory.AssemblyQualifiedName(this); public IAssembly DefinitionAssembly => FullNameFactory.DefinitionAssembly(this); public IScope Scope => FullNameFactory.Scope(this); public ITypeDefOrRef ScopeType => FullNameFactory.ScopeType(this); public bool ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this); public ModuleDef Module => FullNameFactory.OwnerModule(this); public TypeSig TypeSig { get { if (!typeSigAndExtraData_isInitialized) { InitializeTypeSigAndExtraData(); } return typeSig; } set { theLock.EnterWriteLock(); try { typeSig = value; if (!typeSigAndExtraData_isInitialized) { GetTypeSigAndExtraData_NoLock(out extraData); } typeSigAndExtraData_isInitialized = true; } finally { theLock.ExitWriteLock(); } } } public byte[] ExtraData { get { if (!typeSigAndExtraData_isInitialized) { InitializeTypeSigAndExtraData(); } return extraData; } set { if (!typeSigAndExtraData_isInitialized) { InitializeTypeSigAndExtraData(); } extraData = value; } } public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) { InitializeCustomAttributes(); } return customAttributes; } } public bool HasCustomAttributes => CustomAttributes.Count > 0; public int HasCustomDebugInformationTag => 13; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos { get { if (customDebugInfos == null) { InitializeCustomDebugInfos(); } return customDebugInfos; } } private void InitializeTypeSigAndExtraData() { theLock.EnterWriteLock(); try { if (!typeSigAndExtraData_isInitialized) { typeSig = GetTypeSigAndExtraData_NoLock(out extraData); typeSigAndExtraData_isInitialized = true; } } finally { theLock.ExitWriteLock(); } } protected virtual TypeSig GetTypeSigAndExtraData_NoLock(out byte[] extraData) { extraData = null; return null; } protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, new List(), null); } public override string ToString() { return FullName; } } public class TypeSpecUser : TypeSpec { public TypeSpecUser() { } public TypeSpecUser(TypeSig typeSig) { base.typeSig = typeSig; extraData = null; typeSigAndExtraData_isInitialized = true; } } internal sealed class TypeSpecMD : TypeSpec, IMDTokenProviderMD, IMDTokenProvider, IContainsGenericParameter2 { private readonly ModuleDefMD readerModule; private readonly uint origRid; private readonly GenericParamContext gpContext; private readonly uint signatureOffset; public uint OrigRid => origRid; bool IContainsGenericParameter2.ContainsGenericParameter => base.ContainsGenericParameter; protected override TypeSig GetTypeSigAndExtraData_NoLock(out byte[] extraData) { TypeSig typeSig = readerModule.ReadTypeSignature(signatureOffset, gpContext, out extraData); if (typeSig != null) { typeSig.Rid = origRid; } return typeSig; } protected override void InitializeCustomAttributes() { RidList list = readerModule.Metadata.GetCustomAttributeRidList(Table.TypeSpec, origRid); CustomAttributeCollection value = new CustomAttributeCollection(list.Count, list, (object obj, int index) => readerModule.ReadCustomAttribute(list[index])); Interlocked.CompareExchange(ref customAttributes, value, null); } protected override void InitializeCustomDebugInfos() { List list = new List(); readerModule.InitializeCustomDebugInfos(new MDToken(base.MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } public TypeSpecMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { origRid = rid; base.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; readerModule.TablesStream.TryReadTypeSpecRow(origRid, out var row); signatureOffset = row.Signature; } } public sealed class UTF8StringEqualityComparer : IEqualityComparer { public static readonly UTF8StringEqualityComparer Instance = new UTF8StringEqualityComparer(); public bool Equals(UTF8String x, UTF8String y) { return UTF8String.Equals(x, y); } public int GetHashCode(UTF8String obj) { return UTF8String.GetHashCode(obj); } } [DebuggerDisplay("{String}")] public sealed class UTF8String : IEquatable, IComparable { public static readonly UTF8String Empty = new UTF8String(string.Empty); private readonly byte[] data; private string asString; public string String { get { if (asString == null) { asString = ConvertFromUTF8(data); } return asString; } } public byte[] Data => data; public int Length => String.Length; public int DataLength { get { if (data != null) { return data.Length; } return 0; } } public static bool IsNull(UTF8String utf8) { if ((object)utf8 != null) { return utf8.data == null; } return true; } public static bool IsNullOrEmpty(UTF8String utf8) { if ((object)utf8 != null && utf8.data != null) { return utf8.data.Length == 0; } return true; } public static implicit operator string(UTF8String s) { return ToSystemString(s); } public static implicit operator UTF8String(string s) { if (s != null) { return new UTF8String(s); } return null; } public static string ToSystemString(UTF8String utf8) { if ((object)utf8 == null || utf8.data == null) { return null; } if (utf8.data.Length == 0) { return string.Empty; } return utf8.String; } public static string ToSystemStringOrEmpty(UTF8String utf8) { return ToSystemString(utf8) ?? string.Empty; } public static int GetHashCode(UTF8String utf8) { if (IsNullOrEmpty(utf8)) { return 0; } return Utils.GetHashCode(utf8.data); } public int CompareTo(UTF8String other) { return CompareTo(this, other); } public static int CompareTo(UTF8String a, UTF8String b) { return Utils.CompareTo(a?.data, b?.data); } public static int CaseInsensitiveCompareTo(UTF8String a, UTF8String b) { if ((object)a == b) { return 0; } string text = ToSystemString(a); string text2 = ToSystemString(b); if ((object)text == text2) { return 0; } if (text == null) { return -1; } if (text2 == null) { return 1; } return StringComparer.OrdinalIgnoreCase.Compare(text, text2); } public static bool CaseInsensitiveEquals(UTF8String a, UTF8String b) { return CaseInsensitiveCompareTo(a, b) == 0; } public static bool operator ==(UTF8String left, UTF8String right) { return CompareTo(left, right) == 0; } public static bool operator ==(UTF8String left, string right) { return ToSystemString(left) == right; } public static bool operator ==(string left, UTF8String right) { return left == ToSystemString(right); } public static bool operator !=(UTF8String left, UTF8String right) { return CompareTo(left, right) != 0; } public static bool operator !=(UTF8String left, string right) { return ToSystemString(left) != right; } public static bool operator !=(string left, UTF8String right) { return left != ToSystemString(right); } public static bool operator >(UTF8String left, UTF8String right) { return CompareTo(left, right) > 0; } public static bool operator <(UTF8String left, UTF8String right) { return CompareTo(left, right) < 0; } public static bool operator >=(UTF8String left, UTF8String right) { return CompareTo(left, right) >= 0; } public static bool operator <=(UTF8String left, UTF8String right) { return CompareTo(left, right) <= 0; } public UTF8String(byte[] data) { this.data = data; } public UTF8String(string s) : this((s == null) ? null : Encoding.UTF8.GetBytes(s)) { } private static string ConvertFromUTF8(byte[] data) { if (data == null) { return null; } try { return Encoding.UTF8.GetString(data); } catch { } return null; } public static bool Equals(UTF8String a, UTF8String b) { return CompareTo(a, b) == 0; } public bool Equals(UTF8String other) { return CompareTo(this, other) == 0; } public override bool Equals(object obj) { if (!(obj is UTF8String b)) { return false; } return CompareTo(this, b) == 0; } public bool Contains(string value) { return String.Contains(value); } public bool EndsWith(string value) { return String.EndsWith(value); } public bool EndsWith(string value, bool ignoreCase, CultureInfo culture) { return String.EndsWith(value, ignoreCase, culture); } public bool EndsWith(string value, StringComparison comparisonType) { return String.EndsWith(value, comparisonType); } public bool StartsWith(string value) { return String.StartsWith(value); } public bool StartsWith(string value, bool ignoreCase, CultureInfo culture) { return String.StartsWith(value, ignoreCase, culture); } public bool StartsWith(string value, StringComparison comparisonType) { return String.StartsWith(value, comparisonType); } public int CompareTo(string strB) { return String.CompareTo(strB); } public int IndexOf(char value) { return String.IndexOf(value); } public int IndexOf(char value, int startIndex) { return String.IndexOf(value, startIndex); } public int IndexOf(char value, int startIndex, int count) { return String.IndexOf(value, startIndex, count); } public int IndexOf(string value) { return String.IndexOf(value); } public int IndexOf(string value, int startIndex) { return String.IndexOf(value, startIndex); } public int IndexOf(string value, int startIndex, int count) { return String.IndexOf(value, startIndex, count); } public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType) { return String.IndexOf(value, startIndex, count, comparisonType); } public int IndexOf(string value, int startIndex, StringComparison comparisonType) { return String.IndexOf(value, startIndex, comparisonType); } public int IndexOf(string value, StringComparison comparisonType) { return String.IndexOf(value, comparisonType); } public int LastIndexOf(char value) { return String.LastIndexOf(value); } public int LastIndexOf(char value, int startIndex) { return String.LastIndexOf(value, startIndex); } public int LastIndexOf(char value, int startIndex, int count) { return String.LastIndexOf(value, startIndex, count); } public int LastIndexOf(string value) { return String.LastIndexOf(value); } public int LastIndexOf(string value, int startIndex) { return String.LastIndexOf(value, startIndex); } public int LastIndexOf(string value, int startIndex, int count) { return String.LastIndexOf(value, startIndex, count); } public int LastIndexOf(string value, int startIndex, int count, StringComparison comparisonType) { return String.LastIndexOf(value, startIndex, count, comparisonType); } public int LastIndexOf(string value, int startIndex, StringComparison comparisonType) { return String.LastIndexOf(value, startIndex, comparisonType); } public int LastIndexOf(string value, StringComparison comparisonType) { return String.LastIndexOf(value, comparisonType); } public UTF8String Insert(int startIndex, string value) { return new UTF8String(String.Insert(startIndex, value)); } public UTF8String Remove(int startIndex) { return new UTF8String(String.Remove(startIndex)); } public UTF8String Remove(int startIndex, int count) { return new UTF8String(String.Remove(startIndex, count)); } public UTF8String Replace(char oldChar, char newChar) { return new UTF8String(String.Replace(oldChar, newChar)); } public UTF8String Replace(string oldValue, string newValue) { return new UTF8String(String.Replace(oldValue, newValue)); } public UTF8String Substring(int startIndex) { return new UTF8String(String.Substring(startIndex)); } public UTF8String Substring(int startIndex, int length) { return new UTF8String(String.Substring(startIndex, length)); } public UTF8String ToLower() { return new UTF8String(String.ToLower()); } public UTF8String ToLower(CultureInfo culture) { return new UTF8String(String.ToLower(culture)); } public UTF8String ToLowerInvariant() { return new UTF8String(String.ToLowerInvariant()); } public UTF8String ToUpper() { return new UTF8String(String.ToUpper()); } public UTF8String ToUpper(CultureInfo culture) { return new UTF8String(String.ToUpper(culture)); } public UTF8String ToUpperInvariant() { return new UTF8String(String.ToUpperInvariant()); } public UTF8String Trim() { return new UTF8String(String.Trim()); } public override int GetHashCode() { return GetHashCode(this); } public override string ToString() { return String; } } internal sealed class ByteArrayEqualityComparer : IEqualityComparer { public static readonly ByteArrayEqualityComparer Instance = new ByteArrayEqualityComparer(); public bool Equals(byte[] x, byte[] y) { return Utils.Equals(x, y); } public int GetHashCode(byte[] obj) { return Utils.GetHashCode(obj); } } internal static class Utils { internal static string ToHex(byte[] bytes, bool upper) { if (bytes == null) { return ""; } char[] array = new char[bytes.Length * 2]; int i = 0; int num = 0; for (; i < bytes.Length; i++) { byte b = bytes[i]; array[num++] = ToHexChar(b >> 4, upper); array[num++] = ToHexChar(b & 0xF, upper); } return new string(array); } private static char ToHexChar(int val, bool upper) { if (0 <= val && val <= 9) { return (char)(val + 48); } return (char)(val - 10 + (upper ? 65 : 97)); } internal static byte[] ParseBytes(string hexString) { try { if (hexString.Length % 2 != 0) { return null; } byte[] array = new byte[hexString.Length / 2]; for (int i = 0; i < hexString.Length; i += 2) { int num = TryParseHexChar(hexString[i]); int num2 = TryParseHexChar(hexString[i + 1]); if (num < 0 || num2 < 0) { return null; } array[i / 2] = (byte)((num << 4) | num2); } return array; } catch { return null; } } private static int TryParseHexChar(char c) { if ('0' <= c && c <= '9') { return c - 48; } if ('a' <= c && c <= 'f') { return 10 + c - 97; } if ('A' <= c && c <= 'F') { return 10 + c - 65; } return -1; } internal static int CompareTo(byte[] a, byte[] b) { if (a == b) { return 0; } if (a == null) { return -1; } if (b == null) { return 1; } int num = Math.Min(a.Length, b.Length); for (int i = 0; i < num; i++) { byte b2 = a[i]; byte b3 = b[i]; if (b2 < b3) { return -1; } if (b2 > b3) { return 1; } } return a.Length.CompareTo(b.Length); } internal static bool Equals(byte[] a, byte[] b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.Length != b.Length) { return false; } for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { return false; } } return true; } internal static int GetHashCode(byte[] a) { if (a == null || a.Length == 0) { return 0; } int num = Math.Min(a.Length / 2, 20); if (num == 0) { num = 1; } uint num2 = 0u; int num3 = 0; int num4 = a.Length - 1; while (num3 < num) { num2 ^= (uint)(a[num3] | (a[num4] << 8)); num2 = (num2 << 13) | (num2 >> 19); num3++; num4--; } return (int)num2; } internal static int CompareTo(Version a, Version b) { if ((object)a == null) { a = new Version(); } if ((object)b == null) { b = new Version(); } if (a.Major != b.Major) { return a.Major.CompareTo(b.Major); } if (a.Minor != b.Minor) { return a.Minor.CompareTo(b.Minor); } if (GetDefaultVersionValue(a.Build) != GetDefaultVersionValue(b.Build)) { return GetDefaultVersionValue(a.Build).CompareTo(GetDefaultVersionValue(b.Build)); } return GetDefaultVersionValue(a.Revision).CompareTo(GetDefaultVersionValue(b.Revision)); } internal static bool Equals(Version a, Version b) { return CompareTo(a, b) == 0; } internal static Version CreateVersionWithNoUndefinedValues(Version a) { if ((object)a == null) { return new Version(0, 0, 0, 0); } return new Version(a.Major, a.Minor, GetDefaultVersionValue(a.Build), GetDefaultVersionValue(a.Revision)); } private static int GetDefaultVersionValue(int val) { if (val != -1) { return val; } return 0; } internal static Version ParseVersion(string versionString) { try { return CreateVersionWithNoUndefinedValues(new Version(versionString)); } catch { return null; } } internal static int LocaleCompareTo(UTF8String a, UTF8String b) { return GetCanonicalLocale(a).CompareTo(GetCanonicalLocale(b)); } internal static bool LocaleEquals(UTF8String a, UTF8String b) { return LocaleCompareTo(a, b) == 0; } internal static int LocaleCompareTo(UTF8String a, string b) { return GetCanonicalLocale(a).CompareTo(GetCanonicalLocale(b)); } internal static bool LocaleEquals(UTF8String a, string b) { return LocaleCompareTo(a, b) == 0; } internal static int GetHashCodeLocale(UTF8String a) { return GetCanonicalLocale(a).GetHashCode(); } private static string GetCanonicalLocale(UTF8String locale) { return GetCanonicalLocale(UTF8String.ToSystemStringOrEmpty(locale)); } private static string GetCanonicalLocale(string locale) { string text = locale.ToUpperInvariant(); if (text == "NEUTRAL") { text = string.Empty; } return text; } public static uint AlignUp(uint v, uint alignment) { return (v + alignment - 1) & ~(alignment - 1); } public static int AlignUp(int v, uint alignment) { return (int)AlignUp((uint)v, alignment); } public static uint RoundToNextPowerOfTwo(uint num) { num--; num |= num >> 1; num |= num >> 2; num |= num >> 4; num |= num >> 8; num |= num >> 16; return num + 1; } } public enum VariantType : uint { Empty = 0u, None = 0u, Null = 1u, I2 = 2u, I4 = 3u, R4 = 4u, R8 = 5u, CY = 6u, Date = 7u, BStr = 8u, Dispatch = 9u, Error = 10u, Bool = 11u, Variant = 12u, Unknown = 13u, Decimal = 14u, I1 = 16u, UI1 = 17u, UI2 = 18u, UI4 = 19u, I8 = 20u, UI8 = 21u, Int = 22u, UInt = 23u, Void = 24u, HResult = 25u, Ptr = 26u, SafeArray = 27u, CArray = 28u, UserDefined = 29u, LPStr = 30u, LPWStr = 31u, Record = 36u, IntPtr = 37u, UIntPtr = 38u, FileTime = 64u, Blob = 65u, Stream = 66u, Storage = 67u, StreamedObject = 68u, StoredObject = 69u, BlobObject = 70u, CF = 71u, CLSID = 72u, VersionedStream = 73u, BStrBlob = 4095u, Vector = 4096u, Array = 8192u, ByRef = 16384u, Reserved = 32768u, Illegal = 65535u, IllegalMasked = 4095u, TypeMask = 4095u, NotInitialized = uint.MaxValue } [DebuggerDisplay("RVA = {RVA}, Count = {VTables.Count}")] public sealed class VTableFixups : IEnumerable, IEnumerable { private RVA rva; private IList vtables; public RVA RVA { get { return rva; } set { rva = value; } } public IList VTables => vtables; public VTableFixups() { vtables = new List(); } public VTableFixups(ModuleDefMD module) { Initialize(module); } private void Initialize(ModuleDefMD module) { ImageDataDirectory vTableFixups = module.Metadata.ImageCor20Header.VTableFixups; if (vTableFixups.VirtualAddress == (RVA)0u || vTableFixups.Size == 0) { vtables = new List(); return; } rva = vTableFixups.VirtualAddress; vtables = new List((int)vTableFixups.Size / 8); IPEImage pEImage = module.Metadata.PEImage; DataReader dataReader = pEImage.CreateReader(); dataReader.Position = (uint)pEImage.ToFileOffset(vTableFixups.VirtualAddress); ulong num = (ulong)dataReader.Position + (ulong)vTableFixups.Size; while ((ulong)((long)dataReader.Position + 8L) <= num && dataReader.CanRead(8u)) { RVA rVA = (RVA)dataReader.ReadUInt32(); int numSlots = dataReader.ReadUInt16(); VTableFlags flags = (VTableFlags)dataReader.ReadUInt16(); VTable vTable = new VTable(rVA, flags, numSlots); vtables.Add(vTable); uint position = dataReader.Position; dataReader.Position = (uint)pEImage.ToFileOffset(rVA); uint num2 = (vTable.Is64Bit ? 8u : 4u); while (numSlots-- > 0 && dataReader.CanRead(num2)) { vTable.Methods.Add(module.ResolveToken(dataReader.ReadUInt32()) as IMethod); if (num2 == 8) { dataReader.ReadUInt32(); } } dataReader.Position = position; } } public IEnumerator GetEnumerator() { return vtables.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum VTableFlags : ushort { Bit32 = 1, Bit64 = 2, FromUnmanaged = 4, FromUnmanagedRetainAppDomain = 8, CallMostDerived = 0x10 } public sealed class VTable : IEnumerable, IEnumerable { private RVA rva; private VTableFlags flags; private readonly IList methods; public RVA RVA { get { return rva; } set { rva = value; } } public VTableFlags Flags { get { return flags; } set { flags = value; } } public bool Is32Bit => (flags & VTableFlags.Bit32) != 0; public bool Is64Bit => (flags & VTableFlags.Bit64) != 0; public IList Methods => methods; public VTable() { methods = new List(); } public VTable(VTableFlags flags) { this.flags = flags; methods = new List(); } public VTable(RVA rva, VTableFlags flags, int numSlots) { this.rva = rva; this.flags = flags; methods = new List(numSlots); } public VTable(RVA rva, VTableFlags flags, IEnumerable methods) { this.rva = rva; this.flags = flags; this.methods = new List(methods); } public IEnumerator GetEnumerator() { return methods.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override string ToString() { if (methods.Count != 0) { return $"{methods.Count} {rva:X8} {methods[0]}"; } return $"{methods.Count} {rva:X8}"; } } internal enum ClrAssembly { Mscorlib, SystemNumericsVectors, SystemObjectModel, SystemRuntime, SystemRuntimeInteropServicesWindowsRuntime, SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntimeUIXaml } public static class WinMDHelpers { private readonly struct ClassName : IEquatable { public readonly UTF8String Namespace; public readonly UTF8String Name; public readonly bool IsValueType; public ClassName(UTF8String ns, UTF8String name, bool isValueType = false) { Namespace = ns; Name = name; IsValueType = isValueType; } public ClassName(string ns, string name, bool isValueType = false) { Namespace = ns; Name = name; IsValueType = isValueType; } public static bool operator ==(ClassName a, ClassName b) { return a.Equals(b); } public static bool operator !=(ClassName a, ClassName b) { return !a.Equals(b); } public bool Equals(ClassName other) { if (UTF8String.Equals(Namespace, other.Namespace)) { return UTF8String.Equals(Name, other.Name); } return false; } public override bool Equals(object obj) { if (!(obj is ClassName)) { return false; } return Equals((ClassName)obj); } public override int GetHashCode() { return UTF8String.GetHashCode(Namespace) ^ UTF8String.GetHashCode(Name); } public override string ToString() { return $"{Namespace}.{Name}"; } } private sealed class ProjectedClass { public readonly ClassName WinMDClass; public readonly ClassName ClrClass; public readonly ClrAssembly ClrAssembly; public readonly ClrAssembly ContractAssembly; public ProjectedClass(string mdns, string mdname, string clrns, string clrname, ClrAssembly clrAsm, ClrAssembly contractAsm, bool winMDValueType, bool clrValueType) { WinMDClass = new ClassName(mdns, mdname, winMDValueType); ClrClass = new ClassName(clrns, clrname, clrValueType); ClrAssembly = clrAsm; ContractAssembly = contractAsm; } public override string ToString() { return $"{WinMDClass} <-> {ClrClass}, {CreateAssembly(null, ContractAssembly)}"; } } private static readonly ProjectedClass[] ProjectedClasses; private static readonly Dictionary winMDToCLR; private static readonly Version contractAsmVersion; private static readonly UTF8String mscorlibName; private static readonly UTF8String clrAsmName_Mscorlib; private static readonly UTF8String clrAsmName_SystemNumericsVectors; private static readonly UTF8String clrAsmName_SystemObjectModel; private static readonly UTF8String clrAsmName_SystemRuntime; private static readonly UTF8String clrAsmName_SystemRuntimeInteropServicesWindowsRuntime; private static readonly UTF8String clrAsmName_SystemRuntimeWindowsRuntime; private static readonly UTF8String clrAsmName_SystemRuntimeWindowsRuntimeUIXaml; private static readonly byte[] contractPublicKeyToken; private static readonly byte[] neutralPublicKey; private static readonly UTF8String CloseName; private static readonly UTF8String DisposeName; private static readonly UTF8String IDisposableNamespace; private static readonly UTF8String IDisposableName; static WinMDHelpers() { ProjectedClasses = new ProjectedClass[50] { new ProjectedClass("Windows.Foundation.Metadata", "AttributeUsageAttribute", "System", "AttributeUsageAttribute", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Metadata", "AttributeTargets", "System", "AttributeTargets", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI", "Color", "Windows.UI", "Color", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "DateTime", "System", "DateTimeOffset", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "EventHandler`1", "System", "EventHandler`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "HResult", "System", "Exception", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: true, clrValueType: false), new ProjectedClass("Windows.Foundation", "IReference`1", "System", "Nullable`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: true), new ProjectedClass("Windows.Foundation", "Point", "Windows.Foundation", "Point", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "Rect", "Windows.Foundation", "Rect", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "Size", "Windows.Foundation", "Size", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "TimeSpan", "System", "TimeSpan", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation", "Uri", "System", "Uri", ClrAssembly.SystemRuntime, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation", "IClosable", "System", "IDisposable", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IIterable`1", "System.Collections.Generic", "IEnumerable`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IVector`1", "System.Collections.Generic", "IList`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IVectorView`1", "System.Collections.Generic", "IReadOnlyList`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IMap`2", "System.Collections.Generic", "IDictionary`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IMapView`2", "System.Collections.Generic", "IReadOnlyDictionary`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.Foundation.Collections", "IKeyValuePair`2", "System.Collections.Generic", "KeyValuePair`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Input", "ICommand", "System.Windows.Input", "ICommand", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "IBindableIterable", "System.Collections", "IEnumerable", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "IBindableVector", "System.Collections", "IList", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "INotifyCollectionChanged", "System.Collections.Specialized", "INotifyCollectionChanged", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedAction", "System.Collections.Specialized", "NotifyCollectionChangedAction", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Data", "INotifyPropertyChanged", "System.ComponentModel", "INotifyPropertyChanged", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Data", "PropertyChangedEventHandler", "System.ComponentModel", "PropertyChangedEventHandler", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Data", "PropertyChangedEventArgs", "System.ComponentModel", "PropertyChangedEventArgs", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, winMDValueType: false, clrValueType: false), new ProjectedClass("Windows.UI.Xaml", "CornerRadius", "Windows.UI.Xaml", "CornerRadius", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml", "Duration", "Windows.UI.Xaml", "Duration", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml", "DurationType", "Windows.UI.Xaml", "DurationType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml", "GridLength", "Windows.UI.Xaml", "GridLength", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml", "GridUnitType", "Windows.UI.Xaml", "GridUnitType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml", "Thickness", "Windows.UI.Xaml", "Thickness", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Interop", "TypeName", "System", "Type", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, winMDValueType: true, clrValueType: false), new ProjectedClass("Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Media", "Matrix", "Windows.UI.Xaml.Media", "Matrix", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "KeyTime", "Windows.UI.Xaml.Media.Animation", "KeyTime", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.UI.Xaml.Media.Media3D", "Matrix3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Vector2", "System.Numerics", "Vector2", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Vector3", "System.Numerics", "Vector3", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Vector4", "System.Numerics", "Vector4", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Matrix3x2", "System.Numerics", "Matrix3x2", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Matrix4x4", "System.Numerics", "Matrix4x4", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Plane", "System.Numerics", "Plane", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true), new ProjectedClass("Windows.Foundation.Numerics", "Quaternion", "System.Numerics", "Quaternion", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, winMDValueType: true, clrValueType: true) }; winMDToCLR = new Dictionary(); contractAsmVersion = new Version(4, 0, 0, 0); mscorlibName = new UTF8String("mscorlib"); clrAsmName_Mscorlib = new UTF8String("mscorlib"); clrAsmName_SystemNumericsVectors = new UTF8String("System.Numerics.Vectors"); clrAsmName_SystemObjectModel = new UTF8String("System.ObjectModel"); clrAsmName_SystemRuntime = new UTF8String("System.Runtime"); clrAsmName_SystemRuntimeInteropServicesWindowsRuntime = new UTF8String("System.Runtime.InteropServices.WindowsRuntime"); clrAsmName_SystemRuntimeWindowsRuntime = new UTF8String("System.Runtime.WindowsRuntime"); clrAsmName_SystemRuntimeWindowsRuntimeUIXaml = new UTF8String("System.Runtime.WindowsRuntime.UI.Xaml"); contractPublicKeyToken = new byte[8] { 176, 63, 95, 127, 17, 213, 10, 58 }; neutralPublicKey = new byte[8] { 183, 122, 92, 86, 25, 52, 224, 137 }; CloseName = new UTF8String("Close"); DisposeName = new UTF8String("Dispose"); IDisposableNamespace = new UTF8String("System"); IDisposableName = new UTF8String("IDisposable"); ProjectedClass[] projectedClasses = ProjectedClasses; foreach (ProjectedClass projectedClass in projectedClasses) { winMDToCLR.Add(projectedClass.WinMDClass, projectedClass); } } private static AssemblyRef ToCLR(ModuleDef module, ref UTF8String ns, ref UTF8String name) { if (!winMDToCLR.TryGetValue(new ClassName(ns, name), out var value)) { return null; } ns = value.ClrClass.Namespace; name = value.ClrClass.Name; return CreateAssembly(module, value.ContractAssembly); } private static AssemblyRef CreateAssembly(ModuleDef module, ClrAssembly clrAsm) { AssemblyRef assemblyRef = module?.CorLibTypes.AssemblyRef; AssemblyRefUser assemblyRefUser = new AssemblyRefUser(GetName(clrAsm), contractAsmVersion, new PublicKeyToken(GetPublicKeyToken(clrAsm)), UTF8String.Empty); if (assemblyRef != null && assemblyRef.Name == mscorlibName && IsValidMscorlibVersion(assemblyRef.Version)) { assemblyRefUser.Version = assemblyRef.Version; } if (module is ModuleDefMD moduleDefMD) { Version version = null; foreach (AssemblyRef assemblyRef2 in moduleDefMD.GetAssemblyRefs()) { if (!assemblyRef2.IsContentTypeWindowsRuntime && !(assemblyRef2.Name != assemblyRefUser.Name) && !(assemblyRef2.Culture != assemblyRefUser.Culture) && PublicKeyBase.TokenEquals(assemblyRef2.PublicKeyOrToken, assemblyRefUser.PublicKeyOrToken) && IsValidMscorlibVersion(assemblyRef2.Version) && ((object)version == null || assemblyRef2.Version > version)) { version = assemblyRef2.Version; } } if ((object)version != null) { assemblyRefUser.Version = version; } } return assemblyRefUser; } private static bool IsValidMscorlibVersion(Version version) { if ((object)version != null) { return (uint)version.Major <= 5u; } return false; } private static UTF8String GetName(ClrAssembly clrAsm) { return clrAsm switch { ClrAssembly.Mscorlib => clrAsmName_Mscorlib, ClrAssembly.SystemNumericsVectors => clrAsmName_SystemNumericsVectors, ClrAssembly.SystemObjectModel => clrAsmName_SystemObjectModel, ClrAssembly.SystemRuntime => clrAsmName_SystemRuntime, ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime => clrAsmName_SystemRuntimeInteropServicesWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime => clrAsmName_SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml => clrAsmName_SystemRuntimeWindowsRuntimeUIXaml, _ => throw new InvalidOperationException(), }; } private static byte[] GetPublicKeyToken(ClrAssembly clrAsm) { return clrAsm switch { ClrAssembly.Mscorlib => neutralPublicKey, ClrAssembly.SystemNumericsVectors => contractPublicKeyToken, ClrAssembly.SystemObjectModel => contractPublicKeyToken, ClrAssembly.SystemRuntime => contractPublicKeyToken, ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime => contractPublicKeyToken, ClrAssembly.SystemRuntimeWindowsRuntime => neutralPublicKey, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml => neutralPublicKey, _ => throw new InvalidOperationException(), }; } public static TypeRef ToCLR(ModuleDef module, TypeDef td) { bool isClrValueType; return ToCLR(module, td, out isClrValueType); } public static TypeRef ToCLR(ModuleDef module, TypeDef td, out bool isClrValueType) { isClrValueType = false; if (td == null || !td.IsWindowsRuntime) { return null; } IAssembly definitionAssembly = td.DefinitionAssembly; if (definitionAssembly == null || !definitionAssembly.IsContentTypeWindowsRuntime) { return null; } if (!winMDToCLR.TryGetValue(new ClassName(td.Namespace, td.Name), out var value)) { return null; } isClrValueType = value.ClrClass.IsValueType; return new TypeRefUser(module, value.ClrClass.Namespace, value.ClrClass.Name, CreateAssembly(module, value.ContractAssembly)); } public static TypeRef ToCLR(ModuleDef module, TypeRef tr) { bool isClrValueType; return ToCLR(module, tr, out isClrValueType); } public static TypeRef ToCLR(ModuleDef module, TypeRef tr, out bool isClrValueType) { isClrValueType = false; if (tr == null) { return null; } IAssembly definitionAssembly = tr.DefinitionAssembly; if (definitionAssembly == null || !definitionAssembly.IsContentTypeWindowsRuntime) { return null; } if (tr.DeclaringType != null) { return null; } if (!winMDToCLR.TryGetValue(new ClassName(tr.Namespace, tr.Name), out var value)) { return null; } isClrValueType = value.ClrClass.IsValueType; return new TypeRefUser(module, value.ClrClass.Namespace, value.ClrClass.Name, CreateAssembly(module, value.ContractAssembly)); } public static ExportedType ToCLR(ModuleDef module, ExportedType et) { if (et == null) { return null; } IAssembly definitionAssembly = et.DefinitionAssembly; if (definitionAssembly == null || !definitionAssembly.IsContentTypeWindowsRuntime) { return null; } if (et.DeclaringType != null) { return null; } if (!winMDToCLR.TryGetValue(new ClassName(et.TypeNamespace, et.TypeName), out var value)) { return null; } return new ExportedTypeUser(module, 0u, value.ClrClass.Namespace, value.ClrClass.Name, et.Attributes, CreateAssembly(module, value.ContractAssembly)); } public static TypeSig ToCLR(ModuleDef module, TypeSig ts) { if (ts == null) { return null; } ElementType elementType = ts.ElementType; if (elementType != ElementType.Class && elementType != ElementType.ValueType) { return null; } ITypeDefOrRef typeDefOrRef = ((ClassOrValueTypeSig)ts).TypeDefOrRef; TypeRef typeRef; bool isClrValueType; if (typeDefOrRef is TypeDef td) { typeRef = ToCLR(module, td, out isClrValueType); if (typeRef == null) { return null; } } else { if (!(typeDefOrRef is TypeRef tr)) { return null; } typeRef = ToCLR(module, tr, out isClrValueType); if (typeRef == null) { return null; } } if (!isClrValueType) { return new ClassSig(typeRef); } return new ValueTypeSig(typeRef); } public static MemberRef ToCLR(ModuleDef module, MemberRef mr) { if (mr == null) { return null; } if (mr.Name != CloseName) { return null; } MethodSig methodSig = mr.MethodSig; if (methodSig == null) { return null; } IMemberRefParent memberRefParent = mr.Class; IMemberRefParent memberRefParent2; if (memberRefParent is TypeRef tr) { TypeRef typeRef = ToCLR(module, tr); if (typeRef == null || !IsIDisposable(typeRef)) { return null; } memberRefParent2 = typeRef; } else { if (!(memberRefParent is TypeSpec typeSpec)) { return null; } if (!(typeSpec.TypeSig is GenericInstSig genericInstSig) || !(genericInstSig.GenericType is ClassSig)) { return null; } TypeRef typeRef2 = genericInstSig.GenericType.TypeRef; if (typeRef2 == null) { return null; } bool isClrValueType; TypeRef typeRef3 = ToCLR(module, typeRef2, out isClrValueType); if (typeRef3 == null || !IsIDisposable(typeRef3)) { return null; } memberRefParent2 = new TypeSpecUser(new GenericInstSig(isClrValueType ? ((ClassOrValueTypeSig)new ValueTypeSig(typeRef3)) : ((ClassOrValueTypeSig)new ClassSig(typeRef3)), genericInstSig.GenericArguments)); } return new MemberRefUser(mr.Module, DisposeName, methodSig, memberRefParent2); } private static bool IsIDisposable(TypeRef tr) { if (tr.Name == IDisposableName) { return tr.Namespace == IDisposableNamespace; } return false; } public static MemberRef ToCLR(ModuleDef module, MethodDef md) { if (md == null) { return null; } if (md.Name != CloseName) { return null; } TypeDef declaringType = md.DeclaringType; if (declaringType == null) { return null; } TypeRef typeRef = ToCLR(module, declaringType); if (typeRef == null || !IsIDisposable(typeRef)) { return null; } return new MemberRefUser(md.Module, DisposeName, md.MethodSig, typeRef); } } public enum WinMDStatus { None, Pure, Managed } } namespace dnlib.DotNet.Writer { public struct ArrayWriter { private readonly byte[] data; private int position; public int Position { get { return position; } set { position = value; } } public ArrayWriter(byte[] data) { this.data = data; position = 0; } public void WriteSByte(sbyte value) { data[position++] = (byte)value; } public void WriteByte(byte value) { data[position++] = value; } public void WriteInt16(short value) { data[position++] = (byte)value; data[position++] = (byte)(value >> 8); } public void WriteUInt16(ushort value) { data[position++] = (byte)value; data[position++] = (byte)(value >> 8); } public unsafe void WriteInt32(int value) { int num = position; fixed (byte* ptr = data) { *(int*)(ptr + num) = value; } position = num + 4; } public unsafe void WriteUInt32(uint value) { int num = position; fixed (byte* ptr = data) { *(uint*)(ptr + num) = value; } position = num + 4; } public unsafe void WriteInt64(long value) { int num = position; fixed (byte* ptr = data) { *(long*)(ptr + num) = value; } position = num + 8; } public unsafe void WriteUInt64(ulong value) { int num = position; fixed (byte* ptr = data) { *(ulong*)(ptr + num) = value; } position = num + 8; } public unsafe void WriteSingle(float value) { int num = position; fixed (byte* ptr = data) { *(float*)(ptr + num) = value; } position = num + 4; } public unsafe void WriteDouble(double value) { int num = position; fixed (byte* ptr = data) { *(double*)(ptr + num) = value; } position = num + 8; } public void WriteBytes(byte[] source) { WriteBytes(source, 0, source.Length); } public void WriteBytes(byte[] source, int index, int length) { Array.Copy(source, index, data, position, length); position += length; } } public sealed class BlobHeap : HeapBase, IOffsetHeap { private readonly Dictionary cachedDict = new Dictionary(ByteArrayEqualityComparer.Instance); private readonly List cached = new List(); private uint nextOffset = 1u; private byte[] originalData; private Dictionary userRawData; public override string Name => "#Blob"; public void Populate(BlobStream blobStream) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); } if (originalData != null) { throw new InvalidOperationException("Can't call method twice"); } if (nextOffset != 1) { throw new InvalidOperationException("Add() has already been called"); } if (blobStream != null && blobStream.StreamLength != 0) { DataReader reader = blobStream.CreateReader(); originalData = reader.ToArray(); nextOffset = (uint)originalData.Length; Populate(ref reader); } } private void Populate(ref DataReader reader) { reader.Position = 1u; while (reader.Position < reader.Length) { uint position = reader.Position; if (!reader.TryReadCompressedUInt32(out var value)) { if (position == reader.Position) { reader.Position++; } } else if (value != 0 && (ulong)((long)reader.Position + (long)value) <= (ulong)reader.Length) { byte[] key = reader.ReadBytes((int)value); if (!cachedDict.ContainsKey(key)) { cachedDict[key] = position; } } } } public uint Add(byte[] data) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); } if (data == null || data.Length == 0) { return 0u; } if (cachedDict.TryGetValue(data, out var value)) { return value; } return AddToCache(data); } public uint Create(byte[] data) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); } return AddToCache(data ?? Array2.Empty()); } private uint AddToCache(byte[] data) { cached.Add(data); uint result = (cachedDict[data] = nextOffset); nextOffset += (uint)GetRawDataSize(data); return result; } public override uint GetRawLength() { return nextOffset; } protected override void WriteToImpl(DataWriter writer) { if (originalData != null) { writer.WriteBytes(originalData); } else { writer.WriteByte(0); } uint num = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (byte[] item in cached) { int rawDataSize = GetRawDataSize(item); if (userRawData != null && userRawData.TryGetValue(num, out var value)) { if (value.Length != rawDataSize) { throw new InvalidOperationException("Invalid length of raw data"); } writer.WriteBytes(value); } else { writer.WriteCompressedUInt32((uint)item.Length); writer.WriteBytes(item); } num += (uint)rawDataSize; } } public int GetRawDataSize(byte[] data) { return DataWriter.GetCompressedUInt32Length((uint)data.Length) + data.Length; } public void SetRawData(uint offset, byte[] rawData) { if (userRawData == null) { userRawData = new Dictionary(); } userRawData[offset] = rawData ?? throw new ArgumentNullException("rawData"); } public IEnumerable> GetAllRawData() { MemoryStream memStream = new MemoryStream(); DataWriter writer = new DataWriter(memStream); uint offset = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (byte[] item in cached) { memStream.Position = 0L; memStream.SetLength(0L); writer.WriteCompressedUInt32((uint)item.Length); writer.WriteBytes(item); yield return new KeyValuePair(offset, memStream.ToArray()); offset += (uint)(int)memStream.Length; } } } public sealed class ByteArrayChunk : IReuseChunk, IChunk { private readonly byte[] array; private readonly uint alignment; private FileOffset offset; private RVA rva; public FileOffset FileOffset => offset; public RVA RVA => rva; public byte[] Data => array; public ByteArrayChunk(byte[] array, uint alignment = 0u) { this.array = array ?? Array2.Empty(); this.alignment = alignment; } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { return (uint)array.Length <= origSize; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return (uint)array.Length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return alignment; } public void WriteTo(DataWriter writer) { writer.WriteBytes(array); } public override int GetHashCode() { return Utils.GetHashCode(array); } public override bool Equals(object obj) { if (obj is ByteArrayChunk byteArrayChunk) { return Utils.Equals(array, byteArrayChunk.array); } return false; } } public enum ChecksumAlgorithm { SHA1, SHA256, SHA384, SHA512 } public class ChunkList : ChunkListBase where T : class, IChunk { public ChunkList() { chunks = new List(); } public void Add(T chunk, uint alignment) { if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } if (chunk != null) { chunks.Add(new Elem(chunk, alignment)); } } public uint? Remove(T chunk) { if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } if (chunk != null) { List list = chunks; for (int i = 0; i < list.Count; i++) { if (list[i].chunk == chunk) { uint alignment = list[i].alignment; list.RemoveAt(i); return alignment; } } } return null; } } public abstract class ChunkListBase : IChunk where T : IChunk { protected readonly struct Elem { public readonly T chunk; public readonly uint alignment; public Elem(T chunk, uint alignment) { this.chunk = chunk; this.alignment = alignment; } } protected sealed class ElemEqualityComparer : IEqualityComparer { private IEqualityComparer chunkComparer; public ElemEqualityComparer(IEqualityComparer chunkComparer) { this.chunkComparer = chunkComparer; } public bool Equals(Elem x, Elem y) { if (x.alignment == y.alignment) { return chunkComparer.Equals(x.chunk, y.chunk); } return false; } public int GetHashCode(Elem obj) { return (int)obj.alignment + chunkComparer.GetHashCode(obj.chunk); } } protected List chunks; private uint length; private uint virtualSize; protected bool setOffsetCalled; private FileOffset offset; private RVA rva; internal bool IsEmpty => chunks.Count == 0; public FileOffset FileOffset => offset; public RVA RVA => rva; public virtual void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; length = 0u; virtualSize = 0u; foreach (Elem chunk in chunks) { uint num = offset.AlignUp(chunk.alignment) - offset; uint num2 = rva.AlignUp(chunk.alignment) - rva; offset += num; rva += num2; chunk.chunk.SetOffset(offset, rva); if (chunk.chunk.GetVirtualSize() == 0) { offset -= num; rva -= num2; continue; } uint fileLength = chunk.chunk.GetFileLength(); uint num3 = chunk.chunk.GetVirtualSize(); offset += fileLength; rva += num3; length += num + fileLength; virtualSize += num2 + num3; } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return virtualSize; } public void WriteTo(DataWriter writer) { FileOffset fileOffset = offset; foreach (Elem chunk in chunks) { if (chunk.chunk.GetVirtualSize() != 0) { int num = (int)(fileOffset.AlignUp(chunk.alignment) - fileOffset); writer.WriteZeroes(num); chunk.chunk.VerifyWriteTo(writer); fileOffset = (FileOffset)((uint)fileOffset + (uint)(num + (int)chunk.chunk.GetFileLength())); } } } public virtual uint CalculateAlignment() { uint num = 0u; for (int i = 0; i < chunks.Count; i++) { Elem elem = chunks[i]; uint num2 = Math.Max(elem.alignment, elem.chunk.CalculateAlignment()); chunks[i] = new Elem(elem.chunk, num2); num = Math.Max(num, num2); } return num; } } public interface ICustomAttributeWriterHelper : IWriterError, IFullNameFactoryHelper { } public struct CustomAttributeWriter : IDisposable { private readonly ICustomAttributeWriterHelper helper; private RecursionCounter recursionCounter; private readonly StringBuilder sb; private readonly MemoryStream outStream; private readonly DataWriter writer; private readonly bool disposeStream; private GenericArguments genericArguments; public static byte[] Write(ICustomAttributeWriterHelper helper, CustomAttribute ca) { using CustomAttributeWriter customAttributeWriter = new CustomAttributeWriter(helper); customAttributeWriter.Write(ca); return customAttributeWriter.GetResult(); } internal static byte[] Write(ICustomAttributeWriterHelper helper, CustomAttribute ca, DataWriterContext context) { using CustomAttributeWriter customAttributeWriter = new CustomAttributeWriter(helper, context); customAttributeWriter.Write(ca); return customAttributeWriter.GetResult(); } internal static byte[] Write(ICustomAttributeWriterHelper helper, IList namedArgs) { using CustomAttributeWriter customAttributeWriter = new CustomAttributeWriter(helper); customAttributeWriter.Write(namedArgs); return customAttributeWriter.GetResult(); } internal static byte[] Write(ICustomAttributeWriterHelper helper, IList namedArgs, DataWriterContext context) { using CustomAttributeWriter customAttributeWriter = new CustomAttributeWriter(helper, context); customAttributeWriter.Write(namedArgs); return customAttributeWriter.GetResult(); } private CustomAttributeWriter(ICustomAttributeWriterHelper helper) { this.helper = helper; recursionCounter = default(RecursionCounter); sb = new StringBuilder(); outStream = new MemoryStream(); writer = new DataWriter(outStream); genericArguments = null; disposeStream = true; } private CustomAttributeWriter(ICustomAttributeWriterHelper helper, DataWriterContext context) { this.helper = helper; recursionCounter = default(RecursionCounter); sb = new StringBuilder(); outStream = context.OutStream; writer = context.Writer; genericArguments = null; disposeStream = false; outStream.SetLength(0L); outStream.Position = 0L; } private byte[] GetResult() { return outStream.ToArray(); } private void Write(CustomAttribute ca) { if (ca == null) { helper.Error("The custom attribute is null"); return; } if (ca.IsRawBlob) { if ((ca.ConstructorArguments != null && ca.ConstructorArguments.Count > 0) || (ca.NamedArguments != null && ca.NamedArguments.Count > 0)) { helper.Error("Raw custom attribute contains arguments and/or named arguments"); } writer.WriteBytes(ca.RawData); return; } if (ca.Constructor == null) { helper.Error("Custom attribute ctor is null"); return; } MethodSig methodSig = GetMethodSig(ca.Constructor); if (methodSig == null) { helper.Error("Custom attribute ctor's method signature is invalid"); return; } if (ca.ConstructorArguments.Count != methodSig.Params.Count) { helper.Error("Custom attribute arguments count != method sig arguments count"); } if (methodSig.ParamsAfterSentinel != null && methodSig.ParamsAfterSentinel.Count > 0) { helper.Error("Custom attribute ctor has parameters after the sentinel"); } if (ca.NamedArguments.Count > 65535) { helper.Error("Custom attribute has too many named arguments"); } if (ca.Constructor is MemberRef { Class: TypeSpec { TypeSig: GenericInstSig typeSig } }) { genericArguments = new GenericArguments(); genericArguments.PushTypeArgs(typeSig.GenericArguments); } writer.WriteUInt16(1); int num = Math.Min(methodSig.Params.Count, ca.ConstructorArguments.Count); for (int i = 0; i < num; i++) { WriteValue(FixTypeSig(methodSig.Params[i]), ca.ConstructorArguments[i]); } int num2 = Math.Min(65535, ca.NamedArguments.Count); writer.WriteUInt16((ushort)num2); for (int j = 0; j < num2; j++) { Write(ca.NamedArguments[j]); } } private void Write(IList namedArgs) { if (namedArgs == null || namedArgs.Count > 536870911) { helper.Error("Too many custom attribute named arguments"); namedArgs = Array2.Empty(); } writer.WriteCompressedUInt32((uint)namedArgs.Count); for (int i = 0; i < namedArgs.Count; i++) { Write(namedArgs[i]); } } private TypeSig FixTypeSig(TypeSig type) { return SubstituteGenericParameter(type.RemoveModifiers()).RemoveModifiers(); } private TypeSig SubstituteGenericParameter(TypeSig type) { if (genericArguments == null) { return type; } return genericArguments.Resolve(type); } private void WriteValue(TypeSig argType, CAArgument value) { if (argType == null || value.Type == null) { helper.Error("Custom attribute argument type is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } if (argType is SZArraySig arrayType) { IList list = value.Value as IList; if (list == null && value.Value != null) { helper.Error("CAArgument.Value is not null or an array"); } WriteArrayValue(arrayType, list); } else { WriteElem(argType, value); } recursionCounter.Decrement(); } private void WriteArrayValue(SZArraySig arrayType, IList args) { if (arrayType == null) { helper.Error("Custom attribute: Array type is null"); return; } if (args == null) { writer.WriteUInt32(uint.MaxValue); return; } writer.WriteUInt32((uint)args.Count); TypeSig argType = FixTypeSig(arrayType.Next); for (int i = 0; i < args.Count; i++) { WriteValue(argType, args[i]); } } private bool VerifyTypeAndValue(CAArgument value, ElementType etype) { if (!VerifyType(value.Type, etype)) { helper.Error("Custom attribute arg type != value.Type"); return false; } if (!VerifyValue(value.Value, etype)) { helper.Error("Custom attribute value.Value's type != value.Type"); return false; } return true; } private bool VerifyTypeAndValue(CAArgument value, ElementType etype, Type valueType) { if (!VerifyType(value.Type, etype)) { helper.Error("Custom attribute arg type != value.Type"); return false; } if (value.Value != null) { return value.Value.GetType() == valueType; } return true; } private static bool VerifyType(TypeSig type, ElementType etype) { type = type.RemoveModifiers(); if (type != null) { if (etype != type.ElementType) { return type.ElementType == ElementType.ValueType; } return true; } return false; } private static bool VerifyValue(object o, ElementType etype) { if (o == null) { return false; } return Type.GetTypeCode(o.GetType()) switch { TypeCode.Boolean => etype == ElementType.Boolean, TypeCode.Char => etype == ElementType.Char, TypeCode.SByte => etype == ElementType.I1, TypeCode.Byte => etype == ElementType.U1, TypeCode.Int16 => etype == ElementType.I2, TypeCode.UInt16 => etype == ElementType.U2, TypeCode.Int32 => etype == ElementType.I4, TypeCode.UInt32 => etype == ElementType.U4, TypeCode.Int64 => etype == ElementType.I8, TypeCode.UInt64 => etype == ElementType.U8, TypeCode.Single => etype == ElementType.R4, TypeCode.Double => etype == ElementType.R8, _ => false, }; } private static ulong ToUInt64(object o) { ToUInt64(o, out var result); return result; } private static bool ToUInt64(object o, out ulong result) { if (o == null) { result = 0uL; return false; } switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: result = (ulong)(((bool)o) ? 1 : 0); return true; case TypeCode.Char: result = (char)o; return true; case TypeCode.SByte: result = (ulong)(sbyte)o; return true; case TypeCode.Byte: result = (byte)o; return true; case TypeCode.Int16: result = (ulong)(short)o; return true; case TypeCode.UInt16: result = (ushort)o; return true; case TypeCode.Int32: result = (ulong)(int)o; return true; case TypeCode.UInt32: result = (uint)o; return true; case TypeCode.Int64: result = (ulong)(long)o; return true; case TypeCode.UInt64: result = (ulong)o; return true; case TypeCode.Single: result = (ulong)(float)o; return true; case TypeCode.Double: result = (ulong)(double)o; return true; default: result = 0uL; return false; } } private static double ToDouble(object o) { ToDouble(o, out var result); return result; } private static bool ToDouble(object o, out double result) { if (o == null) { result = double.NaN; return false; } switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: result = (((bool)o) ? 1 : 0); return true; case TypeCode.Char: result = (int)(char)o; return true; case TypeCode.SByte: result = (sbyte)o; return true; case TypeCode.Byte: result = (int)(byte)o; return true; case TypeCode.Int16: result = (short)o; return true; case TypeCode.UInt16: result = (int)(ushort)o; return true; case TypeCode.Int32: result = (int)o; return true; case TypeCode.UInt32: result = (uint)o; return true; case TypeCode.Int64: result = (long)o; return true; case TypeCode.UInt64: result = (ulong)o; return true; case TypeCode.Single: result = (float)o; return true; case TypeCode.Double: result = (double)o; return true; default: result = double.NaN; return false; } } private void WriteElem(TypeSig argType, CAArgument value) { if (argType == null) { helper.Error("Custom attribute: Arg type is null"); argType = value.Type; if (argType == null) { return; } } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } switch (argType.ElementType) { case ElementType.Boolean: if (!VerifyTypeAndValue(value, ElementType.Boolean)) { writer.WriteBoolean(ToUInt64(value.Value) != 0); } else { writer.WriteBoolean((bool)value.Value); } break; case ElementType.Char: if (!VerifyTypeAndValue(value, ElementType.Char)) { writer.WriteUInt16((ushort)ToUInt64(value.Value)); } else { writer.WriteUInt16((char)value.Value); } break; case ElementType.I1: if (!VerifyTypeAndValue(value, ElementType.I1)) { writer.WriteSByte((sbyte)ToUInt64(value.Value)); } else { writer.WriteSByte((sbyte)value.Value); } break; case ElementType.U1: if (!VerifyTypeAndValue(value, ElementType.U1)) { writer.WriteByte((byte)ToUInt64(value.Value)); } else { writer.WriteByte((byte)value.Value); } break; case ElementType.I2: if (!VerifyTypeAndValue(value, ElementType.I2)) { writer.WriteInt16((short)ToUInt64(value.Value)); } else { writer.WriteInt16((short)value.Value); } break; case ElementType.U2: if (!VerifyTypeAndValue(value, ElementType.U2)) { writer.WriteUInt16((ushort)ToUInt64(value.Value)); } else { writer.WriteUInt16((ushort)value.Value); } break; case ElementType.I4: if (!VerifyTypeAndValue(value, ElementType.I4)) { writer.WriteInt32((int)ToUInt64(value.Value)); } else { writer.WriteInt32((int)value.Value); } break; case ElementType.U4: if (!VerifyTypeAndValue(value, ElementType.U4)) { writer.WriteUInt32((uint)ToUInt64(value.Value)); } else { writer.WriteUInt32((uint)value.Value); } break; case ElementType.I8: if (!VerifyTypeAndValue(value, ElementType.I8)) { writer.WriteInt64((long)ToUInt64(value.Value)); } else { writer.WriteInt64((long)value.Value); } break; case ElementType.U8: if (!VerifyTypeAndValue(value, ElementType.U8)) { writer.WriteUInt64(ToUInt64(value.Value)); } else { writer.WriteUInt64((ulong)value.Value); } break; case ElementType.R4: if (!VerifyTypeAndValue(value, ElementType.R4)) { writer.WriteSingle((float)ToDouble(value.Value)); } else { writer.WriteSingle((float)value.Value); } break; case ElementType.R8: if (!VerifyTypeAndValue(value, ElementType.R8)) { writer.WriteDouble(ToDouble(value.Value)); } else { writer.WriteDouble((double)value.Value); } break; case ElementType.String: if (VerifyTypeAndValue(value, ElementType.String, typeof(UTF8String))) { WriteUTF8String((UTF8String)value.Value); } else if (VerifyTypeAndValue(value, ElementType.String, typeof(string))) { WriteUTF8String((string)value.Value); } else { WriteUTF8String(UTF8String.Empty); } break; case ElementType.ValueType: { ITypeDefOrRef typeDefOrRef = ((TypeDefOrRefSig)argType).TypeDefOrRef; TypeSig enumUnderlyingType = GetEnumUnderlyingType(argType); if (enumUnderlyingType != null) { WriteElem(enumUnderlyingType, value); } else if (!(typeDefOrRef is TypeRef) || !TryWriteEnumUnderlyingTypeValue(value.Value)) { helper.Error("Custom attribute value is not an enum"); } break; } case ElementType.Class: { ITypeDefOrRef typeDefOrRef = ((TypeDefOrRefSig)argType).TypeDefOrRef; if (CheckCorLibType(argType, "Type")) { if (CheckCorLibType(value.Type, "Type")) { if (value.Value is TypeSig type) { WriteType(type); break; } if (value.Value == null) { WriteUTF8String(null); break; } helper.Error("Custom attribute value is not a type"); WriteUTF8String(UTF8String.Empty); } else { helper.Error("Custom attribute value type is not System.Type"); WriteUTF8String(UTF8String.Empty); } break; } if (typeDefOrRef is TypeRef && TryWriteEnumUnderlyingTypeValue(value.Value)) { break; } goto default; } case ElementType.SZArray: WriteValue(argType, value); break; case ElementType.Object: WriteFieldOrPropType(value.Type); WriteElem(value.Type, value); break; default: helper.Error("Invalid or unsupported element type in custom attribute"); break; } recursionCounter.Decrement(); } private bool TryWriteEnumUnderlyingTypeValue(object o) { if (o == null) { return false; } switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: writer.WriteBoolean((bool)o); break; case TypeCode.Char: writer.WriteUInt16((char)o); break; case TypeCode.SByte: writer.WriteSByte((sbyte)o); break; case TypeCode.Byte: writer.WriteByte((byte)o); break; case TypeCode.Int16: writer.WriteInt16((short)o); break; case TypeCode.UInt16: writer.WriteUInt16((ushort)o); break; case TypeCode.Int32: writer.WriteInt32((int)o); break; case TypeCode.UInt32: writer.WriteUInt32((uint)o); break; case TypeCode.Int64: writer.WriteInt64((long)o); break; case TypeCode.UInt64: writer.WriteUInt64((ulong)o); break; default: return false; } return true; } private static TypeSig GetEnumUnderlyingType(TypeSig type) { return GetEnumTypeDef(type)?.GetEnumUnderlyingType().RemoveModifiers(); } private static TypeDef GetEnumTypeDef(TypeSig type) { if (type == null) { return null; } TypeDef typeDef = GetTypeDef(type); if (typeDef == null) { return null; } if (!typeDef.IsEnum) { return null; } return typeDef; } private static TypeDef GetTypeDef(TypeSig type) { if (type is TypeDefOrRefSig { TypeDef: var typeDef } typeDefOrRefSig) { if (typeDef != null) { return typeDef; } TypeRef typeRef = typeDefOrRefSig.TypeRef; if (typeRef != null) { return typeRef.Resolve(); } } return null; } private void Write(CANamedArgument namedArg) { if (namedArg == null) { helper.Error("Custom attribute named arg is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } if (namedArg.IsProperty) { writer.WriteByte(84); } else { writer.WriteByte(83); } WriteFieldOrPropType(namedArg.Type); WriteUTF8String(namedArg.Name); WriteValue(namedArg.Type, namedArg.Argument); recursionCounter.Decrement(); } private void WriteFieldOrPropType(TypeSig type) { type = type.RemoveModifiers(); if (type == null) { helper.Error("Custom attribute: Field/property type is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } switch (type.ElementType) { case ElementType.Boolean: writer.WriteByte(2); break; case ElementType.Char: writer.WriteByte(3); break; case ElementType.I1: writer.WriteByte(4); break; case ElementType.U1: writer.WriteByte(5); break; case ElementType.I2: writer.WriteByte(6); break; case ElementType.U2: writer.WriteByte(7); break; case ElementType.I4: writer.WriteByte(8); break; case ElementType.U4: writer.WriteByte(9); break; case ElementType.I8: writer.WriteByte(10); break; case ElementType.U8: writer.WriteByte(11); break; case ElementType.R4: writer.WriteByte(12); break; case ElementType.R8: writer.WriteByte(13); break; case ElementType.String: writer.WriteByte(14); break; case ElementType.Object: writer.WriteByte(81); break; case ElementType.SZArray: writer.WriteByte(29); WriteFieldOrPropType(type.Next); break; case ElementType.Class: { ITypeDefOrRef typeDefOrRef = ((TypeDefOrRefSig)type).TypeDefOrRef; if (CheckCorLibType(type, "Type")) { writer.WriteByte(80); break; } if (typeDefOrRef is TypeRef) { writer.WriteByte(85); WriteType(typeDefOrRef); break; } goto default; } case ElementType.ValueType: { ITypeDefOrRef typeDefOrRef = ((TypeDefOrRefSig)type).TypeDefOrRef; if (GetEnumTypeDef(type) != null || typeDefOrRef is TypeRef) { writer.WriteByte(85); WriteType(typeDefOrRef); } else { helper.Error("Custom attribute type doesn't seem to be an enum."); writer.WriteByte(85); WriteType(typeDefOrRef); } break; } default: helper.Error("Custom attribute: Invalid type"); writer.WriteByte(byte.MaxValue); break; } recursionCounter.Decrement(); } private void WriteType(IType type) { if (type == null) { helper.Error("Custom attribute: Type is null"); WriteUTF8String(UTF8String.Empty); } else { sb.Length = 0; WriteUTF8String(FullNameFactory.AssemblyQualifiedName(type, helper, sb)); } } private static bool CheckCorLibType(TypeSig ts, string name) { if (!(ts is TypeDefOrRefSig typeDefOrRefSig)) { return false; } return CheckCorLibType(typeDefOrRefSig.TypeDefOrRef, name); } private static bool CheckCorLibType(ITypeDefOrRef tdr, string name) { if (tdr == null) { return false; } if (!tdr.DefinitionAssembly.IsCorLib()) { return false; } if (tdr is TypeSpec) { return false; } if (tdr.TypeName == name) { return tdr.Namespace == "System"; } return false; } private static MethodSig GetMethodSig(ICustomAttributeType ctor) { return ctor?.MethodSig; } private void WriteUTF8String(UTF8String s) { if ((object)s == null || s.Data == null) { writer.WriteByte(byte.MaxValue); return; } writer.WriteCompressedUInt32((uint)s.Data.Length); writer.WriteBytes(s.Data); } public void Dispose() { if (disposeStream && outStream != null) { outStream.Dispose(); } } } public class DataReaderChunk : IChunk { private FileOffset offset; private RVA rva; private DataReader data; private readonly uint virtualSize; private bool setOffsetCalled; public FileOffset FileOffset => offset; public RVA RVA => rva; public DataReaderChunk(DataReader data) : this(ref data) { } public DataReaderChunk(DataReader data, uint virtualSize) : this(ref data, virtualSize) { } internal DataReaderChunk(ref DataReader data) : this(ref data, data.Length) { } internal DataReaderChunk(ref DataReader data, uint virtualSize) { this.data = data; this.virtualSize = virtualSize; } public DataReader CreateReader() { return data; } public void SetData(DataReader newData) { if (setOffsetCalled && newData.Length != data.Length) { throw new InvalidOperationException("New data must be the same size as the old data after SetOffset() has been called"); } data = newData; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; setOffsetCalled = true; } public uint GetFileLength() { return data.Length; } public uint GetVirtualSize() { return virtualSize; } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { data.Position = 0u; data.CopyTo(writer); } } public sealed class DataReaderHeap : HeapBase { private readonly DataReader heapReader; public override string Name { get; } internal DotNetStream OptionalOriginalStream { get; } public DataReaderHeap(DotNetStream stream) { OptionalOriginalStream = stream ?? throw new ArgumentNullException("stream"); heapReader = stream.CreateReader(); Name = stream.Name; } public DataReaderHeap(string name, DataReader heapReader) { this.heapReader = heapReader; this.heapReader.Position = 0u; Name = name ?? throw new ArgumentNullException("name"); } public override uint GetRawLength() { return heapReader.Length; } protected override void WriteToImpl(DataWriter writer) { heapReader.CopyTo(writer); } } public sealed class DataWriter { private readonly Stream stream; private readonly byte[] buffer; private const int BUFFER_LEN = 8; internal Stream InternalStream => stream; public long Position { get { return stream.Position; } set { stream.Position = value; } } public DataWriter(Stream stream) { if (stream == null) { ThrowArgumentNullException("stream"); } this.stream = stream; buffer = new byte[8]; } private static void ThrowArgumentNullException(string paramName) { throw new ArgumentNullException(paramName); } private static void ThrowArgumentOutOfRangeException(string message) { throw new ArgumentOutOfRangeException(message); } public void WriteBoolean(bool value) { stream.WriteByte(value ? ((byte)1) : ((byte)0)); } public void WriteSByte(sbyte value) { stream.WriteByte((byte)value); } public void WriteByte(byte value) { stream.WriteByte(value); } public void WriteInt16(short value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); stream.Write(array, 0, 2); } public void WriteUInt16(ushort value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); stream.Write(array, 0, 2); } public void WriteInt32(int value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); array[2] = (byte)(value >> 16); array[3] = (byte)(value >> 24); stream.Write(array, 0, 4); } public void WriteUInt32(uint value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); array[2] = (byte)(value >> 16); array[3] = (byte)(value >> 24); stream.Write(array, 0, 4); } public void WriteInt64(long value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); array[2] = (byte)(value >> 16); array[3] = (byte)(value >> 24); array[4] = (byte)(value >> 32); array[5] = (byte)(value >> 40); array[6] = (byte)(value >> 48); array[7] = (byte)(value >> 56); stream.Write(array, 0, 8); } public void WriteUInt64(ulong value) { byte[] array = buffer; array[0] = (byte)value; array[1] = (byte)(value >> 8); array[2] = (byte)(value >> 16); array[3] = (byte)(value >> 24); array[4] = (byte)(value >> 32); array[5] = (byte)(value >> 40); array[6] = (byte)(value >> 48); array[7] = (byte)(value >> 56); stream.Write(array, 0, 8); } public unsafe void WriteSingle(float value) { uint num = *(uint*)(&value); byte[] array = buffer; array[0] = (byte)num; array[1] = (byte)(num >> 8); array[2] = (byte)(num >> 16); array[3] = (byte)(num >> 24); stream.Write(array, 0, 4); } public unsafe void WriteDouble(double value) { ulong num = *(ulong*)(&value); byte[] array = buffer; array[0] = (byte)num; array[1] = (byte)(num >> 8); array[2] = (byte)(num >> 16); array[3] = (byte)(num >> 24); array[4] = (byte)(num >> 32); array[5] = (byte)(num >> 40); array[6] = (byte)(num >> 48); array[7] = (byte)(num >> 56); stream.Write(array, 0, 8); } public void WriteBytes(byte[] source) { stream.Write(source, 0, source.Length); } public void WriteBytes(byte[] source, int index, int length) { stream.Write(source, index, length); } public void WriteCompressedUInt32(uint value) { Stream stream = this.stream; if (value <= 127) { stream.WriteByte((byte)value); } else if (value <= 16383) { stream.WriteByte((byte)((value >> 8) | 0x80)); stream.WriteByte((byte)value); } else if (value <= 536870911) { byte[] array = buffer; array[0] = (byte)((value >> 24) | 0xC0); array[1] = (byte)(value >> 16); array[2] = (byte)(value >> 8); array[3] = (byte)value; stream.Write(array, 0, 4); } else { ThrowArgumentOutOfRangeException("UInt32 value can't be compressed"); } } public void WriteCompressedInt32(int value) { Stream stream = this.stream; uint num = (uint)value >> 31; if (-64 <= value && value <= 63) { uint num2 = (uint)((value & 0x3F) << 1) | num; stream.WriteByte((byte)num2); } else if (-8192 <= value && value <= 8191) { uint num3 = (uint)((value & 0x1FFF) << 1) | num; stream.WriteByte((byte)((num3 >> 8) | 0x80)); stream.WriteByte((byte)num3); } else if (-268435456 <= value && value <= 268435455) { uint num4 = (uint)((value & 0xFFFFFFF) << 1) | num; byte[] array = buffer; array[0] = (byte)((num4 >> 24) | 0xC0); array[1] = (byte)(num4 >> 16); array[2] = (byte)(num4 >> 8); array[3] = (byte)num4; stream.Write(array, 0, 4); } else { ThrowArgumentOutOfRangeException("Int32 value can't be compressed"); } } public static int GetCompressedUInt32Length(uint value) { if (value <= 127) { return 1; } if (value <= 16383) { return 2; } if (value <= 536870911) { return 4; } ThrowArgumentOutOfRangeException("UInt32 value can't be compressed"); return 0; } } public sealed class DebugDirectoryEntry { public IMAGE_DEBUG_DIRECTORY DebugDirectory; public readonly IChunk Chunk; public DebugDirectoryEntry(IChunk chunk) { Chunk = chunk; } } public sealed class DebugDirectory : IReuseChunk, IChunk { public const uint DEFAULT_DEBUGDIRECTORY_ALIGNMENT = 4u; internal const int HEADER_SIZE = 28; private FileOffset offset; private RVA rva; private uint length; private readonly List entries; private bool isReadonly; internal int Count => entries.Count; public FileOffset FileOffset => offset; public RVA RVA => rva; public DebugDirectory() { entries = new List(); } public DebugDirectoryEntry Add(byte[] data) { return Add(new ByteArrayChunk(data)); } public DebugDirectoryEntry Add(IChunk chunk) { if (isReadonly) { throw new InvalidOperationException("Can't add a new DebugDirectory entry when the DebugDirectory is read-only!"); } DebugDirectoryEntry debugDirectoryEntry = new DebugDirectoryEntry(chunk); entries.Add(debugDirectoryEntry); return debugDirectoryEntry; } public DebugDirectoryEntry Add(byte[] data, ImageDebugType type, ushort majorVersion, ushort minorVersion, uint timeDateStamp) { return Add(new ByteArrayChunk(data), type, majorVersion, minorVersion, timeDateStamp); } public DebugDirectoryEntry Add(IChunk chunk, ImageDebugType type, ushort majorVersion, ushort minorVersion, uint timeDateStamp) { DebugDirectoryEntry debugDirectoryEntry = Add(chunk); debugDirectoryEntry.DebugDirectory.Type = type; debugDirectoryEntry.DebugDirectory.MajorVersion = majorVersion; debugDirectoryEntry.DebugDirectory.MinorVersion = minorVersion; debugDirectoryEntry.DebugDirectory.TimeDateStamp = timeDateStamp; return debugDirectoryEntry; } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { if (GetLength(entries, (FileOffset)origRva, origRva) > origSize) { return false; } isReadonly = true; return true; } public void SetOffset(FileOffset offset, RVA rva) { isReadonly = true; this.offset = offset; this.rva = rva; length = GetLength(entries, offset, rva); } private static uint GetLength(List entries, FileOffset offset, RVA rva) { uint num = (uint)(28 * entries.Count); foreach (DebugDirectoryEntry entry in entries) { num = Utils.AlignUp(num, 4u); entry.Chunk.SetOffset(offset + num, rva + num); num += entry.Chunk.GetFileLength(); } return num; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { uint offs = 0u; foreach (DebugDirectoryEntry entry in entries) { writer.WriteUInt32(entry.DebugDirectory.Characteristics); writer.WriteUInt32(entry.DebugDirectory.TimeDateStamp); writer.WriteUInt16(entry.DebugDirectory.MajorVersion); writer.WriteUInt16(entry.DebugDirectory.MinorVersion); writer.WriteUInt32((uint)entry.DebugDirectory.Type); uint fileLength = entry.Chunk.GetFileLength(); writer.WriteUInt32(fileLength); writer.WriteUInt32((uint)((fileLength != 0) ? entry.Chunk.RVA : ((RVA)0u))); writer.WriteUInt32((uint)((fileLength != 0) ? entry.Chunk.FileOffset : ((FileOffset)0u))); offs += 28; } foreach (DebugDirectoryEntry entry2 in entries) { WriteAlign(writer, ref offs); entry2.Chunk.VerifyWriteTo(writer); offs += entry2.Chunk.GetFileLength(); } } private static void WriteAlign(DataWriter writer, ref uint offs) { uint num = Utils.AlignUp(offs, 4u) - offs; offs += num; writer.WriteZeroes((int)num); } } public readonly struct DeclSecurityWriter : ICustomAttributeWriterHelper, IWriterError, IFullNameFactoryHelper { private readonly ModuleDef module; private readonly IWriterError helper; private readonly DataWriterContext context; private readonly bool optimizeCustomAttributeSerializedTypeNames; public static byte[] Write(ModuleDef module, IList secAttrs, IWriterError helper) { return Write(module, secAttrs, helper, optimizeCustomAttributeSerializedTypeNames: false); } public static byte[] Write(ModuleDef module, IList secAttrs, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames) { return new DeclSecurityWriter(module, helper, optimizeCustomAttributeSerializedTypeNames, null).Write(secAttrs); } internal static byte[] Write(ModuleDef module, IList secAttrs, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames, DataWriterContext context) { return new DeclSecurityWriter(module, helper, optimizeCustomAttributeSerializedTypeNames, context).Write(secAttrs); } private DeclSecurityWriter(ModuleDef module, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames, DataWriterContext context) { this.module = module; this.helper = helper; this.context = context; this.optimizeCustomAttributeSerializedTypeNames = optimizeCustomAttributeSerializedTypeNames; } private byte[] Write(IList secAttrs) { if (secAttrs == null) { secAttrs = Array2.Empty(); } string net1xXmlStringInternal = DeclSecurity.GetNet1xXmlStringInternal(secAttrs); if (net1xXmlStringInternal != null) { return WriteFormat1(net1xXmlStringInternal); } return WriteFormat2(secAttrs); } private byte[] WriteFormat1(string xml) { return Encoding.Unicode.GetBytes(xml); } private byte[] WriteFormat2(IList secAttrs) { StringBuilder stringBuilder = new StringBuilder(); MemoryStream memoryStream = new MemoryStream(); DataWriter dataWriter = new DataWriter(memoryStream); dataWriter.WriteByte(46); WriteCompressedUInt32(dataWriter, (uint)secAttrs.Count); int count = secAttrs.Count; for (int i = 0; i < count; i++) { SecurityAttribute securityAttribute = secAttrs[i]; if (securityAttribute == null) { helper.Error("SecurityAttribute is null"); Write(dataWriter, UTF8String.Empty); WriteCompressedUInt32(dataWriter, 1u); WriteCompressedUInt32(dataWriter, 0u); continue; } ITypeDefOrRef attributeType = securityAttribute.AttributeType; string text; if (attributeType == null) { helper.Error("SecurityAttribute attribute type is null"); text = string.Empty; } else { stringBuilder.Length = 0; text = FullNameFactory.AssemblyQualifiedName(attributeType, null, stringBuilder); } Write(dataWriter, text); byte[] array = ((context == null) ? CustomAttributeWriter.Write(this, securityAttribute.NamedArguments) : CustomAttributeWriter.Write(this, securityAttribute.NamedArguments, context)); if (array.Length > 536870911) { helper.Error("Named arguments blob size doesn't fit in 29 bits"); array = Array2.Empty(); } WriteCompressedUInt32(dataWriter, (uint)array.Length); dataWriter.WriteBytes(array); } return memoryStream.ToArray(); } private uint WriteCompressedUInt32(DataWriter writer, uint value) { return writer.WriteCompressedUInt32(helper, value); } private void Write(DataWriter writer, UTF8String s) { writer.Write(helper, s); } void IWriterError.Error(string message) { helper.Error(message); } bool IFullNameFactoryHelper.MustUseAssemblyName(IType type) { return FullNameFactory.MustUseAssemblyName(module, type, optimizeCustomAttributeSerializedTypeNames); } } public static class Extensions { public static void WriteZeroes(this DataWriter writer, int count) { while (count >= 8) { writer.WriteUInt64(0uL); count -= 8; } for (int i = 0; i < count; i++) { writer.WriteByte(0); } } public static void VerifyWriteTo(this IChunk chunk, DataWriter writer) { long position = writer.Position; chunk.WriteTo(writer); if (writer.Position - position != chunk.GetFileLength()) { VerifyWriteToThrow(chunk); } } private static void VerifyWriteToThrow(IChunk chunk) { throw new IOException("Did not write all bytes: " + chunk.GetType().FullName); } internal static void WriteDataDirectory(this DataWriter writer, IChunk chunk) { if (chunk == null || chunk.GetVirtualSize() == 0) { writer.WriteUInt64(0uL); return; } writer.WriteUInt32((uint)chunk.RVA); writer.WriteUInt32(chunk.GetVirtualSize()); } internal static void WriteDebugDirectory(this DataWriter writer, DebugDirectory chunk) { if (chunk == null || chunk.GetVirtualSize() == 0) { writer.WriteUInt64(0uL); return; } writer.WriteUInt32((uint)chunk.RVA); writer.WriteUInt32((uint)(chunk.Count * 28)); } internal static void Error2(this IWriterError helper, string message, params object[] args) { if (helper is IWriterError2 writerError) { writerError.Error(message, args); } else { helper.Error(string.Format(message, args)); } } } public sealed class GuidHeap : HeapBase, IOffsetHeap { private readonly Dictionary guids = new Dictionary(); private Dictionary userRawData; public override string Name => "#GUID"; public uint Add(Guid? guid) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #GUID when it's read-only"); } if (!guid.HasValue) { return 0u; } if (guids.TryGetValue(guid.Value, out var value)) { return value; } value = (uint)(guids.Count + 1); guids.Add(guid.Value, value); return value; } public override uint GetRawLength() { return (uint)(guids.Count * 16); } protected override void WriteToImpl(DataWriter writer) { uint num = 0u; foreach (KeyValuePair guid in guids) { if (userRawData == null || !userRawData.TryGetValue(num, out var value)) { value = guid.Key.ToByteArray(); } writer.WriteBytes(value); num += 16; } } public int GetRawDataSize(Guid data) { return 16; } public void SetRawData(uint offset, byte[] rawData) { if (rawData == null || rawData.Length != 16) { throw new ArgumentException("Invalid size of GUID raw data"); } if (userRawData == null) { userRawData = new Dictionary(); } userRawData[offset] = rawData; } public IEnumerable> GetAllRawData() { uint offset = 0u; foreach (KeyValuePair guid in guids) { yield return new KeyValuePair(offset, guid.Key.ToByteArray()); offset += 16; } } } internal static class Hasher { private static HashAlgorithm CreateHasher(ChecksumAlgorithm checksumAlgorithm) { return checksumAlgorithm switch { ChecksumAlgorithm.SHA1 => SHA1.Create(), ChecksumAlgorithm.SHA256 => SHA256.Create(), ChecksumAlgorithm.SHA384 => SHA384.Create(), ChecksumAlgorithm.SHA512 => SHA512.Create(), _ => throw new ArgumentOutOfRangeException("checksumAlgorithm"), }; } public static string GetChecksumName(ChecksumAlgorithm checksumAlgorithm) { return checksumAlgorithm switch { ChecksumAlgorithm.SHA1 => "SHA1", ChecksumAlgorithm.SHA256 => "SHA256", ChecksumAlgorithm.SHA384 => "SHA384", ChecksumAlgorithm.SHA512 => "SHA512", _ => throw new ArgumentOutOfRangeException("checksumAlgorithm"), }; } public static bool TryGetChecksumAlgorithm(string checksumName, out ChecksumAlgorithm pdbChecksumAlgorithm, out int checksumSize) { switch (checksumName) { case "SHA1": pdbChecksumAlgorithm = ChecksumAlgorithm.SHA1; checksumSize = 20; return true; case "SHA256": pdbChecksumAlgorithm = ChecksumAlgorithm.SHA256; checksumSize = 32; return true; case "SHA384": pdbChecksumAlgorithm = ChecksumAlgorithm.SHA384; checksumSize = 48; return true; case "SHA512": pdbChecksumAlgorithm = ChecksumAlgorithm.SHA512; checksumSize = 64; return true; default: pdbChecksumAlgorithm = ChecksumAlgorithm.SHA1; checksumSize = -1; return false; } } public static byte[] Hash(ChecksumAlgorithm checksumAlgorithm, Stream stream, long length) { byte[] array = new byte[(int)Math.Min(8192L, length)]; using HashAlgorithm hashAlgorithm = CreateHasher(checksumAlgorithm); while (length > 0) { int count = (int)Math.Min(length, array.Length); int num = stream.Read(array, 0, count); if (num == 0) { throw new InvalidOperationException("Couldn't read all bytes"); } hashAlgorithm.TransformBlock(array, 0, num, array, 0); length -= num; } hashAlgorithm.TransformFinalBlock(Array2.Empty(), 0, 0); return hashAlgorithm.Hash; } } public abstract class HeapBase : IHeap, IChunk { internal const uint ALIGNMENT = 4u; private FileOffset offset; private RVA rva; protected bool isReadOnly; public FileOffset FileOffset => offset; public RVA RVA => rva; public abstract string Name { get; } public bool IsEmpty => GetRawLength() <= 1; public bool IsBig => GetFileLength() > 65535; public void SetReadOnly() { isReadOnly = true; } public virtual void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return Utils.AlignUp(GetRawLength(), 4u); } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public abstract uint GetRawLength(); public void WriteTo(DataWriter writer) { WriteToImpl(writer); writer.WriteZeroes((int)(Utils.AlignUp(GetRawLength(), 4u) - GetRawLength())); } protected abstract void WriteToImpl(DataWriter writer); public override string ToString() { return Name; } } public interface IChunk { FileOffset FileOffset { get; } RVA RVA { get; } void SetOffset(FileOffset offset, RVA rva); uint GetFileLength(); uint GetVirtualSize(); uint CalculateAlignment(); void WriteTo(DataWriter writer); } internal interface IReuseChunk : IChunk { bool CanReuse(RVA origRva, uint origSize); } public interface IHeap : IChunk { string Name { get; } bool IsEmpty { get; } void SetReadOnly(); } public sealed class Cor20HeaderOptions { public const ushort DEFAULT_MAJOR_RT_VER = 2; public const ushort DEFAULT_MINOR_RT_VER = 5; public ushort? MajorRuntimeVersion; public ushort? MinorRuntimeVersion; public ComImageFlags? Flags; public uint? EntryPoint; public Cor20HeaderOptions() { } public Cor20HeaderOptions(ComImageFlags flags) { Flags = flags; } public Cor20HeaderOptions(ushort major, ushort minor, ComImageFlags flags) { MajorRuntimeVersion = major; MinorRuntimeVersion = minor; Flags = flags; } } public sealed class ImageCor20Header : IChunk { private FileOffset offset; private RVA rva; private Cor20HeaderOptions options; public Metadata Metadata { get; set; } public NetResources NetResources { get; set; } public StrongNameSignature StrongNameSignature { get; set; } internal IChunk VtableFixups { get; set; } public FileOffset FileOffset => offset; public RVA RVA => rva; public ImageCor20Header(Cor20HeaderOptions options) { this.options = options; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return 72u; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { writer.WriteInt32(72); writer.WriteUInt16(options.MajorRuntimeVersion ?? 2); writer.WriteUInt16(options.MinorRuntimeVersion ?? 5); writer.WriteDataDirectory(Metadata); writer.WriteUInt32((uint)(options.Flags ?? ComImageFlags.ILOnly)); writer.WriteUInt32(options.EntryPoint.GetValueOrDefault()); writer.WriteDataDirectory(NetResources); writer.WriteDataDirectory(StrongNameSignature); writer.WriteDataDirectory(null); writer.WriteDataDirectory(VtableFixups); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); } } public sealed class ImportAddressTable : IChunk { private readonly bool is64bit; private FileOffset offset; private RVA rva; public ImportDirectory ImportDirectory { get; set; } public FileOffset FileOffset => offset; public RVA RVA => rva; internal bool Enable { get; set; } public ImportAddressTable(bool is64bit) { this.is64bit = is64bit; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { if (!Enable) { return 0u; } if (!is64bit) { return 8u; } return 16u; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { if (Enable) { if (is64bit) { writer.WriteUInt64((ulong)ImportDirectory.CorXxxMainRVA); writer.WriteUInt64(0uL); } else { writer.WriteUInt32((uint)ImportDirectory.CorXxxMainRVA); writer.WriteInt32(0); } } } } public sealed class ImportDirectory : IChunk { private readonly bool is64bit; private FileOffset offset; private RVA rva; private bool isExeFile; private uint length; private RVA importLookupTableRVA; private RVA corXxxMainRVA; private RVA dllToImportRVA; private int stringsPadding; private string dllToImport; private string entryPointName; private const uint STRINGS_ALIGNMENT = 16u; public ImportAddressTable ImportAddressTable { get; set; } public RVA CorXxxMainRVA => corXxxMainRVA; public RVA IatCorXxxMainRVA => ImportAddressTable.RVA; public bool IsExeFile { get { return isExeFile; } set { isExeFile = value; } } public FileOffset FileOffset => offset; public RVA RVA => rva; internal bool Enable { get; set; } public string DllToImport { get { return dllToImport ?? "mscoree.dll"; } set { dllToImport = value; } } public string EntryPointName { get { object obj = entryPointName; if (obj == null) { if (!IsExeFile) { return "_CorDllMain"; } obj = "_CorExeMain"; } return (string)obj; } set { entryPointName = value; } } public ImportDirectory(bool is64bit) { this.is64bit = is64bit; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = 40u; importLookupTableRVA = rva + length; length += (uint)(is64bit ? 16 : 8); stringsPadding = (int)(rva.AlignUp(16u) - rva); length += (uint)stringsPadding; corXxxMainRVA = rva + length; length += (uint)(2 + EntryPointName.Length + 1); dllToImportRVA = rva + length; length += (uint)(DllToImport.Length + 1); length++; } public uint GetFileLength() { if (!Enable) { return 0u; } return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { if (Enable) { writer.WriteUInt32((uint)importLookupTableRVA); writer.WriteInt32(0); writer.WriteInt32(0); writer.WriteUInt32((uint)dllToImportRVA); writer.WriteUInt32((uint)ImportAddressTable.RVA); writer.WriteUInt64(0uL); writer.WriteUInt64(0uL); writer.WriteInt32(0); if (is64bit) { writer.WriteUInt64((ulong)corXxxMainRVA); writer.WriteUInt64(0uL); } else { writer.WriteUInt32((uint)corXxxMainRVA); writer.WriteInt32(0); } writer.WriteZeroes(stringsPadding); writer.WriteUInt16(0); writer.WriteBytes(Encoding.UTF8.GetBytes(EntryPointName + "\0")); writer.WriteBytes(Encoding.UTF8.GetBytes(DllToImport + "\0")); writer.WriteByte(0); } } } public interface IOffsetHeap { int GetRawDataSize(TValue data); void SetRawData(uint offset, byte[] rawData); IEnumerable> GetAllRawData(); } public interface IWriterError { void Error(string message); } public interface IWriterError2 : IWriterError { void Error(string message, params object[] args); } internal sealed class ManagedExportsWriter { private sealed class ExportDir : IChunk { private readonly ManagedExportsWriter owner; public FileOffset FileOffset => owner.ExportDirOffset; public RVA RVA => owner.ExportDirRVA; public ExportDir(ManagedExportsWriter owner) { this.owner = owner; } void IChunk.SetOffset(FileOffset offset, RVA rva) { throw new NotSupportedException(); } public uint GetFileLength() { return owner.ExportDirSize; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } void IChunk.WriteTo(DataWriter writer) { throw new NotSupportedException(); } } private sealed class VtableFixupsChunk : IChunk { private readonly ManagedExportsWriter owner; private FileOffset offset; private RVA rva; internal uint length; public FileOffset FileOffset => offset; public RVA RVA => rva; public VtableFixupsChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { owner.WriteVtableFixups(writer); } } private sealed class StubsChunk : IChunk { private readonly ManagedExportsWriter owner; private FileOffset offset; private RVA rva; internal uint length; public FileOffset FileOffset => offset; public RVA RVA => rva; public StubsChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { owner.WriteStubs(writer); } } private sealed class SdataChunk : IChunk { private readonly ManagedExportsWriter owner; private FileOffset offset; private RVA rva; internal uint length; public FileOffset FileOffset => offset; public RVA RVA => rva; public SdataChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { owner.WriteSdata(writer); } } private sealed class MethodInfo { public readonly MethodDef Method; public readonly uint StubChunkOffset; public int FunctionIndex; public uint ManagedVtblOffset; public uint NameOffset; public int NameIndex; public byte[] NameBytes; public MethodInfo(MethodDef method, uint stubChunkOffset) { Method = method; StubChunkOffset = stubChunkOffset; } } private sealed class VTableInfo { public readonly VTableFlags Flags; public readonly List Methods; public uint SdataChunkOffset { get; set; } public VTableInfo(VTableFlags flags) { Flags = flags; Methods = new List(); } } private struct NamesBlob { private readonly struct NameInfo { public readonly uint Offset; public readonly byte[] Bytes; public NameInfo(uint offset, byte[] bytes) { Offset = offset; Bytes = bytes; } } private readonly Dictionary nameOffsets; private readonly List names; private readonly List methodNameOffsets; private uint currentOffset; private int methodNamesCount; private bool methodNamesIsFrozen; public int MethodNamesCount => methodNamesCount; public NamesBlob(bool dummy) { nameOffsets = new Dictionary(StringComparer.Ordinal); names = new List(); methodNameOffsets = new List(); currentOffset = 0u; methodNamesCount = 0; methodNamesIsFrozen = false; } public uint GetMethodNameOffset(string name, out byte[] bytes) { if (methodNamesIsFrozen) { throw new InvalidOperationException(); } methodNamesCount++; uint offset = GetOffset(name, out bytes); methodNameOffsets.Add(offset); return offset; } public uint GetOtherNameOffset(string name) { methodNamesIsFrozen = true; byte[] bytes; return GetOffset(name, out bytes); } private uint GetOffset(string name, out byte[] bytes) { if (nameOffsets.TryGetValue(name, out var value)) { bytes = value.Bytes; return value.Offset; } bytes = GetNameASCIIZ(name); names.Add(bytes); uint num = currentOffset; nameOffsets.Add(name, new NameInfo(num, bytes)); currentOffset += (uint)bytes.Length; return num; } private static byte[] GetNameASCIIZ(string name) { byte[] array = new byte[Encoding.UTF8.GetByteCount(name) + 1]; Encoding.UTF8.GetBytes(name, 0, name.Length, array, 0); if (array[^1] != 0) { throw new ModuleWriterException(); } return array; } public void Write(DataWriter writer) { foreach (byte[] name in names) { writer.WriteBytes(name); } } public uint[] GetMethodNameOffsets() { return methodNameOffsets.ToArray(); } } private struct SdataBytesInfo { public byte[] Data; public uint namesBlobStreamOffset; public uint moduleNameOffset; public uint exportDirModuleNameStreamOffset; public uint exportDirAddressOfFunctionsStreamOffset; public uint addressOfFunctionsStreamOffset; public uint addressOfNamesStreamOffset; public uint addressOfNameOrdinalsStreamOffset; public uint[] MethodNameOffsets; } private const uint DEFAULT_VTBL_FIXUPS_ALIGNMENT = 4u; private const uint DEFAULT_SDATA_ALIGNMENT = 8u; private const StubType stubType = StubType.Export; private readonly string moduleName; private readonly Machine machine; private readonly RelocDirectory relocDirectory; private readonly Metadata metadata; private readonly PEHeaders peHeaders; private readonly Action logError; private readonly VtableFixupsChunk vtableFixups; private readonly StubsChunk stubsChunk; private readonly SdataChunk sdataChunk; private readonly ExportDir exportDir; private readonly List vtables; private readonly List allMethodInfos; private readonly List sortedOrdinalMethodInfos; private readonly List sortedNameMethodInfos; private readonly CpuArch cpuArch; private uint exportDirOffset; private SdataBytesInfo sdataBytesInfo; private bool Is64Bit => machine.Is64Bit(); private FileOffset ExportDirOffset => sdataChunk.FileOffset + exportDirOffset; private RVA ExportDirRVA => sdataChunk.RVA + exportDirOffset; private uint ExportDirSize => 40u; internal bool HasExports => vtables.Count != 0; public ManagedExportsWriter(string moduleName, Machine machine, RelocDirectory relocDirectory, Metadata metadata, PEHeaders peHeaders, Action logError) { this.moduleName = moduleName; this.machine = machine; this.relocDirectory = relocDirectory; this.metadata = metadata; this.peHeaders = peHeaders; this.logError = logError; vtableFixups = new VtableFixupsChunk(this); stubsChunk = new StubsChunk(this); sdataChunk = new SdataChunk(this); exportDir = new ExportDir(this); vtables = new List(); allMethodInfos = new List(); sortedOrdinalMethodInfos = new List(); sortedNameMethodInfos = new List(); CpuArch.TryGetCpuArch(machine, out cpuArch); } internal void AddTextChunks(PESection textSection) { textSection.Add(vtableFixups, 4u); if (cpuArch != null) { textSection.Add(stubsChunk, cpuArch.GetStubAlignment(StubType.Export)); } } internal void AddSdataChunks(PESection sdataSection) { sdataSection.Add(sdataChunk, 8u); } internal void InitializeChunkProperties() { if (allMethodInfos.Count != 0) { peHeaders.ExportDirectory = exportDir; peHeaders.ImageCor20Header.VtableFixups = vtableFixups; } } internal void AddExportedMethods(List methods, uint timestamp) { if (methods.Count != 0) { if (cpuArch == null) { logError("The module has exported methods but the CPU architecture isn't supported: {0} (0x{1:X4})", new object[2] { machine, (ushort)machine }); } else if (methods.Count > 65536) { logError("Too many methods have been exported. No more than 2^16 methods can be exported. Number of exported methods: {0}", new object[1] { methods.Count }); } else { Initialize(methods, timestamp); } } } private void Initialize(List methods, uint timestamp) { Dictionary> dictionary = new Dictionary>(); VTableFlags vTableFlags = ((!Is64Bit) ? VTableFlags.Bit32 : VTableFlags.Bit64); uint num = 0u; uint stubAlignment = cpuArch.GetStubAlignment(StubType.Export); uint stubCodeOffset = cpuArch.GetStubCodeOffset(StubType.Export); uint stubSize = cpuArch.GetStubSize(StubType.Export); foreach (MethodDef method in methods) { MethodExportInfo exportInfo = method.ExportInfo; if (exportInfo != null) { VTableFlags vTableFlags2 = vTableFlags; if ((exportInfo.Options & MethodExportInfoOptions.FromUnmanaged) != MethodExportInfoOptions.None) { vTableFlags2 |= VTableFlags.FromUnmanaged; } if ((exportInfo.Options & MethodExportInfoOptions.FromUnmanagedRetainAppDomain) != MethodExportInfoOptions.None) { vTableFlags2 |= VTableFlags.FromUnmanagedRetainAppDomain; } if ((exportInfo.Options & MethodExportInfoOptions.CallMostDerived) != MethodExportInfoOptions.None) { vTableFlags2 |= VTableFlags.CallMostDerived; } if (!dictionary.TryGetValue((int)vTableFlags2, out var value)) { dictionary.Add((int)vTableFlags2, value = new List()); } if (value.Count == 0 || value[value.Count - 1].Methods.Count >= 65535) { value.Add(new VTableInfo(vTableFlags2)); } MethodInfo item = new MethodInfo(method, num + stubCodeOffset); allMethodInfos.Add(item); value[value.Count - 1].Methods.Add(item); num = (num + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } } foreach (KeyValuePair> item2 in dictionary) { vtables.AddRange(item2.Value); } WriteSdataBlob(timestamp); vtableFixups.length = (uint)(vtables.Count * 8); stubsChunk.length = num; sdataChunk.length = (uint)sdataBytesInfo.Data.Length; uint num2 = 0u; foreach (MethodInfo allMethodInfo in allMethodInfos) { uint num3 = allMethodInfo.StubChunkOffset - stubCodeOffset; if (num2 != num3) { throw new InvalidOperationException(); } cpuArch.WriteStubRelocs(StubType.Export, relocDirectory, stubsChunk, num3); num2 = (num3 + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } if (num2 != num) { throw new InvalidOperationException(); } } private void WriteSdataBlob(uint timestamp) { MemoryStream memoryStream = new MemoryStream(); DataWriter dataWriter = new DataWriter(memoryStream); foreach (VTableInfo vtable in vtables) { vtable.SdataChunkOffset = (uint)dataWriter.Position; foreach (MethodInfo method in vtable.Methods) { method.ManagedVtblOffset = (uint)dataWriter.Position; dataWriter.WriteUInt32(100663296 + metadata.GetRid(method.Method)); if ((vtable.Flags & VTableFlags.Bit64) != 0) { dataWriter.WriteUInt32(0u); } } } NamesBlob namesBlob = new NamesBlob(dummy: false); int num = 0; foreach (MethodInfo allMethodInfo in allMethodInfos) { MethodExportInfo exportInfo = allMethodInfo.Method.ExportInfo; string text = exportInfo.Name; if (text == null) { if (exportInfo.Ordinal.HasValue) { sortedOrdinalMethodInfos.Add(allMethodInfo); continue; } text = allMethodInfo.Method.Name; } if (string.IsNullOrEmpty(text)) { logError("Exported method name is null or empty, method: {0} (0x{1:X8})", new object[2] { allMethodInfo.Method, allMethodInfo.Method.MDToken.Raw }); } else { allMethodInfo.NameOffset = namesBlob.GetMethodNameOffset(text, out allMethodInfo.NameBytes); allMethodInfo.NameIndex = num++; sortedNameMethodInfos.Add(allMethodInfo); } } sdataBytesInfo.MethodNameOffsets = namesBlob.GetMethodNameOffsets(); sdataBytesInfo.moduleNameOffset = namesBlob.GetOtherNameOffset(moduleName); sortedOrdinalMethodInfos.Sort((MethodInfo a, MethodInfo b) => a.Method.ExportInfo.Ordinal.Value.CompareTo(b.Method.ExportInfo.Ordinal.Value)); sortedNameMethodInfos.Sort((MethodInfo a, MethodInfo b) => CompareTo(a.NameBytes, b.NameBytes)); int num2; int num3; if (sortedOrdinalMethodInfos.Count == 0) { num2 = 0; num3 = 0; } else { num2 = sortedOrdinalMethodInfos[0].Method.ExportInfo.Ordinal.Value; num3 = sortedOrdinalMethodInfos[sortedOrdinalMethodInfos.Count - 1].Method.ExportInfo.Ordinal.Value + 1; } int num4 = num3 - num2; int num5 = 0; for (int num6 = 0; num6 < sortedOrdinalMethodInfos.Count; num6++) { int num7 = sortedOrdinalMethodInfos[num6].Method.ExportInfo.Ordinal.Value - num2; sortedOrdinalMethodInfos[num6].FunctionIndex = num7; num5 = num7; } for (int num8 = 0; num8 < sortedNameMethodInfos.Count; num8++) { num5 = num4 + num8; sortedNameMethodInfos[num8].FunctionIndex = num5; } int num9 = num5 + 1; if (num9 > 65536) { logError("Exported function array is too big", Array2.Empty()); return; } exportDirOffset = (uint)dataWriter.Position; dataWriter.WriteUInt32(0u); dataWriter.WriteUInt32(timestamp); dataWriter.WriteUInt32(0u); sdataBytesInfo.exportDirModuleNameStreamOffset = (uint)dataWriter.Position; dataWriter.WriteUInt32(0u); dataWriter.WriteInt32(num2); dataWriter.WriteUInt32((uint)num9); dataWriter.WriteInt32(sdataBytesInfo.MethodNameOffsets.Length); sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset = (uint)dataWriter.Position; dataWriter.WriteUInt32(0u); dataWriter.WriteUInt32(0u); dataWriter.WriteUInt32(0u); sdataBytesInfo.addressOfFunctionsStreamOffset = (uint)dataWriter.Position; dataWriter.WriteZeroes(num9 * 4); sdataBytesInfo.addressOfNamesStreamOffset = (uint)dataWriter.Position; dataWriter.WriteZeroes(sdataBytesInfo.MethodNameOffsets.Length * 4); sdataBytesInfo.addressOfNameOrdinalsStreamOffset = (uint)dataWriter.Position; dataWriter.WriteZeroes(sdataBytesInfo.MethodNameOffsets.Length * 2); sdataBytesInfo.namesBlobStreamOffset = (uint)dataWriter.Position; namesBlob.Write(dataWriter); sdataBytesInfo.Data = memoryStream.ToArray(); } private void WriteSdata(DataWriter writer) { if (sdataBytesInfo.Data != null) { PatchSdataBytesBlob(); writer.WriteBytes(sdataBytesInfo.Data); } } private void PatchSdataBytesBlob() { uint rVA = (uint)sdataChunk.RVA; uint num = rVA + sdataBytesInfo.namesBlobStreamOffset; DataWriter dataWriter = new DataWriter(new MemoryStream(sdataBytesInfo.Data)); dataWriter.Position = sdataBytesInfo.exportDirModuleNameStreamOffset; dataWriter.WriteUInt32(num + sdataBytesInfo.moduleNameOffset); dataWriter.Position = sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset; dataWriter.WriteUInt32(rVA + sdataBytesInfo.addressOfFunctionsStreamOffset); if (sdataBytesInfo.MethodNameOffsets.Length != 0) { dataWriter.WriteUInt32(rVA + sdataBytesInfo.addressOfNamesStreamOffset); dataWriter.WriteUInt32(rVA + sdataBytesInfo.addressOfNameOrdinalsStreamOffset); } uint rVA2 = (uint)stubsChunk.RVA; dataWriter.Position = sdataBytesInfo.addressOfFunctionsStreamOffset; int num2 = 0; foreach (MethodInfo sortedOrdinalMethodInfo in sortedOrdinalMethodInfos) { int num3 = sortedOrdinalMethodInfo.FunctionIndex - num2; if (num3 < 0) { throw new InvalidOperationException(); } while (num3-- > 0) { dataWriter.WriteInt32(0); } dataWriter.WriteUInt32(rVA2 + sortedOrdinalMethodInfo.StubChunkOffset); num2 = sortedOrdinalMethodInfo.FunctionIndex + 1; } foreach (MethodInfo sortedNameMethodInfo in sortedNameMethodInfos) { if (sortedNameMethodInfo.FunctionIndex != num2++) { throw new InvalidOperationException(); } dataWriter.WriteUInt32(rVA2 + sortedNameMethodInfo.StubChunkOffset); } uint[] methodNameOffsets = sdataBytesInfo.MethodNameOffsets; if (methodNameOffsets.Length == 0) { return; } dataWriter.Position = sdataBytesInfo.addressOfNamesStreamOffset; foreach (MethodInfo sortedNameMethodInfo2 in sortedNameMethodInfos) { dataWriter.WriteUInt32(num + methodNameOffsets[sortedNameMethodInfo2.NameIndex]); } dataWriter.Position = sdataBytesInfo.addressOfNameOrdinalsStreamOffset; foreach (MethodInfo sortedNameMethodInfo3 in sortedNameMethodInfos) { dataWriter.WriteUInt16((ushort)sortedNameMethodInfo3.FunctionIndex); } } private void WriteVtableFixups(DataWriter writer) { if (vtables.Count == 0) { return; } foreach (VTableInfo vtable in vtables) { writer.WriteUInt32((uint)(sdataChunk.RVA + vtable.SdataChunkOffset)); writer.WriteUInt16((ushort)vtable.Methods.Count); writer.WriteUInt16((ushort)vtable.Flags); } } private void WriteStubs(DataWriter writer) { if (vtables.Count == 0 || cpuArch == null) { return; } ulong imageBase = peHeaders.ImageBase; uint rVA = (uint)stubsChunk.RVA; uint rVA2 = (uint)sdataChunk.RVA; uint num = 0u; uint stubCodeOffset = cpuArch.GetStubCodeOffset(StubType.Export); uint stubSize = cpuArch.GetStubSize(StubType.Export); uint stubAlignment = cpuArch.GetStubAlignment(StubType.Export); int num2 = (int)(((stubSize + stubAlignment - 1) & ~(stubAlignment - 1)) - stubSize); foreach (MethodInfo allMethodInfo in allMethodInfos) { uint num3 = allMethodInfo.StubChunkOffset - stubCodeOffset; if (num != num3) { throw new InvalidOperationException(); } long position = writer.Position; cpuArch.WriteStub(StubType.Export, writer, imageBase, rVA + num3, rVA2 + allMethodInfo.ManagedVtblOffset); if (position + stubSize != writer.Position) { throw new InvalidOperationException(); } if (num2 != 0) { writer.WriteZeroes(num2); } num = (num3 + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } if (num == stubsChunk.length) { return; } throw new InvalidOperationException(); } private static int CompareTo(byte[] a, byte[] b) { if (a == b) { return 0; } int num = Math.Min(a.Length, b.Length); for (int i = 0; i < num; i++) { int num2 = a[i] - b[i]; if (num2 != 0) { return num2; } } return a.Length - b.Length; } } public readonly struct MarshalBlobWriter : IDisposable, IFullNameFactoryHelper { private readonly ModuleDef module; private readonly MemoryStream outStream; private readonly DataWriter writer; private readonly IWriterError helper; private readonly bool optimizeCustomAttributeSerializedTypeNames; public static byte[] Write(ModuleDef module, MarshalType marshalType, IWriterError helper) { return Write(module, marshalType, helper, optimizeCustomAttributeSerializedTypeNames: false); } public static byte[] Write(ModuleDef module, MarshalType marshalType, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames) { using MarshalBlobWriter marshalBlobWriter = new MarshalBlobWriter(module, helper, optimizeCustomAttributeSerializedTypeNames); return marshalBlobWriter.Write(marshalType); } private MarshalBlobWriter(ModuleDef module, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames) { this.module = module; outStream = new MemoryStream(); writer = new DataWriter(outStream); this.helper = helper; this.optimizeCustomAttributeSerializedTypeNames = optimizeCustomAttributeSerializedTypeNames; } private byte[] Write(MarshalType marshalType) { if (marshalType == null) { return null; } NativeType nativeType = marshalType.NativeType; if (nativeType != NativeType.RawBlob) { if (nativeType > (NativeType)255u) { helper.Error("Invalid MarshalType.NativeType"); } writer.WriteByte((byte)nativeType); } bool canWriteMore = true; switch (nativeType) { case NativeType.FixedSysString: { FixedSysStringMarshalType fixedSysStringMarshalType = (FixedSysStringMarshalType)marshalType; if (fixedSysStringMarshalType.IsSizeValid) { WriteCompressedUInt32((uint)fixedSysStringMarshalType.Size); } break; } case NativeType.SafeArray: { SafeArrayMarshalType safeArrayMarshalType = (SafeArrayMarshalType)marshalType; if (UpdateCanWrite(safeArrayMarshalType.IsVariantTypeValid, "VariantType", ref canWriteMore)) { WriteCompressedUInt32((uint)safeArrayMarshalType.VariantType); } if (UpdateCanWrite(safeArrayMarshalType.IsUserDefinedSubTypeValid, "UserDefinedSubType", ref canWriteMore)) { Write(safeArrayMarshalType.UserDefinedSubType.AssemblyQualifiedName); } break; } case NativeType.FixedArray: { FixedArrayMarshalType fixedArrayMarshalType = (FixedArrayMarshalType)marshalType; if (UpdateCanWrite(fixedArrayMarshalType.IsSizeValid, "Size", ref canWriteMore)) { WriteCompressedUInt32((uint)fixedArrayMarshalType.Size); } if (UpdateCanWrite(fixedArrayMarshalType.IsElementTypeValid, "ElementType", ref canWriteMore)) { WriteCompressedUInt32((uint)fixedArrayMarshalType.ElementType); } break; } case NativeType.Array: { ArrayMarshalType arrayMarshalType = (ArrayMarshalType)marshalType; if (UpdateCanWrite(arrayMarshalType.IsElementTypeValid, "ElementType", ref canWriteMore)) { WriteCompressedUInt32((uint)arrayMarshalType.ElementType); } if (UpdateCanWrite(arrayMarshalType.IsParamNumberValid, "ParamNumber", ref canWriteMore)) { WriteCompressedUInt32((uint)arrayMarshalType.ParamNumber); } if (UpdateCanWrite(arrayMarshalType.IsSizeValid, "Size", ref canWriteMore)) { WriteCompressedUInt32((uint)arrayMarshalType.Size); } if (UpdateCanWrite(arrayMarshalType.IsFlagsValid, "Flags", ref canWriteMore)) { WriteCompressedUInt32((uint)arrayMarshalType.Flags); } break; } case NativeType.CustomMarshaler: { CustomMarshalType customMarshalType = (CustomMarshalType)marshalType; Write(customMarshalType.Guid); Write(customMarshalType.NativeTypeName); ITypeDefOrRef customMarshaler = customMarshalType.CustomMarshaler; string text = ((customMarshaler == null) ? string.Empty : FullNameFactory.AssemblyQualifiedName(customMarshaler, this)); Write(text); Write(customMarshalType.Cookie); break; } case NativeType.IUnknown: case NativeType.IDispatch: case NativeType.IntF: { InterfaceMarshalType interfaceMarshalType = (InterfaceMarshalType)marshalType; if (interfaceMarshalType.IsIidParamIndexValid) { WriteCompressedUInt32((uint)interfaceMarshalType.IidParamIndex); } break; } case NativeType.RawBlob: { byte[] data = ((RawMarshalType)marshalType).Data; if (data != null) { writer.WriteBytes(data); } break; } } return outStream.ToArray(); } private bool UpdateCanWrite(bool isValid, string field, ref bool canWriteMore) { if (!canWriteMore) { if (isValid) { helper.Error2("MarshalType field {0} is valid even though a previous field was invalid.", field); } return canWriteMore; } if (!isValid) { canWriteMore = false; } return canWriteMore; } private uint WriteCompressedUInt32(uint value) { return writer.WriteCompressedUInt32(helper, value); } private void Write(UTF8String s) { writer.Write(helper, s); } public void Dispose() { outStream?.Dispose(); } bool IFullNameFactoryHelper.MustUseAssemblyName(IType type) { return FullNameFactory.MustUseAssemblyName(module, type, optimizeCustomAttributeSerializedTypeNames); } } public struct MaxStackCalculator { private IList instructions; private IList exceptionHandlers; private readonly Dictionary stackHeights; private bool hasError; private int currentMaxStack; public static uint GetMaxStack(IList instructions, IList exceptionHandlers) { new MaxStackCalculator(instructions, exceptionHandlers).Calculate(out var maxStack); return maxStack; } public static bool GetMaxStack(IList instructions, IList exceptionHandlers, out uint maxStack) { return new MaxStackCalculator(instructions, exceptionHandlers).Calculate(out maxStack); } internal static MaxStackCalculator Create() { return new MaxStackCalculator(dummy: true); } private MaxStackCalculator(bool dummy) { instructions = null; exceptionHandlers = null; stackHeights = new Dictionary(); hasError = false; currentMaxStack = 0; } private MaxStackCalculator(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; stackHeights = new Dictionary(); hasError = false; currentMaxStack = 0; } internal void Reset(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; stackHeights.Clear(); hasError = false; currentMaxStack = 0; } internal bool Calculate(out uint maxStack) { IList list = exceptionHandlers; Dictionary dictionary = stackHeights; for (int i = 0; i < list.Count; i++) { ExceptionHandler exceptionHandler = list[i]; if (exceptionHandler == null) { continue; } Instruction tryStart; if ((tryStart = exceptionHandler.TryStart) != null) { dictionary[tryStart] = 0; } if ((tryStart = exceptionHandler.FilterStart) != null) { dictionary[tryStart] = 1; currentMaxStack = 1; } if ((tryStart = exceptionHandler.HandlerStart) != null) { if (exceptionHandler.IsCatch || exceptionHandler.IsFilter) { dictionary[tryStart] = 1; currentMaxStack = 1; } else { dictionary[tryStart] = 0; } } } int value = 0; bool flag = false; IList list2 = instructions; for (int j = 0; j < list2.Count; j++) { Instruction instruction = list2[j]; if (instruction == null) { continue; } if (flag) { dictionary.TryGetValue(instruction, out value); flag = false; } value = WriteStack(instruction, value); dnlib.DotNet.Emit.OpCode opCode = instruction.OpCode; Code code = opCode.Code; if (code == Code.Jmp) { if (value != 0) { hasError = true; } } else { instruction.CalculateStackUsage(out var pushes, out var pops); if (pops == -1) { value = 0; } else { value -= pops; if (value < 0) { hasError = true; value = 0; } value += pushes; } } if (value < 0) { hasError = true; value = 0; } switch (opCode.FlowControl) { case dnlib.DotNet.Emit.FlowControl.Branch: WriteStack(instruction.Operand as Instruction, value); flag = true; break; case dnlib.DotNet.Emit.FlowControl.Call: if (code == Code.Jmp) { flag = true; } break; case dnlib.DotNet.Emit.FlowControl.Cond_Branch: if (code == Code.Switch) { if (instruction.Operand is IList list3) { for (int k = 0; k < list3.Count; k++) { WriteStack(list3[k], value); } } } else { WriteStack(instruction.Operand as Instruction, value); } break; case dnlib.DotNet.Emit.FlowControl.Return: case dnlib.DotNet.Emit.FlowControl.Throw: flag = true; break; } } maxStack = (uint)currentMaxStack; return !hasError; } private int WriteStack(Instruction instr, int stack) { if (instr == null) { hasError = true; return stack; } Dictionary dictionary = stackHeights; if (dictionary.TryGetValue(instr, out var value)) { if (stack != value) { hasError = true; } return value; } dictionary[instr] = stack; if (stack > currentMaxStack) { currentMaxStack = stack; } return stack; } } public interface IMDTable { Table Table { get; } bool IsEmpty { get; } int Rows { get; } bool IsSorted { get; set; } bool IsReadOnly { get; } TableInfo TableInfo { get; set; } void SetReadOnly(); } public sealed class MDTable : IMDTable where TRow : struct { private readonly Table table; private readonly Dictionary cachedDict; private readonly List cached; private TableInfo tableInfo; private bool isSorted; private bool isReadOnly; public Table Table => table; public bool IsEmpty => cached.Count == 0; public int Rows => cached.Count; public bool IsSorted { get { return isSorted; } set { isSorted = value; } } public bool IsReadOnly => isReadOnly; public TableInfo TableInfo { get { return tableInfo; } set { tableInfo = value; } } public TRow this[uint rid] { get { return cached[(int)(rid - 1)]; } set { cached[(int)(rid - 1)] = value; } } public MDTable(Table table, IEqualityComparer equalityComparer) { this.table = table; cachedDict = new Dictionary(equalityComparer); cached = new List(); } public void SetReadOnly() { isReadOnly = true; } public uint Add(TRow row) { if (isReadOnly) { throw new ModuleWriterException($"Trying to modify table {table} after it's been set to read-only"); } if (cachedDict.TryGetValue(row, out var value)) { return value; } return Create(row); } public uint Create(TRow row) { if (isReadOnly) { throw new ModuleWriterException($"Trying to modify table {table} after it's been set to read-only"); } uint num = (uint)(cached.Count + 1); if (!cachedDict.ContainsKey(row)) { cachedDict[row] = num; } cached.Add(row); return num; } public void ReAddRows() { if (isReadOnly) { throw new ModuleWriterException($"Trying to modify table {table} after it's been set to read-only"); } cachedDict.Clear(); for (int i = 0; i < cached.Count; i++) { uint value = (uint)(i + 1); TRow key = cached[i]; if (!cachedDict.ContainsKey(key)) { cachedDict[key] = value; } } } public void Reset() { if (isReadOnly) { throw new ModuleWriterException($"Trying to modify table {table} after it's been set to read-only"); } cachedDict.Clear(); cached.Clear(); } } public static class MDTableWriter { public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; ColumnInfo columnInfo3 = columns[3]; ColumnInfo columnInfo4 = columns[4]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawModuleRow rawModuleRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawModuleRow.Generation); columnInfo.Write24(writer, stringsHeap.GetOffset(rawModuleRow.Name)); columnInfo2.Write24(writer, rawModuleRow.Mvid); columnInfo3.Write24(writer, rawModuleRow.EncId); columnInfo4.Write24(writer, rawModuleRow.EncBaseId); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawTypeRefRow rawTypeRefRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawTypeRefRow.ResolutionScope); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawTypeRefRow.Name)); columnInfo3.Write24(writer, stringsHeap.GetOffset(rawTypeRefRow.Namespace)); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; ColumnInfo columnInfo3 = columns[3]; ColumnInfo columnInfo4 = columns[4]; ColumnInfo columnInfo5 = columns[5]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawTypeDefRow rawTypeDefRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawTypeDefRow.Flags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawTypeDefRow.Name)); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawTypeDefRow.Namespace)); columnInfo3.Write24(writer, rawTypeDefRow.Extends); columnInfo4.Write24(writer, rawTypeDefRow.FieldList); columnInfo5.Write24(writer, rawTypeDefRow.MethodList); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Field); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawFieldRow rawFieldRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawFieldRow.Flags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawFieldRow.Name)); columnInfo2.Write24(writer, rawFieldRow.Signature); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Method); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[3]; ColumnInfo columnInfo2 = columns[4]; ColumnInfo columnInfo3 = columns[5]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawMethodRow rawMethodRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawMethodRow.RVA); writer.WriteUInt16(rawMethodRow.ImplFlags); writer.WriteUInt16(rawMethodRow.Flags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawMethodRow.Name)); columnInfo2.Write24(writer, rawMethodRow.Signature); columnInfo3.Write24(writer, rawMethodRow.ParamList); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Param); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawParamRow rawParamRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawParamRow.Flags); writer.WriteUInt16(rawParamRow.Sequence); columnInfo.Write24(writer, stringsHeap.GetOffset(rawParamRow.Name)); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawInterfaceImplRow rawInterfaceImplRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawInterfaceImplRow.Class); columnInfo2.Write24(writer, rawInterfaceImplRow.Interface); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawMemberRefRow rawMemberRefRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawMemberRefRow.Class); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawMemberRefRow.Name)); columnInfo3.Write24(writer, rawMemberRefRow.Signature); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[2]; ColumnInfo columnInfo2 = columns[3]; for (int i = 0; i < table.Rows; i++) { RawConstantRow rawConstantRow = table[(uint)(i + 1)]; writer.WriteByte(rawConstantRow.Type); writer.WriteByte(rawConstantRow.Padding); columnInfo.Write24(writer, rawConstantRow.Parent); columnInfo2.Write24(writer, rawConstantRow.Value); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; for (int i = 0; i < table.Rows; i++) { RawCustomAttributeRow rawCustomAttributeRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawCustomAttributeRow.Parent); columnInfo2.Write24(writer, rawCustomAttributeRow.Type); columnInfo3.Write24(writer, rawCustomAttributeRow.Value); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawFieldMarshalRow rawFieldMarshalRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawFieldMarshalRow.Parent); columnInfo2.Write24(writer, rawFieldMarshalRow.NativeType); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; for (int i = 0; i < table.Rows; i++) { RawDeclSecurityRow rawDeclSecurityRow = table[(uint)(i + 1)]; writer.WriteInt16(rawDeclSecurityRow.Action); columnInfo.Write24(writer, rawDeclSecurityRow.Parent); columnInfo2.Write24(writer, rawDeclSecurityRow.PermissionSet); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[2]; for (int i = 0; i < table.Rows; i++) { RawClassLayoutRow rawClassLayoutRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawClassLayoutRow.PackingSize); writer.WriteUInt32(rawClassLayoutRow.ClassSize); columnInfo.Write24(writer, rawClassLayoutRow.Parent); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[1]; for (int i = 0; i < table.Rows; i++) { RawFieldLayoutRow rawFieldLayoutRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawFieldLayoutRow.OffSet); columnInfo.Write24(writer, rawFieldLayoutRow.Field); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Signature); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawEventMapRow rawEventMapRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawEventMapRow.Parent); columnInfo2.Write24(writer, rawEventMapRow.EventList); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Event); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawEventRow rawEventRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawEventRow.EventFlags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawEventRow.Name)); columnInfo2.Write24(writer, rawEventRow.EventType); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawPropertyMapRow rawPropertyMapRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawPropertyMapRow.Parent); columnInfo2.Write24(writer, rawPropertyMapRow.PropertyList); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Property); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawPropertyRow rawPropertyRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawPropertyRow.PropFlags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawPropertyRow.Name)); columnInfo2.Write24(writer, rawPropertyRow.Type); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; for (int i = 0; i < table.Rows; i++) { RawMethodSemanticsRow rawMethodSemanticsRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawMethodSemanticsRow.Semantic); columnInfo.Write24(writer, rawMethodSemanticsRow.Method); columnInfo2.Write24(writer, rawMethodSemanticsRow.Association); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; for (int i = 0; i < table.Rows; i++) { RawMethodImplRow rawMethodImplRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawMethodImplRow.Class); columnInfo2.Write24(writer, rawMethodImplRow.MethodBody); columnInfo3.Write24(writer, rawMethodImplRow.MethodDeclaration); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, stringsHeap.GetOffset(table[(uint)(i + 1)].Name)); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[0]; for (int i = 0; i < table.Rows; i++) { columnInfo.Write24(writer, table[(uint)(i + 1)].Signature); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; ColumnInfo columnInfo3 = columns[3]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawImplMapRow rawImplMapRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawImplMapRow.MappingFlags); columnInfo.Write24(writer, rawImplMapRow.MemberForwarded); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawImplMapRow.ImportName)); columnInfo3.Write24(writer, rawImplMapRow.ImportScope); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[1]; for (int i = 0; i < table.Rows; i++) { RawFieldRVARow rawFieldRVARow = table[(uint)(i + 1)]; writer.WriteUInt32(rawFieldRVARow.RVA); columnInfo.Write24(writer, rawFieldRVARow.Field); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { for (int i = 0; i < table.Rows; i++) { RawENCLogRow rawENCLogRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawENCLogRow.Token); writer.WriteUInt32(rawENCLogRow.FuncCode); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { for (int i = 0; i < table.Rows; i++) { writer.WriteUInt32(table[(uint)(i + 1)].Token); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[6]; ColumnInfo columnInfo2 = columns[7]; ColumnInfo columnInfo3 = columns[8]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawAssemblyRow rawAssemblyRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawAssemblyRow.HashAlgId); writer.WriteUInt16(rawAssemblyRow.MajorVersion); writer.WriteUInt16(rawAssemblyRow.MinorVersion); writer.WriteUInt16(rawAssemblyRow.BuildNumber); writer.WriteUInt16(rawAssemblyRow.RevisionNumber); writer.WriteUInt32(rawAssemblyRow.Flags); columnInfo.Write24(writer, rawAssemblyRow.PublicKey); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawAssemblyRow.Name)); columnInfo3.Write24(writer, stringsHeap.GetOffset(rawAssemblyRow.Locale)); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { for (int i = 0; i < table.Rows; i++) { writer.WriteUInt32(table[(uint)(i + 1)].Processor); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { for (int i = 0; i < table.Rows; i++) { RawAssemblyOSRow rawAssemblyOSRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawAssemblyOSRow.OSPlatformId); writer.WriteUInt32(rawAssemblyOSRow.OSMajorVersion); writer.WriteUInt32(rawAssemblyOSRow.OSMinorVersion); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[5]; ColumnInfo columnInfo2 = columns[6]; ColumnInfo columnInfo3 = columns[7]; ColumnInfo columnInfo4 = columns[8]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawAssemblyRefRow rawAssemblyRefRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawAssemblyRefRow.MajorVersion); writer.WriteUInt16(rawAssemblyRefRow.MinorVersion); writer.WriteUInt16(rawAssemblyRefRow.BuildNumber); writer.WriteUInt16(rawAssemblyRefRow.RevisionNumber); writer.WriteUInt32(rawAssemblyRefRow.Flags); columnInfo.Write24(writer, rawAssemblyRefRow.PublicKeyOrToken); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawAssemblyRefRow.Name)); columnInfo3.Write24(writer, stringsHeap.GetOffset(rawAssemblyRefRow.Locale)); columnInfo4.Write24(writer, rawAssemblyRefRow.HashValue); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[1]; for (int i = 0; i < table.Rows; i++) { RawAssemblyRefProcessorRow rawAssemblyRefProcessorRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawAssemblyRefProcessorRow.Processor); columnInfo.Write24(writer, rawAssemblyRefProcessorRow.AssemblyRef); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[3]; for (int i = 0; i < table.Rows; i++) { RawAssemblyRefOSRow rawAssemblyRefOSRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawAssemblyRefOSRow.OSPlatformId); writer.WriteUInt32(rawAssemblyRefOSRow.OSMajorVersion); writer.WriteUInt32(rawAssemblyRefOSRow.OSMinorVersion); columnInfo.Write24(writer, rawAssemblyRefOSRow.AssemblyRef); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[1]; ColumnInfo columnInfo2 = columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawFileRow rawFileRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawFileRow.Flags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawFileRow.Name)); columnInfo2.Write24(writer, rawFileRow.HashValue); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[2]; ColumnInfo columnInfo2 = columns[3]; ColumnInfo columnInfo3 = columns[4]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawExportedTypeRow rawExportedTypeRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawExportedTypeRow.Flags); writer.WriteUInt32(rawExportedTypeRow.TypeDefId); columnInfo.Write24(writer, stringsHeap.GetOffset(rawExportedTypeRow.TypeName)); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawExportedTypeRow.TypeNamespace)); columnInfo3.Write24(writer, rawExportedTypeRow.Implementation); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[2]; ColumnInfo columnInfo2 = columns[3]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawManifestResourceRow rawManifestResourceRow = table[(uint)(i + 1)]; writer.WriteUInt32(rawManifestResourceRow.Offset); writer.WriteUInt32(rawManifestResourceRow.Flags); columnInfo.Write24(writer, stringsHeap.GetOffset(rawManifestResourceRow.Name)); columnInfo2.Write24(writer, rawManifestResourceRow.Implementation); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawNestedClassRow rawNestedClassRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawNestedClassRow.NestedClass); columnInfo2.Write24(writer, rawNestedClassRow.EnclosingClass); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[2]; ColumnInfo columnInfo2 = columns[3]; StringsHeap stringsHeap = metadata.StringsHeap; if (columns.Length >= 5) { ColumnInfo columnInfo3 = columns[4]; for (int i = 0; i < table.Rows; i++) { RawGenericParamRow rawGenericParamRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawGenericParamRow.Number); writer.WriteUInt16(rawGenericParamRow.Flags); columnInfo.Write24(writer, rawGenericParamRow.Owner); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawGenericParamRow.Name)); columnInfo3.Write24(writer, rawGenericParamRow.Kind); } } else { for (int j = 0; j < table.Rows; j++) { RawGenericParamRow rawGenericParamRow2 = table[(uint)(j + 1)]; writer.WriteUInt16(rawGenericParamRow2.Number); writer.WriteUInt16(rawGenericParamRow2.Flags); columnInfo.Write24(writer, rawGenericParamRow2.Owner); columnInfo2.Write24(writer, stringsHeap.GetOffset(rawGenericParamRow2.Name)); } } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawMethodSpecRow rawMethodSpecRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawMethodSpecRow.Method); columnInfo2.Write24(writer, rawMethodSpecRow.Instantiation); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawGenericParamConstraintRow rawGenericParamConstraintRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawGenericParamConstraintRow.Owner); columnInfo2.Write24(writer, rawGenericParamConstraintRow.Constraint); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; ColumnInfo columnInfo4 = columns[3]; for (int i = 0; i < table.Rows; i++) { RawDocumentRow rawDocumentRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawDocumentRow.Name); columnInfo2.Write24(writer, rawDocumentRow.HashAlgorithm); columnInfo3.Write24(writer, rawDocumentRow.Hash); columnInfo4.Write24(writer, rawDocumentRow.Language); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawMethodDebugInformationRow rawMethodDebugInformationRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawMethodDebugInformationRow.Document); columnInfo2.Write24(writer, rawMethodDebugInformationRow.SequencePoints); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; ColumnInfo columnInfo4 = columns[3]; for (int i = 0; i < table.Rows; i++) { RawLocalScopeRow rawLocalScopeRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawLocalScopeRow.Method); columnInfo2.Write24(writer, rawLocalScopeRow.ImportScope); columnInfo3.Write24(writer, rawLocalScopeRow.VariableList); columnInfo4.Write24(writer, rawLocalScopeRow.ConstantList); writer.WriteUInt32(rawLocalScopeRow.StartOffset); writer.WriteUInt32(rawLocalScopeRow.Length); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo columnInfo = table.TableInfo.Columns[2]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawLocalVariableRow rawLocalVariableRow = table[(uint)(i + 1)]; writer.WriteUInt16(rawLocalVariableRow.Attributes); writer.WriteUInt16(rawLocalVariableRow.Index); columnInfo.Write24(writer, stringsHeap.GetOffset(rawLocalVariableRow.Name)); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; StringsHeap stringsHeap = metadata.StringsHeap; for (int i = 0; i < table.Rows; i++) { RawLocalConstantRow rawLocalConstantRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, stringsHeap.GetOffset(rawLocalConstantRow.Name)); columnInfo2.Write24(writer, rawLocalConstantRow.Signature); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawImportScopeRow rawImportScopeRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawImportScopeRow.Parent); columnInfo2.Write24(writer, rawImportScopeRow.Imports); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; for (int i = 0; i < table.Rows; i++) { RawStateMachineMethodRow rawStateMachineMethodRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawStateMachineMethodRow.MoveNextMethod); columnInfo2.Write24(writer, rawStateMachineMethodRow.KickoffMethod); } } public static void Write(this DataWriter writer, Metadata metadata, MDTable table) { ColumnInfo[] columns = table.TableInfo.Columns; ColumnInfo columnInfo = columns[0]; ColumnInfo columnInfo2 = columns[1]; ColumnInfo columnInfo3 = columns[2]; for (int i = 0; i < table.Rows; i++) { RawCustomDebugInformationRow rawCustomDebugInformationRow = table[(uint)(i + 1)]; columnInfo.Write24(writer, rawCustomDebugInformationRow.Parent); columnInfo2.Write24(writer, rawCustomDebugInformationRow.Kind); columnInfo3.Write24(writer, rawCustomDebugInformationRow.Value); } } } [Flags] public enum MetadataFlags : uint { PreserveTypeRefRids = 1u, PreserveTypeDefRids = 2u, PreserveFieldRids = 4u, PreserveMethodRids = 8u, PreserveParamRids = 0x10u, PreserveMemberRefRids = 0x20u, PreserveStandAloneSigRids = 0x40u, PreserveEventRids = 0x80u, PreservePropertyRids = 0x100u, PreserveTypeSpecRids = 0x200u, PreserveMethodSpecRids = 0x400u, PreserveAllMethodRids = 0x428u, PreserveRids = 0x7FFu, PreserveStringsOffsets = 0x800u, PreserveUSOffsets = 0x1000u, PreserveBlobOffsets = 0x2000u, PreserveExtraSignatureData = 0x4000u, PreserveAll = 0x7FFFu, KeepOldMaxStack = 0x8000u, AlwaysCreateGuidHeap = 0x10000u, AlwaysCreateStringsHeap = 0x20000u, AlwaysCreateUSHeap = 0x40000u, AlwaysCreateBlobHeap = 0x80000u, RoslynSortInterfaceImpl = 0x100000u, NoMethodBodies = 0x200000u, NoDotNetResources = 0x400000u, NoFieldData = 0x800000u, OptimizeCustomAttributeSerializedTypeNames = 0x1000000u } public readonly struct MetadataHeapsAddedEventArgs { public Metadata Metadata { get; } public List Heaps { get; } public MetadataHeapsAddedEventArgs(Metadata metadata, List heaps) { Metadata = metadata ?? throw new ArgumentNullException("metadata"); Heaps = heaps ?? throw new ArgumentNullException("heaps"); } } public sealed class MetadataOptions { private MetadataHeaderOptions metadataHeaderOptions; private MetadataHeaderOptions debugMetadataHeaderOptions; private TablesHeapOptions tablesHeapOptions; private List customHeaps; public MetadataFlags Flags; public MetadataHeaderOptions MetadataHeaderOptions { get { return metadataHeaderOptions ?? (metadataHeaderOptions = new MetadataHeaderOptions()); } set { metadataHeaderOptions = value; } } public MetadataHeaderOptions DebugMetadataHeaderOptions { get { return debugMetadataHeaderOptions ?? (debugMetadataHeaderOptions = MetadataHeaderOptions.CreatePortablePdbV1_0()); } set { debugMetadataHeaderOptions = value; } } public TablesHeapOptions TablesHeapOptions { get { return tablesHeapOptions ?? (tablesHeapOptions = new TablesHeapOptions()); } set { tablesHeapOptions = value; } } public TablesHeapOptions DebugTablesHeapOptions { get { return tablesHeapOptions ?? (tablesHeapOptions = TablesHeapOptions.CreatePortablePdbV1_0()); } set { tablesHeapOptions = value; } } public List CustomHeaps => customHeaps ?? (customHeaps = new List()); public event EventHandler2 MetadataHeapsAdded; internal void RaiseMetadataHeapsAdded(MetadataHeapsAddedEventArgs e) { this.MetadataHeapsAdded?.Invoke(e.Metadata, e); } public void PreserveHeapOrder(ModuleDef module, bool addCustomHeaps) { if (module == null) { throw new ArgumentNullException("module"); } if (!(module is ModuleDefMD moduleDefMD)) { return; } if (addCustomHeaps) { IEnumerable source = from a in moduleDefMD.Metadata.AllStreams where a.GetType() == typeof(CustomDotNetStream) select new DataReaderHeap(a); CustomHeaps.AddRange(source.OfType()); } Dictionary streamToOrder = new Dictionary(moduleDefMD.Metadata.AllStreams.Count); int num = 0; int num2 = 0; for (; num < moduleDefMD.Metadata.AllStreams.Count; num++) { DotNetStream dotNetStream = moduleDefMD.Metadata.AllStreams[num]; if (dotNetStream.StartOffset != 0) { streamToOrder.Add(dotNetStream, num2++); } } Dictionary nameToOrder = new Dictionary(moduleDefMD.Metadata.AllStreams.Count, StringComparer.Ordinal); int num3 = 0; int num4 = 0; for (; num3 < moduleDefMD.Metadata.AllStreams.Count; num3++) { DotNetStream dotNetStream2 = moduleDefMD.Metadata.AllStreams[num3]; if (dotNetStream2.StartOffset != 0) { bool flag = dotNetStream2 is BlobStream || dotNetStream2 is GuidStream || dotNetStream2 is PdbStream || dotNetStream2 is StringsStream || dotNetStream2 is TablesStream || dotNetStream2 is USStream; if (!nameToOrder.ContainsKey(dotNetStream2.Name) || flag) { nameToOrder[dotNetStream2.Name] = num4; } num4++; } } MetadataHeapsAdded += delegate(object s, MetadataHeapsAddedEventArgs e) { e.Heaps.Sort(delegate(IHeap a, IHeap b) { int order = GetOrder(streamToOrder, nameToOrder, a); int order2 = GetOrder(streamToOrder, nameToOrder, b); int num5 = order - order2; return (num5 != 0) ? num5 : StringComparer.Ordinal.Compare(a.Name, b.Name); }); }; } private static int GetOrder(Dictionary streamToOrder, Dictionary nameToOrder, IHeap heap) { if (heap is DataReaderHeap { OptionalOriginalStream: { } optionalOriginalStream } && streamToOrder.TryGetValue(optionalOriginalStream, out var value)) { return value; } if (nameToOrder.TryGetValue(heap.Name, out value)) { return value; } return int.MaxValue; } public MetadataOptions() { } public MetadataOptions(MetadataFlags flags) { Flags = flags; } public MetadataOptions(MetadataHeaderOptions mdhOptions) { metadataHeaderOptions = mdhOptions; } public MetadataOptions(MetadataHeaderOptions mdhOptions, MetadataFlags flags) { Flags = flags; metadataHeaderOptions = mdhOptions; } } internal sealed class DataWriterContext { public readonly MemoryStream OutStream; public readonly DataWriter Writer; public DataWriterContext() { OutStream = new MemoryStream(); Writer = new DataWriter(OutStream); } } public enum DebugMetadataKind { None, Standalone } public readonly struct MetadataWriterEventArgs { public Metadata Metadata { get; } public MetadataEvent Event { get; } public MetadataWriterEventArgs(Metadata metadata, MetadataEvent @event) { Metadata = metadata ?? throw new ArgumentNullException("metadata"); Event = @event; } } public readonly struct MetadataProgressEventArgs { public Metadata Metadata { get; } public double Progress { get; } public MetadataProgressEventArgs(Metadata metadata, double progress) { if (progress < 0.0 || progress > 1.0) { throw new ArgumentOutOfRangeException("progress"); } Metadata = metadata ?? throw new ArgumentNullException("metadata"); Progress = progress; } } public abstract class Metadata : IReuseChunk, IChunk, ISignatureWriterHelper, IWriterError, ITokenProvider, ICustomAttributeWriterHelper, IFullNameFactoryHelper, IPortablePdbCustomDebugInfoWriterHelper, IWriterError2 { internal sealed class SortedRows where T : class where TRow : struct { public struct Info { public readonly T data; public TRow row; public Info(T data, ref TRow row) { this.data = data; this.row = row; } } public List infos = new List(); private Dictionary toRid = new Dictionary(); private bool isSorted; public void Add(T data, TRow row) { if (isSorted) { throw new ModuleWriterException($"Adding a row after it's been sorted. Table: {row.GetType()}"); } infos.Add(new Info(data, ref row)); toRid[data] = (uint)(toRid.Count + 1); } public void Sort(Comparison comparison) { infos.Sort(CreateComparison(comparison)); toRid.Clear(); for (int i = 0; i < infos.Count; i++) { toRid[infos[i].data] = (uint)(i + 1); } isSorted = true; } private Comparison CreateComparison(Comparison comparison) { return delegate(Info a, Info b) { int num = comparison(a, b); return (num != 0) ? num : toRid[a.data].CompareTo(toRid[b.data]); }; } public uint Rid(T data) { return toRid[data]; } public bool TryGetRid(T data, out uint rid) { if (data == null) { rid = 0u; return false; } return toRid.TryGetValue(data, out rid); } } internal sealed class Rows where T : class { private Dictionary dict = new Dictionary(); public int Count => dict.Count; public bool TryGetRid(T value, out uint rid) { if (value == null) { rid = 0u; return false; } return dict.TryGetValue(value, out rid); } public bool Exists(T value) { return dict.ContainsKey(value); } public void Add(T value, uint rid) { dict.Add(value, rid); } public uint Rid(T value) { return dict[value]; } public void SetRid(T value, uint rid) { dict[value] = rid; } } private struct MethodScopeDebugInfo { public uint MethodRid; public PdbScope Scope; public uint ScopeStart; public uint ScopeLength; } private uint length; private FileOffset offset; private RVA rva; private readonly MetadataOptions options; private ILogger logger; private readonly MetadataErrorContext errorContext; private readonly NormalMetadata debugMetadata; private readonly bool isStandaloneDebugMetadata; internal readonly ModuleDef module; internal readonly UniqueChunkList constants; internal readonly MethodBodyChunks methodBodies; internal readonly NetResources netResources; internal readonly MetadataHeader metadataHeader; internal readonly PdbHeap pdbHeap; internal readonly TablesHeap tablesHeap; internal readonly StringsHeap stringsHeap; internal readonly USHeap usHeap; internal readonly GuidHeap guidHeap; internal readonly BlobHeap blobHeap; internal TypeDef[] allTypeDefs; internal readonly Rows moduleDefInfos = new Rows(); internal readonly SortedRows interfaceImplInfos = new SortedRows(); internal readonly SortedRows hasConstantInfos = new SortedRows(); internal readonly SortedRows customAttributeInfos = new SortedRows(); internal readonly SortedRows fieldMarshalInfos = new SortedRows(); internal readonly SortedRows declSecurityInfos = new SortedRows(); internal readonly SortedRows classLayoutInfos = new SortedRows(); internal readonly SortedRows fieldLayoutInfos = new SortedRows(); internal readonly Rows eventMapInfos = new Rows(); internal readonly Rows propertyMapInfos = new Rows(); internal readonly SortedRows methodSemanticsInfos = new SortedRows(); internal readonly SortedRows methodImplInfos = new SortedRows(); internal readonly Rows moduleRefInfos = new Rows(); internal readonly SortedRows implMapInfos = new SortedRows(); internal readonly SortedRows fieldRVAInfos = new SortedRows(); internal readonly Rows assemblyInfos = new Rows(); internal readonly Rows assemblyRefInfos = new Rows(); internal readonly Rows fileDefInfos = new Rows(); internal readonly Rows exportedTypeInfos = new Rows(); internal readonly Rows manifestResourceInfos = new Rows(); internal readonly SortedRows nestedClassInfos = new SortedRows(); internal readonly SortedRows genericParamInfos = new SortedRows(); internal readonly SortedRows genericParamConstraintInfos = new SortedRows(); internal readonly Dictionary methodToBody = new Dictionary(); internal readonly Dictionary methodToNativeBody = new Dictionary(); internal readonly Dictionary embeddedResourceToByteArray = new Dictionary(); private readonly Dictionary fieldToInitialValue = new Dictionary(); private readonly Rows pdbDocumentInfos = new Rows(); private bool methodDebugInformationInfosUsed; private readonly SortedRows localScopeInfos = new SortedRows(); private readonly Rows localVariableInfos = new Rows(); private readonly Rows localConstantInfos = new Rows(); private readonly Rows importScopeInfos = new Rows(); private readonly SortedRows stateMachineMethodInfos = new SortedRows(); private readonly SortedRows customDebugInfos = new SortedRows(); private readonly List binaryWriterContexts = new List(); private readonly List serializerMethodContexts = new List(); private readonly List exportedMethods = new List(); private static readonly double[] eventToProgress = new double[15] { 0.0, 0.00134240009466231, 0.00257484711254305, 0.0762721800615359, 0.196633787905108, 0.207788892253819, 0.270543867900699, 0.451478814851716, 0.451478949929206, 0.454664752528583, 0.454664887606073, 0.992591810143725, 0.999984331011171, 1.0, 1.0 }; private static readonly byte[] constantClassByteArray = new byte[4]; private static readonly byte[] constantDefaultByteArray = new byte[8]; private static readonly byte[] directorySeparatorCharUtf8 = Encoding.UTF8.GetBytes(Path.DirectorySeparatorChar.ToString()); private static readonly char[] directorySeparatorCharArray = new char[1] { Path.DirectorySeparatorChar }; private const uint HEAP_ALIGNMENT = 4u; public ILogger Logger { get { return logger; } set { logger = value; } } public ModuleDef Module => module; public UniqueChunkList Constants => constants; public MethodBodyChunks MethodBodyChunks => methodBodies; public NetResources NetResources => netResources; public MetadataHeader MetadataHeader => metadataHeader; public TablesHeap TablesHeap => tablesHeap; public StringsHeap StringsHeap => stringsHeap; public USHeap USHeap => usHeap; public GuidHeap GuidHeap => guidHeap; public BlobHeap BlobHeap => blobHeap; public PdbHeap PdbHeap => pdbHeap; public List ExportedMethods => exportedMethods; internal byte[] AssemblyPublicKey { get; set; } public FileOffset FileOffset => offset; public RVA RVA => rva; public bool PreserveTypeRefRids => (options.Flags & MetadataFlags.PreserveTypeRefRids) != 0; public bool PreserveTypeDefRids => (options.Flags & MetadataFlags.PreserveTypeDefRids) != 0; public bool PreserveFieldRids => (options.Flags & MetadataFlags.PreserveFieldRids) != 0; public bool PreserveMethodRids => (options.Flags & MetadataFlags.PreserveMethodRids) != 0; public bool PreserveParamRids => (options.Flags & MetadataFlags.PreserveParamRids) != 0; public bool PreserveMemberRefRids => (options.Flags & MetadataFlags.PreserveMemberRefRids) != 0; public bool PreserveStandAloneSigRids => (options.Flags & MetadataFlags.PreserveStandAloneSigRids) != 0; public bool PreserveEventRids => (options.Flags & MetadataFlags.PreserveEventRids) != 0; public bool PreservePropertyRids => (options.Flags & MetadataFlags.PreservePropertyRids) != 0; public bool PreserveTypeSpecRids => (options.Flags & MetadataFlags.PreserveTypeSpecRids) != 0; public bool PreserveMethodSpecRids => (options.Flags & MetadataFlags.PreserveMethodSpecRids) != 0; public bool PreserveStringsOffsets { get { return (options.Flags & MetadataFlags.PreserveStringsOffsets) != 0; } set { if (value) { options.Flags |= MetadataFlags.PreserveStringsOffsets; } else { options.Flags &= ~MetadataFlags.PreserveStringsOffsets; } } } public bool PreserveUSOffsets { get { return (options.Flags & MetadataFlags.PreserveUSOffsets) != 0; } set { if (value) { options.Flags |= MetadataFlags.PreserveUSOffsets; } else { options.Flags &= ~MetadataFlags.PreserveUSOffsets; } } } public bool PreserveBlobOffsets { get { return (options.Flags & MetadataFlags.PreserveBlobOffsets) != 0; } set { if (value) { options.Flags |= MetadataFlags.PreserveBlobOffsets; } else { options.Flags &= ~MetadataFlags.PreserveBlobOffsets; } } } public bool PreserveExtraSignatureData { get { return (options.Flags & MetadataFlags.PreserveExtraSignatureData) != 0; } set { if (value) { options.Flags |= MetadataFlags.PreserveExtraSignatureData; } else { options.Flags &= ~MetadataFlags.PreserveExtraSignatureData; } } } public bool KeepOldMaxStack { get { return (options.Flags & MetadataFlags.KeepOldMaxStack) != 0; } set { if (value) { options.Flags |= MetadataFlags.KeepOldMaxStack; } else { options.Flags &= ~MetadataFlags.KeepOldMaxStack; } } } public bool AlwaysCreateGuidHeap { get { return (options.Flags & MetadataFlags.AlwaysCreateGuidHeap) != 0; } set { if (value) { options.Flags |= MetadataFlags.AlwaysCreateGuidHeap; } else { options.Flags &= ~MetadataFlags.AlwaysCreateGuidHeap; } } } public bool AlwaysCreateStringsHeap { get { return (options.Flags & MetadataFlags.AlwaysCreateStringsHeap) != 0; } set { if (value) { options.Flags |= MetadataFlags.AlwaysCreateStringsHeap; } else { options.Flags &= ~MetadataFlags.AlwaysCreateStringsHeap; } } } public bool AlwaysCreateUSHeap { get { return (options.Flags & MetadataFlags.AlwaysCreateUSHeap) != 0; } set { if (value) { options.Flags |= MetadataFlags.AlwaysCreateUSHeap; } else { options.Flags &= ~MetadataFlags.AlwaysCreateUSHeap; } } } public bool AlwaysCreateBlobHeap { get { return (options.Flags & MetadataFlags.AlwaysCreateBlobHeap) != 0; } set { if (value) { options.Flags |= MetadataFlags.AlwaysCreateBlobHeap; } else { options.Flags &= ~MetadataFlags.AlwaysCreateBlobHeap; } } } public bool RoslynSortInterfaceImpl { get { return (options.Flags & MetadataFlags.RoslynSortInterfaceImpl) != 0; } set { if (value) { options.Flags |= MetadataFlags.RoslynSortInterfaceImpl; } else { options.Flags &= ~MetadataFlags.RoslynSortInterfaceImpl; } } } public bool NoMethodBodies { get { return (options.Flags & MetadataFlags.NoMethodBodies) != 0; } set { if (value) { options.Flags |= MetadataFlags.NoMethodBodies; } else { options.Flags &= ~MetadataFlags.NoMethodBodies; } } } public bool NoDotNetResources { get { return (options.Flags & MetadataFlags.NoDotNetResources) != 0; } set { if (value) { options.Flags |= MetadataFlags.NoDotNetResources; } else { options.Flags &= ~MetadataFlags.NoDotNetResources; } } } public bool NoFieldData { get { return (options.Flags & MetadataFlags.NoFieldData) != 0; } set { if (value) { options.Flags |= MetadataFlags.NoFieldData; } else { options.Flags &= ~MetadataFlags.NoFieldData; } } } public bool OptimizeCustomAttributeSerializedTypeNames { get { return (options.Flags & MetadataFlags.OptimizeCustomAttributeSerializedTypeNames) != 0; } set { if (value) { options.Flags |= MetadataFlags.OptimizeCustomAttributeSerializedTypeNames; } else { options.Flags &= ~MetadataFlags.OptimizeCustomAttributeSerializedTypeNames; } } } internal bool KeepFieldRVA { get; set; } protected abstract int NumberOfMethods { get; } public event EventHandler2 MetadataEvent; public event EventHandler2 ProgressUpdated; public static Metadata Create(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetadataOptions options = null, DebugMetadataKind debugKind = DebugMetadataKind.None) { if (options == null) { options = new MetadataOptions(); } if ((options.Flags & MetadataFlags.PreserveRids) != 0 && module is ModuleDefMD) { return new PreserveTokensMetadata(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata: false); } return new NormalMetadata(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata: false); } internal Metadata(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetadataOptions options, DebugMetadataKind debugKind, bool isStandaloneDebugMetadata) { this.module = module; this.constants = constants; this.methodBodies = methodBodies; this.netResources = netResources; this.options = options ?? new MetadataOptions(); metadataHeader = new MetadataHeader(isStandaloneDebugMetadata ? this.options.DebugMetadataHeaderOptions : this.options.MetadataHeaderOptions); tablesHeap = new TablesHeap(this, isStandaloneDebugMetadata ? this.options.DebugTablesHeapOptions : this.options.TablesHeapOptions); stringsHeap = new StringsHeap(); usHeap = new USHeap(); guidHeap = new GuidHeap(); blobHeap = new BlobHeap(); pdbHeap = new PdbHeap(); errorContext = new MetadataErrorContext(); this.isStandaloneDebugMetadata = isStandaloneDebugMetadata; switch (debugKind) { case DebugMetadataKind.Standalone: debugMetadata = new NormalMetadata(module, constants, methodBodies, netResources, options, DebugMetadataKind.None, isStandaloneDebugMetadata: true); break; default: throw new ArgumentOutOfRangeException("debugKind"); case DebugMetadataKind.None: break; } } public uint GetRid(ModuleDef module) { moduleDefInfos.TryGetRid(module, out var rid); return rid; } public abstract uint GetRid(TypeRef tr); public abstract uint GetRid(TypeDef td); public abstract uint GetRid(FieldDef fd); public abstract uint GetRid(MethodDef md); public abstract uint GetRid(ParamDef pd); public uint GetRid(InterfaceImpl ii) { interfaceImplInfos.TryGetRid(ii, out var rid); return rid; } public abstract uint GetRid(MemberRef mr); public uint GetConstantRid(IHasConstant hc) { hasConstantInfos.TryGetRid(hc, out var rid); return rid; } public uint GetCustomAttributeRid(CustomAttribute ca) { customAttributeInfos.TryGetRid(ca, out var rid); return rid; } public uint GetFieldMarshalRid(IHasFieldMarshal hfm) { fieldMarshalInfos.TryGetRid(hfm, out var rid); return rid; } public uint GetRid(DeclSecurity ds) { declSecurityInfos.TryGetRid(ds, out var rid); return rid; } public uint GetClassLayoutRid(TypeDef td) { classLayoutInfos.TryGetRid(td, out var rid); return rid; } public uint GetFieldLayoutRid(FieldDef fd) { fieldLayoutInfos.TryGetRid(fd, out var rid); return rid; } public abstract uint GetRid(StandAloneSig sas); public uint GetEventMapRid(TypeDef td) { eventMapInfos.TryGetRid(td, out var rid); return rid; } public abstract uint GetRid(EventDef ed); public uint GetPropertyMapRid(TypeDef td) { propertyMapInfos.TryGetRid(td, out var rid); return rid; } public abstract uint GetRid(PropertyDef pd); public uint GetMethodSemanticsRid(MethodDef md) { methodSemanticsInfos.TryGetRid(md, out var rid); return rid; } public uint GetRid(ModuleRef mr) { moduleRefInfos.TryGetRid(mr, out var rid); return rid; } public abstract uint GetRid(TypeSpec ts); public uint GetImplMapRid(IMemberForwarded mf) { implMapInfos.TryGetRid(mf, out var rid); return rid; } public uint GetFieldRVARid(FieldDef fd) { fieldRVAInfos.TryGetRid(fd, out var rid); return rid; } public uint GetRid(AssemblyDef asm) { assemblyInfos.TryGetRid(asm, out var rid); return rid; } public uint GetRid(AssemblyRef asmRef) { assemblyRefInfos.TryGetRid(asmRef, out var rid); return rid; } public uint GetRid(FileDef fd) { fileDefInfos.TryGetRid(fd, out var rid); return rid; } public uint GetRid(ExportedType et) { exportedTypeInfos.TryGetRid(et, out var rid); return rid; } public uint GetManifestResourceRid(Resource resource) { manifestResourceInfos.TryGetRid(resource, out var rid); return rid; } public uint GetNestedClassRid(TypeDef td) { nestedClassInfos.TryGetRid(td, out var rid); return rid; } public uint GetRid(GenericParam gp) { genericParamInfos.TryGetRid(gp, out var rid); return rid; } public abstract uint GetRid(MethodSpec ms); public uint GetRid(GenericParamConstraint gpc) { genericParamConstraintInfos.TryGetRid(gpc, out var rid); return rid; } public uint GetRid(PdbDocument doc) { if (debugMetadata == null) { return 0u; } debugMetadata.pdbDocumentInfos.TryGetRid(doc, out var rid); return rid; } public uint GetRid(PdbScope scope) { if (debugMetadata == null) { return 0u; } debugMetadata.localScopeInfos.TryGetRid(scope, out var rid); return rid; } public uint GetRid(PdbLocal local) { if (debugMetadata == null) { return 0u; } debugMetadata.localVariableInfos.TryGetRid(local, out var rid); return rid; } public uint GetRid(PdbConstant constant) { if (debugMetadata == null) { return 0u; } debugMetadata.localConstantInfos.TryGetRid(constant, out var rid); return rid; } public uint GetRid(PdbImportScope importScope) { if (debugMetadata == null) { return 0u; } debugMetadata.importScopeInfos.TryGetRid(importScope, out var rid); return rid; } public uint GetStateMachineMethodRid(PdbAsyncMethodCustomDebugInfo asyncMethod) { if (debugMetadata == null) { return 0u; } debugMetadata.stateMachineMethodInfos.TryGetRid(asyncMethod, out var rid); return rid; } public uint GetStateMachineMethodRid(PdbIteratorMethodCustomDebugInfo iteratorMethod) { if (debugMetadata == null) { return 0u; } debugMetadata.stateMachineMethodInfos.TryGetRid(iteratorMethod, out var rid); return rid; } public uint GetCustomDebugInfoRid(PdbCustomDebugInfo cdi) { if (debugMetadata == null) { return 0u; } debugMetadata.customDebugInfos.TryGetRid(cdi, out var rid); return rid; } public MethodBody GetMethodBody(MethodDef md) { if (md == null) { return null; } methodToBody.TryGetValue(md, out var value); return value; } public uint GetLocalVarSigToken(MethodDef md) { return GetMethodBody(md)?.LocalVarSigTok ?? 0; } public DataReaderChunk GetChunk(EmbeddedResource er) { if (er == null) { return null; } embeddedResourceToByteArray.TryGetValue(er, out var value); return value; } public ByteArrayChunk GetInitialValueChunk(FieldDef fd) { if (fd == null) { return null; } fieldToInitialValue.TryGetValue(fd, out var value); return value; } private ILogger GetLogger() { return logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } protected void Error(string message, params object[] args) { errorContext.Append("Error", ref message, ref args); GetLogger().Log(this, LoggerEvent.Error, message, args); } protected void Warning(string message, params object[] args) { errorContext.Append("Warning", ref message, ref args); GetLogger().Log(this, LoggerEvent.Warning, message, args); } protected void OnMetadataEvent(MetadataEvent evt) { errorContext.Event = evt; RaiseProgress(evt, 0.0); this.MetadataEvent?.Invoke(this, new MetadataWriterEventArgs(this, evt)); } protected void RaiseProgress(MetadataEvent evt, double subProgress) { subProgress = Math.Min(1.0, Math.Max(0.0, subProgress)); double num = eventToProgress[(int)evt]; double num2 = eventToProgress[(int)(evt + 1)]; double val = num + (num2 - num) * subProgress; val = Math.Min(1.0, Math.Max(0.0, val)); this.ProgressUpdated?.Invoke(this, new MetadataProgressEventArgs(this, val)); } public void CreateTables() { OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.BeginCreateTables); if (module.Types.Count == 0 || module.Types[0] == null) { throw new ModuleWriterException("Missing global type"); } if (module is ModuleDefMD moduleDefMD) { if (PreserveStringsOffsets) { stringsHeap.Populate(moduleDefMD.StringsStream); } if (PreserveUSOffsets) { usHeap.Populate(moduleDefMD.USStream); } if (PreserveBlobOffsets) { blobHeap.Populate(moduleDefMD.BlobStream); } } Create(); } private void UpdateMethodRvas() { foreach (KeyValuePair item in methodToBody) { MethodDef key = item.Key; MethodBody value = item.Value; uint rid = GetRid(key); RawMethodRow rawMethodRow = tablesHeap.MethodTable[rid]; rawMethodRow = new RawMethodRow((uint)value.RVA, rawMethodRow.ImplFlags, rawMethodRow.Flags, rawMethodRow.Name, rawMethodRow.Signature, rawMethodRow.ParamList); tablesHeap.MethodTable[rid] = rawMethodRow; } foreach (KeyValuePair item2 in methodToNativeBody) { MethodDef key2 = item2.Key; NativeMethodBody value2 = item2.Value; uint rid2 = GetRid(key2); RawMethodRow rawMethodRow2 = tablesHeap.MethodTable[rid2]; rawMethodRow2 = new RawMethodRow((uint)value2.RVA, rawMethodRow2.ImplFlags, rawMethodRow2.Flags, rawMethodRow2.Name, rawMethodRow2.Signature, rawMethodRow2.ParamList); tablesHeap.MethodTable[rid2] = rawMethodRow2; } } private void UpdateFieldRvas() { foreach (KeyValuePair item in fieldToInitialValue) { FieldDef key = item.Key; ByteArrayChunk value = item.Value; uint rid = fieldRVAInfos.Rid(key); RawFieldRVARow rawFieldRVARow = tablesHeap.FieldRVATable[rid]; rawFieldRVARow = new RawFieldRVARow((uint)value.RVA, rawFieldRVARow.Field); tablesHeap.FieldRVATable[rid] = rawFieldRVARow; } } private void Create() { Initialize(); allTypeDefs = GetAllTypeDefs(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.AllocateTypeDefRids); AllocateTypeDefRids(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids); AllocateMemberDefRids(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.MemberDefRidsAllocated); AddModule(module); AddPdbDocuments(); InitializeMethodDebugInformation(); InitializeTypeDefsAndMemberDefs(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.MemberDefsInitialized); InitializeVTableFixups(); AddExportedTypes(); InitializeEntryPoint(); if (module.Assembly != null) { AddAssembly(module.Assembly, AssemblyPublicKey); } OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.BeforeSortTables); SortTables(); InitializeGenericParamConstraintTable(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.MostTablesSorted); WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.MemberDefCustomAttributesWritten); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.BeginAddResources); AddResources(module.Resources); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.EndAddResources); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.BeginWriteMethodBodies); WriteMethodBodies(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.EndWriteMethodBodies); BeforeSortingCustomAttributes(); InitializeCustomAttributeAndCustomDebugInfoTables(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.OnAllTablesSorted); EverythingInitialized(); OnMetadataEvent(dnlib.DotNet.Writer.MetadataEvent.EndCreateTables); } private void InitializeTypeDefsAndMemberDefs() { int num = allTypeDefs.Length; int num2 = 0; int num3 = 0; int num4 = num / 5; TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { using (errorContext.SetSource(typeDef)) { if (num2++ == num4 && num3 < 5) { RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.MemberDefRidsAllocated, (double)num2 / (double)num); num3++; num4 = (int)((double)num / 5.0 * (double)(num3 + 1)); } if (typeDef == null) { Error("TypeDef is null"); continue; } uint rid = GetRid(typeDef); RawTypeDefRow rawTypeDefRow = tablesHeap.TypeDefTable[rid]; rawTypeDefRow = new RawTypeDefRow((uint)typeDef.Attributes, stringsHeap.Add(typeDef.Name), stringsHeap.Add(typeDef.Namespace), (typeDef.BaseType != null) ? AddTypeDefOrRef(typeDef.BaseType) : 0u, rawTypeDefRow.FieldList, rawTypeDefRow.MethodList); tablesHeap.TypeDefTable[rid] = rawTypeDefRow; AddGenericParams(new MDToken(Table.TypeDef, rid), typeDef.GenericParameters); AddDeclSecurities(new MDToken(Table.TypeDef, rid), typeDef.DeclSecurities); AddInterfaceImpls(rid, typeDef.Interfaces); AddClassLayout(typeDef); AddNestedType(typeDef, typeDef.DeclaringType); IList fields = typeDef.Fields; int count = fields.Count; for (int j = 0; j < count; j++) { FieldDef fieldDef = fields[j]; if (fieldDef == null) { Error("Field is null"); continue; } using (errorContext.SetSource(fieldDef)) { uint rid2 = GetRid(fieldDef); RawFieldRow value = new RawFieldRow((ushort)fieldDef.Attributes, stringsHeap.Add(fieldDef.Name), GetSignature(fieldDef.Signature)); tablesHeap.FieldTable[rid2] = value; AddFieldLayout(fieldDef); AddFieldMarshal(new MDToken(Table.Field, rid2), fieldDef); AddFieldRVA(fieldDef); AddImplMap(new MDToken(Table.Field, rid2), fieldDef); AddConstant(new MDToken(Table.Field, rid2), fieldDef); } } IList methods = typeDef.Methods; count = methods.Count; for (int k = 0; k < count; k++) { MethodDef methodDef = methods[k]; if (methodDef == null) { Error("Method is null"); continue; } using (errorContext.SetSource(methodDef)) { if (methodDef.ExportInfo != null) { ExportedMethods.Add(methodDef); } uint rid3 = GetRid(methodDef); RawMethodRow rawMethodRow = tablesHeap.MethodTable[rid3]; rawMethodRow = new RawMethodRow(rawMethodRow.RVA, (ushort)methodDef.ImplAttributes, (ushort)methodDef.Attributes, stringsHeap.Add(methodDef.Name), GetSignature(methodDef.Signature), rawMethodRow.ParamList); tablesHeap.MethodTable[rid3] = rawMethodRow; AddGenericParams(new MDToken(Table.Method, rid3), methodDef.GenericParameters); AddDeclSecurities(new MDToken(Table.Method, rid3), methodDef.DeclSecurities); AddImplMap(new MDToken(Table.Method, rid3), methodDef); AddMethodImpls(methodDef, methodDef.Overrides); IList paramDefs = methodDef.ParamDefs; int count2 = paramDefs.Count; for (int l = 0; l < count2; l++) { ParamDef paramDef = paramDefs[l]; if (paramDef == null) { Error("Param is null"); continue; } uint rid4 = GetRid(paramDef); RawParamRow value2 = new RawParamRow((ushort)paramDef.Attributes, paramDef.Sequence, stringsHeap.Add(paramDef.Name)); tablesHeap.ParamTable[rid4] = value2; AddConstant(new MDToken(Table.Param, rid4), paramDef); AddFieldMarshal(new MDToken(Table.Param, rid4), paramDef); } } } IList events = typeDef.Events; count = events.Count; for (int m = 0; m < count; m++) { EventDef eventDef = events[m]; if (eventDef == null) { Error("Event is null"); continue; } using (errorContext.SetSource(eventDef)) { uint rid5 = GetRid(eventDef); RawEventRow value3 = new RawEventRow((ushort)eventDef.Attributes, stringsHeap.Add(eventDef.Name), AddTypeDefOrRef(eventDef.EventType)); tablesHeap.EventTable[rid5] = value3; AddMethodSemantics(eventDef); } } IList properties = typeDef.Properties; count = properties.Count; for (int n = 0; n < count; n++) { PropertyDef propertyDef = properties[n]; if (propertyDef == null) { Error("Property is null"); continue; } using (errorContext.SetSource(propertyDef)) { uint rid6 = GetRid(propertyDef); RawPropertyRow value4 = new RawPropertyRow((ushort)propertyDef.Attributes, stringsHeap.Add(propertyDef.Name), GetSignature(propertyDef.Type)); tablesHeap.PropertyTable[rid6] = value4; AddConstant(new MDToken(Table.Property, rid6), propertyDef); AddMethodSemantics(propertyDef); } } } } } private void WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos() { int num = allTypeDefs.Length; int num2 = 0; int num3 = 0; int num4 = num / 5; TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { using (errorContext.SetSource(typeDef)) { if (num2++ == num4 && num3 < 5) { RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.MostTablesSorted, (double)num2 / (double)num); num3++; num4 = (int)((double)num / 5.0 * (double)(num3 + 1)); } if (typeDef == null) { continue; } if (typeDef.HasCustomAttributes || typeDef.HasCustomDebugInfos) { uint rid = GetRid(typeDef); AddCustomAttributes(Table.TypeDef, rid, typeDef); AddCustomDebugInformationList(Table.TypeDef, rid, typeDef); } IList fields = typeDef.Fields; int count = fields.Count; for (int j = 0; j < count; j++) { FieldDef fieldDef = fields[j]; if (fieldDef != null && (fieldDef.HasCustomAttributes || fieldDef.HasCustomDebugInfos)) { uint rid = GetRid(fieldDef); AddCustomAttributes(Table.Field, rid, fieldDef); AddCustomDebugInformationList(Table.Field, rid, fieldDef); } } IList methods = typeDef.Methods; count = methods.Count; for (int k = 0; k < count; k++) { MethodDef methodDef = methods[k]; if (methodDef == null) { continue; } using (errorContext.SetSource(methodDef)) { if (methodDef.HasCustomAttributes) { uint rid = GetRid(methodDef); AddCustomAttributes(Table.Method, rid, methodDef); } IList paramDefs = methodDef.ParamDefs; int count2 = paramDefs.Count; for (int l = 0; l < count2; l++) { ParamDef paramDef = paramDefs[l]; if (paramDef != null && (paramDef.HasCustomAttributes || paramDef.HasCustomDebugInfos)) { uint rid = GetRid(paramDef); AddCustomAttributes(Table.Param, rid, paramDef); AddCustomDebugInformationList(Table.Param, rid, paramDef); } } } } IList events = typeDef.Events; count = events.Count; for (int m = 0; m < count; m++) { EventDef eventDef = events[m]; if (eventDef != null && (eventDef.HasCustomAttributes || eventDef.HasCustomDebugInfos)) { uint rid = GetRid(eventDef); AddCustomAttributes(Table.Event, rid, eventDef); AddCustomDebugInformationList(Table.Event, rid, eventDef); } } IList properties = typeDef.Properties; count = properties.Count; for (int n = 0; n < count; n++) { PropertyDef propertyDef = properties[n]; if (propertyDef != null && (propertyDef.HasCustomAttributes || propertyDef.HasCustomDebugInfos)) { uint rid = GetRid(propertyDef); AddCustomAttributes(Table.Property, rid, propertyDef); AddCustomDebugInformationList(Table.Property, rid, propertyDef); } } } } } private void InitializeVTableFixups() { VTableFixups vTableFixups = module.VTableFixups; if (vTableFixups == null || vTableFixups.VTables.Count == 0) { return; } using (errorContext.SetSource("vtable fixups")) { foreach (VTable item in vTableFixups) { if (item == null) { Error("VTable is null"); continue; } foreach (IMethod item2 in item) { if (item2 != null) { AddMDTokenProvider(item2); } } } } } private void AddExportedTypes() { using (errorContext.SetSource("exported types")) { IList exportedTypes = module.ExportedTypes; Dictionary> dictionary = new Dictionary>(); for (int i = 0; i < exportedTypes.Count; i++) { ExportedType exportedType = exportedTypes[i]; if (exportedType.Implementation is ExportedType key) { if (!dictionary.TryGetValue(key, out var value)) { List list = (dictionary[key] = new List()); value = list; } value.Add(exportedType); } } List list3 = new List(exportedTypes.Count); Dictionary dictionary2 = new Dictionary(); Stack> stack = new Stack>(); stack.Push(exportedTypes.GetEnumerator()); while (stack.Count > 0) { IEnumerator enumerator = stack.Pop(); while (enumerator.MoveNext()) { ExportedType current = enumerator.Current; if (!dictionary2.ContainsKey(current)) { dictionary2[current] = true; list3.Add(current); if (dictionary.TryGetValue(current, out var value2) && value2.Count > 0) { stack.Push(enumerator); enumerator = value2.GetEnumerator(); } } } } int count = list3.Count; for (int j = 0; j < count; j++) { AddExportedType(list3[j]); } } } private void InitializeEntryPoint() { using (errorContext.SetSource("entry point")) { if (module.ManagedEntryPoint is FileDef file) { AddFile(file); } } } private void SortTables() { classLayoutInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); hasConstantInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); declSecurityInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); fieldLayoutInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Field.CompareTo(b.row.Field)); fieldMarshalInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); fieldRVAInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Field.CompareTo(b.row.Field)); implMapInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.MemberForwarded.CompareTo(b.row.MemberForwarded)); methodImplInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Class.CompareTo(b.row.Class)); methodSemanticsInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Association.CompareTo(b.row.Association)); nestedClassInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.NestedClass.CompareTo(b.row.NestedClass)); genericParamInfos.Sort((SortedRows.Info a, SortedRows.Info b) => (a.row.Owner != b.row.Owner) ? a.row.Owner.CompareTo(b.row.Owner) : a.row.Number.CompareTo(b.row.Number)); interfaceImplInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Class.CompareTo(b.row.Class)); tablesHeap.ClassLayoutTable.IsSorted = true; tablesHeap.ConstantTable.IsSorted = true; tablesHeap.DeclSecurityTable.IsSorted = true; tablesHeap.FieldLayoutTable.IsSorted = true; tablesHeap.FieldMarshalTable.IsSorted = true; tablesHeap.FieldRVATable.IsSorted = true; tablesHeap.GenericParamTable.IsSorted = true; tablesHeap.ImplMapTable.IsSorted = true; tablesHeap.InterfaceImplTable.IsSorted = true; tablesHeap.MethodImplTable.IsSorted = true; tablesHeap.MethodSemanticsTable.IsSorted = true; tablesHeap.NestedClassTable.IsSorted = true; tablesHeap.EventMapTable.IsSorted = true; tablesHeap.PropertyMapTable.IsSorted = true; foreach (SortedRows.Info info in classLayoutInfos.infos) { tablesHeap.ClassLayoutTable.Create(info.row); } foreach (SortedRows.Info info2 in hasConstantInfos.infos) { tablesHeap.ConstantTable.Create(info2.row); } foreach (SortedRows.Info info3 in declSecurityInfos.infos) { tablesHeap.DeclSecurityTable.Create(info3.row); } foreach (SortedRows.Info info4 in fieldLayoutInfos.infos) { tablesHeap.FieldLayoutTable.Create(info4.row); } foreach (SortedRows.Info info5 in fieldMarshalInfos.infos) { tablesHeap.FieldMarshalTable.Create(info5.row); } foreach (SortedRows.Info info6 in fieldRVAInfos.infos) { tablesHeap.FieldRVATable.Create(info6.row); } foreach (SortedRows.Info info7 in genericParamInfos.infos) { tablesHeap.GenericParamTable.Create(info7.row); } foreach (SortedRows.Info info8 in implMapInfos.infos) { tablesHeap.ImplMapTable.Create(info8.row); } foreach (SortedRows.Info info9 in interfaceImplInfos.infos) { tablesHeap.InterfaceImplTable.Create(info9.row); } foreach (SortedRows.Info info10 in methodImplInfos.infos) { tablesHeap.MethodImplTable.Create(info10.row); } foreach (SortedRows.Info info11 in methodSemanticsInfos.infos) { tablesHeap.MethodSemanticsTable.Create(info11.row); } foreach (SortedRows.Info info12 in nestedClassInfos.infos) { tablesHeap.NestedClassTable.Create(info12.row); } foreach (SortedRows.Info info13 in interfaceImplInfos.infos) { if (info13.data.HasCustomAttributes || info13.data.HasCustomDebugInfos) { uint rid = interfaceImplInfos.Rid(info13.data); AddCustomAttributes(Table.InterfaceImpl, rid, info13.data); AddCustomDebugInformationList(Table.InterfaceImpl, rid, info13.data); } } foreach (SortedRows.Info info14 in declSecurityInfos.infos) { if (info14.data.HasCustomAttributes || info14.data.HasCustomDebugInfos) { uint rid2 = declSecurityInfos.Rid(info14.data); AddCustomAttributes(Table.DeclSecurity, rid2, info14.data); AddCustomDebugInformationList(Table.DeclSecurity, rid2, info14.data); } } foreach (SortedRows.Info info15 in genericParamInfos.infos) { if (info15.data.HasCustomAttributes || info15.data.HasCustomDebugInfos) { uint rid3 = genericParamInfos.Rid(info15.data); AddCustomAttributes(Table.GenericParam, rid3, info15.data); AddCustomDebugInformationList(Table.GenericParam, rid3, info15.data); } } } private void InitializeGenericParamConstraintTable() { TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { if (typeDef == null) { continue; } using (errorContext.SetSource(typeDef)) { AddGenericParamConstraints(typeDef.GenericParameters); IList methods = typeDef.Methods; int count = methods.Count; for (int j = 0; j < count; j++) { MethodDef methodDef = methods[j]; if (methodDef != null) { using (errorContext.SetSource(methodDef)) { AddGenericParamConstraints(methodDef.GenericParameters); } } } } } genericParamConstraintInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Owner.CompareTo(b.row.Owner)); tablesHeap.GenericParamConstraintTable.IsSorted = true; foreach (SortedRows.Info info in genericParamConstraintInfos.infos) { tablesHeap.GenericParamConstraintTable.Create(info.row); } foreach (SortedRows.Info info2 in genericParamConstraintInfos.infos) { if (info2.data.HasCustomAttributes || info2.data.HasCustomDebugInfos) { uint rid = genericParamConstraintInfos.Rid(info2.data); AddCustomAttributes(Table.GenericParamConstraint, rid, info2.data); AddCustomDebugInformationList(Table.GenericParamConstraint, rid, info2.data); } } } private void InitializeCustomAttributeAndCustomDebugInfoTables() { customAttributeInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); tablesHeap.CustomAttributeTable.IsSorted = true; foreach (SortedRows.Info info in customAttributeInfos.infos) { tablesHeap.CustomAttributeTable.Create(info.row); } if (debugMetadata == null) { return; } debugMetadata.stateMachineMethodInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.MoveNextMethod.CompareTo(b.row.MoveNextMethod)); debugMetadata.tablesHeap.StateMachineMethodTable.IsSorted = true; foreach (SortedRows.Info info2 in debugMetadata.stateMachineMethodInfos.infos) { debugMetadata.tablesHeap.StateMachineMethodTable.Create(info2.row); } debugMetadata.customDebugInfos.Sort((SortedRows.Info a, SortedRows.Info b) => a.row.Parent.CompareTo(b.row.Parent)); debugMetadata.tablesHeap.CustomDebugInformationTable.IsSorted = true; foreach (SortedRows.Info info3 in debugMetadata.customDebugInfos.infos) { debugMetadata.tablesHeap.CustomDebugInformationTable.Create(info3.row); } } private void WriteMethodBodies() { if (NoMethodBodies) { return; } int numberOfMethods = NumberOfMethods; int num = 0; int num2 = 0; int num3 = numberOfMethods / 40; NormalMetadata normalMetadata = debugMetadata; MethodBodyChunks methodBodyChunks = methodBodies; Dictionary dictionary = methodToBody; List list; List list2; SerializerMethodContext ctx; if (normalMetadata == null) { list = null; list2 = null; ctx = null; } else { list = new List(); list2 = new List(); ctx = AllocSerializerMethodContext(); } bool keepOldMaxStack = KeepOldMaxStack; MethodBodyWriter methodBodyWriter = new MethodBodyWriter(this); TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { if (typeDef == null) { continue; } using (errorContext.SetSource(typeDef)) { IList methods = typeDef.Methods; for (int j = 0; j < methods.Count; j++) { MethodDef methodDef = methods[j]; if (methodDef == null) { continue; } using (errorContext.SetSource(methodDef)) { if (num++ == num3 && num2 < 40) { RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.BeginWriteMethodBodies, (double)num / (double)numberOfMethods); num2++; num3 = (int)((double)numberOfMethods / 40.0 * (double)(num2 + 1)); } uint localVarSigToken = 0u; CilBody body = methodDef.Body; if (body != null) { if (body.Instructions.Count != 0 || body.Variables.Count != 0) { methodBodyWriter.Reset(body, keepOldMaxStack || body.KeepOldMaxStack); methodBodyWriter.Write(); RVA rVA = methodDef.RVA; uint metadataBodySize = body.MetadataBodySize; MethodBody value = methodBodyChunks.Add(new MethodBody(methodBodyWriter.Code, methodBodyWriter.ExtraSections, methodBodyWriter.LocalVarSigTok), rVA, metadataBodySize); dictionary[methodDef] = value; localVarSigToken = methodBodyWriter.LocalVarSigTok; } } else { NativeMethodBody nativeBody = methodDef.NativeBody; if (nativeBody != null) { methodToNativeBody[methodDef] = nativeBody; } else if (methodDef.MethodBody != null) { Error("Unsupported method body"); } } if (normalMetadata == null) { continue; } uint rid = GetRid(methodDef); if (body != null) { PdbMethod pdbMethod = body.PdbMethod; if (pdbMethod != null && !IsEmptyRootScope(body, pdbMethod.Scope)) { ctx.SetBody(methodDef); list2.Add(pdbMethod.Scope); while (list2.Count > 0) { PdbScope pdbScope = list2[list2.Count - 1]; list2.RemoveAt(list2.Count - 1); list2.AddRange(pdbScope.Scopes); uint num4 = ctx.GetOffset(pdbScope.Start); uint num5 = ctx.GetOffset(pdbScope.End); list.Add(new MethodScopeDebugInfo { MethodRid = rid, Scope = pdbScope, ScopeStart = num4, ScopeLength = num5 - num4 }); } } } AddCustomDebugInformationList(methodDef, rid, localVarSigToken); } } } } if (normalMetadata != null) { list.Sort(delegate(MethodScopeDebugInfo a, MethodScopeDebugInfo b) { int num8 = a.MethodRid.CompareTo(b.MethodRid); if (num8 != 0) { return num8; } num8 = a.ScopeStart.CompareTo(b.ScopeStart); return (num8 != 0) ? num8 : b.ScopeLength.CompareTo(a.ScopeLength); }); foreach (MethodScopeDebugInfo item in list) { uint rid2 = (uint)(normalMetadata.localScopeInfos.infos.Count + 1); RawLocalScopeRow row = new RawLocalScopeRow(item.MethodRid, AddImportScope(item.Scope.ImportScope), (uint)(normalMetadata.tablesHeap.LocalVariableTable.Rows + 1), (uint)(normalMetadata.tablesHeap.LocalConstantTable.Rows + 1), item.ScopeStart, item.ScopeLength); normalMetadata.localScopeInfos.Add(item.Scope, row); IList variables = item.Scope.Variables; int count = variables.Count; for (int num6 = 0; num6 < count; num6++) { PdbLocal local = variables[num6]; AddLocalVariable(local); } IList list3 = item.Scope.Constants; count = list3.Count; for (int num7 = 0; num7 < count; num7++) { PdbConstant constant = list3[num7]; AddLocalConstant(constant); } AddCustomDebugInformationList(Table.LocalScope, rid2, item.Scope.CustomDebugInfos); } normalMetadata.tablesHeap.LocalScopeTable.IsSorted = true; foreach (SortedRows.Info info in normalMetadata.localScopeInfos.infos) { normalMetadata.tablesHeap.LocalScopeTable.Create(info.row); } } if (ctx != null) { Free(ref ctx); } } private static bool IsEmptyRootScope(CilBody cilBody, PdbScope scope) { if (scope.Variables.Count != 0) { return false; } if (scope.Constants.Count != 0) { return false; } if (scope.Namespaces.Count != 0) { return false; } if (scope.ImportScope != null) { return false; } if (scope.Scopes.Count != 0) { return false; } if (scope.CustomDebugInfos.Count != 0) { return false; } if (scope.End != null) { return false; } if (cilBody.Instructions.Count != 0 && cilBody.Instructions[0] != scope.Start) { return false; } return true; } protected static bool IsEmpty(IList list) where T : class { if (list == null) { return true; } int count = list.Count; for (int i = 0; i < count; i++) { if (list[i] != null) { return false; } } return true; } public MDToken GetToken(object o) { if (o is IMDTokenProvider { MDToken: var mDToken } iMDTokenProvider) { return new MDToken(mDToken.Table, AddMDTokenProvider(iMDTokenProvider)); } if (o is string s) { return new MDToken((Table)112, usHeap.Add(s)); } if (o is MethodSig methodSig) { return new MDToken(Table.StandAloneSig, AddStandAloneSig(methodSig, methodSig.OriginalToken)); } if (o is FieldSig fieldSig) { return new MDToken(Table.StandAloneSig, AddStandAloneSig(fieldSig, 0u)); } if (o == null) { Error("Instruction operand is null"); } else { Error("Invalid instruction operand"); } return new MDToken((Table)255, 16777215); } public virtual MDToken GetToken(IList locals, uint origToken) { if (locals == null || locals.Count == 0) { return new MDToken(Table.Module, 0); } RawStandAloneSigRow row = new RawStandAloneSigRow(GetSignature(new LocalSig(locals, dummy: false))); uint rid = tablesHeap.StandAloneSigTable.Add(row); return new MDToken(Table.StandAloneSig, rid); } protected virtual uint AddStandAloneSig(MethodSig methodSig, uint origToken) { if (methodSig == null) { Error("StandAloneSig: MethodSig is null"); return 0u; } RawStandAloneSigRow row = new RawStandAloneSigRow(GetSignature(methodSig)); return tablesHeap.StandAloneSigTable.Add(row); } protected virtual uint AddStandAloneSig(FieldSig fieldSig, uint origToken) { if (fieldSig == null) { Error("StandAloneSig: FieldSig is null"); return 0u; } RawStandAloneSigRow row = new RawStandAloneSigRow(GetSignature(fieldSig)); return tablesHeap.StandAloneSigTable.Add(row); } private uint AddMDTokenProvider(IMDTokenProvider tp) { if (tp != null) { switch (tp.MDToken.Table) { case Table.Module: return AddModule((ModuleDef)tp); case Table.TypeRef: return AddTypeRef((TypeRef)tp); case Table.TypeDef: return GetRid((TypeDef)tp); case Table.Field: return GetRid((FieldDef)tp); case Table.Method: return GetRid((MethodDef)tp); case Table.Param: return GetRid((ParamDef)tp); case Table.MemberRef: return AddMemberRef((MemberRef)tp); case Table.StandAloneSig: return AddStandAloneSig((StandAloneSig)tp); case Table.Event: return GetRid((EventDef)tp); case Table.Property: return GetRid((PropertyDef)tp); case Table.ModuleRef: return AddModuleRef((ModuleRef)tp); case Table.TypeSpec: return AddTypeSpec((TypeSpec)tp); case Table.Assembly: return AddAssembly((AssemblyDef)tp, null); case Table.AssemblyRef: return AddAssemblyRef((AssemblyRef)tp); case Table.File: return AddFile((FileDef)tp); case Table.ExportedType: return AddExportedType((ExportedType)tp); case Table.MethodSpec: return AddMethodSpec((MethodSpec)tp); } } if (tp == null) { Error("IMDTokenProvider is null"); } else { Error("Invalid IMDTokenProvider"); } return 0u; } protected uint AddTypeDefOrRef(ITypeDefOrRef tdr) { if (tdr == null) { Error("TypeDefOrRef is null"); return 0u; } MDToken token = new MDToken(tdr.MDToken.Table, AddMDTokenProvider(tdr)); if (!CodedToken.TypeDefOrRef.Encode(token, out var codedToken)) { Error("Can't encode TypeDefOrRef token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected uint AddResolutionScope(IResolutionScope rs) { if (rs == null) { return 0u; } MDToken token = new MDToken(rs.MDToken.Table, AddMDTokenProvider(rs)); if (!CodedToken.ResolutionScope.Encode(token, out var codedToken)) { Error("Can't encode ResolutionScope token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected uint AddMethodDefOrRef(IMethodDefOrRef mdr) { if (mdr == null) { Error("MethodDefOrRef is null"); return 0u; } MDToken token = new MDToken(mdr.MDToken.Table, AddMDTokenProvider(mdr)); if (!CodedToken.MethodDefOrRef.Encode(token, out var codedToken)) { Error("Can't encode MethodDefOrRef token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected uint AddMemberRefParent(IMemberRefParent parent) { if (parent == null) { Error("MemberRefParent is null"); return 0u; } MDToken token = new MDToken(parent.MDToken.Table, AddMDTokenProvider(parent)); if (!CodedToken.MemberRefParent.Encode(token, out var codedToken)) { Error("Can't encode MemberRefParent token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected uint AddImplementation(IImplementation impl) { if (impl == null) { Error("Implementation is null"); return 0u; } MDToken token = new MDToken(impl.MDToken.Table, AddMDTokenProvider(impl)); if (!CodedToken.Implementation.Encode(token, out var codedToken)) { Error("Can't encode Implementation token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected uint AddCustomAttributeType(ICustomAttributeType cat) { if (cat == null) { Error("CustomAttributeType is null"); return 0u; } MDToken token = new MDToken(cat.MDToken.Table, AddMDTokenProvider(cat)); if (!CodedToken.CustomAttributeType.Encode(token, out var codedToken)) { Error("Can't encode CustomAttributeType token 0x{0:X8}.", token.Raw); return 0u; } return codedToken; } protected void AddNestedType(TypeDef nestedType, TypeDef declaringType) { if (nestedType != null && declaringType != null) { uint rid = GetRid(nestedType); uint rid2 = GetRid(declaringType); if (rid != 0 && rid2 != 0) { RawNestedClassRow row = new RawNestedClassRow(rid, rid2); nestedClassInfos.Add(declaringType, row); } } } protected uint AddModule(ModuleDef module) { if (module == null) { Error("Module is null"); return 0u; } if (this.module != module) { Error("Module '{0}' must be referenced with a ModuleRef, not a ModuleDef.", module); } if (moduleDefInfos.TryGetRid(module, out var rid)) { return rid; } RawModuleRow row = new RawModuleRow(module.Generation, stringsHeap.Add(module.Name), guidHeap.Add(module.Mvid), guidHeap.Add(module.EncId), guidHeap.Add(module.EncBaseId)); rid = tablesHeap.ModuleTable.Add(row); moduleDefInfos.Add(module, rid); AddCustomAttributes(Table.Module, rid, module); AddCustomDebugInformationList(Table.Module, rid, module); return rid; } protected uint AddModuleRef(ModuleRef modRef) { if (modRef == null) { Error("ModuleRef is null"); return 0u; } if (moduleRefInfos.TryGetRid(modRef, out var rid)) { return rid; } RawModuleRefRow row = new RawModuleRefRow(stringsHeap.Add(modRef.Name)); rid = tablesHeap.ModuleRefTable.Add(row); moduleRefInfos.Add(modRef, rid); AddCustomAttributes(Table.ModuleRef, rid, modRef); AddCustomDebugInformationList(Table.ModuleRef, rid, modRef); return rid; } protected uint AddAssemblyRef(AssemblyRef asmRef) { if (asmRef == null) { Error("AssemblyRef is null"); return 0u; } if (assemblyRefInfos.TryGetRid(asmRef, out var rid)) { return rid; } Version version = Utils.CreateVersionWithNoUndefinedValues(asmRef.Version); RawAssemblyRefRow row = new RawAssemblyRefRow((ushort)version.Major, (ushort)version.Minor, (ushort)version.Build, (ushort)version.Revision, (uint)asmRef.Attributes, blobHeap.Add(PublicKeyBase.GetRawData(asmRef.PublicKeyOrToken)), stringsHeap.Add(asmRef.Name), stringsHeap.Add(asmRef.Culture), blobHeap.Add(asmRef.Hash)); rid = tablesHeap.AssemblyRefTable.Add(row); assemblyRefInfos.Add(asmRef, rid); AddCustomAttributes(Table.AssemblyRef, rid, asmRef); AddCustomDebugInformationList(Table.AssemblyRef, rid, asmRef); return rid; } protected uint AddAssembly(AssemblyDef asm, byte[] publicKey) { if (asm == null) { Error("Assembly is null"); return 0u; } if (assemblyInfos.TryGetRid(asm, out var rid)) { return rid; } AssemblyAttributes assemblyAttributes = asm.Attributes; if (publicKey != null) { assemblyAttributes |= AssemblyAttributes.PublicKey; } else { publicKey = PublicKeyBase.GetRawData(asm.PublicKeyOrToken); } Version version = Utils.CreateVersionWithNoUndefinedValues(asm.Version); RawAssemblyRow row = new RawAssemblyRow((uint)asm.HashAlgorithm, (ushort)version.Major, (ushort)version.Minor, (ushort)version.Build, (ushort)version.Revision, (uint)assemblyAttributes, blobHeap.Add(publicKey), stringsHeap.Add(asm.Name), stringsHeap.Add(asm.Culture)); rid = tablesHeap.AssemblyTable.Add(row); assemblyInfos.Add(asm, rid); AddDeclSecurities(new MDToken(Table.Assembly, rid), asm.DeclSecurities); AddCustomAttributes(Table.Assembly, rid, asm); AddCustomDebugInformationList(Table.Assembly, rid, asm); return rid; } protected void AddGenericParams(MDToken token, IList gps) { if (gps != null) { int count = gps.Count; for (int i = 0; i < count; i++) { AddGenericParam(token, gps[i]); } } } protected void AddGenericParam(MDToken owner, GenericParam gp) { if (gp == null) { Error("GenericParam is null"); return; } if (!CodedToken.TypeOrMethodDef.Encode(owner, out var codedToken)) { Error("Can't encode TypeOrMethodDef token 0x{0:X8}.", owner.Raw); codedToken = 0u; } RawGenericParamRow row = new RawGenericParamRow(gp.Number, (ushort)gp.Flags, codedToken, stringsHeap.Add(gp.Name), (gp.Kind != null) ? AddTypeDefOrRef(gp.Kind) : 0u); genericParamInfos.Add(gp, row); } private void AddGenericParamConstraints(IList gps) { if (gps == null) { return; } int count = gps.Count; for (int i = 0; i < count; i++) { GenericParam genericParam = gps[i]; if (genericParam != null) { uint gpRid = genericParamInfos.Rid(genericParam); AddGenericParamConstraints(gpRid, genericParam.GenericParamConstraints); } } } protected void AddGenericParamConstraints(uint gpRid, IList constraints) { if (constraints != null) { int count = constraints.Count; for (int i = 0; i < count; i++) { AddGenericParamConstraint(gpRid, constraints[i]); } } } protected void AddGenericParamConstraint(uint gpRid, GenericParamConstraint gpc) { if (gpc == null) { Error("GenericParamConstraint is null"); return; } RawGenericParamConstraintRow row = new RawGenericParamConstraintRow(gpRid, AddTypeDefOrRef(gpc.Constraint)); genericParamConstraintInfos.Add(gpc, row); } protected void AddInterfaceImpls(uint typeDefRid, IList ifaces) { int count = ifaces.Count; for (int i = 0; i < count; i++) { InterfaceImpl interfaceImpl = ifaces[i]; if (interfaceImpl != null) { RawInterfaceImplRow row = new RawInterfaceImplRow(typeDefRid, AddTypeDefOrRef(interfaceImpl.Interface)); interfaceImplInfos.Add(interfaceImpl, row); } } } protected void AddFieldLayout(FieldDef field) { if (field != null && field.FieldOffset.HasValue) { uint rid = GetRid(field); RawFieldLayoutRow row = new RawFieldLayoutRow(field.FieldOffset.Value, rid); fieldLayoutInfos.Add(field, row); } } protected void AddFieldMarshal(MDToken parent, IHasFieldMarshal hfm) { if (hfm != null && hfm.MarshalType != null) { MarshalType marshalType = hfm.MarshalType; if (!CodedToken.HasFieldMarshal.Encode(parent, out var codedToken)) { Error("Can't encode HasFieldMarshal token 0x{0:X8}.", parent.Raw); codedToken = 0u; } RawFieldMarshalRow row = new RawFieldMarshalRow(codedToken, blobHeap.Add(MarshalBlobWriter.Write(module, marshalType, this, OptimizeCustomAttributeSerializedTypeNames))); fieldMarshalInfos.Add(hfm, row); } } protected void AddFieldRVA(FieldDef field) { if (NoFieldData) { return; } if (field.RVA != 0 && KeepFieldRVA) { uint rid = GetRid(field); RawFieldRVARow row = new RawFieldRVARow((uint)field.RVA, rid); fieldRVAInfos.Add(field, row); } else { if (field == null || field.InitialValue == null) { return; } byte[] initialValue = field.InitialValue; if (!VerifyFieldSize(field, initialValue.Length)) { Error("Field '{0}' (0x{1:X8}) initial value size != size of field type.", field, field.MDToken.Raw); } uint rid2 = GetRid(field); uint num = 8u; if (field.FieldType is TypeDefOrRefSig typeDefOrRefSig) { ClassLayout classLayout = typeDefOrRefSig.TypeDef?.ClassLayout; if (classLayout != null) { num = Math.Max(num, Utils.RoundToNextPowerOfTwo(classLayout.PackingSize)); } } ByteArrayChunk value = constants.Add(new ByteArrayChunk(initialValue, num), num); fieldToInitialValue[field] = value; RawFieldRVARow row2 = new RawFieldRVARow(0u, rid2); fieldRVAInfos.Add(field, row2); } } private static bool VerifyFieldSize(FieldDef field, int size) { if (field == null) { return false; } if (field.FieldSig == null) { return false; } return field.GetFieldSize() == size; } protected void AddImplMap(MDToken parent, IMemberForwarded mf) { if (mf != null && mf.ImplMap != null) { ImplMap implMap = mf.ImplMap; if (!CodedToken.MemberForwarded.Encode(parent, out var codedToken)) { Error("Can't encode MemberForwarded token 0x{0:X8}.", parent.Raw); codedToken = 0u; } RawImplMapRow row = new RawImplMapRow((ushort)implMap.Attributes, codedToken, stringsHeap.Add(implMap.Name), AddModuleRef(implMap.Module)); implMapInfos.Add(mf, row); } } protected void AddConstant(MDToken parent, IHasConstant hc) { if (hc != null && hc.Constant != null) { Constant constant = hc.Constant; if (!CodedToken.HasConstant.Encode(parent, out var codedToken)) { Error("Can't encode HasConstant token 0x{0:X8}.", parent.Raw); codedToken = 0u; } RawConstantRow row = new RawConstantRow((byte)constant.Type, 0, codedToken, blobHeap.Add(GetConstantValueAsByteArray(constant.Type, constant.Value))); hasConstantInfos.Add(hc, row); } } private byte[] GetConstantValueAsByteArray(ElementType etype, object o) { if (o == null) { if (etype == ElementType.Class) { return constantClassByteArray; } Error("Constant is null"); return constantDefaultByteArray; } TypeCode typeCode = Type.GetTypeCode(o.GetType()); switch (typeCode) { case TypeCode.Boolean: VerifyConstantType(etype, ElementType.Boolean); return BitConverter.GetBytes((bool)o); case TypeCode.Char: VerifyConstantType(etype, ElementType.Char); return BitConverter.GetBytes((char)o); case TypeCode.SByte: VerifyConstantType(etype, ElementType.I1); return new byte[1] { (byte)(sbyte)o }; case TypeCode.Byte: VerifyConstantType(etype, ElementType.U1); return new byte[1] { (byte)o }; case TypeCode.Int16: VerifyConstantType(etype, ElementType.I2); return BitConverter.GetBytes((short)o); case TypeCode.UInt16: VerifyConstantType(etype, ElementType.U2); return BitConverter.GetBytes((ushort)o); case TypeCode.Int32: VerifyConstantType(etype, ElementType.I4); return BitConverter.GetBytes((int)o); case TypeCode.UInt32: VerifyConstantType(etype, ElementType.U4); return BitConverter.GetBytes((uint)o); case TypeCode.Int64: VerifyConstantType(etype, ElementType.I8); return BitConverter.GetBytes((long)o); case TypeCode.UInt64: VerifyConstantType(etype, ElementType.U8); return BitConverter.GetBytes((ulong)o); case TypeCode.Single: VerifyConstantType(etype, ElementType.R4); return BitConverter.GetBytes((float)o); case TypeCode.Double: VerifyConstantType(etype, ElementType.R8); return BitConverter.GetBytes((double)o); case TypeCode.String: VerifyConstantType(etype, ElementType.String); return Encoding.Unicode.GetBytes((string)o); default: Error("Invalid constant type: {0}", typeCode); return constantDefaultByteArray; } } private void VerifyConstantType(ElementType realType, ElementType expectedType) { if (realType != expectedType) { Error("Constant value's type is the wrong type: {0} != {1}", realType, expectedType); } } protected void AddDeclSecurities(MDToken parent, IList declSecurities) { if (declSecurities == null) { return; } if (!CodedToken.HasDeclSecurity.Encode(parent, out var codedToken)) { Error("Can't encode HasDeclSecurity token 0x{0:X8}.", parent.Raw); codedToken = 0u; } DataWriterContext ctx = AllocBinaryWriterContext(); int count = declSecurities.Count; for (int i = 0; i < count; i++) { DeclSecurity declSecurity = declSecurities[i]; if (declSecurity != null) { RawDeclSecurityRow row = new RawDeclSecurityRow((short)declSecurity.Action, codedToken, blobHeap.Add(DeclSecurityWriter.Write(module, declSecurity.SecurityAttributes, this, OptimizeCustomAttributeSerializedTypeNames, ctx))); declSecurityInfos.Add(declSecurity, row); } } Free(ref ctx); } protected void AddMethodSemantics(EventDef evt) { if (evt == null) { Error("Event is null"); return; } uint rid = GetRid(evt); if (rid != 0) { MDToken owner = new MDToken(Table.Event, rid); AddMethodSemantics(owner, evt.AddMethod, MethodSemanticsAttributes.AddOn); AddMethodSemantics(owner, evt.RemoveMethod, MethodSemanticsAttributes.RemoveOn); AddMethodSemantics(owner, evt.InvokeMethod, MethodSemanticsAttributes.Fire); AddMethodSemantics(owner, evt.OtherMethods, MethodSemanticsAttributes.Other); } } protected void AddMethodSemantics(PropertyDef prop) { if (prop == null) { Error("Property is null"); return; } uint rid = GetRid(prop); if (rid != 0) { MDToken owner = new MDToken(Table.Property, rid); AddMethodSemantics(owner, prop.GetMethods, MethodSemanticsAttributes.Getter); AddMethodSemantics(owner, prop.SetMethods, MethodSemanticsAttributes.Setter); AddMethodSemantics(owner, prop.OtherMethods, MethodSemanticsAttributes.Other); } } private void AddMethodSemantics(MDToken owner, IList methods, MethodSemanticsAttributes attrs) { if (methods != null) { int count = methods.Count; for (int i = 0; i < count; i++) { AddMethodSemantics(owner, methods[i], attrs); } } } private void AddMethodSemantics(MDToken owner, MethodDef method, MethodSemanticsAttributes flags) { if (method == null) { return; } uint rid = GetRid(method); if (rid != 0) { if (!CodedToken.HasSemantic.Encode(owner, out var codedToken)) { Error("Can't encode HasSemantic token 0x{0:X8}.", owner.Raw); codedToken = 0u; } RawMethodSemanticsRow row = new RawMethodSemanticsRow((ushort)flags, rid, codedToken); methodSemanticsInfos.Add(method, row); } } private void AddMethodImpls(MethodDef method, IList overrides) { if (overrides == null) { return; } if (method.DeclaringType == null) { Error("Method declaring type is null"); } else if (overrides.Count != 0) { uint rid = GetRid(method.DeclaringType); int count = overrides.Count; for (int i = 0; i < count; i++) { MethodOverride methodOverride = overrides[i]; RawMethodImplRow row = new RawMethodImplRow(rid, AddMethodDefOrRef(methodOverride.MethodBody), AddMethodDefOrRef(methodOverride.MethodDeclaration)); methodImplInfos.Add(method, row); } } } protected void AddClassLayout(TypeDef type) { if (type != null && type.ClassLayout != null) { uint rid = GetRid(type); ClassLayout classLayout = type.ClassLayout; RawClassLayoutRow row = new RawClassLayoutRow(classLayout.PackingSize, classLayout.ClassSize, rid); classLayoutInfos.Add(type, row); } } private void AddResources(IList resources) { if (!NoDotNetResources && resources != null) { int count = resources.Count; for (int i = 0; i < count; i++) { AddResource(resources[i]); } } } private void AddResource(Resource resource) { if (resource is EmbeddedResource er) { AddEmbeddedResource(er); return; } if (resource is AssemblyLinkedResource alr) { AddAssemblyLinkedResource(alr); return; } if (resource is LinkedResource lr) { AddLinkedResource(lr); return; } if (resource == null) { Error("Resource is null"); return; } Error("Invalid resource type: '{0}'.", resource.GetType()); } private uint AddEmbeddedResource(EmbeddedResource er) { if (er == null) { Error("EmbeddedResource is null"); return 0u; } if (manifestResourceInfos.TryGetRid(er, out var rid)) { return rid; } RawManifestResourceRow row = new RawManifestResourceRow(netResources.NextOffset, (uint)er.Attributes, stringsHeap.Add(er.Name), 0u); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(er, rid); embeddedResourceToByteArray[er] = netResources.Add(er.CreateReader()); AddCustomAttributes(Table.ManifestResource, rid, er); AddCustomDebugInformationList(Table.ManifestResource, rid, er); return rid; } private uint AddAssemblyLinkedResource(AssemblyLinkedResource alr) { if (alr == null) { Error("AssemblyLinkedResource is null"); return 0u; } if (manifestResourceInfos.TryGetRid(alr, out var rid)) { return rid; } RawManifestResourceRow row = new RawManifestResourceRow(0u, (uint)alr.Attributes, stringsHeap.Add(alr.Name), AddImplementation(alr.Assembly)); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(alr, rid); AddCustomAttributes(Table.ManifestResource, rid, alr); AddCustomDebugInformationList(Table.ManifestResource, rid, alr); return rid; } private uint AddLinkedResource(LinkedResource lr) { if (lr == null) { Error("LinkedResource is null"); return 0u; } if (manifestResourceInfos.TryGetRid(lr, out var rid)) { return rid; } RawManifestResourceRow row = new RawManifestResourceRow(0u, (uint)lr.Attributes, stringsHeap.Add(lr.Name), AddImplementation(lr.File)); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(lr, rid); AddCustomAttributes(Table.ManifestResource, rid, lr); AddCustomDebugInformationList(Table.ManifestResource, rid, lr); return rid; } protected uint AddFile(FileDef file) { if (file == null) { Error("FileDef is null"); return 0u; } if (fileDefInfos.TryGetRid(file, out var rid)) { return rid; } RawFileRow row = new RawFileRow((uint)file.Flags, stringsHeap.Add(file.Name), blobHeap.Add(file.HashValue)); rid = tablesHeap.FileTable.Add(row); fileDefInfos.Add(file, rid); AddCustomAttributes(Table.File, rid, file); AddCustomDebugInformationList(Table.File, rid, file); return rid; } protected uint AddExportedType(ExportedType et) { if (et == null) { Error("ExportedType is null"); return 0u; } if (exportedTypeInfos.TryGetRid(et, out var rid)) { return rid; } exportedTypeInfos.Add(et, 0u); RawExportedTypeRow row = new RawExportedTypeRow((uint)et.Attributes, et.TypeDefId, stringsHeap.Add(et.TypeName), stringsHeap.Add(et.TypeNamespace), AddImplementation(et.Implementation)); rid = tablesHeap.ExportedTypeTable.Add(row); exportedTypeInfos.SetRid(et, rid); AddCustomAttributes(Table.ExportedType, rid, et); AddCustomDebugInformationList(Table.ExportedType, rid, et); return rid; } protected uint GetSignature(TypeSig ts, byte[] extraData) { byte[] blob; if (ts == null) { Error("TypeSig is null"); blob = null; } else { DataWriterContext ctx = AllocBinaryWriterContext(); blob = SignatureWriter.Write(this, ts, ctx); Free(ref ctx); } AppendExtraData(ref blob, extraData); return blobHeap.Add(blob); } protected uint GetSignature(CallingConventionSig sig) { if (sig == null) { Error("CallingConventionSig is null"); return 0u; } DataWriterContext ctx = AllocBinaryWriterContext(); byte[] blob = SignatureWriter.Write(this, sig, ctx); Free(ref ctx); AppendExtraData(ref blob, sig.ExtraData); return blobHeap.Add(blob); } private void AppendExtraData(ref byte[] blob, byte[] extraData) { if (PreserveExtraSignatureData && extraData != null && extraData.Length != 0) { int num = ((blob != null) ? blob.Length : 0); Array.Resize(ref blob, num + extraData.Length); Array.Copy(extraData, 0, blob, num, extraData.Length); } } protected void AddCustomAttributes(Table table, uint rid, IHasCustomAttribute hca) { AddCustomAttributes(table, rid, hca.CustomAttributes); } private void AddCustomAttributes(Table table, uint rid, CustomAttributeCollection caList) { MDToken token = new MDToken(table, rid); int count = caList.Count; for (int i = 0; i < count; i++) { AddCustomAttribute(token, caList[i]); } } private void AddCustomAttribute(MDToken token, CustomAttribute ca) { if (ca == null) { Error("Custom attribute is null"); return; } if (!CodedToken.HasCustomAttribute.Encode(token, out var codedToken)) { Error("Can't encode HasCustomAttribute token 0x{0:X8}.", token.Raw); codedToken = 0u; } DataWriterContext ctx = AllocBinaryWriterContext(); byte[] data = CustomAttributeWriter.Write(this, ca, ctx); Free(ref ctx); RawCustomAttributeRow row = new RawCustomAttributeRow(codedToken, AddCustomAttributeType(ca.Constructor), blobHeap.Add(data)); customAttributeInfos.Add(ca, row); } private void AddCustomDebugInformationList(MethodDef method, uint rid, uint localVarSigToken) { if (debugMetadata != null) { SerializerMethodContext ctx = AllocSerializerMethodContext(); ctx.SetBody(method); if (method.CustomDebugInfos.Count != 0) { AddCustomDebugInformationCore(ctx, Table.Method, rid, method.CustomDebugInfos); } AddMethodDebugInformation(method, rid, localVarSigToken); Free(ref ctx); } } private void AddMethodDebugInformation(MethodDef method, uint rid, uint localVarSigToken) { CilBody body = method.Body; if (body == null) { return; } GetSingleDocument(body, out var singleDoc, out var firstDoc, out var hasNoSeqPoints); if (hasNoSeqPoints) { return; } DataWriterContext ctx = AllocBinaryWriterContext(); MemoryStream outStream = ctx.OutStream; DataWriter writer = ctx.Writer; outStream.SetLength(0L); outStream.Position = 0L; writer.WriteCompressedUInt32(localVarSigToken); if (singleDoc == null) { writer.WriteCompressedUInt32(VerifyGetRid(firstDoc)); } IList instructions = body.Instructions; PdbDocument pdbDocument = firstDoc; uint num = uint.MaxValue; int num2 = -1; int num3 = 0; uint num4 = 0u; Instruction instruction = null; int num5 = 0; while (num5 < instructions.Count) { instruction = instructions[num5]; SequencePoint sequencePoint = instruction.SequencePoint; if (sequencePoint != null) { if (sequencePoint.Document == null) { Error("PDB document is null"); return; } if (pdbDocument != sequencePoint.Document) { pdbDocument = sequencePoint.Document; writer.WriteCompressedUInt32(0u); writer.WriteCompressedUInt32(VerifyGetRid(pdbDocument)); } if (num == uint.MaxValue) { writer.WriteCompressedUInt32(num4); } else { writer.WriteCompressedUInt32(num4 - num); } num = num4; if (sequencePoint.StartLine == 16707566 && sequencePoint.EndLine == 16707566) { writer.WriteCompressedUInt32(0u); writer.WriteCompressedUInt32(0u); } else { uint num6 = (uint)(sequencePoint.EndLine - sequencePoint.StartLine); int value = sequencePoint.EndColumn - sequencePoint.StartColumn; writer.WriteCompressedUInt32(num6); if (num6 == 0) { writer.WriteCompressedUInt32((uint)value); } else { writer.WriteCompressedInt32(value); } if (num2 < 0) { writer.WriteCompressedUInt32((uint)sequencePoint.StartLine); writer.WriteCompressedUInt32((uint)sequencePoint.StartColumn); } else { writer.WriteCompressedInt32(sequencePoint.StartLine - num2); writer.WriteCompressedInt32(sequencePoint.StartColumn - num3); } num2 = sequencePoint.StartLine; num3 = sequencePoint.StartColumn; } } num5++; num4 += (uint)instruction.GetSize(); } byte[] data = outStream.ToArray(); RawMethodDebugInformationRow value2 = new RawMethodDebugInformationRow((singleDoc != null) ? AddPdbDocument(singleDoc) : 0u, debugMetadata.blobHeap.Add(data)); debugMetadata.tablesHeap.MethodDebugInformationTable[rid] = value2; debugMetadata.methodDebugInformationInfosUsed = true; Free(ref ctx); } private uint VerifyGetRid(PdbDocument doc) { if (!debugMetadata.pdbDocumentInfos.TryGetRid(doc, out var rid)) { Error("PDB document has been removed"); return 0u; } return rid; } private static void GetSingleDocument(CilBody body, out PdbDocument singleDoc, out PdbDocument firstDoc, out bool hasNoSeqPoints) { IList instructions = body.Instructions; int num = 0; singleDoc = null; firstDoc = null; for (int i = 0; i < instructions.Count; i++) { SequencePoint sequencePoint = instructions[i].SequencePoint; if (sequencePoint == null) { continue; } PdbDocument document = sequencePoint.Document; if (document == null) { continue; } if (firstDoc == null) { firstDoc = document; } if (singleDoc != document) { singleDoc = document; num++; if (num > 1) { break; } } } hasNoSeqPoints = num == 0; if (num != 1) { singleDoc = null; } } protected void AddCustomDebugInformationList(Table table, uint rid, IHasCustomDebugInformation hcdi) { if (debugMetadata != null && hcdi.CustomDebugInfos.Count != 0) { SerializerMethodContext ctx = AllocSerializerMethodContext(); ctx.SetBody(null); AddCustomDebugInformationCore(ctx, table, rid, hcdi.CustomDebugInfos); Free(ref ctx); } } private void AddCustomDebugInformationList(Table table, uint rid, IList cdis) { if (debugMetadata != null && cdis.Count != 0) { SerializerMethodContext ctx = AllocSerializerMethodContext(); ctx.SetBody(null); AddCustomDebugInformationCore(ctx, table, rid, cdis); Free(ref ctx); } } private void AddCustomDebugInformationCore(SerializerMethodContext serializerMethodContext, Table table, uint rid, IList cdis) { MDToken token = new MDToken(table, rid); if (!CodedToken.HasCustomDebugInformation.Encode(token, out var codedToken)) { Error("Couldn't encode HasCustomDebugInformation token 0x{0:X8}.", token.Raw); return; } for (int i = 0; i < cdis.Count; i++) { PdbCustomDebugInfo pdbCustomDebugInfo = cdis[i]; if (pdbCustomDebugInfo == null) { Error("Custom debug info is null"); } else { AddCustomDebugInformation(serializerMethodContext, token.Raw, codedToken, pdbCustomDebugInfo); } } } private void AddCustomDebugInformation(SerializerMethodContext serializerMethodContext, uint token, uint encodedToken, PdbCustomDebugInfo cdi) { switch (cdi.Kind) { case PdbCustomDebugInfoKind.SourceServer: case PdbCustomDebugInfoKind.UsingGroups: case PdbCustomDebugInfoKind.ForwardMethodInfo: case PdbCustomDebugInfoKind.ForwardModuleInfo: case PdbCustomDebugInfoKind.StateMachineTypeName: case PdbCustomDebugInfoKind.DynamicLocals: case PdbCustomDebugInfoKind.TupleElementNames: Error("Unsupported custom debug info {0}", cdi.Kind); break; case PdbCustomDebugInfoKind.Unknown: case PdbCustomDebugInfoKind.TupleElementNames_PortablePdb: case PdbCustomDebugInfoKind.DefaultNamespace: case PdbCustomDebugInfoKind.DynamicLocalVariables: case PdbCustomDebugInfoKind.EmbeddedSource: case PdbCustomDebugInfoKind.SourceLink: case PdbCustomDebugInfoKind.CompilationMetadataReferences: case PdbCustomDebugInfoKind.CompilationOptions: case PdbCustomDebugInfoKind.TypeDefinitionDocuments: case PdbCustomDebugInfoKind.EditAndContinueStateMachineStateMap: case PdbCustomDebugInfoKind.PrimaryConstructorInformationBlob: case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: AddCustomDebugInformationCore(serializerMethodContext, encodedToken, cdi, cdi.Guid); break; case PdbCustomDebugInfoKind.AsyncMethod: AddCustomDebugInformationCore(serializerMethodContext, encodedToken, cdi, CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob); AddStateMachineMethod(cdi, token, ((PdbAsyncMethodCustomDebugInfo)cdi).KickoffMethod); break; case PdbCustomDebugInfoKind.IteratorMethod: AddStateMachineMethod(cdi, token, ((PdbIteratorMethodCustomDebugInfo)cdi).KickoffMethod); break; default: Error("Unknown custom debug info {0}.", cdi.Kind); break; } } private void AddStateMachineMethod(PdbCustomDebugInfo cdi, uint moveNextMethodToken, MethodDef kickoffMethod) { if (kickoffMethod == null) { Error("KickoffMethod is null"); return; } RawStateMachineMethodRow row = new RawStateMachineMethodRow(new MDToken(moveNextMethodToken).Rid, GetRid(kickoffMethod)); debugMetadata.stateMachineMethodInfos.Add(cdi, row); } private void AddCustomDebugInformationCore(SerializerMethodContext serializerMethodContext, uint encodedToken, PdbCustomDebugInfo cdi, Guid cdiGuid) { DataWriterContext ctx = AllocBinaryWriterContext(); byte[] data = PortablePdbCustomDebugInfoWriter.Write(this, serializerMethodContext, this, cdi, ctx); Free(ref ctx); RawCustomDebugInformationRow row = new RawCustomDebugInformationRow(encodedToken, debugMetadata.guidHeap.Add(cdiGuid), debugMetadata.blobHeap.Add(data)); debugMetadata.customDebugInfos.Add(cdi, row); } private void InitializeMethodDebugInformation() { if (debugMetadata != null) { int numberOfMethods = NumberOfMethods; for (int i = 0; i < numberOfMethods; i++) { debugMetadata.tablesHeap.MethodDebugInformationTable.Create(default(RawMethodDebugInformationRow)); } } } private void AddPdbDocuments() { if (debugMetadata == null) { return; } foreach (PdbDocument document in module.PdbState.Documents) { AddPdbDocument(document); } } private uint AddPdbDocument(PdbDocument doc) { if (doc == null) { Error("PdbDocument is null"); return 0u; } if (debugMetadata.pdbDocumentInfos.TryGetRid(doc, out var rid)) { return rid; } RawDocumentRow row = new RawDocumentRow(GetDocumentNameBlobOffset(doc.Url), debugMetadata.guidHeap.Add(doc.CheckSumAlgorithmId), debugMetadata.blobHeap.Add(doc.CheckSum), debugMetadata.guidHeap.Add(doc.Language)); rid = debugMetadata.tablesHeap.DocumentTable.Add(row); debugMetadata.pdbDocumentInfos.Add(doc, rid); AddCustomDebugInformationList(Table.Document, rid, doc.CustomDebugInfos); return rid; } private uint GetDocumentNameBlobOffset(string name) { if (name == null) { Error("Document name is null"); name = string.Empty; } DataWriterContext ctx = AllocBinaryWriterContext(); MemoryStream outStream = ctx.OutStream; DataWriter writer = ctx.Writer; outStream.SetLength(0L); outStream.Position = 0L; string[] array = name.Split(directorySeparatorCharArray); if (array.Length == 1) { writer.WriteByte(0); } else { writer.WriteBytes(directorySeparatorCharUtf8); } foreach (string s in array) { uint value = debugMetadata.blobHeap.Add(Encoding.UTF8.GetBytes(s)); writer.WriteCompressedUInt32(value); } uint result = debugMetadata.blobHeap.Add(outStream.ToArray()); Free(ref ctx); return result; } private uint AddImportScope(PdbImportScope scope) { if (scope == null) { return 0u; } if (debugMetadata.importScopeInfos.TryGetRid(scope, out var rid)) { if (rid == 0) { Error("PdbImportScope has an infinite Parent loop"); } return rid; } debugMetadata.importScopeInfos.Add(scope, 0u); DataWriterContext ctx = AllocBinaryWriterContext(); MemoryStream outStream = ctx.OutStream; DataWriter writer = ctx.Writer; outStream.SetLength(0L); outStream.Position = 0L; ImportScopeBlobWriter.Write(this, this, writer, debugMetadata.blobHeap, scope.Imports); byte[] data = outStream.ToArray(); Free(ref ctx); RawImportScopeRow row = new RawImportScopeRow(AddImportScope(scope.Parent), debugMetadata.blobHeap.Add(data)); rid = debugMetadata.tablesHeap.ImportScopeTable.Add(row); debugMetadata.importScopeInfos.SetRid(scope, rid); AddCustomDebugInformationList(Table.ImportScope, rid, scope.CustomDebugInfos); return rid; } private void AddLocalVariable(PdbLocal local) { if (local == null) { Error("PDB local is null"); return; } RawLocalVariableRow row = new RawLocalVariableRow((ushort)local.Attributes, (ushort)local.Index, debugMetadata.stringsHeap.Add(local.Name)); uint rid = debugMetadata.tablesHeap.LocalVariableTable.Create(row); debugMetadata.localVariableInfos.Add(local, rid); AddCustomDebugInformationList(Table.LocalVariable, rid, local.CustomDebugInfos); } private void AddLocalConstant(PdbConstant constant) { if (constant == null) { Error("PDB constant is null"); return; } DataWriterContext ctx = AllocBinaryWriterContext(); MemoryStream outStream = ctx.OutStream; DataWriter writer = ctx.Writer; outStream.SetLength(0L); outStream.Position = 0L; LocalConstantSigBlobWriter.Write(this, this, writer, constant.Type, constant.Value); byte[] data = outStream.ToArray(); Free(ref ctx); RawLocalConstantRow row = new RawLocalConstantRow(debugMetadata.stringsHeap.Add(constant.Name), debugMetadata.blobHeap.Add(data)); uint rid = debugMetadata.tablesHeap.LocalConstantTable.Create(row); debugMetadata.localConstantInfos.Add(constant, rid); AddCustomDebugInformationList(Table.LocalConstant, rid, constant.CustomDebugInfos); } internal void WritePortablePdb(Stream output, uint entryPointToken, out long pdbIdOffset) { if (debugMetadata == null) { throw new InvalidOperationException(); } PdbHeap pdbHeap = debugMetadata.PdbHeap; pdbHeap.EntryPoint = entryPointToken; tablesHeap.GetSystemTableRows(out var mask, pdbHeap.TypeSystemTableRows); debugMetadata.tablesHeap.SetSystemTableRows(pdbHeap.TypeSystemTableRows); if (!debugMetadata.methodDebugInformationInfosUsed) { debugMetadata.tablesHeap.MethodDebugInformationTable.Reset(); } pdbHeap.ReferencedTypeSystemTables = mask; DataWriter writer = new DataWriter(output); debugMetadata.OnBeforeSetOffset(); debugMetadata.SetOffset((FileOffset)0u, (RVA)0u); debugMetadata.GetFileLength(); debugMetadata.VerifyWriteTo(writer); pdbIdOffset = (long)pdbHeap.PdbIdOffset; } uint ISignatureWriterHelper.ToEncodedToken(ITypeDefOrRef typeDefOrRef) { return AddTypeDefOrRef(typeDefOrRef); } void IWriterError.Error(string message) { Error(message); } void IWriterError2.Error(string message, params object[] args) { Error(message, args); } bool IFullNameFactoryHelper.MustUseAssemblyName(IType type) { return FullNameFactory.MustUseAssemblyName(module, type, OptimizeCustomAttributeSerializedTypeNames); } protected virtual void Initialize() { } protected abstract TypeDef[] GetAllTypeDefs(); protected abstract void AllocateTypeDefRids(); protected abstract void AllocateMemberDefRids(); protected abstract uint AddTypeRef(TypeRef tr); protected abstract uint AddTypeSpec(TypeSpec ts); protected abstract uint AddMemberRef(MemberRef mr); protected abstract uint AddStandAloneSig(StandAloneSig sas); protected abstract uint AddMethodSpec(MethodSpec ms); protected virtual void BeforeSortingCustomAttributes() { } protected virtual void EverythingInitialized() { } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { if (length == 0) { throw new InvalidOperationException(); } return length <= origSize; } internal void OnBeforeSetOffset() { stringsHeap.AddOptimizedStringsAndSetReadOnly(); } public void SetOffset(FileOffset offset, RVA rva) { bool flag = this.offset == (FileOffset)0u; this.offset = offset; this.rva = rva; if (flag) { blobHeap.SetReadOnly(); guidHeap.SetReadOnly(); tablesHeap.SetReadOnly(); pdbHeap.SetReadOnly(); tablesHeap.BigStrings = stringsHeap.IsBig; tablesHeap.BigBlob = blobHeap.IsBig; tablesHeap.BigGuid = guidHeap.IsBig; metadataHeader.Heaps = GetHeaps(); } metadataHeader.SetOffset(offset, rva); uint fileLength = metadataHeader.GetFileLength(); offset += fileLength; rva += fileLength; foreach (IHeap heap in metadataHeader.Heaps) { offset = offset.AlignUp(4u); rva = rva.AlignUp(4u); heap.SetOffset(offset, rva); fileLength = heap.GetFileLength(); offset += fileLength; rva += fileLength; } if (!flag && length != rva - this.rva) { throw new InvalidOperationException(); } length = rva - this.rva; if (!isStandaloneDebugMetadata && flag) { UpdateMethodAndFieldRvas(); } } internal void UpdateMethodAndFieldRvas() { UpdateMethodRvas(); UpdateFieldRvas(); } private IList GetHeaps() { List list = new List(); if (isStandaloneDebugMetadata) { list.Add(pdbHeap); list.Add(tablesHeap); if (!stringsHeap.IsEmpty) { list.Add(stringsHeap); } if (!usHeap.IsEmpty) { list.Add(usHeap); } if (!guidHeap.IsEmpty) { list.Add(guidHeap); } if (!blobHeap.IsEmpty) { list.Add(blobHeap); } } else { list.Add(tablesHeap); if (!stringsHeap.IsEmpty || AlwaysCreateStringsHeap) { list.Add(stringsHeap); } if (!usHeap.IsEmpty || AlwaysCreateUSHeap) { list.Add(usHeap); } if (!guidHeap.IsEmpty || AlwaysCreateGuidHeap) { list.Add(guidHeap); } if (!blobHeap.IsEmpty || AlwaysCreateBlobHeap) { list.Add(blobHeap); } list.AddRange(options.CustomHeaps); options.RaiseMetadataHeapsAdded(new MetadataHeapsAddedEventArgs(this, list)); } return list; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { RVA rVA = rva; metadataHeader.VerifyWriteTo(writer); rVA += metadataHeader.GetFileLength(); foreach (IHeap heap in metadataHeader.Heaps) { writer.WriteZeroes((int)(rVA.AlignUp(4u) - rVA)); rVA = rVA.AlignUp(4u); heap.VerifyWriteTo(writer); rVA += heap.GetFileLength(); } } protected static List Sort(IEnumerable pds) { List list = new List(pds); list.Sort(delegate(ParamDef a, ParamDef b) { if (a == null) { return -1; } return (b == null) ? 1 : a.Sequence.CompareTo(b.Sequence); }); return list; } private DataWriterContext AllocBinaryWriterContext() { if (binaryWriterContexts.Count == 0) { return new DataWriterContext(); } DataWriterContext result = binaryWriterContexts[binaryWriterContexts.Count - 1]; binaryWriterContexts.RemoveAt(binaryWriterContexts.Count - 1); return result; } private void Free(ref DataWriterContext ctx) { binaryWriterContexts.Add(ctx); ctx = null; } private SerializerMethodContext AllocSerializerMethodContext() { if (serializerMethodContexts.Count == 0) { return new SerializerMethodContext(this); } SerializerMethodContext result = serializerMethodContexts[serializerMethodContexts.Count - 1]; serializerMethodContexts.RemoveAt(serializerMethodContexts.Count - 1); return result; } private void Free(ref SerializerMethodContext ctx) { serializerMethodContexts.Add(ctx); ctx = null; } } internal sealed class MetadataErrorContext { private sealed class ErrorSource : IDisposable { private MetadataErrorContext context; private readonly ErrorSource originalValue; public object Value { get; } public ErrorSource(MetadataErrorContext context, object value) { this.context = context; Value = value; originalValue = context.source; } public void Dispose() { if (context != null) { context.source = originalValue; context = null; } } } private ErrorSource source; public MetadataEvent Event { get; set; } public IDisposable SetSource(object source) { return this.source = new ErrorSource(this, source); } public void Append(string errorLevel, ref string message, ref object[] args) { int num = 1; string text = source?.Value as string; IMDTokenProvider iMDTokenProvider = source?.Value as IMDTokenProvider; if (iMDTokenProvider != null) { num += 2; } int num2 = args.Length; StringBuilder stringBuilder = new StringBuilder(message); object[] array = new object[args.Length + num]; Array.Copy(args, 0, array, 0, args.Length); if (stringBuilder.Length != 0 && stringBuilder[stringBuilder.Length - 1] != '.') { stringBuilder.Append('.'); } stringBuilder.AppendFormat(" {0} occurred after metadata event {{{1}}}", errorLevel, num2); array[num2] = Event; if (iMDTokenProvider != null) { string text2 = ((iMDTokenProvider is TypeDef) ? "type" : ((iMDTokenProvider is FieldDef) ? "field" : ((iMDTokenProvider is MethodDef) ? "method" : ((iMDTokenProvider is EventDef) ? "event" : ((!(iMDTokenProvider is PropertyDef)) ? "???" : "property"))))); string arg = text2; stringBuilder.AppendFormat(" during writing {0} '{{{1}}}' (0x{{{2}:X8}})", arg, num2 + 1, num2 + 2); array[num2 + 1] = iMDTokenProvider; array[num2 + 2] = iMDTokenProvider.MDToken.Raw; } else if (text != null) { stringBuilder.AppendFormat(" during writing {0}", text); } message = stringBuilder.Append('.').ToString(); args = array; } } public enum MetadataEvent { BeginCreateTables, AllocateTypeDefRids, AllocateMemberDefRids, MemberDefRidsAllocated, MemberDefsInitialized, BeforeSortTables, MostTablesSorted, MemberDefCustomAttributesWritten, BeginAddResources, EndAddResources, BeginWriteMethodBodies, EndWriteMethodBodies, OnAllTablesSorted, EndCreateTables } public sealed class MetadataHeaderOptions { public const string DEFAULT_VERSION_STRING = "v2.0.50727"; public const uint DEFAULT_SIGNATURE = 1112167234u; public uint? Signature; public ushort? MajorVersion; public ushort? MinorVersion; public uint? Reserved1; public string VersionString; public StorageFlags? StorageFlags; public byte? Reserved2; public static MetadataHeaderOptions CreatePortablePdbV1_0() { return new MetadataHeaderOptions { Signature = 1112167234u, MajorVersion = (ushort)1, MinorVersion = (ushort)1, Reserved1 = 0u, VersionString = "PDB v1.0", StorageFlags = dnlib.DotNet.MD.StorageFlags.Normal, Reserved2 = 0 }; } } public sealed class MetadataHeader : IChunk { private IList heaps; private readonly MetadataHeaderOptions options; private uint length; private FileOffset offset; private RVA rva; public FileOffset FileOffset => offset; public RVA RVA => rva; public IList Heaps { get { return heaps; } set { heaps = value; } } public MetadataHeader() : this(null) { } public MetadataHeader(MetadataHeaderOptions options) { this.options = options ?? new MetadataHeaderOptions(); } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = 16u; length += (uint)GetVersionString().Length; length = Utils.AlignUp(length, 4u); length += 4u; IList list = heaps; int count = list.Count; for (int i = 0; i < count; i++) { IHeap heap = list[i]; length += 8u; length += (uint)GetAsciizName(heap.Name).Length; length = Utils.AlignUp(length, 4u); } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { writer.WriteUInt32(options.Signature ?? 1112167234); writer.WriteUInt16(options.MajorVersion ?? 1); writer.WriteUInt16(options.MinorVersion ?? 1); writer.WriteUInt32(options.Reserved1.GetValueOrDefault()); byte[] versionString = GetVersionString(); writer.WriteInt32(Utils.AlignUp(versionString.Length, 4u)); writer.WriteBytes(versionString); writer.WriteZeroes(Utils.AlignUp(versionString.Length, 4u) - versionString.Length); writer.WriteByte((byte)options.StorageFlags.GetValueOrDefault()); writer.WriteByte(options.Reserved2.GetValueOrDefault()); IList list = heaps; writer.WriteUInt16((ushort)list.Count); int count = list.Count; for (int i = 0; i < count; i++) { IHeap heap = list[i]; writer.WriteUInt32(heap.FileOffset - offset); writer.WriteUInt32(heap.GetFileLength()); writer.WriteBytes(versionString = GetAsciizName(heap.Name)); if (versionString.Length > 32) { throw new ModuleWriterException("Heap name '" + heap.Name + "' is > 32 bytes"); } writer.WriteZeroes(Utils.AlignUp(versionString.Length, 4u) - versionString.Length); } } private byte[] GetVersionString() { return Encoding.UTF8.GetBytes((options.VersionString ?? "v2.0.50727") + "\0"); } private byte[] GetAsciizName(string s) { return Encoding.ASCII.GetBytes(s + "\0"); } } public sealed class MethodBody : IChunk { private const uint EXTRA_SECTIONS_ALIGNMENT = 4u; private readonly bool isTiny; private readonly byte[] code; private readonly byte[] extraSections; private uint length; private FileOffset offset; private RVA rva; private readonly uint localVarSigTok; public FileOffset FileOffset => offset; public RVA RVA => rva; public byte[] Code => code; public byte[] ExtraSections => extraSections; public uint LocalVarSigTok => localVarSigTok; public bool IsFat => !isTiny; public bool IsTiny => isTiny; public bool HasExtraSections { get { if (extraSections != null) { return extraSections.Length != 0; } return false; } } public MethodBody(byte[] code) : this(code, null, 0u) { } public MethodBody(byte[] code, byte[] extraSections) : this(code, extraSections, 0u) { } public MethodBody(byte[] code, byte[] extraSections, uint localVarSigTok) { isTiny = (code[0] & 3) == 2; this.code = code; this.extraSections = extraSections; this.localVarSigTok = localVarSigTok; } public int GetApproximateSizeOfMethodBody() { int num = code.Length; if (extraSections != null) { num = Utils.AlignUp(num, 4u); num += extraSections.Length; num = Utils.AlignUp(num, 4u); } return num; } internal bool CanReuse(RVA origRva, uint origSize) { uint num = ((!HasExtraSections) ? ((uint)code.Length) : ((uint)((int)((RVA)((uint)origRva + (uint)code.Length)).AlignUp(4u) + extraSections.Length) - (uint)origRva)); return num <= origSize; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; if (HasExtraSections) { RVA rVA = (RVA)((uint)rva + (uint)code.Length); rVA = rVA.AlignUp(4u); rVA = (RVA)((uint)rVA + (uint)extraSections.Length); length = rVA - rva; } else { length = (uint)code.Length; } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { writer.WriteBytes(code); if (HasExtraSections) { RVA rVA = (RVA)((uint)rva + (uint)code.Length); writer.WriteZeroes((int)(rVA.AlignUp(4u) - rVA)); writer.WriteBytes(extraSections); } } public override int GetHashCode() { return Utils.GetHashCode(code) + Utils.GetHashCode(extraSections); } public override bool Equals(object obj) { if (!(obj is MethodBody methodBody)) { return false; } if (Utils.Equals(code, methodBody.code)) { return Utils.Equals(extraSections, methodBody.extraSections); } return false; } } public sealed class MethodBodyChunks : IChunk { private readonly struct ReusedMethodInfo { public readonly MethodBody MethodBody; public readonly RVA RVA; public ReusedMethodInfo(MethodBody methodBody, RVA rva) { MethodBody = methodBody; RVA = rva; } } private const uint FAT_BODY_ALIGNMENT = 4u; private Dictionary tinyMethodsDict; private Dictionary fatMethodsDict; private readonly List tinyMethods; private readonly List fatMethods; private readonly List reusedMethods; private readonly Dictionary rvaToReusedMethod; private readonly bool shareBodies; private FileOffset offset; private RVA rva; private uint length; private bool setOffsetCalled; private readonly bool alignFatBodies; private uint savedBytes; public FileOffset FileOffset => offset; public RVA RVA => rva; public uint SavedBytes => savedBytes; internal bool CanReuseOldBodyLocation { get; set; } internal bool ReusedAllMethodBodyLocations { get { if (tinyMethods.Count == 0) { return fatMethods.Count == 0; } return false; } } internal bool HasReusedMethods => reusedMethods.Count > 0; public MethodBodyChunks(bool shareBodies) { this.shareBodies = shareBodies; alignFatBodies = true; if (shareBodies) { tinyMethodsDict = new Dictionary(); fatMethodsDict = new Dictionary(); } tinyMethods = new List(); fatMethods = new List(); reusedMethods = new List(); rvaToReusedMethod = new Dictionary(); } public MethodBody Add(MethodBody methodBody) { return Add(methodBody, (RVA)0u, 0u); } internal MethodBody Add(MethodBody methodBody, RVA origRva, uint origSize) { if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } if (CanReuseOldBodyLocation && origRva != 0 && origSize != 0 && methodBody.CanReuse(origRva, origSize)) { if (!rvaToReusedMethod.TryGetValue((uint)origRva, out var value)) { rvaToReusedMethod.Add((uint)origRva, methodBody); reusedMethods.Add(new ReusedMethodInfo(methodBody, origRva)); return methodBody; } if (methodBody.Equals(value)) { return value; } } if (shareBodies) { Dictionary dictionary = (methodBody.IsFat ? fatMethodsDict : tinyMethodsDict); if (dictionary.TryGetValue(methodBody, out var value2)) { savedBytes += (uint)methodBody.GetApproximateSizeOfMethodBody(); return value2; } dictionary[methodBody] = methodBody; } (methodBody.IsFat ? fatMethods : tinyMethods).Add(methodBody); return methodBody; } public bool Remove(MethodBody methodBody) { if (methodBody == null) { throw new ArgumentNullException("methodBody"); } if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } if (CanReuseOldBodyLocation) { throw new InvalidOperationException("Reusing old body locations is enabled. Can't remove bodies."); } return (methodBody.IsFat ? fatMethods : tinyMethods).Remove(methodBody); } internal void InitializeReusedMethodBodies(Func getNewFileOffset) { foreach (ReusedMethodInfo reusedMethod in reusedMethods) { FileOffset fileOffset = getNewFileOffset(reusedMethod.RVA); reusedMethod.MethodBody.SetOffset(fileOffset, reusedMethod.RVA); } } internal void WriteReusedMethodBodies(DataWriter writer, long destStreamBaseOffset) { foreach (ReusedMethodInfo reusedMethod in reusedMethods) { if (reusedMethod.MethodBody.RVA != reusedMethod.RVA) { throw new InvalidOperationException(); } writer.Position = destStreamBaseOffset + (long)reusedMethod.MethodBody.FileOffset; reusedMethod.MethodBody.VerifyWriteTo(writer); } } public void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; tinyMethodsDict = null; fatMethodsDict = null; RVA rVA = rva; foreach (MethodBody tinyMethod in tinyMethods) { tinyMethod.SetOffset(offset, rVA); uint fileLength = tinyMethod.GetFileLength(); rVA += fileLength; offset += fileLength; } foreach (MethodBody fatMethod in fatMethods) { if (alignFatBodies) { uint num = rVA.AlignUp(4u) - rVA; rVA += num; offset += num; } fatMethod.SetOffset(offset, rVA); uint fileLength2 = fatMethod.GetFileLength(); rVA += fileLength2; offset += fileLength2; } length = rVA - rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { RVA rVA = rva; foreach (MethodBody tinyMethod in tinyMethods) { tinyMethod.VerifyWriteTo(writer); rVA += tinyMethod.GetFileLength(); } foreach (MethodBody fatMethod in fatMethods) { if (alignFatBodies) { int num = (int)(rVA.AlignUp(4u) - rVA); writer.WriteZeroes(num); rVA = (RVA)((uint)rVA + (uint)num); } fatMethod.VerifyWriteTo(writer); rVA += fatMethod.GetFileLength(); } } } public interface ITokenProvider : IWriterError { MDToken GetToken(object o); MDToken GetToken(IList locals, uint origToken); } public sealed class MethodBodyWriter : MethodBodyWriterBase { private readonly ITokenProvider helper; private CilBody cilBody; private bool keepMaxStack; private uint codeSize; private uint maxStack; private byte[] code; private byte[] extraSections; private uint localVarSigTok; public byte[] Code => code; public byte[] ExtraSections => extraSections; public uint LocalVarSigTok => localVarSigTok; public MethodBodyWriter(ITokenProvider helper, MethodDef method) : this(helper, method, keepMaxStack: false) { } public MethodBodyWriter(ITokenProvider helper, MethodDef method, bool keepMaxStack) : base(method.Body.Instructions, method.Body.ExceptionHandlers) { this.helper = helper; cilBody = method.Body; this.keepMaxStack = keepMaxStack; } public MethodBodyWriter(ITokenProvider helper, CilBody cilBody) : this(helper, cilBody, keepMaxStack: false) { } public MethodBodyWriter(ITokenProvider helper, CilBody cilBody, bool keepMaxStack) : base(cilBody.Instructions, cilBody.ExceptionHandlers) { this.helper = helper; this.cilBody = cilBody; this.keepMaxStack = keepMaxStack; } internal MethodBodyWriter(ITokenProvider helper) { this.helper = helper; } internal void Reset(CilBody cilBody, bool keepMaxStack) { Reset(cilBody.Instructions, cilBody.ExceptionHandlers); this.cilBody = cilBody; this.keepMaxStack = keepMaxStack; codeSize = 0u; maxStack = 0u; code = null; extraSections = null; localVarSigTok = 0u; } public void Write() { codeSize = InitializeInstructionOffsets(); maxStack = (keepMaxStack ? cilBody.MaxStack : GetMaxStack()); if (NeedFatHeader()) { WriteFatHeader(); } else { WriteTinyHeader(); } if (exceptionHandlers.Count > 0) { WriteExceptionHandlers(); } } public byte[] GetFullMethodBody() { int num = Utils.AlignUp(code.Length, 4u) - code.Length; byte[] array = new byte[code.Length + ((extraSections != null) ? (num + extraSections.Length) : 0)]; Array.Copy(code, 0, array, 0, code.Length); if (extraSections != null) { Array.Copy(extraSections, 0, array, code.Length + num, extraSections.Length); } return array; } private bool NeedFatHeader() { if (codeSize <= 63 && exceptionHandlers.Count <= 0 && !cilBody.HasVariables) { return maxStack > 8; } return true; } private void WriteFatHeader() { if (maxStack > 65535) { Error("MaxStack is too big"); maxStack = 65535u; } ushort num = 12291; if (exceptionHandlers.Count > 0) { num |= 8; } if (cilBody.InitLocals) { num |= 0x10; } code = new byte[12 + codeSize]; ArrayWriter writer = new ArrayWriter(code); writer.WriteUInt16(num); writer.WriteUInt16((ushort)maxStack); writer.WriteUInt32(codeSize); writer.WriteUInt32(localVarSigTok = helper.GetToken(GetLocals(), cilBody.LocalVarSigTok).Raw); if (WriteInstructions(ref writer) != codeSize) { Error("Didn't write all code bytes"); } } private IList GetLocals() { TypeSig[] array = new TypeSig[cilBody.Variables.Count]; for (int i = 0; i < cilBody.Variables.Count; i++) { array[i] = cilBody.Variables[i].Type; } return array; } private void WriteTinyHeader() { localVarSigTok = 0u; code = new byte[1 + codeSize]; ArrayWriter writer = new ArrayWriter(code); writer.WriteByte((byte)((codeSize << 2) | 2)); if (WriteInstructions(ref writer) != codeSize) { Error("Didn't write all code bytes"); } } private void WriteExceptionHandlers() { if (NeedFatExceptionClauses()) { extraSections = WriteFatExceptionClauses(); } else { extraSections = WriteSmallExceptionClauses(); } } private bool NeedFatExceptionClauses() { IList list = exceptionHandlers; if (list.Count > 20) { return true; } for (int i = 0; i < list.Count; i++) { ExceptionHandler exceptionHandler = list[i]; if (!FitsInSmallExceptionClause(exceptionHandler.TryStart, exceptionHandler.TryEnd)) { return true; } if (!FitsInSmallExceptionClause(exceptionHandler.HandlerStart, exceptionHandler.HandlerEnd)) { return true; } } return false; } private bool FitsInSmallExceptionClause(Instruction start, Instruction end) { uint offset = GetOffset2(start); uint offset2 = GetOffset2(end); if (offset2 < offset) { return false; } if (offset <= 65535) { return offset2 - offset <= 255; } return false; } private uint GetOffset2(Instruction instr) { if (instr == null) { return codeSize; } return GetOffset(instr); } private byte[] WriteFatExceptionClauses() { IList list = exceptionHandlers; int num = list.Count; if (num > 699050) { Error("Too many exception handlers"); num = 699050; } byte[] array = new byte[num * 24 + 4]; ArrayWriter arrayWriter = new ArrayWriter(array); arrayWriter.WriteUInt32((uint)((num * 24 + 4 << 8) | 0x41)); for (int i = 0; i < num; i++) { ExceptionHandler exceptionHandler = list[i]; arrayWriter.WriteUInt32((uint)exceptionHandler.HandlerType); uint offset = GetOffset2(exceptionHandler.TryStart); uint offset2 = GetOffset2(exceptionHandler.TryEnd); if (offset2 <= offset) { Error("Exception handler: TryEnd <= TryStart"); } arrayWriter.WriteUInt32(offset); arrayWriter.WriteUInt32(offset2 - offset); offset = GetOffset2(exceptionHandler.HandlerStart); offset2 = GetOffset2(exceptionHandler.HandlerEnd); if (offset2 <= offset) { Error("Exception handler: HandlerEnd <= HandlerStart"); } arrayWriter.WriteUInt32(offset); arrayWriter.WriteUInt32(offset2 - offset); if (exceptionHandler.IsCatch) { arrayWriter.WriteUInt32(helper.GetToken(exceptionHandler.CatchType).Raw); } else if (exceptionHandler.IsFilter) { arrayWriter.WriteUInt32(GetOffset2(exceptionHandler.FilterStart)); } else { arrayWriter.WriteInt32(0); } } if (arrayWriter.Position != array.Length) { throw new InvalidOperationException(); } return array; } private byte[] WriteSmallExceptionClauses() { IList list = exceptionHandlers; int num = list.Count; if (num > 20) { Error("Too many exception handlers"); num = 20; } byte[] array = new byte[num * 12 + 4]; ArrayWriter arrayWriter = new ArrayWriter(array); arrayWriter.WriteUInt32((uint)((num * 12 + 4 << 8) | 1)); for (int i = 0; i < num; i++) { ExceptionHandler exceptionHandler = list[i]; arrayWriter.WriteUInt16((ushort)exceptionHandler.HandlerType); uint offset = GetOffset2(exceptionHandler.TryStart); uint offset2 = GetOffset2(exceptionHandler.TryEnd); if (offset2 <= offset) { Error("Exception handler: TryEnd <= TryStart"); } arrayWriter.WriteUInt16((ushort)offset); arrayWriter.WriteByte((byte)(offset2 - offset)); offset = GetOffset2(exceptionHandler.HandlerStart); offset2 = GetOffset2(exceptionHandler.HandlerEnd); if (offset2 <= offset) { Error("Exception handler: HandlerEnd <= HandlerStart"); } arrayWriter.WriteUInt16((ushort)offset); arrayWriter.WriteByte((byte)(offset2 - offset)); if (exceptionHandler.IsCatch) { arrayWriter.WriteUInt32(helper.GetToken(exceptionHandler.CatchType).Raw); } else if (exceptionHandler.IsFilter) { arrayWriter.WriteUInt32(GetOffset2(exceptionHandler.FilterStart)); } else { arrayWriter.WriteInt32(0); } } if (arrayWriter.Position != array.Length) { throw new InvalidOperationException(); } return array; } protected override void ErrorImpl(string message) { helper.Error(message); } protected override void WriteInlineField(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } protected override void WriteInlineMethod(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } protected override void WriteInlineSig(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } protected override void WriteInlineString(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } protected override void WriteInlineTok(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } protected override void WriteInlineType(ref ArrayWriter writer, Instruction instr) { writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); } } public abstract class MethodBodyWriterBase { protected IList instructions; protected IList exceptionHandlers; private readonly Dictionary offsets = new Dictionary(); private uint firstInstructionOffset; private int errors; private MaxStackCalculator maxStackCalculator = MaxStackCalculator.Create(); public bool ErrorDetected => errors > 0; internal MethodBodyWriterBase() { } protected MethodBodyWriterBase(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; } internal void Reset(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; offsets.Clear(); firstInstructionOffset = 0u; errors = 0; } protected void Error(string message) { errors++; ErrorImpl(message); } protected virtual void ErrorImpl(string message) { } protected uint GetMaxStack() { if (instructions.Count == 0) { return 0u; } maxStackCalculator.Reset(instructions, exceptionHandlers); if (!maxStackCalculator.Calculate(out var maxStack)) { Error("Error calculating max stack value. If the method's obfuscated, set CilBody.KeepOldMaxStack or MetadataOptions.Flags (KeepOldMaxStack, global option) to ignore this error. Otherwise fix your generated CIL code so it conforms to the ECMA standard."); return maxStack + 8; } return maxStack; } protected uint GetOffset(Instruction instr) { if (instr == null) { Error("Instruction is null"); return 0u; } if (offsets.TryGetValue(instr, out var value)) { return value; } Error("Found some other method's instruction or a removed instruction. You probably removed an instruction that is the target of a branch instruction or an instruction that's the first/last instruction in an exception handler."); return 0u; } protected uint InitializeInstructionOffsets() { uint num = 0u; IList list = instructions; for (int i = 0; i < list.Count; i++) { Instruction instruction = list[i]; if (instruction != null) { offsets[instruction] = num; num += GetSizeOfInstruction(instruction); } } return num; } protected virtual uint GetSizeOfInstruction(Instruction instr) { return (uint)instr.GetSize(); } protected uint WriteInstructions(ref ArrayWriter writer) { firstInstructionOffset = (uint)writer.Position; IList list = instructions; for (int i = 0; i < list.Count; i++) { Instruction instruction = list[i]; if (instruction != null) { WriteInstruction(ref writer, instruction); } } return ToInstructionOffset(ref writer); } protected uint ToInstructionOffset(ref ArrayWriter writer) { return (uint)writer.Position - firstInstructionOffset; } protected virtual void WriteInstruction(ref ArrayWriter writer, Instruction instr) { WriteOpCode(ref writer, instr); WriteOperand(ref writer, instr); } protected void WriteOpCode(ref ArrayWriter writer, Instruction instr) { Code code = instr.OpCode.Code; int num = (int)code >> 8; if ((int)code <= 255) { writer.WriteByte((byte)code); return; } switch (num) { case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 254: writer.WriteByte((byte)((int)code >> 8)); writer.WriteByte((byte)code); return; } switch (code) { case Code.UNKNOWN1: writer.WriteByte(0); break; case Code.UNKNOWN2: writer.WriteUInt16(0); break; default: Error("Unknown instruction"); writer.WriteByte(0); break; } } protected void WriteOperand(ref ArrayWriter writer, Instruction instr) { switch (instr.OpCode.OperandType) { case dnlib.DotNet.Emit.OperandType.InlineBrTarget: WriteInlineBrTarget(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineField: WriteInlineField(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineI: WriteInlineI(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineI8: WriteInlineI8(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineMethod: WriteInlineMethod(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineNone: WriteInlineNone(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlinePhi: WriteInlinePhi(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineR: WriteInlineR(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineSig: WriteInlineSig(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineString: WriteInlineString(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineSwitch: WriteInlineSwitch(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineTok: WriteInlineTok(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineType: WriteInlineType(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.InlineVar: WriteInlineVar(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.ShortInlineBrTarget: WriteShortInlineBrTarget(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.ShortInlineI: WriteShortInlineI(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.ShortInlineR: WriteShortInlineR(ref writer, instr); break; case dnlib.DotNet.Emit.OperandType.ShortInlineVar: WriteShortInlineVar(ref writer, instr); break; default: Error("Unknown operand type"); break; } } protected virtual void WriteInlineBrTarget(ref ArrayWriter writer, Instruction instr) { uint value = GetOffset(instr.Operand as Instruction) - (ToInstructionOffset(ref writer) + 4); writer.WriteUInt32(value); } protected abstract void WriteInlineField(ref ArrayWriter writer, Instruction instr); protected virtual void WriteInlineI(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is int) { writer.WriteInt32((int)instr.Operand); return; } Error("Operand is not an Int32"); writer.WriteInt32(0); } protected virtual void WriteInlineI8(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is long) { writer.WriteInt64((long)instr.Operand); return; } Error("Operand is not an Int64"); writer.WriteInt64(0L); } protected abstract void WriteInlineMethod(ref ArrayWriter writer, Instruction instr); protected virtual void WriteInlineNone(ref ArrayWriter writer, Instruction instr) { } protected virtual void WriteInlinePhi(ref ArrayWriter writer, Instruction instr) { } protected virtual void WriteInlineR(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is double) { writer.WriteDouble((double)instr.Operand); return; } Error("Operand is not a Double"); writer.WriteDouble(0.0); } protected abstract void WriteInlineSig(ref ArrayWriter writer, Instruction instr); protected abstract void WriteInlineString(ref ArrayWriter writer, Instruction instr); protected virtual void WriteInlineSwitch(ref ArrayWriter writer, Instruction instr) { if (!(instr.Operand is IList list)) { Error("switch operand is not a list of instructions"); writer.WriteInt32(0); return; } uint num = (uint)(ToInstructionOffset(ref writer) + 4 + list.Count * 4); writer.WriteInt32(list.Count); for (int i = 0; i < list.Count; i++) { Instruction instr2 = list[i]; writer.WriteUInt32(GetOffset(instr2) - num); } } protected abstract void WriteInlineTok(ref ArrayWriter writer, Instruction instr); protected abstract void WriteInlineType(ref ArrayWriter writer, Instruction instr); protected virtual void WriteInlineVar(ref ArrayWriter writer, Instruction instr) { if (!(instr.Operand is IVariable { Index: var index })) { Error("Operand is not a local/arg"); writer.WriteUInt16(0); } else if (0 <= index && index <= 65535) { writer.WriteUInt16((ushort)index); } else { Error("Local/arg index doesn't fit in a UInt16"); writer.WriteUInt16(0); } } protected virtual void WriteShortInlineBrTarget(ref ArrayWriter writer, Instruction instr) { int num = (int)(GetOffset(instr.Operand as Instruction) - (ToInstructionOffset(ref writer) + 1)); if (-128 <= num && num <= 127) { writer.WriteSByte((sbyte)num); return; } Error("Target instruction is too far away for a short branch. Use the long branch or call CilBody.SimplifyBranches() and CilBody.OptimizeBranches()"); writer.WriteByte(0); } protected virtual void WriteShortInlineI(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is sbyte) { writer.WriteSByte((sbyte)instr.Operand); return; } if (instr.Operand is byte) { writer.WriteByte((byte)instr.Operand); return; } Error("Operand is not a Byte or a SByte"); writer.WriteByte(0); } protected virtual void WriteShortInlineR(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is float) { writer.WriteSingle((float)instr.Operand); return; } Error("Operand is not a Single"); writer.WriteSingle(0f); } protected virtual void WriteShortInlineVar(ref ArrayWriter writer, Instruction instr) { if (!(instr.Operand is IVariable { Index: var index })) { Error("Operand is not a local/arg"); writer.WriteByte(0); } else if (0 <= index && index <= 255) { writer.WriteByte((byte)index); } else { Error("Local/arg index doesn't fit in a Byte. Use the longer ldloc/ldarg/stloc/starg instruction."); writer.WriteByte(0); } } } public sealed class ModuleWriterOptions : ModuleWriterOptionsBase { public ModuleWriterOptions(ModuleDef module) : base(module) { } } public sealed class ModuleWriter : ModuleWriterBase { private const uint DEFAULT_RELOC_ALIGNMENT = 4u; private const uint MVID_ALIGNMENT = 1u; private readonly ModuleDef module; private ModuleWriterOptions options; private List sections; private PESection mvidSection; private PESection textSection; private PESection sdataSection; private PESection rsrcSection; private PESection relocSection; private PEHeaders peHeaders; private ImportAddressTable importAddressTable; private ImageCor20Header imageCor20Header; private ImportDirectory importDirectory; private StartupStub startupStub; private RelocDirectory relocDirectory; private ManagedExportsWriter managedExportsWriter; private bool needStartupStub; public override ModuleDef Module => module; public override ModuleWriterOptionsBase TheOptions => Options; public ModuleWriterOptions Options { get { return options ?? (options = new ModuleWriterOptions(module)); } set { options = value; } } public override List Sections => sections; public override PESection TextSection => textSection; internal PESection SdataSection => sdataSection; public override PESection RsrcSection => rsrcSection; public PESection RelocSection => relocSection; public PEHeaders PEHeaders => peHeaders; public ImportAddressTable ImportAddressTable => importAddressTable; public ImageCor20Header ImageCor20Header => imageCor20Header; public ImportDirectory ImportDirectory => importDirectory; public StartupStub StartupStub => startupStub; public RelocDirectory RelocDirectory => relocDirectory; public override void AddSection(PESection section) { if (sections.Count > 0 && sections[sections.Count - 1] == relocSection) { sections.Insert(sections.Count - 1, section); } else { sections.Add(section); } } public ModuleWriter(ModuleDef module) : this(module, null) { } public ModuleWriter(ModuleDef module, ModuleWriterOptions options) { this.module = module; this.options = options; } protected override long WriteImpl() { Initialize(); metadata.CreateTables(); return WriteFile(); } private void Initialize() { CreateSections(); OnWriterEvent(ModuleWriterEvent.PESectionsCreated); CreateChunks(); OnWriterEvent(ModuleWriterEvent.ChunksCreated); AddChunksToSections(); OnWriterEvent(ModuleWriterEvent.ChunksAddedToSections); } protected override Win32Resources GetWin32Resources() { if (Options.NoWin32Resources) { return null; } return Options.Win32Resources ?? module.Win32Resources; } private void CreateSections() { sections = new List(); if (TheOptions.AddMvidSection) { sections.Add(mvidSection = new PESection(".mvid", 1107296320u)); } sections.Add(textSection = new PESection(".text", 1610612768u)); sections.Add(sdataSection = new PESection(".sdata", 3221225536u)); if (GetWin32Resources() != null) { sections.Add(rsrcSection = new PESection(".rsrc", 1073741888u)); } sections.Add(relocSection = new PESection(".reloc", 1107296320u)); } private void CreateChunks() { peHeaders = new PEHeaders(Options.PEHeadersOptions); Machine machine = Options.PEHeadersOptions.Machine ?? Machine.I386; bool is64bit = machine.Is64Bit(); relocDirectory = new RelocDirectory(machine); if (machine.IsI386()) { needStartupStub = true; } importAddressTable = new ImportAddressTable(is64bit); importDirectory = new ImportDirectory(is64bit); startupStub = new StartupStub(relocDirectory, machine, delegate(string format, object[] args) { Error(format, args); }); CreateStrongNameSignature(); imageCor20Header = new ImageCor20Header(Options.Cor20HeaderOptions); CreateMetadataChunks(module); managedExportsWriter = new ManagedExportsWriter(UTF8String.ToSystemStringOrEmpty(module.Name), machine, relocDirectory, metadata, peHeaders, delegate(string format, object[] args) { Error(format, args); }); CreateDebugDirectory(); importDirectory.IsExeFile = Options.IsExeFile; peHeaders.IsExeFile = Options.IsExeFile; } private void AddChunksToSections() { uint alignment = ((Options.PEHeadersOptions.Machine ?? Machine.I386).Is64Bit() ? 8u : 4u); if (mvidSection != null) { mvidSection.Add(new ByteArrayChunk((module.Mvid ?? Guid.Empty).ToByteArray()), 1u); } textSection.Add(importAddressTable, alignment); textSection.Add(imageCor20Header, 4u); textSection.Add(strongNameSignature, 4u); managedExportsWriter.AddTextChunks(textSection); textSection.Add(constants, 8u); textSection.Add(methodBodies, 4u); textSection.Add(netResources, 4u); textSection.Add(metadata, 4u); textSection.Add(debugDirectory, 4u); textSection.Add(importDirectory, alignment); textSection.Add(startupStub, startupStub.Alignment); managedExportsWriter.AddSdataChunks(sdataSection); if (GetWin32Resources() != null) { rsrcSection.Add(win32Resources, 8u); } relocSection.Add(relocDirectory, 4u); } private long WriteFile() { managedExportsWriter.AddExportedMethods(metadata.ExportedMethods, GetTimeDateStamp()); if (managedExportsWriter.HasExports) { needStartupStub = true; } OnWriterEvent(ModuleWriterEvent.BeginWritePdb); WritePdbFile(); OnWriterEvent(ModuleWriterEvent.EndWritePdb); metadata.OnBeforeSetOffset(); OnWriterEvent(ModuleWriterEvent.BeginCalculateRvasAndFileOffsets); List list = new List(); list.Add(peHeaders); if (!managedExportsWriter.HasExports) { sections.Remove(sdataSection); } if (!relocDirectory.NeedsRelocSection && !managedExportsWriter.HasExports && !needStartupStub) { sections.Remove(relocSection); } importAddressTable.Enable = needStartupStub; importDirectory.Enable = needStartupStub; startupStub.Enable = needStartupStub; foreach (PESection section in sections) { list.Add(section); } peHeaders.PESections = sections; int num = sections.IndexOf(relocSection); if (num >= 0 && num != sections.Count - 1) { throw new InvalidOperationException("Reloc section must be the last section, use AddSection() to add a section"); } CalculateRvasAndFileOffsets(list, (FileOffset)0u, (RVA)0u, peHeaders.FileAlignment, peHeaders.SectionAlignment); OnWriterEvent(ModuleWriterEvent.EndCalculateRvasAndFileOffsets); InitializeChunkProperties(); OnWriterEvent(ModuleWriterEvent.BeginWriteChunks); DataWriter dataWriter = new DataWriter(destStream); WriteChunks(dataWriter, list, (FileOffset)0u, peHeaders.FileAlignment); long num2 = dataWriter.Position - destStreamBaseOffset; OnWriterEvent(ModuleWriterEvent.EndWriteChunks); OnWriterEvent(ModuleWriterEvent.BeginStrongNameSign); if (Options.StrongNameKey != null) { StrongNameSign((long)strongNameSignature.FileOffset); } OnWriterEvent(ModuleWriterEvent.EndStrongNameSign); OnWriterEvent(ModuleWriterEvent.BeginWritePEChecksum); if (Options.AddCheckSum) { peHeaders.WriteCheckSum(dataWriter, num2); } OnWriterEvent(ModuleWriterEvent.EndWritePEChecksum); return num2; } private void InitializeChunkProperties() { Options.Cor20HeaderOptions.EntryPoint = GetEntryPoint(); importAddressTable.ImportDirectory = importDirectory; importDirectory.ImportAddressTable = importAddressTable; startupStub.ImportDirectory = importDirectory; startupStub.PEHeaders = peHeaders; peHeaders.StartupStub = startupStub; peHeaders.ImageCor20Header = imageCor20Header; peHeaders.ImportAddressTable = importAddressTable; peHeaders.ImportDirectory = importDirectory; peHeaders.Win32Resources = win32Resources; peHeaders.RelocDirectory = relocDirectory; peHeaders.DebugDirectory = debugDirectory; imageCor20Header.Metadata = metadata; imageCor20Header.NetResources = netResources; imageCor20Header.StrongNameSignature = strongNameSignature; managedExportsWriter.InitializeChunkProperties(); } private uint GetEntryPoint() { uint? entryPoint = Options.Cor20HeaderOptions.EntryPoint; if (entryPoint.HasValue) { return entryPoint.Value; } if (module.ManagedEntryPoint is MethodDef md) { return new MDToken(Table.Method, metadata.GetRid(md)).Raw; } if (module.ManagedEntryPoint is FileDef fd) { return new MDToken(Table.File, metadata.GetRid(fd)).Raw; } uint nativeEntryPoint = (uint)module.NativeEntryPoint; if (nativeEntryPoint != 0) { return nativeEntryPoint; } return 0u; } } public readonly struct ModuleWriterEventArgs { public ModuleWriterBase Writer { get; } public ModuleWriterEvent Event { get; } public ModuleWriterEventArgs(ModuleWriterBase writer, ModuleWriterEvent @event) { Writer = writer ?? throw new ArgumentNullException("writer"); Event = @event; } } public readonly struct ModuleWriterProgressEventArgs { public ModuleWriterBase Writer { get; } public double Progress { get; } public ModuleWriterProgressEventArgs(ModuleWriterBase writer, double progress) { if (progress < 0.0 || progress > 1.0) { throw new ArgumentOutOfRangeException("progress"); } Writer = writer ?? throw new ArgumentNullException("writer"); Progress = progress; } } public readonly struct ContentId { public readonly Guid Guid; public readonly uint Timestamp; public ContentId(Guid guid, uint timestamp) { Guid = guid; Timestamp = timestamp; } } public delegate void EventHandler2(object sender, TEventArgs e); [Flags] public enum PdbWriterOptions { None = 0, NoDiaSymReader = 1, NoOldDiaSymReader = 2, Deterministic = 4, PdbChecksum = 8 } public class ModuleWriterOptionsBase { private PEHeadersOptions peHeadersOptions; private Cor20HeaderOptions cor20HeaderOptions; private MetadataOptions metadataOptions; private ILogger logger; private ILogger metadataLogger; private bool noWin32Resources; private Win32Resources win32Resources; private StrongNameKey strongNameKey; private StrongNamePublicKey strongNamePublicKey; private bool delaySign; private const ChecksumAlgorithm DefaultPdbChecksumAlgorithm = ChecksumAlgorithm.SHA256; public ILogger Logger { get { return logger; } set { logger = value; } } public ILogger MetadataLogger { get { return metadataLogger; } set { metadataLogger = value; } } public PEHeadersOptions PEHeadersOptions { get { return peHeadersOptions ?? (peHeadersOptions = new PEHeadersOptions()); } set { peHeadersOptions = value; } } public Cor20HeaderOptions Cor20HeaderOptions { get { return cor20HeaderOptions ?? (cor20HeaderOptions = new Cor20HeaderOptions()); } set { cor20HeaderOptions = value; } } public MetadataOptions MetadataOptions { get { return metadataOptions ?? (metadataOptions = new MetadataOptions()); } set { metadataOptions = value; } } public bool NoWin32Resources { get { return noWin32Resources; } set { noWin32Resources = value; } } public Win32Resources Win32Resources { get { return win32Resources; } set { win32Resources = value; } } public bool DelaySign { get { return delaySign; } set { delaySign = value; } } public StrongNameKey StrongNameKey { get { return strongNameKey; } set { strongNameKey = value; } } public StrongNamePublicKey StrongNamePublicKey { get { return strongNamePublicKey; } set { strongNamePublicKey = value; } } public bool ShareMethodBodies { get; set; } public bool AddCheckSum { get; set; } public bool Is64Bit { get { if (!PEHeadersOptions.Machine.HasValue) { return false; } return PEHeadersOptions.Machine.Value.Is64Bit(); } } public ModuleKind ModuleKind { get; set; } public bool IsExeFile { get { if (ModuleKind != ModuleKind.Dll) { return ModuleKind != ModuleKind.NetModule; } return false; } } public bool WritePdb { get; set; } public PdbWriterOptions PdbOptions { get; set; } public string PdbFileName { get; set; } public string PdbFileNameInDebugDirectory { get; set; } public Stream PdbStream { get; set; } public Func GetPdbContentId { get; set; } public ChecksumAlgorithm PdbChecksumAlgorithm { get; set; } = ChecksumAlgorithm.SHA256; public bool AddMvidSection { get; set; } public event EventHandler2 WriterEvent; public event EventHandler2 ProgressUpdated; internal void RaiseEvent(object sender, ModuleWriterEventArgs e) { this.WriterEvent?.Invoke(sender, e); } internal void RaiseEvent(object sender, ModuleWriterProgressEventArgs e) { this.ProgressUpdated?.Invoke(sender, e); } protected ModuleWriterOptionsBase(ModuleDef module) { ShareMethodBodies = true; MetadataOptions.MetadataHeaderOptions.VersionString = module.RuntimeVersion; ModuleKind = module.Kind; PEHeadersOptions.Machine = module.Machine; PEHeadersOptions.Characteristics = module.Characteristics; PEHeadersOptions.DllCharacteristics = module.DllCharacteristics; if (module.Kind == ModuleKind.Windows) { PEHeadersOptions.Subsystem = Subsystem.WindowsGui; } else { PEHeadersOptions.Subsystem = Subsystem.WindowsCui; } PEHeadersOptions.NumberOfRvaAndSizes = 16u; Cor20HeaderOptions.Flags = module.Cor20HeaderFlags; if (module.Assembly != null && !PublicKeyBase.IsNullOrEmpty2(module.Assembly.PublicKey)) { Cor20HeaderOptions.Flags |= ComImageFlags.StrongNameSigned; } if (module.Cor20HeaderRuntimeVersion.HasValue) { Cor20HeaderOptions.MajorRuntimeVersion = (ushort)(module.Cor20HeaderRuntimeVersion.Value >> 16); Cor20HeaderOptions.MinorRuntimeVersion = (ushort)module.Cor20HeaderRuntimeVersion.Value; } else if (module.IsClr1x) { Cor20HeaderOptions.MajorRuntimeVersion = (ushort)2; Cor20HeaderOptions.MinorRuntimeVersion = 0; } else { Cor20HeaderOptions.MajorRuntimeVersion = (ushort)2; Cor20HeaderOptions.MinorRuntimeVersion = (ushort)5; } if (module.TablesHeaderVersion.HasValue) { MetadataOptions.TablesHeapOptions.MajorVersion = (byte)(module.TablesHeaderVersion.Value >> 8); MetadataOptions.TablesHeapOptions.MinorVersion = (byte)module.TablesHeaderVersion.Value; } else if (module.IsClr1x) { MetadataOptions.TablesHeapOptions.MajorVersion = (byte)1; MetadataOptions.TablesHeapOptions.MinorVersion = 0; } else { MetadataOptions.TablesHeapOptions.MajorVersion = (byte)2; MetadataOptions.TablesHeapOptions.MinorVersion = 0; } MetadataOptions.Flags |= MetadataFlags.AlwaysCreateGuidHeap; ModuleDefMD moduleDefMD = module as ModuleDefMD; if (moduleDefMD != null) { ImageNTHeaders imageNTHeaders = moduleDefMD.Metadata.PEImage.ImageNTHeaders; PEHeadersOptions.TimeDateStamp = imageNTHeaders.FileHeader.TimeDateStamp; PEHeadersOptions.MajorLinkerVersion = imageNTHeaders.OptionalHeader.MajorLinkerVersion; PEHeadersOptions.MinorLinkerVersion = imageNTHeaders.OptionalHeader.MinorLinkerVersion; PEHeadersOptions.ImageBase = imageNTHeaders.OptionalHeader.ImageBase; PEHeadersOptions.MajorOperatingSystemVersion = imageNTHeaders.OptionalHeader.MajorOperatingSystemVersion; PEHeadersOptions.MinorOperatingSystemVersion = imageNTHeaders.OptionalHeader.MinorOperatingSystemVersion; PEHeadersOptions.MajorImageVersion = imageNTHeaders.OptionalHeader.MajorImageVersion; PEHeadersOptions.MinorImageVersion = imageNTHeaders.OptionalHeader.MinorImageVersion; PEHeadersOptions.MajorSubsystemVersion = imageNTHeaders.OptionalHeader.MajorSubsystemVersion; PEHeadersOptions.MinorSubsystemVersion = imageNTHeaders.OptionalHeader.MinorSubsystemVersion; PEHeadersOptions.Win32VersionValue = imageNTHeaders.OptionalHeader.Win32VersionValue; AddCheckSum = imageNTHeaders.OptionalHeader.CheckSum != 0; AddMvidSection = HasMvidSection(moduleDefMD.Metadata.PEImage.ImageSectionHeaders); if (HasDebugDirectoryEntry(moduleDefMD.Metadata.PEImage.ImageDebugDirectories, ImageDebugType.Reproducible)) { PdbOptions |= PdbWriterOptions.Deterministic; } if (HasDebugDirectoryEntry(moduleDefMD.Metadata.PEImage.ImageDebugDirectories, ImageDebugType.PdbChecksum)) { PdbOptions |= PdbWriterOptions.PdbChecksum; } if (TryGetPdbChecksumAlgorithm(moduleDefMD.Metadata.PEImage, moduleDefMD.Metadata.PEImage.ImageDebugDirectories, out var pdbChecksumAlgorithm)) { PdbChecksumAlgorithm = pdbChecksumAlgorithm; } MetadataOptions.TablesHeapOptions.Log2Rid = moduleDefMD.TablesStream.Log2Rid; } if (Is64Bit) { PEHeadersOptions.Characteristics &= ~Characteristics.Bit32Machine; PEHeadersOptions.Characteristics |= Characteristics.LargeAddressAware; } else if (moduleDefMD == null) { PEHeadersOptions.Characteristics |= Characteristics.Bit32Machine; } } private static bool HasMvidSection(IList sections) { int count = sections.Count; for (int i = 0; i < count; i++) { ImageSectionHeader imageSectionHeader = sections[i]; if (imageSectionHeader.VirtualSize == 16) { byte[] name = imageSectionHeader.Name; if (name[0] == 46 && name[1] == 109 && name[2] == 118 && name[3] == 105 && name[4] == 100 && name[5] == 0) { return true; } } } return false; } private static bool HasDebugDirectoryEntry(IList debugDirs, ImageDebugType type) { int count = debugDirs.Count; for (int i = 0; i < count; i++) { if (debugDirs[i].Type == type) { return true; } } return false; } private static bool TryGetPdbChecksumAlgorithm(IPEImage peImage, IList debugDirs, out ChecksumAlgorithm pdbChecksumAlgorithm) { int count = debugDirs.Count; for (int i = 0; i < count; i++) { ImageDebugDirectory imageDebugDirectory = debugDirs[i]; if (imageDebugDirectory.Type == ImageDebugType.PdbChecksum) { DataReader reader = peImage.CreateReader(imageDebugDirectory.AddressOfRawData, imageDebugDirectory.SizeOfData); if (TryGetPdbChecksumAlgorithm(ref reader, out pdbChecksumAlgorithm)) { return true; } } } pdbChecksumAlgorithm = ChecksumAlgorithm.SHA256; return false; } private static bool TryGetPdbChecksumAlgorithm(ref DataReader reader, out ChecksumAlgorithm pdbChecksumAlgorithm) { try { if (Hasher.TryGetChecksumAlgorithm(reader.TryReadZeroTerminatedUtf8String(), out pdbChecksumAlgorithm, out var checksumSize) && checksumSize == (int)reader.BytesLeft) { return true; } } catch (IOException) { } catch (ArgumentException) { } pdbChecksumAlgorithm = ChecksumAlgorithm.SHA256; return false; } public void InitializeStrongNameSigning(ModuleDef module, StrongNameKey signatureKey) { StrongNameKey = signatureKey; StrongNamePublicKey = null; if (module.Assembly != null) { module.Assembly.CustomAttributes.RemoveAll("System.Reflection.AssemblySignatureKeyAttribute"); } } public void InitializeEnhancedStrongNameSigning(ModuleDef module, StrongNameKey signatureKey, StrongNamePublicKey signaturePubKey) { InitializeStrongNameSigning(module, signatureKey); StrongNameKey = StrongNameKey.WithHashAlgorithm(signaturePubKey.HashAlgorithm); } public void InitializeEnhancedStrongNameSigning(ModuleDef module, StrongNameKey signatureKey, StrongNamePublicKey signaturePubKey, StrongNameKey identityKey, StrongNamePublicKey identityPubKey) { StrongNameKey = signatureKey.WithHashAlgorithm(signaturePubKey.HashAlgorithm); StrongNamePublicKey = identityPubKey; if (module.Assembly != null) { module.Assembly.UpdateOrCreateAssemblySignatureKeyAttribute(identityPubKey, identityKey, signaturePubKey); } } } public abstract class ModuleWriterBase : ILogger { protected internal const uint DEFAULT_CONSTANTS_ALIGNMENT = 8u; protected const uint DEFAULT_METHODBODIES_ALIGNMENT = 4u; protected const uint DEFAULT_NETRESOURCES_ALIGNMENT = 4u; protected const uint DEFAULT_METADATA_ALIGNMENT = 4u; protected internal const uint DEFAULT_WIN32_RESOURCES_ALIGNMENT = 8u; protected const uint DEFAULT_STRONGNAMESIG_ALIGNMENT = 4u; protected const uint DEFAULT_COR20HEADER_ALIGNMENT = 4u; protected Stream destStream; protected UniqueChunkList constants; protected MethodBodyChunks methodBodies; protected NetResources netResources; protected Metadata metadata; protected Win32ResourcesChunk win32Resources; protected long destStreamBaseOffset; protected DebugDirectory debugDirectory; private string createdPdbFileName; protected StrongNameSignature strongNameSignature; private PdbState pdbState; private const uint PdbAge = 1u; private static readonly double[] eventToProgress = new double[30] { 0.0, 0.00128048488389907, 0.0524625293056615, 0.0531036610555682, 0.0535679983835939, 0.0547784058004697, 0.0558606342971218, 0.120553993799033, 0.226210300699921, 0.236002648477671, 0.291089703426468, 0.449919748849947, 0.449919985998736, 0.452716444513587, 0.452716681662375, 0.924922132195272, 0.931410404476231, 0.931425463424305, 0.932072998191503, 0.932175327893773, 0.932175446468167, 0.954646479929387, 0.95492263969368, 0.980563166714175, 0.980563403862964, 0.980563403862964, 0.980563522437358, 0.999975573674777, 1.0, 1.0 }; public abstract ModuleWriterOptionsBase TheOptions { get; } public Stream DestinationStream => destStream; public UniqueChunkList Constants => constants; public MethodBodyChunks MethodBodies => methodBodies; public NetResources NetResources => netResources; public Metadata Metadata => metadata; public Win32ResourcesChunk Win32Resources => win32Resources; public StrongNameSignature StrongNameSignature => strongNameSignature; public abstract List Sections { get; } public abstract PESection TextSection { get; } public abstract PESection RsrcSection { get; } public DebugDirectory DebugDirectory => debugDirectory; public bool IsNativeWriter => this is NativeModuleWriter; public abstract ModuleDef Module { get; } public virtual void AddSection(PESection section) { Sections.Add(section); } public void Write(string fileName) { using FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); fileStream.SetLength(0L); try { Write(fileStream); } catch { fileStream.Close(); DeleteFileNoThrow(fileName); throw; } } private static void DeleteFileNoThrow(string fileName) { if (string.IsNullOrEmpty(fileName)) { return; } try { File.Delete(fileName); } catch { } } public void Write(Stream dest) { pdbState = ((TheOptions.WritePdb && Module.PdbState != null) ? Module.PdbState : null); if (TheOptions.DelaySign) { TheOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.StrongNameSigned; } else if (TheOptions.StrongNameKey != null || TheOptions.StrongNamePublicKey != null) { TheOptions.Cor20HeaderOptions.Flags |= ComImageFlags.StrongNameSigned; } destStream = dest; destStreamBaseOffset = destStream.Position; OnWriterEvent(ModuleWriterEvent.Begin); long num = WriteImpl(); destStream.Position = destStreamBaseOffset + num; OnWriterEvent(ModuleWriterEvent.End); } protected abstract long WriteImpl(); protected void CreateStrongNameSignature() { if (TheOptions.DelaySign && TheOptions.StrongNamePublicKey != null) { int num = TheOptions.StrongNamePublicKey.CreatePublicKey().Length - 32; strongNameSignature = new StrongNameSignature((num > 0) ? num : 128); } else if (TheOptions.StrongNameKey != null) { strongNameSignature = new StrongNameSignature(TheOptions.StrongNameKey.SignatureSize); } else if (Module.Assembly != null && !PublicKeyBase.IsNullOrEmpty2(Module.Assembly.PublicKey)) { int num2 = Module.Assembly.PublicKey.Data.Length - 32; strongNameSignature = new StrongNameSignature((num2 > 0) ? num2 : 128); } else if (((TheOptions.Cor20HeaderOptions.Flags ?? Module.Cor20HeaderFlags) & ComImageFlags.StrongNameSigned) != 0) { strongNameSignature = new StrongNameSignature(128); } } protected void CreateMetadataChunks(ModuleDef module) { constants = new UniqueChunkList(); methodBodies = new MethodBodyChunks(TheOptions.ShareMethodBodies); netResources = new NetResources(4u); metadata = Metadata.Create(debugKind: (pdbState != null && (pdbState.PdbFileKind == PdbFileKind.PortablePDB || pdbState.PdbFileKind == PdbFileKind.EmbeddedPortablePDB)) ? DebugMetadataKind.Standalone : DebugMetadataKind.None, module: module, constants: constants, methodBodies: methodBodies, netResources: netResources, options: TheOptions.MetadataOptions); metadata.Logger = TheOptions.MetadataLogger ?? this; metadata.MetadataEvent += Metadata_MetadataEvent; metadata.ProgressUpdated += Metadata_ProgressUpdated; StrongNamePublicKey strongNamePublicKey = TheOptions.StrongNamePublicKey; if (strongNamePublicKey != null) { metadata.AssemblyPublicKey = strongNamePublicKey.CreatePublicKey(); } else if (TheOptions.StrongNameKey != null) { metadata.AssemblyPublicKey = TheOptions.StrongNameKey.PublicKey; } Win32Resources win32Resources = GetWin32Resources(); if (win32Resources != null) { this.win32Resources = new Win32ResourcesChunk(win32Resources); } } protected abstract Win32Resources GetWin32Resources(); protected void CalculateRvasAndFileOffsets(List chunks, FileOffset offset, RVA rva, uint fileAlignment, uint sectionAlignment) { int count = chunks.Count; uint num = Math.Min(fileAlignment, sectionAlignment); for (int i = 0; i < count; i++) { IChunk chunk = chunks[i]; uint num2 = chunk.CalculateAlignment(); if (num2 > num) { Error("Chunk alignment is too big. Chunk: {0}, alignment: {1:X4}", chunk, num2); } chunk.SetOffset(offset, rva); if (chunk.GetVirtualSize() != 0) { offset += chunk.GetFileLength(); rva += chunk.GetVirtualSize(); offset = offset.AlignUp(fileAlignment); rva = rva.AlignUp(sectionAlignment); } } } protected void WriteChunks(DataWriter writer, List chunks, FileOffset offset, uint fileAlignment) { int count = chunks.Count; for (int i = 0; i < count; i++) { IChunk chunk = chunks[i]; chunk.VerifyWriteTo(writer); if (chunk.GetVirtualSize() != 0) { offset += chunk.GetFileLength(); FileOffset fileOffset = offset.AlignUp(fileAlignment); writer.WriteZeroes((int)(fileOffset - offset)); offset = fileOffset; } } } protected void StrongNameSign(long snSigOffset) { new StrongNameSigner(destStream, destStreamBaseOffset).WriteSignature(TheOptions.StrongNameKey, snSigOffset); } private bool CanWritePdb() { return pdbState != null; } protected void CreateDebugDirectory() { if (CanWritePdb()) { debugDirectory = new DebugDirectory(); } } protected void WritePdbFile() { if (!CanWritePdb()) { return; } if (debugDirectory == null) { throw new InvalidOperationException("debugDirectory is null but WritePdb is true"); } if (pdbState == null) { Error("TheOptions.WritePdb is true but module has no PdbState"); return; } try { switch (pdbState.PdbFileKind) { case PdbFileKind.WindowsPDB: WriteWindowsPdb(pdbState); break; case PdbFileKind.PortablePDB: WritePortablePdb(pdbState, isEmbeddedPortablePdb: false); break; case PdbFileKind.EmbeddedPortablePDB: WritePortablePdb(pdbState, isEmbeddedPortablePdb: true); break; default: Error("Invalid PDB file kind {0}", pdbState.PdbFileKind); break; } } catch { DeleteFileNoThrow(createdPdbFileName); throw; } } private void AddReproduciblePdbDebugDirectoryEntry() { debugDirectory.Add(Array2.Empty(), ImageDebugType.Reproducible, 0, 0, 0u); } private void AddPdbChecksumDebugDirectoryEntry(byte[] checksumBytes, ChecksumAlgorithm checksumAlgorithm) { MemoryStream memoryStream = new MemoryStream(); DataWriter dataWriter = new DataWriter(memoryStream); string checksumName = Hasher.GetChecksumName(checksumAlgorithm); dataWriter.WriteBytes(Encoding.UTF8.GetBytes(checksumName)); dataWriter.WriteByte(0); dataWriter.WriteBytes(checksumBytes); byte[] data = memoryStream.ToArray(); debugDirectory.Add(data, ImageDebugType.PdbChecksum, 1, 0, 0u); } private void WriteWindowsPdb(PdbState pdbState) { bool flag = (TheOptions.PdbOptions & PdbWriterOptions.PdbChecksum) != 0; flag = false; string pdbFilename; SymbolWriter windowsPdbSymbolWriter = GetWindowsPdbSymbolWriter(TheOptions.PdbOptions, out pdbFilename); if (windowsPdbSymbolWriter == null) { Error("Could not create a PDB symbol writer. A Windows OS might be required."); return; } using WindowsPdbWriter windowsPdbWriter = new WindowsPdbWriter(windowsPdbSymbolWriter, pdbState, metadata); windowsPdbWriter.Logger = TheOptions.Logger; windowsPdbWriter.Write(); uint pdbAge = 1u; if (windowsPdbWriter.GetDebugInfo(TheOptions.PdbChecksumAlgorithm, ref pdbAge, out var guid, out var stamp, out var idd, out var codeViewData)) { debugDirectory.Add(GetCodeViewData(guid, pdbAge, TheOptions.PdbFileNameInDebugDirectory ?? pdbFilename), ImageDebugType.CodeView, 0, 0, stamp); } else { if (codeViewData == null) { throw new InvalidOperationException(); } DebugDirectoryEntry debugDirectoryEntry = debugDirectory.Add(codeViewData); debugDirectoryEntry.DebugDirectory = idd; debugDirectoryEntry.DebugDirectory.TimeDateStamp = GetTimeDateStamp(); } if (windowsPdbSymbolWriter.IsDeterministic) { AddReproduciblePdbDebugDirectoryEntry(); } } protected uint GetTimeDateStamp() { uint? timeDateStamp = TheOptions.PEHeadersOptions.TimeDateStamp; if (timeDateStamp.HasValue) { return timeDateStamp.Value; } TheOptions.PEHeadersOptions.TimeDateStamp = PEHeadersOptions.CreateNewTimeDateStamp(); return TheOptions.PEHeadersOptions.TimeDateStamp.Value; } private SymbolWriter GetWindowsPdbSymbolWriter(PdbWriterOptions options, out string pdbFilename) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { pdbFilename = null; return null; } if (TheOptions.PdbStream != null) { Stream pdbStream = TheOptions.PdbStream; string obj = TheOptions.PdbFileName ?? GetStreamName(TheOptions.PdbStream) ?? GetDefaultPdbFileName(); string pdbFileName = obj; pdbFilename = obj; return SymbolReaderWriterFactory.Create(options, pdbStream, pdbFileName); } if (!string.IsNullOrEmpty(TheOptions.PdbFileName)) { createdPdbFileName = (pdbFilename = TheOptions.PdbFileName); return SymbolReaderWriterFactory.Create(options, createdPdbFileName); } createdPdbFileName = (pdbFilename = GetDefaultPdbFileName()); if (createdPdbFileName == null) { return null; } return SymbolReaderWriterFactory.Create(options, createdPdbFileName); } private static string GetStreamName(Stream stream) { return (stream as FileStream)?.Name; } private static string GetModuleName(ModuleDef module) { UTF8String uTF8String = module.Name ?? ((UTF8String)string.Empty); if (string.IsNullOrEmpty(uTF8String)) { return null; } if (uTF8String.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || uTF8String.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || uTF8String.EndsWith(".netmodule", StringComparison.OrdinalIgnoreCase)) { return uTF8String; } return string.Concat(uTF8String, ".pdb"); } private string GetDefaultPdbFileName() { string text = GetStreamName(destStream) ?? GetModuleName(Module); if (string.IsNullOrEmpty(text)) { Error("TheOptions.WritePdb is true but it's not possible to guess the default PDB file name. Set PdbFileName to the name of the PDB file."); return null; } return Path.ChangeExtension(text, "pdb"); } private void WritePortablePdb(PdbState pdbState, bool isEmbeddedPortablePdb) { bool ownsStream = false; Stream stream = null; try { MemoryStream portablePdbStream = null; if (isEmbeddedPortablePdb) { stream = (portablePdbStream = new MemoryStream()); ownsStream = true; } else { stream = GetStandalonePortablePdbStream(out ownsStream); } if (stream == null) { throw new ModuleWriterException("Couldn't create a PDB stream"); } string text = TheOptions.PdbFileName ?? GetStreamName(stream) ?? GetDefaultPdbFileName(); if (isEmbeddedPortablePdb) { text = Path.GetFileName(text); } uint entryPointToken = ((pdbState.UserEntryPoint != null) ? new MDToken(Table.Method, metadata.GetRid(pdbState.UserEntryPoint)).Raw : 0u); metadata.WritePortablePdb(stream, entryPointToken, out var pdbIdOffset); byte[] array = new byte[20]; ArrayWriter arrayWriter = new ArrayWriter(array); byte[] array2; Guid guid; uint timestamp; if ((TheOptions.PdbOptions & PdbWriterOptions.Deterministic) != PdbWriterOptions.None || (TheOptions.PdbOptions & PdbWriterOptions.PdbChecksum) != PdbWriterOptions.None || TheOptions.GetPdbContentId == null) { stream.Position = 0L; array2 = Hasher.Hash(TheOptions.PdbChecksumAlgorithm, stream, stream.Length); if (array2.Length < 20) { throw new ModuleWriterException("Checksum bytes length < 20"); } RoslynContentIdProvider.GetContentId(array2, out guid, out timestamp); } else { ContentId contentId = TheOptions.GetPdbContentId(stream, GetTimeDateStamp()); timestamp = contentId.Timestamp; guid = contentId.Guid; array2 = null; } arrayWriter.WriteBytes(guid.ToByteArray()); arrayWriter.WriteUInt32(timestamp); stream.Position = pdbIdOffset; stream.Write(array, 0, array.Length); debugDirectory.Add(GetCodeViewData(guid, 1u, TheOptions.PdbFileNameInDebugDirectory ?? text), ImageDebugType.CodeView, 256, 20557, timestamp); if (array2 != null) { AddPdbChecksumDebugDirectoryEntry(array2, TheOptions.PdbChecksumAlgorithm); } if ((TheOptions.PdbOptions & PdbWriterOptions.Deterministic) != PdbWriterOptions.None) { AddReproduciblePdbDebugDirectoryEntry(); } if (isEmbeddedPortablePdb) { debugDirectory.Add(CreateEmbeddedPortablePdbBlob(portablePdbStream), ImageDebugType.EmbeddedPortablePdb, 256, 256, 0u); } } finally { if (ownsStream) { stream?.Dispose(); } } } private static byte[] CreateEmbeddedPortablePdbBlob(MemoryStream portablePdbStream) { byte[] array = Compress(portablePdbStream); byte[] array2 = new byte[8 + array.Length]; DataWriter dataWriter = new DataWriter(new MemoryStream(array2)); dataWriter.WriteInt32(1111773261); dataWriter.WriteUInt32((uint)portablePdbStream.Length); dataWriter.WriteBytes(array); return array2; } private static byte[] Compress(MemoryStream sourceStream) { sourceStream.Position = 0L; MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress)) { byte[] array = sourceStream.ToArray(); deflateStream.Write(array, 0, array.Length); } return memoryStream.ToArray(); } private static byte[] GetCodeViewData(Guid guid, uint age, string filename) { MemoryStream memoryStream = new MemoryStream(); DataWriter dataWriter = new DataWriter(memoryStream); dataWriter.WriteInt32(1396986706); dataWriter.WriteBytes(guid.ToByteArray()); dataWriter.WriteUInt32(age); dataWriter.WriteBytes(Encoding.UTF8.GetBytes(filename)); dataWriter.WriteByte(0); return memoryStream.ToArray(); } private Stream GetStandalonePortablePdbStream(out bool ownsStream) { if (TheOptions.PdbStream != null) { ownsStream = false; return TheOptions.PdbStream; } if (!string.IsNullOrEmpty(TheOptions.PdbFileName)) { createdPdbFileName = TheOptions.PdbFileName; } else { createdPdbFileName = GetDefaultPdbFileName(); } if (createdPdbFileName == null) { ownsStream = false; return null; } ownsStream = true; return File.Create(createdPdbFileName); } private void Metadata_MetadataEvent(object sender, MetadataWriterEventArgs e) { switch (e.Event) { case MetadataEvent.BeginCreateTables: OnWriterEvent(ModuleWriterEvent.MDBeginCreateTables); break; case MetadataEvent.AllocateTypeDefRids: OnWriterEvent(ModuleWriterEvent.MDAllocateTypeDefRids); break; case MetadataEvent.AllocateMemberDefRids: OnWriterEvent(ModuleWriterEvent.MDAllocateMemberDefRids); break; case MetadataEvent.MemberDefRidsAllocated: OnWriterEvent(ModuleWriterEvent.MDMemberDefRidsAllocated); break; case MetadataEvent.MemberDefsInitialized: OnWriterEvent(ModuleWriterEvent.MDMemberDefsInitialized); break; case MetadataEvent.BeforeSortTables: OnWriterEvent(ModuleWriterEvent.MDBeforeSortTables); break; case MetadataEvent.MostTablesSorted: OnWriterEvent(ModuleWriterEvent.MDMostTablesSorted); break; case MetadataEvent.MemberDefCustomAttributesWritten: OnWriterEvent(ModuleWriterEvent.MDMemberDefCustomAttributesWritten); break; case MetadataEvent.BeginAddResources: OnWriterEvent(ModuleWriterEvent.MDBeginAddResources); break; case MetadataEvent.EndAddResources: OnWriterEvent(ModuleWriterEvent.MDEndAddResources); break; case MetadataEvent.BeginWriteMethodBodies: OnWriterEvent(ModuleWriterEvent.MDBeginWriteMethodBodies); break; case MetadataEvent.EndWriteMethodBodies: OnWriterEvent(ModuleWriterEvent.MDEndWriteMethodBodies); break; case MetadataEvent.OnAllTablesSorted: OnWriterEvent(ModuleWriterEvent.MDOnAllTablesSorted); break; case MetadataEvent.EndCreateTables: OnWriterEvent(ModuleWriterEvent.MDEndCreateTables); break; } } private void Metadata_ProgressUpdated(object sender, MetadataProgressEventArgs e) { RaiseProgress(ModuleWriterEvent.MDBeginCreateTables, ModuleWriterEvent.BeginWritePdb, e.Progress); } protected void OnWriterEvent(ModuleWriterEvent evt) { RaiseProgress(evt, 0.0); TheOptions.RaiseEvent(this, new ModuleWriterEventArgs(this, evt)); } private void RaiseProgress(ModuleWriterEvent evt, double subProgress) { RaiseProgress(evt, evt + 1, subProgress); } private void RaiseProgress(ModuleWriterEvent evt, ModuleWriterEvent nextEvt, double subProgress) { subProgress = Math.Min(1.0, Math.Max(0.0, subProgress)); double num = eventToProgress[(int)evt]; double num2 = eventToProgress[(int)nextEvt]; double val = num + (num2 - num) * subProgress; val = Math.Min(1.0, Math.Max(0.0, val)); TheOptions.RaiseEvent(this, new ModuleWriterProgressEventArgs(this, val)); } private ILogger GetLogger() { return TheOptions.Logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } void ILogger.Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { GetLogger().Log(this, loggerEvent, format, args); } bool ILogger.IgnoresEvent(LoggerEvent loggerEvent) { return GetLogger().IgnoresEvent(loggerEvent); } protected void Error(string format, params object[] args) { GetLogger().Log(this, LoggerEvent.Error, format, args); } protected void Warning(string format, params object[] args) { GetLogger().Log(this, LoggerEvent.Warning, format, args); } } public enum ModuleWriterEvent { Begin, PESectionsCreated, ChunksCreated, ChunksAddedToSections, MDBeginCreateTables, MDAllocateTypeDefRids, MDAllocateMemberDefRids, MDMemberDefRidsAllocated, MDMemberDefsInitialized, MDBeforeSortTables, MDMostTablesSorted, MDMemberDefCustomAttributesWritten, MDBeginAddResources, MDEndAddResources, MDBeginWriteMethodBodies, MDEndWriteMethodBodies, MDOnAllTablesSorted, MDEndCreateTables, BeginWritePdb, EndWritePdb, BeginCalculateRvasAndFileOffsets, EndCalculateRvasAndFileOffsets, BeginWriteChunks, EndWriteChunks, BeginStrongNameSign, EndStrongNameSign, BeginWritePEChecksum, EndWritePEChecksum, End } [Serializable] public class ModuleWriterException : Exception { public ModuleWriterException() { } public ModuleWriterException(string message) : base(message) { } public ModuleWriterException(string message, Exception innerException) : base(message, innerException) { } protected ModuleWriterException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public sealed class NativeModuleWriterOptions : ModuleWriterOptionsBase { public bool KeepExtraPEData { get; set; } public bool KeepWin32Resources { get; set; } internal bool OptimizeImageSize { get; } public NativeModuleWriterOptions(ModuleDefMD module, bool optimizeImageSize) : base(module) { base.MetadataOptions.Flags |= MetadataFlags.PreserveAllMethodRids; if (optimizeImageSize) { OptimizeImageSize = true; base.MetadataOptions.Flags |= MetadataFlags.PreserveTypeRefRids | MetadataFlags.PreserveTypeDefRids | MetadataFlags.PreserveTypeSpecRids; } } } public sealed class NativeModuleWriter : ModuleWriterBase { private readonly struct ReusedChunkInfo { public IReuseChunk Chunk { get; } public RVA RVA { get; } public ReusedChunkInfo(IReuseChunk chunk, RVA rva) { Chunk = chunk; RVA = rva; } } public sealed class OrigSection : IDisposable { public ImageSectionHeader PESection; public DataReaderChunk Chunk; public OrigSection(ImageSectionHeader peSection) { PESection = peSection; } public void Dispose() { Chunk = null; PESection = null; } public override string ToString() { uint startOffset = Chunk.CreateReader().StartOffset; return $"{PESection.DisplayName} FO:{startOffset:X8} L:{Chunk.CreateReader().Length:X8}"; } } private readonly ModuleDefMD module; private NativeModuleWriterOptions options; private DataReaderChunk extraData; private List origSections; private List reusedChunks; private readonly IPEImage peImage; private List sections; private PESection textSection; private ByteArrayChunk imageCor20Header; private PESection rsrcSection; private long checkSumOffset; public ModuleDefMD ModuleDefMD => module; public override ModuleDef Module => module; public override ModuleWriterOptionsBase TheOptions => Options; public NativeModuleWriterOptions Options { get { return options ?? (options = new NativeModuleWriterOptions(module, optimizeImageSize: true)); } set { options = value; } } public override List Sections => sections; public List OrigSections => origSections; public override PESection TextSection => textSection; public override PESection RsrcSection => rsrcSection; public NativeModuleWriter(ModuleDefMD module, NativeModuleWriterOptions options) { this.module = module; this.options = options; peImage = module.Metadata.PEImage; reusedChunks = new List(); } protected override long WriteImpl() { try { return Write(); } finally { if (origSections != null) { foreach (OrigSection origSection in origSections) { origSection.Dispose(); } } } } private long Write() { Initialize(); metadata.KeepFieldRVA = true; metadata.CreateTables(); return WriteFile(); } private void Initialize() { CreateSections(); OnWriterEvent(ModuleWriterEvent.PESectionsCreated); CreateChunks(); OnWriterEvent(ModuleWriterEvent.ChunksCreated); AddChunksToSections(); OnWriterEvent(ModuleWriterEvent.ChunksAddedToSections); } private void CreateSections() { CreatePESections(); CreateRawSections(); CreateExtraData(); } private void CreateChunks() { CreateMetadataChunks(module); methodBodies.CanReuseOldBodyLocation = Options.OptimizeImageSize; CreateDebugDirectory(); imageCor20Header = new ByteArrayChunk(new byte[72]); CreateStrongNameSignature(); } private void AddChunksToSections() { textSection.Add(imageCor20Header, 4u); textSection.Add(strongNameSignature, 4u); textSection.Add(constants, 8u); textSection.Add(methodBodies, 4u); textSection.Add(netResources, 4u); textSection.Add(metadata, 4u); textSection.Add(debugDirectory, 4u); if (rsrcSection != null) { rsrcSection.Add(win32Resources, 8u); } } protected override Win32Resources GetWin32Resources() { if (Options.KeepWin32Resources) { return null; } if (Options.NoWin32Resources) { return null; } return Options.Win32Resources ?? module.Win32Resources; } private void CreatePESections() { sections = new List(); sections.Add(textSection = new PESection(".text", 1610612768u)); if (GetWin32Resources() != null) { sections.Add(rsrcSection = new PESection(".rsrc", 1073741888u)); } } private void CreateRawSections() { uint fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; origSections = new List(peImage.ImageSectionHeaders.Count); foreach (ImageSectionHeader imageSectionHeader in peImage.ImageSectionHeaders) { OrigSection origSection = new OrigSection(imageSectionHeader); origSections.Add(origSection); uint length = Utils.AlignUp(imageSectionHeader.SizeOfRawData, fileAlignment); origSection.Chunk = new DataReaderChunk(peImage.CreateReader(imageSectionHeader.VirtualAddress, length), imageSectionHeader.VirtualSize); } } private DataReaderChunk CreateHeaderSection(out IChunk extraHeaderData) { int num = (int)GetOffsetAfterLastSectionHeader() + sections.Count * 40; uint num2 = Math.Min(GetFirstRawDataFileOffset(), peImage.ImageNTHeaders.OptionalHeader.SectionAlignment); uint num3 = (uint)num; if (num2 > num3) { num3 = num2; } num3 = Utils.AlignUp(num3, peImage.ImageNTHeaders.OptionalHeader.FileAlignment); if (num3 <= peImage.ImageNTHeaders.OptionalHeader.SectionAlignment) { uint sizeOfHeaders = peImage.ImageNTHeaders.OptionalHeader.SizeOfHeaders; uint num4; if (num3 <= sizeOfHeaders) { num4 = 0u; } else { num4 = num3 - sizeOfHeaders; num3 = sizeOfHeaders; } if (num4 != 0) { extraHeaderData = new ByteArrayChunk(new byte[num4]); } else { extraHeaderData = null; } return new DataReaderChunk(peImage.CreateReader((FileOffset)0u, num3)); } throw new ModuleWriterException("Could not create header"); } private uint GetOffsetAfterLastSectionHeader() { return (uint)peImage.ImageSectionHeaders[peImage.ImageSectionHeaders.Count - 1].EndOffset; } private uint GetFirstRawDataFileOffset() { uint num = uint.MaxValue; foreach (ImageSectionHeader imageSectionHeader in peImage.ImageSectionHeaders) { num = Math.Min(num, imageSectionHeader.PointerToRawData); } return num; } private void CreateExtraData() { if (Options.KeepExtraPEData) { uint lastFileSectionOffset = GetLastFileSectionOffset(); extraData = new DataReaderChunk(peImage.CreateReader((FileOffset)lastFileSectionOffset)); if (extraData.CreateReader().Length == 0) { extraData = null; } } } private uint GetLastFileSectionOffset() { uint num = 0u; foreach (OrigSection origSection in origSections) { num = Math.Max(num, (uint)(origSection.PESection.VirtualAddress + origSection.PESection.SizeOfRawData)); } return (uint)(peImage.ToFileOffset((RVA)(num - 1)) + 1); } private void ReuseIfPossible(PESection section, IReuseChunk chunk, RVA origRva, uint origSize, uint requiredAlignment) { if (origRva == (RVA)0u || origSize == 0 || chunk == null || !chunk.CanReuse(origRva, origSize) || ((uint)origRva & (requiredAlignment - 1)) != 0) { return; } RVA rVA = origRva + origSize; foreach (ReusedChunkInfo reusedChunk in reusedChunks) { if (origRva < reusedChunk.RVA + reusedChunk.Chunk.GetVirtualSize() && rVA > reusedChunk.RVA) { return; } } if (!section.Remove(chunk).HasValue) { throw new InvalidOperationException(); } reusedChunks.Add(new ReusedChunkInfo(chunk, origRva)); } private FileOffset GetNewFileOffset(RVA rva) { foreach (OrigSection origSection in origSections) { ImageSectionHeader pESection = origSection.PESection; if (pESection.VirtualAddress <= rva && rva < pESection.VirtualAddress + Math.Max(pESection.VirtualSize, pESection.SizeOfRawData)) { return origSection.Chunk.FileOffset + (rva - pESection.VirtualAddress); } } return (FileOffset)rva; } private long WriteFile() { uint ep; bool entryPoint = GetEntryPoint(out ep); OnWriterEvent(ModuleWriterEvent.BeginWritePdb); WritePdbFile(); OnWriterEvent(ModuleWriterEvent.EndWritePdb); metadata.OnBeforeSetOffset(); OnWriterEvent(ModuleWriterEvent.BeginCalculateRvasAndFileOffsets); if (Options.OptimizeImageSize) { ImageDataDirectory imageDataDirectory = module.Metadata.ImageCor20Header.Metadata; metadata.SetOffset(peImage.ToFileOffset(imageDataDirectory.VirtualAddress), imageDataDirectory.VirtualAddress); ReuseIfPossible(textSection, metadata, imageDataDirectory.VirtualAddress, imageDataDirectory.Size, 4u); ImageDataDirectory imageDataDirectory2 = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[2]; if (win32Resources != null && imageDataDirectory2.VirtualAddress != 0 && imageDataDirectory2.Size != 0) { FileOffset offset = peImage.ToFileOffset(imageDataDirectory2.VirtualAddress); if (win32Resources.CheckValidOffset(offset)) { win32Resources.SetOffset(offset, imageDataDirectory2.VirtualAddress); ReuseIfPossible(rsrcSection, win32Resources, imageDataDirectory2.VirtualAddress, imageDataDirectory2.Size, 8u); } } ReuseIfPossible(textSection, imageCor20Header, module.Metadata.PEImage.ImageNTHeaders.OptionalHeader.DataDirectories[14].VirtualAddress, module.Metadata.PEImage.ImageNTHeaders.OptionalHeader.DataDirectories[14].Size, 4u); if ((module.Metadata.ImageCor20Header.Flags & ComImageFlags.StrongNameSigned) != 0) { ReuseIfPossible(textSection, strongNameSignature, module.Metadata.ImageCor20Header.StrongNameSignature.VirtualAddress, module.Metadata.ImageCor20Header.StrongNameSignature.Size, 4u); } ReuseIfPossible(textSection, netResources, module.Metadata.ImageCor20Header.Resources.VirtualAddress, module.Metadata.ImageCor20Header.Resources.Size, 4u); if (methodBodies.ReusedAllMethodBodyLocations) { textSection.Remove(methodBodies); } ImageDataDirectory imageDataDirectory3 = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[6]; if (imageDataDirectory3.VirtualAddress != 0 && imageDataDirectory3.Size != 0 && TryGetRealDebugDirectorySize(peImage, out var realSize)) { ReuseIfPossible(textSection, debugDirectory, imageDataDirectory3.VirtualAddress, realSize, 4u); } } if (constants.IsEmpty) { textSection.Remove(constants); } if (netResources.IsEmpty) { textSection.Remove(netResources); } if (textSection.IsEmpty) { sections.Remove(textSection); } if (rsrcSection != null && rsrcSection.IsEmpty) { sections.Remove(rsrcSection); rsrcSection = null; } IChunk extraHeaderData; DataReaderChunk dataReaderChunk = CreateHeaderSection(out extraHeaderData); List list = new List(); uint headerLen; if (extraHeaderData != null) { ChunkList chunkList = new ChunkList(); chunkList.Add(dataReaderChunk, 1u); chunkList.Add(extraHeaderData, 1u); list.Add(chunkList); headerLen = dataReaderChunk.GetVirtualSize() + extraHeaderData.GetVirtualSize(); } else { list.Add(dataReaderChunk); headerLen = dataReaderChunk.GetVirtualSize(); } foreach (OrigSection origSection in origSections) { list.Add(origSection.Chunk); } foreach (PESection section in sections) { list.Add(section); } if (extraData != null) { list.Add(extraData); } CalculateRvasAndFileOffsets(list, (FileOffset)0u, (RVA)0u, peImage.ImageNTHeaders.OptionalHeader.FileAlignment, peImage.ImageNTHeaders.OptionalHeader.SectionAlignment); if (reusedChunks.Count > 0 || methodBodies.HasReusedMethods) { methodBodies.InitializeReusedMethodBodies(GetNewFileOffset); foreach (ReusedChunkInfo reusedChunk in reusedChunks) { FileOffset newFileOffset = GetNewFileOffset(reusedChunk.RVA); reusedChunk.Chunk.SetOffset(newFileOffset, reusedChunk.RVA); } } metadata.UpdateMethodAndFieldRvas(); foreach (OrigSection origSection2 in origSections) { if (origSection2.Chunk.RVA != origSection2.PESection.VirtualAddress) { throw new ModuleWriterException("Invalid section RVA"); } } OnWriterEvent(ModuleWriterEvent.EndCalculateRvasAndFileOffsets); OnWriterEvent(ModuleWriterEvent.BeginWriteChunks); DataWriter dataWriter = new DataWriter(destStream); WriteChunks(dataWriter, list, (FileOffset)0u, peImage.ImageNTHeaders.OptionalHeader.FileAlignment); long num = dataWriter.Position - destStreamBaseOffset; if (reusedChunks.Count > 0 || methodBodies.HasReusedMethods) { long position = dataWriter.Position; foreach (ReusedChunkInfo reusedChunk2 in reusedChunks) { if (reusedChunk2.Chunk.RVA != reusedChunk2.RVA) { throw new InvalidOperationException(); } dataWriter.Position = destStreamBaseOffset + (long)reusedChunk2.Chunk.FileOffset; reusedChunk2.Chunk.VerifyWriteTo(dataWriter); } methodBodies.WriteReusedMethodBodies(dataWriter, destStreamBaseOffset); dataWriter.Position = position; } SectionSizes sectionSizes = new SectionSizes(peImage.ImageNTHeaders.OptionalHeader.FileAlignment, peImage.ImageNTHeaders.OptionalHeader.SectionAlignment, headerLen, GetSectionSizeInfos); UpdateHeaderFields(dataWriter, entryPoint, ep, ref sectionSizes); OnWriterEvent(ModuleWriterEvent.EndWriteChunks); OnWriterEvent(ModuleWriterEvent.BeginStrongNameSign); if (Options.StrongNameKey != null) { StrongNameSign((long)strongNameSignature.FileOffset); } OnWriterEvent(ModuleWriterEvent.EndStrongNameSign); OnWriterEvent(ModuleWriterEvent.BeginWritePEChecksum); if (Options.AddCheckSum) { destStream.Position = destStreamBaseOffset; uint value = destStream.CalculatePECheckSum(num, checkSumOffset); dataWriter.Position = checkSumOffset; dataWriter.WriteUInt32(value); } OnWriterEvent(ModuleWriterEvent.EndWritePEChecksum); return num; } private static bool TryGetRealDebugDirectorySize(IPEImage peImage, out uint realSize) { realSize = 0u; if (peImage.ImageDebugDirectories.Count == 0) { return false; } List list = new List(peImage.ImageDebugDirectories); list.Sort((ImageDebugDirectory a, ImageDebugDirectory b) => a.AddressOfRawData.CompareTo(b.AddressOfRawData)); ImageDataDirectory imageDataDirectory = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[6]; uint num = (uint)(imageDataDirectory.VirtualAddress + imageDataDirectory.Size); for (int num2 = 0; num2 < list.Count; num2++) { uint num3 = (num + 3) & 0xFFFFFFFCu; ImageDebugDirectory imageDebugDirectory = list[num2]; if (imageDebugDirectory.AddressOfRawData != 0 && imageDebugDirectory.SizeOfData != 0) { if (num > (uint)imageDebugDirectory.AddressOfRawData || (uint)imageDebugDirectory.AddressOfRawData > num3) { return false; } num = (uint)(imageDebugDirectory.AddressOfRawData + imageDebugDirectory.SizeOfData); } } realSize = (uint)(num - imageDataDirectory.VirtualAddress); return true; } private bool Is64Bit() { return peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader64; } private Characteristics GetCharacteristics() { Characteristics characteristics = module.Characteristics; characteristics = ((!Is64Bit()) ? (characteristics | Characteristics.Bit32Machine) : (characteristics & ~Characteristics.Bit32Machine)); if (Options.IsExeFile) { return characteristics & ~Characteristics.Dll; } return characteristics | Characteristics.Dll; } private void UpdateHeaderFields(DataWriter writer, bool entryPointIsManagedOrNoEntryPoint, uint entryPointToken, ref SectionSizes sectionSizes) { long position = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; long position2 = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; long position3 = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; long num = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 128; long position4 = destStreamBaseOffset + (long)imageCor20Header.FileOffset; PEHeadersOptions pEHeadersOptions = Options.PEHeadersOptions; writer.Position = position; writer.WriteUInt16((ushort)(pEHeadersOptions.Machine ?? module.Machine)); writer.WriteUInt16((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, pEHeadersOptions.TimeDateStamp); WriteUInt32(writer, pEHeadersOptions.PointerToSymbolTable); WriteUInt32(writer, pEHeadersOptions.NumberOfSymbols); writer.Position += 2L; writer.WriteUInt16((ushort)(pEHeadersOptions.Characteristics ?? GetCharacteristics())); writer.Position = position2; if (peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32) { writer.Position += 2L; WriteByte(writer, pEHeadersOptions.MajorLinkerVersion); WriteByte(writer, pEHeadersOptions.MinorLinkerVersion); writer.WriteUInt32(sectionSizes.SizeOfCode); writer.WriteUInt32(sectionSizes.SizeOfInitdData); writer.WriteUInt32(sectionSizes.SizeOfUninitdData); writer.Position += 4L; writer.WriteUInt32(sectionSizes.BaseOfCode); writer.WriteUInt32(sectionSizes.BaseOfData); WriteUInt32(writer, pEHeadersOptions.ImageBase); writer.Position += 8L; WriteUInt16(writer, pEHeadersOptions.MajorOperatingSystemVersion); WriteUInt16(writer, pEHeadersOptions.MinorOperatingSystemVersion); WriteUInt16(writer, pEHeadersOptions.MajorImageVersion); WriteUInt16(writer, pEHeadersOptions.MinorImageVersion); WriteUInt16(writer, pEHeadersOptions.MajorSubsystemVersion); WriteUInt16(writer, pEHeadersOptions.MinorSubsystemVersion); WriteUInt32(writer, pEHeadersOptions.Win32VersionValue); writer.WriteUInt32(sectionSizes.SizeOfImage); writer.WriteUInt32(sectionSizes.SizeOfHeaders); checkSumOffset = writer.Position; writer.WriteInt32(0); WriteUInt16(writer, pEHeadersOptions.Subsystem); WriteUInt16(writer, pEHeadersOptions.DllCharacteristics); WriteUInt32(writer, pEHeadersOptions.SizeOfStackReserve); WriteUInt32(writer, pEHeadersOptions.SizeOfStackCommit); WriteUInt32(writer, pEHeadersOptions.SizeOfHeapReserve); WriteUInt32(writer, pEHeadersOptions.SizeOfHeapCommit); WriteUInt32(writer, pEHeadersOptions.LoaderFlags); WriteUInt32(writer, pEHeadersOptions.NumberOfRvaAndSizes); } else { writer.Position += 2L; WriteByte(writer, pEHeadersOptions.MajorLinkerVersion); WriteByte(writer, pEHeadersOptions.MinorLinkerVersion); writer.WriteUInt32(sectionSizes.SizeOfCode); writer.WriteUInt32(sectionSizes.SizeOfInitdData); writer.WriteUInt32(sectionSizes.SizeOfUninitdData); writer.Position += 4L; writer.WriteUInt32(sectionSizes.BaseOfCode); WriteUInt64(writer, pEHeadersOptions.ImageBase); writer.Position += 8L; WriteUInt16(writer, pEHeadersOptions.MajorOperatingSystemVersion); WriteUInt16(writer, pEHeadersOptions.MinorOperatingSystemVersion); WriteUInt16(writer, pEHeadersOptions.MajorImageVersion); WriteUInt16(writer, pEHeadersOptions.MinorImageVersion); WriteUInt16(writer, pEHeadersOptions.MajorSubsystemVersion); WriteUInt16(writer, pEHeadersOptions.MinorSubsystemVersion); WriteUInt32(writer, pEHeadersOptions.Win32VersionValue); writer.WriteUInt32(sectionSizes.SizeOfImage); writer.WriteUInt32(sectionSizes.SizeOfHeaders); checkSumOffset = writer.Position; writer.WriteInt32(0); WriteUInt16(writer, pEHeadersOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, pEHeadersOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, pEHeadersOptions.SizeOfStackReserve); WriteUInt64(writer, pEHeadersOptions.SizeOfStackCommit); WriteUInt64(writer, pEHeadersOptions.SizeOfHeapReserve); WriteUInt64(writer, pEHeadersOptions.SizeOfHeapCommit); WriteUInt32(writer, pEHeadersOptions.LoaderFlags); WriteUInt32(writer, pEHeadersOptions.NumberOfRvaAndSizes); } if (win32Resources != null) { writer.Position = num + 16; writer.WriteDataDirectory(win32Resources); } writer.Position = num + 32; writer.WriteDataDirectory(null); writer.Position = num + 48; writer.WriteDebugDirectory(debugDirectory); writer.Position = num + 112; writer.WriteDataDirectory(imageCor20Header); writer.Position = position3; foreach (OrigSection origSection in origSections) { writer.Position += 20L; writer.WriteUInt32((uint)origSection.Chunk.FileOffset); writer.Position += 16L; } foreach (PESection section in sections) { section.WriteHeaderTo(writer, peImage.ImageNTHeaders.OptionalHeader.FileAlignment, peImage.ImageNTHeaders.OptionalHeader.SectionAlignment, (uint)section.RVA); } writer.Position = position4; writer.WriteInt32(72); WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metadata); writer.WriteUInt32((uint)GetComImageFlags(entryPointIsManagedOrNoEntryPoint)); writer.WriteUInt32(entryPointToken); writer.WriteDataDirectory(netResources); writer.WriteDataDirectory(strongNameSignature); WriteDataDirectory(writer, module.Metadata.ImageCor20Header.CodeManagerTable); WriteDataDirectory(writer, module.Metadata.ImageCor20Header.VTableFixups); WriteDataDirectory(writer, module.Metadata.ImageCor20Header.ExportAddressTableJumps); WriteDataDirectory(writer, module.Metadata.ImageCor20Header.ManagedNativeHeader); UpdateVTableFixups(writer); } private static void WriteDataDirectory(DataWriter writer, ImageDataDirectory dataDir) { writer.WriteUInt32((uint)dataDir.VirtualAddress); writer.WriteUInt32(dataDir.Size); } private static void WriteByte(DataWriter writer, byte? value) { if (!value.HasValue) { writer.Position++; } else { writer.WriteByte(value.Value); } } private static void WriteUInt16(DataWriter writer, ushort? value) { if (!value.HasValue) { writer.Position += 2L; } else { writer.WriteUInt16(value.Value); } } private static void WriteUInt16(DataWriter writer, Subsystem? value) { if (!value.HasValue) { writer.Position += 2L; } else { writer.WriteUInt16((ushort)value.Value); } } private static void WriteUInt16(DataWriter writer, DllCharacteristics? value) { if (!value.HasValue) { writer.Position += 2L; } else { writer.WriteUInt16((ushort)value.Value); } } private static void WriteUInt32(DataWriter writer, uint? value) { if (!value.HasValue) { writer.Position += 4L; } else { writer.WriteUInt32(value.Value); } } private static void WriteUInt32(DataWriter writer, ulong? value) { if (!value.HasValue) { writer.Position += 4L; } else { writer.WriteUInt32((uint)value.Value); } } private static void WriteUInt64(DataWriter writer, ulong? value) { if (!value.HasValue) { writer.Position += 8L; } else { writer.WriteUInt64(value.Value); } } private ComImageFlags GetComImageFlags(bool isManagedEntryPoint) { ComImageFlags comImageFlags = Options.Cor20HeaderOptions.Flags ?? module.Cor20HeaderFlags; uint? entryPoint = Options.Cor20HeaderOptions.EntryPoint; if (entryPoint.HasValue) { return comImageFlags; } if (isManagedEntryPoint) { return (ComImageFlags)((uint)comImageFlags & 0xFFFFFFEFu); } return comImageFlags | ComImageFlags.NativeEntryPoint; } private Subsystem GetSubsystem() { if (module.Kind == ModuleKind.Windows) { return Subsystem.WindowsGui; } return Subsystem.WindowsCui; } private long ToWriterOffset(RVA rva) { if (rva == (RVA)0u) { return 0L; } foreach (OrigSection origSection in origSections) { ImageSectionHeader pESection = origSection.PESection; if (pESection.VirtualAddress <= rva && rva < pESection.VirtualAddress + Math.Max(pESection.VirtualSize, pESection.SizeOfRawData)) { return destStreamBaseOffset + (long)origSection.Chunk.FileOffset + (rva - pESection.VirtualAddress); } } return 0L; } private IEnumerable GetSectionSizeInfos() { foreach (OrigSection origSection in origSections) { yield return new SectionSizeInfo(origSection.Chunk.GetVirtualSize(), origSection.PESection.Characteristics); } foreach (PESection section in sections) { yield return new SectionSizeInfo(section.GetVirtualSize(), section.Characteristics); } } private void UpdateVTableFixups(DataWriter writer) { VTableFixups vTableFixups = module.VTableFixups; if (vTableFixups == null || vTableFixups.VTables.Count == 0) { return; } writer.Position = ToWriterOffset(vTableFixups.RVA); if (writer.Position == 0L) { Error("Could not convert RVA to file offset"); return; } foreach (VTable item in vTableFixups) { if (item.Methods.Count > 65535) { throw new ModuleWriterException("Too many methods in vtable"); } writer.WriteUInt32((uint)item.RVA); writer.WriteUInt16((ushort)item.Methods.Count); writer.WriteUInt16((ushort)item.Flags); long position = writer.Position; writer.Position = ToWriterOffset(item.RVA); if (writer.Position == 0L) { if (item.RVA != 0 || item.Methods.Count > 0) { Error("Could not convert RVA to file offset"); } } else { IList methods = item.Methods; int count = methods.Count; for (int i = 0; i < count; i++) { IMethod method = methods[i]; writer.WriteUInt32(GetMethodToken(method)); if (item.Is64Bit) { writer.WriteInt32(0); } } } writer.Position = position; } } private uint GetMethodToken(IMethod method) { if (method is MethodDef md) { return new MDToken(Table.Method, metadata.GetRid(md)).Raw; } if (method is MemberRef mr) { return new MDToken(Table.MemberRef, metadata.GetRid(mr)).Raw; } if (method is MethodSpec ms) { return new MDToken(Table.MethodSpec, metadata.GetRid(ms)).Raw; } if (method == null) { return 0u; } Error("Invalid VTable method type: {0}", method.GetType()); return 0u; } private bool GetEntryPoint(out uint ep) { uint? entryPoint = Options.Cor20HeaderOptions.EntryPoint; if (entryPoint.HasValue) { ep = entryPoint.Value; if (ep != 0) { return (Options.Cor20HeaderOptions.Flags.GetValueOrDefault() & ComImageFlags.NativeEntryPoint) == 0; } return true; } if (module.ManagedEntryPoint is MethodDef md) { ep = new MDToken(Table.Method, metadata.GetRid(md)).Raw; return true; } if (module.ManagedEntryPoint is FileDef fd) { ep = new MDToken(Table.File, metadata.GetRid(fd)).Raw; return true; } ep = (uint)module.NativeEntryPoint; return ep == 0; } } public sealed class NetResources : IReuseChunk, IChunk { private readonly List resources = new List(); private readonly uint alignment; private uint length; private bool setOffsetCalled; private FileOffset offset; private RVA rva; internal bool IsEmpty => resources.Count == 0; public FileOffset FileOffset => offset; public RVA RVA => rva; public uint NextOffset => Utils.AlignUp(length, alignment); public NetResources(uint alignment) { this.alignment = alignment; } public DataReaderChunk Add(DataReader reader) { if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } length = NextOffset + 4 + reader.Length; DataReaderChunk dataReaderChunk = new DataReaderChunk(ref reader); resources.Add(dataReaderChunk); return dataReaderChunk; } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { return length <= origSize; } public void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; foreach (DataReaderChunk resource in resources) { offset = offset.AlignUp(alignment); rva = rva.AlignUp(alignment); resource.SetOffset(offset + 4, rva + 4); uint num = 4 + resource.GetFileLength(); offset += num; rva += num; } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { RVA rVA = rva; foreach (DataReaderChunk resource in resources) { int num = (int)(rVA.AlignUp(alignment) - rVA); writer.WriteZeroes(num); rVA = (RVA)((uint)rVA + (uint)num); writer.WriteUInt32(resource.GetFileLength()); resource.VerifyWriteTo(writer); rVA += 4 + resource.GetFileLength(); } } } internal sealed class NormalMetadata : Metadata { private readonly Rows typeRefInfos = new Rows(); private readonly Rows typeDefInfos = new Rows(); private readonly Rows fieldDefInfos = new Rows(); private readonly Rows methodDefInfos = new Rows(); private readonly Rows paramDefInfos = new Rows(); private readonly Rows memberRefInfos = new Rows(); private readonly Rows standAloneSigInfos = new Rows(); private readonly Rows eventDefInfos = new Rows(); private readonly Rows propertyDefInfos = new Rows(); private readonly Rows typeSpecInfos = new Rows(); private readonly Rows methodSpecInfos = new Rows(); protected override int NumberOfMethods => methodDefInfos.Count; public NormalMetadata(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetadataOptions options, DebugMetadataKind debugKind, bool isStandaloneDebugMetadata) : base(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata) { } protected override TypeDef[] GetAllTypeDefs() { return module.GetTypes().ToArray(); } protected override void AllocateTypeDefRids() { TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { if (typeDef != null) { uint rid = tablesHeap.TypeDefTable.Create(default(RawTypeDefRow)); typeDefInfos.Add(typeDef, rid); } } } protected override void AllocateMemberDefRids() { int num = allTypeDefs.Length; int num2 = 0; int num3 = 0; int num4 = num / 5; uint fieldList = 1u; uint methodList = 1u; uint eventList = 1u; uint propertyList = 1u; uint paramList = 1u; TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { if (num2++ == num4 && num3 < 5) { RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, (double)num2 / (double)num); num3++; num4 = (int)((double)num / 5.0 * (double)(num3 + 1)); } if (typeDef == null) { continue; } uint rid = GetRid(typeDef); RawTypeDefRow rawTypeDefRow = tablesHeap.TypeDefTable[rid]; rawTypeDefRow = new RawTypeDefRow(rawTypeDefRow.Flags, rawTypeDefRow.Name, rawTypeDefRow.Namespace, rawTypeDefRow.Extends, fieldList, methodList); tablesHeap.TypeDefTable[rid] = rawTypeDefRow; IList fields = typeDef.Fields; int count = fields.Count; for (int j = 0; j < count; j++) { FieldDef fieldDef = fields[j]; if (fieldDef != null) { uint num5 = fieldList++; if (num5 != tablesHeap.FieldTable.Create(default(RawFieldRow))) { throw new ModuleWriterException("Invalid field rid"); } fieldDefInfos.Add(fieldDef, num5); } } IList methods = typeDef.Methods; count = methods.Count; for (int k = 0; k < count; k++) { MethodDef methodDef = methods[k]; if (methodDef == null) { continue; } uint num6 = methodList++; RawMethodRow row = new RawMethodRow(0u, 0, 0, 0u, 0u, paramList); if (num6 != tablesHeap.MethodTable.Create(row)) { throw new ModuleWriterException("Invalid method rid"); } methodDefInfos.Add(methodDef, num6); foreach (ParamDef item in Metadata.Sort(methodDef.ParamDefs)) { if (item != null) { uint num7 = paramList++; if (num7 != tablesHeap.ParamTable.Create(default(RawParamRow))) { throw new ModuleWriterException("Invalid param rid"); } paramDefInfos.Add(item, num7); } } } if (!Metadata.IsEmpty(typeDef.Events)) { uint rid2 = tablesHeap.EventMapTable.Create(new RawEventMapRow(rid, eventList)); eventMapInfos.Add(typeDef, rid2); IList events = typeDef.Events; count = events.Count; for (int l = 0; l < count; l++) { EventDef eventDef = events[l]; if (eventDef != null) { uint num8 = eventList++; if (num8 != tablesHeap.EventTable.Create(default(RawEventRow))) { throw new ModuleWriterException("Invalid event rid"); } eventDefInfos.Add(eventDef, num8); } } } if (Metadata.IsEmpty(typeDef.Properties)) { continue; } uint rid3 = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(rid, propertyList)); propertyMapInfos.Add(typeDef, rid3); IList properties = typeDef.Properties; count = properties.Count; for (int m = 0; m < count; m++) { PropertyDef propertyDef = properties[m]; if (propertyDef != null) { uint num9 = propertyList++; if (num9 != tablesHeap.PropertyTable.Create(default(RawPropertyRow))) { throw new ModuleWriterException("Invalid property rid"); } propertyDefInfos.Add(propertyDef, num9); } } } } public override uint GetRid(TypeRef tr) { typeRefInfos.TryGetRid(tr, out var rid); return rid; } public override uint GetRid(TypeDef td) { if (typeDefInfos.TryGetRid(td, out var rid)) { return rid; } if (td == null) { Error("TypeDef is null"); } else { Error("TypeDef '{0}' (0x{1:X8}) is not defined in this module '{2}'. A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); } return 0u; } public override uint GetRid(FieldDef fd) { if (fieldDefInfos.TryGetRid(fd, out var rid)) { return rid; } if (fd == null) { Error("Field is null"); } else { Error("Field '{0}' (0x{1:X8}) is not defined in this module '{2}'. A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); } return 0u; } public override uint GetRid(MethodDef md) { if (methodDefInfos.TryGetRid(md, out var rid)) { return rid; } if (md == null) { Error("Method is null"); } else { Error("Method '{0}' (0x{1:X8}) is not defined in this module '{2}'. A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); } return 0u; } public override uint GetRid(ParamDef pd) { if (paramDefInfos.TryGetRid(pd, out var rid)) { return rid; } if (pd == null) { Error("Param is null"); } else { Error("Param '{0}' (0x{1:X8}) is not defined in this module '{2}'. A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); } return 0u; } public override uint GetRid(MemberRef mr) { memberRefInfos.TryGetRid(mr, out var rid); return rid; } public override uint GetRid(StandAloneSig sas) { standAloneSigInfos.TryGetRid(sas, out var rid); return rid; } public override uint GetRid(EventDef ed) { if (eventDefInfos.TryGetRid(ed, out var rid)) { return rid; } if (ed == null) { Error("Event is null"); } else { Error("Event '{0}' (0x{1:X8}) is not defined in this module '{2}'. An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); } return 0u; } public override uint GetRid(PropertyDef pd) { if (propertyDefInfos.TryGetRid(pd, out var rid)) { return rid; } if (pd == null) { Error("Property is null"); } else { Error("Property '{0}' (0x{1:X8}) is not defined in this module '{2}'. A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); } return 0u; } public override uint GetRid(TypeSpec ts) { typeSpecInfos.TryGetRid(ts, out var rid); return rid; } public override uint GetRid(MethodSpec ms) { methodSpecInfos.TryGetRid(ms, out var rid); return rid; } protected override uint AddTypeRef(TypeRef tr) { if (tr == null) { Error("TypeRef is null"); return 0u; } if (typeRefInfos.TryGetRid(tr, out var rid)) { if (rid == 0) { Error("TypeRef 0x{0:X8} has an infinite ResolutionScope loop.", tr.MDToken.Raw); } return rid; } typeRefInfos.Add(tr, 0u); RawTypeRefRow row = new RawTypeRefRow(AddResolutionScope(tr.ResolutionScope), stringsHeap.Add(tr.Name), stringsHeap.Add(tr.Namespace)); rid = tablesHeap.TypeRefTable.Add(row); typeRefInfos.SetRid(tr, rid); AddCustomAttributes(Table.TypeRef, rid, tr); AddCustomDebugInformationList(Table.TypeRef, rid, tr); return rid; } protected override uint AddTypeSpec(TypeSpec ts) { if (ts == null) { Error("TypeSpec is null"); return 0u; } if (typeSpecInfos.TryGetRid(ts, out var rid)) { if (rid == 0) { Error("TypeSpec 0x{0:X8} has an infinite TypeSig loop.", ts.MDToken.Raw); } return rid; } typeSpecInfos.Add(ts, 0u); RawTypeSpecRow row = new RawTypeSpecRow(GetSignature(ts.TypeSig, ts.ExtraData)); rid = tablesHeap.TypeSpecTable.Add(row); typeSpecInfos.SetRid(ts, rid); AddCustomAttributes(Table.TypeSpec, rid, ts); AddCustomDebugInformationList(Table.TypeSpec, rid, ts); return rid; } protected override uint AddMemberRef(MemberRef mr) { if (mr == null) { Error("MemberRef is null"); return 0u; } if (memberRefInfos.TryGetRid(mr, out var rid)) { return rid; } RawMemberRefRow row = new RawMemberRefRow(AddMemberRefParent(mr.Class), stringsHeap.Add(mr.Name), GetSignature(mr.Signature)); rid = tablesHeap.MemberRefTable.Add(row); memberRefInfos.Add(mr, rid); AddCustomAttributes(Table.MemberRef, rid, mr); AddCustomDebugInformationList(Table.MemberRef, rid, mr); return rid; } protected override uint AddStandAloneSig(StandAloneSig sas) { if (sas == null) { Error("StandAloneSig is null"); return 0u; } if (standAloneSigInfos.TryGetRid(sas, out var rid)) { return rid; } RawStandAloneSigRow row = new RawStandAloneSigRow(GetSignature(sas.Signature)); rid = tablesHeap.StandAloneSigTable.Add(row); standAloneSigInfos.Add(sas, rid); AddCustomAttributes(Table.StandAloneSig, rid, sas); AddCustomDebugInformationList(Table.StandAloneSig, rid, sas); return rid; } protected override uint AddMethodSpec(MethodSpec ms) { if (ms == null) { Error("MethodSpec is null"); return 0u; } if (methodSpecInfos.TryGetRid(ms, out var rid)) { return rid; } RawMethodSpecRow row = new RawMethodSpecRow(AddMethodDefOrRef(ms.Method), GetSignature(ms.Instantiation)); rid = tablesHeap.MethodSpecTable.Add(row); methodSpecInfos.Add(ms, rid); AddCustomAttributes(Table.MethodSpec, rid, ms); AddCustomDebugInformationList(Table.MethodSpec, rid, ms); return rid; } } public sealed class PdbHeap : HeapBase { private readonly byte[] pdbId; private uint entryPoint; private ulong referencedTypeSystemTables; private bool referencedTypeSystemTablesInitd; private int typeSystemTablesCount; private readonly uint[] typeSystemTableRows; public override string Name => "#Pdb"; public byte[] PdbId => pdbId; public uint EntryPoint { get { return entryPoint; } set { entryPoint = value; } } public FileOffset PdbIdOffset => base.FileOffset; public ulong ReferencedTypeSystemTables { get { if (!referencedTypeSystemTablesInitd) { throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); } return referencedTypeSystemTables; } set { if (isReadOnly) { throw new InvalidOperationException("Size has already been calculated, can't write a new value"); } referencedTypeSystemTables = value; referencedTypeSystemTablesInitd = true; typeSystemTablesCount = 0; for (ulong num = value; num != 0L; num >>= 1) { if (((int)num & 1) != 0) { typeSystemTablesCount++; } } } } public uint[] TypeSystemTableRows => typeSystemTableRows; public PdbHeap() { pdbId = new byte[20]; typeSystemTableRows = new uint[64]; } public override uint GetRawLength() { if (!referencedTypeSystemTablesInitd) { throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); } return (uint)(pdbId.Length + 4 + 8 + 4 * typeSystemTablesCount); } protected override void WriteToImpl(DataWriter writer) { if (!referencedTypeSystemTablesInitd) { throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); } writer.WriteBytes(pdbId); writer.WriteUInt32(entryPoint); writer.WriteUInt64(referencedTypeSystemTables); ulong num = referencedTypeSystemTables; int num2 = 0; while (num2 < typeSystemTableRows.Length) { if (((int)num & 1) != 0) { writer.WriteUInt32(typeSystemTableRows[num2]); } num2++; num >>= 1; } } } public sealed class PEHeadersOptions { public const DllCharacteristics DefaultDllCharacteristics = dnlib.PE.DllCharacteristics.DynamicBase | dnlib.PE.DllCharacteristics.NxCompat | dnlib.PE.DllCharacteristics.NoSeh | dnlib.PE.DllCharacteristics.TerminalServerAware; public const Subsystem DEFAULT_SUBSYSTEM = dnlib.PE.Subsystem.WindowsGui; public const byte DEFAULT_MAJOR_LINKER_VERSION = 11; public const byte DEFAULT_MINOR_LINKER_VERSION = 0; public Machine? Machine; public uint? TimeDateStamp; public uint? PointerToSymbolTable; public uint? NumberOfSymbols; public Characteristics? Characteristics; public byte? MajorLinkerVersion; public byte? MinorLinkerVersion; public ulong? ImageBase; public uint? SectionAlignment; public uint? FileAlignment; public ushort? MajorOperatingSystemVersion; public ushort? MinorOperatingSystemVersion; public ushort? MajorImageVersion; public ushort? MinorImageVersion; public ushort? MajorSubsystemVersion; public ushort? MinorSubsystemVersion; public uint? Win32VersionValue; public Subsystem? Subsystem; public DllCharacteristics? DllCharacteristics; public ulong? SizeOfStackReserve; public ulong? SizeOfStackCommit; public ulong? SizeOfHeapReserve; public ulong? SizeOfHeapCommit; public uint? LoaderFlags; public uint? NumberOfRvaAndSizes; private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public static uint CreateNewTimeDateStamp() { return (uint)(DateTime.UtcNow - Epoch).TotalSeconds; } } public sealed class PEHeaders : IChunk { private IList sections; private readonly PEHeadersOptions options; private FileOffset offset; private RVA rva; private uint length; private readonly uint sectionAlignment; private readonly uint fileAlignment; private ulong imageBase; private long startOffset; private long checkSumOffset; private bool isExeFile; private static readonly byte[] dosHeader = new byte[128] { 77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 14, 31, 186, 14, 0, 180, 9, 205, 33, 184, 1, 76, 205, 33, 84, 104, 105, 115, 32, 112, 114, 111, 103, 114, 97, 109, 32, 99, 97, 110, 110, 111, 116, 32, 98, 101, 32, 114, 117, 110, 32, 105, 110, 32, 68, 79, 83, 32, 109, 111, 100, 101, 46, 13, 13, 10, 36, 0, 0, 0, 0, 0, 0, 0 }; public StartupStub StartupStub { get; set; } public ImageCor20Header ImageCor20Header { get; set; } public ImportAddressTable ImportAddressTable { get; set; } public ImportDirectory ImportDirectory { get; set; } public Win32ResourcesChunk Win32Resources { get; set; } public RelocDirectory RelocDirectory { get; set; } public DebugDirectory DebugDirectory { get; set; } internal IChunk ExportDirectory { get; set; } public ulong ImageBase => imageBase; public bool IsExeFile { get { return isExeFile; } set { isExeFile = value; } } public FileOffset FileOffset => offset; public RVA RVA => rva; public uint SectionAlignment => sectionAlignment; public uint FileAlignment => fileAlignment; public IList PESections { get { return sections; } set { sections = value; } } private int SectionsCount { get { int num = 0; foreach (PESection section in sections) { if (section.GetVirtualSize() != 0) { num++; } } return num; } } public PEHeaders() : this(new PEHeadersOptions()) { } public PEHeaders(PEHeadersOptions options) { this.options = options ?? new PEHeadersOptions(); sectionAlignment = this.options.SectionAlignment ?? 8192; fileAlignment = this.options.FileAlignment ?? 512; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = (uint)dosHeader.Length; length += 24u; length += (uint)(Use32BitOptionalHeader() ? 224 : 240); length += (uint)(sections.Count * 40); if (Use32BitOptionalHeader()) { imageBase = (ulong)(((long?)options.ImageBase) ?? ((long)(IsExeFile ? 4194304 : 268435456))); } else { imageBase = (ulong)(((long?)options.ImageBase) ?? (IsExeFile ? 5368709120L : 6442450944L)); } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } private IEnumerable GetSectionSizeInfos() { foreach (PESection section in sections) { uint virtualSize = section.GetVirtualSize(); if (virtualSize != 0) { yield return new SectionSizeInfo(virtualSize, section.Characteristics); } } } public void WriteTo(DataWriter writer) { startOffset = writer.Position; writer.WriteBytes(dosHeader); writer.WriteInt32(17744); writer.WriteUInt16((ushort)GetMachine()); writer.WriteUInt16((ushort)SectionsCount); writer.WriteUInt32(options.TimeDateStamp ?? PEHeadersOptions.CreateNewTimeDateStamp()); writer.WriteUInt32(options.PointerToSymbolTable.GetValueOrDefault()); writer.WriteUInt32(options.NumberOfSymbols.GetValueOrDefault()); writer.WriteUInt16((ushort)(Use32BitOptionalHeader() ? 224u : 240u)); writer.WriteUInt16((ushort)GetCharacteristics()); SectionSizes sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, length, () => GetSectionSizeInfos()); uint value = (uint)((StartupStub != null && StartupStub.Enable) ? StartupStub.EntryPointRVA : ((RVA)0u)); if (Use32BitOptionalHeader()) { writer.WriteUInt16(267); writer.WriteByte(options.MajorLinkerVersion ?? 11); writer.WriteByte(options.MinorLinkerVersion.GetValueOrDefault()); writer.WriteUInt32(sectionSizes.SizeOfCode); writer.WriteUInt32(sectionSizes.SizeOfInitdData); writer.WriteUInt32(sectionSizes.SizeOfUninitdData); writer.WriteUInt32(value); writer.WriteUInt32(sectionSizes.BaseOfCode); writer.WriteUInt32(sectionSizes.BaseOfData); writer.WriteUInt32((uint)imageBase); writer.WriteUInt32(sectionAlignment); writer.WriteUInt32(fileAlignment); writer.WriteUInt16(options.MajorOperatingSystemVersion ?? 4); writer.WriteUInt16(options.MinorOperatingSystemVersion.GetValueOrDefault()); writer.WriteUInt16(options.MajorImageVersion.GetValueOrDefault()); writer.WriteUInt16(options.MinorImageVersion.GetValueOrDefault()); writer.WriteUInt16(options.MajorSubsystemVersion ?? 4); writer.WriteUInt16(options.MinorSubsystemVersion.GetValueOrDefault()); writer.WriteUInt32(options.Win32VersionValue.GetValueOrDefault()); writer.WriteUInt32(sectionSizes.SizeOfImage); writer.WriteUInt32(sectionSizes.SizeOfHeaders); checkSumOffset = writer.Position; writer.WriteInt32(0); writer.WriteUInt16((ushort)(options.Subsystem ?? Subsystem.WindowsGui)); writer.WriteUInt16((ushort)(options.DllCharacteristics ?? (DllCharacteristics.DynamicBase | DllCharacteristics.NxCompat | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware))); writer.WriteUInt32((uint)(options.SizeOfStackReserve ?? 1048576)); writer.WriteUInt32((uint)(options.SizeOfStackCommit ?? 4096)); writer.WriteUInt32((uint)(options.SizeOfHeapReserve ?? 1048576)); writer.WriteUInt32((uint)(options.SizeOfHeapCommit ?? 4096)); writer.WriteUInt32(options.LoaderFlags.GetValueOrDefault()); writer.WriteUInt32(options.NumberOfRvaAndSizes ?? 16); } else { writer.WriteUInt16(523); writer.WriteByte(options.MajorLinkerVersion ?? 11); writer.WriteByte(options.MinorLinkerVersion.GetValueOrDefault()); writer.WriteUInt32(sectionSizes.SizeOfCode); writer.WriteUInt32(sectionSizes.SizeOfInitdData); writer.WriteUInt32(sectionSizes.SizeOfUninitdData); writer.WriteUInt32(value); writer.WriteUInt32(sectionSizes.BaseOfCode); writer.WriteUInt64(imageBase); writer.WriteUInt32(sectionAlignment); writer.WriteUInt32(fileAlignment); writer.WriteUInt16(options.MajorOperatingSystemVersion ?? 4); writer.WriteUInt16(options.MinorOperatingSystemVersion.GetValueOrDefault()); writer.WriteUInt16(options.MajorImageVersion.GetValueOrDefault()); writer.WriteUInt16(options.MinorImageVersion.GetValueOrDefault()); writer.WriteUInt16(options.MajorSubsystemVersion ?? 4); writer.WriteUInt16(options.MinorSubsystemVersion.GetValueOrDefault()); writer.WriteUInt32(options.Win32VersionValue.GetValueOrDefault()); writer.WriteUInt32(sectionSizes.SizeOfImage); writer.WriteUInt32(sectionSizes.SizeOfHeaders); checkSumOffset = writer.Position; writer.WriteInt32(0); writer.WriteUInt16((ushort)(options.Subsystem ?? Subsystem.WindowsGui)); writer.WriteUInt16((ushort)(options.DllCharacteristics ?? (DllCharacteristics.DynamicBase | DllCharacteristics.NxCompat | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware))); writer.WriteUInt64(options.SizeOfStackReserve ?? 4194304); writer.WriteUInt64(options.SizeOfStackCommit ?? 16384); writer.WriteUInt64(options.SizeOfHeapReserve ?? 1048576); writer.WriteUInt64(options.SizeOfHeapCommit ?? 8192); writer.WriteUInt32(options.LoaderFlags.GetValueOrDefault()); writer.WriteUInt32(options.NumberOfRvaAndSizes ?? 16); } writer.WriteDataDirectory(ExportDirectory); writer.WriteDataDirectory(ImportDirectory); writer.WriteDataDirectory(Win32Resources); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); writer.WriteDataDirectory(RelocDirectory); writer.WriteDebugDirectory(DebugDirectory); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); writer.WriteDataDirectory(null); writer.WriteDataDirectory(ImportAddressTable); writer.WriteDataDirectory(null); writer.WriteDataDirectory(ImageCor20Header); writer.WriteDataDirectory(null); uint num = Utils.AlignUp(sectionSizes.SizeOfHeaders, sectionAlignment); int num2 = 0; foreach (PESection section in sections) { if (section.GetVirtualSize() != 0) { num += section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, num); } else { num2++; } } if (num2 != 0) { writer.Position += num2 * 40; } } public void WriteCheckSum(DataWriter writer, long length) { writer.Position = startOffset; uint value = writer.InternalStream.CalculatePECheckSum(length, checkSumOffset); writer.Position = checkSumOffset; writer.WriteUInt32(value); } private Machine GetMachine() { return options.Machine ?? Machine.I386; } private bool Use32BitOptionalHeader() { return !GetMachine().Is64Bit(); } private Characteristics GetCharacteristics() { Characteristics characteristics = options.Characteristics ?? GetDefaultCharacteristics(); if (IsExeFile) { return characteristics & ~Characteristics.Dll; } return characteristics | Characteristics.Dll; } private Characteristics GetDefaultCharacteristics() { if (Use32BitOptionalHeader()) { return Characteristics.ExecutableImage | Characteristics.Bit32Machine; } return Characteristics.ExecutableImage | Characteristics.LargeAddressAware; } } public sealed class PESection : ChunkList { private string name; private uint characteristics; public string Name { get { return name; } set { name = value; } } public uint Characteristics { get { return characteristics; } set { characteristics = value; } } public bool IsCode => (characteristics & 0x20) != 0; public bool IsInitializedData => (characteristics & 0x40) != 0; public bool IsUninitializedData => (characteristics & 0x80) != 0; public PESection(string name, uint characteristics) { this.name = name; this.characteristics = characteristics; } public uint WriteHeaderTo(DataWriter writer, uint fileAlignment, uint sectionAlignment, uint rva) { uint num = GetVirtualSize(); uint fileLength = GetFileLength(); uint result = Utils.AlignUp(num, sectionAlignment); uint value = Utils.AlignUp(fileLength, fileAlignment); uint fileOffset = (uint)base.FileOffset; writer.WriteBytes(Encoding.UTF8.GetBytes(Name + "\0\0\0\0\0\0\0\0"), 0, 8); writer.WriteUInt32(num); writer.WriteUInt32(rva); writer.WriteUInt32(value); writer.WriteUInt32(fileOffset); writer.WriteInt32(0); writer.WriteInt32(0); writer.WriteUInt16(0); writer.WriteUInt16(0); writer.WriteUInt32(Characteristics); return result; } } internal static class PortablePdbConstants { public const ushort FormatVersion = 256; public const ushort EmbeddedVersion = 256; public const ushort PortableCodeViewVersionMagic = 20557; } internal sealed class PreserveTokensMetadata : Metadata { [DebuggerDisplay("{Rid} -> {NewRid} {Def}")] private sealed class MemberDefInfo where T : IMDTokenProvider { public readonly T Def; public uint Rid; public uint NewRid; public MemberDefInfo(T def, uint rid) { Def = def; Rid = rid; NewRid = rid; } } [DebuggerDisplay("Count = {Count}")] private sealed class MemberDefDict where T : IMDTokenProvider { private readonly Type defMDType; private uint userRid = 16777216u; private uint newRid = 1u; private int numDefMDs; private int numDefUsers; private int tableSize; private bool wasSorted; private readonly bool preserveRids; private readonly bool enableRidToInfo; private readonly Dictionary> defToInfo = new Dictionary>(); private Dictionary> ridToInfo; private readonly List> defs = new List>(); private List> sortedDefs; private readonly Dictionary collectionPositions = new Dictionary(); public int Count => defs.Count; public int TableSize => tableSize; public bool NeedPtrTable { get { if (preserveRids) { return !wasSorted; } return false; } } public MemberDefDict(Type defMDType, bool preserveRids) : this(defMDType, preserveRids, enableRidToInfo: false) { } public MemberDefDict(Type defMDType, bool preserveRids, bool enableRidToInfo) { this.defMDType = defMDType; this.preserveRids = preserveRids; this.enableRidToInfo = enableRidToInfo; } public uint Rid(T def) { return defToInfo[def].Rid; } public bool TryGetRid(T def, out uint rid) { if (def == null || !defToInfo.TryGetValue(def, out var value)) { rid = 0u; return false; } rid = value.Rid; return true; } public void Sort(Comparison> comparer) { if (!preserveRids) { sortedDefs = defs; return; } sortedDefs = new List>(defs); sortedDefs.Sort(comparer); wasSorted = true; for (int i = 0; i < sortedDefs.Count; i++) { MemberDefInfo memberDefInfo = sortedDefs[i]; uint num = (memberDefInfo.NewRid = (uint)(i + 1)); if (memberDefInfo.Rid != num) { wasSorted = false; } } } public MemberDefInfo Get(int i) { return defs[i]; } public MemberDefInfo GetSorted(int i) { return sortedDefs[i]; } public MemberDefInfo GetByRid(uint rid) { ridToInfo.TryGetValue(rid, out var value); return value; } public void Add(T def, int collPos) { uint rid; if (def.GetType() == defMDType) { numDefMDs++; rid = (preserveRids ? def.Rid : newRid++); } else { numDefUsers++; rid = (preserveRids ? userRid++ : newRid++); } MemberDefInfo memberDefInfo = new MemberDefInfo(def, rid); defToInfo[def] = memberDefInfo; defs.Add(memberDefInfo); collectionPositions.Add(def, collPos); } public void SortDefs() { if (preserveRids) { defs.Sort((MemberDefInfo a, MemberDefInfo b) => a.Rid.CompareTo(b.Rid)); uint num = ((numDefMDs == 0) ? 1u : (defs[numDefMDs - 1].Rid + 1)); for (int num2 = numDefMDs; num2 < defs.Count; num2++) { defs[num2].Rid = num++; } tableSize = (int)(num - 1); } else { tableSize = defs.Count; } if (enableRidToInfo) { ridToInfo = new Dictionary>(defs.Count); foreach (MemberDefInfo def in defs) { ridToInfo.Add(def.Rid, def); } } if ((uint)tableSize > 16777215u) { throw new ModuleWriterException("Table is too big"); } } public int GetCollectionPosition(T def) { return collectionPositions[def]; } } private readonly ModuleDefMD mod; private readonly Rows typeRefInfos = new Rows(); private readonly Dictionary typeToRid = new Dictionary(); private MemberDefDict fieldDefInfos; private MemberDefDict methodDefInfos; private MemberDefDict paramDefInfos; private readonly Rows memberRefInfos = new Rows(); private readonly Rows standAloneSigInfos = new Rows(); private MemberDefDict eventDefInfos; private MemberDefDict propertyDefInfos; private readonly Rows typeSpecInfos = new Rows(); private readonly Rows methodSpecInfos = new Rows(); private readonly Dictionary callConvTokenToSignature = new Dictionary(); private bool initdTypeRef; private bool initdMemberRef; private bool initdStandAloneSig; private bool initdTypeSpec; private bool initdMethodSpec; private uint dummyPtrTableTypeRid; protected override int NumberOfMethods => methodDefInfos.Count; public PreserveTokensMetadata(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetadataOptions options, DebugMetadataKind debugKind, bool isStandaloneDebugMetadata) : base(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata) { mod = module as ModuleDefMD; if (mod == null) { throw new ModuleWriterException("Not a ModuleDefMD"); } } public override uint GetRid(TypeRef tr) { typeRefInfos.TryGetRid(tr, out var rid); return rid; } public override uint GetRid(TypeDef td) { if (td == null) { Error("TypeDef is null"); return 0u; } if (typeToRid.TryGetValue(td, out var value)) { return value; } Error("TypeDef '{0}' (0x{1:X8}) is not defined in this module '{2}'. A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); return 0u; } public override uint GetRid(FieldDef fd) { if (fieldDefInfos.TryGetRid(fd, out var rid)) { return rid; } if (fd == null) { Error("Field is null"); } else { Error("Field '{0}' (0x{1:X8}) is not defined in this module '{2}'. A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); } return 0u; } public override uint GetRid(MethodDef md) { if (methodDefInfos.TryGetRid(md, out var rid)) { return rid; } if (md == null) { Error("Method is null"); } else { Error("Method '{0}' (0x{1:X8}) is not defined in this module '{2}'. A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); } return 0u; } public override uint GetRid(ParamDef pd) { if (paramDefInfos.TryGetRid(pd, out var rid)) { return rid; } if (pd == null) { Error("Param is null"); } else { Error("Param '{0}' (0x{1:X8}) is not defined in this module '{2}'. A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); } return 0u; } public override uint GetRid(MemberRef mr) { memberRefInfos.TryGetRid(mr, out var rid); return rid; } public override uint GetRid(StandAloneSig sas) { standAloneSigInfos.TryGetRid(sas, out var rid); return rid; } public override uint GetRid(EventDef ed) { if (eventDefInfos.TryGetRid(ed, out var rid)) { return rid; } if (ed == null) { Error("Event is null"); } else { Error("Event '{0}' (0x{1:X8}) is not defined in this module '{2}'. An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); } return 0u; } public override uint GetRid(PropertyDef pd) { if (propertyDefInfos.TryGetRid(pd, out var rid)) { return rid; } if (pd == null) { Error("Property is null"); } else { Error("Property '{0}' (0x{1:X8}) is not defined in this module '{2}'. A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); } return 0u; } public override uint GetRid(TypeSpec ts) { typeSpecInfos.TryGetRid(ts, out var rid); return rid; } public override uint GetRid(MethodSpec ms) { methodSpecInfos.TryGetRid(ms, out var rid); return rid; } protected override void Initialize() { fieldDefInfos = new MemberDefDict(typeof(FieldDefMD), base.PreserveFieldRids); methodDefInfos = new MemberDefDict(typeof(MethodDefMD), base.PreserveMethodRids, enableRidToInfo: true); paramDefInfos = new MemberDefDict(typeof(ParamDefMD), base.PreserveParamRids); eventDefInfos = new MemberDefDict(typeof(EventDefMD), base.PreserveEventRids); propertyDefInfos = new MemberDefDict(typeof(PropertyDefMD), base.PreservePropertyRids); CreateEmptyTableRows(); } protected override TypeDef[] GetAllTypeDefs() { if (!base.PreserveTypeDefRids) { TypeDef[] array = module.GetTypes().ToArray(); InitializeTypeToRid(array); return array; } Dictionary typeToIndex = new Dictionary(); List list = new List(); uint num = 0u; foreach (TypeDef type in module.GetTypes()) { if (type != null) { list.Add(type); uint num2 = num++; if (type.GetType() == typeof(TypeDefMD)) { num2 |= 0x80000000u; } typeToIndex[type] = num2; } } TypeDef globalType = list[0]; list.Sort(delegate(TypeDef a, TypeDef b) { if (a == b) { return 0; } if (a == globalType) { return -1; } if (b == globalType) { return 1; } uint num7 = typeToIndex[a]; uint num8 = typeToIndex[b]; bool flag = (num7 & 0x80000000u) != 0; bool flag2 = (num8 & 0x80000000u) != 0; if (flag == flag2) { if (flag) { return a.Rid.CompareTo(b.Rid); } return (num7 & 0xFFFFFF).CompareTo(num8 & 0xFFFFFF); } return (!flag) ? 1 : (-1); }); List list2 = new List(list.Count); uint num3 = 1u; list2.Add(globalType); for (int num4 = 1; num4 < list.Count; num4++) { TypeDef typeDef = list[num4]; if (typeDef.GetType() != typeof(TypeDefMD)) { while (num4 < list.Count) { list2.Add(list[num4++]); } break; } uint rid = typeDef.Rid; int num5 = (int)(rid - num3 - 1); if (num5 != 0) { for (int num6 = 0; num6 < num5; num6++) { list2.Add(new TypeDefUser("dummy", Guid.NewGuid().ToString("B"), module.CorLibTypes.Object.TypeDefOrRef)); } } list2.Add(typeDef); num3 = rid; } TypeDef[] array2 = list2.ToArray(); InitializeTypeToRid(array2); return array2; } private void InitializeTypeToRid(TypeDef[] types) { uint num = 1u; foreach (TypeDef typeDef in types) { if (typeDef != null && !typeToRid.ContainsKey(typeDef)) { typeToRid[typeDef] = num++; } } } protected override void AllocateTypeDefRids() { TypeDef[] array = allTypeDefs; foreach (TypeDef key in array) { uint num = tablesHeap.TypeDefTable.Create(default(RawTypeDefRow)); if (typeToRid[key] != num) { throw new ModuleWriterException("Got a different rid than expected"); } } } private void CreateEmptyTableRows() { if (base.PreserveTypeRefRids) { uint rows = mod.TablesStream.TypeRefTable.Rows; for (uint num = 0u; num < rows; num++) { tablesHeap.TypeRefTable.Create(default(RawTypeRefRow)); } } if (base.PreserveMemberRefRids) { uint rows = mod.TablesStream.MemberRefTable.Rows; for (uint num2 = 0u; num2 < rows; num2++) { tablesHeap.MemberRefTable.Create(default(RawMemberRefRow)); } } if (base.PreserveStandAloneSigRids) { uint rows = mod.TablesStream.StandAloneSigTable.Rows; for (uint num3 = 0u; num3 < rows; num3++) { tablesHeap.StandAloneSigTable.Create(default(RawStandAloneSigRow)); } } if (base.PreserveTypeSpecRids) { uint rows = mod.TablesStream.TypeSpecTable.Rows; for (uint num4 = 0u; num4 < rows; num4++) { tablesHeap.TypeSpecTable.Create(default(RawTypeSpecRow)); } } if (base.PreserveMethodSpecRids) { uint rows = mod.TablesStream.MethodSpecTable.Rows; for (uint num5 = 0u; num5 < rows; num5++) { tablesHeap.MethodSpecTable.Create(default(RawMethodSpecRow)); } } } private void InitializeUninitializedTableRows() { InitializeTypeRefTableRows(); InitializeMemberRefTableRows(); InitializeStandAloneSigTableRows(); InitializeTypeSpecTableRows(); InitializeMethodSpecTableRows(); } private void InitializeTypeRefTableRows() { if (base.PreserveTypeRefRids && !initdTypeRef) { initdTypeRef = true; uint rows = mod.TablesStream.TypeRefTable.Rows; for (uint num = 1u; num <= rows; num++) { AddTypeRef(mod.ResolveTypeRef(num)); } tablesHeap.TypeRefTable.ReAddRows(); } } private void InitializeMemberRefTableRows() { if (!base.PreserveMemberRefRids || initdMemberRef) { return; } initdMemberRef = true; uint rows = mod.TablesStream.MemberRefTable.Rows; for (uint num = 1u; num <= rows; num++) { if (tablesHeap.MemberRefTable[num].Class == 0) { AddMemberRef(mod.ResolveMemberRef(num), forceIsOld: true); } } tablesHeap.MemberRefTable.ReAddRows(); } private void InitializeStandAloneSigTableRows() { if (!base.PreserveStandAloneSigRids || initdStandAloneSig) { return; } initdStandAloneSig = true; uint rows = mod.TablesStream.StandAloneSigTable.Rows; for (uint num = 1u; num <= rows; num++) { if (tablesHeap.StandAloneSigTable[num].Signature == 0) { AddStandAloneSig(mod.ResolveStandAloneSig(num), forceIsOld: true); } } tablesHeap.StandAloneSigTable.ReAddRows(); } private void InitializeTypeSpecTableRows() { if (!base.PreserveTypeSpecRids || initdTypeSpec) { return; } initdTypeSpec = true; uint rows = mod.TablesStream.TypeSpecTable.Rows; for (uint num = 1u; num <= rows; num++) { if (tablesHeap.TypeSpecTable[num].Signature == 0) { AddTypeSpec(mod.ResolveTypeSpec(num), forceIsOld: true); } } tablesHeap.TypeSpecTable.ReAddRows(); } private void InitializeMethodSpecTableRows() { if (!base.PreserveMethodSpecRids || initdMethodSpec) { return; } initdMethodSpec = true; uint rows = mod.TablesStream.MethodSpecTable.Rows; for (uint num = 1u; num <= rows; num++) { if (tablesHeap.MethodSpecTable[num].Method == 0) { AddMethodSpec(mod.ResolveMethodSpec(num), forceIsOld: true); } } tablesHeap.MethodSpecTable.ReAddRows(); } protected override void AllocateMemberDefRids() { FindMemberDefs(); RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, 0.0); for (int i = 1; i <= fieldDefInfos.TableSize; i++) { if (i != (int)tablesHeap.FieldTable.Create(default(RawFieldRow))) { throw new ModuleWriterException("Invalid field rid"); } } for (int j = 1; j <= methodDefInfos.TableSize; j++) { if (j != (int)tablesHeap.MethodTable.Create(default(RawMethodRow))) { throw new ModuleWriterException("Invalid method rid"); } } for (int k = 1; k <= paramDefInfos.TableSize; k++) { if (k != (int)tablesHeap.ParamTable.Create(default(RawParamRow))) { throw new ModuleWriterException("Invalid param rid"); } } for (int l = 1; l <= eventDefInfos.TableSize; l++) { if (l != (int)tablesHeap.EventTable.Create(default(RawEventRow))) { throw new ModuleWriterException("Invalid event rid"); } } for (int m = 1; m <= propertyDefInfos.TableSize; m++) { if (m != (int)tablesHeap.PropertyTable.Create(default(RawPropertyRow))) { throw new ModuleWriterException("Invalid property rid"); } } SortFields(); SortMethods(); SortParameters(); SortEvents(); SortProperties(); RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, 0.2); if (fieldDefInfos.NeedPtrTable) { for (int n = 0; n < fieldDefInfos.Count; n++) { MemberDefInfo sorted = fieldDefInfos.GetSorted(n); if (n + 1 != (int)tablesHeap.FieldPtrTable.Add(new RawFieldPtrRow(sorted.Rid))) { throw new ModuleWriterException("Invalid field ptr rid"); } } ReUseDeletedFieldRows(); } if (methodDefInfos.NeedPtrTable) { for (int num = 0; num < methodDefInfos.Count; num++) { MemberDefInfo sorted2 = methodDefInfos.GetSorted(num); if (num + 1 != (int)tablesHeap.MethodPtrTable.Add(new RawMethodPtrRow(sorted2.Rid))) { throw new ModuleWriterException("Invalid method ptr rid"); } } ReUseDeletedMethodRows(); } if (paramDefInfos.NeedPtrTable) { for (int num2 = 0; num2 < paramDefInfos.Count; num2++) { MemberDefInfo sorted3 = paramDefInfos.GetSorted(num2); if (num2 + 1 != (int)tablesHeap.ParamPtrTable.Add(new RawParamPtrRow(sorted3.Rid))) { throw new ModuleWriterException("Invalid param ptr rid"); } } ReUseDeletedParamRows(); } if (eventDefInfos.NeedPtrTable) { for (int num3 = 0; num3 < eventDefInfos.Count; num3++) { MemberDefInfo sorted4 = eventDefInfos.GetSorted(num3); if (num3 + 1 != (int)tablesHeap.EventPtrTable.Add(new RawEventPtrRow(sorted4.Rid))) { throw new ModuleWriterException("Invalid event ptr rid"); } } } if (propertyDefInfos.NeedPtrTable) { for (int num4 = 0; num4 < propertyDefInfos.Count; num4++) { MemberDefInfo sorted5 = propertyDefInfos.GetSorted(num4); if (num4 + 1 != (int)tablesHeap.PropertyPtrTable.Add(new RawPropertyPtrRow(sorted5.Rid))) { throw new ModuleWriterException("Invalid property ptr rid"); } } } RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, 0.4); InitializeMethodAndFieldList(); InitializeParamList(); InitializeEventMap(); InitializePropertyMap(); RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, 0.6); if (eventDefInfos.NeedPtrTable) { ReUseDeletedEventRows(); } if (propertyDefInfos.NeedPtrTable) { ReUseDeletedPropertyRows(); } RaiseProgress(dnlib.DotNet.Writer.MetadataEvent.AllocateMemberDefRids, 0.8); InitializeTypeRefTableRows(); InitializeTypeSpecTableRows(); InitializeMemberRefTableRows(); InitializeMethodSpecTableRows(); } private void ReUseDeletedFieldRows() { if (tablesHeap.FieldPtrTable.IsEmpty || fieldDefInfos.TableSize == tablesHeap.FieldPtrTable.Rows) { return; } bool[] array = new bool[fieldDefInfos.TableSize]; for (int i = 0; i < fieldDefInfos.Count; i++) { array[fieldDefInfos.Get(i).Rid - 1] = true; } CreateDummyPtrTableType(); uint signature = GetSignature(new FieldSig(module.CorLibTypes.Byte)); for (int j = 0; j < array.Length; j++) { if (!array[j]) { uint num = (uint)(j + 1); RawFieldRow value = new RawFieldRow(22, stringsHeap.Add($"f{num:X6}"), signature); tablesHeap.FieldTable[num] = value; tablesHeap.FieldPtrTable.Create(new RawFieldPtrRow(num)); } } if (fieldDefInfos.TableSize == tablesHeap.FieldPtrTable.Rows) { return; } throw new ModuleWriterException("Didn't create all dummy fields"); } private void ReUseDeletedMethodRows() { if (tablesHeap.MethodPtrTable.IsEmpty || methodDefInfos.TableSize == tablesHeap.MethodPtrTable.Rows) { return; } bool[] array = new bool[methodDefInfos.TableSize]; for (int i = 0; i < methodDefInfos.Count; i++) { array[methodDefInfos.Get(i).Rid - 1] = true; } CreateDummyPtrTableType(); uint signature = GetSignature(MethodSig.CreateInstance(module.CorLibTypes.Void)); for (int j = 0; j < array.Length; j++) { if (!array[j]) { uint num = (uint)(j + 1); RawMethodRow value = new RawMethodRow(0u, 0, 1478, stringsHeap.Add($"m{num:X6}"), signature, (uint)paramDefInfos.Count); tablesHeap.MethodTable[num] = value; tablesHeap.MethodPtrTable.Create(new RawMethodPtrRow(num)); } } if (methodDefInfos.TableSize == tablesHeap.MethodPtrTable.Rows) { return; } throw new ModuleWriterException("Didn't create all dummy methods"); } private void ReUseDeletedParamRows() { if (tablesHeap.ParamPtrTable.IsEmpty || paramDefInfos.TableSize == tablesHeap.ParamPtrTable.Rows) { return; } bool[] array = new bool[paramDefInfos.TableSize]; for (int i = 0; i < paramDefInfos.Count; i++) { array[paramDefInfos.Get(i).Rid - 1] = true; } CreateDummyPtrTableType(); uint signature = GetSignature(MethodSig.CreateInstance(module.CorLibTypes.Void)); for (int j = 0; j < array.Length; j++) { if (!array[j]) { uint num = (uint)(j + 1); RawParamRow value = new RawParamRow(0, 0, stringsHeap.Add($"p{num:X6}")); tablesHeap.ParamTable[num] = value; uint paramList = tablesHeap.ParamPtrTable.Create(new RawParamPtrRow(num)); RawMethodRow row = new RawMethodRow(0u, 0, 1478, stringsHeap.Add($"mp{num:X6}"), signature, paramList); uint method = tablesHeap.MethodTable.Create(row); if (tablesHeap.MethodPtrTable.Rows > 0) { tablesHeap.MethodPtrTable.Create(new RawMethodPtrRow(method)); } } } if (paramDefInfos.TableSize == tablesHeap.ParamPtrTable.Rows) { return; } throw new ModuleWriterException("Didn't create all dummy params"); } private void ReUseDeletedEventRows() { if (tablesHeap.EventPtrTable.IsEmpty || eventDefInfos.TableSize == tablesHeap.EventPtrTable.Rows) { return; } bool[] array = new bool[eventDefInfos.TableSize]; for (int i = 0; i < eventDefInfos.Count; i++) { array[eventDefInfos.Get(i).Rid - 1] = true; } uint parent = CreateDummyPtrTableType(); tablesHeap.EventMapTable.Create(new RawEventMapRow(parent, (uint)(tablesHeap.EventPtrTable.Rows + 1))); uint eventType = AddTypeDefOrRef(module.CorLibTypes.Object.TypeDefOrRef); for (int j = 0; j < array.Length; j++) { if (!array[j]) { uint num = (uint)(j + 1); RawEventRow value = new RawEventRow(0, stringsHeap.Add($"E{num:X6}"), eventType); tablesHeap.EventTable[num] = value; tablesHeap.EventPtrTable.Create(new RawEventPtrRow(num)); } } if (eventDefInfos.TableSize == tablesHeap.EventPtrTable.Rows) { return; } throw new ModuleWriterException("Didn't create all dummy events"); } private void ReUseDeletedPropertyRows() { if (tablesHeap.PropertyPtrTable.IsEmpty || propertyDefInfos.TableSize == tablesHeap.PropertyPtrTable.Rows) { return; } bool[] array = new bool[propertyDefInfos.TableSize]; for (int i = 0; i < propertyDefInfos.Count; i++) { array[propertyDefInfos.Get(i).Rid - 1] = true; } uint parent = CreateDummyPtrTableType(); tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(parent, (uint)(tablesHeap.PropertyPtrTable.Rows + 1))); uint signature = GetSignature(PropertySig.CreateStatic(module.CorLibTypes.Object)); for (int j = 0; j < array.Length; j++) { if (!array[j]) { uint num = (uint)(j + 1); RawPropertyRow value = new RawPropertyRow(0, stringsHeap.Add($"P{num:X6}"), signature); tablesHeap.PropertyTable[num] = value; tablesHeap.PropertyPtrTable.Create(new RawPropertyPtrRow(num)); } } if (propertyDefInfos.TableSize == tablesHeap.PropertyPtrTable.Rows) { return; } throw new ModuleWriterException("Didn't create all dummy properties"); } private uint CreateDummyPtrTableType() { if (dummyPtrTableTypeRid != 0) { return dummyPtrTableTypeRid; } TypeAttributes flags = TypeAttributes.Abstract; int num = (fieldDefInfos.NeedPtrTable ? fieldDefInfos.Count : fieldDefInfos.TableSize); int num2 = (methodDefInfos.NeedPtrTable ? methodDefInfos.Count : methodDefInfos.TableSize); RawTypeDefRow row = new RawTypeDefRow((uint)flags, stringsHeap.Add(Guid.NewGuid().ToString("B")), stringsHeap.Add("dummy_ptr"), AddTypeDefOrRef(module.CorLibTypes.Object.TypeDefOrRef), (uint)(num + 1), (uint)(num2 + 1)); dummyPtrTableTypeRid = tablesHeap.TypeDefTable.Create(row); if (dummyPtrTableTypeRid == 1) { throw new ModuleWriterException("Dummy ptr type is the first type"); } return dummyPtrTableTypeRid; } private void FindMemberDefs() { Dictionary dictionary = new Dictionary(); TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { if (typeDef == null) { continue; } int num = 0; IList fields = typeDef.Fields; int count = fields.Count; for (int j = 0; j < count; j++) { FieldDef fieldDef = fields[j]; if (fieldDef != null) { fieldDefInfos.Add(fieldDef, num++); } } num = 0; IList methods = typeDef.Methods; count = methods.Count; for (int k = 0; k < count; k++) { MethodDef methodDef = methods[k]; if (methodDef != null) { methodDefInfos.Add(methodDef, num++); } } num = 0; IList events = typeDef.Events; count = events.Count; for (int l = 0; l < count; l++) { EventDef eventDef = events[l]; if (eventDef != null && !dictionary.ContainsKey(eventDef)) { dictionary[eventDef] = true; eventDefInfos.Add(eventDef, num++); } } num = 0; IList properties = typeDef.Properties; count = properties.Count; for (int m = 0; m < count; m++) { PropertyDef propertyDef = properties[m]; if (propertyDef != null && !dictionary.ContainsKey(propertyDef)) { dictionary[propertyDef] = true; propertyDefInfos.Add(propertyDef, num++); } } } fieldDefInfos.SortDefs(); methodDefInfos.SortDefs(); eventDefInfos.SortDefs(); propertyDefInfos.SortDefs(); for (int n = 0; n < methodDefInfos.Count; n++) { MethodDef def = methodDefInfos.Get(n).Def; int num = 0; foreach (ParamDef item in Metadata.Sort(def.ParamDefs)) { if (item != null) { paramDefInfos.Add(item, num++); } } } paramDefInfos.SortDefs(); } private void SortFields() { fieldDefInfos.Sort(delegate(MemberDefInfo a, MemberDefInfo b) { uint num = ((a.Def.DeclaringType != null) ? typeToRid[a.Def.DeclaringType] : 0u); uint num2 = ((b.Def.DeclaringType != null) ? typeToRid[b.Def.DeclaringType] : 0u); if (num == 0 || num2 == 0) { return a.Rid.CompareTo(b.Rid); } return (num != num2) ? num.CompareTo(num2) : fieldDefInfos.GetCollectionPosition(a.Def).CompareTo(fieldDefInfos.GetCollectionPosition(b.Def)); }); } private void SortMethods() { methodDefInfos.Sort(delegate(MemberDefInfo a, MemberDefInfo b) { uint num = ((a.Def.DeclaringType != null) ? typeToRid[a.Def.DeclaringType] : 0u); uint num2 = ((b.Def.DeclaringType != null) ? typeToRid[b.Def.DeclaringType] : 0u); if (num == 0 || num2 == 0) { return a.Rid.CompareTo(b.Rid); } return (num != num2) ? num.CompareTo(num2) : methodDefInfos.GetCollectionPosition(a.Def).CompareTo(methodDefInfos.GetCollectionPosition(b.Def)); }); } private void SortParameters() { paramDefInfos.Sort(delegate(MemberDefInfo a, MemberDefInfo b) { uint num = ((a.Def.DeclaringMethod != null) ? methodDefInfos.Rid(a.Def.DeclaringMethod) : 0u); uint num2 = ((b.Def.DeclaringMethod != null) ? methodDefInfos.Rid(b.Def.DeclaringMethod) : 0u); if (num == 0 || num2 == 0) { return a.Rid.CompareTo(b.Rid); } return (num != num2) ? num.CompareTo(num2) : paramDefInfos.GetCollectionPosition(a.Def).CompareTo(paramDefInfos.GetCollectionPosition(b.Def)); }); } private void SortEvents() { eventDefInfos.Sort(delegate(MemberDefInfo a, MemberDefInfo b) { uint num = ((a.Def.DeclaringType != null) ? typeToRid[a.Def.DeclaringType] : 0u); uint num2 = ((b.Def.DeclaringType != null) ? typeToRid[b.Def.DeclaringType] : 0u); if (num == 0 || num2 == 0) { return a.Rid.CompareTo(b.Rid); } return (num != num2) ? num.CompareTo(num2) : eventDefInfos.GetCollectionPosition(a.Def).CompareTo(eventDefInfos.GetCollectionPosition(b.Def)); }); } private void SortProperties() { propertyDefInfos.Sort(delegate(MemberDefInfo a, MemberDefInfo b) { uint num = ((a.Def.DeclaringType != null) ? typeToRid[a.Def.DeclaringType] : 0u); uint num2 = ((b.Def.DeclaringType != null) ? typeToRid[b.Def.DeclaringType] : 0u); if (num == 0 || num2 == 0) { return a.Rid.CompareTo(b.Rid); } return (num != num2) ? num.CompareTo(num2) : propertyDefInfos.GetCollectionPosition(a.Def).CompareTo(propertyDefInfos.GetCollectionPosition(b.Def)); }); } private void InitializeMethodAndFieldList() { uint num = 1u; uint num2 = 1u; TypeDef[] array = allTypeDefs; foreach (TypeDef typeDef in array) { uint rid = typeToRid[typeDef]; RawTypeDefRow rawTypeDefRow = tablesHeap.TypeDefTable[rid]; rawTypeDefRow = new RawTypeDefRow(rawTypeDefRow.Flags, rawTypeDefRow.Name, rawTypeDefRow.Namespace, rawTypeDefRow.Extends, num, num2); tablesHeap.TypeDefTable[rid] = rawTypeDefRow; num += (uint)typeDef.Fields.Count; num2 += (uint)typeDef.Methods.Count; } } private void InitializeParamList() { uint num = 1u; for (uint num2 = 1u; num2 <= methodDefInfos.TableSize; num2++) { MemberDefInfo byRid = methodDefInfos.GetByRid(num2); RawMethodRow rawMethodRow = tablesHeap.MethodTable[num2]; rawMethodRow = new RawMethodRow(rawMethodRow.RVA, rawMethodRow.ImplFlags, rawMethodRow.Flags, rawMethodRow.Name, rawMethodRow.Signature, num); tablesHeap.MethodTable[num2] = rawMethodRow; if (byRid != null) { num += (uint)byRid.Def.ParamDefs.Count; } } } private void InitializeEventMap() { if (!tablesHeap.EventMapTable.IsEmpty) { throw new ModuleWriterException("EventMap table isn't empty"); } TypeDef typeDef = null; for (int i = 0; i < eventDefInfos.Count; i++) { MemberDefInfo sorted = eventDefInfos.GetSorted(i); if (typeDef != sorted.Def.DeclaringType) { typeDef = sorted.Def.DeclaringType; RawEventMapRow row = new RawEventMapRow(typeToRid[typeDef], sorted.NewRid); uint rid = tablesHeap.EventMapTable.Create(row); eventMapInfos.Add(typeDef, rid); } } } private void InitializePropertyMap() { if (!tablesHeap.PropertyMapTable.IsEmpty) { throw new ModuleWriterException("PropertyMap table isn't empty"); } TypeDef typeDef = null; for (int i = 0; i < propertyDefInfos.Count; i++) { MemberDefInfo sorted = propertyDefInfos.GetSorted(i); if (typeDef != sorted.Def.DeclaringType) { typeDef = sorted.Def.DeclaringType; RawPropertyMapRow row = new RawPropertyMapRow(typeToRid[typeDef], sorted.NewRid); uint rid = tablesHeap.PropertyMapTable.Create(row); propertyMapInfos.Add(typeDef, rid); } } } protected override uint AddTypeRef(TypeRef tr) { if (tr == null) { Error("TypeRef is null"); return 0u; } if (typeRefInfos.TryGetRid(tr, out var rid)) { if (rid == 0) { Error("TypeRef 0x{0:X8} has an infinite ResolutionScope loop.", tr.MDToken.Raw); } return rid; } typeRefInfos.Add(tr, 0u); bool num = base.PreserveTypeRefRids && mod.ResolveTypeRef(tr.Rid) == tr; RawTypeRefRow rawTypeRefRow = new RawTypeRefRow(AddResolutionScope(tr.ResolutionScope), stringsHeap.Add(tr.Name), stringsHeap.Add(tr.Namespace)); if (num) { rid = tr.Rid; tablesHeap.TypeRefTable[tr.Rid] = rawTypeRefRow; } else { rid = tablesHeap.TypeRefTable.Add(rawTypeRefRow); } typeRefInfos.SetRid(tr, rid); AddCustomAttributes(Table.TypeRef, rid, tr); AddCustomDebugInformationList(Table.TypeRef, rid, tr); return rid; } protected override uint AddTypeSpec(TypeSpec ts) { return AddTypeSpec(ts, forceIsOld: false); } private uint AddTypeSpec(TypeSpec ts, bool forceIsOld) { if (ts == null) { Error("TypeSpec is null"); return 0u; } if (typeSpecInfos.TryGetRid(ts, out var rid)) { if (rid == 0) { Error("TypeSpec 0x{0:X8} has an infinite TypeSig loop.", ts.MDToken.Raw); } return rid; } typeSpecInfos.Add(ts, 0u); bool num = forceIsOld || (base.PreserveTypeSpecRids && mod.ResolveTypeSpec(ts.Rid) == ts); RawTypeSpecRow rawTypeSpecRow = new RawTypeSpecRow(GetSignature(ts.TypeSig, ts.ExtraData)); if (num) { rid = ts.Rid; tablesHeap.TypeSpecTable[ts.Rid] = rawTypeSpecRow; } else { rid = tablesHeap.TypeSpecTable.Add(rawTypeSpecRow); } typeSpecInfos.SetRid(ts, rid); AddCustomAttributes(Table.TypeSpec, rid, ts); AddCustomDebugInformationList(Table.TypeSpec, rid, ts); return rid; } protected override uint AddMemberRef(MemberRef mr) { return AddMemberRef(mr, forceIsOld: false); } private uint AddMemberRef(MemberRef mr, bool forceIsOld) { if (mr == null) { Error("MemberRef is null"); return 0u; } if (memberRefInfos.TryGetRid(mr, out var rid)) { return rid; } bool num = forceIsOld || (base.PreserveMemberRefRids && mod.ResolveMemberRef(mr.Rid) == mr); RawMemberRefRow rawMemberRefRow = new RawMemberRefRow(AddMemberRefParent(mr.Class), stringsHeap.Add(mr.Name), GetSignature(mr.Signature)); if (num) { rid = mr.Rid; tablesHeap.MemberRefTable[mr.Rid] = rawMemberRefRow; } else { rid = tablesHeap.MemberRefTable.Add(rawMemberRefRow); } memberRefInfos.Add(mr, rid); AddCustomAttributes(Table.MemberRef, rid, mr); AddCustomDebugInformationList(Table.MemberRef, rid, mr); return rid; } protected override uint AddStandAloneSig(StandAloneSig sas) { return AddStandAloneSig(sas, forceIsOld: false); } private uint AddStandAloneSig(StandAloneSig sas, bool forceIsOld) { if (sas == null) { Error("StandAloneSig is null"); return 0u; } if (standAloneSigInfos.TryGetRid(sas, out var rid)) { return rid; } bool num = forceIsOld || (base.PreserveStandAloneSigRids && mod.ResolveStandAloneSig(sas.Rid) == sas); RawStandAloneSigRow rawStandAloneSigRow = new RawStandAloneSigRow(GetSignature(sas.Signature)); if (num) { rid = sas.Rid; tablesHeap.StandAloneSigTable[sas.Rid] = rawStandAloneSigRow; } else { rid = tablesHeap.StandAloneSigTable.Add(rawStandAloneSigRow); } standAloneSigInfos.Add(sas, rid); AddCustomAttributes(Table.StandAloneSig, rid, sas); AddCustomDebugInformationList(Table.StandAloneSig, rid, sas); return rid; } public override MDToken GetToken(IList locals, uint origToken) { if (!base.PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) { return base.GetToken(locals, origToken); } uint num = AddStandAloneSig(new LocalSig(locals, dummy: false), origToken); if (num == 0) { return base.GetToken(locals, origToken); } return new MDToken(Table.StandAloneSig, num); } protected override uint AddStandAloneSig(MethodSig methodSig, uint origToken) { if (!base.PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) { return base.AddStandAloneSig(methodSig, origToken); } uint num = AddStandAloneSig(methodSig, origToken); if (num == 0) { return base.AddStandAloneSig(methodSig, origToken); } return num; } protected override uint AddStandAloneSig(FieldSig fieldSig, uint origToken) { if (!base.PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) { return base.AddStandAloneSig(fieldSig, origToken); } uint num = AddStandAloneSig(fieldSig, origToken); if (num == 0) { return base.AddStandAloneSig(fieldSig, origToken); } return num; } private uint AddStandAloneSig(CallingConventionSig callConvSig, uint origToken) { uint signature = GetSignature(callConvSig); if (callConvTokenToSignature.TryGetValue(origToken, out var value)) { if (signature == value) { return MDToken.ToRID(origToken); } Warning("Could not preserve StandAloneSig token 0x{0:X8}", origToken); return 0u; } uint rid = MDToken.ToRID(origToken); StandAloneSig standAloneSig = mod.ResolveStandAloneSig(rid); if (standAloneSigInfos.Exists(standAloneSig)) { Warning("StandAloneSig 0x{0:X8} already exists", origToken); return 0u; } CallingConventionSig signature2 = standAloneSig.Signature; try { standAloneSig.Signature = callConvSig; AddStandAloneSig(standAloneSig, forceIsOld: true); } finally { standAloneSig.Signature = signature2; } callConvTokenToSignature.Add(origToken, signature); return MDToken.ToRID(origToken); } private bool IsValidStandAloneSigToken(uint token) { if (MDToken.ToTable(token) != Table.StandAloneSig) { return false; } uint rid = MDToken.ToRID(token); return mod.TablesStream.StandAloneSigTable.IsValidRID(rid); } protected override uint AddMethodSpec(MethodSpec ms) { return AddMethodSpec(ms, forceIsOld: false); } private uint AddMethodSpec(MethodSpec ms, bool forceIsOld) { if (ms == null) { Error("MethodSpec is null"); return 0u; } if (methodSpecInfos.TryGetRid(ms, out var rid)) { return rid; } bool num = forceIsOld || (base.PreserveMethodSpecRids && mod.ResolveMethodSpec(ms.Rid) == ms); RawMethodSpecRow rawMethodSpecRow = new RawMethodSpecRow(AddMethodDefOrRef(ms.Method), GetSignature(ms.Instantiation)); if (num) { rid = ms.Rid; tablesHeap.MethodSpecTable[ms.Rid] = rawMethodSpecRow; } else { rid = tablesHeap.MethodSpecTable.Add(rawMethodSpecRow); } methodSpecInfos.Add(ms, rid); AddCustomAttributes(Table.MethodSpec, rid, ms); AddCustomDebugInformationList(Table.MethodSpec, rid, ms); return rid; } protected override void BeforeSortingCustomAttributes() { InitializeUninitializedTableRows(); } } public sealed class RelocDirectory : IChunk { private readonly struct RelocInfo { public readonly IChunk Chunk; public readonly uint OffsetOrRva; public RelocInfo(IChunk chunk, uint offset) { Chunk = chunk; OffsetOrRva = offset; } } private readonly Machine machine; private readonly List allRelocRvas = new List(); private readonly List> relocSections = new List>(); private bool isReadOnly; private FileOffset offset; private RVA rva; private uint totalSize; public FileOffset FileOffset => offset; public RVA RVA => rva; internal bool NeedsRelocSection => allRelocRvas.Count != 0; public RelocDirectory(Machine machine) { this.machine = machine; } public void SetOffset(FileOffset offset, RVA rva) { isReadOnly = true; this.offset = offset; this.rva = rva; List list = new List(allRelocRvas.Count); foreach (RelocInfo allRelocRva in allRelocRvas) { uint item = ((allRelocRva.Chunk == null) ? allRelocRva.OffsetOrRva : ((uint)(allRelocRva.Chunk.RVA + allRelocRva.OffsetOrRva))); list.Add(item); } list.Sort(); uint num = uint.MaxValue; List list2 = null; foreach (uint item2 in list) { uint num2 = item2 & 0xFFFFF000u; if (num2 != num) { num = num2; if (list2 != null) { totalSize += (uint)(8 + ((list2.Count + 1) & -2) * 2); } list2 = new List(); relocSections.Add(list2); } list2.Add(item2); } if (list2 != null) { totalSize += (uint)(8 + ((list2.Count + 1) & -2) * 2); } } public uint GetFileLength() { return totalSize; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { uint num = (machine.Is64Bit() ? 40960u : 12288u); foreach (List relocSection in relocSections) { writer.WriteUInt32(relocSection[0] & 0xFFFFF000u); writer.WriteUInt32((uint)(8 + ((relocSection.Count + 1) & -2) * 2)); foreach (uint item in relocSection) { writer.WriteUInt16((ushort)(num | (item & 0xFFF))); } if ((relocSection.Count & 1) != 0) { writer.WriteUInt16(0); } } } public void Add(RVA rva) { if (isReadOnly) { throw new InvalidOperationException("Can't add a relocation when the relocs section is read-only"); } allRelocRvas.Add(new RelocInfo(null, (uint)rva)); } public void Add(IChunk chunk, uint offset) { if (isReadOnly) { throw new InvalidOperationException("Can't add a relocation when the relocs section is read-only"); } allRelocRvas.Add(new RelocInfo(chunk, offset)); } } internal static class RoslynContentIdProvider { public static void GetContentId(byte[] hash, out Guid guid, out uint timestamp) { if (hash.Length < 20) { throw new InvalidOperationException(); } byte[] array = new byte[16]; Array.Copy(hash, 0, array, 0, array.Length); array[7] = (byte)((array[7] & 0xF) | 0x40); array[8] = (byte)((array[8] & 0x3F) | 0x80); guid = new Guid(array); timestamp = (uint)(int.MinValue | ((hash[19] << 24) | (hash[18] << 16) | (hash[17] << 8) | hash[16])); } } internal readonly struct SectionSizeInfo { public readonly uint length; public readonly uint characteristics; public SectionSizeInfo(uint length, uint characteristics) { this.length = length; this.characteristics = characteristics; } } internal readonly struct SectionSizes { public readonly uint SizeOfHeaders; public readonly uint SizeOfImage; public readonly uint BaseOfData; public readonly uint BaseOfCode; public readonly uint SizeOfCode; public readonly uint SizeOfInitdData; public readonly uint SizeOfUninitdData; public static uint GetSizeOfHeaders(uint fileAlignment, uint headerLen) { return Utils.AlignUp(headerLen, fileAlignment); } public SectionSizes(uint fileAlignment, uint sectionAlignment, uint headerLen, Func> getSectionSizeInfos) { SizeOfHeaders = GetSizeOfHeaders(fileAlignment, headerLen); SizeOfImage = Utils.AlignUp(SizeOfHeaders, sectionAlignment); BaseOfData = 0u; BaseOfCode = 0u; SizeOfCode = 0u; SizeOfInitdData = 0u; SizeOfUninitdData = 0u; foreach (SectionSizeInfo item in getSectionSizeInfos()) { uint num = Utils.AlignUp(item.length, sectionAlignment); uint num2 = Utils.AlignUp(item.length, fileAlignment); bool flag = (item.characteristics & 0x20) != 0; bool flag2 = (item.characteristics & 0x40) != 0; bool flag3 = (item.characteristics & 0x80) != 0; if (BaseOfCode == 0 && flag) { BaseOfCode = SizeOfImage; } if (BaseOfData == 0 && (flag2 || flag3)) { BaseOfData = SizeOfImage; } if (flag) { SizeOfCode += num2; } if (flag2) { SizeOfInitdData += num2; } if (flag3) { SizeOfUninitdData += num2; } SizeOfImage += num; } } } internal sealed class SerializerMethodContext { private readonly Dictionary toOffset; private readonly IWriterError helper; private MethodDef method; private CilBody body; private uint bodySize; private bool dictInitd; public bool HasBody => body != null; public SerializerMethodContext(IWriterError helper) { toOffset = new Dictionary(); this.helper = helper; } internal void SetBody(MethodDef method) { if (this.method != method) { toOffset.Clear(); this.method = method; body = method?.Body; dictInitd = false; } } public uint GetOffset(Instruction instr) { if (!dictInitd) { if (body == null) { return 0u; } InitializeDict(); } if (instr == null) { return bodySize; } if (toOffset.TryGetValue(instr, out var value)) { return value; } helper.Error("Couldn't find an instruction, maybe it was removed. It's still being referenced by some code or by the PDB"); return bodySize; } public bool IsSameMethod(MethodDef method) { return this.method == method; } private void InitializeDict() { uint num = 0u; IList instructions = body.Instructions; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; toOffset[instruction] = num; num += (uint)instruction.GetSize(); } bodySize = num; dictInitd = true; } } public interface ISignatureWriterHelper : IWriterError { uint ToEncodedToken(ITypeDefOrRef typeDefOrRef); } public struct SignatureWriter : IDisposable { private readonly ISignatureWriterHelper helper; private RecursionCounter recursionCounter; private readonly MemoryStream outStream; private readonly DataWriter writer; private readonly bool disposeStream; public static byte[] Write(ISignatureWriterHelper helper, TypeSig typeSig) { using SignatureWriter signatureWriter = new SignatureWriter(helper); signatureWriter.Write(typeSig); return signatureWriter.GetResult(); } internal static byte[] Write(ISignatureWriterHelper helper, TypeSig typeSig, DataWriterContext context) { using SignatureWriter signatureWriter = new SignatureWriter(helper, context); signatureWriter.Write(typeSig); return signatureWriter.GetResult(); } public static byte[] Write(ISignatureWriterHelper helper, CallingConventionSig sig) { using SignatureWriter signatureWriter = new SignatureWriter(helper); signatureWriter.Write(sig); return signatureWriter.GetResult(); } internal static byte[] Write(ISignatureWriterHelper helper, CallingConventionSig sig, DataWriterContext context) { using SignatureWriter signatureWriter = new SignatureWriter(helper, context); signatureWriter.Write(sig); return signatureWriter.GetResult(); } private SignatureWriter(ISignatureWriterHelper helper) { this.helper = helper; recursionCounter = default(RecursionCounter); outStream = new MemoryStream(); writer = new DataWriter(outStream); disposeStream = true; } private SignatureWriter(ISignatureWriterHelper helper, DataWriterContext context) { this.helper = helper; recursionCounter = default(RecursionCounter); outStream = context.OutStream; writer = context.Writer; disposeStream = false; outStream.SetLength(0L); outStream.Position = 0L; } private byte[] GetResult() { return outStream.ToArray(); } private uint WriteCompressedUInt32(uint value) { return writer.WriteCompressedUInt32(helper, value); } private int WriteCompressedInt32(int value) { return writer.WriteCompressedInt32(helper, value); } private void Write(TypeSig typeSig) { if (typeSig == null) { helper.Error("TypeSig is null"); writer.WriteByte(2); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); writer.WriteByte(2); return; } switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.Sentinel: writer.WriteByte((byte)typeSig.ElementType); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.SZArray: case ElementType.Pinned: writer.WriteByte((byte)typeSig.ElementType); Write(typeSig.Next); break; case ElementType.ValueType: case ElementType.Class: writer.WriteByte((byte)typeSig.ElementType); Write(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: writer.WriteByte((byte)typeSig.ElementType); WriteCompressedUInt32(((GenericSig)typeSig).Number); break; case ElementType.Array: { writer.WriteByte((byte)typeSig.ElementType); ArraySig arraySig = (ArraySig)typeSig; Write(arraySig.Next); WriteCompressedUInt32(arraySig.Rank); if (arraySig.Rank != 0) { uint num = WriteCompressedUInt32((uint)arraySig.Sizes.Count); for (uint num3 = 0u; num3 < num; num3++) { WriteCompressedUInt32(arraySig.Sizes[(int)num3]); } num = WriteCompressedUInt32((uint)arraySig.LowerBounds.Count); for (uint num4 = 0u; num4 < num; num4++) { WriteCompressedInt32(arraySig.LowerBounds[(int)num4]); } } break; } case ElementType.GenericInst: { writer.WriteByte((byte)typeSig.ElementType); GenericInstSig genericInstSig = (GenericInstSig)typeSig; Write(genericInstSig.GenericType); uint num = WriteCompressedUInt32((uint)genericInstSig.GenericArguments.Count); for (uint num2 = 0u; num2 < num; num2++) { Write(genericInstSig.GenericArguments[(int)num2]); } break; } case ElementType.ValueArray: writer.WriteByte((byte)typeSig.ElementType); Write(typeSig.Next); WriteCompressedUInt32((typeSig as ValueArraySig).Size); break; case ElementType.FnPtr: writer.WriteByte((byte)typeSig.ElementType); Write((typeSig as FnPtrSig).Signature); break; case ElementType.CModReqd: case ElementType.CModOpt: writer.WriteByte((byte)typeSig.ElementType); Write((typeSig as ModifierSig).Modifier); Write(typeSig.Next); break; case ElementType.Module: writer.WriteByte((byte)typeSig.ElementType); WriteCompressedUInt32((typeSig as ModuleSig).Index); Write(typeSig.Next); break; default: helper.Error("Unknown or unsupported element type"); writer.WriteByte(2); break; } recursionCounter.Decrement(); } private void Write(ITypeDefOrRef tdr) { if (tdr == null) { helper.Error("TypeDefOrRef is null"); WriteCompressedUInt32(0u); return; } uint num = helper.ToEncodedToken(tdr); if (num > 536870911) { helper.Error("Encoded token doesn't fit in 29 bits"); num = 0u; } WriteCompressedUInt32(num); } private void Write(CallingConventionSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } if (sig is MethodBaseSig sig2) { Write(sig2); } else if (sig is FieldSig sig3) { Write(sig3); } else if (sig is LocalSig sig4) { Write(sig4); } else if (sig is GenericInstMethodSig sig5) { Write(sig5); } else { helper.Error("Unknown calling convention sig"); writer.WriteByte((byte)sig.GetCallingConvention()); } recursionCounter.Decrement(); } private void Write(MethodBaseSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.WriteByte((byte)sig.GetCallingConvention()); if (sig.Generic) { WriteCompressedUInt32(sig.GenParamCount); } uint num = (uint)sig.Params.Count; if (sig.ParamsAfterSentinel != null) { num += (uint)sig.ParamsAfterSentinel.Count; } uint num2 = WriteCompressedUInt32(num); Write(sig.RetType); for (uint num3 = 0u; num3 < num2 && num3 < (uint)sig.Params.Count; num3++) { Write(sig.Params[(int)num3]); } if (sig.ParamsAfterSentinel != null && sig.ParamsAfterSentinel.Count > 0) { writer.WriteByte(65); uint num4 = 0u; uint num5 = (uint)sig.Params.Count; while (num4 < (uint)sig.ParamsAfterSentinel.Count && num5 < num2) { Write(sig.ParamsAfterSentinel[(int)num4]); num4++; num5++; } } recursionCounter.Decrement(); } private void Write(FieldSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.WriteByte((byte)sig.GetCallingConvention()); Write(sig.Type); recursionCounter.Decrement(); } private void Write(LocalSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.WriteByte((byte)sig.GetCallingConvention()); uint num = WriteCompressedUInt32((uint)sig.Locals.Count); if (num >= 65536) { helper.Error("Too many locals, max number of locals is 65535 (0xFFFF)"); } for (uint num2 = 0u; num2 < num; num2++) { Write(sig.Locals[(int)num2]); } recursionCounter.Decrement(); } private void Write(GenericInstMethodSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.WriteByte((byte)sig.GetCallingConvention()); uint num = WriteCompressedUInt32((uint)sig.GenericArguments.Count); for (uint num2 = 0u; num2 < num; num2++) { Write(sig.GenericArguments[(int)num2]); } recursionCounter.Decrement(); } public void Dispose() { if (disposeStream && outStream != null) { outStream.Dispose(); } } } public sealed class StartupStub : IChunk { private const StubType stubType = StubType.EntryPoint; private readonly RelocDirectory relocDirectory; private readonly Machine machine; private readonly CpuArch cpuArch; private readonly Action logError; private FileOffset offset; private RVA rva; public ImportDirectory ImportDirectory { get; set; } public PEHeaders PEHeaders { get; set; } public FileOffset FileOffset => offset; public RVA RVA => rva; public RVA EntryPointRVA => rva + ((cpuArch != null) ? cpuArch.GetStubCodeOffset(StubType.EntryPoint) : 0); internal bool Enable { get; set; } internal uint Alignment { get { if (cpuArch != null) { return cpuArch.GetStubAlignment(StubType.EntryPoint); } return 1u; } } internal StartupStub(RelocDirectory relocDirectory, Machine machine, Action logError) { this.relocDirectory = relocDirectory; this.machine = machine; this.logError = logError; CpuArch.TryGetCpuArch(machine, out cpuArch); } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; if (Enable) { if (cpuArch == null) { logError("The module needs an unmanaged entry point but the CPU architecture isn't supported: {0} (0x{1:X4})", new object[2] { machine, (ushort)machine }); } else { cpuArch.WriteStubRelocs(StubType.EntryPoint, relocDirectory, this, 0u); } } } public uint GetFileLength() { if (!Enable) { return 0u; } if (cpuArch == null) { return 0u; } return cpuArch.GetStubSize(StubType.EntryPoint); } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { if (Enable && cpuArch != null) { cpuArch.WriteStub(StubType.EntryPoint, writer, PEHeaders.ImageBase, (uint)rva, (uint)ImportDirectory.IatCorXxxMainRVA); } } } public sealed class StringsHeap : HeapBase, IOffsetHeap { private sealed class StringsOffsetInfo { public readonly UTF8String Value; public readonly uint StringsId; public uint StringsOffset; public StringsOffsetInfo(UTF8String value, uint stringsId) { Value = value; StringsId = stringsId; } public override string ToString() { return $"{StringsId:X8} {StringsOffset:X4} {Value.String}"; } } private readonly Dictionary cachedDict = new Dictionary(UTF8StringEqualityComparer.Instance); private readonly List cached = new List(); private uint nextOffset = 1u; private byte[] originalData; private Dictionary userRawData; private readonly Dictionary toStringsOffsetInfo = new Dictionary(UTF8StringEqualityComparer.Instance); private readonly Dictionary offsetIdToInfo = new Dictionary(); private readonly List stringsOffsetInfos = new List(); private const uint STRINGS_ID_FLAG = 2147483648u; private uint stringsId = 2147483648u; private static readonly Comparison Comparison_StringsOffsetInfoSorter = StringsOffsetInfoSorter; public override string Name => "#Strings"; public void Populate(StringsStream stringsStream) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); } if (originalData != null) { throw new InvalidOperationException("Can't call method twice"); } if (nextOffset != 1) { throw new InvalidOperationException("Add() has already been called"); } if (stringsStream != null && stringsStream.StreamLength != 0) { DataReader reader = stringsStream.CreateReader(); originalData = reader.ToArray(); nextOffset = (uint)originalData.Length; Populate(ref reader); } } private void Populate(ref DataReader reader) { reader.Position = 1u; while (reader.Position < reader.Length) { uint position = reader.Position; byte[] array = reader.TryReadBytesUntil(0); if (array == null) { break; } reader.ReadByte(); if (array.Length != 0) { UTF8String key = new UTF8String(array); if (!cachedDict.ContainsKey(key)) { cachedDict[key] = position; } } } } internal void AddOptimizedStringsAndSetReadOnly() { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); } SetReadOnly(); stringsOffsetInfos.Sort(Comparison_StringsOffsetInfoSorter); StringsOffsetInfo stringsOffsetInfo = null; foreach (StringsOffsetInfo stringsOffsetInfo2 in stringsOffsetInfos) { if (stringsOffsetInfo != null && EndsWith(stringsOffsetInfo.Value, stringsOffsetInfo2.Value)) { stringsOffsetInfo2.StringsOffset = stringsOffsetInfo.StringsOffset + (uint)(stringsOffsetInfo.Value.Data.Length - stringsOffsetInfo2.Value.Data.Length); } else { stringsOffsetInfo2.StringsOffset = AddToCache(stringsOffsetInfo2.Value); } stringsOffsetInfo = stringsOffsetInfo2; } } private static bool EndsWith(UTF8String s, UTF8String value) { byte[] data = s.Data; byte[] data2 = value.Data; int num = data.Length - data2.Length; if (num < 0) { return false; } for (int i = 0; i < data2.Length; i++) { if (data[num] != data2[i]) { return false; } num++; } return true; } private static int StringsOffsetInfoSorter(StringsOffsetInfo a, StringsOffsetInfo b) { byte[] data = a.Value.Data; byte[] data2 = b.Value.Data; int num = data.Length - 1; int num2 = data2.Length - 1; for (int num3 = Math.Min(data.Length, data2.Length); num3 > 0; num3--) { int num4 = data[num] - data2[num2]; if (num4 != 0) { return num4; } num--; num2--; } return data2.Length - data.Length; } public uint Add(UTF8String s) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); } if (UTF8String.IsNullOrEmpty(s)) { return 0u; } if (toStringsOffsetInfo.TryGetValue(s, out var value)) { return value.StringsId; } if (cachedDict.TryGetValue(s, out var value2)) { return value2; } if (Array.IndexOf(s.Data, (byte)0) >= 0) { throw new ArgumentException("Strings in the #Strings heap can't contain NUL bytes"); } value = new StringsOffsetInfo(s, stringsId++); toStringsOffsetInfo[s] = value; offsetIdToInfo[value.StringsId] = value; stringsOffsetInfos.Add(value); return value.StringsId; } public uint GetOffset(uint offsetId) { if (!isReadOnly) { throw new ModuleWriterException("This method can only be called after all strings have been added and this heap is read-only"); } if ((offsetId & 0x80000000u) == 0) { return offsetId; } if (offsetIdToInfo.TryGetValue(offsetId, out var value)) { return value.StringsOffset; } throw new ArgumentOutOfRangeException("offsetId"); } public uint Create(UTF8String s) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); } if (UTF8String.IsNullOrEmpty(s)) { s = UTF8String.Empty; } if (Array.IndexOf(s.Data, (byte)0) >= 0) { throw new ArgumentException("Strings in the #Strings heap can't contain NUL bytes"); } return AddToCache(s); } private uint AddToCache(UTF8String s) { cached.Add(s); uint result = (cachedDict[s] = nextOffset); nextOffset += (uint)(s.Data.Length + 1); return result; } public override uint GetRawLength() { return nextOffset; } protected override void WriteToImpl(DataWriter writer) { if (originalData != null) { writer.WriteBytes(originalData); } else { writer.WriteByte(0); } uint num = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (UTF8String item in cached) { if (userRawData != null && userRawData.TryGetValue(num, out var value)) { if (value.Length != item.Data.Length + 1) { throw new InvalidOperationException("Invalid length of raw data"); } writer.WriteBytes(value); } else { writer.WriteBytes(item.Data); writer.WriteByte(0); } num += (uint)(item.Data.Length + 1); } } public int GetRawDataSize(UTF8String data) { return data.Data.Length + 1; } public void SetRawData(uint offset, byte[] rawData) { if (userRawData == null) { userRawData = new Dictionary(); } userRawData[offset] = rawData ?? throw new ArgumentNullException("rawData"); } public IEnumerable> GetAllRawData() { uint offset = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (UTF8String item in cached) { byte[] rawData = new byte[item.Data.Length + 1]; Array.Copy(item.Data, rawData, item.Data.Length); yield return new KeyValuePair(offset, rawData); offset += (uint)rawData.Length; } } } public sealed class StrongNameSignature : IReuseChunk, IChunk { private FileOffset offset; private RVA rva; private int size; public FileOffset FileOffset => offset; public RVA RVA => rva; public StrongNameSignature(int size) { this.size = size; } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { return (uint)size <= origSize; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return (uint)size; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { writer.WriteZeroes(size); } } public sealed class TablesHeapOptions { public uint? Reserved1; public byte? MajorVersion; public byte? MinorVersion; public bool? UseENC; public bool? ForceBigColumns; public uint? ExtraData; public byte? Log2Rid; public bool? HasDeletedRows; public static TablesHeapOptions CreatePortablePdbV1_0() { return new TablesHeapOptions { Reserved1 = 0u, MajorVersion = (byte)2, MinorVersion = 0, UseENC = null, ExtraData = null, Log2Rid = null, HasDeletedRows = null }; } } public sealed class TablesHeap : IHeap, IChunk { [StructLayout(LayoutKind.Sequential, Size = 1)] private struct RawDummyRow { private sealed class RawDummyRowEqualityComparer : IEqualityComparer { public bool Equals(RawDummyRow x, RawDummyRow y) { throw new NotSupportedException(); } public int GetHashCode(RawDummyRow obj) { throw new NotSupportedException(); } } public static readonly IEqualityComparer Comparer = new RawDummyRowEqualityComparer(); } private uint length; private byte majorVersion; private byte minorVersion; private bool bigStrings; private bool bigGuid; private bool bigBlob; private bool hasDeletedRows; private readonly Metadata metadata; private readonly TablesHeapOptions options; private FileOffset offset; private RVA rva; public readonly MDTable ModuleTable = new MDTable(Table.Module, RawRowEqualityComparer.Instance); public readonly MDTable TypeRefTable = new MDTable(Table.TypeRef, RawRowEqualityComparer.Instance); public readonly MDTable TypeDefTable = new MDTable(Table.TypeDef, RawRowEqualityComparer.Instance); public readonly MDTable FieldPtrTable = new MDTable(Table.FieldPtr, RawRowEqualityComparer.Instance); public readonly MDTable FieldTable = new MDTable(Table.Field, RawRowEqualityComparer.Instance); public readonly MDTable MethodPtrTable = new MDTable(Table.MethodPtr, RawRowEqualityComparer.Instance); public readonly MDTable MethodTable = new MDTable(Table.Method, RawRowEqualityComparer.Instance); public readonly MDTable ParamPtrTable = new MDTable(Table.ParamPtr, RawRowEqualityComparer.Instance); public readonly MDTable ParamTable = new MDTable(Table.Param, RawRowEqualityComparer.Instance); public readonly MDTable InterfaceImplTable = new MDTable(Table.InterfaceImpl, RawRowEqualityComparer.Instance); public readonly MDTable MemberRefTable = new MDTable(Table.MemberRef, RawRowEqualityComparer.Instance); public readonly MDTable ConstantTable = new MDTable(Table.Constant, RawRowEqualityComparer.Instance); public readonly MDTable CustomAttributeTable = new MDTable(Table.CustomAttribute, RawRowEqualityComparer.Instance); public readonly MDTable FieldMarshalTable = new MDTable(Table.FieldMarshal, RawRowEqualityComparer.Instance); public readonly MDTable DeclSecurityTable = new MDTable(Table.DeclSecurity, RawRowEqualityComparer.Instance); public readonly MDTable ClassLayoutTable = new MDTable(Table.ClassLayout, RawRowEqualityComparer.Instance); public readonly MDTable FieldLayoutTable = new MDTable(Table.FieldLayout, RawRowEqualityComparer.Instance); public readonly MDTable StandAloneSigTable = new MDTable(Table.StandAloneSig, RawRowEqualityComparer.Instance); public readonly MDTable EventMapTable = new MDTable(Table.EventMap, RawRowEqualityComparer.Instance); public readonly MDTable EventPtrTable = new MDTable(Table.EventPtr, RawRowEqualityComparer.Instance); public readonly MDTable EventTable = new MDTable(Table.Event, RawRowEqualityComparer.Instance); public readonly MDTable PropertyMapTable = new MDTable(Table.PropertyMap, RawRowEqualityComparer.Instance); public readonly MDTable PropertyPtrTable = new MDTable(Table.PropertyPtr, RawRowEqualityComparer.Instance); public readonly MDTable PropertyTable = new MDTable(Table.Property, RawRowEqualityComparer.Instance); public readonly MDTable MethodSemanticsTable = new MDTable(Table.MethodSemantics, RawRowEqualityComparer.Instance); public readonly MDTable MethodImplTable = new MDTable(Table.MethodImpl, RawRowEqualityComparer.Instance); public readonly MDTable ModuleRefTable = new MDTable(Table.ModuleRef, RawRowEqualityComparer.Instance); public readonly MDTable TypeSpecTable = new MDTable(Table.TypeSpec, RawRowEqualityComparer.Instance); public readonly MDTable ImplMapTable = new MDTable(Table.ImplMap, RawRowEqualityComparer.Instance); public readonly MDTable FieldRVATable = new MDTable(Table.FieldRVA, RawRowEqualityComparer.Instance); public readonly MDTable ENCLogTable = new MDTable(Table.ENCLog, RawRowEqualityComparer.Instance); public readonly MDTable ENCMapTable = new MDTable(Table.ENCMap, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyTable = new MDTable(Table.Assembly, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyProcessorTable = new MDTable(Table.AssemblyProcessor, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyOSTable = new MDTable(Table.AssemblyOS, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefTable = new MDTable(Table.AssemblyRef, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefProcessorTable = new MDTable(Table.AssemblyRefProcessor, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefOSTable = new MDTable(Table.AssemblyRefOS, RawRowEqualityComparer.Instance); public readonly MDTable FileTable = new MDTable(Table.File, RawRowEqualityComparer.Instance); public readonly MDTable ExportedTypeTable = new MDTable(Table.ExportedType, RawRowEqualityComparer.Instance); public readonly MDTable ManifestResourceTable = new MDTable(Table.ManifestResource, RawRowEqualityComparer.Instance); public readonly MDTable NestedClassTable = new MDTable(Table.NestedClass, RawRowEqualityComparer.Instance); public readonly MDTable GenericParamTable = new MDTable(Table.GenericParam, RawRowEqualityComparer.Instance); public readonly MDTable MethodSpecTable = new MDTable(Table.MethodSpec, RawRowEqualityComparer.Instance); public readonly MDTable GenericParamConstraintTable = new MDTable(Table.GenericParamConstraint, RawRowEqualityComparer.Instance); public readonly MDTable DocumentTable = new MDTable(Table.Document, RawRowEqualityComparer.Instance); public readonly MDTable MethodDebugInformationTable = new MDTable(Table.MethodDebugInformation, RawRowEqualityComparer.Instance); public readonly MDTable LocalScopeTable = new MDTable(Table.LocalScope, RawRowEqualityComparer.Instance); public readonly MDTable LocalVariableTable = new MDTable(Table.LocalVariable, RawRowEqualityComparer.Instance); public readonly MDTable LocalConstantTable = new MDTable(Table.LocalConstant, RawRowEqualityComparer.Instance); public readonly MDTable ImportScopeTable = new MDTable(Table.ImportScope, RawRowEqualityComparer.Instance); public readonly MDTable StateMachineMethodTable = new MDTable(Table.StateMachineMethod, RawRowEqualityComparer.Instance); public readonly MDTable CustomDebugInformationTable = new MDTable(Table.CustomDebugInformation, RawRowEqualityComparer.Instance); public readonly IMDTable[] Tables; private uint[] systemTables; public FileOffset FileOffset => offset; public RVA RVA => rva; public string Name { get { if (!IsENC) { return "#~"; } return "#-"; } } public bool IsEmpty => false; public bool IsENC { get { if (options.UseENC.HasValue) { return options.UseENC.Value; } if (!hasDeletedRows && FieldPtrTable.IsEmpty && MethodPtrTable.IsEmpty && ParamPtrTable.IsEmpty && EventPtrTable.IsEmpty && PropertyPtrTable.IsEmpty && (InterfaceImplTable.IsEmpty || InterfaceImplTable.IsSorted) && (ConstantTable.IsEmpty || ConstantTable.IsSorted) && (CustomAttributeTable.IsEmpty || CustomAttributeTable.IsSorted) && (FieldMarshalTable.IsEmpty || FieldMarshalTable.IsSorted) && (DeclSecurityTable.IsEmpty || DeclSecurityTable.IsSorted) && (ClassLayoutTable.IsEmpty || ClassLayoutTable.IsSorted) && (FieldLayoutTable.IsEmpty || FieldLayoutTable.IsSorted) && (EventMapTable.IsEmpty || EventMapTable.IsSorted) && (PropertyMapTable.IsEmpty || PropertyMapTable.IsSorted) && (MethodSemanticsTable.IsEmpty || MethodSemanticsTable.IsSorted) && (MethodImplTable.IsEmpty || MethodImplTable.IsSorted) && (ImplMapTable.IsEmpty || ImplMapTable.IsSorted) && (FieldRVATable.IsEmpty || FieldRVATable.IsSorted) && (NestedClassTable.IsEmpty || NestedClassTable.IsSorted) && (GenericParamTable.IsEmpty || GenericParamTable.IsSorted)) { if (!GenericParamConstraintTable.IsEmpty) { return !GenericParamConstraintTable.IsSorted; } return false; } return true; } } public bool HasDeletedRows { get { return hasDeletedRows; } set { hasDeletedRows = value; } } public bool BigStrings { get { return bigStrings; } set { bigStrings = value; } } public bool BigGuid { get { return bigGuid; } set { bigGuid = value; } } public bool BigBlob { get { return bigBlob; } set { bigBlob = value; } } public TablesHeap(Metadata metadata, TablesHeapOptions options) { this.metadata = metadata; this.options = options ?? new TablesHeapOptions(); hasDeletedRows = this.options.HasDeletedRows == true; Tables = new IMDTable[56] { ModuleTable, TypeRefTable, TypeDefTable, FieldPtrTable, FieldTable, MethodPtrTable, MethodTable, ParamPtrTable, ParamTable, InterfaceImplTable, MemberRefTable, ConstantTable, CustomAttributeTable, FieldMarshalTable, DeclSecurityTable, ClassLayoutTable, FieldLayoutTable, StandAloneSigTable, EventMapTable, EventPtrTable, EventTable, PropertyMapTable, PropertyPtrTable, PropertyTable, MethodSemanticsTable, MethodImplTable, ModuleRefTable, TypeSpecTable, ImplMapTable, FieldRVATable, ENCLogTable, ENCMapTable, AssemblyTable, AssemblyProcessorTable, AssemblyOSTable, AssemblyRefTable, AssemblyRefProcessorTable, AssemblyRefOSTable, FileTable, ExportedTypeTable, ManifestResourceTable, NestedClassTable, GenericParamTable, MethodSpecTable, GenericParamConstraintTable, new MDTable((Table)45, RawDummyRow.Comparer), new MDTable((Table)46, RawDummyRow.Comparer), new MDTable((Table)47, RawDummyRow.Comparer), DocumentTable, MethodDebugInformationTable, LocalScopeTable, LocalVariableTable, LocalConstantTable, ImportScopeTable, StateMachineMethodTable, CustomDebugInformationTable }; } public void SetReadOnly() { IMDTable[] tables = Tables; for (int i = 0; i < tables.Length; i++) { tables[i].SetReadOnly(); } } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { if (length == 0) { CalculateLength(); } return Utils.AlignUp(length, 4u); } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void CalculateLength() { if (length != 0) { return; } SetReadOnly(); majorVersion = options.MajorVersion ?? 2; minorVersion = options.MinorVersion.GetValueOrDefault(); if (((majorVersion << 8) | minorVersion) <= 256 && (!GenericParamTable.IsEmpty || !MethodSpecTable.IsEmpty || !GenericParamConstraintTable.IsEmpty)) { throw new ModuleWriterException("Tables heap version <= v1.0 but generic tables are not empty"); } DotNetTableSizes dotNetTableSizes = new DotNetTableSizes(); TableInfo[] array = dotNetTableSizes.CreateTables(majorVersion, minorVersion); uint[] rowCounts = GetRowCounts(); uint[] array2 = rowCounts; if (systemTables != null) { array2 = new uint[rowCounts.Length]; for (int i = 0; i < rowCounts.Length; i++) { if (DotNetTableSizes.IsSystemTable((Table)i)) { array2[i] = systemTables[i]; } else { array2[i] = rowCounts[i]; } } } dotNetTableSizes.InitializeSizes(bigStrings, bigGuid, bigBlob, rowCounts, array2, options.ForceBigColumns == true); for (int j = 0; j < Tables.Length; j++) { Tables[j].TableInfo = array[j]; } length = 24u; IMDTable[] tables = Tables; foreach (IMDTable iMDTable in tables) { if (!iMDTable.IsEmpty) { length += (uint)(4 + iMDTable.TableInfo.RowSize * iMDTable.Rows); } } if (options.ExtraData.HasValue) { length += 4u; } } private uint[] GetRowCounts() { uint[] array = new uint[Tables.Length]; for (int i = 0; i < array.Length; i++) { array[i] = (uint)Tables[i].Rows; } return array; } internal void GetSystemTableRows(out ulong mask, uint[] tables) { if (tables.Length != 64) { throw new InvalidOperationException(); } ulong validMask = GetValidMask(); ulong num = 1uL; mask = 0uL; int num2 = 0; while (num2 < 64) { if (DotNetTableSizes.IsSystemTable((Table)num2)) { if ((validMask & num) != 0L) { tables[num2] = (uint)Tables[num2].Rows; mask |= num; } else { tables[num2] = 0u; } } else { tables[num2] = 0u; } num2++; num <<= 1; } } internal void SetSystemTableRows(uint[] systemTables) { this.systemTables = (uint[])systemTables.Clone(); } public void WriteTo(DataWriter writer) { writer.WriteUInt32(options.Reserved1.GetValueOrDefault()); writer.WriteByte(majorVersion); writer.WriteByte(minorVersion); writer.WriteByte((byte)GetMDStreamFlags()); writer.WriteByte(GetLog2Rid()); writer.WriteUInt64(GetValidMask()); writer.WriteUInt64(GetSortedMask()); IMDTable[] tables = Tables; foreach (IMDTable iMDTable in tables) { if (!iMDTable.IsEmpty) { writer.WriteInt32(iMDTable.Rows); } } if (options.ExtraData.HasValue) { writer.WriteUInt32(options.ExtraData.Value); } writer.Write(metadata, ModuleTable); writer.Write(metadata, TypeRefTable); writer.Write(metadata, TypeDefTable); writer.Write(metadata, FieldPtrTable); writer.Write(metadata, FieldTable); writer.Write(metadata, MethodPtrTable); writer.Write(metadata, MethodTable); writer.Write(metadata, ParamPtrTable); writer.Write(metadata, ParamTable); writer.Write(metadata, InterfaceImplTable); writer.Write(metadata, MemberRefTable); writer.Write(metadata, ConstantTable); writer.Write(metadata, CustomAttributeTable); writer.Write(metadata, FieldMarshalTable); writer.Write(metadata, DeclSecurityTable); writer.Write(metadata, ClassLayoutTable); writer.Write(metadata, FieldLayoutTable); writer.Write(metadata, StandAloneSigTable); writer.Write(metadata, EventMapTable); writer.Write(metadata, EventPtrTable); writer.Write(metadata, EventTable); writer.Write(metadata, PropertyMapTable); writer.Write(metadata, PropertyPtrTable); writer.Write(metadata, PropertyTable); writer.Write(metadata, MethodSemanticsTable); writer.Write(metadata, MethodImplTable); writer.Write(metadata, ModuleRefTable); writer.Write(metadata, TypeSpecTable); writer.Write(metadata, ImplMapTable); writer.Write(metadata, FieldRVATable); writer.Write(metadata, ENCLogTable); writer.Write(metadata, ENCMapTable); writer.Write(metadata, AssemblyTable); writer.Write(metadata, AssemblyProcessorTable); writer.Write(metadata, AssemblyOSTable); writer.Write(metadata, AssemblyRefTable); writer.Write(metadata, AssemblyRefProcessorTable); writer.Write(metadata, AssemblyRefOSTable); writer.Write(metadata, FileTable); writer.Write(metadata, ExportedTypeTable); writer.Write(metadata, ManifestResourceTable); writer.Write(metadata, NestedClassTable); writer.Write(metadata, GenericParamTable); writer.Write(metadata, MethodSpecTable); writer.Write(metadata, GenericParamConstraintTable); writer.Write(metadata, DocumentTable); writer.Write(metadata, MethodDebugInformationTable); writer.Write(metadata, LocalScopeTable); writer.Write(metadata, LocalVariableTable); writer.Write(metadata, LocalConstantTable); writer.Write(metadata, ImportScopeTable); writer.Write(metadata, StateMachineMethodTable); writer.Write(metadata, CustomDebugInformationTable); writer.WriteZeroes((int)(Utils.AlignUp(length, 4u) - length)); } private MDStreamFlags GetMDStreamFlags() { MDStreamFlags mDStreamFlags = (MDStreamFlags)0; if (bigStrings) { mDStreamFlags |= MDStreamFlags.BigStrings; } if (bigGuid) { mDStreamFlags |= MDStreamFlags.BigGUID; } if (bigBlob) { mDStreamFlags |= MDStreamFlags.BigBlob; } if (options.ExtraData.HasValue) { mDStreamFlags |= MDStreamFlags.ExtraData; } if (hasDeletedRows) { mDStreamFlags |= MDStreamFlags.HasDelete; } return mDStreamFlags; } private byte GetLog2Rid() { return options.Log2Rid ?? 1; } private ulong GetValidMask() { ulong num = 0uL; IMDTable[] tables = Tables; foreach (IMDTable iMDTable in tables) { if (!iMDTable.IsEmpty) { num |= (ulong)(1L << (int)iMDTable.Table); } } return num; } private ulong GetSortedMask() { ulong num = 0uL; IMDTable[] tables = Tables; foreach (IMDTable iMDTable in tables) { if (iMDTable.IsSorted) { num |= (ulong)(1L << (int)iMDTable.Table); } } return num; } public override string ToString() { return Name; } } public sealed class UniqueChunkList : ChunkListBase where T : class, IChunk { private sealed class DescendingStableComparer : IComparer> { internal static readonly DescendingStableComparer Instance = new DescendingStableComparer(); public int Compare(KeyValuePair x, KeyValuePair y) { int num = -x.Value.alignment.CompareTo(y.Value.alignment); if (num != 0) { return num; } return x.Key.CompareTo(y.Key); } } private Dictionary dict; public UniqueChunkList() : this((IEqualityComparer)EqualityComparer.Default) { } public UniqueChunkList(IEqualityComparer chunkComparer) { chunks = new List(); dict = new Dictionary(new ElemEqualityComparer(chunkComparer)); } public override void SetOffset(FileOffset offset, RVA rva) { dict = null; base.SetOffset(offset, rva); } public T Add(T chunk, uint alignment) { if (setOffsetCalled) { throw new InvalidOperationException("SetOffset() has already been called"); } if (chunk == null) { return null; } Elem elem = new Elem(chunk, alignment); if (dict.TryGetValue(elem, out var value)) { return value.chunk; } dict[elem] = elem; chunks.Add(elem); return elem.chunk; } public override uint CalculateAlignment() { uint result = base.CalculateAlignment(); KeyValuePair[] array = new KeyValuePair[chunks.Count]; for (int i = 0; i < chunks.Count; i++) { array[i] = new KeyValuePair(i, chunks[i]); } Array.Sort(array, DescendingStableComparer.Instance); for (int j = 0; j < array.Length; j++) { chunks[j] = array[j].Value; } return result; } } public sealed class USHeap : HeapBase, IOffsetHeap { private readonly Dictionary cachedDict = new Dictionary(StringComparer.Ordinal); private readonly List cached = new List(); private uint nextOffset = 1u; private byte[] originalData; private Dictionary userRawData; public override string Name => "#US"; public void Populate(USStream usStream) { if (originalData != null) { throw new InvalidOperationException("Can't call method twice"); } if (nextOffset != 1) { throw new InvalidOperationException("Add() has already been called"); } if (usStream != null && usStream.StreamLength != 0) { DataReader reader = usStream.CreateReader(); originalData = reader.ToArray(); nextOffset = (uint)originalData.Length; Populate(ref reader); } } private void Populate(ref DataReader reader) { reader.Position = 1u; while (reader.Position < reader.Length) { uint position = reader.Position; if (!reader.TryReadCompressedUInt32(out var value)) { if (position == reader.Position) { reader.Position++; } } else if (value != 0 && (ulong)((long)reader.Position + (long)value) <= (ulong)reader.Length) { int chars = (int)value / 2; string key = reader.ReadUtf16String(chars); if ((value & 1) != 0) { reader.ReadByte(); } if (!cachedDict.ContainsKey(key)) { cachedDict[key] = position; } } } } public uint Add(string s) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #US when it's read-only"); } if (s == null) { s = string.Empty; } if (cachedDict.TryGetValue(s, out var value)) { return value; } return AddToCache(s); } public uint Create(string s) { if (isReadOnly) { throw new ModuleWriterException("Trying to modify #US when it's read-only"); } return AddToCache(s ?? string.Empty); } private uint AddToCache(string s) { cached.Add(s); uint num = (cachedDict[s] = nextOffset); nextOffset += (uint)GetRawDataSize(s); if (num > 16777215) { throw new ModuleWriterException("#US heap is too big"); } return num; } public override uint GetRawLength() { return nextOffset; } protected override void WriteToImpl(DataWriter writer) { if (originalData != null) { writer.WriteBytes(originalData); } else { writer.WriteByte(0); } uint num = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (string item in cached) { int rawDataSize = GetRawDataSize(item); if (userRawData != null && userRawData.TryGetValue(num, out var value)) { if (value.Length != rawDataSize) { throw new InvalidOperationException("Invalid length of raw data"); } writer.WriteBytes(value); } else { WriteString(writer, item); } num += (uint)rawDataSize; } } private void WriteString(DataWriter writer, string s) { writer.WriteCompressedUInt32((uint)(s.Length * 2 + 1)); byte value = 0; foreach (ushort num in s) { writer.WriteUInt16(num); if (num > 255 || (1 <= num && num <= 8) || (14 <= num && num <= 31) || num == 39 || num == 45 || num == 127) { value = 1; } } writer.WriteByte(value); } public int GetRawDataSize(string data) { return DataWriter.GetCompressedUInt32Length((uint)(data.Length * 2 + 1)) + data.Length * 2 + 1; } public void SetRawData(uint offset, byte[] rawData) { if (userRawData == null) { userRawData = new Dictionary(); } userRawData[offset] = rawData ?? throw new ArgumentNullException("rawData"); } public IEnumerable> GetAllRawData() { MemoryStream memStream = new MemoryStream(); DataWriter writer = new DataWriter(memStream); uint offset = ((originalData == null) ? 1u : ((uint)originalData.Length)); foreach (string item in cached) { memStream.Position = 0L; memStream.SetLength(0L); WriteString(writer, item); yield return new KeyValuePair(offset, memStream.ToArray()); offset += (uint)(int)memStream.Length; } } } public sealed class Win32ResourcesChunk : IReuseChunk, IChunk { private readonly Win32Resources win32Resources; private FileOffset offset; private RVA rva; private uint length; private readonly Dictionary dirDict = new Dictionary(); private readonly List dirList = new List(); private readonly Dictionary dataHeaderDict = new Dictionary(); private readonly List dataHeaderList = new List(); private readonly Dictionary stringsDict = new Dictionary(StringComparer.Ordinal); private readonly List stringsList = new List(); private readonly Dictionary dataDict = new Dictionary(); private readonly List dataList = new List(); private const uint RESOURCE_DIR_ALIGNMENT = 4u; private const uint RESOURCE_DATA_HEADER_ALIGNMENT = 4u; private const uint RESOURCE_STRING_ALIGNMENT = 2u; private const uint RESOURCE_DATA_ALIGNMENT = 4u; public FileOffset FileOffset => offset; public RVA RVA => rva; public Win32ResourcesChunk(Win32Resources win32Resources) { this.win32Resources = win32Resources; } public bool GetFileOffsetAndRvaOf(ResourceDirectoryEntry dirEntry, out FileOffset fileOffset, out RVA rva) { if (dirEntry is ResourceDirectory dir) { return GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); } if (dirEntry is ResourceData dataHeader) { return GetFileOffsetAndRvaOf(dataHeader, out fileOffset, out rva); } fileOffset = (FileOffset)0u; rva = (RVA)0u; return false; } public FileOffset GetFileOffset(ResourceDirectoryEntry dirEntry) { GetFileOffsetAndRvaOf(dirEntry, out var fileOffset, out var _); return fileOffset; } public RVA GetRVA(ResourceDirectoryEntry dirEntry) { GetFileOffsetAndRvaOf(dirEntry, out var _, out var result); return result; } public bool GetFileOffsetAndRvaOf(ResourceDirectory dir, out FileOffset fileOffset, out RVA rva) { if (dir == null || !dirDict.TryGetValue(dir, out var value)) { fileOffset = (FileOffset)0u; rva = (RVA)0u; return false; } fileOffset = offset + value; rva = this.rva + value; return true; } public FileOffset GetFileOffset(ResourceDirectory dir) { GetFileOffsetAndRvaOf(dir, out var fileOffset, out var _); return fileOffset; } public RVA GetRVA(ResourceDirectory dir) { GetFileOffsetAndRvaOf(dir, out var _, out var result); return result; } public bool GetFileOffsetAndRvaOf(ResourceData dataHeader, out FileOffset fileOffset, out RVA rva) { if (dataHeader == null || !dataHeaderDict.TryGetValue(dataHeader, out var value)) { fileOffset = (FileOffset)0u; rva = (RVA)0u; return false; } fileOffset = offset + value; rva = this.rva + value; return true; } public FileOffset GetFileOffset(ResourceData dataHeader) { GetFileOffsetAndRvaOf(dataHeader, out var fileOffset, out var _); return fileOffset; } public RVA GetRVA(ResourceData dataHeader) { GetFileOffsetAndRvaOf(dataHeader, out var _, out var result); return result; } public bool GetFileOffsetAndRvaOf(string name, out FileOffset fileOffset, out RVA rva) { if (name == null || !stringsDict.TryGetValue(name, out var value)) { fileOffset = (FileOffset)0u; rva = (RVA)0u; return false; } fileOffset = offset + value; rva = this.rva + value; return true; } public FileOffset GetFileOffset(string name) { GetFileOffsetAndRvaOf(name, out var fileOffset, out var _); return fileOffset; } public RVA GetRVA(string name) { GetFileOffsetAndRvaOf(name, out var _, out var result); return result; } bool IReuseChunk.CanReuse(RVA origRva, uint origSize) { if (rva == (RVA)0u) { throw new InvalidOperationException(); } return length <= origSize; } internal bool CheckValidOffset(FileOffset offset) { GetMaxAlignment(offset, out var error); return error == null; } private static uint GetMaxAlignment(FileOffset offset, out string error) { error = null; uint val = 1u; val = Math.Max(val, 4u); val = Math.Max(val, 4u); val = Math.Max(val, 2u); val = Math.Max(val, 4u); if (((uint)offset & (val - 1)) != 0) { error = $"Win32 resources section isn't {val}-byte aligned"; } else if (val > 8) { error = "maxAlignment > DEFAULT_WIN32_RESOURCES_ALIGNMENT"; } return val; } public void SetOffset(FileOffset offset, RVA rva) { bool flag = this.offset == (FileOffset)0u; this.offset = offset; this.rva = rva; if (win32Resources == null) { return; } if (!flag) { dirDict.Clear(); dirList.Clear(); dataHeaderDict.Clear(); dataHeaderList.Clear(); stringsDict.Clear(); stringsList.Clear(); dataDict.Clear(); dataList.Clear(); } FindDirectoryEntries(); uint num = 0u; GetMaxAlignment(offset, out var error); if (error != null) { throw new ModuleWriterException(error); } foreach (ResourceDirectory dir in dirList) { num = Utils.AlignUp(num, 4u); dirDict[dir] = num; if (dir != dirList[0]) { AddString(dir.Name); } num += (uint)(16 + (dir.Directories.Count + dir.Data.Count) * 8); } foreach (ResourceData dataHeader in dataHeaderList) { num = Utils.AlignUp(num, 4u); dataHeaderDict[dataHeader] = num; AddString(dataHeader.Name); AddData(dataHeader); num += 16; } foreach (string strings in stringsList) { num = Utils.AlignUp(num, 2u); stringsDict[strings] = num; num += (uint)(2 + strings.Length * 2); } foreach (ResourceData data in dataList) { num = Utils.AlignUp(num, 4u); dataDict[data] = num; num += data.CreateReader().Length; } length = num; } private void AddData(ResourceData data) { if (!dataDict.ContainsKey(data)) { dataList.Add(data); dataDict.Add(data, 0u); } } private void AddString(ResourceName name) { if (name.HasName && !stringsDict.ContainsKey(name.Name)) { stringsList.Add(name.Name); stringsDict.Add(name.Name, 0u); } } private void FindDirectoryEntries() { FindDirectoryEntries(win32Resources.Root); } private void FindDirectoryEntries(ResourceDirectory dir) { if (dirDict.ContainsKey(dir)) { return; } dirList.Add(dir); dirDict[dir] = 0u; IList directories = dir.Directories; int count = directories.Count; for (int i = 0; i < count; i++) { FindDirectoryEntries(directories[i]); } IList data = dir.Data; count = data.Count; for (int j = 0; j < count; j++) { ResourceData resourceData = data[j]; if (!dataHeaderDict.ContainsKey(resourceData)) { dataHeaderList.Add(resourceData); dataHeaderDict[resourceData] = 0u; } } } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public uint CalculateAlignment() { return 0u; } public void WriteTo(DataWriter writer) { uint num = 0u; foreach (ResourceDirectory dir in dirList) { uint num2 = Utils.AlignUp(num, 4u) - num; writer.WriteZeroes((int)num2); num += num2; if (dirDict[dir] != num) { throw new ModuleWriterException("Invalid Win32 resource directory offset"); } num += WriteTo(writer, dir); } foreach (ResourceData dataHeader in dataHeaderList) { uint num3 = Utils.AlignUp(num, 4u) - num; writer.WriteZeroes((int)num3); num += num3; if (dataHeaderDict[dataHeader] != num) { throw new ModuleWriterException("Invalid Win32 resource data header offset"); } num += WriteTo(writer, dataHeader); } foreach (string strings in stringsList) { uint num4 = Utils.AlignUp(num, 2u) - num; writer.WriteZeroes((int)num4); num += num4; if (stringsDict[strings] != num) { throw new ModuleWriterException("Invalid Win32 resource string offset"); } byte[] bytes = Encoding.Unicode.GetBytes(strings); if (bytes.Length / 2 > 65535) { throw new ModuleWriterException("Win32 resource entry name is too long"); } writer.WriteUInt16((ushort)(bytes.Length / 2)); writer.WriteBytes(bytes); num += (uint)(2 + bytes.Length); } byte[] dataBuffer = new byte[8192]; foreach (ResourceData data in dataList) { uint num5 = Utils.AlignUp(num, 4u) - num; writer.WriteZeroes((int)num5); num += num5; if (dataDict[data] != num) { throw new ModuleWriterException("Invalid Win32 resource data offset"); } DataReader dataReader = data.CreateReader(); num += dataReader.BytesLeft; dataReader.CopyTo(writer, dataBuffer); } } private uint WriteTo(DataWriter writer, ResourceDirectory dir) { writer.WriteUInt32(dir.Characteristics); writer.WriteUInt32(dir.TimeDateStamp); writer.WriteUInt16(dir.MajorVersion); writer.WriteUInt16(dir.MinorVersion); GetNamedAndIds(dir, out var named, out var ids); if (named.Count > 65535 || ids.Count > 65535) { throw new ModuleWriterException("Too many named/id Win32 resource entries"); } writer.WriteUInt16((ushort)named.Count); writer.WriteUInt16((ushort)ids.Count); named.Sort((ResourceDirectoryEntry a, ResourceDirectoryEntry b) => a.Name.Name.ToUpperInvariant().CompareTo(b.Name.Name.ToUpperInvariant())); ids.Sort((ResourceDirectoryEntry a, ResourceDirectoryEntry b) => a.Name.Id.CompareTo(b.Name.Id)); foreach (ResourceDirectoryEntry item in named) { writer.WriteUInt32(0x80000000u | stringsDict[item.Name.Name]); writer.WriteUInt32(GetDirectoryEntryOffset(item)); } foreach (ResourceDirectoryEntry item2 in ids) { writer.WriteInt32(item2.Name.Id); writer.WriteUInt32(GetDirectoryEntryOffset(item2)); } return (uint)(16 + (named.Count + ids.Count) * 8); } private uint GetDirectoryEntryOffset(ResourceDirectoryEntry e) { if (e is ResourceData) { return dataHeaderDict[(ResourceData)e]; } return 0x80000000u | dirDict[(ResourceDirectory)e]; } private static void GetNamedAndIds(ResourceDirectory dir, out List named, out List ids) { named = new List(); ids = new List(); IList directories = dir.Directories; int count = directories.Count; for (int i = 0; i < count; i++) { ResourceDirectory resourceDirectory = directories[i]; if (resourceDirectory.Name.HasId) { ids.Add(resourceDirectory); } else { named.Add(resourceDirectory); } } IList data = dir.Data; count = data.Count; for (int j = 0; j < count; j++) { ResourceData resourceData = data[j]; if (resourceData.Name.HasId) { ids.Add(resourceData); } else { named.Add(resourceData); } } } private uint WriteTo(DataWriter writer, ResourceData dataHeader) { writer.WriteUInt32((uint)(rva + dataDict[dataHeader])); writer.WriteUInt32(dataHeader.CreateReader().Length); writer.WriteUInt32(dataHeader.CodePage); writer.WriteUInt32(dataHeader.Reserved); return 16u; } } internal static class WriterUtils { public static uint WriteCompressedUInt32(this DataWriter writer, IWriterError helper, uint value) { if (value > 536870911) { helper.Error("UInt32 value is too big and can't be compressed"); value = 536870911u; } writer.WriteCompressedUInt32(value); return value; } public static int WriteCompressedInt32(this DataWriter writer, IWriterError helper, int value) { if (value < -268435456) { helper.Error("Int32 value is too small and can't be compressed."); value = -268435456; } else if (value > 268435455) { helper.Error("Int32 value is too big and can't be compressed."); value = 268435455; } writer.WriteCompressedInt32(value); return value; } public static void Write(this DataWriter writer, IWriterError helper, UTF8String s) { if (UTF8String.IsNull(s)) { helper.Error("UTF8String is null"); s = UTF8String.Empty; } writer.WriteCompressedUInt32(helper, (uint)s.DataLength); writer.WriteBytes(s.Data); } } } namespace dnlib.DotNet.Resources { public sealed class BuiltInResourceData : IResourceData, IFileSection { private readonly ResourceTypeCode code; private readonly object data; public object Data => data; public ResourceTypeCode Code => code; public FileOffset StartOffset { get; set; } public FileOffset EndOffset { get; set; } public BuiltInResourceData(ResourceTypeCode code, object data) { this.code = code; this.data = data; } public void WriteData(ResourceBinaryWriter writer, IFormatter formatter) { switch (code) { case ResourceTypeCode.String: writer.Write((string)data); break; case ResourceTypeCode.Boolean: writer.Write((bool)data); break; case ResourceTypeCode.Char: writer.Write((ushort)(char)data); break; case ResourceTypeCode.Byte: writer.Write((byte)data); break; case ResourceTypeCode.SByte: writer.Write((sbyte)data); break; case ResourceTypeCode.Int16: writer.Write((short)data); break; case ResourceTypeCode.UInt16: writer.Write((ushort)data); break; case ResourceTypeCode.Int32: writer.Write((int)data); break; case ResourceTypeCode.UInt32: writer.Write((uint)data); break; case ResourceTypeCode.Int64: writer.Write((long)data); break; case ResourceTypeCode.UInt64: writer.Write((ulong)data); break; case ResourceTypeCode.Single: writer.Write((float)data); break; case ResourceTypeCode.Double: writer.Write((double)data); break; case ResourceTypeCode.Decimal: writer.Write((decimal)data); break; case ResourceTypeCode.DateTime: { DateTime dateTime = (DateTime)data; if (writer.FormatVersion == 1) { writer.Write(dateTime.Ticks); } else { writer.Write(dateTime.ToBinary()); } break; } case ResourceTypeCode.TimeSpan: writer.Write(((TimeSpan)data).Ticks); break; case ResourceTypeCode.ByteArray: case ResourceTypeCode.Stream: { if (writer.FormatVersion == 1) { throw new NotSupportedException($"{code} is not supported in format version 1 resources"); } byte[] array = (byte[])data; writer.Write(array.Length); writer.Write(array); break; } default: throw new InvalidOperationException("Unknown resource type code"); case ResourceTypeCode.Null: break; } } public override string ToString() { switch (code) { case ResourceTypeCode.Null: return "null"; case ResourceTypeCode.String: case ResourceTypeCode.Boolean: case ResourceTypeCode.Char: case ResourceTypeCode.Byte: case ResourceTypeCode.SByte: case ResourceTypeCode.Int16: case ResourceTypeCode.UInt16: case ResourceTypeCode.Int32: case ResourceTypeCode.UInt32: case ResourceTypeCode.Int64: case ResourceTypeCode.UInt64: case ResourceTypeCode.Single: case ResourceTypeCode.Double: case ResourceTypeCode.Decimal: case ResourceTypeCode.DateTime: case ResourceTypeCode.TimeSpan: return $"{code}: '{data}'"; case ResourceTypeCode.ByteArray: case ResourceTypeCode.Stream: if (data is byte[] array) { return $"{code}: Length: {array.Length}"; } return $"{code}: '{data}'"; default: return $"{code}: '{data}'"; } } } public interface IResourceData : IFileSection { ResourceTypeCode Code { get; } new FileOffset StartOffset { get; set; } new FileOffset EndOffset { get; set; } void WriteData(ResourceBinaryWriter writer, IFormatter formatter); } public sealed class ResourceBinaryWriter : BinaryWriter { public int FormatVersion { get; internal set; } public ResourceReaderType ReaderType { get; internal set; } internal ResourceBinaryWriter(Stream stream) : base(stream) { } public new void Write7BitEncodedInt(int value) { base.Write7BitEncodedInt(value); } } public class ResourceDataFactory { private sealed class MyBinder : SerializationBinder { public class OkException : Exception { public string AssemblyName { get; set; } public string TypeName { get; set; } } public override Type BindToType(string assemblyName, string typeName) { throw new OkException { AssemblyName = assemblyName, TypeName = typeName }; } } private readonly ModuleDef module; private readonly ModuleDefMD moduleMD; private readonly Dictionary dict = new Dictionary(StringComparer.Ordinal); private readonly Dictionary asmNameToAsmFullName = new Dictionary(StringComparer.Ordinal); protected ModuleDef Module => module; public int Count => dict.Count; public ResourceDataFactory(ModuleDef module) { this.module = module; moduleMD = module as ModuleDefMD; } public BuiltInResourceData CreateNull() { return new BuiltInResourceData(ResourceTypeCode.Null, null); } public BuiltInResourceData Create(string value) { return new BuiltInResourceData(ResourceTypeCode.String, value); } public BuiltInResourceData Create(bool value) { return new BuiltInResourceData(ResourceTypeCode.Boolean, value); } public BuiltInResourceData Create(char value) { return new BuiltInResourceData(ResourceTypeCode.Char, value); } public BuiltInResourceData Create(byte value) { return new BuiltInResourceData(ResourceTypeCode.Byte, value); } public BuiltInResourceData Create(sbyte value) { return new BuiltInResourceData(ResourceTypeCode.SByte, value); } public BuiltInResourceData Create(short value) { return new BuiltInResourceData(ResourceTypeCode.Int16, value); } public BuiltInResourceData Create(ushort value) { return new BuiltInResourceData(ResourceTypeCode.UInt16, value); } public BuiltInResourceData Create(int value) { return new BuiltInResourceData(ResourceTypeCode.Int32, value); } public BuiltInResourceData Create(uint value) { return new BuiltInResourceData(ResourceTypeCode.UInt32, value); } public BuiltInResourceData Create(long value) { return new BuiltInResourceData(ResourceTypeCode.Int64, value); } public BuiltInResourceData Create(ulong value) { return new BuiltInResourceData(ResourceTypeCode.UInt64, value); } public BuiltInResourceData Create(float value) { return new BuiltInResourceData(ResourceTypeCode.Single, value); } public BuiltInResourceData Create(double value) { return new BuiltInResourceData(ResourceTypeCode.Double, value); } public BuiltInResourceData Create(decimal value) { return new BuiltInResourceData(ResourceTypeCode.Decimal, value); } public BuiltInResourceData Create(DateTime value) { return new BuiltInResourceData(ResourceTypeCode.DateTime, value); } public BuiltInResourceData Create(TimeSpan value) { return new BuiltInResourceData(ResourceTypeCode.TimeSpan, value); } public BuiltInResourceData Create(byte[] value) { return new BuiltInResourceData(ResourceTypeCode.ByteArray, value); } public BuiltInResourceData CreateStream(byte[] value) { return new BuiltInResourceData(ResourceTypeCode.Stream, value); } public BinaryResourceData CreateSerialized(byte[] value, SerializationFormat format, UserResourceType type) { return new BinaryResourceData(CreateUserResourceType(type.Name, useFullName: true), value, format); } public BinaryResourceData CreateBinaryFormatterSerialized(byte[] value) { if (!GetSerializedTypeAndAssemblyName(value, out var assemblyName, out var typeName)) { throw new ApplicationException("Could not get serialized type name"); } string fullName = typeName + ", " + assemblyName; return new BinaryResourceData(CreateUserResourceType(fullName), value, SerializationFormat.BinaryFormatter); } private bool GetSerializedTypeAndAssemblyName(byte[] value, out string assemblyName, out string typeName) { try { BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Binder = new MyBinder(); binaryFormatter.Deserialize(new MemoryStream(value)); } catch (MyBinder.OkException ex) { assemblyName = ex.AssemblyName; typeName = ex.TypeName; return true; } catch { } assemblyName = null; typeName = null; return false; } public UserResourceType CreateBuiltinResourceType(ResourceTypeCode typeCode) { string text = typeCode switch { ResourceTypeCode.String => "System.String", ResourceTypeCode.Boolean => "System.Boolean", ResourceTypeCode.Char => "System.Char", ResourceTypeCode.Byte => "System.Byte", ResourceTypeCode.SByte => "System.SByte", ResourceTypeCode.Int16 => "System.Int16", ResourceTypeCode.UInt16 => "System.UInt16", ResourceTypeCode.Int32 => "System.Int32", ResourceTypeCode.UInt32 => "System.UInt32", ResourceTypeCode.Int64 => "System.Int64", ResourceTypeCode.UInt64 => "System.UInt64", ResourceTypeCode.Single => "System.Single", ResourceTypeCode.Double => "System.Double", ResourceTypeCode.Decimal => "System.Decimal", ResourceTypeCode.DateTime => "System.DateTime", ResourceTypeCode.TimeSpan => "System.TimeSpan", _ => null, }; if (text == null) { return null; } return CreateUserResourceType(text + ", " + module.CorLibTypes.AssemblyRef.FullName, useFullName: true); } public UserResourceType CreateUserResourceType(string fullName) { return CreateUserResourceType(fullName, useFullName: false); } private UserResourceType CreateUserResourceType(string fullName, bool useFullName) { if (dict.TryGetValue(fullName, out var value)) { return value; } string text = (useFullName ? fullName : GetRealTypeFullName(fullName)); value = new UserResourceType(text, (ResourceTypeCode)(64 + dict.Count)); dict[fullName] = value; dict[text] = value; return value; } private string GetRealTypeFullName(string fullName) { ITypeDefOrRef typeDefOrRef = TypeNameParser.ParseReflection(module, fullName, null); if (typeDefOrRef == null) { return fullName; } IAssembly definitionAssembly = typeDefOrRef.DefinitionAssembly; if (definitionAssembly == null) { return fullName; } string result = fullName; string realAssemblyName = GetRealAssemblyName(definitionAssembly); if (!string.IsNullOrEmpty(realAssemblyName)) { result = typeDefOrRef.ReflectionFullName + ", " + realAssemblyName; } return result; } private string GetRealAssemblyName(IAssembly asm) { string fullName = asm.FullName; if (!asmNameToAsmFullName.TryGetValue(fullName, out var value)) { value = (asmNameToAsmFullName[fullName] = TryGetRealAssemblyName(asm)); } return value; } private string TryGetRealAssemblyName(IAssembly asm) { UTF8String name = asm.Name; if (name == module.CorLibTypes.AssemblyRef.Name) { return module.CorLibTypes.AssemblyRef.FullName; } if (moduleMD != null) { AssemblyRef assemblyRef = moduleMD.GetAssemblyRef(name); if (assemblyRef != null) { return assemblyRef.FullName; } } return GetAssemblyFullName(name); } protected virtual string GetAssemblyFullName(string simpleName) { return null; } public List GetSortedTypes() { List list = new List(dict.Values); list.Sort((UserResourceType a, UserResourceType b) => ((int)a.Code).CompareTo((int)b.Code)); return list; } } public sealed class ResourceElement { public string Name { get; set; } public IResourceData ResourceData { get; set; } public override string ToString() { return $"N: {Name}, V: {ResourceData}"; } } public sealed class ResourceElementSet { internal const string DeserializingResourceReaderTypeNameRegex = "^System\\.Resources\\.Extensions\\.DeserializingResourceReader,\\s*System\\.Resources\\.Extensions"; internal const string ResourceReaderTypeNameRegex = "^System\\.Resources\\.ResourceReader,\\s*mscorlib"; private readonly Dictionary dict = new Dictionary(StringComparer.Ordinal); public string ResourceReaderTypeName { get; } public string ResourceSetTypeName { get; } public ResourceReaderType ReaderType { get; } public int FormatVersion { get; internal set; } public int Count => dict.Count; public IEnumerable ResourceElements => dict.Values; internal ResourceElementSet(string resourceReaderTypeName, string resourceSetTypeName, ResourceReaderType readerType) { ResourceReaderTypeName = resourceReaderTypeName; ResourceSetTypeName = resourceSetTypeName; ReaderType = readerType; } public void Add(ResourceElement elem) { dict[elem.Name] = elem; } public static ResourceElementSet CreateForDeserializingResourceReader(Version extensionAssemblyVersion, int formatVersion = 2) { string text = "System.Resources.Extensions, Version=" + extensionAssemblyVersion.ToString(4) + ", Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"; return new ResourceElementSet("System.Resources.Extensions.DeserializingResourceReader, " + text, "System.Resources.Extensions.RuntimeResourceSet, " + text, ResourceReaderType.DeserializingResourceReader) { FormatVersion = formatVersion }; } public static ResourceElementSet CreateForResourceReader(ModuleDef module, int formatVersion = 2) { string text = ((!(module.CorLibTypes.AssemblyRef.Name == "mscorlib")) ? "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" : module.CorLibTypes.AssemblyRef.FullName); return new ResourceElementSet("System.Resources.ResourceReader, " + text, "System.Resources.RuntimeResourceSet", ResourceReaderType.ResourceReader) { FormatVersion = formatVersion }; } public static ResourceElementSet CreateForResourceReader(Version mscorlibVersion, int formatVersion = 2) { return new ResourceElementSet("System.Resources.ResourceReader, mscorlib, Version=" + mscorlibVersion.ToString(4) + ", Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Resources.RuntimeResourceSet", ResourceReaderType.ResourceReader) { FormatVersion = formatVersion }; } public ResourceElementSet Clone() { return new ResourceElementSet(ResourceReaderTypeName, ResourceSetTypeName, ReaderType) { FormatVersion = FormatVersion }; } } [Serializable] public sealed class ResourceReaderException : Exception { public ResourceReaderException() { } public ResourceReaderException(string msg) : base(msg) { } public ResourceReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public delegate IResourceData CreateResourceDataDelegate(ResourceDataFactory resourceDataFactory, UserResourceType type, byte[] serializedData, SerializationFormat format); public struct ResourceReader { private sealed class ResourceInfo { public readonly string name; public readonly long offset; public ResourceInfo(string name, long offset) { this.name = name; this.offset = offset; } public override string ToString() { return $"{offset:X8} - {name}"; } } private DataReader reader; private readonly uint baseFileOffset; private readonly ResourceDataFactory resourceDataFactory; private readonly CreateResourceDataDelegate createResourceDataDelegate; private ResourceReader(ResourceDataFactory resourceDataFactory, ref DataReader reader, CreateResourceDataDelegate createResourceDataDelegate) { this.reader = reader; this.resourceDataFactory = resourceDataFactory; this.createResourceDataDelegate = createResourceDataDelegate; baseFileOffset = reader.StartOffset; } public static bool CouldBeResourcesFile(DataReader reader) { if (reader.CanRead(4u)) { return reader.ReadUInt32() == 3203386062u; } return false; } public static ResourceElementSet Read(ModuleDef module, DataReader reader) { return Read(module, reader, null); } public static ResourceElementSet Read(ModuleDef module, DataReader reader, CreateResourceDataDelegate createResourceDataDelegate) { return Read(new ResourceDataFactory(module), reader, createResourceDataDelegate); } public static ResourceElementSet Read(ResourceDataFactory resourceDataFactory, DataReader reader, CreateResourceDataDelegate createResourceDataDelegate) { return new ResourceReader(resourceDataFactory, ref reader, createResourceDataDelegate).Read(); } private ResourceElementSet Read() { uint num = reader.ReadUInt32(); if (num != 3203386062u) { throw new ResourceReaderException($"Invalid resource sig: {num:X8}"); } ResourceElementSet resourceElementSet = ReadHeader(); if (resourceElementSet == null) { throw new ResourceReaderException("Invalid resource reader"); } resourceElementSet.FormatVersion = reader.ReadInt32(); if (resourceElementSet.FormatVersion != 2 && resourceElementSet.FormatVersion != 1) { throw new ResourceReaderException($"Invalid resource version: {resourceElementSet.FormatVersion}"); } int num2 = reader.ReadInt32(); if (num2 < 0) { throw new ResourceReaderException($"Invalid number of resources: {num2}"); } int num3 = reader.ReadInt32(); if (num3 < 0) { throw new ResourceReaderException($"Invalid number of user types: {num3}"); } List list = new List(); for (int i = 0; i < num3; i++) { list.Add(new UserResourceType(reader.ReadSerializedString(), (ResourceTypeCode)(64 + i))); } reader.Position = (reader.Position + 7) & 0xFFFFFFF8u; int[] array = new int[num2]; for (int j = 0; j < num2; j++) { array[j] = reader.ReadInt32(); } int[] array2 = new int[num2]; for (int k = 0; k < num2; k++) { array2[k] = reader.ReadInt32(); } _ = reader.Position; long num4 = reader.ReadInt32(); long num5 = reader.Position; long num6 = reader.Length; List list2 = new List(num2); for (int l = 0; l < num2; l++) { reader.Position = (uint)(num5 + array2[l]); string name = reader.ReadSerializedString(Encoding.Unicode); long offset = num4 + reader.ReadInt32(); list2.Add(new ResourceInfo(name, offset)); } list2.Sort((ResourceInfo a, ResourceInfo b) => a.offset.CompareTo(b.offset)); for (int num7 = 0; num7 < list2.Count; num7++) { ResourceInfo resourceInfo = list2[num7]; ResourceElement resourceElement = new ResourceElement(); resourceElement.Name = resourceInfo.name; reader.Position = (uint)resourceInfo.offset; int size = (int)(((num7 == list2.Count - 1) ? num6 : list2[num7 + 1].offset) - resourceInfo.offset); resourceElement.ResourceData = ((resourceElementSet.FormatVersion == 1) ? ReadResourceDataV1(list, resourceElementSet.ReaderType, size) : ReadResourceDataV2(list, resourceElementSet.ReaderType, size)); resourceElement.ResourceData.StartOffset = (FileOffset)(baseFileOffset + (uint)(int)resourceInfo.offset); resourceElement.ResourceData.EndOffset = (FileOffset)(baseFileOffset + reader.Position); resourceElementSet.Add(resourceElement); } return resourceElementSet; } private IResourceData ReadResourceDataV2(List userTypes, ResourceReaderType readerType, int size) { uint endPos = reader.Position + (uint)size; uint num = reader.Read7BitEncodedUInt32(); switch ((ResourceTypeCode)num) { case ResourceTypeCode.Null: return resourceDataFactory.CreateNull(); case ResourceTypeCode.String: return resourceDataFactory.Create(reader.ReadSerializedString()); case ResourceTypeCode.Boolean: return resourceDataFactory.Create(reader.ReadBoolean()); case ResourceTypeCode.Char: return resourceDataFactory.Create(reader.ReadChar()); case ResourceTypeCode.Byte: return resourceDataFactory.Create(reader.ReadByte()); case ResourceTypeCode.SByte: return resourceDataFactory.Create(reader.ReadSByte()); case ResourceTypeCode.Int16: return resourceDataFactory.Create(reader.ReadInt16()); case ResourceTypeCode.UInt16: return resourceDataFactory.Create(reader.ReadUInt16()); case ResourceTypeCode.Int32: return resourceDataFactory.Create(reader.ReadInt32()); case ResourceTypeCode.UInt32: return resourceDataFactory.Create(reader.ReadUInt32()); case ResourceTypeCode.Int64: return resourceDataFactory.Create(reader.ReadInt64()); case ResourceTypeCode.UInt64: return resourceDataFactory.Create(reader.ReadUInt64()); case ResourceTypeCode.Single: return resourceDataFactory.Create(reader.ReadSingle()); case ResourceTypeCode.Double: return resourceDataFactory.Create(reader.ReadDouble()); case ResourceTypeCode.Decimal: return resourceDataFactory.Create(reader.ReadDecimal()); case ResourceTypeCode.DateTime: return resourceDataFactory.Create(DateTime.FromBinary(reader.ReadInt64())); case ResourceTypeCode.TimeSpan: return resourceDataFactory.Create(new TimeSpan(reader.ReadInt64())); case ResourceTypeCode.ByteArray: return resourceDataFactory.Create(reader.ReadBytes(reader.ReadInt32())); case ResourceTypeCode.Stream: return resourceDataFactory.CreateStream(reader.ReadBytes(reader.ReadInt32())); default: { int num2 = (int)(num - 64); if (num2 < 0 || num2 >= userTypes.Count) { throw new ResourceReaderException($"Invalid resource data code: {num}"); } return ReadSerializedObject(endPos, readerType, userTypes[num2]); } } } private IResourceData ReadResourceDataV1(List userTypes, ResourceReaderType readerType, int size) { uint endPos = reader.Position + (uint)size; int num = reader.Read7BitEncodedInt32(); if (num == -1) { return resourceDataFactory.CreateNull(); } if (num < 0 || num >= userTypes.Count) { throw new ResourceReaderException($"Invalid resource type index: {num}"); } UserResourceType userResourceType = userTypes[num]; int num2 = userResourceType.Name.IndexOf(','); return ((num2 == -1) ? userResourceType.Name : userResourceType.Name.Remove(num2)) switch { "System.String" => resourceDataFactory.Create(reader.ReadSerializedString()), "System.Int32" => resourceDataFactory.Create(reader.ReadInt32()), "System.Byte" => resourceDataFactory.Create(reader.ReadByte()), "System.SByte" => resourceDataFactory.Create(reader.ReadSByte()), "System.Int16" => resourceDataFactory.Create(reader.ReadInt16()), "System.Int64" => resourceDataFactory.Create(reader.ReadInt64()), "System.UInt16" => resourceDataFactory.Create(reader.ReadUInt16()), "System.UInt32" => resourceDataFactory.Create(reader.ReadUInt32()), "System.UInt64" => resourceDataFactory.Create(reader.ReadUInt64()), "System.Single" => resourceDataFactory.Create(reader.ReadSingle()), "System.Double" => resourceDataFactory.Create(reader.ReadDouble()), "System.DateTime" => resourceDataFactory.Create(new DateTime(reader.ReadInt64())), "System.TimeSpan" => resourceDataFactory.Create(new TimeSpan(reader.ReadInt64())), "System.Decimal" => resourceDataFactory.Create(reader.ReadDecimal()), _ => ReadSerializedObject(endPos, readerType, userResourceType), }; } private IResourceData ReadSerializedObject(uint endPos, ResourceReaderType readerType, UserResourceType type) { switch (readerType) { case ResourceReaderType.ResourceReader: { byte[] array = reader.ReadBytes((int)(endPos - reader.Position)); IResourceData resourceData = createResourceDataDelegate?.Invoke(resourceDataFactory, type, array, SerializationFormat.BinaryFormatter); return resourceData ?? resourceDataFactory.CreateSerialized(array, SerializationFormat.BinaryFormatter, type); } case ResourceReaderType.DeserializingResourceReader: { SerializationFormat serializationFormat = (SerializationFormat)reader.Read7BitEncodedInt32(); if (serializationFormat < SerializationFormat.BinaryFormatter || serializationFormat > SerializationFormat.ActivatorStream) { throw new ResourceReaderException($"Invalid serialization format: {serializationFormat}"); } int length = reader.Read7BitEncodedInt32(); byte[] array = reader.ReadBytes(length); IResourceData resourceData = createResourceDataDelegate?.Invoke(resourceDataFactory, type, array, serializationFormat); return resourceData ?? resourceDataFactory.CreateSerialized(array, serializationFormat, type); } default: throw new ResourceReaderException($"Invalid reader type: {readerType}"); } } private ResourceElementSet ReadHeader() { int num = reader.ReadInt32(); if (num != 1) { throw new ResourceReaderException($"Invalid or unsupported header version: {num}"); } int num2 = reader.ReadInt32(); if (num2 < 0) { throw new ResourceReaderException($"Invalid header size: {num2:X8}"); } string text = reader.ReadSerializedString(); string resourceSetTypeName = reader.ReadSerializedString(); ResourceReaderType readerType; if (Regex.IsMatch(text, "^System\\.Resources\\.ResourceReader,\\s*mscorlib")) { readerType = ResourceReaderType.ResourceReader; } else { if (!Regex.IsMatch(text, "^System\\.Resources\\.Extensions\\.DeserializingResourceReader,\\s*System\\.Resources\\.Extensions")) { return null; } readerType = ResourceReaderType.DeserializingResourceReader; } return new ResourceElementSet(text, resourceSetTypeName, readerType); } } public enum ResourceReaderType { ResourceReader, DeserializingResourceReader } public enum ResourceTypeCode { Null = 0, String = 1, Boolean = 2, Char = 3, Byte = 4, SByte = 5, Int16 = 6, UInt16 = 7, Int32 = 8, UInt32 = 9, Int64 = 10, UInt64 = 11, Single = 12, Double = 13, Decimal = 14, DateTime = 15, TimeSpan = 16, ByteArray = 32, Stream = 33, UserTypes = 64 } public sealed class ResourceWriter { private ModuleDef module; private BinaryWriter writer; private ResourceElementSet resources; private ResourceDataFactory typeCreator; private Dictionary dataToNewType = new Dictionary(); private ResourceWriter(ModuleDef module, ResourceDataFactory typeCreator, Stream stream, ResourceElementSet resources) { this.module = module; this.typeCreator = typeCreator; writer = new BinaryWriter(stream); this.resources = resources; } public static void Write(ModuleDef module, Stream stream, ResourceElementSet resources) { new ResourceWriter(module, new ResourceDataFactory(module), stream, resources).Write(); } public static void Write(ModuleDef module, ResourceDataFactory typeCreator, Stream stream, ResourceElementSet resources) { new ResourceWriter(module, typeCreator, stream, resources).Write(); } private void Write() { if (resources.FormatVersion != 1 && resources.FormatVersion != 2) { throw new ArgumentException($"Invalid format version: {resources.FormatVersion}", "resources"); } InitializeUserTypes(resources.FormatVersion); writer.Write(3203386062u); writer.Write(1); WriteReaderType(); writer.Write(resources.FormatVersion); writer.Write(resources.Count); writer.Write(typeCreator.Count); foreach (UserResourceType sortedType in typeCreator.GetSortedTypes()) { writer.Write(sortedType.Name); } int num = 8 - ((int)writer.BaseStream.Position & 7); if (num != 8) { for (int i = 0; i < num; i++) { writer.Write((byte)88); } } MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.Unicode); MemoryStream memoryStream2 = new MemoryStream(); ResourceBinaryWriter resourceBinaryWriter = new ResourceBinaryWriter(memoryStream2) { FormatVersion = resources.FormatVersion, ReaderType = resources.ReaderType }; int[] array = new int[resources.Count]; int[] array2 = new int[resources.Count]; BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); int num2 = 0; foreach (ResourceElement resourceElement in resources.ResourceElements) { array2[num2] = (int)binaryWriter.BaseStream.Position; array[num2] = (int)Hash(resourceElement.Name); num2++; binaryWriter.Write(resourceElement.Name); binaryWriter.Write((int)resourceBinaryWriter.BaseStream.Position); WriteData(resourceBinaryWriter, resourceElement, formatter); } Array.Sort(array, array2); int[] array3 = array; foreach (int value in array3) { writer.Write(value); } array3 = array2; foreach (int value2 in array3) { writer.Write(value2); } writer.Write((int)writer.BaseStream.Position + (int)memoryStream.Length + 4); writer.Write(memoryStream.ToArray()); writer.Write(memoryStream2.ToArray()); } private void WriteData(ResourceBinaryWriter writer, ResourceElement info, IFormatter formatter) { ResourceTypeCode resourceType = GetResourceType(info.ResourceData, writer.FormatVersion); writer.Write7BitEncodedInt((int)resourceType); info.ResourceData.WriteData(writer, formatter); } private ResourceTypeCode GetResourceType(IResourceData data, int formatVersion) { if (formatVersion == 1) { if (data.Code == ResourceTypeCode.Null) { return (ResourceTypeCode)(-1); } return dataToNewType[data].Code - 64; } if (data is BuiltInResourceData) { return data.Code; } return dataToNewType[data].Code; } private static uint Hash(string key) { uint num = 5381u; foreach (char c in key) { num = ((num << 5) + num) ^ c; } return num; } private void InitializeUserTypes(int formatVersion) { foreach (ResourceElement resourceElement in resources.ResourceElements) { UserResourceType userResourceType; if (formatVersion == 1 && resourceElement.ResourceData is BuiltInResourceData builtInResourceData) { userResourceType = typeCreator.CreateBuiltinResourceType(builtInResourceData.Code); if (userResourceType == null) { throw new NotSupportedException($"Unsupported resource type: {builtInResourceData.Code} in format version 1 resource"); } } else { if (!(resourceElement.ResourceData is UserResourceData userResourceData)) { continue; } userResourceType = typeCreator.CreateUserResourceType(userResourceData.TypeName); } dataToNewType[resourceElement.ResourceData] = userResourceType; } } private void WriteReaderType() { MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); if (resources.ResourceReaderTypeName != null && resources.ResourceSetTypeName != null) { binaryWriter.Write(resources.ResourceReaderTypeName); binaryWriter.Write(resources.ResourceSetTypeName); } else { string mscorlibFullname = GetMscorlibFullname(); binaryWriter.Write("System.Resources.ResourceReader, " + mscorlibFullname); binaryWriter.Write("System.Resources.RuntimeResourceSet"); } writer.Write((int)memoryStream.Position); writer.Write(memoryStream.ToArray()); } private string GetMscorlibFullname() { if (module.CorLibTypes.AssemblyRef.Name == "mscorlib") { return module.CorLibTypes.AssemblyRef.FullName; } return "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; } } public abstract class UserResourceData : IResourceData, IFileSection { private readonly UserResourceType type; public string TypeName => type.Name; public ResourceTypeCode Code => type.Code; public FileOffset StartOffset { get; set; } public FileOffset EndOffset { get; set; } public UserResourceData(UserResourceType type) { this.type = type; } public abstract void WriteData(ResourceBinaryWriter writer, IFormatter formatter); } public sealed class BinaryResourceData : UserResourceData { private byte[] data; private SerializationFormat format; public byte[] Data => data; public SerializationFormat Format => format; public BinaryResourceData(UserResourceType type, byte[] data, SerializationFormat format) : base(type) { this.data = data; this.format = format; } public override void WriteData(ResourceBinaryWriter writer, IFormatter formatter) { if (writer.ReaderType == ResourceReaderType.ResourceReader && format != SerializationFormat.BinaryFormatter) { throw new NotSupportedException($"Unsupported serialization format: {format} for {writer.ReaderType}"); } if (writer.ReaderType == ResourceReaderType.DeserializingResourceReader) { writer.Write7BitEncodedInt((int)format); writer.Write7BitEncodedInt(data.Length); } writer.Write(data); } public override string ToString() { return $"Binary: Length: {data.Length} Format: {format}"; } } public enum SerializationFormat { BinaryFormatter = 1, TypeConverterByteArray, TypeConverterString, ActivatorStream } public sealed class UserResourceType { private readonly string name; private readonly ResourceTypeCode code; public string Name => name; public ResourceTypeCode Code => code; public UserResourceType(string name, ResourceTypeCode code) { this.name = name; this.code = code; } public override string ToString() { return $"{code:X2} {name}"; } } } namespace dnlib.DotNet.Pdb { public static class CustomDebugInfoGuids { public static readonly Guid AsyncMethodSteppingInformationBlob = new Guid("54FD2AC5-E925-401A-9C2A-F94F171072F8"); public static readonly Guid DefaultNamespace = new Guid("58B2EAB6-209F-4E4E-A22C-B2D0F910C782"); public static readonly Guid DynamicLocalVariables = new Guid("83C563C4-B4F3-47D5-B824-BA5441477EA8"); public static readonly Guid EmbeddedSource = new Guid("0E8A571B-6926-466E-B4AD-8AB04611F5FE"); public static readonly Guid EncLambdaAndClosureMap = new Guid("A643004C-0240-496F-A783-30D64F4979DE"); public static readonly Guid EncLocalSlotMap = new Guid("755F52A8-91C5-45BE-B4B8-209571E552BD"); public static readonly Guid SourceLink = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A"); public static readonly Guid StateMachineHoistedLocalScopes = new Guid("6DA9A61E-F8C7-4874-BE62-68BC5630DF71"); public static readonly Guid TupleElementNames = new Guid("ED9FDF71-8879-4747-8ED3-FE5EDE3CE710"); public static readonly Guid CompilationMetadataReferences = new Guid("7E4D4708-096E-4C5C-AEDA-CB10BA6A740D"); public static readonly Guid CompilationOptions = new Guid("B5FEEC05-8CD0-4A83-96DA-466284BB4BD8"); public static readonly Guid TypeDefinitionDocuments = new Guid("932E74BC-DBA9-4478-8D46-0F32A7BAB3D3"); public static readonly Guid EncStateMachineStateMap = new Guid("8B78CD68-2EDE-420B-980B-E15884B8AAA3"); public static readonly Guid PrimaryConstructorInformationBlob = new Guid("9D40ACE1-C703-4D0E-BF41-7243060A8FB5"); } internal static class DataReaderFactoryUtils { public static DataReaderFactory TryCreateDataReaderFactory(string filename) { try { if (!File.Exists(filename)) { return null; } return ByteArrayDataReaderFactory.Create(File.ReadAllBytes(filename), filename); } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (SecurityException) { } return null; } } public struct IMAGE_DEBUG_DIRECTORY { public uint Characteristics; public uint TimeDateStamp; public ushort MajorVersion; public ushort MinorVersion; public ImageDebugType Type; public uint SizeOfData; public uint AddressOfRawData; public uint PointerToRawData; } public sealed class PdbConstant : IHasCustomDebugInformation { private string name; private TypeSig type; private object value; private readonly IList customDebugInfos = new List(); public string Name { get { return name; } set { name = value; } } public TypeSig Type { get { return type; } set { type = value; } } public object Value { get { return value; } set { this.value = value; } } public int HasCustomDebugInformationTag => 25; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos => customDebugInfos; public PdbConstant() { } public PdbConstant(string name, TypeSig type, object value) { this.name = name; this.type = type; this.value = value; } public override string ToString() { TypeSig typeSig = Type; object obj = Value; string text = ((typeSig == null) ? "" : typeSig.ToString()); string text2 = ((obj == null) ? "null" : $"{obj} ({obj.GetType().FullName})"); return $"{text} {Name} = {text2}"; } } public enum PdbCustomDebugInfoKind { UsingGroups = 0, ForwardMethodInfo = 1, ForwardModuleInfo = 2, StateMachineHoistedLocalScopes = 3, StateMachineTypeName = 4, DynamicLocals = 5, EditAndContinueLocalSlotMap = 6, EditAndContinueLambdaMap = 7, TupleElementNames = 8, Unknown = int.MinValue, TupleElementNames_PortablePdb = -2147483647, DefaultNamespace = -2147483646, DynamicLocalVariables = -2147483645, EmbeddedSource = -2147483644, SourceLink = -2147483643, SourceServer = -2147483642, AsyncMethod = -2147483641, IteratorMethod = -2147483640, CompilationMetadataReferences = -2147483639, CompilationOptions = -2147483638, TypeDefinitionDocuments = -2147483637, EditAndContinueStateMachineStateMap = -2147483636, PrimaryConstructorInformationBlob = -2147483635 } public abstract class PdbCustomDebugInfo { public abstract PdbCustomDebugInfoKind Kind { get; } public abstract Guid Guid { get; } } public sealed class PdbUnknownCustomDebugInfo : PdbCustomDebugInfo { private readonly PdbCustomDebugInfoKind kind; private readonly Guid guid; private readonly byte[] data; public override PdbCustomDebugInfoKind Kind => kind; public override Guid Guid => guid; public byte[] Data => data; public PdbUnknownCustomDebugInfo(PdbCustomDebugInfoKind kind, byte[] data) { this.kind = kind; this.data = data ?? throw new ArgumentNullException("data"); guid = Guid.Empty; } public PdbUnknownCustomDebugInfo(Guid guid, byte[] data) { kind = PdbCustomDebugInfoKind.Unknown; this.data = data ?? throw new ArgumentNullException("data"); this.guid = guid; } } public sealed class PdbUsingGroupsCustomDebugInfo : PdbCustomDebugInfo { private readonly IList usingCounts; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.UsingGroups; public override Guid Guid => Guid.Empty; public IList UsingCounts => usingCounts; public PdbUsingGroupsCustomDebugInfo() { usingCounts = new List(); } public PdbUsingGroupsCustomDebugInfo(int capacity) { usingCounts = new List(capacity); } } public sealed class PdbForwardMethodInfoCustomDebugInfo : PdbCustomDebugInfo { private IMethodDefOrRef method; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.ForwardMethodInfo; public override Guid Guid => Guid.Empty; public IMethodDefOrRef Method { get { return method; } set { method = value; } } public PdbForwardMethodInfoCustomDebugInfo() { } public PdbForwardMethodInfoCustomDebugInfo(IMethodDefOrRef method) { this.method = method; } } public sealed class PdbForwardModuleInfoCustomDebugInfo : PdbCustomDebugInfo { private IMethodDefOrRef method; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.ForwardModuleInfo; public override Guid Guid => Guid.Empty; public IMethodDefOrRef Method { get { return method; } set { method = value; } } public PdbForwardModuleInfoCustomDebugInfo() { } public PdbForwardModuleInfoCustomDebugInfo(IMethodDefOrRef method) { this.method = method; } } public struct StateMachineHoistedLocalScope { public Instruction Start; public Instruction End; public readonly bool IsSynthesizedLocal { get { if (Start == null) { return End == null; } return false; } } public StateMachineHoistedLocalScope(Instruction start, Instruction end) { Start = start; End = end; } } public sealed class PdbStateMachineHoistedLocalScopesCustomDebugInfo : PdbCustomDebugInfo { private readonly IList scopes; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes; public override Guid Guid => CustomDebugInfoGuids.StateMachineHoistedLocalScopes; public IList Scopes => scopes; public PdbStateMachineHoistedLocalScopesCustomDebugInfo() { scopes = new List(); } public PdbStateMachineHoistedLocalScopesCustomDebugInfo(int capacity) { scopes = new List(capacity); } } public sealed class PdbStateMachineTypeNameCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.StateMachineTypeName; public override Guid Guid => Guid.Empty; public TypeDef Type { get; set; } public PdbStateMachineTypeNameCustomDebugInfo() { } public PdbStateMachineTypeNameCustomDebugInfo(TypeDef type) { Type = type; } } public sealed class PdbDynamicLocalsCustomDebugInfo : PdbCustomDebugInfo { private readonly IList locals; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.DynamicLocals; public override Guid Guid => Guid.Empty; public IList Locals => locals; public PdbDynamicLocalsCustomDebugInfo() { locals = new List(); } public PdbDynamicLocalsCustomDebugInfo(int capacity) { locals = new List(capacity); } } public sealed class PdbDynamicLocal { private readonly IList flags; private string name; private Local local; public IList Flags => flags; public string Name { get { string text = name; if (text != null) { return text; } return local?.Name; } set { name = value; } } public bool IsConstant => Local == null; public bool IsVariable => Local != null; public Local Local { get { return local; } set { local = value; } } public PdbDynamicLocal() { flags = new List(); } public PdbDynamicLocal(int capacity) { flags = new List(capacity); } } public sealed class PdbEditAndContinueLocalSlotMapCustomDebugInfo : PdbCustomDebugInfo { private readonly byte[] data; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap; public override Guid Guid => CustomDebugInfoGuids.EncLocalSlotMap; public byte[] Data => data; public PdbEditAndContinueLocalSlotMapCustomDebugInfo(byte[] data) { this.data = data ?? throw new ArgumentNullException("data"); } } public sealed class PdbEditAndContinueLambdaMapCustomDebugInfo : PdbCustomDebugInfo { private readonly byte[] data; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.EditAndContinueLambdaMap; public override Guid Guid => CustomDebugInfoGuids.EncLambdaAndClosureMap; public byte[] Data => data; public PdbEditAndContinueLambdaMapCustomDebugInfo(byte[] data) { this.data = data ?? throw new ArgumentNullException("data"); } } public sealed class PdbTupleElementNamesCustomDebugInfo : PdbCustomDebugInfo { private readonly IList names; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.TupleElementNames; public override Guid Guid => Guid.Empty; public IList Names => names; public PdbTupleElementNamesCustomDebugInfo() { names = new List(); } public PdbTupleElementNamesCustomDebugInfo(int capacity) { names = new List(capacity); } } public sealed class PdbTupleElementNames { private readonly IList tupleElementNames; private string name; private Local local; private Instruction scopeStart; private Instruction scopeEnd; public string Name { get { string text = name; if (text != null) { return text; } return local?.Name; } set { name = value; } } public Local Local { get { return local; } set { local = value; } } public bool IsConstant => local == null; public bool IsVariable => local != null; public Instruction ScopeStart { get { return scopeStart; } set { scopeStart = value; } } public Instruction ScopeEnd { get { return scopeEnd; } set { scopeEnd = value; } } public IList TupleElementNames => tupleElementNames; public PdbTupleElementNames() { tupleElementNames = new List(); } public PdbTupleElementNames(int capacity) { tupleElementNames = new List(capacity); } } public sealed class PortablePdbTupleElementNamesCustomDebugInfo : PdbCustomDebugInfo { private readonly IList names; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.TupleElementNames_PortablePdb; public override Guid Guid => CustomDebugInfoGuids.TupleElementNames; public IList Names => names; public PortablePdbTupleElementNamesCustomDebugInfo() { names = new List(); } public PortablePdbTupleElementNamesCustomDebugInfo(int capacity) { names = new List(capacity); } } internal sealed class PdbAsyncMethodSteppingInformationCustomDebugInfo : PdbCustomDebugInfo { private readonly IList asyncStepInfos; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.Unknown; public override Guid Guid => CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob; public Instruction CatchHandler { get; set; } public IList AsyncStepInfos => asyncStepInfos; public PdbAsyncMethodSteppingInformationCustomDebugInfo() { asyncStepInfos = new List(); } } public sealed class PdbDefaultNamespaceCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.DefaultNamespace; public override Guid Guid => CustomDebugInfoGuids.DefaultNamespace; public string Namespace { get; set; } public PdbDefaultNamespaceCustomDebugInfo() { } public PdbDefaultNamespaceCustomDebugInfo(string defaultNamespace) { Namespace = defaultNamespace; } } public sealed class PdbDynamicLocalVariablesCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.DynamicLocalVariables; public override Guid Guid => CustomDebugInfoGuids.DynamicLocalVariables; public bool[] Flags { get; set; } public PdbDynamicLocalVariablesCustomDebugInfo() { } public PdbDynamicLocalVariablesCustomDebugInfo(bool[] flags) { Flags = flags; } } public sealed class PdbEmbeddedSourceCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.EmbeddedSource; public override Guid Guid => CustomDebugInfoGuids.EmbeddedSource; public byte[] SourceCodeBlob { get; set; } public PdbEmbeddedSourceCustomDebugInfo() { } public PdbEmbeddedSourceCustomDebugInfo(byte[] sourceCodeBlob) { SourceCodeBlob = sourceCodeBlob; } } public sealed class PdbSourceLinkCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.SourceLink; public override Guid Guid => CustomDebugInfoGuids.SourceLink; public byte[] FileBlob { get; set; } public PdbSourceLinkCustomDebugInfo() { } public PdbSourceLinkCustomDebugInfo(byte[] fileBlob) { FileBlob = fileBlob; } } public sealed class PdbSourceServerCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.SourceServer; public override Guid Guid => Guid.Empty; public byte[] FileBlob { get; set; } public PdbSourceServerCustomDebugInfo() { } public PdbSourceServerCustomDebugInfo(byte[] fileBlob) { FileBlob = fileBlob; } } public sealed class PdbAsyncMethodCustomDebugInfo : PdbCustomDebugInfo { private readonly IList asyncStepInfos; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.AsyncMethod; public override Guid Guid => Guid.Empty; public MethodDef KickoffMethod { get; set; } public Instruction CatchHandlerInstruction { get; set; } public IList StepInfos => asyncStepInfos; public PdbAsyncMethodCustomDebugInfo() { asyncStepInfos = new List(); } public PdbAsyncMethodCustomDebugInfo(int stepInfosCapacity) { asyncStepInfos = new List(stepInfosCapacity); } } public struct PdbAsyncStepInfo { public Instruction YieldInstruction; public MethodDef BreakpointMethod; public Instruction BreakpointInstruction; public PdbAsyncStepInfo(Instruction yieldInstruction, MethodDef breakpointMethod, Instruction breakpointInstruction) { YieldInstruction = yieldInstruction; BreakpointMethod = breakpointMethod; BreakpointInstruction = breakpointInstruction; } } public sealed class PdbIteratorMethodCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.IteratorMethod; public override Guid Guid => Guid.Empty; public MethodDef KickoffMethod { get; set; } public PdbIteratorMethodCustomDebugInfo() { } public PdbIteratorMethodCustomDebugInfo(MethodDef kickoffMethod) { KickoffMethod = kickoffMethod; } } public sealed class PdbCompilationMetadataReferencesCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.CompilationMetadataReferences; public override Guid Guid => CustomDebugInfoGuids.CompilationMetadataReferences; public List References { get; } public PdbCompilationMetadataReferencesCustomDebugInfo() { References = new List(); } } [Flags] public enum PdbCompilationMetadataReferenceFlags : byte { None = 0, Assembly = 1, EmbedInteropTypes = 2 } public sealed class PdbCompilationMetadataReference { public string Name { get; set; } public string Aliases { get; set; } public PdbCompilationMetadataReferenceFlags Flags { get; set; } public uint Timestamp { get; set; } public uint SizeOfImage { get; set; } public Guid Mvid { get; set; } public PdbCompilationMetadataReference() { Name = string.Empty; Aliases = string.Empty; } public PdbCompilationMetadataReference(string name, string aliases, PdbCompilationMetadataReferenceFlags flags, uint timestamp, uint sizeOfImage, Guid mvid) { Name = name; Aliases = aliases; Flags = flags; Timestamp = timestamp; SizeOfImage = sizeOfImage; Mvid = mvid; } } public sealed class PdbCompilationOptionsCustomDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.CompilationOptions; public override Guid Guid => CustomDebugInfoGuids.CompilationOptions; public List> Options { get; } public PdbCompilationOptionsCustomDebugInfo() { Options = new List>(); } } public class PdbTypeDefinitionDocumentsDebugInfo : PdbCustomDebugInfo { protected IList documents; public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.TypeDefinitionDocuments; public override Guid Guid => CustomDebugInfoGuids.TypeDefinitionDocuments; public IList Documents { get { if (documents == null) { InitializeDocuments(); } return documents; } } protected virtual void InitializeDocuments() { Interlocked.CompareExchange(ref documents, new List(), null); } } internal sealed class PdbTypeDefinitionDocumentsDebugInfoMD : PdbTypeDefinitionDocumentsDebugInfo { private readonly ModuleDef readerModule; private readonly IList documentTokens; protected override void InitializeDocuments() { List list = new List(documentTokens.Count); if (readerModule.PdbState != null) { for (int i = 0; i < documentTokens.Count; i++) { if (readerModule.PdbState.tokenToDocument.TryGetValue(documentTokens[i], out var value)) { list.Add(value); } } } Interlocked.CompareExchange(ref documents, list, null); } public PdbTypeDefinitionDocumentsDebugInfoMD(ModuleDef readerModule, IList documentTokens) { this.readerModule = readerModule; this.documentTokens = documentTokens; } } public sealed class PdbEditAndContinueStateMachineStateMapDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.EditAndContinueStateMachineStateMap; public override Guid Guid => CustomDebugInfoGuids.EncStateMachineStateMap; public List StateMachineStates { get; } public PdbEditAndContinueStateMachineStateMapDebugInfo() { StateMachineStates = new List(); } } public struct StateMachineStateInfo { public readonly int SyntaxOffset; public readonly StateMachineState State; public StateMachineStateInfo(int syntaxOffset, StateMachineState state) { SyntaxOffset = syntaxOffset; State = state; } } public enum StateMachineState { FirstResumableAsyncIteratorState = -4, InitialAsyncIteratorState = -3, FirstIteratorFinalizeState = -3, FinishedState = -2, NotStartedOrRunningState = -1, FirstUnusedState = 0, FirstResumableAsyncState = 0, InitialIteratorState = 0, FirstResumableIteratorState = 1 } public sealed class PrimaryConstructorInformationBlobDebugInfo : PdbCustomDebugInfo { public override PdbCustomDebugInfoKind Kind => PdbCustomDebugInfoKind.PrimaryConstructorInformationBlob; public override Guid Guid => CustomDebugInfoGuids.PrimaryConstructorInformationBlob; public byte[] Blob { get; set; } public PrimaryConstructorInformationBlobDebugInfo() { } public PrimaryConstructorInformationBlobDebugInfo(byte[] blob) { Blob = blob; } } [DebuggerDisplay("{Url}")] public sealed class PdbDocument : IHasCustomDebugInformation { private IList customDebugInfos; public string Url { get; set; } public Guid Language { get; set; } public Guid LanguageVendor { get; set; } public Guid DocumentType { get; set; } public Guid CheckSumAlgorithmId { get; set; } public byte[] CheckSum { get; set; } public int HasCustomDebugInformationTag => 22; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos => customDebugInfos; public MDToken? MDToken { get; internal set; } public PdbDocument() { } public PdbDocument(SymbolDocument symDoc) : this(symDoc, partial: false) { } private PdbDocument(SymbolDocument symDoc, bool partial) { if (symDoc == null) { throw new ArgumentNullException("symDoc"); } Url = symDoc.URL; if (!partial) { Initialize(symDoc); } } internal static PdbDocument CreatePartialForCompare(SymbolDocument symDoc) { return new PdbDocument(symDoc, partial: true); } internal void Initialize(SymbolDocument symDoc) { Language = symDoc.Language; LanguageVendor = symDoc.LanguageVendor; DocumentType = symDoc.DocumentType; CheckSumAlgorithmId = symDoc.CheckSumAlgorithmId; CheckSum = symDoc.CheckSum; customDebugInfos = new List(); PdbCustomDebugInfo[] array = symDoc.CustomDebugInfos; foreach (PdbCustomDebugInfo item in array) { customDebugInfos.Add(item); } MDToken = symDoc.MDToken; } public PdbDocument(string url, Guid language, Guid languageVendor, Guid documentType, Guid checkSumAlgorithmId, byte[] checkSum) { Url = url; Language = language; LanguageVendor = languageVendor; DocumentType = documentType; CheckSumAlgorithmId = checkSumAlgorithmId; CheckSum = checkSum; } public override int GetHashCode() { return StringComparer.OrdinalIgnoreCase.GetHashCode(Url ?? string.Empty); } public override bool Equals(object obj) { if (!(obj is PdbDocument pdbDocument)) { return false; } return StringComparer.OrdinalIgnoreCase.Equals(Url ?? string.Empty, pdbDocument.Url ?? string.Empty); } } public static class PdbDocumentConstants { public static readonly Guid LanguageCSharp = new Guid("3F5162F8-07C6-11D3-9053-00C04FA302A1"); public static readonly Guid LanguageVisualBasic = new Guid("3A12D0B8-C26C-11D0-B442-00A0244A1DD2"); public static readonly Guid LanguageFSharp = new Guid("AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3"); public static readonly Guid HashSHA1 = new Guid("FF1816EC-AA5E-4D10-87F7-6F4963833460"); public static readonly Guid HashSHA256 = new Guid("8829D00F-11B8-4213-878B-770E8597AC16"); public static readonly Guid LanguageVendorMicrosoft = new Guid("994B45C4-E6E9-11D2-903F-00C04FA302A1"); public static readonly Guid DocumentTypeText = new Guid("5A869D0B-6611-11D3-BD2A-0000F80849BD"); } public enum PdbFileKind { WindowsPDB, PortablePDB, EmbeddedPortablePDB } public sealed class PdbImportScope : IHasCustomDebugInformation { private readonly IList imports = new List(); private readonly IList customDebugInfos = new List(); public PdbImportScope Parent { get; set; } public IList Imports => imports; public bool HasImports => imports.Count > 0; public int HasCustomDebugInformationTag => 26; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos => customDebugInfos; } public enum PdbImportDefinitionKind { ImportNamespace, ImportAssemblyNamespace, ImportType, ImportXmlNamespace, ImportAssemblyReferenceAlias, AliasAssemblyReference, AliasNamespace, AliasAssemblyNamespace, AliasType } public abstract class PdbImport { public abstract PdbImportDefinitionKind Kind { get; } internal abstract void PreventNewClasses(); } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportNamespace : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.ImportNamespace; public string TargetNamespace { get; set; } public PdbImportNamespace() { } public PdbImportNamespace(string targetNamespace) { TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {TargetNamespace}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportAssemblyNamespace : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.ImportAssemblyNamespace; public AssemblyRef TargetAssembly { get; set; } public string TargetNamespace { get; set; } public PdbImportAssemblyNamespace() { } public PdbImportAssemblyNamespace(AssemblyRef targetAssembly, string targetNamespace) { TargetAssembly = targetAssembly; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {TargetAssembly} {TargetNamespace}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportType : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.ImportType; public ITypeDefOrRef TargetType { get; set; } public PdbImportType() { } public PdbImportType(ITypeDefOrRef targetType) { TargetType = targetType; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {TargetType}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportXmlNamespace : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.ImportXmlNamespace; public string Alias { get; set; } public string TargetNamespace { get; set; } public PdbImportXmlNamespace() { } public PdbImportXmlNamespace(string alias, string targetNamespace) { Alias = alias; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias} = {TargetNamespace}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportAssemblyReferenceAlias : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.ImportAssemblyReferenceAlias; public string Alias { get; set; } public PdbImportAssemblyReferenceAlias() { } public PdbImportAssemblyReferenceAlias(string alias) { Alias = alias; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasAssemblyReference : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.AliasAssemblyReference; public string Alias { get; set; } public AssemblyRef TargetAssembly { get; set; } public PdbAliasAssemblyReference() { } public PdbAliasAssemblyReference(string alias, AssemblyRef targetAssembly) { Alias = alias; TargetAssembly = targetAssembly; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias} = {TargetAssembly}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasNamespace : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.AliasNamespace; public string Alias { get; set; } public string TargetNamespace { get; set; } public PdbAliasNamespace() { } public PdbAliasNamespace(string alias, string targetNamespace) { Alias = alias; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias} = {TargetNamespace}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasAssemblyNamespace : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.AliasAssemblyNamespace; public string Alias { get; set; } public AssemblyRef TargetAssembly { get; set; } public string TargetNamespace { get; set; } public PdbAliasAssemblyNamespace() { } public PdbAliasAssemblyNamespace(string alias, AssemblyRef targetAssembly, string targetNamespace) { Alias = alias; TargetAssembly = targetAssembly; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias} = {TargetAssembly} {TargetNamespace}"; } } [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasType : PdbImport { public sealed override PdbImportDefinitionKind Kind => PdbImportDefinitionKind.AliasType; public string Alias { get; set; } public ITypeDefOrRef TargetType { get; set; } public PdbAliasType() { } public PdbAliasType(string alias, ITypeDefOrRef targetType) { Alias = alias; TargetType = targetType; } internal sealed override void PreventNewClasses() { } private string GetDebuggerString() { return $"{Kind}: {Alias} = {TargetType}"; } } public sealed class PdbLocal : IHasCustomDebugInformation { private readonly IList customDebugInfos = new List(); public Local Local { get; set; } public string Name { get; set; } public PdbLocalAttributes Attributes { get; set; } public int Index => Local.Index; public bool IsDebuggerHidden { get { return (Attributes & PdbLocalAttributes.DebuggerHidden) != 0; } set { if (value) { Attributes |= PdbLocalAttributes.DebuggerHidden; } else { Attributes &= ~PdbLocalAttributes.DebuggerHidden; } } } public int HasCustomDebugInformationTag => 24; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos => customDebugInfos; public PdbLocal() { } public PdbLocal(Local local, string name, PdbLocalAttributes attributes) { Local = local; Name = name; Attributes = attributes; } } [Flags] public enum PdbLocalAttributes { None = 0, DebuggerHidden = 1 } public sealed class PdbMethod { public PdbScope Scope { get; set; } } internal readonly struct PdbReaderContext { private readonly IPEImage peImage; private readonly ImageDebugDirectory codeViewDebugDir; public bool HasDebugInfo => codeViewDebugDir != null; public ImageDebugDirectory CodeViewDebugDirectory => codeViewDebugDir; public PdbReaderOptions Options { get; } public PdbReaderContext(IPEImage peImage, PdbReaderOptions options) { this.peImage = peImage; Options = options; codeViewDebugDir = TryGetDebugDirectoryEntry(peImage, ImageDebugType.CodeView); } public ImageDebugDirectory TryGetDebugDirectoryEntry(ImageDebugType imageDebugType) { return TryGetDebugDirectoryEntry(peImage, imageDebugType); } private static ImageDebugDirectory TryGetDebugDirectoryEntry(IPEImage peImage, ImageDebugType imageDebugType) { IList imageDebugDirectories = peImage.ImageDebugDirectories; int count = imageDebugDirectories.Count; for (int i = 0; i < count; i++) { ImageDebugDirectory imageDebugDirectory = imageDebugDirectories[i]; if (imageDebugDirectory.Type == imageDebugType) { return imageDebugDirectory; } } return null; } public bool TryGetCodeViewData(out Guid guid, out uint age) { string pdbFilename; return TryGetCodeViewData(out guid, out age, out pdbFilename); } public bool TryGetCodeViewData(out Guid guid, out uint age, out string pdbFilename) { guid = Guid.Empty; age = 0u; pdbFilename = null; DataReader codeViewDataReader = GetCodeViewDataReader(); if (codeViewDataReader.Length < 25) { return false; } if (codeViewDataReader.ReadUInt32() != 1396986706) { return false; } guid = codeViewDataReader.ReadGuid(); age = codeViewDataReader.ReadUInt32(); pdbFilename = codeViewDataReader.TryReadZeroTerminatedUtf8String(); return pdbFilename != null; } private DataReader GetCodeViewDataReader() { if (codeViewDebugDir == null) { return default(DataReader); } return CreateReader(codeViewDebugDir.AddressOfRawData, codeViewDebugDir.SizeOfData); } public DataReader CreateReader(RVA rva, uint size) { if (rva == (RVA)0u || size == 0) { return default(DataReader); } DataReader result = peImage.CreateReader(rva, size); if (result.Length != size) { return default(DataReader); } return result; } } [Flags] public enum PdbReaderOptions { None = 0, MicrosoftComReader = 1, NoDiaSymReader = 2, NoOldDiaSymReader = 4 } [DebuggerDisplay("{Start} - {End}")] public sealed class PdbScope : IHasCustomDebugInformation { private readonly IList scopes = new List(); private readonly IList locals = new List(); private readonly IList namespaces = new List(); private readonly IList constants = new List(); private readonly IList customDebugInfos = new List(); public Instruction Start { get; set; } public Instruction End { get; set; } public IList Scopes => scopes; public bool HasScopes => scopes.Count > 0; public IList Variables => locals; public bool HasVariables => locals.Count > 0; public IList Namespaces => namespaces; public bool HasNamespaces => namespaces.Count > 0; public PdbImportScope ImportScope { get; set; } public IList Constants => constants; public bool HasConstants => constants.Count > 0; public int HasCustomDebugInformationTag => 23; public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0; public IList CustomDebugInfos => customDebugInfos; } public sealed class PdbState { private struct CreateScopeState { public SymbolScope SymScope; public PdbScope PdbScope; public IList Children; public int ChildrenIndex; } private readonly SymbolReader reader; private readonly Dictionary docDict = new Dictionary(); internal readonly Dictionary tokenToDocument = new Dictionary(); private MethodDef userEntryPoint; private readonly Compiler compiler; private readonly PdbFileKind originalPdbFileKind; private readonly Lock theLock = Lock.Create(); private static readonly UTF8String nameAssemblyVisualBasic = new UTF8String("Microsoft.VisualBasic"); private static readonly UTF8String nameAssemblyVisualBasicCore = new UTF8String("Microsoft.VisualBasic.Core"); public PdbFileKind PdbFileKind { get; set; } public MethodDef UserEntryPoint { get { return userEntryPoint; } set { userEntryPoint = value; } } public IEnumerable Documents { get { theLock.EnterWriteLock(); try { return new List(docDict.Values); } finally { theLock.ExitWriteLock(); } } } public bool HasDocuments { get { theLock.EnterWriteLock(); try { return docDict.Count > 0; } finally { theLock.ExitWriteLock(); } } } internal Compiler Compiler => compiler; public PdbState(ModuleDef module, PdbFileKind pdbFileKind) { if (module == null) { throw new ArgumentNullException("module"); } compiler = CalculateCompiler(module); PdbFileKind = pdbFileKind; originalPdbFileKind = pdbFileKind; } public PdbState(SymbolReader reader, ModuleDefMD module) { if (module == null) { throw new ArgumentNullException("module"); } this.reader = reader ?? throw new ArgumentNullException("reader"); reader.Initialize(module); PdbFileKind = reader.PdbFileKind; originalPdbFileKind = reader.PdbFileKind; compiler = CalculateCompiler(module); userEntryPoint = module.ResolveToken(reader.UserEntryPoint) as MethodDef; IList documents = reader.Documents; int count = documents.Count; for (int i = 0; i < count; i++) { Add_NoLock(documents[i]); } } public PdbDocument Add(PdbDocument doc) { theLock.EnterWriteLock(); try { return Add_NoLock(doc); } finally { theLock.ExitWriteLock(); } } private PdbDocument Add_NoLock(PdbDocument doc) { if (docDict.TryGetValue(doc, out var value)) { return value; } docDict.Add(doc, doc); if (doc.MDToken.HasValue) { tokenToDocument.Add(doc.MDToken.Value, doc); } return doc; } private PdbDocument Add_NoLock(SymbolDocument symDoc) { PdbDocument pdbDocument = PdbDocument.CreatePartialForCompare(symDoc); if (docDict.TryGetValue(pdbDocument, out var value)) { return value; } pdbDocument.Initialize(symDoc); docDict.Add(pdbDocument, pdbDocument); if (symDoc.MDToken.HasValue) { tokenToDocument.Add(symDoc.MDToken.Value, pdbDocument); } return pdbDocument; } public bool Remove(PdbDocument doc) { theLock.EnterWriteLock(); try { if (doc.MDToken.HasValue) { tokenToDocument.Remove(doc.MDToken.Value); } return docDict.Remove(doc); } finally { theLock.ExitWriteLock(); } } public PdbDocument GetExisting(PdbDocument doc) { theLock.EnterWriteLock(); try { docDict.TryGetValue(doc, out var value); return value; } finally { theLock.ExitWriteLock(); } } public void RemoveAllDocuments() { RemoveAllDocuments(returnDocs: false); } public List RemoveAllDocuments(bool returnDocs) { theLock.EnterWriteLock(); try { List result = (returnDocs ? new List(docDict.Values) : null); tokenToDocument.Clear(); docDict.Clear(); return result; } finally { theLock.ExitWriteLock(); } } internal void InitializeMethodBody(ModuleDefMD module, MethodDef ownerMethod, CilBody body) { if (reader != null) { SymbolMethod method = reader.GetMethod(ownerMethod, 1); if (method != null) { PdbMethod pdbMethod = new PdbMethod(); pdbMethod.Scope = CreateScope(module, GenericParamContext.Create(ownerMethod), body, method.RootScope); AddSequencePoints(body, method); body.PdbMethod = pdbMethod; } } } internal void InitializeCustomDebugInfos(MethodDef ownerMethod, CilBody body, IList customDebugInfos) { if (reader != null) { reader.GetMethod(ownerMethod, 1)?.GetCustomDebugInfos(ownerMethod, body, customDebugInfos); } } private static Compiler CalculateCompiler(ModuleDef module) { if (module == null) { return Compiler.Other; } foreach (AssemblyRef assemblyRef in module.GetAssemblyRefs()) { if (assemblyRef.Name == nameAssemblyVisualBasic || assemblyRef.Name == nameAssemblyVisualBasicCore) { return Compiler.VisualBasic; } } return Compiler.Other; } private void AddSequencePoints(CilBody body, SymbolMethod method) { int index = 0; IList sequencePoints = method.SequencePoints; int count = sequencePoints.Count; for (int i = 0; i < count; i++) { SymbolSequencePoint symbolSequencePoint = sequencePoints[i]; Instruction instruction = GetInstruction(body.Instructions, symbolSequencePoint.Offset, ref index); if (instruction != null) { SequencePoint sequencePoint = new SequencePoint { Document = Add_NoLock(symbolSequencePoint.Document), StartLine = symbolSequencePoint.Line, StartColumn = symbolSequencePoint.Column, EndLine = symbolSequencePoint.EndLine, EndColumn = symbolSequencePoint.EndColumn }; instruction.SequencePoint = sequencePoint; } } } private PdbScope CreateScope(ModuleDefMD module, GenericParamContext gpContext, CilBody body, SymbolScope symScope) { if (symScope == null) { return null; } Stack stack = new Stack(); CreateScopeState item = new CreateScopeState { SymScope = symScope }; int num = (PdbUtils.IsEndInclusive(originalPdbFileKind, Compiler) ? 1 : 0); while (true) { int index = 0; item.PdbScope = new PdbScope { Start = GetInstruction(body.Instructions, item.SymScope.StartOffset, ref index), End = GetInstruction(body.Instructions, item.SymScope.EndOffset + num, ref index) }; IList customDebugInfos = item.SymScope.CustomDebugInfos; int count = customDebugInfos.Count; for (int i = 0; i < count; i++) { item.PdbScope.CustomDebugInfos.Add(customDebugInfos[i]); } IList locals = item.SymScope.Locals; count = locals.Count; for (int j = 0; j < count; j++) { SymbolVariable symbolVariable = locals[j]; int index2 = symbolVariable.Index; if ((uint)index2 < (uint)body.Variables.Count) { Local local = body.Variables[index2]; string name = symbolVariable.Name; local.SetName(name); PdbLocalAttributes attributes = symbolVariable.Attributes; local.SetAttributes(attributes); PdbLocal pdbLocal = new PdbLocal(local, name, attributes); customDebugInfos = symbolVariable.CustomDebugInfos; int count2 = customDebugInfos.Count; for (int k = 0; k < count2; k++) { pdbLocal.CustomDebugInfos.Add(customDebugInfos[k]); } item.PdbScope.Variables.Add(pdbLocal); } } IList namespaces = item.SymScope.Namespaces; count = namespaces.Count; for (int l = 0; l < count; l++) { item.PdbScope.Namespaces.Add(namespaces[l].Name); } item.PdbScope.ImportScope = item.SymScope.ImportScope; IList constants = item.SymScope.GetConstants(module, gpContext); PdbConstant pdbConstant; for (int m = 0; m < constants.Count; item.PdbScope.Constants.Add(pdbConstant), m++) { pdbConstant = constants[m]; TypeSig typeSig = pdbConstant.Type.RemovePinnedAndModifiers(); if (typeSig == null) { continue; } switch (typeSig.ElementType) { case ElementType.Boolean: if (pdbConstant.Value is short) { pdbConstant.Value = (short)pdbConstant.Value != 0; } continue; case ElementType.Char: if (pdbConstant.Value is ushort) { pdbConstant.Value = (char)(ushort)pdbConstant.Value; } continue; case ElementType.I1: if (pdbConstant.Value is short) { pdbConstant.Value = (sbyte)(short)pdbConstant.Value; } continue; case ElementType.U1: if (pdbConstant.Value is short) { pdbConstant.Value = (byte)(short)pdbConstant.Value; } continue; case ElementType.String: if (PdbFileKind == PdbFileKind.WindowsPDB) { if (pdbConstant.Value is int && (int)pdbConstant.Value == 0) { pdbConstant.Value = null; } else if (pdbConstant.Value == null) { pdbConstant.Value = string.Empty; } } continue; case ElementType.GenericInst: if (((GenericInstSig)typeSig).GenericType is ValueTypeSig) { continue; } break; case ElementType.Var: case ElementType.MVar: { GenericParam genericParam = ((GenericSig)typeSig).GenericParam; if (genericParam == null || genericParam.HasNotNullableValueTypeConstraint || !genericParam.HasReferenceTypeConstraint) { continue; } break; } case ElementType.Void: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.Ptr: case ElementType.ByRef: case ElementType.ValueType: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: continue; } if (pdbConstant.Value is int && (int)pdbConstant.Value == 0) { pdbConstant.Value = null; } } item.ChildrenIndex = 0; item.Children = item.SymScope.Children; while (item.ChildrenIndex >= item.Children.Count) { if (stack.Count == 0) { return item.PdbScope; } PdbScope pdbScope = item.PdbScope; item = stack.Pop(); item.PdbScope.Scopes.Add(pdbScope); item.ChildrenIndex++; } SymbolScope symScope2 = item.Children[item.ChildrenIndex]; stack.Push(item); item = new CreateScopeState { SymScope = symScope2 }; } } private static Instruction GetInstruction(IList instrs, int offset, ref int index) { if (instrs.Count > 0 && offset > instrs[instrs.Count - 1].Offset) { return null; } for (int i = index; i < instrs.Count; i++) { Instruction instruction = instrs[i]; if (instruction.Offset >= offset) { if (instruction.Offset != offset) { break; } index = i; return instruction; } } for (int j = 0; j < index; j++) { Instruction instruction2 = instrs[j]; if (instruction2.Offset >= offset) { if (instruction2.Offset != offset) { break; } index = j; return instruction2; } } return null; } internal void InitializeCustomDebugInfos(MDToken token, GenericParamContext gpContext, IList result) { reader?.GetCustomDebugInfos(token.ToInt32(), gpContext, result); } internal void Dispose() { reader?.Dispose(); } } internal enum Compiler { Other, VisualBasic } internal static class PdbUtils { public static bool IsEndInclusive(PdbFileKind pdbFileKind, Compiler compiler) { if (pdbFileKind == PdbFileKind.WindowsPDB) { return compiler == Compiler.VisualBasic; } return false; } } [DebuggerDisplay("({StartLine}, {StartColumn}) - ({EndLine}, {EndColumn}) {Document.Url}")] public sealed class SequencePoint { public PdbDocument Document { get; set; } public int StartLine { get; set; } public int StartColumn { get; set; } public int EndLine { get; set; } public int EndColumn { get; set; } public SequencePoint Clone() { return new SequencePoint { Document = Document, StartLine = StartLine, StartColumn = StartColumn, EndLine = EndLine, EndColumn = EndColumn }; } } internal static class SymbolReaderFactory { private static readonly char[] windowsPathSepChars = new char[2] { '\\', '/' }; public static SymbolReader CreateFromAssemblyFile(PdbReaderOptions options, dnlib.DotNet.MD.Metadata metadata, string assemblyFileName) { PdbReaderContext pdbReaderContext = new PdbReaderContext(metadata.PEImage, options); if (!pdbReaderContext.HasDebugInfo) { return null; } if (!pdbReaderContext.TryGetCodeViewData(out var _, out var _, out var pdbFilename)) { return null; } int num = pdbFilename.LastIndexOfAny(windowsPathSepChars); string text = ((num < 0) ? pdbFilename : pdbFilename.Substring(num + 1)); string text2; try { text2 = ((assemblyFileName == string.Empty) ? text : Path.Combine(Path.GetDirectoryName(assemblyFileName), text)); if (!File.Exists(text2)) { string text3 = Path.GetExtension(text); if (string.IsNullOrEmpty(text3)) { text3 = "pdb"; } text2 = Path.ChangeExtension(assemblyFileName, text3); } } catch (ArgumentException) { return null; } return Create(options, metadata, text2); } public static SymbolReader Create(PdbReaderOptions options, dnlib.DotNet.MD.Metadata metadata, string pdbFileName) { PdbReaderContext pdbContext = new PdbReaderContext(metadata.PEImage, options); if (!pdbContext.HasDebugInfo) { return null; } return CreateCore(pdbContext, metadata, DataReaderFactoryUtils.TryCreateDataReaderFactory(pdbFileName)); } public static SymbolReader Create(PdbReaderOptions options, dnlib.DotNet.MD.Metadata metadata, byte[] pdbData) { PdbReaderContext pdbContext = new PdbReaderContext(metadata.PEImage, options); if (!pdbContext.HasDebugInfo) { return null; } return CreateCore(pdbContext, metadata, ByteArrayDataReaderFactory.Create(pdbData, null)); } public static SymbolReader Create(PdbReaderOptions options, dnlib.DotNet.MD.Metadata metadata, DataReaderFactory pdbStream) { return CreateCore(new PdbReaderContext(metadata.PEImage, options), metadata, pdbStream); } private static SymbolReader CreateCore(PdbReaderContext pdbContext, dnlib.DotNet.MD.Metadata metadata, DataReaderFactory pdbStream) { SymbolReader symbolReader = null; bool flag = true; try { if (!pdbContext.HasDebugInfo) { return null; } bool flag2 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); symbolReader = ((!((pdbContext.Options & PdbReaderOptions.MicrosoftComReader) != 0 && flag2) || pdbStream == null || !IsWindowsPdb(pdbStream.CreateReader())) ? CreateManaged(pdbContext, metadata, pdbStream) : SymbolReaderWriterFactory.Create(pdbContext, metadata, pdbStream)); if (symbolReader != null) { flag = false; return symbolReader; } } catch (IOException) { } finally { if (flag) { pdbStream?.Dispose(); symbolReader?.Dispose(); } } return null; } private static bool IsWindowsPdb(DataReader reader) { if (!reader.CanRead("Microsoft C/C++ MSF 7.00\r\n\u001aDS\0".Length)) { return false; } return reader.ReadString("Microsoft C/C++ MSF 7.00\r\n\u001aDS\0".Length, Encoding.ASCII) == "Microsoft C/C++ MSF 7.00\r\n\u001aDS\0"; } public static SymbolReader TryCreateEmbeddedPdbReader(PdbReaderOptions options, dnlib.DotNet.MD.Metadata metadata) { PdbReaderContext pdbContext = new PdbReaderContext(metadata.PEImage, options); if (!pdbContext.HasDebugInfo) { return null; } return TryCreateEmbeddedPortablePdbReader(pdbContext, metadata); } private static SymbolReader CreateManaged(PdbReaderContext pdbContext, dnlib.DotNet.MD.Metadata metadata, DataReaderFactory pdbStream) { try { SymbolReader symbolReader = TryCreateEmbeddedPortablePdbReader(pdbContext, metadata); if (symbolReader != null) { pdbStream?.Dispose(); return symbolReader; } return CreateManagedCore(pdbContext, pdbStream); } catch { pdbStream?.Dispose(); throw; } } private static SymbolReader CreateManagedCore(PdbReaderContext pdbContext, DataReaderFactory pdbStream) { if (pdbStream == null) { return null; } try { DataReader dataReader = pdbStream.CreateReader(); if (dataReader.Length >= 4) { if (dataReader.ReadUInt32() == 1112167234) { return dnlib.DotNet.Pdb.Portable.SymbolReaderFactory.TryCreate(pdbContext, pdbStream, isEmbeddedPortablePdb: false); } return dnlib.DotNet.Pdb.Managed.SymbolReaderFactory.Create(pdbContext, pdbStream); } } catch (IOException) { } pdbStream?.Dispose(); return null; } private static SymbolReader TryCreateEmbeddedPortablePdbReader(PdbReaderContext pdbContext, dnlib.DotNet.MD.Metadata metadata) { return dnlib.DotNet.Pdb.Portable.SymbolReaderFactory.TryCreateEmbeddedPortablePdbReader(pdbContext, metadata); } } } namespace dnlib.DotNet.Pdb.WindowsPdb { [Flags] internal enum CorSymVarFlag : uint { VAR_IS_COMP_GEN = 1u } internal static class CustomDebugInfoConstants { public const int Version = 4; public const int RecordVersion = 4; } internal struct PdbCustomDebugInfoReader { private readonly ModuleDef module; private readonly TypeDef typeOpt; private readonly CilBody bodyOpt; private readonly GenericParamContext gpContext; private DataReader reader; public static void Read(MethodDef method, CilBody body, IList result, byte[] data) { try { DataReader dataReader = ByteArrayDataReaderFactory.CreateReader(data); new PdbCustomDebugInfoReader(method, body, ref dataReader).Read(result); } catch (ArgumentException) { } catch (OutOfMemoryException) { } catch (IOException) { } } private PdbCustomDebugInfoReader(MethodDef method, CilBody body, ref DataReader reader) { module = method.Module; typeOpt = method.DeclaringType; bodyOpt = body; gpContext = GenericParamContext.Create(method); this.reader = reader; } private void Read(IList result) { if (reader.Length < 4 || reader.ReadByte() != 4) { return; } reader.ReadByte(); reader.Position += 2u; while (reader.CanRead(8u)) { int num = reader.ReadByte(); PdbCustomDebugInfoKind pdbCustomDebugInfoKind = (PdbCustomDebugInfoKind)reader.ReadByte(); reader.Position++; int num2 = reader.ReadByte(); int num3 = reader.ReadInt32(); if (num3 < 8 || (ulong)((long)reader.Position - 8L + (uint)num3) > (ulong)reader.Length) { break; } if (pdbCustomDebugInfoKind <= PdbCustomDebugInfoKind.DynamicLocals) { num2 = 0; } if (num2 > 3) { break; } uint position = reader.Position - 8 + (uint)num3; if (num == 4) { ulong num4 = (ulong)((long)reader.Position - 8L + (uint)num3 - (uint)num2); PdbCustomDebugInfo pdbCustomDebugInfo = ReadRecord(pdbCustomDebugInfoKind, num4); if (reader.Position > num4) { break; } if (pdbCustomDebugInfo != null) { result.Add(pdbCustomDebugInfo); } } reader.Position = position; } } private PdbCustomDebugInfo ReadRecord(PdbCustomDebugInfoKind recKind, ulong recPosEnd) { switch (recKind) { case PdbCustomDebugInfoKind.UsingGroups: { int num = reader.ReadUInt16(); if (num < 0) { return null; } PdbUsingGroupsCustomDebugInfo pdbUsingGroupsCustomDebugInfo = new PdbUsingGroupsCustomDebugInfo(num); for (int m = 0; m < num; m++) { pdbUsingGroupsCustomDebugInfo.UsingCounts.Add(reader.ReadUInt16()); } return pdbUsingGroupsCustomDebugInfo; } case PdbCustomDebugInfoKind.ForwardMethodInfo: if (!(module.ResolveToken(reader.ReadUInt32(), gpContext) is IMethodDefOrRef method2)) { return null; } return new PdbForwardMethodInfoCustomDebugInfo(method2); case PdbCustomDebugInfoKind.ForwardModuleInfo: if (!(module.ResolveToken(reader.ReadUInt32(), gpContext) is IMethodDefOrRef method)) { return null; } return new PdbForwardModuleInfoCustomDebugInfo(method); case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: { if (bodyOpt == null) { return null; } int num = reader.ReadInt32(); if (num < 0) { return null; } PdbStateMachineHoistedLocalScopesCustomDebugInfo pdbStateMachineHoistedLocalScopesCustomDebugInfo = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(num); for (int n = 0; n < num; n++) { uint num6 = reader.ReadUInt32(); uint num7 = reader.ReadUInt32(); if (num6 > num7) { return null; } if (num7 == 0) { pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes.Add(default(StateMachineHoistedLocalScope)); continue; } Instruction instruction = GetInstruction(num6); Instruction instruction2 = GetInstruction(num7 + 1); if (instruction == null) { return null; } pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes.Add(new StateMachineHoistedLocalScope(instruction, instruction2)); } return pdbStateMachineHoistedLocalScopesCustomDebugInfo; } case PdbCustomDebugInfoKind.StateMachineTypeName: { string text2 = ReadUnicodeZ(recPosEnd, needZeroChar: true); if (text2 == null) { return null; } TypeDef nestedType = GetNestedType(text2); if (nestedType == null) { return null; } return new PdbStateMachineTypeNameCustomDebugInfo(nestedType); } case PdbCustomDebugInfoKind.DynamicLocals: { if (bodyOpt == null) { return null; } int num = reader.ReadInt32(); if ((ulong)(reader.Position + (long)(uint)num * 200L) > recPosEnd) { return null; } PdbDynamicLocalsCustomDebugInfo pdbDynamicLocalsCustomDebugInfo = new PdbDynamicLocalsCustomDebugInfo(num); for (int k = 0; k < num; k++) { reader.Position += 64u; int num4 = reader.ReadInt32(); if ((uint)num4 > 64u) { return null; } PdbDynamicLocal pdbDynamicLocal = new PdbDynamicLocal(num4); uint position = reader.Position; reader.Position -= 68u; for (int l = 0; l < num4; l++) { pdbDynamicLocal.Flags.Add(reader.ReadByte()); } reader.Position = position; int num3 = reader.ReadInt32(); if (num3 != 0 && (uint)num3 >= (uint)bodyOpt.Variables.Count) { return null; } uint num5 = reader.Position + 128; string text2 = ReadUnicodeZ(num5, needZeroChar: false); reader.Position = num5; Local local = ((num3 < bodyOpt.Variables.Count) ? bodyOpt.Variables[num3] : null); if (num3 == 0 && local != null && local.Name != text2) { local = null; } if (local != null && local.Name == text2) { text2 = null; } pdbDynamicLocal.Name = text2; pdbDynamicLocal.Local = local; pdbDynamicLocalsCustomDebugInfo.Locals.Add(pdbDynamicLocal); } return pdbDynamicLocalsCustomDebugInfo; } case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: { byte[] data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLocalSlotMapCustomDebugInfo(data); } case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: { byte[] data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLambdaMapCustomDebugInfo(data); } case PdbCustomDebugInfoKind.TupleElementNames: { if (bodyOpt == null) { return null; } int num = reader.ReadInt32(); if (num < 0) { return null; } PdbTupleElementNamesCustomDebugInfo pdbTupleElementNamesCustomDebugInfo = new PdbTupleElementNamesCustomDebugInfo(num); for (int i = 0; i < num; i++) { int num2 = reader.ReadInt32(); if ((uint)num2 >= 10000u) { return null; } PdbTupleElementNames pdbTupleElementNames = new PdbTupleElementNames(num2); for (int j = 0; j < num2; j++) { string text = ReadUTF8Z(recPosEnd); if (text == null) { return null; } pdbTupleElementNames.TupleElementNames.Add(text); } int num3 = reader.ReadInt32(); uint offset = reader.ReadUInt32(); uint offset2 = reader.ReadUInt32(); string text2 = ReadUTF8Z(recPosEnd); if (text2 == null) { return null; } Local local; if (num3 == -1) { local = null; pdbTupleElementNames.ScopeStart = GetInstruction(offset); pdbTupleElementNames.ScopeEnd = GetInstruction(offset2); if (pdbTupleElementNames.ScopeStart == null) { return null; } } else { if ((uint)num3 >= (uint)bodyOpt.Variables.Count) { return null; } local = bodyOpt.Variables[num3]; } if (local != null && local.Name == text2) { text2 = null; } pdbTupleElementNames.Local = local; pdbTupleElementNames.Name = text2; pdbTupleElementNamesCustomDebugInfo.Names.Add(pdbTupleElementNames); } return pdbTupleElementNamesCustomDebugInfo; } default: { byte[] data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbUnknownCustomDebugInfo(recKind, data); } } } private TypeDef GetNestedType(string name) { if (typeOpt == null) { return null; } IList nestedTypes = typeOpt.NestedTypes; int count = nestedTypes.Count; for (int i = 0; i < count; i++) { TypeDef typeDef = nestedTypes[i]; if (!UTF8String.IsNullOrEmpty(typeDef.Namespace)) { continue; } if (typeDef.Name == name) { return typeDef; } string text = typeDef.Name.String; if (!text.StartsWith(name) || text.Length < name.Length + 2) { continue; } int length = name.Length; if (text[length] != '`') { continue; } bool flag = true; for (length++; length < text.Length; length++) { if (!char.IsDigit(text[length])) { flag = false; break; } } if (flag) { return typeDef; } } return null; } private string ReadUnicodeZ(ulong recPosEnd, bool needZeroChar) { StringBuilder stringBuilder = new StringBuilder(); while (true) { if (reader.Position >= recPosEnd) { if (!needZeroChar) { return stringBuilder.ToString(); } return null; } char c = reader.ReadChar(); if (c == '\0') { break; } stringBuilder.Append(c); } return stringBuilder.ToString(); } private string ReadUTF8Z(ulong recPosEnd) { if (reader.Position > recPosEnd) { return null; } return reader.TryReadZeroTerminatedUtf8String(); } private Instruction GetInstruction(uint offset) { IList instructions = bodyOpt.Instructions; int num = 0; int num2 = instructions.Count - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; Instruction instruction = instructions[num3]; if (instruction.Offset == offset) { return instruction; } if (offset < instruction.Offset) { num2 = num3 - 1; } else { num = num3 + 1; } } return null; } } internal sealed class PdbCustomDebugInfoWriterContext { public ILogger Logger; public readonly MemoryStream MemoryStream; public readonly DataWriter Writer; public readonly Dictionary InstructionToOffsetDict; public PdbCustomDebugInfoWriterContext() { MemoryStream = new MemoryStream(); Writer = new DataWriter(MemoryStream); InstructionToOffsetDict = new Dictionary(); } } internal struct PdbCustomDebugInfoWriter { private readonly dnlib.DotNet.Writer.Metadata metadata; private readonly MethodDef method; private readonly ILogger logger; private readonly MemoryStream memoryStream; private readonly DataWriter writer; private readonly Dictionary instructionToOffsetDict; private uint bodySize; private bool instructionToOffsetDictInitd; public static byte[] Write(dnlib.DotNet.Writer.Metadata metadata, MethodDef method, PdbCustomDebugInfoWriterContext context, IList customDebugInfos) { return new PdbCustomDebugInfoWriter(metadata, method, context).Write(customDebugInfos); } private PdbCustomDebugInfoWriter(dnlib.DotNet.Writer.Metadata metadata, MethodDef method, PdbCustomDebugInfoWriterContext context) { this.metadata = metadata; this.method = method; logger = context.Logger; memoryStream = context.MemoryStream; writer = context.Writer; instructionToOffsetDict = context.InstructionToOffsetDict; bodySize = 0u; instructionToOffsetDictInitd = false; memoryStream.SetLength(0L); memoryStream.Position = 0L; } private void InitializeInstructionDictionary() { instructionToOffsetDict.Clear(); CilBody body = method.Body; if (body != null) { IList instructions = body.Instructions; uint num = 0u; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; instructionToOffsetDict[instruction] = num; num += (uint)instruction.GetSize(); } bodySize = num; instructionToOffsetDictInitd = true; } } private uint GetInstructionOffset(Instruction instr, bool nullIsEndOfMethod) { if (!instructionToOffsetDictInitd) { InitializeInstructionDictionary(); } if (instr == null) { if (nullIsEndOfMethod) { return bodySize; } Error("Instruction is null"); return uint.MaxValue; } if (instructionToOffsetDict.TryGetValue(instr, out var value)) { return value; } Error("Instruction is missing in body but it's still being referenced by PDB data. Method {0} (0x{1:X8}), instruction: {2}", method, method.MDToken.Raw, instr); return uint.MaxValue; } private void Error(string message, params object[] args) { logger.Log(this, LoggerEvent.Error, message, args); } private byte[] Write(IList customDebugInfos) { if (customDebugInfos.Count == 0) { return null; } if (customDebugInfos.Count > 255) { Error("Too many custom debug infos. Count must be <= 255"); return null; } writer.WriteByte(4); writer.WriteByte((byte)customDebugInfos.Count); writer.WriteUInt16(0); for (int i = 0; i < customDebugInfos.Count; i++) { PdbCustomDebugInfo pdbCustomDebugInfo = customDebugInfos[i]; if (pdbCustomDebugInfo == null) { Error("Custom debug info is null"); return null; } if ((uint)pdbCustomDebugInfo.Kind > 255u) { Error("Invalid custom debug info kind"); return null; } long position = writer.Position; writer.WriteByte(4); writer.WriteByte((byte)pdbCustomDebugInfo.Kind); writer.WriteUInt16(0); writer.WriteUInt32(0u); switch (pdbCustomDebugInfo.Kind) { case PdbCustomDebugInfoKind.UsingGroups: { if (!(pdbCustomDebugInfo is PdbUsingGroupsCustomDebugInfo pdbUsingGroupsCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } int count = pdbUsingGroupsCustomDebugInfo.UsingCounts.Count; if (count > 65535) { Error("UsingCounts contains more than 0xFFFF elements"); return null; } writer.WriteUInt16((ushort)count); for (int j = 0; j < count; j++) { writer.WriteUInt16(pdbUsingGroupsCustomDebugInfo.UsingCounts[j]); } break; } case PdbCustomDebugInfoKind.ForwardMethodInfo: { if (!(pdbCustomDebugInfo is PdbForwardMethodInfoCustomDebugInfo pdbForwardMethodInfoCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } uint methodToken = GetMethodToken(pdbForwardMethodInfoCustomDebugInfo.Method); if (methodToken == 0) { return null; } writer.WriteUInt32(methodToken); break; } case PdbCustomDebugInfoKind.ForwardModuleInfo: { if (!(pdbCustomDebugInfo is PdbForwardModuleInfoCustomDebugInfo pdbForwardModuleInfoCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } uint methodToken = GetMethodToken(pdbForwardModuleInfoCustomDebugInfo.Method); if (methodToken == 0) { return null; } writer.WriteUInt32(methodToken); break; } case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: { if (!(pdbCustomDebugInfo is PdbStateMachineHoistedLocalScopesCustomDebugInfo pdbStateMachineHoistedLocalScopesCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } int count = pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes.Count; writer.WriteInt32(count); for (int j = 0; j < count; j++) { StateMachineHoistedLocalScope stateMachineHoistedLocalScope = pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes[j]; if (stateMachineHoistedLocalScope.IsSynthesizedLocal) { writer.WriteInt32(0); writer.WriteInt32(0); } else { writer.WriteUInt32(GetInstructionOffset(stateMachineHoistedLocalScope.Start, nullIsEndOfMethod: false)); writer.WriteUInt32(GetInstructionOffset(stateMachineHoistedLocalScope.End, nullIsEndOfMethod: true) - 1); } } break; } case PdbCustomDebugInfoKind.StateMachineTypeName: if (!(pdbCustomDebugInfo is PdbStateMachineTypeNameCustomDebugInfo { Type: var type })) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } if (type == null) { Error("State machine type is null"); return null; } WriteUnicodeZ(MetadataNameToRoslynName(type.Name)); break; case PdbCustomDebugInfoKind.DynamicLocals: { if (!(pdbCustomDebugInfo is PdbDynamicLocalsCustomDebugInfo pdbDynamicLocalsCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } int count = pdbDynamicLocalsCustomDebugInfo.Locals.Count; writer.WriteInt32(count); for (int j = 0; j < count; j++) { PdbDynamicLocal pdbDynamicLocal = pdbDynamicLocalsCustomDebugInfo.Locals[j]; if (pdbDynamicLocal == null) { Error("Dynamic local is null"); return null; } if (pdbDynamicLocal.Flags.Count > 64) { Error("Dynamic local flags is longer than 64 bytes"); return null; } string text = pdbDynamicLocal.Name; if (text == null) { text = string.Empty; } if (text.Length > 64) { Error("Dynamic local name is longer than 64 chars"); return null; } if (text.IndexOf('\0') >= 0) { Error("Dynamic local name contains a NUL char"); return null; } int k; for (k = 0; k < pdbDynamicLocal.Flags.Count; k++) { writer.WriteByte(pdbDynamicLocal.Flags[k]); } while (k++ < 64) { writer.WriteByte(0); } writer.WriteInt32(pdbDynamicLocal.Flags.Count); if (pdbDynamicLocal.Local == null) { writer.WriteInt32(0); } else { writer.WriteInt32(pdbDynamicLocal.Local.Index); } for (k = 0; k < text.Length; k++) { writer.WriteUInt16(text[k]); } while (k++ < 64) { writer.WriteUInt16(0); } } break; } case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: if (!(pdbCustomDebugInfo is PdbEditAndContinueLocalSlotMapCustomDebugInfo pdbEditAndContinueLocalSlotMapCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } writer.WriteBytes(pdbEditAndContinueLocalSlotMapCustomDebugInfo.Data); break; case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: if (!(pdbCustomDebugInfo is PdbEditAndContinueLambdaMapCustomDebugInfo pdbEditAndContinueLambdaMapCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } writer.WriteBytes(pdbEditAndContinueLambdaMapCustomDebugInfo.Data); break; case PdbCustomDebugInfoKind.TupleElementNames: { if (!(pdbCustomDebugInfo is PdbTupleElementNamesCustomDebugInfo pdbTupleElementNamesCustomDebugInfo)) { Error("Unsupported custom debug info type {0}", pdbCustomDebugInfo.GetType()); return null; } int count = pdbTupleElementNamesCustomDebugInfo.Names.Count; writer.WriteInt32(count); for (int j = 0; j < count; j++) { PdbTupleElementNames pdbTupleElementNames = pdbTupleElementNamesCustomDebugInfo.Names[j]; if (pdbTupleElementNames == null) { Error("Tuple name info is null"); return null; } writer.WriteInt32(pdbTupleElementNames.TupleElementNames.Count); for (int k = 0; k < pdbTupleElementNames.TupleElementNames.Count; k++) { WriteUTF8Z(pdbTupleElementNames.TupleElementNames[k]); } if (pdbTupleElementNames.Local == null) { writer.WriteInt32(-1); writer.WriteUInt32(GetInstructionOffset(pdbTupleElementNames.ScopeStart, nullIsEndOfMethod: false)); writer.WriteUInt32(GetInstructionOffset(pdbTupleElementNames.ScopeEnd, nullIsEndOfMethod: true)); } else { writer.WriteInt32(pdbTupleElementNames.Local.Index); writer.WriteInt64(0L); } WriteUTF8Z(pdbTupleElementNames.Name); } break; } default: if (!(pdbCustomDebugInfo is PdbUnknownCustomDebugInfo pdbUnknownCustomDebugInfo)) { Error("Unsupported custom debug info class {0}", pdbCustomDebugInfo.GetType()); return null; } writer.WriteBytes(pdbUnknownCustomDebugInfo.Data); break; } long position2 = writer.Position; long num = position2 - position; long num2 = (num + 3) & -4; if (num2 > uint.MaxValue) { Error("Custom debug info record is too big"); return null; } writer.Position = position + 3; if (pdbCustomDebugInfo.Kind <= PdbCustomDebugInfoKind.DynamicLocals) { writer.WriteByte(0); } else { writer.WriteByte((byte)(num2 - num)); } writer.WriteUInt32((uint)num2); writer.Position = position2; while (writer.Position < position + num2) { writer.WriteByte(0); } } return memoryStream.ToArray(); } private string MetadataNameToRoslynName(string name) { if (name == null) { return name; } int num = name.LastIndexOf('`'); if (num < 0) { return name; } return name.Substring(0, num); } private void WriteUnicodeZ(string s) { if (s == null) { Error("String is null"); return; } if (s.IndexOf('\0') >= 0) { Error("String contains a NUL char: {0}", s); return; } for (int i = 0; i < s.Length; i++) { writer.WriteUInt16(s[i]); } writer.WriteUInt16(0); } private void WriteUTF8Z(string s) { if (s == null) { Error("String is null"); } else if (s.IndexOf('\0') >= 0) { Error("String contains a NUL char: {0}", s); } else { writer.WriteBytes(Encoding.UTF8.GetBytes(s)); writer.WriteByte(0); } } private uint GetMethodToken(IMethodDefOrRef method) { if (method == null) { Error("Method is null"); return 0u; } if (method is MethodDef methodDef) { uint rid = metadata.GetRid(methodDef); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, metadata.Module); return 0u; } return new MDToken(methodDef.MDToken.Table, rid).Raw; } if (method is MemberRef { IsMethodRef: not false } memberRef) { return metadata.GetToken(memberRef).Raw; } Error("Not a method"); return 0u; } } internal static class PseudoCustomDebugInfoFactory { public static PdbAsyncMethodCustomDebugInfo TryCreateAsyncMethod(ModuleDef module, MethodDef method, CilBody body, int asyncKickoffMethod, IList asyncStepInfos, uint? asyncCatchHandlerILOffset) { MDToken mdToken = new MDToken(asyncKickoffMethod); if (mdToken.Table != Table.Method) { return null; } MethodDef kickoffMethod = module.ResolveToken(mdToken) as MethodDef; PdbAsyncMethodCustomDebugInfo pdbAsyncMethodCustomDebugInfo = new PdbAsyncMethodCustomDebugInfo(asyncStepInfos.Count); pdbAsyncMethodCustomDebugInfo.KickoffMethod = kickoffMethod; if (asyncCatchHandlerILOffset.HasValue) { pdbAsyncMethodCustomDebugInfo.CatchHandlerInstruction = GetInstruction(body, asyncCatchHandlerILOffset.Value); } int count = asyncStepInfos.Count; for (int i = 0; i < count; i++) { SymbolAsyncStepInfo symbolAsyncStepInfo = asyncStepInfos[i]; Instruction instruction = GetInstruction(body, symbolAsyncStepInfo.YieldOffset); if (instruction == null) { continue; } MethodDef methodDef; Instruction instruction2; if (method.MDToken.Raw == symbolAsyncStepInfo.BreakpointMethod) { methodDef = method; instruction2 = GetInstruction(body, symbolAsyncStepInfo.BreakpointOffset); } else { MDToken mdToken2 = new MDToken(symbolAsyncStepInfo.BreakpointMethod); if (mdToken2.Table != Table.Method) { continue; } methodDef = module.ResolveToken(mdToken2) as MethodDef; if (methodDef == null) { continue; } instruction2 = GetInstruction(methodDef.Body, symbolAsyncStepInfo.BreakpointOffset); } if (instruction2 != null) { pdbAsyncMethodCustomDebugInfo.StepInfos.Add(new PdbAsyncStepInfo(instruction, methodDef, instruction2)); } } return pdbAsyncMethodCustomDebugInfo; } private static Instruction GetInstruction(CilBody body, uint offset) { if (body == null) { return null; } IList instructions = body.Instructions; int num = 0; int num2 = instructions.Count - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; Instruction instruction = instructions[num3]; if (instruction.Offset == offset) { return instruction; } if (offset < instruction.Offset) { num2 = num3 - 1; } else { num = num3 + 1; } } return null; } } internal abstract class SymbolWriter : IDisposable { public abstract bool IsDeterministic { get; } public abstract bool SupportsAsyncMethods { get; } public abstract void Initialize(dnlib.DotNet.Writer.Metadata metadata); public abstract void Close(); public abstract bool GetDebugInfo(ChecksumAlgorithm pdbChecksumAlgorithm, ref uint pdbAge, out Guid guid, out uint stamp, out IMAGE_DEBUG_DIRECTORY pIDD, out byte[] codeViewData); public abstract void SetUserEntryPoint(MDToken entryMethod); public abstract ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType); public abstract void SetSourceServerData(byte[] data); public abstract void SetSourceLinkData(byte[] data); public abstract void OpenMethod(MDToken method); public abstract void CloseMethod(); public abstract int OpenScope(int startOffset); public abstract void CloseScope(int endOffset); public abstract void SetSymAttribute(MDToken parent, string name, byte[] data); public abstract void UsingNamespace(string fullName); public abstract void DefineSequencePoints(ISymbolDocumentWriter document, uint arraySize, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns); public abstract void DefineLocalVariable(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3, uint startOffset, uint endOffset); public abstract void DefineConstant(string name, object value, uint sigToken); public abstract void DefineKickoffMethod(uint kickoffMethod); public abstract void DefineCatchHandlerILOffset(uint catchHandlerOffset); public abstract void DefineAsyncStepInfo(uint[] yieldOffsets, uint[] breakpointOffset, uint[] breakpointMethod); public abstract void Dispose(); } internal sealed class WindowsPdbWriter : IDisposable { private sealed class SequencePointHelper { private readonly Dictionary checkedPdbDocs = new Dictionary(); private int[] instrOffsets = Array2.Empty(); private int[] startLines; private int[] startColumns; private int[] endLines; private int[] endColumns; public void Write(WindowsPdbWriter pdbWriter, IList instrs) { checkedPdbDocs.Clear(); while (true) { PdbDocument pdbDocument = null; bool flag = false; int num = 0; int i = 0; Instruction instruction = null; for (int j = 0; j < instrs.Count; j++, i += instruction.GetSize()) { instruction = instrs[j]; SequencePoint sequencePoint = instruction.SequencePoint; if (sequencePoint == null || sequencePoint.Document == null || checkedPdbDocs.ContainsKey(sequencePoint.Document)) { continue; } if (pdbDocument == null) { pdbDocument = sequencePoint.Document; } else if (pdbDocument != sequencePoint.Document) { flag = true; continue; } if (num >= instrOffsets.Length) { int num2 = num * 2; if (num2 < 64) { num2 = 64; } Array.Resize(ref instrOffsets, num2); Array.Resize(ref startLines, num2); Array.Resize(ref startColumns, num2); Array.Resize(ref endLines, num2); Array.Resize(ref endColumns, num2); } instrOffsets[num] = i; startLines[num] = sequencePoint.StartLine; startColumns[num] = sequencePoint.StartColumn; endLines[num] = sequencePoint.EndLine; endColumns[num] = sequencePoint.EndColumn; num++; } if (num != 0) { pdbWriter.writer.DefineSequencePoints(pdbWriter.Add(pdbDocument), (uint)num, instrOffsets, startLines, startColumns, endLines, endColumns); } if (flag) { if (pdbDocument != null) { checkedPdbDocs.Add(pdbDocument, value: true); } continue; } break; } } } private struct CurrentMethod { private readonly WindowsPdbWriter pdbWriter; public readonly MethodDef Method; private readonly Dictionary toOffset; public readonly uint BodySize; public CurrentMethod(WindowsPdbWriter pdbWriter, MethodDef method, Dictionary toOffset) { this.pdbWriter = pdbWriter; Method = method; this.toOffset = toOffset; toOffset.Clear(); uint num = 0u; IList instructions = method.Body.Instructions; int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; toOffset[instruction] = num; num += (uint)instruction.GetSize(); } BodySize = num; } public readonly int GetOffset(Instruction instr) { if (instr == null) { return (int)BodySize; } if (toOffset.TryGetValue(instr, out var value)) { return (int)value; } pdbWriter.Error("Instruction was removed from the body but is referenced from PdbScope: {0}", instr); return (int)BodySize; } } private SymbolWriter writer; private readonly PdbState pdbState; private readonly ModuleDef module; private readonly dnlib.DotNet.Writer.Metadata metadata; private readonly Dictionary pdbDocs = new Dictionary(); private readonly SequencePointHelper seqPointsHelper = new SequencePointHelper(); private readonly Dictionary instrToOffset; private readonly PdbCustomDebugInfoWriterContext customDebugInfoWriterContext; private readonly int localsEndScopeIncValue; private static readonly object boxedZeroInt32 = 0; public ILogger Logger { get; set; } public WindowsPdbWriter(SymbolWriter writer, PdbState pdbState, dnlib.DotNet.Writer.Metadata metadata) : this(pdbState, metadata) { if (pdbState == null) { throw new ArgumentNullException("pdbState"); } if (metadata == null) { throw new ArgumentNullException("metadata"); } this.writer = writer ?? throw new ArgumentNullException("writer"); writer.Initialize(metadata); } private WindowsPdbWriter(PdbState pdbState, dnlib.DotNet.Writer.Metadata metadata) { this.pdbState = pdbState; this.metadata = metadata; module = metadata.Module; instrToOffset = new Dictionary(); customDebugInfoWriterContext = new PdbCustomDebugInfoWriterContext(); localsEndScopeIncValue = (PdbUtils.IsEndInclusive(PdbFileKind.WindowsPDB, pdbState.Compiler) ? 1 : 0); } private ISymbolDocumentWriter Add(PdbDocument pdbDoc) { if (pdbDocs.TryGetValue(pdbDoc, out var value)) { return value; } value = writer.DefineDocument(pdbDoc.Url, pdbDoc.Language, pdbDoc.LanguageVendor, pdbDoc.DocumentType); value.SetCheckSum(pdbDoc.CheckSumAlgorithmId, pdbDoc.CheckSum); if (TryGetCustomDebugInfo(pdbDoc, out var cdi)) { value.SetSource(cdi.SourceCodeBlob); } pdbDocs.Add(pdbDoc, value); return value; } private static bool TryGetCustomDebugInfo(IHasCustomDebugInformation hci, out TCDI cdi) where TCDI : PdbCustomDebugInfo { IList customDebugInfos = hci.CustomDebugInfos; int count = customDebugInfos.Count; for (int i = 0; i < count; i++) { if (customDebugInfos[i] is TCDI val) { cdi = val; return true; } } cdi = null; return false; } public void Write() { writer.SetUserEntryPoint(GetUserEntryPointToken()); List cdiBuilder = new List(); foreach (TypeDef type in module.GetTypes()) { if (type == null) { continue; } IList methods = type.Methods; int count = methods.Count; for (int i = 0; i < count; i++) { MethodDef methodDef = methods[i]; if (methodDef != null && ShouldAddMethod(methodDef)) { Write(methodDef, cdiBuilder); } } } if (TryGetCustomDebugInfo(module, out var cdi)) { writer.SetSourceLinkData(cdi.FileBlob); } if (TryGetCustomDebugInfo(module, out var cdi2)) { writer.SetSourceServerData(cdi2.FileBlob); } } private bool ShouldAddMethod(MethodDef method) { CilBody body = method.Body; if (body == null) { return false; } if (body.HasPdbMethod) { return true; } LocalList variables = body.Variables; int count = variables.Count; for (int i = 0; i < count; i++) { Local local = variables[i]; if (local.Name != null) { return true; } if (local.Attributes != PdbLocalAttributes.None) { return true; } } IList instructions = body.Instructions; count = instructions.Count; for (int j = 0; j < count; j++) { if (instructions[j].SequencePoint != null) { return true; } } return false; } private void Write(MethodDef method, List cdiBuilder) { uint rid = metadata.GetRid(method); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, module); return; } CurrentMethod info = new CurrentMethod(this, method, instrToOffset); CilBody body = method.Body; MDToken mDToken = new MDToken(Table.Method, rid); writer.OpenMethod(mDToken); seqPointsHelper.Write(this, info.Method.Body.Instructions); PdbMethod pdbMethod = body.PdbMethod; if (pdbMethod == null) { pdbMethod = (body.PdbMethod = new PdbMethod()); } PdbScope pdbScope = pdbMethod.Scope; if (pdbScope == null) { pdbScope = (pdbMethod.Scope = new PdbScope()); } if (pdbScope.Namespaces.Count == 0 && pdbScope.Variables.Count == 0 && pdbScope.Constants.Count == 0) { if (pdbScope.Scopes.Count == 0) { writer.OpenScope(0); writer.CloseScope((int)info.BodySize); } else { IList scopes = pdbScope.Scopes; int count = scopes.Count; for (int i = 0; i < count; i++) { WriteScope(ref info, scopes[i], 0); } } } else { WriteScope(ref info, pdbScope, 0); } GetPseudoCustomDebugInfos(method.CustomDebugInfos, cdiBuilder, out var asyncMethod); if (cdiBuilder.Count != 0) { customDebugInfoWriterContext.Logger = GetLogger(); byte[] array = PdbCustomDebugInfoWriter.Write(metadata, method, customDebugInfoWriterContext, cdiBuilder); if (array != null) { writer.SetSymAttribute(mDToken, "MD2", array); } } if (asyncMethod != null) { if (!writer.SupportsAsyncMethods) { Error("PDB symbol writer doesn't support writing async methods"); } else { WriteAsyncMethod(ref info, asyncMethod); } } writer.CloseMethod(); } private void GetPseudoCustomDebugInfos(IList customDebugInfos, List cdiBuilder, out PdbAsyncMethodCustomDebugInfo asyncMethod) { cdiBuilder.Clear(); asyncMethod = null; int count = customDebugInfos.Count; for (int i = 0; i < count; i++) { PdbCustomDebugInfo pdbCustomDebugInfo = customDebugInfos[i]; if (pdbCustomDebugInfo.Kind == PdbCustomDebugInfoKind.AsyncMethod) { if (asyncMethod != null) { Error("Duplicate async method custom debug info"); } else { asyncMethod = (PdbAsyncMethodCustomDebugInfo)pdbCustomDebugInfo; } } else if ((uint)pdbCustomDebugInfo.Kind > 255u) { Error("Custom debug info {0} isn't supported by Windows PDB files", pdbCustomDebugInfo.Kind); } else { cdiBuilder.Add(pdbCustomDebugInfo); } } } private uint GetMethodToken(MethodDef method) { uint rid = metadata.GetRid(method); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, module); } return new MDToken(Table.Method, rid).Raw; } private void WriteAsyncMethod(ref CurrentMethod info, PdbAsyncMethodCustomDebugInfo asyncMethod) { if (asyncMethod.KickoffMethod == null) { Error("KickoffMethod is null"); return; } uint methodToken = GetMethodToken(asyncMethod.KickoffMethod); writer.DefineKickoffMethod(methodToken); if (asyncMethod.CatchHandlerInstruction != null) { int offset = info.GetOffset(asyncMethod.CatchHandlerInstruction); writer.DefineCatchHandlerILOffset((uint)offset); } IList stepInfos = asyncMethod.StepInfos; uint[] array = new uint[stepInfos.Count]; uint[] array2 = new uint[stepInfos.Count]; uint[] array3 = new uint[stepInfos.Count]; for (int i = 0; i < array.Length; i++) { PdbAsyncStepInfo pdbAsyncStepInfo = stepInfos[i]; if (pdbAsyncStepInfo.YieldInstruction == null) { Error("YieldInstruction is null"); return; } if (pdbAsyncStepInfo.BreakpointMethod == null) { Error("BreakpointMethod is null"); return; } if (pdbAsyncStepInfo.BreakpointInstruction == null) { Error("BreakpointInstruction is null"); return; } array[i] = (uint)info.GetOffset(pdbAsyncStepInfo.YieldInstruction); array2[i] = (uint)GetExternalInstructionOffset(ref info, pdbAsyncStepInfo.BreakpointMethod, pdbAsyncStepInfo.BreakpointInstruction); array3[i] = GetMethodToken(pdbAsyncStepInfo.BreakpointMethod); } writer.DefineAsyncStepInfo(array, array2, array3); } private int GetExternalInstructionOffset(ref CurrentMethod info, MethodDef method, Instruction instr) { if (info.Method == method) { return info.GetOffset(instr); } CilBody body = method.Body; if (body == null) { Error("Method body is null"); return 0; } IList instructions = body.Instructions; int num = 0; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; if (instruction == instr) { return num; } num += instruction.GetSize(); } if (instr == null) { return num; } Error("Async method instruction has been removed but it's still being referenced by PDB info: BP Instruction: {0}, BP Method: {1} (0x{2:X8}), Current Method: {3} (0x{4:X8})", instr, method, method.MDToken.Raw, info.Method, info.Method.MDToken.Raw); return 0; } private void WriteScope(ref CurrentMethod info, PdbScope scope, int recursionCounter) { if (recursionCounter >= 1000) { Error("Too many PdbScopes"); return; } int offset = info.GetOffset(scope.Start); int offset2 = info.GetOffset(scope.End); writer.OpenScope(offset); AddLocals(info.Method, scope.Variables, (uint)offset, (uint)offset2); if (scope.Constants.Count > 0) { IList constants = scope.Constants; FieldSig fieldSig = new FieldSig(); for (int i = 0; i < constants.Count; i++) { PdbConstant pdbConstant = constants[i]; fieldSig.Type = pdbConstant.Type; MDToken token = metadata.GetToken(fieldSig); writer.DefineConstant(pdbConstant.Name, pdbConstant.Value ?? boxedZeroInt32, token.Raw); } } IList namespaces = scope.Namespaces; int count = namespaces.Count; for (int j = 0; j < count; j++) { writer.UsingNamespace(namespaces[j]); } IList scopes = scope.Scopes; count = scopes.Count; for (int k = 0; k < count; k++) { WriteScope(ref info, scopes[k], recursionCounter + 1); } writer.CloseScope((offset == 0 && offset2 == info.BodySize) ? offset2 : (offset2 - localsEndScopeIncValue)); } private void AddLocals(MethodDef method, IList locals, uint startOffset, uint endOffset) { if (locals.Count == 0) { return; } uint localVarSigToken = metadata.GetLocalVarSigToken(method); if (localVarSigToken == 0) { Error("Method {0} ({1:X8}) has no local signature token", method, method.MDToken.Raw); return; } int count = locals.Count; for (int i = 0; i < count; i++) { PdbLocal pdbLocal = locals[i]; uint pdbLocalFlags = GetPdbLocalFlags(pdbLocal.Attributes); if (pdbLocalFlags != 0 || pdbLocal.Name != null) { writer.DefineLocalVariable(pdbLocal.Name ?? string.Empty, pdbLocalFlags, localVarSigToken, 1u, (uint)pdbLocal.Index, 0u, 0u, startOffset, endOffset); } } } private static uint GetPdbLocalFlags(PdbLocalAttributes attributes) { if ((attributes & PdbLocalAttributes.DebuggerHidden) != PdbLocalAttributes.None) { return 1u; } return 0u; } private MDToken GetUserEntryPointToken() { MethodDef userEntryPoint = pdbState.UserEntryPoint; if (userEntryPoint == null) { return default(MDToken); } uint rid = metadata.GetRid(userEntryPoint); if (rid == 0) { Error("PDB user entry point method {0} ({1:X8}) is not defined in this module ({2})", userEntryPoint, userEntryPoint.MDToken.Raw, module); return default(MDToken); } return new MDToken(Table.Method, rid); } public bool GetDebugInfo(ChecksumAlgorithm pdbChecksumAlgorithm, ref uint pdbAge, out Guid guid, out uint stamp, out IMAGE_DEBUG_DIRECTORY idd, out byte[] codeViewData) { return writer.GetDebugInfo(pdbChecksumAlgorithm, ref pdbAge, out guid, out stamp, out idd, out codeViewData); } public void Close() { writer.Close(); } private ILogger GetLogger() { return Logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } private void Error(string message, params object[] args) { GetLogger().Log(this, LoggerEvent.Error, message, args); } public void Dispose() { if (writer != null) { Close(); } writer?.Dispose(); writer = null; } } } namespace dnlib.DotNet.Pdb.Symbols { public struct SymbolAsyncStepInfo { public uint YieldOffset; public uint BreakpointOffset; public uint BreakpointMethod; public SymbolAsyncStepInfo(uint yieldOffset, uint breakpointOffset, uint breakpointMethod) { YieldOffset = yieldOffset; BreakpointOffset = breakpointOffset; BreakpointMethod = breakpointMethod; } } public abstract class SymbolDocument { public abstract string URL { get; } public abstract Guid Language { get; } public abstract Guid LanguageVendor { get; } public abstract Guid DocumentType { get; } public abstract Guid CheckSumAlgorithmId { get; } public abstract byte[] CheckSum { get; } public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; } public abstract MDToken? MDToken { get; } } public abstract class SymbolMethod { public abstract int Token { get; } public abstract SymbolScope RootScope { get; } public abstract IList SequencePoints { get; } public abstract void GetCustomDebugInfos(MethodDef method, CilBody body, IList result); } public abstract class SymbolNamespace { public abstract string Name { get; } } public abstract class SymbolReader : IDisposable { public abstract PdbFileKind PdbFileKind { get; } public abstract int UserEntryPoint { get; } public abstract IList Documents { get; } public abstract void Initialize(ModuleDef module); public abstract SymbolMethod GetMethod(MethodDef method, int version); public abstract void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result); public virtual void Dispose() { } } public abstract class SymbolScope { public abstract SymbolMethod Method { get; } public abstract SymbolScope Parent { get; } public abstract int StartOffset { get; } public abstract int EndOffset { get; } public abstract IList Children { get; } public abstract IList Locals { get; } public abstract IList Namespaces { get; } public abstract IList CustomDebugInfos { get; } public abstract PdbImportScope ImportScope { get; } public abstract IList GetConstants(ModuleDef module, GenericParamContext gpContext); } [DebuggerDisplay("{GetDebuggerString(),nq}")] public struct SymbolSequencePoint { public int Offset; public SymbolDocument Document; public int Line; public int Column; public int EndLine; public int EndColumn; private readonly string GetDebuggerString() { StringBuilder stringBuilder = new StringBuilder(); if (Line == 16707566 && EndLine == 16707566) { stringBuilder.Append(""); } else { stringBuilder.Append("("); stringBuilder.Append(Line); stringBuilder.Append(","); stringBuilder.Append(Column); stringBuilder.Append(")-("); stringBuilder.Append(EndLine); stringBuilder.Append(","); stringBuilder.Append(EndColumn); stringBuilder.Append(")"); } stringBuilder.Append(": "); stringBuilder.Append(Document.URL); return stringBuilder.ToString(); } } public abstract class SymbolVariable { public abstract string Name { get; } public abstract PdbLocalAttributes Attributes { get; } public abstract int Index { get; } public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; } } } namespace dnlib.DotNet.Pdb.Portable { internal struct DocumentNameReader { private const int MAX_NAME_LENGTH = 65536; private readonly Dictionary docNamePartDict; private readonly BlobStream blobStream; private readonly StringBuilder sb; private char[] prevSepChars; private int prevSepCharsLength; private byte[] prevSepCharBytes; private int prevSepCharBytesCount; public DocumentNameReader(BlobStream blobStream) { docNamePartDict = new Dictionary(); this.blobStream = blobStream; sb = new StringBuilder(); prevSepChars = new char[2]; prevSepCharsLength = 0; prevSepCharBytes = new byte[3]; prevSepCharBytesCount = 0; } public string ReadDocumentName(uint offset) { sb.Length = 0; if (!blobStream.TryCreateReader(offset, out var reader)) { return string.Empty; } int charLength; char[] array = ReadSeparatorChar(ref reader, out charLength); bool flag = false; while (reader.Position < reader.Length) { if (flag) { sb.Append(array, 0, charLength); } flag = charLength != 1 || array[0] != '\0'; string value = ReadDocumentNamePart(reader.ReadCompressedUInt32()); sb.Append(value); if (sb.Length > 65536) { sb.Length = 65536; break; } } return sb.ToString(); } private string ReadDocumentNamePart(uint offset) { if (docNamePartDict.TryGetValue(offset, out var value)) { return value; } if (!blobStream.TryCreateReader(offset, out var reader)) { return string.Empty; } value = reader.ReadUtf8String((int)reader.BytesLeft); docNamePartDict.Add(offset, value); return value; } private char[] ReadSeparatorChar(ref DataReader reader, out int charLength) { if (prevSepCharBytesCount != 0 && prevSepCharBytesCount <= reader.Length) { uint position = reader.Position; bool flag = true; for (int i = 0; i < prevSepCharBytesCount; i++) { if (i >= prevSepCharBytes.Length || reader.ReadByte() != prevSepCharBytes[i]) { flag = false; break; } } if (flag) { charLength = prevSepCharsLength; return prevSepChars; } reader.Position = position; } Decoder decoder = Encoding.UTF8.GetDecoder(); byte[] array = new byte[1]; prevSepCharBytesCount = 0; int num = 0; while (true) { byte b = reader.ReadByte(); prevSepCharBytesCount++; if (num == 0 && b == 0) { break; } if (num < prevSepCharBytes.Length) { prevSepCharBytes[num] = b; } array[0] = b; bool flush = reader.Position + 1 == reader.Length; decoder.Convert(array, 0, 1, prevSepChars, 0, prevSepChars.Length, flush, out var _, out prevSepCharsLength, out var _); if (prevSepCharsLength > 0) { break; } num++; } charLength = prevSepCharsLength; return prevSepChars; } } internal static class ImportDefinitionKindUtils { public const PdbImportDefinitionKind UNKNOWN_IMPORT_KIND = (PdbImportDefinitionKind)(-1); public static PdbImportDefinitionKind ToPdbImportDefinitionKind(uint value) { return value switch { 1u => PdbImportDefinitionKind.ImportNamespace, 2u => PdbImportDefinitionKind.ImportAssemblyNamespace, 3u => PdbImportDefinitionKind.ImportType, 4u => PdbImportDefinitionKind.ImportXmlNamespace, 5u => PdbImportDefinitionKind.ImportAssemblyReferenceAlias, 6u => PdbImportDefinitionKind.AliasAssemblyReference, 7u => PdbImportDefinitionKind.AliasNamespace, 8u => PdbImportDefinitionKind.AliasAssemblyNamespace, 9u => PdbImportDefinitionKind.AliasType, _ => (PdbImportDefinitionKind)(-1), }; } public static bool ToImportDefinitionKind(PdbImportDefinitionKind kind, out uint rawKind) { switch (kind) { case PdbImportDefinitionKind.ImportNamespace: rawKind = 1u; return true; case PdbImportDefinitionKind.ImportAssemblyNamespace: rawKind = 2u; return true; case PdbImportDefinitionKind.ImportType: rawKind = 3u; return true; case PdbImportDefinitionKind.ImportXmlNamespace: rawKind = 4u; return true; case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: rawKind = 5u; return true; case PdbImportDefinitionKind.AliasAssemblyReference: rawKind = 6u; return true; case PdbImportDefinitionKind.AliasNamespace: rawKind = 7u; return true; case PdbImportDefinitionKind.AliasAssemblyNamespace: rawKind = 8u; return true; case PdbImportDefinitionKind.AliasType: rawKind = 9u; return true; default: rawKind = uint.MaxValue; return false; } } } internal readonly struct ImportScopeBlobReader { private readonly ModuleDef module; private readonly BlobStream blobStream; public ImportScopeBlobReader(ModuleDef module, BlobStream blobStream) { this.module = module; this.blobStream = blobStream; } public void Read(uint imports, IList result) { if (imports == 0 || !blobStream.TryCreateReader(imports, out var reader)) { return; } while (reader.Position < reader.Length) { PdbImport pdbImport; switch (ImportDefinitionKindUtils.ToPdbImportDefinitionKind(reader.ReadCompressedUInt32())) { case PdbImportDefinitionKind.ImportNamespace: { string targetNamespace = ReadUTF8(reader.ReadCompressedUInt32()); pdbImport = new PdbImportNamespace(targetNamespace); break; } case PdbImportDefinitionKind.ImportAssemblyNamespace: { AssemblyRef targetAssembly = TryReadAssemblyRef(reader.ReadCompressedUInt32()); string targetNamespace = ReadUTF8(reader.ReadCompressedUInt32()); pdbImport = new PdbImportAssemblyNamespace(targetAssembly, targetNamespace); break; } case PdbImportDefinitionKind.ImportType: { ITypeDefOrRef targetType = TryReadType(reader.ReadCompressedUInt32()); pdbImport = new PdbImportType(targetType); break; } case PdbImportDefinitionKind.ImportXmlNamespace: { string alias5 = ReadUTF8(reader.ReadCompressedUInt32()); string targetNamespace = ReadUTF8(reader.ReadCompressedUInt32()); pdbImport = new PdbImportXmlNamespace(alias5, targetNamespace); break; } case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: pdbImport = new PdbImportAssemblyReferenceAlias(ReadUTF8(reader.ReadCompressedUInt32())); break; case PdbImportDefinitionKind.AliasAssemblyReference: { string alias4 = ReadUTF8(reader.ReadCompressedUInt32()); AssemblyRef targetAssembly = TryReadAssemblyRef(reader.ReadCompressedUInt32()); pdbImport = new PdbAliasAssemblyReference(alias4, targetAssembly); break; } case PdbImportDefinitionKind.AliasNamespace: { string alias3 = ReadUTF8(reader.ReadCompressedUInt32()); string targetNamespace = ReadUTF8(reader.ReadCompressedUInt32()); pdbImport = new PdbAliasNamespace(alias3, targetNamespace); break; } case PdbImportDefinitionKind.AliasAssemblyNamespace: { string alias2 = ReadUTF8(reader.ReadCompressedUInt32()); AssemblyRef targetAssembly = TryReadAssemblyRef(reader.ReadCompressedUInt32()); string targetNamespace = ReadUTF8(reader.ReadCompressedUInt32()); pdbImport = new PdbAliasAssemblyNamespace(alias2, targetAssembly, targetNamespace); break; } case PdbImportDefinitionKind.AliasType: { string alias = ReadUTF8(reader.ReadCompressedUInt32()); ITypeDefOrRef targetType = TryReadType(reader.ReadCompressedUInt32()); pdbImport = new PdbAliasType(alias, targetType); break; } case (PdbImportDefinitionKind)(-1): pdbImport = null; break; default: pdbImport = null; break; } if (pdbImport != null) { result.Add(pdbImport); } } } private ITypeDefOrRef TryReadType(uint codedToken) { if (!CodedToken.TypeDefOrRef.Decode(codedToken, out uint token)) { return null; } return module.ResolveToken(token) as ITypeDefOrRef; } private AssemblyRef TryReadAssemblyRef(uint rid) { return module.ResolveToken(587202560 + rid) as AssemblyRef; } private string ReadUTF8(uint offset) { if (!blobStream.TryCreateReader(offset, out var reader)) { return string.Empty; } return reader.ReadUtf8String((int)reader.BytesLeft); } } internal readonly struct ImportScopeBlobWriter { private readonly IWriterError helper; private readonly dnlib.DotNet.Writer.Metadata systemMetadata; private readonly BlobHeap blobHeap; private ImportScopeBlobWriter(IWriterError helper, dnlib.DotNet.Writer.Metadata systemMetadata, BlobHeap blobHeap) { this.helper = helper; this.systemMetadata = systemMetadata; this.blobHeap = blobHeap; } public static void Write(IWriterError helper, dnlib.DotNet.Writer.Metadata systemMetadata, DataWriter writer, BlobHeap blobHeap, IList imports) { new ImportScopeBlobWriter(helper, systemMetadata, blobHeap).Write(writer, imports); } private uint WriteUTF8(string s) { if (s == null) { helper.Error("String is null"); s = string.Empty; } byte[] bytes = Encoding.UTF8.GetBytes(s); return blobHeap.Add(bytes); } private void Write(DataWriter writer, IList imports) { int count = imports.Count; for (int i = 0; i < count; i++) { PdbImport pdbImport = imports[i]; if (!ImportDefinitionKindUtils.ToImportDefinitionKind(pdbImport.Kind, out var rawKind)) { helper.Error2("Unknown import definition kind: {0}.", pdbImport.Kind); break; } writer.WriteCompressedUInt32(rawKind); switch (pdbImport.Kind) { case PdbImportDefinitionKind.ImportNamespace: writer.WriteCompressedUInt32(WriteUTF8(((PdbImportNamespace)pdbImport).TargetNamespace)); break; case PdbImportDefinitionKind.ImportAssemblyNamespace: writer.WriteCompressedUInt32(systemMetadata.GetToken(((PdbImportAssemblyNamespace)pdbImport).TargetAssembly).Rid); writer.WriteCompressedUInt32(WriteUTF8(((PdbImportAssemblyNamespace)pdbImport).TargetNamespace)); break; case PdbImportDefinitionKind.ImportType: writer.WriteCompressedUInt32(GetTypeDefOrRefEncodedToken(((PdbImportType)pdbImport).TargetType)); break; case PdbImportDefinitionKind.ImportXmlNamespace: writer.WriteCompressedUInt32(WriteUTF8(((PdbImportXmlNamespace)pdbImport).Alias)); writer.WriteCompressedUInt32(WriteUTF8(((PdbImportXmlNamespace)pdbImport).TargetNamespace)); break; case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: writer.WriteCompressedUInt32(WriteUTF8(((PdbImportAssemblyReferenceAlias)pdbImport).Alias)); break; case PdbImportDefinitionKind.AliasAssemblyReference: writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyReference)pdbImport).Alias)); writer.WriteCompressedUInt32(systemMetadata.GetToken(((PdbAliasAssemblyReference)pdbImport).TargetAssembly).Rid); break; case PdbImportDefinitionKind.AliasNamespace: writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasNamespace)pdbImport).Alias)); writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasNamespace)pdbImport).TargetNamespace)); break; case PdbImportDefinitionKind.AliasAssemblyNamespace: writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyNamespace)pdbImport).Alias)); writer.WriteCompressedUInt32(systemMetadata.GetToken(((PdbAliasAssemblyNamespace)pdbImport).TargetAssembly).Rid); writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyNamespace)pdbImport).TargetNamespace)); break; case PdbImportDefinitionKind.AliasType: writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasType)pdbImport).Alias)); writer.WriteCompressedUInt32(GetTypeDefOrRefEncodedToken(((PdbAliasType)pdbImport).TargetType)); break; default: helper.Error2("Unknown import definition kind: {0}.", pdbImport.Kind); return; } } } private uint GetTypeDefOrRefEncodedToken(ITypeDefOrRef tdr) { if (tdr == null) { helper.Error("ITypeDefOrRef is null"); return 0u; } MDToken token = systemMetadata.GetToken(tdr); if (CodedToken.TypeDefOrRef.Encode(token, out var codedToken)) { return codedToken; } helper.Error2("Could not encode token 0x{0:X8}.", token.Raw); return 0u; } } internal static class ListCache { private static volatile List cachedList; public static List AllocList() { return Interlocked.Exchange(ref cachedList, null) ?? new List(); } public static void Free(ref List list) { list.Clear(); cachedList = list; } public static T[] FreeAndToArray(ref List list) { T[] result = list.ToArray(); Free(ref list); return result; } } internal struct LocalConstantSigBlobReader { private readonly ModuleDef module; private DataReader reader; private readonly GenericParamContext gpContext; private RecursionCounter recursionCounter; private static readonly UTF8String stringSystem = new UTF8String("System"); private static readonly UTF8String stringDecimal = new UTF8String("Decimal"); private static readonly UTF8String stringDateTime = new UTF8String("DateTime"); public LocalConstantSigBlobReader(ModuleDef module, ref DataReader reader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.gpContext = gpContext; recursionCounter = default(RecursionCounter); } public bool Read(out TypeSig type, out object value) { return ReadCatch(out type, out value); } private bool ReadCatch(out TypeSig type, out object value) { try { return ReadCore(out type, out value); } catch { } type = null; value = null; return false; } private bool ReadCore(out TypeSig type, out object value) { if (!recursionCounter.Increment()) { type = null; value = null; return false; } bool flag; switch ((ElementType)reader.ReadByte()) { case ElementType.Boolean: type = module.CorLibTypes.Boolean; value = reader.ReadBoolean(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.Char: type = module.CorLibTypes.Char; value = reader.ReadChar(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.I1: type = module.CorLibTypes.SByte; value = reader.ReadSByte(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.U1: type = module.CorLibTypes.Byte; value = reader.ReadByte(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.I2: type = module.CorLibTypes.Int16; value = reader.ReadInt16(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.U2: type = module.CorLibTypes.UInt16; value = reader.ReadUInt16(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.I4: type = module.CorLibTypes.Int32; value = reader.ReadInt32(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.U4: type = module.CorLibTypes.UInt32; value = reader.ReadUInt32(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.I8: type = module.CorLibTypes.Int64; value = reader.ReadInt64(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.U8: type = module.CorLibTypes.UInt64; value = reader.ReadUInt64(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } flag = true; break; case ElementType.R4: type = module.CorLibTypes.Single; value = reader.ReadSingle(); flag = true; break; case ElementType.R8: type = module.CorLibTypes.Double; value = reader.ReadDouble(); flag = true; break; case ElementType.String: type = module.CorLibTypes.String; value = ReadString(); flag = true; break; case ElementType.Ptr: flag = ReadCatch(out type, out value); if (flag) { type = new PtrSig(type); } break; case ElementType.ByRef: flag = ReadCatch(out type, out value); if (flag) { type = new ByRefSig(type); } break; case ElementType.Object: type = module.CorLibTypes.Object; value = null; flag = true; break; case ElementType.ValueType: { ITypeDefOrRef modifier = ReadTypeDefOrRef(); type = modifier.ToTypeSig(); value = null; if (GetName(modifier, out var @namespace, out var name) && @namespace == stringSystem && modifier.DefinitionAssembly.IsCorLib()) { if (name == stringDecimal) { if (reader.Length - reader.Position != 13) { goto default; } try { byte b = reader.ReadByte(); value = new decimal(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), (b & 0x80) != 0, (byte)(b & 0x7F)); } catch { goto default; } } else if (name == stringDateTime) { if (reader.Length - reader.Position != 8) { goto default; } try { value = new DateTime(reader.ReadInt64()); } catch { goto default; } } } if (value == null && reader.Position != reader.Length) { value = reader.ReadRemainingBytes(); } flag = true; break; } case ElementType.Class: type = new ClassSig(ReadTypeDefOrRef()); value = ((reader.Position == reader.Length) ? null : reader.ReadRemainingBytes()); flag = true; break; case ElementType.CModReqd: { ITypeDefOrRef modifier = ReadTypeDefOrRef(); flag = ReadCatch(out type, out value); if (flag) { type = new CModReqdSig(modifier, type); } break; } case ElementType.CModOpt: { ITypeDefOrRef modifier = ReadTypeDefOrRef(); flag = ReadCatch(out type, out value); if (flag) { type = new CModOptSig(modifier, type); } break; } default: flag = false; type = null; value = null; break; } recursionCounter.Decrement(); return flag; } private static bool GetName(ITypeDefOrRef tdr, out UTF8String @namespace, out UTF8String name) { if (tdr is TypeRef typeRef) { @namespace = typeRef.Namespace; name = typeRef.Name; return true; } if (tdr is TypeDef typeDef) { @namespace = typeDef.Namespace; name = typeDef.Name; return true; } @namespace = null; name = null; return false; } private TypeSig ReadTypeDefOrRefSig() { if (!reader.TryReadCompressedUInt32(out var value)) { return null; } return ((ISignatureReaderHelper)module).ResolveTypeDefOrRef(value, gpContext).ToTypeSig(); } private ITypeDefOrRef ReadTypeDefOrRef() { if (!reader.TryReadCompressedUInt32(out var value)) { return null; } ITypeDefOrRef typeDefOrRef = ((ISignatureReaderHelper)module).ResolveTypeDefOrRef(value, gpContext); CorLibTypeSig corLibTypeSig = module.CorLibTypes.GetCorLibTypeSig(typeDefOrRef); if (corLibTypeSig != null) { return corLibTypeSig.TypeDefOrRef; } return typeDefOrRef; } private string ReadString() { if (reader.Position == reader.Length) { return string.Empty; } if (reader.ReadByte() == byte.MaxValue && reader.Position == reader.Length) { return null; } reader.Position--; return reader.ReadUtf16String((int)(reader.BytesLeft / 2)); } } internal readonly struct LocalConstantSigBlobWriter { private readonly IWriterError helper; private readonly dnlib.DotNet.Writer.Metadata systemMetadata; private static readonly UTF8String stringSystem = new UTF8String("System"); private static readonly UTF8String stringDecimal = new UTF8String("Decimal"); private static readonly UTF8String stringDateTime = new UTF8String("DateTime"); private LocalConstantSigBlobWriter(IWriterError helper, dnlib.DotNet.Writer.Metadata systemMetadata) { this.helper = helper; this.systemMetadata = systemMetadata; } public static void Write(IWriterError helper, dnlib.DotNet.Writer.Metadata systemMetadata, DataWriter writer, TypeSig type, object value) { new LocalConstantSigBlobWriter(helper, systemMetadata).Write(writer, type, value); } private void Write(DataWriter writer, TypeSig type, object value) { while (type != null) { ElementType elementType = type.ElementType; writer.WriteByte((byte)elementType); switch (elementType) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: WritePrimitiveValue(writer, elementType, value); return; case ElementType.R4: if (value is float) { writer.WriteSingle((float)value); return; } helper.Error("Expected a Single constant"); writer.WriteSingle(0f); return; case ElementType.R8: if (value is double) { writer.WriteDouble((double)value); return; } helper.Error("Expected a Double constant"); writer.WriteDouble(0.0); return; case ElementType.String: if (value == null) { writer.WriteByte(byte.MaxValue); } else if (value is string) { writer.WriteBytes(Encoding.Unicode.GetBytes((string)value)); } else { helper.Error("Expected a String constant"); } return; case ElementType.Ptr: case ElementType.ByRef: WriteTypeDefOrRef(writer, new TypeSpecUser(type)); return; case ElementType.Object: return; case ElementType.ValueType: { ITypeDefOrRef typeDefOrRef = ((ValueTypeSig)type).TypeDefOrRef; TypeDef typeDef = typeDefOrRef.ResolveTypeDef(); if (typeDef == null) { helper.Error2("Couldn't resolve type 0x{0:X8}.", typeDefOrRef?.MDToken.Raw ?? 0); return; } if (typeDef.IsEnum) { TypeSig a = typeDef.GetEnumUnderlyingType().RemovePinnedAndModifiers(); ElementType elementType2 = a.GetElementType(); if (elementType2 - 2 <= ElementType.U4) { writer.Position--; writer.WriteByte((byte)a.GetElementType()); WritePrimitiveValue(writer, a.GetElementType(), value); WriteTypeDefOrRef(writer, typeDefOrRef); } else { helper.Error("Invalid enum underlying type"); } return; } WriteTypeDefOrRef(writer, typeDefOrRef); bool flag = false; if (GetName(typeDefOrRef, out var @namespace, out var name) && @namespace == stringSystem && typeDefOrRef.DefinitionAssembly.IsCorLib()) { if (name == stringDecimal) { if (value is decimal) { int[] bits = decimal.GetBits((decimal)value); writer.WriteByte((byte)((bits[3] >>> 31 << 7) | ((bits[3] >>> 16) & 0x7F))); writer.WriteInt32(bits[0]); writer.WriteInt32(bits[1]); writer.WriteInt32(bits[2]); } else { helper.Error("Expected a Decimal constant"); writer.WriteBytes(new byte[13]); } flag = true; } else if (name == stringDateTime) { if (value is DateTime) { writer.WriteInt64(((DateTime)value).Ticks); } else { helper.Error("Expected a DateTime constant"); writer.WriteInt64(0L); } flag = true; } } if (!flag) { if (value is byte[]) { writer.WriteBytes((byte[])value); } else if (value != null) { helper.Error2("Unsupported constant: {0}.", value.GetType().FullName); } } return; } case ElementType.Class: WriteTypeDefOrRef(writer, ((ClassSig)type).TypeDefOrRef); if (value is byte[]) { writer.WriteBytes((byte[])value); } else if (value != null) { helper.Error("Expected a null constant"); } return; case ElementType.CModReqd: case ElementType.CModOpt: break; case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: case ElementType.SZArray: case ElementType.MVar: WriteTypeDefOrRef(writer, new TypeSpecUser(type)); return; default: helper.Error2("Unsupported element type in LocalConstant sig blob: {0}.", elementType); return; } WriteTypeDefOrRef(writer, ((ModifierSig)type).Modifier); type = type.Next; } } private static bool GetName(ITypeDefOrRef tdr, out UTF8String @namespace, out UTF8String name) { if (tdr is TypeRef typeRef) { @namespace = typeRef.Namespace; name = typeRef.Name; return true; } if (tdr is TypeDef typeDef) { @namespace = typeDef.Namespace; name = typeDef.Name; return true; } @namespace = null; name = null; return false; } private void WritePrimitiveValue(DataWriter writer, ElementType et, object value) { switch (et) { case ElementType.Boolean: if (value is bool) { writer.WriteBoolean((bool)value); break; } helper.Error("Expected a Boolean constant"); writer.WriteBoolean(value: false); break; case ElementType.Char: if (value is char) { writer.WriteUInt16((char)value); break; } helper.Error("Expected a Char constant"); writer.WriteUInt16(0); break; case ElementType.I1: if (value is sbyte) { writer.WriteSByte((sbyte)value); break; } helper.Error("Expected a SByte constant"); writer.WriteSByte(0); break; case ElementType.U1: if (value is byte) { writer.WriteByte((byte)value); break; } helper.Error("Expected a Byte constant"); writer.WriteByte(0); break; case ElementType.I2: if (value is short) { writer.WriteInt16((short)value); break; } helper.Error("Expected an Int16 constant"); writer.WriteInt16(0); break; case ElementType.U2: if (value is ushort) { writer.WriteUInt16((ushort)value); break; } helper.Error("Expected a UInt16 constant"); writer.WriteUInt16(0); break; case ElementType.I4: if (value is int) { writer.WriteInt32((int)value); break; } helper.Error("Expected an Int32 constant"); writer.WriteInt32(0); break; case ElementType.U4: if (value is uint) { writer.WriteUInt32((uint)value); break; } helper.Error("Expected a UInt32 constant"); writer.WriteUInt32(0u); break; case ElementType.I8: if (value is long) { writer.WriteInt64((long)value); break; } helper.Error("Expected an Int64 constant"); writer.WriteInt64(0L); break; case ElementType.U8: if (value is ulong) { writer.WriteUInt64((ulong)value); break; } helper.Error("Expected a UInt64 constant"); writer.WriteUInt64(0uL); break; default: throw new InvalidOperationException(); } } private void WriteTypeDefOrRef(DataWriter writer, ITypeDefOrRef tdr) { if (!CodedToken.TypeDefOrRef.Encode(systemMetadata.GetToken(tdr), out var codedToken)) { helper.Error("Couldn't encode a TypeDefOrRef"); } else { writer.WriteCompressedUInt32(codedToken); } } } internal struct PortablePdbCustomDebugInfoReader { private readonly ModuleDef module; private readonly TypeDef typeOpt; private readonly CilBody bodyOpt; private readonly GenericParamContext gpContext; private DataReader reader; public static PdbCustomDebugInfo Read(ModuleDef module, TypeDef typeOpt, CilBody bodyOpt, GenericParamContext gpContext, Guid kind, ref DataReader reader) { try { return new PortablePdbCustomDebugInfoReader(module, typeOpt, bodyOpt, gpContext, ref reader).Read(kind); } catch (ArgumentException) { } catch (OutOfMemoryException) { } catch (IOException) { } return null; } private PortablePdbCustomDebugInfoReader(ModuleDef module, TypeDef typeOpt, CilBody bodyOpt, GenericParamContext gpContext, ref DataReader reader) { this.module = module; this.typeOpt = typeOpt; this.bodyOpt = bodyOpt; this.gpContext = gpContext; this.reader = reader; } private PdbCustomDebugInfo Read(Guid kind) { if (kind == CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob) { return ReadAsyncMethodSteppingInformationBlob(); } if (kind == CustomDebugInfoGuids.DefaultNamespace) { return ReadDefaultNamespace(); } if (kind == CustomDebugInfoGuids.DynamicLocalVariables) { return ReadDynamicLocalVariables(reader.Length); } if (kind == CustomDebugInfoGuids.EmbeddedSource) { return ReadEmbeddedSource(); } if (kind == CustomDebugInfoGuids.EncLambdaAndClosureMap) { return ReadEncLambdaAndClosureMap(reader.Length); } if (kind == CustomDebugInfoGuids.EncLocalSlotMap) { return ReadEncLocalSlotMap(reader.Length); } if (kind == CustomDebugInfoGuids.SourceLink) { return ReadSourceLink(); } if (kind == CustomDebugInfoGuids.StateMachineHoistedLocalScopes) { return ReadStateMachineHoistedLocalScopes(); } if (kind == CustomDebugInfoGuids.TupleElementNames) { return ReadTupleElementNames(); } if (kind == CustomDebugInfoGuids.CompilationMetadataReferences) { return ReadCompilationMetadataReferences(); } if (kind == CustomDebugInfoGuids.CompilationOptions) { return ReadCompilationOptions(); } if (kind == CustomDebugInfoGuids.TypeDefinitionDocuments) { return ReadTypeDefinitionDocuments(); } if (kind == CustomDebugInfoGuids.EncStateMachineStateMap) { return ReadEncStateMachineStateMap(); } if (kind == CustomDebugInfoGuids.PrimaryConstructorInformationBlob) { return ReadPrimaryConstructorInformationBlob(); } return new PdbUnknownCustomDebugInfo(kind, reader.ReadRemainingBytes()); } private PdbCustomDebugInfo ReadAsyncMethodSteppingInformationBlob() { if (bodyOpt == null) { return null; } uint num = reader.ReadUInt32() - 1; Instruction instruction; if (num == uint.MaxValue) { instruction = null; } else { instruction = GetInstruction(num); if (instruction == null) { return null; } } PdbAsyncMethodSteppingInformationCustomDebugInfo pdbAsyncMethodSteppingInformationCustomDebugInfo = new PdbAsyncMethodSteppingInformationCustomDebugInfo(); pdbAsyncMethodSteppingInformationCustomDebugInfo.CatchHandler = instruction; while (reader.Position < reader.Length) { Instruction instruction2 = GetInstruction(reader.ReadUInt32()); if (instruction2 == null) { return null; } uint offset = reader.ReadUInt32(); uint rid = reader.ReadCompressedUInt32(); MDToken mDToken = new MDToken(Table.Method, rid); MethodDef methodDef; Instruction instruction3; if (gpContext.Method != null && mDToken == gpContext.Method.MDToken) { methodDef = gpContext.Method; instruction3 = GetInstruction(offset); } else { methodDef = module.ResolveToken(mDToken, gpContext) as MethodDef; if (methodDef == null) { return null; } instruction3 = GetInstruction(methodDef, offset); } if (instruction3 == null) { return null; } pdbAsyncMethodSteppingInformationCustomDebugInfo.AsyncStepInfos.Add(new PdbAsyncStepInfo(instruction2, methodDef, instruction3)); } return pdbAsyncMethodSteppingInformationCustomDebugInfo; } private PdbCustomDebugInfo ReadDefaultNamespace() { return new PdbDefaultNamespaceCustomDebugInfo(reader.ReadUtf8String((int)reader.BytesLeft)); } private PdbCustomDebugInfo ReadDynamicLocalVariables(long recPosEnd) { bool[] array = new bool[reader.Length * 8]; int num = 0; while (reader.Position < reader.Length) { int num2 = reader.ReadByte(); for (int num3 = 1; num3 < 256; num3 <<= 1) { array[num++] = (num2 & num3) != 0; } } return new PdbDynamicLocalVariablesCustomDebugInfo(array); } private PdbCustomDebugInfo ReadEmbeddedSource() { return new PdbEmbeddedSourceCustomDebugInfo(reader.ReadRemainingBytes()); } private PdbCustomDebugInfo ReadEncLambdaAndClosureMap(long recPosEnd) { return new PdbEditAndContinueLambdaMapCustomDebugInfo(reader.ReadBytes((int)(recPosEnd - reader.Position))); } private PdbCustomDebugInfo ReadEncLocalSlotMap(long recPosEnd) { return new PdbEditAndContinueLocalSlotMapCustomDebugInfo(reader.ReadBytes((int)(recPosEnd - reader.Position))); } private PdbCustomDebugInfo ReadSourceLink() { return new PdbSourceLinkCustomDebugInfo(reader.ReadRemainingBytes()); } private PdbCustomDebugInfo ReadStateMachineHoistedLocalScopes() { if (bodyOpt == null) { return null; } int num = (int)(reader.Length / 8); PdbStateMachineHoistedLocalScopesCustomDebugInfo pdbStateMachineHoistedLocalScopesCustomDebugInfo = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(num); for (int i = 0; i < num; i++) { uint num2 = reader.ReadUInt32(); uint num3 = reader.ReadUInt32(); if (num2 == 0 && num3 == 0) { pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes.Add(default(StateMachineHoistedLocalScope)); continue; } Instruction instruction = GetInstruction(num2); Instruction instruction2 = GetInstruction(num2 + num3); if (instruction == null) { return null; } pdbStateMachineHoistedLocalScopesCustomDebugInfo.Scopes.Add(new StateMachineHoistedLocalScope(instruction, instruction2)); } return pdbStateMachineHoistedLocalScopesCustomDebugInfo; } private PdbCustomDebugInfo ReadTupleElementNames() { PortablePdbTupleElementNamesCustomDebugInfo portablePdbTupleElementNamesCustomDebugInfo = new PortablePdbTupleElementNamesCustomDebugInfo(); while (reader.Position < reader.Length) { string item = ReadUTF8Z(reader.Length); portablePdbTupleElementNamesCustomDebugInfo.Names.Add(item); } return portablePdbTupleElementNamesCustomDebugInfo; } private string ReadUTF8Z(long recPosEnd) { if (reader.Position > recPosEnd) { return null; } return reader.TryReadZeroTerminatedUtf8String(); } private PdbCustomDebugInfo ReadCompilationMetadataReferences() { PdbCompilationMetadataReferencesCustomDebugInfo pdbCompilationMetadataReferencesCustomDebugInfo = new PdbCompilationMetadataReferencesCustomDebugInfo(); while (reader.BytesLeft != 0) { string text = reader.TryReadZeroTerminatedUtf8String(); if (text == null) { break; } string text2 = reader.TryReadZeroTerminatedUtf8String(); if (text2 == null || reader.BytesLeft < 25) { break; } PdbCompilationMetadataReferenceFlags flags = (PdbCompilationMetadataReferenceFlags)reader.ReadByte(); uint timestamp = reader.ReadUInt32(); uint sizeOfImage = reader.ReadUInt32(); Guid mvid = reader.ReadGuid(); PdbCompilationMetadataReference item = new PdbCompilationMetadataReference(text, text2, flags, timestamp, sizeOfImage, mvid); pdbCompilationMetadataReferencesCustomDebugInfo.References.Add(item); } return pdbCompilationMetadataReferencesCustomDebugInfo; } private PdbCustomDebugInfo ReadCompilationOptions() { PdbCompilationOptionsCustomDebugInfo pdbCompilationOptionsCustomDebugInfo = new PdbCompilationOptionsCustomDebugInfo(); while (reader.BytesLeft != 0) { string text = reader.TryReadZeroTerminatedUtf8String(); if (text == null) { break; } string text2 = reader.TryReadZeroTerminatedUtf8String(); if (text2 == null) { break; } pdbCompilationOptionsCustomDebugInfo.Options.Add(new KeyValuePair(text, text2)); } return pdbCompilationOptionsCustomDebugInfo; } private PdbCustomDebugInfo ReadTypeDefinitionDocuments() { List list = new List(); while (reader.BytesLeft != 0) { list.Add(new MDToken(Table.Document, reader.ReadCompressedUInt32())); } return new PdbTypeDefinitionDocumentsDebugInfoMD(module, list); } private PdbCustomDebugInfo ReadEncStateMachineStateMap() { PdbEditAndContinueStateMachineStateMapDebugInfo pdbEditAndContinueStateMachineStateMapDebugInfo = new PdbEditAndContinueStateMachineStateMapDebugInfo(); uint num = reader.ReadCompressedUInt32(); if (num != 0) { long num2 = 0L - (long)reader.ReadCompressedUInt32(); while (num != 0) { int state = reader.ReadCompressedInt32(); int syntaxOffset = (int)(num2 + reader.ReadCompressedUInt32()); pdbEditAndContinueStateMachineStateMapDebugInfo.StateMachineStates.Add(new StateMachineStateInfo(syntaxOffset, (StateMachineState)state)); num--; } } return pdbEditAndContinueStateMachineStateMapDebugInfo; } private PdbCustomDebugInfo ReadPrimaryConstructorInformationBlob() { return new PrimaryConstructorInformationBlobDebugInfo(reader.ReadRemainingBytes()); } private Instruction GetInstruction(uint offset) { IList instructions = bodyOpt.Instructions; int num = 0; int num2 = instructions.Count - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; Instruction instruction = instructions[num3]; if (instruction.Offset == offset) { return instruction; } if (offset < instruction.Offset) { num2 = num3 - 1; } else { num = num3 + 1; } } return null; } private static Instruction GetInstruction(MethodDef method, uint offset) { if (method == null) { return null; } CilBody body = method.Body; if (body == null) { return null; } IList instructions = body.Instructions; int num = 0; int num2 = instructions.Count - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; Instruction instruction = instructions[num3]; if (instruction.Offset == offset) { return instruction; } if (offset < instruction.Offset) { num2 = num3 - 1; } else { num = num3 + 1; } } return null; } } internal interface IPortablePdbCustomDebugInfoWriterHelper : IWriterError { } internal readonly struct PortablePdbCustomDebugInfoWriter { private readonly IPortablePdbCustomDebugInfoWriterHelper helper; private readonly SerializerMethodContext methodContext; private readonly dnlib.DotNet.Writer.Metadata systemMetadata; private readonly MemoryStream outStream; private readonly DataWriter writer; public static byte[] Write(IPortablePdbCustomDebugInfoWriterHelper helper, SerializerMethodContext methodContext, dnlib.DotNet.Writer.Metadata systemMetadata, PdbCustomDebugInfo cdi, DataWriterContext context) { return new PortablePdbCustomDebugInfoWriter(helper, methodContext, systemMetadata, context).Write(cdi); } private PortablePdbCustomDebugInfoWriter(IPortablePdbCustomDebugInfoWriterHelper helper, SerializerMethodContext methodContext, dnlib.DotNet.Writer.Metadata systemMetadata, DataWriterContext context) { this.helper = helper; this.methodContext = methodContext; this.systemMetadata = systemMetadata; outStream = context.OutStream; writer = context.Writer; outStream.SetLength(0L); outStream.Position = 0L; } private byte[] Write(PdbCustomDebugInfo cdi) { switch (cdi.Kind) { default: helper.Error("Unreachable code, caller should filter these out"); return null; case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: WriteStateMachineHoistedLocalScopes((PdbStateMachineHoistedLocalScopesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: WriteEditAndContinueLocalSlotMap((PdbEditAndContinueLocalSlotMapCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: WriteEditAndContinueLambdaMap((PdbEditAndContinueLambdaMapCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.Unknown: WriteUnknown((PdbUnknownCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.TupleElementNames_PortablePdb: WriteTupleElementNames((PortablePdbTupleElementNamesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.DefaultNamespace: WriteDefaultNamespace((PdbDefaultNamespaceCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.DynamicLocalVariables: WriteDynamicLocalVariables((PdbDynamicLocalVariablesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EmbeddedSource: WriteEmbeddedSource((PdbEmbeddedSourceCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.SourceLink: WriteSourceLink((PdbSourceLinkCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.AsyncMethod: WriteAsyncMethodSteppingInformation((PdbAsyncMethodCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.CompilationMetadataReferences: WriteCompilationMetadataReferences((PdbCompilationMetadataReferencesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.CompilationOptions: WriteCompilationOptions((PdbCompilationOptionsCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.TypeDefinitionDocuments: WriteTypeDefinitionDocuments((PdbTypeDefinitionDocumentsDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EditAndContinueStateMachineStateMap: WriteEditAndContinueStateMachineStateMap((PdbEditAndContinueStateMachineStateMapDebugInfo)cdi); break; case PdbCustomDebugInfoKind.PrimaryConstructorInformationBlob: WritePrimaryConstructorInformationBlob((PrimaryConstructorInformationBlobDebugInfo)cdi); break; } return outStream.ToArray(); } private void WriteUTF8Z(string s) { if (s.IndexOf('\0') >= 0) { helper.Error("String must not contain any NUL bytes"); } byte[] bytes = Encoding.UTF8.GetBytes(s); writer.WriteBytes(bytes); writer.WriteByte(0); } private void WriteStateMachineHoistedLocalScopes(PdbStateMachineHoistedLocalScopesCustomDebugInfo cdi) { if (!methodContext.HasBody) { helper.Error2("Method has no body, can't write custom debug info: {0}.", cdi.Kind); return; } IList scopes = cdi.Scopes; int count = scopes.Count; for (int i = 0; i < count; i++) { StateMachineHoistedLocalScope stateMachineHoistedLocalScope = scopes[i]; uint num; uint num2; if (stateMachineHoistedLocalScope.IsSynthesizedLocal) { num = 0u; num2 = 0u; } else { Instruction start = stateMachineHoistedLocalScope.Start; if (start == null) { helper.Error("Instruction is null"); break; } num = methodContext.GetOffset(start); num2 = methodContext.GetOffset(stateMachineHoistedLocalScope.End); } if (num > num2) { helper.Error("End instruction is before start instruction"); break; } writer.WriteUInt32(num); writer.WriteUInt32(num2 - num); } } private void WriteEditAndContinueLocalSlotMap(PdbEditAndContinueLocalSlotMapCustomDebugInfo cdi) { byte[] data = cdi.Data; if (data == null) { helper.Error("Data blob is null"); } else { writer.WriteBytes(data); } } private void WriteEditAndContinueLambdaMap(PdbEditAndContinueLambdaMapCustomDebugInfo cdi) { byte[] data = cdi.Data; if (data == null) { helper.Error("Data blob is null"); } else { writer.WriteBytes(data); } } private void WriteUnknown(PdbUnknownCustomDebugInfo cdi) { byte[] data = cdi.Data; if (data == null) { helper.Error("Data blob is null"); } else { writer.WriteBytes(data); } } private void WriteTupleElementNames(PortablePdbTupleElementNamesCustomDebugInfo cdi) { IList names = cdi.Names; int count = names.Count; for (int i = 0; i < count; i++) { string text = names[i]; if (text == null) { helper.Error("Tuple name is null"); break; } WriteUTF8Z(text); } } private void WriteDefaultNamespace(PdbDefaultNamespaceCustomDebugInfo cdi) { string text = cdi.Namespace; if (text == null) { helper.Error("Default namespace is null"); return; } byte[] bytes = Encoding.UTF8.GetBytes(text); writer.WriteBytes(bytes); } private void WriteDynamicLocalVariables(PdbDynamicLocalVariablesCustomDebugInfo cdi) { bool[] flags = cdi.Flags; for (int i = 0; i < flags.Length; i += 8) { writer.WriteByte(ToByte(flags, i)); } } private static byte ToByte(bool[] flags, int index) { int num = 0; int num2 = 1; int num3 = index; while (num3 < flags.Length) { if (flags[num3]) { num |= num2; } num3++; num2 <<= 1; } return (byte)num; } private void WriteEmbeddedSource(PdbEmbeddedSourceCustomDebugInfo cdi) { byte[] sourceCodeBlob = cdi.SourceCodeBlob; if (sourceCodeBlob == null) { helper.Error("Source code blob is null"); } else { writer.WriteBytes(sourceCodeBlob); } } private void WriteSourceLink(PdbSourceLinkCustomDebugInfo cdi) { byte[] fileBlob = cdi.FileBlob; if (fileBlob == null) { helper.Error("Source link blob is null"); } else { writer.WriteBytes(fileBlob); } } private void WriteAsyncMethodSteppingInformation(PdbAsyncMethodCustomDebugInfo cdi) { if (!methodContext.HasBody) { helper.Error2("Method has no body, can't write custom debug info: {0}.", cdi.Kind); return; } uint value = ((cdi.CatchHandlerInstruction != null) ? (methodContext.GetOffset(cdi.CatchHandlerInstruction) + 1) : 0u); writer.WriteUInt32(value); IList stepInfos = cdi.StepInfos; int count = stepInfos.Count; for (int i = 0; i < count; i++) { PdbAsyncStepInfo pdbAsyncStepInfo = stepInfos[i]; if (pdbAsyncStepInfo.YieldInstruction == null) { helper.Error("YieldInstruction is null"); break; } if (pdbAsyncStepInfo.BreakpointMethod == null) { helper.Error("BreakpointMethod is null"); break; } if (pdbAsyncStepInfo.BreakpointInstruction == null) { helper.Error("BreakpointInstruction is null"); break; } uint offset = methodContext.GetOffset(pdbAsyncStepInfo.YieldInstruction); uint value2 = ((!methodContext.IsSameMethod(pdbAsyncStepInfo.BreakpointMethod)) ? GetOffsetSlow(pdbAsyncStepInfo.BreakpointMethod, pdbAsyncStepInfo.BreakpointInstruction) : methodContext.GetOffset(pdbAsyncStepInfo.BreakpointInstruction)); uint rid = systemMetadata.GetRid(pdbAsyncStepInfo.BreakpointMethod); writer.WriteUInt32(offset); writer.WriteUInt32(value2); writer.WriteCompressedUInt32(rid); } } private uint GetOffsetSlow(MethodDef method, Instruction instr) { CilBody body = method.Body; if (body == null) { helper.Error("Method has no body"); return uint.MaxValue; } IList instructions = body.Instructions; uint num = 0u; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; if (instruction == instr) { return num; } num += (uint)instruction.GetSize(); } helper.Error("Couldn't find an instruction, maybe it was removed. It's still being referenced by some code or by the PDB"); return uint.MaxValue; } private void WriteCompilationMetadataReferences(PdbCompilationMetadataReferencesCustomDebugInfo cdi) { foreach (PdbCompilationMetadataReference reference in cdi.References) { string name = reference.Name; if (name == null) { helper.Error("Metadata reference name is null"); break; } WriteUTF8Z(name); string aliases = reference.Aliases; if (aliases == null) { helper.Error("Metadata reference aliases is null"); break; } WriteUTF8Z(aliases); writer.WriteByte((byte)reference.Flags); writer.WriteUInt32(reference.Timestamp); writer.WriteUInt32(reference.SizeOfImage); writer.WriteBytes(reference.Mvid.ToByteArray()); } } private void WriteCompilationOptions(PdbCompilationOptionsCustomDebugInfo cdi) { foreach (KeyValuePair option in cdi.Options) { if (option.Key == null) { helper.Error("Compiler option `key` is null"); break; } if (option.Value == null) { helper.Error("Compiler option `value` is null"); break; } WriteUTF8Z(option.Key); WriteUTF8Z(option.Value); } } private void WriteTypeDefinitionDocuments(PdbTypeDefinitionDocumentsDebugInfo cdi) { foreach (PdbDocument document in cdi.Documents) { writer.WriteCompressedUInt32(systemMetadata.GetRid(document)); } } private void WriteEditAndContinueStateMachineStateMap(PdbEditAndContinueStateMachineStateMapDebugInfo cdi) { writer.WriteCompressedUInt32((uint)cdi.StateMachineStates.Count); if (cdi.StateMachineStates.Count <= 0) { return; } int num = Math.Min(cdi.StateMachineStates.Min((StateMachineStateInfo state) => state.SyntaxOffset), 0); writer.WriteCompressedUInt32((uint)(-num)); foreach (StateMachineStateInfo stateMachineState in cdi.StateMachineStates) { writer.WriteCompressedInt32((int)stateMachineState.State); writer.WriteCompressedUInt32((uint)(stateMachineState.SyntaxOffset - num)); } } private void WritePrimaryConstructorInformationBlob(PrimaryConstructorInformationBlobDebugInfo cdi) { byte[] blob = cdi.Blob; if (blob == null) { helper.Error("Primary constructor information blob is null"); } else { writer.WriteBytes(blob); } } } internal sealed class PortablePdbReader : SymbolReader { private readonly PdbFileKind pdbFileKind; private ModuleDef module; private readonly dnlib.DotNet.MD.Metadata pdbMetadata; private SymbolDocument[] documents; public override PdbFileKind PdbFileKind => pdbFileKind; public override int UserEntryPoint => pdbMetadata.PdbStream.EntryPoint.ToInt32(); public override IList Documents => documents; public PortablePdbReader(DataReaderFactory pdbStream, PdbFileKind pdbFileKind) { this.pdbFileKind = pdbFileKind; pdbMetadata = MetadataFactory.CreateStandalonePortablePDB(pdbStream, verify: true); } internal bool MatchesModule(Guid pdbGuid, uint timestamp, uint age) { PdbStream pdbStream = pdbMetadata.PdbStream; if (pdbStream != null) { byte[] array = pdbStream.Id; Array.Resize(ref array, 16); if (new Guid(array) != pdbGuid) { return false; } if (BitConverter.ToUInt32(pdbStream.Id, 16) != timestamp) { return false; } if (age != 1) { return false; } return true; } return false; } public override void Initialize(ModuleDef module) { this.module = module; documents = ReadDocuments(); } private static Guid GetLanguageVendor(Guid language) { if (language == PdbDocumentConstants.LanguageCSharp || language == PdbDocumentConstants.LanguageVisualBasic || language == PdbDocumentConstants.LanguageFSharp) { return PdbDocumentConstants.LanguageVendorMicrosoft; } return Guid.Empty; } private SymbolDocument[] ReadDocuments() { SymbolDocument[] array = new SymbolDocument[pdbMetadata.TablesStream.DocumentTable.Rows]; DocumentNameReader documentNameReader = new DocumentNameReader(pdbMetadata.BlobStream); List list = ListCache.AllocList(); GenericParamContext gpContext = default(GenericParamContext); for (int i = 0; i < array.Length; i++) { uint rid = (uint)(i + 1); pdbMetadata.TablesStream.TryReadDocumentRow(rid, out var row); string url = documentNameReader.ReadDocumentName(row.Name); Guid language = pdbMetadata.GuidStream.Read(row.Language) ?? Guid.Empty; Guid languageVendor = GetLanguageVendor(language); Guid documentTypeText = PdbDocumentConstants.DocumentTypeText; Guid checkSumAlgorithmId = pdbMetadata.GuidStream.Read(row.HashAlgorithm) ?? Guid.Empty; byte[] checkSum = pdbMetadata.BlobStream.ReadNoNull(row.Hash); MDToken mdToken = new MDToken(Table.Document, rid); int token = mdToken.ToInt32(); list.Clear(); GetCustomDebugInfos(token, gpContext, list); PdbCustomDebugInfo[] customDebugInfos = ((list.Count == 0) ? Array2.Empty() : list.ToArray()); array[i] = new SymbolDocumentImpl(url, language, languageVendor, documentTypeText, checkSumAlgorithmId, checkSum, customDebugInfos, mdToken); } ListCache.Free(ref list); return array; } private bool TryGetSymbolDocument(uint rid, out SymbolDocument document) { int num = (int)(rid - 1); if ((uint)num >= (uint)documents.Length) { document = null; return false; } document = documents[num]; return true; } public override SymbolMethod GetMethod(MethodDef method, int version) { if (version != 1) { return null; } MDTable methodDebugInformationTable = pdbMetadata.TablesStream.MethodDebugInformationTable; uint rid = method.Rid; if (!methodDebugInformationTable.IsValidRID(rid)) { return null; } SymbolSequencePoint[] sequencePoints = ReadSequencePoints(rid) ?? Array2.Empty(); GenericParamContext gpContext = GenericParamContext.Create(method); SymbolScopeImpl symbolScopeImpl = ReadScope(rid, gpContext); int kickoffMethod = GetKickoffMethod(rid); return symbolScopeImpl.method = new SymbolMethodImpl(this, method.MDToken.ToInt32(), symbolScopeImpl, sequencePoints, kickoffMethod); } private int GetKickoffMethod(uint methodRid) { uint stateMachineMethodRid = pdbMetadata.GetStateMachineMethodRid(methodRid); if (stateMachineMethodRid == 0) { return 0; } if (!pdbMetadata.TablesStream.TryReadStateMachineMethodRow(stateMachineMethodRid, out var row)) { return 0; } return (int)(100663296 + row.KickoffMethod); } private SymbolSequencePoint[] ReadSequencePoints(uint methodRid) { if (!pdbMetadata.TablesStream.MethodDebugInformationTable.IsValidRID(methodRid)) { return null; } if (!pdbMetadata.TablesStream.TryReadMethodDebugInformationRow(methodRid, out var row)) { return null; } if (row.SequencePoints == 0) { return null; } uint num = row.Document; if (!pdbMetadata.BlobStream.TryCreateReader(row.SequencePoints, out var reader)) { return null; } List list = ListCache.AllocList(); reader.ReadCompressedUInt32(); if (num == 0) { num = reader.ReadCompressedUInt32(); } TryGetSymbolDocument(num, out var document); uint num2 = uint.MaxValue; int num3 = -1; int num4 = 0; bool flag = false; while (reader.Position < reader.Length) { uint num5 = reader.ReadCompressedUInt32(); if (num5 == 0 && flag) { num = reader.ReadCompressedUInt32(); TryGetSymbolDocument(num, out document); } else { if (document == null) { return null; } SymbolSequencePoint item = new SymbolSequencePoint { Document = document }; if (num2 == uint.MaxValue) { num2 = num5; } else { if (num5 == 0) { return null; } num2 += num5; } item.Offset = (int)num2; uint num6 = reader.ReadCompressedUInt32(); int num7 = ((num6 == 0) ? ((int)reader.ReadCompressedUInt32()) : reader.ReadCompressedInt32()); if (num6 == 0 && num7 == 0) { item.Line = 16707566; item.EndLine = 16707566; item.Column = 0; item.EndColumn = 0; } else { if (num3 < 0) { num3 = (int)reader.ReadCompressedUInt32(); num4 = (int)reader.ReadCompressedUInt32(); } else { num3 += reader.ReadCompressedInt32(); num4 += reader.ReadCompressedInt32(); } item.Line = num3; item.EndLine = num3 + (int)num6; item.Column = num4; item.EndColumn = num4 + num7; } list.Add(item); } flag = true; } return ListCache.FreeAndToArray(ref list); } private SymbolScopeImpl ReadScope(uint methodRid, GenericParamContext gpContext) { RidList localScopeRidList = pdbMetadata.GetLocalScopeRidList(methodRid); SymbolScopeImpl symbolScopeImpl = null; if (localScopeRidList.Count != 0) { List list = ListCache.AllocList(); List list2 = ListCache.AllocList(); ImportScopeBlobReader importScopeBlobReader = new ImportScopeBlobReader(module, pdbMetadata.BlobStream); for (int i = 0; i < localScopeRidList.Count; i++) { uint num = localScopeRidList[i]; int token = new MDToken(Table.LocalScope, num).ToInt32(); pdbMetadata.TablesStream.TryReadLocalScopeRow(num, out var row); uint startOffset = row.StartOffset; uint num2 = startOffset + row.Length; SymbolScopeImpl symbolScopeImpl2 = null; while (list2.Count > 0) { SymbolScopeImpl symbolScopeImpl3 = list2[list2.Count - 1]; if (startOffset >= symbolScopeImpl3.StartOffset && num2 <= symbolScopeImpl3.EndOffset) { symbolScopeImpl2 = symbolScopeImpl3; break; } list2.RemoveAt(list2.Count - 1); } list.Clear(); GetCustomDebugInfos(token, gpContext, list); PdbCustomDebugInfo[] customDebugInfos = ((list.Count == 0) ? Array2.Empty() : list.ToArray()); SymbolScopeImpl symbolScopeImpl4 = new SymbolScopeImpl(this, symbolScopeImpl2, (int)startOffset, (int)num2, customDebugInfos); if (symbolScopeImpl == null) { symbolScopeImpl = symbolScopeImpl4; } list2.Add(symbolScopeImpl4); symbolScopeImpl2?.childrenList.Add(symbolScopeImpl4); symbolScopeImpl4.importScope = ReadPdbImportScope(ref importScopeBlobReader, row.ImportScope, gpContext); ReadVariables(symbolScopeImpl4, gpContext, pdbMetadata.GetLocalVariableRidList(num)); ReadConstants(symbolScopeImpl4, pdbMetadata.GetLocalConstantRidList(num)); } ListCache.Free(ref list2); ListCache.Free(ref list); } return symbolScopeImpl ?? new SymbolScopeImpl(this, null, 0, int.MaxValue, Array2.Empty()); } private PdbImportScope ReadPdbImportScope(ref ImportScopeBlobReader importScopeBlobReader, uint importScope, GenericParamContext gpContext) { if (importScope == 0) { return null; } PdbImportScope pdbImportScope = null; PdbImportScope pdbImportScope2 = null; int num = 0; while (importScope != 0) { if (num >= 1000) { return null; } int token = new MDToken(Table.ImportScope, importScope).ToInt32(); if (!pdbMetadata.TablesStream.TryReadImportScopeRow(importScope, out var row)) { return null; } PdbImportScope pdbImportScope3 = new PdbImportScope(); GetCustomDebugInfos(token, gpContext, pdbImportScope3.CustomDebugInfos); if (pdbImportScope == null) { pdbImportScope = pdbImportScope3; } if (pdbImportScope2 != null) { pdbImportScope2.Parent = pdbImportScope3; } importScopeBlobReader.Read(row.Imports, pdbImportScope3.Imports); pdbImportScope2 = pdbImportScope3; importScope = row.Parent; num++; } return pdbImportScope; } private void ReadVariables(SymbolScopeImpl scope, GenericParamContext gpContext, RidList rids) { if (rids.Count != 0) { _ = pdbMetadata.TablesStream.LocalVariableTable; List list = ListCache.AllocList(); for (int i = 0; i < rids.Count; i++) { uint rid = rids[i]; int token = new MDToken(Table.LocalVariable, rid).ToInt32(); list.Clear(); GetCustomDebugInfos(token, gpContext, list); PdbCustomDebugInfo[] customDebugInfos = ((list.Count == 0) ? Array2.Empty() : list.ToArray()); pdbMetadata.TablesStream.TryReadLocalVariableRow(rid, out var row); UTF8String uTF8String = pdbMetadata.StringsStream.Read(row.Name); scope.localsList.Add(new SymbolVariableImpl(uTF8String, ToSymbolVariableAttributes(row.Attributes), row.Index, customDebugInfos)); } ListCache.Free(ref list); } } private static PdbLocalAttributes ToSymbolVariableAttributes(ushort attributes) { PdbLocalAttributes pdbLocalAttributes = PdbLocalAttributes.None; if ((attributes & 1) != 0) { pdbLocalAttributes |= PdbLocalAttributes.DebuggerHidden; } return pdbLocalAttributes; } private void ReadConstants(SymbolScopeImpl scope, RidList rids) { if (rids.Count != 0) { scope.SetConstants(pdbMetadata, rids); } } internal void GetCustomDebugInfos(SymbolMethodImpl symMethod, MethodDef method, CilBody body, IList result) { GetCustomDebugInfos(method.MDToken.ToInt32(), GenericParamContext.Create(method), result, method, body, out var asyncStepInfo); if (asyncStepInfo != null) { PdbAsyncMethodCustomDebugInfo pdbAsyncMethodCustomDebugInfo = TryCreateAsyncMethod(module, symMethod.KickoffMethod, asyncStepInfo.AsyncStepInfos, asyncStepInfo.CatchHandler); if (pdbAsyncMethodCustomDebugInfo != null) { result.Add(pdbAsyncMethodCustomDebugInfo); } } else if (symMethod.KickoffMethod != 0) { PdbIteratorMethodCustomDebugInfo pdbIteratorMethodCustomDebugInfo = TryCreateIteratorMethod(module, symMethod.KickoffMethod); if (pdbIteratorMethodCustomDebugInfo != null) { result.Add(pdbIteratorMethodCustomDebugInfo); } } } private PdbAsyncMethodCustomDebugInfo TryCreateAsyncMethod(ModuleDef module, int asyncKickoffMethod, IList asyncStepInfos, Instruction asyncCatchHandler) { MDToken mdToken = new MDToken(asyncKickoffMethod); if (mdToken.Table != Table.Method) { return null; } PdbAsyncMethodCustomDebugInfo pdbAsyncMethodCustomDebugInfo = new PdbAsyncMethodCustomDebugInfo(asyncStepInfos.Count); pdbAsyncMethodCustomDebugInfo.KickoffMethod = module.ResolveToken(mdToken) as MethodDef; pdbAsyncMethodCustomDebugInfo.CatchHandlerInstruction = asyncCatchHandler; int count = asyncStepInfos.Count; for (int i = 0; i < count; i++) { pdbAsyncMethodCustomDebugInfo.StepInfos.Add(asyncStepInfos[i]); } return pdbAsyncMethodCustomDebugInfo; } private PdbIteratorMethodCustomDebugInfo TryCreateIteratorMethod(ModuleDef module, int iteratorKickoffMethod) { MDToken mdToken = new MDToken(iteratorKickoffMethod); if (mdToken.Table != Table.Method) { return null; } return new PdbIteratorMethodCustomDebugInfo(module.ResolveToken(mdToken) as MethodDef); } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { GetCustomDebugInfos(token, gpContext, result, null, null, out var _); } private void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result, MethodDef methodOpt, CilBody bodyOpt, out PdbAsyncMethodSteppingInformationCustomDebugInfo asyncStepInfo) { asyncStepInfo = null; MDToken mDToken = new MDToken(token); RidList customDebugInformationRidList = pdbMetadata.GetCustomDebugInformationRidList(mDToken.Table, mDToken.Rid); if (customDebugInformationRidList.Count == 0) { return; } TypeDef typeOpt = methodOpt?.DeclaringType; for (int i = 0; i < customDebugInformationRidList.Count; i++) { uint rid = customDebugInformationRidList[i]; if (!pdbMetadata.TablesStream.TryReadCustomDebugInformationRow(rid, out var row)) { continue; } Guid? guid = pdbMetadata.GuidStream.Read(row.Kind); if (!pdbMetadata.BlobStream.TryCreateReader(row.Value, out var reader) || !guid.HasValue) { continue; } PdbCustomDebugInfo pdbCustomDebugInfo = PortablePdbCustomDebugInfoReader.Read(module, typeOpt, bodyOpt, gpContext, guid.Value, ref reader); if (pdbCustomDebugInfo != null) { if (pdbCustomDebugInfo is PdbAsyncMethodSteppingInformationCustomDebugInfo pdbAsyncMethodSteppingInformationCustomDebugInfo) { asyncStepInfo = pdbAsyncMethodSteppingInformationCustomDebugInfo; } else { result.Add(pdbCustomDebugInfo); } } } } public override void Dispose() { pdbMetadata.Dispose(); } } internal static class SequencePointConstants { public const int HIDDEN_LINE = 16707566; public const int HIDDEN_COLUMN = 0; } [DebuggerDisplay("{GetDebuggerString(),nq}")] internal sealed class SymbolDocumentImpl : SymbolDocument { private readonly string url; private Guid language; private Guid languageVendor; private Guid documentType; private Guid checkSumAlgorithmId; private readonly byte[] checkSum; private readonly PdbCustomDebugInfo[] customDebugInfos; private MDToken mdToken; public override string URL => url; public override Guid Language => language; public override Guid LanguageVendor => languageVendor; public override Guid DocumentType => documentType; public override Guid CheckSumAlgorithmId => checkSumAlgorithmId; public override byte[] CheckSum => checkSum; public override PdbCustomDebugInfo[] CustomDebugInfos => customDebugInfos; public override MDToken? MDToken => mdToken; private string GetDebuggerString() { StringBuilder stringBuilder = new StringBuilder(); if (language == PdbDocumentConstants.LanguageCSharp) { stringBuilder.Append("C#"); } else if (language == PdbDocumentConstants.LanguageVisualBasic) { stringBuilder.Append("VB"); } else if (language == PdbDocumentConstants.LanguageFSharp) { stringBuilder.Append("F#"); } else { stringBuilder.Append(language.ToString()); } stringBuilder.Append(", "); if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA1) { stringBuilder.Append("SHA-1"); } else if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA256) { stringBuilder.Append("SHA-256"); } else { stringBuilder.Append(checkSumAlgorithmId.ToString()); } stringBuilder.Append(": "); stringBuilder.Append(url); return stringBuilder.ToString(); } public SymbolDocumentImpl(string url, Guid language, Guid languageVendor, Guid documentType, Guid checkSumAlgorithmId, byte[] checkSum, PdbCustomDebugInfo[] customDebugInfos, MDToken mdToken) { this.url = url; this.language = language; this.languageVendor = languageVendor; this.documentType = documentType; this.checkSumAlgorithmId = checkSumAlgorithmId; this.checkSum = checkSum; this.customDebugInfos = customDebugInfos; this.mdToken = mdToken; } } internal sealed class SymbolMethodImpl : SymbolMethod { private readonly PortablePdbReader reader; private readonly int token; private readonly SymbolScope rootScope; private readonly SymbolSequencePoint[] sequencePoints; private readonly int kickoffMethod; public override int Token => token; public override SymbolScope RootScope => rootScope; public override IList SequencePoints => sequencePoints; public int KickoffMethod => kickoffMethod; public SymbolMethodImpl(PortablePdbReader reader, int token, SymbolScope rootScope, SymbolSequencePoint[] sequencePoints, int kickoffMethod) { this.reader = reader; this.token = token; this.rootScope = rootScope; this.sequencePoints = sequencePoints; this.kickoffMethod = kickoffMethod; } public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } internal static class SymbolReaderFactory { public static SymbolReader TryCreate(PdbReaderContext pdbContext, DataReaderFactory pdbStream, bool isEmbeddedPortablePdb) { bool flag = true; try { if (!pdbContext.HasDebugInfo) { return null; } if (pdbStream == null) { return null; } if (pdbStream.Length < 4) { return null; } if (pdbStream.CreateReader().ReadUInt32() != 1112167234) { return null; } ImageDebugDirectory codeViewDebugDirectory = pdbContext.CodeViewDebugDirectory; if (codeViewDebugDirectory == null) { return null; } if (!pdbContext.TryGetCodeViewData(out var guid, out var age)) { return null; } PortablePdbReader portablePdbReader = new PortablePdbReader(pdbStream, (!isEmbeddedPortablePdb) ? PdbFileKind.PortablePDB : PdbFileKind.EmbeddedPortablePDB); if (!portablePdbReader.MatchesModule(guid, codeViewDebugDirectory.TimeDateStamp, age)) { return null; } flag = false; return portablePdbReader; } catch (IOException) { } finally { if (flag) { pdbStream?.Dispose(); } } return null; } public static SymbolReader TryCreateEmbeddedPortablePdbReader(PdbReaderContext pdbContext, dnlib.DotNet.MD.Metadata metadata) { if (metadata == null) { return null; } try { if (!pdbContext.HasDebugInfo) { return null; } ImageDebugDirectory imageDebugDirectory = pdbContext.TryGetDebugDirectoryEntry(ImageDebugType.EmbeddedPortablePdb); if (imageDebugDirectory == null) { return null; } DataReader dataReader = pdbContext.CreateReader(imageDebugDirectory.AddressOfRawData, imageDebugDirectory.SizeOfData); if (dataReader.Length < 8) { return null; } if (dataReader.ReadUInt32() != 1111773261) { return null; } uint num = dataReader.ReadUInt32(); if ((num & 0x80000000u) != 0) { return null; } byte[] array = new byte[num]; using DeflateStream deflateStream = new DeflateStream(dataReader.AsStream(), CompressionMode.Decompress); int i; int num2; for (i = 0; i < array.Length; i += num2) { num2 = deflateStream.Read(array, i, array.Length - i); if (num2 == 0) { break; } } if (i != array.Length) { return null; } ByteArrayDataReaderFactory pdbStream = ByteArrayDataReaderFactory.Create(array, null); return TryCreate(pdbContext, pdbStream, isEmbeddedPortablePdb: true); } catch (IOException) { } return null; } } internal sealed class SymbolScopeImpl : SymbolScope { private readonly PortablePdbReader owner; internal SymbolMethod method; private readonly SymbolScopeImpl parent; private readonly int startOffset; private readonly int endOffset; internal readonly List childrenList; internal readonly List localsList; internal PdbImportScope importScope; private readonly PdbCustomDebugInfo[] customDebugInfos; private dnlib.DotNet.MD.Metadata constantsMetadata; private RidList constantRidList; public override SymbolMethod Method { get { if (method != null) { return method; } SymbolScopeImpl symbolScopeImpl = parent; if (symbolScopeImpl == null) { return method; } while (symbolScopeImpl.parent != null) { symbolScopeImpl = symbolScopeImpl.parent; } return method = symbolScopeImpl.method; } } public override SymbolScope Parent => parent; public override int StartOffset => startOffset; public override int EndOffset => endOffset; public override IList Children => childrenList; public override IList Locals => localsList; public override IList Namespaces => Array2.Empty(); public override IList CustomDebugInfos => customDebugInfos; public override PdbImportScope ImportScope => importScope; public SymbolScopeImpl(PortablePdbReader owner, SymbolScopeImpl parent, int startOffset, int endOffset, PdbCustomDebugInfo[] customDebugInfos) { this.owner = owner; method = null; this.parent = parent; this.startOffset = startOffset; this.endOffset = endOffset; childrenList = new List(); localsList = new List(); this.customDebugInfos = customDebugInfos; } internal void SetConstants(dnlib.DotNet.MD.Metadata metadata, RidList rids) { constantsMetadata = metadata; constantRidList = rids; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (constantRidList.Count == 0) { return Array2.Empty(); } PdbConstant[] array = new PdbConstant[constantRidList.Count]; int num = 0; for (int i = 0; i < array.Length; i++) { uint rid = constantRidList[i]; constantsMetadata.TablesStream.TryReadLocalConstantRow(rid, out var row); UTF8String uTF8String = constantsMetadata.StringsStream.Read(row.Name); if (constantsMetadata.BlobStream.TryCreateReader(row.Signature, out var reader) && new LocalConstantSigBlobReader(module, ref reader, gpContext).Read(out var type, out var value)) { PdbConstant pdbConstant = new PdbConstant(uTF8String, type, value); int token = new MDToken(Table.LocalConstant, rid).ToInt32(); owner.GetCustomDebugInfos(token, gpContext, pdbConstant.CustomDebugInfos); array[num++] = pdbConstant; } } if (array.Length != num) { Array.Resize(ref array, num); } return array; } } internal sealed class SymbolVariableImpl : SymbolVariable { private readonly string name; private readonly PdbLocalAttributes attributes; private readonly int index; private readonly PdbCustomDebugInfo[] customDebugInfos; public override string Name => name; public override PdbLocalAttributes Attributes => attributes; public override int Index => index; public override PdbCustomDebugInfo[] CustomDebugInfos => customDebugInfos; public SymbolVariableImpl(string name, PdbLocalAttributes attributes, int index, PdbCustomDebugInfo[] customDebugInfos) { this.name = name; this.attributes = attributes; this.index = index; this.customDebugInfos = customDebugInfos; } } } namespace dnlib.DotNet.Pdb.Managed { internal sealed class DbiDocument : SymbolDocument { private readonly string url; private Guid language; private Guid languageVendor; private Guid documentType; private Guid checkSumAlgorithmId; private byte[] checkSum; private byte[] sourceCode; private PdbCustomDebugInfo[] customDebugInfos; public override string URL => url; public override Guid Language => language; public override Guid LanguageVendor => languageVendor; public override Guid DocumentType => documentType; public override Guid CheckSumAlgorithmId => checkSumAlgorithmId; public override byte[] CheckSum => checkSum; private byte[] SourceCode => sourceCode; public override PdbCustomDebugInfo[] CustomDebugInfos { get { if (customDebugInfos == null) { byte[] array = SourceCode; if (array != null) { customDebugInfos = new PdbCustomDebugInfo[1] { new PdbEmbeddedSourceCustomDebugInfo(array) }; } else { customDebugInfos = Array2.Empty(); } } return customDebugInfos; } } public override MDToken? MDToken => null; public DbiDocument(string url) { this.url = url; documentType = SymDocumentType.Text; } public void Read(ref DataReader reader) { reader.Position = 0u; language = reader.ReadGuid(); languageVendor = reader.ReadGuid(); documentType = reader.ReadGuid(); checkSumAlgorithmId = reader.ReadGuid(); int length = reader.ReadInt32(); int num = reader.ReadInt32(); checkSum = reader.ReadBytes(length); sourceCode = ((num == 0) ? null : reader.ReadBytes(num)); } } internal sealed class DbiFunction : SymbolMethod { internal int token; internal PdbReader reader; private List lines; private const string asyncMethodInfoAttributeName = "asyncMethodInfo"; private volatile SymbolAsyncStepInfo[] asyncStepInfos; public override int Token => token; public string Name { get; private set; } public PdbAddress Address { get; private set; } public DbiScope Root { get; private set; } public List Lines { get { return lines; } set { lines = value; } } public override SymbolScope RootScope => Root; public override IList SequencePoints { get { List list = lines; if (list == null) { return Array2.Empty(); } return list; } } public int AsyncKickoffMethod { get { byte[] symAttribute = Root.GetSymAttribute("asyncMethodInfo"); if (symAttribute == null || symAttribute.Length < 4) { return 0; } return BitConverter.ToInt32(symAttribute, 0); } } public uint? AsyncCatchHandlerILOffset { get { byte[] symAttribute = Root.GetSymAttribute("asyncMethodInfo"); if (symAttribute == null || symAttribute.Length < 8) { return null; } uint num = BitConverter.ToUInt32(symAttribute, 4); if (num != uint.MaxValue) { return num; } return null; } } public IList AsyncStepInfos { get { if (asyncStepInfos == null) { asyncStepInfos = CreateSymbolAsyncStepInfos(); } return asyncStepInfos; } } public void Read(ref DataReader reader, uint recEnd) { reader.Position += 4u; uint scopeEnd = reader.ReadUInt32(); reader.Position += 4u; uint length = reader.ReadUInt32(); reader.Position += 8u; token = reader.ReadInt32(); Address = PdbAddress.ReadAddress(ref reader); reader.Position += 3u; Name = PdbReader.ReadCString(ref reader); reader.Position = recEnd; Root = new DbiScope(this, null, "", Address.Offset, length); Root.Read(default(RecursionCounter), ref reader, scopeEnd); FixOffsets(default(RecursionCounter), Root); } private void FixOffsets(RecursionCounter counter, DbiScope scope) { if (counter.Increment()) { scope.startOffset -= (int)Address.Offset; scope.endOffset -= (int)Address.Offset; IList children = scope.Children; int count = children.Count; for (int i = 0; i < count; i++) { FixOffsets(counter, (DbiScope)children[i]); } counter.Decrement(); } } private SymbolAsyncStepInfo[] CreateSymbolAsyncStepInfos() { byte[] symAttribute = Root.GetSymAttribute("asyncMethodInfo"); if (symAttribute == null || symAttribute.Length < 12) { return Array2.Empty(); } int num = 8; int num2 = BitConverter.ToInt32(symAttribute, num); num += 4; if (num + (long)num2 * 12L > symAttribute.Length) { return Array2.Empty(); } if (num2 == 0) { return Array2.Empty(); } SymbolAsyncStepInfo[] array = new SymbolAsyncStepInfo[num2]; for (int i = 0; i < array.Length; i++) { array[i] = new SymbolAsyncStepInfo(BitConverter.ToUInt32(symAttribute, num), BitConverter.ToUInt32(symAttribute, num + 8), BitConverter.ToUInt32(symAttribute, num + 4)); num += 12; } return array; } public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } internal sealed class DbiModule { private uint cbSyms; private uint cbOldLines; private uint cbLines; public ushort StreamId { get; private set; } public string ModuleName { get; private set; } public string ObjectName { get; private set; } public List Functions { get; private set; } public List Documents { get; private set; } public DbiModule() { Functions = new List(); Documents = new List(); } public void Read(ref DataReader reader) { reader.Position += 34u; StreamId = reader.ReadUInt16(); cbSyms = reader.ReadUInt32(); cbOldLines = reader.ReadUInt32(); cbLines = reader.ReadUInt32(); reader.Position += 16u; if ((int)cbSyms < 0) { cbSyms = 0u; } if ((int)cbOldLines < 0) { cbOldLines = 0u; } if ((int)cbLines < 0) { cbLines = 0u; } ModuleName = PdbReader.ReadCString(ref reader); ObjectName = PdbReader.ReadCString(ref reader); reader.Position = (reader.Position + 3) & 0xFFFFFFFCu; } public void LoadFunctions(PdbReader pdbReader, ref DataReader reader) { reader.Position = 0u; ReadFunctions(reader.Slice(reader.Position, cbSyms)); if (Functions.Count > 0) { reader.Position += cbSyms + cbOldLines; ReadLines(pdbReader, reader.Slice(reader.Position, cbLines)); } } private void ReadFunctions(DataReader reader) { if (reader.ReadUInt32() != 4) { throw new PdbException("Invalid signature"); } while (reader.Position < reader.Length) { ushort num = reader.ReadUInt16(); uint num2 = reader.Position + num; SymbolType symbolType = (SymbolType)reader.ReadUInt16(); if (symbolType - 4394 <= SymbolType.S_COMPILE) { DbiFunction dbiFunction = new DbiFunction(); dbiFunction.Read(ref reader, num2); Functions.Add(dbiFunction); } else { reader.Position = num2; } } } private void ReadLines(PdbReader pdbReader, DataReader reader) { Dictionary documents = new Dictionary(); reader.Position = 0u; while (reader.Position < reader.Length) { uint num = reader.ReadUInt32(); uint num2 = reader.ReadUInt32(); uint num3 = (reader.Position + num2 + 3) & 0xFFFFFFFCu; if (num == 244) { ReadFiles(pdbReader, documents, ref reader, num3); } reader.Position = num3; } DbiFunction[] array = new DbiFunction[Functions.Count]; Functions.CopyTo(array, 0); Array.Sort(array, (DbiFunction a, DbiFunction b) => a.Address.CompareTo(b.Address)); reader.Position = 0u; while (reader.Position < reader.Length) { uint num4 = reader.ReadUInt32(); uint num5 = reader.ReadUInt32(); uint num6 = reader.Position + num5; if (num4 == 242) { ReadLines(array, documents, ref reader, num6); } reader.Position = num6; } } private void ReadFiles(PdbReader pdbReader, Dictionary documents, ref DataReader reader, uint end) { uint position = reader.Position; while (reader.Position < end) { uint key = reader.Position - position; uint nameId = reader.ReadUInt32(); byte b = reader.ReadByte(); reader.ReadByte(); DbiDocument document = pdbReader.GetDocument(nameId); documents.Add(key, document); reader.Position += b; reader.Position = (reader.Position + 3) & 0xFFFFFFFCu; } } private void ReadLines(DbiFunction[] funcs, Dictionary documents, ref DataReader reader, uint end) { PdbAddress pdbAddress = PdbAddress.ReadAddress(ref reader); int num = 0; int num2 = funcs.Length - 1; int i = -1; while (num <= num2) { int num3 = num + (num2 - num >> 1); PdbAddress address = funcs[num3].Address; if (address < pdbAddress) { num = num3 + 1; continue; } if (address > pdbAddress) { num2 = num3 - 1; continue; } i = num3; break; } if (i == -1) { return; } ushort num4 = reader.ReadUInt16(); reader.Position += 4u; if (funcs[i].Lines == null) { while (i > 0) { DbiFunction dbiFunction = funcs[i - 1]; if (dbiFunction != null && dbiFunction.Address != pdbAddress) { break; } i--; } } else { for (; i < funcs.Length - 1 && funcs[i] != null && !(funcs[i + 1].Address != pdbAddress); i++) { } } DbiFunction dbiFunction2 = funcs[i]; if (dbiFunction2.Lines != null) { return; } dbiFunction2.Lines = new List(); while (reader.Position < end) { DbiDocument document = documents[reader.ReadUInt32()]; uint num5 = reader.ReadUInt32(); reader.Position += 4u; uint position = reader.Position; uint num6 = reader.Position + num5 * 8; for (uint num7 = 0u; num7 < num5; num7++) { reader.Position = position + num7 * 8; SymbolSequencePoint item = new SymbolSequencePoint { Document = document }; item.Offset = reader.ReadInt32(); uint num8 = reader.ReadUInt32(); item.Line = (int)(num8 & 0xFFFFFF); item.EndLine = item.Line + (int)((num8 >> 24) & 0x7F); if ((num4 & 1) != 0) { reader.Position = num6 + num7 * 4; item.Column = reader.ReadUInt16(); item.EndColumn = reader.ReadUInt16(); } dbiFunction2.Lines.Add(item); } } } } internal sealed class DbiNamespace : SymbolNamespace { private readonly string name; public override string Name => name; public DbiNamespace(string ns) { name = ns; } } internal sealed class DbiScope : SymbolScope { private readonly struct ConstantInfo { public readonly string Name; public readonly uint SignatureToken; public readonly object Value; public ConstantInfo(string name, uint signatureToken, object value) { Name = name; SignatureToken = signatureToken; Value = value; } } internal readonly struct OemInfo { public readonly string Name; public readonly byte[] Data; public OemInfo(string name, byte[] data) { Name = name; Data = data; } public override string ToString() { return $"{Name} = ({Data.Length} bytes)"; } } private readonly SymbolMethod method; private readonly SymbolScope parent; internal int startOffset; internal int endOffset; private readonly List childrenList; private readonly List localsList; private readonly List namespacesList; private List oemInfos; private List constants; private static readonly byte[] dotNetOemGuid = new byte[16] { 201, 63, 234, 198, 179, 89, 214, 73, 188, 37, 9, 2, 187, 171, 180, 96 }; public override SymbolMethod Method => method; public override SymbolScope Parent => parent; public override int StartOffset => startOffset; public override int EndOffset => endOffset; public override IList Children => childrenList; public override IList Locals => localsList; public override IList Namespaces => namespacesList; public override IList CustomDebugInfos => Array2.Empty(); public override PdbImportScope ImportScope => null; public string Name { get; private set; } public DbiScope(SymbolMethod method, SymbolScope parent, string name, uint offset, uint length) { this.method = method; this.parent = parent; Name = name; startOffset = (int)offset; endOffset = (int)(offset + length); childrenList = new List(); localsList = new List(); namespacesList = new List(); } public void Read(RecursionCounter counter, ref DataReader reader, uint scopeEnd) { if (!counter.Increment()) { throw new PdbException("Scopes too deep"); } while (reader.Position < scopeEnd) { ushort num = reader.ReadUInt16(); uint num2 = reader.Position + num; SymbolType symbolType = (SymbolType)reader.ReadUInt16(); DbiScope dbiScope = null; uint? num3 = null; switch (symbolType) { case SymbolType.S_BLOCK32: { reader.Position += 4u; num3 = reader.ReadUInt32(); uint length = reader.ReadUInt32(); PdbAddress pdbAddress = PdbAddress.ReadAddress(ref reader); string name = PdbReader.ReadCString(ref reader); dbiScope = new DbiScope(method, this, name, pdbAddress.Offset, length); break; } case SymbolType.S_UNAMESPACE: namespacesList.Add(new DbiNamespace(PdbReader.ReadCString(ref reader))); break; case SymbolType.S_MANSLOT: { DbiVariable dbiVariable = new DbiVariable(); if (dbiVariable.Read(ref reader)) { localsList.Add(dbiVariable); } break; } case SymbolType.S_OEM: { if ((ulong)((long)reader.Position + 20L) > (ulong)num2 || !ReadAndCompareBytes(ref reader, num2, dotNetOemGuid)) { break; } reader.Position += 4u; string name = ReadUnicodeString(ref reader, num2); if (name != null) { byte[] data = reader.ReadBytes((int)(num2 - reader.Position)); if (oemInfos == null) { oemInfos = new List(1); } oemInfos.Add(new OemInfo(name, data)); } break; } case SymbolType.S_MANCONSTANT: { uint signatureToken = reader.ReadUInt32(); if (NumericReader.TryReadNumeric(ref reader, num2, out var value)) { string name = PdbReader.ReadCString(ref reader); if (constants == null) { constants = new List(); } constants.Add(new ConstantInfo(name, signatureToken, value)); } break; } } reader.Position = num2; if (dbiScope != null) { dbiScope.Read(counter, ref reader, num3.Value); childrenList.Add(dbiScope); dbiScope = null; } } counter.Decrement(); if (reader.Position != scopeEnd) { Debugger.Break(); } } private static string ReadUnicodeString(ref DataReader reader, uint end) { StringBuilder stringBuilder = new StringBuilder(); while (true) { if ((ulong)((long)reader.Position + 2L) > (ulong)end) { return null; } char c = reader.ReadChar(); if (c == '\0') { break; } stringBuilder.Append(c); } return stringBuilder.ToString(); } private static bool ReadAndCompareBytes(ref DataReader reader, uint end, byte[] bytes) { if ((ulong)((long)reader.Position + (long)(uint)bytes.Length) > (ulong)end) { return false; } for (int i = 0; i < bytes.Length; i++) { if (reader.ReadByte() != bytes[i]) { return false; } } return true; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (constants == null) { return Array2.Empty(); } PdbConstant[] array = new PdbConstant[constants.Count]; for (int i = 0; i < array.Length; i++) { ConstantInfo constantInfo = constants[i]; array[i] = new PdbConstant(type: ((!(module.ResolveToken(constantInfo.SignatureToken, gpContext) is StandAloneSig standAloneSig)) ? null : (standAloneSig.Signature as FieldSig))?.Type, name: constantInfo.Name, value: constantInfo.Value); } return array; } internal byte[] GetSymAttribute(string name) { if (oemInfos == null) { return null; } foreach (OemInfo oemInfo in oemInfos) { if (oemInfo.Name == name) { return oemInfo.Data; } } return null; } } internal sealed class DbiVariable : SymbolVariable { private string name; private PdbLocalAttributes attributes; private int index; public override string Name => name; public override PdbLocalAttributes Attributes => attributes; public override int Index => index; public override PdbCustomDebugInfo[] CustomDebugInfos => Array2.Empty(); public bool Read(ref DataReader reader) { index = reader.ReadInt32(); reader.Position += 10u; ushort num = reader.ReadUInt16(); attributes = GetAttributes(num); name = PdbReader.ReadCString(ref reader); return (num & 1) == 0; } private static PdbLocalAttributes GetAttributes(uint flags) { PdbLocalAttributes pdbLocalAttributes = PdbLocalAttributes.None; if ((flags & 4) != 0) { pdbLocalAttributes |= PdbLocalAttributes.DebuggerHidden; } return pdbLocalAttributes; } } internal enum ModuleStreamType : uint { Symbols = 241u, Lines, StringTable, FileInfo, FrameData, InlineeLines, CrossScopeImports, CrossScopeExports, ILLines, FuncMDTokenMap, TypeMDTokenMap, MergedAssemblyInput } internal sealed class MsfStream { public DataReader Content; public MsfStream(DataReader[] pages, uint length) { byte[] array = new byte[length]; int num = 0; for (int i = 0; i < pages.Length; i++) { DataReader dataReader = pages[i]; dataReader.Position = 0u; int num2 = Math.Min((int)dataReader.Length, (int)(length - num)); dataReader.ReadBytes(array, num, num2); num += num2; } Content = ByteArrayDataReaderFactory.CreateReader(array); } } internal enum NumericLeaf : ushort { LF_NUMERIC = 32768, LF_CHAR = 32768, LF_SHORT = 32769, LF_USHORT = 32770, LF_LONG = 32771, LF_ULONG = 32772, LF_REAL32 = 32773, LF_REAL64 = 32774, LF_REAL80 = 32775, LF_REAL128 = 32776, LF_QUADWORD = 32777, LF_UQUADWORD = 32778, LF_REAL48 = 32779, LF_COMPLEX32 = 32780, LF_COMPLEX64 = 32781, LF_COMPLEX80 = 32782, LF_COMPLEX128 = 32783, LF_VARSTRING = 32784, LF_RESERVED_8011 = 32785, LF_RESERVED_8012 = 32786, LF_RESERVED_8013 = 32787, LF_RESERVED_8014 = 32788, LF_RESERVED_8015 = 32789, LF_RESERVED_8016 = 32790, LF_OCTWORD = 32791, LF_UOCTWORD = 32792, LF_VARIANT = 32793, LF_DATE = 32794, LF_UTF8STRING = 32795, LF_REAL16 = 32796 } internal static class NumericReader { public static bool TryReadNumeric(ref DataReader reader, ulong end, out object value) { value = null; ulong num = reader.Position; if (num + 2 > end) { return false; } NumericLeaf numericLeaf = (NumericLeaf)reader.ReadUInt16(); if ((int)numericLeaf < 32768) { value = (short)numericLeaf; return true; } switch (numericLeaf) { case NumericLeaf.LF_NUMERIC: if (num > end) { return false; } value = reader.ReadSByte(); return true; case NumericLeaf.LF_SHORT: if (num + 2 > end) { return false; } value = reader.ReadInt16(); return true; case NumericLeaf.LF_USHORT: if (num + 2 > end) { return false; } value = reader.ReadUInt16(); return true; case NumericLeaf.LF_LONG: if (num + 4 > end) { return false; } value = reader.ReadInt32(); return true; case NumericLeaf.LF_ULONG: if (num + 4 > end) { return false; } value = reader.ReadUInt32(); return true; case NumericLeaf.LF_REAL32: if (num + 4 > end) { return false; } value = reader.ReadSingle(); return true; case NumericLeaf.LF_REAL64: if (num + 8 > end) { return false; } value = reader.ReadDouble(); return true; case NumericLeaf.LF_QUADWORD: if (num + 8 > end) { return false; } value = reader.ReadInt64(); return true; case NumericLeaf.LF_UQUADWORD: if (num + 8 > end) { return false; } value = reader.ReadUInt64(); return true; case NumericLeaf.LF_VARSTRING: { if (num + 2 > end) { return false; } int num3 = reader.ReadUInt16(); if (num + (uint)num3 > end) { return false; } value = reader.ReadUtf8String(num3); return true; } case NumericLeaf.LF_VARIANT: { if (num + 16 > end) { return false; } int num2 = reader.ReadInt32(); int hi = reader.ReadInt32(); int lo = reader.ReadInt32(); int mid = reader.ReadInt32(); byte b = (byte)(num2 >> 16); if (b <= 28) { value = new decimal(lo, mid, hi, num2 < 0, b); } else { value = null; } return true; } default: return false; } } } [DebuggerDisplay("{Section}:{Offset}")] internal readonly struct PdbAddress : IEquatable, IComparable { public readonly ushort Section; public readonly uint Offset; public PdbAddress(ushort section, int offset) { Section = section; Offset = (uint)offset; } public PdbAddress(ushort section, uint offset) { Section = section; Offset = offset; } public static bool operator <=(PdbAddress a, PdbAddress b) { return a.CompareTo(b) <= 0; } public static bool operator <(PdbAddress a, PdbAddress b) { return a.CompareTo(b) < 0; } public static bool operator >=(PdbAddress a, PdbAddress b) { return a.CompareTo(b) >= 0; } public static bool operator >(PdbAddress a, PdbAddress b) { return a.CompareTo(b) > 0; } public static bool operator ==(PdbAddress a, PdbAddress b) { return a.Equals(b); } public static bool operator !=(PdbAddress a, PdbAddress b) { return !a.Equals(b); } public int CompareTo(PdbAddress other) { if (Section != other.Section) { return Section.CompareTo(other.Section); } return Offset.CompareTo(other.Offset); } public bool Equals(PdbAddress other) { if (Section == other.Section) { return Offset == other.Offset; } return false; } public override bool Equals(object obj) { if (!(obj is PdbAddress)) { return false; } return Equals((PdbAddress)obj); } public override int GetHashCode() { return (Section << 16) ^ (int)Offset; } public override string ToString() { return $"{Section:X4}:{Offset:X8}"; } public static PdbAddress ReadAddress(ref DataReader reader) { uint offset = reader.ReadUInt32(); return new PdbAddress(reader.ReadUInt16(), offset); } } [Serializable] internal sealed class PdbException : Exception { public PdbException() { } public PdbException(string message) : base("Failed to read PDB: " + message) { } public PdbException(Exception innerException) : base("Failed to read PDB: " + innerException.Message, innerException) { } public PdbException(SerializationInfo info, StreamingContext context) : base(info, context) { } } internal sealed class PdbReader : SymbolReader { private MsfStream[] streams; private Dictionary names; private Dictionary strings; private List modules; private ModuleDef module; private const int STREAM_ROOT = 0; private const int STREAM_NAMES = 1; private const int STREAM_TPI = 2; private const int STREAM_DBI = 3; private const ushort STREAM_INVALID_INDEX = ushort.MaxValue; private Dictionary documents; private Dictionary functions; private byte[] sourcelinkData; private byte[] srcsrvData; private uint entryPt; private readonly Guid expectedGuid; private readonly uint expectedAge; private volatile SymbolDocument[] documentsResult; public override PdbFileKind PdbFileKind => PdbFileKind.WindowsPDB; private uint Age { get; set; } private Guid Guid { get; set; } internal bool MatchesModule { get { if (expectedGuid == Guid) { return expectedAge == Age; } return false; } } public override IList Documents { get { if (documentsResult == null) { SymbolDocument[] array = new SymbolDocument[documents.Count]; int num = 0; foreach (KeyValuePair document in documents) { array[num++] = document.Value; } documentsResult = array; } return documentsResult; } } public override int UserEntryPoint => (int)entryPt; public PdbReader(Guid expectedGuid, uint expectedAge) { this.expectedGuid = expectedGuid; this.expectedAge = expectedAge; } public override void Initialize(ModuleDef module) { this.module = module; } public void Read(DataReader reader) { try { ReadInternal(ref reader); } catch (Exception ex) { if (ex is PdbException) { throw; } throw new PdbException(ex); } finally { streams = null; names = null; strings = null; modules = null; } } private static uint RoundUpDiv(uint value, uint divisor) { return (value + divisor - 1) / divisor; } private void ReadInternal(ref DataReader reader) { if (reader.ReadString(30, Encoding.ASCII) != "Microsoft C/C++ MSF 7.00\r\n\u001aDS\0") { throw new PdbException("Invalid signature"); } reader.Position += 2u; uint num = reader.ReadUInt32(); reader.ReadUInt32(); uint num2 = reader.ReadUInt32(); uint num3 = reader.ReadUInt32(); reader.ReadUInt32(); uint num4 = RoundUpDiv(num3, num); uint num5 = RoundUpDiv(num4 * 4, num); if (num2 * num != reader.Length) { throw new PdbException("File size mismatch"); } DataReader[] array = new DataReader[num2]; uint num6 = 0u; for (uint num7 = 0u; num7 < num2; num7++) { array[num7] = reader.Slice(num6, num); num6 += num; } DataReader[] array2 = new DataReader[num4]; int num8 = 0; for (int i = 0; i < num5; i++) { if (num8 >= num4) { break; } DataReader dataReader = array[reader.ReadUInt32()]; dataReader.Position = 0u; while (dataReader.Position < dataReader.Length && num8 < num4) { array2[num8] = array[dataReader.ReadUInt32()]; num8++; } } ReadRootDirectory(new MsfStream(array2, num3), array, num); ReadNames(); if (!MatchesModule) { return; } ReadStringTable(); ushort? num9 = ReadModules(); documents = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (DbiModule module in modules) { if (IsValidStreamIndex(module.StreamId)) { module.LoadFunctions(this, ref streams[module.StreamId].Content); } } if (IsValidStreamIndex(num9 ?? ushort.MaxValue)) { ApplyRidMap(ref streams[num9.Value].Content); } functions = new Dictionary(); foreach (DbiModule module2 in modules) { foreach (DbiFunction function in module2.Functions) { function.reader = this; functions.Add(function.Token, function); } } sourcelinkData = TryGetRawFileData("sourcelink"); srcsrvData = TryGetRawFileData("srcsrv"); } private byte[] TryGetRawFileData(string name) { if (!names.TryGetValue(name, out var value)) { return null; } if (value > 65535 || !IsValidStreamIndex((ushort)value)) { return null; } return streams[value].Content.ToArray(); } private bool IsValidStreamIndex(ushort index) { if (index != ushort.MaxValue) { return index < streams.Length; } return false; } private void ReadRootDirectory(MsfStream stream, DataReader[] pages, uint pageSize) { uint num = stream.Content.ReadUInt32(); uint[] array = new uint[num]; for (int i = 0; i < array.Length; i++) { array[i] = stream.Content.ReadUInt32(); } streams = new MsfStream[num]; for (int j = 0; j < array.Length; j++) { if (array[j] == uint.MaxValue) { streams[j] = null; continue; } DataReader[] array2 = new DataReader[RoundUpDiv(array[j], pageSize)]; for (int k = 0; k < array2.Length; k++) { array2[k] = pages[stream.Content.ReadUInt32()]; } streams[j] = new MsfStream(array2, array[j]); } } private void ReadNames() { ref DataReader content = ref streams[1].Content; content.Position = 8u; Age = content.ReadUInt32(); Guid = content.ReadGuid(); uint num = content.ReadUInt32(); DataReader reader = content.Slice(content.Position, num); content.Position += num; content.ReadUInt32(); uint val = content.ReadUInt32(); BitArray bitArray = new BitArray(content.ReadBytes(content.ReadInt32() * 4)); if (content.ReadUInt32() != 0) { throw new NotSupportedException(); } names = new Dictionary(StringComparer.OrdinalIgnoreCase); val = Math.Min(val, (uint)bitArray.Count); for (int i = 0; i < val; i++) { if (bitArray[i]) { uint position = content.ReadUInt32(); uint value = content.ReadUInt32(); reader.Position = position; string key = ReadCString(ref reader); names[key] = value; } } } private void ReadStringTable() { if (!names.TryGetValue("/names", out var value)) { throw new PdbException("String table not found"); } ref DataReader content = ref streams[value].Content; content.Position = 8u; uint num = content.ReadUInt32(); DataReader reader = content.Slice(content.Position, num); content.Position += num; uint num2 = content.ReadUInt32(); strings = new Dictionary((int)num2); for (uint num3 = 0u; num3 < num2; num3++) { uint num4 = content.ReadUInt32(); if (num4 != 0) { reader.Position = num4; strings[num4] = ReadCString(ref reader); } } } private static uint ReadSizeField(ref DataReader reader) { int num = reader.ReadInt32(); if (num > 0) { return (uint)num; } return 0u; } private ushort? ReadModules() { ref DataReader content = ref streams[3].Content; modules = new List(); if (content.Length == 0) { return null; } content.Position = 20u; ushort num = content.ReadUInt16(); content.Position += 2u; uint num2 = ReadSizeField(ref content); uint num3 = 0u; num3 += ReadSizeField(ref content); num3 += ReadSizeField(ref content); num3 += ReadSizeField(ref content); num3 += ReadSizeField(ref content); content.ReadUInt32(); uint num4 = ReadSizeField(ref content); num3 += ReadSizeField(ref content); content.Position += 8u; DataReader reader = content.Slice(content.Position, num2); while (reader.Position < reader.Length) { DbiModule dbiModule = new DbiModule(); dbiModule.Read(ref reader); modules.Add(dbiModule); } if (IsValidStreamIndex(num)) { ReadGlobalSymbols(ref streams[num].Content); } if (num4 != 0) { content.Position += num2; content.Position += num3; content.Position += 12u; return content.ReadUInt16(); } return null; } internal DbiDocument GetDocument(uint nameId) { string text = strings[nameId]; if (!documents.TryGetValue(text, out var value)) { value = new DbiDocument(text); if (names.TryGetValue("/src/files/" + text, out var value2)) { value.Read(ref streams[value2].Content); } documents.Add(text, value); } return value; } private void ReadGlobalSymbols(ref DataReader reader) { reader.Position = 0u; while (reader.Position < reader.Length) { ushort num = reader.ReadUInt16(); uint position = reader.Position + num; if (reader.ReadUInt16() == 4366) { reader.Position += 4u; uint num2 = reader.ReadUInt32(); reader.Position += 2u; if (ReadCString(ref reader) == "COM+_Entry_Point") { entryPt = num2; break; } } reader.Position = position; } } private void ApplyRidMap(ref DataReader reader) { reader.Position = 0u; uint[] array = new uint[reader.Length / 4]; for (int i = 0; i < array.Length; i++) { array[i] = reader.ReadUInt32(); } foreach (DbiModule module in modules) { foreach (DbiFunction function in module.Functions) { uint num = (uint)(function.Token & 0xFFFFFF); num = array[num]; function.token = (int)((function.Token & 0xFF000000u) | num); } } if (entryPt != 0) { uint num2 = entryPt & 0xFFFFFF; num2 = array[num2]; entryPt = (entryPt & 0xFF000000u) | num2; } } internal static string ReadCString(ref DataReader reader) { return reader.TryReadZeroTerminatedUtf8String() ?? string.Empty; } public override SymbolMethod GetMethod(MethodDef method, int version) { if (version != 1) { return null; } if (functions.TryGetValue(method.MDToken.ToInt32(), out var value)) { return value; } return null; } internal void GetCustomDebugInfos(DbiFunction symMethod, MethodDef method, CilBody body, IList result) { PdbAsyncMethodCustomDebugInfo pdbAsyncMethodCustomDebugInfo = PseudoCustomDebugInfoFactory.TryCreateAsyncMethod(method.Module, method, body, symMethod.AsyncKickoffMethod, symMethod.AsyncStepInfos, symMethod.AsyncCatchHandlerILOffset); if (pdbAsyncMethodCustomDebugInfo != null) { result.Add(pdbAsyncMethodCustomDebugInfo); } byte[] symAttribute = symMethod.Root.GetSymAttribute("MD2"); if (symAttribute != null) { PdbCustomDebugInfoReader.Read(method, body, result, symAttribute); } } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { if (token == 1) { GetCustomDebugInfos_ModuleDef(result); } } private void GetCustomDebugInfos_ModuleDef(IList result) { if (sourcelinkData != null) { result.Add(new PdbSourceLinkCustomDebugInfo(sourcelinkData)); } if (srcsrvData != null) { result.Add(new PdbSourceServerCustomDebugInfo(srcsrvData)); } } } internal static class SymbolReaderFactory { public static SymbolReader Create(PdbReaderContext pdbContext, DataReaderFactory pdbStream) { if (pdbStream == null) { return null; } try { if (pdbContext.CodeViewDebugDirectory == null) { return null; } if (!pdbContext.TryGetCodeViewData(out var guid, out var age)) { return null; } PdbReader pdbReader = new PdbReader(guid, age); pdbReader.Read(pdbStream.CreateReader()); if (pdbReader.MatchesModule) { return pdbReader; } return null; } catch (PdbException) { } catch (IOException) { } finally { pdbStream?.Dispose(); } return null; } } internal enum SymbolType : ushort { S_COMPILE = 1, S_REGISTER_16t = 2, S_CONSTANT_16t = 3, S_UDT_16t = 4, S_SSEARCH = 5, S_END = 6, S_SKIP = 7, S_CVRESERVE = 8, S_OBJNAME_ST = 9, S_ENDARG = 10, S_COBOLUDT_16t = 11, S_MANYREG_16t = 12, S_RETURN = 13, S_ENTRYTHIS = 14, S_BPREL16 = 256, S_LDATA16 = 257, S_GDATA16 = 258, S_PUB16 = 259, S_LPROC16 = 260, S_GPROC16 = 261, S_THUNK16 = 262, S_BLOCK16 = 263, S_WITH16 = 264, S_LABEL16 = 265, S_CEXMODEL16 = 266, S_VFTABLE16 = 267, S_REGREL16 = 268, S_BPREL32_16t = 512, S_LDATA32_16t = 513, S_GDATA32_16t = 514, S_PUB32_16t = 515, S_LPROC32_16t = 516, S_GPROC32_16t = 517, S_THUNK32_ST = 518, S_BLOCK32_ST = 519, S_WITH32_ST = 520, S_LABEL32_ST = 521, S_CEXMODEL32 = 522, S_VFTABLE32_16t = 523, S_REGREL32_16t = 524, S_LTHREAD32_16t = 525, S_GTHREAD32_16t = 526, S_SLINK32 = 527, S_LPROCMIPS_16t = 768, S_GPROCMIPS_16t = 769, S_PROCREF_ST = 1024, S_DATAREF_ST = 1025, S_ALIGN = 1026, S_LPROCREF_ST = 1027, S_OEM = 1028, S_TI16_MAX = 4096, S_REGISTER_ST = 4097, S_CONSTANT_ST = 4098, S_UDT_ST = 4099, S_COBOLUDT_ST = 4100, S_MANYREG_ST = 4101, S_BPREL32_ST = 4102, S_LDATA32_ST = 4103, S_GDATA32_ST = 4104, S_PUB32_ST = 4105, S_LPROC32_ST = 4106, S_GPROC32_ST = 4107, S_VFTABLE32 = 4108, S_REGREL32_ST = 4109, S_LTHREAD32_ST = 4110, S_GTHREAD32_ST = 4111, S_LPROCMIPS_ST = 4112, S_GPROCMIPS_ST = 4113, S_FRAMEPROC = 4114, S_COMPILE2_ST = 4115, S_MANYREG2_ST = 4116, S_LPROCIA64_ST = 4117, S_GPROCIA64_ST = 4118, S_LOCALSLOT_ST = 4119, S_PARAMSLOT_ST = 4120, S_ANNOTATION = 4121, S_GMANPROC_ST = 4122, S_LMANPROC_ST = 4123, S_RESERVED1 = 4124, S_RESERVED2 = 4125, S_RESERVED3 = 4126, S_RESERVED4 = 4127, S_LMANDATA_ST = 4128, S_GMANDATA_ST = 4129, S_MANFRAMEREL_ST = 4130, S_MANREGISTER_ST = 4131, S_MANSLOT_ST = 4132, S_MANMANYREG_ST = 4133, S_MANREGREL_ST = 4134, S_MANMANYREG2_ST = 4135, S_MANTYPREF = 4136, S_UNAMESPACE_ST = 4137, S_ST_MAX = 4352, S_OBJNAME = 4353, S_THUNK32 = 4354, S_BLOCK32 = 4355, S_WITH32 = 4356, S_LABEL32 = 4357, S_REGISTER = 4358, S_CONSTANT = 4359, S_UDT = 4360, S_COBOLUDT = 4361, S_MANYREG = 4362, S_BPREL32 = 4363, S_LDATA32 = 4364, S_GDATA32 = 4365, S_PUB32 = 4366, S_LPROC32 = 4367, S_GPROC32 = 4368, S_REGREL32 = 4369, S_LTHREAD32 = 4370, S_GTHREAD32 = 4371, S_LPROCMIPS = 4372, S_GPROCMIPS = 4373, S_COMPILE2 = 4374, S_MANYREG2 = 4375, S_LPROCIA64 = 4376, S_GPROCIA64 = 4377, S_LOCALSLOT = 4378, S_PARAMSLOT = 4379, S_LMANDATA = 4380, S_GMANDATA = 4381, S_MANFRAMEREL = 4382, S_MANREGISTER = 4383, S_MANSLOT = 4384, S_MANMANYREG = 4385, S_MANREGREL = 4386, S_MANMANYREG2 = 4387, S_UNAMESPACE = 4388, S_PROCREF = 4389, S_DATAREF = 4390, S_LPROCREF = 4391, S_ANNOTATIONREF = 4392, S_TOKENREF = 4393, S_GMANPROC = 4394, S_LMANPROC = 4395, S_TRAMPOLINE = 4396, S_MANCONSTANT = 4397, S_ATTR_FRAMEREL = 4398, S_ATTR_REGISTER = 4399, S_ATTR_REGREL = 4400, S_ATTR_MANYREG = 4401, S_SEPCODE = 4402, S_LOCAL_2005 = 4403, S_DEFRANGE_2005 = 4404, S_DEFRANGE2_2005 = 4405, S_SECTION = 4406, S_COFFGROUP = 4407, S_EXPORT = 4408, S_CALLSITEINFO = 4409, S_FRAMECOOKIE = 4410, S_DISCARDED = 4411, S_COMPILE3 = 4412, S_ENVBLOCK = 4413, S_LOCAL = 4414, S_DEFRANGE = 4415, S_DEFRANGE_SUBFIELD = 4416, S_DEFRANGE_REGISTER = 4417, S_DEFRANGE_FRAMEPOINTER_REL = 4418, S_DEFRANGE_SUBFIELD_REGISTER = 4419, S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 4420, S_DEFRANGE_REGISTER_REL = 4421, S_LPROC32_ID = 4422, S_GPROC32_ID = 4423, S_LPROCMIPS_ID = 4424, S_GPROCMIPS_ID = 4425, S_LPROCIA64_ID = 4426, S_GPROCIA64_ID = 4427, S_BUILDINFO = 4428, S_INLINESITE = 4429, S_INLINESITE_END = 4430, S_PROC_ID_END = 4431, S_DEFRANGE_HLSL = 4432, S_GDATA_HLSL = 4433, S_LDATA_HLSL = 4434, S_FILESTATIC = 4435, S_LOCAL_DPC_GROUPSHARED = 4436, S_LPROC32_DPC = 4437, S_LPROC32_DPC_ID = 4438, S_DEFRANGE_DPC_PTR_TAG = 4439, S_DPC_SYM_TAG_MAP = 4440, S_ARMSWITCHTABLE = 4441, S_CALLEES = 4442, S_CALLERS = 4443, S_POGODATA = 4444, S_INLINESITE2 = 4445, S_HEAPALLOCSITE = 4446, S_RECTYPE_MAX = 4447 } } namespace dnlib.DotNet.Pdb.Dss { [ComImport] [ComVisible(true)] [Guid("969708D2-05E5-4861-A3B0-96E473CDF63F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedDispose { [PreserveSig] int Destroy(); } [ComImport] [ComVisible(true)] [Guid("997DD0CC-A76F-4c82-8D79-EA87559D27AD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedSourceServerModule { [PreserveSig] int GetSourceServerData(out int pDataByteCount, out IntPtr ppData); } [ComImport] [ComVisible(true)] [Guid("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedReader { void GetDocument([In][MarshalAs(UnmanagedType.LPWStr)] string url, [In] Guid language, [In] Guid languageVendor, [In] Guid documentType, out ISymUnmanagedDocument pRetVal); void GetDocuments([In] uint cDocs, out uint pcDocs, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] pDocs); [PreserveSig] int GetUserEntryPoint(out uint pToken); void GetMethod([In] uint token, out ISymUnmanagedMethod retVal); [PreserveSig] int GetMethodByVersion([In] uint token, [In] int version, out ISymUnmanagedMethod pRetVal); void GetVariables([In] uint parent, [In] uint cVars, out uint pcVars, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedVariable[] pVars); void GetGlobalVariables([In] uint cVars, out uint pcVars, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] pVars); void GetMethodFromDocumentPosition([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, out ISymUnmanagedMethod pRetVal); void GetSymAttribute([In] uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cBuffer, out uint pcBuffer, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer); void GetNamespaces([In] uint cNameSpaces, out uint pcNameSpaces, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); [PreserveSig] int Initialize([In][MarshalAs(UnmanagedType.IUnknown)] object importer, [In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In][MarshalAs(UnmanagedType.LPWStr)] string searchPath, [In] IStream pIStream); void UpdateSymbolStore([In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream); void ReplaceSymbolStore([In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream); void GetSymbolStoreFileName([In] uint cchName, out uint pcchName, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetMethodsFromDocumentPosition([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, out uint pcMethod, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] ISymUnmanagedMethod[] pRetVal); void GetDocumentVersion([In] ISymUnmanagedDocument pDoc, out int version, out bool pbCurrent); void GetMethodVersion([In] ISymUnmanagedMethod pMethod, out int version); } [ComImport] [ComVisible(true)] [Guid("A09E53B2-2A57-4cca-8F63-B84F7C35D4AA")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedReader2 : ISymUnmanagedReader { void _VtblGap1_17(); void GetMethodByVersionPreRemap(uint token, uint version, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedMethod pRetVal); void GetSymAttributePreRemap(uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, uint cBuffer, out uint pcBuffer, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer); void GetMethodsInDocument(ISymUnmanagedDocument document, uint bufferLength, out uint count, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedMethod[] methods); } [ComImport] [ComVisible(true)] [Guid("6151CAD9-E1EE-437A-A808-F64838C0D046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedReader3 : ISymUnmanagedReader2, ISymUnmanagedReader { void _VtblGap1_20(); void GetSymAttributeByVersion(uint token, uint version, [MarshalAs(UnmanagedType.LPWStr)] string name, uint cBuffer, out uint pcBuffer, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] buffer); void GetSymAttributeByVersionPreRemap(int methodToken, int version, [MarshalAs(UnmanagedType.LPWStr)] string name, int cBuffer, out int pcBuffer, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] buffer); } [ComImport] [ComVisible(true)] [Guid("E65C58B7-2948-434D-8A6D-481740A00C16")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedReader4 : ISymUnmanagedReader3, ISymUnmanagedReader2, ISymUnmanagedReader { void _VtblGap1_22(); [PreserveSig] int MatchesModule(Guid guid, uint stamp, uint age, [MarshalAs(UnmanagedType.Bool)] out bool result); void GetPortableDebugMetadata(out IntPtr pMetadata, out uint pcMetadata); [PreserveSig] int GetSourceServerData(out IntPtr data, out int pcData); } [ComImport] [ComVisible(true)] [Guid("6576C987-7E8D-4298-A6E1-6F9783165F07")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedReader5 : ISymUnmanagedReader4, ISymUnmanagedReader3, ISymUnmanagedReader2, ISymUnmanagedReader { void _VtblGap1_25(); void GetPortableDebugMetadataByVersion(uint version, out IntPtr pMetadata, out uint pcMetadata); } [ComImport] [ComVisible(true)] [Guid("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedDocument { void GetURL([In] uint cchUrl, out uint pcchUrl, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szUrl); void GetDocumentType(out Guid pRetVal); void GetLanguage(out Guid pRetVal); void GetLanguageVendor(out Guid pRetVal); void GetCheckSumAlgorithmId(out Guid pRetVal); void GetCheckSum([In] uint cData, out uint pcData, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] data); void FindClosestLine([In] uint line, out uint pRetVal); void HasEmbeddedSource(out bool pRetVal); [PreserveSig] int GetSourceLength(out int pRetVal); [PreserveSig] int GetSourceRange([In] uint startLine, [In] uint startColumn, [In] uint endLine, [In] uint endColumn, [In] int cSourceBytes, out int pcSourceBytes, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] source); } [ComImport] [ComVisible(true)] [Guid("B62B923C-B500-3158-A543-24F307A8B7E1")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedMethod { void GetToken(out uint pToken); void GetSequencePointCount(out uint pRetVal); void GetRootScope(out ISymUnmanagedScope pRetVal); void GetScopeFromOffset([In] uint offset, out ISymUnmanagedScope pRetVal); void GetOffset([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, out uint pRetVal); void GetRanges([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cRanges, out uint pcRanges, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] int[] ranges); void GetParameters([In] uint cParams, out uint pcParams, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] parameters); void GetNamespace(out ISymUnmanagedNamespace pRetVal); void GetSourceStartEnd([In] ISymUnmanagedDocument[] docs, [In] int[] lines, [In] int[] columns, out bool pRetVal); void GetSequencePoints([In] uint cPoints, out uint pcPoints, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] offsets, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] documents, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] lines, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] columns, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] endLines, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] endColumns); } [ComImport] [ComVisible(true)] [Guid("5DA320C8-9C2C-4E5A-B823-027E0677B359")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedMethod2 : ISymUnmanagedMethod { void _VtblGap1_10(); void GetLocalSignatureToken(out uint token); } [ComImport] [ComVisible(true)] [Guid("B20D55B3-532E-4906-87E7-25BD5734ABD2")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedAsyncMethod { bool IsAsyncMethod(); uint GetKickoffMethod(); bool HasCatchHandlerILOffset(); uint GetCatchHandlerILOffset(); uint GetAsyncStepInfoCount(); void GetAsyncStepInfo([In] uint cStepInfo, out uint pcStepInfo, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] yieldOffsets, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointOffset, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointMethod); } [ComImport] [ComVisible(true)] [Guid("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedVariable { void GetName([In] uint cchName, out uint pcchName, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetAttributes(out uint pRetVal); void GetSignature([In] uint cSig, out uint pcSig, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] sig); void GetAddressKind(out uint pRetVal); void GetAddressField1(out uint pRetVal); void GetAddressField2(out uint pRetVal); void GetAddressField3(out uint pRetVal); void GetStartOffset(out uint pRetVal); void GetEndOffset(out uint pRetVal); } [ComImport] [ComVisible(true)] [Guid("0DFF7289-54F8-11D3-BD28-0000F80849BD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedNamespace { void GetName([In] uint cchName, out uint pcchName, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetNamespaces([In] uint cNameSpaces, out uint pcNameSpaces, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); void GetVariables([In] uint cVars, out uint pcVars, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] pVars); } [ComImport] [ComVisible(true)] [Guid("68005D0F-B8E0-3B01-84D5-A11A94154942")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedScope { void GetMethod(out ISymUnmanagedMethod pRetVal); void GetParent(out ISymUnmanagedScope pRetVal); void GetChildren([In] uint cChildren, out uint pcChildren, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedScope[] children); void GetStartOffset(out uint pRetVal); void GetEndOffset(out uint pRetVal); void GetLocalCount(out uint pRetVal); void GetLocals([In] uint cLocals, out uint pcLocals, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] locals); void GetNamespaces([In] uint cNameSpaces, out uint pcNameSpaces, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); } [ComImport] [ComVisible(true)] [Guid("AE932FBA-3FD8-4dba-8232-30A2309B02DB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedScope2 : ISymUnmanagedScope { new void GetMethod(out ISymUnmanagedMethod pRetVal); new void GetParent(out ISymUnmanagedScope pRetVal); new void GetChildren([In] uint cChildren, out uint pcChildren, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedScope[] children); new void GetStartOffset(out uint pRetVal); new void GetEndOffset(out uint pRetVal); new void GetLocalCount(out uint pRetVal); new void GetLocals([In] uint cLocals, out uint pcLocals, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] locals); new void GetNamespaces([In] uint cNameSpaces, out uint pcNameSpaces, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); uint GetConstantCount(); void GetConstants([In] uint cConstants, out uint pcConstants, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedConstant[] constants); } [ComImport] [ComVisible(true)] [Guid("48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedConstant { void GetName([In] uint cchName, out uint pcchName, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetValue(out object pValue); [PreserveSig] int GetSignature([In] uint cSig, out uint pcSig, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] sig); } [ComImport] [ComVisible(true)] [Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMetaDataImport { void CloseEnum(IntPtr hEnum); void CountEnum(IntPtr hEnum, ref uint pulCount); void ResetEnum(IntPtr hEnum, uint ulPos); void EnumTypeDefs(IntPtr phEnum, uint[] rTypeDefs, uint cMax, out uint pcTypeDefs); void EnumInterfaceImpls(ref IntPtr phEnum, uint td, uint[] rImpls, uint cMax, ref uint pcImpls); void EnumTypeRefs(ref IntPtr phEnum, uint[] rTypeRefs, uint cMax, ref uint pcTypeRefs); void FindTypeDefByName([In][MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint tkEnclosingClass, out uint ptd); void GetScopeProps([Out] IntPtr szName, [In] uint cchName, out uint pchName, out Guid pmvid); void GetModuleFromScope(out uint pmd); unsafe void GetTypeDefProps([In] uint td, [In] ushort* szTypeDef, [In] uint cchTypeDef, [Out] uint* pchTypeDef, [Out] uint* pdwTypeDefFlags, [Out] uint* ptkExtends); void GetInterfaceImplProps([In] uint iiImpl, out uint pClass, out uint ptkIface); unsafe void GetTypeRefProps([In] uint tr, [Out] uint* ptkResolutionScope, [Out] ushort* szName, [In] uint cchName, [Out] uint* pchName); void ResolveTypeRef(uint tr, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppIScope, out uint ptd); void EnumMembers([In][Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rMembers, [In] uint cMax, out uint pcTokens); void EnumMembersWithName([In][Out] ref IntPtr phEnum, [In] uint cl, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] uint[] rMembers, [In] uint cMax, out uint pcTokens); void EnumMethods([In][Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rMethods, [In] uint cMax, out uint pcTokens); void EnumMethodsWithName([In][Out] ref IntPtr phEnum, [In] uint cl, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, uint[] rMethods, [In] uint cMax, out uint pcTokens); void EnumFields([In][Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rFields, [In] uint cMax, out uint pcTokens); void EnumFieldsWithName([In][Out] ref IntPtr phEnum, [In] uint cl, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] uint[] rFields, [In] uint cMax, out uint pcTokens); void EnumParams([In][Out] ref IntPtr phEnum, [In] uint mb, [Out] uint[] rParams, [In] uint cMax, out uint pcTokens); void EnumMemberRefs([In][Out] ref IntPtr phEnum, [In] uint tkParent, [Out] uint[] rMemberRefs, [In] uint cMax, out uint pcTokens); void EnumMethodImpls([In][Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rMethodBody, [Out] uint[] rMethodDecl, [In] uint cMax, out uint pcTokens); void EnumPermissionSets([In][Out] ref IntPtr phEnum, [In] uint tk, [In] uint dwActions, [Out] uint[] rPermission, [In] uint cMax, out uint pcTokens); void FindMember([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, out uint pmb); void FindMethod([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, out uint pmb); void FindField([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, out uint pmb); void FindMemberRef([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, out uint pmr); unsafe void GetMethodProps(uint mb, uint* pClass, [In] ushort* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, [Out] IntPtr* ppvSigBlob, [Out] uint* pcbSigBlob, [Out] uint* pulCodeRVA, [Out] uint* pdwImplFlags); void GetMemberRefProps([In] uint mr, out uint ptk, [Out] IntPtr szMember, [In] uint cchMember, out uint pchMember, out IntPtr ppvSigBlob, out uint pbSig); void EnumProperties([In][Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rProperties, [In] uint cMax, out uint pcProperties); void EnumEvents([In][Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rEvents, [In] uint cMax, out uint pcEvents); void GetEventProps([In] uint ev, out uint pClass, [Out][MarshalAs(UnmanagedType.LPWStr)] string szEvent, [In] uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, [In][Out] uint[] rmdOtherMethod, [In] uint cMax, out uint pcOtherMethod); void EnumMethodSemantics([In][Out] ref IntPtr phEnum, [In] uint mb, [In][Out] uint[] rEventProp, [In] uint cMax, out uint pcEventProp); void GetMethodSemantics([In] uint mb, [In] uint tkEventProp, out uint pdwSemanticsFlags); void GetClassLayout([In] uint td, out uint pdwPackSize, out IntPtr rFieldOffset, [In] uint cMax, out uint pcFieldOffset, out uint pulClassSize); void GetFieldMarshal([In] uint tk, out IntPtr ppvNativeType, out uint pcbNativeType); void GetRVA(uint tk, out uint pulCodeRVA, out uint pdwImplFlags); void GetPermissionSetProps([In] uint pm, out uint pdwAction, out IntPtr ppvPermission, out uint pcbPermission); unsafe void GetSigFromToken([In] uint mdSig, [Out] byte** ppvSig, [Out] uint* pcbSig); void GetModuleRefProps([In] uint mur, [Out] IntPtr szName, [In] uint cchName, out uint pchName); void EnumModuleRefs([In][Out] ref IntPtr phEnum, [Out] uint[] rModuleRefs, [In] uint cmax, out uint pcModuleRefs); void GetTypeSpecFromToken([In] uint typespec, out IntPtr ppvSig, out uint pcbSig); void GetNameFromToken([In] uint tk, out IntPtr pszUtf8NamePtr); void EnumUnresolvedMethods([In][Out] ref IntPtr phEnum, [Out] uint[] rMethods, [In] uint cMax, out uint pcTokens); void GetUserString([In] uint stk, [Out] IntPtr szString, [In] uint cchString, out uint pchString); void GetPinvokeMap([In] uint tk, out uint pdwMappingFlags, [Out] IntPtr szImportName, [In] uint cchImportName, out uint pchImportName, out uint pmrImportDLL); void EnumSignatures([In][Out] ref IntPtr phEnum, [Out] uint[] rSignatures, [In] uint cmax, out uint pcSignatures); void EnumTypeSpecs([In][Out] ref IntPtr phEnum, [Out] uint[] rTypeSpecs, [In] uint cmax, out uint pcTypeSpecs); void EnumUserStrings([In][Out] ref IntPtr phEnum, [Out] uint[] rStrings, [In] uint cmax, out uint pcStrings); void GetParamForMethodIndex([In] uint md, [In] uint ulParamSeq, out uint ppd); void EnumCustomAttributes([In][Out] IntPtr phEnum, [In] uint tk, [In] uint tkType, [Out] uint[] rCustomAttributes, [In] uint cMax, out uint pcCustomAttributes); void GetCustomAttributeProps([In] uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob, out uint pcbSize); void FindTypeRef([In] uint tkResolutionScope, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, out uint ptr); void GetMemberProps(uint mb, out uint pClass, IntPtr szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue); void GetFieldProps(uint mb, out uint pClass, IntPtr szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue); void GetPropertyProps([In] uint prop, out uint pClass, [Out] IntPtr szProperty, [In] uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, [In][Out] uint[] rmdOtherMethod, [In] uint cMax, out uint pcOtherMethod); void GetParamProps([In] uint tk, out uint pmd, out uint pulSequence, [Out] IntPtr szName, [Out] uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue); void GetCustomAttributeByName([In] uint tkObj, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, out IntPtr ppData, out uint pcbData); bool IsValidToken([In] uint tk); unsafe void GetNestedClassProps([In] uint tdNestedClass, [Out] uint* ptdEnclosingClass); void GetNativeCallConvFromSig([In] IntPtr pvSig, [In] uint cbSig, out uint pCallConv); void IsGlobal([In] uint pd, out int pbGlobal); } [ComImport] [ComVisible(true)] [Guid("BA3FEE4C-ECB9-4E41-83B7-183FA41CD859")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMetaDataEmit { void SetModuleProps([In][MarshalAs(UnmanagedType.LPWStr)] string szName); void Save([In][MarshalAs(UnmanagedType.LPWStr)] string szFile, [In] uint dwSaveFlags); void SaveToStream([In] IStream pIStream, [In] uint dwSaveFlags); void GetSaveSize([In] int fSave, out uint pdwSaveSize); void DefineTypeDef([In][MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements, out uint ptd); void DefineNestedType([In][MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements, [In] uint tdEncloser, out uint ptd); void SetHandler([In][MarshalAs(UnmanagedType.IUnknown)] object pUnk); void DefineMethod(uint td, [MarshalAs(UnmanagedType.LPWStr)] string szName, uint dwMethodFlags, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags, out uint pmd); void DefineMethodImpl([In] uint td, [In] uint tkBody, [In] uint tkDecl); void DefineTypeRefByName([In] uint tkResolutionScope, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, out uint ptr); void DefineImportType([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport pImport, [In] uint tdImport, [In] IntPtr pAssemEmit, out uint ptr); void DefineMemberRef([In] uint tkImport, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, out uint pmr); void DefineImportMember([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport pImport, [In] uint mbMember, [In] IntPtr pAssemEmit, [In] uint tkParent, out uint pmr); void DefineEvent([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szEvent, [In] uint dwEventFlags, [In] uint tkEventType, [In] uint mdAddOn, [In] uint mdRemoveOn, [In] uint mdFire, [In] uint[] rmdOtherMethods, out uint pmdEvent); void SetClassLayout([In] uint td, [In] uint dwPackSize, [In] IntPtr rFieldOffsets, [In] uint ulClassSize); void DeleteClassLayout([In] uint td); void SetFieldMarshal([In] uint tk, [In] IntPtr pvNativeType, [In] uint cbNativeType); void DeleteFieldMarshal([In] uint tk); void DefinePermissionSet([In] uint tk, [In] uint dwAction, [In] IntPtr pvPermission, [In] uint cbPermission, out uint ppm); void SetRVA([In] uint md, [In] uint ulRVA); void GetTokenFromSig([In] IntPtr pvSig, [In] uint cbSig, out uint pmsig); void DefineModuleRef([In][MarshalAs(UnmanagedType.LPWStr)] string szName, out uint pmur); void SetParent([In] uint mr, [In] uint tk); void GetTokenFromTypeSpec([In] IntPtr pvSig, [In] uint cbSig, out uint ptypespec); void SaveToMemory(out IntPtr pbData, [In] uint cbData); void DefineUserString([In][MarshalAs(UnmanagedType.LPWStr)] string szString, [In] uint cchString, out uint pstk); void DeleteToken([In] uint tkObj); void SetMethodProps([In] uint md, [In] uint dwMethodFlags, [In] uint ulCodeRVA, [In] uint dwImplFlags); void SetTypeDefProps([In] uint td, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements); void SetEventProps([In] uint ev, [In] uint dwEventFlags, [In] uint tkEventType, [In] uint mdAddOn, [In] uint mdRemoveOn, [In] uint mdFire, [In] uint[] rmdOtherMethods); void SetPermissionSetProps([In] uint tk, [In] uint dwAction, [In] IntPtr pvPermission, [In] uint cbPermission, out uint ppm); void DefinePinvokeMap([In] uint tk, [In] uint dwMappingFlags, [In][MarshalAs(UnmanagedType.LPWStr)] string szImportName, [In] uint mrImportDLL); void SetPinvokeMap([In] uint tk, [In] uint dwMappingFlags, [In][MarshalAs(UnmanagedType.LPWStr)] string szImportName, [In] uint mrImportDLL); void DeletePinvokeMap([In] uint tk); void DefineCustomAttribute([In] uint tkOwner, [In] uint tkCtor, [In] IntPtr pCustomAttribute, [In] uint cbCustomAttribute, out uint pcv); void SetCustomAttributeValue([In] uint pcv, [In] IntPtr pCustomAttribute, [In] uint cbCustomAttribute); void DefineField(uint td, [MarshalAs(UnmanagedType.LPWStr)] string szName, uint dwFieldFlags, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, out uint pmd); void DefineProperty([In] uint td, [In][MarshalAs(UnmanagedType.LPWStr)] string szProperty, [In] uint dwPropFlags, [In] IntPtr pvSig, [In] uint cbSig, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [In] uint mdSetter, [In] uint mdGetter, [In] uint[] rmdOtherMethods, out uint pmdProp); void DefineParam([In] uint md, [In] uint ulParamSeq, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] uint dwParamFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, out uint ppd); void SetFieldProps([In] uint fd, [In] uint dwFieldFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue); void SetPropertyProps([In] uint pr, [In] uint dwPropFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [In] uint mdSetter, [In] uint mdGetter, [In] uint[] rmdOtherMethods); void SetParamProps([In] uint pd, [In][MarshalAs(UnmanagedType.LPWStr)] string szName, [In] uint dwParamFlags, [In] uint dwCPlusTypeFlag, [Out] IntPtr pValue, [In] uint cchValue); void DefineSecurityAttributeSet([In] uint tkObj, [In] IntPtr rSecAttrs, [In] uint cSecAttrs, out uint pulErrorAttr); void ApplyEditAndContinue([In][MarshalAs(UnmanagedType.IUnknown)] object pImport); void TranslateSigWithScope([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport import, [In] IntPtr pbSigBlob, [In] uint cbSigBlob, [In] IntPtr pAssemEmit, [In] IMetaDataEmit emit, [Out] IntPtr pvTranslatedSig, uint cbTranslatedSigMax, out uint pcbTranslatedSig); void SetMethodImplFlags([In] uint md, uint dwImplFlags); void SetFieldRVA([In] uint fd, [In] uint ulRVA); void Merge([In] IMetaDataImport pImport, [In] IntPtr pHostMapToken, [In][MarshalAs(UnmanagedType.IUnknown)] object pHandler); void MergeEnd(); } [ComImport] [ComVisible(true)] [Guid("ED14AA72-78E2-4884-84E2-334293AE5214")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter { void DefineDocument([In][MarshalAs(UnmanagedType.LPWStr)] string url, [In] ref Guid language, [In] ref Guid languageVendor, [In] ref Guid documentType, out ISymUnmanagedDocumentWriter pRetVal); void SetUserEntryPoint([In] uint entryMethod); void OpenMethod([In] uint method); void CloseMethod(); void OpenScope([In] uint startOffset, out uint pRetVal); void CloseScope([In] uint endOffset); void SetScopeRange([In] uint scopeID, [In] uint startOffset, [In] uint endOffset); void DefineLocalVariable([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineParameter([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sequence, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineField([In] uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineGlobalVariable([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void Close(); void SetSymAttribute([In] uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cData, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] data); void OpenNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string name); void CloseNamespace(); void UsingNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string fullName); void SetMethodSourceRange([In] ISymUnmanagedDocumentWriter startDoc, [In] uint startLine, [In] uint startColumn, [In] ISymUnmanagedDocumentWriter endDoc, [In] uint endLine, [In] uint endColumn); void Initialize([In] IntPtr emitter, [In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream, [In] bool fFullBuild); void GetDebugInfo(out IMAGE_DEBUG_DIRECTORY pIDD, [In] uint cData, out uint pcData, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data); void DefineSequencePoints([In] ISymUnmanagedDocumentWriter document, [In] uint spCount, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); void RemapToken([In] uint oldToken, [In] uint newToken); void Initialize2([In][MarshalAs(UnmanagedType.IUnknown)] object emitter, [In][MarshalAs(UnmanagedType.LPWStr)] string tempfilename, [In] IStream pIStream, [In] bool fFullBuild, [In][MarshalAs(UnmanagedType.LPWStr)] string finalfilename); void DefineConstant([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature); void Abort(); } [ComImport] [ComVisible(true)] [Guid("0B97726E-9E6D-4F05-9A26-424022093CAA")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter2 { void DefineDocument([In][MarshalAs(UnmanagedType.LPWStr)] string url, [In] ref Guid language, [In] ref Guid languageVendor, [In] ref Guid documentType, out ISymUnmanagedDocumentWriter pRetVal); void SetUserEntryPoint([In] uint entryMethod); void OpenMethod([In] uint method); void CloseMethod(); void OpenScope([In] uint startOffset, out uint pRetVal); void CloseScope([In] uint endOffset); void SetScopeRange([In] uint scopeID, [In] uint startOffset, [In] uint endOffset); void DefineLocalVariable([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineParameter([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sequence, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineField([In] uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineGlobalVariable([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void Close(); void SetSymAttribute([In] uint parent, [In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cData, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] data); void OpenNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string name); void CloseNamespace(); void UsingNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string fullName); void SetMethodSourceRange([In] ISymUnmanagedDocumentWriter startDoc, [In] uint startLine, [In] uint startColumn, [In] ISymUnmanagedDocumentWriter endDoc, [In] uint endLine, [In] uint endColumn); void Initialize([In][MarshalAs(UnmanagedType.IUnknown)] object emitter, [In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream, [In] bool fFullBuild); void GetDebugInfo(out IMAGE_DEBUG_DIRECTORY pIDD, [In] uint cData, out uint pcData, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data); void DefineSequencePoints([In] ISymUnmanagedDocumentWriter document, [In] uint spCount, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); void RemapToken([In] uint oldToken, [In] uint newToken); void Initialize2([In][MarshalAs(UnmanagedType.IUnknown)] object emitter, [In][MarshalAs(UnmanagedType.LPWStr)] string tempfilename, [In] IStream pIStream, [In] bool fFullBuild, [In][MarshalAs(UnmanagedType.LPWStr)] string finalfilename); void DefineConstant([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint cSig, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature); void Abort(); void DefineLocalVariable2([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sigToken, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineGlobalVariable2([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sigToken, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineConstant2([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint sigToken); } [ComImport] [ComVisible(true)] [Guid("12F1E02C-1E05-4B0E-9468-EBC9D1BB040F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter3 : ISymUnmanagedWriter2 { void _VtblGap1_27(); void OpenMethod2(uint method, uint isect, uint offset); void Commit(); } [ComImport] [ComVisible(true)] [Guid("BC7E3F53-F458-4C23-9DBD-A189E6E96594")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter4 : ISymUnmanagedWriter3, ISymUnmanagedWriter2 { void _VtblGap1_29(); void GetDebugInfoWithPadding([In][Out] ref IMAGE_DEBUG_DIRECTORY pIDD, uint cData, out uint pcData, IntPtr data); } [ComImport] [ComVisible(true)] [Guid("DCF7780D-BDE9-45DF-ACFE-21731A32000C")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter5 : ISymUnmanagedWriter4, ISymUnmanagedWriter3, ISymUnmanagedWriter2 { void _VtblGap1_30(); void OpenMapTokensToSourceSpans(); void CloseMapTokensToSourceSpans(); void MapTokenToSourceSpan(uint token, ISymUnmanagedDocumentWriter document, uint line, uint column, uint endLine, uint endColumn); } [ComImport] [ComVisible(true)] [Guid("CA6C2ED9-103D-46A9-B03B-05446485848B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter6 : ISymUnmanagedWriter5, ISymUnmanagedWriter4, ISymUnmanagedWriter3, ISymUnmanagedWriter2 { void _VtblGap1_33(); void InitializeDeterministic([MarshalAs(UnmanagedType.IUnknown)] object emitter, [MarshalAs(UnmanagedType.IUnknown)] object stream); } [ComImport] [ComVisible(true)] [Guid("22DAEAF2-70F6-4EF1-B0C3-984F0BF27BFD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter7 : ISymUnmanagedWriter6, ISymUnmanagedWriter5, ISymUnmanagedWriter4, ISymUnmanagedWriter3, ISymUnmanagedWriter2 { void _VtblGap1_34(); void UpdateSignatureByHashingContent(IntPtr buffer, uint cData); } [ComImport] [ComVisible(true)] [Guid("5BA52F3B-6BF8-40FC-B476-D39C529B331E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter8 : ISymUnmanagedWriter7, ISymUnmanagedWriter6, ISymUnmanagedWriter5, ISymUnmanagedWriter4, ISymUnmanagedWriter3, ISymUnmanagedWriter2 { void _VtblGap1_35(); void UpdateSignature(Guid pdbId, uint stamp, uint age); void SetSourceServerData(IntPtr data, uint cData); void SetSourceLinkData(IntPtr data, uint cData); } [ComImport] [ComVisible(true)] [Guid("98ECEE1E-752D-11d3-8D56-00C04F680B2B")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IPdbWriter { void _VtblGap1_4(); void GetSignatureAge(out uint sig, out uint age); } [ComImport] [ComVisible(true)] [Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedDocumentWriter { void SetSource([In] uint sourceSize, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] source); void SetCheckSum([In] Guid algorithmId, [In] uint checkSumSize, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] checkSum); } [ComImport] [ComVisible(true)] [Guid("FC073774-1739-4232-BD56-A027294BEC15")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedAsyncMethodPropertiesWriter { void DefineKickoffMethod([In] uint kickoffMethod); void DefineCatchHandlerILOffset([In] uint catchHandlerOffset); void DefineAsyncStepInfo([In] uint count, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] yieldOffsets, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointOffset, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointMethod); } internal sealed class DataReaderIStream : IStream, IDisposable { private enum STREAM_SEEK { SET, CUR, END } private enum STATFLAG { DEFAULT, NONAME, NOOPEN } private enum STGTY { STORAGE = 1, STREAM, LOCKBYTES, PROPERTY } private readonly DataReaderFactory dataReaderFactory; private DataReader reader; private readonly string name; private const int STG_E_INVALIDFUNCTION = -2147287039; private const int STG_E_CANTSAVE = -2147286781; public DataReaderIStream(DataReaderFactory dataReaderFactory) : this(dataReaderFactory, dataReaderFactory.CreateReader(), string.Empty) { } private DataReaderIStream(DataReaderFactory dataReaderFactory, DataReader reader, string name) { this.dataReaderFactory = dataReaderFactory ?? throw new ArgumentNullException("dataReaderFactory"); this.reader = reader; this.name = name ?? string.Empty; } public void Clone(out IStream ppstm) { ppstm = new DataReaderIStream(dataReaderFactory, reader, name); } public void Commit(int grfCommitFlags) { } public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { if (cb > int.MaxValue) { cb = 2147483647L; } else if (cb < 0) { cb = 0L; } int num = (int)cb; if ((ulong)((long)reader.Position + (long)(uint)num) > (ulong)reader.Length) { num = (int)(reader.Length - Math.Min(reader.Position, reader.Length)); } byte[] array = new byte[num]; Read(array, num, pcbRead); if (pcbRead != IntPtr.Zero) { Marshal.WriteInt64(pcbRead, Marshal.ReadInt32(pcbRead)); } pstm.Write(array, array.Length, pcbWritten); if (pcbWritten != IntPtr.Zero) { Marshal.WriteInt64(pcbWritten, Marshal.ReadInt32(pcbWritten)); } } public void LockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(-2147287039); } public void Read(byte[] pv, int cb, IntPtr pcbRead) { if (cb < 0) { cb = 0; } cb = (int)Math.Min(reader.BytesLeft, (uint)cb); reader.ReadBytes(pv, 0, cb); if (pcbRead != IntPtr.Zero) { Marshal.WriteInt32(pcbRead, cb); } } public void Revert() { } public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { switch ((STREAM_SEEK)dwOrigin) { case STREAM_SEEK.SET: reader.Position = (uint)dlibMove; break; case STREAM_SEEK.CUR: reader.Position = (uint)(reader.Position + dlibMove); break; case STREAM_SEEK.END: reader.Position = (uint)(reader.Length + dlibMove); break; } if (plibNewPosition != IntPtr.Zero) { Marshal.WriteInt64(plibNewPosition, reader.Position); } } public void SetSize(long libNewSize) { Marshal.ThrowExceptionForHR(-2147287039); } public void Stat(out STATSTG pstatstg, int grfStatFlag) { STATSTG sTATSTG = new STATSTG { cbSize = reader.Length, clsid = Guid.Empty, grfLocksSupported = 0, grfMode = 0, grfStateBits = 0 }; if ((grfStatFlag & 1) == 0) { sTATSTG.pwcsName = name; } sTATSTG.reserved = 0; sTATSTG.type = 2; pstatstg = sTATSTG; } public void UnlockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(-2147287039); } public void Write(byte[] pv, int cb, IntPtr pcbWritten) { Marshal.ThrowExceptionForHR(-2147286781); } public void Dispose() { } } internal sealed class MDEmitter : MetaDataImport, IMetaDataEmit { private readonly dnlib.DotNet.Writer.Metadata metadata; private readonly Dictionary tokenToTypeDef; private readonly Dictionary tokenToMethodDef; public MDEmitter(dnlib.DotNet.Writer.Metadata metadata) { this.metadata = metadata; tokenToTypeDef = new Dictionary(metadata.TablesHeap.TypeDefTable.Rows); tokenToMethodDef = new Dictionary(metadata.TablesHeap.MethodTable.Rows); foreach (TypeDef type in metadata.Module.GetTypes()) { if (type == null) { continue; } tokenToTypeDef.Add(new MDToken(Table.TypeDef, metadata.GetRid(type)).Raw, type); foreach (MethodDef method in type.Methods) { if (method != null) { tokenToMethodDef.Add(new MDToken(Table.Method, metadata.GetRid(method)).Raw, method); } } } } public unsafe override void GetMethodProps(uint mb, uint* pClass, ushort* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr* ppvSigBlob, uint* pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags) { if (mb >> 24 != 6) { throw new ArgumentException(); } MethodDef methodDef = tokenToMethodDef[mb]; RawMethodRow rawMethodRow = metadata.TablesHeap.MethodTable[mb & 0xFFFFFF]; if (pClass != null) { *pClass = new MDToken(Table.TypeDef, metadata.GetRid(methodDef.DeclaringType)).Raw; } if (pdwAttr != null) { *pdwAttr = rawMethodRow.Flags; } if (ppvSigBlob != null) { *ppvSigBlob = IntPtr.Zero; } if (pcbSigBlob != null) { *pcbSigBlob = 0u; } if (pulCodeRVA != null) { *pulCodeRVA = rawMethodRow.RVA; } if (pdwImplFlags != null) { *pdwImplFlags = rawMethodRow.ImplFlags; } string text = methodDef.Name.String ?? string.Empty; int num = (int)Math.Min((uint)(text.Length + 1), cchMethod); if (szMethod != null) { int num2 = 0; while (num2 < num - 1) { *szMethod = text[num2]; num2++; szMethod++; } if (num > 0) { *szMethod = 0; } } if (pchMethod != null) { *pchMethod = (uint)num; } } public unsafe override void GetTypeDefProps(uint td, ushort* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends) { if (td >> 24 != 2) { throw new ArgumentException(); } TypeDef typeDef = tokenToTypeDef[td]; RawTypeDefRow rawTypeDefRow = metadata.TablesHeap.TypeDefTable[td & 0xFFFFFF]; if (pdwTypeDefFlags != null) { *pdwTypeDefFlags = rawTypeDefRow.Flags; } if (ptkExtends != null) { *ptkExtends = rawTypeDefRow.Extends; } CopyTypeName(typeDef.Namespace, typeDef.Name, szTypeDef, cchTypeDef, pchTypeDef); } public unsafe override void GetNestedClassProps(uint tdNestedClass, uint* ptdEnclosingClass) { if (tdNestedClass >> 24 != 2) { throw new ArgumentException(); } TypeDef declaringType = tokenToTypeDef[tdNestedClass].DeclaringType; if (ptdEnclosingClass != null) { if (declaringType == null) { *ptdEnclosingClass = 0u; } else { *ptdEnclosingClass = new MDToken(Table.TypeDef, metadata.GetRid(declaringType)).Raw; } } } void IMetaDataEmit.GetTokenFromSig(IntPtr pvSig, uint cbSig, out uint pmsig) { pmsig = 285212672u; } void IMetaDataEmit.SetModuleProps(string szName) { throw new NotImplementedException(); } void IMetaDataEmit.Save(string szFile, uint dwSaveFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SaveToStream(IStream pIStream, uint dwSaveFlags) { throw new NotImplementedException(); } void IMetaDataEmit.GetSaveSize(int fSave, out uint pdwSaveSize) { throw new NotImplementedException(); } void IMetaDataEmit.DefineTypeDef(string szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements, out uint ptd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineNestedType(string szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements, uint tdEncloser, out uint ptd) { throw new NotImplementedException(); } void IMetaDataEmit.SetHandler(object pUnk) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMethod(uint td, string szName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags, out uint pmd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMethodImpl(uint td, uint tkBody, uint tkDecl) { throw new NotImplementedException(); } void IMetaDataEmit.DefineTypeRefByName(uint tkResolutionScope, string szName, out uint ptr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineImportType(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint tdImport, IntPtr pAssemEmit, out uint ptr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMemberRef(uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineImportMember(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent, out uint pmr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint[] rmdOtherMethods, out uint pmdEvent) { throw new NotImplementedException(); } void IMetaDataEmit.SetClassLayout(uint td, uint dwPackSize, IntPtr rFieldOffsets, uint ulClassSize) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteClassLayout(uint td) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldMarshal(uint tk, IntPtr pvNativeType, uint cbNativeType) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteFieldMarshal(uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.DefinePermissionSet(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission, out uint ppm) { throw new NotImplementedException(); } void IMetaDataEmit.SetRVA(uint md, uint ulRVA) { throw new NotImplementedException(); } void IMetaDataEmit.DefineModuleRef(string szName, out uint pmur) { throw new NotImplementedException(); } void IMetaDataEmit.SetParent(uint mr, uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.GetTokenFromTypeSpec(IntPtr pvSig, uint cbSig, out uint ptypespec) { throw new NotImplementedException(); } void IMetaDataEmit.SaveToMemory(out IntPtr pbData, uint cbData) { throw new NotImplementedException(); } void IMetaDataEmit.DefineUserString(string szString, uint cchString, out uint pstk) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteToken(uint tkObj) { throw new NotImplementedException(); } void IMetaDataEmit.SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements) { throw new NotImplementedException(); } void IMetaDataEmit.SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint[] rmdOtherMethods) { throw new NotImplementedException(); } void IMetaDataEmit.SetPermissionSetProps(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission, out uint ppm) { throw new NotImplementedException(); } void IMetaDataEmit.DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } void IMetaDataEmit.SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } void IMetaDataEmit.DeletePinvokeMap(uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.DefineCustomAttribute(uint tkOwner, uint tkCtor, IntPtr pCustomAttribute, uint cbCustomAttribute, out uint pcv) { throw new NotImplementedException(); } void IMetaDataEmit.SetCustomAttributeValue(uint pcv, IntPtr pCustomAttribute, uint cbCustomAttribute) { throw new NotImplementedException(); } void IMetaDataEmit.DefineField(uint td, string szName, uint dwFieldFlags, IntPtr pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, out uint pmd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineProperty(uint td, string szProperty, uint dwPropFlags, IntPtr pvSig, uint cbSig, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, uint[] rmdOtherMethods, out uint pmdProp) { throw new NotImplementedException(); } void IMetaDataEmit.DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, out uint ppd) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } void IMetaDataEmit.SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, uint[] rmdOtherMethods) { throw new NotImplementedException(); } void IMetaDataEmit.SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } void IMetaDataEmit.DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs, out uint pulErrorAttr) { throw new NotImplementedException(); } void IMetaDataEmit.ApplyEditAndContinue(object pImport) { throw new NotImplementedException(); } void IMetaDataEmit.TranslateSigWithScope(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport import, IntPtr pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr pvTranslatedSig, uint cbTranslatedSigMax, out uint pcbTranslatedSig) { throw new NotImplementedException(); } void IMetaDataEmit.SetMethodImplFlags(uint md, uint dwImplFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldRVA(uint fd, uint ulRVA) { throw new NotImplementedException(); } void IMetaDataEmit.Merge(IMetaDataImport pImport, IntPtr pHostMapToken, object pHandler) { throw new NotImplementedException(); } void IMetaDataEmit.MergeEnd() { throw new NotImplementedException(); } } internal abstract class MetaDataImport : IMetaDataImport { public unsafe virtual void GetTypeDefProps([In] uint td, [In] ushort* szTypeDef, [In] uint cchTypeDef, [Out] uint* pchTypeDef, [Out] uint* pdwTypeDefFlags, [Out] uint* ptkExtends) { throw new NotImplementedException(); } public unsafe virtual void GetMethodProps(uint mb, uint* pClass, [In] ushort* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, [Out] IntPtr* ppvSigBlob, [Out] uint* pcbSigBlob, [Out] uint* pulCodeRVA, [Out] uint* pdwImplFlags) { throw new NotImplementedException(); } public unsafe virtual void GetNestedClassProps([In] uint tdNestedClass, [Out] uint* ptdEnclosingClass) { throw new NotImplementedException(); } public unsafe virtual void GetSigFromToken(uint mdSig, byte** ppvSig, uint* pcbSig) { throw new NotImplementedException(); } public unsafe virtual void GetTypeRefProps(uint tr, uint* ptkResolutionScope, ushort* szName, uint cchName, uint* pchName) { throw new NotImplementedException(); } protected unsafe void CopyTypeName(string typeNamespace, string typeName, ushort* destBuffer, uint destBufferLen, uint* requiredLength) { if (typeName == null) { typeName = string.Empty; } if (typeNamespace == null) { typeNamespace = string.Empty; } if (destBuffer != null && destBufferLen != 0) { uint num = destBufferLen - 1; uint num2 = 0u; if (typeNamespace.Length > 0) { int num3 = 0; while (num3 < typeNamespace.Length && num2 < num) { *(destBuffer++) = typeNamespace[num3]; num3++; num2++; } if (num2 < num) { *(destBuffer++) = 46; num2++; } } int num4 = 0; while (num4 < typeName.Length && num2 < num) { *(destBuffer++) = typeName[num4]; num4++; num2++; } *destBuffer = 0; } if (requiredLength != null) { int num5 = ((typeNamespace.Length == 0) ? typeName.Length : (typeNamespace.Length + 1 + typeName.Length)); int num6 = Math.Min(num5, (int)Math.Min(2147483647u, (destBufferLen != 0) ? (destBufferLen - 1) : 0u)); if (destBuffer != null) { *requiredLength = (uint)num6; } else { *requiredLength = (uint)num5; } } } void IMetaDataImport.CloseEnum(IntPtr hEnum) { throw new NotImplementedException(); } void IMetaDataImport.CountEnum(IntPtr hEnum, ref uint pulCount) { throw new NotImplementedException(); } void IMetaDataImport.ResetEnum(IntPtr hEnum, uint ulPos) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeDefs(IntPtr phEnum, uint[] rTypeDefs, uint cMax, out uint pcTypeDefs) { throw new NotImplementedException(); } void IMetaDataImport.EnumInterfaceImpls(ref IntPtr phEnum, uint td, uint[] rImpls, uint cMax, ref uint pcImpls) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeRefs(ref IntPtr phEnum, uint[] rTypeRefs, uint cMax, ref uint pcTypeRefs) { throw new NotImplementedException(); } void IMetaDataImport.FindTypeDefByName(string szTypeDef, uint tkEnclosingClass, out uint ptd) { throw new NotImplementedException(); } void IMetaDataImport.GetScopeProps(IntPtr szName, uint cchName, out uint pchName, out Guid pmvid) { throw new NotImplementedException(); } void IMetaDataImport.GetModuleFromScope(out uint pmd) { throw new NotImplementedException(); } void IMetaDataImport.GetInterfaceImplProps(uint iiImpl, out uint pClass, out uint ptkIface) { throw new NotImplementedException(); } void IMetaDataImport.ResolveTypeRef(uint tr, ref Guid riid, out object ppIScope, out uint ptd) { throw new NotImplementedException(); } void IMetaDataImport.EnumMembers(ref IntPtr phEnum, uint cl, uint[] rMembers, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMembersWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rMembers, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethods(ref IntPtr phEnum, uint cl, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodsWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumFields(ref IntPtr phEnum, uint cl, uint[] rFields, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumFieldsWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rFields, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumParams(ref IntPtr phEnum, uint mb, uint[] rParams, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMemberRefs(ref IntPtr phEnum, uint tkParent, uint[] rMemberRefs, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodImpls(ref IntPtr phEnum, uint td, uint[] rMethodBody, uint[] rMethodDecl, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumPermissionSets(ref IntPtr phEnum, uint tk, uint dwActions, uint[] rPermission, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.FindMember(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindMethod(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindField(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindMemberRef(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmr) { throw new NotImplementedException(); } void IMetaDataImport.GetMemberRefProps(uint mr, out uint ptk, IntPtr szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob, out uint pbSig) { throw new NotImplementedException(); } void IMetaDataImport.EnumProperties(ref IntPtr phEnum, uint td, uint[] rProperties, uint cMax, out uint pcProperties) { throw new NotImplementedException(); } void IMetaDataImport.EnumEvents(ref IntPtr phEnum, uint td, uint[] rEvents, uint cMax, out uint pcEvents) { throw new NotImplementedException(); } void IMetaDataImport.GetEventProps(uint ev, out uint pClass, string szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, uint[] rmdOtherMethod, uint cMax, out uint pcOtherMethod) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodSemantics(ref IntPtr phEnum, uint mb, uint[] rEventProp, uint cMax, out uint pcEventProp) { throw new NotImplementedException(); } void IMetaDataImport.GetMethodSemantics(uint mb, uint tkEventProp, out uint pdwSemanticsFlags) { throw new NotImplementedException(); } void IMetaDataImport.GetClassLayout(uint td, out uint pdwPackSize, out IntPtr rFieldOffset, uint cMax, out uint pcFieldOffset, out uint pulClassSize) { throw new NotImplementedException(); } void IMetaDataImport.GetFieldMarshal(uint tk, out IntPtr ppvNativeType, out uint pcbNativeType) { throw new NotImplementedException(); } void IMetaDataImport.GetRVA(uint tk, out uint pulCodeRVA, out uint pdwImplFlags) { throw new NotImplementedException(); } void IMetaDataImport.GetPermissionSetProps(uint pm, out uint pdwAction, out IntPtr ppvPermission, out uint pcbPermission) { throw new NotImplementedException(); } void IMetaDataImport.GetModuleRefProps(uint mur, IntPtr szName, uint cchName, out uint pchName) { throw new NotImplementedException(); } void IMetaDataImport.EnumModuleRefs(ref IntPtr phEnum, uint[] rModuleRefs, uint cmax, out uint pcModuleRefs) { throw new NotImplementedException(); } void IMetaDataImport.GetTypeSpecFromToken(uint typespec, out IntPtr ppvSig, out uint pcbSig) { throw new NotImplementedException(); } void IMetaDataImport.GetNameFromToken(uint tk, out IntPtr pszUtf8NamePtr) { throw new NotImplementedException(); } void IMetaDataImport.EnumUnresolvedMethods(ref IntPtr phEnum, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.GetUserString(uint stk, IntPtr szString, uint cchString, out uint pchString) { throw new NotImplementedException(); } void IMetaDataImport.GetPinvokeMap(uint tk, out uint pdwMappingFlags, IntPtr szImportName, uint cchImportName, out uint pchImportName, out uint pmrImportDLL) { throw new NotImplementedException(); } void IMetaDataImport.EnumSignatures(ref IntPtr phEnum, uint[] rSignatures, uint cmax, out uint pcSignatures) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeSpecs(ref IntPtr phEnum, uint[] rTypeSpecs, uint cmax, out uint pcTypeSpecs) { throw new NotImplementedException(); } void IMetaDataImport.EnumUserStrings(ref IntPtr phEnum, uint[] rStrings, uint cmax, out uint pcStrings) { throw new NotImplementedException(); } void IMetaDataImport.GetParamForMethodIndex(uint md, uint ulParamSeq, out uint ppd) { throw new NotImplementedException(); } void IMetaDataImport.EnumCustomAttributes(IntPtr phEnum, uint tk, uint tkType, uint[] rCustomAttributes, uint cMax, out uint pcCustomAttributes) { throw new NotImplementedException(); } void IMetaDataImport.GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob, out uint pcbSize) { throw new NotImplementedException(); } void IMetaDataImport.FindTypeRef(uint tkResolutionScope, string szName, out uint ptr) { throw new NotImplementedException(); } void IMetaDataImport.GetMemberProps(uint mb, out uint pClass, IntPtr szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetFieldProps(uint mb, out uint pClass, IntPtr szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetPropertyProps(uint prop, out uint pClass, IntPtr szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, uint[] rmdOtherMethod, uint cMax, out uint pcOtherMethod) { throw new NotImplementedException(); } void IMetaDataImport.GetParamProps(uint tk, out uint pmd, out uint pulSequence, IntPtr szName, uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetCustomAttributeByName(uint tkObj, string szName, out IntPtr ppData, out uint pcbData) { throw new NotImplementedException(); } bool IMetaDataImport.IsValidToken(uint tk) { throw new NotImplementedException(); } void IMetaDataImport.GetNativeCallConvFromSig(IntPtr pvSig, uint cbSig, out uint pCallConv) { throw new NotImplementedException(); } void IMetaDataImport.IsGlobal(uint pd, out int pbGlobal) { throw new NotImplementedException(); } } internal sealed class ReaderMetaDataImport : MetaDataImport, IDisposable { private dnlib.DotNet.MD.Metadata metadata; private unsafe byte* blobPtr; private IntPtr addrToFree; public unsafe ReaderMetaDataImport(dnlib.DotNet.MD.Metadata metadata) { this.metadata = metadata ?? throw new ArgumentNullException("metadata"); DataReader dataReader = metadata.BlobStream.CreateReader(); addrToFree = Marshal.AllocHGlobal((int)dataReader.BytesLeft); blobPtr = (byte*)(void*)addrToFree; if (blobPtr == null) { throw new OutOfMemoryException(); } dataReader.ReadBytes(blobPtr, (int)dataReader.BytesLeft); } ~ReaderMetaDataImport() { Dispose(disposing: false); } public unsafe override void GetTypeRefProps(uint tr, uint* ptkResolutionScope, ushort* szName, uint cchName, uint* pchName) { MDToken mDToken = new MDToken(tr); if (mDToken.Table != Table.TypeRef) { throw new ArgumentException(); } if (!metadata.TablesStream.TryReadTypeRefRow(mDToken.Rid, out var row)) { throw new ArgumentException(); } if (ptkResolutionScope != null) { *ptkResolutionScope = row.ResolutionScope; } if (szName != null || pchName != null) { UTF8String uTF8String = metadata.StringsStream.ReadNoNull(row.Namespace); UTF8String uTF8String2 = metadata.StringsStream.ReadNoNull(row.Name); CopyTypeName(uTF8String, uTF8String2, szName, cchName, pchName); } } public unsafe override void GetTypeDefProps(uint td, ushort* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends) { MDToken mDToken = new MDToken(td); if (mDToken.Table != Table.TypeDef) { throw new ArgumentException(); } if (!metadata.TablesStream.TryReadTypeDefRow(mDToken.Rid, out var row)) { throw new ArgumentException(); } if (pdwTypeDefFlags != null) { *pdwTypeDefFlags = row.Flags; } if (ptkExtends != null) { *ptkExtends = row.Extends; } if (szTypeDef != null || pchTypeDef != null) { UTF8String uTF8String = metadata.StringsStream.ReadNoNull(row.Namespace); UTF8String uTF8String2 = metadata.StringsStream.ReadNoNull(row.Name); CopyTypeName(uTF8String, uTF8String2, szTypeDef, cchTypeDef, pchTypeDef); } } public unsafe override void GetSigFromToken(uint mdSig, byte** ppvSig, uint* pcbSig) { MDToken mDToken = new MDToken(mdSig); if (mDToken.Table != Table.StandAloneSig) { throw new ArgumentException(); } if (!metadata.TablesStream.TryReadStandAloneSigRow(mDToken.Rid, out var row)) { throw new ArgumentException(); } if (!metadata.BlobStream.TryCreateReader(row.Signature, out var reader)) { throw new ArgumentException(); } if (ppvSig != null) { *ppvSig = blobPtr + (uint)(reader.StartOffset - metadata.BlobStream.StartOffset); } if (pcbSig != null) { *pcbSig = reader.Length; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } private unsafe void Dispose(bool disposing) { metadata = null; IntPtr intPtr = Interlocked.Exchange(ref addrToFree, IntPtr.Zero); blobPtr = null; if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } } internal sealed class StreamIStream : IStream { private enum STREAM_SEEK { SET, CUR, END } private enum STATFLAG { DEFAULT, NONAME, NOOPEN } private enum STGTY { STORAGE = 1, STREAM, LOCKBYTES, PROPERTY } private readonly Stream stream; private readonly string name; private const int STG_E_INVALIDFUNCTION = -2147287039; public StreamIStream(Stream stream) : this(stream, string.Empty) { } public StreamIStream(Stream stream, string name) { this.stream = stream ?? throw new ArgumentNullException("stream"); this.name = name ?? string.Empty; } public void Clone(out IStream ppstm) { Marshal.ThrowExceptionForHR(-2147287039); throw new Exception(); } public void Commit(int grfCommitFlags) { stream.Flush(); } public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { if (cb > int.MaxValue) { cb = 2147483647L; } else if (cb < 0) { cb = 0L; } int num = (int)cb; if (stream.Position + num < num || stream.Position + num > stream.Length) { num = (int)(stream.Length - Math.Min(stream.Position, stream.Length)); } byte[] array = new byte[num]; Read(array, num, pcbRead); if (pcbRead != IntPtr.Zero) { Marshal.WriteInt64(pcbRead, Marshal.ReadInt32(pcbRead)); } pstm.Write(array, array.Length, pcbWritten); if (pcbWritten != IntPtr.Zero) { Marshal.WriteInt64(pcbWritten, Marshal.ReadInt32(pcbWritten)); } } public void LockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(-2147287039); } public void Read(byte[] pv, int cb, IntPtr pcbRead) { if (cb < 0) { cb = 0; } cb = stream.Read(pv, 0, cb); if (pcbRead != IntPtr.Zero) { Marshal.WriteInt32(pcbRead, cb); } } public void Revert() { } public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { switch ((STREAM_SEEK)dwOrigin) { case STREAM_SEEK.SET: stream.Position = dlibMove; break; case STREAM_SEEK.CUR: stream.Position += dlibMove; break; case STREAM_SEEK.END: stream.Position = stream.Length + dlibMove; break; } if (plibNewPosition != IntPtr.Zero) { Marshal.WriteInt64(plibNewPosition, stream.Position); } } public void SetSize(long libNewSize) { stream.SetLength(libNewSize); } public void Stat(out STATSTG pstatstg, int grfStatFlag) { STATSTG sTATSTG = new STATSTG { cbSize = stream.Length, clsid = Guid.Empty, grfLocksSupported = 0, grfMode = 2, grfStateBits = 0 }; if ((grfStatFlag & 1) == 0) { sTATSTG.pwcsName = name; } sTATSTG.reserved = 0; sTATSTG.type = 2; pstatstg = sTATSTG; } public void UnlockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(-2147287039); } public void Write(byte[] pv, int cb, IntPtr pcbWritten) { stream.Write(pv, 0, cb); if (pcbWritten != IntPtr.Zero) { Marshal.WriteInt32(pcbWritten, cb); } } } internal sealed class SymbolDocumentImpl : SymbolDocument { private readonly ISymUnmanagedDocument document; private PdbCustomDebugInfo[] customDebugInfos; public ISymUnmanagedDocument SymUnmanagedDocument => document; public override Guid CheckSumAlgorithmId { get { document.GetCheckSumAlgorithmId(out var pRetVal); return pRetVal; } } public override Guid DocumentType { get { document.GetDocumentType(out var pRetVal); return pRetVal; } } public override Guid Language { get { document.GetLanguage(out var pRetVal); return pRetVal; } } public override Guid LanguageVendor { get { document.GetLanguageVendor(out var pRetVal); return pRetVal; } } public override string URL { get { document.GetURL(0u, out var pcchUrl, null); char[] array = new char[pcchUrl]; document.GetURL((uint)array.Length, out pcchUrl, array); if (array.Length == 0) { return string.Empty; } return new string(array, 0, array.Length - 1); } } public override byte[] CheckSum { get { document.GetCheckSum(0u, out var pcData, null); byte[] array = new byte[pcData]; document.GetCheckSum((uint)array.Length, out pcData, array); return array; } } private byte[] SourceCode { get { if (document.GetSourceLength(out var pRetVal) < 0) { return null; } if (pRetVal <= 0) { return null; } byte[] array = new byte[pRetVal]; if (document.GetSourceRange(0u, 0u, 2147483647u, 2147483647u, pRetVal, out var pcSourceBytes, array) < 0) { return null; } if (pcSourceBytes <= 0) { return null; } if (pcSourceBytes != array.Length) { Array.Resize(ref array, pcSourceBytes); } return array; } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { if (customDebugInfos == null) { byte[] sourceCode = SourceCode; if (sourceCode != null) { customDebugInfos = new PdbCustomDebugInfo[1] { new PdbEmbeddedSourceCustomDebugInfo(sourceCode) }; } else { customDebugInfos = Array2.Empty(); } } return customDebugInfos; } } public override MDToken? MDToken => null; public SymbolDocumentImpl(ISymUnmanagedDocument document) { this.document = document; } } internal sealed class SymbolDocumentWriter : ISymbolDocumentWriter { private readonly ISymUnmanagedDocumentWriter writer; public ISymUnmanagedDocumentWriter SymUnmanagedDocumentWriter => writer; public SymbolDocumentWriter(ISymUnmanagedDocumentWriter writer) { this.writer = writer; } public void SetCheckSum(Guid algorithmId, byte[] checkSum) { if (checkSum != null && checkSum.Length != 0 && algorithmId != Guid.Empty) { writer.SetCheckSum(algorithmId, (uint)checkSum.Length, checkSum); } } public void SetSource(byte[] source) { writer.SetSource((uint)source.Length, source); } } internal sealed class SymbolMethodImpl : SymbolMethod { private readonly SymbolReaderImpl reader; private readonly ISymUnmanagedMethod method; private readonly ISymUnmanagedAsyncMethod asyncMethod; private volatile SymbolScope rootScope; private volatile SymbolSequencePoint[] sequencePoints; private volatile SymbolAsyncStepInfo[] asyncStepInfos; public override int Token { get { method.GetToken(out var pToken); return (int)pToken; } } public override SymbolScope RootScope { get { if (rootScope == null) { method.GetRootScope(out var pRetVal); Interlocked.CompareExchange(ref rootScope, (pRetVal == null) ? null : new SymbolScopeImpl(pRetVal, this, null), null); } return rootScope; } } public override IList SequencePoints { get { if (sequencePoints == null) { method.GetSequencePointCount(out var pRetVal); SymbolSequencePoint[] array = new SymbolSequencePoint[pRetVal]; int[] array2 = new int[array.Length]; _ = new ISymbolDocument[array.Length]; int[] array3 = new int[array.Length]; int[] array4 = new int[array.Length]; int[] array5 = new int[array.Length]; int[] array6 = new int[array.Length]; ISymUnmanagedDocument[] array7 = new ISymUnmanagedDocument[array.Length]; if (array.Length != 0) { method.GetSequencePoints((uint)array.Length, out var _, array2, array7, array3, array4, array5, array6); } for (int i = 0; i < array.Length; i++) { array[i] = new SymbolSequencePoint { Offset = array2[i], Document = new SymbolDocumentImpl(array7[i]), Line = array3[i], Column = array4[i], EndLine = array5[i], EndColumn = array6[i] }; } sequencePoints = array; } return sequencePoints; } } public int AsyncKickoffMethod { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) { return 0; } return (int)asyncMethod.GetKickoffMethod(); } } public uint? AsyncCatchHandlerILOffset { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) { return null; } if (!asyncMethod.HasCatchHandlerILOffset()) { return null; } return asyncMethod.GetCatchHandlerILOffset(); } } public IList AsyncStepInfos { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) { return null; } if (asyncStepInfos == null) { uint pcStepInfo = asyncMethod.GetAsyncStepInfoCount(); uint[] array = new uint[pcStepInfo]; uint[] array2 = new uint[pcStepInfo]; uint[] array3 = new uint[pcStepInfo]; asyncMethod.GetAsyncStepInfo(pcStepInfo, out pcStepInfo, array, array2, array3); SymbolAsyncStepInfo[] array4 = new SymbolAsyncStepInfo[pcStepInfo]; for (int i = 0; i < array4.Length; i++) { array4[i] = new SymbolAsyncStepInfo(array[i], array2[i], array3[i]); } asyncStepInfos = array4; } return asyncStepInfos; } } public SymbolMethodImpl(SymbolReaderImpl reader, ISymUnmanagedMethod method) { this.reader = reader; this.method = method; asyncMethod = method as ISymUnmanagedAsyncMethod; } public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } internal sealed class SymbolNamespaceImpl : SymbolNamespace { private readonly ISymUnmanagedNamespace ns; public override string Name { get { ns.GetName(0u, out var pcchName, null); char[] array = new char[pcchName]; ns.GetName((uint)array.Length, out pcchName, array); if (array.Length == 0) { return string.Empty; } return new string(array, 0, array.Length - 1); } } public SymbolNamespaceImpl(ISymUnmanagedNamespace @namespace) { ns = @namespace; } } internal sealed class SymbolReaderImpl : SymbolReader { private ModuleDef module; private ISymUnmanagedReader reader; private object[] objsToKeepAlive; private const int E_FAIL = -2147467259; private volatile SymbolDocument[] documents; public override PdbFileKind PdbFileKind => PdbFileKind.WindowsPDB; public override int UserEntryPoint { get { uint pToken; int userEntryPoint = reader.GetUserEntryPoint(out pToken); if (userEntryPoint == -2147467259) { return 0; } Marshal.ThrowExceptionForHR(userEntryPoint); return (int)pToken; } } public override IList Documents { get { if (documents == null) { reader.GetDocuments(0u, out var pcDocs, null); ISymUnmanagedDocument[] array = new ISymUnmanagedDocument[pcDocs]; reader.GetDocuments((uint)array.Length, out pcDocs, array); SymbolDocument[] array2 = new SymbolDocument[pcDocs]; for (uint num = 0u; num < pcDocs; num++) { array2[num] = new SymbolDocumentImpl(array[num]); } documents = array2; } return documents; } } public SymbolReaderImpl(ISymUnmanagedReader reader, object[] objsToKeepAlive) { this.reader = reader ?? throw new ArgumentNullException("reader"); this.objsToKeepAlive = objsToKeepAlive ?? throw new ArgumentNullException("objsToKeepAlive"); } ~SymbolReaderImpl() { Dispose(disposing: false); } public override void Initialize(ModuleDef module) { this.module = module; } public override SymbolMethod GetMethod(MethodDef method, int version) { ISymUnmanagedMethod pRetVal; int methodByVersion = reader.GetMethodByVersion(method.MDToken.Raw, version, out pRetVal); if (methodByVersion == -2147467259) { return null; } Marshal.ThrowExceptionForHR(methodByVersion); if (pRetVal != null) { return new SymbolMethodImpl(this, pRetVal); } return null; } internal void GetCustomDebugInfos(SymbolMethodImpl symMethod, MethodDef method, CilBody body, IList result) { PdbAsyncMethodCustomDebugInfo pdbAsyncMethodCustomDebugInfo = PseudoCustomDebugInfoFactory.TryCreateAsyncMethod(method.Module, method, body, symMethod.AsyncKickoffMethod, symMethod.AsyncStepInfos, symMethod.AsyncCatchHandlerILOffset); if (pdbAsyncMethodCustomDebugInfo != null) { result.Add(pdbAsyncMethodCustomDebugInfo); } reader.GetSymAttribute(method.MDToken.Raw, "MD2", 0u, out var pcBuffer, null); if (pcBuffer != 0) { byte[] array = new byte[pcBuffer]; reader.GetSymAttribute(method.MDToken.Raw, "MD2", (uint)array.Length, out pcBuffer, array); PdbCustomDebugInfoReader.Read(method, body, result, array); } } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { if (token == 1) { GetCustomDebugInfos_ModuleDef(result); } } private void GetCustomDebugInfos_ModuleDef(IList result) { byte[] sourceLinkData = GetSourceLinkData(); if (sourceLinkData != null) { result.Add(new PdbSourceLinkCustomDebugInfo(sourceLinkData)); } byte[] sourceServerData = GetSourceServerData(); if (sourceServerData != null) { result.Add(new PdbSourceServerCustomDebugInfo(sourceServerData)); } } private byte[] GetSourceLinkData() { if (reader is ISymUnmanagedReader4 symUnmanagedReader && symUnmanagedReader.GetSourceServerData(out var data, out var pcData) == 0) { if (pcData == 0) { return Array2.Empty(); } byte[] array = new byte[pcData]; Marshal.Copy(data, array, 0, array.Length); return array; } return null; } private byte[] GetSourceServerData() { if (reader is ISymUnmanagedSourceServerModule symUnmanagedSourceServerModule) { IntPtr ppData = IntPtr.Zero; try { if (symUnmanagedSourceServerModule.GetSourceServerData(out var pDataByteCount, out ppData) == 0) { if (pDataByteCount == 0) { return Array2.Empty(); } byte[] array = new byte[pDataByteCount]; Marshal.Copy(ppData, array, 0, array.Length); return array; } } finally { if (ppData != IntPtr.Zero) { Marshal.FreeCoTaskMem(ppData); } } } return null; } public override void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { (reader as ISymUnmanagedDispose)?.Destroy(); object[] array = objsToKeepAlive; if (array != null) { object[] array2 = array; for (int i = 0; i < array2.Length; i++) { (array2[i] as IDisposable)?.Dispose(); } } module = null; reader = null; objsToKeepAlive = null; } public bool MatchesModule(Guid pdbId, uint stamp, uint age) { if (reader is ISymUnmanagedReader4 symUnmanagedReader) { if (symUnmanagedReader.MatchesModule(pdbId, stamp, age, out var result) < 0) { return false; } return result; } return true; } } [SupportedOSPlatform("windows")] internal static class SymbolReaderWriterFactory { private static readonly Guid CLSID_CorSymReader_SxS = new Guid("0A3976C5-4529-4ef8-B0B0-42EED37082CD"); private static Type CorSymReader_Type; private static readonly Guid CLSID_CorSymWriter_SxS = new Guid(182640304u, 63745, 18315, 187, 159, 136, 30, 232, 6, 103, 136); private static Type CorSymWriterType; private static volatile bool canTry_Microsoft_DiaSymReader_Native = true; [DllImport("Microsoft.DiaSymReader.Native.x86.dll", EntryPoint = "CreateSymReader")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymReader_x86(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)] out object symReader); [DllImport("Microsoft.DiaSymReader.Native.amd64.dll", EntryPoint = "CreateSymReader")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymReader_x64(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)] out object symReader); [DllImport("Microsoft.DiaSymReader.Native.arm.dll", EntryPoint = "CreateSymReader")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymReader_arm(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)] out object symReader); [DllImport("Microsoft.DiaSymReader.Native.arm64.dll", EntryPoint = "CreateSymReader")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymReader_arm64(ref Guid id, [MarshalAs(UnmanagedType.IUnknown)] out object symReader); [DllImport("Microsoft.DiaSymReader.Native.x86.dll", EntryPoint = "CreateSymWriter")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymWriter_x86(ref Guid guid, [MarshalAs(UnmanagedType.IUnknown)] out object symWriter); [DllImport("Microsoft.DiaSymReader.Native.amd64.dll", EntryPoint = "CreateSymWriter")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymWriter_x64(ref Guid guid, [MarshalAs(UnmanagedType.IUnknown)] out object symWriter); [DllImport("Microsoft.DiaSymReader.Native.arm.dll", EntryPoint = "CreateSymWriter")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymWriter_arm(ref Guid guid, [MarshalAs(UnmanagedType.IUnknown)] out object symWriter); [DllImport("Microsoft.DiaSymReader.Native.arm64.dll", EntryPoint = "CreateSymWriter")] [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories | DllImportSearchPath.AssemblyDirectory)] private static extern void CreateSymWriter_arm64(ref Guid guid, [MarshalAs(UnmanagedType.IUnknown)] out object symWriter); public static SymbolReader Create(PdbReaderContext pdbContext, dnlib.DotNet.MD.Metadata metadata, DataReaderFactory pdbStream) { ISymUnmanagedReader symUnmanagedReader = null; SymbolReaderImpl symbolReaderImpl = null; ReaderMetaDataImport readerMetaDataImport = null; DataReaderIStream dataReaderIStream = null; bool flag = true; try { if (pdbStream == null) { return null; } ImageDebugDirectory codeViewDebugDirectory = pdbContext.CodeViewDebugDirectory; if (codeViewDebugDirectory == null) { return null; } if (!pdbContext.TryGetCodeViewData(out var guid, out var age)) { return null; } symUnmanagedReader = CreateSymUnmanagedReader(pdbContext.Options); if (symUnmanagedReader == null) { return null; } readerMetaDataImport = new ReaderMetaDataImport(metadata); dataReaderIStream = new DataReaderIStream(pdbStream); if (symUnmanagedReader.Initialize(readerMetaDataImport, null, null, dataReaderIStream) < 0) { return null; } symbolReaderImpl = new SymbolReaderImpl(symUnmanagedReader, new object[3] { pdbStream, readerMetaDataImport, dataReaderIStream }); if (!symbolReaderImpl.MatchesModule(guid, codeViewDebugDirectory.TimeDateStamp, age)) { return null; } flag = false; return symbolReaderImpl; } catch (IOException) { } catch (InvalidCastException) { } catch (COMException) { } finally { if (flag) { pdbStream?.Dispose(); symbolReaderImpl?.Dispose(); readerMetaDataImport?.Dispose(); dataReaderIStream?.Dispose(); (symUnmanagedReader as ISymUnmanagedDispose)?.Destroy(); } } return null; } private static ISymUnmanagedReader CreateSymUnmanagedReader(PdbReaderOptions options) { bool num = (options & PdbReaderOptions.NoDiaSymReader) == 0; bool flag = (options & PdbReaderOptions.NoOldDiaSymReader) == 0; if (num && canTry_Microsoft_DiaSymReader_Native) { try { Guid id = CLSID_CorSymReader_SxS; object symReader; switch (ProcessorArchUtils.GetProcessCpuArchitecture()) { case Machine.AMD64: CreateSymReader_x64(ref id, out symReader); break; case Machine.I386: CreateSymReader_x86(ref id, out symReader); break; case Machine.ARMNT: CreateSymReader_arm(ref id, out symReader); break; case Machine.ARM64: CreateSymReader_arm64(ref id, out symReader); break; default: symReader = null; break; } if (symReader is ISymUnmanagedReader result) { return result; } } catch (DllNotFoundException) { } catch { } canTry_Microsoft_DiaSymReader_Native = false; } if (flag) { return (ISymUnmanagedReader)Activator.CreateInstance(CorSymReader_Type ?? (CorSymReader_Type = Type.GetTypeFromCLSID(CLSID_CorSymReader_SxS))); } return null; } private static ISymUnmanagedWriter2 CreateSymUnmanagedWriter2(PdbWriterOptions options) { bool num = (options & PdbWriterOptions.NoDiaSymReader) == 0; bool flag = (options & PdbWriterOptions.NoOldDiaSymReader) == 0; if (num && canTry_Microsoft_DiaSymReader_Native) { try { Guid guid = CLSID_CorSymWriter_SxS; object symWriter; switch (ProcessorArchUtils.GetProcessCpuArchitecture()) { case Machine.AMD64: CreateSymWriter_x64(ref guid, out symWriter); break; case Machine.I386: CreateSymWriter_x86(ref guid, out symWriter); break; case Machine.ARMNT: CreateSymWriter_arm(ref guid, out symWriter); break; case Machine.ARM64: CreateSymWriter_arm64(ref guid, out symWriter); break; default: symWriter = null; break; } if (symWriter is ISymUnmanagedWriter2 result) { return result; } } catch (DllNotFoundException) { } catch { } canTry_Microsoft_DiaSymReader_Native = false; } if (flag) { return (ISymUnmanagedWriter2)Activator.CreateInstance(CorSymWriterType ?? (CorSymWriterType = Type.GetTypeFromCLSID(CLSID_CorSymWriter_SxS))); } return null; } public static SymbolWriter Create(PdbWriterOptions options, string pdbFileName) { if (File.Exists(pdbFileName)) { File.Delete(pdbFileName); } return new SymbolWriterImpl(CreateSymUnmanagedWriter2(options), pdbFileName, File.Create(pdbFileName), options, ownsStream: true); } public static SymbolWriter Create(PdbWriterOptions options, Stream pdbStream, string pdbFileName) { return new SymbolWriterImpl(CreateSymUnmanagedWriter2(options), pdbFileName, pdbStream, options, ownsStream: false); } } internal sealed class SymbolScopeImpl : SymbolScope { private readonly ISymUnmanagedScope scope; private readonly SymbolMethod method; private readonly SymbolScope parent; private volatile SymbolScope[] children; private volatile SymbolVariable[] locals; private volatile SymbolNamespace[] namespaces; public override SymbolMethod Method => method; public override SymbolScope Parent => parent; public override int StartOffset { get { scope.GetStartOffset(out var pRetVal); return (int)pRetVal; } } public override int EndOffset { get { scope.GetEndOffset(out var pRetVal); return (int)pRetVal; } } public override IList Children { get { if (children == null) { scope.GetChildren(0u, out var pcChildren, null); ISymUnmanagedScope[] array = new ISymUnmanagedScope[pcChildren]; scope.GetChildren((uint)array.Length, out pcChildren, array); SymbolScope[] array2 = new SymbolScope[pcChildren]; for (uint num = 0u; num < pcChildren; num++) { array2[num] = new SymbolScopeImpl(array[num], method, this); } children = array2; } return children; } } public override IList Locals { get { if (locals == null) { scope.GetLocals(0u, out var pcLocals, null); ISymUnmanagedVariable[] array = new ISymUnmanagedVariable[pcLocals]; scope.GetLocals((uint)array.Length, out pcLocals, array); SymbolVariable[] array2 = new SymbolVariable[pcLocals]; for (uint num = 0u; num < pcLocals; num++) { array2[num] = new SymbolVariableImpl(array[num]); } locals = array2; } return locals; } } public override IList Namespaces { get { if (namespaces == null) { scope.GetNamespaces(0u, out var pcNameSpaces, null); ISymUnmanagedNamespace[] array = new ISymUnmanagedNamespace[pcNameSpaces]; scope.GetNamespaces((uint)array.Length, out pcNameSpaces, array); SymbolNamespace[] array2 = new SymbolNamespace[pcNameSpaces]; for (uint num = 0u; num < pcNameSpaces; num++) { array2[num] = new SymbolNamespaceImpl(array[num]); } namespaces = array2; } return namespaces; } } public override IList CustomDebugInfos => Array2.Empty(); public override PdbImportScope ImportScope => null; public SymbolScopeImpl(ISymUnmanagedScope scope, SymbolMethod method, SymbolScope parent) { this.scope = scope; this.method = method; this.parent = parent; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (!(scope is ISymUnmanagedScope2 symUnmanagedScope)) { return Array2.Empty(); } symUnmanagedScope.GetConstants(0u, out var pcConstants, null); if (pcConstants == 0) { return Array2.Empty(); } ISymUnmanagedConstant[] array = new ISymUnmanagedConstant[pcConstants]; symUnmanagedScope.GetConstants((uint)array.Length, out pcConstants, array); PdbConstant[] array2 = new PdbConstant[pcConstants]; for (uint num = 0u; num < pcConstants; num++) { ISymUnmanagedConstant symUnmanagedConstant = array[num]; string name = GetName(symUnmanagedConstant); symUnmanagedConstant.GetValue(out var pValue); byte[] signatureBytes = GetSignatureBytes(symUnmanagedConstant); TypeSig type = ((signatureBytes.Length != 0) ? SignatureReader.ReadTypeSig(module, module.CorLibTypes, signatureBytes, gpContext) : null); array2[num] = new PdbConstant(name, type, pValue); } return array2; } private string GetName(ISymUnmanagedConstant unc) { unc.GetName(0u, out var pcchName, null); char[] array = new char[pcchName]; unc.GetName((uint)array.Length, out pcchName, array); if (array.Length == 0) { return string.Empty; } return new string(array, 0, array.Length - 1); } private byte[] GetSignatureBytes(ISymUnmanagedConstant unc) { uint pcSig; int signature = unc.GetSignature(0u, out pcSig, null); if (pcSig == 0 || (signature < 0 && signature != -2147467259 && signature != -2147467263)) { return Array2.Empty(); } byte[] array = new byte[pcSig]; if (unc.GetSignature((uint)array.Length, out pcSig, array) != 0) { return Array2.Empty(); } return array; } } internal sealed class SymbolVariableImpl : SymbolVariable { private readonly ISymUnmanagedVariable variable; public override int Index { get { variable.GetAddressField1(out var pRetVal); return (int)pRetVal; } } public override PdbLocalAttributes Attributes { get { variable.GetAttributes(out var pRetVal); if ((pRetVal & 1) != 0) { return PdbLocalAttributes.DebuggerHidden; } return PdbLocalAttributes.None; } } public override string Name { get { variable.GetName(0u, out var pcchName, null); char[] array = new char[pcchName]; variable.GetName((uint)array.Length, out pcchName, array); if (array.Length == 0) { return string.Empty; } return new string(array, 0, array.Length - 1); } } public override PdbCustomDebugInfo[] CustomDebugInfos => Array2.Empty(); public SymbolVariableImpl(ISymUnmanagedVariable variable) { this.variable = variable; } } [SupportedOSPlatform("windows")] internal sealed class SymbolWriterImpl : SymbolWriter { private readonly ISymUnmanagedWriter2 writer; private readonly ISymUnmanagedAsyncMethodPropertiesWriter asyncMethodWriter; private readonly string pdbFileName; private readonly Stream pdbStream; private readonly bool ownsStream; private readonly bool isDeterministic; private bool closeCalled; public override bool IsDeterministic => isDeterministic; public override bool SupportsAsyncMethods => asyncMethodWriter != null; public SymbolWriterImpl(ISymUnmanagedWriter2 writer, string pdbFileName, Stream pdbStream, PdbWriterOptions options, bool ownsStream) { this.writer = writer ?? throw new ArgumentNullException("writer"); asyncMethodWriter = writer as ISymUnmanagedAsyncMethodPropertiesWriter; this.pdbStream = pdbStream ?? throw new ArgumentNullException("pdbStream"); this.pdbFileName = pdbFileName; this.ownsStream = ownsStream; isDeterministic = (options & PdbWriterOptions.Deterministic) != PdbWriterOptions.None && writer is ISymUnmanagedWriter6; } public override void Close() { if (!closeCalled) { closeCalled = true; writer.Close(); } } public override void CloseMethod() { writer.CloseMethod(); } public override void CloseScope(int endOffset) { writer.CloseScope((uint)endOffset); } public override void DefineAsyncStepInfo(uint[] yieldOffsets, uint[] breakpointOffset, uint[] breakpointMethod) { if (asyncMethodWriter == null) { throw new InvalidOperationException(); } if (yieldOffsets.Length != breakpointOffset.Length || yieldOffsets.Length != breakpointMethod.Length) { throw new ArgumentException(); } asyncMethodWriter.DefineAsyncStepInfo((uint)yieldOffsets.Length, yieldOffsets, breakpointOffset, breakpointMethod); } public override void DefineCatchHandlerILOffset(uint catchHandlerOffset) { if (asyncMethodWriter == null) { throw new InvalidOperationException(); } asyncMethodWriter.DefineCatchHandlerILOffset(catchHandlerOffset); } public override void DefineConstant(string name, object value, uint sigToken) { writer.DefineConstant2(name, value, sigToken); } public override ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { writer.DefineDocument(url, ref language, ref languageVendor, ref documentType, out var pRetVal); if (pRetVal != null) { return new SymbolDocumentWriter(pRetVal); } return null; } public override void DefineKickoffMethod(uint kickoffMethod) { if (asyncMethodWriter == null) { throw new InvalidOperationException(); } asyncMethodWriter.DefineKickoffMethod(kickoffMethod); } public override void DefineSequencePoints(ISymbolDocumentWriter document, uint arraySize, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { if (!(document is SymbolDocumentWriter symbolDocumentWriter)) { throw new ArgumentException("document isn't a non-null SymbolDocumentWriter instance"); } writer.DefineSequencePoints(symbolDocumentWriter.SymUnmanagedDocumentWriter, arraySize, offsets, lines, columns, endLines, endColumns); } public override void OpenMethod(MDToken method) { writer.OpenMethod(method.Raw); } public override int OpenScope(int startOffset) { writer.OpenScope((uint)startOffset, out var pRetVal); return (int)pRetVal; } public override void SetSymAttribute(MDToken parent, string name, byte[] data) { writer.SetSymAttribute(parent.Raw, name, (uint)data.Length, data); } public override void SetUserEntryPoint(MDToken entryMethod) { writer.SetUserEntryPoint(entryMethod.Raw); } public override void UsingNamespace(string fullName) { writer.UsingNamespace(fullName); } public unsafe override bool GetDebugInfo(ChecksumAlgorithm pdbChecksumAlgorithm, ref uint pdbAge, out Guid guid, out uint stamp, out IMAGE_DEBUG_DIRECTORY pIDD, out byte[] codeViewData) { pIDD = default(IMAGE_DEBUG_DIRECTORY); codeViewData = null; if (isDeterministic) { ((ISymUnmanagedWriter3)writer).Commit(); long position = pdbStream.Position; pdbStream.Position = 0L; byte[] array = Hasher.Hash(pdbChecksumAlgorithm, pdbStream, pdbStream.Length); pdbStream.Position = position; if (writer is ISymUnmanagedWriter8 symUnmanagedWriter) { RoslynContentIdProvider.GetContentId(array, out guid, out stamp); symUnmanagedWriter.UpdateSignature(guid, stamp, pdbAge); return true; } if (writer is ISymUnmanagedWriter7 symUnmanagedWriter2) { fixed (byte* value = array) { symUnmanagedWriter2.UpdateSignatureByHashingContent(new IntPtr(value), (uint)array.Length); } } } writer.GetDebugInfo(out pIDD, 0u, out var pcData, null); codeViewData = new byte[pcData]; writer.GetDebugInfo(out pIDD, pcData, out pcData, codeViewData); if (writer is IPdbWriter pdbWriter) { byte[] array2 = new byte[16]; Array.Copy(codeViewData, 4, array2, 0, 16); guid = new Guid(array2); pdbWriter.GetSignatureAge(out stamp, out var age); pdbAge = age; return true; } guid = default(Guid); stamp = 0u; return false; } public override void DefineLocalVariable(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3, uint startOffset, uint endOffset) { writer.DefineLocalVariable2(name, attributes, sigToken, addrKind, addr1, addr2, addr3, startOffset, endOffset); } public override void Initialize(dnlib.DotNet.Writer.Metadata metadata) { if (isDeterministic) { ((ISymUnmanagedWriter6)writer).InitializeDeterministic(new MDEmitter(metadata), new StreamIStream(pdbStream)); } else { writer.Initialize(new MDEmitter(metadata), pdbFileName, new StreamIStream(pdbStream), fFullBuild: true); } } public unsafe override void SetSourceServerData(byte[] data) { if (data != null && writer is ISymUnmanagedWriter8 symUnmanagedWriter) { fixed (byte* ptr = data) { void* value = ptr; symUnmanagedWriter.SetSourceServerData(new IntPtr(value), (uint)data.Length); } } } public unsafe override void SetSourceLinkData(byte[] data) { if (data != null && writer is ISymUnmanagedWriter8 symUnmanagedWriter) { fixed (byte* ptr = data) { void* value = ptr; symUnmanagedWriter.SetSourceLinkData(new IntPtr(value), (uint)data.Length); } } } public override void Dispose() { Marshal.FinalReleaseComObject(writer); if (ownsStream) { pdbStream.Dispose(); } } } } namespace dnlib.DotNet.MD { public sealed class BlobStream : HeapStream { public BlobStream() { } public BlobStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } public byte[] Read(uint offset) { if (offset == 0) { return Array2.Empty(); } if (!TryCreateReader(offset, out var reader)) { return null; } return reader.ToArray(); } public byte[] ReadNoNull(uint offset) { return Read(offset) ?? Array2.Empty(); } public DataReader CreateReader(uint offset) { if (TryCreateReader(offset, out var reader)) { return reader; } return default(DataReader); } public bool TryCreateReader(uint offset, out DataReader reader) { reader = dataReader; if (!IsValidOffset(offset)) { return false; } reader.Position = offset; if (!reader.TryReadCompressedUInt32(out var value)) { return false; } if (!reader.CanRead(value)) { return false; } reader = reader.Slice(reader.Position, value); return true; } } public sealed class CodedToken { public static readonly CodedToken TypeDefOrRef = new CodedToken(2, new Table[3] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }); public static readonly CodedToken HasConstant = new CodedToken(2, new Table[3] { Table.Field, Table.Param, Table.Property }); public static readonly CodedToken HasCustomAttribute = new CodedToken(5, new Table[24] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, Table.Module, Table.Module }); public static readonly CodedToken HasFieldMarshal = new CodedToken(1, new Table[2] { Table.Field, Table.Param }); public static readonly CodedToken HasDeclSecurity = new CodedToken(2, new Table[3] { Table.TypeDef, Table.Method, Table.Assembly }); public static readonly CodedToken MemberRefParent = new CodedToken(3, new Table[5] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }); public static readonly CodedToken HasSemantic = new CodedToken(1, new Table[2] { Table.Event, Table.Property }); public static readonly CodedToken MethodDefOrRef = new CodedToken(1, new Table[2] { Table.Method, Table.MemberRef }); public static readonly CodedToken MemberForwarded = new CodedToken(1, new Table[2] { Table.Field, Table.Method }); public static readonly CodedToken Implementation = new CodedToken(2, new Table[3] { Table.File, Table.AssemblyRef, Table.ExportedType }); public static readonly CodedToken CustomAttributeType = new CodedToken(3, new Table[5] { Table.Module, Table.Module, Table.Method, Table.MemberRef, Table.Module }); public static readonly CodedToken ResolutionScope = new CodedToken(2, new Table[4] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }); public static readonly CodedToken TypeOrMethodDef = new CodedToken(1, new Table[2] { Table.TypeDef, Table.Method }); public static readonly CodedToken HasCustomDebugInformation = new CodedToken(5, new Table[27] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope }); private readonly Table[] tableTypes; private readonly int bits; private readonly int mask; public Table[] TableTypes => tableTypes; public int Bits => bits; internal CodedToken(int bits, Table[] tableTypes) { this.bits = bits; mask = (1 << bits) - 1; this.tableTypes = tableTypes; } public uint Encode(MDToken token) { return Encode(token.Raw); } public uint Encode(uint token) { Encode(token, out var codedToken); return codedToken; } public bool Encode(MDToken token, out uint codedToken) { return Encode(token.Raw, out codedToken); } public bool Encode(uint token, out uint codedToken) { int num = Array.IndexOf(tableTypes, MDToken.ToTable(token)); if (num < 0) { codedToken = uint.MaxValue; return false; } codedToken = (MDToken.ToRID(token) << bits) | (uint)num; return true; } public MDToken Decode2(uint codedToken) { Decode(codedToken, out uint token); return new MDToken(token); } public uint Decode(uint codedToken) { Decode(codedToken, out uint token); return token; } public bool Decode(uint codedToken, out MDToken token) { uint token2; bool result = Decode(codedToken, out token2); token = new MDToken(token2); return result; } public bool Decode(uint codedToken, out uint token) { uint num = codedToken >> bits; int num2 = (int)(codedToken & mask); if (num > 16777215 || num2 >= tableTypes.Length) { token = 0u; return false; } token = ((uint)tableTypes[num2] << 24) | num; return true; } } [DebuggerDisplay("{offset} {size} {name}")] public sealed class ColumnInfo { private readonly byte index; private byte offset; private readonly ColumnSize columnSize; private byte size; private readonly string name; public int Index => index; public int Offset { get { return offset; } internal set { offset = (byte)value; } } public int Size { get { return size; } internal set { size = (byte)value; } } public string Name => name; public ColumnSize ColumnSize => columnSize; public ColumnInfo(byte index, string name, ColumnSize columnSize) { this.index = index; this.name = name; this.columnSize = columnSize; } public ColumnInfo(byte index, string name, ColumnSize columnSize, byte offset, byte size) { this.index = index; this.name = name; this.columnSize = columnSize; this.offset = offset; this.size = size; } public uint Read(ref DataReader reader) { return size switch { 1 => reader.ReadByte(), 2 => reader.ReadUInt16(), 4 => reader.ReadUInt32(), _ => throw new InvalidOperationException("Invalid column size"), }; } internal uint Unsafe_Read24(ref DataReader reader) { if (size != 2) { return reader.Unsafe_ReadUInt32(); } return reader.Unsafe_ReadUInt16(); } public void Write(DataWriter writer, uint value) { switch (size) { case 1: writer.WriteByte((byte)value); break; case 2: writer.WriteUInt16((ushort)value); break; case 4: writer.WriteUInt32(value); break; default: throw new InvalidOperationException("Invalid column size"); } } internal void Write24(DataWriter writer, uint value) { if (size == 2) { writer.WriteUInt16((ushort)value); } else { writer.WriteUInt32(value); } } } public enum ColumnSize : 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, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55, Byte = 64, Int16 = 65, UInt16 = 66, Int32 = 67, UInt32 = 68, Strings = 69, GUID = 70, Blob = 71, TypeDefOrRef = 72, HasConstant = 73, HasCustomAttribute = 74, HasFieldMarshal = 75, HasDeclSecurity = 76, MemberRefParent = 77, HasSemantic = 78, MethodDefOrRef = 79, MemberForwarded = 80, Implementation = 81, CustomAttributeType = 82, ResolutionScope = 83, TypeOrMethodDef = 84, HasCustomDebugInformation = 85 } [Flags] public enum ComImageFlags : uint { ILOnly = 1u, Bit32Required = 2u, ILLibrary = 4u, StrongNameSigned = 8u, NativeEntryPoint = 0x10u, TrackDebugData = 0x10000u, Bit32Preferred = 0x20000u } internal sealed class CompressedMetadata : MetadataBase { private readonly CLRRuntimeReaderKind runtime; public override bool IsCompressed => true; public CompressedMetadata(IPEImage peImage, ImageCor20Header cor20Header, MetadataHeader mdHeader, CLRRuntimeReaderKind runtime) : base(peImage, cor20Header, mdHeader) { this.runtime = runtime; } internal CompressedMetadata(MetadataHeader mdHeader, bool isStandalonePortablePdb, CLRRuntimeReaderKind runtime) : base(mdHeader, isStandalonePortablePdb) { this.runtime = runtime; } protected override void InitializeInternal(DataReaderFactory mdReaderFactory, uint metadataBaseOffset) { DotNetStream dotNetStream = null; List list = new List(allStreams); bool forceAllBig = false; try { for (int num = mdHeader.StreamHeaders.Count - 1; num >= 0; num--) { StreamHeader streamHeader = mdHeader.StreamHeaders[num]; switch (streamHeader.Name) { case "#Strings": if (stringsStream == null) { stringsStream = new StringsStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(stringsStream); continue; } break; case "#US": if (usStream == null) { usStream = new USStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(usStream); continue; } break; case "#Blob": if (blobStream == null) { blobStream = new BlobStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(blobStream); continue; } break; case "#GUID": if (guidStream == null) { guidStream = new GuidStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(guidStream); continue; } break; case "#~": if (tablesStream == null) { tablesStream = new TablesStream(mdReaderFactory, metadataBaseOffset, streamHeader, runtime); list.Add(tablesStream); continue; } break; case "#Pdb": if (isStandalonePortablePdb && pdbStream == null) { pdbStream = new PdbStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(pdbStream); continue; } break; case "#JTD": if (runtime == CLRRuntimeReaderKind.Mono) { forceAllBig = true; continue; } break; } dotNetStream = new CustomDotNetStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(dotNetStream); dotNetStream = null; } } finally { dotNetStream?.Dispose(); list.Reverse(); allStreams = list; } if (tablesStream == null) { throw new BadImageFormatException("Missing MD stream"); } if (pdbStream != null) { tablesStream.Initialize(pdbStream.TypeSystemTableRows, forceAllBig); } else { tablesStream.Initialize(null, forceAllBig); } } public override RidList GetFieldRidList(uint typeDefRid) { return GetRidList(tablesStream.TypeDefTable, typeDefRid, 4, tablesStream.FieldTable); } public override RidList GetMethodRidList(uint typeDefRid) { return GetRidList(tablesStream.TypeDefTable, typeDefRid, 5, tablesStream.MethodTable); } public override RidList GetParamRidList(uint methodRid) { return GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable); } public override RidList GetEventRidList(uint eventMapRid) { return GetRidList(tablesStream.EventMapTable, eventMapRid, 1, tablesStream.EventTable); } public override RidList GetPropertyRidList(uint propertyMapRid) { return GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable); } public override RidList GetLocalVariableRidList(uint localScopeRid) { return GetRidList(tablesStream.LocalScopeTable, localScopeRid, 2, tablesStream.LocalVariableTable); } public override RidList GetLocalConstantRidList(uint localScopeRid) { return GetRidList(tablesStream.LocalScopeTable, localScopeRid, 3, tablesStream.LocalConstantTable); } private RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest) { ColumnInfo column = tableSource.TableInfo.Columns[colIndex]; if (!tablesStream.TryReadColumn24(tableSource, tableSourceRid, column, out var value)) { return RidList.Empty; } uint value2; bool flag = tablesStream.TryReadColumn24(tableSource, tableSourceRid + 1, column, out value2); uint num = tableDest.Rows + 1; if (value == 0 || value >= num) { return RidList.Empty; } uint num2 = ((!flag || (value2 == 0 && tableSourceRid + 1 == tableSource.Rows && tableDest.Rows == 65535)) ? num : value2); if (num2 < value) { num2 = value; } if (num2 > num) { num2 = num; } return RidList.Create(value, num2 - value); } protected override uint BinarySearch(MDTable tableSource, int keyColIndex, uint key) { ColumnInfo column = tableSource.TableInfo.Columns[keyColIndex]; uint num = 1u; uint num2 = tableSource.Rows; while (num <= num2) { uint num3 = (num + num2) / 2; if (!tablesStream.TryReadColumn24(tableSource, num3, column, out var value)) { break; } if (key == value) { return num3; } if (value > key) { num2 = num3 - 1; } else { num = num3 + 1; } } return 0u; } } public class CustomDotNetStream : DotNetStream { public CustomDotNetStream() { } public CustomDotNetStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } } [DebuggerDisplay("{dataReader.Length} {streamHeader.Name}")] public abstract class DotNetStream : IFileSection, IDisposable { protected DataReader dataReader; private StreamHeader streamHeader; private DataReaderFactory mdReaderFactory; private uint metadataBaseOffset; public FileOffset StartOffset => (FileOffset)dataReader.StartOffset; public FileOffset EndOffset => (FileOffset)dataReader.EndOffset; public uint StreamLength => dataReader.Length; public StreamHeader StreamHeader => streamHeader; public string Name { get { if (streamHeader != null) { return streamHeader.Name; } return string.Empty; } } public DataReader CreateReader() { return dataReader; } protected DotNetStream() { streamHeader = null; dataReader = default(DataReader); } protected DotNetStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) { this.mdReaderFactory = mdReaderFactory; mdReaderFactory.DataReaderInvalidated += DataReaderFactory_DataReaderInvalidated; this.mdReaderFactory = mdReaderFactory; this.metadataBaseOffset = metadataBaseOffset; this.streamHeader = streamHeader; RecreateReader(mdReaderFactory, metadataBaseOffset, streamHeader, notifyThisClass: false); } private void DataReaderFactory_DataReaderInvalidated(object sender, EventArgs e) { RecreateReader(mdReaderFactory, metadataBaseOffset, streamHeader, notifyThisClass: true); } private void RecreateReader(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader, bool notifyThisClass) { if (mdReaderFactory == null || streamHeader == null) { dataReader = default(DataReader); } else { dataReader = mdReaderFactory.CreateReader(metadataBaseOffset + streamHeader.Offset, streamHeader.StreamSize); } if (notifyThisClass) { OnReaderRecreated(); } } protected virtual void OnReaderRecreated() { } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { DataReaderFactory dataReaderFactory = mdReaderFactory; if (dataReaderFactory != null) { dataReaderFactory.DataReaderInvalidated -= DataReaderFactory_DataReaderInvalidated; } streamHeader = null; mdReaderFactory = null; } } public virtual bool IsValidIndex(uint index) { return IsValidOffset(index); } public bool IsValidOffset(uint offset) { if (offset != 0) { return offset < dataReader.Length; } return true; } public bool IsValidOffset(uint offset, int size) { if (size == 0) { return IsValidOffset(offset); } if (size > 0) { return (ulong)((long)offset + (long)(uint)size) <= (ulong)dataReader.Length; } return false; } } public abstract class HeapStream : DotNetStream { protected HeapStream() { } protected HeapStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } } public sealed class DotNetTableSizes { private bool bigStrings; private bool bigGuid; private bool bigBlob; private bool forceAllBig; private TableInfo[] tableInfos; internal const int normalMaxTables = 56; internal static bool IsSystemTable(Table table) { return (int)table < 48; } public void InitializeSizes(bool bigStrings, bool bigGuid, bool bigBlob, IList systemRowCounts, IList debugRowCounts) { InitializeSizes(bigStrings, bigGuid, bigBlob, systemRowCounts, debugRowCounts, forceAllBig: false); } internal void InitializeSizes(bool bigStrings, bool bigGuid, bool bigBlob, IList systemRowCounts, IList debugRowCounts, bool forceAllBig) { this.bigStrings = bigStrings || forceAllBig; this.bigGuid = bigGuid || forceAllBig; this.bigBlob = bigBlob || forceAllBig; this.forceAllBig = forceAllBig; TableInfo[] array = tableInfos; foreach (TableInfo tableInfo in array) { IList rowCounts = (IsSystemTable(tableInfo.Table) ? systemRowCounts : debugRowCounts); int num = 0; ColumnInfo[] columns = tableInfo.Columns; foreach (ColumnInfo columnInfo in columns) { columnInfo.Offset = num; int num2 = (columnInfo.Size = GetSize(columnInfo.ColumnSize, rowCounts)); num += num2; } tableInfo.RowSize = num; } } private int GetSize(ColumnSize columnSize, IList rowCounts) { if (0 <= (int)columnSize && (int)columnSize <= 55) { int num = (int)(columnSize - 0); uint num2 = ((num < rowCounts.Count) ? rowCounts[num] : 0u); if (!forceAllBig && num2 <= 65535) { return 2; } return 4; } if (72 <= (int)columnSize && (int)columnSize <= 85) { CodedToken codedToken = columnSize switch { ColumnSize.TypeDefOrRef => CodedToken.TypeDefOrRef, ColumnSize.HasConstant => CodedToken.HasConstant, ColumnSize.HasCustomAttribute => CodedToken.HasCustomAttribute, ColumnSize.HasFieldMarshal => CodedToken.HasFieldMarshal, ColumnSize.HasDeclSecurity => CodedToken.HasDeclSecurity, ColumnSize.MemberRefParent => CodedToken.MemberRefParent, ColumnSize.HasSemantic => CodedToken.HasSemantic, ColumnSize.MethodDefOrRef => CodedToken.MethodDefOrRef, ColumnSize.MemberForwarded => CodedToken.MemberForwarded, ColumnSize.Implementation => CodedToken.Implementation, ColumnSize.CustomAttributeType => CodedToken.CustomAttributeType, ColumnSize.ResolutionScope => CodedToken.ResolutionScope, ColumnSize.TypeOrMethodDef => CodedToken.TypeOrMethodDef, ColumnSize.HasCustomDebugInformation => CodedToken.HasCustomDebugInformation, _ => throw new InvalidOperationException($"Invalid ColumnSize: {columnSize}"), }; uint num3 = 0u; Table[] tableTypes = codedToken.TableTypes; for (int i = 0; i < tableTypes.Length; i++) { int num4 = (int)tableTypes[i]; uint num5 = ((num4 < rowCounts.Count) ? rowCounts[num4] : 0u); if (num5 > num3) { num3 = num5; } } uint num6 = num3 << codedToken.Bits; if (!forceAllBig && num6 <= 65535) { return 2; } return 4; } switch (columnSize) { case ColumnSize.Byte: return 1; case ColumnSize.Int16: return 2; case ColumnSize.UInt16: return 2; case ColumnSize.Int32: return 4; case ColumnSize.UInt32: return 4; case ColumnSize.Strings: if (!forceAllBig && !bigStrings) { return 2; } return 4; case ColumnSize.GUID: if (!forceAllBig && !bigGuid) { return 2; } return 4; case ColumnSize.Blob: if (!forceAllBig && !bigBlob) { return 2; } return 4; default: throw new InvalidOperationException($"Invalid ColumnSize: {columnSize}"); } } public TableInfo[] CreateTables(byte majorVersion, byte minorVersion) { int maxPresentTables; return CreateTables(majorVersion, minorVersion, out maxPresentTables); } public TableInfo[] CreateTables(byte majorVersion, byte minorVersion, out int maxPresentTables) { maxPresentTables = ((majorVersion == 1 && minorVersion == 0) ? 42 : 56); TableInfo[] array = new TableInfo[56] { new TableInfo(Table.Module, "Module", new ColumnInfo[5] { new ColumnInfo(0, "Generation", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Mvid", ColumnSize.GUID), new ColumnInfo(3, "EncId", ColumnSize.GUID), new ColumnInfo(4, "EncBaseId", ColumnSize.GUID) }), new TableInfo(Table.TypeRef, "TypeRef", new ColumnInfo[3] { new ColumnInfo(0, "ResolutionScope", ColumnSize.ResolutionScope), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Namespace", ColumnSize.Strings) }), new TableInfo(Table.TypeDef, "TypeDef", new ColumnInfo[6] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Namespace", ColumnSize.Strings), new ColumnInfo(3, "Extends", ColumnSize.TypeDefOrRef), new ColumnInfo(4, "FieldList", ColumnSize.Field), new ColumnInfo(5, "MethodList", ColumnSize.Method) }), new TableInfo(Table.FieldPtr, "FieldPtr", new ColumnInfo[1] { new ColumnInfo(0, "Field", ColumnSize.Field) }), new TableInfo(Table.Field, "Field", new ColumnInfo[3] { new ColumnInfo(0, "Flags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Signature", ColumnSize.Blob) }), new TableInfo(Table.MethodPtr, "MethodPtr", new ColumnInfo[1] { new ColumnInfo(0, "Method", ColumnSize.Method) }), new TableInfo(Table.Method, "Method", new ColumnInfo[6] { new ColumnInfo(0, "RVA", ColumnSize.UInt32), new ColumnInfo(1, "ImplFlags", ColumnSize.UInt16), new ColumnInfo(2, "Flags", ColumnSize.UInt16), new ColumnInfo(3, "Name", ColumnSize.Strings), new ColumnInfo(4, "Signature", ColumnSize.Blob), new ColumnInfo(5, "ParamList", ColumnSize.Param) }), new TableInfo(Table.ParamPtr, "ParamPtr", new ColumnInfo[1] { new ColumnInfo(0, "Param", ColumnSize.Param) }), new TableInfo(Table.Param, "Param", new ColumnInfo[3] { new ColumnInfo(0, "Flags", ColumnSize.UInt16), new ColumnInfo(1, "Sequence", ColumnSize.UInt16), new ColumnInfo(2, "Name", ColumnSize.Strings) }), new TableInfo(Table.InterfaceImpl, "InterfaceImpl", new ColumnInfo[2] { new ColumnInfo(0, "Class", ColumnSize.TypeDef), new ColumnInfo(1, "Interface", ColumnSize.TypeDefOrRef) }), new TableInfo(Table.MemberRef, "MemberRef", new ColumnInfo[3] { new ColumnInfo(0, "Class", ColumnSize.MemberRefParent), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Signature", ColumnSize.Blob) }), new TableInfo(Table.Constant, "Constant", new ColumnInfo[4] { new ColumnInfo(0, "Type", ColumnSize.Byte), new ColumnInfo(1, "Padding", ColumnSize.Byte), new ColumnInfo(2, "Parent", ColumnSize.HasConstant), new ColumnInfo(3, "Value", ColumnSize.Blob) }), new TableInfo(Table.CustomAttribute, "CustomAttribute", new ColumnInfo[3] { new ColumnInfo(0, "Parent", ColumnSize.HasCustomAttribute), new ColumnInfo(1, "Type", ColumnSize.CustomAttributeType), new ColumnInfo(2, "Value", ColumnSize.Blob) }), new TableInfo(Table.FieldMarshal, "FieldMarshal", new ColumnInfo[2] { new ColumnInfo(0, "Parent", ColumnSize.HasFieldMarshal), new ColumnInfo(1, "NativeType", ColumnSize.Blob) }), new TableInfo(Table.DeclSecurity, "DeclSecurity", new ColumnInfo[3] { new ColumnInfo(0, "Action", ColumnSize.Int16), new ColumnInfo(1, "Parent", ColumnSize.HasDeclSecurity), new ColumnInfo(2, "PermissionSet", ColumnSize.Blob) }), new TableInfo(Table.ClassLayout, "ClassLayout", new ColumnInfo[3] { new ColumnInfo(0, "PackingSize", ColumnSize.UInt16), new ColumnInfo(1, "ClassSize", ColumnSize.UInt32), new ColumnInfo(2, "Parent", ColumnSize.TypeDef) }), new TableInfo(Table.FieldLayout, "FieldLayout", new ColumnInfo[2] { new ColumnInfo(0, "OffSet", ColumnSize.UInt32), new ColumnInfo(1, "Field", ColumnSize.Field) }), new TableInfo(Table.StandAloneSig, "StandAloneSig", new ColumnInfo[1] { new ColumnInfo(0, "Signature", ColumnSize.Blob) }), new TableInfo(Table.EventMap, "EventMap", new ColumnInfo[2] { new ColumnInfo(0, "Parent", ColumnSize.TypeDef), new ColumnInfo(1, "EventList", ColumnSize.Event) }), new TableInfo(Table.EventPtr, "EventPtr", new ColumnInfo[1] { new ColumnInfo(0, "Event", ColumnSize.Event) }), new TableInfo(Table.Event, "Event", new ColumnInfo[3] { new ColumnInfo(0, "EventFlags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "EventType", ColumnSize.TypeDefOrRef) }), new TableInfo(Table.PropertyMap, "PropertyMap", new ColumnInfo[2] { new ColumnInfo(0, "Parent", ColumnSize.TypeDef), new ColumnInfo(1, "PropertyList", ColumnSize.Property) }), new TableInfo(Table.PropertyPtr, "PropertyPtr", new ColumnInfo[1] { new ColumnInfo(0, "Property", ColumnSize.Property) }), new TableInfo(Table.Property, "Property", new ColumnInfo[3] { new ColumnInfo(0, "PropFlags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Type", ColumnSize.Blob) }), new TableInfo(Table.MethodSemantics, "MethodSemantics", new ColumnInfo[3] { new ColumnInfo(0, "Semantic", ColumnSize.UInt16), new ColumnInfo(1, "Method", ColumnSize.Method), new ColumnInfo(2, "Association", ColumnSize.HasSemantic) }), new TableInfo(Table.MethodImpl, "MethodImpl", new ColumnInfo[3] { new ColumnInfo(0, "Class", ColumnSize.TypeDef), new ColumnInfo(1, "MethodBody", ColumnSize.MethodDefOrRef), new ColumnInfo(2, "MethodDeclaration", ColumnSize.MethodDefOrRef) }), new TableInfo(Table.ModuleRef, "ModuleRef", new ColumnInfo[1] { new ColumnInfo(0, "Name", ColumnSize.Strings) }), new TableInfo(Table.TypeSpec, "TypeSpec", new ColumnInfo[1] { new ColumnInfo(0, "Signature", ColumnSize.Blob) }), new TableInfo(Table.ImplMap, "ImplMap", new ColumnInfo[4] { new ColumnInfo(0, "MappingFlags", ColumnSize.UInt16), new ColumnInfo(1, "MemberForwarded", ColumnSize.MemberForwarded), new ColumnInfo(2, "ImportName", ColumnSize.Strings), new ColumnInfo(3, "ImportScope", ColumnSize.ModuleRef) }), new TableInfo(Table.FieldRVA, "FieldRVA", new ColumnInfo[2] { new ColumnInfo(0, "RVA", ColumnSize.UInt32), new ColumnInfo(1, "Field", ColumnSize.Field) }), new TableInfo(Table.ENCLog, "ENCLog", new ColumnInfo[2] { new ColumnInfo(0, "Token", ColumnSize.UInt32), new ColumnInfo(1, "FuncCode", ColumnSize.UInt32) }), new TableInfo(Table.ENCMap, "ENCMap", new ColumnInfo[1] { new ColumnInfo(0, "Token", ColumnSize.UInt32) }), new TableInfo(Table.Assembly, "Assembly", new ColumnInfo[9] { new ColumnInfo(0, "HashAlgId", ColumnSize.UInt32), new ColumnInfo(1, "MajorVersion", ColumnSize.UInt16), new ColumnInfo(2, "MinorVersion", ColumnSize.UInt16), new ColumnInfo(3, "BuildNumber", ColumnSize.UInt16), new ColumnInfo(4, "RevisionNumber", ColumnSize.UInt16), new ColumnInfo(5, "Flags", ColumnSize.UInt32), new ColumnInfo(6, "PublicKey", ColumnSize.Blob), new ColumnInfo(7, "Name", ColumnSize.Strings), new ColumnInfo(8, "Locale", ColumnSize.Strings) }), new TableInfo(Table.AssemblyProcessor, "AssemblyProcessor", new ColumnInfo[1] { new ColumnInfo(0, "Processor", ColumnSize.UInt32) }), new TableInfo(Table.AssemblyOS, "AssemblyOS", new ColumnInfo[3] { new ColumnInfo(0, "OSPlatformId", ColumnSize.UInt32), new ColumnInfo(1, "OSMajorVersion", ColumnSize.UInt32), new ColumnInfo(2, "OSMinorVersion", ColumnSize.UInt32) }), new TableInfo(Table.AssemblyRef, "AssemblyRef", new ColumnInfo[9] { new ColumnInfo(0, "MajorVersion", ColumnSize.UInt16), new ColumnInfo(1, "MinorVersion", ColumnSize.UInt16), new ColumnInfo(2, "BuildNumber", ColumnSize.UInt16), new ColumnInfo(3, "RevisionNumber", ColumnSize.UInt16), new ColumnInfo(4, "Flags", ColumnSize.UInt32), new ColumnInfo(5, "PublicKeyOrToken", ColumnSize.Blob), new ColumnInfo(6, "Name", ColumnSize.Strings), new ColumnInfo(7, "Locale", ColumnSize.Strings), new ColumnInfo(8, "HashValue", ColumnSize.Blob) }), new TableInfo(Table.AssemblyRefProcessor, "AssemblyRefProcessor", new ColumnInfo[2] { new ColumnInfo(0, "Processor", ColumnSize.UInt32), new ColumnInfo(1, "AssemblyRef", ColumnSize.AssemblyRef) }), new TableInfo(Table.AssemblyRefOS, "AssemblyRefOS", new ColumnInfo[4] { new ColumnInfo(0, "OSPlatformId", ColumnSize.UInt32), new ColumnInfo(1, "OSMajorVersion", ColumnSize.UInt32), new ColumnInfo(2, "OSMinorVersion", ColumnSize.UInt32), new ColumnInfo(3, "AssemblyRef", ColumnSize.AssemblyRef) }), new TableInfo(Table.File, "File", new ColumnInfo[3] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "HashValue", ColumnSize.Blob) }), new TableInfo(Table.ExportedType, "ExportedType", new ColumnInfo[5] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "TypeDefId", ColumnSize.UInt32), new ColumnInfo(2, "TypeName", ColumnSize.Strings), new ColumnInfo(3, "TypeNamespace", ColumnSize.Strings), new ColumnInfo(4, "Implementation", ColumnSize.Implementation) }), new TableInfo(Table.ManifestResource, "ManifestResource", new ColumnInfo[4] { new ColumnInfo(0, "Offset", ColumnSize.UInt32), new ColumnInfo(1, "Flags", ColumnSize.UInt32), new ColumnInfo(2, "Name", ColumnSize.Strings), new ColumnInfo(3, "Implementation", ColumnSize.Implementation) }), new TableInfo(Table.NestedClass, "NestedClass", new ColumnInfo[2] { new ColumnInfo(0, "NestedClass", ColumnSize.TypeDef), new ColumnInfo(1, "EnclosingClass", ColumnSize.TypeDef) }), null, null, null, null, null, null, null, null, null, null, null, null, null, null }; if (majorVersion == 1 && minorVersion == 1) { array[42] = new TableInfo(Table.GenericParam, "GenericParam", new ColumnInfo[5] { new ColumnInfo(0, "Number", ColumnSize.UInt16), new ColumnInfo(1, "Flags", ColumnSize.UInt16), new ColumnInfo(2, "Owner", ColumnSize.TypeOrMethodDef), new ColumnInfo(3, "Name", ColumnSize.Strings), new ColumnInfo(4, "Kind", ColumnSize.TypeDefOrRef) }); } else { array[42] = new TableInfo(Table.GenericParam, "GenericParam", new ColumnInfo[4] { new ColumnInfo(0, "Number", ColumnSize.UInt16), new ColumnInfo(1, "Flags", ColumnSize.UInt16), new ColumnInfo(2, "Owner", ColumnSize.TypeOrMethodDef), new ColumnInfo(3, "Name", ColumnSize.Strings) }); } array[43] = new TableInfo(Table.MethodSpec, "MethodSpec", new ColumnInfo[2] { new ColumnInfo(0, "Method", ColumnSize.MethodDefOrRef), new ColumnInfo(1, "Instantiation", ColumnSize.Blob) }); array[44] = new TableInfo(Table.GenericParamConstraint, "GenericParamConstraint", new ColumnInfo[2] { new ColumnInfo(0, "Owner", ColumnSize.GenericParam), new ColumnInfo(1, "Constraint", ColumnSize.TypeDefOrRef) }); array[45] = new TableInfo((Table)45, string.Empty, new ColumnInfo[0]); array[46] = new TableInfo((Table)46, string.Empty, new ColumnInfo[0]); array[47] = new TableInfo((Table)47, string.Empty, new ColumnInfo[0]); array[48] = new TableInfo(Table.Document, "Document", new ColumnInfo[4] { new ColumnInfo(0, "Name", ColumnSize.Blob), new ColumnInfo(1, "HashAlgorithm", ColumnSize.GUID), new ColumnInfo(2, "Hash", ColumnSize.Blob), new ColumnInfo(3, "Language", ColumnSize.GUID) }); array[49] = new TableInfo(Table.MethodDebugInformation, "MethodDebugInformation", new ColumnInfo[2] { new ColumnInfo(0, "Document", ColumnSize.Document), new ColumnInfo(1, "SequencePoints", ColumnSize.Blob) }); array[50] = new TableInfo(Table.LocalScope, "LocalScope", new ColumnInfo[6] { new ColumnInfo(0, "Method", ColumnSize.Method), new ColumnInfo(1, "ImportScope", ColumnSize.ImportScope), new ColumnInfo(2, "VariableList", ColumnSize.LocalVariable), new ColumnInfo(3, "ConstantList", ColumnSize.LocalConstant), new ColumnInfo(4, "StartOffset", ColumnSize.UInt32), new ColumnInfo(5, "Length", ColumnSize.UInt32) }); array[51] = new TableInfo(Table.LocalVariable, "LocalVariable", new ColumnInfo[3] { new ColumnInfo(0, "Attributes", ColumnSize.UInt16), new ColumnInfo(1, "Index", ColumnSize.UInt16), new ColumnInfo(2, "Name", ColumnSize.Strings) }); array[52] = new TableInfo(Table.LocalConstant, "LocalConstant", new ColumnInfo[2] { new ColumnInfo(0, "Name", ColumnSize.Strings), new ColumnInfo(1, "Signature", ColumnSize.Blob) }); array[53] = new TableInfo(Table.ImportScope, "ImportScope", new ColumnInfo[2] { new ColumnInfo(0, "Parent", ColumnSize.ImportScope), new ColumnInfo(1, "Imports", ColumnSize.Blob) }); array[54] = new TableInfo(Table.StateMachineMethod, "StateMachineMethod", new ColumnInfo[2] { new ColumnInfo(0, "MoveNextMethod", ColumnSize.Method), new ColumnInfo(1, "KickoffMethod", ColumnSize.Method) }); array[55] = new TableInfo(Table.CustomDebugInformation, "CustomDebugInformation", new ColumnInfo[3] { new ColumnInfo(0, "Parent", ColumnSize.HasCustomDebugInformation), new ColumnInfo(1, "Kind", ColumnSize.GUID), new ColumnInfo(2, "Value", ColumnSize.Blob) }); return tableInfos = array; } } internal sealed class ENCMetadata : MetadataBase { private static readonly UTF8String DeletedName = "_Deleted"; private bool hasMethodPtr; private bool hasFieldPtr; private bool hasParamPtr; private bool hasEventPtr; private bool hasPropertyPtr; private bool hasDeletedFields; private bool hasDeletedNonFields; private readonly CLRRuntimeReaderKind runtime; private readonly Dictionary sortedTables = new Dictionary(); private readonly Lock theLock = Lock.Create(); public override bool IsCompressed => false; public ENCMetadata(IPEImage peImage, ImageCor20Header cor20Header, MetadataHeader mdHeader, CLRRuntimeReaderKind runtime) : base(peImage, cor20Header, mdHeader) { this.runtime = runtime; } internal ENCMetadata(MetadataHeader mdHeader, bool isStandalonePortablePdb, CLRRuntimeReaderKind runtime) : base(mdHeader, isStandalonePortablePdb) { this.runtime = runtime; } protected override void InitializeInternal(DataReaderFactory mdReaderFactory, uint metadataBaseOffset) { DotNetStream dotNetStream = null; bool forceAllBig = false; try { if (runtime == CLRRuntimeReaderKind.Mono) { List list = new List(allStreams); for (int num = mdHeader.StreamHeaders.Count - 1; num >= 0; num--) { StreamHeader streamHeader = mdHeader.StreamHeaders[num]; switch (streamHeader.Name) { case "#Strings": if (stringsStream == null) { stringsStream = new StringsStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(stringsStream); continue; } break; case "#US": if (usStream == null) { usStream = new USStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(usStream); continue; } break; case "#Blob": if (blobStream == null) { blobStream = new BlobStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(blobStream); continue; } break; case "#GUID": if (guidStream == null) { guidStream = new GuidStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(guidStream); continue; } break; case "#-": case "#~": if (tablesStream == null) { tablesStream = new TablesStream(mdReaderFactory, metadataBaseOffset, streamHeader, runtime); list.Add(tablesStream); continue; } break; case "#Pdb": if (isStandalonePortablePdb && pdbStream == null) { pdbStream = new PdbStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(pdbStream); continue; } break; case "#JTD": forceAllBig = true; continue; } dotNetStream = new CustomDotNetStream(mdReaderFactory, metadataBaseOffset, streamHeader); list.Add(dotNetStream); dotNetStream = null; } list.Reverse(); allStreams = list; } else { foreach (StreamHeader streamHeader2 in mdHeader.StreamHeaders) { switch (streamHeader2.Name.ToUpperInvariant()) { case "#STRINGS": if (stringsStream == null) { stringsStream = new StringsStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(stringsStream); continue; } break; case "#US": if (usStream == null) { usStream = new USStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(usStream); continue; } break; case "#BLOB": if (blobStream == null) { blobStream = new BlobStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(blobStream); continue; } break; case "#GUID": if (guidStream == null) { guidStream = new GuidStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(guidStream); continue; } break; case "#-": case "#~": if (tablesStream == null) { tablesStream = new TablesStream(mdReaderFactory, metadataBaseOffset, streamHeader2, runtime); allStreams.Add(tablesStream); continue; } break; case "#PDB": if (isStandalonePortablePdb && pdbStream == null && streamHeader2.Name == "#Pdb") { pdbStream = new PdbStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(pdbStream); continue; } break; case "#JTD": forceAllBig = true; continue; } dotNetStream = new CustomDotNetStream(mdReaderFactory, metadataBaseOffset, streamHeader2); allStreams.Add(dotNetStream); dotNetStream = null; } } } finally { dotNetStream?.Dispose(); } if (tablesStream == null) { throw new BadImageFormatException("Missing MD stream"); } if (pdbStream != null) { tablesStream.Initialize(pdbStream.TypeSystemTableRows, forceAllBig); } else { tablesStream.Initialize(null, forceAllBig); } hasFieldPtr = !tablesStream.FieldPtrTable.IsEmpty; hasMethodPtr = !tablesStream.MethodPtrTable.IsEmpty; hasParamPtr = !tablesStream.ParamPtrTable.IsEmpty; hasEventPtr = !tablesStream.EventPtrTable.IsEmpty; hasPropertyPtr = !tablesStream.PropertyPtrTable.IsEmpty; switch (runtime) { case CLRRuntimeReaderKind.CLR: hasDeletedFields = tablesStream.HasDelete; hasDeletedNonFields = tablesStream.HasDelete; break; case CLRRuntimeReaderKind.Mono: hasDeletedFields = true; hasDeletedNonFields = false; break; default: throw new InvalidOperationException(); } } public override RidList GetTypeDefRidList() { if (!hasDeletedNonFields) { return base.GetTypeDefRidList(); } uint rows = tablesStream.TypeDefTable.Rows; List list = new List((int)rows); for (uint num = 1u; num <= rows; num++) { if (tablesStream.TryReadTypeDefRow(num, out var row) && (num == 1 || !stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))) { list.Add(num); } } return RidList.Create(list); } public override RidList GetExportedTypeRidList() { if (!hasDeletedNonFields) { return base.GetExportedTypeRidList(); } uint rows = tablesStream.ExportedTypeTable.Rows; List list = new List((int)rows); for (uint num = 1u; num <= rows; num++) { if (tablesStream.TryReadExportedTypeRow(num, out var row) && !stringsStream.ReadNoNull(row.TypeName).StartsWith(DeletedName)) { list.Add(num); } } return RidList.Create(list); } private uint ToFieldRid(uint listRid) { if (!hasFieldPtr) { return listRid; } if (!tablesStream.TryReadColumn24(tablesStream.FieldPtrTable, listRid, 0, out var value)) { return 0u; } return value; } private uint ToMethodRid(uint listRid) { if (!hasMethodPtr) { return listRid; } if (!tablesStream.TryReadColumn24(tablesStream.MethodPtrTable, listRid, 0, out var value)) { return 0u; } return value; } private uint ToParamRid(uint listRid) { if (!hasParamPtr) { return listRid; } if (!tablesStream.TryReadColumn24(tablesStream.ParamPtrTable, listRid, 0, out var value)) { return 0u; } return value; } private uint ToEventRid(uint listRid) { if (!hasEventPtr) { return listRid; } if (!tablesStream.TryReadColumn24(tablesStream.EventPtrTable, listRid, 0, out var value)) { return 0u; } return value; } private uint ToPropertyRid(uint listRid) { if (!hasPropertyPtr) { return listRid; } if (!tablesStream.TryReadColumn24(tablesStream.PropertyPtrTable, listRid, 0, out var value)) { return 0u; } return value; } public override RidList GetFieldRidList(uint typeDefRid) { RidList ridList = GetRidList(tablesStream.TypeDefTable, typeDefRid, 4, tablesStream.FieldTable); if (ridList.Count == 0 || (!hasFieldPtr && !hasDeletedFields)) { return ridList; } MDTable fieldTable = tablesStream.FieldTable; List list = new List(ridList.Count); for (int i = 0; i < ridList.Count; i++) { uint num = ToFieldRid(ridList[i]); if (fieldTable.IsInvalidRID(num)) { continue; } if (hasDeletedFields) { if (!tablesStream.TryReadFieldRow(num, out var row)) { continue; } if (runtime == CLRRuntimeReaderKind.CLR) { if ((row.Flags & 0x400) != 0 && stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) { continue; } } else if ((row.Flags & 0x600) == 1536 && stringsStream.ReadNoNull(row.Name) == DeletedName) { continue; } } list.Add(num); } return RidList.Create(list); } public override RidList GetMethodRidList(uint typeDefRid) { RidList ridList = GetRidList(tablesStream.TypeDefTable, typeDefRid, 5, tablesStream.MethodTable); if (ridList.Count == 0 || (!hasMethodPtr && !hasDeletedNonFields)) { return ridList; } MDTable methodTable = tablesStream.MethodTable; List list = new List(ridList.Count); for (int i = 0; i < ridList.Count; i++) { uint num = ToMethodRid(ridList[i]); if (!methodTable.IsInvalidRID(num) && (!hasDeletedNonFields || (tablesStream.TryReadMethodRow(num, out var row) && ((row.Flags & 0x1000) == 0 || !stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))))) { list.Add(num); } } return RidList.Create(list); } public override RidList GetParamRidList(uint methodRid) { RidList ridList = GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable); if (ridList.Count == 0 || !hasParamPtr) { return ridList; } MDTable paramTable = tablesStream.ParamTable; List list = new List(ridList.Count); for (int i = 0; i < ridList.Count; i++) { uint num = ToParamRid(ridList[i]); if (!paramTable.IsInvalidRID(num)) { list.Add(num); } } return RidList.Create(list); } public override RidList GetEventRidList(uint eventMapRid) { RidList ridList = GetRidList(tablesStream.EventMapTable, eventMapRid, 1, tablesStream.EventTable); if (ridList.Count == 0 || (!hasEventPtr && !hasDeletedNonFields)) { return ridList; } MDTable eventTable = tablesStream.EventTable; List list = new List(ridList.Count); for (int i = 0; i < ridList.Count; i++) { uint num = ToEventRid(ridList[i]); if (!eventTable.IsInvalidRID(num) && (!hasDeletedNonFields || (tablesStream.TryReadEventRow(num, out var row) && ((row.EventFlags & 0x400) == 0 || !stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))))) { list.Add(num); } } return RidList.Create(list); } public override RidList GetPropertyRidList(uint propertyMapRid) { RidList ridList = GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable); if (ridList.Count == 0 || (!hasPropertyPtr && !hasDeletedNonFields)) { return ridList; } MDTable propertyTable = tablesStream.PropertyTable; List list = new List(ridList.Count); for (int i = 0; i < ridList.Count; i++) { uint num = ToPropertyRid(ridList[i]); if (!propertyTable.IsInvalidRID(num) && (!hasDeletedNonFields || (tablesStream.TryReadPropertyRow(num, out var row) && ((row.PropFlags & 0x400) == 0 || !stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))))) { list.Add(num); } } return RidList.Create(list); } public override RidList GetLocalVariableRidList(uint localScopeRid) { return GetRidList(tablesStream.LocalScopeTable, localScopeRid, 2, tablesStream.LocalVariableTable); } public override RidList GetLocalConstantRidList(uint localScopeRid) { return GetRidList(tablesStream.LocalScopeTable, localScopeRid, 3, tablesStream.LocalConstantTable); } private RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest) { ColumnInfo column = tableSource.TableInfo.Columns[colIndex]; if (!tablesStream.TryReadColumn24(tableSource, tableSourceRid, column, out var value)) { return RidList.Empty; } uint value2; bool flag = tablesStream.TryReadColumn24(tableSource, tableSourceRid + 1, column, out value2); uint num = tableDest.Rows + 1; if (value == 0 || value >= num) { return RidList.Empty; } uint num2 = ((flag && value2 != 0) ? value2 : num); if (num2 < value) { num2 = value; } if (num2 > num) { num2 = num; } return RidList.Create(value, num2 - value); } protected override uint BinarySearch(MDTable tableSource, int keyColIndex, uint key) { ColumnInfo column = tableSource.TableInfo.Columns[keyColIndex]; uint num = 1u; uint num2 = tableSource.Rows; while (num <= num2) { uint num3 = (num + num2) / 2; if (!tablesStream.TryReadColumn24(tableSource, num3, column, out var value)) { break; } if (key == value) { return num3; } if (value > key) { num2 = num3 - 1; } else { num = num3 + 1; } } if (tableSource.Table == Table.GenericParam && !tablesStream.IsSorted(tableSource)) { return LinearSearch(tableSource, keyColIndex, key); } return 0u; } private uint LinearSearch(MDTable tableSource, int keyColIndex, uint key) { if (tableSource == null) { return 0u; } ColumnInfo column = tableSource.TableInfo.Columns[keyColIndex]; uint value; for (uint num = 1u; num <= tableSource.Rows && tablesStream.TryReadColumn24(tableSource, num, column, out value); num++) { if (key == value) { return num; } } return 0u; } protected override RidList FindAllRowsUnsorted(MDTable tableSource, int keyColIndex, uint key) { if (tablesStream.IsSorted(tableSource)) { return FindAllRows(tableSource, keyColIndex, key); } theLock.EnterWriteLock(); SortedTable value; try { if (!sortedTables.TryGetValue(tableSource.Table, out value)) { value = (sortedTables[tableSource.Table] = new SortedTable(tableSource, keyColIndex)); } } finally { theLock.ExitWriteLock(); } return value.FindAllRows(key); } } public sealed class GuidStream : HeapStream { public GuidStream() { } public GuidStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } public override bool IsValidIndex(uint index) { if (index != 0) { if (index <= 268435456) { return IsValidOffset((index - 1) * 16, 16); } return false; } return true; } public Guid? Read(uint index) { if (index == 0 || !IsValidIndex(index)) { return null; } DataReader dataReader = base.dataReader; dataReader.Position = (index - 1) * 16; return dataReader.ReadGuid(); } } public enum HeapType : uint { Strings, Guid, Blob, US } public sealed class ImageCor20Header : FileSection { private readonly uint cb; private readonly ushort majorRuntimeVersion; private readonly ushort minorRuntimeVersion; private readonly ImageDataDirectory metadata; private readonly ComImageFlags flags; private readonly uint entryPointToken_or_RVA; private readonly ImageDataDirectory resources; private readonly ImageDataDirectory strongNameSignature; private readonly ImageDataDirectory codeManagerTable; private readonly ImageDataDirectory vtableFixups; private readonly ImageDataDirectory exportAddressTableJumps; private readonly ImageDataDirectory managedNativeHeader; public bool HasNativeHeader => (flags & ComImageFlags.ILLibrary) != 0; public uint CB => cb; public ushort MajorRuntimeVersion => majorRuntimeVersion; public ushort MinorRuntimeVersion => minorRuntimeVersion; public ImageDataDirectory Metadata => metadata; public ComImageFlags Flags => flags; public uint EntryPointToken_or_RVA => entryPointToken_or_RVA; public ImageDataDirectory Resources => resources; public ImageDataDirectory StrongNameSignature => strongNameSignature; public ImageDataDirectory CodeManagerTable => codeManagerTable; public ImageDataDirectory VTableFixups => vtableFixups; public ImageDataDirectory ExportAddressTableJumps => exportAddressTableJumps; public ImageDataDirectory ManagedNativeHeader => managedNativeHeader; public ImageCor20Header(ref DataReader reader, bool verify) { SetStartOffset(ref reader); cb = reader.ReadUInt32(); if (verify && cb < 72) { throw new BadImageFormatException("Invalid IMAGE_COR20_HEADER.cb value"); } majorRuntimeVersion = reader.ReadUInt16(); minorRuntimeVersion = reader.ReadUInt16(); metadata = new ImageDataDirectory(ref reader, verify); flags = (ComImageFlags)reader.ReadUInt32(); entryPointToken_or_RVA = reader.ReadUInt32(); resources = new ImageDataDirectory(ref reader, verify); strongNameSignature = new ImageDataDirectory(ref reader, verify); codeManagerTable = new ImageDataDirectory(ref reader, verify); vtableFixups = new ImageDataDirectory(ref reader, verify); exportAddressTableJumps = new ImageDataDirectory(ref reader, verify); managedNativeHeader = new ImageDataDirectory(ref reader, verify); SetEndoffset(ref reader); } } public interface IColumnReader { bool ReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value); } public interface IRowReader where TRow : struct { bool TryReadRow(uint rid, out TRow row); } public static class MDHeaderRuntimeVersion { public const string MS_CLR_10 = "v1.0.3705"; public const string MS_CLR_10_X86RETAIL = "v1.x86ret"; public const string MS_CLR_10_RETAIL = "retail"; public const string MS_CLR_10_COMPLUS = "COMPLUS"; public const string MS_CLR_11 = "v1.1.4322"; public const string MS_CLR_20 = "v2.0.50727"; public const string MS_CLR_40 = "v4.0.30319"; public const string MS_CLR_10_PREFIX = "v1.0"; public const string MS_CLR_10_PREFIX_X86RETAIL = "v1.x86"; public const string MS_CLR_11_PREFIX = "v1.1"; public const string MS_CLR_20_PREFIX = "v2.0"; public const string MS_CLR_40_PREFIX = "v4.0"; public const string ECMA_2002 = "Standard CLI 2002"; public const string ECMA_2005 = "Standard CLI 2005"; public const string PORTABLE_PDB_V1_0 = "PDB v1.0"; } [Flags] public enum MDStreamFlags : byte { BigStrings = 1, BigGUID = 2, BigBlob = 4, Padding = 8, DeltaOnly = 0x20, ExtraData = 0x40, HasDelete = 0x80 } [DebuggerDisplay("DL:{dataReader.Length} R:{numRows} RS:{tableInfo.RowSize} C:{Count} {tableInfo.Name}")] public sealed class MDTable : IDisposable, IFileSection { private readonly Table table; private uint numRows; private TableInfo tableInfo; private DataReader dataReader; internal readonly ColumnInfo Column0; internal readonly ColumnInfo Column1; internal readonly ColumnInfo Column2; internal readonly ColumnInfo Column3; internal readonly ColumnInfo Column4; internal readonly ColumnInfo Column5; internal readonly ColumnInfo Column6; internal readonly ColumnInfo Column7; internal readonly ColumnInfo Column8; private int Count => tableInfo.Columns.Length; public FileOffset StartOffset => (FileOffset)dataReader.StartOffset; public FileOffset EndOffset => (FileOffset)dataReader.EndOffset; public Table Table => table; public string Name => tableInfo.Name; public uint Rows => numRows; public uint RowSize => (uint)tableInfo.RowSize; public IList Columns => tableInfo.Columns; public bool IsEmpty => numRows == 0; public TableInfo TableInfo => tableInfo; internal DataReader DataReader { get { return dataReader; } set { dataReader = value; } } internal MDTable(Table table, uint numRows, TableInfo tableInfo) { this.table = table; this.numRows = numRows; this.tableInfo = tableInfo; ColumnInfo[] columns = tableInfo.Columns; int num = columns.Length; if (num > 0) { Column0 = columns[0]; } if (num > 1) { Column1 = columns[1]; } if (num > 2) { Column2 = columns[2]; } if (num > 3) { Column3 = columns[3]; } if (num > 4) { Column4 = columns[4]; } if (num > 5) { Column5 = columns[5]; } if (num > 6) { Column6 = columns[6]; } if (num > 7) { Column7 = columns[7]; } if (num > 8) { Column8 = columns[8]; } } public bool IsValidRID(uint rid) { if (rid != 0) { return rid <= numRows; } return false; } public bool IsInvalidRID(uint rid) { if (rid != 0) { return rid > numRows; } return true; } public void Dispose() { numRows = 0u; tableInfo = null; dataReader = default(DataReader); } } public abstract class Metadata : IDisposable { public abstract bool IsCompressed { get; } public abstract bool IsStandalonePortablePdb { get; } public abstract ImageCor20Header ImageCor20Header { get; } public abstract uint Version { get; } public abstract string VersionString { get; } public abstract IPEImage PEImage { get; } public abstract MetadataHeader MetadataHeader { get; } public abstract StringsStream StringsStream { get; } public abstract USStream USStream { get; } public abstract BlobStream BlobStream { get; } public abstract GuidStream GuidStream { get; } public abstract TablesStream TablesStream { get; } public abstract PdbStream PdbStream { get; } public abstract IList AllStreams { get; } public abstract RidList GetTypeDefRidList(); public abstract RidList GetExportedTypeRidList(); public abstract RidList GetFieldRidList(uint typeDefRid); public abstract RidList GetMethodRidList(uint typeDefRid); public abstract RidList GetParamRidList(uint methodRid); public abstract RidList GetEventRidList(uint eventMapRid); public abstract RidList GetPropertyRidList(uint propertyMapRid); public abstract RidList GetInterfaceImplRidList(uint typeDefRid); public abstract RidList GetGenericParamRidList(Table table, uint rid); public abstract RidList GetGenericParamConstraintRidList(uint genericParamRid); public abstract RidList GetCustomAttributeRidList(Table table, uint rid); public abstract RidList GetDeclSecurityRidList(Table table, uint rid); public abstract RidList GetMethodSemanticsRidList(Table table, uint rid); public abstract RidList GetMethodImplRidList(uint typeDefRid); public abstract uint GetClassLayoutRid(uint typeDefRid); public abstract uint GetFieldLayoutRid(uint fieldRid); public abstract uint GetFieldMarshalRid(Table table, uint rid); public abstract uint GetFieldRVARid(uint fieldRid); public abstract uint GetImplMapRid(Table table, uint rid); public abstract uint GetNestedClassRid(uint typeDefRid); public abstract uint GetEventMapRid(uint typeDefRid); public abstract uint GetPropertyMapRid(uint typeDefRid); public abstract uint GetConstantRid(Table table, uint rid); public abstract uint GetOwnerTypeOfField(uint fieldRid); public abstract uint GetOwnerTypeOfMethod(uint methodRid); public abstract uint GetOwnerTypeOfEvent(uint eventRid); public abstract uint GetOwnerTypeOfProperty(uint propertyRid); public abstract uint GetOwnerOfGenericParam(uint gpRid); public abstract uint GetOwnerOfGenericParamConstraint(uint gpcRid); public abstract uint GetOwnerOfParam(uint paramRid); public abstract RidList GetNestedClassRidList(uint typeDefRid); public abstract RidList GetNonNestedClassRidList(); public abstract RidList GetLocalScopeRidList(uint methodRid); public abstract RidList GetLocalVariableRidList(uint localScopeRid); public abstract RidList GetLocalConstantRidList(uint localScopeRid); public abstract uint GetStateMachineMethodRid(uint methodRid); public abstract RidList GetCustomDebugInformationRidList(Table table, uint rid); public abstract void Dispose(); } internal abstract class MetadataBase : Metadata { protected sealed class SortedTable { [DebuggerDisplay("{rid} {key}")] private readonly struct RowInfo : IComparable { public readonly uint rid; public readonly uint key; public RowInfo(uint rid, uint key) { this.rid = rid; this.key = key; } public int CompareTo(RowInfo other) { if (key < other.key) { return -1; } if (key > other.key) { return 1; } return rid.CompareTo(other.rid); } } private RowInfo[] rows; public SortedTable(MDTable mdTable, int keyColIndex) { InitializeKeys(mdTable, keyColIndex); Array.Sort(rows); } private void InitializeKeys(MDTable mdTable, int keyColIndex) { ColumnInfo columnInfo = mdTable.TableInfo.Columns[keyColIndex]; rows = new RowInfo[mdTable.Rows + 1]; if (mdTable.Rows == 0) { return; } DataReader reader = mdTable.DataReader; reader.Position = (uint)columnInfo.Offset; uint num = (uint)(mdTable.TableInfo.RowSize - columnInfo.Size); for (uint num2 = 1u; num2 <= mdTable.Rows; num2++) { rows[num2] = new RowInfo(num2, columnInfo.Unsafe_Read24(ref reader)); if (num2 < mdTable.Rows) { reader.Position += num; } } } private int BinarySearch(uint key) { int num = 1; int num2 = rows.Length - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; uint key2 = rows[num3].key; if (key == key2) { return num3; } if (key2 > key) { num2 = num3 - 1; } else { num = num3 + 1; } } return 0; } public RidList FindAllRows(uint key) { int num = BinarySearch(key); if (num == 0) { return RidList.Empty; } int i = num + 1; while (num > 1 && key == rows[num - 1].key) { num--; } for (; i < rows.Length && key == rows[i].key; i++) { } List list = new List(i - num); for (int j = num; j < i; j++) { list.Add(rows[j].rid); } return RidList.Create(list); } } protected IPEImage peImage; protected ImageCor20Header cor20Header; protected MetadataHeader mdHeader; protected StringsStream stringsStream; protected USStream usStream; protected BlobStream blobStream; protected GuidStream guidStream; protected TablesStream tablesStream; protected PdbStream pdbStream; protected IList allStreams; protected readonly bool isStandalonePortablePdb; private uint[] fieldRidToTypeDefRid; private uint[] methodRidToTypeDefRid; private uint[] eventRidToTypeDefRid; private uint[] propertyRidToTypeDefRid; private uint[] gpRidToOwnerRid; private uint[] gpcRidToOwnerRid; private uint[] paramRidToOwnerRid; private Dictionary> typeDefRidToNestedClasses; private StrongBox nonNestedTypes; private DataReaderFactory mdReaderFactoryToDisposeLater; private SortedTable eventMapSortedTable; private SortedTable propertyMapSortedTable; public override bool IsStandalonePortablePdb => isStandalonePortablePdb; public override ImageCor20Header ImageCor20Header => cor20Header; public override uint Version => (uint)((mdHeader.MajorVersion << 16) | mdHeader.MinorVersion); public override string VersionString => mdHeader.VersionString; public override IPEImage PEImage => peImage; public override MetadataHeader MetadataHeader => mdHeader; public override StringsStream StringsStream => stringsStream; public override USStream USStream => usStream; public override BlobStream BlobStream => blobStream; public override GuidStream GuidStream => guidStream; public override TablesStream TablesStream => tablesStream; public override PdbStream PdbStream => pdbStream; public override IList AllStreams => allStreams; protected MetadataBase(IPEImage peImage, ImageCor20Header cor20Header, MetadataHeader mdHeader) { try { allStreams = new List(); this.peImage = peImage; this.cor20Header = cor20Header; this.mdHeader = mdHeader; isStandalonePortablePdb = false; } catch { peImage?.Dispose(); throw; } } internal MetadataBase(MetadataHeader mdHeader, bool isStandalonePortablePdb) { allStreams = new List(); peImage = null; cor20Header = null; this.mdHeader = mdHeader; this.isStandalonePortablePdb = isStandalonePortablePdb; } public void Initialize(DataReaderFactory mdReaderFactory) { mdReaderFactoryToDisposeLater = mdReaderFactory; uint metadataBaseOffset; if (peImage != null) { metadataBaseOffset = (uint)peImage.ToFileOffset(cor20Header.Metadata.VirtualAddress); mdReaderFactory = peImage.DataReaderFactory; } else { metadataBaseOffset = 0u; } InitializeInternal(mdReaderFactory, metadataBaseOffset); if (tablesStream == null) { throw new BadImageFormatException("Missing MD stream"); } if (isStandalonePortablePdb && pdbStream == null) { throw new BadImageFormatException("Missing #Pdb stream"); } InitializeNonExistentHeaps(); } protected void InitializeNonExistentHeaps() { if (stringsStream == null) { stringsStream = new StringsStream(); } if (usStream == null) { usStream = new USStream(); } if (blobStream == null) { blobStream = new BlobStream(); } if (guidStream == null) { guidStream = new GuidStream(); } } protected abstract void InitializeInternal(DataReaderFactory mdReaderFactory, uint metadataBaseOffset); public override RidList GetTypeDefRidList() { return RidList.Create(1u, tablesStream.TypeDefTable.Rows); } public override RidList GetExportedTypeRidList() { return RidList.Create(1u, tablesStream.ExportedTypeTable.Rows); } protected abstract uint BinarySearch(MDTable tableSource, int keyColIndex, uint key); protected RidList FindAllRows(MDTable tableSource, int keyColIndex, uint key) { uint num = BinarySearch(tableSource, keyColIndex, key); if (tableSource.IsInvalidRID(num)) { return RidList.Empty; } uint num2 = num + 1; ColumnInfo column = tableSource.TableInfo.Columns[keyColIndex]; uint value; while (num > 1 && tablesStream.TryReadColumn24(tableSource, num - 1, column, out value) && key == value) { num--; } uint value2; for (; num2 <= tableSource.Rows && tablesStream.TryReadColumn24(tableSource, num2, column, out value2); num2++) { if (key != value2) { break; } } return RidList.Create(num, num2 - num); } protected virtual RidList FindAllRowsUnsorted(MDTable tableSource, int keyColIndex, uint key) { return FindAllRows(tableSource, keyColIndex, key); } public override RidList GetInterfaceImplRidList(uint typeDefRid) { return FindAllRowsUnsorted(tablesStream.InterfaceImplTable, 0, typeDefRid); } public override RidList GetGenericParamRidList(Table table, uint rid) { if (!CodedToken.TypeOrMethodDef.Encode(new MDToken(table, rid), out var codedToken)) { return RidList.Empty; } return FindAllRowsUnsorted(tablesStream.GenericParamTable, 2, codedToken); } public override RidList GetGenericParamConstraintRidList(uint genericParamRid) { return FindAllRowsUnsorted(tablesStream.GenericParamConstraintTable, 0, genericParamRid); } public override RidList GetCustomAttributeRidList(Table table, uint rid) { if (!CodedToken.HasCustomAttribute.Encode(new MDToken(table, rid), out var codedToken)) { return RidList.Empty; } return FindAllRowsUnsorted(tablesStream.CustomAttributeTable, 0, codedToken); } public override RidList GetDeclSecurityRidList(Table table, uint rid) { if (!CodedToken.HasDeclSecurity.Encode(new MDToken(table, rid), out var codedToken)) { return RidList.Empty; } return FindAllRowsUnsorted(tablesStream.DeclSecurityTable, 1, codedToken); } public override RidList GetMethodSemanticsRidList(Table table, uint rid) { if (!CodedToken.HasSemantic.Encode(new MDToken(table, rid), out var codedToken)) { return RidList.Empty; } return FindAllRowsUnsorted(tablesStream.MethodSemanticsTable, 2, codedToken); } public override RidList GetMethodImplRidList(uint typeDefRid) { return FindAllRowsUnsorted(tablesStream.MethodImplTable, 0, typeDefRid); } public override uint GetClassLayoutRid(uint typeDefRid) { RidList ridList = FindAllRowsUnsorted(tablesStream.ClassLayoutTable, 2, typeDefRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetFieldLayoutRid(uint fieldRid) { RidList ridList = FindAllRowsUnsorted(tablesStream.FieldLayoutTable, 1, fieldRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetFieldMarshalRid(Table table, uint rid) { if (!CodedToken.HasFieldMarshal.Encode(new MDToken(table, rid), out var codedToken)) { return 0u; } RidList ridList = FindAllRowsUnsorted(tablesStream.FieldMarshalTable, 0, codedToken); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetFieldRVARid(uint fieldRid) { RidList ridList = FindAllRowsUnsorted(tablesStream.FieldRVATable, 1, fieldRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetImplMapRid(Table table, uint rid) { if (!CodedToken.MemberForwarded.Encode(new MDToken(table, rid), out var codedToken)) { return 0u; } RidList ridList = FindAllRowsUnsorted(tablesStream.ImplMapTable, 1, codedToken); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetNestedClassRid(uint typeDefRid) { RidList ridList = FindAllRowsUnsorted(tablesStream.NestedClassTable, 0, typeDefRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetEventMapRid(uint typeDefRid) { if (eventMapSortedTable == null) { Interlocked.CompareExchange(ref eventMapSortedTable, new SortedTable(tablesStream.EventMapTable, 0), null); } RidList ridList = eventMapSortedTable.FindAllRows(typeDefRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetPropertyMapRid(uint typeDefRid) { if (propertyMapSortedTable == null) { Interlocked.CompareExchange(ref propertyMapSortedTable, new SortedTable(tablesStream.PropertyMapTable, 0), null); } RidList ridList = propertyMapSortedTable.FindAllRows(typeDefRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetConstantRid(Table table, uint rid) { if (!CodedToken.HasConstant.Encode(new MDToken(table, rid), out var codedToken)) { return 0u; } RidList ridList = FindAllRowsUnsorted(tablesStream.ConstantTable, 2, codedToken); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override uint GetOwnerTypeOfField(uint fieldRid) { if (fieldRidToTypeDefRid == null) { InitializeInverseFieldOwnerRidList(); } uint num = fieldRid - 1; if (num >= fieldRidToTypeDefRid.LongLength) { return 0u; } return fieldRidToTypeDefRid[num]; } private void InitializeInverseFieldOwnerRidList() { if (fieldRidToTypeDefRid != null) { return; } uint[] array = new uint[tablesStream.FieldTable.Rows]; RidList typeDefRidList = GetTypeDefRidList(); for (int i = 0; i < typeDefRidList.Count; i++) { uint num = typeDefRidList[i]; RidList fieldRidList = GetFieldRidList(num); for (int j = 0; j < fieldRidList.Count; j++) { uint num2 = fieldRidList[j] - 1; if (array[num2] == 0) { array[num2] = num; } } } Interlocked.CompareExchange(ref fieldRidToTypeDefRid, array, null); } public override uint GetOwnerTypeOfMethod(uint methodRid) { if (methodRidToTypeDefRid == null) { InitializeInverseMethodOwnerRidList(); } uint num = methodRid - 1; if (num >= methodRidToTypeDefRid.LongLength) { return 0u; } return methodRidToTypeDefRid[num]; } private void InitializeInverseMethodOwnerRidList() { if (methodRidToTypeDefRid != null) { return; } uint[] array = new uint[tablesStream.MethodTable.Rows]; RidList typeDefRidList = GetTypeDefRidList(); for (int i = 0; i < typeDefRidList.Count; i++) { uint num = typeDefRidList[i]; RidList methodRidList = GetMethodRidList(num); for (int j = 0; j < methodRidList.Count; j++) { uint num2 = methodRidList[j] - 1; if (array[num2] == 0) { array[num2] = num; } } } Interlocked.CompareExchange(ref methodRidToTypeDefRid, array, null); } public override uint GetOwnerTypeOfEvent(uint eventRid) { if (eventRidToTypeDefRid == null) { InitializeInverseEventOwnerRidList(); } uint num = eventRid - 1; if (num >= eventRidToTypeDefRid.LongLength) { return 0u; } return eventRidToTypeDefRid[num]; } private void InitializeInverseEventOwnerRidList() { if (eventRidToTypeDefRid != null) { return; } uint[] array = new uint[tablesStream.EventTable.Rows]; RidList typeDefRidList = GetTypeDefRidList(); for (int i = 0; i < typeDefRidList.Count; i++) { uint num = typeDefRidList[i]; RidList eventRidList = GetEventRidList(GetEventMapRid(num)); for (int j = 0; j < eventRidList.Count; j++) { uint num2 = eventRidList[j] - 1; if (array[num2] == 0) { array[num2] = num; } } } Interlocked.CompareExchange(ref eventRidToTypeDefRid, array, null); } public override uint GetOwnerTypeOfProperty(uint propertyRid) { if (propertyRidToTypeDefRid == null) { InitializeInversePropertyOwnerRidList(); } uint num = propertyRid - 1; if (num >= propertyRidToTypeDefRid.LongLength) { return 0u; } return propertyRidToTypeDefRid[num]; } private void InitializeInversePropertyOwnerRidList() { if (propertyRidToTypeDefRid != null) { return; } uint[] array = new uint[tablesStream.PropertyTable.Rows]; RidList typeDefRidList = GetTypeDefRidList(); for (int i = 0; i < typeDefRidList.Count; i++) { uint num = typeDefRidList[i]; RidList propertyRidList = GetPropertyRidList(GetPropertyMapRid(num)); for (int j = 0; j < propertyRidList.Count; j++) { uint num2 = propertyRidList[j] - 1; if (array[num2] == 0) { array[num2] = num; } } } Interlocked.CompareExchange(ref propertyRidToTypeDefRid, array, null); } public override uint GetOwnerOfGenericParam(uint gpRid) { if (gpRidToOwnerRid == null) { InitializeInverseGenericParamOwnerRidList(); } uint num = gpRid - 1; if (num >= gpRidToOwnerRid.LongLength) { return 0u; } return gpRidToOwnerRid[num]; } private void InitializeInverseGenericParamOwnerRidList() { if (gpRidToOwnerRid != null) { return; } MDTable genericParamTable = tablesStream.GenericParamTable; uint[] array = new uint[genericParamTable.Rows]; ColumnInfo column = genericParamTable.TableInfo.Columns[2]; Dictionary dictionary = new Dictionary(); for (uint num = 1u; num <= genericParamTable.Rows; num++) { if (tablesStream.TryReadColumn24(genericParamTable, num, column, out var value)) { dictionary[value] = true; } } List list = new List(dictionary.Keys); list.Sort(); for (int i = 0; i < list.Count; i++) { if (!CodedToken.TypeOrMethodDef.Decode(list[i], out uint token)) { continue; } RidList genericParamRidList = GetGenericParamRidList(MDToken.ToTable(token), MDToken.ToRID(token)); for (int j = 0; j < genericParamRidList.Count; j++) { uint num2 = genericParamRidList[j] - 1; if (array[num2] == 0) { array[num2] = list[i]; } } } Interlocked.CompareExchange(ref gpRidToOwnerRid, array, null); } public override uint GetOwnerOfGenericParamConstraint(uint gpcRid) { if (gpcRidToOwnerRid == null) { InitializeInverseGenericParamConstraintOwnerRidList(); } uint num = gpcRid - 1; if (num >= gpcRidToOwnerRid.LongLength) { return 0u; } return gpcRidToOwnerRid[num]; } private void InitializeInverseGenericParamConstraintOwnerRidList() { if (gpcRidToOwnerRid != null) { return; } MDTable genericParamConstraintTable = tablesStream.GenericParamConstraintTable; uint[] array = new uint[genericParamConstraintTable.Rows]; ColumnInfo column = genericParamConstraintTable.TableInfo.Columns[0]; Dictionary dictionary = new Dictionary(); for (uint num = 1u; num <= genericParamConstraintTable.Rows; num++) { if (tablesStream.TryReadColumn24(genericParamConstraintTable, num, column, out var value)) { dictionary[value] = true; } } List list = new List(dictionary.Keys); list.Sort(); for (int i = 0; i < list.Count; i++) { uint num2 = list[i]; RidList genericParamConstraintRidList = GetGenericParamConstraintRidList(num2); for (int j = 0; j < genericParamConstraintRidList.Count; j++) { uint num3 = genericParamConstraintRidList[j] - 1; if (array[num3] == 0) { array[num3] = num2; } } } Interlocked.CompareExchange(ref gpcRidToOwnerRid, array, null); } public override uint GetOwnerOfParam(uint paramRid) { if (paramRidToOwnerRid == null) { InitializeInverseParamOwnerRidList(); } uint num = paramRid - 1; if (num >= paramRidToOwnerRid.LongLength) { return 0u; } return paramRidToOwnerRid[num]; } private void InitializeInverseParamOwnerRidList() { if (paramRidToOwnerRid != null) { return; } uint[] array = new uint[tablesStream.ParamTable.Rows]; MDTable methodTable = tablesStream.MethodTable; for (uint num = 1u; num <= methodTable.Rows; num++) { RidList paramRidList = GetParamRidList(num); for (int i = 0; i < paramRidList.Count; i++) { uint num2 = paramRidList[i] - 1; if (array[num2] == 0) { array[num2] = num; } } } Interlocked.CompareExchange(ref paramRidToOwnerRid, array, null); } public override RidList GetNestedClassRidList(uint typeDefRid) { if (typeDefRidToNestedClasses == null) { InitializeNestedClassesDictionary(); } if (typeDefRidToNestedClasses.TryGetValue(typeDefRid, out var value)) { return RidList.Create(value); } return RidList.Empty; } private void InitializeNestedClassesDictionary() { MDTable nestedClassTable = tablesStream.NestedClassTable; MDTable typeDefTable = tablesStream.TypeDefTable; Dictionary dictionary = null; RidList typeDefRidList = GetTypeDefRidList(); if (typeDefRidList.Count != (int)typeDefTable.Rows) { dictionary = new Dictionary(typeDefRidList.Count); for (int i = 0; i < typeDefRidList.Count; i++) { dictionary[typeDefRidList[i]] = true; } } Dictionary dictionary2 = new Dictionary((int)nestedClassTable.Rows); List list = new List((int)nestedClassTable.Rows); for (uint num = 1u; num <= nestedClassTable.Rows; num++) { if ((dictionary == null || dictionary.ContainsKey(num)) && tablesStream.TryReadNestedClassRow(num, out var row) && typeDefTable.IsValidRID(row.NestedClass) && typeDefTable.IsValidRID(row.EnclosingClass) && !dictionary2.ContainsKey(row.NestedClass)) { dictionary2[row.NestedClass] = true; list.Add(row.NestedClass); } } Dictionary> dictionary3 = new Dictionary>(); int count = list.Count; for (int j = 0; j < count; j++) { uint num2 = list[j]; if (tablesStream.TryReadNestedClassRow(GetNestedClassRid(num2), out var row2)) { if (!dictionary3.TryGetValue(row2.EnclosingClass, out var value)) { value = (dictionary3[row2.EnclosingClass] = new List()); } value.Add(num2); } } List list3 = new List((int)(typeDefTable.Rows - dictionary2.Count)); for (uint num3 = 1u; num3 <= typeDefTable.Rows; num3++) { if ((dictionary == null || dictionary.ContainsKey(num3)) && !dictionary2.ContainsKey(num3)) { list3.Add(num3); } } Interlocked.CompareExchange(ref nonNestedTypes, new StrongBox(RidList.Create(list3)), null); Interlocked.CompareExchange(ref typeDefRidToNestedClasses, dictionary3, null); } public override RidList GetNonNestedClassRidList() { if (typeDefRidToNestedClasses == null) { InitializeNestedClassesDictionary(); } return nonNestedTypes.Value; } public override RidList GetLocalScopeRidList(uint methodRid) { return FindAllRows(tablesStream.LocalScopeTable, 0, methodRid); } public override uint GetStateMachineMethodRid(uint methodRid) { RidList ridList = FindAllRows(tablesStream.StateMachineMethodTable, 0, methodRid); if (ridList.Count != 0) { return ridList[0]; } return 0u; } public override RidList GetCustomDebugInformationRidList(Table table, uint rid) { if (!CodedToken.HasCustomDebugInformation.Encode(new MDToken(table, rid), out var codedToken)) { return RidList.Empty; } return FindAllRows(tablesStream.CustomDebugInformationTable, 0, codedToken); } public override void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!disposing) { return; } peImage?.Dispose(); stringsStream?.Dispose(); usStream?.Dispose(); blobStream?.Dispose(); guidStream?.Dispose(); tablesStream?.Dispose(); IList list = allStreams; if (list != null) { foreach (DotNetStream item in list) { item?.Dispose(); } } mdReaderFactoryToDisposeLater?.Dispose(); peImage = null; cor20Header = null; mdHeader = null; stringsStream = null; usStream = null; blobStream = null; guidStream = null; tablesStream = null; allStreams = null; fieldRidToTypeDefRid = null; methodRidToTypeDefRid = null; typeDefRidToNestedClasses = null; mdReaderFactoryToDisposeLater = null; } } public static class MetadataFactory { private enum MetadataType { Unknown, Compressed, ENC } internal static MetadataBase Load(string fileName, CLRRuntimeReaderKind runtime) { IPEImage iPEImage = null; try { return Load(iPEImage = new PEImage(fileName), runtime); } catch { iPEImage?.Dispose(); throw; } } internal static MetadataBase Load(byte[] data, CLRRuntimeReaderKind runtime) { IPEImage iPEImage = null; try { return Load(iPEImage = new PEImage(data), runtime); } catch { iPEImage?.Dispose(); throw; } } internal static MetadataBase Load(IntPtr addr, CLRRuntimeReaderKind runtime) { IPEImage iPEImage = null; try { return Load(iPEImage = new PEImage(addr, ImageLayout.Memory, verify: true), runtime); } catch { iPEImage?.Dispose(); iPEImage = null; } try { return Load(iPEImage = new PEImage(addr, ImageLayout.File, verify: true), runtime); } catch { iPEImage?.Dispose(); throw; } } internal static MetadataBase Load(IntPtr addr, ImageLayout imageLayout, CLRRuntimeReaderKind runtime) { IPEImage iPEImage = null; try { return Load(iPEImage = new PEImage(addr, imageLayout, verify: true), runtime); } catch { iPEImage?.Dispose(); throw; } } internal static MetadataBase Load(IPEImage peImage, CLRRuntimeReaderKind runtime) { return Create(peImage, runtime, verify: true); } public static Metadata CreateMetadata(IPEImage peImage) { return CreateMetadata(peImage, CLRRuntimeReaderKind.CLR); } public static Metadata CreateMetadata(IPEImage peImage, CLRRuntimeReaderKind runtime) { return Create(peImage, runtime, verify: true); } public static Metadata CreateMetadata(IPEImage peImage, bool verify) { return CreateMetadata(peImage, CLRRuntimeReaderKind.CLR, verify); } public static Metadata CreateMetadata(IPEImage peImage, CLRRuntimeReaderKind runtime, bool verify) { return Create(peImage, runtime, verify); } private static MetadataBase Create(IPEImage peImage, CLRRuntimeReaderKind runtime, bool verify) { MetadataBase metadataBase = null; try { ImageDataDirectory imageDataDirectory = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14]; if (imageDataDirectory.VirtualAddress == (RVA)0u) { throw new BadImageFormatException(".NET data directory RVA is 0"); } DataReader reader = peImage.CreateReader(imageDataDirectory.VirtualAddress, 72u); ImageCor20Header imageCor20Header = new ImageCor20Header(ref reader, verify && runtime == CLRRuntimeReaderKind.CLR); if (imageCor20Header.Metadata.VirtualAddress == (RVA)0u) { throw new BadImageFormatException(".NET metadata RVA is 0"); } RVA virtualAddress = imageCor20Header.Metadata.VirtualAddress; DataReader reader2 = peImage.CreateReader(virtualAddress); MetadataHeader metadataHeader = new MetadataHeader(ref reader2, runtime, verify); if (verify) { foreach (StreamHeader streamHeader in metadataHeader.StreamHeaders) { if ((ulong)((long)streamHeader.Offset + (long)streamHeader.StreamSize) > (ulong)reader2.EndOffset) { throw new BadImageFormatException("Invalid stream header"); } } } metadataBase = GetMetadataType(metadataHeader.StreamHeaders, runtime) switch { MetadataType.Compressed => new CompressedMetadata(peImage, imageCor20Header, metadataHeader, runtime), MetadataType.ENC => new ENCMetadata(peImage, imageCor20Header, metadataHeader, runtime), _ => throw new BadImageFormatException("No #~ or #- stream found"), }; metadataBase.Initialize(null); return metadataBase; } catch { metadataBase?.Dispose(); throw; } } internal static MetadataBase CreateStandalonePortablePDB(DataReaderFactory mdReaderFactory, bool verify) { MetadataBase metadataBase = null; try { DataReader reader = mdReaderFactory.CreateReader(); MetadataHeader metadataHeader = new MetadataHeader(ref reader, CLRRuntimeReaderKind.CLR, verify); if (verify) { foreach (StreamHeader streamHeader in metadataHeader.StreamHeaders) { if (streamHeader.Offset + streamHeader.StreamSize < streamHeader.Offset || streamHeader.Offset + streamHeader.StreamSize > reader.Length) { throw new BadImageFormatException("Invalid stream header"); } } } metadataBase = GetMetadataType(metadataHeader.StreamHeaders, CLRRuntimeReaderKind.CLR) switch { MetadataType.Compressed => new CompressedMetadata(metadataHeader, isStandalonePortablePdb: true, CLRRuntimeReaderKind.CLR), MetadataType.ENC => new ENCMetadata(metadataHeader, isStandalonePortablePdb: true, CLRRuntimeReaderKind.CLR), _ => throw new BadImageFormatException("No #~ or #- stream found"), }; metadataBase.Initialize(mdReaderFactory); return metadataBase; } catch { metadataBase?.Dispose(); throw; } } private static MetadataType GetMetadataType(IList streamHeaders, CLRRuntimeReaderKind runtime) { MetadataType? metadataType = null; switch (runtime) { case CLRRuntimeReaderKind.CLR: foreach (StreamHeader streamHeader in streamHeaders) { if (!metadataType.HasValue) { if (streamHeader.Name == "#~") { metadataType = MetadataType.Compressed; } else if (streamHeader.Name == "#-") { metadataType = MetadataType.ENC; } } if (streamHeader.Name == "#Schema") { metadataType = MetadataType.ENC; } } break; case CLRRuntimeReaderKind.Mono: foreach (StreamHeader streamHeader2 in streamHeaders) { if (streamHeader2.Name == "#~") { metadataType = MetadataType.Compressed; } else if (streamHeader2.Name == "#-") { metadataType = MetadataType.ENC; break; } } break; default: throw new ArgumentOutOfRangeException("runtime"); } if (!metadataType.HasValue) { return MetadataType.Unknown; } return metadataType.Value; } } public sealed class MetadataHeader : FileSection { private readonly uint signature; private readonly ushort majorVersion; private readonly ushort minorVersion; private readonly uint reserved1; private readonly uint stringLength; private readonly string versionString; private readonly FileOffset offset2ndPart; private readonly StorageFlags flags; private readonly byte reserved2; private readonly ushort streams; private readonly IList streamHeaders; public uint Signature => signature; public ushort MajorVersion => majorVersion; public ushort MinorVersion => minorVersion; public uint Reserved1 => reserved1; public uint StringLength => stringLength; public string VersionString => versionString; public FileOffset StorageHeaderOffset => offset2ndPart; public StorageFlags Flags => flags; public byte Reserved2 => reserved2; public ushort Streams => streams; public IList StreamHeaders => streamHeaders; public MetadataHeader(ref DataReader reader, bool verify) : this(ref reader, CLRRuntimeReaderKind.CLR, verify) { } public MetadataHeader(ref DataReader reader, CLRRuntimeReaderKind runtime, bool verify) { SetStartOffset(ref reader); signature = reader.ReadUInt32(); if (verify && signature != 1112167234) { throw new BadImageFormatException("Invalid metadata header signature"); } majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); reserved1 = reader.ReadUInt32(); stringLength = reader.ReadUInt32(); versionString = ReadString(ref reader, stringLength, runtime); offset2ndPart = (FileOffset)reader.CurrentOffset; flags = (StorageFlags)reader.ReadByte(); reserved2 = reader.ReadByte(); streams = reader.ReadUInt16(); streamHeaders = new StreamHeader[streams]; for (int i = 0; i < streamHeaders.Count; i++) { bool failedVerification; StreamHeader streamHeader = new StreamHeader(ref reader, throwOnError: false, verify, runtime, out failedVerification); if (failedVerification || (ulong)((long)streamHeader.Offset + (long)streamHeader.StreamSize) > (ulong)reader.EndOffset) { streamHeader = new StreamHeader(0u, 0u, ""); } streamHeaders[i] = streamHeader; } SetEndoffset(ref reader); } private static string ReadString(ref DataReader reader, uint maxLength, CLRRuntimeReaderKind runtime) { ulong num = (ulong)reader.CurrentOffset + (ulong)maxLength; if (runtime == CLRRuntimeReaderKind.Mono) { num = (num + 3) / 4 * 4; } if (num > reader.EndOffset) { throw new BadImageFormatException("Invalid MD version string"); } byte[] array = new byte[maxLength]; uint num2; for (num2 = 0u; num2 < maxLength; num2++) { byte b = reader.ReadByte(); if (b == 0) { break; } array[num2] = b; } reader.CurrentOffset = (uint)num; return Encoding.UTF8.GetString(array, 0, (int)num2); } } public sealed class PdbStream : HeapStream { public byte[] Id { get; private set; } public MDToken EntryPoint { get; private set; } public ulong ReferencedTypeSystemTables { get; private set; } public uint[] TypeSystemTableRows { get; private set; } public PdbStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { DataReader dataReader = CreateReader(); Id = dataReader.ReadBytes(20); EntryPoint = new MDToken(dataReader.ReadUInt32()); ulong num = (ReferencedTypeSystemTables = dataReader.ReadUInt64()); uint[] array = new uint[64]; int num3 = 0; while (num3 < array.Length) { if (((int)num & 1) != 0) { array[num3] = dataReader.ReadUInt32(); } num3++; num >>= 1; } TypeSystemTableRows = array; } } public sealed class RawRowEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { public static readonly RawRowEqualityComparer Instance = new RawRowEqualityComparer(); private static int rol(uint val, int shift) { return (int)((val << shift) | (val >> 32 - shift)); } public bool Equals(RawModuleRow x, RawModuleRow y) { if (x.Generation == y.Generation && x.Name == y.Name && x.Mvid == y.Mvid && x.EncId == y.EncId) { return x.EncBaseId == y.EncBaseId; } return false; } public int GetHashCode(RawModuleRow obj) { return obj.Generation + rol(obj.Name, 3) + rol(obj.Mvid, 7) + rol(obj.EncId, 11) + rol(obj.EncBaseId, 15); } public bool Equals(RawTypeRefRow x, RawTypeRefRow y) { if (x.ResolutionScope == y.ResolutionScope && x.Name == y.Name) { return x.Namespace == y.Namespace; } return false; } public int GetHashCode(RawTypeRefRow obj) { return (int)obj.ResolutionScope + rol(obj.Name, 3) + rol(obj.Namespace, 7); } public bool Equals(RawTypeDefRow x, RawTypeDefRow y) { if (x.Flags == y.Flags && x.Name == y.Name && x.Namespace == y.Namespace && x.Extends == y.Extends && x.FieldList == y.FieldList) { return x.MethodList == y.MethodList; } return false; } public int GetHashCode(RawTypeDefRow obj) { return (int)obj.Flags + rol(obj.Name, 3) + rol(obj.Namespace, 7) + rol(obj.Extends, 11) + rol(obj.FieldList, 15) + rol(obj.MethodList, 19); } public bool Equals(RawFieldPtrRow x, RawFieldPtrRow y) { return x.Field == y.Field; } public int GetHashCode(RawFieldPtrRow obj) { return (int)obj.Field; } public bool Equals(RawFieldRow x, RawFieldRow y) { if (x.Flags == y.Flags && x.Name == y.Name) { return x.Signature == y.Signature; } return false; } public int GetHashCode(RawFieldRow obj) { return obj.Flags + rol(obj.Name, 3) + rol(obj.Signature, 7); } public bool Equals(RawMethodPtrRow x, RawMethodPtrRow y) { return x.Method == y.Method; } public int GetHashCode(RawMethodPtrRow obj) { return (int)obj.Method; } public bool Equals(RawMethodRow x, RawMethodRow y) { if (x.RVA == y.RVA && x.ImplFlags == y.ImplFlags && x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature) { return x.ParamList == y.ParamList; } return false; } public int GetHashCode(RawMethodRow obj) { return (int)obj.RVA + rol(obj.ImplFlags, 3) + rol(obj.Flags, 7) + rol(obj.Name, 11) + rol(obj.Signature, 15) + rol(obj.ParamList, 19); } public bool Equals(RawParamPtrRow x, RawParamPtrRow y) { return x.Param == y.Param; } public int GetHashCode(RawParamPtrRow obj) { return (int)obj.Param; } public bool Equals(RawParamRow x, RawParamRow y) { if (x.Flags == y.Flags && x.Sequence == y.Sequence) { return x.Name == y.Name; } return false; } public int GetHashCode(RawParamRow obj) { return obj.Flags + rol(obj.Sequence, 3) + rol(obj.Name, 7); } public bool Equals(RawInterfaceImplRow x, RawInterfaceImplRow y) { if (x.Class == y.Class) { return x.Interface == y.Interface; } return false; } public int GetHashCode(RawInterfaceImplRow obj) { return (int)obj.Class + rol(obj.Interface, 3); } public bool Equals(RawMemberRefRow x, RawMemberRefRow y) { if (x.Class == y.Class && x.Name == y.Name) { return x.Signature == y.Signature; } return false; } public int GetHashCode(RawMemberRefRow obj) { return (int)obj.Class + rol(obj.Name, 3) + rol(obj.Signature, 7); } public bool Equals(RawConstantRow x, RawConstantRow y) { if (x.Type == y.Type && x.Padding == y.Padding && x.Parent == y.Parent) { return x.Value == y.Value; } return false; } public int GetHashCode(RawConstantRow obj) { return obj.Type + rol(obj.Padding, 3) + rol(obj.Parent, 7) + rol(obj.Value, 11); } public bool Equals(RawCustomAttributeRow x, RawCustomAttributeRow y) { if (x.Parent == y.Parent && x.Type == y.Type) { return x.Value == y.Value; } return false; } public int GetHashCode(RawCustomAttributeRow obj) { return (int)obj.Parent + rol(obj.Type, 3) + rol(obj.Value, 7); } public bool Equals(RawFieldMarshalRow x, RawFieldMarshalRow y) { if (x.Parent == y.Parent) { return x.NativeType == y.NativeType; } return false; } public int GetHashCode(RawFieldMarshalRow obj) { return (int)obj.Parent + rol(obj.NativeType, 3); } public bool Equals(RawDeclSecurityRow x, RawDeclSecurityRow y) { if (x.Action == y.Action && x.Parent == y.Parent) { return x.PermissionSet == y.PermissionSet; } return false; } public int GetHashCode(RawDeclSecurityRow obj) { return obj.Action + rol(obj.Parent, 3) + rol(obj.PermissionSet, 7); } public bool Equals(RawClassLayoutRow x, RawClassLayoutRow y) { if (x.PackingSize == y.PackingSize && x.ClassSize == y.ClassSize) { return x.Parent == y.Parent; } return false; } public int GetHashCode(RawClassLayoutRow obj) { return obj.PackingSize + rol(obj.ClassSize, 3) + rol(obj.Parent, 7); } public bool Equals(RawFieldLayoutRow x, RawFieldLayoutRow y) { if (x.OffSet == y.OffSet) { return x.Field == y.Field; } return false; } public int GetHashCode(RawFieldLayoutRow obj) { return (int)obj.OffSet + rol(obj.Field, 3); } public bool Equals(RawStandAloneSigRow x, RawStandAloneSigRow y) { return x.Signature == y.Signature; } public int GetHashCode(RawStandAloneSigRow obj) { return (int)obj.Signature; } public bool Equals(RawEventMapRow x, RawEventMapRow y) { if (x.Parent == y.Parent) { return x.EventList == y.EventList; } return false; } public int GetHashCode(RawEventMapRow obj) { return (int)obj.Parent + rol(obj.EventList, 3); } public bool Equals(RawEventPtrRow x, RawEventPtrRow y) { return x.Event == y.Event; } public int GetHashCode(RawEventPtrRow obj) { return (int)obj.Event; } public bool Equals(RawEventRow x, RawEventRow y) { if (x.EventFlags == y.EventFlags && x.Name == y.Name) { return x.EventType == y.EventType; } return false; } public int GetHashCode(RawEventRow obj) { return obj.EventFlags + rol(obj.Name, 3) + rol(obj.EventType, 7); } public bool Equals(RawPropertyMapRow x, RawPropertyMapRow y) { if (x.Parent == y.Parent) { return x.PropertyList == y.PropertyList; } return false; } public int GetHashCode(RawPropertyMapRow obj) { return (int)obj.Parent + rol(obj.PropertyList, 3); } public bool Equals(RawPropertyPtrRow x, RawPropertyPtrRow y) { return x.Property == y.Property; } public int GetHashCode(RawPropertyPtrRow obj) { return (int)obj.Property; } public bool Equals(RawPropertyRow x, RawPropertyRow y) { if (x.PropFlags == y.PropFlags && x.Name == y.Name) { return x.Type == y.Type; } return false; } public int GetHashCode(RawPropertyRow obj) { return obj.PropFlags + rol(obj.Name, 3) + rol(obj.Type, 7); } public bool Equals(RawMethodSemanticsRow x, RawMethodSemanticsRow y) { if (x.Semantic == y.Semantic && x.Method == y.Method) { return x.Association == y.Association; } return false; } public int GetHashCode(RawMethodSemanticsRow obj) { return obj.Semantic + rol(obj.Method, 3) + rol(obj.Association, 7); } public bool Equals(RawMethodImplRow x, RawMethodImplRow y) { if (x.Class == y.Class && x.MethodBody == y.MethodBody) { return x.MethodDeclaration == y.MethodDeclaration; } return false; } public int GetHashCode(RawMethodImplRow obj) { return (int)obj.Class + rol(obj.MethodBody, 3) + rol(obj.MethodDeclaration, 7); } public bool Equals(RawModuleRefRow x, RawModuleRefRow y) { return x.Name == y.Name; } public int GetHashCode(RawModuleRefRow obj) { return (int)obj.Name; } public bool Equals(RawTypeSpecRow x, RawTypeSpecRow y) { return x.Signature == y.Signature; } public int GetHashCode(RawTypeSpecRow obj) { return (int)obj.Signature; } public bool Equals(RawImplMapRow x, RawImplMapRow y) { if (x.MappingFlags == y.MappingFlags && x.MemberForwarded == y.MemberForwarded && x.ImportName == y.ImportName) { return x.ImportScope == y.ImportScope; } return false; } public int GetHashCode(RawImplMapRow obj) { return obj.MappingFlags + rol(obj.MemberForwarded, 3) + rol(obj.ImportName, 7) + rol(obj.ImportScope, 11); } public bool Equals(RawFieldRVARow x, RawFieldRVARow y) { if (x.RVA == y.RVA) { return x.Field == y.Field; } return false; } public int GetHashCode(RawFieldRVARow obj) { return (int)obj.RVA + rol(obj.Field, 3); } public bool Equals(RawENCLogRow x, RawENCLogRow y) { if (x.Token == y.Token) { return x.FuncCode == y.FuncCode; } return false; } public int GetHashCode(RawENCLogRow obj) { return (int)obj.Token + rol(obj.FuncCode, 3); } public bool Equals(RawENCMapRow x, RawENCMapRow y) { return x.Token == y.Token; } public int GetHashCode(RawENCMapRow obj) { return (int)obj.Token; } public bool Equals(RawAssemblyRow x, RawAssemblyRow y) { if (x.HashAlgId == y.HashAlgId && x.MajorVersion == y.MajorVersion && x.MinorVersion == y.MinorVersion && x.BuildNumber == y.BuildNumber && x.RevisionNumber == y.RevisionNumber && x.Flags == y.Flags && x.PublicKey == y.PublicKey && x.Name == y.Name) { return x.Locale == y.Locale; } return false; } public int GetHashCode(RawAssemblyRow obj) { return (int)obj.HashAlgId + rol(obj.MajorVersion, 3) + rol(obj.MinorVersion, 7) + rol(obj.BuildNumber, 11) + rol(obj.RevisionNumber, 15) + rol(obj.Flags, 19) + rol(obj.PublicKey, 23) + rol(obj.Name, 27) + rol(obj.Locale, 31); } public bool Equals(RawAssemblyProcessorRow x, RawAssemblyProcessorRow y) { return x.Processor == y.Processor; } public int GetHashCode(RawAssemblyProcessorRow obj) { return (int)obj.Processor; } public bool Equals(RawAssemblyOSRow x, RawAssemblyOSRow y) { if (x.OSPlatformId == y.OSPlatformId && x.OSMajorVersion == y.OSMajorVersion) { return x.OSMinorVersion == y.OSMinorVersion; } return false; } public int GetHashCode(RawAssemblyOSRow obj) { return (int)obj.OSPlatformId + rol(obj.OSMajorVersion, 3) + rol(obj.OSMinorVersion, 7); } public bool Equals(RawAssemblyRefRow x, RawAssemblyRefRow y) { if (x.MajorVersion == y.MajorVersion && x.MinorVersion == y.MinorVersion && x.BuildNumber == y.BuildNumber && x.RevisionNumber == y.RevisionNumber && x.Flags == y.Flags && x.PublicKeyOrToken == y.PublicKeyOrToken && x.Name == y.Name && x.Locale == y.Locale) { return x.HashValue == y.HashValue; } return false; } public int GetHashCode(RawAssemblyRefRow obj) { return obj.MajorVersion + rol(obj.MinorVersion, 3) + rol(obj.BuildNumber, 7) + rol(obj.RevisionNumber, 11) + rol(obj.Flags, 15) + rol(obj.PublicKeyOrToken, 19) + rol(obj.Name, 23) + rol(obj.Locale, 27) + rol(obj.HashValue, 31); } public bool Equals(RawAssemblyRefProcessorRow x, RawAssemblyRefProcessorRow y) { if (x.Processor == y.Processor) { return x.AssemblyRef == y.AssemblyRef; } return false; } public int GetHashCode(RawAssemblyRefProcessorRow obj) { return (int)obj.Processor + rol(obj.AssemblyRef, 3); } public bool Equals(RawAssemblyRefOSRow x, RawAssemblyRefOSRow y) { if (x.OSPlatformId == y.OSPlatformId && x.OSMajorVersion == y.OSMajorVersion && x.OSMinorVersion == y.OSMinorVersion) { return x.AssemblyRef == y.AssemblyRef; } return false; } public int GetHashCode(RawAssemblyRefOSRow obj) { return (int)obj.OSPlatformId + rol(obj.OSMajorVersion, 3) + rol(obj.OSMinorVersion, 7) + rol(obj.AssemblyRef, 11); } public bool Equals(RawFileRow x, RawFileRow y) { if (x.Flags == y.Flags && x.Name == y.Name) { return x.HashValue == y.HashValue; } return false; } public int GetHashCode(RawFileRow obj) { return (int)obj.Flags + rol(obj.Name, 3) + rol(obj.HashValue, 7); } public bool Equals(RawExportedTypeRow x, RawExportedTypeRow y) { if (x.Flags == y.Flags && x.TypeDefId == y.TypeDefId && x.TypeName == y.TypeName && x.TypeNamespace == y.TypeNamespace) { return x.Implementation == y.Implementation; } return false; } public int GetHashCode(RawExportedTypeRow obj) { return (int)obj.Flags + rol(obj.TypeDefId, 3) + rol(obj.TypeName, 7) + rol(obj.TypeNamespace, 11) + rol(obj.Implementation, 15); } public bool Equals(RawManifestResourceRow x, RawManifestResourceRow y) { if (x.Offset == y.Offset && x.Flags == y.Flags && x.Name == y.Name) { return x.Implementation == y.Implementation; } return false; } public int GetHashCode(RawManifestResourceRow obj) { return (int)obj.Offset + rol(obj.Flags, 3) + rol(obj.Name, 7) + rol(obj.Implementation, 11); } public bool Equals(RawNestedClassRow x, RawNestedClassRow y) { if (x.NestedClass == y.NestedClass) { return x.EnclosingClass == y.EnclosingClass; } return false; } public int GetHashCode(RawNestedClassRow obj) { return (int)obj.NestedClass + rol(obj.EnclosingClass, 3); } public bool Equals(RawGenericParamRow x, RawGenericParamRow y) { if (x.Number == y.Number && x.Flags == y.Flags && x.Owner == y.Owner && x.Name == y.Name) { return x.Kind == y.Kind; } return false; } public int GetHashCode(RawGenericParamRow obj) { return obj.Number + rol(obj.Flags, 3) + rol(obj.Owner, 7) + rol(obj.Name, 11) + rol(obj.Kind, 15); } public bool Equals(RawMethodSpecRow x, RawMethodSpecRow y) { if (x.Method == y.Method) { return x.Instantiation == y.Instantiation; } return false; } public int GetHashCode(RawMethodSpecRow obj) { return (int)obj.Method + rol(obj.Instantiation, 3); } public bool Equals(RawGenericParamConstraintRow x, RawGenericParamConstraintRow y) { if (x.Owner == y.Owner) { return x.Constraint == y.Constraint; } return false; } public int GetHashCode(RawGenericParamConstraintRow obj) { return (int)obj.Owner + rol(obj.Constraint, 3); } public bool Equals(RawDocumentRow x, RawDocumentRow y) { if (x.Name == y.Name && x.HashAlgorithm == y.HashAlgorithm && x.Hash == y.Hash) { return x.Language == y.Language; } return false; } public int GetHashCode(RawDocumentRow obj) { return (int)obj.Name + rol(obj.HashAlgorithm, 3) + rol(obj.Hash, 7) + rol(obj.Language, 11); } public bool Equals(RawMethodDebugInformationRow x, RawMethodDebugInformationRow y) { if (x.Document == y.Document) { return x.SequencePoints == y.SequencePoints; } return false; } public int GetHashCode(RawMethodDebugInformationRow obj) { return (int)obj.Document + rol(obj.SequencePoints, 3); } public bool Equals(RawLocalScopeRow x, RawLocalScopeRow y) { if (x.Method == y.Method && x.ImportScope == y.ImportScope && x.VariableList == y.VariableList && x.ConstantList == y.ConstantList && x.StartOffset == y.StartOffset) { return x.Length == y.Length; } return false; } public int GetHashCode(RawLocalScopeRow obj) { return (int)obj.Method + rol(obj.ImportScope, 3) + rol(obj.VariableList, 7) + rol(obj.ConstantList, 11) + rol(obj.StartOffset, 15) + rol(obj.Length, 19); } public bool Equals(RawLocalVariableRow x, RawLocalVariableRow y) { if (x.Attributes == y.Attributes && x.Index == y.Index) { return x.Name == y.Name; } return false; } public int GetHashCode(RawLocalVariableRow obj) { return obj.Attributes + rol(obj.Index, 3) + rol(obj.Name, 7); } public bool Equals(RawLocalConstantRow x, RawLocalConstantRow y) { if (x.Name == y.Name) { return x.Signature == y.Signature; } return false; } public int GetHashCode(RawLocalConstantRow obj) { return (int)obj.Name + rol(obj.Signature, 3); } public bool Equals(RawImportScopeRow x, RawImportScopeRow y) { if (x.Parent == y.Parent) { return x.Imports == y.Imports; } return false; } public int GetHashCode(RawImportScopeRow obj) { return (int)obj.Parent + rol(obj.Imports, 3); } public bool Equals(RawStateMachineMethodRow x, RawStateMachineMethodRow y) { if (x.MoveNextMethod == y.MoveNextMethod) { return x.KickoffMethod == y.KickoffMethod; } return false; } public int GetHashCode(RawStateMachineMethodRow obj) { return (int)obj.MoveNextMethod + rol(obj.KickoffMethod, 3); } public bool Equals(RawCustomDebugInformationRow x, RawCustomDebugInformationRow y) { if (x.Parent == y.Parent && x.Kind == y.Kind) { return x.Value == y.Value; } return false; } public int GetHashCode(RawCustomDebugInformationRow obj) { return (int)obj.Parent + rol(obj.Kind, 3) + rol(obj.Value, 7); } } public readonly struct RawModuleRow { public readonly ushort Generation; public readonly uint Name; public readonly uint Mvid; public readonly uint EncId; public readonly uint EncBaseId; public uint this[int index] => index switch { 0 => Generation, 1 => Name, 2 => Mvid, 3 => EncId, 4 => EncBaseId, _ => 0u, }; public RawModuleRow(ushort Generation, uint Name, uint Mvid, uint EncId, uint EncBaseId) { this.Generation = Generation; this.Name = Name; this.Mvid = Mvid; this.EncId = EncId; this.EncBaseId = EncBaseId; } } public readonly struct RawTypeRefRow { public readonly uint ResolutionScope; public readonly uint Name; public readonly uint Namespace; public uint this[int index] => index switch { 0 => ResolutionScope, 1 => Name, 2 => Namespace, _ => 0u, }; public RawTypeRefRow(uint ResolutionScope, uint Name, uint Namespace) { this.ResolutionScope = ResolutionScope; this.Name = Name; this.Namespace = Namespace; } } public readonly struct RawTypeDefRow { public readonly uint Flags; public readonly uint Name; public readonly uint Namespace; public readonly uint Extends; public readonly uint FieldList; public readonly uint MethodList; public uint this[int index] => index switch { 0 => Flags, 1 => Name, 2 => Namespace, 3 => Extends, 4 => FieldList, 5 => MethodList, _ => 0u, }; public RawTypeDefRow(uint Flags, uint Name, uint Namespace, uint Extends, uint FieldList, uint MethodList) { this.Flags = Flags; this.Name = Name; this.Namespace = Namespace; this.Extends = Extends; this.FieldList = FieldList; this.MethodList = MethodList; } } public readonly struct RawFieldPtrRow { public readonly uint Field; public uint this[int index] { get { if (index == 0) { return Field; } return 0u; } } public RawFieldPtrRow(uint Field) { this.Field = Field; } } public readonly struct RawFieldRow { public readonly ushort Flags; public readonly uint Name; public readonly uint Signature; public uint this[int index] => index switch { 0 => Flags, 1 => Name, 2 => Signature, _ => 0u, }; public RawFieldRow(ushort Flags, uint Name, uint Signature) { this.Flags = Flags; this.Name = Name; this.Signature = Signature; } } public readonly struct RawMethodPtrRow { public readonly uint Method; public uint this[int index] { get { if (index == 0) { return Method; } return 0u; } } public RawMethodPtrRow(uint Method) { this.Method = Method; } } public readonly struct RawMethodRow { public readonly uint RVA; public readonly ushort ImplFlags; public readonly ushort Flags; public readonly uint Name; public readonly uint Signature; public readonly uint ParamList; public uint this[int index] => index switch { 0 => RVA, 1 => ImplFlags, 2 => Flags, 3 => Name, 4 => Signature, 5 => ParamList, _ => 0u, }; public RawMethodRow(uint RVA, ushort ImplFlags, ushort Flags, uint Name, uint Signature, uint ParamList) { this.RVA = RVA; this.ImplFlags = ImplFlags; this.Flags = Flags; this.Name = Name; this.Signature = Signature; this.ParamList = ParamList; } } public readonly struct RawParamPtrRow { public readonly uint Param; public uint this[int index] { get { if (index == 0) { return Param; } return 0u; } } public RawParamPtrRow(uint Param) { this.Param = Param; } } public readonly struct RawParamRow { public readonly ushort Flags; public readonly ushort Sequence; public readonly uint Name; public uint this[int index] => index switch { 0 => Flags, 1 => Sequence, 2 => Name, _ => 0u, }; public RawParamRow(ushort Flags, ushort Sequence, uint Name) { this.Flags = Flags; this.Sequence = Sequence; this.Name = Name; } } public readonly struct RawInterfaceImplRow { public readonly uint Class; public readonly uint Interface; public uint this[int index] => index switch { 0 => Class, 1 => Interface, _ => 0u, }; public RawInterfaceImplRow(uint Class, uint Interface) { this.Class = Class; this.Interface = Interface; } } public readonly struct RawMemberRefRow { public readonly uint Class; public readonly uint Name; public readonly uint Signature; public uint this[int index] => index switch { 0 => Class, 1 => Name, 2 => Signature, _ => 0u, }; public RawMemberRefRow(uint Class, uint Name, uint Signature) { this.Class = Class; this.Name = Name; this.Signature = Signature; } } public readonly struct RawConstantRow { public readonly byte Type; public readonly byte Padding; public readonly uint Parent; public readonly uint Value; public uint this[int index] => index switch { 0 => Type, 1 => Padding, 2 => Parent, 3 => Value, _ => 0u, }; public RawConstantRow(byte Type, byte Padding, uint Parent, uint Value) { this.Type = Type; this.Padding = Padding; this.Parent = Parent; this.Value = Value; } } public readonly struct RawCustomAttributeRow { public readonly uint Parent; public readonly uint Type; public readonly uint Value; public uint this[int index] => index switch { 0 => Parent, 1 => Type, 2 => Value, _ => 0u, }; public RawCustomAttributeRow(uint Parent, uint Type, uint Value) { this.Parent = Parent; this.Type = Type; this.Value = Value; } } public readonly struct RawFieldMarshalRow { public readonly uint Parent; public readonly uint NativeType; public uint this[int index] => index switch { 0 => Parent, 1 => NativeType, _ => 0u, }; public RawFieldMarshalRow(uint Parent, uint NativeType) { this.Parent = Parent; this.NativeType = NativeType; } } public readonly struct RawDeclSecurityRow { public readonly short Action; public readonly uint Parent; public readonly uint PermissionSet; public uint this[int index] => index switch { 0 => (uint)Action, 1 => Parent, 2 => PermissionSet, _ => 0u, }; public RawDeclSecurityRow(short Action, uint Parent, uint PermissionSet) { this.Action = Action; this.Parent = Parent; this.PermissionSet = PermissionSet; } } public readonly struct RawClassLayoutRow { public readonly ushort PackingSize; public readonly uint ClassSize; public readonly uint Parent; public uint this[int index] => index switch { 0 => PackingSize, 1 => ClassSize, 2 => Parent, _ => 0u, }; public RawClassLayoutRow(ushort PackingSize, uint ClassSize, uint Parent) { this.PackingSize = PackingSize; this.ClassSize = ClassSize; this.Parent = Parent; } } public readonly struct RawFieldLayoutRow { public readonly uint OffSet; public readonly uint Field; public uint this[int index] => index switch { 0 => OffSet, 1 => Field, _ => 0u, }; public RawFieldLayoutRow(uint OffSet, uint Field) { this.OffSet = OffSet; this.Field = Field; } } public readonly struct RawStandAloneSigRow { public readonly uint Signature; public uint this[int index] { get { if (index == 0) { return Signature; } return 0u; } } public RawStandAloneSigRow(uint Signature) { this.Signature = Signature; } } public readonly struct RawEventMapRow { public readonly uint Parent; public readonly uint EventList; public uint this[int index] => index switch { 0 => Parent, 1 => EventList, _ => 0u, }; public RawEventMapRow(uint Parent, uint EventList) { this.Parent = Parent; this.EventList = EventList; } } public readonly struct RawEventPtrRow { public readonly uint Event; public uint this[int index] { get { if (index == 0) { return Event; } return 0u; } } public RawEventPtrRow(uint Event) { this.Event = Event; } } public readonly struct RawEventRow { public readonly ushort EventFlags; public readonly uint Name; public readonly uint EventType; public uint this[int index] => index switch { 0 => EventFlags, 1 => Name, 2 => EventType, _ => 0u, }; public RawEventRow(ushort EventFlags, uint Name, uint EventType) { this.EventFlags = EventFlags; this.Name = Name; this.EventType = EventType; } } public readonly struct RawPropertyMapRow { public readonly uint Parent; public readonly uint PropertyList; public uint this[int index] => index switch { 0 => Parent, 1 => PropertyList, _ => 0u, }; public RawPropertyMapRow(uint Parent, uint PropertyList) { this.Parent = Parent; this.PropertyList = PropertyList; } } public readonly struct RawPropertyPtrRow { public readonly uint Property; public uint this[int index] { get { if (index == 0) { return Property; } return 0u; } } public RawPropertyPtrRow(uint Property) { this.Property = Property; } } public readonly struct RawPropertyRow { public readonly ushort PropFlags; public readonly uint Name; public readonly uint Type; public uint this[int index] => index switch { 0 => PropFlags, 1 => Name, 2 => Type, _ => 0u, }; public RawPropertyRow(ushort PropFlags, uint Name, uint Type) { this.PropFlags = PropFlags; this.Name = Name; this.Type = Type; } } public readonly struct RawMethodSemanticsRow { public readonly ushort Semantic; public readonly uint Method; public readonly uint Association; public uint this[int index] => index switch { 0 => Semantic, 1 => Method, 2 => Association, _ => 0u, }; public RawMethodSemanticsRow(ushort Semantic, uint Method, uint Association) { this.Semantic = Semantic; this.Method = Method; this.Association = Association; } } public readonly struct RawMethodImplRow { public readonly uint Class; public readonly uint MethodBody; public readonly uint MethodDeclaration; public uint this[int index] => index switch { 0 => Class, 1 => MethodBody, 2 => MethodDeclaration, _ => 0u, }; public RawMethodImplRow(uint Class, uint MethodBody, uint MethodDeclaration) { this.Class = Class; this.MethodBody = MethodBody; this.MethodDeclaration = MethodDeclaration; } } public readonly struct RawModuleRefRow { public readonly uint Name; public uint this[int index] { get { if (index == 0) { return Name; } return 0u; } } public RawModuleRefRow(uint Name) { this.Name = Name; } } public readonly struct RawTypeSpecRow { public readonly uint Signature; public uint this[int index] { get { if (index == 0) { return Signature; } return 0u; } } public RawTypeSpecRow(uint Signature) { this.Signature = Signature; } } public readonly struct RawImplMapRow { public readonly ushort MappingFlags; public readonly uint MemberForwarded; public readonly uint ImportName; public readonly uint ImportScope; public uint this[int index] => index switch { 0 => MappingFlags, 1 => MemberForwarded, 2 => ImportName, 3 => ImportScope, _ => 0u, }; public RawImplMapRow(ushort MappingFlags, uint MemberForwarded, uint ImportName, uint ImportScope) { this.MappingFlags = MappingFlags; this.MemberForwarded = MemberForwarded; this.ImportName = ImportName; this.ImportScope = ImportScope; } } public readonly struct RawFieldRVARow { public readonly uint RVA; public readonly uint Field; public uint this[int index] => index switch { 0 => RVA, 1 => Field, _ => 0u, }; public RawFieldRVARow(uint RVA, uint Field) { this.RVA = RVA; this.Field = Field; } } public readonly struct RawENCLogRow { public readonly uint Token; public readonly uint FuncCode; public uint this[int index] => index switch { 0 => Token, 1 => FuncCode, _ => 0u, }; public RawENCLogRow(uint Token, uint FuncCode) { this.Token = Token; this.FuncCode = FuncCode; } } public readonly struct RawENCMapRow { public readonly uint Token; public uint this[int index] { get { if (index == 0) { return Token; } return 0u; } } public RawENCMapRow(uint Token) { this.Token = Token; } } public readonly struct RawAssemblyRow { public readonly uint HashAlgId; public readonly ushort MajorVersion; public readonly ushort MinorVersion; public readonly ushort BuildNumber; public readonly ushort RevisionNumber; public readonly uint Flags; public readonly uint PublicKey; public readonly uint Name; public readonly uint Locale; public uint this[int index] => index switch { 0 => HashAlgId, 1 => MajorVersion, 2 => MinorVersion, 3 => BuildNumber, 4 => RevisionNumber, 5 => Flags, 6 => PublicKey, 7 => Name, 8 => Locale, _ => 0u, }; public RawAssemblyRow(uint HashAlgId, ushort MajorVersion, ushort MinorVersion, ushort BuildNumber, ushort RevisionNumber, uint Flags, uint PublicKey, uint Name, uint Locale) { this.HashAlgId = HashAlgId; this.MajorVersion = MajorVersion; this.MinorVersion = MinorVersion; this.BuildNumber = BuildNumber; this.RevisionNumber = RevisionNumber; this.Flags = Flags; this.PublicKey = PublicKey; this.Name = Name; this.Locale = Locale; } } public readonly struct RawAssemblyProcessorRow { public readonly uint Processor; public uint this[int index] { get { if (index == 0) { return Processor; } return 0u; } } public RawAssemblyProcessorRow(uint Processor) { this.Processor = Processor; } } public readonly struct RawAssemblyOSRow { public readonly uint OSPlatformId; public readonly uint OSMajorVersion; public readonly uint OSMinorVersion; public uint this[int index] => index switch { 0 => OSPlatformId, 1 => OSMajorVersion, 2 => OSMinorVersion, _ => 0u, }; public RawAssemblyOSRow(uint OSPlatformId, uint OSMajorVersion, uint OSMinorVersion) { this.OSPlatformId = OSPlatformId; this.OSMajorVersion = OSMajorVersion; this.OSMinorVersion = OSMinorVersion; } } public readonly struct RawAssemblyRefRow { public readonly ushort MajorVersion; public readonly ushort MinorVersion; public readonly ushort BuildNumber; public readonly ushort RevisionNumber; public readonly uint Flags; public readonly uint PublicKeyOrToken; public readonly uint Name; public readonly uint Locale; public readonly uint HashValue; public uint this[int index] => index switch { 0 => MajorVersion, 1 => MinorVersion, 2 => BuildNumber, 3 => RevisionNumber, 4 => Flags, 5 => PublicKeyOrToken, 6 => Name, 7 => Locale, 8 => HashValue, _ => 0u, }; public RawAssemblyRefRow(ushort MajorVersion, ushort MinorVersion, ushort BuildNumber, ushort RevisionNumber, uint Flags, uint PublicKeyOrToken, uint Name, uint Locale, uint HashValue) { this.MajorVersion = MajorVersion; this.MinorVersion = MinorVersion; this.BuildNumber = BuildNumber; this.RevisionNumber = RevisionNumber; this.Flags = Flags; this.PublicKeyOrToken = PublicKeyOrToken; this.Name = Name; this.Locale = Locale; this.HashValue = HashValue; } } public readonly struct RawAssemblyRefProcessorRow { public readonly uint Processor; public readonly uint AssemblyRef; public uint this[int index] => index switch { 0 => Processor, 1 => AssemblyRef, _ => 0u, }; public RawAssemblyRefProcessorRow(uint Processor, uint AssemblyRef) { this.Processor = Processor; this.AssemblyRef = AssemblyRef; } } public readonly struct RawAssemblyRefOSRow { public readonly uint OSPlatformId; public readonly uint OSMajorVersion; public readonly uint OSMinorVersion; public readonly uint AssemblyRef; public uint this[int index] => index switch { 0 => OSPlatformId, 1 => OSMajorVersion, 2 => OSMinorVersion, 3 => AssemblyRef, _ => 0u, }; public RawAssemblyRefOSRow(uint OSPlatformId, uint OSMajorVersion, uint OSMinorVersion, uint AssemblyRef) { this.OSPlatformId = OSPlatformId; this.OSMajorVersion = OSMajorVersion; this.OSMinorVersion = OSMinorVersion; this.AssemblyRef = AssemblyRef; } } public readonly struct RawFileRow { public readonly uint Flags; public readonly uint Name; public readonly uint HashValue; public uint this[int index] => index switch { 0 => Flags, 1 => Name, 2 => HashValue, _ => 0u, }; public RawFileRow(uint Flags, uint Name, uint HashValue) { this.Flags = Flags; this.Name = Name; this.HashValue = HashValue; } } public readonly struct RawExportedTypeRow { public readonly uint Flags; public readonly uint TypeDefId; public readonly uint TypeName; public readonly uint TypeNamespace; public readonly uint Implementation; public uint this[int index] => index switch { 0 => Flags, 1 => TypeDefId, 2 => TypeName, 3 => TypeNamespace, 4 => Implementation, _ => 0u, }; public RawExportedTypeRow(uint Flags, uint TypeDefId, uint TypeName, uint TypeNamespace, uint Implementation) { this.Flags = Flags; this.TypeDefId = TypeDefId; this.TypeName = TypeName; this.TypeNamespace = TypeNamespace; this.Implementation = Implementation; } } public readonly struct RawManifestResourceRow { public readonly uint Offset; public readonly uint Flags; public readonly uint Name; public readonly uint Implementation; public uint this[int index] => index switch { 0 => Offset, 1 => Flags, 2 => Name, 3 => Implementation, _ => 0u, }; public RawManifestResourceRow(uint Offset, uint Flags, uint Name, uint Implementation) { this.Offset = Offset; this.Flags = Flags; this.Name = Name; this.Implementation = Implementation; } } public readonly struct RawNestedClassRow { public readonly uint NestedClass; public readonly uint EnclosingClass; public uint this[int index] => index switch { 0 => NestedClass, 1 => EnclosingClass, _ => 0u, }; public RawNestedClassRow(uint NestedClass, uint EnclosingClass) { this.NestedClass = NestedClass; this.EnclosingClass = EnclosingClass; } } public readonly struct RawGenericParamRow { public readonly ushort Number; public readonly ushort Flags; public readonly uint Owner; public readonly uint Name; public readonly uint Kind; public uint this[int index] => index switch { 0 => Number, 1 => Flags, 2 => Owner, 3 => Name, 4 => Kind, _ => 0u, }; public RawGenericParamRow(ushort Number, ushort Flags, uint Owner, uint Name, uint Kind) { this.Number = Number; this.Flags = Flags; this.Owner = Owner; this.Name = Name; this.Kind = Kind; } public RawGenericParamRow(ushort Number, ushort Flags, uint Owner, uint Name) { this.Number = Number; this.Flags = Flags; this.Owner = Owner; this.Name = Name; Kind = 0u; } } public readonly struct RawMethodSpecRow { public readonly uint Method; public readonly uint Instantiation; public uint this[int index] => index switch { 0 => Method, 1 => Instantiation, _ => 0u, }; public RawMethodSpecRow(uint Method, uint Instantiation) { this.Method = Method; this.Instantiation = Instantiation; } } public readonly struct RawGenericParamConstraintRow { public readonly uint Owner; public readonly uint Constraint; public uint this[int index] => index switch { 0 => Owner, 1 => Constraint, _ => 0u, }; public RawGenericParamConstraintRow(uint Owner, uint Constraint) { this.Owner = Owner; this.Constraint = Constraint; } } public readonly struct RawDocumentRow { public readonly uint Name; public readonly uint HashAlgorithm; public readonly uint Hash; public readonly uint Language; public uint this[int index] => index switch { 0 => Name, 1 => HashAlgorithm, 2 => Hash, 3 => Language, _ => 0u, }; public RawDocumentRow(uint Name, uint HashAlgorithm, uint Hash, uint Language) { this.Name = Name; this.HashAlgorithm = HashAlgorithm; this.Hash = Hash; this.Language = Language; } } public readonly struct RawMethodDebugInformationRow { public readonly uint Document; public readonly uint SequencePoints; public uint this[int index] => index switch { 0 => Document, 1 => SequencePoints, _ => 0u, }; public RawMethodDebugInformationRow(uint Document, uint SequencePoints) { this.Document = Document; this.SequencePoints = SequencePoints; } } public readonly struct RawLocalScopeRow { public readonly uint Method; public readonly uint ImportScope; public readonly uint VariableList; public readonly uint ConstantList; public readonly uint StartOffset; public readonly uint Length; public uint this[int index] => index switch { 0 => Method, 1 => ImportScope, 2 => VariableList, 3 => ConstantList, 4 => StartOffset, 5 => Length, _ => 0u, }; public RawLocalScopeRow(uint Method, uint ImportScope, uint VariableList, uint ConstantList, uint StartOffset, uint Length) { this.Method = Method; this.ImportScope = ImportScope; this.VariableList = VariableList; this.ConstantList = ConstantList; this.StartOffset = StartOffset; this.Length = Length; } } public readonly struct RawLocalVariableRow { public readonly ushort Attributes; public readonly ushort Index; public readonly uint Name; public uint this[int index] => index switch { 0 => Attributes, 1 => Index, 2 => Name, _ => 0u, }; public RawLocalVariableRow(ushort Attributes, ushort Index, uint Name) { this.Attributes = Attributes; this.Index = Index; this.Name = Name; } } public readonly struct RawLocalConstantRow { public readonly uint Name; public readonly uint Signature; public uint this[int index] => index switch { 0 => Name, 1 => Signature, _ => 0u, }; public RawLocalConstantRow(uint Name, uint Signature) { this.Name = Name; this.Signature = Signature; } } public readonly struct RawImportScopeRow { public readonly uint Parent; public readonly uint Imports; public uint this[int index] => index switch { 0 => Parent, 1 => Imports, _ => 0u, }; public RawImportScopeRow(uint Parent, uint Imports) { this.Parent = Parent; this.Imports = Imports; } } public readonly struct RawStateMachineMethodRow { public readonly uint MoveNextMethod; public readonly uint KickoffMethod; public uint this[int index] => index switch { 0 => MoveNextMethod, 1 => KickoffMethod, _ => 0u, }; public RawStateMachineMethodRow(uint MoveNextMethod, uint KickoffMethod) { this.MoveNextMethod = MoveNextMethod; this.KickoffMethod = KickoffMethod; } } public readonly struct RawCustomDebugInformationRow { public readonly uint Parent; public readonly uint Kind; public readonly uint Value; public uint this[int index] => index switch { 0 => Parent, 1 => Kind, 2 => Value, _ => 0u, }; public RawCustomDebugInformationRow(uint Parent, uint Kind, uint Value) { this.Parent = Parent; this.Kind = Kind; this.Value = Value; } } [DebuggerDisplay("Count = {Count}")] public readonly struct RidList : IEnumerable, IEnumerable { public struct Enumerator : IEnumerator, IEnumerator, IDisposable { private readonly uint startRid; private readonly uint length; private readonly IList rids; private uint index; private uint current; public uint Current => current; object IEnumerator.Current => current; internal Enumerator(in RidList list) { startRid = list.startRid; length = list.length; rids = list.rids; index = 0u; current = 0u; } public void Dispose() { } public bool MoveNext() { if (rids == null && index < length) { current = startRid + index; index++; return true; } return MoveNextOther(); } private bool MoveNextOther() { if (index >= length) { current = 0u; return false; } if (rids != null) { current = rids[(int)index]; } else { current = startRid + index; } index++; return true; } void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly uint startRid; private readonly uint length; private readonly IList rids; public static readonly RidList Empty = Create(0u, 0u); public uint this[int index] { get { if (rids != null) { if ((uint)index >= (uint)rids.Count) { return 0u; } return rids[index]; } if ((uint)index >= length) { return 0u; } return startRid + (uint)index; } } public int Count => (int)length; public static RidList Create(uint startRid, uint length) { return new RidList(startRid, length); } public static RidList Create(IList rids) { return new RidList(rids); } private RidList(uint startRid, uint length) { this.startRid = startRid; this.length = length; rids = null; } private RidList(IList rids) { this.rids = rids ?? throw new ArgumentNullException("rids"); startRid = 0u; length = (uint)rids.Count; } public Enumerator GetEnumerator() { return new Enumerator(in this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum StorageFlags : byte { Normal = 0, ExtraData = 1 } [DebuggerDisplay("O:{offset} L:{streamSize} {name}")] public sealed class StreamHeader : FileSection { private readonly uint offset; private readonly uint streamSize; private readonly string name; public uint Offset => offset; public uint StreamSize => streamSize; public string Name => name; public StreamHeader(ref DataReader reader, bool verify) : this(ref reader, verify, verify, CLRRuntimeReaderKind.CLR, out var _) { } internal StreamHeader(ref DataReader reader, bool throwOnError, bool verify, CLRRuntimeReaderKind runtime, out bool failedVerification) { failedVerification = false; SetStartOffset(ref reader); offset = reader.ReadUInt32(); streamSize = reader.ReadUInt32(); name = ReadString(ref reader, 32, verify, ref failedVerification); SetEndoffset(ref reader); if (runtime == CLRRuntimeReaderKind.Mono) { if (offset > reader.Length) { offset = reader.Length; } streamSize = reader.Length - offset; } if (verify && offset + size < offset) { failedVerification = true; } if (throwOnError & failedVerification) { throw new BadImageFormatException("Invalid stream header"); } } internal StreamHeader(uint offset, uint streamSize, string name) { this.offset = offset; this.streamSize = streamSize; this.name = name ?? throw new ArgumentNullException("name"); } private static string ReadString(ref DataReader reader, int maxLen, bool verify, ref bool failedVerification) { uint position = reader.Position; StringBuilder stringBuilder = new StringBuilder(maxLen); int i; for (i = 0; i < maxLen; i++) { byte b = reader.ReadByte(); if (b == 0) { break; } stringBuilder.Append((char)b); } if (verify && i == maxLen) { failedVerification = true; } if (i != maxLen) { reader.Position = position + (uint)((i + 1 + 3) & -4); } return stringBuilder.ToString(); } } public sealed class StringsStream : HeapStream { public StringsStream() { } public StringsStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } public UTF8String Read(uint offset) { if (offset >= base.StreamLength) { return null; } DataReader dataReader = base.dataReader; dataReader.Position = offset; byte[] array = dataReader.TryReadBytesUntil(0); if (array == null) { return null; } return new UTF8String(array); } public UTF8String ReadNoNull(uint offset) { return Read(offset) ?? UTF8String.Empty; } } public enum Table : 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, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55 } [DebuggerDisplay("{rowSize} {name}")] public sealed class TableInfo { private readonly Table table; private int rowSize; private readonly ColumnInfo[] columns; private readonly string name; public Table Table => table; public int RowSize { get { return rowSize; } internal set { rowSize = value; } } public ColumnInfo[] Columns => columns; public string Name => name; public TableInfo(Table table, string name, ColumnInfo[] columns) { this.table = table; this.name = name; this.columns = columns; } public TableInfo(Table table, string name, ColumnInfo[] columns, int rowSize) { this.table = table; this.name = name; this.columns = columns; this.rowSize = rowSize; } } public sealed class TablesStream : DotNetStream { private bool initialized; private uint reserved1; private byte majorVersion; private byte minorVersion; private MDStreamFlags flags; private byte log2Rid; private ulong validMask; private ulong sortedMask; private uint extraData; private MDTable[] mdTables; private uint mdTablesPos; private IColumnReader columnReader; private IRowReader methodRowReader; private readonly CLRRuntimeReaderKind runtime; public MDTable ModuleTable { get; private set; } public MDTable TypeRefTable { get; private set; } public MDTable TypeDefTable { get; private set; } public MDTable FieldPtrTable { get; private set; } public MDTable FieldTable { get; private set; } public MDTable MethodPtrTable { get; private set; } public MDTable MethodTable { get; private set; } public MDTable ParamPtrTable { get; private set; } public MDTable ParamTable { get; private set; } public MDTable InterfaceImplTable { get; private set; } public MDTable MemberRefTable { get; private set; } public MDTable ConstantTable { get; private set; } public MDTable CustomAttributeTable { get; private set; } public MDTable FieldMarshalTable { get; private set; } public MDTable DeclSecurityTable { get; private set; } public MDTable ClassLayoutTable { get; private set; } public MDTable FieldLayoutTable { get; private set; } public MDTable StandAloneSigTable { get; private set; } public MDTable EventMapTable { get; private set; } public MDTable EventPtrTable { get; private set; } public MDTable EventTable { get; private set; } public MDTable PropertyMapTable { get; private set; } public MDTable PropertyPtrTable { get; private set; } public MDTable PropertyTable { get; private set; } public MDTable MethodSemanticsTable { get; private set; } public MDTable MethodImplTable { get; private set; } public MDTable ModuleRefTable { get; private set; } public MDTable TypeSpecTable { get; private set; } public MDTable ImplMapTable { get; private set; } public MDTable FieldRVATable { get; private set; } public MDTable ENCLogTable { get; private set; } public MDTable ENCMapTable { get; private set; } public MDTable AssemblyTable { get; private set; } public MDTable AssemblyProcessorTable { get; private set; } public MDTable AssemblyOSTable { get; private set; } public MDTable AssemblyRefTable { get; private set; } public MDTable AssemblyRefProcessorTable { get; private set; } public MDTable AssemblyRefOSTable { get; private set; } public MDTable FileTable { get; private set; } public MDTable ExportedTypeTable { get; private set; } public MDTable ManifestResourceTable { get; private set; } public MDTable NestedClassTable { get; private set; } public MDTable GenericParamTable { get; private set; } public MDTable MethodSpecTable { get; private set; } public MDTable GenericParamConstraintTable { get; private set; } public MDTable DocumentTable { get; private set; } public MDTable MethodDebugInformationTable { get; private set; } public MDTable LocalScopeTable { get; private set; } public MDTable LocalVariableTable { get; private set; } public MDTable LocalConstantTable { get; private set; } public MDTable ImportScopeTable { get; private set; } public MDTable StateMachineMethodTable { get; private set; } public MDTable CustomDebugInformationTable { get; private set; } public IColumnReader ColumnReader { get { return columnReader; } set { columnReader = value; } } public IRowReader MethodRowReader { get { return methodRowReader; } set { methodRowReader = value; } } public uint Reserved1 => reserved1; public ushort Version => (ushort)((majorVersion << 8) | minorVersion); public MDStreamFlags Flags => flags; public byte Log2Rid => log2Rid; public ulong ValidMask => validMask; public ulong SortedMask => sortedMask; public uint ExtraData => extraData; public MDTable[] MDTables => mdTables; public bool HasBigStrings => (flags & MDStreamFlags.BigStrings) != 0; public bool HasBigGUID => (flags & MDStreamFlags.BigGUID) != 0; public bool HasBigBlob => (flags & MDStreamFlags.BigBlob) != 0; public bool HasPadding { get { if (runtime == CLRRuntimeReaderKind.CLR) { return (flags & MDStreamFlags.Padding) != 0; } return false; } } public bool HasDeltaOnly { get { if (runtime == CLRRuntimeReaderKind.CLR) { return (flags & MDStreamFlags.DeltaOnly) != 0; } return false; } } public bool HasExtraData { get { if (runtime == CLRRuntimeReaderKind.CLR) { return (flags & MDStreamFlags.ExtraData) != 0; } return false; } } public bool HasDelete { get { if (runtime == CLRRuntimeReaderKind.CLR) { return (flags & MDStreamFlags.HasDelete) != 0; } return false; } } public TablesStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : this(mdReaderFactory, metadataBaseOffset, streamHeader, CLRRuntimeReaderKind.CLR) { } public TablesStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader, CLRRuntimeReaderKind runtime) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { this.runtime = runtime; } public void Initialize(uint[] typeSystemTableRows) { Initialize(typeSystemTableRows, forceAllBig: false); } internal void Initialize(uint[] typeSystemTableRows, bool forceAllBig) { if (initialized) { throw new Exception("Initialize() has already been called"); } initialized = true; DataReader dataReader = base.dataReader; reserved1 = dataReader.ReadUInt32(); majorVersion = dataReader.ReadByte(); minorVersion = dataReader.ReadByte(); flags = (MDStreamFlags)dataReader.ReadByte(); log2Rid = dataReader.ReadByte(); validMask = dataReader.ReadUInt64(); sortedMask = dataReader.ReadUInt64(); if (runtime == CLRRuntimeReaderKind.Mono) { sortedMask = ulong.MaxValue; } DotNetTableSizes dotNetTableSizes = new DotNetTableSizes(); byte b = majorVersion; byte b2 = minorVersion; if (runtime == CLRRuntimeReaderKind.Mono) { b = 2; b2 = 0; } int maxPresentTables; TableInfo[] array = dotNetTableSizes.CreateTables(b, b2, out maxPresentTables); if (typeSystemTableRows != null) { maxPresentTables = 56; } mdTables = new MDTable[array.Length]; ulong num = validMask; uint[] array2 = new uint[64]; for (int i = 0; i < 64; i++) { uint num2 = (((num & 1) != 0L) ? dataReader.ReadUInt32() : 0u); num2 &= 0xFFFFFF; if (i >= maxPresentTables) { num2 = 0u; } array2[i] = num2; if (i < mdTables.Length) { mdTables[i] = new MDTable((Table)i, num2, array[i]); } num >>= 1; } if (HasExtraData) { extraData = dataReader.ReadUInt32(); } uint[] array3 = array2; if (typeSystemTableRows != null) { array3 = new uint[array2.Length]; for (int j = 0; j < 64; j++) { if (DotNetTableSizes.IsSystemTable((Table)j)) { array3[j] = typeSystemTableRows[j]; } else { array3[j] = array2[j]; } } } dotNetTableSizes.InitializeSizes(HasBigStrings, HasBigGUID, HasBigBlob, array2, array3, forceAllBig); mdTablesPos = dataReader.Position; InitializeMdTableReaders(); InitializeTables(); } protected override void OnReaderRecreated() { InitializeMdTableReaders(); } private void InitializeMdTableReaders() { DataReader dataReader = base.dataReader; dataReader.Position = mdTablesPos; uint num = dataReader.Position; MDTable[] array = mdTables; foreach (MDTable mDTable in array) { uint num2 = (uint)mDTable.TableInfo.RowSize * mDTable.Rows; if (num > dataReader.Length) { num = dataReader.Length; } if ((ulong)((long)num + (long)num2) > (ulong)dataReader.Length) { num2 = dataReader.Length - num; } mDTable.DataReader = dataReader.Slice(num, num2); uint num3 = num + num2; if (num3 < num) { throw new BadImageFormatException("Too big MD table"); } num = num3; } } private void InitializeTables() { ModuleTable = mdTables[0]; TypeRefTable = mdTables[1]; TypeDefTable = mdTables[2]; FieldPtrTable = mdTables[3]; FieldTable = mdTables[4]; MethodPtrTable = mdTables[5]; MethodTable = mdTables[6]; ParamPtrTable = mdTables[7]; ParamTable = mdTables[8]; InterfaceImplTable = mdTables[9]; MemberRefTable = mdTables[10]; ConstantTable = mdTables[11]; CustomAttributeTable = mdTables[12]; FieldMarshalTable = mdTables[13]; DeclSecurityTable = mdTables[14]; ClassLayoutTable = mdTables[15]; FieldLayoutTable = mdTables[16]; StandAloneSigTable = mdTables[17]; EventMapTable = mdTables[18]; EventPtrTable = mdTables[19]; EventTable = mdTables[20]; PropertyMapTable = mdTables[21]; PropertyPtrTable = mdTables[22]; PropertyTable = mdTables[23]; MethodSemanticsTable = mdTables[24]; MethodImplTable = mdTables[25]; ModuleRefTable = mdTables[26]; TypeSpecTable = mdTables[27]; ImplMapTable = mdTables[28]; FieldRVATable = mdTables[29]; ENCLogTable = mdTables[30]; ENCMapTable = mdTables[31]; AssemblyTable = mdTables[32]; AssemblyProcessorTable = mdTables[33]; AssemblyOSTable = mdTables[34]; AssemblyRefTable = mdTables[35]; AssemblyRefProcessorTable = mdTables[36]; AssemblyRefOSTable = mdTables[37]; FileTable = mdTables[38]; ExportedTypeTable = mdTables[39]; ManifestResourceTable = mdTables[40]; NestedClassTable = mdTables[41]; GenericParamTable = mdTables[42]; MethodSpecTable = mdTables[43]; GenericParamConstraintTable = mdTables[44]; DocumentTable = mdTables[48]; MethodDebugInformationTable = mdTables[49]; LocalScopeTable = mdTables[50]; LocalVariableTable = mdTables[51]; LocalConstantTable = mdTables[52]; ImportScopeTable = mdTables[53]; StateMachineMethodTable = mdTables[54]; CustomDebugInformationTable = mdTables[55]; } protected override void Dispose(bool disposing) { if (disposing) { MDTable[] array = mdTables; if (array != null) { MDTable[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i]?.Dispose(); } mdTables = null; } } base.Dispose(disposing); } public MDTable Get(Table table) { if ((uint)table >= (uint)mdTables.Length) { return null; } return mdTables[(uint)table]; } public bool HasTable(Table table) { return (uint)table < (uint)mdTables.Length; } public bool IsSorted(MDTable table) { int table2 = (int)table.Table; if ((uint)table2 >= 64u) { return false; } return (sortedMask & (ulong)(1L << table2)) != 0; } public bool TryReadModuleRow(uint rid, out RawModuleRow row) { MDTable moduleTable = ModuleTable; if (moduleTable.IsInvalidRID(rid)) { row = default(RawModuleRow); return false; } DataReader reader = moduleTable.DataReader; reader.Position = (rid - 1) * (uint)moduleTable.TableInfo.RowSize; row = new RawModuleRow(reader.Unsafe_ReadUInt16(), moduleTable.Column1.Unsafe_Read24(ref reader), moduleTable.Column2.Unsafe_Read24(ref reader), moduleTable.Column3.Unsafe_Read24(ref reader), moduleTable.Column4.Unsafe_Read24(ref reader)); return true; } public bool TryReadTypeRefRow(uint rid, out RawTypeRefRow row) { MDTable typeRefTable = TypeRefTable; if (typeRefTable.IsInvalidRID(rid)) { row = default(RawTypeRefRow); return false; } DataReader reader = typeRefTable.DataReader; reader.Position = (rid - 1) * (uint)typeRefTable.TableInfo.RowSize; row = new RawTypeRefRow(typeRefTable.Column0.Unsafe_Read24(ref reader), typeRefTable.Column1.Unsafe_Read24(ref reader), typeRefTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadTypeDefRow(uint rid, out RawTypeDefRow row) { MDTable typeDefTable = TypeDefTable; if (typeDefTable.IsInvalidRID(rid)) { row = default(RawTypeDefRow); return false; } DataReader reader = typeDefTable.DataReader; reader.Position = (rid - 1) * (uint)typeDefTable.TableInfo.RowSize; row = new RawTypeDefRow(reader.Unsafe_ReadUInt32(), typeDefTable.Column1.Unsafe_Read24(ref reader), typeDefTable.Column2.Unsafe_Read24(ref reader), typeDefTable.Column3.Unsafe_Read24(ref reader), typeDefTable.Column4.Unsafe_Read24(ref reader), typeDefTable.Column5.Unsafe_Read24(ref reader)); return true; } public bool TryReadFieldPtrRow(uint rid, out RawFieldPtrRow row) { MDTable fieldPtrTable = FieldPtrTable; if (fieldPtrTable.IsInvalidRID(rid)) { row = default(RawFieldPtrRow); return false; } DataReader reader = fieldPtrTable.DataReader; reader.Position = (rid - 1) * (uint)fieldPtrTable.TableInfo.RowSize; row = new RawFieldPtrRow(fieldPtrTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadFieldRow(uint rid, out RawFieldRow row) { MDTable fieldTable = FieldTable; if (fieldTable.IsInvalidRID(rid)) { row = default(RawFieldRow); return false; } DataReader reader = fieldTable.DataReader; reader.Position = (rid - 1) * (uint)fieldTable.TableInfo.RowSize; row = new RawFieldRow(reader.Unsafe_ReadUInt16(), fieldTable.Column1.Unsafe_Read24(ref reader), fieldTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodPtrRow(uint rid, out RawMethodPtrRow row) { MDTable methodPtrTable = MethodPtrTable; if (methodPtrTable.IsInvalidRID(rid)) { row = default(RawMethodPtrRow); return false; } DataReader reader = methodPtrTable.DataReader; reader.Position = (rid - 1) * (uint)methodPtrTable.TableInfo.RowSize; row = new RawMethodPtrRow(methodPtrTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodRow(uint rid, out RawMethodRow row) { MDTable methodTable = MethodTable; if (methodTable.IsInvalidRID(rid)) { row = default(RawMethodRow); return false; } IRowReader rowReader = methodRowReader; if (rowReader != null && rowReader.TryReadRow(rid, out row)) { return true; } DataReader reader = methodTable.DataReader; reader.Position = (rid - 1) * (uint)methodTable.TableInfo.RowSize; row = new RawMethodRow(reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), methodTable.Column3.Unsafe_Read24(ref reader), methodTable.Column4.Unsafe_Read24(ref reader), methodTable.Column5.Unsafe_Read24(ref reader)); return true; } public bool TryReadParamPtrRow(uint rid, out RawParamPtrRow row) { MDTable paramPtrTable = ParamPtrTable; if (paramPtrTable.IsInvalidRID(rid)) { row = default(RawParamPtrRow); return false; } DataReader reader = paramPtrTable.DataReader; reader.Position = (rid - 1) * (uint)paramPtrTable.TableInfo.RowSize; row = new RawParamPtrRow(paramPtrTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadParamRow(uint rid, out RawParamRow row) { MDTable paramTable = ParamTable; if (paramTable.IsInvalidRID(rid)) { row = default(RawParamRow); return false; } DataReader reader = paramTable.DataReader; reader.Position = (rid - 1) * (uint)paramTable.TableInfo.RowSize; row = new RawParamRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), paramTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadInterfaceImplRow(uint rid, out RawInterfaceImplRow row) { MDTable interfaceImplTable = InterfaceImplTable; if (interfaceImplTable.IsInvalidRID(rid)) { row = default(RawInterfaceImplRow); return false; } DataReader reader = interfaceImplTable.DataReader; reader.Position = (rid - 1) * (uint)interfaceImplTable.TableInfo.RowSize; row = new RawInterfaceImplRow(interfaceImplTable.Column0.Unsafe_Read24(ref reader), interfaceImplTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadMemberRefRow(uint rid, out RawMemberRefRow row) { MDTable memberRefTable = MemberRefTable; if (memberRefTable.IsInvalidRID(rid)) { row = default(RawMemberRefRow); return false; } DataReader reader = memberRefTable.DataReader; reader.Position = (rid - 1) * (uint)memberRefTable.TableInfo.RowSize; row = new RawMemberRefRow(memberRefTable.Column0.Unsafe_Read24(ref reader), memberRefTable.Column1.Unsafe_Read24(ref reader), memberRefTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadConstantRow(uint rid, out RawConstantRow row) { MDTable constantTable = ConstantTable; if (constantTable.IsInvalidRID(rid)) { row = default(RawConstantRow); return false; } DataReader reader = constantTable.DataReader; reader.Position = (rid - 1) * (uint)constantTable.TableInfo.RowSize; row = new RawConstantRow(reader.Unsafe_ReadByte(), reader.Unsafe_ReadByte(), constantTable.Column2.Unsafe_Read24(ref reader), constantTable.Column3.Unsafe_Read24(ref reader)); return true; } public bool TryReadCustomAttributeRow(uint rid, out RawCustomAttributeRow row) { MDTable customAttributeTable = CustomAttributeTable; if (customAttributeTable.IsInvalidRID(rid)) { row = default(RawCustomAttributeRow); return false; } DataReader reader = customAttributeTable.DataReader; reader.Position = (rid - 1) * (uint)customAttributeTable.TableInfo.RowSize; row = new RawCustomAttributeRow(customAttributeTable.Column0.Unsafe_Read24(ref reader), customAttributeTable.Column1.Unsafe_Read24(ref reader), customAttributeTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadFieldMarshalRow(uint rid, out RawFieldMarshalRow row) { MDTable fieldMarshalTable = FieldMarshalTable; if (fieldMarshalTable.IsInvalidRID(rid)) { row = default(RawFieldMarshalRow); return false; } DataReader reader = fieldMarshalTable.DataReader; reader.Position = (rid - 1) * (uint)fieldMarshalTable.TableInfo.RowSize; row = new RawFieldMarshalRow(fieldMarshalTable.Column0.Unsafe_Read24(ref reader), fieldMarshalTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadDeclSecurityRow(uint rid, out RawDeclSecurityRow row) { MDTable declSecurityTable = DeclSecurityTable; if (declSecurityTable.IsInvalidRID(rid)) { row = default(RawDeclSecurityRow); return false; } DataReader reader = declSecurityTable.DataReader; reader.Position = (rid - 1) * (uint)declSecurityTable.TableInfo.RowSize; row = new RawDeclSecurityRow((short)reader.Unsafe_ReadUInt16(), declSecurityTable.Column1.Unsafe_Read24(ref reader), declSecurityTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadClassLayoutRow(uint rid, out RawClassLayoutRow row) { MDTable classLayoutTable = ClassLayoutTable; if (classLayoutTable.IsInvalidRID(rid)) { row = default(RawClassLayoutRow); return false; } DataReader reader = classLayoutTable.DataReader; reader.Position = (rid - 1) * (uint)classLayoutTable.TableInfo.RowSize; row = new RawClassLayoutRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt32(), classLayoutTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadFieldLayoutRow(uint rid, out RawFieldLayoutRow row) { MDTable fieldLayoutTable = FieldLayoutTable; if (fieldLayoutTable.IsInvalidRID(rid)) { row = default(RawFieldLayoutRow); return false; } DataReader reader = fieldLayoutTable.DataReader; reader.Position = (rid - 1) * (uint)fieldLayoutTable.TableInfo.RowSize; row = new RawFieldLayoutRow(reader.Unsafe_ReadUInt32(), fieldLayoutTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadStandAloneSigRow(uint rid, out RawStandAloneSigRow row) { MDTable standAloneSigTable = StandAloneSigTable; if (standAloneSigTable.IsInvalidRID(rid)) { row = default(RawStandAloneSigRow); return false; } DataReader reader = standAloneSigTable.DataReader; reader.Position = (rid - 1) * (uint)standAloneSigTable.TableInfo.RowSize; row = new RawStandAloneSigRow(standAloneSigTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadEventMapRow(uint rid, out RawEventMapRow row) { MDTable eventMapTable = EventMapTable; if (eventMapTable.IsInvalidRID(rid)) { row = default(RawEventMapRow); return false; } DataReader reader = eventMapTable.DataReader; reader.Position = (rid - 1) * (uint)eventMapTable.TableInfo.RowSize; row = new RawEventMapRow(eventMapTable.Column0.Unsafe_Read24(ref reader), eventMapTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadEventPtrRow(uint rid, out RawEventPtrRow row) { MDTable eventPtrTable = EventPtrTable; if (eventPtrTable.IsInvalidRID(rid)) { row = default(RawEventPtrRow); return false; } DataReader reader = eventPtrTable.DataReader; reader.Position = (rid - 1) * (uint)eventPtrTable.TableInfo.RowSize; row = new RawEventPtrRow(eventPtrTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadEventRow(uint rid, out RawEventRow row) { MDTable eventTable = EventTable; if (eventTable.IsInvalidRID(rid)) { row = default(RawEventRow); return false; } DataReader reader = eventTable.DataReader; reader.Position = (rid - 1) * (uint)eventTable.TableInfo.RowSize; row = new RawEventRow(reader.Unsafe_ReadUInt16(), eventTable.Column1.Unsafe_Read24(ref reader), eventTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadPropertyMapRow(uint rid, out RawPropertyMapRow row) { MDTable propertyMapTable = PropertyMapTable; if (propertyMapTable.IsInvalidRID(rid)) { row = default(RawPropertyMapRow); return false; } DataReader reader = propertyMapTable.DataReader; reader.Position = (rid - 1) * (uint)propertyMapTable.TableInfo.RowSize; row = new RawPropertyMapRow(propertyMapTable.Column0.Unsafe_Read24(ref reader), propertyMapTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadPropertyPtrRow(uint rid, out RawPropertyPtrRow row) { MDTable propertyPtrTable = PropertyPtrTable; if (propertyPtrTable.IsInvalidRID(rid)) { row = default(RawPropertyPtrRow); return false; } DataReader reader = propertyPtrTable.DataReader; reader.Position = (rid - 1) * (uint)propertyPtrTable.TableInfo.RowSize; row = new RawPropertyPtrRow(propertyPtrTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadPropertyRow(uint rid, out RawPropertyRow row) { MDTable propertyTable = PropertyTable; if (propertyTable.IsInvalidRID(rid)) { row = default(RawPropertyRow); return false; } DataReader reader = propertyTable.DataReader; reader.Position = (rid - 1) * (uint)propertyTable.TableInfo.RowSize; row = new RawPropertyRow(reader.Unsafe_ReadUInt16(), propertyTable.Column1.Unsafe_Read24(ref reader), propertyTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodSemanticsRow(uint rid, out RawMethodSemanticsRow row) { MDTable methodSemanticsTable = MethodSemanticsTable; if (methodSemanticsTable.IsInvalidRID(rid)) { row = default(RawMethodSemanticsRow); return false; } DataReader reader = methodSemanticsTable.DataReader; reader.Position = (rid - 1) * (uint)methodSemanticsTable.TableInfo.RowSize; row = new RawMethodSemanticsRow(reader.Unsafe_ReadUInt16(), methodSemanticsTable.Column1.Unsafe_Read24(ref reader), methodSemanticsTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodImplRow(uint rid, out RawMethodImplRow row) { MDTable methodImplTable = MethodImplTable; if (methodImplTable.IsInvalidRID(rid)) { row = default(RawMethodImplRow); return false; } DataReader reader = methodImplTable.DataReader; reader.Position = (rid - 1) * (uint)methodImplTable.TableInfo.RowSize; row = new RawMethodImplRow(methodImplTable.Column0.Unsafe_Read24(ref reader), methodImplTable.Column1.Unsafe_Read24(ref reader), methodImplTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadModuleRefRow(uint rid, out RawModuleRefRow row) { MDTable moduleRefTable = ModuleRefTable; if (moduleRefTable.IsInvalidRID(rid)) { row = default(RawModuleRefRow); return false; } DataReader reader = moduleRefTable.DataReader; reader.Position = (rid - 1) * (uint)moduleRefTable.TableInfo.RowSize; row = new RawModuleRefRow(moduleRefTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadTypeSpecRow(uint rid, out RawTypeSpecRow row) { MDTable typeSpecTable = TypeSpecTable; if (typeSpecTable.IsInvalidRID(rid)) { row = default(RawTypeSpecRow); return false; } DataReader reader = typeSpecTable.DataReader; reader.Position = (rid - 1) * (uint)typeSpecTable.TableInfo.RowSize; row = new RawTypeSpecRow(typeSpecTable.Column0.Unsafe_Read24(ref reader)); return true; } public bool TryReadImplMapRow(uint rid, out RawImplMapRow row) { MDTable implMapTable = ImplMapTable; if (implMapTable.IsInvalidRID(rid)) { row = default(RawImplMapRow); return false; } DataReader reader = implMapTable.DataReader; reader.Position = (rid - 1) * (uint)implMapTable.TableInfo.RowSize; row = new RawImplMapRow(reader.Unsafe_ReadUInt16(), implMapTable.Column1.Unsafe_Read24(ref reader), implMapTable.Column2.Unsafe_Read24(ref reader), implMapTable.Column3.Unsafe_Read24(ref reader)); return true; } public bool TryReadFieldRVARow(uint rid, out RawFieldRVARow row) { MDTable fieldRVATable = FieldRVATable; if (fieldRVATable.IsInvalidRID(rid)) { row = default(RawFieldRVARow); return false; } DataReader reader = fieldRVATable.DataReader; reader.Position = (rid - 1) * (uint)fieldRVATable.TableInfo.RowSize; row = new RawFieldRVARow(reader.Unsafe_ReadUInt32(), fieldRVATable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadENCLogRow(uint rid, out RawENCLogRow row) { MDTable eNCLogTable = ENCLogTable; if (eNCLogTable.IsInvalidRID(rid)) { row = default(RawENCLogRow); return false; } DataReader dataReader = eNCLogTable.DataReader; dataReader.Position = (rid - 1) * (uint)eNCLogTable.TableInfo.RowSize; row = new RawENCLogRow(dataReader.Unsafe_ReadUInt32(), dataReader.Unsafe_ReadUInt32()); return true; } public bool TryReadENCMapRow(uint rid, out RawENCMapRow row) { MDTable eNCMapTable = ENCMapTable; if (eNCMapTable.IsInvalidRID(rid)) { row = default(RawENCMapRow); return false; } DataReader dataReader = eNCMapTable.DataReader; dataReader.Position = (rid - 1) * (uint)eNCMapTable.TableInfo.RowSize; row = new RawENCMapRow(dataReader.Unsafe_ReadUInt32()); return true; } public bool TryReadAssemblyRow(uint rid, out RawAssemblyRow row) { MDTable assemblyTable = AssemblyTable; if (assemblyTable.IsInvalidRID(rid)) { row = default(RawAssemblyRow); return false; } DataReader reader = assemblyTable.DataReader; reader.Position = (rid - 1) * (uint)assemblyTable.TableInfo.RowSize; row = new RawAssemblyRow(reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt32(), assemblyTable.Column6.Unsafe_Read24(ref reader), assemblyTable.Column7.Unsafe_Read24(ref reader), assemblyTable.Column8.Unsafe_Read24(ref reader)); return true; } public bool TryReadAssemblyProcessorRow(uint rid, out RawAssemblyProcessorRow row) { MDTable assemblyProcessorTable = AssemblyProcessorTable; if (assemblyProcessorTable.IsInvalidRID(rid)) { row = default(RawAssemblyProcessorRow); return false; } DataReader dataReader = assemblyProcessorTable.DataReader; dataReader.Position = (rid - 1) * (uint)assemblyProcessorTable.TableInfo.RowSize; row = new RawAssemblyProcessorRow(dataReader.Unsafe_ReadUInt32()); return true; } public bool TryReadAssemblyOSRow(uint rid, out RawAssemblyOSRow row) { MDTable assemblyOSTable = AssemblyOSTable; if (assemblyOSTable.IsInvalidRID(rid)) { row = default(RawAssemblyOSRow); return false; } DataReader dataReader = assemblyOSTable.DataReader; dataReader.Position = (rid - 1) * (uint)assemblyOSTable.TableInfo.RowSize; row = new RawAssemblyOSRow(dataReader.Unsafe_ReadUInt32(), dataReader.Unsafe_ReadUInt32(), dataReader.Unsafe_ReadUInt32()); return true; } public bool TryReadAssemblyRefRow(uint rid, out RawAssemblyRefRow row) { MDTable assemblyRefTable = AssemblyRefTable; if (assemblyRefTable.IsInvalidRID(rid)) { row = default(RawAssemblyRefRow); return false; } DataReader reader = assemblyRefTable.DataReader; reader.Position = (rid - 1) * (uint)assemblyRefTable.TableInfo.RowSize; row = new RawAssemblyRefRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt32(), assemblyRefTable.Column5.Unsafe_Read24(ref reader), assemblyRefTable.Column6.Unsafe_Read24(ref reader), assemblyRefTable.Column7.Unsafe_Read24(ref reader), assemblyRefTable.Column8.Unsafe_Read24(ref reader)); return true; } public bool TryReadAssemblyRefProcessorRow(uint rid, out RawAssemblyRefProcessorRow row) { MDTable assemblyRefProcessorTable = AssemblyRefProcessorTable; if (assemblyRefProcessorTable.IsInvalidRID(rid)) { row = default(RawAssemblyRefProcessorRow); return false; } DataReader reader = assemblyRefProcessorTable.DataReader; reader.Position = (rid - 1) * (uint)assemblyRefProcessorTable.TableInfo.RowSize; row = new RawAssemblyRefProcessorRow(reader.Unsafe_ReadUInt32(), assemblyRefProcessorTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadAssemblyRefOSRow(uint rid, out RawAssemblyRefOSRow row) { MDTable assemblyRefOSTable = AssemblyRefOSTable; if (assemblyRefOSTable.IsInvalidRID(rid)) { row = default(RawAssemblyRefOSRow); return false; } DataReader reader = assemblyRefOSTable.DataReader; reader.Position = (rid - 1) * (uint)assemblyRefOSTable.TableInfo.RowSize; row = new RawAssemblyRefOSRow(reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt32(), assemblyRefOSTable.Column3.Unsafe_Read24(ref reader)); return true; } public bool TryReadFileRow(uint rid, out RawFileRow row) { MDTable fileTable = FileTable; if (fileTable.IsInvalidRID(rid)) { row = default(RawFileRow); return false; } DataReader reader = fileTable.DataReader; reader.Position = (rid - 1) * (uint)fileTable.TableInfo.RowSize; row = new RawFileRow(reader.Unsafe_ReadUInt32(), fileTable.Column1.Unsafe_Read24(ref reader), fileTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadExportedTypeRow(uint rid, out RawExportedTypeRow row) { MDTable exportedTypeTable = ExportedTypeTable; if (exportedTypeTable.IsInvalidRID(rid)) { row = default(RawExportedTypeRow); return false; } DataReader reader = exportedTypeTable.DataReader; reader.Position = (rid - 1) * (uint)exportedTypeTable.TableInfo.RowSize; row = new RawExportedTypeRow(reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt32(), exportedTypeTable.Column2.Unsafe_Read24(ref reader), exportedTypeTable.Column3.Unsafe_Read24(ref reader), exportedTypeTable.Column4.Unsafe_Read24(ref reader)); return true; } public bool TryReadManifestResourceRow(uint rid, out RawManifestResourceRow row) { MDTable manifestResourceTable = ManifestResourceTable; if (manifestResourceTable.IsInvalidRID(rid)) { row = default(RawManifestResourceRow); return false; } DataReader reader = manifestResourceTable.DataReader; reader.Position = (rid - 1) * (uint)manifestResourceTable.TableInfo.RowSize; row = new RawManifestResourceRow(reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt32(), manifestResourceTable.Column2.Unsafe_Read24(ref reader), manifestResourceTable.Column3.Unsafe_Read24(ref reader)); return true; } public bool TryReadNestedClassRow(uint rid, out RawNestedClassRow row) { MDTable nestedClassTable = NestedClassTable; if (nestedClassTable.IsInvalidRID(rid)) { row = default(RawNestedClassRow); return false; } DataReader reader = nestedClassTable.DataReader; reader.Position = (rid - 1) * (uint)nestedClassTable.TableInfo.RowSize; row = new RawNestedClassRow(nestedClassTable.Column0.Unsafe_Read24(ref reader), nestedClassTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadGenericParamRow(uint rid, out RawGenericParamRow row) { MDTable genericParamTable = GenericParamTable; if (genericParamTable.IsInvalidRID(rid)) { row = default(RawGenericParamRow); return false; } DataReader reader = genericParamTable.DataReader; reader.Position = (rid - 1) * (uint)genericParamTable.TableInfo.RowSize; if (genericParamTable.Column4 == null) { row = new RawGenericParamRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), genericParamTable.Column2.Unsafe_Read24(ref reader), genericParamTable.Column3.Unsafe_Read24(ref reader)); return true; } row = new RawGenericParamRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), genericParamTable.Column2.Unsafe_Read24(ref reader), genericParamTable.Column3.Unsafe_Read24(ref reader), genericParamTable.Column4.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodSpecRow(uint rid, out RawMethodSpecRow row) { MDTable methodSpecTable = MethodSpecTable; if (methodSpecTable.IsInvalidRID(rid)) { row = default(RawMethodSpecRow); return false; } DataReader reader = methodSpecTable.DataReader; reader.Position = (rid - 1) * (uint)methodSpecTable.TableInfo.RowSize; row = new RawMethodSpecRow(methodSpecTable.Column0.Unsafe_Read24(ref reader), methodSpecTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadGenericParamConstraintRow(uint rid, out RawGenericParamConstraintRow row) { MDTable genericParamConstraintTable = GenericParamConstraintTable; if (genericParamConstraintTable.IsInvalidRID(rid)) { row = default(RawGenericParamConstraintRow); return false; } DataReader reader = genericParamConstraintTable.DataReader; reader.Position = (rid - 1) * (uint)genericParamConstraintTable.TableInfo.RowSize; row = new RawGenericParamConstraintRow(genericParamConstraintTable.Column0.Unsafe_Read24(ref reader), genericParamConstraintTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadDocumentRow(uint rid, out RawDocumentRow row) { MDTable documentTable = DocumentTable; if (documentTable.IsInvalidRID(rid)) { row = default(RawDocumentRow); return false; } DataReader reader = documentTable.DataReader; reader.Position = (rid - 1) * (uint)documentTable.TableInfo.RowSize; row = new RawDocumentRow(documentTable.Column0.Unsafe_Read24(ref reader), documentTable.Column1.Unsafe_Read24(ref reader), documentTable.Column2.Unsafe_Read24(ref reader), documentTable.Column3.Unsafe_Read24(ref reader)); return true; } public bool TryReadMethodDebugInformationRow(uint rid, out RawMethodDebugInformationRow row) { MDTable methodDebugInformationTable = MethodDebugInformationTable; if (methodDebugInformationTable.IsInvalidRID(rid)) { row = default(RawMethodDebugInformationRow); return false; } DataReader reader = methodDebugInformationTable.DataReader; reader.Position = (rid - 1) * (uint)methodDebugInformationTable.TableInfo.RowSize; row = new RawMethodDebugInformationRow(methodDebugInformationTable.Column0.Unsafe_Read24(ref reader), methodDebugInformationTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadLocalScopeRow(uint rid, out RawLocalScopeRow row) { MDTable localScopeTable = LocalScopeTable; if (localScopeTable.IsInvalidRID(rid)) { row = default(RawLocalScopeRow); return false; } DataReader reader = localScopeTable.DataReader; reader.Position = (rid - 1) * (uint)localScopeTable.TableInfo.RowSize; row = new RawLocalScopeRow(localScopeTable.Column0.Unsafe_Read24(ref reader), localScopeTable.Column1.Unsafe_Read24(ref reader), localScopeTable.Column2.Unsafe_Read24(ref reader), localScopeTable.Column3.Unsafe_Read24(ref reader), reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt32()); return true; } public bool TryReadLocalVariableRow(uint rid, out RawLocalVariableRow row) { MDTable localVariableTable = LocalVariableTable; if (localVariableTable.IsInvalidRID(rid)) { row = default(RawLocalVariableRow); return false; } DataReader reader = localVariableTable.DataReader; reader.Position = (rid - 1) * (uint)localVariableTable.TableInfo.RowSize; row = new RawLocalVariableRow(reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), localVariableTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadLocalConstantRow(uint rid, out RawLocalConstantRow row) { MDTable localConstantTable = LocalConstantTable; if (localConstantTable.IsInvalidRID(rid)) { row = default(RawLocalConstantRow); return false; } DataReader reader = localConstantTable.DataReader; reader.Position = (rid - 1) * (uint)localConstantTable.TableInfo.RowSize; row = new RawLocalConstantRow(localConstantTable.Column0.Unsafe_Read24(ref reader), localConstantTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadImportScopeRow(uint rid, out RawImportScopeRow row) { MDTable importScopeTable = ImportScopeTable; if (importScopeTable.IsInvalidRID(rid)) { row = default(RawImportScopeRow); return false; } DataReader reader = importScopeTable.DataReader; reader.Position = (rid - 1) * (uint)importScopeTable.TableInfo.RowSize; row = new RawImportScopeRow(importScopeTable.Column0.Unsafe_Read24(ref reader), importScopeTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadStateMachineMethodRow(uint rid, out RawStateMachineMethodRow row) { MDTable stateMachineMethodTable = StateMachineMethodTable; if (stateMachineMethodTable.IsInvalidRID(rid)) { row = default(RawStateMachineMethodRow); return false; } DataReader reader = stateMachineMethodTable.DataReader; reader.Position = (rid - 1) * (uint)stateMachineMethodTable.TableInfo.RowSize; row = new RawStateMachineMethodRow(stateMachineMethodTable.Column0.Unsafe_Read24(ref reader), stateMachineMethodTable.Column1.Unsafe_Read24(ref reader)); return true; } public bool TryReadCustomDebugInformationRow(uint rid, out RawCustomDebugInformationRow row) { MDTable customDebugInformationTable = CustomDebugInformationTable; if (customDebugInformationTable.IsInvalidRID(rid)) { row = default(RawCustomDebugInformationRow); return false; } DataReader reader = customDebugInformationTable.DataReader; reader.Position = (rid - 1) * (uint)customDebugInformationTable.TableInfo.RowSize; row = new RawCustomDebugInformationRow(customDebugInformationTable.Column0.Unsafe_Read24(ref reader), customDebugInformationTable.Column1.Unsafe_Read24(ref reader), customDebugInformationTable.Column2.Unsafe_Read24(ref reader)); return true; } public bool TryReadColumn(MDTable table, uint rid, int colIndex, out uint value) { return TryReadColumn(table, rid, table.TableInfo.Columns[colIndex], out value); } public bool TryReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value) { if (table.IsInvalidRID(rid)) { value = 0u; return false; } IColumnReader columnReader = this.columnReader; if (columnReader != null && columnReader.ReadColumn(table, rid, column, out value)) { return true; } DataReader reader = table.DataReader; reader.Position = (uint)((int)(rid - 1) * table.TableInfo.RowSize + column.Offset); value = column.Read(ref reader); return true; } internal bool TryReadColumn24(MDTable table, uint rid, int colIndex, out uint value) { return TryReadColumn24(table, rid, table.TableInfo.Columns[colIndex], out value); } internal bool TryReadColumn24(MDTable table, uint rid, ColumnInfo column, out uint value) { if (table.IsInvalidRID(rid)) { value = 0u; return false; } IColumnReader columnReader = this.columnReader; if (columnReader != null && columnReader.ReadColumn(table, rid, column, out value)) { return true; } DataReader dataReader = table.DataReader; dataReader.Position = (uint)((int)(rid - 1) * table.TableInfo.RowSize + column.Offset); value = ((column.Size == 2) ? dataReader.Unsafe_ReadUInt16() : dataReader.Unsafe_ReadUInt32()); return true; } } public sealed class USStream : HeapStream { public USStream() { } public USStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } public string Read(uint offset) { if (offset == 0) { return string.Empty; } if (!IsValidOffset(offset)) { return null; } DataReader dataReader = base.dataReader; dataReader.Position = offset; if (!dataReader.TryReadCompressedUInt32(out var value)) { return null; } if (!dataReader.CanRead(value)) { return null; } try { return dataReader.ReadUtf16String((int)(value / 2)); } catch (OutOfMemoryException) { throw; } catch { return string.Empty; } } public string ReadNoNull(uint offset) { return Read(offset) ?? string.Empty; } } } namespace dnlib.DotNet.Emit { public enum Code : ushort { UNKNOWN1 = 256, UNKNOWN2 = 257, Add = 88, Add_Ovf = 214, Add_Ovf_Un = 215, And = 95, Arglist = 65024, Beq = 59, Beq_S = 46, Bge = 60, Bge_S = 47, Bge_Un = 65, Bge_Un_S = 52, Bgt = 61, Bgt_S = 48, Bgt_Un = 66, Bgt_Un_S = 53, Ble = 62, Ble_S = 49, Ble_Un = 67, Ble_Un_S = 54, Blt = 63, Blt_S = 50, Blt_Un = 68, Blt_Un_S = 55, Bne_Un = 64, Bne_Un_S = 51, Box = 140, Br = 56, Br_S = 43, Break = 1, Brfalse = 57, Brfalse_S = 44, Brtrue = 58, Brtrue_S = 45, Call = 40, Calli = 41, Callvirt = 111, Castclass = 116, Ceq = 65025, Cgt = 65026, Cgt_Un = 65027, Ckfinite = 195, Clt = 65028, Clt_Un = 65029, Constrained = 65046, Conv_I = 211, Conv_I1 = 103, Conv_I2 = 104, Conv_I4 = 105, Conv_I8 = 106, Conv_Ovf_I = 212, Conv_Ovf_I_Un = 138, Conv_Ovf_I1 = 179, Conv_Ovf_I1_Un = 130, Conv_Ovf_I2 = 181, Conv_Ovf_I2_Un = 131, Conv_Ovf_I4 = 183, Conv_Ovf_I4_Un = 132, Conv_Ovf_I8 = 185, Conv_Ovf_I8_Un = 133, Conv_Ovf_U = 213, Conv_Ovf_U_Un = 139, Conv_Ovf_U1 = 180, Conv_Ovf_U1_Un = 134, Conv_Ovf_U2 = 182, Conv_Ovf_U2_Un = 135, Conv_Ovf_U4 = 184, Conv_Ovf_U4_Un = 136, Conv_Ovf_U8 = 186, Conv_Ovf_U8_Un = 137, Conv_R_Un = 118, Conv_R4 = 107, Conv_R8 = 108, Conv_U = 224, Conv_U1 = 210, Conv_U2 = 209, Conv_U4 = 109, Conv_U8 = 110, Cpblk = 65047, Cpobj = 112, Div = 91, Div_Un = 92, Dup = 37, Endfilter = 65041, Endfinally = 220, Initblk = 65048, Initobj = 65045, Isinst = 117, Jmp = 39, Ldarg = 65033, Ldarg_0 = 2, Ldarg_1 = 3, Ldarg_2 = 4, Ldarg_3 = 5, Ldarg_S = 14, Ldarga = 65034, Ldarga_S = 15, Ldc_I4 = 32, 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_M1 = 21, Ldc_I4_S = 31, Ldc_I8 = 33, Ldc_R4 = 34, Ldc_R8 = 35, Ldelem = 163, Ldelem_I = 151, Ldelem_I1 = 144, Ldelem_I2 = 146, Ldelem_I4 = 148, Ldelem_I8 = 150, Ldelem_R4 = 152, Ldelem_R8 = 153, Ldelem_Ref = 154, Ldelem_U1 = 145, Ldelem_U2 = 147, Ldelem_U4 = 149, Ldelema = 143, Ldfld = 123, Ldflda = 124, Ldftn = 65030, Ldind_I = 77, Ldind_I1 = 70, Ldind_I2 = 72, Ldind_I4 = 74, Ldind_I8 = 76, Ldind_R4 = 78, Ldind_R8 = 79, Ldind_Ref = 80, Ldind_U1 = 71, Ldind_U2 = 73, Ldind_U4 = 75, Ldlen = 142, Ldloc = 65036, Ldloc_0 = 6, Ldloc_1 = 7, Ldloc_2 = 8, Ldloc_3 = 9, Ldloc_S = 17, Ldloca = 65037, Ldloca_S = 18, Ldnull = 20, Ldobj = 113, Ldsfld = 126, Ldsflda = 127, Ldstr = 114, Ldtoken = 208, Ldvirtftn = 65031, Leave = 221, Leave_S = 222, Localloc = 65039, Mkrefany = 198, Mul = 90, Mul_Ovf = 216, Mul_Ovf_Un = 217, Neg = 101, Newarr = 141, Newobj = 115, No = 65049, Nop = 0, Not = 102, Or = 96, Pop = 38, Prefix1 = 254, Prefix2 = 253, Prefix3 = 252, Prefix4 = 251, Prefix5 = 250, Prefix6 = 249, Prefix7 = 248, Prefixref = 255, Readonly = 65054, Refanytype = 65053, Refanyval = 194, Rem = 93, Rem_Un = 94, Ret = 42, Rethrow = 65050, Shl = 98, Shr = 99, Shr_Un = 100, Sizeof = 65052, Starg = 65035, Starg_S = 16, Stelem = 164, Stelem_I = 155, Stelem_I1 = 156, Stelem_I2 = 157, Stelem_I4 = 158, Stelem_I8 = 159, Stelem_R4 = 160, Stelem_R8 = 161, Stelem_Ref = 162, Stfld = 125, Stind_I = 223, Stind_I1 = 82, Stind_I2 = 83, Stind_I4 = 84, Stind_I8 = 85, Stind_R4 = 86, Stind_R8 = 87, Stind_Ref = 81, Stloc = 65038, Stloc_0 = 10, Stloc_1 = 11, Stloc_2 = 12, Stloc_3 = 13, Stloc_S = 19, Stobj = 129, Stsfld = 128, Sub = 89, Sub_Ovf = 218, Sub_Ovf_Un = 219, Switch = 69, Tailcall = 65044, Throw = 122, Unaligned = 65042, Unbox = 121, Unbox_Any = 165, Volatile = 65043, Xor = 97 } public static class Extensions { public static bool IsExperimental(this Code code) { byte b = (byte)((int)code >> 8); if (b >= 240) { return b <= 251; } return false; } public static OpCode ToOpCode(this Code code) { byte b = (byte)((int)code >> 8); byte b2 = (byte)code; return b switch { 0 => OpCodes.OneByteOpCodes[b2], 254 => OpCodes.TwoByteOpCodes[b2], _ => code switch { Code.UNKNOWN1 => OpCodes.UNKNOWN1, Code.UNKNOWN2 => OpCodes.UNKNOWN2, _ => null, }, }; } public static OpCode ToOpCode(this Code code, ModuleContext context) { byte b = (byte)((int)code >> 8); byte b2 = (byte)code; switch (b) { case 0: return OpCodes.OneByteOpCodes[b2]; case 254: return OpCodes.TwoByteOpCodes[b2]; default: { OpCode experimentalOpCode = context.GetExperimentalOpCode(b, b2); if (experimentalOpCode != null) { return experimentalOpCode; } return code switch { Code.UNKNOWN1 => OpCodes.UNKNOWN1, Code.UNKNOWN2 => OpCodes.UNKNOWN2, _ => null, }; } } } public static OpCode GetOpCode(this Instruction self) { return self?.OpCode ?? OpCodes.UNKNOWN1; } public static object GetOperand(this Instruction self) { return self?.Operand; } public static uint GetOffset(this Instruction self) { return self?.Offset ?? 0; } public static SequencePoint GetSequencePoint(this Instruction self) { return self?.SequencePoint; } public static IMDTokenProvider ResolveToken(this IInstructionOperandResolver self, uint token) { return self.ResolveToken(token, default(GenericParamContext)); } } [Flags] public enum DynamicMethodBodyReaderOptions { None = 0, UnknownDeclaringType = 1 } public class DynamicMethodBodyReader : MethodBodyReaderBase, ISignatureReaderHelper { private class ReflectionFieldInfo { private FieldInfo fieldInfo; private readonly string fieldName1; private readonly string fieldName2; public ReflectionFieldInfo(string fieldName) { fieldName1 = fieldName; } public ReflectionFieldInfo(string fieldName1, string fieldName2) { this.fieldName1 = fieldName1; this.fieldName2 = fieldName2; } public object Read(object instance) { if ((object)fieldInfo == null) { InitializeField(instance.GetType()); } if ((object)fieldInfo == null) { throw new Exception($"Couldn't find field '{fieldName1}' or '{fieldName2}'"); } return fieldInfo.GetValue(instance); } public bool Exists(object instance) { InitializeField(instance.GetType()); return (object)fieldInfo != null; } private void InitializeField(Type type) { if ((object)fieldInfo == null) { fieldInfo = type.GetField(fieldName1, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)fieldInfo == null && fieldName2 != null) { fieldInfo = type.GetField(fieldName2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } } } private class ExceptionInfo { public int[] CatchAddr; public Type[] CatchClass; public int[] CatchEndAddr; public int CurrentCatch; public int[] Type; public int StartAddr; public int EndAddr; public int EndFinally; } private static readonly ReflectionFieldInfo rtdmOwnerFieldInfo = new ReflectionFieldInfo("m_owner"); private static readonly ReflectionFieldInfo dmResolverFieldInfo = new ReflectionFieldInfo("m_resolver", "_resolver"); private static readonly ReflectionFieldInfo rslvCodeFieldInfo = new ReflectionFieldInfo("m_code"); private static readonly ReflectionFieldInfo rslvDynamicScopeFieldInfo = new ReflectionFieldInfo("m_scope"); private static readonly ReflectionFieldInfo rslvMethodFieldInfo = new ReflectionFieldInfo("m_method"); private static readonly ReflectionFieldInfo rslvLocalsFieldInfo = new ReflectionFieldInfo("m_localSignature"); private static readonly ReflectionFieldInfo rslvMaxStackFieldInfo = new ReflectionFieldInfo("m_stackSize"); private static readonly ReflectionFieldInfo rslvExceptionsFieldInfo = new ReflectionFieldInfo("m_exceptions"); private static readonly ReflectionFieldInfo rslvExceptionHeaderFieldInfo = new ReflectionFieldInfo("m_exceptionHeader"); private static readonly ReflectionFieldInfo scopeTokensFieldInfo = new ReflectionFieldInfo("m_tokens"); private static readonly ReflectionFieldInfo gfiFieldHandleFieldInfo = new ReflectionFieldInfo("m_field", "m_fieldHandle"); private static readonly ReflectionFieldInfo gfiContextFieldInfo = new ReflectionFieldInfo("m_context"); private static readonly ReflectionFieldInfo gmiMethodHandleFieldInfo = new ReflectionFieldInfo("m_method", "m_methodHandle"); private static readonly ReflectionFieldInfo gmiContextFieldInfo = new ReflectionFieldInfo("m_context"); private static readonly ReflectionFieldInfo ehCatchAddrFieldInfo = new ReflectionFieldInfo("m_catchAddr"); private static readonly ReflectionFieldInfo ehCatchClassFieldInfo = new ReflectionFieldInfo("m_catchClass"); private static readonly ReflectionFieldInfo ehCatchEndAddrFieldInfo = new ReflectionFieldInfo("m_catchEndAddr"); private static readonly ReflectionFieldInfo ehCurrentCatchFieldInfo = new ReflectionFieldInfo("m_currentCatch"); private static readonly ReflectionFieldInfo ehTypeFieldInfo = new ReflectionFieldInfo("m_type"); private static readonly ReflectionFieldInfo ehStartAddrFieldInfo = new ReflectionFieldInfo("m_startAddr"); private static readonly ReflectionFieldInfo ehEndAddrFieldInfo = new ReflectionFieldInfo("m_endAddr"); private static readonly ReflectionFieldInfo ehEndFinallyFieldInfo = new ReflectionFieldInfo("m_endFinally"); private static readonly ReflectionFieldInfo vamMethodFieldInfo = new ReflectionFieldInfo("m_method"); private static readonly ReflectionFieldInfo vamDynamicMethodFieldInfo = new ReflectionFieldInfo("m_dynamicMethod"); private static readonly ReflectionFieldInfo dmDynamicILInfoFieldInfo = new ReflectionFieldInfo("m_DynamicILInfo", "_dynamicILInfo"); private static readonly ReflectionFieldInfo dynILInfoMaxStackFieldInfo = new ReflectionFieldInfo("m_maxStackSize"); private readonly ModuleDef module; private readonly Importer importer; private readonly GenericParamContext gpContext; private readonly MethodDef method; private readonly int codeSize; private readonly int maxStack; private readonly bool initLocals; private readonly List tokens; private readonly IList ehInfos; private readonly byte[] ehHeader; private readonly string methodName; private readonly DynamicMethodBodyReaderOptions options; public DynamicMethodBodyReader(ModuleDef module, object obj) : this(module, obj, default(GenericParamContext)) { } public DynamicMethodBodyReader(ModuleDef module, object obj, GenericParamContext gpContext) : this(module, obj, new Importer(module, ImporterOptions.TryToUseDefs, gpContext), DynamicMethodBodyReaderOptions.None) { } public DynamicMethodBodyReader(ModuleDef module, object obj, Importer importer) : this(module, obj, importer, DynamicMethodBodyReaderOptions.None) { } public DynamicMethodBodyReader(ModuleDef module, object obj, Importer importer, DynamicMethodBodyReaderOptions options) : base(module.Context) { this.module = module; this.importer = importer; this.options = options; gpContext = importer.gpContext; methodName = null; if (obj == null) { throw new ArgumentNullException("obj"); } if (obj is Delegate obj2) { obj = obj2.Method; if (obj == null) { throw new Exception("Delegate.Method is null"); } } if (obj.GetType().ToString() == "System.Reflection.Emit.DynamicMethod+RTDynamicMethod") { obj = rtdmOwnerFieldInfo.Read(obj) as DynamicMethod; if (obj == null) { throw new Exception("RTDynamicMethod.m_owner is null or invalid"); } } if (obj is DynamicMethod dynamicMethod) { methodName = dynamicMethod.Name; obj = dmResolverFieldInfo.Read(obj) ?? dmDynamicILInfoFieldInfo.Read(obj); if (obj == null) { throw new Exception("No resolver found"); } } string text = obj.GetType().ToString(); bool flag = text == "System.Reflection.Emit.DynamicILInfo"; if (text != "System.Reflection.Emit.DynamicResolver" && !flag) { throw new Exception("Couldn't find DynamicResolver or DynamicILInfo"); } if (!(rslvCodeFieldInfo.Read(obj) is byte[] array)) { throw new Exception("No code"); } codeSize = array.Length; if (!(rslvMethodFieldInfo.Read(obj) is DynamicMethod dynamicMethod2)) { throw new Exception("No method"); } initLocals = dynamicMethod2.InitLocals; maxStack = (flag ? ((int)dynILInfoMaxStackFieldInfo.Read(obj)) : ((int)rslvMaxStackFieldInfo.Read(obj))); object obj3 = rslvDynamicScopeFieldInfo.Read(obj); if (obj3 == null) { throw new Exception("No scope"); } if (!(scopeTokensFieldInfo.Read(obj3) is IList list)) { throw new Exception("No tokens"); } tokens = new List(list.Count); for (int i = 0; i < list.Count; i++) { tokens.Add(list[i]); } if (flag) { ehHeader = rslvExceptionsFieldInfo.Read(obj) as byte[]; } else { ehInfos = (IList)rslvExceptionsFieldInfo.Read(obj); ehHeader = rslvExceptionHeaderFieldInfo.Read(obj) as byte[]; } UpdateLocals(rslvLocalsFieldInfo.Read(obj) as byte[]); reader = ByteArrayDataReaderFactory.CreateReader(array); method = CreateMethodDef(dynamicMethod2); parameters = method.Parameters; } private static List CreateExceptionInfos(IList ehInfos) { if (ehInfos == null) { return new List(); } List list = new List(ehInfos.Count); int count = ehInfos.Count; for (int i = 0; i < count; i++) { object instance = ehInfos[i]; ExceptionInfo item = new ExceptionInfo { CatchAddr = (int[])ehCatchAddrFieldInfo.Read(instance), CatchClass = (Type[])ehCatchClassFieldInfo.Read(instance), CatchEndAddr = (int[])ehCatchEndAddrFieldInfo.Read(instance), CurrentCatch = (int)ehCurrentCatchFieldInfo.Read(instance), Type = (int[])ehTypeFieldInfo.Read(instance), StartAddr = (int)ehStartAddrFieldInfo.Read(instance), EndAddr = (int)ehEndAddrFieldInfo.Read(instance), EndFinally = (int)ehEndFinallyFieldInfo.Read(instance) }; list.Add(item); } return list; } private void UpdateLocals(byte[] localsSig) { if (localsSig != null && localsSig.Length != 0 && SignatureReader.ReadSig(this, module.CorLibTypes, localsSig, gpContext) is LocalSig { Locals: var list }) { int count = list.Count; for (int i = 0; i < count; i++) { locals.Add(new Local(list[i])); } } } private MethodDef CreateMethodDef(MethodBase delMethod) { MethodDefUser methodDefUser = new MethodDefUser(); TypeSig returnType = GetReturnType(delMethod); List list = GetParameters(delMethod); if (true) { methodDefUser.Signature = MethodSig.CreateStatic(returnType, list.ToArray()); } else { methodDefUser.Signature = MethodSig.CreateInstance(returnType, list.ToArray()); } methodDefUser.Parameters.UpdateParameterTypes(); methodDefUser.ImplAttributes = MethodImplAttributes.IL; methodDefUser.Attributes = MethodAttributes.PrivateScope; if (true) { methodDefUser.Attributes |= MethodAttributes.Static; } return module.UpdateRowId(methodDefUser); } private TypeSig GetReturnType(MethodBase mb) { if (mb is MethodInfo methodInfo) { return importer.ImportAsTypeSig(methodInfo.ReturnType); } return module.CorLibTypes.Void; } private List GetParameters(MethodBase delMethod) { List list = new List(); ParameterInfo[] array = delMethod.GetParameters(); foreach (ParameterInfo parameterInfo in array) { list.Add(importer.ImportAsTypeSig(parameterInfo.ParameterType)); } return list; } public bool Read() { ReadInstructionsNumBytes((uint)codeSize); CreateExceptionHandlers(); return true; } private void CreateExceptionHandlers() { if (ehHeader != null) { if (ehHeader.Length < 4) { return; } BinaryReader binaryReader = new BinaryReader(new MemoryStream(ehHeader)); if ((binaryReader.ReadByte() & 0x40) == 0) { int num = (ushort)((binaryReader.ReadByte() - 2) / 12); binaryReader.ReadUInt16(); for (int i = 0; i < num; i++) { if (binaryReader.BaseStream.Position + 12 > binaryReader.BaseStream.Length) { break; } ExceptionHandler exceptionHandler = new ExceptionHandler(); exceptionHandler.HandlerType = (ExceptionHandlerType)binaryReader.ReadUInt16(); int num2 = binaryReader.ReadUInt16(); exceptionHandler.TryStart = GetInstructionThrow((uint)num2); exceptionHandler.TryEnd = GetInstruction((uint)(binaryReader.ReadByte() + num2)); num2 = binaryReader.ReadUInt16(); exceptionHandler.HandlerStart = GetInstructionThrow((uint)num2); exceptionHandler.HandlerEnd = GetInstruction((uint)(binaryReader.ReadByte() + num2)); if (exceptionHandler.IsCatch) { exceptionHandler.CatchType = ReadToken(binaryReader.ReadUInt32()) as ITypeDefOrRef; } else if (exceptionHandler.IsFilter) { exceptionHandler.FilterStart = GetInstruction(binaryReader.ReadUInt32()); } else { binaryReader.ReadUInt32(); } exceptionHandlers.Add(exceptionHandler); } return; } binaryReader.BaseStream.Position--; int num3 = (ushort)(((binaryReader.ReadUInt32() >> 8) - 4) / 24); for (int j = 0; j < num3; j++) { if (binaryReader.BaseStream.Position + 24 > binaryReader.BaseStream.Length) { break; } ExceptionHandler exceptionHandler2 = new ExceptionHandler(); exceptionHandler2.HandlerType = (ExceptionHandlerType)binaryReader.ReadUInt32(); uint num4 = binaryReader.ReadUInt32(); exceptionHandler2.TryStart = GetInstructionThrow(num4); exceptionHandler2.TryEnd = GetInstruction(binaryReader.ReadUInt32() + num4); num4 = binaryReader.ReadUInt32(); exceptionHandler2.HandlerStart = GetInstructionThrow(num4); exceptionHandler2.HandlerEnd = GetInstruction(binaryReader.ReadUInt32() + num4); if (exceptionHandler2.IsCatch) { exceptionHandler2.CatchType = ReadToken(binaryReader.ReadUInt32()) as ITypeDefOrRef; } else if (exceptionHandler2.IsFilter) { exceptionHandler2.FilterStart = GetInstruction(binaryReader.ReadUInt32()); } else { binaryReader.ReadUInt32(); } exceptionHandlers.Add(exceptionHandler2); } } else { if (ehInfos == null) { return; } foreach (ExceptionInfo item in CreateExceptionInfos(ehInfos)) { Instruction instructionThrow = GetInstructionThrow((uint)item.StartAddr); Instruction instruction = GetInstruction((uint)item.EndAddr); Instruction instruction2 = ((item.EndFinally < 0) ? null : GetInstruction((uint)item.EndFinally)); for (int k = 0; k < item.CurrentCatch; k++) { ExceptionHandler exceptionHandler3 = new ExceptionHandler(); exceptionHandler3.HandlerType = (ExceptionHandlerType)item.Type[k]; exceptionHandler3.TryStart = instructionThrow; exceptionHandler3.TryEnd = (exceptionHandler3.IsFinally ? instruction2 : instruction); exceptionHandler3.FilterStart = null; exceptionHandler3.HandlerStart = GetInstructionThrow((uint)item.CatchAddr[k]); exceptionHandler3.HandlerEnd = GetInstruction((uint)item.CatchEndAddr[k]); exceptionHandler3.CatchType = importer.Import(item.CatchClass[k]); exceptionHandlers.Add(exceptionHandler3); } } } } public MethodDef GetMethod() { CilBody cilBody = new CilBody(initLocals, instructions, exceptionHandlers, locals); cilBody.MaxStack = (ushort)Math.Min(maxStack, 65535); instructions = null; exceptionHandlers = null; locals = null; method.Body = cilBody; method.Name = methodName; return method; } protected override IField ReadInlineField(Instruction instr) { return ReadToken(reader.ReadUInt32()) as IField; } protected override IMethod ReadInlineMethod(Instruction instr) { return ReadToken(reader.ReadUInt32()) as IMethod; } protected override MethodSig ReadInlineSig(Instruction instr) { return ReadToken(reader.ReadUInt32()) as MethodSig; } protected override string ReadInlineString(Instruction instr) { return (ReadToken(reader.ReadUInt32()) as string) ?? string.Empty; } protected override ITokenOperand ReadInlineTok(Instruction instr) { return ReadToken(reader.ReadUInt32()) as ITokenOperand; } protected override ITypeDefOrRef ReadInlineType(Instruction instr) { return ReadToken(reader.ReadUInt32()) as ITypeDefOrRef; } private object ReadToken(uint token) { uint num = token & 0xFFFFFF; switch (token >> 24) { case 2u: return ImportType(num); case 4u: return ImportField(num); case 6u: case 10u: return ImportMethod(num); case 17u: return ImportSignature(num); case 112u: return Resolve(num) as string; default: return null; } } private IMethod ImportMethod(uint rid) { object obj = Resolve(rid); if (obj == null) { return null; } if (obj is RuntimeMethodHandle) { if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != DynamicMethodBodyReaderOptions.None) { return importer.Import(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj, default(RuntimeTypeHandle))); } return importer.Import(MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj)); } if (obj.GetType().ToString() == "System.Reflection.Emit.GenericMethodInfo") { RuntimeTypeHandle declaringType = (RuntimeTypeHandle)gmiContextFieldInfo.Read(obj); MethodBase methodFromHandle = MethodBase.GetMethodFromHandle((RuntimeMethodHandle)gmiMethodHandleFieldInfo.Read(obj), declaringType); return importer.Import(methodFromHandle); } if (obj.GetType().ToString() == "System.Reflection.Emit.VarArgMethod") { MethodInfo varArgMethod = GetVarArgMethod(obj); if (!(varArgMethod is DynamicMethod)) { return importer.Import(varArgMethod); } obj = varArgMethod; } if (obj is DynamicMethod) { throw new Exception("DynamicMethod calls another DynamicMethod"); } return null; } private MethodInfo GetVarArgMethod(object obj) { if (vamDynamicMethodFieldInfo.Exists(obj)) { MethodInfo methodInfo = vamMethodFieldInfo.Read(obj) as MethodInfo; return (vamDynamicMethodFieldInfo.Read(obj) as DynamicMethod) ?? methodInfo; } return vamMethodFieldInfo.Read(obj) as MethodInfo; } private IField ImportField(uint rid) { object obj = Resolve(rid); if (obj == null) { return null; } if (obj is RuntimeFieldHandle) { if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != DynamicMethodBodyReaderOptions.None) { return importer.Import(FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj, default(RuntimeTypeHandle))); } return importer.Import(FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj)); } if (obj.GetType().ToString() == "System.Reflection.Emit.GenericFieldInfo") { RuntimeTypeHandle declaringType = (RuntimeTypeHandle)gfiContextFieldInfo.Read(obj); FieldInfo fieldFromHandle = FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)gfiFieldHandleFieldInfo.Read(obj), declaringType); return importer.Import(fieldFromHandle); } return null; } private ITypeDefOrRef ImportType(uint rid) { object obj = Resolve(rid); if (obj is RuntimeTypeHandle) { return importer.Import(Type.GetTypeFromHandle((RuntimeTypeHandle)obj)); } return null; } private CallingConventionSig ImportSignature(uint rid) { if (!(Resolve(rid) is byte[] signature)) { return null; } return SignatureReader.ReadSig(this, module.CorLibTypes, signature, gpContext); } private object Resolve(uint index) { if (index >= (uint)tokens.Count) { return null; } return tokens[(int)index]; } public override void RestoreMethod(MethodDef method) { base.RestoreMethod(method); CilBody body = method.Body; body.InitLocals = initLocals; body.MaxStack = (ushort)Math.Min(maxStack, 65535); } ITypeDefOrRef ISignatureReaderHelper.ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { if (!CodedToken.TypeDefOrRef.Decode(codedToken, out uint token)) { return null; } Table table = MDToken.ToTable(token); if (table - 1 <= Table.TypeRef || table == Table.TypeSpec) { return module.ResolveToken(token) as ITypeDefOrRef; } return null; } TypeSig ISignatureReaderHelper.ConvertRTInternalAddress(IntPtr address) { return importer.ImportAsTypeSig(MethodTableToTypeConverter.Convert(address)); } } public sealed class ExceptionHandler { public Instruction TryStart; public Instruction TryEnd; public Instruction FilterStart; public Instruction HandlerStart; public Instruction HandlerEnd; public ITypeDefOrRef CatchType; public ExceptionHandlerType HandlerType; public bool IsCatch => (HandlerType & (ExceptionHandlerType.Filter | ExceptionHandlerType.Finally | ExceptionHandlerType.Fault)) == 0; public bool IsFilter => (HandlerType & ExceptionHandlerType.Filter) != 0; public bool IsFinally => (HandlerType & ExceptionHandlerType.Finally) != 0; public bool IsFault => (HandlerType & ExceptionHandlerType.Fault) != 0; public ExceptionHandler() { } public ExceptionHandler(ExceptionHandlerType handlerType) { HandlerType = handlerType; } } [Flags] public enum ExceptionHandlerType { Catch = 0, Filter = 1, Finally = 2, Fault = 4, Duplicated = 8 } public enum FlowControl { Branch, Break, Call, Cond_Branch, Meta, Next, Phi, Return, Throw } public sealed class Instruction { public OpCode OpCode; public object Operand; public uint Offset; public SequencePoint SequencePoint; public Instruction() { } public Instruction(OpCode opCode) { OpCode = opCode; } public Instruction(OpCode opCode, object operand) { OpCode = opCode; Operand = operand; } public static Instruction Create(OpCode opCode) { if (opCode.OperandType != OperandType.InlineNone) { throw new ArgumentException("Must be a no-operand opcode", "opCode"); } return new Instruction(opCode); } public static Instruction Create(OpCode opCode, byte value) { if (opCode.Code != Code.Unaligned) { throw new ArgumentException("Opcode does not have a byte operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, sbyte value) { if (opCode.Code != Code.Ldc_I4_S) { throw new ArgumentException("Opcode does not have a sbyte operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, int value) { if (opCode.OperandType != OperandType.InlineI) { throw new ArgumentException("Opcode does not have an int32 operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, long value) { if (opCode.OperandType != OperandType.InlineI8) { throw new ArgumentException("Opcode does not have an int64 operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, float value) { if (opCode.OperandType != OperandType.ShortInlineR) { throw new ArgumentException("Opcode does not have a real4 operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, double value) { if (opCode.OperandType != OperandType.InlineR) { throw new ArgumentException("Opcode does not have a real8 operand", "opCode"); } return new Instruction(opCode, value); } public static Instruction Create(OpCode opCode, string s) { if (opCode.OperandType != OperandType.InlineString) { throw new ArgumentException("Opcode does not have a string operand", "opCode"); } return new Instruction(opCode, s); } public static Instruction Create(OpCode opCode, Instruction target) { if (opCode.OperandType != OperandType.ShortInlineBrTarget && opCode.OperandType != OperandType.InlineBrTarget) { throw new ArgumentException("Opcode does not have an instruction operand", "opCode"); } return new Instruction(opCode, target); } public static Instruction Create(OpCode opCode, IList targets) { if (opCode.OperandType != OperandType.InlineSwitch) { throw new ArgumentException("Opcode does not have a targets array operand", "opCode"); } return new Instruction(opCode, targets); } public static Instruction Create(OpCode opCode, ITypeDefOrRef type) { if (opCode.OperandType != OperandType.InlineType && opCode.OperandType != OperandType.InlineTok) { throw new ArgumentException("Opcode does not have a type operand", "opCode"); } return new Instruction(opCode, type); } public static Instruction Create(OpCode opCode, CorLibTypeSig type) { return Create(opCode, type.TypeDefOrRef); } public static Instruction Create(OpCode opCode, MemberRef mr) { if (opCode.OperandType != OperandType.InlineField && opCode.OperandType != OperandType.InlineMethod && opCode.OperandType != OperandType.InlineTok) { throw new ArgumentException("Opcode does not have a field operand", "opCode"); } return new Instruction(opCode, mr); } public static Instruction Create(OpCode opCode, IField field) { if (opCode.OperandType != OperandType.InlineField && opCode.OperandType != OperandType.InlineTok) { throw new ArgumentException("Opcode does not have a field operand", "opCode"); } return new Instruction(opCode, field); } public static Instruction Create(OpCode opCode, IMethod method) { if (opCode.OperandType != OperandType.InlineMethod && opCode.OperandType != OperandType.InlineTok) { throw new ArgumentException("Opcode does not have a method operand", "opCode"); } return new Instruction(opCode, method); } public static Instruction Create(OpCode opCode, ITokenOperand token) { if (opCode.OperandType != OperandType.InlineTok) { throw new ArgumentException("Opcode does not have a token operand", "opCode"); } return new Instruction(opCode, token); } public static Instruction Create(OpCode opCode, MethodSig methodSig) { if (opCode.OperandType != OperandType.InlineSig) { throw new ArgumentException("Opcode does not have a method sig operand", "opCode"); } return new Instruction(opCode, methodSig); } public static Instruction Create(OpCode opCode, Parameter parameter) { if (opCode.OperandType != OperandType.ShortInlineVar && opCode.OperandType != OperandType.InlineVar) { throw new ArgumentException("Opcode does not have a method parameter operand", "opCode"); } return new Instruction(opCode, parameter); } public static Instruction Create(OpCode opCode, Local local) { if (opCode.OperandType != OperandType.ShortInlineVar && opCode.OperandType != OperandType.InlineVar) { throw new ArgumentException("Opcode does not have a method local operand", "opCode"); } return new Instruction(opCode, local); } public static Instruction CreateLdcI4(int value) { switch (value) { case -1: return OpCodes.Ldc_I4_M1.ToInstruction(); case 0: return OpCodes.Ldc_I4_0.ToInstruction(); case 1: return OpCodes.Ldc_I4_1.ToInstruction(); case 2: return OpCodes.Ldc_I4_2.ToInstruction(); case 3: return OpCodes.Ldc_I4_3.ToInstruction(); case 4: return OpCodes.Ldc_I4_4.ToInstruction(); case 5: return OpCodes.Ldc_I4_5.ToInstruction(); case 6: return OpCodes.Ldc_I4_6.ToInstruction(); case 7: return OpCodes.Ldc_I4_7.ToInstruction(); case 8: return OpCodes.Ldc_I4_8.ToInstruction(); default: if (-128 <= value && value <= 127) { return new Instruction(OpCodes.Ldc_I4_S, (sbyte)value); } return new Instruction(OpCodes.Ldc_I4, value); } } public int GetSize() { OpCode opCode = OpCode; switch (opCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.InlineField: case OperandType.InlineI: case OperandType.InlineMethod: case OperandType.InlineSig: case OperandType.InlineString: case OperandType.InlineTok: case OperandType.InlineType: case OperandType.ShortInlineR: return opCode.Size + 4; case OperandType.InlineI8: case OperandType.InlineR: return opCode.Size + 8; default: return opCode.Size; case OperandType.InlineSwitch: { IList list = Operand as IList; return opCode.Size + 4 + ((list != null) ? (list.Count * 4) : 0); } case OperandType.InlineVar: return opCode.Size + 2; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineVar: return opCode.Size + 1; } } private static bool IsSystemVoid(TypeSig type) { return type.RemovePinnedAndModifiers().GetElementType() == ElementType.Void; } public void UpdateStack(ref int stack) { UpdateStack(ref stack, methodHasReturnValue: false); } public void UpdateStack(ref int stack, bool methodHasReturnValue) { CalculateStackUsage(methodHasReturnValue, out var pushes, out var pops); if (pops == -1) { stack = 0; } else { stack += pushes - pops; } } public void CalculateStackUsage(out int pushes, out int pops) { CalculateStackUsage(methodHasReturnValue: false, out pushes, out pops); } public void CalculateStackUsage(bool methodHasReturnValue, out int pushes, out int pops) { OpCode opCode = OpCode; if (opCode.FlowControl == FlowControl.Call) { CalculateStackUsageCall(opCode.Code, out pushes, out pops); } else { CalculateStackUsageNonCall(opCode, methodHasReturnValue, out pushes, out pops); } } private void CalculateStackUsageCall(Code code, out int pushes, out int pops) { pushes = 0; pops = 0; if (code == Code.Jmp) { return; } object operand = Operand; MethodSig methodSig = ((!(operand is IMethod method)) ? (operand as MethodSig) : method.MethodSig); if (methodSig != null) { bool implicitThis = methodSig.ImplicitThis; if (!IsSystemVoid(methodSig.RetType) || (code == Code.Newobj && methodSig.HasThis)) { pushes++; } pops += methodSig.Params.Count; IList paramsAfterSentinel = methodSig.ParamsAfterSentinel; if (paramsAfterSentinel != null) { pops += paramsAfterSentinel.Count; } if (implicitThis && code != Code.Newobj) { pops++; } if (code == Code.Calli) { pops++; } } } private void CalculateStackUsageNonCall(OpCode opCode, bool hasReturnValue, out int pushes, out int pops) { switch (opCode.StackBehaviourPush) { case StackBehaviour.Push0: pushes = 0; break; case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: pushes = 1; break; case StackBehaviour.Push1_push1: pushes = 2; break; default: pushes = 0; break; } switch (opCode.StackBehaviourPop) { case StackBehaviour.Pop0: pops = 0; break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: pops = 1; break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: pops = 2; break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_popi: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: case StackBehaviour.Popref_popi_pop1: pops = 3; break; case StackBehaviour.PopAll: pops = -1; break; case StackBehaviour.Varpop: if (hasReturnValue) { pops = 1; } else { pops = 0; } break; default: pops = 0; break; } } public bool IsLeave() { if (OpCode != OpCodes.Leave) { return OpCode == OpCodes.Leave_S; } return true; } public bool IsBr() { if (OpCode != OpCodes.Br) { return OpCode == OpCodes.Br_S; } return true; } public bool IsBrfalse() { if (OpCode != OpCodes.Brfalse) { return OpCode == OpCodes.Brfalse_S; } return true; } public bool IsBrtrue() { if (OpCode != OpCodes.Brtrue) { return OpCode == OpCodes.Brtrue_S; } return true; } public bool IsConditionalBranch() { Code code = OpCode.Code; if (code - 44 <= Code.Stloc_1 || code - 57 <= Code.Stloc_1) { return true; } return false; } public bool IsLdcI4() { Code code = OpCode.Code; if (code - 21 <= Code.Stloc_1) { return true; } return false; } public int GetLdcI4Value() { return OpCode.Code switch { Code.Ldc_I4_M1 => -1, Code.Ldc_I4_0 => 0, Code.Ldc_I4_1 => 1, Code.Ldc_I4_2 => 2, Code.Ldc_I4_3 => 3, Code.Ldc_I4_4 => 4, Code.Ldc_I4_5 => 5, Code.Ldc_I4_6 => 6, Code.Ldc_I4_7 => 7, Code.Ldc_I4_8 => 8, Code.Ldc_I4_S => (sbyte)Operand, Code.Ldc_I4 => (int)Operand, _ => throw new InvalidOperationException($"Not a ldc.i4 instruction: {this}"), }; } public bool IsLdarg() { Code code = OpCode.Code; if (code - 2 <= Code.Ldarg_1 || code == Code.Ldarg_S || code == Code.Ldarg) { return true; } return false; } public bool IsLdloc() { Code code = OpCode.Code; if (code - 6 <= Code.Ldarg_1 || code == Code.Ldloc_S || code == Code.Ldloc) { return true; } return false; } public bool IsStarg() { Code code = OpCode.Code; if (code == Code.Starg_S || code == Code.Starg) { return true; } return false; } public bool IsStloc() { Code code = OpCode.Code; if (code - 10 <= Code.Ldarg_1 || code == Code.Stloc_S || code == Code.Stloc) { return true; } return false; } public Local GetLocal(IList locals) { Code code = OpCode.Code; int num; switch (code) { case Code.Ldloc_S: case Code.Ldloca_S: case Code.Stloc_S: case Code.Ldloc: case Code.Ldloca: case Code.Stloc: return Operand as Local; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: num = (int)(code - 6); break; case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: num = (int)(code - 10); break; default: return null; } if ((uint)num < (uint)locals.Count) { return locals[num]; } return null; } public int GetParameterIndex() { switch (OpCode.Code) { case Code.Ldarg_0: return 0; case Code.Ldarg_1: return 1; case Code.Ldarg_2: return 2; case Code.Ldarg_3: return 3; case Code.Ldarg_S: case Code.Ldarga_S: case Code.Starg_S: case Code.Ldarg: case Code.Ldarga: case Code.Starg: if (Operand is Parameter parameter) { return parameter.Index; } break; } return -1; } public Parameter GetParameter(IList parameters) { int parameterIndex = GetParameterIndex(); if ((uint)parameterIndex < (uint)parameters.Count) { return parameters[parameterIndex]; } return null; } public TypeSig GetArgumentType(MethodSig methodSig, ITypeDefOrRef declaringType) { if (methodSig == null) { return null; } int num = GetParameterIndex(); if (num == 0 && methodSig.ImplicitThis) { if (declaringType == null) { return null; } TypeSig typeSig; bool isValueType; if (declaringType is TypeSpec typeSpec) { typeSig = typeSpec.TypeSig; isValueType = typeSig.IsValueType; } else { TypeDef typeDef = declaringType.ResolveTypeDef(); if (typeDef == null) { return declaringType.ToTypeSig(); } isValueType = typeDef.IsValueType; ClassOrValueTypeSig classOrValueTypeSig = (isValueType ? ((ClassOrValueTypeSig)new ValueTypeSig(typeDef)) : ((ClassOrValueTypeSig)new ClassSig(typeDef))); if (typeDef.HasGenericParameters) { int count = typeDef.GenericParameters.Count; List list = new List(count); for (int i = 0; i < count; i++) { list.Add(new GenericVar(i, typeDef)); } typeSig = new GenericInstSig(classOrValueTypeSig, list); } else { typeSig = classOrValueTypeSig; } } if (!isValueType) { return typeSig; } return new ByRefSig(typeSig); } if (methodSig.ImplicitThis) { num--; } if ((uint)num < (uint)methodSig.Params.Count) { return methodSig.Params[num]; } return null; } public Instruction Clone() { return new Instruction { Offset = Offset, OpCode = OpCode, Operand = Operand, SequencePoint = SequencePoint }; } public override string ToString() { return InstructionPrinter.ToString(this); } } public static class InstructionPrinter { public static string ToString(Instruction instr) { if (instr == null) { return string.Empty; } StringBuilder stringBuilder2; StringBuilder stringBuilder = (stringBuilder2 = new StringBuilder()); StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(5, 1, stringBuilder2); handler.AppendLiteral("IL_"); handler.AppendFormatted(instr.Offset, "X4"); handler.AppendLiteral(": "); stringBuilder2.Append(ref handler); stringBuilder.Append(instr.OpCode.Name); AddOperandString(stringBuilder, instr, " "); return stringBuilder.ToString(); } public static string GetOperandString(Instruction instr) { StringBuilder stringBuilder = new StringBuilder(); AddOperandString(stringBuilder, instr, string.Empty); return stringBuilder.ToString(); } public static void AddOperandString(StringBuilder sb, Instruction instr) { AddOperandString(sb, instr, string.Empty); } public static void AddOperandString(StringBuilder sb, Instruction instr, string extra) { object operand = instr.Operand; switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: sb.Append(extra); AddInstructionTarget(sb, operand as Instruction); break; case OperandType.InlineField: case OperandType.InlineMethod: case OperandType.InlineTok: case OperandType.InlineType: sb.Append(extra); if (operand is IFullName) { sb.Append((operand as IFullName).FullName); } else if (operand != null) { sb.Append(operand.ToString()); } else { sb.Append("null"); } break; case OperandType.InlineI: case OperandType.InlineI8: case OperandType.InlineR: case OperandType.ShortInlineI: case OperandType.ShortInlineR: { StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(0, 2, sb); handler.AppendFormatted(extra); handler.AppendFormatted(operand); sb.Append(ref handler); break; } case OperandType.InlineSig: sb.Append(extra); FullNameFactory.MethodFullNameSB(null, (UTF8String)null, operand as MethodSig, null, null, null, sb); break; case OperandType.InlineString: sb.Append(extra); EscapeString(sb, operand as string, addQuotes: true); break; case OperandType.InlineSwitch: { if (!(operand is IList list)) { sb.Append("null"); break; } sb.Append('('); for (int i = 0; i < list.Count; i++) { if (i != 0) { sb.Append(','); } AddInstructionTarget(sb, list[i]); } sb.Append(')'); break; } case OperandType.InlineVar: case OperandType.ShortInlineVar: sb.Append(extra); if (operand == null) { sb.Append("null"); } else { sb.Append(operand.ToString()); } break; case OperandType.InlineNone: case OperandType.InlinePhi: case OperandType.NOT_USED_8: break; } } private static void AddInstructionTarget(StringBuilder sb, Instruction targetInstr) { if (targetInstr == null) { sb.Append("null"); return; } StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, sb); handler.AppendLiteral("IL_"); handler.AppendFormatted(targetInstr.Offset, "X4"); sb.Append(ref handler); } private static void EscapeString(StringBuilder sb, string s, bool addQuotes) { if (s == null) { sb.Append("null"); return; } if (addQuotes) { sb.Append('"'); } foreach (char c in s) { if (c < ' ') { switch (c) { case '\a': sb.Append("\\a"); continue; case '\b': sb.Append("\\b"); continue; case '\f': sb.Append("\\f"); continue; case '\n': sb.Append("\\n"); continue; case '\r': sb.Append("\\r"); continue; case '\t': sb.Append("\\t"); continue; case '\v': sb.Append("\\v"); continue; } StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, sb); handler.AppendLiteral("\\u"); handler.AppendFormatted((int)c, "X4"); sb.Append(ref handler); } else if (c == '\\' || c == '"') { sb.Append('\\'); sb.Append(c); } else { sb.Append(c); } } if (addQuotes) { sb.Append('"'); } } } [Serializable] public class InvalidMethodException : Exception { public InvalidMethodException() { } public InvalidMethodException(string msg) : base(msg) { } public InvalidMethodException(string msg, Exception innerException) : base(msg, innerException) { } protected InvalidMethodException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(LocalList_CollectionDebugView))] public sealed class LocalList : IListListener, IList, ICollection, IEnumerable, IEnumerable { private readonly LazyList locals; public int Count => locals.Count; public IList Locals => locals; public Local this[int index] { get { return locals[index]; } set { locals[index] = value; } } public bool IsReadOnly => false; public LocalList() { locals = new LazyList(this); } public LocalList(IList locals) { this.locals = new LazyList(this); for (int i = 0; i < locals.Count; i++) { this.locals.Add(locals[i]); } } public Local Add(Local local) { locals.Add(local); return local; } void IListListener.OnLazyAdd(int index, ref Local value) { } void IListListener.OnAdd(int index, Local value) { value.Index = index; } void IListListener.OnRemove(int index, Local value) { value.Index = -1; } void IListListener.OnResize(int index) { for (int i = index; i < locals.Count_NoLock; i++) { locals.Get_NoLock(i).Index = i; } } void IListListener.OnClear() { foreach (Local item in locals.GetEnumerable_NoLock()) { item.Index = -1; } } public int IndexOf(Local item) { return locals.IndexOf(item); } public void Insert(int index, Local item) { locals.Insert(index, item); } public void RemoveAt(int index) { locals.RemoveAt(index); } void ICollection.Add(Local item) { locals.Add(item); } public void Clear() { locals.Clear(); } public bool Contains(Local item) { return locals.Contains(item); } public void CopyTo(Local[] array, int arrayIndex) { locals.CopyTo(array, arrayIndex); } public bool Remove(Local item) { return locals.Remove(item); } public LazyList.Enumerator GetEnumerator() { return locals.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return locals.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } public sealed class Local : IVariable { private TypeSig typeSig; private int index; private string name; private PdbLocalAttributes attributes; public TypeSig Type { get { return typeSig; } set { typeSig = value; } } public int Index { get { return index; } internal set { index = value; } } public string Name { get { return name; } set { name = value; } } public PdbLocalAttributes Attributes { get { return attributes; } set { attributes = value; } } internal void SetName(string name) { this.name = name; } internal void SetAttributes(PdbLocalAttributes attributes) { this.attributes = attributes; } public Local(TypeSig typeSig) { this.typeSig = typeSig; } public Local(TypeSig typeSig, string name) { this.typeSig = typeSig; this.name = name; } public Local(TypeSig typeSig, string name, int index) { this.typeSig = typeSig; this.name = name; this.index = index; } public override string ToString() { string text = name; if (string.IsNullOrEmpty(text)) { return $"V_{Index}"; } return text; } } public abstract class MethodBody { } public sealed class NativeMethodBody : MethodBody { private RVA rva; public RVA RVA { get { return rva; } set { rva = value; } } public NativeMethodBody() { } public NativeMethodBody(RVA rva) { this.rva = rva; } } public sealed class CilBody : MethodBody { private bool keepOldMaxStack; private bool initLocals; private byte headerSize; private ushort maxStack; private uint localVarSigTok; private readonly IList instructions; private readonly IList exceptionHandlers; private readonly LocalList localList; public const byte SMALL_HEADER_SIZE = 1; private PdbMethod pdbMethod; public bool KeepOldMaxStack { get { return keepOldMaxStack; } set { keepOldMaxStack = value; } } public bool InitLocals { get { return initLocals; } set { initLocals = value; } } public byte HeaderSize { get { return headerSize; } set { headerSize = value; } } public bool IsSmallHeader => headerSize == 1; public bool IsBigHeader => headerSize != 1; public ushort MaxStack { get { return maxStack; } set { maxStack = value; } } public uint LocalVarSigTok { get { return localVarSigTok; } set { localVarSigTok = value; } } public bool HasInstructions => instructions.Count > 0; public IList Instructions => instructions; public bool HasExceptionHandlers => exceptionHandlers.Count > 0; public IList ExceptionHandlers => exceptionHandlers; public bool HasVariables => localList.Count > 0; public LocalList Variables => localList; public PdbMethod PdbMethod { get { return pdbMethod; } set { pdbMethod = value; } } public bool HasPdbMethod => PdbMethod != null; internal uint MetadataBodySize { get; set; } public CilBody() { initLocals = true; instructions = new List(); exceptionHandlers = new List(); localList = new LocalList(); } public CilBody(bool initLocals, IList instructions, IList exceptionHandlers, IList locals) { this.initLocals = initLocals; this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; localList = new LocalList(locals); } public void SimplifyMacros(IList parameters) { instructions.SimplifyMacros(localList, parameters); } public void OptimizeMacros() { instructions.OptimizeMacros(); } public void SimplifyBranches() { instructions.SimplifyBranches(); } public void OptimizeBranches() { instructions.OptimizeBranches(); } public uint UpdateInstructionOffsets() { return instructions.UpdateInstructionOffsets(); } } public interface IStringResolver { string ReadUserString(uint token); } public interface IInstructionOperandResolver : ITokenResolver, IStringResolver { } public sealed class MethodBodyReader : MethodBodyReaderBase { private readonly IInstructionOperandResolver opResolver; private bool hasReadHeader; private byte headerSize; private ushort flags; private ushort maxStack; private uint codeSize; private uint localVarSigTok; private uint startOfHeader; private uint totalBodySize; private DataReader? exceptionsReader; private readonly GenericParamContext gpContext; public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader reader, MethodDef method) { return CreateCilBody(opResolver, reader, null, method.Parameters, default(GenericParamContext)); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader reader, MethodDef method, GenericParamContext gpContext) { return CreateCilBody(opResolver, reader, null, method.Parameters, gpContext); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader reader, IList parameters) { return CreateCilBody(opResolver, reader, null, parameters, default(GenericParamContext)); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader reader, IList parameters, GenericParamContext gpContext) { return CreateCilBody(opResolver, reader, null, parameters, gpContext); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader reader, IList parameters, GenericParamContext gpContext, ModuleContext context) { return CreateCilBody(opResolver, reader, null, parameters, gpContext, context); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters) { return CreateCilBody(opResolver, ByteArrayDataReaderFactory.CreateReader(code), (exceptions == null) ? ((DataReader?)null) : new DataReader?(ByteArrayDataReaderFactory.CreateReader(exceptions)), parameters, default(GenericParamContext)); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, GenericParamContext gpContext) { return CreateCilBody(opResolver, ByteArrayDataReaderFactory.CreateReader(code), (exceptions == null) ? ((DataReader?)null) : new DataReader?(ByteArrayDataReaderFactory.CreateReader(exceptions)), parameters, gpContext); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters) { return CreateCilBody(opResolver, codeReader, ehReader, parameters, default(GenericParamContext)); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters, GenericParamContext gpContext) { return CreateCilBody(opResolver, codeReader, ehReader, parameters, gpContext, null); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters, GenericParamContext gpContext, ModuleContext context) { MethodBodyReader methodBodyReader = new MethodBodyReader(opResolver, codeReader, ehReader, parameters, gpContext, context); if (!methodBodyReader.Read()) { return new CilBody(); } return methodBodyReader.CreateCilBody(); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok) { return CreateCilBody(opResolver, code, exceptions, parameters, flags, maxStack, codeSize, localVarSigTok, default(GenericParamContext)); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok, GenericParamContext gpContext) { return CreateCilBody(opResolver, code, exceptions, parameters, flags, maxStack, codeSize, localVarSigTok, gpContext, null); } public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok, GenericParamContext gpContext, ModuleContext context) { DataReader codeReader = ByteArrayDataReaderFactory.CreateReader(code); DataReader? ehReader = ((exceptions == null) ? ((DataReader?)null) : new DataReader?(ByteArrayDataReaderFactory.CreateReader(exceptions))); MethodBodyReader methodBodyReader = new MethodBodyReader(opResolver, codeReader, ehReader, parameters, gpContext, context); methodBodyReader.SetHeader(flags, maxStack, codeSize, localVarSigTok); if (!methodBodyReader.Read()) { return new CilBody(); } return methodBodyReader.CreateCilBody(); } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader reader, MethodDef method) : this(opResolver, reader, null, method.Parameters, default(GenericParamContext)) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader reader, MethodDef method, GenericParamContext gpContext) : this(opResolver, reader, null, method.Parameters, gpContext) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader reader, IList parameters) : this(opResolver, reader, null, parameters, default(GenericParamContext)) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader reader, IList parameters, GenericParamContext gpContext) : this(opResolver, reader, null, parameters, gpContext) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters) : this(opResolver, codeReader, ehReader, parameters, default(GenericParamContext)) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters, GenericParamContext gpContext) : this(opResolver, codeReader, ehReader, parameters, gpContext, null) { } public MethodBodyReader(IInstructionOperandResolver opResolver, DataReader codeReader, DataReader? ehReader, IList parameters, GenericParamContext gpContext, ModuleContext context) : base(codeReader, parameters, context) { this.opResolver = opResolver; exceptionsReader = ehReader; this.gpContext = gpContext; startOfHeader = uint.MaxValue; } private void SetHeader(ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok) { hasReadHeader = true; this.flags = flags; this.maxStack = maxStack; this.codeSize = codeSize; this.localVarSigTok = localVarSigTok; } public bool Read() { try { if (!ReadHeader()) { return false; } SetLocals(ReadLocals()); ReadInstructions(); ReadExceptionHandlers(out totalBodySize); return true; } catch (InvalidMethodException) { return false; } catch (IOException) { return false; } } private bool ReadHeader() { if (hasReadHeader) { return true; } hasReadHeader = true; startOfHeader = reader.Position; byte b = reader.ReadByte(); switch (b & 7) { case 2: case 6: flags = 2; maxStack = 8; codeSize = (uint)(b >> 2); localVarSigTok = 0u; headerSize = 1; break; case 3: flags = (ushort)((reader.ReadByte() << 8) | b); headerSize = (byte)(flags >> 12); maxStack = reader.ReadUInt16(); codeSize = reader.ReadUInt32(); localVarSigTok = reader.ReadUInt32(); reader.Position = reader.Position - 12 + (uint)(headerSize * 4); if (headerSize < 3) { flags &= 65527; } headerSize *= 4; break; default: return false; } if ((ulong)((long)reader.Position + (long)codeSize) > (ulong)reader.Length) { return false; } return true; } private IList ReadLocals() { if (!(opResolver.ResolveToken(localVarSigTok, gpContext) is StandAloneSig { LocalSig: var localSig })) { return null; } return localSig?.Locals; } private void ReadInstructions() { ReadInstructionsNumBytes(codeSize); } protected override IField ReadInlineField(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; } protected override IMethod ReadInlineMethod(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; } protected override MethodSig ReadInlineSig(Instruction instr) { if (!(opResolver.ResolveToken(reader.ReadUInt32(), gpContext) is StandAloneSig { MethodSig: var methodSig } standAloneSig)) { return null; } if (methodSig != null) { methodSig.OriginalToken = standAloneSig.MDToken.Raw; } return methodSig; } protected override string ReadInlineString(Instruction instr) { return opResolver.ReadUserString(reader.ReadUInt32()) ?? string.Empty; } protected override ITokenOperand ReadInlineTok(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand; } protected override ITypeDefOrRef ReadInlineType(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; } private void ReadExceptionHandlers(out uint totalBodySize) { if ((flags & 8) == 0) { totalBodySize = ((startOfHeader != uint.MaxValue) ? (reader.Position - startOfHeader) : 0u); return; } DataReader? dataReader = exceptionsReader; bool flag; DataReader ehReader; if (dataReader.HasValue) { flag = false; ehReader = exceptionsReader.Value; } else { flag = true; ehReader = reader; ehReader.Position = (ehReader.Position + 3) & 0xFFFFFFFCu; } byte b = ehReader.ReadByte(); if ((b & 0x3F) != 1) { totalBodySize = ((startOfHeader != uint.MaxValue) ? (reader.Position - startOfHeader) : 0u); return; } if ((b & 0x40) != 0) { ReadFatExceptionHandlers(ref ehReader); } else { ReadSmallExceptionHandlers(ref ehReader); } if (flag) { totalBodySize = ((startOfHeader != uint.MaxValue) ? (ehReader.Position - startOfHeader) : 0u); } else { totalBodySize = 0u; } } private void ReadFatExceptionHandlers(ref DataReader ehReader) { ehReader.Position--; int num = (int)((ehReader.ReadUInt32() >> 8) / 24); for (int i = 0; i < num; i++) { ExceptionHandler exceptionHandler = new ExceptionHandler((ExceptionHandlerType)ehReader.ReadUInt32()); uint num2 = ehReader.ReadUInt32(); exceptionHandler.TryStart = GetInstruction(num2); exceptionHandler.TryEnd = GetInstruction(num2 + ehReader.ReadUInt32()); num2 = ehReader.ReadUInt32(); exceptionHandler.HandlerStart = GetInstruction(num2); exceptionHandler.HandlerEnd = GetInstruction(num2 + ehReader.ReadUInt32()); if (exceptionHandler.IsCatch) { exceptionHandler.CatchType = opResolver.ResolveToken(ehReader.ReadUInt32(), gpContext) as ITypeDefOrRef; } else if (exceptionHandler.IsFilter) { exceptionHandler.FilterStart = GetInstruction(ehReader.ReadUInt32()); } else { ehReader.ReadUInt32(); } Add(exceptionHandler); } } private void ReadSmallExceptionHandlers(ref DataReader ehReader) { int num = (int)((uint)ehReader.ReadByte() / 12u); ehReader.Position += 2u; for (int i = 0; i < num; i++) { ExceptionHandler exceptionHandler = new ExceptionHandler((ExceptionHandlerType)ehReader.ReadUInt16()); uint num2 = ehReader.ReadUInt16(); exceptionHandler.TryStart = GetInstruction(num2); exceptionHandler.TryEnd = GetInstruction(num2 + ehReader.ReadByte()); num2 = ehReader.ReadUInt16(); exceptionHandler.HandlerStart = GetInstruction(num2); exceptionHandler.HandlerEnd = GetInstruction(num2 + ehReader.ReadByte()); if (exceptionHandler.IsCatch) { exceptionHandler.CatchType = opResolver.ResolveToken(ehReader.ReadUInt32(), gpContext) as ITypeDefOrRef; } else if (exceptionHandler.IsFilter) { exceptionHandler.FilterStart = GetInstruction(ehReader.ReadUInt32()); } else { ehReader.ReadUInt32(); } Add(exceptionHandler); } } public CilBody CreateCilBody() { CilBody result = new CilBody(flags == 2 || (flags & 0x10) != 0, instructions, exceptionHandlers, locals) { HeaderSize = headerSize, MaxStack = maxStack, LocalVarSigTok = localVarSigTok, MetadataBodySize = totalBodySize }; instructions = null; exceptionHandlers = null; locals = null; return result; } } public abstract class MethodBodyReaderBase { protected DataReader reader; protected IList parameters; protected IList locals = new List(); protected IList instructions; protected IList exceptionHandlers = new List(); private uint currentOffset; protected uint codeEndOffs; protected uint codeStartOffs; private readonly ModuleContext context; public IList Parameters => parameters; public IList Locals => locals; public IList Instructions => instructions; public IList ExceptionHandlers => exceptionHandlers; protected MethodBodyReaderBase() { } protected MethodBodyReaderBase(ModuleContext context) { this.context = context; } protected MethodBodyReaderBase(DataReader reader) : this(reader, null) { } protected MethodBodyReaderBase(DataReader reader, IList parameters) : this(reader, parameters, null) { } protected MethodBodyReaderBase(DataReader reader, IList parameters, ModuleContext context) { this.reader = reader; this.parameters = parameters; this.context = context; } protected void SetLocals(IList newLocals) { IList list = locals; list.Clear(); if (newLocals != null) { int count = newLocals.Count; for (int i = 0; i < count; i++) { list.Add(new Local(newLocals[i])); } } } protected void SetLocals(IList newLocals) { IList list = locals; list.Clear(); if (newLocals != null) { int count = newLocals.Count; for (int i = 0; i < count; i++) { list.Add(new Local(newLocals[i].Type)); } } } protected void ReadInstructions(int numInstrs) { codeStartOffs = reader.Position; codeEndOffs = reader.Length; instructions = new List(numInstrs); currentOffset = 0u; IList list = instructions; for (int i = 0; i < numInstrs; i++) { if (reader.Position >= codeEndOffs) { break; } list.Add(ReadOneInstruction()); } FixBranches(); } protected void ReadInstructionsNumBytes(uint codeSize) { codeStartOffs = reader.Position; codeEndOffs = reader.Position + codeSize; if (codeEndOffs < codeStartOffs || codeEndOffs > reader.Length) { throw new InvalidMethodException("Invalid code size"); } instructions = new List(); currentOffset = 0u; IList list = instructions; while (reader.Position < codeEndOffs) { list.Add(ReadOneInstruction()); } reader.Position = codeEndOffs; FixBranches(); } private void FixBranches() { IList list = instructions; int count = list.Count; for (int i = 0; i < count; i++) { Instruction instruction = list[i]; switch (instruction.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: instruction.Operand = GetInstruction((uint)instruction.Operand); break; case OperandType.InlineSwitch: { IList list2 = (IList)instruction.Operand; Instruction[] array = new Instruction[list2.Count]; for (int j = 0; j < list2.Count; j++) { array[j] = GetInstruction(list2[j]); } instruction.Operand = array; break; } } } } protected Instruction GetInstruction(uint offset) { IList list = instructions; int num = 0; int num2 = list.Count - 1; while (num <= num2 && num2 != -1) { int num3 = (num + num2) / 2; Instruction instruction = list[num3]; if (instruction.Offset == offset) { return instruction; } if (offset < instruction.Offset) { num2 = num3 - 1; } else { num = num3 + 1; } } return null; } protected Instruction GetInstructionThrow(uint offset) { Instruction instruction = GetInstruction(offset); if (instruction != null) { return instruction; } throw new InvalidOperationException($"There's no instruction @ {offset:X4}"); } private Instruction ReadOneInstruction() { Instruction instruction = new Instruction(); instruction.Offset = currentOffset; instruction.OpCode = ReadOpCode(); instruction.Operand = ReadOperand(instruction); if (instruction.OpCode.Code == Code.Switch) { IList list = (IList)instruction.Operand; currentOffset += (uint)(instruction.OpCode.Size + 4 + 4 * list.Count); } else { currentOffset += (uint)instruction.GetSize(); } if (currentOffset < instruction.Offset) { reader.Position = codeEndOffs; } return instruction; } private OpCode ReadOpCode() { byte b = reader.ReadByte(); switch (b) { case 254: return OpCodes.TwoByteOpCodes[reader.ReadByte()]; case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: if (context != null && reader.BytesLeft >= 1) { OpCode experimentalOpCode = context.GetExperimentalOpCode(b, reader.ReadByte()); if (experimentalOpCode != null) { return experimentalOpCode; } reader.Position--; } break; } return OpCodes.OneByteOpCodes[b]; } private object ReadOperand(Instruction instr) { return instr.OpCode.OperandType switch { OperandType.InlineBrTarget => ReadInlineBrTarget(instr), OperandType.InlineField => ReadInlineField(instr), OperandType.InlineI => ReadInlineI(instr), OperandType.InlineI8 => ReadInlineI8(instr), OperandType.InlineMethod => ReadInlineMethod(instr), OperandType.InlineNone => ReadInlineNone(instr), OperandType.InlinePhi => ReadInlinePhi(instr), OperandType.InlineR => ReadInlineR(instr), OperandType.InlineSig => ReadInlineSig(instr), OperandType.InlineString => ReadInlineString(instr), OperandType.InlineSwitch => ReadInlineSwitch(instr), OperandType.InlineTok => ReadInlineTok(instr), OperandType.InlineType => ReadInlineType(instr), OperandType.InlineVar => ReadInlineVar(instr), OperandType.ShortInlineBrTarget => ReadShortInlineBrTarget(instr), OperandType.ShortInlineI => ReadShortInlineI(instr), OperandType.ShortInlineR => ReadShortInlineR(instr), OperandType.ShortInlineVar => ReadShortInlineVar(instr), _ => throw new InvalidOperationException("Invalid OpCode.OperandType"), }; } protected virtual uint ReadInlineBrTarget(Instruction instr) { return (uint)((int)instr.Offset + instr.GetSize()) + reader.ReadUInt32(); } protected abstract IField ReadInlineField(Instruction instr); protected virtual int ReadInlineI(Instruction instr) { return reader.ReadInt32(); } protected virtual long ReadInlineI8(Instruction instr) { return reader.ReadInt64(); } protected abstract IMethod ReadInlineMethod(Instruction instr); protected virtual object ReadInlineNone(Instruction instr) { return null; } protected virtual object ReadInlinePhi(Instruction instr) { return null; } protected virtual double ReadInlineR(Instruction instr) { return reader.ReadDouble(); } protected abstract MethodSig ReadInlineSig(Instruction instr); protected abstract string ReadInlineString(Instruction instr); protected virtual IList ReadInlineSwitch(Instruction instr) { uint num = reader.ReadUInt32(); long num2 = instr.Offset + instr.OpCode.Size + 4 + (long)num * 4L; if (num2 > uint.MaxValue || codeStartOffs + num2 > codeEndOffs) { reader.Position = codeEndOffs; return Array2.Empty(); } uint[] array = new uint[num]; uint num3 = (uint)num2; for (int i = 0; i < array.Length; i++) { array[i] = num3 + reader.ReadUInt32(); } return array; } protected abstract ITokenOperand ReadInlineTok(Instruction instr); protected abstract ITypeDefOrRef ReadInlineType(Instruction instr); protected virtual IVariable ReadInlineVar(Instruction instr) { if (IsArgOperandInstruction(instr)) { return ReadInlineVarArg(instr); } return ReadInlineVarLocal(instr); } protected virtual Parameter ReadInlineVarArg(Instruction instr) { return GetParameter(reader.ReadUInt16()); } protected virtual Local ReadInlineVarLocal(Instruction instr) { return GetLocal(reader.ReadUInt16()); } protected virtual uint ReadShortInlineBrTarget(Instruction instr) { return (uint)((int)instr.Offset + instr.GetSize() + reader.ReadSByte()); } protected virtual object ReadShortInlineI(Instruction instr) { if (instr.OpCode.Code == Code.Ldc_I4_S) { return reader.ReadSByte(); } return reader.ReadByte(); } protected virtual float ReadShortInlineR(Instruction instr) { return reader.ReadSingle(); } protected virtual IVariable ReadShortInlineVar(Instruction instr) { if (IsArgOperandInstruction(instr)) { return ReadShortInlineVarArg(instr); } return ReadShortInlineVarLocal(instr); } protected virtual Parameter ReadShortInlineVarArg(Instruction instr) { return GetParameter(reader.ReadByte()); } protected virtual Local ReadShortInlineVarLocal(Instruction instr) { return GetLocal(reader.ReadByte()); } protected static bool IsArgOperandInstruction(Instruction instr) { Code code = instr.OpCode.Code; if (code - 14 <= Code.Ldarg_0 || code - 65033 <= Code.Ldarg_0) { return true; } return false; } protected Parameter GetParameter(int index) { IList list = parameters; if ((uint)index < (uint)list.Count) { return list[index]; } return null; } protected Local GetLocal(int index) { IList list = locals; if ((uint)index < (uint)list.Count) { return list[index]; } return null; } protected bool Add(ExceptionHandler eh) { uint offset = GetOffset(eh.TryStart); uint offset2 = GetOffset(eh.TryEnd); if (offset2 <= offset) { return false; } uint offset3 = GetOffset(eh.HandlerStart); uint offset4 = GetOffset(eh.HandlerEnd); if (offset4 <= offset3) { return false; } if (eh.IsFilter) { if (eh.FilterStart == null) { return false; } if (eh.FilterStart.Offset >= offset3) { return false; } } if (offset3 <= offset && offset < offset4) { return false; } if (offset3 < offset2 && offset2 <= offset4) { return false; } if (offset <= offset3 && offset3 < offset2) { return false; } if (offset < offset4 && offset4 <= offset2) { return false; } exceptionHandlers.Add(eh); return true; } private uint GetOffset(Instruction instr) { if (instr != null) { return instr.Offset; } IList list = instructions; if (list.Count == 0) { return 0u; } return list[list.Count - 1].Offset; } public virtual void RestoreMethod(MethodDef method) { CilBody body = method.Body; body.Variables.Clear(); IList list = locals; if (list != null) { int count = list.Count; for (int i = 0; i < count; i++) { body.Variables.Add(list[i]); } } body.Instructions.Clear(); IList list2 = instructions; if (list2 != null) { int count2 = list2.Count; for (int j = 0; j < count2; j++) { body.Instructions.Add(list2[j]); } } body.ExceptionHandlers.Clear(); IList list3 = exceptionHandlers; if (list3 != null) { int count3 = list3.Count; for (int k = 0; k < count3; k++) { body.ExceptionHandlers.Add(list3[k]); } } } } internal static class MethodTableToTypeConverter { private const string METHOD_NAME = "m"; private static readonly MethodInfo setMethodBodyMethodInfo; private static readonly FieldInfo localSignatureFieldInfo; private static readonly FieldInfo sigDoneFieldInfo; private static readonly FieldInfo currSigFieldInfo; private static readonly FieldInfo signatureFieldInfo; private static readonly FieldInfo ptrFieldInfo; private static readonly Dictionary addrToType; private static ModuleBuilder moduleBuilder; private static int numNewTypes; private static object lockObj; static MethodTableToTypeConverter() { setMethodBodyMethodInfo = typeof(MethodBuilder).GetMethod("SetMethodBody", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); localSignatureFieldInfo = typeof(ILGenerator).GetField("m_localSignature", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); sigDoneFieldInfo = typeof(SignatureHelper).GetField("m_sigDone", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); currSigFieldInfo = typeof(SignatureHelper).GetField("m_currSig", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); signatureFieldInfo = typeof(SignatureHelper).GetField("m_signature", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ptrFieldInfo = typeof(RuntimeTypeHandle).GetField("m_ptr", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); addrToType = new Dictionary(); lockObj = new object(); if ((object)ptrFieldInfo == null) { moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynAsm"), AssemblyBuilderAccess.Run).DefineDynamicModule("DynMod"); } if ((object)localSignatureFieldInfo == null) { localSignatureFieldInfo = Type.GetType("System.Reflection.Emit.RuntimeILGenerator")?.GetField("m_localSignature", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } public static Type Convert(IntPtr address) { lock (lockObj) { if (addrToType.TryGetValue(address, out var value)) { return value; } value = GetTypeNET20(address) ?? GetTypeUsingTypeBuilder(address); addrToType[address] = value; return value; } } private static Type GetTypeUsingTypeBuilder(IntPtr address) { if ((object)moduleBuilder == null) { return null; } TypeBuilder typeBuilder = moduleBuilder.DefineType(GetNextTypeName()); MethodBuilder mb = typeBuilder.DefineMethod("m", System.Reflection.MethodAttributes.Static, typeof(void), Array2.Empty()); try { if ((object)setMethodBodyMethodInfo != null) { return GetTypeNET45(typeBuilder, mb, address); } return GetTypeNET40(typeBuilder, mb, address); } catch { moduleBuilder = null; return null; } } private static Type GetTypeNET45(TypeBuilder tb, MethodBuilder mb, IntPtr address) { byte[] array = new byte[1] { 42 }; int num = 8; byte[] localSignature = GetLocalSignature(address); setMethodBodyMethodInfo.Invoke(mb, new object[5] { array, num, localSignature, null, null }); return tb.CreateType().GetMethod("m", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetMethodBody() .LocalVariables[0].LocalType; } private static Type GetTypeNET40(TypeBuilder tb, MethodBuilder mb, IntPtr address) { ILGenerator iLGenerator = mb.GetILGenerator(); iLGenerator.Emit(System.Reflection.Emit.OpCodes.Ret); iLGenerator.DeclareLocal(typeof(int)); byte[] localSignature = GetLocalSignature(address); SignatureHelper obj = (SignatureHelper)localSignatureFieldInfo.GetValue(iLGenerator); sigDoneFieldInfo.SetValue(obj, true); currSigFieldInfo.SetValue(obj, localSignature.Length); signatureFieldInfo.SetValue(obj, localSignature); return tb.CreateType().GetMethod("m", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetMethodBody() .LocalVariables[0].LocalType; } private static Type GetTypeNET20(IntPtr address) { if ((object)ptrFieldInfo == null) { return null; } object obj = default(RuntimeTypeHandle); ptrFieldInfo.SetValue(obj, address); return Type.GetTypeFromHandle((RuntimeTypeHandle)obj); } private static string GetNextTypeName() { return $"Type{numNewTypes++}"; } private static byte[] GetLocalSignature(IntPtr mtAddr) { ulong num = (ulong)mtAddr.ToInt64(); if (IntPtr.Size != 4) { byte[] obj = new byte[11] { 7, 1, 33, 0, 0, 0, 0, 0, 0, 0, 0 }; obj[3] = (byte)num; obj[4] = (byte)(num >> 8); obj[5] = (byte)(num >> 16); obj[6] = (byte)(num >> 24); obj[7] = (byte)(num >> 32); obj[8] = (byte)(num >> 40); obj[9] = (byte)(num >> 48); obj[10] = (byte)(num >> 56); return obj; } byte[] obj2 = new byte[7] { 7, 1, 33, 0, 0, 0, 0 }; obj2[3] = (byte)num; obj2[4] = (byte)(num >> 8); obj2[5] = (byte)(num >> 16); obj2[6] = (byte)(num >> 24); return obj2; } } public static class MethodUtils { public static void SimplifyMacros(this IList instructions, IList locals, IList parameters) { int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; switch (instruction.OpCode.Code) { case Code.Beq_S: instruction.OpCode = OpCodes.Beq; break; case Code.Bge_S: instruction.OpCode = OpCodes.Bge; break; case Code.Bge_Un_S: instruction.OpCode = OpCodes.Bge_Un; break; case Code.Bgt_S: instruction.OpCode = OpCodes.Bgt; break; case Code.Bgt_Un_S: instruction.OpCode = OpCodes.Bgt_Un; break; case Code.Ble_S: instruction.OpCode = OpCodes.Ble; break; case Code.Ble_Un_S: instruction.OpCode = OpCodes.Ble_Un; break; case Code.Blt_S: instruction.OpCode = OpCodes.Blt; break; case Code.Blt_Un_S: instruction.OpCode = OpCodes.Blt_Un; break; case Code.Bne_Un_S: instruction.OpCode = OpCodes.Bne_Un; break; case Code.Br_S: instruction.OpCode = OpCodes.Br; break; case Code.Brfalse_S: instruction.OpCode = OpCodes.Brfalse; break; case Code.Brtrue_S: instruction.OpCode = OpCodes.Brtrue; break; case Code.Ldarg_0: instruction.OpCode = OpCodes.Ldarg; instruction.Operand = ReadList(parameters, 0); break; case Code.Ldarg_1: instruction.OpCode = OpCodes.Ldarg; instruction.Operand = ReadList(parameters, 1); break; case Code.Ldarg_2: instruction.OpCode = OpCodes.Ldarg; instruction.Operand = ReadList(parameters, 2); break; case Code.Ldarg_3: instruction.OpCode = OpCodes.Ldarg; instruction.Operand = ReadList(parameters, 3); break; case Code.Ldarg_S: instruction.OpCode = OpCodes.Ldarg; break; case Code.Ldarga_S: instruction.OpCode = OpCodes.Ldarga; break; case Code.Ldc_I4_0: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 0; break; case Code.Ldc_I4_1: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 1; break; case Code.Ldc_I4_2: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 2; break; case Code.Ldc_I4_3: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 3; break; case Code.Ldc_I4_4: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 4; break; case Code.Ldc_I4_5: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 5; break; case Code.Ldc_I4_6: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 6; break; case Code.Ldc_I4_7: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 7; break; case Code.Ldc_I4_8: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = 8; break; case Code.Ldc_I4_M1: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = -1; break; case Code.Ldc_I4_S: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = (int)(sbyte)instruction.Operand; break; case Code.Ldloc_0: instruction.OpCode = OpCodes.Ldloc; instruction.Operand = ReadList(locals, 0); break; case Code.Ldloc_1: instruction.OpCode = OpCodes.Ldloc; instruction.Operand = ReadList(locals, 1); break; case Code.Ldloc_2: instruction.OpCode = OpCodes.Ldloc; instruction.Operand = ReadList(locals, 2); break; case Code.Ldloc_3: instruction.OpCode = OpCodes.Ldloc; instruction.Operand = ReadList(locals, 3); break; case Code.Ldloc_S: instruction.OpCode = OpCodes.Ldloc; break; case Code.Ldloca_S: instruction.OpCode = OpCodes.Ldloca; break; case Code.Leave_S: instruction.OpCode = OpCodes.Leave; break; case Code.Starg_S: instruction.OpCode = OpCodes.Starg; break; case Code.Stloc_0: instruction.OpCode = OpCodes.Stloc; instruction.Operand = ReadList(locals, 0); break; case Code.Stloc_1: instruction.OpCode = OpCodes.Stloc; instruction.Operand = ReadList(locals, 1); break; case Code.Stloc_2: instruction.OpCode = OpCodes.Stloc; instruction.Operand = ReadList(locals, 2); break; case Code.Stloc_3: instruction.OpCode = OpCodes.Stloc; instruction.Operand = ReadList(locals, 3); break; case Code.Stloc_S: instruction.OpCode = OpCodes.Stloc; break; } } } private static T ReadList(IList list, int index) { if (list == null) { return default(T); } if ((uint)index < (uint)list.Count) { return list[index]; } return default(T); } public static void OptimizeMacros(this IList instructions) { int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; switch (instruction.OpCode.Code) { case Code.Ldarg_S: case Code.Ldarg: if (instruction.Operand is Parameter parameter2) { if (parameter2.Index == 0) { instruction.OpCode = OpCodes.Ldarg_0; instruction.Operand = null; } else if (parameter2.Index == 1) { instruction.OpCode = OpCodes.Ldarg_1; instruction.Operand = null; } else if (parameter2.Index == 2) { instruction.OpCode = OpCodes.Ldarg_2; instruction.Operand = null; } else if (parameter2.Index == 3) { instruction.OpCode = OpCodes.Ldarg_3; instruction.Operand = null; } else if (0 <= parameter2.Index && parameter2.Index <= 255) { instruction.OpCode = OpCodes.Ldarg_S; } } break; case Code.Ldarga: if (instruction.Operand is Parameter parameter && 0 <= parameter.Index && parameter.Index <= 255) { instruction.OpCode = OpCodes.Ldarga_S; } break; case Code.Ldc_I4_S: case Code.Ldc_I4: { int num; if (instruction.Operand is int) { num = (int)instruction.Operand; } else { if (!(instruction.Operand is sbyte)) { break; } num = (sbyte)instruction.Operand; } switch (num) { case 0: instruction.OpCode = OpCodes.Ldc_I4_0; instruction.Operand = null; break; case 1: instruction.OpCode = OpCodes.Ldc_I4_1; instruction.Operand = null; break; case 2: instruction.OpCode = OpCodes.Ldc_I4_2; instruction.Operand = null; break; case 3: instruction.OpCode = OpCodes.Ldc_I4_3; instruction.Operand = null; break; case 4: instruction.OpCode = OpCodes.Ldc_I4_4; instruction.Operand = null; break; case 5: instruction.OpCode = OpCodes.Ldc_I4_5; instruction.Operand = null; break; case 6: instruction.OpCode = OpCodes.Ldc_I4_6; instruction.Operand = null; break; case 7: instruction.OpCode = OpCodes.Ldc_I4_7; instruction.Operand = null; break; case 8: instruction.OpCode = OpCodes.Ldc_I4_8; instruction.Operand = null; break; case -1: instruction.OpCode = OpCodes.Ldc_I4_M1; instruction.Operand = null; break; default: if (-128 <= num && num <= 127) { instruction.OpCode = OpCodes.Ldc_I4_S; instruction.Operand = (sbyte)num; } break; } break; } case Code.Ldloc_S: case Code.Ldloc: if (instruction.Operand is Local local2) { if (local2.Index == 0) { instruction.OpCode = OpCodes.Ldloc_0; instruction.Operand = null; } else if (local2.Index == 1) { instruction.OpCode = OpCodes.Ldloc_1; instruction.Operand = null; } else if (local2.Index == 2) { instruction.OpCode = OpCodes.Ldloc_2; instruction.Operand = null; } else if (local2.Index == 3) { instruction.OpCode = OpCodes.Ldloc_3; instruction.Operand = null; } else if (0 <= local2.Index && local2.Index <= 255) { instruction.OpCode = OpCodes.Ldloc_S; } } break; case Code.Ldloca: if (instruction.Operand is Local local3 && 0 <= local3.Index && local3.Index <= 255) { instruction.OpCode = OpCodes.Ldloca_S; } break; case Code.Starg: if (instruction.Operand is Parameter parameter3 && 0 <= parameter3.Index && parameter3.Index <= 255) { instruction.OpCode = OpCodes.Starg_S; } break; case Code.Stloc_S: case Code.Stloc: if (instruction.Operand is Local local) { if (local.Index == 0) { instruction.OpCode = OpCodes.Stloc_0; instruction.Operand = null; } else if (local.Index == 1) { instruction.OpCode = OpCodes.Stloc_1; instruction.Operand = null; } else if (local.Index == 2) { instruction.OpCode = OpCodes.Stloc_2; instruction.Operand = null; } else if (local.Index == 3) { instruction.OpCode = OpCodes.Stloc_3; instruction.Operand = null; } else if (0 <= local.Index && local.Index <= 255) { instruction.OpCode = OpCodes.Stloc_S; } } break; } } instructions.OptimizeBranches(); } public static void SimplifyBranches(this IList instructions) { int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; switch (instruction.OpCode.Code) { case Code.Beq_S: instruction.OpCode = OpCodes.Beq; break; case Code.Bge_S: instruction.OpCode = OpCodes.Bge; break; case Code.Bgt_S: instruction.OpCode = OpCodes.Bgt; break; case Code.Ble_S: instruction.OpCode = OpCodes.Ble; break; case Code.Blt_S: instruction.OpCode = OpCodes.Blt; break; case Code.Bne_Un_S: instruction.OpCode = OpCodes.Bne_Un; break; case Code.Bge_Un_S: instruction.OpCode = OpCodes.Bge_Un; break; case Code.Bgt_Un_S: instruction.OpCode = OpCodes.Bgt_Un; break; case Code.Ble_Un_S: instruction.OpCode = OpCodes.Ble_Un; break; case Code.Blt_Un_S: instruction.OpCode = OpCodes.Blt_Un; break; case Code.Br_S: instruction.OpCode = OpCodes.Br; break; case Code.Brfalse_S: instruction.OpCode = OpCodes.Brfalse; break; case Code.Brtrue_S: instruction.OpCode = OpCodes.Brtrue; break; case Code.Leave_S: instruction.OpCode = OpCodes.Leave; break; } } } public static void OptimizeBranches(this IList instructions) { bool flag; do { instructions.UpdateInstructionOffsets(); flag = false; int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; OpCode opCode; switch (instruction.OpCode.Code) { case Code.Beq: opCode = OpCodes.Beq_S; break; case Code.Bge: opCode = OpCodes.Bge_S; break; case Code.Bge_Un: opCode = OpCodes.Bge_Un_S; break; case Code.Bgt: opCode = OpCodes.Bgt_S; break; case Code.Bgt_Un: opCode = OpCodes.Bgt_Un_S; break; case Code.Ble: opCode = OpCodes.Ble_S; break; case Code.Ble_Un: opCode = OpCodes.Ble_Un_S; break; case Code.Blt: opCode = OpCodes.Blt_S; break; case Code.Blt_Un: opCode = OpCodes.Blt_Un_S; break; case Code.Bne_Un: opCode = OpCodes.Bne_Un_S; break; case Code.Br: opCode = OpCodes.Br_S; break; case Code.Brfalse: opCode = OpCodes.Brfalse_S; break; case Code.Brtrue: opCode = OpCodes.Brtrue_S; break; case Code.Leave: opCode = OpCodes.Leave_S; break; default: continue; } if (instruction.Operand is Instruction instruction2) { int num = ((instruction2.Offset < instruction.Offset) ? ((int)instruction.Offset + opCode.Size + 1) : ((int)instruction.Offset + instruction.GetSize())); int num2 = (int)instruction2.Offset - num; if (-128 <= num2 && num2 <= 127) { instruction.OpCode = opCode; flag = true; } } } } while (flag); } public static uint UpdateInstructionOffsets(this IList instructions) { uint num = 0u; int count = instructions.Count; for (int i = 0; i < count; i++) { Instruction instruction = instructions[i]; instruction.Offset = num; num += (uint)instruction.GetSize(); } return num; } } public sealed class OpCode { public readonly string Name; public readonly Code Code; public readonly OperandType OperandType; public readonly FlowControl FlowControl; public readonly OpCodeType OpCodeType; public readonly StackBehaviour StackBehaviourPush; public readonly StackBehaviour StackBehaviourPop; public short Value => (short)Code; public int Size { get { if ((int)Code >= 256 && Code != Code.UNKNOWN1) { return 2; } return 1; } } public OpCode(string name, byte first, byte second, OperandType operandType, FlowControl flowControl, StackBehaviour push, StackBehaviour pop) : this(name, (Code)((first << 8) | second), operandType, flowControl, OpCodeType.Experimental, push, pop, experimental: true) { } internal OpCode(string name, Code code, OperandType operandType, FlowControl flowControl, OpCodeType opCodeType, StackBehaviour push, StackBehaviour pop, bool experimental = false) { Name = name; Code = code; OperandType = operandType; FlowControl = flowControl; OpCodeType = opCodeType; StackBehaviourPush = push; StackBehaviourPop = pop; if (!experimental) { if ((int)code >> 8 == 0) { OpCodes.OneByteOpCodes[(byte)code] = this; } else if ((int)code >> 8 == 254) { OpCodes.TwoByteOpCodes[(byte)code] = this; } } } public Instruction ToInstruction() { return Instruction.Create(this); } public Instruction ToInstruction(byte value) { return Instruction.Create(this, value); } public Instruction ToInstruction(sbyte value) { return Instruction.Create(this, value); } public Instruction ToInstruction(int value) { return Instruction.Create(this, value); } public Instruction ToInstruction(long value) { return Instruction.Create(this, value); } public Instruction ToInstruction(float value) { return Instruction.Create(this, value); } public Instruction ToInstruction(double value) { return Instruction.Create(this, value); } public Instruction ToInstruction(string s) { return Instruction.Create(this, s); } public Instruction ToInstruction(Instruction target) { return Instruction.Create(this, target); } public Instruction ToInstruction(IList targets) { return Instruction.Create(this, targets); } public Instruction ToInstruction(ITypeDefOrRef type) { return Instruction.Create(this, type); } public Instruction ToInstruction(CorLibTypeSig type) { return Instruction.Create(this, type.TypeDefOrRef); } public Instruction ToInstruction(MemberRef mr) { return Instruction.Create(this, mr); } public Instruction ToInstruction(IField field) { return Instruction.Create(this, field); } public Instruction ToInstruction(IMethod method) { return Instruction.Create(this, method); } public Instruction ToInstruction(ITokenOperand token) { return Instruction.Create(this, token); } public Instruction ToInstruction(MethodSig methodSig) { return Instruction.Create(this, methodSig); } public Instruction ToInstruction(Parameter parameter) { return Instruction.Create(this, parameter); } public Instruction ToInstruction(Local local) { return Instruction.Create(this, local); } public override string ToString() { return Name; } } public static class OpCodes { public static readonly OpCode[] OneByteOpCodes; public static readonly OpCode[] TwoByteOpCodes; public static readonly OpCode UNKNOWN1; public static readonly OpCode UNKNOWN2; public static readonly OpCode Nop; public static readonly OpCode Break; public static readonly OpCode Ldarg_0; public static readonly OpCode Ldarg_1; public static readonly OpCode Ldarg_2; public static readonly OpCode Ldarg_3; public static readonly OpCode Ldloc_0; public static readonly OpCode Ldloc_1; public static readonly OpCode Ldloc_2; public static readonly OpCode Ldloc_3; public static readonly OpCode Stloc_0; public static readonly OpCode Stloc_1; public static readonly OpCode Stloc_2; public static readonly OpCode Stloc_3; public static readonly OpCode Ldarg_S; public static readonly OpCode Ldarga_S; public static readonly OpCode Starg_S; public static readonly OpCode Ldloc_S; public static readonly OpCode Ldloca_S; public static readonly OpCode Stloc_S; public static readonly OpCode Ldnull; public static readonly OpCode Ldc_I4_M1; public static readonly OpCode Ldc_I4_0; public static readonly OpCode Ldc_I4_1; public static readonly OpCode Ldc_I4_2; public static readonly OpCode Ldc_I4_3; public static readonly OpCode Ldc_I4_4; public static readonly OpCode Ldc_I4_5; public static readonly OpCode Ldc_I4_6; public static readonly OpCode Ldc_I4_7; public static readonly OpCode Ldc_I4_8; public static readonly OpCode Ldc_I4_S; public static readonly OpCode Ldc_I4; public static readonly OpCode Ldc_I8; public static readonly OpCode Ldc_R4; public static readonly OpCode Ldc_R8; public static readonly OpCode Dup; public static readonly OpCode Pop; public static readonly OpCode Jmp; public static readonly OpCode Call; public static readonly OpCode Calli; public static readonly OpCode Ret; public static readonly OpCode Br_S; public static readonly OpCode Brfalse_S; public static readonly OpCode Brtrue_S; public static readonly OpCode Beq_S; public static readonly OpCode Bge_S; public static readonly OpCode Bgt_S; public static readonly OpCode Ble_S; public static readonly OpCode Blt_S; public static readonly OpCode Bne_Un_S; public static readonly OpCode Bge_Un_S; public static readonly OpCode Bgt_Un_S; public static readonly OpCode Ble_Un_S; public static readonly OpCode Blt_Un_S; public static readonly OpCode Br; public static readonly OpCode Brfalse; public static readonly OpCode Brtrue; public static readonly OpCode Beq; public static readonly OpCode Bge; public static readonly OpCode Bgt; public static readonly OpCode Ble; public static readonly OpCode Blt; public static readonly OpCode Bne_Un; public static readonly OpCode Bge_Un; public static readonly OpCode Bgt_Un; public static readonly OpCode Ble_Un; public static readonly OpCode Blt_Un; public static readonly OpCode Switch; public static readonly OpCode Ldind_I1; public static readonly OpCode Ldind_U1; public static readonly OpCode Ldind_I2; public static readonly OpCode Ldind_U2; public static readonly OpCode Ldind_I4; public static readonly OpCode Ldind_U4; public static readonly OpCode Ldind_I8; public static readonly OpCode Ldind_I; public static readonly OpCode Ldind_R4; public static readonly OpCode Ldind_R8; public static readonly OpCode Ldind_Ref; public static readonly OpCode Stind_Ref; public static readonly OpCode Stind_I1; public static readonly OpCode Stind_I2; public static readonly OpCode Stind_I4; public static readonly OpCode Stind_I8; public static readonly OpCode Stind_R4; public static readonly OpCode Stind_R8; public static readonly OpCode Add; public static readonly OpCode Sub; public static readonly OpCode Mul; public static readonly OpCode Div; public static readonly OpCode Div_Un; public static readonly OpCode Rem; public static readonly OpCode Rem_Un; public static readonly OpCode And; public static readonly OpCode Or; public static readonly OpCode Xor; public static readonly OpCode Shl; public static readonly OpCode Shr; public static readonly OpCode Shr_Un; public static readonly OpCode Neg; public static readonly OpCode Not; public static readonly OpCode Conv_I1; public static readonly OpCode Conv_I2; public static readonly OpCode Conv_I4; public static readonly OpCode Conv_I8; public static readonly OpCode Conv_R4; public static readonly OpCode Conv_R8; public static readonly OpCode Conv_U4; public static readonly OpCode Conv_U8; public static readonly OpCode Callvirt; public static readonly OpCode Cpobj; public static readonly OpCode Ldobj; public static readonly OpCode Ldstr; public static readonly OpCode Newobj; public static readonly OpCode Castclass; public static readonly OpCode Isinst; public static readonly OpCode Conv_R_Un; public static readonly OpCode Unbox; public static readonly OpCode Throw; public static readonly OpCode Ldfld; public static readonly OpCode Ldflda; public static readonly OpCode Stfld; public static readonly OpCode Ldsfld; public static readonly OpCode Ldsflda; public static readonly OpCode Stsfld; public static readonly OpCode Stobj; public static readonly OpCode Conv_Ovf_I1_Un; public static readonly OpCode Conv_Ovf_I2_Un; public static readonly OpCode Conv_Ovf_I4_Un; public static readonly OpCode Conv_Ovf_I8_Un; public static readonly OpCode Conv_Ovf_U1_Un; public static readonly OpCode Conv_Ovf_U2_Un; public static readonly OpCode Conv_Ovf_U4_Un; public static readonly OpCode Conv_Ovf_U8_Un; public static readonly OpCode Conv_Ovf_I_Un; public static readonly OpCode Conv_Ovf_U_Un; public static readonly OpCode Box; public static readonly OpCode Newarr; public static readonly OpCode Ldlen; public static readonly OpCode Ldelema; public static readonly OpCode Ldelem_I1; public static readonly OpCode Ldelem_U1; public static readonly OpCode Ldelem_I2; public static readonly OpCode Ldelem_U2; public static readonly OpCode Ldelem_I4; public static readonly OpCode Ldelem_U4; public static readonly OpCode Ldelem_I8; public static readonly OpCode Ldelem_I; public static readonly OpCode Ldelem_R4; public static readonly OpCode Ldelem_R8; public static readonly OpCode Ldelem_Ref; public static readonly OpCode Stelem_I; public static readonly OpCode Stelem_I1; public static readonly OpCode Stelem_I2; public static readonly OpCode Stelem_I4; public static readonly OpCode Stelem_I8; public static readonly OpCode Stelem_R4; public static readonly OpCode Stelem_R8; public static readonly OpCode Stelem_Ref; public static readonly OpCode Ldelem; public static readonly OpCode Stelem; public static readonly OpCode Unbox_Any; public static readonly OpCode Conv_Ovf_I1; public static readonly OpCode Conv_Ovf_U1; public static readonly OpCode Conv_Ovf_I2; public static readonly OpCode Conv_Ovf_U2; public static readonly OpCode Conv_Ovf_I4; public static readonly OpCode Conv_Ovf_U4; public static readonly OpCode Conv_Ovf_I8; public static readonly OpCode Conv_Ovf_U8; public static readonly OpCode Refanyval; public static readonly OpCode Ckfinite; public static readonly OpCode Mkrefany; public static readonly OpCode Ldtoken; public static readonly OpCode Conv_U2; public static readonly OpCode Conv_U1; public static readonly OpCode Conv_I; public static readonly OpCode Conv_Ovf_I; public static readonly OpCode Conv_Ovf_U; public static readonly OpCode Add_Ovf; public static readonly OpCode Add_Ovf_Un; public static readonly OpCode Mul_Ovf; public static readonly OpCode Mul_Ovf_Un; public static readonly OpCode Sub_Ovf; public static readonly OpCode Sub_Ovf_Un; public static readonly OpCode Endfinally; public static readonly OpCode Leave; public static readonly OpCode Leave_S; public static readonly OpCode Stind_I; public static readonly OpCode Conv_U; public static readonly OpCode Prefix7; public static readonly OpCode Prefix6; public static readonly OpCode Prefix5; public static readonly OpCode Prefix4; public static readonly OpCode Prefix3; public static readonly OpCode Prefix2; public static readonly OpCode Prefix1; public static readonly OpCode Prefixref; public static readonly OpCode Arglist; public static readonly OpCode Ceq; public static readonly OpCode Cgt; public static readonly OpCode Cgt_Un; public static readonly OpCode Clt; public static readonly OpCode Clt_Un; public static readonly OpCode Ldftn; public static readonly OpCode Ldvirtftn; public static readonly OpCode Ldarg; public static readonly OpCode Ldarga; public static readonly OpCode Starg; public static readonly OpCode Ldloc; public static readonly OpCode Ldloca; public static readonly OpCode Stloc; public static readonly OpCode Localloc; public static readonly OpCode Endfilter; public static readonly OpCode Unaligned; public static readonly OpCode Volatile; public static readonly OpCode Tailcall; public static readonly OpCode Initobj; public static readonly OpCode Constrained; public static readonly OpCode Cpblk; public static readonly OpCode Initblk; public static readonly OpCode No; public static readonly OpCode Rethrow; public static readonly OpCode Sizeof; public static readonly OpCode Refanytype; public static readonly OpCode Readonly; static OpCodes() { OneByteOpCodes = new OpCode[256]; TwoByteOpCodes = new OpCode[256]; UNKNOWN1 = new OpCode("UNKNOWN1", Code.UNKNOWN1, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); UNKNOWN2 = new OpCode("UNKNOWN2", Code.UNKNOWN2, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Nop = new OpCode("nop", Code.Nop, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); Break = new OpCode("break", Code.Break, OperandType.InlineNone, FlowControl.Break, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); Ldarg_0 = new OpCode("ldarg.0", Code.Ldarg_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldarg_1 = new OpCode("ldarg.1", Code.Ldarg_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldarg_2 = new OpCode("ldarg.2", Code.Ldarg_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldarg_3 = new OpCode("ldarg.3", Code.Ldarg_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloc_0 = new OpCode("ldloc.0", Code.Ldloc_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloc_1 = new OpCode("ldloc.1", Code.Ldloc_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloc_2 = new OpCode("ldloc.2", Code.Ldloc_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloc_3 = new OpCode("ldloc.3", Code.Ldloc_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Stloc_0 = new OpCode("stloc.0", Code.Stloc_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Stloc_1 = new OpCode("stloc.1", Code.Stloc_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Stloc_2 = new OpCode("stloc.2", Code.Stloc_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Stloc_3 = new OpCode("stloc.3", Code.Stloc_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Ldarg_S = new OpCode("ldarg.s", Code.Ldarg_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldarga_S = new OpCode("ldarga.s", Code.Ldarga_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Starg_S = new OpCode("starg.s", Code.Starg_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Ldloc_S = new OpCode("ldloc.s", Code.Ldloc_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloca_S = new OpCode("ldloca.s", Code.Ldloca_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Stloc_S = new OpCode("stloc.s", Code.Stloc_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); Ldnull = new OpCode("ldnull", Code.Ldnull, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Pop0); Ldc_I4_M1 = new OpCode("ldc.i4.m1", Code.Ldc_I4_M1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_0 = new OpCode("ldc.i4.0", Code.Ldc_I4_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_1 = new OpCode("ldc.i4.1", Code.Ldc_I4_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_2 = new OpCode("ldc.i4.2", Code.Ldc_I4_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_3 = new OpCode("ldc.i4.3", Code.Ldc_I4_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_4 = new OpCode("ldc.i4.4", Code.Ldc_I4_4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_5 = new OpCode("ldc.i4.5", Code.Ldc_I4_5, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_6 = new OpCode("ldc.i4.6", Code.Ldc_I4_6, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_7 = new OpCode("ldc.i4.7", Code.Ldc_I4_7, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_8 = new OpCode("ldc.i4.8", Code.Ldc_I4_8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4_S = new OpCode("ldc.i4.s", Code.Ldc_I4_S, OperandType.ShortInlineI, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I4 = new OpCode("ldc.i4", Code.Ldc_I4, OperandType.InlineI, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldc_I8 = new OpCode("ldc.i8", Code.Ldc_I8, OperandType.InlineI8, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop0); Ldc_R4 = new OpCode("ldc.r4", Code.Ldc_R4, OperandType.ShortInlineR, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Pop0); Ldc_R8 = new OpCode("ldc.r8", Code.Ldc_R8, OperandType.InlineR, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop0); Dup = new OpCode("dup", Code.Dup, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1_push1, StackBehaviour.Pop1); Pop = new OpCode("pop", Code.Pop, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); Jmp = new OpCode("jmp", Code.Jmp, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); Call = new OpCode("call", Code.Call, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Varpush, StackBehaviour.Varpop); Calli = new OpCode("calli", Code.Calli, OperandType.InlineSig, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Varpush, StackBehaviour.Varpop); Ret = new OpCode("ret", Code.Ret, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Varpop); Br_S = new OpCode("br.s", Code.Br_S, OperandType.ShortInlineBrTarget, FlowControl.Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop0); Brfalse_S = new OpCode("brfalse.s", Code.Brfalse_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Popi); Brtrue_S = new OpCode("brtrue.s", Code.Brtrue_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Popi); Beq_S = new OpCode("beq.s", Code.Beq_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bge_S = new OpCode("bge.s", Code.Bge_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bgt_S = new OpCode("bgt.s", Code.Bgt_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Ble_S = new OpCode("ble.s", Code.Ble_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Blt_S = new OpCode("blt.s", Code.Blt_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bne_Un_S = new OpCode("bne.un.s", Code.Bne_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bge_Un_S = new OpCode("bge.un.s", Code.Bge_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bgt_Un_S = new OpCode("bgt.un.s", Code.Bgt_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Ble_Un_S = new OpCode("ble.un.s", Code.Ble_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Blt_Un_S = new OpCode("blt.un.s", Code.Blt_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Br = new OpCode("br", Code.Br, OperandType.InlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); Brfalse = new OpCode("brfalse", Code.Brfalse, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); Brtrue = new OpCode("brtrue", Code.Brtrue, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); Beq = new OpCode("beq", Code.Beq, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bge = new OpCode("bge", Code.Bge, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bgt = new OpCode("bgt", Code.Bgt, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Ble = new OpCode("ble", Code.Ble, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Blt = new OpCode("blt", Code.Blt, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bne_Un = new OpCode("bne.un", Code.Bne_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bge_Un = new OpCode("bge.un", Code.Bge_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Bgt_Un = new OpCode("bgt.un", Code.Bgt_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Ble_Un = new OpCode("ble.un", Code.Ble_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Blt_Un = new OpCode("blt.un", Code.Blt_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); Switch = new OpCode("switch", Code.Switch, OperandType.InlineSwitch, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); Ldind_I1 = new OpCode("ldind.i1", Code.Ldind_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_U1 = new OpCode("ldind.u1", Code.Ldind_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_I2 = new OpCode("ldind.i2", Code.Ldind_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_U2 = new OpCode("ldind.u2", Code.Ldind_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_I4 = new OpCode("ldind.i4", Code.Ldind_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_U4 = new OpCode("ldind.u4", Code.Ldind_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_I8 = new OpCode("ldind.i8", Code.Ldind_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Popi); Ldind_I = new OpCode("ldind.i", Code.Ldind_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Ldind_R4 = new OpCode("ldind.r4", Code.Ldind_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Popi); Ldind_R8 = new OpCode("ldind.r8", Code.Ldind_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Popi); Ldind_Ref = new OpCode("ldind.ref", Code.Ldind_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Popi); Stind_Ref = new OpCode("stind.ref", Code.Stind_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); Stind_I1 = new OpCode("stind.i1", Code.Stind_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); Stind_I2 = new OpCode("stind.i2", Code.Stind_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); Stind_I4 = new OpCode("stind.i4", Code.Stind_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); Stind_I8 = new OpCode("stind.i8", Code.Stind_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi8); Stind_R4 = new OpCode("stind.r4", Code.Stind_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popr4); Stind_R8 = new OpCode("stind.r8", Code.Stind_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popr8); Add = new OpCode("add", Code.Add, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Sub = new OpCode("sub", Code.Sub, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Mul = new OpCode("mul", Code.Mul, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Div = new OpCode("div", Code.Div, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Div_Un = new OpCode("div.un", Code.Div_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Rem = new OpCode("rem", Code.Rem, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Rem_Un = new OpCode("rem.un", Code.Rem_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); And = new OpCode("and", Code.And, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Or = new OpCode("or", Code.Or, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Xor = new OpCode("xor", Code.Xor, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Shl = new OpCode("shl", Code.Shl, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Shr = new OpCode("shr", Code.Shr, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Shr_Un = new OpCode("shr.un", Code.Shr_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Neg = new OpCode("neg", Code.Neg, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1); Not = new OpCode("not", Code.Not, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1); Conv_I1 = new OpCode("conv.i1", Code.Conv_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_I2 = new OpCode("conv.i2", Code.Conv_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_I4 = new OpCode("conv.i4", Code.Conv_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_I8 = new OpCode("conv.i8", Code.Conv_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Conv_R4 = new OpCode("conv.r4", Code.Conv_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Pop1); Conv_R8 = new OpCode("conv.r8", Code.Conv_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); Conv_U4 = new OpCode("conv.u4", Code.Conv_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_U8 = new OpCode("conv.u8", Code.Conv_U8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Callvirt = new OpCode("callvirt", Code.Callvirt, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Objmodel, StackBehaviour.Varpush, StackBehaviour.Varpop); Cpobj = new OpCode("cpobj", Code.Cpobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popi_popi); Ldobj = new OpCode("ldobj", Code.Ldobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popi); Ldstr = new OpCode("ldstr", Code.Ldstr, OperandType.InlineString, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Pop0); Newobj = new OpCode("newobj", Code.Newobj, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Varpop); Castclass = new OpCode("castclass", Code.Castclass, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popref); Isinst = new OpCode("isinst", Code.Isinst, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); Conv_R_Un = new OpCode("conv.r.un", Code.Conv_R_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); Unbox = new OpCode("unbox", Code.Unbox, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popref); Throw = new OpCode("throw", Code.Throw, OperandType.InlineNone, FlowControl.Throw, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref); Ldfld = new OpCode("ldfld", Code.Ldfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref); Ldflda = new OpCode("ldflda", Code.Ldflda, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); Stfld = new OpCode("stfld", Code.Stfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_pop1); Ldsfld = new OpCode("ldsfld", Code.Ldsfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Pop0); Ldsflda = new OpCode("ldsflda", Code.Ldsflda, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Pop0); Stsfld = new OpCode("stsfld", Code.Stsfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Pop1); Stobj = new OpCode("stobj", Code.Stobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_pop1); Conv_Ovf_I1_Un = new OpCode("conv.ovf.i1.un", Code.Conv_Ovf_I1_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I2_Un = new OpCode("conv.ovf.i2.un", Code.Conv_Ovf_I2_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I4_Un = new OpCode("conv.ovf.i4.un", Code.Conv_Ovf_I4_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I8_Un = new OpCode("conv.ovf.i8.un", Code.Conv_Ovf_I8_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Conv_Ovf_U1_Un = new OpCode("conv.ovf.u1.un", Code.Conv_Ovf_U1_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U2_Un = new OpCode("conv.ovf.u2.un", Code.Conv_Ovf_U2_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U4_Un = new OpCode("conv.ovf.u4.un", Code.Conv_Ovf_U4_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U8_Un = new OpCode("conv.ovf.u8.un", Code.Conv_Ovf_U8_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Conv_Ovf_I_Un = new OpCode("conv.ovf.i.un", Code.Conv_Ovf_I_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U_Un = new OpCode("conv.ovf.u.un", Code.Conv_Ovf_U_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Box = new OpCode("box", Code.Box, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Pop1); Newarr = new OpCode("newarr", Code.Newarr, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popi); Ldlen = new OpCode("ldlen", Code.Ldlen, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); Ldelema = new OpCode("ldelema", Code.Ldelema, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_I1 = new OpCode("ldelem.i1", Code.Ldelem_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_U1 = new OpCode("ldelem.u1", Code.Ldelem_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_I2 = new OpCode("ldelem.i2", Code.Ldelem_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_U2 = new OpCode("ldelem.u2", Code.Ldelem_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_I4 = new OpCode("ldelem.i4", Code.Ldelem_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_U4 = new OpCode("ldelem.u4", Code.Ldelem_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_I8 = new OpCode("ldelem.i8", Code.Ldelem_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi8, StackBehaviour.Popref_popi); Ldelem_I = new OpCode("ldelem.i", Code.Ldelem_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); Ldelem_R4 = new OpCode("ldelem.r4", Code.Ldelem_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushr4, StackBehaviour.Popref_popi); Ldelem_R8 = new OpCode("ldelem.r8", Code.Ldelem_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushr8, StackBehaviour.Popref_popi); Ldelem_Ref = new OpCode("ldelem.ref", Code.Ldelem_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popref_popi); Stelem_I = new OpCode("stelem.i", Code.Stelem_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); Stelem_I1 = new OpCode("stelem.i1", Code.Stelem_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); Stelem_I2 = new OpCode("stelem.i2", Code.Stelem_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); Stelem_I4 = new OpCode("stelem.i4", Code.Stelem_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); Stelem_I8 = new OpCode("stelem.i8", Code.Stelem_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi8); Stelem_R4 = new OpCode("stelem.r4", Code.Stelem_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popr4); Stelem_R8 = new OpCode("stelem.r8", Code.Stelem_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popr8); Stelem_Ref = new OpCode("stelem.ref", Code.Stelem_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popref); Ldelem = new OpCode("ldelem", Code.Ldelem, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref_popi); Stelem = new OpCode("stelem", Code.Stelem, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_pop1); Unbox_Any = new OpCode("unbox.any", Code.Unbox_Any, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref); Conv_Ovf_I1 = new OpCode("conv.ovf.i1", Code.Conv_Ovf_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U1 = new OpCode("conv.ovf.u1", Code.Conv_Ovf_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I2 = new OpCode("conv.ovf.i2", Code.Conv_Ovf_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U2 = new OpCode("conv.ovf.u2", Code.Conv_Ovf_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I4 = new OpCode("conv.ovf.i4", Code.Conv_Ovf_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U4 = new OpCode("conv.ovf.u4", Code.Conv_Ovf_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I8 = new OpCode("conv.ovf.i8", Code.Conv_Ovf_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Conv_Ovf_U8 = new OpCode("conv.ovf.u8", Code.Conv_Ovf_U8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); Refanyval = new OpCode("refanyval", Code.Refanyval, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Ckfinite = new OpCode("ckfinite", Code.Ckfinite, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); Mkrefany = new OpCode("mkrefany", Code.Mkrefany, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Popi); Ldtoken = new OpCode("ldtoken", Code.Ldtoken, OperandType.InlineTok, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Conv_U2 = new OpCode("conv.u2", Code.Conv_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_U1 = new OpCode("conv.u1", Code.Conv_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_I = new OpCode("conv.i", Code.Conv_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_I = new OpCode("conv.ovf.i", Code.Conv_Ovf_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Conv_Ovf_U = new OpCode("conv.ovf.u", Code.Conv_Ovf_U, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Add_Ovf = new OpCode("add.ovf", Code.Add_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Add_Ovf_Un = new OpCode("add.ovf.un", Code.Add_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Mul_Ovf = new OpCode("mul.ovf", Code.Mul_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Mul_Ovf_Un = new OpCode("mul.ovf.un", Code.Mul_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Sub_Ovf = new OpCode("sub.ovf", Code.Sub_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Sub_Ovf_Un = new OpCode("sub.ovf.un", Code.Sub_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); Endfinally = new OpCode("endfinally", Code.Endfinally, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); Leave = new OpCode("leave", Code.Leave, OperandType.InlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); Leave_S = new OpCode("leave.s", Code.Leave_S, OperandType.ShortInlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); Stind_I = new OpCode("stind.i", Code.Stind_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); Conv_U = new OpCode("conv.u", Code.Conv_U, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Prefix7 = new OpCode("prefix7", Code.Prefix7, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix6 = new OpCode("prefix6", Code.Prefix6, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix5 = new OpCode("prefix5", Code.Prefix5, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix4 = new OpCode("prefix4", Code.Prefix4, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix3 = new OpCode("prefix3", Code.Prefix3, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix2 = new OpCode("prefix2", Code.Prefix2, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefix1 = new OpCode("prefix1", Code.Prefix1, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Prefixref = new OpCode("prefixref", Code.Prefixref, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); Arglist = new OpCode("arglist", Code.Arglist, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Ceq = new OpCode("ceq", Code.Ceq, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); Cgt = new OpCode("cgt", Code.Cgt, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); Cgt_Un = new OpCode("cgt.un", Code.Cgt_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); Clt = new OpCode("clt", Code.Clt, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); Clt_Un = new OpCode("clt.un", Code.Clt_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); Ldftn = new OpCode("ldftn", Code.Ldftn, OperandType.InlineMethod, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Ldvirtftn = new OpCode("ldvirtftn", Code.Ldvirtftn, OperandType.InlineMethod, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popref); Ldarg = new OpCode("ldarg", Code.Ldarg, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop0); Ldarga = new OpCode("ldarga", Code.Ldarga, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Starg = new OpCode("starg", Code.Starg, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); Ldloc = new OpCode("ldloc", Code.Ldloc, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop0); Ldloca = new OpCode("ldloca", Code.Ldloca, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Stloc = new OpCode("stloc", Code.Stloc, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); Localloc = new OpCode("localloc", Code.Localloc, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); Endfilter = new OpCode("endfilter", Code.Endfilter, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); Unaligned = new OpCode("unaligned.", Code.Unaligned, OperandType.ShortInlineI, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); Volatile = new OpCode("volatile.", Code.Volatile, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); Tailcall = new OpCode("tail.", Code.Tailcall, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); Initobj = new OpCode("initobj", Code.Initobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popi); Constrained = new OpCode("constrained.", Code.Constrained, OperandType.InlineType, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); Cpblk = new OpCode("cpblk", Code.Cpblk, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi_popi); Initblk = new OpCode("initblk", Code.Initblk, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi_popi); No = new OpCode("no.", Code.No, OperandType.ShortInlineI, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); Rethrow = new OpCode("rethrow", Code.Rethrow, OperandType.InlineNone, FlowControl.Throw, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Pop0); Sizeof = new OpCode("sizeof", Code.Sizeof, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); Refanytype = new OpCode("refanytype", Code.Refanytype, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); Readonly = new OpCode("readonly.", Code.Readonly, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); for (int i = 0; i < OneByteOpCodes.Length; i++) { if (OneByteOpCodes[i] == null) { OneByteOpCodes[i] = UNKNOWN1; } } for (int j = 0; j < TwoByteOpCodes.Length; j++) { if (TwoByteOpCodes[j] == null) { TwoByteOpCodes[j] = UNKNOWN2; } } } } public enum OpCodeType : byte { Annotation, Macro, Nternal, Objmodel, Prefix, Primitive, Experimental } public enum OperandType : byte { InlineBrTarget, InlineField, InlineI, InlineI8, InlineMethod, InlineNone, InlinePhi, InlineR, NOT_USED_8, InlineSig, InlineString, InlineSwitch, InlineTok, InlineType, InlineVar, ShortInlineBrTarget, ShortInlineI, ShortInlineR, ShortInlineVar } public enum StackBehaviour : byte { Pop0 = 0, Pop1 = 1, Pop1_pop1 = 2, Popi = 3, Popi_pop1 = 4, Popi_popi = 5, Popi_popi8 = 6, Popi_popi_popi = 7, Popi_popr4 = 8, Popi_popr8 = 9, Popref = 10, Popref_pop1 = 11, Popref_popi = 12, Popref_popi_popi = 13, Popref_popi_popi8 = 14, Popref_popi_popr4 = 15, Popref_popi_popr8 = 16, Popref_popi_popref = 17, Push0 = 18, Push1 = 19, Push1_push1 = 20, Pushi = 21, Pushi8 = 22, Pushr4 = 23, Pushr8 = 24, Pushref = 25, Varpop = 26, Varpush = 27, Popref_popi_pop1 = 28, PopAll = byte.MaxValue } }