Example #1
0
        /// <summary>
        /// Create metadata module from a stream.
        /// </summary>
        /// <param name="peStream">Stream containing portable executable image. Position zero should contain the first byte of the DOS header ("MZ").</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, the responsibility for disposal of the stream is transferred upon entry of the constructor
        /// unless the arguments given are invalid.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="ArgumentException">The stream doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
        /// <exception cref="BadImageFormatException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and the PE headers of the image are invalid.
        /// </exception>
        /// <exception cref="IOException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and an error occurs while reading the stream.
        /// </exception>
        public static ModuleMetadata CreateFromStream(Stream peStream, PEStreamOptions options)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(
                          CodeAnalysisResources.StreamMustSupportReadAndSeek,
                          nameof(peStream)
                          );
            }

            // Workaround of issue https://github.com/dotnet/corefx/issues/1815:
            if (
                peStream.Length == 0 &&
                (options & PEStreamOptions.PrefetchEntireImage) != 0 &&
                (options & PEStreamOptions.PrefetchMetadata) != 0
                )
            {
                // throws BadImageFormatException:
                new PEHeaders(peStream);
            }

            // ownership of the stream is passed on PEReader:
            return(new ModuleMetadata(new PEReader(peStream, options)));
        }
Example #2
0
        public unsafe void CreateFromUnmanagedMemoryStream_Prefetcha_LeaveOpenTrue(PEStreamOptions options)
        {
            var assembly = TestResources.Basic.Members;

            fixed(byte *assemblyPtr = assembly)
            {
                var disposed = false;
                var seeked   = false;
                var stream   = new MockUnmanagedMemoryStream(assemblyPtr, assembly.LongLength)
                {
                    OnDispose = _ => disposed = true,
                    OnSeek    = (_, _) => seeked = true,
                };

                var metadata = ModuleMetadata.CreateFromStream(stream, options | PEStreamOptions.LeaveOpen);

                Assert.Equal(new AssemblyIdentity("Members"), metadata.Module.ReadAssemblyIdentityOrThrow());

                // Disposing the metadata should not dispose the stream.
                metadata.Dispose();
                Assert.False(disposed);

                stream.Dispose();
                Assert.True(disposed);

                // We should have seeked.  This stream will be viewed as a normal stream since we're prefetching
                // everything.
                Assert.True(seeked);
            }
        }
Example #3
0
        /// <summary>
        /// Returns the portable PDB reader for the assembly path
        /// </summary>
        /// <param name="assemblyPath">file path of the assembly or null if the module is in-memory or dynamic</param>
        /// <param name="isFileLayout">type of in-memory PE layout, if true, file based layout otherwise, loaded layout</param>
        /// <param name="peStream">in-memory PE stream or null</param>
        /// <returns>symbol file or null</returns>
        /// <remarks>
        /// Assumes that neither PE image nor PDB loaded into memory can be unloaded or moved around.
        /// </remarks>
        public ISymbolFile OpenSymbolFile(string assemblyPath, bool isFileLayout, Stream peStream)
        {
            if (assemblyPath == null && peStream == null)
            {
                throw new ArgumentNullException(nameof(assemblyPath));
            }
            if (peStream is not null && !peStream.CanSeek)
            {
                throw new ArgumentException(nameof(peStream));
            }

            PEStreamOptions options = isFileLayout ? PEStreamOptions.Default : PEStreamOptions.IsLoadedImage;

            if (peStream == null)
            {
                peStream = Utilities.TryOpenFile(assemblyPath);
                if (peStream == null)
                {
                    return(null);
                }

                options = PEStreamOptions.Default;
            }

            try
            {
                using (var peReader = new PEReader(peStream, options))
                {
                    ReadPortableDebugTableEntries(peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry);

                    // First try .pdb file specified in CodeView data (we prefer .pdb file on disk over embedded PDB
                    // since embedded PDB needs decompression which is less efficient than memory-mapping the file).
                    if (codeViewEntry.DataSize != 0)
                    {
                        var result = TryOpenReaderFromCodeView(peReader, codeViewEntry, assemblyPath);
                        if (result != null)
                        {
                            return(result);
                        }
                    }

                    // if it failed try Embedded Portable PDB (if available):
                    if (embeddedPdbEntry.DataSize != 0)
                    {
                        return(TryOpenReaderFromEmbeddedPdb(peReader, embeddedPdbEntry));
                    }
                }
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                // nop
            }

            return(null);
        }
 public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
                                  PEStreamOptions options = PEStreamOptions.Default)
 {
     this.options              = options;
     this.TargetFramework      = targetFramework ?? string.Empty;
     this.mainAssemblyFileName = mainAssemblyFileName;
     this.baseDirectory        = Path.GetDirectoryName(mainAssemblyFileName);
     this.throwOnError         = throwOnError;
     if (string.IsNullOrWhiteSpace(this.baseDirectory))
     {
         this.baseDirectory = Environment.CurrentDirectory;
     }
     AddSearchDirectory(baseDirectory);
 }
