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); } }
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); } }
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()); } }
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); } }
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); }
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); }
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); }
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); }
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); }
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); }
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) }
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(); } } }
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(); }
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); }
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); }
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); }
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); }
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)); } } }
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); } }
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); }
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); }
/// <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(); } } }
/// <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(); } } }
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); }