From 50686097fbbe4520fe6022fb10d6c4ba04d364e1 Mon Sep 17 00:00:00 2001 From: fcurdi Date: Sat, 16 May 2020 11:30:17 -0300 Subject: [PATCH 1/3] add IsVirtual property to IMethodReference --- MetadataProvider/AssemblyExtractor.cs | 20 ++++++++++++++++++-- Model/Types/TypeDefinitions.cs | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/MetadataProvider/AssemblyExtractor.cs b/MetadataProvider/AssemblyExtractor.cs index 66787d90..f058f90f 100644 --- a/MetadataProvider/AssemblyExtractor.cs +++ b/MetadataProvider/AssemblyExtractor.cs @@ -971,8 +971,10 @@ private IInstruction ExtractInstruction(ILInstruction operation) break; case SRM.ILOpCode.Ldftn: + instruction = ProcessLoadMethodAddress(operation, false); + break; case SRM.ILOpCode.Ldvirtftn: - instruction = ProcessLoadMethodAddress(operation); + instruction = ProcessLoadMethodAddress(operation, true); break; case SRM.ILOpCode.Ldc_i4: @@ -1573,10 +1575,24 @@ private IInstruction ProcessLoadField(ILInstruction op) return instruction; } - private IInstruction ProcessLoadMethodAddress(ILInstruction op) + private IInstruction ProcessLoadMethodAddress(ILInstruction op, bool isVirtual) { var operation = OperationHelper.ToLoadMethodAddressOperation(op.Opcode); var method = GetOperand(op); + switch (method) + { + case MethodDefinition methodDefinition: + { + methodDefinition.IsVirtual = isVirtual; + break; + } + case MethodReference methodReference: + { + methodReference.IsVirtual = isVirtual; + break; + } + default: throw new Exception("case not handled"); + } var instruction = new LoadMethodAddressInstruction(op.Offset, operation, method); return instruction; diff --git a/Model/Types/TypeDefinitions.cs b/Model/Types/TypeDefinitions.cs index 27062ea7..752a3540 100644 --- a/Model/Types/TypeDefinitions.cs +++ b/Model/Types/TypeDefinitions.cs @@ -286,6 +286,7 @@ public interface IMethodReference : ITypeMemberReference, IMetadataReference, IG IMethodReference GenericMethod { get; } MethodDefinition ResolvedMethod { get; } bool IsStatic { get; } + bool IsVirtual { get; } } public class MethodReference : IMethodReference @@ -302,6 +303,7 @@ public class MethodReference : IMethodReference public IList Parameters { get; private set; } public IMethodReference GenericMethod { get; set; } public bool IsStatic { get; set; } + public bool IsVirtual { get; set; } public MethodReference(string name, IType returnType) { From 5c27c62d3c10b014a5bc371e503eb8803c7081c4 Mon Sep 17 00:00:00 2001 From: fcurdi Date: Sat, 22 Aug 2020 17:07:26 -0300 Subject: [PATCH 2/3] fix method instantiation problem --- MetadataProvider/AssemblyExtractor.cs | 5 ++++- Model/Types/TypeDefinitions.cs | 29 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/MetadataProvider/AssemblyExtractor.cs b/MetadataProvider/AssemblyExtractor.cs index f058f90f..ae625ebf 100644 --- a/MetadataProvider/AssemblyExtractor.cs +++ b/MetadataProvider/AssemblyExtractor.cs @@ -1307,7 +1307,10 @@ private IMethodReference GetMethodReference(SRM.MethodSpecificationHandle handle CreateGenericParameterReferences(GenericParameterKind.Method, genericArguments.Length); var method = GetMethodReference(methodspec.Method); - method = method.Instantiate(genericArguments); + // method might have not been extracted yet so some properties might be missing (ex: returnType, isStatic, etc). + // a proxy is used instead so when the method is actually extracted, this instantiated one is also complete. Otherwise the instantiated + // one will have null in some of its properties. + method = new MethodInstantiationProxy(method, genericArguments); BindGenericParameterReferences(GenericParameterKind.Method, method); return method; diff --git a/Model/Types/TypeDefinitions.cs b/Model/Types/TypeDefinitions.cs index 752a3540..e17d7a7e 100644 --- a/Model/Types/TypeDefinitions.cs +++ b/Model/Types/TypeDefinitions.cs @@ -587,6 +587,35 @@ public override string ToString() return result.ToString(); } } + + public class MethodInstantiationProxy : IMethodReference + { + public IBasicType ContainingType => method.ContainingType; + public ISet Attributes => method.Attributes; + public int GenericParameterCount => method.GenericParameterCount; + public IType ReturnType => method.ReturnType; + public string Name => method.Name; + public string GenericName => method.GenericName; + public IList Parameters => method.Parameters; + public IList GenericArguments => genericArguments; + public IMethodReference GenericMethod => method; + + public MethodDefinition ResolvedMethod => + throw new InvalidOperationException("Use Resolve method to bind this reference with some host."); + + public bool IsStatic => method.IsStatic; + public bool IsVirtual => method.IsVirtual; + + private readonly IMethodReference method; + private readonly IList genericArguments; + + public MethodInstantiationProxy(IMethodReference method, IEnumerable genericArguments) + { + this.method = method; + this.genericArguments = new List(); + this.genericArguments.AddRange(genericArguments); + } + } public enum TypeDefinitionKind { From 29a56ee90f5634e824e365f49e3d2c2c39f685cf Mon Sep 17 00:00:00 2001 From: fcurdi Date: Sat, 22 Aug 2020 17:28:38 -0300 Subject: [PATCH 3/3] comment --- MetadataProvider/AssemblyExtractor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MetadataProvider/AssemblyExtractor.cs b/MetadataProvider/AssemblyExtractor.cs index ae625ebf..9a500c8c 100644 --- a/MetadataProvider/AssemblyExtractor.cs +++ b/MetadataProvider/AssemblyExtractor.cs @@ -1307,9 +1307,9 @@ private IMethodReference GetMethodReference(SRM.MethodSpecificationHandle handle CreateGenericParameterReferences(GenericParameterKind.Method, genericArguments.Length); var method = GetMethodReference(methodspec.Method); - // method might have not been extracted yet so some properties might be missing (ex: returnType, isStatic, etc). - // a proxy is used instead so when the method is actually extracted, this instantiated one is also complete. Otherwise the instantiated - // one will have null in some of its properties. + // method might have not been extracted yet so some fields might be missing (ex: returnType, isStatic, etc). + // a proxy is used instead so when the method is actually extracted, this instantiated one is updated as well. + // Otherwise the instantiated one would have some null fields. method = new MethodInstantiationProxy(method, genericArguments); BindGenericParameterReferences(GenericParameterKind.Method, method);