예제 #1
0
파일: PdbToXml.cs 프로젝트: riversky/roslyn
        public unsafe static void ToXml(TextWriter xmlWriter, Stream pdbStream, Stream peStream, PdbToXmlOptions options = PdbToXmlOptions.Default, string methodName = null)
        {
            IEnumerable<MethodHandle> methodHandles;
            var headers = new PEHeaders(peStream);
            byte[] metadata = new byte[headers.MetadataSize];
            peStream.Seek(headers.MetadataStartOffset, SeekOrigin.Begin);
            peStream.Read(metadata, 0, headers.MetadataSize);

            fixed (byte* metadataPtr = metadata)
            {
                var metadataReader = new MetadataReader((IntPtr)metadataPtr, metadata.Length);

                if (string.IsNullOrEmpty(methodName))
                {
                    methodHandles = metadataReader.MethodDefinitions;
                }
                else
                {
                    methodHandles = metadataReader.MethodDefinitions.
                        Where(methodHandle => GetQualifiedMethodName(metadataReader, methodHandle) == methodName);
                }

                ToXml(xmlWriter, pdbStream, metadataReader, options, methodHandles);
            }
        }
예제 #2
0
 internal static unsafe MetadataReader GetMetadataReader(byte[] peImage, out int metadataStartOffset, bool isModule = false, MetadataReaderOptions options = MetadataReaderOptions.Default, MetadataStringDecoder decoder = null)
 {
     GCHandle pinned = GetPinnedPEImage(peImage);
     var headers = new PEHeaders(new MemoryStream(peImage));
     metadataStartOffset = headers.MetadataStartOffset;
     return new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize, options, decoder);
 }
        public unsafe void CreateFromMetadata_Module()
        {
            var netModule = TestResources.MetadataTests.NetModule01.ModuleCS00;
            PEHeaders h = new PEHeaders(new MemoryStream(netModule));

            fixed (byte* ptr = &netModule[h.MetadataStartOffset])
            {
                ModuleMetadata.CreateFromMetadata((IntPtr)ptr, h.MetadataSize);
            }
        }
예제 #4
0
 internal static unsafe MetadataReader GetMetadataReader(byte[] peImage, out int metadataStartOffset, bool isModule = false, MetadataStringDecoder decoder = null)
 {
     GCHandle pinned;
     if (!peImages.TryGetValue(peImage, out pinned))
     {
         peImages.Add(peImage, pinned = GCHandle.Alloc(peImage, GCHandleType.Pinned));
     }
     var headers = new PEHeaders(new MemoryStream(peImage));
     metadataStartOffset = headers.MetadataStartOffset;
     return new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize, MetadataReaderOptions.Default, decoder);
 }
        public unsafe void CreateFromMetadata_Assembly()
        {
            var assembly = TestResources.MetadataTests.Basic.Members;
            PEHeaders h = new PEHeaders(new MemoryStream(assembly));

            fixed (byte* ptr = &assembly[h.MetadataStartOffset])
            {
                var metadata = ModuleMetadata.CreateFromMetadata((IntPtr)ptr, h.MetadataSize);
                Assert.Equal(new AssemblyIdentity("Members"), metadata.Module.ReadAssemblyIdentityOrThrow());
            }
        }
예제 #6
0
        public unsafe static void ToXml(TextWriter xmlWriter, Stream pdbStream, Stream peStream, PdbToXmlOptions options = PdbToXmlOptions.Default, string methodName = null)
        {
            IEnumerable<MethodHandle> methodHandles;
            var headers = new PEHeaders(peStream);
            byte[] metadata = new byte[headers.MetadataSize];
            peStream.Seek(headers.MetadataStartOffset, SeekOrigin.Begin);
            peStream.Read(metadata, 0, headers.MetadataSize);

            fixed (byte* metadataPtr = metadata)
            {
                var metadataReader = new MetadataReader((IntPtr)metadataPtr, metadata.Length);

                if (string.IsNullOrEmpty(methodName))
                {
                    methodHandles = metadataReader.MethodDefinitions;
                }
                else
                {
                    var matching = metadataReader.MethodDefinitions.
                        Where(methodHandle => GetQualifiedMethodName(metadataReader, methodHandle) == methodName).ToArray();

                    if (matching.Length == 0)
                    {
                        xmlWriter.WriteLine("<error>");
                        xmlWriter.WriteLine(string.Format("<message>No method '{0}' found in metadata.</message>", methodName));
                        xmlWriter.WriteLine("<available-methods>");

                        foreach (var methodHandle in metadataReader.MethodDefinitions)
                        {
                            xmlWriter.Write("<method><![CDATA[");
                            xmlWriter.Write(GetQualifiedMethodName(metadataReader, methodHandle));
                            xmlWriter.Write("]]></method>");
                            xmlWriter.WriteLine();
                        }

                        xmlWriter.WriteLine("</available-methods>");
                        xmlWriter.WriteLine("</error>");

                        return;
                    }

                    methodHandles = matching;
                }

                ToXml(xmlWriter, pdbStream, metadataReader, options, methodHandles);
            }
        }