Example #5
0
        /// <summary>
        /// Create metadata module from a stream.
        /// </summary>
        /// <param name="peStream">Stream containing portable executable image. Position zero should contain the first byte of the DOS header ("MZ").</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, the responsibility for disposal of the stream is transferred upon entry of the constructor
        /// unless the arguments given are invalid.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="ArgumentException">The stream doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
        /// <exception cref="BadImageFormatException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and the PE headers of the image are invalid.
        /// </exception>
        /// <exception cref="IOException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and an error occurs while reading the stream.
        /// </exception>
        public static ModuleMetadata CreateFromStream(Stream peStream, PEStreamOptions options)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            // ownership of the stream is passed on PEReader:
            return(new ModuleMetadata(new PEReader(peStream, options)));
        }
Example #6
0
        LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions, bool applyWinRTProjections)
        {
            MetadataReaderOptions options = applyWinRTProjections
                                ? MetadataReaderOptions.ApplyWindowsRuntimeProjections
                                : MetadataReaderOptions.None;

            PEFile module = new PEFile(fileName, stream, streamOptions, metadataOptions: options);

            debugInfoProvider = LoadDebugInfo(module);
            lock (loadedAssemblies)
            {
                loadedAssemblies.Add(module, this);
            }
            return(new LoadResult(module));
        }
Example #7
0
 public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
                                  PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
 {
     this.streamOptions   = streamOptions;
     this.metadataOptions = metadataOptions;
     this.targetFramework = targetFramework ?? string.Empty;
     (targetFrameworkIdentifier, targetFrameworkVersion) = ParseTargetFramework(this.targetFramework);
     this.mainAssemblyFileName = mainAssemblyFileName;
     this.baseDirectory        = Path.GetDirectoryName(mainAssemblyFileName);
     this.throwOnError         = throwOnError;
     if (string.IsNullOrWhiteSpace(this.baseDirectory))
     {
         this.baseDirectory = Environment.CurrentDirectory;
     }
     AddSearchDirectory(baseDirectory);
 }
