Browse Source

Add Debug Metadata Explorer

pull/1930/head
Siegfried Pammer 5 years ago
parent
commit
2efca22fae
  1. 25
      ICSharpCode.Decompiler/DebugInfo/KnownGuids.cs
  2. 15
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 27
      ICSharpCode.Decompiler/Metadata/Dom.cs
  5. 13
      ILSpy/DebugInfo/PortableDebugInfoProvider.cs
  6. 33
      ILSpy/ILSpy.csproj
  7. 79
      ILSpy/Metadata/DebugMetadataTreeNode.cs
  8. 161
      ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
  9. 149
      ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
  10. 109
      ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
  11. 108
      ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
  12. 129
      ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
  13. 110
      ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
  14. 150
      ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
  15. 141
      ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
  16. 11
      ILSpy/Metadata/MetadataTableTreeNode.cs
  17. 4
      ILSpy/TreeNodes/AssemblyTreeNode.cs

25
ICSharpCode.Decompiler/DebugInfo/KnownGuids.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.Decompiler.DebugInfo
{
public static class KnownGuids
{
public static readonly Guid CSharpLanguageGuid = new Guid("3f5162f8-07c6-11d3-9053-00c04fa302a1");
public static readonly Guid VBLanguageGuid = new Guid("3a12d0b8-c26c-11d0-b442-00a0244a1dd2");
public static readonly Guid FSharpLanguageGuid = new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3");
public static readonly Guid StateMachineHoistedLocalScopes = new Guid("6DA9A61E-F8C7-4874-BE62-68BC5630DF71");
public static readonly Guid DynamicLocalVariables = new Guid("83C563C4-B4F3-47D5-B824-BA5441477EA8");
public static readonly Guid DefaultNamespaces = new Guid("58b2eab6-209f-4e4e-a22c-b2d0f910c782");
public static readonly Guid EditAndContinueLocalSlotMap = new Guid("755F52A8-91C5-45BE-B4B8-209571E552BD");
public static readonly Guid EditAndContinueLambdaAndClosureMap = new Guid("A643004C-0240-496F-A783-30D64F4979DE");
public static readonly Guid EmbeddedSource = new Guid("0e8a571b-6926-466e-b4ad-8ab04611f5fe");
public static readonly Guid SourceLink = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A");
public static readonly Guid MethodSteppingInformation = new Guid("54FD2AC5-E925-401A-9C2A-F94F171072F8");
public static readonly Guid HashAlgorithmSHA1 = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460");
public static readonly Guid HashAlgorithmSHA256 = new Guid("8829d00f-11b8-4213-878b-770e8597ac16");
}
}

