Browse Source

Initial implementation of metadata explorer.

pull/1716/head
Siegfried Pammer 6 years ago
parent
commit
8dbfa825d3
  1. 91
      ILSpy/Commands/DecompileCommand.cs
  2. 20
      ILSpy/ILSpy.csproj
  3. 101
      ILSpy/Metadata/CoffHeaderTreeNode.cs
  4. 91
      ILSpy/Metadata/DataDirectoriesTreeNode.cs
  5. 74
      ILSpy/Metadata/DosHeaderTreeNode.cs
  6. 55
      ILSpy/Metadata/EntityHandleTemplate.cs
  7. 96
      ILSpy/Metadata/ExportedTypeTableTreeNode.cs
  8. 100
      ILSpy/Metadata/FieldTableTreeNode.cs
  9. 70
      ILSpy/Metadata/Helpers.cs
  10. 339
      ILSpy/Metadata/MetadataTableViews.xaml
  11. 39
      ILSpy/Metadata/MetadataTableViews.xaml.cs
  12. 84
      ILSpy/Metadata/MetadataTreeNode.cs
  13. 100
      ILSpy/Metadata/MethodTableTreeNode.cs
  14. 95
      ILSpy/Metadata/ModuleTableTreeNode.cs
  15. 125
      ILSpy/Metadata/OptionalHeaderTreeNode.cs
  16. 75
      ILSpy/Metadata/StringHandleTemplate.cs
  17. 125
      ILSpy/Metadata/TypeDefTableTreeNode.cs
  18. 89
      ILSpy/Metadata/TypeRefTableTreeNode.cs
  19. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs

91
ILSpy/Commands/DecompileCommand.cs

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = "Decompile", Order = 10)]
class DecompileCommand : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
var (c, selectedItem) = context.GetColumnAndRowFromMousePosition();
if (c is FilterableGridViewColumn column && column.CellTemplateSelector is HandleTemplate && selectedItem is IMemberTreeNode) {
var selectedHandle = MetadataTokens.EntityHandle((int)selectedItem.GetType().GetProperty(column.SortBy).GetValue(selectedItem));
return !selectedHandle.IsNil && (selectedHandle.Kind == HandleKind.TypeDefinition || selectedHandle.Kind == HandleKind.FieldDefinition || selectedHandle.Kind == HandleKind.MethodDefinition || selectedHandle.Kind == HandleKind.PropertyDefinition || selectedHandle.Kind == HandleKind.EventDefinition);
}
if (context.SelectedTreeNodes == null)
return context.Reference?.Reference is IEntity;
return context.SelectedTreeNodes.Length == 1 && context.SelectedTreeNodes.All(n => n is IMemberTreeNode);
}
public bool IsEnabled(TextViewContext context)
{
var (c, selectedItem) = context.GetColumnAndRowFromMousePosition();
if (c is FilterableGridViewColumn column && column.CellTemplateSelector is HandleTemplate && selectedItem is IMemberTreeNode) {
var selectedHandle = MetadataTokens.EntityHandle((int)selectedItem.GetType().GetProperty(column.SortBy).GetValue(selectedItem));
return !selectedHandle.IsNil && (selectedHandle.Kind == HandleKind.TypeDefinition || selectedHandle.Kind == HandleKind.FieldDefinition || selectedHandle.Kind == HandleKind.MethodDefinition || selectedHandle.Kind == HandleKind.PropertyDefinition || selectedHandle.Kind == HandleKind.EventDefinition);
}
if (context.SelectedTreeNodes == null)
return context.Reference?.Reference is IEntity;
foreach (IMemberTreeNode node in context.SelectedTreeNodes) {
if (!IsValidReference(node.Member))
return false;
}
return true;
}
bool IsValidReference(object reference)
{
return reference is IEntity;
}
public void Execute(TextViewContext context)
{
IEntity selection = null;
var (c, selectedItem) = context.GetColumnAndRowFromMousePosition();
if (c is FilterableGridViewColumn column && column.CellTemplateSelector is HandleTemplate && selectedItem is IMemberTreeNode semanticContext) {
var selectedHandle = MetadataTokens.EntityHandle((int)selectedItem.GetType().GetProperty(column.SortBy).GetValue(selectedItem));
var module = (MetadataModule)semanticContext.Member.ParentModule;
switch (selectedHandle.Kind) {
case HandleKind.TypeDefinition:
selection = module.GetDefinition((TypeDefinitionHandle)selectedHandle);
break;
case HandleKind.FieldDefinition:
selection = module.GetDefinition((FieldDefinitionHandle)selectedHandle);
break;
case HandleKind.MethodDefinition:
selection = module.GetDefinition((MethodDefinitionHandle)selectedHandle);
break;
case HandleKind.PropertyDefinition:
selection = module.GetDefinition((PropertyDefinitionHandle)selectedHandle);
break;
case HandleKind.EventDefinition:
selection = module.GetDefinition((EventDefinitionHandle)selectedHandle);
break;
}
} else if (context.SelectedTreeNodes?[0] is IMemberTreeNode node) {
selection = node.Member;
} else if (context.Reference?.Reference is IEntity entity) {
selection = entity;
}
if (selection != null)
MainWindow.Instance.JumpToReference(selection);
}
}
}

20
ILSpy/ILSpy.csproj

