private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);
                RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

            #if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
            #endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                            entryParser.GetUnsigned();

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned()));
                        IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset);

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
            #if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
            #endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
        public static RuntimeTypeHandle GetTypeFromNativeLayoutSignature(ref NativeParser parser, uint offset)
        {
            IntPtr remainingSignature;
            RuntimeTypeHandle typeHandle;

            IntPtr signatureAddress = parser.Reader.OffsetToAddress(offset);
            bool success = TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(signatureAddress, null, null, out typeHandle, out remainingSignature);

            // Reset the parser to after the type
            parser = new NativeParser(parser.Reader, parser.Reader.AddressToOffset(remainingSignature));

            return typeHandle;
        }
        public MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, uint nativeLayoutOffset)
        {
            NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset);

            string methodName = parser.GetString();

            // Signatures are indirected to through a relative offset so that we don't have to parse them
            // when not comparing signatures (parsing them requires resolving types and is tremendously
            // expensive).
            NativeParser sigParser = parser.GetParserFromRelativeOffset();
            IntPtr methodSigPtr = sigParser.Reader.OffsetToAddress(sigParser.Offset);

            return new MethodNameAndSignature(methodName, methodSigPtr);
        }
Exemple #4
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;
        }
Exemple #5
0
        private static RuntimeTypeHandle[] GetTypeSequence(ref ExternalReferencesTable extRefs, ref NativeParser parser)
        {
            uint count = parser.GetUnsigned();
            RuntimeTypeHandle[] result = new RuntimeTypeHandle[count];
            for (uint i = 0; i < count; i++)
                result[i] = extRefs.GetRuntimeTypeHandleFromIndex(parser.GetUnsigned());

            return result;
        }
        private bool CompareTypeSigs(ref NativeParser parser1, NativeFormatModuleInfo moduleHandle1, ref NativeParser parser2, NativeFormatModuleInfo moduleHandle2)
        {
            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint data1;
            uint startOffset1       = parser1.Offset;
            var  typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1);

            // If the parser is at a lookback type, get a new parser for it and recurse.
            // Since we haven't read the element type of parser2 yet, we just pass it in unchanged
            if (typeSignatureKind1 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser1 = parser1.GetLookbackParser(data1);
                return(CompareTypeSigs(ref lookbackParser1, moduleHandle1, ref parser2, moduleHandle2));
            }

            uint data2;
            uint startOffset2       = parser2.Offset;
            var  typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2);

            // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1
            // before recursing.
            if (typeSignatureKind2 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser2 = parser2.GetLookbackParser(data2);
                parser1 = new NativeParser(parser1.Reader, startOffset1);
                return(CompareTypeSigs(ref parser1, moduleHandle1, ref lookbackParser2, moduleHandle2));
            }

            if (typeSignatureKind1 != typeSignatureKind2)
            {
                return(false);
            }

            switch (typeSignatureKind1)
            {
            case TypeSignatureKind.Lookback:
            {
                //  Recursion above better have removed all lookbacks
                Debug.Assert(false, "Unexpected lookback type");
                return(false);
            }

            case TypeSignatureKind.Modifier:
            {
                // Ensure the modifier kind (vector, pointer, byref) is the same
                if (data1 != data2)
                {
                    return(false);
                }
                return(CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2));
            }

            case TypeSignatureKind.Variable:
            {
                // variable index is in data
                if (data1 != data2)
                {
                    return(false);
                }
                break;
            }

            case TypeSignatureKind.MultiDimArray:
            {
                // rank is in data
                if (data1 != data2)
                {
                    return(false);
                }

                if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                {
                    return(false);
                }

                uint boundCount1 = parser1.GetUnsigned();
                uint boundCount2 = parser2.GetUnsigned();
                if (boundCount1 != boundCount2)
                {
                    return(false);
                }

                for (uint i = 0; i < boundCount1; i++)
                {
                    if (parser1.GetUnsigned() != parser2.GetUnsigned())
                    {
                        return(false);
                    }
                }

                uint lowerBoundCount1 = parser1.GetUnsigned();
                uint lowerBoundCount2 = parser2.GetUnsigned();
                if (lowerBoundCount1 != lowerBoundCount2)
                {
                    return(false);
                }

                for (uint i = 0; i < lowerBoundCount1; i++)
                {
                    if (parser1.GetUnsigned() != parser2.GetUnsigned())
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.FunctionPointer:
            {
                // callingConvention is in data
                if (data1 != data2)
                {
                    return(false);
                }
                uint argCount1 = parser1.GetUnsigned();
                uint argCount2 = parser2.GetUnsigned();
                if (argCount1 != argCount2)
                {
                    return(false);
                }
                for (uint i = 0; i < argCount1; i++)
                {
                    if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.Instantiation:
            {
                // Type parameter count is in data
                if (data1 != data2)
                {
                    return(false);
                }

                if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                {
                    return(false);
                }

                for (uint i = 0; i < data1; i++)
                {
                    if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.External:
            {
                RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(moduleHandle1, data1);
                RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(moduleHandle2, data2);
                if (!typeHandle1.Equals(typeHandle2))
                {
                    return(false);
                }

                break;
            }

            default:
                return(false);
            }
            return(true);
        }
        /// <summary>
        /// IF THESE SEMANTICS EVER CHANGE UPDATE THE LOGIC WHICH DEFINES THIS BEHAVIOR IN
        /// THE DYNAMIC TYPE LOADER AS WELL AS THE COMPILER.
        ///
        /// Parameter's are considered to have type layout dependent on their generic instantiation
        /// if the type of the parameter in its signature is a type variable, or if the type is a generic
        /// structure which meets 2 characteristics:
        /// 1. Structure size/layout is affected by the size/layout of one or more of its generic parameters
        /// 2. One or more of the generic parameters is a type variable, or a generic structure which also recursively
        ///    would satisfy constraint 2. (Note, that in the recursion case, whether or not the structure is affected
        ///    by the size/layout of its generic parameters is not investigated.)
        ///
        /// Examples parameter types, and behavior.
        ///
        /// T = true
        /// List[T] = false
        /// StructNotDependentOnArgsForSize[T] = false
        /// GenStructDependencyOnArgsForSize[T] = true
        /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true
        /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false
        ///
        /// Example non-parameter type behavior
        /// T = true
        /// List[T] = false
        /// StructNotDependentOnArgsForSize[T] = *true*
        /// GenStructDependencyOnArgsForSize[T] = true
        /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[T]] = true
        /// StructNotDependentOnArgsForSize[GenStructDependencyOnArgsForSize[List[T]]]] = false
        /// </summary>
        private bool TypeSignatureHasVarsNeedingCallingConventionConverter(ref NativeParser parser, NativeFormatModuleInfo moduleHandle, TypeSystemContext context, HasVarsInvestigationLevel investigationLevel)
        {
            uint data;
            var  kind = parser.GetTypeSignatureKind(out data);

            switch (kind)
            {
            case TypeSignatureKind.External: return(false);

            case TypeSignatureKind.Variable: return(true);

            case TypeSignatureKind.Lookback:
            {
                var lookbackParser = parser.GetLookbackParser(data);
                return(TypeSignatureHasVarsNeedingCallingConventionConverter(ref lookbackParser, moduleHandle, context, investigationLevel));
            }

            case TypeSignatureKind.Instantiation:
            {
                RuntimeTypeHandle genericTypeDef;
                if (!TryGetTypeFromSimpleTypeSignature(ref parser, moduleHandle, out genericTypeDef))
                {
                    Debug.Assert(false);
                    return(true);           // Returning true will prevent further reading from the native parser
                }

                if (!RuntimeAugments.IsValueType(genericTypeDef))
                {
                    // Reference types are treated like pointers. No calling convention conversion needed. Just consume the rest of the signature.
                    for (uint i = 0; i < data; i++)
                    {
                        TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore);
                    }
                    return(false);
                }
                else
                {
                    bool result = false;
                    for (uint i = 0; i < data; i++)
                    {
                        result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.NotParameter) || result;
                    }

                    if ((result == true) && (investigationLevel == HasVarsInvestigationLevel.Parameter))
                    {
                        if (!TryComputeHasInstantiationDeterminedSize(genericTypeDef, context, out result))
                        {
                            Environment.FailFast("Unable to setup calling convention converter correctly");
                        }

                        return(result);
                    }

                    return(result);
                }
            }

            case TypeSignatureKind.Modifier:
            {
                // Arrays, pointers and byref types signatures are treated as pointers, not requiring calling convention conversion.
                // Just consume the parameter type from the stream and return false;
                TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore);
                return(false);
            }

            case TypeSignatureKind.MultiDimArray:
            {
                // No need for a calling convention converter for this case. Just consume the signature from the stream.

                TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore);

                uint boundCount = parser.GetUnsigned();
                for (uint i = 0; i < boundCount; i++)
                {
                    parser.GetUnsigned();
                }

                uint lowerBoundCount = parser.GetUnsigned();
                for (uint i = 0; i < lowerBoundCount; i++)
                {
                    parser.GetUnsigned();
                }
            }
                return(false);

            case TypeSignatureKind.FunctionPointer:
            {
                // No need for a calling convention converter for this case. Just consume the signature from the stream.

                uint argCount = parser.GetUnsigned();
                for (uint i = 0; i < argCount; i++)
                {
                    TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.Ignore);
                }
            }
                return(false);

            default:
                parser.ThrowBadImageFormatException();
                return(true);
            }
        }
