Browse Source

Add IDebugInfoProvider implementations to ILSpy

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
ce894c4ad4
  1. 2
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  2. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 9
      ICSharpCode.Decompiler/Metadata/Dom.cs
  4. 47
      ICSharpCode.Decompiler/Metadata/SequencePoint.cs
  5. 155
      ILSpy/DebugInfo/DiaSymNativeDebugInfoProvider.cs
  6. 82
      ILSpy/DebugInfo/PortableDebugInfoProvider.cs
  7. 4
      ILSpy/ILSpy.csproj
  8. 36
      ILSpy/LoadedAssembly.cs
  9. BIN
      ILSpy/packages.config

2
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -269,7 +269,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -269,7 +269,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (sp.IsHidden) {
output.WriteLine("hidden");
} else {
output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.Document.Url}");
output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.DocumentUrl}");
}
nextSequencePointIndex++;
}

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -82,7 +82,7 @@ namespace ICSharpCode.Decompiler.IL @@ -82,7 +82,7 @@ namespace ICSharpCode.Decompiler.IL
this.methodSignature = methodDefinition.DecodeSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
this.body = body;
this.reader = body.GetILReader();
//this.debugInfo = metadata.GetMethodDebugInformation(method.Handle.ToDebugInformationHandle());
this.debugInfo = module.DebugInfo;
this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();

9
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -70,7 +70,10 @@ namespace ICSharpCode.Decompiler.Metadata @@ -70,7 +70,10 @@ namespace ICSharpCode.Decompiler.Metadata
EntityHandle Handle { get; }
}
public struct Variable { }
public struct Variable
{
public string Name { get; set; }
}
public interface IDebugInfoProvider
{
@ -530,12 +533,12 @@ namespace ICSharpCode.Decompiler.Metadata @@ -530,12 +533,12 @@ namespace ICSharpCode.Decompiler.Metadata
public IList<SequencePoint> GetSequencePoints()
{
return Module.DebugInfo?.GetSequencePoints(Handle);
return Module.DebugInfo?.GetSequencePoints(Handle) ?? EmptyList<SequencePoint>.Instance;
}
public IList<Variable> GetVariables()
{
return Module.DebugInfo?.GetVariables(Handle);
return Module.DebugInfo?.GetVariables(Handle) ?? EmptyList<Variable>.Instance;
}
}

47
ICSharpCode.Decompiler/Metadata/SequencePoint.cs

@ -37,56 +37,11 @@ namespace ICSharpCode.Decompiler.Metadata @@ -37,56 +37,11 @@ namespace ICSharpCode.Decompiler.Metadata
get { return StartLine == 0xfeefee && StartLine == EndLine; }
}
public Document Document { get; set; }
public string DocumentUrl { get; set; }
internal void SetHidden()
{
StartLine = EndLine = 0xfeefee;
}
}
public struct Document : IEquatable<Document>
{
public PEFile Module { get; }
public DocumentHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public Document(PEFile module, DocumentHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
SRMDocument This() => Module.GetMetadataReader().GetDocument(Handle);
public bool Equals(Document other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is Document md)
return Equals(md);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(Document lhs, Document rhs) => lhs.Equals(rhs);
public static bool operator !=(Document lhs, Document rhs) => !lhs.Equals(rhs);
public string Url {
get {
if (Handle.IsNil)
return null;
var h = This().Name;
if (h.IsNil) return null;
return Module.GetMetadataReader().GetString(h);
}
}
}
}