15
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -41,13 +41,6 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -41,13 +41,6 @@ namespace ICSharpCode.Decompiler.DebugInfo
{
public class PortablePdbWriter
{
static readonly Guid CSharpLanguageGuid = new Guid("3f5162f8-07c6-11d3-9053-00c04fa302a1");
static readonly Guid DebugInfoEmbeddedSource = new Guid("0e8a571b-6926-466e-b4ad-8ab04611f5fe");
static readonly Guid MethodSteppingInformationBlobId = new Guid("54FD2AC5-E925-401A-9C2A-F94F171072F8");
static readonly Guid HashAlgorithmSHA1 = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460");
static readonly Guid HashAlgorithmSHA256 = new Guid("8829d00f-11b8-4213-878b-770e8597ac16");
static readonly FileVersionInfo decompilerVersion = FileVersionInfo.GetVersionInfo(typeof(CSharpDecompiler).Assembly.Location);
public static bool HasCodeViewDebugDirectoryEntry(PEFile file)
@ -95,13 +88,13 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -95,13 +88,13 @@ namespace ICSharpCode.Decompiler.DebugInfo
// Create Document(Handle)
var document = metadata.AddDocument(name,
hashAlgorithm: metadata.GetOrAddGuid(HashAlgorithmSHA256),
hashAlgorithm: metadata.GetOrAddGuid(KnownGuids.HashAlgorithmSHA256),
hash: metadata.GetOrAddBlob(sourceCheckSum),
language: metadata.GetOrAddGuid(CSharpLanguageGuid));
language: metadata.GetOrAddGuid(KnownGuids.CSharpLanguageGuid));
// Add embedded source to the PDB
customDocumentDebugInfo.Add((document,
metadata.GetOrAddGuid(DebugInfoEmbeddedSource),
metadata.GetOrAddGuid(KnownGuids.EmbeddedSource),
sourceBlob));
debugInfoGen.GenerateImportScopes(metadata, globalImportScope);
@ -121,7 +114,7 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -121,7 +114,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
}
if (function.IsAsync) {
customMethodDebugInfo.Add((methodHandle,
metadata.GetOrAddGuid(MethodSteppingInformationBlobId),
metadata.GetOrAddGuid(KnownGuids.MethodSteppingInformation),
metadata.GetOrAddBlob(function.AsyncDebugInfo.BuildBlob(methodHandle))));
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -63,6 +63,7 @@ @@ -63,6 +63,7 @@
<Compile Include="CSharp\CSharpLanguageVersion.cs" />
<Compile Include="CSharp\RequiredNamespaceCollector.cs" />
<Compile Include="CSharp\SequencePointBuilder.cs" />
<Compile Include="DebugInfo\KnownGuids.cs" />
<Compile Include="Disassembler\DisassemblerSignatureTypeProvider.cs" />
<Compile Include="Documentation\XmlDocumentationElement.cs" />
<Compile Include="IL\ControlFlow\AwaitInFinallyTransform.cs" />

27
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -213,7 +213,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -213,7 +213,7 @@ namespace ICSharpCode.Decompiler.Metadata
public class GenericContext
{
readonly PEFile module;
readonly MetadataReader metadata;
readonly TypeDefinitionHandle declaringType;
readonly MethodDefinitionHandle method;
@ -223,14 +223,27 @@ namespace ICSharpCode.Decompiler.Metadata @@ -223,14 +223,27 @@ namespace ICSharpCode.Decompiler.Metadata
public GenericContext(MethodDefinitionHandle method, PEFile module)
{
this.module = module;
this.metadata = module.Metadata;
this.method = method;
this.declaringType = module.Metadata.GetMethodDefinition(method).GetDeclaringType();
}
public GenericContext(MethodDefinitionHandle method, MetadataReader metadata)
{
this.metadata = metadata;
this.method = method;
this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType();
}
public GenericContext(TypeDefinitionHandle declaringType, PEFile module)
{
this.module = module;
this.metadata = module.Metadata;
this.declaringType = declaringType;
}
public GenericContext(TypeDefinitionHandle declaringType, MetadataReader metadata)
{
this.metadata = metadata;
this.declaringType = declaringType;
}
@ -239,7 +252,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -239,7 +252,7 @@ namespace ICSharpCode.Decompiler.Metadata
GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index);
if (genericParameter.IsNil)
return index.ToString();
return module.Metadata.GetString(module.Metadata.GetGenericParameter(genericParameter).Name);
return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
}
public string GetGenericMethodTypeParameterName(int index)
@ -247,13 +260,13 @@ namespace ICSharpCode.Decompiler.Metadata @@ -247,13 +260,13 @@ namespace ICSharpCode.Decompiler.Metadata
GenericParameterHandle genericParameter = GetGenericMethodTypeParameterHandleOrNull(index);
if (genericParameter.IsNil)
return index.ToString();
return module.Metadata.GetString(module.Metadata.GetGenericParameter(genericParameter).Name);
return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
}
public GenericParameterHandle GetGenericTypeParameterHandleOrNull(int index)
{
GenericParameterHandleCollection genericParameters;
if (declaringType.IsNil || index < 0 || index >= (genericParameters = module.Metadata.GetTypeDefinition(declaringType).GetGenericParameters()).Count)
if (declaringType.IsNil || index < 0 || index >= (genericParameters = metadata.GetTypeDefinition(declaringType).GetGenericParameters()).Count)
return MetadataTokens.GenericParameterHandle(0);
return genericParameters[index];
}
@ -261,7 +274,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -261,7 +274,7 @@ namespace ICSharpCode.Decompiler.Metadata
public GenericParameterHandle GetGenericMethodTypeParameterHandleOrNull(int index)
{
GenericParameterHandleCollection genericParameters;
if (method.IsNil || index < 0 || index >= (genericParameters = module.Metadata.GetMethodDefinition(method).GetGenericParameters()).Count)
if (method.IsNil || index < 0 || index >= (genericParameters = metadata.GetMethodDefinition(method).GetGenericParameters()).Count)
return MetadataTokens.GenericParameterHandle(0);
return genericParameters[index];
}

