Browse Source

Port ILFunction and SequencePointBuilder

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
adca1f8867
  1. 4
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  2. 10
      ICSharpCode.Decompiler/CecilExtensions.cs
  3. 22
      ICSharpCode.Decompiler/DecompilerException.cs
  4. 8
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  5. 226
      ICSharpCode.Decompiler/SRMExtensions.cs
  6. 8
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
  7. 12
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  8. 20
      ILSpy/Languages/Language.cs

4
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -314,10 +314,10 @@ namespace ICSharpCode.Decompiler.CSharp
newList.Add(sequencePoint); newList.Add(sequencePoint);
pos = sequencePoint.EndOffset; pos = sequencePoint.EndOffset;
} }
if (pos < function.CecilMethod.Body.CodeSize) { if (pos < function.CodeSize) {
var hidden = new Metadata.SequencePoint(); var hidden = new Metadata.SequencePoint();
hidden.Offset = pos; hidden.Offset = pos;
hidden.EndOffset = function.CecilMethod.Body.CodeSize; hidden.EndOffset = function.CodeSize;
hidden.SetHidden(); hidden.SetHidden();
newList.Add(hidden); newList.Add(hidden);
} }

10
ICSharpCode.Decompiler/CecilExtensions.cs

@ -31,16 +31,6 @@ namespace ICSharpCode.Decompiler
/// </summary> /// </summary>
public static class CecilExtensions public static class CecilExtensions
{ {
/// <summary>
/// Gets the (exclusive) end offset of this instruction.
/// </summary>
public static int GetEndOffset(this Instruction inst)
{
if (inst == null)
throw new ArgumentNullException(nameof(inst));
return inst.Offset + inst.GetSize();
}
public static string OffsetToString(int offset) public static string OffsetToString(int offset)
{ {
return string.Format("IL_{0:x4}", offset); return string.Format("IL_{0:x4}", offset);

22
ICSharpCode.Decompiler/DecompilerException.cs

@ -20,12 +20,12 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security; using System.Security;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
@ -34,20 +34,26 @@ namespace ICSharpCode.Decompiler
/// </summary> /// </summary>
public class DecompilerException : Exception, ISerializable public class DecompilerException : Exception, ISerializable
{ {
public AssemblyNameDefinition AssemblyName => DecompiledMethod.Module.Assembly.Name; public string AssemblyName => Module.FullName;
public string FileName => DecompiledMethod.Module.FileName; public string FileName => Module.FileName;
public FullTypeName DecompiledType => new FullTypeName(DecompiledMethod.DeclaringType.FullName); public MethodDefinitionHandle DecompiledMethod { get; }
public Metadata.PEFile Module { get; }
public MethodDefinition DecompiledMethod { get; } public DecompilerException(Metadata.PEFile module, MethodDefinitionHandle decompiledMethod, Exception innerException)
: base("Error decompiling " + GetFullName(decompiledMethod, module.GetMetadataReader()) + Environment.NewLine, innerException)
public DecompilerException(MethodDefinition decompiledMethod, Exception innerException)
: base("Error decompiling " + decompiledMethod.FullName + Environment.NewLine, innerException)
{ {
this.Module = module;
this.DecompiledMethod = decompiledMethod; this.DecompiledMethod = decompiledMethod;
} }
private static string GetFullName(MethodDefinitionHandle decompiledMethod, MetadataReader metadata)
{
var method = metadata.GetMethodDefinition(decompiledMethod);
return $"{method.GetDeclaringType().GetFullTypeName(metadata).ToString()}.{metadata.GetString(method.Name)}";
}
// This constructor is needed for serialization. // This constructor is needed for serialization.
protected DecompilerException(SerializationInfo info, StreamingContext context) : base(info, context) protected DecompilerException(SerializationInfo info, StreamingContext context) : base(info, context)
{ {

8
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -19,7 +19,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using Mono.Cecil;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -30,7 +29,7 @@ namespace ICSharpCode.Decompiler.IL
partial class ILFunction partial class ILFunction
{ {
public readonly IMethod Method; public readonly IMethod Method;
public readonly MethodDefinition CecilMethod; public readonly int CodeSize;
public readonly ILVariableCollection Variables; public readonly ILVariableCollection Variables;
/// <summary> /// <summary>
@ -73,11 +72,10 @@ namespace ICSharpCode.Decompiler.IL
public readonly IReadOnlyList<IParameter> Parameters; public readonly IReadOnlyList<IParameter> Parameters;
public ILFunction(IMethod method, MethodDefinition cecilMethod, ILInstruction body) : base(OpCode.ILFunction) public ILFunction(IMethod method, int codeSize, ILInstruction body) : base(OpCode.ILFunction)
{ {
this.Body = body; this.Body = body;
this.Method = method; this.Method = method;
this.CecilMethod = cecilMethod;
this.ReturnType = Method?.ReturnType; this.ReturnType = Method?.ReturnType;
this.Parameters = Method?.Parameters; this.Parameters = Method?.Parameters;
this.Variables = new ILVariableCollection(this); this.Variables = new ILVariableCollection(this);
@ -164,7 +162,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
var usedILRanges = new List<LongInterval>(); var usedILRanges = new List<LongInterval>();
MarkUsedILRanges(body); MarkUsedILRanges(body);
return new LongSet(new LongInterval(0, CecilMethod.Body.CodeSize)).ExceptWith(new LongSet(usedILRanges)); return new LongSet(new LongInterval(0, CodeSize)).ExceptWith(new LongSet(usedILRanges));
void MarkUsedILRanges(ILInstruction inst) void MarkUsedILRanges(ILInstruction inst)
{ {

226
ICSharpCode.Decompiler/SRMExtensions.cs

@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -82,11 +84,7 @@ namespace ICSharpCode.Decompiler
public static bool IsExtensionMethod(this MethodDefinition methodDefinition, MetadataReader reader) public static bool IsExtensionMethod(this MethodDefinition methodDefinition, MetadataReader reader)
{ {
if (methodDefinition.HasFlag(MethodAttributes.Static)) { if (methodDefinition.HasFlag(MethodAttributes.Static)) {
foreach (var attribute in methodDefinition.GetCustomAttributes()) { return methodDefinition.GetCustomAttributes().HasAttributeOfType<System.Runtime.CompilerServices.ExtensionAttribute>(reader);
string typeName = reader.GetCustomAttribute(attribute).GetAttributeType(reader).GetFullTypeName(reader).ToString();
if (typeName == "System.Runtime.CompilerServices.ExtensionAttribute")
return true;
}
} }
return false; return false;
} }
@ -136,23 +134,6 @@ namespace ICSharpCode.Decompiler
return accessors.Raiser; return accessors.Raiser;
} }
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new NotSupportedException();
}
}
public static TypeReferenceHandle GetDeclaringType(this TypeReference tr) public static TypeReferenceHandle GetDeclaringType(this TypeReference tr)
{ {
switch (tr.ResolutionScope.Kind) { switch (tr.ResolutionScope.Kind) {
@ -234,5 +215,206 @@ namespace ICSharpCode.Decompiler
throw new NotSupportedException(); throw new NotSupportedException();
} }
} }
public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata)
{
string name = metadata.GetString(type.Name);
if (type.Namespace.IsNil && type.HasGeneratedName(metadata) && (name.Contains("AnonType") || name.Contains("AnonymousType"))) {
return type.IsCompilerGenerated(metadata);
}
return false;
}
#region HasGeneratedName
public static bool IsGeneratedName(this StringHandle handle, MetadataReader metadata)
{
return !handle.IsNil && metadata.GetString(handle).StartsWith("<", StringComparison.Ordinal);
}
public static bool HasGeneratedName(this MethodDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetMethodDefinition(handle).Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this TypeDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetTypeDefinition(handle).Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this TypeDefinition type, MetadataReader metadata)
{
return type.Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this FieldDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetFieldDefinition(handle).Name.IsGeneratedName(metadata);
}
#endregion
#region IsCompilerGenerated
public static bool IsCompilerGenerated(this MethodDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetMethodDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGenerated(this MethodDefinition method, MetadataReader metadata)
{
return method.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
}
public static bool IsCompilerGenerated(this FieldDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetFieldDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGenerated(this FieldDefinition field, MetadataReader metadata)
{
return field.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
}
public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetTypeDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGenerated(this TypeDefinition type, MetadataReader metadata)
{
return type.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
}
#endregion
#region Attribute extensions
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new NotSupportedException();
}
}
public static bool HasCompilerGeneratedAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.Runtime.CompilerServices.CompilerGeneratedAttribute>(metadata);
}
public static bool HasParamArrayAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.ParamArrayAttribute>(metadata);
}
public static bool HasDefaultMemberAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.Reflection.DefaultMemberAttribute>(metadata);
}
public static bool HasAttributeOfType(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata, Type type)
{
var typeName = type.FullName;
foreach (var handle in customAttributes) {
var customAttribute = metadata.GetCustomAttribute(handle);
var attributeTypeName = customAttribute.GetAttributeType(metadata).GetFullTypeName(metadata).ToString();
if (typeName == attributeTypeName)
return true;
}
return false;
}
public static bool HasAttributeOfType<TAttribute>(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata) where TAttribute : Attribute
{
return HasAttributeOfType(customAttributes, metadata, typeof(TAttribute));
}
#endregion
public static byte[] GetInitialValue(this FieldDefinition field, PEReader pefile)
{
if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0)
return Empty<byte>.Array;
int rva = field.GetRelativeVirtualAddress();
int size = field.DecodeSignature(new FieldValueSizeDecoder(), default);
var headers = pefile.PEHeaders;
int index = headers.GetContainingSectionIndex(rva);
var sectionHeader = headers.SectionHeaders[index];
var sectionData = pefile.GetEntireImage();
int totalOffset = rva + sectionHeader.PointerToRawData - sectionHeader.VirtualAddress;
var reader = sectionData.GetReader();
reader.Offset += totalOffset;
int offset = field.GetOffset();
if (offset > 0)
reader.Offset += offset;
return reader.ReadBytes(size);
}
class FieldValueSizeDecoder : ISignatureTypeProvider<int, Unit>
{
public int GetArrayType(int elementType, ArrayShape shape) => elementType;
public int GetByReferenceType(int elementType) => elementType;
public int GetFunctionPointerType(MethodSignature<int> signature) => IntPtr.Size;
public int GetGenericInstantiation(int genericType, ImmutableArray<int> typeArguments) => throw new NotSupportedException();
public int GetGenericMethodParameter(Unit genericContext, int index) => throw new NotSupportedException();
public int GetGenericTypeParameter(Unit genericContext, int index) => throw new NotSupportedException();
public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType;
public int GetPinnedType(int elementType) => elementType;
public int GetPointerType(int elementType) => elementType;
public int GetPrimitiveType(PrimitiveTypeCode typeCode)
{
switch (typeCode) {
case PrimitiveTypeCode.Boolean:
case PrimitiveTypeCode.Byte:
case PrimitiveTypeCode.SByte:
return 1;
case PrimitiveTypeCode.Char:
case PrimitiveTypeCode.Int16:
case PrimitiveTypeCode.UInt16:
return 2;
case PrimitiveTypeCode.Int32:
case PrimitiveTypeCode.UInt32:
case PrimitiveTypeCode.Single:
return 4;
case PrimitiveTypeCode.Int64:
case PrimitiveTypeCode.UInt64:
case PrimitiveTypeCode.Double:
return 8;
case PrimitiveTypeCode.IntPtr:
case PrimitiveTypeCode.UIntPtr:
return IntPtr.Size;
default:
throw new NotSupportedException();
}
}
public int GetSZArrayType(int elementType) => throw new NotSupportedException();
public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
var td = reader.GetTypeDefinition(handle);
return td.GetLayout().Size;
}
public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
public int GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
}
} }
} }