Exemple #8
0
        private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType);

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle);

            int hashCode = openCallingTypeHandle.GetHashCode();

            hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode();

#if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name);
#endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader))
                {
                    continue;
                }

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                {
                    continue;
                }

                NativeParser            gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable         gvmHashtable   = new NativeHashtable(gvmTableParser);
                ExternalReferencesTable extRefs        = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle))
                    {
                        continue;
                    }

                    RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle))
                    {
                        continue;
                    }

                    uint parsedCallingNameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, parsedCallingNameAndSigToken);

                    if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature))
                    {
                        continue;
                    }

                    uint parsedTargetMethodNameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, parsedTargetMethodNameAndSigToken);

                    Debug.Assert(targetMethodNameAndSignature != null);

                    return(TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer));
                }
            }

            return(false);
        }
        private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType);

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle);

            int hashCode = openCallingTypeHandle.GetHashCode();

            hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode();

#if GVM_RESOLUTION_TRACE
            Debug.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name);
#endif

            foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader))
                {
                    continue;
                }

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                {
                    continue;
                }

                NativeParser            gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable         gvmHashtable   = new NativeHashtable(gvmTableParser);
                ExternalReferencesTable extRefs        = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(module);

                var lookup = gvmHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle))
                    {
                        continue;
                    }

                    RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle))
                    {
                        continue;
                    }

                    uint parsedCallingNameAndSigToken = entryParser.GetUnsigned();
                    MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedCallingNameAndSigToken);

                    if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature))
                    {
                        continue;
                    }

                    uint parsedTargetMethodNameAndSigToken = entryParser.GetUnsigned();
                    MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedTargetMethodNameAndSigToken);

                    Debug.Assert(targetMethodNameAndSignature != null);

                    if (!TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer))
                    {
                        var sb = new System.Text.StringBuilder();
                        sb.AppendLine("Generic virtual method pointer lookup failure.");
                        sb.AppendLine();
                        sb.AppendLine("Declaring type handle: " + declaringType.LowLevelToStringRawEETypeAddress());
                        sb.AppendLine("Target type handle: " + targetTypeHandle.LowLevelToStringRawEETypeAddress());
                        sb.AppendLine("Method name: " + targetMethodNameAndSignature.Name);
                        sb.AppendLine("Instantiation:");
                        for (int i = 0; i < genericArguments.Length; i++)
                        {
                            sb.AppendLine("  Argument " + i.LowLevelToString() + ": " + genericArguments[i].LowLevelToStringRawEETypeAddress());
                        }

                        Environment.FailFast(sb.ToString());
                    }

                    return(true);
                }
            }

            return(false);
        }
 internal abstract bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, TypeManagerHandle moduleHandle);
        private bool ResolveInterfaceGenericVirtualMethodSlot(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature)
        {
            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle;
            RuntimeTypeHandle[] callingTypeInstantiation;
            if (!TryGetOpenTypeDefinition(declaringType, out openCallingTypeHandle, out callingTypeInstantiation))
                return false;

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle;
            RuntimeTypeHandle[] targetTypeInstantiation;
            if (!TryGetOpenTypeDefinition(targetTypeHandle, out openTargetTypeHandle, out targetTypeInstantiation))
                return false;

            #if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name);
            #endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader))
                    continue;

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                    continue;

                NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser);

                ExternalReferencesTable extRefs = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode());

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!openCallingTypeHandle.Equals(interfaceTypeHandle))
                        continue;

                    uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);

                    if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature))
                        continue;

                    // For each of the possible GVM slot targets for the current interface call, we will do the following:
                    //
                    //  Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look
                    //          for ones that match the target object's type.
                    //
                    //  Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target
                    //          provides an implementation for
                    //
                    //  Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument
                    //          substitution (in case of a generic interface), and check if this interface signature is assignable from the
                    //          calling interface signature (from the name and sig input). if there is an exact match based on
                    //          interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface
                    //          type is compatible with the initial slots interface by means of variance.
                    //          This is done by calling the TypeLoaderEnvironment helper function.
                    //
                    // Example:
                    //      public interface IFoo<out T, out U>
                    //      {
                    //          string M1<V>();
                    //      }
                    //      public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U>
                    //      {
                    //          string IFoo<T, U>.M1<V>() { ... }
                    //          public virtual string M1<V>() { ... }
                    //      }
                    //      public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T>
                    //      {
                    //          string IFoo<U, T>.M1<V>() { ... }
                    //      }
                    //
                    //  GVM Table layout for IFoo<T, U>.M1<V>:
                    //  {
                    //      InterfaceTypeHandle = IFoo<T, U>
                    //      InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) }
                    //      GVMTargetSlots[] =
                    //      {
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo2<T, U>
                    //              ImplementingTypes = {
                    //                  ImplementingTypeHandle = Foo2<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) }
                    //              }
                    //          },
                    //      }
                    //  }
                    //

                    uint currentOffset = entryParser.Offset;

                    // Non-variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false))
                    {
                        return true;
                    }

                    entryParser.Offset = currentOffset;

                    // Variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        private unsafe bool ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle;
            RuntimeTypeHandle[] callingTypeInstantiation;
            if (!TryGetOpenTypeDefinition(declaringType, out openCallingTypeHandle, out callingTypeInstantiation))
                return false;

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle;
            RuntimeTypeHandle[] targetTypeInstantiation;
            if (!TryGetOpenTypeDefinition(targetTypeHandle, out openTargetTypeHandle, out targetTypeInstantiation))
                return false;

            int hashCode = openCallingTypeHandle.GetHashCode();
            hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode();

            #if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name);
            #endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader))
                    continue;

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                    continue;

                NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser);
                ExternalReferencesTable extRefs = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle))
                        continue;

                    RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle))
                        continue;

                    uint parsedCallingNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedCallingNameAndSigToken);

                    if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature))
                        continue;

                    uint parsedTargetMethodNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedTargetMethodNameAndSigToken);

                    Debug.Assert(targetMethodNameAndSignature != null);

                    return TypeLoaderEnvironment.Instance.TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer);
                }
            }

            return false;
        }
