From 394a3cbc4dd50f12cadd525b12e329b6a0f1f030 Mon Sep 17 00:00:00 2001 From: Jb Evain Date: Thu, 29 Aug 2019 15:07:08 -0700 Subject: [PATCH] Add support for reading and writing document checksums in native pdbs --- .../ISymUnmanagedDocumentWriter.cs | 3 ++ symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs | 8 ++-- symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs | 3 ++ .../pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs | 20 ++++++-- symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs | 48 +++++++++---------- symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs | 6 ++- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs index e64ec78d1..2e8589e73 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs @@ -6,6 +6,7 @@ // Licensed under the MIT/X11 license. // +using System; using System.Runtime.InteropServices; namespace Mono.Cecil.Pdb { @@ -14,5 +15,7 @@ namespace Mono.Cecil.Pdb { [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] [ComImport] interface ISymUnmanagedDocumentWriter { + void SetSource (uint sourceSize, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 0)] byte [] source); + void SetCheckSum (Guid algorithmId, uint checkSumSize, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] checkSum); } } diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs index f3ca8b20e..2d6b1ba8c 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs @@ -352,9 +352,11 @@ Document GetDocument (PdbSource source) return document; document = new Document (name) { - Language = source.language.ToLanguage (), - LanguageVendor = source.vendor.ToVendor (), - Type = source.doctype.ToType (), + LanguageGuid = source.language, + LanguageVendorGuid = source.vendor, + TypeGuid = source.doctype, + HashAlgorithmGuid = source.checksumAlgorithm, + Hash = source.checksum, }; documents.Add (name, document); return document; diff --git a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs index a0a07476e..01b6c7a51 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs @@ -246,6 +246,9 @@ SymDocumentWriter GetDocument (Document document) document.LanguageVendorGuid, document.TypeGuid); + if (!document.Hash.IsNullOrEmpty ()) + doc_writer.SetCheckSum (document.HashAlgorithmGuid, document.Hash); + documents [document.Url] = doc_writer; return doc_writer; } diff --git a/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs index 83cea8e54..3112c80a3 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs @@ -13,16 +13,26 @@ namespace Mono.Cecil.Pdb { internal class SymDocumentWriter { - readonly ISymUnmanagedDocumentWriter m_unmanagedDocumentWriter; + readonly ISymUnmanagedDocumentWriter writer; - public SymDocumentWriter (ISymUnmanagedDocumentWriter unmanagedDocumentWriter) + public ISymUnmanagedDocumentWriter Writer { - m_unmanagedDocumentWriter = unmanagedDocumentWriter; + get { return writer; } } - public ISymUnmanagedDocumentWriter GetUnmanaged () + public SymDocumentWriter (ISymUnmanagedDocumentWriter writer) { - return m_unmanagedDocumentWriter; + this.writer = writer; + } + + public void SetSource (byte [] source) + { + writer.SetSource ((uint) source.Length, source); + } + + public void SetCheckSum (Guid hashAlgo, byte [] checkSum) + { + writer.SetCheckSum (hashAlgo, (uint) checkSum.Length, checkSum); } } } diff --git a/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs index 7006c68c7..f309f2f6c 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs @@ -28,7 +28,7 @@ static extern int CoCreateInstance ( static Guid s_symUnmangedWriterIID = new Guid("0b97726e-9e6d-4f05-9a26-424022093caa"); static Guid s_CorSymWriter_SxS_ClassID = new Guid ("108296c1-281e-11d3-bd22-0000f80849bd"); - readonly ISymUnmanagedWriter2 m_writer; + readonly ISymUnmanagedWriter2 writer; readonly Collection documents; public SymWriter () @@ -36,7 +36,7 @@ public SymWriter () object objWriter; CoCreateInstance (ref s_CorSymWriter_SxS_ClassID, null, 1, ref s_symUnmangedWriterIID, out objWriter); - m_writer = (ISymUnmanagedWriter2) objWriter; + writer = (ISymUnmanagedWriter2) objWriter; documents = new Collection (); } @@ -45,10 +45,10 @@ public byte[] GetDebugInfo (out ImageDebugDirectory idd) int size; // get size of debug info - m_writer.GetDebugInfo (out idd, 0, out size, null); + writer.GetDebugInfo (out idd, 0, out size, null); byte[] debug_info = new byte[size]; - m_writer.GetDebugInfo (out idd, size, out size, debug_info); + writer.GetDebugInfo (out idd, size, out size, debug_info); return debug_info; } @@ -63,23 +63,23 @@ public void DefineLocalVariable2 ( int startOffset, int endOffset) { - m_writer.DefineLocalVariable2 (name, (int)attributes, sigToken, 1 /* ILOffset*/, addr1, addr2, addr3, startOffset, endOffset); + writer.DefineLocalVariable2 (name, (int)attributes, sigToken, 1 /* ILOffset*/, addr1, addr2, addr3, startOffset, endOffset); } public void DefineConstant2 (string name, object value, int sigToken) { if (value == null) { - m_writer.DefineConstant2 (name, 0, sigToken); + writer.DefineConstant2 (name, 0, sigToken); return; } - m_writer.DefineConstant2 (name, value, sigToken); + writer.DefineConstant2 (name, value, sigToken); } public void Close () { - m_writer.Close (); - Marshal.ReleaseComObject (m_writer); + writer.Close (); + Marshal.ReleaseComObject (writer); foreach (var document in documents) Marshal.ReleaseComObject (document); @@ -87,69 +87,69 @@ public void Close () public void CloseMethod () { - m_writer.CloseMethod (); + writer.CloseMethod (); } public void CloseNamespace () { - m_writer.CloseNamespace (); + writer.CloseNamespace (); } public void CloseScope (int endOffset) { - m_writer.CloseScope (endOffset); + writer.CloseScope (endOffset); } public SymDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType) { - ISymUnmanagedDocumentWriter unmanagedDocumentWriter; - m_writer.DefineDocument (url, ref language, ref languageVendor, ref documentType, out unmanagedDocumentWriter); + ISymUnmanagedDocumentWriter doc_writer; + writer.DefineDocument (url, ref language, ref languageVendor, ref documentType, out doc_writer); - documents.Add (unmanagedDocumentWriter); - return new SymDocumentWriter (unmanagedDocumentWriter); + documents.Add (doc_writer); + return new SymDocumentWriter (doc_writer); } public void DefineSequencePoints (SymDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { - m_writer.DefineSequencePoints (document.GetUnmanaged(), offsets.Length, offsets, lines, columns, endLines, endColumns); + writer.DefineSequencePoints (document.Writer, offsets.Length, offsets, lines, columns, endLines, endColumns); } public void Initialize (object emitter, string filename, bool fFullBuild) { - m_writer.Initialize (emitter, filename, null, fFullBuild); + writer.Initialize (emitter, filename, null, fFullBuild); } public void SetUserEntryPoint (int methodToken) { - m_writer.SetUserEntryPoint (methodToken); + writer.SetUserEntryPoint (methodToken); } public void OpenMethod (int methodToken) { - m_writer.OpenMethod (methodToken); + writer.OpenMethod (methodToken); } public void OpenNamespace (string name) { - m_writer.OpenNamespace (name); + writer.OpenNamespace (name); } public int OpenScope (int startOffset) { int result; - m_writer.OpenScope (startOffset, out result); + writer.OpenScope (startOffset, out result); return result; } public void UsingNamespace (string fullName) { - m_writer.UsingNamespace (fullName); + writer.UsingNamespace (fullName); } public void DefineCustomMetadata (string name, byte [] metadata) { var handle = GCHandle.Alloc (metadata, GCHandleType.Pinned); - m_writer.SetSymAttribute (0, name, (uint) metadata.Length, handle.AddrOfPinnedObject ()); + writer.SetSymAttribute (0, name, (uint) metadata.Length, handle.AddrOfPinnedObject ()); handle.Free (); } } diff --git a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs index 2269cb5c9..797f68059 100644 --- a/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs +++ b/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs @@ -99,7 +99,8 @@ public void Document () Assert.AreEqual (@"c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs", document.Url); Assert.AreEqual (DocumentType.Text, document.Type); - Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentHashAlgorithm.MD5, document.HashAlgorithm); + Assert.AreEqual (new byte [] { 228, 176, 152, 54, 82, 238, 238, 68, 237, 156, 5, 142, 118, 160, 118, 245 }, document.Hash); Assert.AreEqual (DocumentLanguage.CSharp, document.Language); Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); @@ -119,7 +120,8 @@ public void BasicDocument () Assert.AreEqual (@"c:\tmp\VBConsApp\Program.vb", document.Url); Assert.AreEqual (DocumentType.Text, document.Type); - Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentHashAlgorithm.MD5, document.HashAlgorithm); + Assert.AreEqual (new byte [] { 184, 188, 100, 23, 27, 123, 187, 201, 175, 206, 110, 198, 242, 139, 154, 119 }, document.Hash); Assert.AreEqual (DocumentLanguage.Basic, document.Language); Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider));