Beispiel #1
0
 void IDisposable.Dispose()
 {
     if (_reader != null)
     {
         _reader.Dispose();
     }
 }
Beispiel #2
0
        private RoAssembly LoadFromStreamCore(Stream peStream)
        {
            PEReader peReader          = new PEReader(peStream);
            PEReader peReaderToDispose = peReader; // Ensure peReader is disposed immediately if we throw an exception before we're done.

            try
            {
                if (!peReader.HasMetadata)
                {
                    throw new BadImageFormatException(SR.NoMetadataInPeImage);
                }

                string           location    = (peStream is FileStream fs) ? (fs.Name ?? string.Empty) : string.Empty;
                MetadataReader   reader      = peReader.GetMetadataReader();
                RoAssembly       newAssembly = new EcmaAssembly(this, peReader, reader, location);
                AssemblyNameData defNameData = newAssembly.GetAssemblyNameDataNoCopy();
                byte[]           pkt         = defNameData.PublicKeyToken ?? Array.Empty <byte>();
                if (pkt.Length == 0 && defNameData.PublicKey != null && defNameData.PublicKey.Length != 0)
                {
                    pkt = defNameData.PublicKey.ComputePublicKeyToken();
                }
                RoAssemblyName defName = new RoAssemblyName(defNameData.Name, defNameData.Version, defNameData.CultureName, pkt);
                Guid           mvid    = newAssembly.ManifestModule.ModuleVersionId;

                LoadedAssemblyEntry candidate = new LoadedAssemblyEntry(newAssembly, mvid);
                LoadedAssemblyEntry winner    = _loadedAssemblies.GetOrAdd(defName, candidate);
                if (winner.Assembly == newAssembly)
                {
                    // We won the race.
                    RegisterForDisposal(peReader);
                    peReaderToDispose = null;
                    return(_binds.GetOrAdd(defName, winner.Assembly));

                    // What if we lost the race to bind the defName in the _binds list? Should we ignore it and return the newly created assembly
                    // (like Assembly.LoadModule()) does or return the prior assembly (like we do if we lose the race to commit into _loadedAssemblies?)
                    // There's no perfect answer here. Fundamentally, the dilemma comes about because our apis don't lets apps properly separate
                    // the act of creating an Assembly object from the act of committing the TypeLoader to bind to it.
                    //
                    // We will choose to return the prior winner so that the api is consistent with itself. This is how other LoadFrom()
                    // apis work and they're used a lot more than LoadModule().
                }
                else
                {
                    // We lost the race but check for a MVID mismatch.
                    if (mvid != winner.Mvid)
                    {
                        throw new FileLoadException(SR.Format(SR.FileLoadDuplicateAssemblies, defName));
                    }
                }

                return(winner.Assembly);
            }
            finally
            {
                peReaderToDispose?.Dispose();
            }
        }
Beispiel #3
0
 void IDisposable.Dispose()
 {
     if (pdb != null)
     {
         pdb.Dispose();
     }
     peReader.Dispose();
     stream.Dispose();
 }