Exemple #13
0
 internal Enumerator(NativeParser parser, uint endOffset, byte lowHashcode)
 {
     _parser      = parser;
     _endOffset   = endOffset;
     _lowHashcode = lowHashcode;
 }
        /// <summary>
        /// Try to look up field acccess info for given canon in metadata blobs for all available modules.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            IntPtr            fieldHandleModule            = ModuleList.Instance.GetModuleForMetadataReader(metadataReader);
            bool              isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle);
            string            fieldName     = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle);

            foreach (IntPtr mappingTableModule in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    if ((canonFormKind == CanonicalFormKind.Universal) != entryFlags.HasFlag(FieldTableFlags.IsUniversalCanonicalEntry))
                    {
                        continue;
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) &&
                        !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle))
                    {
                        continue;
                    }

                    if (entryFlags.HasFlag(FieldTableFlags.HasMetadataHandle))
                    {
                        Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle();
                        if (!fieldHandle.Equals(entryFieldHandle))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (fieldName == null)
                        {
                            MetadataReader       mdReader;
                            TypeDefinitionHandle typeDefHandleUnused;
                            bool success = Instance.TryGetMetadataForNamedType(
                                declaringTypeHandleDefinition,
                                out mdReader,
                                out typeDefHandleUnused);
                            Debug.Assert(success);

                            fieldName = mdReader.GetString(fieldHandle.GetField(mdReader).Name);
                        }

                        string entryFieldName = entryParser.GetString();

                        if (fieldName != entryFieldName)
                        {
                            continue;
                        }
                    }

                    int    cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned();
                    int    fieldOffset;
                    IntPtr fieldAddressCookie = IntPtr.Zero;

                    if (canonFormKind == CanonicalFormKind.Universal)
                    {
                        if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, (uint)cookieOrOffsetOrOrdinal, out fieldOffset))
                        {
                            Debug.Assert(false);
                            return(false);
                        }
                    }
                    else
                    {
                        fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);
                    }

                    if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic)
                    {
                        if (canonFormKind != CanonicalFormKind.Universal)
                        {
                            fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule, fieldOffset);
                        }

                        if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle))
                        {
                            // In this case we didn't find an exact match, but we did find a canonically equivalent match
                            // We might be in the dynamic type case, or the canonically equivalent, but not the same case.

                            if (!RuntimeAugments.IsDynamicType(declaringTypeHandle))
                            {
                                int offsetToCreateCookieFor = fieldOffset;
                                // We're working with a statically generated type, but we didn't find an exact match in the tables
                                if (canonFormKind != CanonicalFormKind.Universal)
                                {
                                    offsetToCreateCookieFor = checked ((int)TypeLoaderEnvironment.GetThreadStaticTypeOffsetFromThreadStaticCookie(fieldAddressCookie));
                                }

                                fieldAddressCookie = TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(declaringTypeHandle, checked ((uint)offsetToCreateCookieFor));
                            }
                        }
                    }

                    fieldAccessMetadata.MappingTableModule = mappingTableModule;
                    fieldAccessMetadata.Cookie             = fieldAddressCookie;
                    fieldAccessMetadata.Flags  = entryFlags;
                    fieldAccessMetadata.Offset = fieldOffset;
                    return(true);
                }
            }

            return(false);
        }
        private unsafe TypeDesc GetLookbackType(ref NativeParser parser, uint lookback)
        {
            var lookbackParser = parser.GetLookbackParser(lookback);

            return(GetType(ref lookbackParser));
        }
Exemple #16
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;
                    }
                }
            }
        }
 internal override void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser)
 {
     if (!baseTypeParser.IsNull)
     {
         // If the base type is available from the native layout info use it if the type we have is a NoMetadataType
         SetBaseType((DefType)nativeLayoutInfoLoadContext.GetType(ref baseTypeParser));
     }
     else
     {
         // Set the base type for no metadata types, if we reach this point, and there isn't a parser, then we simply use the value from the template
         SetBaseType(ComputeTemplate().BaseType);
     }
 }