Example #8
0
        /// <summary>
        /// Create metadata module from a stream.
        /// </summary>
        /// <param name="peStream">Stream containing portable executable image. Position zero should contain the first byte of the DOS header ("MZ").</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, the responsibility for disposal of the stream is transferred upon entry of the constructor
        /// unless the arguments given are invalid.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="ArgumentException">The stream doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
        /// <exception cref="BadImageFormatException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and the PE headers of the image are invalid.
        /// </exception>
        /// <exception cref="IOException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and an error occurs while reading the stream.
        /// </exception>
        public static ModuleMetadata CreateFromStream(Stream peStream, PEStreamOptions options)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            var prefetch = (options & (PEStreamOptions.PrefetchEntireImage | PEStreamOptions.PrefetchMetadata)) != 0;

            // If this stream is an UnmanagedMemoryStream, we can heavily optimize creating the metadata by directly
            // accessing the underlying memory. Note: we can only do this if the caller asked us not to prefetch the
            // metadata from the stream.  In that case, we want to fall through below and have the PEReader read
            // everything into a copy immediately.  If, however, we are allowed to be lazy, we can create an efficient
            // metadata that is backed directly by the memory that is backed in, and which will release that memory (if
            // requested) once it is done with it.
            if (!prefetch && peStream is UnmanagedMemoryStream unmanagedMemoryStream)
            {
                unsafe
                {
                    Action?onDispose = options.HasFlag(PEStreamOptions.LeaveOpen)
                        ? null
                        : unmanagedMemoryStream.Dispose;

                    return(CreateFromImage(
                               unmanagedMemoryStream.PositionPointer,
                               (int)Math.Min(unmanagedMemoryStream.Length, int.MaxValue),
                               onDispose));
                }
            }

            // Workaround of issue https://github.com/dotnet/corefx/issues/1815:
            if (peStream.Length == 0 && (options & PEStreamOptions.PrefetchEntireImage) != 0 && (options & PEStreamOptions.PrefetchMetadata) != 0)
            {
                // throws BadImageFormatException:
                new PEHeaders(peStream);
            }

            // ownership of the stream is passed on PEReader:
            return(new ModuleMetadata(new PEReader(peStream, options), onDispose: null));
        }
Example #9
0
        public MyAssemblyResolver(
            string mainAssemblyFileName,
            bool throwOnError,
            string targetFramework,
            PEStreamOptions streamOptions         = PEStreamOptions.Default,
            MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
        {
            _streamOptions   = streamOptions;
            _metadataOptions = metadataOptions;

            _baseAssemblyResolver = new UniversalAssemblyResolver(
                mainAssemblyFileName,
                throwOnError,
                targetFramework,
                streamOptions,
                metadataOptions
                );
        }
 public UniversalAssemblyResolver(string?mainAssemblyFileName, bool throwOnError, string?targetFramework,
                                  string?runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
 {
     this.mainAssemblyFileName = mainAssemblyFileName;
     this.throwOnError         = throwOnError;
     this.streamOptions        = streamOptions;
     this.metadataOptions      = metadataOptions;
     this.targetFramework      = targetFramework ?? string.Empty;
     this.runtimePack          = runtimePack ?? "Microsoft.NETCore.App";
     (targetFrameworkIdentifier, targetFrameworkVersion) = ParseTargetFramework(this.targetFramework);
     this.dotNetCorePathFinder = new Lazy <DotNetCorePathFinder>(InitDotNetCorePathFinder);
     if (mainAssemblyFileName != null)
     {
         string baseDirectory = Path.GetDirectoryName(mainAssemblyFileName);
         if (string.IsNullOrWhiteSpace(this.baseDirectory))
         {
             this.baseDirectory = Environment.CurrentDirectory;
         }
         AddSearchDirectory(baseDirectory);
     }
 }
Example #11
0
        LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions)
        {
            MetadataReaderOptions options;

            if (DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections)
            {
                options = MetadataReaderOptions.ApplyWindowsRuntimeProjections;
            }
            else
            {
                options = MetadataReaderOptions.None;
            }

            PEFile module = new PEFile(fileName, stream, streamOptions, metadataOptions: options);

            if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols)
            {
                try
                {
                    debugInfoProvider = DebugInfoUtils.FromFile(module, PdbFileOverride)
                                        ?? DebugInfoUtils.LoadSymbols(module);
                }
                catch (IOException)
                {
                }
                catch (UnauthorizedAccessException)
                {
                }
                catch (InvalidOperationException)
                {
                    // ignore any errors during symbol loading
                }
            }
            lock (loadedAssemblies)
            {
                loadedAssemblies.Add(module, this);
            }
            return(new LoadResult(module));
        }
Example #12
0
        LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions)
        {
            MetadataReaderOptions options;

            if (DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections)
            {
                options = MetadataReaderOptions.ApplyWindowsRuntimeProjections;
            }
            else
            {
                options = MetadataReaderOptions.None;
            }

            PEFile module = new PEFile(fileName, stream, streamOptions, metadataOptions: options);

            debugInfoProvider = LoadDebugInfo(module);
            lock (loadedAssemblies)
            {
                loadedAssemblies.Add(module, this);
            }
            return(new LoadResult(module));
        }
