public static bool TryGetFieldAccessMetadata(
     MetadataReader metadataReader,
     RuntimeTypeHandle runtimeTypeHandle,
     FieldHandle fieldHandle,
     out FieldAccessMetadata fieldAccessMetadata)
 {
     throw new NotImplementedException();
 }
Esempio n. 2
0
        /// <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>
        public static bool TryGetFieldAccessMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle runtimeTypeHandle,
            FieldHandle fieldHandle,
            out FieldAccessMetadata fieldAccessMetadata)
        {
            fieldAccessMetadata = default(FieldAccessMetadata);

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                    metadataReader,
                    runtimeTypeHandle,
                    fieldHandle,
                    CanonicalFormKind.Specific,
                    ref fieldAccessMetadata))
            {
                return(true);
            }

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                    metadataReader,
                    runtimeTypeHandle,
                    fieldHandle,
                    CanonicalFormKind.Universal,
                    ref fieldAccessMetadata))
            {
                return(true);
            }

            TypeSystemContext context = TypeSystemContextFactory.Create();

            bool success = TryGetFieldAccessMetadataFromNativeFormatMetadata(
                metadataReader,
                runtimeTypeHandle,
                fieldHandle,
                context,
                ref fieldAccessMetadata);

            TypeSystemContextFactory.Recycle(context);

            return(success);
        }
        /// <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>
        public static bool TryGetFieldAccessMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle runtimeTypeHandle,
            FieldHandle fieldHandle,
            out FieldAccessMetadata fieldAccessMetadata)
        {
            fieldAccessMetadata = default(FieldAccessMetadata);

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                metadataReader,
                runtimeTypeHandle,
                fieldHandle,
                CanonicalFormKind.Specific,
                ref fieldAccessMetadata))
            {
                return true;
            }

            if (TryGetFieldAccessMetadataFromFieldAccessMap(
                metadataReader,
                runtimeTypeHandle,
                fieldHandle,
                CanonicalFormKind.Universal,
                ref fieldAccessMetadata))
            {
                return true;
            }

            TypeSystemContext context = TypeSystemContextFactory.Create();

            bool success = TryGetFieldAccessMetadataFromNativeFormatMetadata(
                metadataReader,
                runtimeTypeHandle,
                fieldHandle,
                context,
                ref fieldAccessMetadata);

            TypeSystemContextFactory.Recycle(context);

            return success;
        }
Esempio n. 4
0
        /// <summary>
        /// Try to figure out field access information based on type metadata for native format types.
        /// </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 TryGetFieldAccessMetadataFromNativeFormatMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            TypeSystemContext context,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            Field  field     = metadataReader.GetField(fieldHandle);
            string fieldName = metadataReader.GetString(field.Name);

            TypeDesc declaringType = context.ResolveRuntimeTypeHandle(declaringTypeHandle);

#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            if (declaringType is MetadataType)
            {
                return(TryGetFieldAccessMetadataForNativeFormatType(declaringType, fieldName, ref fieldAccessMetadata));
            }
#endif

            return(false);
        }
Esempio n. 5
0
        /// <summary>
        /// Locate field on native format type and fill in the field access flags and offset.
        /// </summary>
        /// <param name="type">Metadata reader for the declaring type</param>
        /// <param name="fieldName">Field name</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataForNativeFormatType(
            TypeDesc type,
            string fieldName,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            FieldDesc fieldDesc = type.GetField(fieldName);
            if (fieldDesc == null)
            {
                return(false);
            }

            fieldAccessMetadata.MappingTableModule = IntPtr.Zero;

#if SUPPORTS_R2R_LOADING
            fieldAccessMetadata.MappingTableModule = ModuleList.Instance.GetModuleForMetadataReader(((NativeFormatType)type.GetTypeDefinition()).MetadataReader);