8
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -80,14 +80,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
return context.GetSpecializingTypeSystem(newSubstitution); return context.GetSpecializingTypeSystem(newSubstitution);
} }
public Mono.Cecil.TypeDefinition GetCecil(ITypeDefinition typeDefinition) public System.Reflection.Metadata.MetadataReader GetMetadata()
{ {
return context.GetCecil(typeDefinition); return context.GetMetadata();
} }
public Mono.Cecil.MemberReference GetCecil(IMember member) public IMember ResolveAsMember(System.Reflection.Metadata.EntityHandle memberReference)
{ {
return context.GetCecil(member); throw new NotImplementedException();
} }
} }
} }

12
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -758,6 +758,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
#endregion #endregion
#region IsCompilerGenerated
static readonly FullTypeName compilerGeneratedAttributeTypeName = new FullTypeName("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
public static bool IsCompilerGenereated(this IEntity entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
return entity.GetAttribute(compilerGeneratedAttributeTypeName) != null;
}
#endregion
#region IAssembly.GetTypeDefinition(string,string,int) #region IAssembly.GetTypeDefinition(string,string,int)
/// <summary> /// <summary>
/// Gets the type definition for a top-level type. /// Gets the type definition for a top-level type.

20
ILSpy/Languages/Language.cs

@ -287,22 +287,26 @@ namespace ICSharpCode.ILSpy
} }
} }
public static string GetRuntimeDisplayName(PEFile module) public static string GetRuntimeDisplayName(TargetRuntime runtime)
{ {
string version = module.GetMetadataReader().MetadataVersion; switch (runtime) {
switch (version[1]) { case TargetRuntime.Net_1_0:
case '1':
if (version[3] == 1)
return ".NET 1.1"; return ".NET 1.1";
else case TargetRuntime.Net_1_1:
return ".NET 1.0"; return ".NET 1.0";
case '2': case TargetRuntime.Net_2_0:
return ".NET 2.0"; return ".NET 2.0";
case '4': case TargetRuntime.Net_4_0:
return ".NET 4.0"; return ".NET 4.0";
} }
return null; return null;
} }
public static string GetRuntimeDisplayName(PEFile module)
{
return GetRuntimeDisplayName(module.GetRuntime());
}
} }
class ILSignatureProvider : SRM.ISignatureTypeProvider<string, GenericContext> class ILSignatureProvider : SRM.ISignatureTypeProvider<string, GenericContext>

Loading…
Cancel
Save