예제 #7
0
        public void CheckCOFFAndPEOptionalHeadersARM()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source,
                compOptions: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.Arm));

            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.False(peHeaders.Requires64Bits());
            Assert.True(peHeaders.IsDll);
            Assert.False(peHeaders.IsExe);
            //interesting Optional PE header bits
            //We will use a range beginning with 0x30 to identify the Roslyn compiler family.
            Assert.Equal(0x30, peHeaders.PEHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeaders.PEHeader.MinorLinkerVersion);
            // the default value is the same as the 32 bit default value
            Assert.Equal(0x10000000u, peHeaders.PEHeader.ImageBase);
            Assert.Equal(0x200, peHeaders.PEHeader.FileAlignment);
            Assert.Equal(0x8540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE
            Assert.Equal(0x01c4, (ushort)peHeaders.CoffHeader.Machine);
            Assert.Equal(6, peHeaders.PEHeader.MajorSubsystemVersion);    //Arm targets only run on 6.2 and above
            Assert.Equal(2, peHeaders.PEHeader.MinorSubsystemVersion);
            //The following ensure that the runtime startup stub was not emitted. It is not needed on modern operating systems.
            Assert.Equal(0, peHeaders.PEHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.ImportAddressTableDirectory.Size);
            Assert.Equal(0, peHeaders.PEHeader.ImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.ImportTableDirectory.Size);
            Assert.Equal(0, peHeaders.PEHeader.BaseRelocationTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.BaseRelocationTableDirectory.Size);
        }
예제 #8
0
        public void CheckCOFFAndPEOptionalHeaders64()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source,
                compOptions: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.X64));

            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.True(peHeaders.Requires64Bits());
            Assert.True(peHeaders.IsDll);
            Assert.False(peHeaders.IsExe);
            //interesting Optional PE header bits
            //We will use a range beginning with 0x30 to identify the Roslyn compiler family.
            Assert.Equal(0x30, peHeaders.PEHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeaders.PEHeader.MinorLinkerVersion);
            // the default value is the same as the 32 bit default value
            Assert.Equal(0x0000000180000000u, peHeaders.PEHeader.ImageBase); 
            Assert.Equal(0x00000200, peHeaders.PEHeader.FileAlignment);      //doesn't change based on architecture.
            Assert.Equal(0x8540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE
            //Verify additional items
            Assert.Equal(0x00400000u, peHeaders.PEHeader.SizeOfStackReserve);
            Assert.Equal(0x4000u, peHeaders.PEHeader.SizeOfStackCommit);
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfHeapReserve);
            Assert.Equal(0x2000u, peHeaders.PEHeader.SizeOfHeapCommit);
            Assert.Equal(0x8664, (ushort)peHeaders.CoffHeader.Machine);     //AMD64 (K8)

            //default for non-arm, non-appcontainer outputs. EDMAURER: This is an intentional change from Dev11.
            //Should we find that it is too disruptive. We will consider rolling back.
            //It turns out to be too disruptive. Rolling back to 4.0
            Assert.Equal(4, peHeaders.PEHeader.MajorSubsystemVersion);    
            Assert.Equal(0, peHeaders.PEHeader.MinorSubsystemVersion);

            //The following ensure that the runtime startup stub was not emitted. It is not needed on modern operating systems.
            Assert.Equal(0, peHeaders.PEHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.ImportAddressTableDirectory.Size);
            Assert.Equal(0, peHeaders.PEHeader.ImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.ImportTableDirectory.Size);
            Assert.Equal(0, peHeaders.PEHeader.BaseRelocationTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeaders.PEHeader.BaseRelocationTableDirectory.Size);
        }
예제 #9
0
        public void CheckCOFFAndPEOptionalHeaders32()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source,
                compOptions: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.False(peHeaders.Requires64Bits());
            Assert.True(peHeaders.IsDll);
            Assert.False(peHeaders.IsExe);
            //interesting Optional PE header bits
            //We will use a range beginning with 0x30 to identify the Roslyn compiler family.
            Assert.Equal(0x30, peHeaders.PEHeader.MajorLinkerVersion);   
            Assert.Equal(0, peHeaders.PEHeader.MinorLinkerVersion); 
            Assert.Equal(0x10000000u, peHeaders.PEHeader.ImageBase);
            Assert.Equal(0x200, peHeaders.PEHeader.FileAlignment);
            Assert.Equal(0x8540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE
            //Verify additional items 
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfStackReserve);
            Assert.Equal(0x1000u, peHeaders.PEHeader.SizeOfStackCommit);
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfHeapReserve);
            Assert.Equal(0x1000u, peHeaders.PEHeader.SizeOfHeapCommit);
        }
예제 #10
0
        public void CheckCorflags()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            PEHeaders peHeaders;

            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.AnyCpu));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(CorFlags.ILOnly, peHeaders.CorHeader.Flags);

            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X86));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(CorFlags.ILOnly | CorFlags.Requires32Bit, peHeaders.CorHeader.Flags);

            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X64));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(CorFlags.ILOnly, peHeaders.CorHeader.Flags);
            Assert.True(peHeaders.Requires64Bits());
            Assert.True(peHeaders.RequiresAmdInstructionSet());

            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.AnyCpu32BitPreferred));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.False(peHeaders.Requires64Bits());
            Assert.False(peHeaders.RequiresAmdInstructionSet());
            Assert.Equal(CorFlags.ILOnly | CorFlags.Requires32Bit | CorFlags.Prefers32Bit, peHeaders.CorHeader.Flags);

            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.Arm));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.False(peHeaders.Requires64Bits());
            Assert.False(peHeaders.RequiresAmdInstructionSet());
            Assert.Equal(CorFlags.ILOnly, peHeaders.CorHeader.Flags);
        }
