Example #1
0
        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;
        }
Example #3
0
        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);
        }
Example #4
0
        /// <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;
                    }
                }
            }
        }
Example #5
0
        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);
        }
Example #7
0
        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);
            }
Example #9
0
        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;
        }
Example #15
0
        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);
        }
Example #16
0
        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);
        }
Example #17
0
        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);
            }