Beispiel #4
0
        public Task <DocumentDebugInfoReader?> GetDocumentDebugInfoReaderAsync(string dllPath, CancellationToken cancellationToken)
        {
            var dllStream = IOUtilities.PerformIO(() => File.OpenRead(dllPath));

            if (dllStream is null)
            {
                return(Task.FromResult <DocumentDebugInfoReader?>(null));
            }

            Stream?pdbStream = null;
            DocumentDebugInfoReader?result = null;
            var peReader = new PEReader(dllStream);

            try
            {
                if (peReader.TryOpenAssociatedPortablePdb(dllPath, pdbPath => File.OpenRead(pdbPath), out var pdbReaderProvider, out _))
                {
                    Contract.ThrowIfNull(pdbReaderProvider);

                    result = new DocumentDebugInfoReader(peReader, pdbReaderProvider);
                }

                // TODO: Otherwise call the debugger to find the PDB from a symbol server etc.
                if (result is null)
                {
                    // Debugger needs:
                    // - PDB MVID
                    // - PDB Age
                    // - PDB TimeStamp
                    // - PDB Path
                    // - DLL Path
                    //
                    // Most of this info comes from the CodeView Debug Directory from the dll
                }
            }
            catch (BadImageFormatException)
            {
                // If the PDB is corrupt in some way we can just ignore it, and let the system fall through to another provider
                // TODO: Log this to the output window: https://github.com/dotnet/roslyn/issues/57352
                result = null;
            }
            finally
            {
                // If we're returning a result then it will own the disposal of the reader, but if not
                // then we need to do it ourselves.
                if (result is null)
                {
                    pdbStream?.Dispose();
                    peReader.Dispose();
                }
            }

            return(Task.FromResult <DocumentDebugInfoReader?>(result));
        }
        private RoAssembly LoadFromStreamCore(Stream peStream)
        {
            PEReader peReader          = new PEReader(peStream);
            PEReader?peReaderToDispose = peReader;  // Ensure peReader is disposed immediately if we throw an exception before we're done.

            try
            {
                if (!peReader.HasMetadata)
                {
                    throw new BadImageFormatException(SR.NoMetadataInPeImage);
                }

                string           location    = (peStream is FileStream fs) ? (fs.Name ?? string.Empty) : string.Empty;
                MetadataReader   reader      = peReader.GetMetadataReader();
                RoAssembly       candidate   = new EcmaAssembly(this, peReader, reader, location);
                AssemblyNameData defNameData = candidate.GetAssemblyNameDataNoCopy();
                byte[]           pkt         = defNameData.PublicKeyToken ?? Array.Empty <byte>();
                if (pkt.Length == 0 && defNameData.PublicKey != null && defNameData.PublicKey.Length != 0)
                {
                    pkt = defNameData.PublicKey.ComputePublicKeyToken() !;
                }
                RoAssemblyName defName = new RoAssemblyName(defNameData.Name, defNameData.Version, defNameData.CultureName, pkt, defNameData.Flags);

                RoAssembly winner = _loadedAssemblies.GetOrAdd(defName, candidate);
                if (winner == candidate)
                {
                    // We won the race.
                    RegisterForDisposal(peReader);
                    peReaderToDispose = null;

                    // We do not add to the _binds list because the binding list is only for assemblies that have been resolved through
                    // the Resolve method. This allows the resolver to have complete control over selecting the appropriate assembly
                    // based on Version, CultureName and PublicKeyToken.

                    return(winner);
                }
                else
                {
                    // We lost the race but check for a Mvid mismatch.
                    if (candidate.ManifestModule.ModuleVersionId != winner.ManifestModule.ModuleVersionId)
                    {
                        throw new FileLoadException(SR.Format(SR.FileLoadDuplicateAssemblies, defName));
                    }
                }

                return(winner);
            }
            finally
            {
                peReaderToDispose?.Dispose();
            }
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                if (disposing)
                {
                    _peReader.Dispose();
                    _emitStream.Dispose();
                }

                _disposedValue = true;
            }
        }
Beispiel #7
0
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    _metadataAnalyzer?.Dispose();
                    _dllReader?.Dispose();
                    _dllFile?.Dispose();
                }

                disposedValue = true;
            }
        }
Beispiel #8
0
        public void Dispose()
        {
            if (_peReader != null)
            {
                _peReader.Dispose();
                _peReader = null;
            }

            if (_fs != null)
            {
                _fs.Dispose();
                _fs = null;
            }
        }