#endif
            fieldAccessMetadata.Offset = fieldDesc.Offset;
            fieldAccessMetadata.Flags  = FieldTableFlags.HasMetadataHandle;

            if (fieldDesc.IsThreadStatic)
            {
                // Specify that the data is thread local
                fieldAccessMetadata.Flags |= FieldTableFlags.ThreadStatic;

                // Specify that the general purpose field access routine that only relies on offset should be used.
                fieldAccessMetadata.Flags |= FieldTableFlags.IsUniversalCanonicalEntry;
            }
            else if (fieldDesc.IsStatic)
            {
                uint nonGcStaticsRVA = 0;
                uint gcStaticsRVA    = 0;
                bool nonGenericCase  = false;

                if (type is MetadataType)
                {
                    // Static fields on Non-Generic types are contained within the module, and their offsets
                    // are adjusted by their static rva base.
                    nonGenericCase = true;

#if SUPPORTS_R2R_LOADING
                    if (!TryGetStaticsTableEntry((MetadataType)type, nonGcStaticsRVA: out nonGcStaticsRVA, gcStaticsRVA: out gcStaticsRVA))
#endif
                    {
                        Environment.FailFast(
                            "Failed to locate statics table entry for for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                }

                if (fieldDesc.HasGCStaticBase)
                {
                    if ((gcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)gcStaticsRVA;
                    fieldAccessMetadata.Flags  |= FieldTableFlags.IsGcSection;
                }
                else
                {
                    if ((nonGcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "Non-GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)nonGcStaticsRVA;
                }
                fieldAccessMetadata.Flags |= FieldTableFlags.Static;
                return(true);
            }
            else
            {
                // Instance field
                fieldAccessMetadata.Flags |= FieldTableFlags.Instance;
            }

            return(true);
#else
            return(false);
#endif
        }
Esempio n. 6
0
        /// <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
                    {
#if CORERT
                        fieldOffset = cookieOrOffsetOrOrdinal;
#else
                        fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);
#endif
                    }

                    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);
        }
Esempio n. 7
0
        /// <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 static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            string            fieldName = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = TypeLoaderEnvironment.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;
                    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.FieldOffsetEncodedDirectly) != 0)
                        {
                            fieldOffset = (int)entryParser.GetUnsigned();
                        }
                        else
                        {
                            fieldOffset        = 0;
                            fieldAddressCookie = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned());

                            FieldTableFlags storageClass = entryFlags & FieldTableFlags.StorageClass;
                            if (storageClass == FieldTableFlags.GCStatic || storageClass == FieldTableFlags.ThreadStatic)
                            {
                                fieldOffset = (int)entryParser.GetUnsigned();
                            }
                        }
                    }

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

            return(false);
        }
        /// <summary>
        /// Locate field on native format type and fill in the field access flags and offset.
        /// </summary>
        /// <param name="type">Metadata reader for the declaring type</param>
        /// <param name="fieldName">Field name</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataForNativeFormatType(
            TypeDesc type,
            string fieldName,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            FieldDesc fieldDesc = type.GetField(fieldName);
            if (fieldDesc == null)
            {
                return false;
            }

            fieldAccessMetadata.MappingTableModule = IntPtr.Zero;

#if SUPPORTS_R2R_LOADING
            fieldAccessMetadata.MappingTableModule = ModuleList.Instance.GetModuleForMetadataReader(((NativeFormatType)type.GetTypeDefinition()).MetadataReader);
#endif
            fieldAccessMetadata.Offset = fieldDesc.Offset;
            fieldAccessMetadata.Flags = FieldTableFlags.HasMetadataHandle;

            if (fieldDesc.IsThreadStatic)
            {
                // Specify that the data is thread local
                fieldAccessMetadata.Flags |= FieldTableFlags.ThreadStatic;

                // Specify that the general purpose field access routine that only relies on offset should be used.
                fieldAccessMetadata.Flags |= FieldTableFlags.IsUniversalCanonicalEntry;
            }
            else if (fieldDesc.IsStatic)
            {
                uint nonGcStaticsRVA = 0;
                uint gcStaticsRVA = 0;
                bool nonGenericCase = false;

                if (type is MetadataType)
                {
                    // Static fields on Non-Generic types are contained within the module, and their offsets
                    // are adjusted by their static rva base.
                    nonGenericCase = true;

#if SUPPORTS_R2R_LOADING
                    if (!TryGetStaticsTableEntry((MetadataType)type, nonGcStaticsRVA: out nonGcStaticsRVA, gcStaticsRVA: out gcStaticsRVA))
#endif
                    {
                        Environment.FailFast(
                            "Failed to locate statics table entry for for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                }

                if (fieldDesc.HasGCStaticBase)
                {
                    if ((gcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)gcStaticsRVA;
                    fieldAccessMetadata.Flags |= FieldTableFlags.IsGcSection;
                }
                else
                {
                    if ((nonGcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "Non-GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)nonGcStaticsRVA;
                }
                fieldAccessMetadata.Flags |= FieldTableFlags.Static;
                return true;
            }
            else
            {
                // Instance field
                fieldAccessMetadata.Flags |= FieldTableFlags.Instance;
            }

            return true;
#else
            return false;
#endif
        }
        /// <summary>
        /// Try to figure out field access information based on type metadata for native format types.
        /// </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 TryGetFieldAccessMetadataFromNativeFormatMetadata(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            TypeSystemContext context,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            Field field = metadataReader.GetField(fieldHandle);
            string fieldName = metadataReader.GetString(field.Name);

            TypeDesc declaringType = context.ResolveRuntimeTypeHandle(declaringTypeHandle);

#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            if (declaringType is MetadataType)
            {
                return TryGetFieldAccessMetadataForNativeFormatType(declaringType, fieldName, ref fieldAccessMetadata);
            }
#endif

            return false;
        }
        /// <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
                    {
#if CORERT
                        fieldOffset = cookieOrOffsetOrOrdinal;
#else
                        fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);
#endif
                    }

                    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;
        }
Esempio n. 11
0
 public static bool TryGetFieldAccessMetadata(
     MetadataReader metadataReader,
     RuntimeTypeHandle runtimeTypeHandle,
     FieldHandle fieldHandle,
     out FieldAccessMetadata fieldAccessMetadata)
 {
     throw new NotImplementedException();
 }