Exemple #18
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);
        }
Exemple #19
0
 public static RuntimeTypeHandle GetTypeFromNativeLayoutSignature(ref NativeParser parser, uint offset)
 {
     throw new NotImplementedException();
 }
        private bool CompareTypeSigWithType(ref NativeParser parser, TypeManagerHandle moduleHandle, Handle typeHandle)
        {
            while (typeHandle.HandleType == HandleType.TypeSpecification)
            {
                typeHandle = typeHandle
                             .ToTypeSpecificationHandle(_metadataReader)
                             .GetTypeSpecification(_metadataReader)
                             .Signature;
            }

            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint startOffset = parser.Offset;

            uint data;
            var  typeSignatureKind = parser.GetTypeSignatureKind(out data);

            switch (typeSignatureKind)
            {
            case TypeSignatureKind.Lookback:
            {
                NativeParser lookbackParser = parser.GetLookbackParser(data);
                return(CompareTypeSigWithType(ref lookbackParser, moduleHandle, typeHandle));
            }

            case TypeSignatureKind.Modifier:
            {
                // Ensure the modifier kind (vector, pointer, byref) is the same
                TypeModifierKind modifierKind = (TypeModifierKind)data;
                switch (modifierKind)
                {
                case TypeModifierKind.Array:
                    if (typeHandle.HandleType == HandleType.SZArraySignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToSZArraySignatureHandle(_metadataReader)
                                                      .GetSZArraySignature(_metadataReader)
                                                      .ElementType));
                    }
                    return(false);

                case TypeModifierKind.ByRef:
                    if (typeHandle.HandleType == HandleType.ByReferenceSignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToByReferenceSignatureHandle(_metadataReader)
                                                      .GetByReferenceSignature(_metadataReader)
                                                      .Type));
                    }
                    return(false);

                case TypeModifierKind.Pointer:
                    if (typeHandle.HandleType == HandleType.PointerSignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToPointerSignatureHandle(_metadataReader)
                                                      .GetPointerSignature(_metadataReader)
                                                      .Type));
                    }
                    return(false);

                default:
                    Debug.Assert(null == "invalid type modifier kind");
                    return(false);
                }
            }

            case TypeSignatureKind.Variable:
            {
                bool isMethodVar = (data & 0x1) == 1;
                uint index       = data >> 1;

                if (isMethodVar)
                {
                    if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature)
                    {
                        return(index == typeHandle
                               .ToMethodTypeVariableSignatureHandle(_metadataReader)
                               .GetMethodTypeVariableSignature(_metadataReader)
                               .Number);
                    }
                }
                else
                {
                    if (typeHandle.HandleType == HandleType.TypeVariableSignature)
                    {
                        return(index == typeHandle
                               .ToTypeVariableSignatureHandle(_metadataReader)
                               .GetTypeVariableSignature(_metadataReader)
                               .Number);
                    }
                }

                return(false);
            }

            case TypeSignatureKind.MultiDimArray:
            {
                if (typeHandle.HandleType != HandleType.ArraySignature)
                {
                    return(false);
                }

                ArraySignature sig = typeHandle
                                     .ToArraySignatureHandle(_metadataReader)
                                     .GetArraySignature(_metadataReader);

                if (data != sig.Rank)
                {
                    return(false);
                }

                if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.ElementType))
                {
                    return(false);
                }

                uint boundCount1 = parser.GetUnsigned();
                for (uint i = 0; i < boundCount1; i++)
                {
                    parser.GetUnsigned();
                }

                uint lowerBoundCount1 = parser.GetUnsigned();

                for (uint i = 0; i < lowerBoundCount1; i++)
                {
                    parser.GetUnsigned();
                }
                break;
            }

            case TypeSignatureKind.FunctionPointer:
            {
                // callingConvention is in data
                uint argCount1 = parser.GetUnsigned();

                for (uint i = 0; i < argCount1; i++)
                {
                    if (!CompareTypeSigWithType(ref parser, moduleHandle, typeHandle))
                    {
                        return(false);
                    }
                }
                return(false);
            }

            case TypeSignatureKind.Instantiation:
            {
                if (typeHandle.HandleType != HandleType.TypeInstantiationSignature)
                {
                    return(false);
                }

                TypeInstantiationSignature sig = typeHandle
                                                 .ToTypeInstantiationSignatureHandle(_metadataReader)
                                                 .GetTypeInstantiationSignature(_metadataReader);

                if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.GenericType))
                {
                    return(false);
                }

                uint genericArgIndex = 0;
                foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments)
                {
                    if (genericArgIndex >= data)
                    {
                        // The metadata generic has more parameters than the native layour
                        return(false);
                    }
                    if (!CompareTypeSigWithType(ref parser, moduleHandle, genericArgumentTypeHandle))
                    {
                        return(false);
                    }
                    genericArgIndex++;
                }
                // Make sure all generic parameters have been matched
                return(genericArgIndex == data);
            }

            case TypeSignatureKind.BuiltIn:
            case TypeSignatureKind.External:
            {
                RuntimeTypeHandle type2;
                switch (typeHandle.HandleType)
                {
                case HandleType.TypeDefinition:
                    if (!TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(
                            new QTypeDefinition(_metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader)), out type2))
                    {
                        return(false);
                    }
                    break;

                case HandleType.TypeReference:
                    if (!TypeLoaderEnvironment.TryResolveNamedTypeForTypeReference(
                            _metadataReader, typeHandle.ToTypeReferenceHandle(_metadataReader), out type2))
                    {
                        return(false);
                    }
                    break;

                default:
                    return(false);
                }

                RuntimeTypeHandle type1 = default(RuntimeTypeHandle);
                if (typeSignatureKind == TypeSignatureKind.External)
                {
                    type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, moduleHandle, startOffset);
                }
                else
                {
                    type1 = ((Internal.TypeSystem.WellKnownType)data).GetRuntimeTypeHandle();
                }

                return(type1.Equals(type2));
            }

            default:
                return(false);
            }
            return(true);
        }
Exemple #21
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);
        }
Exemple #22
0
        private bool ResolveInterfaceGenericVirtualMethodSlot_Static(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature)
        {
            // Get the open type definition of the containing type of the generic virtual method being resolved
            RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType);

            // Get the open type definition of the current type of the object instance on which the GVM is being resolved
            RuntimeTypeHandle openTargetTypeHandle;

            RuntimeTypeHandle[] targetTypeInstantiation;
            openTargetTypeHandle = GetOpenTypeDefinition(targetTypeHandle, out targetTypeInstantiation);