13
ILSpy/DebugInfo/PortableDebugInfoProvider.cs

@ -26,19 +26,22 @@ namespace ICSharpCode.Decompiler.PdbProvider @@ -26,19 +26,22 @@ namespace ICSharpCode.Decompiler.PdbProvider
class PortableDebugInfoProvider : IDebugInfoProvider
{
string pdbFileName;
MetadataReaderProvider provider;
internal MetadataReaderProvider Provider { get; }
internal bool IsEmbedded => pdbFileName == null;
public PortableDebugInfoProvider(string pdbFileName, MetadataReaderProvider provider)
{
this.pdbFileName = pdbFileName;
this.provider = provider;
this.Provider = provider;
}
public string Description => pdbFileName == null ? "Embedded in this assembly" : $"Loaded from portable PDB: {pdbFileName}";
public IList<Decompiler.DebugInfo.SequencePoint> GetSequencePoints(MethodDefinitionHandle method)
{
var metadata = provider.GetMetadataReader();
var metadata = Provider.GetMetadataReader();
var debugInfo = metadata.GetMethodDebugInformation(method);
var sequencePoints = new List<Decompiler.DebugInfo.SequencePoint>();
@ -67,7 +70,7 @@ namespace ICSharpCode.Decompiler.PdbProvider @@ -67,7 +70,7 @@ namespace ICSharpCode.Decompiler.PdbProvider
public IList<Variable> GetVariables(MethodDefinitionHandle method)
{
var metadata = provider.GetMetadataReader();
var metadata = Provider.GetMetadataReader();
var variables = new List<Variable>();
foreach (var h in metadata.GetLocalScopes(method)) {
@ -83,7 +86,7 @@ namespace ICSharpCode.Decompiler.PdbProvider @@ -83,7 +86,7 @@ namespace ICSharpCode.Decompiler.PdbProvider
public bool TryGetName(MethodDefinitionHandle method, int index, out string name)
{
var metadata = provider.GetMetadataReader();
var metadata = Provider.GetMetadataReader();
name = null;
foreach (var h in metadata.GetLocalScopes(method)) {

33
ILSpy/ILSpy.csproj

@ -169,11 +169,44 @@ @@ -169,11 +169,44 @@
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DataGridCustomTextColumn.cs" />
<Compile Include="Metadata\DebugTables\LocalConstantTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\ImportScopeTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\LocalVariableTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\LocalScopeTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\CustomDebugInformationTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\StateMachineMethodTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\MethodDebugInformationTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\DebugTables\DocumentTableTreeNode.cs">
<SubType>Code</SubType>
<Generator>MSBuild:Compile</Generator>
</Compile>
<Compile Include="Metadata\FlagsFilterControl.xaml.cs" />
<Compile Include="Metadata\FlagsTooltip.xaml.cs" />
<Compile Include="Metadata\HexFilterControl.xaml.cs" />
<Compile Include="Metadata\MetadataProtocolHandler.cs" />
<Compile Include="Metadata\MetadataTableTreeNode.cs" />
<Compile Include="Metadata\DebugMetadataTreeNode.cs" />
<Compile Include="ViewModels\ManageAssemblyListsViewModel.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" />
<Compile Include="Views\CreateListDialog.xaml.cs">

79
ILSpy/Metadata/DebugMetadataTreeNode.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata
{
class DebugMetadataTreeNode : ILSpyTreeNode
{
private PEFile module;
private MetadataReader provider;
private AssemblyTreeNode assemblyTreeNode;
private bool isEmbedded;
public DebugMetadataTreeNode(PEFile module, bool isEmbedded, MetadataReader provider, AssemblyTreeNode assemblyTreeNode)
{
this.module = module;
this.provider = provider;
this.assemblyTreeNode = assemblyTreeNode;
this.isEmbedded = isEmbedded;
this.Text = "Debug Metadata (" + (isEmbedded ? "Embedded" : "From portable PDB") + ")";
this.LazyLoading = true;
}
public override object Text { get; }
public override object Icon => Images.Library;
public override bool View(TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
return false;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Debug Metadata");
}
protected override void LoadChildren()
{
this.Children.Add(new DocumentTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new MethodDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new LocalScopeTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new LocalVariableTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new LocalConstantTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new ImportScopeTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new StateMachineMethodTableTreeNode(this.module, this.provider, isEmbedded));
this.Children.Add(new CustomDebugInformationTableTreeNode(this.module, this.provider, isEmbedded));
}
public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
{
return this.Children.OfType<MetadataTableTreeNode>().SingleOrDefault(x => x.Kind == kind);
}
}
}

161
ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs

@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class CustomDebugInformationTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public CustomDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.CustomDebugInformation, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"37 CustomDebugInformation ({metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<CustomDebugInformationEntry>();
CustomDebugInformationEntry scrollTargetEntry = default;
foreach (var row in metadata.CustomDebugInformation) {
CustomDebugInformationEntry entry = new CustomDebugInformationEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct CustomDebugInformationEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly CustomDebugInformationHandle handle;
readonly CustomDebugInformation debugInfo;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public int Parent => MetadataTokens.GetToken(debugInfo.Parent);
public string ParentTooltip {
get {
ITextOutput output = new PlainTextOutput();
var context = new GenericContext(default(TypeDefinitionHandle), module);
debugInfo.Parent.WriteTo(module, output, context);
return output.ToString();
}
}
[StringFormat("X8")]
public int Kind => MetadataTokens.GetHeapOffset(debugInfo.Kind);
public string KindTooltip {
get {
if (debugInfo.Kind.IsNil)
return null;
var guid = metadata.GetGuid(debugInfo.Kind);
if (KnownGuids.StateMachineHoistedLocalScopes == guid) {
return "State Machine Hoisted Local Scopes (C# / VB) [" + guid + "]";
}
if (KnownGuids.DynamicLocalVariables == guid) {
return "Dynamic Local Variables (C#) [" + guid + "]";
}
if (KnownGuids.DefaultNamespaces == guid) {
return "Default Namespaces (VB) [" + guid + "]";
}
if (KnownGuids.EditAndContinueLocalSlotMap == guid) {
return "Edit And Continue Local Slot Map (C# / VB) [" + guid + "]";
}
if (KnownGuids.EditAndContinueLambdaAndClosureMap == guid) {
return "Edit And Continue Lambda And Closure Map (C# / VB) [" + guid + "]";
}
if (KnownGuids.EmbeddedSource == guid) {
return "State Machine Hoisted Local Scopes (C# / VB) [" + guid + "]";
}
if (KnownGuids.SourceLink == guid) {
return "Source Link (C# / VB) [" + guid + "]";
}
if (KnownGuids.MethodSteppingInformation == guid) {
return "Method Stepping Information (C# / VB) [" + guid + "]";
}
return $"Unknown [" + guid + "]";
}
}
[StringFormat("X")]
public int Value => MetadataTokens.GetHeapOffset(debugInfo.Value);
public string ValueTooltip {
get {
return null;
}
}
public CustomDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, CustomDebugInformationHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.CustomDebugInformation)
+ metadata.GetTableRowSize(TableIndex.CustomDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.debugInfo = metadata.GetCustomDebugInformation(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "CustomDebugInformation");
}
}
}

149
ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs

@ -0,0 +1,149 @@ @@ -0,0 +1,149 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class DocumentTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public DocumentTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.Document, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"30 Document ({metadata.GetTableRowCount(TableIndex.Document)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<DocumentEntry>();
DocumentEntry scrollTargetEntry = default;
foreach (var row in metadata.Documents) {
DocumentEntry entry = new DocumentEntry(metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct DocumentEntry
{
readonly int? offset;
readonly MetadataReader metadata;
readonly DocumentHandle handle;
readonly Document document;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
public string Name => metadata.GetString(document.Name);
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{Name}\"";
[StringFormat("X")]
public int HashAlgorithm => MetadataTokens.GetHeapOffset(document.HashAlgorithm);
public string HashAlgorithmTooltip {
get {
if (document.HashAlgorithm.IsNil)
return null;
Guid guid = metadata.GetGuid(document.HashAlgorithm);
if (guid == KnownGuids.HashAlgorithmSHA1)
return "SHA1 [ff1816ec-aa5e-4d10-87f7-6f4963833460]";
if (guid == KnownGuids.HashAlgorithmSHA256)
return "SHA256 [8829d00f-11b8-4213-878b-770e8597ac16]";
return $"Unknown [" + guid + "]";
}
}
[StringFormat("X")]
public int Hash => MetadataTokens.GetHeapOffset(document.Hash);
public string HashTooltip {
get {
if (document.Hash.IsNil)
return null;
System.Collections.Immutable.ImmutableArray<byte> token = metadata.GetBlobContent(document.Hash);
return token.ToHexString(token.Length);
}
}
[StringFormat("X")]
public int Language => MetadataTokens.GetHeapOffset(document.Language);
public string LanguageTooltip {
get {
if (document.Language.IsNil)
return null;
Guid guid = metadata.GetGuid(document.Language);
if (guid == KnownGuids.CSharpLanguageGuid)
return "Visual C# [3f5162f8-07c6-11d3-9053-00c04fa302a1]";
if (guid == KnownGuids.VBLanguageGuid)
return "Visual Basic [3a12d0b8-c26c-11d0-b442-00a0244a1dd2]";
if (guid == KnownGuids.FSharpLanguageGuid)
return "Visual F# [ab4f38c9-b6e6-43ba-be3b-58080b2ccce3]";
return $"Unknown [" + guid + "]";
}
}
public DocumentEntry(MetadataReader metadata, bool isEmbedded, DocumentHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.Document)
+ metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1);
this.metadata = metadata;
this.handle = handle;
this.document = metadata.GetDocument(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Document");
}
}
}

109
ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using System.Linq;
namespace ICSharpCode.ILSpy.Metadata
{
internal class ImportScopeTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public ImportScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.ImportScope, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"35 ImportScope ({metadata.GetTableRowCount(TableIndex.ImportScope)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<ImportScopeEntry>();
ImportScopeEntry scrollTargetEntry = default;
foreach (var row in metadata.ImportScopes) {
ImportScopeEntry entry = new ImportScopeEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct ImportScopeEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly ImportScopeHandle handle;
readonly ImportScope localScope;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public int Parent => MetadataTokens.GetToken(localScope.Parent);
[StringFormat("X")]
public int Imports => MetadataTokens.GetHeapOffset(localScope.ImportsBlob);
public ImportScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, ImportScopeHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.ImportScope)
+ metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.localScope = metadata.GetImportScope(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "ImportScope");
}
}
}

108
ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class LocalConstantTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public LocalConstantTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.LocalConstant, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"34 LocalConstant ({metadata.GetTableRowCount(TableIndex.LocalConstant)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<LocalConstantEntry>();
LocalConstantEntry scrollTargetEntry = default;
foreach (var row in metadata.LocalConstants) {
LocalConstantEntry entry = new LocalConstantEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct LocalConstantEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly LocalConstantHandle handle;
readonly LocalConstant localConst;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
public string Name => metadata.GetString(localConst.Name);
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localConst.Name):X} \"{Name}\"";
[StringFormat("X")]
public int Signature => MetadataTokens.GetToken(localConst.Signature);
public LocalConstantEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalConstantHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalConstant)
+ metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.localConst = metadata.GetLocalConstant(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Document");
}
}
}