@ -102,6 +102,7 @@ @@ -102,6 +102,7 @@
<Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands\DecompileCommand.cs" />
<Compile Include="Commands\DisassembleAllCommand.cs" />
<Compile Include="Commands\ExitCommand.cs" />
<Compile Include="Commands\CommandWrapper.cs" />
@ -159,6 +160,21 @@ @@ -159,6 +160,21 @@
<Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" />
<Compile Include="Metadata\DataDirectoriesTreeNode.cs" />
<Compile Include="Metadata\DosHeaderTreeNode.cs" />
<Compile Include="Metadata\CoffHeaderTreeNode.cs" />
<Compile Include="Metadata\EntityHandleTemplate.cs" />
<Compile Include="Metadata\MethodTableTreeNode.cs" />
<Compile Include="Metadata\FieldTableTreeNode.cs" />
<Compile Include="Metadata\Helpers.cs" />
<Compile Include="Metadata\StringHandleTemplate.cs" />
<Compile Include="Metadata\TypeDefTableTreeNode.cs" />
<Compile Include="Metadata\TypeRefTableTreeNode.cs" />
<Compile Include="Metadata\ModuleTableTreeNode.cs" />
<Compile Include="Metadata\ExportedTypeTableTreeNode.cs" />
<Compile Include="Metadata\MetadataTableViews.xaml.cs" />
<Compile Include="Metadata\MetadataTreeNode.cs" />
<Compile Include="Metadata\OptionalHeaderTreeNode.cs" />
<Compile Include="Search\LiteralSearchStrategy.cs" />
<Compile Include="LoadedAssembly.cs" />
<Compile Include="LoadedAssemblyExtensions.cs" />
@ -314,6 +330,7 @@ @@ -314,6 +330,7 @@
<Page Include="CreateListDialog.xaml" />
<Page Include="DebugSteps.xaml" />
<Page Include="MainWindow.xaml" />
<Page Include="Metadata\MetadataTableViews.xaml" />
<Page Include="OpenFromGacDialog.xaml" />
<Page Include="OpenListDialog.xaml" />
<Page Include="NugetPackageBrowserDialog.xaml" />
@ -390,6 +407,9 @@ @@ -390,6 +407,9 @@
<ItemGroup>
<Page Update="@(Page)" SubType="Designer" Generator="MSBuild:Compile" />
<Page Update="Metadata\MetadataTableViews.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>

101
ILSpy/Metadata/CoffHeaderTreeNode.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
class CoffHeaderTreeNode : ILSpyTreeNode
{
private PEFile module;
public CoffHeaderTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => "COFF Header";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
var dataGrid = new DataGrid {
Columns = {
new DataGridTextColumn { IsReadOnly = true, Header = "Member", Binding = new Binding("Member") },
new DataGridTextColumn { IsReadOnly = true, Header = "Offset", Binding = new Binding("Offset") { StringFormat = "X8" } },
new DataGridTextColumn { IsReadOnly = true, Header = "Size", Binding = new Binding("Size") },
new DataGridTextColumn { IsReadOnly = true, Header = "Value", Binding = new Binding(".") { Converter = ByteWidthConverter.Instance } },
new DataGridTextColumn { IsReadOnly = true, Header = "Meaning", Binding = new Binding("Meaning") },
},
AutoGenerateColumns = false,
CanUserAddRows = false,
CanUserDeleteRows = false,
RowDetailsTemplateSelector = new CharacteristicsDataTemplateSelector(),
RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible
};
var headers = module.Reader.PEHeaders;
var header = headers.CoffHeader;
var entries = new List<Entry>();
entries.Add(new Entry(headers.CoffHeaderStartOffset, (int)header.Machine, 2, "Machine", header.Machine.ToString()));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 2, (int)header.NumberOfSections, 2, "Number of Sections", "Number of sections; indicates size of the Section Table, which immediately follows the headers."));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 4, header.TimeDateStamp, 4, "Time/Date Stamp", DateTimeOffset.FromUnixTimeSeconds(unchecked((uint)header.TimeDateStamp)).DateTime + " - Time and date the file was created in seconds since January 1st 1970 00:00:00 or 0."));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 8, header.PointerToSymbolTable, 4, "Pointer to Symbol Table", "Always 0 in .NET executables."));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 12, header.NumberOfSymbols, 4, "Number of Symbols", "Always 0 in .NET executables."));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 16, (int)header.SizeOfOptionalHeader, 2, "Optional Header Size", "Size of the optional header."));
entries.Add(new Entry(headers.CoffHeaderStartOffset + 18, (int)header.Characteristics, 2, "Characteristics", "Flags indicating attributes of the file."));
dataGrid.ItemsSource = entries;
textView.ShowContent(new[] { this }, dataGrid);
return true;
}
private class CharacteristicsDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (((Entry)item).Member == "Characteristics")
return MakeDataTemplate((int)((Entry)item).Value);
return new DataTemplate();
}
private DataTemplate MakeDataTemplate(int flags)
{
FrameworkElementFactory dataGridFactory = new FrameworkElementFactory(typeof(DataGrid));
dataGridFactory.SetValue(DataGrid.ItemsSourceProperty, new[] {
new { Value = (flags & 0x0001) != 0, Meaning = "Relocation info stripped from file" },
new { Value = (flags & 0x0002) != 0, Meaning = "File is executable" },
new { Value = (flags & 0x0004) != 0, Meaning = "Line numbers stripped from file" },
new { Value = (flags & 0x0008) != 0, Meaning = "Local symbols stripped from file" },
new { Value = (flags & 0x0010) != 0, Meaning = "Aggressively trim working set" },
new { Value = (flags & 0x0020) != 0, Meaning = "Large address aware" },
new { Value = (flags & 0x0040) != 0, Meaning = "Reserved" },
new { Value = (flags & 0x0080) != 0, Meaning = "Bytes of machine words are reversed (Low)" },
new { Value = (flags & 0x0100) != 0, Meaning = "32-bit word machine" },
new { Value = (flags & 0x0200) != 0, Meaning = "Debugging info stripped from file in .DBG file" },
new { Value = (flags & 0x0400) != 0, Meaning = "If image is on removable media, copy and run from the swap file" },
new { Value = (flags & 0x0800) != 0, Meaning = "If image is on Net, copy and run from the swap file" },
new { Value = (flags & 0x1000) != 0, Meaning = "System" },
new { Value = (flags & 0x2000) != 0, Meaning = "DLL" },
new { Value = (flags & 0x4000) != 0, Meaning = "File should only be run on a UP machine" },
new { Value = (flags & 0x8000) != 0, Meaning = "Bytes of machine words are reversed (High)" },
});
DataTemplate template = new DataTemplate();
template.VisualTree = dataGridFactory;
return template;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "COFF Header");
}
}
}