#if REFLECTION_EXECUTION_TRACE
            ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name);
#endif

            foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle)))
            {
                NativeReader gvmTableReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader))
                {
                    continue;
                }

                NativeReader nativeLayoutReader;
                if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader))
                {
                    continue;
                }

                NativeParser    gvmTableParser = new NativeParser(gvmTableReader, 0);
                NativeHashtable gvmHashtable   = new NativeHashtable(gvmTableParser);

                ExternalReferencesTable extRefs = default(ExternalReferencesTable);
                extRefs.InitializeCommonFixupsTable(moduleHandle);

                var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode());

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!openCallingTypeHandle.Equals(interfaceTypeHandle))
                    {
                        continue;
                    }

                    uint nameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned());
                    MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, nameAndSigToken);

                    if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature))
                    {
                        continue;
                    }

                    // For each of the possible GVM slot targets for the current interface call, we will do the following:
                    //
                    //  Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look
                    //          for ones that match the target object's type.
                    //
                    //  Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target
                    //          provides an implementation for
                    //
                    //  Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument
                    //          substitution (in case of a generic interface), and check if this interface signature is assignable from the
                    //          calling interface signature (from the name and sig input). if there is an exact match based on
                    //          interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface
                    //          type is compatible with the initial slots interface by means of variance.
                    //          This is done by calling the TypeLoaderEnvironment helper function.
                    //
                    // Example:
                    //      public interface IFoo<out T, out U>
                    //      {
                    //          string M1<V>();
                    //      }
                    //      public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U>
                    //      {
                    //          string IFoo<T, U>.M1<V>() { ... }
                    //          public virtual string M1<V>() { ... }
                    //      }
                    //      public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T>
                    //      {
                    //          string IFoo<U, T>.M1<V>() { ... }
                    //      }
                    //
                    //  GVM Table layout for IFoo<T, U>.M1<V>:
                    //  {
                    //      InterfaceTypeHandle = IFoo<T, U>
                    //      InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) }
                    //      GVMTargetSlots[] =
                    //      {
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo1<T, U>
                    //              ImplementingTypes[] = {
                    //                  ImplementingTypeHandle = Foo1<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) }
                    //              }
                    //          },
                    //
                    //          {
                    //              TargetMethodNameAndSignature = { "M1", SigOf(M1) }
                    //              TargetTypeHandle = Foo2<T, U>
                    //              ImplementingTypes = {
                    //                  ImplementingTypeHandle = Foo2<T, U>
                    //                  ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) }
                    //              }
                    //          },
                    //      }
                    //  }
                    //

                    uint currentOffset = entryParser.Offset;

                    // Non-variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false))
                    {
                        return(true);
                    }

                    entryParser.Offset = currentOffset;

                    // Variant dispatch of a variant generic interface generic virtual method.
                    if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #23
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);
        }
Exemple #24
0
        private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, moduleHandle, nameAndSigToken);
                RuntimeTypeHandle      targetTypeHandle             = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

#if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
#endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                        {
                            entryParser.GetUnsigned();
                        }

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetNativeLayoutOffsetFromIndex(entryParser.GetUnsigned()));

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, moduleHandle, targetTypeInstantiation, null, out currentIfaceTypeHandle))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
#if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
#endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType          = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemple #25
0
 internal AllEntriesEnumerator(NativeHashtable table)
 {
     _table         = table;
     _currentBucket = 0;
     _parser        = _table.GetParserForBucket(_currentBucket, out _endOffset);
 }
        private bool CompareMethodSigs(NativeParser parser1, NativeFormatModuleInfo moduleHandle1, NativeParser parser2, NativeFormatModuleInfo moduleHandle2)
        {
            MethodCallingConvention callingConvention1 = (MethodCallingConvention)parser1.GetUnsigned();
            MethodCallingConvention callingConvention2 = (MethodCallingConvention)parser2.GetUnsigned();

            if (callingConvention1 != callingConvention2)
            {
                return(false);
            }

            if ((callingConvention1 & MethodCallingConvention.Generic) == MethodCallingConvention.Generic)
            {
                if (parser1.GetUnsigned() != parser2.GetUnsigned())
                {
                    return(false);
                }
            }

            uint parameterCount1 = parser1.GetUnsigned();
            uint parameterCount2 = parser2.GetUnsigned();

            if (parameterCount1 != parameterCount2)
            {
                return(false);
            }

            // Compare one extra parameter to account for the return type
            for (uint i = 0; i <= parameterCount1; i++)
            {
                if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Try to look up field access info for given canon in metadata blobs for all available modules.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private unsafe static bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            TypeManagerHandle fieldHandleModule            = ModuleList.Instance.GetModuleForMetadataReader(metadataReader);
            bool              isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle);
            string            fieldName     = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle);

            foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    if ((canonFormKind == CanonicalFormKind.Universal) != ((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) != 0))
                    {
                        continue;
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) &&
                        !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle))
                    {
                        continue;
                    }

                    if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0)
                    {
                        Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle();
                        if (!fieldHandle.Equals(entryFieldHandle))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (fieldName == null)
                        {
                            QTypeDefinition qTypeDefinition;

                            bool success = Instance.TryGetMetadataForNamedType(
                                declaringTypeHandleDefinition,
                                out qTypeDefinition);
                            Debug.Assert(success);

                            MetadataReader nativeFormatMetadataReader = qTypeDefinition.NativeFormatReader;

                            fieldName = nativeFormatMetadataReader.GetString(fieldHandle.GetField(nativeFormatMetadataReader).Name);
                        }

                        string entryFieldName = entryParser.GetString();

                        if (fieldName != entryFieldName)
                        {
                            continue;
                        }
                    }

                    int    fieldOffset = -1;
                    int    threadStaticsStartOffset = -1;
                    IntPtr fieldAddressCookie       = IntPtr.Zero;

                    if (canonFormKind == CanonicalFormKind.Universal)
                    {
                        if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, entryParser.GetUnsigned() /* field ordinal */, out fieldOffset))
                        {
                            Debug.Assert(false);
                            return(false);
                        }
                    }
                    else
                    {
                        if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic)
                        {
                            if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0)
                            {
                                if ((entryFlags & FieldTableFlags.IsAnyCanonicalEntry) == 0)
                                {
                                    int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned());
                                    fieldAddressCookie       = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets);
                                    threadStaticsStartOffset = *(int *)fieldAddressCookie.ToPointer();
                                }
                                fieldOffset = (int)entryParser.GetUnsigned();
                            }
                            else
                            {
                                int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned());
                                fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets);
                                ThreadStaticFieldOffsets *pThreadStaticFieldOffsets = (ThreadStaticFieldOffsets *)fieldAddressCookie.ToPointer();

                                threadStaticsStartOffset = (int)pThreadStaticFieldOffsets->StartingOffsetInTlsBlock;
                                fieldOffset = (int)pThreadStaticFieldOffsets->FieldOffset;
                            }
                        }
                        else
                        {
                            if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0)
                            {
                                fieldOffset = (int)entryParser.GetUnsigned();
                            }
                            else
                            {
#if PROJECTN
                                fieldOffset = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned());