Beispiel #9
0
        public void Dispose()
        {
            var peStream = new MemoryStream(PortablePdbs.DocumentsEmbeddedDll);
            var reader   = new PEReader(peStream);

            MetadataReaderProvider pdbProvider;
            string pdbPath;

            Assert.True(reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out pdbProvider, out pdbPath));
            Assert.NotNull(pdbProvider);
            Assert.Null(pdbPath);

            var ddEntries  = reader.ReadDebugDirectory();
            var ddCodeView = ddEntries[0];
            var ddEmbedded = ddEntries[2];

            var embeddedPdbProvider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(ddEmbedded);

            // dispose the PEReader:
            reader.Dispose();

            Assert.False(reader.IsEntireImageAvailable);

            Assert.Throws <ObjectDisposedException>(() => reader.PEHeaders);
            Assert.Throws <ObjectDisposedException>(() => reader.HasMetadata);
            Assert.Throws <ObjectDisposedException>(() => reader.GetMetadata());
            Assert.Throws <ObjectDisposedException>(() => reader.GetSectionData(1000));
            Assert.Throws <ObjectDisposedException>(() => reader.GetMetadataReader());
            Assert.Throws <ObjectDisposedException>(() => reader.GetMethodBody(0));
            Assert.Throws <ObjectDisposedException>(() => reader.GetEntireImage());
            Assert.Throws <ObjectDisposedException>(() => reader.ReadDebugDirectory());
            Assert.Throws <ObjectDisposedException>(() => reader.ReadCodeViewDebugDirectoryData(ddCodeView));
            Assert.Throws <ObjectDisposedException>(() => reader.ReadEmbeddedPortablePdbDebugDirectoryData(ddEmbedded));

            MetadataReaderProvider __;
            string ___;

            Assert.Throws <ObjectDisposedException>(() => reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out __, out ___));

            // ok to use providers after PEReader disposed:
            var pdbReader = pdbProvider.GetMetadataReader();

            Assert.Equal(13, pdbReader.Documents.Count);

            pdbReader = embeddedPdbProvider.GetMetadataReader();
            Assert.Equal(13, pdbReader.Documents.Count);

            embeddedPdbProvider.Dispose();
        }
Beispiel #10
0
        internal static unsafe AssemblyName GetAssemblyName(string assemblyFile)
        {
            if (assemblyFile == null)
            {
                throw new ArgumentNullException(nameof(assemblyFile));
            }

            FileStream?              fileStream = null;
            MemoryMappedFile?        mappedFile = null;
            MemoryMappedViewAccessor?accessor   = null;
            PEReader?peReader = null;

            try
            {
                try
                {
                    // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict
                    fileStream = new FileStream(assemblyFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false);
                    if (fileStream.Length == 0)
                    {
                        throw new BadImageFormatException(SR.PEImageDoesNotHaveMetadata, assemblyFile);
                    }

                    mappedFile = MemoryMappedFile.CreateFromFile(
                        fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true);
                    accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);

                    SafeMemoryMappedViewHandle?safeBuffer = accessor.SafeMemoryMappedViewHandle;
                    peReader = new PEReader((byte *)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength);
                    MetadataReader mdReader     = peReader.GetMetadataReader(MetadataReaderOptions.None);
                    AssemblyName   assemblyName = mdReader.GetAssemblyDefinition().GetAssemblyName();
                    return(assemblyName);
                }
                finally
                {
                    peReader?.Dispose();
                    accessor?.Dispose();
                    mappedFile?.Dispose();
                    fileStream?.Dispose();
                }
            }
            catch (InvalidOperationException ex)
            {
                throw new BadImageFormatException(ex.Message);
            }
        }
Beispiel #11
0
        void IDisposable.Dispose()
        {
            if (!_isDisposed)
            {
                for (int i = 0; i < _readerVersions.Length; i++)
                {
                    int hr = (_readerVersions[i] as ISymUnmanagedDispose).Destroy();
                    SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr);
                    _readerVersions[i] = null;
                }

                _peReaderOpt?.Dispose();
                _metadataImport.Dispose();

                _isDisposed = true;
            }
        }
Beispiel #12
0
        public void Close()
        {
            if (_peReader != null)
            {
                _peReader.Dispose();
            }

            if (_assemblyStream != null)
            {
                _assemblyStream.Close();
            }

            _attributes     = null;
            _reader         = null;
            _peReader       = null;
            _assemblyStream = null;
        }