91
ILSpy/Metadata/DataDirectoriesTreeNode.cs

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
using System.Reflection.PortableExecutable;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
class DataDirectoriesTreeNode : ILSpyTreeNode
{
private PEFile module;
public DataDirectoriesTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => "Data Directories";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
var dataGrid = new DataGrid {
Columns = {
new DataGridTextColumn { IsReadOnly = true, Header = "Name", Binding = new Binding("Name") },
new DataGridTextColumn { IsReadOnly = true, Header = "RVA", Binding = new Binding("RVA") { StringFormat = "X8" } },
new DataGridTextColumn { IsReadOnly = true, Header = "Size", Binding = new Binding("Size") { StringFormat = "X8" } },
new DataGridTextColumn { IsReadOnly = true, Header = "Section", Binding = new Binding("Section") },
},
AutoGenerateColumns = false,
CanUserAddRows = false,
CanUserDeleteRows = false,
};
var headers = module.Reader.PEHeaders;
var reader = module.Reader.GetEntireImage().GetReader(headers.PEHeaderStartOffset, 128);
var header = headers.PEHeader;
var entries = new DataDirectoryEntry[] {
new DataDirectoryEntry(headers, "Export Table", header.ExportTableDirectory),
new DataDirectoryEntry(headers, "Import Table", header.ImportTableDirectory),
new DataDirectoryEntry(headers, "Resource Table", header.ResourceTableDirectory),
new DataDirectoryEntry(headers, "Exception Table", header.ExceptionTableDirectory),
new DataDirectoryEntry(headers, "Certificate Table", header.CertificateTableDirectory),
new DataDirectoryEntry(headers, "Base Relocation Table", header.BaseRelocationTableDirectory),
new DataDirectoryEntry(headers, "Debug Table", header.DebugTableDirectory),
new DataDirectoryEntry(headers, "Copyright Table", header.CopyrightTableDirectory),
new DataDirectoryEntry(headers, "Global Pointer Table", header.GlobalPointerTableDirectory),
new DataDirectoryEntry(headers, "Thread Local Storage Table", header.ThreadLocalStorageTableDirectory),
new DataDirectoryEntry(headers, "Load Config", header.LoadConfigTableDirectory),
new DataDirectoryEntry(headers, "Bound Import", header.BoundImportTableDirectory),
new DataDirectoryEntry(headers, "Import Address Table", header.ImportAddressTableDirectory),
new DataDirectoryEntry(headers, "Delay Import Descriptor", header.DelayImportTableDirectory),
new DataDirectoryEntry(headers, "CLI Header", header.CorHeaderTableDirectory),
};
dataGrid.ItemsSource = entries;
textView.ShowContent(new[] { this }, dataGrid);
return true;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Data Directories");
}
class DataDirectoryEntry
{
public string Name { get; set; }
public int RVA { get; set; }
public int Size { get; set; }
public string Section { get; set; }
public DataDirectoryEntry(string name, int rva, int size, string section)
{
this.Name = name;
this.RVA = rva;
this.Size = size;
this.Section = section;
}
public DataDirectoryEntry(PEHeaders headers, string name, DirectoryEntry entry)
: this(name, entry.RelativeVirtualAddress, entry.Size, (headers.GetContainingSectionIndex(entry.RelativeVirtualAddress) >= 0) ? headers.SectionHeaders[headers.GetContainingSectionIndex(entry.RelativeVirtualAddress)].Name : "")
{
}
}
}
}

74
ILSpy/Metadata/DosHeaderTreeNode.cs

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
class DosHeaderTreeNode : ILSpyTreeNode
{
private PEFile module;
public DosHeaderTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => "DOS Header";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
var view = Helpers.CreateListView("EntryView");
var reader = module.Reader.GetEntireImage().GetReader(0, 64);
var entries = new List<Entry>();
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_magic", "Magic Number (MZ)"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_cblp", "Bytes on last page of file"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_cp", "Pages in file"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_crlc", "Relocations"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_cparhdr", "Size of header in paragraphs"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_minalloc", "Minimum extra paragraphs needed"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_maxalloc", "Maximum extra paragraphs needed"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_ss", "Initial (relative) SS value"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_sp", "Initial SP value"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_csum", "Checksum"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_ip", "Initial IP value"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_cs", "Initial (relative) CS value"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_lfarlc", "File address of relocation table"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_ovno", "Overlay number"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res[0]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res[1]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res[2]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res[3]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_oemid", "OEM identifier (for e_oeminfo)"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_oeminfo", "OEM information; e_oemid specific"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[0]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[1]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[2]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[3]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[4]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[5]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[6]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[7]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[8]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "e_res2[9]", "Reserved words"));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "e_lfanew", "File address of new exe header"));
view.ItemsSource = entries;
textView.ShowContent(new[] { this }, view);
return true;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "DOS Header");
}
}
}

55
ILSpy/Metadata/EntityHandleTemplate.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ICSharpCode.ILSpy.Metadata
{
public class HandleTemplate : DataTemplateSelector
{
public string ValuePropertyName { get; set; }
public string TooltipPropertyName { get; set; }
private DataTemplate template;
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (template != null)
return template;
var textBlock = new FrameworkElementFactory(typeof(TextBlock), "textBlock");
textBlock.SetValue(FrameworkElement.MarginProperty, new Thickness(3, 1, 0, 0));
textBlock.SetBinding(TextBlock.TextProperty, new Binding(ValuePropertyName) { StringFormat = "X8" });
var textBox = new FrameworkElementFactory(typeof(TextBox), "textBox");
textBox.SetBinding(TextBox.TextProperty, new Binding(ValuePropertyName) { StringFormat = "X8", Mode = BindingMode.OneWay });
textBox.SetValue(TextBox.VisibilityProperty, Visibility.Hidden);
textBox.SetValue(TextBox.IsReadOnlyCaretVisibleProperty, true);
textBox.SetValue(TextBox.IsReadOnlyProperty, true);
if (TooltipPropertyName != null)
textBox.SetBinding(FrameworkElement.ToolTipProperty, new Binding(TooltipPropertyName));
var grid = new FrameworkElementFactory(typeof(Grid));
grid.AppendChild(textBlock);
grid.AppendChild(textBox);
template = new DataTemplate {
VisualTree = grid,
Triggers = {
new Trigger {
Property = UIElement.IsMouseOverProperty,
Value = true,
Setters = {
new Setter(UIElement.VisibilityProperty, Visibility.Visible, "textBox"),
new Setter(UIElement.VisibilityProperty, Visibility.Hidden, "textBlock"),
}
},
new Trigger {
Property = UIElement.IsKeyboardFocusWithinProperty,
Value = true,
Setters = {
new Setter(UIElement.VisibilityProperty, Visibility.Visible, "textBox"),
new Setter(UIElement.VisibilityProperty, Visibility.Hidden, "textBlock"),
}
}
}
};
return template;
}
}
}