#else
                                fieldOffset        = 0;
                                fieldAddressCookie = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned());

                                if ((entryFlags & FieldTableFlags.IsGcSection) != 0)
                                {
                                    fieldOffset = (int)entryParser.GetUnsigned();
                                }
#endif
                            }
                        }
                    }

                    if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic)
                    {
                        // TODO: CoreRT support

                        if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle))
                        {
                            if (!TypeLoaderEnvironment.Instance.TryGetThreadStaticStartOffset(declaringTypeHandle, out threadStaticsStartOffset))
                            {
                                return(false);
                            }
                        }

                        fieldAddressCookie = new IntPtr(threadStaticsStartOffset);
                    }

                    fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle;
                    fieldAccessMetadata.Cookie             = fieldAddressCookie;
                    fieldAccessMetadata.Flags  = entryFlags;
                    fieldAccessMetadata.Offset = fieldOffset;
                    return(true);
                }
            }

            return(false);
        }
Exemple #28
0
        private InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = null;
            nativeLayoutInfoToken  = 0;
            var canonForm = concreteMethod.GetCanonMethodTarget(kind);
            var hashCode  = canonForm.GetHashCode();

            foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules())
            {
                NativeReader nativeLayoutReader = TypeLoaderEnvironment.Instance.GetNativeLayoutInfoReader(moduleInfo.Handle);
                if (nativeLayoutReader == null)
                {
                    continue;
                }

                ExternalReferencesTable externalFixupsTable;
                NativeHashtable         genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out externalFixupsTable);

                if (genericMethodTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var context = new NativeLayoutInfoLoadContext
                {
                    _typeSystemContext     = concreteMethod.Context,
                    _typeArgumentHandles   = concreteMethod.OwningType.Instantiation,
                    _methodArgumentHandles = concreteMethod.Instantiation,
                    _module = moduleInfo
                };

                var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var methodSignatureParser = new NativeParser(nativeLayoutReader, externalFixupsTable.GetExternalNativeLayoutOffset(entryParser.GetUnsigned()));

                    // Get the unified generic method holder and convert it to its canonical form
                    var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser);
                    Debug.Assert(candidateTemplate.Instantiation.Length > 0);

                    if (canonForm == candidateTemplate.GetCanonMethodTarget(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoModule = moduleInfo;
                        nativeLayoutInfoToken  = (uint)externalFixupsTable.GetExternalNativeLayoutOffset(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal && candidateTemplate != candidateTemplate.GetCanonMethodTarget(kind)) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind)));

                        return(candidateTemplate);
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString());
            return(null);
        }
        /// <summary>
        /// Try to look up non-gc/gc static effective field bases for a non-generic non-dynamic type.
        /// </summary>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldAccessKind">type of static base to find</param>
        /// <param name="staticsRegionAddress">Output - statics region address info</param>
        /// <returns>true when found, false otherwise</returns>
        private static unsafe bool TryGetStaticFieldBaseFromFieldAccessMap(
            RuntimeTypeHandle declaringTypeHandle,
            FieldAccessStaticDataKind fieldAccessKind,
            out IntPtr staticsRegionAddress)
        {
            staticsRegionAddress = IntPtr.Zero;
            byte *comparableStaticRegionAddress = null;

            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, CanonicalFormKind.Specific);

            // This function only finds results for non-dynamic, non-generic types
            if (RuntimeAugments.IsDynamicType(declaringTypeHandle) || RuntimeAugments.IsGenericType(declaringTypeHandle))
            {
                return(false);
            }

            foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    Debug.Assert((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) == 0);

                    if ((entryFlags & FieldTableFlags.Static) == 0)
                    {
                        continue;
                    }

                    switch (fieldAccessKind)
                    {
                    case FieldAccessStaticDataKind.NonGC:
                        if ((entryFlags & FieldTableFlags.IsGcSection) != 0)
                        {
                            continue;
                        }
                        if ((entryFlags & FieldTableFlags.ThreadStatic) != 0)
                        {
                            continue;
                        }
                        break;

                    case FieldAccessStaticDataKind.GC:
                        if ((entryFlags & FieldTableFlags.IsGcSection) != 0)
                        {
                            continue;
                        }
                        if ((entryFlags & FieldTableFlags.ThreadStatic) != 0)
                        {
                            continue;
                        }
                        break;

                    case FieldAccessStaticDataKind.TLS:
                    default:
                        // TODO! TLS statics
                        Environment.FailFast("TLS static field access not yet supported");
                        return(false);
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle))
                    {
                        continue;
                    }

                    if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0)
                    {
                        // skip metadata handle
                        entryParser.GetUnsigned();
                    }
                    else
                    {
                        // skip field name
                        entryParser.SkipString();
                    }

                    int cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned();
                    int fieldOffset             = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);

                    IntPtr fieldAddress = RvaToNonGenericStaticFieldAddress(
                        mappingTableModule.Handle, fieldOffset);

                    if ((comparableStaticRegionAddress == null) || (comparableStaticRegionAddress > fieldAddress.ToPointer()))
                    {
                        comparableStaticRegionAddress = (byte *)fieldAddress.ToPointer();
                    }
                }

                // Static fields for a type can only be found in at most one module
                if (comparableStaticRegionAddress != null)
                {
                    break;
                }
            }

            if (comparableStaticRegionAddress != null)
            {
                staticsRegionAddress = new IntPtr(comparableStaticRegionAddress);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #30
0
        private object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature)
        {
            Instantiation typeGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(typeGenericArgumentHandles ?? Array.Empty<RuntimeTypeHandle>());
            Instantiation methodGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(methodGenericArgumentHandles ?? Array.Empty<RuntimeTypeHandle>());

            NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext();
            nativeLayoutContext._module = ModuleList.GetModuleInfoByHandle(moduleHandle);
            nativeLayoutContext._typeSystemContext = typeSystemContext;
            nativeLayoutContext._typeArgumentHandles = typeGenericArguments;
            nativeLayoutContext._methodArgumentHandles = methodGenericArguments;

            if (isMethodSignature)
                return nativeLayoutContext.GetMethod(ref parser);
            else
                return nativeLayoutContext.GetType(ref parser);
        }
