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 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; }
private unsafe static void NewParameterizedArray(byte *parameterBuffer, uint parameterBufferSize) { uint offset = 0; NativeReader reader = new NativeReader(parameterBuffer, parameterBufferSize); ulong[] debuggerPreparedExternalReferences; offset = BuildDebuggerPreparedExternalReferences(reader, offset, out debuggerPreparedExternalReferences); NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create(); nativeLayoutContext._module = null; nativeLayoutContext._typeSystemContext = typeSystemContext; nativeLayoutContext._typeArgumentHandles = Instantiation.Empty; nativeLayoutContext._methodArgumentHandles = Instantiation.Empty; nativeLayoutContext._debuggerPreparedExternalReferences = debuggerPreparedExternalReferences; NativeParser parser = new NativeParser(reader, offset); TypeDesc arrElementType = TypeLoaderEnvironment.Instance.GetConstructedTypeFromParserAndNativeLayoutContext(ref parser, nativeLayoutContext); TypeSystemContextFactory.Recycle(typeSystemContext); uint rank = parser.GetUnsigned(); int[] dims = new int[rank]; int[] lowerBounds = new int[rank]; for (uint i = 0; i < rank; ++i) { dims[i] = (int)parser.GetUnsigned(); } for (uint i = 0; i < rank; ++i) { lowerBounds[i] = (int)parser.GetUnsigned(); } RuntimeTypeHandle typeHandle = arrElementType.GetRuntimeTypeHandle(); RuntimeTypeHandle arrayTypeHandle = default(RuntimeTypeHandle); Array returnValue; // Get an array RuntimeTypeHandle given an element's RuntimeTypeHandle and rank. // Pass false for isMdArray, and rank == -1 for SzArrays bool succeed = false; if (rank == 1 && lowerBounds[0] == 0) { succeed = TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType( typeHandle, false, -1, out arrayTypeHandle); Debug.Assert(succeed); returnValue = Internal.Runtime.Augments.RuntimeAugments.NewArray( arrayTypeHandle, dims[0]); } else { succeed = TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType( typeHandle, true, (int)rank, out arrayTypeHandle ); Debug.Assert(succeed); returnValue = Internal.Runtime.Augments.RuntimeAugments.NewMultiDimArray( arrayTypeHandle, dims, lowerBounds ); } GCHandle returnValueHandle = GCHandle.Alloc(returnValue); IntPtr returnValueHandlePointer = GCHandle.ToIntPtr(returnValueHandle); uint returnHandleIdentifier = RuntimeAugments.RhpRecordDebuggeeInitiatedHandle(returnValueHandlePointer); ReturnToDebuggerWithReturn(returnHandleIdentifier, returnValueHandlePointer, false); }
/// <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; } } } }
private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, 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.GetExternalNativeLayoutOffset(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, 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.GetExternalNativeLayoutOffset(entryParser.GetUnsigned())); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, 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); }
private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle instanceTypeHandle, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch, bool defaultMethods) { uint numTargetImplementations = entryParser.GetUnsigned(); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" :: Declaring type = " + GetTypeNameDebug(declaringType)); Debug.WriteLine(" :: Target type = " + GetTypeNameDebug(openTargetTypeHandle)); #endif for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature targetMethodNameAndSignature = null; RuntimeTypeHandle targetTypeHandle = default; bool isDefaultInterfaceMethodImplementation; if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction) { targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif } else { isDefaultInterfaceMethodImplementation = true; } uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current implementing type = " + GetTypeNameDebug(implementingTypeHandle)); #endif uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle) || defaultMethods != isDefaultInterfaceMethodImplementation) { // 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, entryParser.GetUnsigned()); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle)) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current interface on type = " + GetTypeNameDebug(currentIfaceTypeHandle)); #endif Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif if (targetMethodNameAndSignature == null) { if (nameAndSigToken == SpecialGVMInterfaceEntry.Diamond) { throw new AmbiguousImplementationException(); } else { Debug.Assert(nameAndSigToken == SpecialGVMInterfaceEntry.Reabstraction); throw new EntryPointNotFoundException(); } } // 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 if (!RuntimeAugments.IsInterface(targetTypeHandle) || !RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle)) { // Not a default interface method or default interface method on a non-generic type. // We have a usable type handle. declaringType = targetTypeHandle; } else if (RuntimeAugments.IsGenericType(currentIfaceTypeHandle) && RuntimeAugments.GetGenericDefinition(currentIfaceTypeHandle).Equals(targetTypeHandle)) { // Default interface method implemented on the same type that declared the slot. // Use the instantiation as-is from what we found. declaringType = currentIfaceTypeHandle; } else { declaringType = default; // Default interface method implemented on a different generic interface. // We need to find a usable instantiation. There should be only one match because we // would be dealing with a diamond otherwise. int numInstanceInterfaces = RuntimeAugments.GetInterfaceCount(instanceTypeHandle); for (int instIntfIndex = 0; instIntfIndex < numInstanceInterfaces; instIntfIndex++) { RuntimeTypeHandle instIntf = RuntimeAugments.GetInterface(instanceTypeHandle, instIntfIndex); if (RuntimeAugments.IsGenericType(instIntf) && RuntimeAugments.GetGenericDefinition(instIntf).Equals(targetTypeHandle)) { // Got a potential interface. Check if the implementing interface is in the interface // list. We don't want IsAssignableFrom because we need an exact match. int numIntInterfaces = RuntimeAugments.GetInterfaceCount(instIntf); for (int intIntfIndex = 0; intIntfIndex < numIntInterfaces; intIntfIndex++) { if (RuntimeAugments.GetInterface(instIntf, intIntfIndex).Equals(currentIfaceTypeHandle)) { Debug.Assert(declaringType.IsNull()); declaringType = instIntf; #if !DEBUG break; #endif } } #if !DEBUG if (!declaringType.IsNull()) { break; } #endif } } Debug.Assert(!declaringType.IsNull()); } methodNameAndSignature = targetMethodNameAndSignature; return(true); } } } } } return(false); }
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; 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); }
internal override bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, IntPtr moduleHandle) { // Compare entry with inputs as we parse it. If we get a mismatch, stop parsing and move to the next entry... RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedDeclaringTypeHandle.Equals(_declaringType)) { return(false); } // Hash table names / sigs are indirected through to the native layout info MethodNameAndSignature nameAndSignature; if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned(), out nameAndSignature)) { return(false); } if (!nameAndSignature.Equals(_nameAndSignature)) { return(false); } int parsedArity = (int)entryParser.GetSequenceCount(); int lookupArity = (_methodToLookup != null ? _methodToLookup.Instantiation.Length : _genericMethodArgumentHandles.Length); if (parsedArity != lookupArity) { return(false); } for (int i = 0; i < parsedArity; i++) { RuntimeTypeHandle parsedArg = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); RuntimeTypeHandle lookupArg = (_methodToLookup != null ? _methodToLookup.Instantiation[i].RuntimeTypeHandle : _genericMethodArgumentHandles[i]); if (!parsedArg.Equals(lookupArg)) { return(false); } } return(true); }
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); }
private unsafe bool TryGetStructData(RuntimeTypeHandle structTypeHandle, out ExternalReferencesTable externalReferences, out NativeParser entryParser) { int structHashcode = structTypeHandle.GetHashCode(); externalReferences = default(ExternalReferencesTable); entryParser = default(NativeParser); foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) { 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 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 CompareTypeSigs(ref NativeParser parser1, ref NativeParser parser2) { // 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, ref parser2)); } 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, ref lookbackParser2)); } 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, ref parser2)); } 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, ref parser2)) { 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, ref parser2)) { return(false); } } break; } case TypeSignatureKind.Instantiation: { // Type parameter count is in data if (data1 != data2) { return(false); } if (!CompareTypeSigs(ref parser1, ref parser2)) { return(false); } for (uint i = 0; i < data1; i++) { if (!CompareTypeSigs(ref parser1, ref parser2)) { return(false); } } break; } case TypeSignatureKind.External: { RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(ref parser1, data1); RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(ref parser2, 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, 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, context, investigationLevel)); } case TypeSignatureKind.Instantiation: { RuntimeTypeHandle genericTypeDef; if (!TryGetTypeFromSimpleTypeSignature(ref parser, 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, context, HasVarsInvestigationLevel.Ignore); } return(false); } else { bool result = false; for (uint i = 0; i < data; i++) { result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, 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, 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, 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, context, HasVarsInvestigationLevel.Ignore); } } return(false); default: parser.ThrowBadImageFormatException(); return(true); } }
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 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 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 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; }
internal override bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, IntPtr moduleHandle) { // // Entries read from the hashtable are loaded as GenericMethodDescs, and compared to the input. // This lookup is slower than the lookups using RuntimeTypeHandles, but can handle cases where we don't have // RuntimeTypeHandle values for all of the components of the input GenericMethodDesc, but still need to look it up in case the // method dictionary statically really exists // TypeSystemContext context = _methodToLookup.Context; RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); // Hash table names / sigs are indirected through to the native layout info MethodNameAndSignature nameAndSignature; if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned(), out nameAndSignature)) { return(false); } RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser); DefType parsedDeclaringType = context.ResolveRuntimeTypeHandle(parsedDeclaringTypeHandle) as DefType; Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(parsedArgsHandles); InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs, IntPtr.Zero, false); return(parsedGenericMethod == _methodToLookup); }