96
ILSpy/Metadata/ExportedTypeTableTreeNode.cs

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.Metadata
{
internal class ExportedTypeTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public ExportedTypeTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"27 ExportedType ({module.Metadata.GetTableRowCount(TableIndex.ExportedType)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("ExportedTypesView");
var metadata = module.Metadata;
var list = new List<ExportedTypeEntry>();
foreach (var row in metadata.ExportedTypes) {
list.Add(new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, metadata, row, metadata.GetExportedType(row)));
}
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct ExportedTypeEntry
{
readonly int metadataOffset;
readonly MetadataReader metadata;
readonly ExportedTypeHandle handle;
readonly ExportedType type;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.ExportedType)
+ metadata.GetTableRowSize(TableIndex.ExportedType) * (RID-1);
public int Attributes => (int)type.Attributes;
public string AttributesTooltip => Helpers.AttributesToString(type.Attributes);
public int TypeDefId => type.GetTypeDefinitionId();
public int TypeName => MetadataTokens.GetHeapOffset(type.Name);
public string TypeNameTooltip => metadata.GetString(type.Name);
public int TypeNamespace => MetadataTokens.GetHeapOffset(type.Namespace);
public string TypeNamespaceTooltip => metadata.GetString(type.Namespace);
public int Implementation => MetadataTokens.GetToken(type.Implementation);
public ExportedTypeEntry(int metadataOffset, MetadataReader metadata, ExportedTypeHandle handle, ExportedType type)
{
this.metadataOffset = metadataOffset;
this.metadata = metadata;
this.handle = handle;
this.type = type;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "ExportedType");
}
}
}

100
ILSpy/Metadata/FieldTableTreeNode.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
internal class FieldTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public FieldTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"04 Field ({module.Metadata.GetTableRowCount(TableIndex.Field)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("FieldDefsView");
var metadata = module.Metadata;
var list = new List<FieldDefEntry>();
foreach (var row in metadata.FieldDefinitions)
list.Add(new FieldDefEntry(module, row));
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct FieldDefEntry : IMemberTreeNode
{
readonly int metadataOffset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly FieldDefinitionHandle handle;
readonly FieldDefinition fieldDef;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.Field)
+ metadata.GetTableRowSize(TableIndex.Field) * (RID - 1);
public int Attributes => (int)fieldDef.Attributes;
public string AttributesTooltip => null; //Helpers.AttributesToString(fieldDef.Attributes);
public int NameStringHandle => MetadataTokens.GetHeapOffset(fieldDef.Name);
public string Name => metadata.GetString(fieldDef.Name);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature);
public string SignatureTooltip {
get {
ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)handle).WriteTo(module, output, context);
return output.ToString();
}
}
public FieldDefEntry(PEFile module, FieldDefinitionHandle handle)
{
this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
this.module = module;
this.metadata = module.Metadata;
this.handle = handle;
this.fieldDef = metadata.GetFieldDefinition(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "FieldDefs");
}
}
}

70
ILSpy/Metadata/Helpers.cs

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.ILSpy.Controls;
namespace ICSharpCode.ILSpy.Metadata
{
static class Helpers
{
public static ListView CreateListView(string name)
{
MetadataTableViews dict = new MetadataTableViews();
var view = new ListView {
View = (GridView)dict[name],
ItemContainerStyle = (Style)dict["ItemContainerStyle"]
};
ContextMenuProvider.Add(view);
FilterableGridViewColumn.SetSortMode(view, ListViewSortMode.Automatic);
foreach (var column in ((GridView)view.View).Columns) {
FilterableGridViewColumn.SetParentView(column, view);
}
return view;
}
public static string AttributesToString(TypeAttributes attributes)
{
const TypeAttributes allMasks = TypeAttributes.ClassSemanticsMask | TypeAttributes.CustomFormatMask | TypeAttributes.LayoutMask | TypeAttributes.ReservedMask | TypeAttributes.StringFormatMask | TypeAttributes.VisibilityMask;
StringBuilder sb = new StringBuilder();
var visibility = attributes & TypeAttributes.VisibilityMask;
sb.AppendLine("Visibility: " + (visibility == 0 ? "NotPublic" : typeof(TypeAttributes).GetEnumName(visibility)));
var layout = attributes & TypeAttributes.LayoutMask;
sb.AppendLine("Class layout: " + (layout == 0 ? "AutoLayout" : typeof(TypeAttributes).GetEnumName(layout)));
var semantics = attributes & TypeAttributes.ClassSemanticsMask;
sb.AppendLine("Class semantics: " + (semantics == 0 ? "Class" : typeof(TypeAttributes).GetEnumName(semantics)));
var stringFormat = attributes & TypeAttributes.StringFormatMask;
sb.AppendLine("String format: " + (stringFormat == 0 ? "AnsiClass" : typeof(TypeAttributes).GetEnumName(stringFormat)));
var customStringFormat = attributes & TypeAttributes.CustomFormatMask;
sb.AppendLine("Custom string format: 0x" + customStringFormat.ToString("x"));
var reserved = attributes & TypeAttributes.ReservedMask;
sb.AppendLine("Reserved attributes: " + (reserved == 0 ? "" : reserved.ToString()));
var additional = attributes & ~allMasks;
sb.Append("Additional attributes: ");
AdditionalAttributes(sb, additional);
if (sb.Length == 0)
return null;
return sb.ToString();
}
static void AdditionalAttributes(StringBuilder sb, TypeAttributes attributes)
{
bool first = true;
for (int bit = 0; bit < 32; bit++) {
var value = (TypeAttributes)(1 << bit);
if ((attributes & value) != 0) {
if (!first)
sb.Append(", ");
first = false;
sb.Append(typeof(TypeAttributes).GetEnumName(value));
}
}
}
}
}

339
ILSpy/Metadata/MetadataTableViews.xaml

