void IDisposable.Dispose() { if (_reader != null) { _reader.Dispose(); } }
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(); } }
void IDisposable.Dispose() { if (pdb != null) { pdb.Dispose(); } peReader.Dispose(); stream.Dispose(); }
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; } }
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; } }
public void Dispose() { if (_peReader != null) { _peReader.Dispose(); _peReader = null; } if (_fs != null) { _fs.Dispose(); _fs = null; } }
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(); }
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); } }
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; } }
public void Close() { if (_peReader != null) { _peReader.Dispose(); } if (_assemblyStream != null) { _assemblyStream.Close(); } _attributes = null; _reader = null; _peReader = null; _assemblyStream = null; }
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); }
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); }
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(); } } }
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(); }
void IDisposable.Dispose() => _reader?.Dispose();
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();
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); } } } }
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(); }
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); }