Exemple #31
0
 /// Parse the native layout to ensure that the type has proper base type setup.
 /// This is used to generalize out some behavior of NoMetadataTypes which actually use this information
 internal virtual void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser)
 {
     return;
 }
Exemple #32
0
        private static unsafe bool TryGetStructData(RuntimeTypeHandle structTypeHandle, out ExternalReferencesTable externalReferences, out NativeParser entryParser)
        {
            int structHashcode = structTypeHandle.GetHashCode();

            externalReferences = default(ExternalReferencesTable);
            entryParser        = default(NativeParser);
            foreach (TypeManagerHandle module in RuntimeAugments.GetLoadedModules())
            {
                NativeReader structMapReader;
                if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.StructMarshallingStubMap, out structMapReader))
                {
                    NativeParser    structMapParser = new NativeParser(structMapReader, 0);
                    NativeHashtable structHashtable = new NativeHashtable(structMapParser);

                    externalReferences.InitializeCommonFixupsTable(module);

                    var lookup = structHashtable.Lookup(structHashcode);
                    while (!(entryParser = lookup.GetNext()).IsNull)
                    {
                        RuntimeTypeHandle foundStructType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                        if (foundStructType.Equals(structTypeHandle))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Exemple #33
0
        private static ComputedStaticFieldLayout ParseStaticRegionSizesFromNativeLayout(TypeDesc type)
        {
            LayoutInt nonGcDataSize  = LayoutInt.Zero;
            LayoutInt gcDataSize     = LayoutInt.Zero;
            LayoutInt threadDataSize = LayoutInt.Zero;

            TypeBuilderState state          = type.GetOrCreateTypeBuilderState();
            NativeParser     typeInfoParser = state.GetParserForNativeLayoutInfo();

            BagElementKind kind;

            while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End)
            {
                switch (kind)
                {
                case BagElementKind.NonGcStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    nonGcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                case BagElementKind.GcStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    gcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                case BagElementKind.ThreadStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    threadDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                default:
                    typeInfoParser.SkipInteger();
                    break;
                }
            }

            ComputedStaticFieldLayout staticLayout = new ComputedStaticFieldLayout()
            {
                GcStatics = new StaticsBlock()
                {
                    Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
                NonGcStatics = new StaticsBlock()
                {
                    Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
                Offsets         = null, // We're not computing field offsets here, so return null
                ThreadGcStatics = new StaticsBlock()
                {
                    Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
                ThreadNonGcStatics = new StaticsBlock()
                {
                    Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero
                },
            };

            return(staticLayout);
        }
        private bool CompareTypeSigWithType(ref NativeParser parser, Handle typeHandle)
        {
            while (typeHandle.HandleType == HandleType.TypeSpecification)
            {
                typeHandle = typeHandle
                    .ToTypeSpecificationHandle(_metadataReader)
                    .GetTypeSpecification(_metadataReader)
                    .Signature;
            }

            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint startOffset = parser.Offset;

            uint data;
            var typeSignatureKind = parser.GetTypeSignatureKind(out data);

            switch (typeSignatureKind)
            {
                case TypeSignatureKind.Lookback:
                    {
                        NativeParser lookbackParser = parser.GetLookbackParser(data);
                        return CompareTypeSigWithType(ref lookbackParser, typeHandle);
                    }

                case TypeSignatureKind.Modifier:
                    {
                        // Ensure the modifier kind (vector, pointer, byref) is the same
                        TypeModifierKind modifierKind = (TypeModifierKind)data;
                        switch (modifierKind)
                        {
                            case TypeModifierKind.Array:
                                if (typeHandle.HandleType == HandleType.SZArraySignature)
                                {
                                    return CompareTypeSigWithType(ref parser, typeHandle
                                        .ToSZArraySignatureHandle(_metadataReader)
                                        .GetSZArraySignature(_metadataReader)
                                        .ElementType);
                                }
                                return false;

                            case TypeModifierKind.ByRef:
                                if (typeHandle.HandleType == HandleType.ByReferenceSignature)
                                {
                                    return CompareTypeSigWithType(ref parser, typeHandle
                                        .ToByReferenceSignatureHandle(_metadataReader)
                                        .GetByReferenceSignature(_metadataReader)
                                        .Type);
                                }
                                return false;

                            case TypeModifierKind.Pointer:
                                if (typeHandle.HandleType == HandleType.PointerSignature)
                                {
                                    return CompareTypeSigWithType(ref parser, typeHandle
                                        .ToPointerSignatureHandle(_metadataReader)
                                        .GetPointerSignature(_metadataReader)
                                        .Type);
                                }
                                return false;

                            default:
                                Debug.Assert(null == "invalid type modifier kind");
                                return false;
                        }
                    }

                case TypeSignatureKind.Variable:
                    {
                        bool isMethodVar = (data & 0x1) == 1;
                        uint index = data >> 1;

                        if (isMethodVar)
                        {
                            if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature)
                            {
                                return index == typeHandle
                                    .ToMethodTypeVariableSignatureHandle(_metadataReader)
                                    .GetMethodTypeVariableSignature(_metadataReader)
                                    .Number;
                            }
                        }
                        else
                        {
                            if (typeHandle.HandleType == HandleType.TypeVariableSignature)
                            {
                                return index == typeHandle
                                    .ToTypeVariableSignatureHandle(_metadataReader)
                                    .GetTypeVariableSignature(_metadataReader)
                                    .Number;
                            }
                        }

                        return false;
                    }

                case TypeSignatureKind.MultiDimArray:
                    {
                        if (typeHandle.HandleType != HandleType.ArraySignature)
                        {
                            return false;
                        }

                        ArraySignature sig = typeHandle
                            .ToArraySignatureHandle(_metadataReader)
                            .GetArraySignature(_metadataReader);

                        if (data != sig.Rank)
                            return false;

                        if (!CompareTypeSigWithType(ref parser, sig.ElementType))
                            return false;

                        uint boundCount1 = parser.GetUnsigned();
                        for (uint i = 0; i < boundCount1; i++)
                        {
                            parser.GetUnsigned();
                        }

                        uint lowerBoundCount1 = parser.GetUnsigned();

                        for (uint i = 0; i < lowerBoundCount1; i++)
                        {
                            parser.GetUnsigned();
                        }
                        break;
                    }

                case TypeSignatureKind.FunctionPointer:
                    {
                        // callingConvention is in data
                        uint argCount1 = parser.GetUnsigned();

                        for (uint i = 0; i < argCount1; i++)
                        {
                            if (!CompareTypeSigWithType(ref parser, typeHandle))
                                return false;
                        }
                        return false;
                    }

                case TypeSignatureKind.Instantiation:
                    {
                        if (typeHandle.HandleType != HandleType.TypeInstantiationSignature)
                        {
                            return false;
                        }

                        TypeInstantiationSignature sig = typeHandle
                            .ToTypeInstantiationSignatureHandle(_metadataReader)
                            .GetTypeInstantiationSignature(_metadataReader);

                        if (!CompareTypeSigWithType(ref parser, sig.GenericType))
                        {
                            return false;
                        }

                        uint genericArgIndex = 0;
                        foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments)
                        {
                            if (genericArgIndex >= data)
                            {
                                // The metadata generic has more parameters than the native layour
                                return false;
                            }
                            if (!CompareTypeSigWithType(ref parser, genericArgumentTypeHandle))
                            {
                                return false;
                            }
                            genericArgIndex++;
                        }
                        // Make sure all generic parameters have been matched
                        return genericArgIndex == data;
                    }

                case TypeSignatureKind.External:
                    {
                        RuntimeTypeHandle type2;
                        switch (typeHandle.HandleType)
                        {
                            case HandleType.TypeDefinition:
                                if (!TypeLoaderEnvironment.Instance.TryGetOrCreateNamedTypeForMetadata(
                                    _metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader), out type2))
                                {
                                    return false;
                                }
                                break;

                            case HandleType.TypeReference:
                                if (!TypeLoaderEnvironment.TryGetNamedTypeForTypeReference(
                                    _metadataReader, typeHandle.ToTypeReferenceHandle(_metadataReader), out type2))
                                {
                                    return false;
                                }
                                break;

                            default:
                                return false;
                        }

                        RuntimeTypeHandle type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, startOffset);
                        return type1.Equals(type2);
                    }

                default:
                    return false;
            }
            return true;
        }