Example #13
0
        /// <summary>
        /// Resolves the specified full assembly name.
        /// </summary>
        /// <param name="reference">A reference with details about the assembly.</param>
        /// <param name="parent">The parent of the reference.</param>
        /// <param name="input">The directories potentially containing the assemblies.</param>
        /// <param name="framework">The framework we are processing for.</param>
        /// <param name="parameters">Parameters to provide to the reflection system..</param>
        /// <returns>The assembly definitions.</returns>
        public static PEFile?Resolve(this IAssemblyReference reference, IModule parent, InputAssembliesGroup input, NuGetFramework framework, PEStreamOptions parameters = PEStreamOptions.PrefetchMetadata)
        {
            var fileName = GetFileName(reference, parent, input, framework);

            return(string.IsNullOrWhiteSpace(fileName) ? null : new PEFile(fileName, parameters));
        }
Example #14
0
 public PEFile(string fileName, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
     : this(fileName, new PEReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), streamOptions), metadataOptions)
 {
 }
Example #15
0
 /// <summary>
 /// Creates a Portable Executable reader over a PE image stored in a stream beginning at its current position and ending at the end of the stream.
 /// </summary>
 /// <param name="peStream">PE image stream.</param>
 /// <param name="options">
 /// Options specifying how sections of the PE image are read from the stream.
 /// 
 /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/> 
 /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
 /// 
 /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data 
 /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
 /// by caller while the <see cref="PEReader"/> is alive and undisposed.
 /// 
 /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/> 
 /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
 /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
 /// after construction.
 /// </param>
 /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
 /// <exception cref="BadImageFormatException">
 /// <see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.
 /// </exception>
 public PEReader(Stream peStream, PEStreamOptions options)
     : this(peStream, options, 0)
 {
 }
Example #16
0
        /// <summary>
        /// Creates a Portable Executable reader over a PE image of the given size beginning at the stream's current position.
        /// </summary>
        /// <param name="peStream">PE image stream.</param>
        /// <param name="size">PE image size.</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// 
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/> 
        /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
        /// 
        /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data 
        /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="PEReader"/> is alive and undisposed.
        /// 
        /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/> 
        /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        /// <exception cref="IOException">Error reading from the stream (only when prefetching data).</exception>
        public unsafe PEReader(Stream peStream, PEStreamOptions options, int size)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(SR.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            long start = peStream.Position;
            int actualSize = StreamExtensions.GetAndValidateSize(peStream, size, nameof(peStream));

            bool closeStream = true;
            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);

                if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
                {
                    _peImage = new StreamMemoryBlockProvider(peStream, start, actualSize, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
                    closeStream = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
                    {
                        var imageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, start, actualSize);
                        _lazyImageBlock = imageBlock;
                        _peImage = new ExternalMemoryBlockProvider(imageBlock.Pointer, imageBlock.Size);

                        // if the caller asked for metadata initialize the PE headers (calculates metadata offset):
                        if ((options & PEStreamOptions.PrefetchMetadata) != 0)
                        {
                            InitializePEHeaders();
                        }
                    }
                    else
                    {
                        // The peImage is left null, but the lazyMetadataBlock is initialized up front.
                        _lazyPEHeaders = new PEHeaders(peStream);
                        _lazyMetadataBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, _lazyPEHeaders.MetadataStartOffset, _lazyPEHeaders.MetadataSize);
                    }
                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & PEStreamOptions.LeaveOpen) == 0)
                {
                    peStream.Dispose();
                }
            }
        }
Example #17
0
 /// <summary>
 /// Creates a single-module assembly.
 /// </summary>
 /// <param name="peStream">Manifest module PE image stream.</param>
 /// <param name="options">False to close the stream upon disposal of the metadata.</param>
 /// <exception cref="BadImageFormatException">The PE image format is invalid.</exception>
 public static AssemblyMetadata CreateFromImageStream(Stream peStream, PEStreamOptions options)
 {
     return(Create(ModuleMetadata.CreateFromImageStream(peStream, options)));
 }