예제 #11
0
파일: CvtRes.cs 프로젝트: GloryChou/roslyn
        static internal Microsoft.Cci.ResourceSection ReadWin32ResourcesFromCOFF(Stream stream)
        {
            var peHeaders = new PEHeaders(stream);
            var rsrc1 = new SectionHeader();
            var rsrc2 = new SectionHeader();

            int foundCount = 0;
            foreach (var sectionHeader in peHeaders.SectionHeaders)
            {
                if (sectionHeader.Name == ".rsrc$01")
                {
                    rsrc1 = sectionHeader;
                    foundCount++;
                }
                else if (sectionHeader.Name == ".rsrc$02")
                {
                    rsrc2 = sectionHeader;
                    foundCount++;
                }
            }

            if (foundCount != 2)
                throw new ResourceException(CodeAnalysisResources.CoffResourceMissingSection);

            ConfirmSectionValues(rsrc1, stream.Length);
            ConfirmSectionValues(rsrc2, stream.Length);

            //This will be the final resource section bytes without a header. It contains the concatenation
            //of .rsrc$02 on to the end of .rsrc$01.
            var imageResourceSectionBytes = new byte[checked(rsrc1.SizeOfRawData + rsrc2.SizeOfRawData)];

            stream.Seek(rsrc1.PointerToRawData, SeekOrigin.Begin);
            stream.Read(imageResourceSectionBytes, 0, rsrc1.SizeOfRawData);
            stream.Seek(rsrc2.PointerToRawData, SeekOrigin.Begin);
            stream.Read(imageResourceSectionBytes, rsrc1.SizeOfRawData, rsrc2.SizeOfRawData);

            const int SizeOfRelocationEntry = 10;

            try
            {
                var relocLastAddress = checked(rsrc1.PointerToRelocations + (rsrc1.NumberOfRelocations * SizeOfRelocationEntry));

                if (relocLastAddress > stream.Length)
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);
            }
            catch (OverflowException)
            {
                throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);
            }

            //.rsrc$01 contains the directory tree. .rsrc$02 contains the raw resource data.
            //.rsrc$01 has references to spots in .rsrc$02. Those spots are expressed as relocations.
            //These will need to be fixed up when the RVA of the .rsrc section in the final image is known.
            var relocationOffsets = new uint[rsrc1.NumberOfRelocations];    //offsets into .rsrc$01

            var relocationSymbolIndices = new uint[rsrc1.NumberOfRelocations];

            var reader = new BinaryReader(stream, Encoding.Unicode);
            stream.Position = rsrc1.PointerToRelocations;

            for (int i = 0; i < rsrc1.NumberOfRelocations; i++)
            {
                relocationOffsets[i] = reader.ReadUInt32();
                //What is being read and stored is the reloc's "Value"
                //This is the symbol's index.
                relocationSymbolIndices[i] = reader.ReadUInt32();
                reader.ReadUInt16(); //we do nothing with the "Type"
            }

            //now that symbol indices are gathered, begin indexing the symbols
            stream.Position = peHeaders.CoffHeader.PointerToSymbolTable;
            const uint ImageSizeOfSymbol = 18;

            try
            {
                var lastSymAddress = checked(peHeaders.CoffHeader.PointerToSymbolTable + peHeaders.CoffHeader.NumberOfSymbols * ImageSizeOfSymbol);

                if (lastSymAddress > stream.Length)
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);
            }
            catch (OverflowException)
            {
                throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);
            }

            var outputStream = new MemoryStream(imageResourceSectionBytes);
            var writer = new BinaryWriter(outputStream);  //encoding shouldn't matter. There are no strings being written.

            for (int i = 0; i < relocationSymbolIndices.Length; i++)
            {
                if (relocationSymbolIndices[i] > peHeaders.CoffHeader.NumberOfSymbols)
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidRelocation);

                var offsetOfSymbol = peHeaders.CoffHeader.PointerToSymbolTable + relocationSymbolIndices[i] * ImageSizeOfSymbol;

                stream.Position = offsetOfSymbol;
                stream.Position += 8; //skip over symbol name
                var symValue = reader.ReadUInt32();
                var symSection = reader.ReadInt16();
                var symType = reader.ReadUInt16();
                //ignore the rest of the fields.

                const ushort IMAGE_SYM_TYPE_NULL = 0x0000;

                if (symType != IMAGE_SYM_TYPE_NULL ||
                    symSection != 3)  //3rd section is .rsrc$02
                    throw new ResourceException(CodeAnalysisResources.CoffResourceInvalidSymbol);

                //perform relocation. We are concatenating the contents of .rsrc$02 (the raw resource data)
                //on to the end of .rsrc$01 (the directory tree) to yield the final resource section for the image.
                //The directory tree has references into the raw resource data. These references are expressed
                //in the final image as file positions, not positions relative to the beginning of the section.
                //First make the resources be relative to the beginning of the section by adding the size
                //of .rsrc$01 to them. They will ultimately need the RVA of the final image resource section added 
                //to them. We don't know that yet. That is why the array of offsets is preserved. 

                outputStream.Position = relocationOffsets[i];
                writer.Write((uint)(symValue + rsrc1.SizeOfRawData));
            }

            return new Cci.ResourceSection(imageResourceSectionBytes, relocationOffsets);
        }
