diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 00f5f5d0c..eef9ee3a6 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -135,6 +135,18 @@ + + Code + MSBuild:Compile + + + Code + MSBuild:Compile + + + Code + MSBuild:Compile + Code MSBuild:Compile diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs index b5dcd3a43..bf7da39fb 100644 --- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs @@ -101,7 +101,6 @@ namespace ICSharpCode.ILSpy.Metadata public string ParentTooltip { get { - return null; ITextOutput output = new PlainTextOutput(); var context = new GenericContext(default(TypeDefinitionHandle), module); ((EntityHandle)classLayout.Parent).WriteTo(module, output, context); @@ -123,13 +122,13 @@ namespace ICSharpCode.ILSpy.Metadata var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ClassLayout) + metadata.GetTableRowSize(TableIndex.ClassLayout) * (row - 1); this.Offset = metadataOffset + rowOffset; - this.classLayout = new ClassLayout(ptr, metadata.GetTableRowCount(TableIndex.TypeDef) <= ushort.MaxValue); + this.classLayout = new ClassLayout(ptr + rowOffset, metadata.GetTableRowCount(TableIndex.TypeDef) <= ushort.MaxValue); } } public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { - language.WriteCommentLine(output, "CustomAttributes"); + language.WriteCommentLine(output, "ClassLayouts"); } } } diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs new file mode 100644 index 000000000..00ff4ba15 --- /dev/null +++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs @@ -0,0 +1,140 @@ +// 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.Linq; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.InteropServices; +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.ILSpy.TextView; +using ICSharpCode.ILSpy.TreeNodes; + +namespace ICSharpCode.ILSpy.Metadata +{ + class EventMapTableTreeNode : ILSpyTreeNode + { + private PEFile module; + + public EventMapTableTreeNode(PEFile module) + { + this.module = module; + } + + public override object Text => $"12 EventMap ({module.Metadata.GetTableRowCount(TableIndex.EventMap)})"; + + 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); + var metadata = module.Metadata; + + var list = new List(); + + var length = metadata.GetTableRowCount(TableIndex.EventMap); + byte* ptr = metadata.MetadataPointer; + int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + for (int rid = 1; rid <= length; rid++) { + list.Add(new EventMapEntry(module, ptr, metadataOffset, rid)); + } + + view.ItemsSource = list; + + tabPage.Content = view; + return true; + } + + readonly struct EventMap + { + public readonly TypeDefinitionHandle Parent; + public readonly EventDefinitionHandle EventList; + + public unsafe EventMap(byte *ptr, int typeDefSize, int eventDefSize) + { + Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetRowNum(ptr, typeDefSize)); + EventList = MetadataTokens.EventDefinitionHandle(Helpers.GetRowNum(ptr + typeDefSize, eventDefSize)); + } + } + + unsafe struct EventMapEntry + { + readonly PEFile module; + readonly MetadataReader metadata; + readonly EventMap eventMap; + + public int RID { get; } + + public int Token => 0x12000000 | RID; + + public int Offset { get; } + + [StringFormat("X8")] + public int Parent => MetadataTokens.GetToken(eventMap.Parent); + + public string ParentTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)eventMap.Parent).WriteTo(module, output, context); + return output.ToString(); + } + } + + [StringFormat("X8")] + public int EventList => MetadataTokens.GetToken(eventMap.EventList); + + public string EventListTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)eventMap.EventList).WriteTo(module, output, context); + return output.ToString(); + } + } + + public EventMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) + { + this.module = module; + this.metadata = module.Metadata; + this.RID = row; + var rowOffset = metadata.GetTableMetadataOffset(TableIndex.EventMap) + + metadata.GetTableRowSize(TableIndex.EventMap) * (row - 1); + this.Offset = metadataOffset + rowOffset; + int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; + int eventDefSize = metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4; + this.eventMap = new EventMap(ptr + rowOffset, typeDefSize, eventDefSize); + } + } + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, "EventMap"); + } + } +} diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs new file mode 100644 index 000000000..86de64b6b --- /dev/null +++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs @@ -0,0 +1,138 @@ +// 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.Linq; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.InteropServices; +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.ILSpy.TextView; +using ICSharpCode.ILSpy.TreeNodes; + +namespace ICSharpCode.ILSpy.Metadata +{ + class InterfaceImplTableTreeNode : ILSpyTreeNode + { + private PEFile module; + + public InterfaceImplTableTreeNode(PEFile module) + { + this.module = module; + } + + public override object Text => $"09 InterfaceImpl ({module.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})"; + + 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); + var metadata = module.Metadata; + + var list = new List(); + + var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl); + byte* ptr = metadata.MetadataPointer; + int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + for (int rid = 1; rid <= length; rid++) { + list.Add(new InterfaceImplEntry(module, ptr, metadataOffset, rid)); + } + + view.ItemsSource = list; + + tabPage.Content = view; + return true; + } + + readonly struct InterfaceImpl + { + public readonly EntityHandle Class; + public readonly EntityHandle Interface; + + public unsafe InterfaceImpl(byte *ptr, int classSize, int interfaceSize) + { + Class = MetadataTokens.TypeDefinitionHandle(Helpers.GetRowNum(ptr, classSize)); + Interface = Helpers.FromTypeDefOrRefTag((uint)Helpers.GetRowNum(ptr + classSize, interfaceSize)); + } + } + + unsafe struct InterfaceImplEntry + { + readonly PEFile module; + readonly MetadataReader metadata; + readonly InterfaceImpl interfaceImpl; + + public int RID { get; } + + public int Token => 0x09000000 | RID; + + public int Offset { get; } + + [StringFormat("X8")] + public int Class => MetadataTokens.GetToken(interfaceImpl.Class); + + public string ClassTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)interfaceImpl.Class).WriteTo(module, output, context); + return output.ToString(); + } + } + + [StringFormat("X8")] + public int Interface => MetadataTokens.GetToken(interfaceImpl.Interface); + + public string InterfaceTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)interfaceImpl.Interface).WriteTo(module, output, context); + return output.ToString(); + } + } + + public InterfaceImplEntry(PEFile module, byte* ptr, int metadataOffset, int row) + { + this.module = module; + this.metadata = module.Metadata; + this.RID = row; + var rowOffset = metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl) + + metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1); + this.Offset = metadataOffset + rowOffset; + this.interfaceImpl = new InterfaceImpl(ptr + rowOffset, metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec)); + } + } + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, "InterfaceImpls"); + } + } +} diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs new file mode 100644 index 000000000..889d101f4 --- /dev/null +++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs @@ -0,0 +1,140 @@ +// 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.Linq; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.InteropServices; +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.ILSpy.TextView; +using ICSharpCode.ILSpy.TreeNodes; + +namespace ICSharpCode.ILSpy.Metadata +{ + class PropertyMapTableTreeNode : ILSpyTreeNode + { + private PEFile module; + + public PropertyMapTableTreeNode(PEFile module) + { + this.module = module; + } + + public override object Text => $"15 PropertyMap ({module.Metadata.GetTableRowCount(TableIndex.PropertyMap)})"; + + 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); + var metadata = module.Metadata; + + var list = new List(); + + var length = metadata.GetTableRowCount(TableIndex.PropertyMap); + byte* ptr = metadata.MetadataPointer; + int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + for (int rid = 1; rid <= length; rid++) { + list.Add(new PropertyMapEntry(module, ptr, metadataOffset, rid)); + } + + view.ItemsSource = list; + + tabPage.Content = view; + return true; + } + + readonly struct PropertyMap + { + public readonly TypeDefinitionHandle Parent; + public readonly PropertyDefinitionHandle PropertyList; + + public unsafe PropertyMap(byte *ptr, int typeDefSize, int propertyDefSize) + { + Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetRowNum(ptr, typeDefSize)); + PropertyList = MetadataTokens.PropertyDefinitionHandle(Helpers.GetRowNum(ptr + typeDefSize, propertyDefSize)); + } + } + + unsafe struct PropertyMapEntry + { + readonly PEFile module; + readonly MetadataReader metadata; + readonly PropertyMap propertyMap; + + public int RID { get; } + + public int Token => 0x15000000 | RID; + + public int Offset { get; } + + [StringFormat("X8")] + public int Parent => MetadataTokens.GetToken(propertyMap.Parent); + + public string ParentTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)propertyMap.Parent).WriteTo(module, output, context); + return output.ToString(); + } + } + + [StringFormat("X8")] + public int EventList => MetadataTokens.GetToken(propertyMap.PropertyList); + + public string PropertyListTooltip { + get { + ITextOutput output = new PlainTextOutput(); + var context = new GenericContext(default(TypeDefinitionHandle), module); + ((EntityHandle)propertyMap.PropertyList).WriteTo(module, output, context); + return output.ToString(); + } + } + + public PropertyMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) + { + this.module = module; + this.metadata = module.Metadata; + this.RID = row; + var rowOffset = metadata.GetTableMetadataOffset(TableIndex.PropertyMap) + + metadata.GetTableRowSize(TableIndex.PropertyMap) * (row - 1); + this.Offset = metadataOffset + rowOffset; + int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; + int propertyDefSize = metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4; + this.propertyMap = new PropertyMap(ptr + rowOffset, typeDefSize, propertyDefSize); + } + } + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, "PropertyMap"); + } + } +} diff --git a/ILSpy/Metadata/Helpers.cs b/ILSpy/Metadata/Helpers.cs index 73625a902..2e355d706 100644 --- a/ILSpy/Metadata/Helpers.cs +++ b/ILSpy/Metadata/Helpers.cs @@ -22,7 +22,9 @@ using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; @@ -126,6 +128,42 @@ namespace ICSharpCode.ILSpy.Metadata } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe int GetRowNum(byte* ptr, int size) + { + int result = 0; + for (int i = 0; i < size; i += 2) { + result |= ptr[i] << 8 * i; + result |= ptr[i + 1] << 8 * (i + 1); + } + return result; + } + + static Helpers() + { + rowCounts = typeof(MetadataReader) + .GetField("TableRowCounts", BindingFlags.NonPublic | BindingFlags.Instance); + computeCodedTokenSize = typeof(MetadataReader) + .GetMethod("ComputeCodedTokenSize", BindingFlags.Instance | BindingFlags.NonPublic); + fromTypeDefOrRefTag = typeof(TypeDefinitionHandle).Assembly + .GetType("System.Reflection.Metadata.Ecma335.TypeDefOrRefTag") + .GetMethod("ConvertToHandle", BindingFlags.Static | BindingFlags.NonPublic); + } + + readonly static FieldInfo rowCounts; + readonly static MethodInfo computeCodedTokenSize; + readonly static MethodInfo fromTypeDefOrRefTag; + + public static EntityHandle FromTypeDefOrRefTag(uint tag) + { + return (EntityHandle)fromTypeDefOrRefTag.Invoke(null, new object[] { tag }); + } + + public static int ComputeCodedTokenSize(this MetadataReader metadata, int largeRowSize, TableMask mask) + { + return (int)computeCodedTokenSize.Invoke(metadata, new object[] { largeRowSize, rowCounts.GetValue(metadata), (ulong)mask }); + } + class UnderlyingEnumValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) @@ -155,4 +193,64 @@ namespace ICSharpCode.ILSpy.Metadata this.Format = format; } } + + [Flags] + internal enum TableMask : ulong + { + Module = 0x1, + TypeRef = 0x2, + TypeDef = 0x4, + FieldPtr = 0x8, + Field = 0x10, + MethodPtr = 0x20, + MethodDef = 0x40, + ParamPtr = 0x80, + Param = 0x100, + InterfaceImpl = 0x200, + MemberRef = 0x400, + Constant = 0x800, + CustomAttribute = 0x1000, + FieldMarshal = 0x2000, + DeclSecurity = 0x4000, + ClassLayout = 0x8000, + FieldLayout = 0x10000, + StandAloneSig = 0x20000, + EventMap = 0x40000, + EventPtr = 0x80000, + Event = 0x100000, + PropertyMap = 0x200000, + PropertyPtr = 0x400000, + Property = 0x800000, + MethodSemantics = 0x1000000, + MethodImpl = 0x2000000, + ModuleRef = 0x4000000, + TypeSpec = 0x8000000, + ImplMap = 0x10000000, + FieldRva = 0x20000000, + EnCLog = 0x40000000, + EnCMap = 0x80000000, + Assembly = 0x100000000, + AssemblyRef = 0x800000000, + File = 0x4000000000, + ExportedType = 0x8000000000, + ManifestResource = 0x10000000000, + NestedClass = 0x20000000000, + GenericParam = 0x40000000000, + MethodSpec = 0x80000000000, + GenericParamConstraint = 0x100000000000, + Document = 0x1000000000000, + MethodDebugInformation = 0x2000000000000, + LocalScope = 0x4000000000000, + LocalVariable = 0x8000000000000, + LocalConstant = 0x10000000000000, + ImportScope = 0x20000000000000, + StateMachineMethod = 0x40000000000000, + CustomDebugInformation = 0x80000000000000, + PtrTables = 0x4800A8, + EncTables = 0xC0000000, + TypeSystemTables = 0x1FC9FFFFFFFF, + DebugTables = 0xFF000000000000, + AllTables = 0xFF1FC9FFFFFFFF, + ValidPortablePdbExternalTables = 0x1FC93FB7FF57 + } } diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs index d1e7c5082..dbf5dcb43 100644 --- a/ILSpy/Metadata/MetadataTreeNode.cs +++ b/ILSpy/Metadata/MetadataTreeNode.cs @@ -73,14 +73,16 @@ namespace ICSharpCode.ILSpy.Metadata this.Children.Add(new FieldTableTreeNode(module)); this.Children.Add(new MethodTableTreeNode(module)); this.Children.Add(new ParamTableTreeNode(module)); - //this.Children.Add(new InterfaceImplTableTreeNode(module)); + this.Children.Add(new InterfaceImplTableTreeNode(module)); this.Children.Add(new MemberRefTableTreeNode(module)); this.Children.Add(new ConstantTableTreeNode(module)); this.Children.Add(new CustomAttributeTableTreeNode(module)); this.Children.Add(new DeclSecurityTableTreeNode(module)); this.Children.Add(new ClassLayoutTableTreeNode(module)); this.Children.Add(new StandAloneSigTableTreeNode(module)); + this.Children.Add(new EventMapTableTreeNode(module)); this.Children.Add(new EventTableTreeNode(module)); + this.Children.Add(new PropertyMapTableTreeNode(module)); this.Children.Add(new PropertyTableTreeNode(module)); this.Children.Add(new MethodSemanticsTableTreeNode(module)); this.Children.Add(new MethodImplTableTreeNode(module));