155
ILSpy/DebugInfo/DiaSymNativeDebugInfoProvider.cs

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using Microsoft.DiaSymReader;
namespace ICSharpCode.ILSpy.DebugInfo
{
class DiaSymNativeDebugInfoProvider : IDebugInfoProvider, ISymReaderMetadataProvider
{
PEFile module;
string pdbFileName;
Stream stream;
MetadataReader metadata;
ISymUnmanagedReader5 reader;
public DiaSymNativeDebugInfoProvider(PEFile module, string pdbFileName, Stream stream)
{
this.module = module;
this.pdbFileName = pdbFileName;
this.stream = stream;
this.metadata = module.GetMetadataReader();
this.reader = SymUnmanagedReaderFactory.CreateReader<ISymUnmanagedReader5>(stream, this);
}
public IList<Decompiler.Metadata.SequencePoint> GetSequencePoints(MethodDefinitionHandle handle)
{
var method = reader.GetMethod(MetadataTokens.GetToken(handle));
if (method.GetSequencePointCount(out int count) != 0)
return Empty<Decompiler.Metadata.SequencePoint>.Array;
var sequencePoints = new Decompiler.Metadata.SequencePoint[count];
var points = method.GetSequencePoints();
int i = 0;
var buffer = new char[1024];
foreach (var point in points) {
string url;
if (point.Document.GetUrl(buffer.Length, out int length, buffer) == 0) {
url = new string(buffer, 0, length - 1);
} else {
url = "";
}
sequencePoints[i] = new Decompiler.Metadata.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,
EndLine = point.EndLine,
EndColumn = point.EndColumn,
DocumentUrl = url
};
i++;
}
return sequencePoints;
}
public IList<Variable> GetVariables(MethodDefinitionHandle handle)
{
var method = reader.GetMethod(MetadataTokens.GetToken(handle));
var scopes = new Queue<ISymUnmanagedScope>(new[] { method.GetRootScope() });
var variables = new List<Variable>();
while (scopes.Count > 0) {
var scope = scopes.Dequeue();
foreach (var local in scope.GetLocals()) {
variables.Add(new Variable() { Name = local.GetName() });
}
foreach (var s in scope.GetChildren())
scopes.Enqueue(s);
}
return variables;
}
public bool TryGetName(MethodDefinitionHandle handle, int index, out string name)
{
var method = reader.GetMethod(MetadataTokens.GetToken(handle));
var scopes = new Queue<ISymUnmanagedScope>(new[] { method.GetRootScope() });
name = null;
while (scopes.Count > 0) {
var scope = scopes.Dequeue();
foreach (var local in scope.GetLocals()) {
if (local.GetSlot() == index) {
name = local.GetName();
return true;
}
}
foreach (var s in scope.GetChildren())
scopes.Enqueue(s);
}
return false;
}
unsafe bool ISymReaderMetadataProvider.TryGetStandaloneSignature(int standaloneSignatureToken, out byte* signature, out int length)
{
var handle = (StandaloneSignatureHandle)MetadataTokens.Handle(standaloneSignatureToken);
if (handle.IsNil) {
signature = null;
length = 0;
return false;
}
var sig = metadata.GetStandaloneSignature(handle);
var blob = metadata.GetBlobReader(sig.Signature);
signature = blob.StartPointer;
length = blob.Length;
return true;
}
bool ISymReaderMetadataProvider.TryGetTypeDefinitionInfo(int typeDefinitionToken, out string namespaceName, out string typeName, out TypeAttributes attributes)
{
var handle = (TypeDefinitionHandle)MetadataTokens.Handle(typeDefinitionToken);
if (handle.IsNil) {
namespaceName = null;
typeName = null;
attributes = 0;
return false;
}
var typeDefinition = metadata.GetTypeDefinition(handle);
namespaceName = metadata.GetString(typeDefinition.Namespace);
typeName = metadata.GetString(typeDefinition.Name);
attributes = typeDefinition.Attributes;
return true;
}
bool ISymReaderMetadataProvider.TryGetTypeReferenceInfo(int typeReferenceToken, out string namespaceName, out string typeName)
{
var handle = (TypeReferenceHandle)MetadataTokens.Handle(typeReferenceToken);
if (handle.IsNil) {
namespaceName = null;
typeName = null;
return false;
}
var typeReference = metadata.GetTypeReference(handle);
namespaceName = metadata.GetString(typeReference.Namespace);
typeName = metadata.GetString(typeReference.Name);
return true;
}
}
}