예제 #12
0
        public void CheckBaseAddress()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            // last four hex digits get zero'ed
            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithBaseAddress(0x0000000010111111));
            var peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x10110000ul, peHeaders.PEHeader.ImageBase);

            // test rounding up of values
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithBaseAddress(0x8000));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x10000ul, peHeaders.PEHeader.ImageBase);

            // values less than 0x8000 get default baseaddress
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithBaseAddress(0x7fff));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x00400000u, peHeaders.PEHeader.ImageBase);

            // default for 32bit
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X86));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x00400000u, peHeaders.PEHeader.ImageBase);

            // max for 32bit
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X86).WithBaseAddress(0xffff7fff));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0xffff0000ul, peHeaders.PEHeader.ImageBase);

            // max+1 for 32bit
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X86).WithBaseAddress(0xffff8000));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x00400000u, peHeaders.PEHeader.ImageBase);

            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X64));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x0000000140000000u, peHeaders.PEHeader.ImageBase);

            // max for 64bit
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X64).WithBaseAddress(0xffffffffffff7fff));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0xffffffffffff0000ul, peHeaders.PEHeader.ImageBase);

            // max+1 for 64bit
            compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X64).WithBaseAddress(0xffffffffffff8000));
            peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(0x0000000140000000u, peHeaders.PEHeader.ImageBase);
        }
예제 #13
0
        public void CheckDllCharacteristicsHighEntropyVA()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithHighEntropyVirtualAddressSpace(true));
            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.Equal(0x8560u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE | HIGH_ENTROPY_VA (0x20)
        }
예제 #14
0
파일: PEReader.cs 프로젝트: uppi/SharpLang
        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();
                }
            }
        }
