Skip to content
/ cecil Public
forked from jbevain/cecil

Commit

Permalink
Revert "Fix deterministic MVID and add PdbChecksum (#31)"
Browse files Browse the repository at this point in the history
This reverts commit ff616bf.
  • Loading branch information
marek-safar committed Jan 20, 2022
1 parent 9fd4a5c commit 03aabb4
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 500 deletions.
179 changes: 52 additions & 127 deletions Mono.Cecil.Cil/PortablePdb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;

using Mono.Cecil.Metadata;
using Mono.Cecil.PE;

Expand All @@ -39,7 +39,7 @@ public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStre

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

Expand Down Expand Up @@ -234,27 +234,24 @@ public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName)
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)
{
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);
}
}

Expand All @@ -263,14 +260,9 @@ public sealed class PortablePdbWriter : ISymbolWriter {
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)
Expand All @@ -286,94 +278,56 @@ internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition modul
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 ()
{
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 ()
Expand All @@ -389,8 +343,10 @@ void CheckMethodDebugInformationTable ()

public void Dispose ()
{
writer.stream.Dispose ();
final_stream.Dispose ();
if (IsEmbedded)
return;

WritePdbFile ();
}

void WritePdbFile ()
Expand All @@ -404,18 +360,15 @@ void WritePdbFile ()
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 ());

Expand Down Expand Up @@ -446,32 +399,6 @@ void WriteTableHeap ()
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 {
Expand Down Expand Up @@ -508,14 +435,9 @@ public ISymbolReaderProvider GetReaderProvider ()
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,
Expand All @@ -540,12 +462,15 @@ public ImageDebugHeader GetDebugHeader ()

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 ()
Expand Down
6 changes: 0 additions & 6 deletions Mono.Cecil.Cil/Symbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public enum ImageDebugType {
CodeView = 2,
Deterministic = 16,
EmbeddedPortablePdb = 17,
PdbChecksum = 19,
}

public sealed class ImageDebugHeader {
Expand Down Expand Up @@ -1175,11 +1174,6 @@ public static ImageDebugHeaderEntry GetEmbeddedPortablePdbEntry (this ImageDebug
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)
Expand Down
5 changes: 1 addition & 4 deletions Mono.Cecil.PE/ImageReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ sealed class ImageReader : BinaryStreamReader {
DataDirectory metadata;

uint table_heap_offset;
uint pdb_heap_offset;

public ImageReader (Disposable<Stream> stream, string file_name)
: base (stream.value)
Expand Down Expand Up @@ -401,7 +400,6 @@ void ReadMetadataStream (Section section)
break;
case "#Pdb":
image.PdbHeap = new PdbHeap (data);
pdb_heap_offset = offset;
break;
}
}
Expand Down Expand Up @@ -770,7 +768,7 @@ public static Image ReadImage (Disposable<Stream> stream, string file_name)
}
}

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);
Expand All @@ -787,7 +785,6 @@ public static Image ReadPortablePdb (Disposable<Stream> stream, string file_name

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);
Expand Down
Loading

0 comments on commit 03aabb4

Please sign in to comment.