| File: System\Reflection\TypeLoading\Modules\Ecma\EcmaModule.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj (System.Reflection.MetadataLoadContext) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; namespace System.Reflection.TypeLoading.Ecma { /// <summary> /// Base class for all Module objects created by a MetadataLoadContext and get its metadata from a PEReader. /// </summary> internal sealed partial class EcmaModule : RoModule { private const int ModuleTypeToken = 0x02000001; private readonly EcmaAssembly _assembly; private readonly GuardedPEReader _guardedPEReader; // // "fullyQualifiedName" determines the string returned by Module.FullyQualifiedName. It is typically set to the full path of the // file on disk containing the module. // internal EcmaModule(EcmaAssembly assembly, string fullyQualifiedName, PEReader peReader, MetadataReader reader) : base(fullyQualifiedName) { Debug.Assert(assembly != null); Debug.Assert(fullyQualifiedName != null); Debug.Assert(peReader != null); Debug.Assert(reader != null); _assembly = assembly; _guardedPEReader = new GuardedPEReader(assembly.Loader, peReader, reader); _neverAccessThisExceptThroughModuleDefinitionProperty = reader.GetModuleDefinition(); } internal sealed override RoAssembly GetRoAssembly() => _assembly; internal EcmaAssembly GetEcmaAssembly() => _assembly; public sealed override bool IsResource() => false; public sealed override int MDStreamVersion => throw new NotSupportedException(SR.NotSupported_MDStreamVersion); public sealed override int MetadataToken => 0x00000001; // The Module Table is exactly 1 record long so the token is always mdtModule | 0x000001 public sealed override Guid ModuleVersionId => ModuleDefinition.Mvid.GetGuid(Reader); public sealed override string ScopeName => ModuleDefinition.Name.GetString(Reader); public sealed override IEnumerable<CustomAttributeData> CustomAttributes => ModuleDefinition.GetCustomAttributes().ToTrueCustomAttributes(this); internal MethodInfo? ComputeEntryPoint(bool fileRefEntryPointAllowed) { PEHeaders peHeaders = PEReader.PEHeaders; CorHeader corHeader = peHeaders.CorHeader!; if ((corHeader.Flags & CorFlags.NativeEntryPoint) != 0) return null; int entryPointToken = corHeader.EntryPointTokenOrRelativeVirtualAddress; Handle handle = entryPointToken.ToHandle(); if (handle.IsNil) return null; HandleKind kind = handle.Kind; switch (kind) { case HandleKind.MethodDefinition: { MethodDefinitionHandle mdh = (MethodDefinitionHandle)handle; return mdh.ResolveMethod<MethodInfo>(this, default); } case HandleKind.AssemblyFile: { if (!fileRefEntryPointAllowed) throw new BadImageFormatException(); MetadataReader reader = Reader; string moduleName = ((AssemblyFileHandle)handle).GetAssemblyFile(reader).Name.GetString(reader); EcmaModule? roModule = (EcmaModule?)(Assembly.GetModule(moduleName)); return roModule!.ComputeEntryPoint(fileRefEntryPointAllowed: false); } default: throw new BadImageFormatException(); } } public sealed override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) { PEHeaders peHeaders = PEReader.PEHeaders; PEMagic peMagic = peHeaders.PEHeader!.Magic; Machine coffMachine = peHeaders.CoffHeader.Machine; CorFlags corFlags = peHeaders.CorHeader!.Flags; peKind = default; if ((corFlags & CorFlags.ILOnly) != 0) peKind |= PortableExecutableKinds.ILOnly; if ((corFlags & CorFlags.Prefers32Bit) != 0) peKind |= PortableExecutableKinds.Preferred32Bit; else if ((corFlags & CorFlags.Requires32Bit) != 0) peKind |= PortableExecutableKinds.Required32Bit; if (peMagic == PEMagic.PE32Plus) peKind |= PortableExecutableKinds.PE32Plus; machine = (ImageFileMachine)coffMachine; } // // Search for members on <Module> type. // public sealed override FieldInfo? GetField(string name, BindingFlags bindingAttr) => GetModuleType().GetField(name, bindingAttr); public sealed override FieldInfo[] GetFields(BindingFlags bindingFlags) => GetModuleType().GetFields(bindingFlags); public sealed override MethodInfo[] GetMethods(BindingFlags bindingFlags) => GetModuleType().GetMethods(bindingFlags); protected sealed override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => GetModuleType().InternalGetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers); private EcmaDefinitionType GetModuleType() => ModuleTypeToken.ToTypeDefinitionHandle().ResolveTypeDef(this); public sealed override Type[] GetTypes() { // Note: we don't expect this process to generate any loader exceptions so no need to implement the ReflectionTypeLoadException // logic. EnsureTypeDefTableFullyFilled(); return TypeDefTable.ToArray<Type>(skip: 1); // 0x02000001 is the <Module> type which is always skipped by this api. } internal sealed override IEnumerable<RoType>? GetDefinedRoTypes() { EnsureTypeDefTableFullyFilled(); return TypeDefTable.EnumerateValues(skip: 1)!; // 0x02000001 is the <Module> type which is always skipped by this api. } internal PEReader PEReader => _guardedPEReader.PEReader; internal MetadataReader Reader => _guardedPEReader.Reader; private ref readonly ModuleDefinition ModuleDefinition { get { Loader.DisposeCheck(); return ref _neverAccessThisExceptThroughModuleDefinitionProperty; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] // Block from debugger watch windows so they don't AV the debugged process. private readonly ModuleDefinition _neverAccessThisExceptThroughModuleDefinitionProperty; } }