Example #18
0
        /// <summary>
        /// Creates a Portable Executable reader over a PE image of the given size beginning at the stream's current position.
        /// </summary>
        /// <param name="peStream">PE image stream.</param>
        /// <param name="size">PE image size.</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        ///
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/>
        /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
        ///
        /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data
        /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="PEReader"/> is alive and undisposed.
        ///
        /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/>
        /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        public PEReader(Stream peStream, PEStreamOptions options, int size)
            : this(peStream, options, (int?)size)

        {
        }
Example #19
0
 /// <summary>
 /// Creates a Portable Executable reader over a PE image stored in a stream beginning at its current position and ending at the end of the stream.
 /// </summary>
 /// <param name="peStream">PE image stream.</param>
 /// <param name="options">
 /// Options specifying how sections of the PE image are read from the stream.
 /// 
 /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/> 
 /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
 /// 
 /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data 
 /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
 /// by caller while the <see cref="PEReader"/> is alive and undisposed.
 /// 
 /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/> 
 /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
 /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
 /// after construction.
 /// </param>
 /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
 /// <exception cref="BadImageFormatException">
 /// <see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.
 /// </exception>
 public PEReader(Stream peStream, PEStreamOptions options)
     : this(peStream, options, (int?)null)
 {
 }
Example #20
0
        /// <summary>
        /// Creates a Portable Executable reader over a PE image of the given size beginning at the stream's current position.
        /// </summary>
        /// <param name="peStream">PE image stream.</param>
        /// <param name="size">PE image size.</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// 
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/> 
        /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
        /// 
        /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data 
        /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="PEReader"/> is alive and undisposed.
        /// 
        /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/> 
        /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        public PEReader(Stream peStream, PEStreamOptions options, int size)
            : this(peStream, options, (int?)size)

        {
        }
Example #21
0
        /// <summary>
        /// Creates a Portable Executable reader over a PE image of the given size beginning at the stream's current position.
        /// </summary>
        /// <param name="peStream">PE image stream.</param>
        /// <param name="size">PE image size.</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        ///
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/>
        /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
        ///
        /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data
        /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="PEReader"/> is alive and undisposed.
        ///
        /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/>
        /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        /// <exception cref="IOException">Error reading from the stream (only when prefetching data).</exception>
        /// <exception cref="BadImageFormatException"><see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.</exception>
        public unsafe PEReader(Stream peStream, PEStreamOptions options, int size)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(SR.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            IsLoadedImage = (options & PEStreamOptions.IsLoadedImage) != 0;

            long start      = peStream.Position;
            int  actualSize = StreamExtensions.GetAndValidateSize(peStream, size, nameof(peStream));

            bool closeStream = true;

            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);

                if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
                {
                    _peImage    = new StreamMemoryBlockProvider(peStream, start, actualSize, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
                    closeStream = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
                    {
                        var imageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, start, actualSize);
                        _lazyImageBlock = imageBlock;
                        _peImage        = new ExternalMemoryBlockProvider(imageBlock.Pointer, imageBlock.Size);

                        // if the caller asked for metadata initialize the PE headers (calculates metadata offset):
                        if ((options & PEStreamOptions.PrefetchMetadata) != 0)
                        {
                            InitializePEHeaders();
                        }
                    }
                    else
                    {
                        // The peImage is left null, but the lazyMetadataBlock is initialized up front.
                        _lazyPEHeaders     = new PEHeaders(peStream);
                        _lazyMetadataBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, _lazyPEHeaders.MetadataStartOffset, _lazyPEHeaders.MetadataSize);
                    }
                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & PEStreamOptions.LeaveOpen) == 0)
                {
                    peStream.Dispose();
                }
            }
        }