Exemple #35
0
        private static void EnsureFieldLayoutLoadedForUniversalType(DefType type, NativeLayoutInfoLoadContext loadContext, NativeParser fieldLayoutParser)
        {
            Debug.Assert(type.HasInstantiation);
            Debug.Assert(type.ComputeTemplate().IsCanonicalSubtype(CanonicalFormKind.Universal));

            if (type.NativeLayoutFields != null)
            {
                return;
            }

            type.NativeLayoutFields = ParseFieldLayout(type, loadContext, fieldLayoutParser);
        }
Exemple #36
0
 public static RuntimeTypeHandle GetTypeFromNativeLayoutSignature(ref NativeParser parser, uint offset)
 {
     throw new NotImplementedException();
 }
Exemple #37
0
        private static NativeLayoutFieldDesc[] ParseFieldLayout(DefType owningType,
                                                                NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser fieldLayoutParser)
        {
            if (fieldLayoutParser.IsNull)
            {
                return(Empty <NativeLayoutFieldDesc> .Array);
            }

            uint numFields = fieldLayoutParser.GetUnsigned();
            var  fields    = new NativeLayoutFieldDesc[numFields];

            for (int i = 0; i < numFields; i++)
            {
                TypeDesc fieldType = nativeLayoutInfoLoadContext.GetType(ref fieldLayoutParser);
                NativeFormat.FieldStorage storage = (NativeFormat.FieldStorage)fieldLayoutParser.GetUnsigned();
                fields[i] = new NativeLayoutFieldDesc(owningType, fieldType, storage);
            }

            return(fields);
        }
Exemple #38
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;
        }
Exemple #39
0
        public override DefType[] ComputeRuntimeInterfaces(TypeDesc type)
        {
            TypeBuilderState state = type.GetOrCreateTypeBuilderState();
            int totalInterfaces    = RuntimeAugments.GetInterfaceCount(state.TemplateType.RuntimeTypeHandle);

            TypeLoaderLogger.WriteLine("Building runtime interfaces for type " + type.ToString() + " (total interfaces = " + totalInterfaces.LowLevelToString() + ") ...");

            DefType[] interfaces    = new DefType[totalInterfaces];
            int       numInterfaces = 0;

            //
            // Copy over all interfaces from base class
            //
            if (type.BaseType != null)
            {
                foreach (var baseInterface in type.BaseType.RuntimeInterfaces)
                {
                    // There should be no duplicates
                    Debug.Assert(!InterfaceInSet(interfaces, numInterfaces, baseInterface));
                    interfaces[numInterfaces++] = baseInterface;
                    TypeLoaderLogger.WriteLine("    -> Added basetype interface " + baseInterface.ToString() + " on type " + type.ToString());
                }
            }

            NativeParser typeInfoParser  = state.GetParserForNativeLayoutInfo();
            NativeParser interfaceParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.ImplementedInterfaces);

            TypeDesc[] implementedInterfaces;
            if (!interfaceParser.IsNull)
            {
                implementedInterfaces = state.NativeLayoutInfo.LoadContext.GetTypeSequence(ref interfaceParser);
            }
            else
            {
                implementedInterfaces = TypeDesc.EmptyTypes;
            }

            // Note that the order in which the interfaces are added to the list is same as the order in which the MDIL binder adds them.
            // It is required for correctness

            foreach (TypeDesc interfaceType in implementedInterfaces)
            {
                DefType interfaceTypeAsDefType = (DefType)interfaceType;

                // Skip duplicates
                if (InterfaceInSet(interfaces, numInterfaces, interfaceTypeAsDefType))
                {
                    continue;
                }
                interfaces[numInterfaces++] = interfaceTypeAsDefType;

                TypeLoaderLogger.WriteLine("    -> Added interface " + interfaceTypeAsDefType.ToString() + " on type " + type.ToString());

                foreach (var inheritedInterface in interfaceTypeAsDefType.RuntimeInterfaces)
                {
                    // Skip duplicates
                    if (InterfaceInSet(interfaces, numInterfaces, inheritedInterface))
                    {
                        continue;
                    }
                    interfaces[numInterfaces++] = inheritedInterface;
                    TypeLoaderLogger.WriteLine("    -> Added inherited interface " + inheritedInterface.ToString() + " on type " + type.ToString());
                }
            }

            // TODO: Handle the screwy cases of generic interface folding
            Debug.Assert(numInterfaces == totalInterfaces, "Unexpected number of interfaces");

            return(interfaces);
        }