Browse Source

Fix bugs when dealing with pinned local vars and varargs methods

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
fb41cfe4f8
  1. 48
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 90
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  3. 3
      ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
  4. 22
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  5. 20
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  6. 5
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

48
ICSharpCode.Decompiler/IL/ILReader.cs

@ -28,6 +28,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ArrayType = ICSharpCode.Decompiler.TypeSystem.ArrayType; using ArrayType = ICSharpCode.Decompiler.TypeSystem.ArrayType;
using ByReferenceType = ICSharpCode.Decompiler.TypeSystem.ByReferenceType; using ByReferenceType = ICSharpCode.Decompiler.TypeSystem.ByReferenceType;
using PinnedType = ICSharpCode.Decompiler.TypeSystem.Implementation.PinnedType;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
@ -53,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL
IMethod method; IMethod method;
MethodBodyBlock body; MethodBodyBlock body;
Metadata.IDebugInfoProvider debugInfo; Metadata.IDebugInfoProvider debugInfo;
ITypeResolveContext resolveContext;
MethodSignature<ITypeReference> methodSignature; MethodSignature<ITypeReference> methodSignature;
StackType methodReturnStackType; StackType methodReturnStackType;
BlobReader reader; BlobReader reader;
@ -86,8 +86,7 @@ namespace ICSharpCode.Decompiler.IL
this.currentStack = ImmutableStack<ILVariable>.Empty; this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>(); this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.resolveContext = new SimpleTypeResolveContext(this.method); this.methodReturnStackType = typeSystem.ResolveFromSignature(TypeSystem.Implementation.DynamicAwareTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata)).GetStackType();
this.methodReturnStackType = TypeSystem.Implementation.DynamicAwareTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata).Resolve(resolveContext).GetStackType();
InitParameterVariables(); InitParameterVariables();
localVariables = InitLocalVariables(); localVariables = InitLocalVariables();
if (body.LocalVariablesInitialized) { if (body.LocalVariablesInitialized) {
@ -140,7 +139,12 @@ namespace ICSharpCode.Decompiler.IL
void InitParameterVariables() void InitParameterVariables()
{ {
parameterVariables = new ILVariable[GetPopCount(OpCode.Call, method)]; int popCount = method.Parameters.Count;
if (!method.IsStatic)
popCount++;
if (method.Parameters.LastOrDefault()?.Type == SpecialType.ArgList)
popCount--;
parameterVariables = new ILVariable[popCount];
int paramIndex = 0; int offset = 0; int paramIndex = 0; int offset = 0;
if (methodSignature.Header.IsInstance) { if (methodSignature.Header.IsInstance) {
offset = 1; offset = 1;
@ -154,10 +158,17 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(paramIndex == parameterVariables.Length); Debug.Assert(paramIndex == parameterVariables.Length);
} }
ILVariable CreateILVariable(int index, ITypeReference type) ILVariable CreateILVariable(int index, ITypeReference typeRef)
{ {
VariableKind kind = IsPinned(type) ? VariableKind.PinnedLocal : VariableKind.Local; IType type = typeSystem.ResolveFromSignature(typeRef);
ILVariable ilVar = new ILVariable(kind, type.Resolve(resolveContext), index); VariableKind kind;
if (type is PinnedType pinned) {
kind = VariableKind.PinnedLocal;
type = pinned.ElementType;
} else {
kind = VariableKind.Local;
}
ILVariable ilVar = new ILVariable(kind, type, index);
if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) { if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) {
ilVar.Name = "V_" + index; ilVar.Name = "V_" + index;
ilVar.HasGeneratedName = true; ilVar.HasGeneratedName = true;
@ -170,14 +181,13 @@ namespace ICSharpCode.Decompiler.IL
return ilVar; return ilVar;
} }
bool IsPinned(ITypeReference type)
{
return type is TypeSystem.Implementation.PinnedTypeReference;
}
ILVariable CreateILVariable(int index, ITypeReference typeReference, string name) ILVariable CreateILVariable(int index, ITypeReference typeReference, string name)
{ {
IType parameterType = typeReference.Resolve(resolveContext); IType parameterType = typeSystem.ResolveFromSignature(typeReference);
ITypeDefinition def = parameterType.GetDefinition();
if (def != null && index < 0 && def.IsReferenceType == false) {
parameterType = new ByReferenceType(parameterType);
}
Debug.Assert(!parameterType.IsUnbound()); Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) { if (parameterType.IsUnbound()) {
// parameter types should not be unbound, the only known cause for these is a Cecil bug: // parameter types should not be unbound, the only known cause for these is a Cecil bug:
@ -1288,12 +1298,12 @@ namespace ICSharpCode.Decompiler.IL
var parameterTypes = new IType[signature.ParameterTypes.Length]; var parameterTypes = new IType[signature.ParameterTypes.Length];
var arguments = new ILInstruction[parameterTypes.Length]; var arguments = new ILInstruction[parameterTypes.Length];
for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) { for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) {
parameterTypes[i] = signature.ParameterTypes[i].Resolve(resolveContext); parameterTypes[i] = typeSystem.ResolveFromSignature(signature.ParameterTypes[i]);
arguments[i] = Pop(parameterTypes[i].GetStackType()); arguments[i] = Pop(parameterTypes[i].GetStackType());
} }
var call = new CallIndirect( var call = new CallIndirect(
signature.Header.CallingConvention, signature.Header.CallingConvention,
signature.ReturnType.Resolve(resolveContext), typeSystem.ResolveFromSignature(signature.ReturnType),
parameterTypes.ToImmutableArray(), parameterTypes.ToImmutableArray(),
arguments, arguments,
functionPointer functionPointer
@ -1304,14 +1314,6 @@ namespace ICSharpCode.Decompiler.IL
return call; return call;
} }
static int GetPopCount(OpCode callCode, IMethod method)
{
int popCount = method.Parameters.Count;
if (callCode != OpCode.NewObj && !method.IsStatic)
popCount++;
return popCount;
}
ILInstruction Comparison(ComparisonKind kind, bool un = false) ILInstruction Comparison(ComparisonKind kind, bool un = false)
{ {
var right = Pop(); var right = Pop();

90
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -98,46 +98,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
entityDict[entity] = mr; entityDict[entity] = mr;
} }
/* public IType ResolveFromSignature(ITypeReference typeReference)
Metadata.IMetadataEntity GetMetadata(IUnresolvedEntity member)
{ {
if (member == null) return typeReference.Resolve(context);
return null;
lock (entityDict) {
if (entityDict.TryGetValue(member, out var mr))
return mr;
return null;
}
}
/// <summary>
/// Retrieves the Cecil member definition for the specified member.
/// </summary>
/// <remarks>
/// Returns null if the member is not defined in the module being decompiled.
/// </remarks>
public Metadata.IMetadataEntity GetMetadata(IMember member)
{
if (member == null)
return null;
return GetMetadata(member.UnresolvedMember);
}
/// <summary>
/// Retrieves the Cecil type definition.
/// </summary>
/// <remarks>
/// Returns null if the type is not defined in the module being decompiled.
/// </remarks>
public Metadata.TypeDefinition GetMetadata(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return default;
return (Metadata.TypeDefinition)GetMetadata(typeDefinition.Parts[0]);
} }
*/
public IMember ResolveAsMember(SRM.EntityHandle memberReference) public IMember ResolveAsMember(SRM.EntityHandle memberReference)
{ {
@ -208,21 +172,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference); var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Field); Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Field);
declaringType = ResolveAsType(memberRef.Parent); declaringType = ResolveAsType(memberRef.Parent);
switch (memberRef.Parent.Kind) { field = FindNonGenericField(metadata, memberRef, declaringType);
case SRM.HandleKind.TypeReference:
field = FindNonGenericField(metadata, memberRef, declaringType);
break;
case SRM.HandleKind.TypeSpecification:
throw new NotImplementedException();
/*if (fieldReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)fieldReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null));
}*/
default:
throw new NotSupportedException();
}
break; break;
default:
throw new NotSupportedException();
}
if (declaringType.TypeArguments.Count > 0) {
field = (IField)field.Specialize(new TypeParameterSubstitution(declaringType.TypeArguments, null));
} }
fieldLookupCache.Add(fieldReference, field); fieldLookupCache.Add(fieldReference, field);
} }
@ -246,6 +202,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IField CreateFakeField(IType declaringType, string name, ITypeReference returnType) IField CreateFakeField(IType declaringType, string name, ITypeReference returnType)
{ {
Debug.Assert(false, $"Creating fake field for {name}!");
var f = new DefaultUnresolvedField(); var f = new DefaultUnresolvedField();
f.Name = name; f.Name = name;
f.ReturnType = returnType; f.ReturnType = returnType;
@ -281,13 +238,25 @@ namespace ICSharpCode.Decompiler.TypeSystem
IType declaringType; IType declaringType;
IReadOnlyList<IType> classTypeArguments = null; IReadOnlyList<IType> classTypeArguments = null;
IReadOnlyList<IType> methodTypeArguments = null; IReadOnlyList<IType> methodTypeArguments = null;
SRM.MethodSignature<ITypeReference>? signature = null;
if (!methodLookupCache.TryGetValue(methodReference, out method)) { if (!methodLookupCache.TryGetValue(methodReference, out method)) {
var metadata = moduleDefinition.GetMetadataReader(); var metadata = moduleDefinition.GetMetadataReader();
switch (methodReference.Kind) { switch (methodReference.Kind) {
case SRM.HandleKind.MethodDefinition: case SRM.HandleKind.MethodDefinition:
case SRM.HandleKind.MemberReference: var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference);
signature = methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
method = FindNonGenericMethod(metadata, methodReference, out declaringType); method = FindNonGenericMethod(metadata, methodReference, out declaringType);
break; break;
case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
var elementMethod = methodReference;
if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
elementMethod = (SRM.MethodDefinitionHandle)memberRef.Parent;
}
method = FindNonGenericMethod(metadata, elementMethod, out declaringType);
break;
case SRM.HandleKind.MethodSpecification: case SRM.HandleKind.MethodSpecification:
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference); var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
method = FindNonGenericMethod(metadata, methodSpec.Method, out declaringType); method = FindNonGenericMethod(metadata, methodSpec.Method, out declaringType);
@ -299,6 +268,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
if (signature?.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
method = new VarArgInstanceMethod(method, signature.Value.ParameterTypes.Skip(signature.Value.RequiredParameterCount).Select(p => p.Resolve(context)));
}
if (declaringType.TypeArguments.Count > 0) { if (declaringType.TypeArguments.Count > 0) {
classTypeArguments = declaringType.TypeArguments.ToList(); classTypeArguments = declaringType.TypeArguments.ToList();
} }
@ -338,8 +310,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
case SRM.HandleKind.MemberReference: case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference); var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method); Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
declaringType = ResolveAsType(memberRef.Parent);
// TODO : Support other handles // TODO : Support other handles
switch (memberRef.Parent.Kind) {
case SRM.HandleKind.MethodDefinition:
FindNonGenericMethod(metadata, memberRef.Parent, out declaringType);
break;
default:
declaringType = ResolveAsType(memberRef.Parent);
break;
}
declaringTypeDefinition = declaringType.GetDefinition(); declaringTypeDefinition = declaringType.GetDefinition();
var signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default); var signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
if (declaringTypeDefinition == null) { if (declaringTypeDefinition == null) {
@ -407,7 +386,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<ITypeReference> signature) IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<ITypeReference> signature)
{ {
Debug.Assert(false, $"Creating fake method for {name}!"); Debug.Assert(declaringType is ArrayType, $"Creating fake method for {name}!");
var m = new DefaultUnresolvedMethod(); var m = new DefaultUnresolvedMethod();
if (name == ".ctor" || name == ".cctor") if (name == ".ctor" || name == ".cctor")
m.SymbolKind = SymbolKind.Constructor; m.SymbolKind = SymbolKind.Constructor;
@ -416,7 +395,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
m.ReturnType = signature.ReturnType; m.ReturnType = signature.ReturnType;
m.IsStatic = !signature.Header.IsInstance; m.IsStatic = !signature.Header.IsInstance;
ITypeReference declaringTypeReference;
lock (typeReferenceCecilLoader) { lock (typeReferenceCecilLoader) {
var metadata = moduleDefinition.GetMetadataReader(); var metadata = moduleDefinition.GetMetadataReader();
for (int i = 0; i < signature.GenericParameterCount; i++) { for (int i = 0; i < signature.GenericParameterCount; i++) {

3
ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs

@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
public interface IDecompilerTypeSystem public interface IDecompilerTypeSystem
{ {
ICompilation Compilation { get; } ICompilation Compilation { get; }
IType ResolveFromSignature(ITypeReference typeReference);
IType ResolveAsType(EntityHandle typeReference); IType ResolveAsType(EntityHandle typeReference);
IField ResolveAsField(EntityHandle fieldReference); IField ResolveAsField(EntityHandle fieldReference);
IMethod ResolveAsMethod(EntityHandle methodReference); IMethod ResolveAsMethod(EntityHandle methodReference);

22
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -189,6 +189,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
sealed class TypeDefTokenTypeReference : ITypeReference
{
readonly SRM.EntityHandle token;
public TypeDefTokenTypeReference(SRM.EntityHandle token)
{
if (token.Kind != SRM.HandleKind.TypeDefinition)
throw new ArgumentException(nameof(token), "must be TypeDef token");
this.token = token;
}
public IType Resolve(ITypeResolveContext context)
{
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
if (td != null)
return td;
return SpecialType.UnknownType;
}
}
class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit> class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit>
{ {
public static readonly TypeReferenceSignatureDecoder Instance = new TypeReferenceSignatureDecoder(); public static readonly TypeReferenceSignatureDecoder Instance = new TypeReferenceSignatureDecoder();
@ -252,7 +272,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeReference GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{ {
return new GetClassTypeReference(handle.GetFullTypeName(reader), DefaultAssemblyReference.CurrentAssembly); return new TypeDefTokenTypeReference(handle);
} }
public ITypeReference GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)

20
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

@ -313,26 +313,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new NotSupportedException(); throw new NotSupportedException();
} }
} }
sealed class TypeDefTokenTypeReference : ITypeReference
{
readonly EntityHandle token;
public TypeDefTokenTypeReference(EntityHandle token)
{
if (token.Kind != HandleKind.TypeDefinition)
throw new ArgumentException(nameof(token), "must be TypeDef token");
this.token = token;
}
public IType Resolve(ITypeResolveContext context)
{
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
if (td != null)
return td;
return SpecialType.UnknownType;
}
}
#endregion #endregion
#region Read Attributes #region Read Attributes

5
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -53,6 +53,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return substitution; } get { return substitution; }
} }
public IType ResolveFromSignature(ITypeReference typeReference)
{
return context.ResolveFromSignature(typeReference).AcceptVisitor(substitution);
}
public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference) public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference)
{ {
return context.ResolveAsType(typeReference).AcceptVisitor(substitution); return context.ResolveAsType(typeReference).AcceptVisitor(substitution);

Loading…
Cancel
Save