Example #22
0
        /// <summary>
        /// Create metadata module from a stream.
        /// </summary>
        /// <param name="peStream">Stream containing portable executable image. Position zero should contain the first byte of the DOS header ("MZ").</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, the responsibility for disposal of the stream is transferred upon entry of the constructor
        /// unless the arguments given are invalid.
        /// </param>
        /// <exception cref="BadImageFormatException"><paramref name="peStream"/> is not valid portable executable image containing CLI metadata</exception>
        /// <exception cref="ArgumentException">The stream doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
        public static ModuleMetadata CreateFromImageStream(Stream peStream, PEStreamOptions options)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException("peStream");
            }

            if (!peStream.CanRead || !peStream.CanSeek) 
            {
                throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, "peImage");
            }

            // ownership of the stream is passed on PEReader:
            return new ModuleMetadata(new PEReader(peStream, options));
        }
Example #23
0
 public PEFile(string fileName, Stream stream, PEStreamOptions options = PEStreamOptions.Default)
     : this(fileName, new PEReader(stream, options))
 {
 }
Example #24
0
 public PEFile(string fileName, PEStreamOptions options = PEStreamOptions.Default)
     : this(fileName, new PEReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), options))
 {
 }
Example #25
0
 public static bool IsValid(this PEStreamOptions options)
 {
     return((options & ~(PEStreamOptions.LeaveOpen | PEStreamOptions.PrefetchEntireImage | PEStreamOptions.PrefetchMetadata)) == 0);
 }
Example #26
0
 public PEFile(string fileName, Stream stream, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
     : this(fileName, new PEReader(stream, streamOptions), metadataOptions)
 {
 }
Example #27
0
        private unsafe PEReader(Stream peStream, PEStreamOptions options, int?sizeOpt)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException("peStream");
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(MetadataResources.StreamMustSupportReadAndSeek, "peStream");
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException("options");
            }

            long start = peStream.Position;
            int  size  = PEBinaryReader.GetAndValidateSize(peStream, sizeOpt);

            bool closeStream = true;

            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);

                if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
                {
                    this.peImage = new StreamMemoryBlockProvider(peStream, start, size, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
                    closeStream  = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
                    {
                        var imageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, 0, (int)Math.Min(peStream.Length, int.MaxValue));
                        this.lazyImageBlock = imageBlock;
                        this.peImage        = new ExternalMemoryBlockProvider(imageBlock.Pointer, imageBlock.Size);

                        // if the caller asked for metadata initialize the PE headers (calculates metadata offset):
                        if ((options & PEStreamOptions.PrefetchMetadata) != 0)
                        {
                            InitializePEHeaders();
                        }
                    }
                    else
                    {
                        // The peImage is left null, but the lazyMetadataBlock is initialized up front.
                        this.lazyPEHeaders     = new PEHeaders(peStream);
                        this.lazyMetadataBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, lazyPEHeaders.MetadataStartOffset, lazyPEHeaders.MetadataSize);
                    }
                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & PEStreamOptions.LeaveOpen) == 0)
                {
                    peStream.Dispose();
                }
            }
        }
Example #28
0
        /// <summary>
        /// Constructs a PEImage class for a given PE image (dll/exe) in memory.
        /// </summary>
        /// <param name="stream">A Stream that contains a PE image at its 0th offset.  This stream must be seekable.</param>
        /// <param name="leaveOpen">Whether or not to leave the stream open, if this is set to false stream will be
        /// disposed when this object is.</param>
        /// <param name="isVirtual">Whether stream points to a PE image mapped into an address space (such as in a live process or crash dump).</param>
        public PEImage(Stream stream, bool leaveOpen, bool isVirtual)
        {
            _isVirtual = isVirtual;
            _stream    = stream ?? throw new ArgumentNullException(nameof(stream));

            if (!stream.CanSeek)
            {
                throw new ArgumentException($"{nameof(stream)} is not seekable.");
            }

            ushort dosHeaderMagic = Read <ushort>(0);

            if (dosHeaderMagic != ExpectedDosHeaderMagic)
            {
                if (!leaveOpen)
                {
                    stream.Dispose();
                }

                return;
            }

            int peHeaderOffset = Read <int>(PESignatureOffsetLocation);

            if (peHeaderOffset == 0)
            {
                if (!leaveOpen)
                {
                    stream.Dispose();
                }

                return;
            }

            uint peSignature = Read <uint>(peHeaderOffset);

            if (peSignature != ExpectedPESignature)
            {
                if (!leaveOpen)
                {
                    stream.Dispose();
                }

                return;
            }

            SeekTo(0);

            PEStreamOptions options = PEStreamOptions.Default;

            if (leaveOpen)
            {
                options |= PEStreamOptions.LeaveOpen;
            }

            if (isVirtual)
            {
                options |= PEStreamOptions.IsLoadedImage;
            }

            try
            {
                var reader = new PEReader(stream, options);
                _peHeaders = reader.PEHeaders;
                Reader     = reader;
            }
            catch (BadImageFormatException)
            {
            }
            catch (EndOfStreamException)
            {
            }
        }
