/SHFB/Source/MRefBuilder/CCI/Reader.cs
C# | 5822 lines | 5398 code | 311 blank | 113 comment | 1647 complexity | 4e5dc2e8accf5056413d2140985e6bc7 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
Large files files are truncated, but you can click here to view the full file
- // Copyright Š Microsoft Corporation.
- // This source file is subject to the Microsoft Permissive License.
- // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
- // All other rights reserved.
-
- // Change history:
- // 11/21/2013 - EFW - Cleared out the conditional statements and updated based on changes to ListTemplate.cs.
- // 12/15/2013 - EFW - Fixed a bug found when parsing the .NET 4.5.1 Framework assemblies
-
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using Marshal = System.Runtime.InteropServices.Marshal;
- using System.Runtime.InteropServices;
-
- namespace System.Compiler.Metadata
- {
- enum CorOpenFlags : uint
- {
- ofRead = 0x00000000, // Open scope for read
- ofWrite = 0x00000001, // Open scope for write.
- ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory.
- ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image
- ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib.
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("809c652e-7396-11d2-9771-00A0C9B4D50C")]
- interface IMetaDataDispenser
- {
- void DefineScope(ref Guid clsid, uint createFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval);
- [PreserveSig]
- int OpenScope(string scope, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object import);
- void OpenScopeOnMemory(IntPtr data, uint dataSize, uint openFlags, [In] ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object retval);
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("AA544D42-28CB-11d3-BD22-0000F80849BD")]
- interface ISymUnmanagedBinder
- {
- [PreserveSig]
- int GetReaderForFile([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, out ISymUnmanagedReader reader);
- ISymUnmanagedReader GetReaderForStream([MarshalAs(UnmanagedType.IUnknown)] object importer, [MarshalAs(UnmanagedType.IUnknown)] object stream);
- }
- [ComImport, Guid("ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(false)]
- interface ISymUnmanagedBinder2 : ISymUnmanagedBinder
- {
- void GetReaderForFile(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String filename, [MarshalAs(UnmanagedType.LPWStr)] String SearchPath, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal);
- void GetReaderFromStream(IntPtr importer, IntPtr stream, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader retVal);
- [PreserveSig]
- int GetReaderForFile2([MarshalAs(UnmanagedType.IUnknown)] object importer, [MarshalAs(UnmanagedType.LPWStr)] String fileName, [MarshalAs(UnmanagedType.LPWStr)] String searchPath, int searchPolicy, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader pRetVal);
- // void GetReaderForFile3(IntPtr importer, [MarshalAs(UnmanagedType.LPWStr)] String fileName, [MarshalAs(UnmanagedType.LPWStr)] String searchPath, int searchPolicy, IntPtr callback, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedReader pRetVal);
- }
- [ComImport, Guid("AA544D41-28CB-11d3-BD22-0000F80849BD")]
- class CorSymBinder
- {
- }
- [ComImport, Guid("0A29FF9E-7F9C-4437-8B11-F424491E3931")]
- class CorSymBinder2
- {
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5")]
- interface ISymUnmanagedReader
- {
- ISymUnmanagedDocument GetDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType);
- void GetDocuments(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] docs);
- uint GetUserEntryPoint();
- [PreserveSig]
- int GetMethod(uint token, ref ISymUnmanagedMethod method);
- ISymUnmanagedMethod GetMethodByVersion(uint token, int version);
- void GetVariables(uint parent, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedVariable[] vars);
- void GetGlobalVariables(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] vars);
- ISymUnmanagedMethod GetMethodFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column);
- void GetSymAttribute(uint parent, string name, ulong size, ref uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer);
- void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces);
- void Initialize([MarshalAs(UnmanagedType.IUnknown)] object importer, string filename, string searchPath, [MarshalAs(UnmanagedType.IUnknown)] object stream);
- void UpdateSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream);
- void ReplaceSymbolStore(string filename, [MarshalAs(UnmanagedType.IUnknown)] object stream);
- void GetSymbolStoreFileName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name);
- void GetMethodsFromDocumentPosition(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] ISymUnmanagedMethod[] retval);
- void GetDocumentVersion(ISymUnmanagedDocument doc, out int version, out bool isLatest);
- void GetMethodVersion(ISymUnmanagedMethod method, out int version);
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B62B923C-B500-3158-A543-24F307A8B7E1")]
- interface ISymUnmanagedMethod
- {
- uint GetToken();
- uint GetSequencePointCount();
- ISymUnmanagedScope GetRootScope();
- ISymUnmanagedScope GetScopeFromOffset(uint offset);
- uint Getoffset(ISymUnmanagedDocument document, uint line, uint column);
- void GetRanges(ISymUnmanagedDocument document, uint line, uint column, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] ranges);
- void GetParameters(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] parms);
- IntPtr GetNamespace();
- bool GetSourceStartEnd([MarshalAs(UnmanagedType.LPArray, SizeConst = 2)] ISymUnmanagedDocument[] docs, [MarshalAs(UnmanagedType.LPArray)] uint[] lines, [MarshalAs(UnmanagedType.LPArray)] uint[] columns);
- void GetSequencePoints(uint size, out uint length,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] offsets,
- [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, SizeParamIndex = 0)] IntPtr[] documents,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] lines,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] columns,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endLines,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] endColumns);
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08")]
- interface ISymUnmanagedDocument
- {
- void GetURL(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] url);
- void GetDocumentType(out Guid retval);
- void GetLanguage(out Guid retval);
- void GetLanguageVendor(out Guid retval);
- void GetCheckSumAlgorithmId(out Guid retval);
- void GetCheckSum(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] data);
- uint FindClosestLine(uint line);
- bool HasEmbeddedSource();
- uint GetSourceLength();
- void GetSourceRange(uint startLine, uint startColumn, uint endLine, uint endColumn, uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] source);
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB")]
- interface ISymUnmanagedVariable
- {
- void GetName(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] name);
- uint GetAttributes();
- void GetSignature(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] name);
- uint GetAddressKind();
- uint GetAddressField1();
- uint GetAddressField2();
- uint GetAddressField3();
- uint GetStartOffset();
- uint GetEndOffset();
- }
- [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("68005D0F-B8E0-3B01-84D5-A11A94154942")]
- interface ISymUnmanagedScope
- {
- ISymUnmanagedMethod GetMethod();
- ISymUnmanagedScope GetParent();
- void GetChildren(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] children);
- uint GetStartOffset();
- uint GetEndOffset();
- uint GetLocalCount();
- void GetLocals(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] locals);
- void GetNamespaces(uint size, out uint length, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] namespaces);
- }
-
- internal sealed class UnmanagedBuffer : IDisposable
- {
- internal IntPtr Pointer;
- internal UnmanagedBuffer(int length)
- {
- this.Pointer = Marshal.AllocHGlobal(length);
- }
- public void Dispose()
- {
- if (this.Pointer != IntPtr.Zero)
- Marshal.FreeHGlobal(this.Pointer);
- this.Pointer = IntPtr.Zero;
- GC.SuppressFinalize(this);
- }
- ~UnmanagedBuffer()
- {
- this.Dispose();
- }
- }
- internal unsafe class Reader : IDisposable
- {
- private string directory;
- private string fileName;
- private bool doNotLockFile;
- private Module/*!*/ module = new Module();
- internal TypeNode currentType;
- private long sortedTablesMask;
- internal MetadataReader/*!*/ tables;
- private UnmanagedBuffer unmanagedBuffer;
- private int bufferLength;
- private IDictionary/*!*/ localAssemblyCache; //use for simple names
- internal readonly static IDictionary/*!*/ StaticAssemblyCache = new SynchronizedWeakDictionary(); //use for strong names
- private bool useStaticCache;
- //^ [Microsoft.Contracts.SpecInternal]
- private TrivialHashtable namespaceTable;
- internal NamespaceList namespaceList;
- internal ISymUnmanagedReader debugReader;
-
- internal bool getDebugSymbols;
- private bool getDebugSymbolsFailed;
- private TypeNodeList currentTypeParameters;
- private TypeNodeList currentMethodTypeParameters;
- internal bool preserveShortBranches;
-
- internal unsafe Reader(byte[]/*!*/ buffer, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
- {
- Debug.Assert(buffer != null);
- if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
- this.localAssemblyCache = localAssemblyCache;
- this.getDebugSymbols = getDebugInfo;
- this.doNotLockFile = false;
- this.useStaticCache = useStaticCache;
- this.preserveShortBranches = preserveShortBranches;
- int n = this.bufferLength = buffer.Length;
- this.unmanagedBuffer = new UnmanagedBuffer(n);
- //^ base();
- byte* pb = (byte*)this.unmanagedBuffer.Pointer;
- for (int i = 0; i < n; i++) *pb++ = buffer[i];
- }
-
- internal Reader(string/*!*/ fileName, IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
- {
- if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
- this.localAssemblyCache = localAssemblyCache;
- fileName = System.IO.Path.GetFullPath(fileName);
- this.fileName = fileName;
- this.directory = System.IO.Path.GetDirectoryName(fileName);
- this.getDebugSymbols = getDebugInfo;
- this.doNotLockFile = doNotLockFile;
- this.useStaticCache = useStaticCache;
- this.preserveShortBranches = preserveShortBranches;
- //^ base();
- }
- internal Reader(IDictionary localAssemblyCache, bool doNotLockFile, bool getDebugInfo, bool useStaticCache, bool preserveShortBranches)
- {
- if (localAssemblyCache == null) localAssemblyCache = new Hashtable();
- this.localAssemblyCache = localAssemblyCache;
- this.directory = System.IO.Directory.GetCurrentDirectory();
- this.getDebugSymbols = getDebugInfo;
- this.doNotLockFile = doNotLockFile;
- this.useStaticCache = useStaticCache;
- this.preserveShortBranches = preserveShortBranches;
- //^ base();
- }
- public void Dispose()
- {
- if (this.unmanagedBuffer != null)
- this.unmanagedBuffer.Dispose();
- this.unmanagedBuffer = null;
- if (this.tables != null)
- this.tables.Dispose();
- //this.tables = null;
-
- if (this.debugReader != null)
- Marshal.ReleaseComObject(this.debugReader);
- this.debugReader = null;
- }
- private unsafe void SetupReader()
- {
- Debug.Assert(this.localAssemblyCache != null);
-
- if (this.doNotLockFile)
- {
- using (System.IO.FileStream inputStream = new System.IO.FileStream(this.fileName,
- System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
- {
- this.ReadFileIntoUnmanagedBuffer(inputStream);
- }
- }
- if (this.unmanagedBuffer == null)
- this.tables = new MetadataReader(this.fileName); //Uses a memory map that locks the file
- else
- this.tables = new MetadataReader((byte*)this.unmanagedBuffer.Pointer, this.bufferLength);
-
- //^ assume this.tables.tablesHeader != null;
- this.sortedTablesMask = this.tables.tablesHeader.maskSorted;
- }
-
- [DllImport("kernel32", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- static extern unsafe bool ReadFile(IntPtr FileHandle, byte* Buffer, int NumberOfBytesToRead, int* NumberOfBytesRead, IntPtr Overlapped);
-
- private unsafe void ReadFileIntoUnmanagedBuffer(System.IO.FileStream/*!*/ inputStream)
- {
- long size = inputStream.Seek(0, System.IO.SeekOrigin.End);
- if (size > int.MaxValue) throw new System.IO.FileLoadException();
- inputStream.Seek(0, System.IO.SeekOrigin.Begin);
- int n = (int)size;
- this.bufferLength = n;
- this.unmanagedBuffer = new UnmanagedBuffer(n);
- byte* pb = (byte*)this.unmanagedBuffer.Pointer;
-
- if(!Reader.ReadFile(inputStream.SafeFileHandle.DangerousGetHandle(), pb, n, &n, IntPtr.Zero))
- throw new System.IO.FileLoadException();
- }
- internal void SetupDebugReader(string filename, string pdbSearchPath)
- {
- if (filename == null) return;
- CorSymBinder binderObj1 = null;
- CorSymBinder2 binderObj2 = null;
- getDebugSymbolsFailed = false;
- object importer = null;
- try
- {
- int hresult = 0;
- try
- {
- binderObj2 = new CorSymBinder2();
- ISymUnmanagedBinder2 binder2 = (ISymUnmanagedBinder2)binderObj2;
-
- importer = new EmptyImporter();
- hresult = binder2.GetReaderForFile(importer, filename, pdbSearchPath, out this.debugReader);
- }
- catch (COMException e)
- {
- // could not instantiate ISymUnmanagedBinder2, fall back to ISymUnmanagedBinder
- if ((uint)e.ErrorCode == 0x80040111)
- {
- binderObj1 = new CorSymBinder();
- ISymUnmanagedBinder binder = (ISymUnmanagedBinder)binderObj1;
- hresult = binder.GetReaderForFile(importer, filename, null, out this.debugReader);
- }
- else
- {
- throw;
- }
- }
- switch ((uint)hresult)
- {
- case 0x0: break;
- case 0x806d0005: // EC_NOT_FOUND
- case 0x806d0014: // EC_INVALID_EXE_TIMESTAMP
- // Sometimes GetReaderForFile erroneously reports missing pdb files as being "out of date",
- // so we check if the file actually exists before reporting the error.
- // The mere absence of a pdb file is not an error. If not present, do not report.
- if (System.IO.File.Exists(System.IO.Path.ChangeExtension(filename, ".pdb")))
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExceptionStrings.PdbAssociatedWithFileIsOutOfDate, filename));
- break;
- default:
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
- ExceptionStrings.GetReaderForFileReturnedUnexpectedHResult, hresult.ToString("X")));
- }
- }
- catch (Exception e)
- {
- this.getDebugSymbols = false;
- this.getDebugSymbolsFailed = true;
- if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
- this.module.MetadataImportErrors.Add(e);
- }
- finally
- {
- if (binderObj1 != null) Marshal.ReleaseComObject(binderObj1);
- if (binderObj2 != null) Marshal.ReleaseComObject(binderObj2);
- }
- }
- private AssemblyNode ReadAssembly()
- {
- try
- {
- AssemblyNode assembly = new AssemblyNode(new Module.TypeNodeProvider(this.GetTypeFromName),
- new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor),
- new Module.ResourceProvider(this.GetResources), this.directory);
- assembly.reader = this;
- this.ReadModuleProperties(assembly);
- this.ReadAssemblyProperties(assembly); //Hashvalue, Name, etc.
- this.module = assembly;
- this.ReadAssemblyReferences(assembly);
- this.ReadModuleReferences(assembly);
- AssemblyNode cachedAssembly = this.GetCachedAssembly(assembly);
- if (cachedAssembly != null) return cachedAssembly;
- if (this.getDebugSymbols) assembly.SetupDebugReader(null);
-
- assembly.AfterAssemblyLoadProcessing();
-
- return assembly;
- }
- catch (Exception e)
- {
- if (this.module == null) return null;
- if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
- this.module.MetadataImportErrors.Add(e);
- return this.module as AssemblyNode;
- }
- }
-
- private AssemblyNode GetCachedAssembly(AssemblyNode/*!*/ assembly)
- {
- //Always return the one true mscorlib. Things get too weird if more than one mscorlib is being read at the same time.
- //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assembly.Name && CoreSystemTypes.SystemAssembly.reader != null) {
- // if (CoreSystemTypes.SystemAssembly.reader != this) {
- // if (this.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbols && !CoreSystemTypes.SystemAssembly.reader.getDebugSymbolsFailed)
- // CoreSystemTypes.SystemAssembly.SetupDebugReader(null);
- // this.Dispose();
- // }
- // return CoreSystemTypes.SystemAssembly;
- //}
- if (assembly.PublicKeyOrToken == null || assembly.PublicKeyOrToken.Length == 0)
- {
- AssemblyNode cachedAssembly = null;
- if (assembly.Location != null)
- cachedAssembly = this.localAssemblyCache[assembly.Location] as AssemblyNode;
- if (cachedAssembly == null && assembly.Name != null)
- {
- cachedAssembly = this.localAssemblyCache[assembly.Name] as AssemblyNode;
- if (cachedAssembly != null && assembly.Location != null)
- this.localAssemblyCache[assembly.Location] = cachedAssembly;
- }
- if (cachedAssembly != null)
- {
- if (cachedAssembly.reader != this && cachedAssembly.reader != null)
- {
- if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed)
- cachedAssembly.SetupDebugReader(null);
- this.Dispose();
- }
- return cachedAssembly;
- }
- lock (Reader.StaticAssemblyCache)
- {
- if (assembly.Name != null)
- this.localAssemblyCache[assembly.Name] = assembly;
- if (this.fileName != null)
- this.localAssemblyCache[this.fileName] = assembly;
- }
- }
- else
- {
- string assemblyStrongName = assembly.StrongName;
- AssemblyNode cachedAssembly = null;
- if (this.useStaticCache)
- {
- //See if assembly is a platform assembly (and apply unification)
- AssemblyReference assemblyReference = new AssemblyReference(assembly);
- AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(assemblyReference.Name).UniqueIdKey];
- if (aRef != null && assemblyReference.Version != null && aRef.Version >= assemblyReference.Version && aRef.MatchesIgnoringVersion(assemblyReference))
- {
- AssemblyNode platformAssembly = aRef.assembly;
- if (platformAssembly == null)
- {
- Debug.Assert(aRef.Location != null);
- if (Path.GetFullPath(aRef.Location) == assembly.Location)
- {
- if (aRef.Version != assemblyReference.Version)
- {
- HandleError(assembly, String.Format(CultureInfo.CurrentCulture, ExceptionStrings.BadTargetPlatformLocation, assembly.Name, TargetPlatform.PlatformAssembliesLocation, assembly.Version, aRef.Version));
- }
- lock (Reader.StaticAssemblyCache)
- {
- Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
- if (aRef.Location != null)
- Reader.StaticAssemblyCache[aRef.Location] = assembly;
- }
- return null; //Prevents infinite recursion
- }
- platformAssembly = AssemblyNode.GetAssembly(aRef.Location, this.doNotLockFile, this.getDebugSymbols, this.useStaticCache);
- }
- if (platformAssembly != null)
- {
- lock (Reader.StaticAssemblyCache)
- {
- if (aRef.Location != null)
- Reader.StaticAssemblyCache[aRef.Location] = platformAssembly;
- Reader.StaticAssemblyCache[assemblyStrongName] = platformAssembly;
- }
- return aRef.assembly = platformAssembly;
- }
- }
- cachedAssembly = Reader.StaticAssemblyCache[assemblyStrongName] as AssemblyNode;
- if (cachedAssembly != null)
- {
- if (aRef == null && assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc &&
- assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location)
- {
- lock (Reader.StaticAssemblyCache)
- {
- Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
- }
- return null;
- }
- if (cachedAssembly.reader != this && cachedAssembly.reader != null)
- {
- if (this.getDebugSymbols && !cachedAssembly.reader.getDebugSymbols && !cachedAssembly.reader.getDebugSymbolsFailed)
- cachedAssembly.SetupDebugReader(null);
- this.Dispose();
- }
- return cachedAssembly;
- }
- lock (Reader.StaticAssemblyCache)
- {
- Reader.StaticAssemblyCache[assemblyStrongName] = assembly;
- if (this.fileName != null)
- {
- Reader.StaticAssemblyCache[this.fileName] = assembly;
- }
- }
- }
- else
- {
- cachedAssembly = this.localAssemblyCache[assemblyStrongName] as AssemblyNode;
- if (cachedAssembly != null)
- {
- if (assembly.FileLastWriteTimeUtc > cachedAssembly.FileLastWriteTimeUtc &&
- assembly.Location != null && cachedAssembly.Location != null && assembly.Location == cachedAssembly.Location)
- {
- this.localAssemblyCache[assemblyStrongName] = assembly;
- return null;
- }
- if (cachedAssembly.reader != this && cachedAssembly.reader != null)
- {
- if (this.getDebugSymbols && cachedAssembly.reader.debugReader == null && !cachedAssembly.reader.getDebugSymbolsFailed)
- cachedAssembly.SetupDebugReader(null);
-
- this.Dispose();
- }
- return cachedAssembly;
- }
- this.localAssemblyCache[assemblyStrongName] = assembly;
- if (this.fileName != null) this.localAssemblyCache[this.fileName] = assembly;
- }
- }
- return null;
- }
- internal Module ReadModule()
- {
- try
- {
- if (this.fileName != null)
- {
- if (!System.IO.File.Exists(this.fileName)) return null;
- AssemblyNode cachedAssembly;
- if (this.useStaticCache)
- {
- cachedAssembly = Reader.StaticAssemblyCache[this.fileName] as AssemblyNode;
- if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName))
- {
- this.Dispose();
- return cachedAssembly;
- }
- }
- cachedAssembly = this.localAssemblyCache[this.fileName] as AssemblyNode;
- if (cachedAssembly != null && cachedAssembly.FileLastWriteTimeUtc == System.IO.File.GetLastWriteTimeUtc(this.fileName))
- {
- this.Dispose();
- return cachedAssembly;
- }
- }
- this.SetupReader();
- if (this.tables.AssemblyTable.Length > 0) return this.ReadAssembly();
- Module module = this.module = new Module(new Module.TypeNodeProvider(this.GetTypeFromName),
- new Module.TypeNodeListProvider(this.GetTypeList), new Module.CustomAttributeProvider(this.GetCustomAttributesFor),
- new Module.ResourceProvider(this.GetResources));
- module.reader = this;
- this.ReadModuleProperties(module);
- this.module = module;
- this.ReadAssemblyReferences(module);
- this.ReadModuleReferences(module);
- if (this.getDebugSymbols) this.SetupDebugReader(this.fileName, null);
- return module;
- }
- catch (Exception e)
- {
- if (this.module == null) return null;
- if (this.module.MetadataImportErrors == null) this.module.MetadataImportErrors = new ArrayList();
- this.module.MetadataImportErrors.Add(e);
- return module;
- }
- }
-
- private void ReadModuleProperties(Module/*!*/ module)
- {
- ModuleRow[] mods = this.tables.ModuleTable;
- if (mods.Length != 1) throw new InvalidMetadataException(ExceptionStrings.InvalidModuleTable);
- ModuleRow mrow = mods[0];
- module.reader = this;
- module.FileAlignment = this.tables.fileAlignment;
- module.HashValue = this.tables.HashValue;
- module.Kind = this.tables.moduleKind;
- module.Location = this.fileName;
- module.TargetRuntimeVersion = this.tables.targetRuntimeVersion;
- module.LinkerMajorVersion = this.tables.linkerMajorVersion;
- module.LinkerMinorVersion = this.tables.linkerMinorVersion;
- module.MetadataFormatMajorVersion = this.tables.metadataFormatMajorVersion;
- module.MetadataFormatMinorVersion = this.tables.metadataFormatMinorVersion;
- module.Name = this.tables.GetString(mrow.Name);
- module.Mvid = this.tables.GetGuid(mrow.Mvid);
- module.PEKind = this.tables.peKind;
- module.TrackDebugData = this.tables.TrackDebugData;
- }
- private void ReadAssemblyProperties(AssemblyNode/*!*/ assembly)
- {
- AssemblyRow assemblyRow = this.tables.AssemblyTable[0];
- assembly.HashAlgorithm = (AssemblyHashAlgorithm)assemblyRow.HashAlgId;
- assembly.Version = new System.Version(assemblyRow.MajorVersion, assemblyRow.MinorVersion, assemblyRow.BuildNumber, assemblyRow.RevisionNumber);
- assembly.Flags = (AssemblyFlags)assemblyRow.Flags;
- assembly.PublicKeyOrToken = this.tables.GetBlob(assemblyRow.PublicKey);
- assembly.ModuleName = assembly.Name;
- assembly.Name = this.tables.GetString(assemblyRow.Name);
- assembly.Culture = this.tables.GetString(assemblyRow.Culture);
- if (this.fileName != null)
- {
- assembly.FileLastWriteTimeUtc = System.IO.File.GetLastWriteTimeUtc(this.fileName);
- }
- assembly.ContainingAssembly = assembly;
- }
-
- private void ReadAssemblyReferences(Module/*!*/ module)
- {
- AssemblyRefRow[] assems = this.tables.AssemblyRefTable;
- int n = assems.Length;
-
- AssemblyReferenceList assemblies = module.AssemblyReferences = new AssemblyReferenceList();
-
- for(int i = 0; i < n; i++)
- {
- AssemblyRefRow arr = assems[i];
- AssemblyReference assemRef = new AssemblyReference();
- assemRef.Version = new System.Version(arr.MajorVersion, arr.MinorVersion, arr.BuildNumber, arr.RevisionNumber);
- assemRef.Flags = (AssemblyFlags)arr.Flags;
- assemRef.PublicKeyOrToken = this.tables.GetBlob(arr.PublicKeyOrToken);
- assemRef.Name = this.tables.GetString(arr.Name);
-
- //if (CoreSystemTypes.SystemAssembly != null && CoreSystemTypes.SystemAssembly.Name == assemRef.Name &&
- // assemRef.Version > CoreSystemTypes.SystemAssembly.Version){
- // HandleError(module, ExceptionStrings.ModuleOrAssemblyDependsOnMoreRecentVersionOfCoreLibrary);
- //}
-
- assemRef.Culture = this.tables.GetString(arr.Culture);
-
- if(assemRef.Culture != null && assemRef.Culture.Length == 0)
- assemRef.Culture = null;
-
- assemRef.HashValue = this.tables.GetBlob(arr.HashValue);
- assemRef.Reader = this;
- assems[i].AssemblyReference = assemRef;
-
- assemblies.Add(assemRef);
- }
- }
-
- private void ReadModuleReferences(Module/*!*/ module)
- {
- FileRow[] files = this.tables.FileTable;
- ModuleRefRow[] modRefs = this.tables.ModuleRefTable;
- int n = modRefs.Length;
- ModuleReferenceList modules = module.ModuleReferences = new ModuleReferenceList();
-
- for(int i = 0; i < n; i++)
- {
- Module mod;
- int nameIndex = modRefs[i].Name;
- string name = this.tables.GetString(nameIndex);
- string dir = GetDirectoryName(this.module.Location);
- string location = Combine(dir, name);
-
- for (int j = 0, m = files == null ? 0 : files.Length; j < m; j++)
- {
- if(files[j].Name != nameIndex)
- continue;
-
- if ((files[j].Flags & (int)FileFlags.ContainsNoMetaData) == 0)
- mod = Module.GetModule(location, this.doNotLockFile, this.getDebugSymbols, false);
- else
- mod = null;
-
- if(mod == null)
- {
- mod = new Module();
- mod.Name = name;
- mod.Location = location;
- mod.Kind = ModuleKind.UnmanagedDynamicallyLinkedLibrary;
- }
-
- mod.HashValue = this.tables.GetBlob(files[j].HashValue);
- mod.ContainingAssembly = module.ContainingAssembly;
- modRefs[i].Module = mod;
- modules.Add(new ModuleReference(name, mod));
- goto nextModRef;
- }
-
- mod = new Module();
- mod.Name = name;
- mod.Kind = ModuleKind.UnmanagedDynamicallyLinkedLibrary;
- if (System.IO.File.Exists(location)) mod.Location = location;
- mod.ContainingAssembly = module.ContainingAssembly;
- modRefs[i].Module = mod;
- modules.Add(new ModuleReference(name, mod));
- nextModRef: ;
- }
- }
-
- private static string ReadSerString(MemoryCursor/*!*/ sigReader)
- {
- int n = sigReader.ReadCompressedInt();
- if (n < 0) return null;
- return sigReader.ReadUTF8(n);
- }
- private void AddFieldsToType(TypeNode/*!*/ type, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end)
- {
- for (int i = start; i < end; i++)
- {
- int ii = i;
- if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field;
- Field field = this.GetFieldFromDef(ii, type);
- if (field != null) type.Members.Add(field);
- }
- }
- private void GetUnderlyingTypeOfEnumNode(EnumNode /*!*/enumNode, FieldRow[]/*!*/ fieldDefs, FieldPtrRow[]/*!*/ fieldPtrs, int start, int end)
- {
- TypeNode underlyingType = null;
- for (int i = start; i < end; i++)
- {
- int ii = i;
- if (fieldPtrs.Length > 0) ii = fieldPtrs[i - 1].Field;
- FieldRow fld = fieldDefs[ii - 1];
- if (fld.Field != null && !fld.Field.IsStatic)
- {
- underlyingType = fld.Field.Type;
- break;
- }
- FieldFlags fieldFlags = (FieldFlags)fld.Flags;
- if ((fieldFlags & FieldFlags.Static) == 0)
- {
- this.tables.GetSignatureLength(fld.Signature);
- MemoryCursor sigReader = this.tables.GetNewCursor();
- GetAndCheckSignatureToken(6, sigReader);
- underlyingType = this.ParseTypeSignature(sigReader);
- break;
- }
- }
- enumNode.underlyingType = underlyingType;
- }
- private void AddMethodsToType(TypeNode/*!*/ type, MethodPtrRow[]/*!*/ methodPtrs, int start, int end)
- //^ requires type.members != null;
- {
- for (int i = start; i < end; i++)
- {
- int ii = i;
- if (methodPtrs.Length > 0) ii = methodPtrs[i - 1].Method;
- Method method = this.GetMethodFromDef(ii, type);
- if (method != null && ((method.Flags & MethodFlags.RTSpecialName) == 0 || method.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey))
- type.members.Add(method);
- }
- }
- private void AddMoreStuffToParameters(Method method, ParameterList parameters, int start, int end)
- {
- ParamRow[] pars = this.tables.ParamTable;
- int n = parameters == null ? 0 : parameters.Count;
- for (int i = start; i < end; i++)
- {
- ParamRow pr = pars[i - 1];
- if (pr.Sequence == 0 && method != null)
- {
- //The parameter entry with sequence 0 is used as a target for custom attributes that apply to the return value
- method.ReturnAttributes = this.GetCustomAttributesFor((i << 5) | 4);
- if ((pr.Flags & (int)ParameterFlags.HasFieldMarshal) != 0)
- method.ReturnTypeMarshallingInformation = this.GetMarshallingInformation((i << 1) | 1);
- this.AddMoreStuffToParameters(null, parameters, start + 1, end);
- return;
- }
- int j = pr.Sequence;
- if (j < 1 || j > n) continue; //Bad metadata, ignore
- if (parameters == null) continue;
- Parameter par = parameters[j - 1];
- par.Attributes = this.GetCustomAttributesFor((i << 5) | 4);
- par.Flags = (ParameterFlags)pr.Flags;
- if ((par.Flags & ParameterFlags.HasDefault) != 0)
- par.DefaultValue = this.GetLiteral((i << 2) | 1, par.Type);
- if ((par.Flags & ParameterFlags.HasFieldMarshal) != 0)
- par.MarshallingInformation = this.GetMarshallingInformation((i << 1) | 1);
- par.Name = tables.GetIdentifier(pr.Name);
- }
- }
-
- private void AddPropertiesToType(TypeNode/*!*/ type, PropertyRow[]/*!*/ propertyDefs, PropertyPtrRow[]/*!*/ propertyPtrs, int start, int end)
- //requires type.members != null;
- {
- MetadataReader tables = this.tables;
- for (int i = start; i < end; i++)
- {
- int ii = i;
- if (propertyPtrs.Length > 0) ii = propertyPtrs[i - 1].Property;
- PropertyRow prop = propertyDefs[ii - 1];
- Property property = new Property();
- property.Attributes = this.GetCustomAttributesFor((ii << 5) | 9);
- property.DeclaringType = type;
- property.Flags = (PropertyFlags)prop.Flags;
- property.Name = tables.GetIdentifier(prop.Name);
- if ((property.Flags & PropertyFlags.RTSpecialName) == 0 || property.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
- {
- this.AddMethodsToProperty(ii, property);
- type.members.Add(property);
- }
- //REVIEW: the signature seems to be redundant. Is there any point in retrieving it?
- }
- }
- private void AddMethodsToProperty(int propIndex, Property/*!*/ property)
- {
- int codedPropIndex = (propIndex << 1) | 1;
- MetadataReader tables = this.tables;
- MethodRow[] methods = tables.MethodTable;
- MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable;
- int i = 0, n = methodSemantics.Length, j = n - 1;
- bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1;
- if (sorted)
- {
- while (i < j)
- {
- int k = (i + j) / 2;
- if (methodSemantics[k].Association < codedPropIndex)
- i = k + 1;
- else
- j = k;
- }
- while (i > 0 && methodSemantics[i - 1].Association == codedPropIndex) i--;
- }
- for (; i < n; i++)
- {
- MethodSemanticsRow meth = methodSemantics[i];
- Method propertyMethod = methods[meth.Method - 1].Method;
- if (propertyMethod == null) continue;
- if (meth.Association == codedPropIndex)
- {
- propertyMethod.DeclaringMember = property;
- switch (meth.Semantics)
- {
- case 0x0001: property.Setter = propertyMethod; break;
- case 0x0002: property.Getter = propertyMethod; break;
- default:
- if (property.OtherMethods == null) property.OtherMethods = new MethodList();
- property.OtherMethods.Add(propertyMethod); break;
- }
- }
- else if (sorted)
- break;
- }
- }
- private void AddEventsToType(TypeNode/*!*/ type, EventRow[]/*!*/ eventDefs, EventPtrRow[]/*!*/ eventPtrs, int start, int end)
- {
- MetadataReader tables = this.tables;
- for (int i = start; i < end; i++)
- {
- int ii = i;
- if (eventPtrs.Length > 0) ii = eventPtrs[i].Event;
- EventRow ev = eventDefs[ii - 1];
- Event evnt = new Event();
- evnt.Attributes = this.GetCustomAttributesFor((ii << 5) | 10);
- evnt.DeclaringType = type;
- evnt.Flags = (EventFlags)ev.Flags;
- evnt.HandlerType = this.DecodeAndGetTypeDefOrRefOrSpec(ev.EventType);
- evnt.Name = tables.GetIdentifier(ev.Name);
- if ((evnt.Flags & EventFlags.RTSpecialName) == 0 || evnt.Name.UniqueIdKey != StandardIds._Deleted.UniqueIdKey)
- {
- this.AddMethodsToEvent(ii, evnt);
- type.Members.Add(evnt);
- }
- }
- }
- private void AddMethodsToEvent(int eventIndex, Event/*!*/ evnt)
- {
- int codedEventIndex = eventIndex << 1;
- MetadataReader tables = this.tables;
- MethodRow[] methods = tables.MethodTable;
- MethodSemanticsRow[] methodSemantics = tables.MethodSemanticsTable;
- int i = 0, n = methodSemantics.Length, j = n - 1;
- bool sorted = (this.sortedTablesMask >> (int)TableIndices.MethodSemantics) % 2 == 1;
- if (sorted)
- {
- while (i < j)
- {
- int k = (i + j) / 2;
- if (methodSemantics[k].Association < codedEventIndex)
- i = k + 1;
- else
- j = k;
- }
- while (i > 0 && methodSemantics[i - 1].Association == codedEventIndex) i--;
- }
- MethodFlags handlerFlags = (MethodFlags)0;
- for (; i < n; i++)
- {
- MethodSemanticsRow meth = methodSemantics[i];
- Method eventMethod = methods[meth.Method - 1].Method;
- if (eventMethod == null) continue;
- if (meth.Association == codedEventIndex)
- {
- eventMethod.DeclaringMember = evnt;
- switch (meth.Semantics)
- {
- case 0x0008: evnt.HandlerAdder = eventMethod; handlerFlags = eventMethod.Flags; break;
- case 0x0010: evnt.HandlerRemover = eventMethod; handlerFlags = eventMethod.Flags; break;
- case 0x0020: evnt.HandlerCaller = eventMethod; break;
- default:
- if (evnt.OtherMethods == null) evnt.OtherMethods = new MethodList();
- evnt.OtherMethods.Add(eventMethod); break;
- }
- }
- else if (sorted)
- break;
- }
- evnt.HandlerFlags = handlerFlags;
- }
- private bool TypeDefOrRefOrSpecIsClass(int codedIndex)
- {
- if (codedIndex == 0) return false;
- switch (codedIndex & 0x3)
- {
- case 0x00: return this.TypeDefIsClass(codedIndex >> 2);
- case 0x01: TypeNode t = this.GetTypeFromRef(codedIndex >> 2); return t is Class;
- case 0x02: return this.TypeSpecIsClass(codedIndex >> 2);
- }
- throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
- }
- private bool TypeDefOrRefOrSpecIsClassButNotValueTypeBaseClass(int codedIndex)
- {
- if (codedIndex == 0) return false;
- switch (codedIndex & 0x3)
- {
- case 0x00: return this.TypeDefIsClassButNotValueTypeBaseClass(codedIndex >> 2);
- case 0x01:
- TypeNode t = this.GetTypeFromRef(codedIndex >> 2);
- return t != CoreSystemTypes.ValueType && t != CoreSystemTypes.Enum && t is Class;
- case 0x02: return this.TypeSpecIsClass(codedIndex >> 2);
- }
- throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
- }
- private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex)
- {
- if (codedIndex == 0) return null;
- switch (codedIndex & 0x3)
- {
- case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
- case 0x01: return this.GetTypeFromRef(codedIndex >> 2);
- case 0x02: return this.GetTypeFromSpec(codedIndex >> 2);
- }
- throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
- }
- private TypeNode DecodeAndGetTypeDefOrRefOrSpec(int codedIndex, bool expectStruct)
- {
- if (codedIndex == 0) return null;
- switch (codedIndex & 0x3)
- {
- case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
- case 0x01: return this.GetTypeFromRef(codedIndex >> 2, expectStruct);
- case 0x02: return this.GetTypeFromSpec(codedIndex >> 2);
- }
- throw new InvalidMetadataException(ExceptionStrings.BadTypeDefOrRef);
- }
-
- private TypeNode GetTypeIfNotGenericInstance(int codedIndex)
- {
- if (codedIndex == 0) return null;
- switch (codedIndex & 0x3)
- {
- case 0x00: return this.GetTypeFromDef(codedIndex >> 2);
- case 0x01: return this.GetTypeFromRef(codedIndex >> 2, false);
- }
- return null;
- }
- internal AssemblyNode/*!*/ GetAssemblyFromReference(AssemblyReference/*!*/ assemblyReference)
- {
- lock (this)
- {
- if (SystemAssemblyLocation.ParsedAssembly != null && (assemblyReference.Name == "mscorlib" || assembl…
Large files files are truncated, but you can click here to view the full file