.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

303 lines
9.6 KiB

// 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.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;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using DataGridExtensions;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata
{
static class Helpers
{
public static DataGrid PrepareDataGrid(TabPageModel tabPage, ILSpyTreeNode selectedNode)
{
if (!(tabPage.Content is DataGrid view && view.Name == "MetadataView"))
{
view = new MetaDataGrid() {
Name = "MetadataView",
GridLinesVisibility = DataGridGridLinesVisibility.None,
CanUserAddRows = false,
CanUserDeleteRows = false,
CanUserReorderColumns = false,
HeadersVisibility = DataGridHeadersVisibility.Column,
EnableColumnVirtualization = true,
EnableRowVirtualization = true,
RowHeight = 20,
IsReadOnly = true,
SelectionMode = DataGridSelectionMode.Single,
SelectionUnit = DataGridSelectionUnit.FullRow,
SelectedTreeNode = selectedNode,
CellStyle = (Style)MetadataTableViews.Instance["DataGridCellStyle"],
};
ContextMenuProvider.Add(view);
DataGridFilter.SetIsAutoFilterEnabled(view, true);
DataGridFilter.SetContentFilterFactory(view, new RegexContentFilterFactory());
}
DataGridFilter.GetFilter(view).Clear();
view.RowDetailsTemplateSelector = null;
view.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed;
((MetaDataGrid)view).SelectedTreeNode = selectedNode;
if (!view.AutoGenerateColumns)
view.Columns.Clear();
view.AutoGenerateColumns = true;
view.AutoGeneratingColumn += View_AutoGeneratingColumn;
view.AutoGeneratedColumns += View_AutoGeneratedColumns;
return view;
}
internal static void View_AutoGeneratedColumns(object sender, EventArgs e)
{
((DataGrid)sender).AutoGeneratedColumns -= View_AutoGeneratedColumns;
((DataGrid)sender).AutoGeneratingColumn -= View_AutoGeneratingColumn;
}
internal static void View_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay };
e.Column = new DataGridTextColumn() {
Header = e.PropertyName,
Binding = binding
};
switch (e.PropertyName)
{
case "RID":
case "Meaning":
e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["DefaultFilter"]);
break;
case "Token":
case "Offset":
case "RVA":
case "StartOffset":
case "Length":
binding.StringFormat = "X8";
e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]);
break;
case "RowDetails":
e.Cancel = true;
break;
default:
e.Cancel = e.PropertyName.Contains("Tooltip");
if (!e.Cancel)
{
e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["DefaultFilter"]);
}
break;
}
if (!e.Cancel)
{
ApplyAttributes((PropertyDescriptor)e.PropertyDescriptor, binding, e.Column);
}
}
static void ApplyAttributes(PropertyDescriptor descriptor, Binding binding, DataGridColumn column)
{
if (descriptor.PropertyType.IsEnum)
{
binding.Converter = new UnderlyingEnumValueConverter();
string key = descriptor.PropertyType.Name + "Filter";
column.SetTemplate((ControlTemplate)MetadataTableViews.Instance[key]);
}
var stringFormat = descriptor.Attributes.OfType<StringFormatAttribute>().FirstOrDefault();
if (stringFormat != null)
{
binding.StringFormat = stringFormat.Format;
if (!descriptor.PropertyType.IsEnum
&& stringFormat.Format.StartsWith("X", StringComparison.OrdinalIgnoreCase))
{
column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int GetValue(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);
fromHasFieldMarshalTag = typeof(TypeDefinitionHandle).Assembly
.GetType("System.Reflection.Metadata.Ecma335.HasFieldMarshalTag")
.GetMethod("ConvertToHandle", BindingFlags.Static | BindingFlags.NonPublic);
fromMemberForwardedTag = typeof(TypeDefinitionHandle).Assembly
.GetType("System.Reflection.Metadata.Ecma335.MemberForwardedTag")
.GetMethod("ConvertToHandle", BindingFlags.Static | BindingFlags.NonPublic);
}
readonly static FieldInfo rowCounts;
readonly static MethodInfo computeCodedTokenSize;
readonly static MethodInfo fromTypeDefOrRefTag;
readonly static MethodInfo fromHasFieldMarshalTag;
readonly static MethodInfo fromMemberForwardedTag;
public static EntityHandle FromHasFieldMarshalTag(uint tag)
{
return (EntityHandle)fromHasFieldMarshalTag.Invoke(null, new object[] { tag });
}
public static EntityHandle FromMemberForwardedTag(uint tag)
{
return (EntityHandle)fromMemberForwardedTag.Invoke(null, new object[] { tag });
}
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)
{
var t = value.GetType();
if (t.IsEnum)
{
return (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, value, false);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public static string ReadUTF8StringNullTerminated(this ref BlobReader reader)
{
int length = reader.IndexOf(0);
string s = reader.ReadUTF8(length);
reader.ReadByte();
return s;
}
}
class StringFormatAttribute : Attribute
{
public string Format { get; }
public StringFormatAttribute(string format)
{
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
}
}