129
ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using System.Linq;
namespace ICSharpCode.ILSpy.Metadata
{
internal class LocalScopeTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public LocalScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.LocalScope, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"32 LocalScope ({metadata.GetTableRowCount(TableIndex.LocalScope)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<LocalScopeEntry>();
LocalScopeEntry scrollTargetEntry = default;
foreach (var row in metadata.LocalScopes) {
LocalScopeEntry entry = new LocalScopeEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct LocalScopeEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly LocalScopeHandle handle;
readonly LocalScope localScope;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public int Method => MetadataTokens.GetToken(localScope.Method);
public string MethodTooltip {
get {
ITextOutput output = new PlainTextOutput();
((EntityHandle)localScope.Method).WriteTo(module, output, Decompiler.Metadata.GenericContext.Empty);
return output.ToString();
}
}
[StringFormat("X8")]
public int ImportScope => MetadataTokens.GetToken(localScope.ImportScope);
[StringFormat("X8")]
public int VariableList => MetadataTokens.GetToken(localScope.GetLocalVariables().FirstOrDefault());
[StringFormat("X8")]
public int ConstantList => MetadataTokens.GetToken(localScope.GetLocalConstants().FirstOrDefault());
[StringFormat("X8")]
public int StartOffset => localScope.StartOffset;
[StringFormat("X8")]
public int Length => localScope.Length;
public LocalScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalScopeHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalScope)
+ metadata.GetTableRowSize(TableIndex.LocalScope) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.localScope = metadata.GetLocalScope(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "LocalScope");
}
}
}

