Browse Source

Merge pull request #2678 from andrewcrawley/custom-pdb-id

pull/2693/head
Siegfried Pammer 3 years ago committed by GitHub
parent
commit
ca9c288dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 47
      ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs
  3. 19
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/CustomPdbId.xml
  4. 14
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -307,6 +307,7 @@ @@ -307,6 +307,7 @@
<ItemGroup>
<Content Include="TestCases\PdbGen\ForLoopTests.xml" />
<Content Include="TestCases\PdbGen\CustomPdbId.xml" />
<Content Include="TestCases\PdbGen\HelloWorld.xml" />
<Content Include="TestCases\PdbGen\LambdaCapturing.xml" />
</ItemGroup>

47
ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Text;
@ -46,18 +47,38 @@ namespace ICSharpCode.Decompiler.Tests @@ -46,18 +47,38 @@ namespace ICSharpCode.Decompiler.Tests
TestGeneratePdb();
}
[Test]
public void CustomPdbId()
{
// Generate a PDB for an assembly using a randomly-generated ID, then validate that the PDB uses the specified ID
(string peFileName, string pdbFileName) = CompileTestCase(nameof(CustomPdbId));
var moduleDefinition = new PEFile(peFileName);
var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Metadata.DetectTargetFrameworkId(), null, PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
var expectedPdbId = new BlobContentId(Guid.NewGuid(), (uint)Random.Shared.Next());
using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, nameof(CustomPdbId) + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
pdbStream.SetLength(0);
PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true, pdbId: expectedPdbId);
pdbStream.Position = 0;
var metadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader();
var generatedPdbId = new BlobContentId(metadataReader.DebugMetadataHeader.Id);
Assert.AreEqual(expectedPdbId.Guid, generatedPdbId.Guid);
Assert.AreEqual(expectedPdbId.Stamp, generatedPdbId.Stamp);
}
}
private void TestGeneratePdb([CallerMemberName] string testName = null)
{
const PdbToXmlOptions options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.IncludeTokens | PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.IncludeMethodSpans;
string xmlFile = Path.Combine(TestCasePath, testName + ".xml");
string xmlContent = File.ReadAllText(xmlFile);
XDocument document = XDocument.Parse(xmlContent);
var files = document.Descendants("file").ToDictionary(f => f.Attribute("name").Value, f => f.Value);
Tester.CompileCSharpWithPdb(Path.Combine(TestCasePath, testName + ".expected"), files);
(string peFileName, string pdbFileName) = CompileTestCase(testName);
string peFileName = Path.Combine(TestCasePath, testName + ".expected.dll");
string pdbFileName = Path.Combine(TestCasePath, testName + ".expected.pdb");
var moduleDefinition = new PEFile(peFileName);
var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Metadata.DetectTargetFrameworkId(), null, PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
@ -87,6 +108,20 @@ namespace ICSharpCode.Decompiler.Tests @@ -87,6 +108,20 @@ namespace ICSharpCode.Decompiler.Tests
Assert.AreEqual(Normalize(expectedFileName), Normalize(generatedFileName));
}
private (string peFileName, string pdbFileName) CompileTestCase(string testName)
{
string xmlFile = Path.Combine(TestCasePath, testName + ".xml");
string xmlContent = File.ReadAllText(xmlFile);
XDocument document = XDocument.Parse(xmlContent);
var files = document.Descendants("file").ToDictionary(f => f.Attribute("name").Value, f => f.Value);
Tester.CompileCSharpWithPdb(Path.Combine(TestCasePath, testName + ".expected"), files);
string peFileName = Path.Combine(TestCasePath, testName + ".expected.dll");
string pdbFileName = Path.Combine(TestCasePath, testName + ".expected.pdb");
return (peFileName, pdbFileName);
}
private void ProcessXmlFile(string fileName)
{
var document = XDocument.Load(fileName);

19
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/CustomPdbId.xml

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen;
public class HelloWorld
{
public static void Main(string[] args)
{
Console.ReadKey();
Console.WriteLine("Hello World!");
Console.ReadKey();
}
}
]]></file>
</files>
</symbols>

14
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView);
}
public static void WritePdb(PEFile file, CSharpDecompiler decompiler, DecompilerSettings settings, Stream targetStream, bool noLogo = false)
public static void WritePdb(PEFile file, CSharpDecompiler decompiler, DecompilerSettings settings, Stream targetStream, bool noLogo = false, BlobContentId? pdbId = null)
{
MetadataBuilder metadata = new MetadataBuilder();
MetadataReader reader = file.Metadata;
@ -195,10 +195,14 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -195,10 +195,14 @@ namespace ICSharpCode.Decompiler.DebugInfo
metadata.AddCustomDebugInformation(row.Parent, row.Guid, row.Blob);
}
var debugDir = file.Reader.ReadDebugDirectory().FirstOrDefault(dir => dir.Type == DebugDirectoryEntryType.CodeView);
var portable = file.Reader.ReadCodeViewDebugDirectoryData(debugDir);
var contentId = new BlobContentId(portable.Guid, debugDir.Stamp);
PortablePdbBuilder serializer = new PortablePdbBuilder(metadata, GetRowCounts(reader), entrypointHandle, blobs => contentId);
if (pdbId == null)
{
var debugDir = file.Reader.ReadDebugDirectory().FirstOrDefault(dir => dir.Type == DebugDirectoryEntryType.CodeView);
var portable = file.Reader.ReadCodeViewDebugDirectoryData(debugDir);
pdbId = new BlobContentId(portable.Guid, debugDir.Stamp);
}
PortablePdbBuilder serializer = new PortablePdbBuilder(metadata, GetRowCounts(reader), entrypointHandle, blobs => pdbId.Value);
BlobBuilder blobBuilder = new BlobBuilder();
serializer.Serialize(blobBuilder);
blobBuilder.WriteContentTo(targetStream);

Loading…
Cancel
Save