예제 #15
0
        public unsafe void PointerAndLength()
        {
            GCHandle pinned = GetPinnedPEImage(NetModule.AppCS);
            var headers = new PEHeaders(new MemoryStream(NetModule.AppCS));
            byte* ptr = (byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset;
            var reader = new MetadataReader(ptr, headers.MetadataSize);

            Assert.True(ptr == reader.MetadataPointer);
            Assert.Equal(headers.MetadataSize, reader.MetadataLength);
        }
        private void GetStorageInfoFromTemporaryStorage(FileKey moduleFileKey, out ITemporaryStreamStorage storage, out Stream stream, out IntPtr pImage)
        {
            int size;
            using (var copyStream = SerializableBytes.CreateWritableStream())
            {
                // open a file and let it go as soon as possible
                using (var fileStream = FileUtilities.OpenRead(moduleFileKey.FullPath))
                {
                    var headers = new PEHeaders(fileStream);

                    var offset = headers.MetadataStartOffset;
                    size = headers.MetadataSize;

                    // given metadata contains no metadata info.
                    // throw bad image format exception so that we can show right diagnostic to user.
                    if (size <= 0)
                    {
                        throw new BadImageFormatException();
                    }

                    StreamCopy(fileStream, copyStream, offset, size);
                }

                // copy over the data to temp storage and let pooled stream go
                storage = _temporaryStorageService.CreateTemporaryStreamStorage(CancellationToken.None);

                copyStream.Position = 0;
                storage.WriteStream(copyStream);
            }

            // get stream that owns direct access memory
            stream = storage.ReadStream(CancellationToken.None);

            // stream size must be same as what metadata reader said the size should be.
            Contract.ThrowIfFalse(stream.Length == size);

            // under VS host, direct access should be supported
            var directAccess = (ISupportDirectMemoryAccess)stream;
            pImage = directAccess.GetPointer();
        }
예제 #17
0
 public void EmittedSubsystemVersion()
 {
     var compilation = CSharpCompilation.Create("a.dll", options: TestOptions.Dll.WithSubsystemVersion(SubsystemVersion.Create(5, 1)));
     var peHeaders = new PEHeaders(compilation.EmitToStream());
     Assert.Equal(5, peHeaders.PEHeader.MajorSubsystemVersion);
     Assert.Equal(1, peHeaders.PEHeader.MinorSubsystemVersion);
 }
예제 #18
0
        public void PEHeaders2()
        {
            var options = EmitOptions.Default.
                WithFileAlignment(512).
                WithBaseAddress(0x123456789ABCDEF).
                WithHighEntropyVirtualAddressSpace(true).
                WithSubsystemVersion(SubsystemVersion.WindowsXP);

            var syntax = SyntaxFactory.ParseSyntaxTree(@"class C { static void Main() { } }", TestOptions.Regular);

            var peStream = CreateCompilationWithMscorlib(
                syntax,
                options: TestOptions.DebugExe.WithPlatform(Platform.X64).WithDeterministic(true),
                assemblyName: "B37A4FCD-ED76-4924-A2AD-298836056E00").EmitToStream(options);

            peStream.Position = 0;
            var peHeaders = new PEHeaders(peStream);

            var peHeader = peHeaders.PEHeader;
            var coffHeader = peHeaders.CoffHeader;
            var corHeader = peHeaders.CorHeader;

            Assert.Equal(PEMagic.PE32Plus, peHeader.Magic);
            Assert.Equal(0x00000000, peHeader.AddressOfEntryPoint);
            Assert.Equal(0x00002000, peHeader.BaseOfCode);
            Assert.Equal(0x00000000, peHeader.BaseOfData);
            Assert.Equal(0x00000200, peHeader.SizeOfHeaders);
            Assert.Equal(0x00000400, peHeader.SizeOfCode);
            Assert.Equal(0x00002000u, peHeader.SizeOfHeapCommit);
            Assert.Equal(0x00100000u, peHeader.SizeOfHeapReserve);
            Assert.Equal(0x00004000, peHeader.SizeOfImage);
            Assert.Equal(0x00000000, peHeader.SizeOfInitializedData);
            Assert.Equal(0x00004000u, peHeader.SizeOfStackCommit);
            Assert.Equal(0x0400000u, peHeader.SizeOfStackReserve);
            Assert.Equal(0, peHeader.SizeOfUninitializedData);
            Assert.Equal(Subsystem.WindowsCui, peHeader.Subsystem);
            Assert.Equal(0u, peHeader.CheckSum);
            Assert.Equal(0x200, peHeader.FileAlignment);
            Assert.Equal(0x0123456789ac0000u, peHeader.ImageBase);
            Assert.Equal(0x2000, peHeader.SectionAlignment);
            Assert.Equal(0, peHeader.MajorImageVersion);
            Assert.Equal(0, peHeader.MinorImageVersion);
            Assert.Equal(0x30, peHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeader.MinorLinkerVersion);
            Assert.Equal(4, peHeader.MajorOperatingSystemVersion);
            Assert.Equal(0, peHeader.MinorOperatingSystemVersion);
            Assert.Equal(5, peHeader.MajorSubsystemVersion);
            Assert.Equal(1, peHeader.MinorSubsystemVersion);
            Assert.Equal(16, peHeader.NumberOfRvaAndSizes);
            Assert.Equal(0x200, peHeader.SizeOfHeaders);

            Assert.Equal(0, peHeader.BaseRelocationTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.BaseRelocationTableDirectory.Size);
            Assert.Equal(0, peHeader.BoundImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.BoundImportTableDirectory.Size);
            Assert.Equal(0, peHeader.CertificateTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.CertificateTableDirectory.Size);
            Assert.Equal(0, peHeader.CopyrightTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.CopyrightTableDirectory.Size);
            Assert.Equal(0x2000, peHeader.CorHeaderTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x48, peHeader.CorHeaderTableDirectory.Size);
            Assert.Equal(0x2324, peHeader.DebugTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x1C, peHeader.DebugTableDirectory.Size);
            Assert.Equal(0, peHeader.ExceptionTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ExceptionTableDirectory.Size);
            Assert.Equal(0, peHeader.ExportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ExportTableDirectory.Size);
            Assert.Equal(0, peHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ImportAddressTableDirectory.Size);
            Assert.Equal(0, peHeader.ImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ImportTableDirectory.Size);
            Assert.Equal(0, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.LoadConfigTableDirectory.Size);
            Assert.Equal(0, peHeader.ResourceTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ResourceTableDirectory.Size);
            Assert.Equal(0, peHeader.ThreadLocalStorageTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ThreadLocalStorageTableDirectory.Size);

            Assert.Equal(Characteristics.LargeAddressAware | Characteristics.ExecutableImage, coffHeader.Characteristics);
            Assert.Equal(Machine.Amd64, coffHeader.Machine);
            Assert.Equal(1, coffHeader.NumberOfSections);
            Assert.Equal(0, coffHeader.NumberOfSymbols);
            Assert.Equal(0, coffHeader.PointerToSymbolTable);
            Assert.Equal(240, coffHeader.SizeOfOptionalHeader);
            Assert.Equal(-862605524, coffHeader.TimeDateStamp);

            Assert.Equal(0x06000001, corHeader.EntryPointTokenOrRelativeVirtualAddress);
            Assert.Equal(CorFlags.ILOnly, corHeader.Flags);
            Assert.Equal(2, corHeader.MajorRuntimeVersion);
            Assert.Equal(5, corHeader.MinorRuntimeVersion);

            Assert.Equal(0, corHeader.CodeManagerTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.CodeManagerTableDirectory.Size);
            Assert.Equal(0, corHeader.ExportAddressTableJumpsDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ExportAddressTableJumpsDirectory.Size);
            Assert.Equal(0, corHeader.ManagedNativeHeaderDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ManagedNativeHeaderDirectory.Size);
            Assert.Equal(0x2054, corHeader.MetadataDirectory.RelativeVirtualAddress);
            Assert.Equal(0x02d0, corHeader.MetadataDirectory.Size);
            Assert.Equal(0, corHeader.ResourcesDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ResourcesDirectory.Size);
            Assert.Equal(0, corHeader.StrongNameSignatureDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.StrongNameSignatureDirectory.Size);
            Assert.Equal(0, corHeader.VtableFixupsDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.VtableFixupsDirectory.Size);

            var sections = peHeaders.SectionHeaders;
            Assert.Equal(1, sections.Length);

            Assert.Equal(".text", sections[0].Name);
            Assert.Equal(0, sections[0].NumberOfLineNumbers);
            Assert.Equal(0, sections[0].NumberOfRelocations);
            Assert.Equal(0, sections[0].PointerToLineNumbers);
            Assert.Equal(0x200, sections[0].PointerToRawData);
            Assert.Equal(0, sections[0].PointerToRelocations);
            Assert.Equal(SectionCharacteristics.ContainsCode | SectionCharacteristics.MemExecute | SectionCharacteristics.MemRead, sections[0].SectionCharacteristics);
            Assert.Equal(0x400, sections[0].SizeOfRawData);
            Assert.Equal(0x2000, sections[0].VirtualAddress);
            Assert.Equal(832, sections[0].VirtualSize);
        }
예제 #19
0
        public void CheckCOFFAndPEOptionalHeaders32Exe()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source,
                compOptions: TestOptions.Exe.WithPlatform(Platform.AnyCpu));

            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.False(peHeaders.Requires64Bits());
            Assert.True(peHeaders.IsExe);
            Assert.False(peHeaders.IsDll);
            //interesting Optional PE header bits
            //We will use a range beginning with 0x30 to identify the Roslyn compiler family.
            Assert.Equal(0x30, peHeaders.PEHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeaders.PEHeader.MinorLinkerVersion);
            Assert.Equal(0x00400000ul, peHeaders.PEHeader.ImageBase);
            Assert.Equal(0x00000200, peHeaders.PEHeader.FileAlignment);
            Assert.True(peHeaders.IsConsoleApplication); //should change if this is a windows app.
            Assert.Equal(0x8540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfStackReserve);
            Assert.Equal(0x1000u, peHeaders.PEHeader.SizeOfStackCommit);
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfHeapReserve);
            Assert.Equal(0x1000u, peHeaders.PEHeader.SizeOfHeapCommit);

            //The following ensure that the runtime startup stub was emitted. It is not needed on modern operating systems.
            Assert.NotEqual(0, peHeaders.PEHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.NotEqual(0, peHeaders.PEHeader.ImportAddressTableDirectory.Size);
            Assert.NotEqual(0, peHeaders.PEHeader.ImportTableDirectory.RelativeVirtualAddress);
            Assert.NotEqual(0, peHeaders.PEHeader.ImportTableDirectory.Size);
            Assert.NotEqual(0, peHeaders.PEHeader.BaseRelocationTableDirectory.RelativeVirtualAddress);
            Assert.NotEqual(0, peHeaders.PEHeader.BaseRelocationTableDirectory.Size);
        }