110
ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class LocalVariableTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public LocalVariableTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.LocalVariable, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"33 LocalVariable ({metadata.GetTableRowCount(TableIndex.LocalVariable)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<LocalVariableEntry>();
LocalVariableEntry scrollTargetEntry = default;
foreach (var row in metadata.LocalVariables) {
LocalVariableEntry entry = new LocalVariableEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct LocalVariableEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly LocalVariableHandle handle;
readonly LocalVariable localVar;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public LocalVariableAttributes Attributes => localVar.Attributes;
public object AttributesTooltip => new FlagsTooltip() {
FlagGroup.CreateMultipleChoiceGroup(typeof(LocalVariableAttributes)),
};
public int Index => localVar.Index;
public string Name => metadata.GetString(localVar.Name);
public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localVar.Name):X} \"{Name}\"";
public LocalVariableEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalVariableHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalVariable)
+ metadata.GetTableRowSize(TableIndex.LocalVariable) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.localVar = metadata.GetLocalVariable(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Document");
}
}
}

150
ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class MethodDebugInformationTableTreeNode : DebugMetadataTableTreeNode
{
private readonly bool isEmbedded;
public MethodDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base(HandleKind.MethodDebugInformation, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"31 MethodDebugInformation ({metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})";
public override object Icon => Images.Literal;
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<MethodDebugInformationEntry>();
MethodDebugInformationEntry scrollTargetEntry = default;
foreach (var row in metadata.MethodDebugInformation) {
MethodDebugInformationEntry entry = new MethodDebugInformationEntry(module, metadata, isEmbedded, row);
if (entry.RID == scrollTarget) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
struct MethodDebugInformationEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly MethodDebugInformationHandle handle;
readonly MethodDebugInformation debugInfo;
public int RID => MetadataTokens.GetRowNumber(handle);
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public int Document => MetadataTokens.GetToken(debugInfo.Document);
public string DocumentTooltip {
get {
if (debugInfo.Document.IsNil)
return null;
var document = metadata.GetDocument(debugInfo.Document);
return $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{metadata.GetString(document.Name)}\"";
}
}
[StringFormat("X")]
public int SequencePoints => MetadataTokens.GetHeapOffset(debugInfo.SequencePointsBlob);
public string SequencePointsTooltip {
get {
if (debugInfo.SequencePointsBlob.IsNil)
return null;
StringBuilder sb = new StringBuilder();
foreach (var p in debugInfo.GetSequencePoints()) {
sb.AppendLine($"document='{MetadataTokens.GetToken(p.Document):X8}', offset={p.Offset}, start={p.StartLine};{p.StartColumn}, end={p.EndLine};{p.EndColumn}, hidden={p.IsHidden}");
}
return sb.ToString().TrimEnd();
}
}
[StringFormat("X")]
public int LocalSignature => MetadataTokens.GetToken(debugInfo.LocalSignature);
public string LocalSignatureTooltip {
get {
if (debugInfo.LocalSignature.IsNil)
return null;
ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), metadata);
StandaloneSignature localSignature = module.Metadata.GetStandaloneSignature(debugInfo.LocalSignature);
var signatureDecoder = new DisassemblerSignatureTypeProvider(module, output);
int index = 0;
foreach (var item in localSignature.DecodeLocalSignature(signatureDecoder, context)) {
if (index > 0) output.WriteLine();
output.Write("[{0}] ", index);
item(ILNameSyntax.Signature);
index++;
}
return output.ToString();
}
}
public MethodDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, MethodDebugInformationHandle handle)
{
this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.MethodDebugInformation)
+ metadata.GetTableRowSize(TableIndex.MethodDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1);
this.module = module;
this.metadata = metadata;
this.handle = handle;
this.debugInfo = metadata.GetMethodDebugInformation(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "MethodDebugInformation");
}
}
}