@ -0,0 +1,339 @@ @@ -0,0 +1,339 @@
<ResourceDictionary x:Class="ICSharpCode.ILSpy.Metadata.MetadataTableViews"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.Metadata">
<Style x:Key="ItemContainerStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
<DataTemplate x:Key="RowIDDataTemplate">
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding RID}" />
<TextBox x:Name="textBox" Text="{Binding RID, Mode=OneWay}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="OffsetDataTemplate">
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding Offset, StringFormat=X8}" />
<TextBox x:Name="textBox" Text="{Binding Offset, Mode=OneWay, StringFormat=X8}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
<local:ByteWidthConverter x:Key="byteWidthConverter" />
<local:HandleTemplate x:Key="DefinitionHandleDataTemplate" ValuePropertyName="Token" />
<local:StringHandleTemplate x:Key="NameStringHandleDataTemplate" ValuePropertyName="Name" HandlePropertyName="NameStringHandle" />
<local:StringHandleTemplate x:Key="NamespaceStringHandleDataTemplate" ValuePropertyName="Namespace" HandlePropertyName="NamespaceStringHandle" />
<local:HandleTemplate x:Key="SignatureBlobHandleDataTemplate" TooltipPropertyName="SignatureTooltip" ValuePropertyName="Signature" />
<GridView x:Key="EntryView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="Member" SortBy="Member" FilterBy="Member">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding Member}" />
<TextBox x:Name="textBox" Text="{Binding Member, Mode=OneWay}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8" CellTemplate="{StaticResource OffsetDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Size" SortBy="Size" FilterBy="Size">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding Size}" />
<TextBox x:Name="textBox" Text="{Binding Size, Mode=OneWay}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Value" SortBy="Value" FilterBy="Value">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding ., Converter={StaticResource byteWidthConverter}}" />
<TextBox x:Name="textBox" Text="{Binding ., Mode=OneWay, Converter={StaticResource byteWidthConverter}}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Meaning" SortBy="Meaning" FilterBy="Meaning">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="3,1,0,0" x:Name="textBlock" Text="{Binding Meaning}" />
<TextBox x:Name="textBox" Text="{Binding Meaning, Mode=OneWay}" Visibility="Hidden" IsReadOnly="True" IsReadOnlyCaretVisible="True" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="textBox" Property="Visibility" Value="Visible" />
<Setter TargetName="textBlock" Property="Visibility" Value="Hidden" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
</GridView>
<GridView x:Key="ModulesView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID" CellTemplate="{StaticResource RowIDDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8" CellTemplateSelector="{StaticResource DefinitionHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Generation" SortBy="Generation" FilterBy="Generation">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Generation}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Name" SortBy="Name" FilterBy="Name" CellTemplateSelector="{StaticResource NameStringHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Mvid" SortBy="Mvid" FilterBy="Mvid">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mvid, StringFormat=X}" ToolTip="{Binding MvidTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="GenerationId" SortBy="GenerationId" FilterBy="GenerationId">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding GenerationId, StringFormat=X}" ToolTip="{Binding GenerationIdTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="BaseGenerationId" SortBy="BaseGenerationId" FilterBy="BaseGenerationId">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding BaseGenerationId, StringFormat=X}" ToolTip="{Binding BaseGenerationIdTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
</GridView>
<GridView x:Key="TypeRefsView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID" CellTemplate="{StaticResource RowIDDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8" CellTemplateSelector="{StaticResource DefinitionHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="ResolutionScope" SortBy="ResolutionScope" FilterBy="ResolutionScope">
<controls:FilterableGridViewColumn.CellTemplateSelector>
<local:HandleTemplate ValuePropertyName="ResolutionScope" TooltipPropertyName="ResolutionScopeSignature" />
</controls:FilterableGridViewColumn.CellTemplateSelector>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Name" SortBy="Name" FilterBy="Name" CellTemplateSelector="{StaticResource NameStringHandleDataTemplate}" />
<controls:FilterableGridViewColumn Header="Namespace" SortBy="Namespace" FilterBy="Namespace" CellTemplateSelector="{StaticResource NamespaceStringHandleDataTemplate}"/>
</GridView>
<GridView x:Key="TypeDefsView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID" CellTemplate="{StaticResource RowIDDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8" CellTemplateSelector="{StaticResource DefinitionHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Attributes" SortBy="Attributes" FilterBy="Attributes">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Attributes, StringFormat=X8}" ToolTip="{Binding AttributesTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Name" SortBy="Name" FilterBy="Name" CellTemplateSelector="{StaticResource NameStringHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Namespace" SortBy="Namespace" FilterBy="Namespace" CellTemplateSelector="{StaticResource NamespaceStringHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="BaseType" SortBy="BaseType" FilterBy="BaseType">
<controls:FilterableGridViewColumn.CellTemplateSelector>
<local:HandleTemplate ValuePropertyName="BaseType" TooltipPropertyName="BaseTypeSignature" />
</controls:FilterableGridViewColumn.CellTemplateSelector>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="FieldList" SortBy="FieldList" FilterBy="FieldList">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FieldList, StringFormat=X}" ToolTip="{Binding FieldListTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="MethodList" SortBy="MethodList" FilterBy="MethodList">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding MethodList, StringFormat=X}" ToolTip="{Binding MethodListTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
</GridView>
<GridView x:Key="FieldDefsView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID" CellTemplate="{StaticResource RowIDDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8" CellTemplateSelector="{StaticResource DefinitionHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Attributes" SortBy="Attributes" FilterBy="Attributes">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Attributes, StringFormat=X8}" ToolTip="{Binding AttributesTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Name" SortBy="Name" FilterBy="Name" CellTemplateSelector="{StaticResource NameStringHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Signature" SortBy="Signature" FilterBy="Signature" CellTemplateSelector="{StaticResource SignatureBlobHandleDataTemplate}"/>
</GridView>
<GridView x:Key="MethodDefsView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID" CellTemplate="{StaticResource RowIDDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8" CellTemplateSelector="{StaticResource DefinitionHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Attributes" SortBy="Attributes" FilterBy="Attributes">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Attributes, StringFormat=X8}" ToolTip="{Binding AttributesTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Name" SortBy="Name" FilterBy="Name" CellTemplateSelector="{StaticResource NameStringHandleDataTemplate}"/>
<controls:FilterableGridViewColumn Header="Signature" SortBy="Signature" FilterBy="Signature" CellTemplateSelector="{StaticResource SignatureBlobHandleDataTemplate}"/>
</GridView>
<GridView x:Key="ExportedTypesView" AllowsColumnReorder="False">
<controls:FilterableGridViewColumn Header="RID" SortBy="RID" FilterBy="RID">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RID}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Token" SortBy="Token" FilterBy="Token" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Token, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Offset" SortBy="Offset" FilterBy="Offset" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Offset, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Attributes" SortBy="Attributes" FilterBy="Attributes" FilterFormatString="X8">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Attributes, StringFormat=X8}" ToolTip="{Binding AttributesTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="TypeDefId" SortBy="TypeDefId" FilterBy="TypeDefId">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TypeDefId, StringFormat=X}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="TypeName" SortBy="TypeName" FilterBy="TypeName">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TypeName, StringFormat=X}" ToolTip="{Binding TypeNameTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="TypeNamespace" SortBy="TypeNamespace" FilterBy="TypeNamespace">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TypeNamespace, StringFormat=X}" ToolTip="{Binding TypeNamespaceTooltip}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
<controls:FilterableGridViewColumn Header="Implementation" SortBy="Implementation" FilterBy="Implementation">
<controls:FilterableGridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Implementation, StringFormat=X8}" />
</DataTemplate>
</controls:FilterableGridViewColumn.CellTemplate>
</controls:FilterableGridViewColumn>
</GridView>
</ResourceDictionary>

39
ILSpy/Metadata/MetadataTableViews.xaml.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ICSharpCode.ILSpy.Metadata
{
/// <summary>
/// Interaction logic for MetadataTableViews.xaml
/// </summary>
public partial class MetadataTableViews : ResourceDictionary
{
public MetadataTableViews()
{
InitializeComponent();
}
static MetadataTableViews instance;
public static MetadataTableViews Instance {
get {
if (instance == null) {
instance = new MetadataTableViews();
}
return instance;
}
}
}
}

84
ILSpy/Metadata/MetadataTreeNode.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
class MetadataTreeNode : ILSpyTreeNode
{
private PEFile module;
private AssemblyTreeNode assemblyTreeNode;
public MetadataTreeNode(PEFile module, AssemblyTreeNode assemblyTreeNode)
{
this.module = module;
this.assemblyTreeNode = assemblyTreeNode;
this.LazyLoading = true;
}
public override object Text => "Metadata";
public override object Icon => Images.Library;
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Metadata");
}
protected override void LoadChildren()
{
this.Children.Add(new DosHeaderTreeNode(module));
this.Children.Add(new CoffHeaderTreeNode(module));
this.Children.Add(new OptionalHeaderTreeNode(module));
this.Children.Add(new DataDirectoriesTreeNode(module));
this.Children.Add(new ModuleTableTreeNode(module));
this.Children.Add(new TypeRefTableTreeNode(module));
this.Children.Add(new TypeDefTableTreeNode(module));
this.Children.Add(new FieldTableTreeNode(module));
this.Children.Add(new MethodTableTreeNode(module));
this.Children.Add(new ExportedTypeTableTreeNode(module));
}
}
class Entry
{
public string Member { get; set; }
public int Offset { get; set; }
public int Size { get; set; }
public object Value { get; set; }
public string Meaning { get; set; }
public Entry(int offset, object value, int size, string member, string meaning)
{
this.Member = member;
this.Offset = offset;
this.Size = size;
this.Value = value;
this.Meaning = meaning;
}
}
class ByteWidthConverter : IValueConverter
{
public static readonly ByteWidthConverter Instance = new ByteWidthConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Format("{0:X" + 2 * ((Entry)value).Size + "}", ((Entry)value).Value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

100
ILSpy/Metadata/MethodTableTreeNode.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
internal class MethodTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public MethodTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"06 Method ({module.Metadata.GetTableRowCount(TableIndex.MethodDef)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("MethodDefsView");
var metadata = module.Metadata;
var list = new List<MethodDefEntry>();
foreach (var row in metadata.MethodDefinitions)
list.Add(new MethodDefEntry(module, row));
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct MethodDefEntry : IMemberTreeNode
{
readonly int metadataOffset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly MethodDefinitionHandle handle;
readonly MethodDefinition methodDef;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.MethodDef)
+ metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1);
public int Attributes => (int)methodDef.Attributes;
public string AttributesTooltip => null; //Helpers.AttributesToString(MethodDef.Attributes);
public int NameStringHandle => MetadataTokens.GetHeapOffset(methodDef.Name);
public string Name => metadata.GetString(methodDef.Name);
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
public int Signature => MetadataTokens.GetHeapOffset(methodDef.Signature);
public string SignatureTooltip {
get {
ITextOutput output = new PlainTextOutput();
var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module);
((EntityHandle)handle).WriteTo(module, output, context);
return output.ToString();
}
}
public MethodDefEntry(PEFile module, MethodDefinitionHandle handle)
{
this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
this.module = module;
this.metadata = module.Metadata;
this.handle = handle;
this.methodDef = metadata.GetMethodDefinition(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "MethodDefs");
}
}
}

