diff options
author | Marek Safar <marek.safar@gmail.com> | 2022-01-20 13:00:40 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2022-01-20 13:00:40 +0300 |
commit | 03aabb40d2a5d9b22c94bfc6e4fe5a5b85badb8f (patch) | |
tree | 32aeeb50545c5596235f6215c45b9b2e49bf0366 | |
parent | 9fd4a5ca53cfc8baee82abe0ca1f46d489625913 (diff) |
Revert "Fix deterministic MVID and add PdbChecksum (#31)"
This reverts commit ff616bf90e3aff2292a0b1536f7af13cd8810276.
-rw-r--r-- | Mono.Cecil.Cil/PortablePdb.cs | 179 | ||||
-rw-r--r-- | Mono.Cecil.Cil/Symbols.cs | 6 | ||||
-rw-r--r-- | Mono.Cecil.PE/ImageReader.cs | 5 | ||||
-rw-r--r-- | Mono.Cecil.PE/ImageWriter.cs | 34 | ||||
-rw-r--r-- | Mono.Cecil/AssemblyWriter.cs | 49 | ||||
-rw-r--r-- | Mono.Security.Cryptography/CryptoService.cs | 2 | ||||
-rw-r--r-- | Test/Mono.Cecil.Tests/ImageReadTests.cs | 18 | ||||
-rw-r--r-- | Test/Mono.Cecil.Tests/PortablePdbTests.cs | 303 | ||||
-rw-r--r-- | Test/Resources/assemblies/EmbeddedPdbChecksumLib.dll | bin | 9728 -> 0 bytes | |||
-rw-r--r-- | Test/Resources/assemblies/PdbChecksumLib.dll | bin | 4096 -> 0 bytes | |||
-rw-r--r-- | Test/Resources/assemblies/PdbChecksumLib.pdb | bin | 9576 -> 0 bytes | |||
-rw-r--r-- | symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs | 11 |
12 files changed, 107 insertions, 500 deletions
diff --git a/Mono.Cecil.Cil/PortablePdb.cs b/Mono.Cecil.Cil/PortablePdb.cs index d8c43f6..aff6b29 100644 --- a/Mono.Cecil.Cil/PortablePdb.cs +++ b/Mono.Cecil.Cil/PortablePdb.cs @@ -12,7 +12,7 @@ using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; -using System.Security.Cryptography; + using Mono.Cecil.Metadata; using Mono.Cecil.PE; @@ -39,7 +39,7 @@ namespace Mono.Cecil.Cil { ISymbolReader GetSymbolReader (ModuleDefinition module, Disposable<Stream> symbolStream, string fileName) { - return new PortablePdbReader (ImageReader.ReadPortablePdb (symbolStream, fileName, out _), module); + return new PortablePdbReader (ImageReader.ReadPortablePdb (symbolStream, fileName), module); } } @@ -234,8 +234,8 @@ namespace Mono.Cecil.Cil { Mixin.CheckModule (module); Mixin.CheckFileName (fileName); - var file = File.Open (Mixin.GetPdbFileName (fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite); - return GetSymbolWriter (module, Disposable.Owned (file as Stream), Disposable.NotOwned ((Stream)null)); + var file = File.OpenWrite (Mixin.GetPdbFileName (fileName)); + return GetSymbolWriter (module, Disposable.Owned (file as Stream)); } public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) @@ -243,18 +243,15 @@ namespace Mono.Cecil.Cil { Mixin.CheckModule (module); Mixin.CheckStream (symbolStream); - // In order to compute the PDB checksum, the stream we're writing to needs to be able to - // seek and read as well. We can't assume this about a stream provided by the user. - // So in this case, create a memory stream to cache the PDB. - return GetSymbolWriter (module, Disposable.Owned (new MemoryStream() as Stream), Disposable.NotOwned (symbolStream)); + return GetSymbolWriter (module, Disposable.NotOwned (symbolStream)); } - ISymbolWriter GetSymbolWriter (ModuleDefinition module, Disposable<Stream> stream, Disposable<Stream> final_stream) + ISymbolWriter GetSymbolWriter (ModuleDefinition module, Disposable<Stream> stream) { var metadata = new MetadataBuilder (module, this); var writer = ImageWriter.CreateDebugWriter (module, metadata, stream); - return new PortablePdbWriter (metadata, module, writer, final_stream); + return new PortablePdbWriter (metadata, module, writer); } } @@ -263,14 +260,9 @@ namespace Mono.Cecil.Cil { readonly MetadataBuilder pdb_metadata; readonly ModuleDefinition module; readonly ImageWriter writer; - readonly Disposable<Stream> final_stream; MetadataBuilder module_metadata; - internal byte [] pdb_checksum; - internal Guid pdb_id_guid; - internal uint pdb_id_age; - bool IsEmbedded { get { return writer == null; } } internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module) @@ -286,11 +278,10 @@ namespace Mono.Cecil.Cil { pdb_metadata.AddCustomDebugInformations (module); } - internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module, ImageWriter writer, Disposable<Stream> final_stream) + internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module, ImageWriter writer) : this (pdb_metadata, module) { this.writer = writer; - this.final_stream = final_stream; } public ISymbolReaderProvider GetReaderProvider () @@ -298,82 +289,45 @@ namespace Mono.Cecil.Cil { return new PortablePdbReaderProvider (); } - public void Write (MethodDebugInformation info) - { - CheckMethodDebugInformationTable (); - - pdb_metadata.AddMethodDebugInformation (info); - } - public ImageDebugHeader GetDebugHeader () { if (IsEmbedded) return new ImageDebugHeader (); - WritePdbFile (); - - if (final_stream.value != null) { - writer.BaseStream.Seek (0, SeekOrigin.Begin); - var buffer = new byte [8192]; - CryptoService.CopyStreamChunk (writer.BaseStream, final_stream.value, buffer, (int)writer.BaseStream.Length); - } + var directory = new ImageDebugDirectory () { + MajorVersion = 256, + MinorVersion = 20557, + Type = ImageDebugType.CodeView, + TimeDateStamp = (int) module.timestamp, + }; - ImageDebugHeaderEntry codeViewEntry; - { - var codeViewDirectory = new ImageDebugDirectory () { - MajorVersion = 256, - MinorVersion = 20557, - Type = ImageDebugType.CodeView, - TimeDateStamp = (int)module.timestamp, - }; - - var buffer = new ByteBuffer (); - // RSDS - buffer.WriteUInt32 (0x53445352); - // Module ID - buffer.WriteBytes (pdb_id_guid.ToByteArray ()); - // PDB Age - buffer.WriteUInt32 (pdb_id_age); - // PDB Path - var fileName = writer.BaseStream.GetFileName (); - if (string.IsNullOrEmpty (fileName)) { - fileName = module.Assembly.Name.Name + ".pdb"; - } - buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (fileName)); - buffer.WriteByte (0); - - var data = new byte [buffer.length]; - Buffer.BlockCopy (buffer.buffer, 0, data, 0, buffer.length); - codeViewDirectory.SizeOfData = data.Length; - - codeViewEntry = new ImageDebugHeaderEntry (codeViewDirectory, data); + var buffer = new ByteBuffer (); + // RSDS + buffer.WriteUInt32 (0x53445352); + // Module ID + buffer.WriteBytes (module.Mvid.ToByteArray ()); + // PDB Age + buffer.WriteUInt32 (1); + // PDB Path + var fileName = writer.BaseStream.GetFileName (); + if (string.IsNullOrEmpty (fileName)) { + fileName = module.Assembly.Name.Name + ".pdb"; } + buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (fileName)); + buffer.WriteByte (0); - ImageDebugHeaderEntry pdbChecksumEntry; - { - var pdbChecksumDirectory = new ImageDebugDirectory () { - MajorVersion = 1, - MinorVersion = 0, - Type = ImageDebugType.PdbChecksum, - TimeDateStamp = 0 - }; - - var buffer = new ByteBuffer (); - // SHA256 - Algorithm name - buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes ("SHA256")); - buffer.WriteByte (0); - - // Checksum - 32 bytes - buffer.WriteBytes (pdb_checksum); + var data = new byte [buffer.length]; + Buffer.BlockCopy (buffer.buffer, 0, data, 0, buffer.length); + directory.SizeOfData = data.Length; - var data = new byte [buffer.length]; - Buffer.BlockCopy (buffer.buffer, 0, data, 0, buffer.length); - pdbChecksumDirectory.SizeOfData = data.Length; + return new ImageDebugHeader (new ImageDebugHeaderEntry (directory, data)); + } - pdbChecksumEntry = new ImageDebugHeaderEntry (pdbChecksumDirectory, data); - } + public void Write (MethodDebugInformation info) + { + CheckMethodDebugInformationTable (); - return new ImageDebugHeader (new ImageDebugHeaderEntry [] { codeViewEntry, pdbChecksumEntry }); + pdb_metadata.AddMethodDebugInformation (info); } void CheckMethodDebugInformationTable () @@ -389,8 +343,10 @@ namespace Mono.Cecil.Cil { public void Dispose () { - writer.stream.Dispose (); - final_stream.Dispose (); + if (IsEmbedded) + return; + + WritePdbFile (); } void WritePdbFile () @@ -404,18 +360,15 @@ namespace Mono.Cecil.Cil { writer.WriteMetadata (); writer.Flush (); - - ComputeChecksumAndPdbId (); - - WritePdbId (); + writer.stream.Dispose (); } void WritePdbHeap () { var pdb_heap = pdb_metadata.pdb_heap; - // PDB ID ( GUID + TimeStamp ) are left zeroed out for now. Will be filled at the end with a hash. - pdb_heap.WriteBytes (20); + pdb_heap.WriteBytes (module.Mvid.ToByteArray ()); + pdb_heap.WriteUInt32 (module_metadata.timestamp); pdb_heap.WriteUInt32 (module_metadata.entry_point.ToUInt32 ()); @@ -446,32 +399,6 @@ namespace Mono.Cecil.Cil { pdb_metadata.table_heap.ComputeTableInformations (); pdb_metadata.table_heap.WriteTableHeap (); } - - void ComputeChecksumAndPdbId () - { - var buffer = new byte [8192]; - - // Compute the has of the entire file - PDB ID is zeroes still - writer.BaseStream.Seek (0, SeekOrigin.Begin); - var sha256 = SHA256.Create (); - using (var crypto_stream = new CryptoStream (Stream.Null, sha256, CryptoStreamMode.Write)) { - CryptoService.CopyStreamChunk (writer.BaseStream, crypto_stream, buffer, (int)writer.BaseStream.Length); - } - - pdb_checksum = sha256.Hash; - - var hashBytes = new ByteBuffer (pdb_checksum); - pdb_id_guid = new Guid (hashBytes.ReadBytes (16)); - pdb_id_age = hashBytes.ReadUInt32 (); - } - - void WritePdbId () - { - // PDB ID is the first 20 bytes of the PdbHeap - writer.MoveToRVA (TextSegment.PdbHeap); - writer.WriteBytes (pdb_id_guid.ToByteArray ()); - writer.WriteUInt32 (pdb_id_age); - } } public sealed class EmbeddedPortablePdbWriterProvider : ISymbolWriterProvider { @@ -508,14 +435,9 @@ namespace Mono.Cecil.Cil { return new EmbeddedPortablePdbReaderProvider (); } - public void Write (MethodDebugInformation info) - { - writer.Write (info); - } - public ImageDebugHeader GetDebugHeader () { - ImageDebugHeader pdbDebugHeader = writer.GetDebugHeader (); + writer.Dispose (); var directory = new ImageDebugDirectory { Type = ImageDebugType.EmbeddedPortablePdb, @@ -540,12 +462,15 @@ namespace Mono.Cecil.Cil { directory.SizeOfData = (int) data.Length; - var debugHeaderEntries = new ImageDebugHeaderEntry [pdbDebugHeader.Entries.Length + 1]; - for (int i = 0; i < pdbDebugHeader.Entries.Length; i++) - debugHeaderEntries [i] = pdbDebugHeader.Entries [i]; - debugHeaderEntries [debugHeaderEntries.Length - 1] = new ImageDebugHeaderEntry (directory, data.ToArray ()); + return new ImageDebugHeader (new [] { + writer.GetDebugHeader ().Entries [0], + new ImageDebugHeaderEntry (directory, data.ToArray ()) + }); + } - return new ImageDebugHeader (debugHeaderEntries); + public void Write (MethodDebugInformation info) + { + writer.Write (info); } public void Dispose () diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs index a669067..5e92b67 100644 --- a/Mono.Cecil.Cil/Symbols.cs +++ b/Mono.Cecil.Cil/Symbols.cs @@ -39,7 +39,6 @@ namespace Mono.Cecil.Cil { CodeView = 2, Deterministic = 16, EmbeddedPortablePdb = 17, - PdbChecksum = 19, } public sealed class ImageDebugHeader { @@ -1175,11 +1174,6 @@ namespace Mono.Cecil { return GetEntry (header, ImageDebugType.EmbeddedPortablePdb); } - public static ImageDebugHeaderEntry GetPdbChecksumEntry (this ImageDebugHeader header) - { - return GetEntry (header, ImageDebugType.PdbChecksum); - } - private static ImageDebugHeaderEntry GetEntry (this ImageDebugHeader header, ImageDebugType type) { if (!header.HasEntries) diff --git a/Mono.Cecil.PE/ImageReader.cs b/Mono.Cecil.PE/ImageReader.cs index a34e64d..5358129 100644 --- a/Mono.Cecil.PE/ImageReader.cs +++ b/Mono.Cecil.PE/ImageReader.cs @@ -27,7 +27,6 @@ namespace Mono.Cecil.PE { DataDirectory metadata; uint table_heap_offset; - uint pdb_heap_offset; public ImageReader (Disposable<Stream> stream, string file_name) : base (stream.value) @@ -401,7 +400,6 @@ namespace Mono.Cecil.PE { break; case "#Pdb": image.PdbHeap = new PdbHeap (data); - pdb_heap_offset = offset; break; } } @@ -770,7 +768,7 @@ namespace Mono.Cecil.PE { } } - public static Image ReadPortablePdb (Disposable<Stream> stream, string file_name, out uint pdb_heap_offset) + public static Image ReadPortablePdb (Disposable<Stream> stream, string file_name) { try { var reader = new ImageReader (stream, file_name); @@ -787,7 +785,6 @@ namespace Mono.Cecil.PE { reader.metadata = new DataDirectory (0, length); reader.ReadMetadata (); - pdb_heap_offset = reader.pdb_heap_offset; return reader.image; } catch (EndOfStreamException e) { throw new BadImageFormatException (stream.value.GetFileName (), e); diff --git a/Mono.Cecil.PE/ImageWriter.cs b/Mono.Cecil.PE/ImageWriter.cs index 0648f59..a8a3fa8 100644 --- a/Mono.Cecil.PE/ImageWriter.cs +++ b/Mono.Cecil.PE/ImageWriter.cs @@ -48,9 +48,7 @@ namespace Mono.Cecil.PE { ushort sections; - internal long debug_header_entries_position; - - ImageWriter (ModuleDefinition module, string runtime_version, MetadataBuilder metadata, Disposable<Stream> stream, bool metadataOnly = false, ImageDebugHeader debugHeader = null) + ImageWriter (ModuleDefinition module, string runtime_version, MetadataBuilder metadata, Disposable<Stream> stream, bool metadataOnly = false) : base (stream.value) { this.module = module; @@ -63,18 +61,26 @@ namespace Mono.Cecil.PE { this.pe64 = module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64 || module.Architecture == TargetArchitecture.ARM64; this.has_reloc = module.Architecture == TargetArchitecture.I386; + this.GetDebugHeader (); this.GetWin32Resources (); + this.BuildTextMap (); + this.sections = (ushort) (has_reloc ? 2 : 1); // text + reloc? + } + + void GetDebugHeader () + { + var symbol_writer = metadata.symbol_writer; + if (symbol_writer != null) + debug_header = symbol_writer.GetDebugHeader (); - debug_header = debugHeader; if (module.HasDebugHeader) { var header = module.GetDebugHeader (); var deterministic = header.GetDeterministicEntry (); - if (deterministic != null) - debug_header = debug_header.AddDeterministicEntry (); - } + if (deterministic == null) + return; - this.BuildTextMap (); - this.sections = (ushort)(has_reloc ? 2 : 1); // text + reloc? + debug_header = debug_header.AddDeterministicEntry (); + } } void GetWin32Resources () @@ -90,9 +96,9 @@ namespace Mono.Cecil.PE { } } - public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable<Stream> stream, ImageDebugHeader debugHeader) + public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable<Stream> stream) { - var writer = new ImageWriter (module, module.runtime_version, metadata, stream, metadataOnly: false, debugHeader: debugHeader); + var writer = new ImageWriter (module, module.runtime_version, metadata, stream); writer.BuildSections (); return writer; } @@ -373,7 +379,7 @@ namespace Mono.Cecil.PE { BaseStream.Seek (GetRVAFileOffset (section, rva), SeekOrigin.Begin); } - internal void MoveToRVA (TextSegment segment) + void MoveToRVA (TextSegment segment) { MoveToRVA (text, text_map.GetRVA (segment)); } @@ -594,9 +600,7 @@ namespace Mono.Cecil.PE { data_start += entry.Data.Length; } - - debug_header_entries_position = BaseStream.Position; - + for (var i = 0; i < debug_header.Entries.Length; i++) { var entry = debug_header.Entries [i]; WriteBytes (entry.Data); diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index e60ab1d..c83f997 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -118,17 +118,13 @@ namespace Mono.Cecil { metadata.SetSymbolWriter (symbol_writer); BuildMetadata (module, metadata); - ImageDebugHeader debugHeader = null; - if (symbol_writer != null) - debugHeader = symbol_writer.GetDebugHeader (); + if (parameters.DeterministicMvid) + metadata.ComputeDeterministicMvid (); - var writer = ImageWriter.CreateWriter (module, metadata, stream, debugHeader); + var writer = ImageWriter.CreateWriter (module, metadata, stream); stream.value.SetLength (0); writer.WriteImage (); - if (parameters.DeterministicMvid) - ComputeDeterministicMvid (writer, module); - if (parameters.HasStrongNameKey) CryptoService.StrongName (stream.value, writer, parameters); } @@ -160,26 +156,6 @@ namespace Mono.Cecil { return symbol_writer_provider.GetSymbolWriter (module, fq_name); } - - static void ComputeDeterministicMvid (ImageWriter writer, ModuleDefinition module) - { - long previousPosition = writer.BaseStream.Position; - writer.BaseStream.Seek(0, SeekOrigin.Begin); - - // The hash should be computed with the MVID set to all zeroes - // which it is - we explicitly write all zeroes GUID into the heap - // as the MVID. - // Same goes for strong name signature, which also already in the image but all zeroes right now. - Guid guid = CryptoService.ComputeGuid (CryptoService.ComputeHash (writer.BaseStream)); - - // The MVID GUID is always the first GUID in the GUID heap - writer.MoveToRVA (TextSegment.GuidHeap); - writer.WriteBytes (guid.ToByteArray ()); - writer.Flush (); - module.Mvid = guid; - - writer.BaseStream.Seek(previousPosition, SeekOrigin.Begin); - } } abstract class MetadataTable { @@ -2666,6 +2642,25 @@ namespace Mono.Cecil { method_debug_information_table.rows [rid - 1].Col2 = GetBlobIndex (signature); } + + public void ComputeDeterministicMvid () + { + var guid = CryptoService.ComputeGuid (CryptoService.ComputeHash ( + data, + resources, + string_heap, + user_string_heap, + blob_heap, + table_heap, + code)); + + var position = guid_heap.position; + guid_heap.position = 0; + guid_heap.WriteBytes (guid.ToByteArray ()); + guid_heap.position = position; + + module.Mvid = guid; + } } sealed class SignatureWriter : ByteBuffer { diff --git a/Mono.Security.Cryptography/CryptoService.cs b/Mono.Security.Cryptography/CryptoService.cs index 3877deb..dd9613f 100644 --- a/Mono.Security.Cryptography/CryptoService.cs +++ b/Mono.Security.Cryptography/CryptoService.cs @@ -109,7 +109,7 @@ namespace Mono.Cecil { return sha1.Hash; } - public static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length) + static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length) { while (length > 0) { int read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, length)); diff --git a/Test/Mono.Cecil.Tests/ImageReadTests.cs b/Test/Mono.Cecil.Tests/ImageReadTests.cs index f663b60..ef6ab06 100644 --- a/Test/Mono.Cecil.Tests/ImageReadTests.cs +++ b/Test/Mono.Cecil.Tests/ImageReadTests.cs @@ -237,16 +237,9 @@ namespace Mono.Cecil.Tests { var header = module.GetDebugHeader (); - Assert.IsTrue (header.Entries.Length >= 2); + Assert.AreEqual (2, header.Entries.Length); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.CodeView)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.Deterministic)); - - // If read directly from a file the PdbChecksum may not be persent (in this test case it isn't) - // but when written through Cecil it will always be there. - if (header.Entries.Length > 2) { - Assert.AreEqual (3, header.Entries.Length); - Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.PdbChecksum)); - } }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); } @@ -258,17 +251,10 @@ namespace Mono.Cecil.Tests { var header = module.GetDebugHeader (); - Assert.IsTrue (header.Entries.Length >= 3); + Assert.AreEqual (3, header.Entries.Length); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.CodeView)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.Deterministic)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.EmbeddedPortablePdb)); - - // If read directly from a file the PdbChecksum may not be persent (in this test case it isn't) - // but when written through Cecil it will always be there. - if (header.Entries.Length > 3) { - Assert.AreEqual (4, header.Entries.Length); - Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.PdbChecksum)); - } }, symbolReaderProvider: typeof (EmbeddedPortablePdbReaderProvider), symbolWriterProvider: typeof (EmbeddedPortablePdbWriterProvider)); } } diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs index 1401f63..d9786cb 100644 --- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs +++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -1,8 +1,6 @@ using System; using System.IO; -using System.IO.Compression; using System.Linq; -using System.Security.Cryptography; using System.Text; using NUnit.Framework; @@ -359,23 +357,15 @@ namespace Mono.Cecil.Tests { var header = module.GetDebugHeader (); Assert.IsNotNull (header); - Assert.IsTrue (header.Entries.Length >= 2); + Assert.AreEqual (2, header.Entries.Length); - int i = 0; - var cv = header.Entries [i++]; + var cv = header.Entries [0]; Assert.AreEqual (ImageDebugType.CodeView, cv.Directory.Type); - if (header.Entries.Length > 2) { - Assert.AreEqual (3, header.Entries.Length); - var pdbChecksum = header.Entries [i++]; - Assert.AreEqual (ImageDebugType.PdbChecksum, pdbChecksum.Directory.Type); - } - - var eppdb = header.Entries [i++]; + var eppdb = header.Entries [1]; Assert.AreEqual (ImageDebugType.EmbeddedPortablePdb, eppdb.Directory.Type); Assert.AreEqual (0x0100, eppdb.Directory.MajorVersion); Assert.AreEqual (0x0100, eppdb.Directory.MinorVersion); - }, symbolReaderProvider: typeof (EmbeddedPortablePdbReaderProvider), symbolWriterProvider: typeof (EmbeddedPortablePdbWriterProvider)); } @@ -410,7 +400,7 @@ namespace Mono.Cecil.Tests { { TestModule ("PdbTarget.exe", test, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); TestModule ("EmbeddedPdbTarget.exe", test, verify: !Platform.OnMono); - TestModule ("EmbeddedCompressedPdbTarget.exe", test, symbolReaderProvider: typeof(EmbeddedPortablePdbReaderProvider), symbolWriterProvider: typeof (EmbeddedPortablePdbWriterProvider)); + TestModule ("EmbeddedCompressedPdbTarget.exe", test, symbolReaderProvider: typeof(EmbeddedPortablePdbReaderProvider), symbolWriterProvider: typeof(EmbeddedPortablePdbWriterProvider)); } [Test] @@ -614,7 +604,7 @@ class Program } [Test] - public void PortablePdbLineInfo() + public void PortablePdbLineInfo () { TestModule ("line.exe", module => { var type = module.GetType ("Tests"); @@ -819,288 +809,5 @@ class Program } }); } - - [Test] - public void DoubleWriteAndReadWithDeterministicMvidAndVariousChanges () - { - Guid mvidIn, mvidARM64Out, mvidX64Out; - - const string resource = "mylib.dll"; - { - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - mvidIn = module.Mvid; - module.Architecture = TargetArchitecture.ARM64; // Can't use I386 as it writes different import table size -> differnt MVID - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - mvidARM64Out = module.Mvid; - } - - Assert.AreNotEqual (mvidIn, mvidARM64Out); - } - - { - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - Assert.AreEqual (mvidIn, module.Mvid); - module.Architecture = TargetArchitecture.AMD64; - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - mvidX64Out = module.Mvid; - } - - Assert.AreNotEqual (mvidARM64Out, mvidX64Out); - } - - { - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - Assert.AreEqual (mvidIn, module.Mvid); - module.Architecture = TargetArchitecture.AMD64; - module.timestamp = 42; - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - Guid mvidDifferentTimeStamp; - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - mvidDifferentTimeStamp = module.Mvid; - } - - Assert.AreNotEqual (mvidX64Out, mvidDifferentTimeStamp); - } - } - - [Test] - public void ReadPortablePdbChecksum () - { - const string resource = "PdbChecksumLib.dll"; - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - GetPdbChecksumData (module.GetDebugHeader (), out string algorithmName, out byte [] checksum); - Assert.AreEqual ("SHA256", algorithmName); - - string pdbPath = GetDebugHeaderPdbPath (module); - CalculatePdbChecksumAndId (pdbPath, out byte [] expectedChecksum, out byte [] pdbId); - - CollectionAssert.AreEqual (expectedChecksum, checksum); - } - } - - [Test] - public void ReadEmbeddedPortablePdbChecksum () - { - const string resource = "EmbeddedPdbChecksumLib.dll"; - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - var debugHeader = module.GetDebugHeader (); - GetPdbChecksumData (debugHeader, out string algorithmName, out byte [] checksum); - Assert.AreEqual ("SHA256", algorithmName); - - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); - CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out byte [] pdbId); - - CollectionAssert.AreEqual (expectedChecksum, checksum); - } - } - - [Test] - public void WritePortablePdbChecksum () - { - const string resource = "PdbChecksumLib.dll"; - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - GetPdbChecksumData (module.GetDebugHeader (), out string algorithmName, out byte [] checksum); - Assert.AreEqual ("SHA256", algorithmName); - - string pdbPath = GetDebugHeaderPdbPath (module); - CalculatePdbChecksumAndId (pdbPath, out byte [] expectedChecksum, out byte [] pdbId); - - CollectionAssert.AreEqual (expectedChecksum, checksum); - } - } - - [Test] - public void WritePortablePdbToWriteOnlyStream () - { - const string resource = "PdbChecksumLib.dll"; - string destination = Path.GetTempFileName (); - - // Note that the module stream already requires read access even on writing to be able to compute strong name - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) - using (var pdbStream = new FileStream (destination + ".pdb", FileMode.Create, FileAccess.Write)) { - module.Write (destination, new WriterParameters { - DeterministicMvid = true, - WriteSymbols = true, - SymbolWriterProvider = new PortablePdbWriterProvider (), - SymbolStream = pdbStream - }); - } - } - - [Test] - public void DoubleWritePortablePdbDeterministicPdbId () - { - const string resource = "PdbChecksumLib.dll"; - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - byte [] pdbIdOne; - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - string pdbPath = GetDebugHeaderPdbPath (module); - CalculatePdbChecksumAndId (pdbPath, out byte [] expectedChecksum, out pdbIdOne); - } - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - byte [] pdbIdTwo; - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - string pdbPath = GetDebugHeaderPdbPath (module); - CalculatePdbChecksumAndId (pdbPath, out byte [] expectedChecksum, out pdbIdTwo); - } - - CollectionAssert.AreEqual (pdbIdOne, pdbIdTwo); - } - - [Test] - public void WriteEmbeddedPortablePdbChecksum () - { - const string resource = "EmbeddedPdbChecksumLib.dll"; - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - var debugHeader = module.GetDebugHeader (); - GetPdbChecksumData (debugHeader, out string algorithmName, out byte [] checksum); - Assert.AreEqual ("SHA256", algorithmName); - - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); - CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out byte [] pdbId); - - CollectionAssert.AreEqual (expectedChecksum, checksum); - } - } - - [Test] - public void DoubleWriteEmbeddedPortablePdbChecksum () - { - const string resource = "EmbeddedPdbChecksumLib.dll"; - string destination = Path.GetTempFileName (); - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - byte [] pdbIdOne; - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - var debugHeader = module.GetDebugHeader (); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); - CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out pdbIdOne); - } - - using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { - module.Write (destination, new WriterParameters { DeterministicMvid = true, WriteSymbols = true }); - } - - byte [] pdbIdTwo; - using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { - var debugHeader = module.GetDebugHeader (); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); - CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out pdbIdTwo); - } - - CollectionAssert.AreEqual (pdbIdOne, pdbIdTwo); - } - - private void GetEmbeddedPdb (ImageDebugHeader debugHeader, out byte [] embeddedPdb) - { - var entry = Mixin.GetEmbeddedPortablePdbEntry (debugHeader); - Assert.IsNotNull (entry); - - var compressed_stream = new MemoryStream (entry.Data); - var reader = new BinaryStreamReader (compressed_stream); - Assert.AreEqual (0x4244504D, reader.ReadInt32 ()); - var length = reader.ReadInt32 (); - var decompressed_stream = new MemoryStream (length); - - using (var deflate = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) - deflate.CopyTo (decompressed_stream); - - embeddedPdb = decompressed_stream.ToArray (); - } - - private void GetPdbChecksumData (ImageDebugHeader debugHeader, out string algorithmName, out byte [] checksum) - { - var entry = Mixin.GetPdbChecksumEntry (debugHeader); - Assert.IsNotNull (entry); - - var length = Array.IndexOf (entry.Data, (byte)0, 0); - var bytes = new byte [length]; - Buffer.BlockCopy (entry.Data, 0, bytes, 0, length); - algorithmName = Encoding.UTF8.GetString (bytes); - int checksumSize = 0; - switch (algorithmName) { - case "SHA256": checksumSize = 32; break; - case "SHA384": checksumSize = 48; break; - case "SHA512": checksumSize = 64; break; - } - checksum = new byte [checksumSize]; - Buffer.BlockCopy (entry.Data, length + 1, checksum, 0, checksumSize); - } - - private void CalculatePdbChecksumAndId (string filePath, out byte [] pdbChecksum, out byte [] pdbId) - { - using (var fs = File.OpenRead (filePath)) - CalculatePdbChecksumAndId (fs, out pdbChecksum, out pdbId); - } - - private void CalculatePdbChecksumAndId (byte [] data, out byte [] pdbChecksum, out byte [] pdbId) - { - using (var pdb = new MemoryStream (data)) - CalculatePdbChecksumAndId (pdb, out pdbChecksum, out pdbId); - } - - private void CalculatePdbChecksumAndId (Stream pdbStream, out byte [] pdbChecksum, out byte [] pdbId) - { - // Get the offset of the PDB heap (this requires parsing several headers - // so it's easier to use the ImageReader directly for this) - Image image = ImageReader.ReadPortablePdb (new Disposable<Stream> (pdbStream, false), "test.pdb", out uint pdbHeapOffset); - pdbId = new byte [20]; - Array.Copy (image.PdbHeap.data, 0, pdbId, 0, 20); - - pdbStream.Seek (0, SeekOrigin.Begin); - byte [] rawBytes = pdbStream.ReadAll (); - - var bytes = new byte [rawBytes.Length]; - - Array.Copy (rawBytes, 0, bytes, 0, pdbHeapOffset); - - // Zero out the PDB ID (20 bytes) - for (int i = 0; i < 20; bytes [i + pdbHeapOffset] = 0, i++) ; - - Array.Copy (rawBytes, pdbHeapOffset + 20, bytes, pdbHeapOffset + 20, rawBytes.Length - pdbHeapOffset - 20); - - var sha256 = SHA256.Create (); - pdbChecksum = sha256.ComputeHash (bytes); - } } } diff --git a/Test/Resources/assemblies/EmbeddedPdbChecksumLib.dll b/Test/Resources/assemblies/EmbeddedPdbChecksumLib.dll Binary files differdeleted file mode 100644 index 2de939b..0000000 --- a/Test/Resources/assemblies/EmbeddedPdbChecksumLib.dll +++ /dev/null diff --git a/Test/Resources/assemblies/PdbChecksumLib.dll b/Test/Resources/assemblies/PdbChecksumLib.dll Binary files differdeleted file mode 100644 index 9c28db7..0000000 --- a/Test/Resources/assemblies/PdbChecksumLib.dll +++ /dev/null diff --git a/Test/Resources/assemblies/PdbChecksumLib.pdb b/Test/Resources/assemblies/PdbChecksumLib.pdb Binary files differdeleted file mode 100644 index 81975e7..0000000 --- a/Test/Resources/assemblies/PdbChecksumLib.pdb +++ /dev/null diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs index 9a9166b..01b6c7a 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs @@ -44,15 +44,9 @@ namespace Mono.Cecil.Pdb { public ImageDebugHeader GetDebugHeader () { - var entry_point = module.EntryPoint; - if (entry_point != null) - writer.SetUserEntryPoint (entry_point.MetadataToken.ToInt32 ()); - ImageDebugDirectory directory; var data = writer.GetDebugInfo (out directory); directory.TimeDateStamp = (int) module.timestamp; - - writer.Close (); return new ImageDebugHeader (new ImageDebugHeaderEntry (directory, data)); } @@ -261,6 +255,11 @@ namespace Mono.Cecil.Pdb { public void Dispose () { + var entry_point = module.EntryPoint; + if (entry_point != null) + writer.SetUserEntryPoint (entry_point.MetadataToken.ToInt32 ()); + + writer.Close (); } } |