141
ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
{
internal class StateMachineMethodTableTreeNode : DebugMetadataTableTreeNode
{
readonly bool isEmbedded;
public StateMachineMethodTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded)
: base((HandleKind)0x36, module, metadata)
{
this.isEmbedded = isEmbedded;
}
public override object Text => $"36 StateMachineMethod ({metadata.GetTableRowCount(TableIndex.StateMachineMethod)})";
public override object Icon => Images.Literal;
public unsafe override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
tabPage.SupportsLanguageSwitching = false;
var view = Helpers.PrepareDataGrid(tabPage, this);
var list = new List<StateMachineMethodEntry>();
StateMachineMethodEntry scrollTargetEntry = default;
var length = metadata.GetTableRowCount(TableIndex.StateMachineMethod);
byte* ptr = metadata.MetadataPointer;
for (int rid = 1; rid <= length; rid++) {
StateMachineMethodEntry entry = new StateMachineMethodEntry(module, ptr, isEmbedded, rid);
if (scrollTarget == rid) {
scrollTargetEntry = entry;
}
list.Add(entry);
}
view.ItemsSource = list;
tabPage.Content = view;
if (scrollTargetEntry.RID > 1) {
ScrollItemIntoView(view, scrollTargetEntry);
}
return true;
}
readonly struct StateMachineMethod
{
public readonly MethodDefinitionHandle MoveNextMethod;
public readonly MethodDefinitionHandle KickoffMethod;
public unsafe StateMachineMethod(byte* ptr, int methodDefSize)
{
MoveNextMethod = MetadataTokens.MethodDefinitionHandle(Helpers.GetValue(ptr, methodDefSize));
KickoffMethod = MetadataTokens.MethodDefinitionHandle(Helpers.GetValue(ptr + methodDefSize, methodDefSize));
}
}
unsafe struct StateMachineMethodEntry
{
readonly int? offset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly StateMachineMethod stateMachineMethod;
public int RID { get; }
public object Offset => offset == null ? "n/a" : (object)offset;
[StringFormat("X8")]
public int MoveNextMethod => MetadataTokens.GetToken(stateMachineMethod.MoveNextMethod);
public string MoveNextMethodTooltip {
get {
ITextOutput output = new PlainTextOutput();
var context = new GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)stateMachineMethod.MoveNextMethod).WriteTo(module, output, context);
return output.ToString();
}
}
[StringFormat("X8")]
public int KickoffMethod => MetadataTokens.GetToken(stateMachineMethod.KickoffMethod);
public string KickoffMethodTooltip {
get {
ITextOutput output = new PlainTextOutput();
var context = new GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)stateMachineMethod.KickoffMethod).WriteTo(module, output, context);
return output.ToString();
}
}
public StateMachineMethodEntry(PEFile module, byte* ptr, bool isEmbedded, int row)
{
this.module = module;
this.metadata = module.Metadata;
this.RID = row;
int rowOffset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod)
+ metadata.GetTableRowSize(TableIndex.StateMachineMethod) * (row - 1);
this.offset = isEmbedded ? null : (int?)rowOffset;
this.stateMachineMethod = new StateMachineMethod(ptr + rowOffset, metadata.GetTableRowCount(TableIndex.MethodDef) < ushort.MaxValue ? 2 : 4);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "StateMachineMethod");
}
}
}

11
ILSpy/Metadata/MetadataTableTreeNode.cs

@ -62,4 +62,15 @@ namespace ICSharpCode.ILSpy.Metadata @@ -62,4 +62,15 @@ namespace ICSharpCode.ILSpy.Metadata
this.scrollTarget = default;
}
}
internal abstract class DebugMetadataTableTreeNode : MetadataTableTreeNode
{
protected MetadataReader metadata;
public DebugMetadataTableTreeNode(HandleKind kind, PEFile module, MetadataReader metadata)
: base(kind, module)
{
this.metadata = metadata;
}
}
}

4
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -143,6 +143,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -143,6 +143,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
var assembly = (MetadataModule)typeSystem.MainModule;
var metadata = module.Metadata;
this.Children.Add(new Metadata.MetadataTreeNode(module, this));
Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull();
if (debugInfo is Decompiler.PdbProvider.PortableDebugInfoProvider ppdb) {
this.Children.Add(new Metadata.DebugMetadataTreeNode(module, ppdb.IsEmbedded, ppdb.Provider.GetMetadataReader(), this));
}
this.Children.Add(new ReferenceFolderTreeNode(module, this));
if (module.Resources.Any())
this.Children.Add(new ResourceListTreeNode(module));

Loading…
Cancel
Save