95
ILSpy/Metadata/ModuleTableTreeNode.cs

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.Metadata
{
internal class ModuleTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public ModuleTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"00 Module ({module.Metadata.GetTableRowCount(TableIndex.Module)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("ModulesView");
var metadata = module.Metadata;
var list = new List<ModuleEntry>();
list.Add(new ModuleEntry(module.Reader.PEHeaders.MetadataStartOffset, metadata, EntityHandle.ModuleDefinition, metadata.GetModuleDefinition()));
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct ModuleEntry
{
readonly int metadataOffset;
readonly MetadataReader metadata;
readonly ModuleDefinitionHandle handle;
readonly ModuleDefinition module;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.Module)
+ metadata.GetTableRowSize(TableIndex.Module) * (RID-1);
public int Generation => module.Generation;
public int NameStringHandle => MetadataTokens.GetHeapOffset(module.Name);
public string Name => metadata.GetString(module.Name);
public int Mvid => MetadataTokens.GetHeapOffset(module.Mvid);
public string MvidTooltip => metadata.GetGuid(module.Mvid).ToString();
public int GenerationId => MetadataTokens.GetHeapOffset(module.GenerationId);
public string GenerationIdTooltip => module.GenerationId.IsNil ? null : metadata.GetGuid(module.GenerationId).ToString();
public int BaseGenerationId => MetadataTokens.GetHeapOffset(module.BaseGenerationId);
public string BaseGenerationIdTooltip => module.BaseGenerationId.IsNil ? null : metadata.GetGuid(module.BaseGenerationId).ToString();
public ModuleEntry(int metadataOffset, MetadataReader metadata, ModuleDefinitionHandle handle, ModuleDefinition module)
{
this.metadataOffset = metadataOffset;
this.metadata = metadata;
this.handle = handle;
this.module = module;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Modules");
}
}
}