예제 #20
0
        public void CheckCOFFAndPEOptionalHeaders64Exe()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithPlatform(Platform.X64));
            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.True(peHeaders.Requires64Bits());
            Assert.True(peHeaders.IsExe);
            Assert.False(peHeaders.IsDll);
            //interesting Optional PE header bits
            //We will use a range beginning with 0x30 to identify the Roslyn compiler family.
            Assert.Equal(0x30, peHeaders.PEHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeaders.PEHeader.MinorLinkerVersion);
            Assert.Equal(0x0000000140000000ul, peHeaders.PEHeader.ImageBase); 
            Assert.Equal(0x200, peHeaders.PEHeader.FileAlignment);  //doesn't change based on architecture
            Assert.True(peHeaders.IsConsoleApplication); //should change if this is a windows app.
            Assert.Equal(0x8540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE
            Assert.Equal(0x00400000u, peHeaders.PEHeader.SizeOfStackReserve);
            Assert.Equal(0x4000u, peHeaders.PEHeader.SizeOfStackCommit);
            Assert.Equal(0x00100000u, peHeaders.PEHeader.SizeOfHeapReserve); //no sure why we don't bump this up relative to 32bit as well.
            Assert.Equal(0x2000u, peHeaders.PEHeader.SizeOfHeapCommit);
        }
예제 #21
0
        public unsafe void LinkedNetmoduleMetadataMustProvideFullPEImage()
        {
            var netModule = TestResources.MetadataTests.NetModule01.ModuleCS00;
            PEHeaders h = new PEHeaders(new MemoryStream(netModule));

            fixed (byte* ptr = &netModule[h.MetadataStartOffset])
            {
                using (var mdModule = ModuleMetadata.CreateFromMetadata((IntPtr)ptr, h.MetadataSize))
                {
                    var c = CSharpCompilation.Create("Foo", references: new[] { MscorlibRef, mdModule.GetReference(display: "ModuleCS00") }, options: TestOptions.ReleaseDll);
                    c.VerifyDiagnostics(
                        // error CS7098: Linked netmodule metadata must provide a full PE image: 'ModuleCS00'.
                        Diagnostic(ErrorCode.ERR_LinkedNetmoduleMetadataMustProvideFullPEImage).WithArguments("ModuleCS00").WithLocation(1, 1));
                }
            }
        }
