Browse Source

Ignore document checksum and blob length in PdbGenerationTestRunner

pull/1440/head
Siegfried Pammer 6 years ago
parent
commit
b4c376d195
  1. 2
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  2. 45
      ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs
  3. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore
  4. 23
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml
  5. 34
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

2
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -356,7 +356,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
List<SyntaxTree> syntaxTrees = new List<SyntaxTree>(); List<SyntaxTree> syntaxTrees = new List<SyntaxTree>();
foreach (KeyValuePair<string, string> file in sourceFiles) { foreach (KeyValuePair<string, string> file in sourceFiles) {
var sourceText = SourceText.From(file.Value, Encoding.UTF8); var sourceText = SourceText.From(file.Value, new UTF8Encoding(false), SourceHashAlgorithm.Sha256);
syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key)); syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key));
embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText)); embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText));
} }

45
ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
@ -22,7 +23,8 @@ namespace ICSharpCode.Decompiler.Tests
{ {
static readonly string TestCasePath = Tester.TestCasePath + "/PdbGen"; static readonly string TestCasePath = Tester.TestCasePath + "/PdbGen";
[Test, Ignore("Needs adjustments in generator")] [Test]
[Ignore("Needs adjustments in generator")]
public void HelloWorld() public void HelloWorld()
{ {
TestGeneratePdb(); TestGeneratePdb();
@ -44,11 +46,46 @@ namespace ICSharpCode.Decompiler.Tests
var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream); pdbStream.SetLength(0);
PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true);
pdbStream.Position = 0; pdbStream.Position = 0;
string resultFile = PdbToXmlConverter.ToXml(pdbStream, moduleDefinition.Reader.GetEntireImage().GetContent().ToArray(), options); using (Stream peStream = File.OpenRead(peFileName))
Assert.AreEqual(xmlContent, resultFile); using (Stream expectedPdbStream = File.OpenRead(pdbFileName)) {
using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8)) {
PdbToXmlConverter.ToXml(writer, expectedPdbStream, peStream, options);
}
peStream.Position = 0;
using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8)) {
PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options);
}
}
} }
ProcessXmlFile(Path.ChangeExtension(pdbFileName, ".xml"));
ProcessXmlFile(Path.ChangeExtension(xmlFile, ".generated.xml"));
Assert.AreEqual(File.ReadAllText(xmlFile), File.ReadAllText(Path.ChangeExtension(xmlFile, ".generated.xml")));
} }
private void ProcessXmlFile(string v)
{
var document = XDocument.Load(v);
foreach (var file in document.Descendants("file")) {
file.Attribute("checksum").Remove();
file.Attribute("embeddedSourceLength").Remove();
file.ReplaceNodes(new XCData(file.Value.Replace("\uFEFF", "")));
}
document.Save(v, SaveOptions.None);
}
}
class StringWriterWithEncoding : StringWriter
{
readonly Encoding encoding;
public StringWriterWithEncoding(Encoding encoding)
{
this.encoding = encoding ?? throw new ArgumentNullException("encoding");
}
public override Encoding Encoding => encoding;
} }
} }

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/.gitignore vendored