Example #29
0
 /// <summary>
 /// Creates a Portable Executable reader over a PE image stored in a stream beginning at its current position and ending at the end of the stream.
 /// </summary>
 /// <param name="peStream">PE image stream.</param>
 /// <param name="options">
 /// Options specifying how sections of the PE image are read from the stream.
 ///
 /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/>
 /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
 ///
 /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data
 /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
 /// by caller while the <see cref="PEReader"/> is alive and undisposed.
 ///
 /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/>
 /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
 /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
 /// after construction.
 /// </param>
 /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
 /// <exception cref="IOException">Error reading from the stream (only when prefetching data).</exception>
 /// <exception cref="BadImageFormatException"><see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.</exception>
 public PEReader(Stream peStream, PEStreamOptions options)
     : this(peStream, options, 0)
 {
 }
Example #30
0
 /// <summary>
 /// Creates a Portable Executable reader over a PE image stored in a stream beginning at its current position and ending at the end of the stream.
 /// </summary>
 /// <param name="peStream">PE image stream.</param>
 /// <param name="options">
 /// Options specifying how sections of the PE image are read from the stream.
 ///
 /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/>
 /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
 ///
 /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data
 /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
 /// by caller while the <see cref="PEReader"/> is alive and undisposed.
 ///
 /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/>
 /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
 /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
 /// after construction.
 /// </param>
 /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
 /// <exception cref="BadImageFormatException">
 /// <see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.
 /// </exception>
 public PEReader(Stream peStream, PEStreamOptions options)
     : this(peStream, options, (int?)null)
 {
 }
Example #31
0
        /// <summary>
        /// Create metadata module from a stream.
        /// </summary>
        /// <param name="peStream">Stream containing portable executable image. Position zero should contain the first byte of the DOS header ("MZ").</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, the responsibility for disposal of the stream is transferred upon entry of the constructor
        /// unless the arguments given are invalid.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="ArgumentException">The stream doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="options"/> has an invalid value.</exception>
        /// <exception cref="BadImageFormatException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and the PE headers of the image are invalid.
        /// </exception>
        /// <exception cref="IOException">
        /// <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified and an error occurs while reading the stream.
        /// </exception>
        public static ModuleMetadata CreateFromStream(Stream peStream, PEStreamOptions options)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            // Workaround of issue https://github.com/dotnet/corefx/issues/1815: 
            if (peStream.Length == 0 && (options & PEStreamOptions.PrefetchEntireImage) != 0 && (options & PEStreamOptions.PrefetchMetadata) != 0)
            {
                // throws BadImageFormatException:
                new PEHeaders(peStream);
            }

            // ownership of the stream is passed on PEReader:
            return new ModuleMetadata(new PEReader(peStream, options));
        }
Example #32
0
 /// <summary>
 /// Creates a single-module assembly.
 /// </summary>
 /// <param name="peStream">Manifest module PE image stream.</param>
 /// <param name="options">False to close the stream upon disposal of the metadata.</param>
 /// <exception cref="BadImageFormatException">The PE image format is invalid.</exception>
 public static AssemblyMetadata CreateFromStream(Stream peStream, PEStreamOptions options)
 {
     return Create(ModuleMetadata.CreateFromStream(peStream, options));
 }