Beispiel #13
0
        public void Ctor()
        {
            Assert.Throws <ArgumentNullException>(() => new PEReader(null, PEStreamOptions.Default));

            var invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 });

            // the stream should not be disposed if the arguments are bad
            Assert.Throws <ArgumentOutOfRangeException>(() => new PEReader(invalid, (PEStreamOptions)int.MaxValue));
            Assert.True(invalid.CanRead);

            // no BadImageFormatException if we're prefetching the entire image:
            var peReader0 = new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.LeaveOpen);

            Assert.True(invalid.CanRead);
            Assert.Throws <BadImageFormatException>(() => peReader0.PEHeaders);
            invalid.Position = 0;

            // BadImageFormatException if we're prefetching the entire image and metadata:
            Assert.Throws <BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen));
            Assert.True(invalid.CanRead);
            invalid.Position = 0;

            // the stream should be disposed if the content is bad:
            Assert.Throws <BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata));
            Assert.False(invalid.CanRead);

            // the stream should not be disposed if we specified LeaveOpen flag:
            invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 });
            Assert.Throws <BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen));
            Assert.True(invalid.CanRead);

            // valid metadata:
            var valid    = new MemoryStream(Misc.Members);
            var peReader = new PEReader(valid, PEStreamOptions.Default);

            Assert.True(valid.CanRead);
            peReader.Dispose();
            Assert.False(valid.CanRead);
        }
Beispiel #14
0
        public void Ctor()
        {
            Assert.Throws<ArgumentNullException>(() => new PEReader(null, PEStreamOptions.Default));

            var invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 });

            // the stream should not be disposed if the arguments are bad
            Assert.Throws<ArgumentOutOfRangeException>(() => new PEReader(invalid, (PEStreamOptions)int.MaxValue));
            Assert.True(invalid.CanRead);

            // no BadImageFormatException if we're prefetching the entire image:
            var peReader0 = new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.LeaveOpen);
            Assert.True(invalid.CanRead);
            Assert.Throws<BadImageFormatException>(() => peReader0.PEHeaders);
            invalid.Position = 0;

            // BadImageFormatException if we're prefetching the entire image and metadata:
            Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchEntireImage | PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen));
            Assert.True(invalid.CanRead);
            invalid.Position = 0;

            // the stream should be disposed if the content is bad:
            Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata));
            Assert.False(invalid.CanRead);

            // the stream should not be disposed if we specified LeaveOpen flag:
            invalid = new MemoryStream(new byte[] { 1, 2, 3, 4 });
            Assert.Throws<BadImageFormatException>(() => new PEReader(invalid, PEStreamOptions.PrefetchMetadata | PEStreamOptions.LeaveOpen));
            Assert.True(invalid.CanRead);

            // valid metadata:
            var valid = new MemoryStream(Misc.Members);
            var peReader = new PEReader(valid, PEStreamOptions.Default);
            Assert.True(valid.CanRead);
            peReader.Dispose();
            Assert.False(valid.CanRead);
        }