125
ILSpy/Metadata/OptionalHeaderTreeNode.cs

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy.Metadata
{
class OptionalHeaderTreeNode : ILSpyTreeNode
{
private PEFile module;
public OptionalHeaderTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => "Optional Header";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
var dataGrid = new DataGrid {
Columns = {
new DataGridTextColumn { IsReadOnly = true, Header = "Member", Binding = new Binding("Member") },
new DataGridTextColumn { IsReadOnly = true, Header = "Offset", Binding = new Binding("Offset") { StringFormat = "X8" } },
new DataGridTextColumn { IsReadOnly = true, Header = "Size", Binding = new Binding("Size") },
new DataGridTextColumn { IsReadOnly = true, Header = "Value", Binding = new Binding(".") { Converter = ByteWidthConverter.Instance } },
new DataGridTextColumn { IsReadOnly = true, Header = "Meaning", Binding = new Binding("Meaning") },
},
AutoGenerateColumns = false,
CanUserAddRows = false,
CanUserDeleteRows = false,
RowDetailsTemplateSelector = new DllCharacteristicsDataTemplateSelector(),
RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Visible
};
var headers = module.Reader.PEHeaders;
var reader = module.Reader.GetEntireImage().GetReader(headers.PEHeaderStartOffset, 128);
var header = headers.PEHeader;
var entries = new List<Entry>();
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 2, "Magic", header.Magic.ToString()));
entries.Add(new Entry(reader.Offset, reader.ReadByte(), 1, "Major Linker Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadByte(), 1, "Minor Linker Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Code Size", "Size of the code (text) section, or the sum of all code sections if there are multiple sections."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Initialized Data Size", "Size of the initialized data section, or the sum of all code sections if there are multiple data sections."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Uninitialized Data Size", "Size of the uninitialized data section, or the sum of all code sections if there are multiple uninitialized data sections."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Entry Point RVA", "RVA of entry point, needs to point to bytes 0xFF 0x25 followed by the RVA in a section marked execute / read for EXEs or 0 for DLLs"));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Base Of Code", "RVA of the code section."));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Base Of Data", "RVA of the data section."));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Image Base", "Shall be a multiple of 0x10000."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Section Alignment", "Shall be greater than File Alignment."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "File Alignment", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Major OS Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Minor OS Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Major Image Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Minor Image Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Major Subsystem Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Minor Subsystem Version", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt32(), 4, "Win32VersionValue", ""));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Image Size", "Size, in bytes, of image, including all headers and padding; shall be a multiple of Section Alignment."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Header Size", "Combined size of MS-DOS Header, PE Header, PE Optional Header and padding; shall be a multiple of the file alignment."));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "File Checksum", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "Subsystem", header.Subsystem.ToString()));
entries.Add(new Entry(reader.Offset, reader.ReadUInt16(), 4, "DLL Characteristics", header.DllCharacteristics.ToString()));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Stack Reserve Size", ""));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Stack Commit Size", ""));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Heap Reserve Size", ""));
entries.Add(new Entry(reader.Offset, header.Magic == PEMagic.PE32Plus ? reader.ReadUInt64() : reader.ReadUInt32(), header.Magic == PEMagic.PE32Plus ? 8 : 4, "Heap Commit Size", ""));
entries.Add(new Entry(reader.Offset, reader.ReadUInt32(), 4, "Loader Flags", ""));
entries.Add(new Entry(reader.Offset, reader.ReadInt32(), 4, "Number of Data Directories", ""));
dataGrid.ItemsSource = entries;
textView.ShowContent(new[] { this }, dataGrid);
return true;
}
private class DllCharacteristicsDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (((Entry)item).Member == "DLL Characteristics")
return MakeDataTemplate((ushort)((Entry)item).Value);
return new DataTemplate();
}
private DataTemplate MakeDataTemplate(ushort flags)
{
FrameworkElementFactory dataGridFactory = new FrameworkElementFactory(typeof(DataGrid));
dataGridFactory.SetValue(DataGrid.ItemsSourceProperty, new[] {
new { Value = (flags & 0x0001) != 0, Meaning = "Unused" },
new { Value = (flags & 0x0002) != 0, Meaning = "Unused" },
new { Value = (flags & 0x0004) != 0, Meaning = "Unused" },
new { Value = (flags & 0x0008) != 0, Meaning = "Unused" },
new { Value = (flags & 0x0010) != 0, Meaning = "Unused" },
new { Value = (flags & 0x0020) != 0, Meaning = "ASLR with 64-bit address space" },
new { Value = (flags & 0x0040) != 0, Meaning = "DLL can be relocated at load time" },
new { Value = (flags & 0x0080) != 0, Meaning = "Code integrity checks are enforced" },
new { Value = (flags & 0x0100) != 0, Meaning = "Image is NX compatible" },
new { Value = (flags & 0x0200) != 0, Meaning = "Isolation aware, but do not isolate the image" },
new { Value = (flags & 0x0400) != 0, Meaning = "Does not use structured exception handling (SEH)" },
new { Value = (flags & 0x0800) != 0, Meaning = "Do not bind the image" },
new { Value = (flags & 0x1000) != 0, Meaning = "Image should execute in an AppContainer" },
new { Value = (flags & 0x2000) != 0, Meaning = "Driver is a WDM Driver" },
new { Value = (flags & 0x4000) != 0, Meaning = "Image supports Control Flow Guard" },
new { Value = (flags & 0x8000) != 0, Meaning = "Image is Terminal Server aware" },
});
DataTemplate template = new DataTemplate();
template.VisualTree = dataGridFactory;
return template;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "Optional Header");
}
}
}