@ -1,2 +1,4 @@
/*.dll /*.dll
/*.pdb /*.pdb
/*.expected.xml
/*.generated.xml

23
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml

@ -1,33 +1,38 @@
<?xml version="1.0" encoding="utf-16"?> <?xml version="1.0" encoding="utf-8"?>
<symbols> <symbols>
<files> <files>
<file id="1" name="HelloWorld.cs" language="C#" checksumAlgorithm="SHA1" checksum="80-99-0D-B3-EA-B0-A3-72-39-A0-C5-FB-17-13-1B-CC-BF-3D-4C-AA" embeddedSourceLength="200"><![CDATA[using System; <file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{ {
public class HelloWorld public class HelloWorld
{ {
public static void Hello() public static void Main(string[] args)
{ {
Console.ReadKey();
Console.WriteLine("Hello World!"); Console.WriteLine("Hello World!");
Console.ReadKey();
} }
} }
} }
]]></file> ]]></file>
</files> </files>
<methods> <methods>
<method containingType="ICSharpCode.Decompiler.Tests.TestCases.PdbGen.HelloWorld" name="Hello" token="0x6000001"> <method containingType="ICSharpCode.Decompiler.Tests.TestCases.PdbGen.HelloWorld" name="Main" parameterNames="args" token="0x6000001">
<sequencePoints> <sequencePoints>
<entry offset="0x0" startLine="8" startColumn="3" endLine="8" endColumn="4" document="1" /> <entry offset="0x0" startLine="8" startColumn="3" endLine="8" endColumn="4" document="1" />
<entry offset="0x1" startLine="9" startColumn="4" endLine="9" endColumn="38" document="1" /> <entry offset="0x1" startLine="9" startColumn="4" endLine="9" endColumn="22" document="1" />
<entry offset="0xc" startLine="10" startColumn="3" endLine="10" endColumn="4" document="1" /> <entry offset="0x7" startLine="10" startColumn="4" endLine="10" endColumn="38" document="1" />
<entry offset="0x12" startLine="11" startColumn="4" endLine="11" endColumn="22" document="1" />
<entry offset="0x18" startLine="12" startColumn="3" endLine="12" endColumn="4" document="1" />
</sequencePoints> </sequencePoints>
<scope startOffset="0x0" endOffset="0xd" /> <scope startOffset="0x0" endOffset="0x19" />
</method> </method>
</methods> </methods>
<method-spans> <method-spans>
<method declaringType="ICSharpCode.Decompiler.Tests.TestCases.PdbGen.HelloWorld" methodName="Hello" token="0x6000001"> <method declaringType="ICSharpCode.Decompiler.Tests.TestCases.PdbGen.HelloWorld" methodName="Main" parameterNames="args" token="0x6000001">
<document startLine="8" endLine="10" /> <document startLine="8" endLine="12" />
</method> </method>
</method-spans> </method-spans>
</symbols> </symbols>

34
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
@ -47,19 +48,19 @@ namespace ICSharpCode.Decompiler.DebugInfo
public static readonly Guid HashAlgorithmSHA1 = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460"); public static readonly Guid HashAlgorithmSHA1 = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460");
public static readonly Guid HashAlgorithmSHA256 = new Guid("8829d00f-11b8-4213-878b-770e8597ac16"); public static readonly Guid HashAlgorithmSHA256 = new Guid("8829d00f-11b8-4213-878b-770e8597ac16");
static readonly FileVersionInfo decompilerVersion = FileVersionInfo.GetVersionInfo(typeof(CSharpDecompiler).Assembly.Location); static readonly FileVersionInfo decompilerVersion = FileVersionInfo.GetVersionInfo(typeof(CSharpDecompiler).Assembly.Location);
static readonly SHA256 hasher = SHA256.Create();
public static bool HasCodeViewDebugDirectoryEntry(PEFile file) public static bool HasCodeViewDebugDirectoryEntry(PEFile file)
{ {
return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView);
} }
public static void WritePdb(PEFile file, CSharpDecompiler decompiler, DecompilerSettings settings, Stream targetStream) public static void WritePdb(PEFile file, CSharpDecompiler decompiler, DecompilerSettings settings, Stream targetStream, bool noLogo = false)
{ {
MetadataBuilder metadata = new MetadataBuilder(); MetadataBuilder metadata = new MetadataBuilder();
MetadataReader reader = file.Metadata; MetadataReader reader = file.Metadata;
var entrypointHandle = MetadataTokens.MethodDefinitionHandle(file.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); var entrypointHandle = MetadataTokens.MethodDefinitionHandle(file.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress);
var hasher = SHA256.Create();
var sequencePointBlobs = new Dictionary<MethodDefinitionHandle, (DocumentHandle Document, BlobHandle SequencePoints)>(); var sequencePointBlobs = new Dictionary<MethodDefinitionHandle, (DocumentHandle Document, BlobHandle SequencePoints)>();
var emptyList = new List<SequencePoint>(); var emptyList = new List<SequencePoint>();
var globalImportScope = metadata.AddImportScope(default, default); var globalImportScope = metadata.AddImportScope(default, default);
@ -67,13 +68,18 @@ namespace ICSharpCode.Decompiler.DebugInfo
foreach (var handle in reader.GetTopLevelTypeDefinitions()) { foreach (var handle in reader.GetTopLevelTypeDefinitions()) {
var type = reader.GetTypeDefinition(handle); var type = reader.GetTypeDefinition(handle);
// Generate syntax tree, source and checksum // Generate syntax tree
var name = metadata.GetOrAddDocumentName(type.GetFullTypeName(reader).ReflectionName.Replace('.', Path.DirectorySeparatorChar) + ".cs");
var syntaxTree = decompiler.DecompileTypes(new[] { handle }); var syntaxTree = decompiler.DecompileTypes(new[] { handle });
syntaxTree.InsertChildAfter(null, new Comment(" PDB and source generated by ICSharpCode.Decompiler " + decompilerVersion.FileVersion), Roles.Comment); if (!syntaxTree.HasChildren)
continue;
// Generate source and checksum
var name = metadata.GetOrAddDocumentName(type.GetFullTypeName(reader).ReflectionName.Replace('.', Path.DirectorySeparatorChar) + ".cs");
if (!noLogo)
syntaxTree.InsertChildAfter(null, new Comment(" PDB and source generated by ICSharpCode.Decompiler " + decompilerVersion.FileVersion), Roles.Comment);
var sourceText = SyntaxTreeToString(syntaxTree, settings); var sourceText = SyntaxTreeToString(syntaxTree, settings);
var sourceCheckSum = hasher.ComputeHash(Encoding.UTF8.GetBytes(sourceText)); var sourceBlob = WriteSourceToBlob(metadata, sourceText, out var sourceCheckSum);
var sourceBlob = WriteSourceToBlob(metadata, sourceText);
// Create Document(Handle) // Create Document(Handle)
var document = metadata.AddDocument(name, var document = metadata.AddDocument(name,
@ -143,11 +149,19 @@ namespace ICSharpCode.Decompiler.DebugInfo
} }
} }
static BlobHandle WriteSourceToBlob(MetadataBuilder metadata, string sourceText) static BlobHandle WriteSourceToBlob(MetadataBuilder metadata, string sourceText, out byte[] sourceCheckSum)
{ {
var builder = new BlobBuilder(); var builder = new BlobBuilder();
builder.WriteInt32(0); // uncompressed using (var memory = new MemoryStream()) {
builder.WriteUTF8(sourceText); var deflate = new DeflateStream(memory, CompressionLevel.Optimal, leaveOpen: true);
byte[] bytes = Encoding.UTF8.GetBytes(sourceText);
deflate.Write(bytes, 0, bytes.Length);
deflate.Close();
byte[] buffer = memory.ToArray();
builder.WriteInt32(bytes.Length); // compressed
builder.WriteBytes(buffer);
sourceCheckSum = hasher.ComputeHash(bytes);
}
return metadata.GetOrAddBlob(builder); return metadata.GetOrAddBlob(builder);
} }

Loading…
Cancel
Save