提交 53128bf0 编写于 作者: N Neal Gafter

Ensure that the new deterministic-timestamp section is generated in non-debug scenarios

上级 23d18d1d
......@@ -2160,7 +2160,7 @@ public unsafe void PEHeaders1()
var corHeader = peHeaders.CorHeader;
Assert.Equal(PEMagic.PE32, peHeader.Magic);
Assert.Equal(0x00002362, peHeader.AddressOfEntryPoint);
Assert.Equal(0x0000237E, peHeader.AddressOfEntryPoint);
Assert.Equal(0x00002000, peHeader.BaseOfCode);
Assert.Equal(0x00004000, peHeader.BaseOfData);
Assert.Equal(0x00002000, peHeader.SizeOfHeaders);
......@@ -2199,15 +2199,15 @@ public unsafe void PEHeaders1()
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(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(0x2310, peHeader.ImportTableDirectory.RelativeVirtualAddress);
Assert.Equal(0x232C, peHeader.ImportTableDirectory.RelativeVirtualAddress);
Assert.Equal(0x4f, peHeader.ImportTableDirectory.Size);
Assert.Equal(0, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
Assert.Equal(0, peHeader.LoadConfigTableDirectory.Size);
......@@ -2225,30 +2225,30 @@ public unsafe void PEHeaders1()
peStream.Read(importAddressTableDirectoryBytes, 0, importAddressTableDirectoryBytes.Length);
AssertEx.Equal(new byte[]
{
0x44, 0x23, 0x00, 0x00,
0x60, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
}, importAddressTableDirectoryBytes);
int importTableDirectoryOffset;
Assert.True(peHeaders.TryGetDirectoryOffset(peHeader.ImportTableDirectory, out importTableDirectoryOffset));
Assert.Equal(0x2310, 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[]
{
0x38, 0x23, 0x00, 0x00, // RVA
0x54, 0x23, 0x00, 0x00, // RVA
0x00, 0x00, 0x00, 0x00, // 0
0x00, 0x00, 0x00, 0x00, // 0
0x52, 0x23, 0x00, 0x00, // name RVA
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,
0x44, 0x23, 0x00, 0x00, // hint RVA
0x60, 0x23, 0x00, 0x00, // hint RVA
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, // hint
......@@ -2271,7 +2271,7 @@ public unsafe void PEHeaders1()
Assert.Equal(0, coffHeader.NumberOfSymbols);
Assert.Equal(0, coffHeader.PointerToSymbolTable);
Assert.Equal(0xe0, coffHeader.SizeOfOptionalHeader);
Assert.Equal(-1017800620, coffHeader.TimeDateStamp);
Assert.Equal(-609170495, coffHeader.TimeDateStamp);
Assert.Equal(0, corHeader.EntryPointTokenOrRelativeVirtualAddress);
Assert.Equal(CorFlags.ILOnly, corHeader.Flags);
......@@ -2305,7 +2305,7 @@ public unsafe void PEHeaders1()
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);
Assert.Equal(900, sections[0].VirtualSize);
Assert.Equal(".reloc", sections[1].Name);
Assert.Equal(0, sections[1].NumberOfLineNumbers);
......@@ -2321,7 +2321,7 @@ public unsafe void PEHeaders1()
var relocBlock = peReader.GetSectionData(sections[1].VirtualAddress);
var relocBytes = new byte[sections[1].VirtualSize];
Marshal.Copy((IntPtr)relocBlock.Pointer, relocBytes, 0, relocBytes.Length);
Assert.Equal(new byte[] { 0, 0x20, 0, 0, 0x0c, 0, 0, 0, 0x64, 0x33, 0, 0 }, relocBytes);
AssertEx.Equal(new byte[] { 0, 0x20, 0, 0, 0x0c, 0, 0, 0, 0x80, 0x33, 0, 0 }, relocBytes);
}
[Fact]
......@@ -2386,8 +2386,8 @@ public void PEHeaders2()
Assert.Equal(0, peHeader.CopyrightTableDirectory.Size);
Assert.Equal(0x2000, peHeader.CorHeaderTableDirectory.RelativeVirtualAddress);
Assert.Equal(0x48, peHeader.CorHeaderTableDirectory.Size);
Assert.Equal(0, peHeader.DebugTableDirectory.RelativeVirtualAddress);
Assert.Equal(0, peHeader.DebugTableDirectory.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);
......@@ -2409,7 +2409,7 @@ public void PEHeaders2()
Assert.Equal(0, coffHeader.NumberOfSymbols);
Assert.Equal(0, coffHeader.PointerToSymbolTable);
Assert.Equal(240, coffHeader.SizeOfOptionalHeader);
Assert.Equal(-1439607823, coffHeader.TimeDateStamp);
Assert.Equal(-862605524, coffHeader.TimeDateStamp);
Assert.Equal(0x06000001, corHeader.EntryPointTokenOrRelativeVirtualAddress);
Assert.Equal(CorFlags.ILOnly, corHeader.Flags);
......@@ -2443,7 +2443,7 @@ public void PEHeaders2()
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(804, sections[0].VirtualSize);
Assert.Equal(832, sections[0].VirtualSize);
}
}
}
......@@ -202,7 +202,7 @@ private bool WritePeToStream(MetadataWriter mdWriter, Func<Stream> getPeStream,
DirectoryEntry importAddressTable = default(DirectoryEntry);
int entryPointAddress = 0;
if (EmitPdb)
if (EmitPdb || _deterministic)
{
debugDirectory = new DirectoryEntry(textSectionRva + ComputeOffsetToDebugTable(metadataSizes), ImageDebugDirectoryBaseSize);
}
......@@ -477,11 +477,14 @@ private int ComputeOffsetToMetadata(int ilStreamLength)
/// The size of our debug directory: one entry for debug information, and an optional second one indicating
/// that the timestamp is deterministic (i.e. not really a timestamp)
/// </summary>
private int ImageDebugDirectoryBaseSize => (_deterministic ? 2 : 1) * ImageDebugDirectoryEntrySize;
private int ImageDebugDirectoryBaseSize =>
(_deterministic ? ImageDebugDirectoryEntrySize : 0) +
(EmitPdb ? ImageDebugDirectoryEntrySize : 0);
private int ComputeSizeOfDebugDirectoryData()
{
return
// The debug directory data is only needed if this.EmitPdb.
return (!EmitPdb) ? 0 :
4 + // 4B signature "RSDS"
16 + // GUID
sizeof(uint) + // Age
......@@ -490,7 +493,7 @@ private int ComputeSizeOfDebugDirectoryData()
private int ComputeSizeOfDebugDirectory()
{
return EmitPdb ? ImageDebugDirectoryBaseSize + ComputeSizeOfDebugDirectoryData() : 0;
return ImageDebugDirectoryBaseSize + ComputeSizeOfDebugDirectoryData();
}
private int ComputeSizeOfPeHeaders(int sectionCount)
......@@ -1220,7 +1223,7 @@ private static void WriteSectionHeader(SectionHeader sectionHeader, BlobBuilder
// strong name signature:
WriteSpaceForHash(peStream, metadataSizes.StrongNameSignatureSize);
if (EmitPdb)
if (EmitPdb || _deterministic)
{
WriteDebugTable(peStream, textSection, nativePdbContentId, portablePdbContentId, metadataSizes);
}
......@@ -1384,41 +1387,41 @@ uint pointerToRawData
writer.WriteUInt32(pointerToRawData);
}
private static byte[] zeroStamp = new byte[4]; // four bytes of zero
private readonly static byte[] zeroStamp = new byte[4]; // four bytes of zero
/// <summary>
/// Write the entire "Debug Directory (Image Only)" along with data that it points to.
/// </summary>
/// <param name="peStream"></param>
/// <param name="textSection"></param>
/// <param name="nativePdbContentId"></param>
/// <param name="portablePdbContentId"></param>
/// <param name="metadataSizes"></param>
private void WriteDebugTable(Stream peStream, SectionHeader textSection, ContentId nativePdbContentId, ContentId portablePdbContentId, MetadataSizes metadataSizes)
{
int tableSize = ImageDebugDirectoryBaseSize;
Debug.Assert(nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault);
Debug.Assert(tableSize != 0);
Debug.Assert(nativePdbContentId.IsDefault || portablePdbContentId.IsDefault);
Debug.Assert(!EmitPdb || (nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault));
var writer = PooledBlobBuilder.GetInstance();
const int ImageDebugTypeCodeView = 2;
uint dataOffset = (uint)(ComputeOffsetToDebugTable(metadataSizes) + tableSize);
int dataSize = ComputeSizeOfDebugDirectoryData();
WriteDebugTableEntry(writer,
stamp: nativePdbContentId.Stamp ?? portablePdbContentId.Stamp,
version: portablePdbContentId.IsDefault ? (uint)0 : ('P' << 24 | 'M' << 16 | 0x01 << 8 | 0x00),
debugType: ImageDebugTypeCodeView,
sizeOfData: (uint)dataSize,
addressOfRawData: (uint)textSection.RelativeVirtualAddress + dataOffset, // RVA of the data
pointerToRawData: (uint)textSection.PointerToRawData + dataOffset); // position of the data in the PE stream
if (this.EmitPdb)
{
const int IMAGE_DEBUG_TYPE_CODEVIEW = 2; // from PE spec
uint dataOffset = (uint)(ComputeOffsetToDebugTable(metadataSizes) + tableSize);
WriteDebugTableEntry(writer,
stamp: nativePdbContentId.Stamp ?? portablePdbContentId.Stamp,
version: portablePdbContentId.IsDefault ? (uint)0 : ('P' << 24 | 'M' << 16 | 0x01 << 8 | 0x00),
debugType: IMAGE_DEBUG_TYPE_CODEVIEW,
sizeOfData: (uint)dataSize,
addressOfRawData: (uint)textSection.RelativeVirtualAddress + dataOffset, // RVA of the data
pointerToRawData: (uint)textSection.PointerToRawData + dataOffset); // position of the data in the PE stream
}
if (this._deterministic)
{
const int ImageDebugTypeDeterministicTimestamp = 16;
const int IMAGE_DEBUG_TYPE_NO_TIMESTAMP = 16; // from PE spec
WriteDebugTableEntry(writer,
stamp: zeroStamp,
version: 0,
debugType: ImageDebugTypeDeterministicTimestamp,
debugType: IMAGE_DEBUG_TYPE_NO_TIMESTAMP,
sizeOfData: 0,
addressOfRawData: 0,
pointerToRawData: 0);
......@@ -1431,24 +1434,27 @@ private void WriteDebugTable(Stream peStream, SectionHeader textSection, Content
// The following is additional data beyond the debug directory at the offset `dataOffset`
// pointed to by the ImageDebugTypeCodeView entry.
writer.WriteByte((byte)'R');
writer.WriteByte((byte)'S');
writer.WriteByte((byte)'D');
writer.WriteByte((byte)'S');
if (EmitPdb)
{
writer.WriteByte((byte)'R');
writer.WriteByte((byte)'S');
writer.WriteByte((byte)'D');
writer.WriteByte((byte)'S');
// PDB id:
writer.WriteBytes(nativePdbContentId.Guid ?? portablePdbContentId.Guid);
// PDB id:
writer.WriteBytes(nativePdbContentId.Guid ?? portablePdbContentId.Guid);
// age
writer.WriteUInt32(PdbWriter.Age);
// age
writer.WriteUInt32(PdbWriter.Age);
// UTF-8 encoded zero-terminated path to PDB
int pathStart = writer.Position;
writer.WriteUTF8(_pdbPathOpt, allowUnpairedSurrogates: true);
writer.WriteByte(0);
// UTF-8 encoded zero-terminated path to PDB
int pathStart = writer.Position;
writer.WriteUTF8(_pdbPathOpt, allowUnpairedSurrogates: true);
writer.WriteByte(0);
// padding:
writer.WriteBytes(0, Math.Max(0, _minPdbPath - (writer.Position - pathStart)));
// padding:
writer.WriteBytes(0, Math.Max(0, _minPdbPath - (writer.Position - pathStart)));
}
// We should now have written all and precisely the data we said we'd write for the table and its data.
Debug.Assert(writer.Count == tableSize + dataSize);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册