75
ILSpy/Metadata/StringHandleTemplate.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ICSharpCode.ILSpy.Metadata
{
public class StringHandleTemplate : DataTemplateSelector
{
public string ValuePropertyName { get; set; }
public string HandlePropertyName { get; set; }
private DataTemplate template;
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (template != null)
return template;
var textBlock = new FrameworkElementFactory(typeof(TextBlock), "textBlock");
textBlock.SetValue(FrameworkElement.MarginProperty, new Thickness(3, 1, 0, 0));
textBlock.SetBinding(TextBlock.TextProperty, new Binding(ValuePropertyName) { StringFormat = "\"{0}\"" });
var textBox = new FrameworkElementFactory(typeof(TextBox), "textBox");
textBox.SetBinding(TextBox.TextProperty, new Binding(ValuePropertyName) { StringFormat = "\"{0}\"", Mode = BindingMode.OneWay });
textBox.SetValue(TextBox.VisibilityProperty, Visibility.Hidden);
textBox.SetValue(TextBox.IsReadOnlyCaretVisibleProperty, true);
textBox.SetValue(TextBox.IsReadOnlyProperty, true);
textBox.SetBinding(FrameworkElement.ToolTipProperty, new MultiBinding {
Converter = new StringHandleConverter(),
Bindings = {
new Binding(HandlePropertyName),
new Binding(ValuePropertyName)
}
});
var grid = new FrameworkElementFactory(typeof(Grid));
grid.AppendChild(textBlock);
grid.AppendChild(textBox);
template = new DataTemplate {
VisualTree = grid,
Triggers = {
new Trigger {
Property = UIElement.IsMouseOverProperty,
Value = true,
Setters = {
new Setter(UIElement.VisibilityProperty, Visibility.Visible, "textBox"),
new Setter(UIElement.VisibilityProperty, Visibility.Hidden, "textBlock"),
}
},
new Trigger {
Property = UIElement.IsKeyboardFocusWithinProperty,
Value = true,
Setters = {
new Setter(UIElement.VisibilityProperty, Visibility.Visible, "textBox"),
new Setter(UIElement.VisibilityProperty, Visibility.Hidden, "textBlock"),
}
}
}
};
return template;
}
private class StringHandleConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return string.Format("{0:X} \"{1}\"", values[0], values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
}

125
ILSpy/Metadata/TypeDefTableTreeNode.cs

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.Metadata
{
internal class TypeDefTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public TypeDefTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"02 TypeDef ({module.Metadata.GetTableRowCount(TableIndex.TypeDef)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("TypeDefsView");
var metadata = module.Metadata;
var list = new List<TypeDefEntry>();
foreach (var row in metadata.TypeDefinitions)
list.Add(new TypeDefEntry(module, row));
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct TypeDefEntry : IMemberTreeNode
{
readonly int metadataOffset;
readonly PEFile module;
readonly MetadataReader metadata;
readonly TypeDefinitionHandle handle;
readonly TypeDefinition typeDef;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.TypeDef)
+ metadata.GetTableRowSize(TableIndex.TypeDef) * (RID-1);
public int Attributes => (int)typeDef.Attributes;
public string AttributesTooltip => Helpers.AttributesToString(typeDef.Attributes);
public int NameStringHandle => MetadataTokens.GetHeapOffset(typeDef.Name);
public string Name => metadata.GetString(typeDef.Name);
public int NamespaceStringHandle => MetadataTokens.GetHeapOffset(typeDef.Namespace);
public string Namespace => metadata.GetString(typeDef.Namespace);
public int BaseType => MetadataTokens.GetToken(typeDef.BaseType);
public string BaseTypeSignature {
get {
var output = new PlainTextOutput();
var provider = new DisassemblerSignatureProvider(module, output);
if (typeDef.BaseType.IsNil)
return null;
switch (typeDef.BaseType.Kind) {
case HandleKind.TypeDefinition:
provider.GetTypeFromDefinition(module.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
return output.ToString();
case HandleKind.TypeReference:
provider.GetTypeFromReference(module.Metadata, (TypeReferenceHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
return output.ToString();
case HandleKind.TypeSpecification:
provider.GetTypeFromSpecification(module.Metadata, new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module), (TypeSpecificationHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature);
return output.ToString();
default:
return null;
}
}
}
public int FieldList => MetadataTokens.GetToken(typeDef.GetFields().FirstOrDefault());
public int MethodList => MetadataTokens.GetToken(typeDef.GetMethods().FirstOrDefault());
IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemOrNull()?.MainModule).GetDefinition(handle);
public TypeDefEntry(PEFile module, TypeDefinitionHandle handle)
{
this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
this.module = module;
this.metadata = module.Metadata;
this.handle = handle;
this.typeDef = metadata.GetTypeDefinition(handle);
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "TypeDefs");
}
}
}

89
ILSpy/Metadata/TypeRefTableTreeNode.cs

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Windows.Controls;
using System.Windows.Data;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.Metadata
{
internal class TypeRefTableTreeNode : ILSpyTreeNode
{
private PEFile module;
public TypeRefTableTreeNode(PEFile module)
{
this.module = module;
}
public override object Text => $"01 TypeRef ({module.Metadata.GetTableRowCount(TableIndex.TypeRef)})";
public override object Icon => Images.Literal;
public override bool View(DecompilerTextView textView)
{
ListView view = Helpers.CreateListView("TypeRefsView");
var metadata = module.Metadata;
var list = new List<TypeRefEntry>();
foreach (var row in metadata.TypeReferences)
list.Add(new TypeRefEntry(module.Reader.PEHeaders.MetadataStartOffset, metadata, row, metadata.GetTypeReference(row)));
view.ItemsSource = list;
textView.ShowContent(new[] { this }, view);
return true;
}
struct TypeRefEntry
{
readonly int metadataOffset;
readonly MetadataReader metadata;
readonly TypeReferenceHandle handle;
readonly TypeReference typeRef;
public int RID => MetadataTokens.GetRowNumber(handle);
public int Token => MetadataTokens.GetToken(handle);
public int Offset => metadataOffset
+ metadata.GetTableMetadataOffset(TableIndex.TypeRef)
+ metadata.GetTableRowSize(TableIndex.TypeRef) * (RID-1);
public int ResolutionScope => MetadataTokens.GetToken(typeRef.ResolutionScope);
public int Name => MetadataTokens.GetHeapOffset(typeRef.Name);
public string NameTooltip => metadata.GetString(typeRef.Name);
public int Namespace => MetadataTokens.GetHeapOffset(typeRef.Namespace);
public string NamespaceTooltip => metadata.GetString(typeRef.Namespace);
public TypeRefEntry(int metadataOffset, MetadataReader metadata, TypeReferenceHandle handle, TypeReference typeRef)
{
this.metadataOffset = metadataOffset;
this.metadata = metadata;
this.handle = handle;
this.typeRef = typeRef;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, "TypeRefs");
}
}
}

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
typeSystem = LoadedAssembly.GetTypeSystemOrNull();
var assembly = (MetadataModule)typeSystem.MainModule;
var metadata = module.Metadata;
this.Children.Add(new Metadata.MetadataTreeNode(module, this));
this.Children.Add(new ReferenceFolderTreeNode(module, this));
if (module.Resources.Any())
this.Children.Add(new ResourceListTreeNode(module));

Loading…
Cancel
Save