Ejemplo n.º 1
0
        public unsafe void PEHeaders1()
        {
            var options = EmitOptions.Default.WithFileAlignment(8192);
            var syntax = SyntaxFactory.ParseSyntaxTree(@"class C {}", TestOptions.Regular);

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

            peStream.Position = 0;
            var peReader = new PEReader(peStream);

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

            Assert.Equal(PEMagic.PE32, peHeader.Magic);
            Assert.Equal(0x0000237E, 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(DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware, peHeader.DllCharacteristics);
            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(0x2310, 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(0x2000, peHeader.ImportAddressTableDirectory.RelativeVirtualAddress);
            Assert.Equal(0x8, peHeader.ImportAddressTableDirectory.Size);
            Assert.Equal(0x232C, 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);

            int importAddressTableDirectoryOffset;
            Assert.True(peHeaders.TryGetDirectoryOffset(peHeader.ImportAddressTableDirectory, out importAddressTableDirectoryOffset));
            Assert.Equal(0x2000, importAddressTableDirectoryOffset);

            var importAddressTableDirectoryBytes = new byte[peHeader.ImportAddressTableDirectory.Size];
            peStream.Position = importAddressTableDirectoryOffset;
            peStream.Read(importAddressTableDirectoryBytes, 0, importAddressTableDirectoryBytes.Length);
            AssertEx.Equal(new byte[]
            {
                0x60, 0x23, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00
            }, importAddressTableDirectoryBytes);

            int importTableDirectoryOffset;
            Assert.True(peHeaders.TryGetDirectoryOffset(peHeader.ImportTableDirectory, out importTableDirectoryOffset));
            Assert.Equal(0x232C, importTableDirectoryOffset);

            var importTableDirectoryBytes = new byte[peHeader.ImportTableDirectory.Size];
            peStream.Position = importTableDirectoryOffset;
            peStream.Read(importTableDirectoryBytes, 0, importTableDirectoryBytes.Length);
            AssertEx.Equal(new byte[]
            {
                0x54, 0x23, 0x00, 0x00, // RVA
                0x00, 0x00, 0x00, 0x00, // 0
                0x00, 0x00, 0x00, 0x00, // 0
                0x6E, 0x23, 0x00, 0x00, // name RVA
                0x00, 0x20, 0x00, 0x00, // ImportAddressTableDirectory RVA
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x60, 0x23, 0x00, 0x00, // hint RVA
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00,             // hint
                (byte)'_', (byte)'C', (byte)'o', (byte)'r', (byte)'D', (byte)'l', (byte)'l', (byte)'M', (byte)'a', (byte)'i', (byte)'n', 0x00,
                (byte)'m', (byte)'s', (byte)'c', (byte)'o', (byte)'r', (byte)'e', (byte)'e', (byte)'.', (byte)'d', (byte)'l', (byte)'l', 0x00,
                0x00
            }, importTableDirectoryBytes);

            var entryPointSectionIndex = peHeaders.GetContainingSectionIndex(peHeader.AddressOfEntryPoint);
            Assert.Equal(0, entryPointSectionIndex);

            peStream.Position = peHeaders.SectionHeaders[0].PointerToRawData + peHeader.AddressOfEntryPoint - peHeaders.SectionHeaders[0].VirtualAddress;
            byte[] startupStub = new byte[8];
            peStream.Read(startupStub, 0, startupStub.Length);
            AssertEx.Equal(new byte[] { 0xFF, 0x25, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00 }, startupStub);

            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(-609170495, 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);

            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(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(900, sections[0].VirtualSize);

            Assert.Equal(".reloc", 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);

            var relocBlock = peReader.GetSectionData(sections[1].VirtualAddress);
            var relocBytes = new byte[sections[1].VirtualSize];
            Marshal.Copy((IntPtr)relocBlock.Pointer, relocBytes, 0, relocBytes.Length);
            AssertEx.Equal(new byte[] { 0, 0x20, 0, 0, 0x0c, 0, 0, 0, 0x80, 0x33, 0, 0 }, relocBytes);
        }