/// <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 (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();

                    Debug.Assert(!entryFlags.HasFlag(FieldTableFlags.IsUniversalCanonicalEntry));

                    if (!entryFlags.HasFlag(FieldTableFlags.Static))
                        continue;

                    switch (fieldAccessKind)
                    {
                        case FieldAccessStaticDataKind.NonGC:
                            if (entryFlags.HasFlag(FieldTableFlags.IsGcSection))
                                continue;
                            if (entryFlags.HasFlag(FieldTableFlags.ThreadStatic))
                                continue;
                            break;
                        case FieldAccessStaticDataKind.GC:
                            if (!entryFlags.HasFlag(FieldTableFlags.IsGcSection))
                                continue;
                            if (entryFlags.HasFlag(FieldTableFlags.ThreadStatic))
                                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.HasFlag(FieldTableFlags.HasMetadataHandle))
                    {
                        // 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, 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;
            }
        }
Esempio n. 2
0
        /// <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 unsafe static 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 (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();

                    Debug.Assert(!entryFlags.HasFlag(FieldTableFlags.IsUniversalCanonicalEntry));

                    if (!entryFlags.HasFlag(FieldTableFlags.Static))
                    {
                        continue;
                    }

                    switch (fieldAccessKind)
                    {
                    case FieldAccessStaticDataKind.NonGC:
                        if (entryFlags.HasFlag(FieldTableFlags.IsGcSection))
                        {
                            continue;
                        }
                        if (entryFlags.HasFlag(FieldTableFlags.ThreadStatic))
                        {
                            continue;
                        }
                        break;

                    case FieldAccessStaticDataKind.GC:
                        if (!entryFlags.HasFlag(FieldTableFlags.IsGcSection))
                        {
                            continue;
                        }
                        if (entryFlags.HasFlag(FieldTableFlags.ThreadStatic))
                        {
                            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.HasFlag(FieldTableFlags.HasMetadataHandle))
                    {
                        // 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, 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);
            }
        }
        /// <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;

            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();
                    FieldTableFlags storageClass = entryFlags & FieldTableFlags.StorageClass;

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

                    if (storageClass == FieldTableFlags.Instance)
                    {
                        continue;
                    }

                    switch (fieldAccessKind)
                    {
                    case FieldAccessStaticDataKind.NonGC:
                        if (storageClass != FieldTableFlags.NonGCStatic)
                        {
                            continue;
                        }
                        break;

                    case FieldAccessStaticDataKind.GC:
                        if (storageClass != FieldTableFlags.GCStatic)
                        {
                            continue;
                        }
                        break;

                    case FieldAccessStaticDataKind.TLS:
                        if (storageClass != FieldTableFlags.ThreadStatic)
                        {
                            continue;
                        }
                        break;

                    default:
                        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();
                    }

                    IntPtr fieldAddress = IntPtr.Zero;

                    if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) == 0)
                    {
                        fieldAddress = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned());
                    }

                    if (fieldAddress != IntPtr.Zero)
                    {
                        staticsRegionAddress = fieldAddress;
                        break;
                    }
                }

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

            return(staticsRegionAddress != IntPtr.Zero);
        }