private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch) { uint numTargetImplementations = entryParser.GetUnsigned(); for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle)) { // Skip over signatures data for (uint l = 0; l < numIfaceSigs; l++) entryParser.GetUnsigned(); continue; } for (uint l = 0; l < numIfaceSigs; l++) { RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle); NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned())); IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr)) { Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller declaringType = targetTypeHandle; methodNameAndSignature = targetMethodNameAndSignature; return true; } } } } } return false; }
public static RuntimeTypeHandle GetTypeFromNativeLayoutSignature(ref NativeParser parser, uint offset) { IntPtr remainingSignature; RuntimeTypeHandle typeHandle; IntPtr signatureAddress = parser.Reader.OffsetToAddress(offset); bool success = TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(signatureAddress, null, null, out typeHandle, out remainingSignature); // Reset the parser to after the type parser = new NativeParser(parser.Reader, parser.Reader.AddressToOffset(remainingSignature)); return typeHandle; }
public MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, uint nativeLayoutOffset) { NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset); string methodName = parser.GetString(); // Signatures are indirected to through a relative offset so that we don't have to parse them // when not comparing signatures (parsing them requires resolving types and is tremendously // expensive). NativeParser sigParser = parser.GetParserFromRelativeOffset(); IntPtr methodSigPtr = sigParser.Reader.OffsetToAddress(sigParser.Offset); return new MethodNameAndSignature(methodName, methodSigPtr); }
public static bool CompareMethodSigWithMethodInfo(NativeParser reader, MethodBase methodBase) { if (!CompareCallingConventions((MethodCallingConvention)reader.GetUnsigned(), methodBase)) return false; // Sigs are encoded in the native layout as uninstantiated. Work with the generic method def // here so that the arguments will compare properly. MethodBase uninstantiatedMethod = methodBase; if (methodBase is MethodInfo && methodBase.IsGenericMethod && !methodBase.IsGenericMethodDefinition) { uninstantiatedMethod = ((MethodInfo)methodBase).GetGenericMethodDefinition(); } if (uninstantiatedMethod.IsGenericMethod) { uint genericParamCount1 = reader.GetUnsigned(); int genericParamCount2 = uninstantiatedMethod.GetGenericArguments().Length; if (genericParamCount1 != genericParamCount2) return false; } uint parameterCount = reader.GetUnsigned(); if (parameterCount != uninstantiatedMethod.GetParameters().Length) return false; if (uninstantiatedMethod is MethodInfo) { // Not a constructor. Compare return types if (!CompareTypeSigWithType(ref reader, ((MethodInfo)uninstantiatedMethod).ReturnType)) return false; } else { Debug.Assert(uninstantiatedMethod is ConstructorInfo); // The first parameter had better be void on a constructor if (!CompareTypeSigWithType(ref reader, CommonRuntimeTypes.Void)) return false; } for (uint i = 0; i < parameterCount; i++) { if (!CompareTypeSigWithType(ref reader, uninstantiatedMethod.GetParameters()[i].ParameterType)) return false; } return true; }
private static RuntimeTypeHandle[] GetTypeSequence(ref ExternalReferencesTable extRefs, ref NativeParser parser) { uint count = parser.GetUnsigned(); RuntimeTypeHandle[] result = new RuntimeTypeHandle[count]; for (uint i = 0; i < count; i++) result[i] = extRefs.GetRuntimeTypeHandleFromIndex(parser.GetUnsigned()); return result; }
private bool CompareTypeSigs(ref NativeParser parser1, NativeFormatModuleInfo moduleHandle1, ref NativeParser parser2, NativeFormatModuleInfo moduleHandle2) { // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint data1; uint startOffset1 = parser1.Offset; var typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1); // If the parser is at a lookback type, get a new parser for it and recurse. // Since we haven't read the element type of parser2 yet, we just pass it in unchanged if (typeSignatureKind1 == TypeSignatureKind.Lookback) { NativeParser lookbackParser1 = parser1.GetLookbackParser(data1); return(CompareTypeSigs(ref lookbackParser1, moduleHandle1, ref parser2, moduleHandle2)); } uint data2; uint startOffset2 = parser2.Offset; var typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2); // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1 // before recursing. if (typeSignatureKind2 == TypeSignatureKind.Lookback) { NativeParser lookbackParser2 = parser2.GetLookbackParser(data2); parser1 = new NativeParser(parser1.Reader, startOffset1); return(CompareTypeSigs(ref parser1, moduleHandle1, ref lookbackParser2, moduleHandle2)); } if (typeSignatureKind1 != typeSignatureKind2) { return(false); } switch (typeSignatureKind1) { case TypeSignatureKind.Lookback: { // Recursion above better have removed all lookbacks Debug.Assert(false, "Unexpected lookback type"); return(false); } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same if (data1 != data2) { return(false); } return(CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)); } case TypeSignatureKind.Variable: { // variable index is in data if (data1 != data2) { return(false); } break; } case TypeSignatureKind.MultiDimArray: { // rank is in data if (data1 != data2) { return(false); } if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) { return(false); } uint boundCount1 = parser1.GetUnsigned(); uint boundCount2 = parser2.GetUnsigned(); if (boundCount1 != boundCount2) { return(false); } for (uint i = 0; i < boundCount1; i++) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) { return(false); } } uint lowerBoundCount1 = parser1.GetUnsigned(); uint lowerBoundCount2 = parser2.GetUnsigned(); if (lowerBoundCount1 != lowerBoundCount2) { return(false); } for (uint i = 0; i < lowerBoundCount1; i++) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) { return(false); } } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data if (data1 != data2) { return(false); } uint argCount1 = parser1.GetUnsigned(); uint argCount2 = parser2.GetUnsigned(); if (argCount1 != argCount2) { return(false); } for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) { return(false); } } break; } case TypeSignatureKind.Instantiation: { // Type parameter count is in data if (data1 != data2) { return(false); } if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) { return(false); } for (uint i = 0; i < data1; i++) { if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) { return(false); } } break; } case TypeSignatureKind.External: { RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(moduleHandle1, data1); RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(moduleHandle2, data2); if (!typeHandle1.Equals(typeHandle2)) { return(false); } break; } default: return(false); } return(true); }
/// <summary> /// IF THESE SEMANTICS EVER CHANGE UPDATE THE LOGIC WHICH DEFINES THIS BEHAVIOR IN /// THE DYNAMIC TYPE LOADER AS WELL AS THE COMPILER. /// /// Parameter's are considered to have type layout dependent on their generic instantiation /// if the type of the parameter in its signature is a type variable, or if the type is a generic /// structure which meets 2 characteristics: /// 1. Structure size/layout is affected by the size/layout of one or more of its generic parameters /// 2. One or more of the generic parameters is a type variable, or a generic structure which also recursively /// would satisfy constraint 2. (Note, that in the recursion case, whether or not the structure is affected /// by the size/layout of its generic parameters is not investigated.) /// /// Examples parameter types, and behavior. /// /// T = true /// List[T] = false /// StructNotDependentOnArgsForSize[T] = false /// GenStructDependencyOnArgsForSize[T] = true /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false /// /// Example non-parameter type behavior /// T = true /// List[T] = false /// StructNotDependentOnArgsForSize[T] = *true* /// GenStructDependencyOnArgsForSize[T] = true /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false /// </summary> private bool TypeSignatureHasVarsNeedingCallingConventionConverter(ref NativeParser parser, NativeFormatModuleInfo moduleHandle, TypeSystemContext context, HasVarsInvestigationLevel investigationLevel) { uint data; var kind = parser.GetTypeSignatureKind(out data); switch (kind) { case TypeSignatureKind.External: return(false); case TypeSignatureKind.Variable: return(true); case TypeSignatureKind.Lookback: { var lookbackParser = parser.GetLookbackParser(data); return(TypeSignatureHasVarsNeedingCallingConventionConverter(ref lookbackParser, moduleHandle, context, investigationLevel)); } case TypeSignatureKind.Instantiation: { RuntimeTypeHandle genericTypeDef; if (!TryGetTypeFromSimpleTypeSignature(ref parser, moduleHandle, out genericTypeDef)) { Debug.Assert(false); return(true); // Returning true will prevent further reading from the native parser } if (!RuntimeAugments.IsValueType(genericTypeDef)) { // Reference types are treated like pointers. No calling convention conversion needed. Just consume the rest of the signature. for (uint i = 0; i < data; i++) { TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore); } return(false); } else { bool result = false; for (uint i = 0; i < data; i++) { result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.NotParameter) || result; } if ((result == true) && (investigationLevel == HasVarsInvestigationLevel.Parameter)) { if (!TryComputeHasInstantiationDeterminedSize(genericTypeDef, context, out result)) { Environment.FailFast("Unable to setup calling convention converter correctly"); } return(result); } return(result); } } case TypeSignatureKind.Modifier: { // Arrays, pointers and byref types signatures are treated as pointers, not requiring calling convention conversion. // Just consume the parameter type from the stream and return false; TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore); return(false); } case TypeSignatureKind.MultiDimArray: { // No need for a calling convention converter for this case. Just consume the signature from the stream. TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore); uint boundCount = parser.GetUnsigned(); for (uint i = 0; i < boundCount; i++) { parser.GetUnsigned(); } uint lowerBoundCount = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount; i++) { parser.GetUnsigned(); } } return(false); case TypeSignatureKind.FunctionPointer: { // No need for a calling convention converter for this case. Just consume the signature from the stream. uint argCount = parser.GetUnsigned(); for (uint i = 0; i < argCount; i++) { TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore); } } return(false); default: parser.ThrowBadImageFormatException(); return(true); } }
private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle); int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) { continue; } RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) { continue; } uint parsedCallingNameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) { continue; } uint parsedTargetMethodNameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); return(TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer)); } } return(false); }
private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle); int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if GVM_RESOLUTION_TRACE Debug.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(module); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) { continue; } RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) { continue; } uint parsedCallingNameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) { continue; } uint parsedTargetMethodNameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); if (!TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer)) { var sb = new System.Text.StringBuilder(); sb.AppendLine("Generic virtual method pointer lookup failure."); sb.AppendLine(); sb.AppendLine("Declaring type handle: " + declaringType.LowLevelToStringRawEETypeAddress()); sb.AppendLine("Target type handle: " + targetTypeHandle.LowLevelToStringRawEETypeAddress()); sb.AppendLine("Method name: " + targetMethodNameAndSignature.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < genericArguments.Length; i++) { sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + genericArguments[i].LowLevelToStringRawEETypeAddress()); } Environment.FailFast(sb.ToString()); } return(true); } } return(false); }
internal abstract bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, TypeManagerHandle moduleHandle);
private bool ResolveInterfaceGenericVirtualMethodSlot(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle; RuntimeTypeHandle[] callingTypeInstantiation; if (!TryGetOpenTypeDefinition(declaringType, out openCallingTypeHandle, out callingTypeInstantiation)) return false; // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle; RuntimeTypeHandle[] targetTypeInstantiation; if (!TryGetOpenTypeDefinition(targetTypeHandle, out openTargetTypeHandle, out targetTypeInstantiation)) return false; #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader)) continue; NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) continue; NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode()); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!openCallingTypeHandle.Equals(interfaceTypeHandle)) continue; uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature)) continue; // For each of the possible GVM slot targets for the current interface call, we will do the following: // // Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look // for ones that match the target object's type. // // Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target // provides an implementation for // // Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument // substitution (in case of a generic interface), and check if this interface signature is assignable from the // calling interface signature (from the name and sig input). if there is an exact match based on // interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface // type is compatible with the initial slots interface by means of variance. // This is done by calling the TypeLoaderEnvironment helper function. // // Example: // public interface IFoo<out T, out U> // { // string M1<V>(); // } // public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U> // { // string IFoo<T, U>.M1<V>() { ... } // public virtual string M1<V>() { ... } // } // public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T> // { // string IFoo<U, T>.M1<V>() { ... } // } // // GVM Table layout for IFoo<T, U>.M1<V>: // { // InterfaceTypeHandle = IFoo<T, U> // InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) } // GVMTargetSlots[] = // { // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo2<T, U> // ImplementingTypes = { // ImplementingTypeHandle = Foo2<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) } // } // }, // } // } // uint currentOffset = entryParser.Offset; // Non-variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false)) { return true; } entryParser.Offset = currentOffset; // Variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true)) { return true; } } } return false; }
private unsafe bool ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle; RuntimeTypeHandle[] callingTypeInstantiation; if (!TryGetOpenTypeDefinition(declaringType, out openCallingTypeHandle, out callingTypeInstantiation)) return false; // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle; RuntimeTypeHandle[] targetTypeInstantiation; if (!TryGetOpenTypeDefinition(targetTypeHandle, out openTargetTypeHandle, out targetTypeInstantiation)) return false; int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) continue; NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) continue; NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) continue; RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) continue; uint parsedCallingNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) continue; uint parsedTargetMethodNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); return TypeLoaderEnvironment.Instance.TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer); } } return false; }
internal Enumerator(NativeParser parser, uint endOffset, byte lowHashcode) { _parser = parser; _endOffset = endOffset; _lowHashcode = lowHashcode; }
/// <summary> /// Try to look up field acccess info for given canon in metadata blobs for all available modules. /// </summary> /// <param name="metadataReader">Metadata reader for the declaring type</param> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldHandle">Field handle</param> /// <param name="canonFormKind">Canonical form to use</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> private static bool TryGetFieldAccessMetadataFromFieldAccessMap( MetadataReader metadataReader, RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, CanonicalFormKind canonFormKind, ref FieldAccessMetadata fieldAccessMetadata) { CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind); IntPtr fieldHandleModule = ModuleList.Instance.GetModuleForMetadataReader(metadataReader); bool isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle); string fieldName = null; RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle); foreach (IntPtr mappingTableModule in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) { NativeReader fieldMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader)) { continue; } NativeParser fieldMapParser = new NativeParser(fieldMapReader, 0); NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule)) { continue; } var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned(); if ((canonFormKind == CanonicalFormKind.Universal) != entryFlags.HasFlag(FieldTableFlags.IsUniversalCanonicalEntry)) { continue; } RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) && !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle)) { continue; } if (entryFlags.HasFlag(FieldTableFlags.HasMetadataHandle)) { Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle(); if (!fieldHandle.Equals(entryFieldHandle)) { continue; } } else { if (fieldName == null) { MetadataReader mdReader; TypeDefinitionHandle typeDefHandleUnused; bool success = Instance.TryGetMetadataForNamedType( declaringTypeHandleDefinition, out mdReader, out typeDefHandleUnused); Debug.Assert(success); fieldName = mdReader.GetString(fieldHandle.GetField(mdReader).Name); } string entryFieldName = entryParser.GetString(); if (fieldName != entryFieldName) { continue; } } int cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned(); int fieldOffset; IntPtr fieldAddressCookie = IntPtr.Zero; if (canonFormKind == CanonicalFormKind.Universal) { if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, (uint)cookieOrOffsetOrOrdinal, out fieldOffset)) { Debug.Assert(false); return(false); } } else { fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal); } if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic) { if (canonFormKind != CanonicalFormKind.Universal) { fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule, fieldOffset); } if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle)) { // In this case we didn't find an exact match, but we did find a canonically equivalent match // We might be in the dynamic type case, or the canonically equivalent, but not the same case. if (!RuntimeAugments.IsDynamicType(declaringTypeHandle)) { int offsetToCreateCookieFor = fieldOffset; // We're working with a statically generated type, but we didn't find an exact match in the tables if (canonFormKind != CanonicalFormKind.Universal) { offsetToCreateCookieFor = checked ((int)TypeLoaderEnvironment.GetThreadStaticTypeOffsetFromThreadStaticCookie(fieldAddressCookie)); } fieldAddressCookie = TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(declaringTypeHandle, checked ((uint)offsetToCreateCookieFor)); } } } fieldAccessMetadata.MappingTableModule = mappingTableModule; fieldAccessMetadata.Cookie = fieldAddressCookie; fieldAccessMetadata.Flags = entryFlags; fieldAccessMetadata.Offset = fieldOffset; return(true); } } return(false); }
private unsafe TypeDesc GetLookbackType(ref NativeParser parser, uint lookback) { var lookbackParser = parser.GetLookbackParser(lookback); return(GetType(ref lookbackParser)); }
/// <summary> /// Prepare the StaticGCLayout/ThreadStaticGCLayout/GcStaticDesc/ThreadStaticDesc fields by /// reading native layout or metadata as appropriate. This method should only be called for types which /// are actually to be created. /// </summary> public void PrepareStaticGCLayout() { if (!_staticGCLayoutPrepared) { _staticGCLayoutPrepared = true; DefType defType = TypeBeingBuilt as DefType; if (defType == null) { // Array/pointer types do not have static fields } else if (defType.IsTemplateCanonical()) { // Canonical templates get their layout directly from the NativeLayoutInfo. // Parse it and pull that info out here. NativeParser typeInfoParser = GetParserForNativeLayoutInfo(); BagElementKind kind; while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End) { switch (kind) { case BagElementKind.GcStaticDesc: GcStaticDesc = NativeLayoutInfo.LoadContext.GetGCStaticInfo(typeInfoParser.GetUnsigned()); break; case BagElementKind.ThreadStaticDesc: ThreadStaticDesc = NativeLayoutInfo.LoadContext.GetGCStaticInfo(typeInfoParser.GetUnsigned()); break; case BagElementKind.GcStaticEEType: GcStaticEEType = NativeLayoutInfo.LoadContext.GetGCStaticInfo(typeInfoParser.GetUnsigned()); break; default: typeInfoParser.SkipInteger(); break; } } } else { // Compute GC layout boolean array from field information. IEnumerable <FieldDesc> fields = GetFieldsForGCLayout(); LowLevelList <bool> threadStaticLayout = null; LowLevelList <bool> gcStaticLayout = null; foreach (FieldDesc field in fields) { if (!field.IsStatic) { continue; } if (field.IsLiteral) { continue; } LowLevelList <bool> gcLayoutInfo = null; if (field.IsThreadStatic) { if (threadStaticLayout == null) { threadStaticLayout = new LowLevelList <bool>(); } gcLayoutInfo = threadStaticLayout; } else if (field.HasGCStaticBase) { if (gcStaticLayout == null) { gcStaticLayout = new LowLevelList <bool>(); } gcLayoutInfo = gcStaticLayout; } else { // Non-GC static no need to record information continue; } TypeBuilder.GCLayout fieldGcLayout = GetFieldGCLayout(field.FieldType); fieldGcLayout.WriteToBitfield(gcLayoutInfo, field.Offset.AsInt); } if (gcStaticLayout != null && gcStaticLayout.Count > 0) { StaticGCLayout = gcStaticLayout; } if (threadStaticLayout != null && threadStaticLayout.Count > 0) { ThreadStaticGCLayout = threadStaticLayout; } } } }
internal override void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser) { if (!baseTypeParser.IsNull) { // If the base type is available from the native layout info use it if the type we have is a NoMetadataType SetBaseType((DefType)nativeLayoutInfoLoadContext.GetType(ref baseTypeParser)); } else { // Set the base type for no metadata types, if we reach this point, and there isn't a parser, then we simply use the value from the template SetBaseType(ComputeTemplate().BaseType); } }
internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Common( TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader, ulong[] debuggerPreparedExternalReferences) { bool isNotDebuggerCall = debuggerPreparedExternalReferences == null; hasThis = false; parameters = null; NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); nativeLayoutContext._module = isNotDebuggerCall ? (NativeFormatModuleInfo)methodSig.GetModuleInfo() : null; nativeLayoutContext._typeSystemContext = context; nativeLayoutContext._typeArgumentHandles = typeInstantiation; nativeLayoutContext._methodArgumentHandles = methodInstantiation; nativeLayoutContext._debuggerPreparedExternalReferences = debuggerPreparedExternalReferences; NativeFormatModuleInfo module = null; NativeReader reader = null; if (isNotDebuggerCall) { reader = GetNativeLayoutInfoReader(methodSig); module = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(methodSig.ModuleHandle)); } else { reader = nativeReader; } NativeParser parser = new NativeParser(reader, methodSig.NativeLayoutOffset); MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); hasThis = !callingConvention.HasFlag(MethodCallingConvention.Static); uint numGenArgs = callingConvention.HasFlag(MethodCallingConvention.Generic) ? parser.GetUnsigned() : 0; uint parameterCount = parser.GetUnsigned(); parameters = new TypeDesc[parameterCount + 1]; parametersWithGenericDependentLayout = new bool[parameterCount + 1]; // One extra parameter to account for the return type for (uint i = 0; i <= parameterCount; i++) { // NativeParser is a struct, so it can be copied. NativeParser parserCopy = parser; // Parse the signature twice. The first time to find out the exact type of the signature // The second time to identify if the parameter loaded via the signature should be forced to be // passed byref as part of the universal generic calling convention. parameters[i] = GetConstructedTypeFromParserAndNativeLayoutContext(ref parser, nativeLayoutContext); parametersWithGenericDependentLayout[i] = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parserCopy, module, context, HasVarsInvestigationLevel.Parameter); if (parameters[i] == null) { return(false); } } return(true); }
public static RuntimeTypeHandle GetTypeFromNativeLayoutSignature(ref NativeParser parser, uint offset) { throw new NotImplementedException(); }
private bool CompareTypeSigWithType(ref NativeParser parser, TypeManagerHandle moduleHandle, Handle typeHandle) { while (typeHandle.HandleType == HandleType.TypeSpecification) { typeHandle = typeHandle .ToTypeSpecificationHandle(_metadataReader) .GetTypeSpecification(_metadataReader) .Signature; } // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint startOffset = parser.Offset; uint data; var typeSignatureKind = parser.GetTypeSignatureKind(out data); switch (typeSignatureKind) { case TypeSignatureKind.Lookback: { NativeParser lookbackParser = parser.GetLookbackParser(data); return(CompareTypeSigWithType(ref lookbackParser, moduleHandle, typeHandle)); } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same TypeModifierKind modifierKind = (TypeModifierKind)data; switch (modifierKind) { case TypeModifierKind.Array: if (typeHandle.HandleType == HandleType.SZArraySignature) { return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle .ToSZArraySignatureHandle(_metadataReader) .GetSZArraySignature(_metadataReader) .ElementType)); } return(false); case TypeModifierKind.ByRef: if (typeHandle.HandleType == HandleType.ByReferenceSignature) { return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle .ToByReferenceSignatureHandle(_metadataReader) .GetByReferenceSignature(_metadataReader) .Type)); } return(false); case TypeModifierKind.Pointer: if (typeHandle.HandleType == HandleType.PointerSignature) { return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle .ToPointerSignatureHandle(_metadataReader) .GetPointerSignature(_metadataReader) .Type)); } return(false); default: Debug.Assert(null == "invalid type modifier kind"); return(false); } } case TypeSignatureKind.Variable: { bool isMethodVar = (data & 0x1) == 1; uint index = data >> 1; if (isMethodVar) { if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature) { return(index == typeHandle .ToMethodTypeVariableSignatureHandle(_metadataReader) .GetMethodTypeVariableSignature(_metadataReader) .Number); } } else { if (typeHandle.HandleType == HandleType.TypeVariableSignature) { return(index == typeHandle .ToTypeVariableSignatureHandle(_metadataReader) .GetTypeVariableSignature(_metadataReader) .Number); } } return(false); } case TypeSignatureKind.MultiDimArray: { if (typeHandle.HandleType != HandleType.ArraySignature) { return(false); } ArraySignature sig = typeHandle .ToArraySignatureHandle(_metadataReader) .GetArraySignature(_metadataReader); if (data != sig.Rank) { return(false); } if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.ElementType)) { return(false); } uint boundCount1 = parser.GetUnsigned(); for (uint i = 0; i < boundCount1; i++) { parser.GetUnsigned(); } uint lowerBoundCount1 = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount1; i++) { parser.GetUnsigned(); } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data uint argCount1 = parser.GetUnsigned(); for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigWithType(ref parser, moduleHandle, typeHandle)) { return(false); } } return(false); } case TypeSignatureKind.Instantiation: { if (typeHandle.HandleType != HandleType.TypeInstantiationSignature) { return(false); } TypeInstantiationSignature sig = typeHandle .ToTypeInstantiationSignatureHandle(_metadataReader) .GetTypeInstantiationSignature(_metadataReader); if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.GenericType)) { return(false); } uint genericArgIndex = 0; foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments) { if (genericArgIndex >= data) { // The metadata generic has more parameters than the native layour return(false); } if (!CompareTypeSigWithType(ref parser, moduleHandle, genericArgumentTypeHandle)) { return(false); } genericArgIndex++; } // Make sure all generic parameters have been matched return(genericArgIndex == data); } case TypeSignatureKind.BuiltIn: case TypeSignatureKind.External: { RuntimeTypeHandle type2; switch (typeHandle.HandleType) { case HandleType.TypeDefinition: if (!TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata( new QTypeDefinition(_metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader)), out type2)) { return(false); } break; case HandleType.TypeReference: if (!TypeLoaderEnvironment.TryResolveNamedTypeForTypeReference( _metadataReader, typeHandle.ToTypeReferenceHandle(_metadataReader), out type2)) { return(false); } break; default: return(false); } RuntimeTypeHandle type1 = default(RuntimeTypeHandle); if (typeSignatureKind == TypeSignatureKind.External) { type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, moduleHandle, startOffset); } else { type1 = ((Internal.TypeSystem.WellKnownType)data).GetRuntimeTypeHandle(); } return(type1.Equals(type2)); } default: return(false); } return(true); }
public static bool CompareMethodSigWithMethodInfo(NativeParser reader, MethodBase methodBase) { if (!CompareCallingConventions((MethodCallingConvention)reader.GetUnsigned(), methodBase)) { return(false); } // Sigs are encoded in the native layout as uninstantiated. Work with the generic method def // here so that the arguments will compare properly. MethodBase uninstantiatedMethod = methodBase; if (methodBase is MethodInfo && methodBase.IsGenericMethod && !methodBase.IsGenericMethodDefinition) { uninstantiatedMethod = ((MethodInfo)methodBase).GetGenericMethodDefinition(); } if (uninstantiatedMethod.IsGenericMethod) { uint genericParamCount1 = reader.GetUnsigned(); int genericParamCount2 = uninstantiatedMethod.GetGenericArguments().Length; if (genericParamCount1 != genericParamCount2) { return(false); } } uint parameterCount = reader.GetUnsigned(); if (parameterCount != uninstantiatedMethod.GetParameters().Length) { return(false); } if (uninstantiatedMethod is MethodInfo) { // Not a constructor. Compare return types if (!CompareTypeSigWithType(ref reader, ((MethodInfo)uninstantiatedMethod).ReturnType)) { return(false); } } else { Debug.Assert(uninstantiatedMethod is ConstructorInfo); // The first parameter had better be void on a constructor if (!CompareTypeSigWithType(ref reader, CommonRuntimeTypes.Void)) { return(false); } } for (uint i = 0; i < parameterCount; i++) { if (!CompareTypeSigWithType(ref reader, uninstantiatedMethod.GetParameters()[i].ParameterType)) { return(false); } } return(true); }
private bool ResolveInterfaceGenericVirtualMethodSlot_Static(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle; RuntimeTypeHandle[] targetTypeInstantiation; openTargetTypeHandle = GetOpenTypeDefinition(targetTypeHandle, out targetTypeInstantiation); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode()); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!openCallingTypeHandle.Equals(interfaceTypeHandle)) { continue; } uint nameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature)) { continue; } // For each of the possible GVM slot targets for the current interface call, we will do the following: // // Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look // for ones that match the target object's type. // // Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target // provides an implementation for // // Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument // substitution (in case of a generic interface), and check if this interface signature is assignable from the // calling interface signature (from the name and sig input). if there is an exact match based on // interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface // type is compatible with the initial slots interface by means of variance. // This is done by calling the TypeLoaderEnvironment helper function. // // Example: // public interface IFoo<out T, out U> // { // string M1<V>(); // } // public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U> // { // string IFoo<T, U>.M1<V>() { ... } // public virtual string M1<V>() { ... } // } // public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T> // { // string IFoo<U, T>.M1<V>() { ... } // } // // GVM Table layout for IFoo<T, U>.M1<V>: // { // InterfaceTypeHandle = IFoo<T, U> // InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) } // GVMTargetSlots[] = // { // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo2<T, U> // ImplementingTypes = { // ImplementingTypeHandle = Foo2<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) } // } // }, // } // } // uint currentOffset = entryParser.Offset; // Non-variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false)) { return(true); } entryParser.Offset = currentOffset; // Variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true)) { return(true); } } } return(false); }
private static bool CompareTypeSigWithType(ref NativeParser parser, Type type) { // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint startOffset = parser.Offset; uint data; var typeSignatureKind = parser.GetTypeSignatureKind(out data); switch (typeSignatureKind) { case TypeSignatureKind.Lookback: { NativeParser lookbackParser = parser.GetLookbackParser(data); return(CompareTypeSigWithType(ref lookbackParser, type)); } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same TypeModifierKind modifierKind = (TypeModifierKind)data; switch (modifierKind) { case TypeModifierKind.Array: if (!type.IsArray) { return(false); } break; case TypeModifierKind.ByRef: if (!type.IsByRef) { return(false); } break; case TypeModifierKind.Pointer: if (!type.IsPointer) { return(false); } break; } return(CompareTypeSigWithType(ref parser, type.GetElementType())); } case TypeSignatureKind.Variable: { if (!type.IsGenericParameter) { return(false); } bool isMethodVar = (data & 0x1) == 1; uint index = data >> 1; if (index != type.GenericParameterPosition) { return(false); } // MVARs are represented as having a non-null DeclaringMethod in the reflection object model if (isMethodVar ^ (type.GetTypeInfo().DeclaringMethod != null)) { return(false); } break; } case TypeSignatureKind.MultiDimArray: { if (!type.IsArray) { return(false); } if (data != type.GetArrayRank()) { return(false); } if (!CompareTypeSigWithType(ref parser, type.GetElementType())) { return(false); } uint boundCount1 = parser.GetUnsigned(); for (uint i = 0; i < boundCount1; i++) { parser.GetUnsigned(); } uint lowerBoundCount1 = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount1; i++) { parser.GetUnsigned(); } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data uint argCount1 = parser.GetUnsigned(); for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigWithType(ref parser, type)) { return(false); } } return(false); } case TypeSignatureKind.Instantiation: { // Type Def if (!type.GetTypeInfo().IsGenericType) { return(false); } if (!CompareTypeSigWithType(ref parser, type.GetGenericTypeDefinition())) { return(false); } for (uint i = 0; i < data; i++) { if (!CompareTypeSigWithType(ref parser, type.GenericTypeArguments[i])) { return(false); } } break; } case TypeSignatureKind.External: { RuntimeTypeHandle type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, startOffset); if (!CanGetTypeHandle(type)) { return(false); } RuntimeTypeHandle type2 = type.TypeHandle; if (!type1.Equals(type2)) { return(false); } break; } default: return(false); } return(true); }
private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch) { uint numTargetImplementations = entryParser.GetUnsigned(); for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, nameAndSigToken); RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle)) { // Skip over signatures data for (uint l = 0; l < numIfaceSigs; l++) { entryParser.GetUnsigned(); } continue; } for (uint l = 0; l < numIfaceSigs; l++) { RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle); NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned())); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, moduleHandle, targetTypeInstantiation, null, out currentIfaceTypeHandle)) { Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller declaringType = targetTypeHandle; methodNameAndSignature = targetMethodNameAndSignature; return(true); } } } } } return(false); }
internal AllEntriesEnumerator(NativeHashtable table) { _table = table; _currentBucket = 0; _parser = _table.GetParserForBucket(_currentBucket, out _endOffset); }
private bool CompareMethodSigs(NativeParser parser1, NativeFormatModuleInfo moduleHandle1, NativeParser parser2, NativeFormatModuleInfo moduleHandle2) { MethodCallingConvention callingConvention1 = (MethodCallingConvention)parser1.GetUnsigned(); MethodCallingConvention callingConvention2 = (MethodCallingConvention)parser2.GetUnsigned(); if (callingConvention1 != callingConvention2) { return(false); } if ((callingConvention1 & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) { return(false); } } uint parameterCount1 = parser1.GetUnsigned(); uint parameterCount2 = parser2.GetUnsigned(); if (parameterCount1 != parameterCount2) { return(false); } // Compare one extra parameter to account for the return type for (uint i = 0; i <= parameterCount1; i++) { if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) { return(false); } } return(true); }
/// <summary> /// Try to look up field access info for given canon in metadata blobs for all available modules. /// </summary> /// <param name="metadataReader">Metadata reader for the declaring type</param> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldHandle">Field handle</param> /// <param name="canonFormKind">Canonical form to use</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> private unsafe static bool TryGetFieldAccessMetadataFromFieldAccessMap( MetadataReader metadataReader, RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, CanonicalFormKind canonFormKind, ref FieldAccessMetadata fieldAccessMetadata) { CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind); TypeManagerHandle fieldHandleModule = ModuleList.Instance.GetModuleForMetadataReader(metadataReader); bool isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle); string fieldName = null; RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle); foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) { NativeReader fieldMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader)) { continue; } NativeParser fieldMapParser = new NativeParser(fieldMapReader, 0); NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule)) { continue; } var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned(); if ((canonFormKind == CanonicalFormKind.Universal) != ((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) != 0)) { continue; } RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) && !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle)) { continue; } if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0) { Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle(); if (!fieldHandle.Equals(entryFieldHandle)) { continue; } } else { if (fieldName == null) { QTypeDefinition qTypeDefinition; bool success = Instance.TryGetMetadataForNamedType( declaringTypeHandleDefinition, out qTypeDefinition); Debug.Assert(success); MetadataReader nativeFormatMetadataReader = qTypeDefinition.NativeFormatReader; fieldName = nativeFormatMetadataReader.GetString(fieldHandle.GetField(nativeFormatMetadataReader).Name); } string entryFieldName = entryParser.GetString(); if (fieldName != entryFieldName) { continue; } } int fieldOffset = -1; int threadStaticsStartOffset = -1; IntPtr fieldAddressCookie = IntPtr.Zero; if (canonFormKind == CanonicalFormKind.Universal) { if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, entryParser.GetUnsigned() /* field ordinal */, out fieldOffset)) { Debug.Assert(false); return(false); } } else { if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic) { if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) { if ((entryFlags & FieldTableFlags.IsAnyCanonicalEntry) == 0) { int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets); threadStaticsStartOffset = *(int *)fieldAddressCookie.ToPointer(); } fieldOffset = (int)entryParser.GetUnsigned(); } else { int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets); ThreadStaticFieldOffsets *pThreadStaticFieldOffsets = (ThreadStaticFieldOffsets *)fieldAddressCookie.ToPointer(); threadStaticsStartOffset = (int)pThreadStaticFieldOffsets->StartingOffsetInTlsBlock; fieldOffset = (int)pThreadStaticFieldOffsets->FieldOffset; } } else { if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) { fieldOffset = (int)entryParser.GetUnsigned(); } else { #if PROJECTN fieldOffset = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); #else fieldOffset = 0; fieldAddressCookie = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned()); if ((entryFlags & FieldTableFlags.IsGcSection) != 0) { fieldOffset = (int)entryParser.GetUnsigned(); } #endif } } } if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic) { // TODO: CoreRT support if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle)) { if (!TypeLoaderEnvironment.Instance.TryGetThreadStaticStartOffset(declaringTypeHandle, out threadStaticsStartOffset)) { return(false); } } fieldAddressCookie = new IntPtr(threadStaticsStartOffset); } fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle; fieldAccessMetadata.Cookie = fieldAddressCookie; fieldAccessMetadata.Flags = entryFlags; fieldAccessMetadata.Offset = fieldOffset; return(true); } } return(false); }
private InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken) { nativeLayoutInfoModule = null; nativeLayoutInfoToken = 0; var canonForm = concreteMethod.GetCanonMethodTarget(kind); var hashCode = canonForm.GetHashCode(); foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules()) { NativeReader nativeLayoutReader = TypeLoaderEnvironment.Instance.GetNativeLayoutInfoReader(moduleInfo.Handle); if (nativeLayoutReader == null) { continue; } ExternalReferencesTable externalFixupsTable; NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out externalFixupsTable); if (genericMethodTemplatesHashtable.IsNull) { continue; } var context = new NativeLayoutInfoLoadContext { _typeSystemContext = concreteMethod.Context, _typeArgumentHandles = concreteMethod.OwningType.Instantiation, _methodArgumentHandles = concreteMethod.Instantiation, _module = moduleInfo }; var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = enumerator.GetNext()).IsNull) { var methodSignatureParser = new NativeParser(nativeLayoutReader, externalFixupsTable.GetExternalNativeLayoutOffset(entryParser.GetUnsigned())); // Get the unified generic method holder and convert it to its canonical form var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser); Debug.Assert(candidateTemplate.Instantiation.Length > 0); if (canonForm == candidateTemplate.GetCanonMethodTarget(kind)) { TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString()); nativeLayoutInfoModule = moduleInfo; nativeLayoutInfoToken = (uint)externalFixupsTable.GetExternalNativeLayoutOffset(entryParser.GetUnsigned()); if (nativeLayoutInfoToken == BadTokenFixupValue) { // TODO: once multifile gets fixed up, make this throw a BadImageFormatException TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping"); continue; } Debug.Assert( (kind != CanonicalFormKind.Universal && candidateTemplate != candidateTemplate.GetCanonMethodTarget(kind)) || (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind))); return(candidateTemplate); } } } TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString()); return(null); }
/// <summary> /// Try to look up non-gc/gc static effective field bases for a non-generic non-dynamic type. /// </summary> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldAccessKind">type of static base to find</param> /// <param name="staticsRegionAddress">Output - statics region address info</param> /// <returns>true when found, false otherwise</returns> private static unsafe bool TryGetStaticFieldBaseFromFieldAccessMap( RuntimeTypeHandle declaringTypeHandle, FieldAccessStaticDataKind fieldAccessKind, out IntPtr staticsRegionAddress) { staticsRegionAddress = IntPtr.Zero; byte *comparableStaticRegionAddress = null; CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, CanonicalFormKind.Specific); // This function only finds results for non-dynamic, non-generic types if (RuntimeAugments.IsDynamicType(declaringTypeHandle) || RuntimeAugments.IsGenericType(declaringTypeHandle)) { return(false); } foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) { NativeReader fieldMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader)) { continue; } NativeParser fieldMapParser = new NativeParser(fieldMapReader, 0); NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule)) { continue; } var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned(); Debug.Assert((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) == 0); if ((entryFlags & FieldTableFlags.Static) == 0) { continue; } switch (fieldAccessKind) { case FieldAccessStaticDataKind.NonGC: if ((entryFlags & FieldTableFlags.IsGcSection) != 0) { continue; } if ((entryFlags & FieldTableFlags.ThreadStatic) != 0) { continue; } break; case FieldAccessStaticDataKind.GC: if ((entryFlags & FieldTableFlags.IsGcSection) != 0) { continue; } if ((entryFlags & FieldTableFlags.ThreadStatic) != 0) { continue; } break; case FieldAccessStaticDataKind.TLS: default: // TODO! TLS statics Environment.FailFast("TLS static field access not yet supported"); return(false); } RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle)) { continue; } if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0) { // skip metadata handle entryParser.GetUnsigned(); } else { // skip field name entryParser.SkipString(); } int cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned(); int fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal); IntPtr fieldAddress = RvaToNonGenericStaticFieldAddress( mappingTableModule.Handle, fieldOffset); if ((comparableStaticRegionAddress == null) || (comparableStaticRegionAddress > fieldAddress.ToPointer())) { comparableStaticRegionAddress = (byte *)fieldAddress.ToPointer(); } } // Static fields for a type can only be found in at most one module if (comparableStaticRegionAddress != null) { break; } } if (comparableStaticRegionAddress != null) { staticsRegionAddress = new IntPtr(comparableStaticRegionAddress); return(true); } else { return(false); } }
private object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature) { Instantiation typeGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(typeGenericArgumentHandles ?? Array.Empty<RuntimeTypeHandle>()); Instantiation methodGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(methodGenericArgumentHandles ?? Array.Empty<RuntimeTypeHandle>()); NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); nativeLayoutContext._module = ModuleList.GetModuleInfoByHandle(moduleHandle); nativeLayoutContext._typeSystemContext = typeSystemContext; nativeLayoutContext._typeArgumentHandles = typeGenericArguments; nativeLayoutContext._methodArgumentHandles = methodGenericArguments; if (isMethodSignature) return nativeLayoutContext.GetMethod(ref parser); else return nativeLayoutContext.GetType(ref parser); }
/// Parse the native layout to ensure that the type has proper base type setup. /// This is used to generalize out some behavior of NoMetadataTypes which actually use this information internal virtual void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser) { return; }
private static unsafe bool TryGetStructData(RuntimeTypeHandle structTypeHandle, out ExternalReferencesTable externalReferences, out NativeParser entryParser) { int structHashcode = structTypeHandle.GetHashCode(); externalReferences = default(ExternalReferencesTable); entryParser = default(NativeParser); foreach (TypeManagerHandle module in RuntimeAugments.GetLoadedModules()) { NativeReader structMapReader; if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.StructMarshallingStubMap, out structMapReader)) { NativeParser structMapParser = new NativeParser(structMapReader, 0); NativeHashtable structHashtable = new NativeHashtable(structMapParser); externalReferences.InitializeCommonFixupsTable(module); var lookup = structHashtable.Lookup(structHashcode); while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle foundStructType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (foundStructType.Equals(structTypeHandle)) { return(true); } } } } return(false); }
private static ComputedStaticFieldLayout ParseStaticRegionSizesFromNativeLayout(TypeDesc type) { LayoutInt nonGcDataSize = LayoutInt.Zero; LayoutInt gcDataSize = LayoutInt.Zero; LayoutInt threadDataSize = LayoutInt.Zero; TypeBuilderState state = type.GetOrCreateTypeBuilderState(); NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo(); BagElementKind kind; while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End) { switch (kind) { case BagElementKind.NonGcStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) nonGcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned())); break; case BagElementKind.GcStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) gcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned())); break; case BagElementKind.ThreadStaticDataSize: TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize"); // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later) threadDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned())); break; default: typeInfoParser.SkipInteger(); break; } } ComputedStaticFieldLayout staticLayout = new ComputedStaticFieldLayout() { GcStatics = new StaticsBlock() { Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, NonGcStatics = new StaticsBlock() { Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, Offsets = null, // We're not computing field offsets here, so return null ThreadGcStatics = new StaticsBlock() { Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible }, ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero }, }; return(staticLayout); }
private bool CompareTypeSigWithType(ref NativeParser parser, Handle typeHandle) { while (typeHandle.HandleType == HandleType.TypeSpecification) { typeHandle = typeHandle .ToTypeSpecificationHandle(_metadataReader) .GetTypeSpecification(_metadataReader) .Signature; } // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint startOffset = parser.Offset; uint data; var typeSignatureKind = parser.GetTypeSignatureKind(out data); switch (typeSignatureKind) { case TypeSignatureKind.Lookback: { NativeParser lookbackParser = parser.GetLookbackParser(data); return CompareTypeSigWithType(ref lookbackParser, typeHandle); } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same TypeModifierKind modifierKind = (TypeModifierKind)data; switch (modifierKind) { case TypeModifierKind.Array: if (typeHandle.HandleType == HandleType.SZArraySignature) { return CompareTypeSigWithType(ref parser, typeHandle .ToSZArraySignatureHandle(_metadataReader) .GetSZArraySignature(_metadataReader) .ElementType); } return false; case TypeModifierKind.ByRef: if (typeHandle.HandleType == HandleType.ByReferenceSignature) { return CompareTypeSigWithType(ref parser, typeHandle .ToByReferenceSignatureHandle(_metadataReader) .GetByReferenceSignature(_metadataReader) .Type); } return false; case TypeModifierKind.Pointer: if (typeHandle.HandleType == HandleType.PointerSignature) { return CompareTypeSigWithType(ref parser, typeHandle .ToPointerSignatureHandle(_metadataReader) .GetPointerSignature(_metadataReader) .Type); } return false; default: Debug.Assert(null == "invalid type modifier kind"); return false; } } case TypeSignatureKind.Variable: { bool isMethodVar = (data & 0x1) == 1; uint index = data >> 1; if (isMethodVar) { if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature) { return index == typeHandle .ToMethodTypeVariableSignatureHandle(_metadataReader) .GetMethodTypeVariableSignature(_metadataReader) .Number; } } else { if (typeHandle.HandleType == HandleType.TypeVariableSignature) { return index == typeHandle .ToTypeVariableSignatureHandle(_metadataReader) .GetTypeVariableSignature(_metadataReader) .Number; } } return false; } case TypeSignatureKind.MultiDimArray: { if (typeHandle.HandleType != HandleType.ArraySignature) { return false; } ArraySignature sig = typeHandle .ToArraySignatureHandle(_metadataReader) .GetArraySignature(_metadataReader); if (data != sig.Rank) return false; if (!CompareTypeSigWithType(ref parser, sig.ElementType)) return false; uint boundCount1 = parser.GetUnsigned(); for (uint i = 0; i < boundCount1; i++) { parser.GetUnsigned(); } uint lowerBoundCount1 = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount1; i++) { parser.GetUnsigned(); } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data uint argCount1 = parser.GetUnsigned(); for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigWithType(ref parser, typeHandle)) return false; } return false; } case TypeSignatureKind.Instantiation: { if (typeHandle.HandleType != HandleType.TypeInstantiationSignature) { return false; } TypeInstantiationSignature sig = typeHandle .ToTypeInstantiationSignatureHandle(_metadataReader) .GetTypeInstantiationSignature(_metadataReader); if (!CompareTypeSigWithType(ref parser, sig.GenericType)) { return false; } uint genericArgIndex = 0; foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments) { if (genericArgIndex >= data) { // The metadata generic has more parameters than the native layour return false; } if (!CompareTypeSigWithType(ref parser, genericArgumentTypeHandle)) { return false; } genericArgIndex++; } // Make sure all generic parameters have been matched return genericArgIndex == data; } case TypeSignatureKind.External: { RuntimeTypeHandle type2; switch (typeHandle.HandleType) { case HandleType.TypeDefinition: if (!TypeLoaderEnvironment.Instance.TryGetOrCreateNamedTypeForMetadata( _metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader), out type2)) { return false; } break; case HandleType.TypeReference: if (!TypeLoaderEnvironment.TryGetNamedTypeForTypeReference( _metadataReader, typeHandle.ToTypeReferenceHandle(_metadataReader), out type2)) { return false; } break; default: return false; } RuntimeTypeHandle type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, startOffset); return type1.Equals(type2); } default: return false; } return true; }
private static void EnsureFieldLayoutLoadedForUniversalType(DefType type, NativeLayoutInfoLoadContext loadContext, NativeParser fieldLayoutParser) { Debug.Assert(type.HasInstantiation); Debug.Assert(type.ComputeTemplate().IsCanonicalSubtype(CanonicalFormKind.Universal)); if (type.NativeLayoutFields != null) { return; } type.NativeLayoutFields = ParseFieldLayout(type, loadContext, fieldLayoutParser); }
private static NativeLayoutFieldDesc[] ParseFieldLayout(DefType owningType, NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser fieldLayoutParser) { if (fieldLayoutParser.IsNull) { return(Empty <NativeLayoutFieldDesc> .Array); } uint numFields = fieldLayoutParser.GetUnsigned(); var fields = new NativeLayoutFieldDesc[numFields]; for (int i = 0; i < numFields; i++) { TypeDesc fieldType = nativeLayoutInfoLoadContext.GetType(ref fieldLayoutParser); NativeFormat.FieldStorage storage = (NativeFormat.FieldStorage)fieldLayoutParser.GetUnsigned(); fields[i] = new NativeLayoutFieldDesc(owningType, fieldType, storage); } return(fields); }
private static bool CompareTypeSigWithType(ref NativeParser parser, Type type) { // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint startOffset = parser.Offset; uint data; var typeSignatureKind = parser.GetTypeSignatureKind(out data); switch (typeSignatureKind) { case TypeSignatureKind.Lookback: { NativeParser lookbackParser = parser.GetLookbackParser(data); return CompareTypeSigWithType(ref lookbackParser, type); } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same TypeModifierKind modifierKind = (TypeModifierKind)data; switch (modifierKind) { case TypeModifierKind.Array: if (!type.IsArray) return false; break; case TypeModifierKind.ByRef: if (!type.IsByRef) return false; break; case TypeModifierKind.Pointer: if (!type.IsPointer) return false; break; } return CompareTypeSigWithType(ref parser, type.GetElementType()); } case TypeSignatureKind.Variable: { if (!type.IsGenericParameter) return false; bool isMethodVar = (data & 0x1) == 1; uint index = data >> 1; if (index != type.GenericParameterPosition) return false; // MVARs are represented as having a non-null DeclaringMethod in the reflection object model if (isMethodVar ^ (type.GetTypeInfo().DeclaringMethod != null)) return false; break; } case TypeSignatureKind.MultiDimArray: { if (!type.IsArray) return false; if (data != type.GetArrayRank()) return false; if (!CompareTypeSigWithType(ref parser, type.GetElementType())) return false; uint boundCount1 = parser.GetUnsigned(); for (uint i = 0; i < boundCount1; i++) { parser.GetUnsigned(); } uint lowerBoundCount1 = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount1; i++) { parser.GetUnsigned(); } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data uint argCount1 = parser.GetUnsigned(); for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigWithType(ref parser, type)) return false; } return false; } case TypeSignatureKind.Instantiation: { // Type Def if (!type.GetTypeInfo().IsGenericType) return false; if (!CompareTypeSigWithType(ref parser, type.GetGenericTypeDefinition())) return false; for (uint i = 0; i < data; i++) { if (!CompareTypeSigWithType(ref parser, type.GenericTypeArguments[i])) return false; } break; } case TypeSignatureKind.External: { RuntimeTypeHandle type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, startOffset); if (!CanGetTypeHandle(type)) return false; RuntimeTypeHandle type2 = type.TypeHandle; if (!type1.Equals(type2)) return false; break; } default: return false; } return true; }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc type) { TypeBuilderState state = type.GetOrCreateTypeBuilderState(); int totalInterfaces = RuntimeAugments.GetInterfaceCount(state.TemplateType.RuntimeTypeHandle); TypeLoaderLogger.WriteLine("Building runtime interfaces for type " + type.ToString() + " (total interfaces = " + totalInterfaces.LowLevelToString() + ") ..."); DefType[] interfaces = new DefType[totalInterfaces]; int numInterfaces = 0; // // Copy over all interfaces from base class // if (type.BaseType != null) { foreach (var baseInterface in type.BaseType.RuntimeInterfaces) { // There should be no duplicates Debug.Assert(!InterfaceInSet(interfaces, numInterfaces, baseInterface)); interfaces[numInterfaces++] = baseInterface; TypeLoaderLogger.WriteLine(" -> Added basetype interface " + baseInterface.ToString() + " on type " + type.ToString()); } } NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo(); NativeParser interfaceParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.ImplementedInterfaces); TypeDesc[] implementedInterfaces; if (!interfaceParser.IsNull) { implementedInterfaces = state.NativeLayoutInfo.LoadContext.GetTypeSequence(ref interfaceParser); } else { implementedInterfaces = TypeDesc.EmptyTypes; } // Note that the order in which the interfaces are added to the list is same as the order in which the MDIL binder adds them. // It is required for correctness foreach (TypeDesc interfaceType in implementedInterfaces) { DefType interfaceTypeAsDefType = (DefType)interfaceType; // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, interfaceTypeAsDefType)) { continue; } interfaces[numInterfaces++] = interfaceTypeAsDefType; TypeLoaderLogger.WriteLine(" -> Added interface " + interfaceTypeAsDefType.ToString() + " on type " + type.ToString()); foreach (var inheritedInterface in interfaceTypeAsDefType.RuntimeInterfaces) { // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, inheritedInterface)) { continue; } interfaces[numInterfaces++] = inheritedInterface; TypeLoaderLogger.WriteLine(" -> Added inherited interface " + inheritedInterface.ToString() + " on type " + type.ToString()); } } // TODO: Handle the screwy cases of generic interface folding Debug.Assert(numInterfaces == totalInterfaces, "Unexpected number of interfaces"); return(interfaces); }