Beispiel #15
0
        public static void Load(string libName)
        {
            //AppDomain appDomain = AppDomain.CreateDomain("LibDomain_" + Path.GetFileName(libName));
            //AssemblyName assemblyName = new AssemblyName(libName);
            //var core = typeof(object).Assembly;
            //var corepath = core.CodeBase;

            //PathAssemblyResolver resolver = new PathAssemblyResolver(new string[] { Path.GetDirectoryName(corepath), $"{Environment.CurrentDirectory}" });

            ////MetadataAssemblyResolver resolver =
            //MetadataLoadContext context = new MetadataLoadContext(resolver, "mscorlib");
            //Assembly asm = context.LoadFromAssemblyPath(libName);
            //var list = asm.CustomAttributes;

            bool haveMyAttribute = false;

            using (FileStream fileStream = new FileStream(libName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                PEReader       peReader = new PEReader(fileStream, PEStreamOptions.LeaveOpen);
                MetadataReader reader   = peReader.GetMetadataReader();
                CustomAttributeHandleCollection customAttributes = reader.CustomAttributes;
                foreach (CustomAttributeHandle item in customAttributes)
                {
                    try
                    {
                        CustomAttribute attribute = reader.GetCustomAttribute(item);
                        MemberReference ctor      = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
                        TypeReference   attrType  = reader.GetTypeReference((TypeReferenceHandle)ctor.Parent);
                        string          nsName    = reader.GetString(attrType.Namespace);
                        string          typeName  = reader.GetString(attrType.Name);
                        Debug.WriteLine($"{nsName}.{typeName}");
                        if (nsName == "ImageLib.Loader" && typeName == "InitLoaderAttribute")
                        {
                            haveMyAttribute = true;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
                peReader.Dispose();

                //var asm = Assembly.ReflectionOnlyLoadFrom(libName);
                //if (asm.CustomAttributes.Any(a => a.AttributeType == typeof(InitLoaderAttribute)))
                //{
                //    Assembly assembly = Assembly.LoadFrom(libName);
                //    Load(assembly);
                //}

                if (haveMyAttribute)
                {
                    var context = new AssemblyLoadContext(null, true);
                    fileStream.Position = 0;
                    var asm = context.LoadFromStream(fileStream);
                    Load(asm, null);
                    context.Unloading += a =>
                    {
                    };
                    context.Unload();
                }
            }
        }
Beispiel #16
0
 public void Dispose()
 {
     PEReader.Dispose();
 }
 /// <inheritdoc />
 public void Dispose()
 {
     _reader?.Dispose();
 }
 public void Dispose()
 {
     _pdbReaderProvider.Dispose();
     _peReader.Dispose();
 }
 public void Dispose()
 {
     _peReader.Dispose();
     _peStream.Dispose();
 }
 public void Dispose()
 {
     _metaReader = null;
     _peReader.Dispose();
     _fs.Dispose();
 }
Beispiel #21
0
 void IDisposable.Dispose()
 => _reader?.Dispose();
Beispiel #22
0
        public void Dispose()
        {
            var peStream = new MemoryStream(PortablePdbs.DocumentsEmbeddedDll);
            var reader = new PEReader(peStream);

            MetadataReaderProvider pdbProvider;
            string pdbPath;

            Assert.True(reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out pdbProvider, out pdbPath));
            Assert.NotNull(pdbProvider);
            Assert.Null(pdbPath);

            var ddEntries = reader.ReadDebugDirectory();
            var ddCodeView = ddEntries[0];
            var ddEmbedded = ddEntries[2];

            var embeddedPdbProvider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(ddEmbedded);

            // dispose the PEReader:
            reader.Dispose();

            Assert.False(reader.IsEntireImageAvailable);

            Assert.Throws<ObjectDisposedException>(() => reader.PEHeaders);
            Assert.Throws<ObjectDisposedException>(() => reader.HasMetadata);
            Assert.Throws<ObjectDisposedException>(() => reader.GetMetadata());
            Assert.Throws<ObjectDisposedException>(() => reader.GetSectionData(1000));
            Assert.Throws<ObjectDisposedException>(() => reader.GetMetadataReader());
            Assert.Throws<ObjectDisposedException>(() => reader.GetMethodBody(0));
            Assert.Throws<ObjectDisposedException>(() => reader.GetEntireImage());
            Assert.Throws<ObjectDisposedException>(() => reader.ReadDebugDirectory());
            Assert.Throws<ObjectDisposedException>(() => reader.ReadCodeViewDebugDirectoryData(ddCodeView));
            Assert.Throws<ObjectDisposedException>(() => reader.ReadEmbeddedPortablePdbDebugDirectoryData(ddEmbedded));

            MetadataReaderProvider __;
            string ___;
            Assert.Throws<ObjectDisposedException>(() => reader.TryOpenAssociatedPortablePdb(@"x", _ => null, out __, out ___));

            // ok to use providers after PEReader disposed:
            var pdbReader = pdbProvider.GetMetadataReader();
            Assert.Equal(13, pdbReader.Documents.Count);

            pdbReader = embeddedPdbProvider.GetMetadataReader();
            Assert.Equal(13, pdbReader.Documents.Count);

            embeddedPdbProvider.Dispose();
        }
 /// <inheritdoc/>
 protected override void OnDisposing()
 {
     _metadataReaderProvider.Dispose();
     _peReader.Dispose();
 }
 public void Dispose() => PEReader.Dispose();
Beispiel #25
0
 public void Dispose()
 {
     _peReader.Dispose();
 }
        partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool foundMatch)
        {
            lock (s_ecmaLoadedAssemblies)
            {
                for (int i = 0; i < s_ecmaLoadedAssemblies.Count; i++)
                {
                    PEInfo info = s_ecmaLoadedAssemblies[i];
                    if (AssemblyNameMatches(refName, info.Name, ref preferredException))
                    {
                        if (foundMatch)
                        {
                            exception = new AmbiguousMatchException();
                            return;
                        }

                        result.EcmaMetadataReader = info.Reader;
                        foundMatch = result.EcmaMetadataReader != null;

                        // For failed matches, we will never be able to succeed, so return now
                        if (!foundMatch)
                        {
                            return;
                        }
                    }
                }

                if (!foundMatch)
                {
                    try
                    {
                        // Not found in already loaded list, attempt to source assembly from disk
                        foreach (string filePath in FilePathsForAssembly(refName))
                        {
                            FileStream ownedFileStream = null;
                            PEReader   ownedPEReader   = null;
                            try
                            {
                                if (!RuntimeAugments.FileExists(filePath))
                                {
                                    continue;
                                }

                                try
                                {
                                    ownedFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                                }
                                catch (System.IO.IOException)
                                {
                                    // Failure to open a file is not fundamentally an assembly load error, but it does indicate this file cannot be used
                                    continue;
                                }

                                ownedPEReader = new PEReader(ownedFileStream);
                                // FileStream ownership transferred to ownedPEReader
                                ownedFileStream = null;

                                if (!ownedPEReader.HasMetadata)
                                {
                                    continue;
                                }

                                MetadataReader reader = ownedPEReader.GetMetadataReader();
                                // Create AssemblyName from MetadataReader
                                RuntimeAssemblyName runtimeAssemblyName = reader.GetAssemblyDefinition().ToRuntimeAssemblyName(reader).CanonicalizePublicKeyToken();

                                // If assembly name doesn't match, it isn't the one we're looking for. Continue to look for more assemblies
                                if (!AssemblyNameMatches(refName, runtimeAssemblyName, ref preferredException))
                                {
                                    continue;
                                }

                                // This is the one we are looking for, add it to the list of loaded assemblies
                                PEInfo peinfo = new PEInfo(runtimeAssemblyName, reader, ownedPEReader);

                                s_ecmaLoadedAssemblies.Add(peinfo);

                                // At this point the PE reader is no longer owned by this code, but is owned by the s_ecmaLoadedAssemblies list
                                PEReader pe = ownedPEReader;
                                ownedPEReader = null;

                                ModuleList moduleList    = ModuleList.Instance;
                                ModuleInfo newModuleInfo = new EcmaModuleInfo(moduleList.SystemModule.Handle, pe, reader);
                                moduleList.RegisterModule(newModuleInfo);

                                foundMatch = true;
                                result.EcmaMetadataReader = peinfo.Reader;
                                break;
                            }
                            finally
                            {
                                if (ownedFileStream != null)
                                {
                                    ownedFileStream.Dispose();
                                }

                                if (ownedPEReader != null)
                                {
                                    ownedPEReader.Dispose();
                                }
                            }
                        }
                    }
                    catch (System.IO.IOException)
                    { }
                    catch (System.ArgumentException)
                    { }
                    catch (System.BadImageFormatException badImageFormat)
                    {
                        exception = badImageFormat;
                    }

                    // Cache missed lookups
                    if (cacheMissedLookups && !foundMatch)
                    {
                        PEInfo peinfo = new PEInfo(refName, null, null);
                        s_ecmaLoadedAssemblies.Add(peinfo);
                    }
                }
            }
        }
Beispiel #27
0
        public async Task <DocumentDebugInfoReader?> GetDocumentDebugInfoReaderAsync(string dllPath, TelemetryMessage telemetry, CancellationToken cancellationToken)
        {
            var dllStream = IOUtilities.PerformIO(() => File.OpenRead(dllPath));

            if (dllStream is null)
            {
                return(null);
            }

            Stream?pdbStream = null;
            DocumentDebugInfoReader?result = null;
            var peReader = new PEReader(dllStream);

            try
            {
                // Try to load the pdb file from disk, or embedded
                if (peReader.TryOpenAssociatedPortablePdb(dllPath, pdbPath => File.OpenRead(pdbPath), out var pdbReaderProvider, out var pdbFilePath))
                {
                    Contract.ThrowIfNull(pdbReaderProvider);

                    if (pdbFilePath is null)
                    {
                        telemetry.SetPdbSource("embedded");
                        _logger?.Log(FeaturesResources.Found_embedded_PDB_file);
                    }
                    else
                    {
                        telemetry.SetPdbSource("ondisk");
                        _logger?.Log(FeaturesResources.Found_PDB_file_at_0, pdbFilePath);
                    }

                    result = new DocumentDebugInfoReader(peReader, pdbReaderProvider);
                }

                if (result is null)
                {
                    if (_sourceLinkService is null)
                    {
                        _logger?.Log(FeaturesResources.Could_not_find_PDB_on_disk_or_embedded);
                    }
                    else
                    {
                        var delay = Task.Delay(SymbolLocatorTimeout, cancellationToken);
                        // Call the debugger to find the PDB from a symbol server etc.
                        var pdbResultTask = _sourceLinkService.GetPdbFilePathAsync(dllPath, peReader, cancellationToken);

                        var winner = await Task.WhenAny(pdbResultTask, delay).ConfigureAwait(false);

                        if (winner == pdbResultTask)
                        {
                            var pdbResult = await pdbResultTask.ConfigureAwait(false);

                            if (pdbResult is not null)
                            {
                                pdbStream = IOUtilities.PerformIO(() => File.OpenRead(pdbResult.PdbFilePath));
                                if (pdbStream is not null)
                                {
                                    var readerProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                                    telemetry.SetPdbSource("symbolserver");
                                    result = new DocumentDebugInfoReader(peReader, readerProvider);
                                    _logger?.Log(FeaturesResources.Found_PDB_on_symbol_server);
                                }
                                else
                                {
                                    _logger?.Log(FeaturesResources.Found_PDB_on_symbol_server_but_could_not_read_file);
                                }
                            }
                            else
                            {
                                _logger?.Log(FeaturesResources.Could_not_find_PDB_on_disk_or_embedded_or_server);
                            }
                        }
                        else
                        {
                            telemetry.SetPdbSource("timeout");
                            _logger?.Log(FeaturesResources.Timeout_symbol_server);
                        }
                    }
                }
            }
            catch (BadImageFormatException ex)
            {
                // If the PDB is corrupt in some way we can just ignore it, and let the system fall through to another provider
                _logger?.Log(FeaturesResources.Error_reading_PDB_0, ex.Message);
                result = null;
            }
            finally
            {
                // If we're returning a result then it will own the disposal of the reader, but if not
                // then we need to do it ourselves.
                if (result is null)
                {
                    pdbStream?.Dispose();
                    peReader.Dispose();
                }
            }

            return(result);
        }
        // TODO: Revert to using Mono.Cecil when https://github.com/jbevain/cecil/issues/306 is fixed.
        public IEnumerable <PackageVerifierIssue> Validate(PackageAnalysisContext context)
        {
            var issues = new List <PackageVerifierIssue>();

            foreach (var currentFile in context.PackageReader.GetFiles())
            {
                var extension = Path.GetExtension(currentFile);
                if (!extension.Equals(".dll", StringComparison.OrdinalIgnoreCase) &&
                    !extension.Equals(".exe", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                using (var packageFileStream = context.PackageReader.GetStream(currentFile))
                    using (var stream = new MemoryStream())
                    {
                        // packageFileStream is not a seekable stream. So wrap it in a memory stream for PEReader to consume.
                        packageFileStream.CopyTo(stream);
                        stream.Position = 0;
                        PEReader       peReader = null;
                        MetadataReader reader;
                        try
                        {
                            peReader = new PEReader(stream);
                            reader   = peReader.GetMetadataReader();
                        }
                        catch
                        {
                            // This assembly is not managed.
                            peReader?.Dispose();
                            continue;
                        }

                        using (peReader)
                        {
                            foreach (var handle in reader.CustomAttributes)
                            {
                                var    customAttribute = reader.GetCustomAttribute(handle);
                                string typeName;
                                if (customAttribute.Constructor.Kind == HandleKind.MemberReference)
                                {
                                    var ctor = reader.GetMemberReference((MemberReferenceHandle)customAttribute.Constructor);
                                    var type = reader.GetTypeReference((TypeReferenceHandle)ctor.Parent);
                                    typeName = reader.GetString(type.Name);
                                }
                                else if (customAttribute.Constructor.Kind == HandleKind.MethodDefinition)
                                {
                                    var method = reader.GetMethodDefinition((MethodDefinitionHandle)customAttribute.Constructor);
                                    var type   = reader.GetTypeDefinition(method.GetDeclaringType());
                                    typeName = reader.GetString(type.Name);
                                }
                                else
                                {
                                    throw new InvalidOperationException($"Unknown CustomAttribute constructor type '{customAttribute.Constructor.Kind}");
                                }

                                if (string.Equals(typeof(DebuggableAttribute).Name, typeName, StringComparison.Ordinal))
                                {
                                    var attribute = customAttribute.DecodeValue(NullProvider.Instance);

                                    var debuggingMode = (DebuggableAttribute.DebuggingModes)attribute.FixedArguments.Single().Value;
                                    if (debuggingMode.HasFlag(DebuggableAttribute.DebuggingModes.Default) ||
                                        debuggingMode.HasFlag(DebuggableAttribute.DebuggingModes.DisableOptimizations))
                                    {
                                        issues.Add(PackageIssueFactory.AssemblyHasIncorrectBuildConfiguration(currentFile));
                                    }
                                    ;

                                    break;
                                }
                            }
                        }
                    }
            }

            return(issues);
        }
 public void TearDownMetadataReader()
 {
     _peReader.Dispose();
     _stream.Dispose();
 }
Beispiel #30
0
        public async Task <DocumentDebugInfoReader?> GetDocumentDebugInfoReaderAsync(string dllPath, IPdbSourceDocumentLogger?logger, CancellationToken cancellationToken)
        {
            var dllStream = IOUtilities.PerformIO(() => File.OpenRead(dllPath));

            if (dllStream is null)
            {
                return(null);
            }

            Stream?pdbStream = null;
            DocumentDebugInfoReader?result = null;
            var peReader = new PEReader(dllStream);

            try
            {
                // Try to load the pdb file from disk, or embedded
                if (peReader.TryOpenAssociatedPortablePdb(dllPath, pdbPath => File.OpenRead(pdbPath), out var pdbReaderProvider, out _))
                {
                    Contract.ThrowIfNull(pdbReaderProvider);

                    result = new DocumentDebugInfoReader(peReader, pdbReaderProvider);
                }

                // Otherwise call the debugger to find the PDB from a symbol server etc.
                if (result is null && _sourceLinkService is not null)
                {
                    var delay         = Task.Delay(SymbolLocatorTimeout, cancellationToken);
                    var pdbResultTask = _sourceLinkService.GetPdbFilePathAsync(dllPath, peReader, logger, cancellationToken);

                    var winner = await Task.WhenAny(pdbResultTask, delay).ConfigureAwait(false);

                    if (winner == pdbResultTask)
                    {
                        var pdbResult = await pdbResultTask.ConfigureAwait(false);

                        // TODO: Support windows PDBs: https://github.com/dotnet/roslyn/issues/55834
                        // TODO: Log results from pdbResult.Log: https://github.com/dotnet/roslyn/issues/57352
                        if (pdbResult is not null && pdbResult.IsPortablePdb)
                        {
                            pdbStream = IOUtilities.PerformIO(() => File.OpenRead(pdbResult.PdbFilePath));
                            if (pdbStream is not null)
                            {
                                var readerProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                                result = new DocumentDebugInfoReader(peReader, readerProvider);
                            }
                        }
                    }
                    else
                    {
                        // TODO: Log the timeout: https://github.com/dotnet/roslyn/issues/57352
                    }
                }
            }
            catch (BadImageFormatException)
            {
                // If the PDB is corrupt in some way we can just ignore it, and let the system fall through to another provider
                // TODO: Log this to the output window: https://github.com/dotnet/roslyn/issues/57352
                result = null;
            }
            finally
            {
                // If we're returning a result then it will own the disposal of the reader, but if not
                // then we need to do it ourselves.
                if (result is null)
                {
                    pdbStream?.Dispose();
                    peReader.Dispose();
                }
            }

            return(result);
        }