예제 #22
0
        public void CheckDllCharacteristicsWinRtApp()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.WinRtExe);
            var peHeaders = new PEHeaders(compilation.EmitToStream());

            //interesting COFF bits
            Assert.Equal(0x9540u, (ushort)peHeaders.PEHeader.DllCharacteristics);  //DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE | IMAGE_DLLCHARACTERISTICS_APPCONTAINER (0x1000)
        }
 private static void AssertFileIsSigned(TempFile file)
 {
     //TODO should check to see that the output was actually signed
     using (var metadata = new FileStream(file.Path, FileMode.Open))
     {
         var flags = new PEHeaders(metadata).CorHeader.Flags;
         Assert.Equal(CorFlags.StrongNameSigned, flags & CorFlags.StrongNameSigned);
     }
 }
예제 #24
0
        public void CheckFileAlignment()
        {
            string source = @"
class C
{
    public static void Main()
    {
    }
}";
            var compilation = CreateCompilationWithMscorlib(source, compOptions: TestOptions.Exe.WithFileAlignment(1024));
            var peHeaders = new PEHeaders(compilation.EmitToStream());
            Assert.Equal(1024, peHeaders.PEHeader.FileAlignment);
        }
예제 #25
0
        public byte[] ReadMetadata(string fileName)
        {
            using (var stream = File.OpenRead(fileName))
            {
                var peHeader = new PEHeaders(stream);

                var metadata = new byte[peHeader.MetadataSize];
                stream.Position = peHeader.MetadataStartOffset;
                stream.Read(metadata, 0, peHeader.MetadataSize);

                return metadata;
            }
        }
 public void EmittedSubsystemVersion()
 {
     var compilation = CSharpCompilation.Create("a.dll", references: new[] { MscorlibRef }, options: TestOptions.ReleaseDll);
     var peHeaders = new PEHeaders(compilation.EmitToStream(options: new EmitOptions(subsystemVersion: SubsystemVersion.Create(5, 1))));
     Assert.Equal(5, peHeaders.PEHeader.MajorSubsystemVersion);
     Assert.Equal(1, peHeaders.PEHeader.MinorSubsystemVersion);
 }
예제 #27
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();
                }
            }
        }
예제 #28
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();
                }
            }
        }