82
ILSpy/DebugInfo/PortableDebugInfoProvider.cs

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.DebugInfo
{
class PortableDebugInfoProvider : IDebugInfoProvider
{
string pdbFileName;
MetadataReaderProvider provider;
public PortableDebugInfoProvider(string pdbFileName, MetadataReaderProvider provider)
{
this.pdbFileName = pdbFileName;
this.provider = provider;
}
public IList<Decompiler.Metadata.SequencePoint> GetSequencePoints(MethodDefinitionHandle method)
{
var metadata = provider.GetMetadataReader();
var debugInfo = metadata.GetMethodDebugInformation(method);
var sequencePoints = new List<Decompiler.Metadata.SequencePoint>();
foreach (var point in debugInfo.GetSequencePoints()) {
string documentFileName;
if (!point.Document.IsNil) {
var document = metadata.GetDocument(point.Document);
documentFileName = metadata.GetString(document.Name);
} else {
documentFileName = "";
}
sequencePoints.Add(new Decompiler.Metadata.SequencePoint() {
Offset = point.Offset,
StartLine = point.StartLine,
StartColumn = point.StartColumn,
EndLine = point.EndLine,
EndColumn = point.EndColumn,
DocumentUrl = documentFileName
});
}
return sequencePoints;
}
public IList<Variable> GetVariables(MethodDefinitionHandle method)
{
var metadata = provider.GetMetadataReader();
var variables = new List<Variable>();
foreach (var h in metadata.GetLocalScopes(method)) {
var scope = metadata.GetLocalScope(h);
foreach (var v in scope.GetLocalVariables()) {
var var = metadata.GetLocalVariable(v);
variables.Add(new Variable { Name = metadata.GetString(var.Name) });
}
}
return variables;
}
public bool TryGetName(MethodDefinitionHandle method, int index, out string name)
{
var metadata = provider.GetMetadataReader();
name = null;
foreach (var h in metadata.GetLocalScopes(method)) {
var scope = metadata.GetLocalScope(h);
foreach (var v in scope.GetLocalVariables()) {
var var = metadata.GetLocalVariable(v);
if (var.Index == index) {
name = metadata.GetString(var.Name);
return true;
}
}
}
return false;
}
}
}

4
ILSpy/ILSpy.csproj

@ -50,7 +50,9 @@ @@ -50,7 +50,9 @@
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="5.0.4" />
<PackageReference Include="Microsoft.DiaSymReader.Native" Version="1.7.0" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.5.23" />
<PackageReference Include="Microsoft.DiaSymReader" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
@ -102,6 +104,8 @@ @@ -102,6 +104,8 @@
<Compile Include="CreateListDialog.xaml.cs">
<DependentUpon>CreateListDialog.xaml</DependentUpon>
</Compile>
<Compile Include="DebugInfo\DiaSymNativeDebugInfoProvider.cs" />
<Compile Include="DebugInfo\PortableDebugInfoProvider.cs" />
<Compile Include="DebugSteps.xaml.cs">
<DependentUpon>DebugSteps.xaml</DependentUpon>
</Compile>

36
ILSpy/LoadedAssembly.cs

@ -19,11 +19,13 @@ @@ -19,11 +19,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.DebugInfo;
using ICSharpCode.ILSpy.Options;
using static System.Reflection.Metadata.PEReaderExtensions;
@ -144,28 +146,28 @@ namespace ICSharpCode.ILSpy @@ -144,28 +146,28 @@ namespace ICSharpCode.ILSpy
private void LoadSymbols(PEFile module)
{
/*string pdbDirectory = Path.GetDirectoryName(fileName);
if (!reader.TryOpenAssociatedPortablePdb(pdbDirectory, OpenStream, out var provider, out var pdbFileName) {
return;
}
// search for pdb in same directory as dll
string pdbName = Path.Combine(, Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbName)) {
using (Stream s = File.OpenRead(pdbName)) {
module.ReadSymbols(new Mono.Cecil.Pdb.PdbReaderProvider().GetSymbolReader(module, s));
string pdbDirectory = Path.GetDirectoryName(fileName);
var reader = module.Reader;
// try to open portable pdb file/embedded pdb info:
if (reader.TryOpenAssociatedPortablePdb(pdbDirectory, OpenStream, out var provider, out var pdbFileName)) {
module.DebugInfo = new PortableDebugInfoProvider(pdbFileName, provider);
} else {
// search for pdb in same directory as dll
pdbFileName = Path.Combine(pdbDirectory, Path.GetFileNameWithoutExtension(fileName) + ".pdb");
if (File.Exists(pdbFileName)) {
module.DebugInfo = new DiaSymNativeDebugInfoProvider(module, pdbFileName, File.OpenRead(pdbFileName));
return;
}
return;
// TODO: use symbol cache, get symbols from microsoft
}
// TODO: use symbol cache, get symbols from microsoft
Stream OpenStream(string pdbFileName)
Stream OpenStream(string fileName)
{
}*/
return File.OpenRead(fileName);
}
}
[ThreadStatic]
static int assemblyLoadDisableCount;

BIN
ILSpy/packages.config

Binary file not shown.
Loading…
Cancel
Save