예제 #29
0
        public void PEHeaders1()
        {
            var options = EmitOptions.Default.WithFileAlignment(8192);
            var syntax = SyntaxFactory.ParseSyntaxTree(@"class C {}", TestOptions.Regular.WithDeterministicFeature());

            var peStream = CreateCompilationWithMscorlib(syntax, assemblyName: "46B9C2B2-B7A0-45C5-9EF9-28DDF739FD9E").EmitToStream(options);

            peStream.Position = 0;
            var peHeaders = new PEHeaders(peStream);

            var peHeader = peHeaders.PEHeader;
            var coffHeader = peHeaders.CoffHeader;
            var corHeader = peHeaders.CorHeader;

            Assert.Equal(PEMagic.PE32, peHeader.Magic);
            Assert.Equal(0x00002362, peHeader.AddressOfEntryPoint);
            Assert.Equal(0x00002000, peHeader.BaseOfCode);
            Assert.Equal(0x00004000, peHeader.BaseOfData);
            Assert.Equal(0x00002000, peHeader.SizeOfHeaders);
            Assert.Equal(0x00002000, peHeader.SizeOfCode);
            Assert.Equal(0x00001000u, peHeader.SizeOfHeapCommit);
            Assert.Equal(0x00100000u, peHeader.SizeOfHeapReserve);
            Assert.Equal(0x00006000, peHeader.SizeOfImage);
            Assert.Equal(0x00002000, peHeader.SizeOfInitializedData);
            Assert.Equal(0x00001000u, peHeader.SizeOfStackCommit);
            Assert.Equal(0x00100000u, peHeader.SizeOfStackReserve);
            Assert.Equal(0, peHeader.SizeOfUninitializedData);
            Assert.Equal(Subsystem.WindowsCui, peHeader.Subsystem);
            Assert.Equal(0u, peHeader.CheckSum);
            Assert.Equal(0x2000, peHeader.FileAlignment);
            Assert.Equal(0x10000000u, peHeader.ImageBase);
            Assert.Equal(0x2000, peHeader.SectionAlignment);
            Assert.Equal(0, peHeader.MajorImageVersion);
            Assert.Equal(0, peHeader.MinorImageVersion);
            Assert.Equal(0x30, peHeader.MajorLinkerVersion);
            Assert.Equal(0, peHeader.MinorLinkerVersion);
            Assert.Equal(4, peHeader.MajorOperatingSystemVersion);
            Assert.Equal(0, peHeader.MinorOperatingSystemVersion);
            Assert.Equal(4, peHeader.MajorSubsystemVersion);
            Assert.Equal(0, peHeader.MinorSubsystemVersion);
            Assert.Equal(16, peHeader.NumberOfRvaAndSizes);
            Assert.Equal(0x2000, peHeader.SizeOfHeaders);

            Assert.Equal(0x4000, peHeader.BaseRelocationTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0xc, peHeader.BaseRelocationTableDirectory.Size);
            Assert.Equal(0, peHeader.BoundImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.BoundImportTableDirectory.Size);
            Assert.Equal(0, peHeader.CertificateTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.CertificateTableDirectory.Size);
            Assert.Equal(0, peHeader.CopyrightTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.CopyrightTableDirectory.Size);
            Assert.Equal(0x2008, peHeader.CorHeaderTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x48, peHeader.CorHeaderTableDirectory.Size);
            Assert.Equal(0, peHeader.DebugTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.DebugTableDirectory.Size);
            Assert.Equal(0, peHeader.ExceptionTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ExceptionTableDirectory.Size);
            Assert.Equal(0, peHeader.ExportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ExportTableDirectory.Size);
            Assert.Equal(0x2000, peHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x8, peHeader.ImportAddressTableDirectory.Size);
            Assert.Equal(0x2310, peHeader.ImportTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x4f, peHeader.ImportTableDirectory.Size);
            Assert.Equal(0, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.LoadConfigTableDirectory.Size);
            Assert.Equal(0, peHeader.ResourceTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ResourceTableDirectory.Size);
            Assert.Equal(0, peHeader.ThreadLocalStorageTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, peHeader.ThreadLocalStorageTableDirectory.Size);

            Assert.Equal(Characteristics.Dll | Characteristics.LargeAddressAware | Characteristics.ExecutableImage, coffHeader.Characteristics);
            Assert.Equal(Machine.I386, coffHeader.Machine);
            Assert.Equal(2, coffHeader.NumberOfSections);
            Assert.Equal(0, coffHeader.NumberOfSymbols);
            Assert.Equal(0, coffHeader.PointerToSymbolTable);
            Assert.Equal(0xe0, coffHeader.SizeOfOptionalHeader);
            Assert.Equal(-1017800620, coffHeader.TimeDateStamp);

            Assert.Equal(0, corHeader.EntryPointTokenOrRelativeVirtualAddress);
            Assert.Equal(CorFlags.ILOnly, corHeader.Flags);
            Assert.Equal(2, corHeader.MajorRuntimeVersion);
            Assert.Equal(5, corHeader.MinorRuntimeVersion);

            Assert.Equal(0, corHeader.CodeManagerTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.CodeManagerTableDirectory.Size);
            Assert.Equal(0, corHeader.ExportAddressTableJumpsDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ExportAddressTableJumpsDirectory.Size);
            Assert.Equal(0, corHeader.ManagedNativeHeaderDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ManagedNativeHeaderDirectory.Size);
            Assert.Equal(0x2058, corHeader.MetadataDirectory.RelativeVirtualAddress);
            Assert.Equal(0x02b8, corHeader.MetadataDirectory.Size);
            Assert.Equal(0, corHeader.ResourcesDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.ResourcesDirectory.Size);
            Assert.Equal(0, corHeader.StrongNameSignatureDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.StrongNameSignatureDirectory.Size);
            Assert.Equal(0, corHeader.VtableFixupsDirectory.RelativeVirtualAddress);
            Assert.Equal(0, corHeader.VtableFixupsDirectory.Size);

            var sections = peHeaders.SectionHeaders;
            Assert.Equal(2, sections.Length);

            // TODO: bug in the reader, should return ".text". Fixed in vNext. https://github.com/dotnet/corefx/issues/1805
            Assert.Equal(".text\0\0\0", sections[0].Name);
            Assert.Equal(0, sections[0].NumberOfLineNumbers);
            Assert.Equal(0, sections[0].NumberOfRelocations);
            Assert.Equal(0, sections[0].PointerToLineNumbers);
            Assert.Equal(0x2000, sections[0].PointerToRawData);
            Assert.Equal(0, sections[0].PointerToRelocations);
            Assert.Equal(SectionCharacteristics.ContainsCode | SectionCharacteristics.MemExecute | SectionCharacteristics.MemRead, sections[0].SectionCharacteristics);
            Assert.Equal(0x2000, sections[0].SizeOfRawData);
            Assert.Equal(0x2000, sections[0].VirtualAddress);
            Assert.Equal(872, sections[0].VirtualSize);

            // TODO: bug in the reader, should return ".reloc". Fixed in vNext. https://github.com/dotnet/corefx/issues/1805
            Assert.Equal(".reloc\0\0", sections[1].Name);
            Assert.Equal(0, sections[1].NumberOfLineNumbers);
            Assert.Equal(0, sections[1].NumberOfRelocations);
            Assert.Equal(0, sections[1].PointerToLineNumbers);
            Assert.Equal(0x4000, sections[1].PointerToRawData);
            Assert.Equal(0, sections[1].PointerToRelocations);
            Assert.Equal(SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemDiscardable | SectionCharacteristics.MemRead, sections[1].SectionCharacteristics);
            Assert.Equal(0x2000, sections[1].SizeOfRawData);
            Assert.Equal(0x4000, sections[1].VirtualAddress);
            Assert.Equal(12, sections[1].VirtualSize);
        }