diff options
Diffstat (limited to 'src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs')
-rw-r--r-- | src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs | 2422 |
1 files changed, 2422 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs new file mode 100644 index 0000000000..ce2a592ae2 --- /dev/null +++ b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -0,0 +1,2422 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +namespace System.Reflection.Emit +{ + using System.Runtime.InteropServices; + using System; + using System.Collections.Generic; + using System.Diagnostics.SymbolStore; + using System.Globalization; + using System.Reflection; + using System.Diagnostics; + using System.IO; + using System.Resources; + using System.Security; + using System.Security.Permissions; + using System.Runtime.Serialization; + using System.Text; + using System.Threading; + using System.Runtime.Versioning; + using System.Runtime.CompilerServices; + using System.Diagnostics.Contracts; + + internal sealed class InternalModuleBuilder : RuntimeModule + { + #region Private Data Members + // WARNING!! WARNING!! + // InternalModuleBuilder should not contain any data members as its reflectbase is the same as Module. + #endregion + + private InternalModuleBuilder() { } + + #region object overrides + public override bool Equals(object obj) + { + if (obj == null) + return false; + + if (obj is InternalModuleBuilder) + return ((object)this == obj); + + return obj.Equals(this); + } + // Need a dummy GetHashCode to pair with Equals + public override int GetHashCode() { return base.GetHashCode(); } + #endregion + } + + // deliberately not [serializable] + [HostProtection(MayLeakOnAbort = true)] + [ClassInterface(ClassInterfaceType.None)] + [ComDefaultInterface(typeof(_ModuleBuilder))] + [System.Runtime.InteropServices.ComVisible(true)] + public class ModuleBuilder : Module, _ModuleBuilder + { + #region FCalls + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr nCreateISymWriterForDynamicModule(Module module, String filename); + + #endregion + + #region Internal Static Members + static internal String UnmangleTypeName(String typeName) + { + // Gets the original type name, without '+' name mangling. + + int i = typeName.Length - 1; + while (true) + { + i = typeName.LastIndexOf('+', i); + if (i == -1) + break; + + bool evenSlashes = true; + int iSlash = i; + while (typeName[--iSlash] == '\\') + evenSlashes = !evenSlashes; + + // Even number of slashes means this '+' is a name separator + if (evenSlashes) + break; + + i = iSlash; + } + + return typeName.Substring(i + 1); + } + + #endregion + + #region Intenral Data Members + // m_TypeBuilder contains both TypeBuilder and EnumBuilder objects + private Dictionary<string, Type> m_TypeBuilderDict; + private ISymbolWriter m_iSymWriter; + internal ModuleBuilderData m_moduleData; +#if !FEATURE_CORECLR + private MethodToken m_EntryPoint; +#endif //!FEATURE_CORECLR + internal InternalModuleBuilder m_internalModuleBuilder; + // This is the "external" AssemblyBuilder + // only the "external" ModuleBuilder has this set + private AssemblyBuilder m_assemblyBuilder; + internal AssemblyBuilder ContainingAssemblyBuilder { get { return m_assemblyBuilder; } } + #endregion + + #region Constructor + internal ModuleBuilder(AssemblyBuilder assemblyBuilder, InternalModuleBuilder internalModuleBuilder) + { + m_internalModuleBuilder = internalModuleBuilder; + m_assemblyBuilder = assemblyBuilder; + } + #endregion + + #region Private Members + internal void AddType(string name, Type type) + { + m_TypeBuilderDict.Add(name, type); + } + + internal void CheckTypeNameConflict(String strTypeName, Type enclosingType) + { + Type foundType = null; + if (m_TypeBuilderDict.TryGetValue(strTypeName, out foundType) && + object.ReferenceEquals(foundType.DeclaringType, enclosingType)) + { + // Cannot have two types with the same name + throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName")); + } + } + + private Type GetType(String strFormat, Type baseType) + { + // This function takes a string to describe the compound type, such as "[,][]", and a baseType. + + if (strFormat == null || strFormat.Equals(String.Empty)) + { + return baseType; + } + + // convert the format string to byte array and then call FormCompoundType + return SymbolType.FormCompoundType(strFormat, baseType, 0); + + } + + + internal void CheckContext(params Type[][] typess) + { + ContainingAssemblyBuilder.CheckContext(typess); + } + internal void CheckContext(params Type[] types) + { + ContainingAssemblyBuilder.CheckContext(types); + } + + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetTypeRef(RuntimeModule module, String strFullName, RuntimeModule refedModule, String strRefedModuleFileName, int tkResolution); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetMemberRef(RuntimeModule module, RuntimeModule refedModule, int tr, int defToken); + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRef(Module refedModule, int tr, int defToken) + { + return GetMemberRef(GetNativeHandle(), GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), tr, defToken); + } + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetMemberRefFromSignature(RuntimeModule module, int tr, String methodName, byte[] signature, int length); + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRefFromSignature(int tr, String methodName, byte[] signature, int length) + { + return GetMemberRefFromSignature(GetNativeHandle(), tr, methodName, signature, length); + } + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetMemberRefOfMethodInfo(RuntimeModule module, int tr, IRuntimeMethodInfo method); + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRefOfMethodInfo(int tr, RuntimeMethodInfo method) + { + Contract.Assert(method != null); + +#if FEATURE_APPX + if (ContainingAssemblyBuilder.ProfileAPICheck) + { + if ((method.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", method.FullName)); + } +#endif + + return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method); + } + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRefOfMethodInfo(int tr, RuntimeConstructorInfo method) + { + Contract.Assert(method != null); + +#if FEATURE_APPX + if (ContainingAssemblyBuilder.ProfileAPICheck) + { + if ((method.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", method.FullName)); + } +#endif + + return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method); + } + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetMemberRefOfFieldInfo(RuntimeModule module, int tkType, RuntimeTypeHandle declaringType, int tkField); + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRefOfFieldInfo(int tkType, RuntimeTypeHandle declaringType, RuntimeFieldInfo runtimeField) + { + Contract.Assert(runtimeField != null); + +#if FEATURE_APPX + if (ContainingAssemblyBuilder.ProfileAPICheck) + { + RtFieldInfo rtField = runtimeField as RtFieldInfo; + if (rtField != null && (rtField.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtField.FullName)); + } +#endif + + return GetMemberRefOfFieldInfo(GetNativeHandle(), tkType, declaringType, runtimeField.MetadataToken); + } + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetTokenFromTypeSpec(RuntimeModule pModule, byte[] signature, int length); + + [System.Security.SecurityCritical] // auto-generated + private int GetTokenFromTypeSpec(byte[] signature, int length) + { + return GetTokenFromTypeSpec(GetNativeHandle(), signature, length); + } + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetArrayMethodToken(RuntimeModule module, int tkTypeSpec, String methodName, byte[] signature, int sigLength); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static int GetStringConstant(RuntimeModule module, String str, int length); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void PreSavePEFile(RuntimeModule module, int portableExecutableKind, int imageFileMachine); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void SavePEFile(RuntimeModule module, String fileName, int entryPoint, int isExe, bool isManifestFile); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void AddResource( + RuntimeModule module, String strName, + byte[] resBytes, int resByteCount, int tkFile, int attribute, + int portableExecutableKind, int imageFileMachine); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void SetModuleName(RuntimeModule module, String strModuleName); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + internal extern static void SetFieldRVAContent(RuntimeModule module, int fdToken, byte[] data, int length); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void DefineNativeResourceFile(RuntimeModule module, + String strFilename, + int portableExecutableKind, + int ImageFileMachine); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private extern static void DefineNativeResourceBytes(RuntimeModule module, + byte[] pbResource, int cbResource, + int portableExecutableKind, + int imageFileMachine); + + [System.Security.SecurityCritical] // auto-generated + internal void DefineNativeResource(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + string strResourceFileName = m_moduleData.m_strResourceFileName; + byte[] resourceBytes = m_moduleData.m_resourceBytes; + + if (strResourceFileName != null) + { + DefineNativeResourceFile(GetNativeHandle(), + strResourceFileName, + (int)portableExecutableKind, (int)imageFileMachine); + } + else + if (resourceBytes != null) + { + DefineNativeResourceBytes(GetNativeHandle(), + resourceBytes, resourceBytes.Length, + (int)portableExecutableKind, (int)imageFileMachine); + } + } + + #endregion + + #region Internal Members + internal virtual Type FindTypeBuilderWithName(String strTypeName, bool ignoreCase) + { + if (ignoreCase) + { + foreach (string name in m_TypeBuilderDict.Keys) + { + if (String.Compare(name, strTypeName, (StringComparison.OrdinalIgnoreCase)) == 0) + return m_TypeBuilderDict[name]; + } + } + else + { + Type foundType; + if (m_TypeBuilderDict.TryGetValue(strTypeName, out foundType)) + return foundType; + } + + return null; + } + +#if !FEATURE_CORECLR + internal void SetEntryPoint(MethodToken entryPoint) + { + // Sets the entry point of the module to be a given method. If no entry point + // is specified, calling EmitPEFile will generate a dll. + // AssemblyBuilder.SetEntryPoint has already demanded required permission + m_EntryPoint = entryPoint; + } +#endif //!FEATURE_CORECLR + + +#if !FEATURE_CORECLR + // This is a helper called by AssemblyBuilder save to presave information for the persistable modules. + // no need to lock here because we have already taken the lock in AssemblyBuilder.Save + [System.Security.SecurityCritical] // auto-generated + internal void PreSave(String fileName, + PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) + { + if (m_moduleData.m_isSaved == true) + { + // can only save once + throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, + Environment.GetResourceString("InvalidOperation_ModuleHasBeenSaved"), + m_moduleData.m_strModuleName)); + } + + if (m_moduleData.m_fGlobalBeenCreated == false && m_moduleData.m_fHasGlobal == true) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalFunctionNotBaked")); + + TypeBuilder typeBuilder; + foreach (Type item in m_TypeBuilderDict.Values) + { + if (item is TypeBuilder) + { + typeBuilder = (TypeBuilder)item; + } + else + { + EnumBuilder enumBuilder = (EnumBuilder)item; + typeBuilder = enumBuilder.m_typeBuilder; + } + + if (!typeBuilder.IsCreated()) + { + // cannot save to PE file without creating all of the types first + throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture, + Environment.GetResourceString("NotSupported_NotAllTypesAreBaked"), + typeBuilder.FullName)); + } + } + + PreSavePEFile(GetNativeHandle(), (int)portableExecutableKind, (int)imageFileMachine); + } + + // no need to lock here because we have already taken the lock in AssemblyBuilder.Save + [System.Security.SecurityCritical] // auto-generated + internal void Save(String fileName, bool isAssemblyFile, PortableExecutableKinds portableExecutableKind, + ImageFileMachine imageFileMachine) + { + // This is a helper called by AssemblyBuilder save to save information for the persistable modules. + if (m_moduleData.m_embeddedRes != null) + { + // There are embedded resources for this module + ResWriterData resWriter; + + // Add each resource content into the to be saved PE file + for (resWriter = m_moduleData.m_embeddedRes; resWriter != null; resWriter = resWriter.m_nextResWriter) + { + if (resWriter.m_resWriter != null) + resWriter.m_resWriter.Generate(); + + byte[] resBytes = new byte[resWriter.m_memoryStream.Length]; + resWriter.m_memoryStream.Flush(); + resWriter.m_memoryStream.Position = 0; + resWriter.m_memoryStream.Read(resBytes, 0, resBytes.Length); + + AddResource(GetNativeHandle(), + resWriter.m_strName, + resBytes, + resBytes.Length, + m_moduleData.FileToken, + (int)resWriter.m_attribute, + (int)portableExecutableKind, + (int)imageFileMachine); + } + } + + DefineNativeResource(portableExecutableKind, imageFileMachine); + + PEFileKinds pekind = isAssemblyFile ? ContainingAssemblyBuilder.m_assemblyData.m_peFileKind : PEFileKinds.Dll; + + SavePEFile(GetNativeHandle(), fileName, m_EntryPoint.Token, (int)pekind, isAssemblyFile); + + m_moduleData.m_isSaved = true; + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated + private int GetTypeRefNested(Type type, Module refedModule, String strRefedModuleFileName) + { + // This function will generate correct TypeRef token for top level type and nested type. + + Type enclosingType = type.DeclaringType; + int tkResolution = 0; + String typeName = type.FullName; + + if (enclosingType != null) + { + tkResolution = GetTypeRefNested(enclosingType, refedModule, strRefedModuleFileName); + typeName = UnmangleTypeName(typeName); + } + + Contract.Assert(!type.IsByRef, "Must not be ByRef."); + Contract.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments."); + +#if FEATURE_APPX + if (ContainingAssemblyBuilder.ProfileAPICheck) + { + RuntimeType rtType = type as RuntimeType; + if (rtType != null && (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName)); + } + } +#endif + + return GetTypeRef(GetNativeHandle(), typeName, GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), strRefedModuleFileName, tkResolution); + } + + [System.Security.SecurityCritical] // auto-generated + internal MethodToken InternalGetConstructorToken(ConstructorInfo con, bool usingRef) + { + // Helper to get constructor token. If usingRef is true, we will never use the def token + + if (con == null) + throw new ArgumentNullException("con"); + Contract.EndContractBlock(); + + int tr; + int mr = 0; + + ConstructorBuilder conBuilder = null; + ConstructorOnTypeBuilderInstantiation conOnTypeBuilderInst = null; + RuntimeConstructorInfo rtCon = null; + + if ( (conBuilder = con as ConstructorBuilder) != null ) + { + if (usingRef == false && conBuilder.Module.Equals(this)) + return conBuilder.GetToken(); + + // constructor is defined in a different module + tr = GetTypeTokenInternal(con.ReflectedType).Token; + mr = GetMemberRef(con.ReflectedType.Module, tr, conBuilder.GetToken().Token); + } + else if ( (conOnTypeBuilderInst = con as ConstructorOnTypeBuilderInstantiation) != null ) + { + if (usingRef == true) throw new InvalidOperationException(); + + tr = GetTypeTokenInternal(con.DeclaringType).Token; + mr = GetMemberRef(con.DeclaringType.Module, tr, conOnTypeBuilderInst.MetadataTokenInternal); + } + else if ( (rtCon = con as RuntimeConstructorInfo) != null && con.ReflectedType.IsArray == false) + { + // constructor is not a dynamic field + // We need to get the TypeRef tokens + + tr = GetTypeTokenInternal(con.ReflectedType).Token; + mr = GetMemberRefOfMethodInfo(tr, rtCon); + } + else + { + // some user derived ConstructorInfo + // go through the slower code path, i.e. retrieve parameters and form signature helper. + ParameterInfo[] parameters = con.GetParameters(); + if (parameters == null) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo")); + + int count = parameters.Length; + Type[] parameterTypes = new Type[count]; + Type[][] requiredCustomModifiers = new Type[count][]; + Type[][] optionalCustomModifiers = new Type[count][]; + + for (int i = 0; i < count; i++) + { + if (parameters[i] == null) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo")); + + parameterTypes[i] = parameters[i].ParameterType; + requiredCustomModifiers[i] = parameters[i].GetRequiredCustomModifiers(); + optionalCustomModifiers[i] = parameters[i].GetOptionalCustomModifiers(); + } + + tr = GetTypeTokenInternal(con.ReflectedType).Token; + + SignatureHelper sigHelp = SignatureHelper.GetMethodSigHelper(this, con.CallingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers); + int length; + byte[] sigBytes = sigHelp.InternalGetSignature(out length); + + mr = GetMemberRefFromSignature(tr, con.Name, sigBytes, length); + } + + return new MethodToken( mr ); + } + + [System.Security.SecurityCritical] // auto-generated + internal void Init(String strModuleName, String strFileName, int tkFile) + { + m_moduleData = new ModuleBuilderData(this, strModuleName, strFileName, tkFile); + m_TypeBuilderDict = new Dictionary<string, Type>(); + } + + // This is a method for changing module and file name of the manifest module (created by default for + // each assembly). + [System.Security.SecurityCritical] // auto-generated + internal void ModifyModuleName(string name) + { + // Reset the names in the managed ModuleBuilderData + m_moduleData.ModifyModuleName(name); + + // Reset the name in the underlying metadata + ModuleBuilder.SetModuleName(GetNativeHandle(), name); + } + + internal void SetSymWriter(ISymbolWriter writer) + { + m_iSymWriter = writer; + } + + internal object SyncRoot + { + get + { + return ContainingAssemblyBuilder.SyncRoot; + } + } + + #endregion + + #region Module Overrides + + // m_internalModuleBuilder is null iff this is a "internal" ModuleBuilder + internal InternalModuleBuilder InternalModule + { + get + { + return m_internalModuleBuilder; + } + } + + internal override ModuleHandle GetModuleHandle() + { + return new ModuleHandle(GetNativeHandle()); + } + + internal RuntimeModule GetNativeHandle() + { + return InternalModule.GetNativeHandle(); + } + + private static RuntimeModule GetRuntimeModuleFromModule(Module m) + { + ModuleBuilder mb = m as ModuleBuilder; + if (mb != null) + { + return mb.InternalModule; + } + + return m as RuntimeModule; + } + + [System.Security.SecurityCritical] // auto-generated + private int GetMemberRefToken(MethodBase method, IEnumerable<Type> optionalParameterTypes) + { + Type[] parameterTypes; + Type returnType; + int tkParent; + int cGenericParameters = 0; + + if (method.IsGenericMethod) + { + if (!method.IsGenericMethodDefinition) + throw new InvalidOperationException(); + + cGenericParameters = method.GetGenericArguments().Length; + } + + if (optionalParameterTypes != null) + { + if ((method.CallingConvention & CallingConventions.VarArgs) == 0) + { + // Client should not supply optional parameter in default calling convention + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention")); + } + } + + MethodInfo masmi = method as MethodInfo; + + if (method.DeclaringType.IsGenericType) + { + MethodBase methDef = null; // methodInfo = G<Foo>.M<Bar> ==> methDef = G<T>.M<S> + + MethodOnTypeBuilderInstantiation motbi; + ConstructorOnTypeBuilderInstantiation cotbi; + + if ((motbi = method as MethodOnTypeBuilderInstantiation) != null) + { + methDef = motbi.m_method; + } + else if ((cotbi = method as ConstructorOnTypeBuilderInstantiation) != null) + { + methDef = cotbi.m_ctor; + } + else if (method is MethodBuilder || method is ConstructorBuilder) + { + // methodInfo must be GenericMethodDefinition; trying to emit G<?>.M<S> + methDef = method; + } + else + { + Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); + + if (method.IsGenericMethod) + { + Contract.Assert(masmi != null); + + methDef = masmi.GetGenericMethodDefinition(); + methDef = methDef.Module.ResolveMethod( + method.MetadataToken, + methDef.DeclaringType != null ? methDef.DeclaringType.GetGenericArguments() : null, + methDef.GetGenericArguments()); + } + else + { + methDef = method.Module.ResolveMethod( + method.MetadataToken, + method.DeclaringType != null ? method.DeclaringType.GetGenericArguments() : null, + null); + } + } + + parameterTypes = methDef.GetParameterTypes(); + returnType = MethodBuilder.GetMethodBaseReturnType(methDef); + } + else + { + parameterTypes = method.GetParameterTypes(); + returnType = MethodBuilder.GetMethodBaseReturnType(method); + } + + int sigLength; + byte[] sigBytes = GetMemberRefSignature(method.CallingConvention, returnType, parameterTypes, + optionalParameterTypes, cGenericParameters).InternalGetSignature(out sigLength); + + if (method.DeclaringType.IsGenericType) + { + int length; + byte[] sig = SignatureHelper.GetTypeSigToken(this, method.DeclaringType).InternalGetSignature(out length); + tkParent = GetTokenFromTypeSpec(sig, length); + } + else if (!method.Module.Equals(this)) + { + // Use typeRef as parent because the method's declaringType lives in a different assembly + tkParent = GetTypeToken(method.DeclaringType).Token; + } + else + { + // Use methodDef as parent because the method lives in this assembly and its declaringType has no generic arguments + if (masmi != null) + tkParent = GetMethodToken(masmi).Token; + else + tkParent = GetConstructorToken(method as ConstructorInfo).Token; + } + + return GetMemberRefFromSignature(tkParent, method.Name, sigBytes, sigLength); + } + + [System.Security.SecurityCritical] // auto-generated + internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, + Type[] parameterTypes, IEnumerable<Type> optionalParameterTypes, int cGenericParameters) + { + int cParams = (parameterTypes == null) ? 0 : parameterTypes.Length; + SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters); + + for (int i = 0; i < cParams; i++) + { + sig.AddArgument(parameterTypes[i]); + } + + if (optionalParameterTypes != null) { + int i = 0; + foreach (Type type in optionalParameterTypes) + { + // add the sentinel + if (i == 0) + { + sig.AddSentinel(); + } + + sig.AddArgument(type); + i++; + } + } + + return sig; + } + + #endregion + + #region object overrides + public override bool Equals(object obj) + { + return InternalModule.Equals(obj); + } + // Need a dummy GetHashCode to pair with Equals + public override int GetHashCode() { return InternalModule.GetHashCode(); } + #endregion + + #region ICustomAttributeProvider Members + public override Object[] GetCustomAttributes(bool inherit) + { + return InternalModule.GetCustomAttributes(inherit); + } + + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return InternalModule.GetCustomAttributes(attributeType, inherit); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + return InternalModule.IsDefined(attributeType, inherit); + } + + public override IList<CustomAttributeData> GetCustomAttributesData() + { + return InternalModule.GetCustomAttributesData(); + } + #endregion + + #region Module Overrides + + public override Type[] GetTypes() + { + lock(SyncRoot) + { + return GetTypesNoLock(); + } + } + + internal Type[] GetTypesNoLock() + { + int size = m_TypeBuilderDict.Count; + Type[] typeList = new Type[m_TypeBuilderDict.Count]; + int i = 0; + + foreach (Type builder in m_TypeBuilderDict.Values) + { + EnumBuilder enumBldr = builder as EnumBuilder; + TypeBuilder tmpTypeBldr; + + if (enumBldr != null) + tmpTypeBldr = enumBldr.m_typeBuilder; + else + tmpTypeBldr = (TypeBuilder)builder; + + // We should not return TypeBuilders. + // Otherwise anyone can emit code in it. + if (tmpTypeBldr.IsCreated()) + typeList[i++] = tmpTypeBldr.UnderlyingSystemType; + else + typeList[i++] = builder; + } + + return typeList; + } + + [System.Runtime.InteropServices.ComVisible(true)] + public override Type GetType(String className) + { + return GetType(className, false, false); + } + + [System.Runtime.InteropServices.ComVisible(true)] + public override Type GetType(String className, bool ignoreCase) + { + return GetType(className, false, ignoreCase); + } + + [System.Runtime.InteropServices.ComVisible(true)] + public override Type GetType(String className, bool throwOnError, bool ignoreCase) + { + lock(SyncRoot) + { + return GetTypeNoLock(className, throwOnError, ignoreCase); + } + } + + private Type GetTypeNoLock(String className, bool throwOnError, bool ignoreCase) + { + // public API to to a type. The reason that we need this function override from module + // is because clients might need to get foo[] when foo is being built. For example, if + // foo class contains a data member of type foo[]. + // This API first delegate to the Module.GetType implementation. If succeeded, great! + // If not, we have to look up the current module to find the TypeBuilder to represent the base + // type and form the Type object for "foo[,]". + + // Module.GetType() will verify className. + Type baseType = InternalModule.GetType(className, throwOnError, ignoreCase); + if (baseType != null) + return baseType; + + // Now try to see if we contain a TypeBuilder for this type or not. + // Might have a compound type name, indicated via an unescaped + // '[', '*' or '&'. Split the name at this point. + String baseName = null; + String parameters = null; + int startIndex = 0; + + while (startIndex <= className.Length) + { + // Are there any possible special characters left? + int i = className.IndexOfAny(new char[]{'[', '*', '&'}, startIndex); + if (i == -1) + { + // No, type name is simple. + baseName = className; + parameters = null; + break; + } + + // Found a potential special character, but it might be escaped. + int slashes = 0; + for (int j = i - 1; j >= 0 && className[j] == '\\'; j--) + slashes++; + + // Odd number of slashes indicates escaping. + if (slashes % 2 == 1) + { + startIndex = i + 1; + continue; + } + + // Found the end of the base type name. + baseName = className.Substring(0, i); + parameters = className.Substring(i); + break; + } + + // If we didn't find a basename yet, the entire class name is + // the base name and we don't have a composite type. + if (baseName == null) + { + baseName = className; + parameters = null; + } + + baseName = baseName.Replace(@"\\",@"\").Replace(@"\[",@"[").Replace(@"\*",@"*").Replace(@"\&",@"&"); + + if (parameters != null) + { + // try to see if reflection can find the base type. It can be such that reflection + // does not support the complex format string yet! + + baseType = InternalModule.GetType(baseName, false, ignoreCase); + } + + if (baseType == null) + { + // try to find it among the unbaked types. + // starting with the current module first of all. + baseType = FindTypeBuilderWithName(baseName, ignoreCase); + if (baseType == null && Assembly is AssemblyBuilder) + { + // now goto Assembly level to find the type. + int size; + List<ModuleBuilder> modList; + + modList = ContainingAssemblyBuilder.m_assemblyData.m_moduleBuilderList; + size = modList.Count; + for (int i = 0; i < size && baseType == null; i++) + { + ModuleBuilder mBuilder = modList[i]; + baseType = mBuilder.FindTypeBuilderWithName(baseName, ignoreCase); + } + } + if (baseType == null) + return null; + } + + if (parameters == null) + return baseType; + + return GetType(parameters, baseType); + } + + public override String FullyQualifiedName + { +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + get + { + String fullyQualifiedName = m_moduleData.m_strFileName; + if (fullyQualifiedName == null) + return null; + if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null) + { + fullyQualifiedName = Path.Combine(ContainingAssemblyBuilder.m_assemblyData.m_strDir, fullyQualifiedName); + fullyQualifiedName = Path.UnsafeGetFullPath(fullyQualifiedName); + } + + if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null && fullyQualifiedName != null) + { + new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullyQualifiedName ).Demand(); + } + + return fullyQualifiedName; + } + } + + public override byte[] ResolveSignature(int metadataToken) + { + return InternalModule.ResolveSignature(metadataToken); + } + + public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + return InternalModule.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments); + } + + public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + return InternalModule.ResolveField(metadataToken, genericTypeArguments, genericMethodArguments); + } + + public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + return InternalModule.ResolveType(metadataToken, genericTypeArguments, genericMethodArguments); + } + + public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) + { + return InternalModule.ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments); + } + + public override string ResolveString(int metadataToken) + { + return InternalModule.ResolveString(metadataToken); + } + + public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) + { + InternalModule.GetPEKind(out peKind, out machine); + } + + public override int MDStreamVersion + { + get + { + return InternalModule.MDStreamVersion; + } + } + + public override Guid ModuleVersionId + { + get + { + return InternalModule.ModuleVersionId; + } + } + + public override int MetadataToken + { + get + { + return InternalModule.MetadataToken; + } + } + + public override bool IsResource() + { + return InternalModule.IsResource(); + } + + public override FieldInfo[] GetFields(BindingFlags bindingFlags) + { + return InternalModule.GetFields(bindingFlags); + } + + public override FieldInfo GetField(String name, BindingFlags bindingAttr) + { + return InternalModule.GetField(name, bindingAttr); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingFlags) + { + return InternalModule.GetMethods(bindingFlags); + } + + protected override MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder, + CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + { + // Cannot call InternalModule.GetMethods because it doesn't allow types to be null + return InternalModule.GetMethodInternal(name, bindingAttr, binder, callConvention, types, modifiers); + } + + public override String ScopeName + { + get + { + return InternalModule.ScopeName; + } + } + + public override String Name + { + get + { + return InternalModule.Name; + } + } + + public override Assembly Assembly + { + [Pure] + get + { + return m_assemblyBuilder; + } + } + +#if FEATURE_X509 && FEATURE_CAS_POLICY + public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() + { + return InternalModule.GetSignerCertificate(); + } +#endif // FEATURE_X509 && FEATURE_CAS_POLICY + #endregion + + #region Public Members + + #region Define Type + [System.Security.SecuritySafeCritical] // auto-generated + public TypeBuilder DefineType(String name) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + return DefineTypeNoLock(name, TypeAttributes.NotPublic, null, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize); + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public TypeBuilder DefineType(String name, TypeAttributes attr) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + return DefineTypeNoLock(name, attr, null, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize); + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + // Why do we only call CheckContext here? Why don't we call it in the other overloads? + CheckContext(parent); + + return DefineTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, int typesize) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + return DefineTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, typesize); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock (SyncRoot) + { + return DefineTypeNoLock(name, attr, parent, null, packingSize, typesize); + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + [System.Runtime.InteropServices.ComVisible(true)] + public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, Type[] interfaces) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + return DefineTypeNoLock(name, attr, parent, interfaces, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize); + } + } + + [System.Security.SecurityCritical] // auto-generated + private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + return new TypeBuilder(name, attr, parent, interfaces, this, packingSize, typesize, null); ; + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packsize) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + lock(SyncRoot) + { + return DefineTypeNoLock(name, attr, parent, packsize); + } + } + + [System.Security.SecurityCritical] // auto-generated + private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, PackingSize packsize) + { + Contract.Ensures(Contract.Result<TypeBuilder>() != null); + + return new TypeBuilder(name, attr, parent, null, this, packsize, TypeBuilder.UnspecifiedTypeSize, null); + } + + #endregion + + #region Define Enum + + // This API can only be used to construct a top-level (not nested) enum type. + // Nested enum types can be defined manually using ModuleBuilder.DefineType. + [System.Security.SecuritySafeCritical] // auto-generated + public EnumBuilder DefineEnum(String name, TypeAttributes visibility, Type underlyingType) + { + Contract.Ensures(Contract.Result<EnumBuilder>() != null); + + CheckContext(underlyingType); + lock(SyncRoot) + { + EnumBuilder enumBuilder = DefineEnumNoLock(name, visibility, underlyingType); + + // This enum is not generic, nested, and cannot have any element type. + Contract.Assert(name == enumBuilder.FullName); + + // Replace the TypeBuilder object in m_TypeBuilderDict with this EnumBuilder object. + Contract.Assert(enumBuilder.m_typeBuilder == m_TypeBuilderDict[name]); + m_TypeBuilderDict[name] = enumBuilder; + + return enumBuilder; + } + } + + [System.Security.SecurityCritical] // auto-generated + private EnumBuilder DefineEnumNoLock(String name, TypeAttributes visibility, Type underlyingType) + { + Contract.Ensures(Contract.Result<EnumBuilder>() != null); + + return new EnumBuilder(name, underlyingType, visibility, this); + } + + #endregion + + #region Define Resource +#if !FEATURE_CORECLR + public IResourceWriter DefineResource(String name, String description) + { + // Define embedded managed resource to be stored in this module + Contract.Ensures(Contract.Result<IResourceWriter>() != null); + + return DefineResource(name, description, ResourceAttributes.Public); + } + + public IResourceWriter DefineResource(String name, String description, ResourceAttributes attribute) + { + // Define embedded managed resource to be stored in this module + Contract.Ensures(Contract.Result<IResourceWriter>() != null); + + lock(SyncRoot) + { + return DefineResourceNoLock(name, description, attribute); + } + } + + private IResourceWriter DefineResourceNoLock(String name, String description, ResourceAttributes attribute) + { + // Define embedded managed resource to be stored in this module + + if (IsTransient()) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); + + if (name == null) + throw new ArgumentNullException("name"); + if (name.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + Contract.Ensures(Contract.Result<IResourceWriter>() != null); + Contract.EndContractBlock(); + + if (m_assemblyBuilder.IsPersistable()) + { + m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name); + + MemoryStream stream = new MemoryStream(); + ResourceWriter resWriter = new ResourceWriter(stream); + ResWriterData resWriterData = new ResWriterData( resWriter, stream, name, String.Empty, String.Empty, attribute); + + // chain it to the embedded resource list + resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes; + m_moduleData.m_embeddedRes = resWriterData; + return resWriter; + } + else + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); + } + } +#endif // !FEATURE_CORECLR + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public void DefineManifestResource(String name, Stream stream, ResourceAttributes attribute) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (stream == null) + throw new ArgumentNullException("stream"); + Contract.EndContractBlock(); + + // Define embedded managed resource to be stored in this module + + lock(SyncRoot) + { + DefineManifestResourceNoLock(name, stream, attribute); + } + } + + private void DefineManifestResourceNoLock(String name, Stream stream, ResourceAttributes attribute) + { + // Define embedded managed resource to be stored in this module + if (IsTransient()) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); + Contract.EndContractBlock(); + +#if !FEATURE_CORECLR + if (name == null) + throw new ArgumentNullException("name"); + if (name.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + + if (m_assemblyBuilder.IsPersistable()) + { + m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name); + + ResWriterData resWriterData = new ResWriterData( null, stream, name, String.Empty, String.Empty, attribute); + + // chain it to the embedded resource list + resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes; + m_moduleData.m_embeddedRes = resWriterData; + } + else + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); + } +#endif // !FEATURE_CORECLR + } + + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public void DefineUnmanagedResource(Byte[] resource) + { + lock(SyncRoot) + { + DefineUnmanagedResourceInternalNoLock(resource); + } + } + + internal void DefineUnmanagedResourceInternalNoLock(Byte[] resource) + { + if (resource == null) + throw new ArgumentNullException("resource"); + Contract.EndContractBlock(); + + if (m_moduleData.m_strResourceFileName != null || m_moduleData.m_resourceBytes != null) + throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); + + m_moduleData.m_resourceBytes = new byte[resource.Length]; + Buffer.BlockCopy(resource, 0, m_moduleData.m_resourceBytes, 0, resource.Length); + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + public void DefineUnmanagedResource(String resourceFileName) + { + lock(SyncRoot) + { + DefineUnmanagedResourceFileInternalNoLock(resourceFileName); + } + } + + [System.Security.SecurityCritical] // auto-generated + internal void DefineUnmanagedResourceFileInternalNoLock(String resourceFileName) + { + if (resourceFileName == null) + throw new ArgumentNullException("resourceFileName"); + Contract.EndContractBlock(); + + if (m_moduleData.m_resourceBytes != null || m_moduleData.m_strResourceFileName != null) + throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); + + // Check caller has the right to read the file. + string strFullFileName; + strFullFileName = Path.UnsafeGetFullPath(resourceFileName); + new FileIOPermission(FileIOPermissionAccess.Read, strFullFileName).Demand(); + + new EnvironmentPermission(PermissionState.Unrestricted).Assert(); + try + { + if (File.UnsafeExists(resourceFileName) == false) + throw new FileNotFoundException(Environment.GetResourceString( + "IO.FileNotFound_FileName", + resourceFileName), resourceFileName); + } + finally + { + CodeAccessPermission.RevertAssert(); + } + + m_moduleData.m_strResourceFileName = strFullFileName; + } + #endregion + + #region Define Global Method + public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) + { + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + + return DefineGlobalMethod(name, attributes, CallingConventions.Standard, returnType, parameterTypes); + } + + public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, CallingConventions callingConvention, + Type returnType, Type[] parameterTypes) + { + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + + return DefineGlobalMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null); + } + + public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, CallingConventions callingConvention, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + lock(SyncRoot) + { + return DefineGlobalMethodNoLock(name, attributes, callingConvention, returnType, + requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, + parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + } + + private MethodBuilder DefineGlobalMethodNoLock(String name, MethodAttributes attributes, CallingConventions callingConvention, + Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, + Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + if (m_moduleData.m_fGlobalBeenCreated == true) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated")); + + if (name == null) + throw new ArgumentNullException("name"); + + if (name.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + + if ((attributes & MethodAttributes.Static) == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_GlobalFunctionHasToBeStatic")); + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + Contract.EndContractBlock(); + + CheckContext(returnType); + CheckContext(requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes); + CheckContext(requiredParameterTypeCustomModifiers); + CheckContext(optionalParameterTypeCustomModifiers); + + m_moduleData.m_fHasGlobal = true; + + return m_moduleData.m_globalTypeBuilder.DefineMethod(name, attributes, callingConvention, + returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, + parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public MethodBuilder DefinePInvokeMethod(String name, String dllName, MethodAttributes attributes, + CallingConventions callingConvention, Type returnType, Type[] parameterTypes, + CallingConvention nativeCallConv, CharSet nativeCharSet) + { + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + + return DefinePInvokeMethod(name, dllName, name, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet); + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes, + CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, + CharSet nativeCharSet) + { + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + + lock(SyncRoot) + { + return DefinePInvokeMethodNoLock(name, dllName, entryName, attributes, callingConvention, + returnType, parameterTypes, nativeCallConv, nativeCharSet); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + private MethodBuilder DefinePInvokeMethodNoLock(String name, String dllName, String entryName, MethodAttributes attributes, + CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, + CharSet nativeCharSet) + { + //Global methods must be static. + if ((attributes & MethodAttributes.Static) == 0) + { + throw new ArgumentException(Environment.GetResourceString("Argument_GlobalFunctionHasToBeStatic")); + } + Contract.Ensures(Contract.Result<MethodBuilder>() != null); + Contract.EndContractBlock(); + + CheckContext(returnType); + CheckContext(parameterTypes); + + m_moduleData.m_fHasGlobal = true; + return m_moduleData.m_globalTypeBuilder.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet); + } + + public void CreateGlobalFunctions() + { + lock(SyncRoot) + { + CreateGlobalFunctionsNoLock(); + } + } + + private void CreateGlobalFunctionsNoLock() + { + if (m_moduleData.m_fGlobalBeenCreated) + { + // cannot create globals twice + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule")); + } + m_moduleData.m_globalTypeBuilder.CreateType(); + m_moduleData.m_fGlobalBeenCreated = true; + } + + #endregion + + #region Define Data + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public FieldBuilder DefineInitializedData(String name, byte[] data, FieldAttributes attributes) + { + // This method will define an initialized Data in .sdata. + // We will create a fake TypeDef to represent the data with size. This TypeDef + // will be the signature for the Field. + Contract.Ensures(Contract.Result<FieldBuilder>() != null); + + lock(SyncRoot) + { + return DefineInitializedDataNoLock(name, data, attributes); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + private FieldBuilder DefineInitializedDataNoLock(String name, byte[] data, FieldAttributes attributes) + { + // This method will define an initialized Data in .sdata. + // We will create a fake TypeDef to represent the data with size. This TypeDef + // will be the signature for the Field. + if (m_moduleData.m_fGlobalBeenCreated == true) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated")); + } + Contract.Ensures(Contract.Result<FieldBuilder>() != null); + Contract.EndContractBlock(); + + m_moduleData.m_fHasGlobal = true; + return m_moduleData.m_globalTypeBuilder.DefineInitializedData(name, data, attributes); + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + public FieldBuilder DefineUninitializedData(String name, int size, FieldAttributes attributes) + { + Contract.Ensures(Contract.Result<FieldBuilder>() != null); + + lock(SyncRoot) + { + return DefineUninitializedDataNoLock(name, size, attributes); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + private FieldBuilder DefineUninitializedDataNoLock(String name, int size, FieldAttributes attributes) + { + // This method will define an uninitialized Data in .sdata. + // We will create a fake TypeDef to represent the data with size. This TypeDef + // will be the signature for the Field. + + if (m_moduleData.m_fGlobalBeenCreated == true) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated")); + } + Contract.Ensures(Contract.Result<FieldBuilder>() != null); + Contract.EndContractBlock(); + + m_moduleData.m_fHasGlobal = true; + return m_moduleData.m_globalTypeBuilder.DefineUninitializedData(name, size, attributes); + } + + #endregion + + #region GetToken + // For a generic type definition, we should return the token for the generic type definition itself in two cases: + // 1. GetTypeToken + // 2. ldtoken (see ILGenerator) + // For all other occasions we should return the generic type instantiated on its formal parameters. + [System.Security.SecurityCritical] // auto-generated + internal TypeToken GetTypeTokenInternal(Type type) + { + return GetTypeTokenInternal(type, false); + } + + [System.Security.SecurityCritical] // auto-generated + private TypeToken GetTypeTokenInternal(Type type, bool getGenericDefinition) + { + lock(SyncRoot) + { + return GetTypeTokenWorkerNoLock(type, getGenericDefinition); + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public TypeToken GetTypeToken(Type type) + { + return GetTypeTokenInternal(type, true); + } + + [System.Security.SecurityCritical] // auto-generated + private TypeToken GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition) + { + if (type == null) + throw new ArgumentNullException("type"); + Contract.EndContractBlock(); + + CheckContext(type); + + // Return a token for the class relative to the Module. Tokens + // are used to indentify objects when the objects are used in IL + // instructions. Tokens are always relative to the Module. For example, + // the token value for System.String is likely to be different from + // Module to Module. Calling GetTypeToken will cause a reference to be + // added to the Module. This reference becomes a perminate part of the Module, + // multiple calles to this method with the same class have no additional side affects. + // This function is optimized to use the TypeDef token if Type is within the same module. + // We should also be aware of multiple dynamic modules and multiple implementation of Type!!! + + if (type.IsByRef) + throw new ArgumentException(Environment.GetResourceString("Argument_CannotGetTypeTokenForByRef")); + + if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) || + type.IsGenericParameter || + type.IsArray || + type.IsPointer) + { + int length; + byte[] sig = SignatureHelper.GetTypeSigToken(this, type).InternalGetSignature(out length); + return new TypeToken(GetTokenFromTypeSpec(sig, length)); + } + + Module refedModule = type.Module; + + if (refedModule.Equals(this)) + { + // no need to do anything additional other than defining the TypeRef Token + TypeBuilder typeBuilder = null; + GenericTypeParameterBuilder paramBuilder = null; + + EnumBuilder enumBuilder = type as EnumBuilder; + if (enumBuilder != null) + typeBuilder = enumBuilder.m_typeBuilder; + else + typeBuilder = type as TypeBuilder; + + if (typeBuilder != null) + { + // optimization: if the type is defined in this module, + // just return the token + // + return typeBuilder.TypeToken; + } + else if ((paramBuilder = type as GenericTypeParameterBuilder) != null) + { + return new TypeToken(paramBuilder.MetadataTokenInternal); + } + + return new TypeToken(GetTypeRefNested(type, this, String.Empty)); + } + + // After this point, the referenced module is not the same as the referencing + // module. + // + ModuleBuilder refedModuleBuilder = refedModule as ModuleBuilder; + +#if !FEATURE_CORECLR + Contract.Assert(refedModuleBuilder != null || refedModule is RuntimeModule); + bool isRefedModuleTransient = refedModuleBuilder != null ? + refedModuleBuilder.IsTransient() : + ((RuntimeModule)refedModule).IsTransientInternal(); + + // We cannot have a non-transient module referencing to a transient module. + if (IsTransient() == false && isRefedModuleTransient) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadTransientModuleReference")); + } +#endif // !FEATURE_CORECLR + + String strRefedModuleFileName = String.Empty; + if (refedModule.Assembly.Equals(this.Assembly)) + { + // if the referenced module is in the same assembly, the resolution + // scope of the type token will be a module ref, we will need + // the file name of the referenced module for that. + // if the refed module is in a different assembly, the resolution + // scope of the type token will be an assembly ref. We don't need + // the file name of the referenced module. + if (refedModuleBuilder == null) + { + refedModuleBuilder = this.ContainingAssemblyBuilder.GetModuleBuilder((InternalModuleBuilder)refedModule); + } + strRefedModuleFileName = refedModuleBuilder.m_moduleData.m_strFileName; + } + + return new TypeToken(GetTypeRefNested(type, refedModule, strRefedModuleFileName)); + } + + public TypeToken GetTypeToken(String name) + { + // Return a token for the class relative to the Module. + // Module.GetType() verifies name + + // Unfortunately, we will need to load the Type and then call GetTypeToken in + // order to correctly track the assembly reference information. + + return GetTypeToken(InternalModule.GetType(name, false, true)); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public MethodToken GetMethodToken(MethodInfo method) + { + lock(SyncRoot) + { + return GetMethodTokenNoLock(method, true); + } + } + + [System.Security.SecurityCritical] // auto-generated + internal MethodToken GetMethodTokenInternal(MethodInfo method) + { + lock(SyncRoot) + { + return GetMethodTokenNoLock(method, false); + } + } + + // For a method on a generic type, we should return the methoddef token on the generic type definition in two cases + // 1. GetMethodToken + // 2. ldtoken (see ILGenerator) + // For all other occasions we should return the method on the generic type instantiated on the formal parameters. + [System.Security.SecurityCritical] // auto-generated + private MethodToken GetMethodTokenNoLock(MethodInfo method, bool getGenericTypeDefinition) + { + // Return a MemberRef token if MethodInfo is not defined in this module. Or + // return the MethodDef token. + if (method == null) + throw new ArgumentNullException("method"); + Contract.EndContractBlock(); + + int tr; + int mr = 0; + + SymbolMethod symMethod = null; + MethodBuilder methBuilder = null; + + if ( (methBuilder = method as MethodBuilder) != null ) + { + int methodToken = methBuilder.MetadataTokenInternal; + if (method.Module.Equals(this)) + return new MethodToken(methodToken); + + if (method.DeclaringType == null) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule")); + + // method is defined in a different module + tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token; + mr = GetMemberRef(method.DeclaringType.Module, tr, methodToken); + } + else if (method is MethodOnTypeBuilderInstantiation) + { + return new MethodToken(GetMemberRefToken(method, null)); + } + else if ((symMethod = method as SymbolMethod) != null) + { + if (symMethod.GetModule() == this) + return symMethod.GetToken(); + + // form the method token + return symMethod.GetToken(this); + } + else + { + Type declaringType = method.DeclaringType; + + // We need to get the TypeRef tokens + if (declaringType == null) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule")); + + RuntimeMethodInfo rtMeth = null; + + if (declaringType.IsArray == true) + { + // use reflection to build signature to work around the E_T_VAR problem in EEClass + ParameterInfo[] paramInfo = method.GetParameters(); + + Type[] tt = new Type[paramInfo.Length]; + + for (int i = 0; i < paramInfo.Length; i++) + tt[i] = paramInfo[i].ParameterType; + + return GetArrayMethodToken(declaringType, method.Name, method.CallingConvention, method.ReturnType, tt); + } + else if ( (rtMeth = method as RuntimeMethodInfo) != null ) + { + tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token; + mr = GetMemberRefOfMethodInfo(tr, rtMeth); + } + else + { + // some user derived ConstructorInfo + // go through the slower code path, i.e. retrieve parameters and form signature helper. + ParameterInfo[] parameters = method.GetParameters(); + + Type[] parameterTypes = new Type[parameters.Length]; + Type[][] requiredCustomModifiers = new Type[parameterTypes.Length][]; + Type[][] optionalCustomModifiers = new Type[parameterTypes.Length][]; + + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i] = parameters[i].ParameterType; + requiredCustomModifiers[i] = parameters[i].GetRequiredCustomModifiers(); + optionalCustomModifiers[i] = parameters[i].GetOptionalCustomModifiers(); + } + + tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token; + + SignatureHelper sigHelp; + + try + { + sigHelp = SignatureHelper.GetMethodSigHelper( + this, method.CallingConvention, method.ReturnType, + method.ReturnParameter.GetRequiredCustomModifiers(), method.ReturnParameter.GetOptionalCustomModifiers(), + parameterTypes, requiredCustomModifiers, optionalCustomModifiers); + } + catch(NotImplementedException) + { + // Legacy code deriving from MethodInfo may not have implemented ReturnParameter. + sigHelp = SignatureHelper.GetMethodSigHelper(this, method.ReturnType, parameterTypes); + } + + int length; + byte[] sigBytes = sigHelp.InternalGetSignature(out length); + mr = GetMemberRefFromSignature(tr, method.Name, sigBytes, length); + } + } + + return new MethodToken(mr); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes) + { + if (constructor == null) + { + throw new ArgumentNullException("constructor"); + } + + lock (SyncRoot) + { + // useMethodDef is not applicable - constructors aren't generic + return new MethodToken(GetMethodTokenInternal(constructor, optionalParameterTypes, false)); + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes) + { + if (method == null) + { + throw new ArgumentNullException("method"); + } + + // useMethodDef flag only affects the result if we pass in a generic method definition. + // If the caller is looking for a token for an ldtoken/ldftn/ldvirtftn instruction and passes in a generic method definition info/builder, + // we correclty return the MethodDef/Ref token of the generic definition that can be used with ldtoken/ldftn/ldvirtftn. + // + // If the caller is looking for a token for a call/callvirt/jmp instruction and passes in a generic method definition info/builder, + // we also return the generic MethodDef/Ref token, which is indeed not acceptable for call/callvirt/jmp instruction. + // But the caller can always instantiate the info/builder and pass it in. Then we build the right MethodSpec. + + lock (SyncRoot) + { + return new MethodToken(GetMethodTokenInternal(method, optionalParameterTypes, true)); + } + } + + [System.Security.SecurityCritical] // auto-generated + internal int GetMethodTokenInternal(MethodBase method, IEnumerable<Type> optionalParameterTypes, bool useMethodDef) + { + int tk = 0; + MethodInfo methodInfo = method as MethodInfo; + + if (method.IsGenericMethod) + { + // Constructors cannot be generic. + Contract.Assert(methodInfo != null); + + // Given M<Bar> unbind to M<S> + MethodInfo methodInfoUnbound = methodInfo; + bool isGenericMethodDef = methodInfo.IsGenericMethodDefinition; + + if (!isGenericMethodDef) + { + methodInfoUnbound = methodInfo.GetGenericMethodDefinition(); + } + + if (!this.Equals(methodInfoUnbound.Module) + || (methodInfoUnbound.DeclaringType != null && methodInfoUnbound.DeclaringType.IsGenericType)) + { + tk = GetMemberRefToken(methodInfoUnbound, null); + } + else + { + tk = GetMethodTokenInternal(methodInfoUnbound).Token; + } + + // For Ldtoken, Ldftn, and Ldvirtftn, we should emit the method def/ref token for a generic method definition. + if (isGenericMethodDef && useMethodDef) + { + return tk; + } + + // Create signature of method instantiation M<Bar> + int sigLength; + byte[] sigBytes = SignatureHelper.GetMethodSpecSigHelper( + this, methodInfo.GetGenericArguments()).InternalGetSignature(out sigLength); + + // Create MethodSepc M<Bar> with parent G?.M<S> + tk = TypeBuilder.DefineMethodSpec(this.GetNativeHandle(), tk, sigBytes, sigLength); + } + else + { + if (((method.CallingConvention & CallingConventions.VarArgs) == 0) && + (method.DeclaringType == null || !method.DeclaringType.IsGenericType)) + { + if (methodInfo != null) + { + tk = GetMethodTokenInternal(methodInfo).Token; + } + else + { + tk = GetConstructorToken(method as ConstructorInfo).Token; + } + } + else + { + tk = GetMemberRefToken(method, optionalParameterTypes); + } + } + + return tk; + } + + [System.Security.SecuritySafeCritical] // auto-generated + public MethodToken GetArrayMethodToken(Type arrayClass, String methodName, CallingConventions callingConvention, + Type returnType, Type[] parameterTypes) + { + lock(SyncRoot) + { + return GetArrayMethodTokenNoLock(arrayClass, methodName, callingConvention, returnType, parameterTypes); + } + } + + [System.Security.SecurityCritical] // auto-generated + private MethodToken GetArrayMethodTokenNoLock(Type arrayClass, String methodName, CallingConventions callingConvention, + Type returnType, Type[] parameterTypes) + { + if (arrayClass == null) + throw new ArgumentNullException("arrayClass"); + + if (methodName == null) + throw new ArgumentNullException("methodName"); + + if (methodName.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "methodName"); + + if (arrayClass.IsArray == false) + throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass")); + Contract.EndContractBlock(); + + CheckContext(returnType, arrayClass); + CheckContext(parameterTypes); + + // Return a token for the MethodInfo for a method on an Array. This is primarily + // used to get the LoadElementAddress method. + + int length; + + SignatureHelper sigHelp = SignatureHelper.GetMethodSigHelper( + this, callingConvention, returnType, null, null, parameterTypes, null, null); + + byte[] sigBytes = sigHelp.InternalGetSignature(out length); + + TypeToken typeSpec = GetTypeTokenInternal(arrayClass); + + return new MethodToken(GetArrayMethodToken(GetNativeHandle(), + typeSpec.Token, methodName, sigBytes, length)); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public MethodInfo GetArrayMethod(Type arrayClass, String methodName, CallingConventions callingConvention, + Type returnType, Type[] parameterTypes) + { + CheckContext(returnType, arrayClass); + CheckContext(parameterTypes); + + // GetArrayMethod is useful when you have an array of a type whose definition has not been completed and + // you want to access methods defined on Array. For example, you might define a type and want to define a + // method that takes an array of the type as a parameter. In order to access the elements of the array, + // you will need to call methods of the Array class. + + MethodToken token = GetArrayMethodToken(arrayClass, methodName, callingConvention, returnType, parameterTypes); + + return new SymbolMethod(this, token, arrayClass, methodName, callingConvention, returnType, parameterTypes); + } + + [System.Security.SecuritySafeCritical] // auto-generated + [System.Runtime.InteropServices.ComVisible(true)] + public MethodToken GetConstructorToken(ConstructorInfo con) + { + // Return a token for the ConstructorInfo relative to the Module. + return InternalGetConstructorToken(con, false); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public FieldToken GetFieldToken(FieldInfo field) + { + lock(SyncRoot) + { + return GetFieldTokenNoLock(field); + } + } + + [System.Security.SecurityCritical] // auto-generated + private FieldToken GetFieldTokenNoLock(FieldInfo field) + { + if (field == null) { + throw new ArgumentNullException("con"); + } + Contract.EndContractBlock(); + + int tr; + int mr = 0; + + FieldBuilder fdBuilder = null; + RuntimeFieldInfo rtField = null; + FieldOnTypeBuilderInstantiation fOnTB = null; + + if ((fdBuilder = field as FieldBuilder) != null) + { + if (field.DeclaringType != null && field.DeclaringType.IsGenericType) + { + int length; + byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length); + tr = GetTokenFromTypeSpec(sig, length); + mr = GetMemberRef(this, tr, fdBuilder.GetToken().Token); + } + else if (fdBuilder.Module.Equals(this)) + { + // field is defined in the same module + return fdBuilder.GetToken(); + } + else + { + // field is defined in a different module + if (field.DeclaringType == null) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule")); + } + tr = GetTypeTokenInternal(field.DeclaringType).Token; + mr = GetMemberRef(field.ReflectedType.Module, tr, fdBuilder.GetToken().Token); + } + } + else if ( (rtField = field as RuntimeFieldInfo) != null) + { + // FieldInfo is not an dynamic field + + // We need to get the TypeRef tokens + if (field.DeclaringType == null) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule")); + } + + if (field.DeclaringType != null && field.DeclaringType.IsGenericType) + { + int length; + byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length); + tr = GetTokenFromTypeSpec(sig, length); + mr = GetMemberRefOfFieldInfo(tr, field.DeclaringType.GetTypeHandleInternal(), rtField); + } + else + { + tr = GetTypeTokenInternal(field.DeclaringType).Token; + mr = GetMemberRefOfFieldInfo(tr, field.DeclaringType.GetTypeHandleInternal(), rtField); + } + } + else if ( (fOnTB = field as FieldOnTypeBuilderInstantiation) != null) + { + FieldInfo fb = fOnTB.FieldInfo; + int length; + byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length); + tr = GetTokenFromTypeSpec(sig, length); + mr = GetMemberRef(fb.ReflectedType.Module, tr, fOnTB.MetadataTokenInternal); + } + else + { + // user defined FieldInfo + tr = GetTypeTokenInternal(field.ReflectedType).Token; + + SignatureHelper sigHelp = SignatureHelper.GetFieldSigHelper(this); + + sigHelp.AddArgument(field.FieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers()); + + int length; + byte[] sigBytes = sigHelp.InternalGetSignature(out length); + + mr = GetMemberRefFromSignature(tr, field.Name, sigBytes, length); + } + + return new FieldToken(mr, field.GetType()); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public StringToken GetStringConstant(String str) + { + if (str == null) + { + throw new ArgumentNullException("str"); + } + Contract.EndContractBlock(); + + // Returns a token representing a String constant. If the string + // value has already been defined, the existing token will be returned. + return new StringToken(GetStringConstant(GetNativeHandle(), str, str.Length)); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public SignatureToken GetSignatureToken(SignatureHelper sigHelper) + { + // Define signature token given a signature helper. This will define a metadata + // token for the signature described by SignatureHelper. + + if (sigHelper == null) + { + throw new ArgumentNullException("sigHelper"); + } + Contract.EndContractBlock(); + + int sigLength; + byte[] sigBytes; + + // get the signature in byte form + sigBytes = sigHelper.InternalGetSignature(out sigLength); + return new SignatureToken(TypeBuilder.GetTokenFromSig(GetNativeHandle(), sigBytes, sigLength), this); + } + [System.Security.SecuritySafeCritical] // auto-generated + public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength) + { + if (sigBytes == null) + throw new ArgumentNullException("sigBytes"); + Contract.EndContractBlock(); + + byte[] localSigBytes = new byte[sigBytes.Length]; + Buffer.BlockCopy(sigBytes, 0, localSigBytes, 0, sigBytes.Length); + + return new SignatureToken(TypeBuilder.GetTokenFromSig(GetNativeHandle(), localSigBytes, sigLength), this); + } + + #endregion + + #region Other + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + [System.Runtime.InteropServices.ComVisible(true)] + public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) + { + if (con == null) + throw new ArgumentNullException("con"); + if (binaryAttribute == null) + throw new ArgumentNullException("binaryAttribute"); + Contract.EndContractBlock(); + + TypeBuilder.DefineCustomAttribute( + this, + 1, // This is hard coding the module token to 1 + this.GetConstructorToken(con).Token, + binaryAttribute, + false, false); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public void SetCustomAttribute(CustomAttributeBuilder customBuilder) + { + if (customBuilder == null) + { + throw new ArgumentNullException("customBuilder"); + } + Contract.EndContractBlock(); + + customBuilder.CreateCustomAttribute(this, 1); // This is hard coding the module token to 1 + } + + // This API returns the symbol writer being used to write debug symbols for this + // module (if any). + // + // WARNING: It is unlikely this API can be used correctly by applications in any + // reasonable way. It may be called internally from within TypeBuilder.CreateType. + // + // Specifically: + // 1. The underlying symbol writer (written in unmanaged code) is not necessarily well + // hardenned and fuzz-tested against malicious API calls. The security of partial-trust + // symbol writing is improved by restricting usage of the writer APIs to the well-structured + // uses in ModuleBuilder. + // 2. TypeBuilder.CreateType emits all the symbols for the type. This will effectively + // overwrite anything someone may have written manually about the type (specifically + // ISymbolWriter.OpenMethod is specced to clear anything previously written for the + // specified method) + // 3. Someone could technically update the symbols for a method after CreateType is + // called, but the debugger (which uses these symbols) assumes that they are only + // updated at TypeBuilder.CreateType time. The changes wouldn't be visible (committed + // to the underlying stream) until another type was baked. + // 4. Access to the writer is supposed to be synchronized (the underlying COM API is + // not thread safe, and these are only thin wrappers on top of them). Exposing this + // directly allows the synchronization to be violated. We know that concurrent symbol + // writer access can cause AVs and other problems. The writer APIs should not be callable + // directly by partial-trust code, but if they could this would be a security hole. + // Regardless, this is a reliability bug. + // + // For these reasons, we should consider making this API internal in Arrowhead + // (as it is in Silverlight), and consider validating that we're within a call + // to TypeBuilder.CreateType whenever this is used. + public ISymbolWriter GetSymWriter() + { + return m_iSymWriter; + } + +#if FEATURE_CORECLR + [System.Security.SecuritySafeCritical] +#endif + public ISymbolDocumentWriter DefineDocument(String url, Guid language, Guid languageVendor, Guid documentType) + { + // url cannot be null but can be an empty string + if (url == null) + throw new ArgumentNullException("url"); + Contract.EndContractBlock(); + + lock(SyncRoot) + { + return DefineDocumentNoLock(url, language, languageVendor, documentType); + } + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + private ISymbolDocumentWriter DefineDocumentNoLock(String url, Guid language, Guid languageVendor, Guid documentType) + { + if (m_iSymWriter == null) + { + // Cannot DefineDocument when it is not a debug module + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule")); + } + + return m_iSymWriter.DefineDocument(url, language, languageVendor, documentType); + } + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#else + [System.Security.SecuritySafeCritical] +#endif + public void SetUserEntryPoint(MethodInfo entryPoint) + { + lock(SyncRoot) + { + SetUserEntryPointNoLock(entryPoint); + } + } + + [System.Security.SecurityCritical] // auto-generated + private void SetUserEntryPointNoLock(MethodInfo entryPoint) + { + // Set the user entry point. Compiler may generate startup stub before calling user main. + // The startup stub will be the entry point. While the user "main" will be the user entry + // point so that debugger will not step into the compiler entry point. + + if (entryPoint == null) + { + throw new ArgumentNullException("entryPoint"); + } + Contract.EndContractBlock(); + + if (m_iSymWriter == null) + { + // Cannot set entry point when it is not a debug module + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule")); + } + + if (entryPoint.DeclaringType != null) + { + if (!entryPoint.Module.Equals(this)) + { + // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder + throw new InvalidOperationException(Environment.GetResourceString("Argument_NotInTheSameModuleBuilder")); + } + } + else + { + // unfortunately this check is missing for global function passed in as RuntimeMethodInfo. + // The problem is that Reflection does not + // allow us to get the containing module giving a global function + MethodBuilder mb = entryPoint as MethodBuilder; + if (mb != null && mb.GetModuleBuilder() != this) + { + // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder + throw new InvalidOperationException(Environment.GetResourceString("Argument_NotInTheSameModuleBuilder")); + } + } + + // get the metadata token value and create the SymbolStore's token value class + SymbolToken tkMethod = new SymbolToken(GetMethodTokenInternal(entryPoint).Token); + + // set the UserEntryPoint + m_iSymWriter.SetUserEntryPoint(tkMethod); + } + + public void SetSymCustomAttribute(String name, byte[] data) + { + lock(SyncRoot) + { + SetSymCustomAttributeNoLock(name, data); + } + } + + private void SetSymCustomAttributeNoLock(String name, byte[] data) + { + if (m_iSymWriter == null) + { + // Cannot SetSymCustomAttribute when it is not a debug module + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule")); + } + + // This API has never worked. It seems like we might want to call m_iSymWriter.SetSymAttribute, + // but we don't have a metadata token to associate the attribute with. Instead + // MethodBuilder.SetSymCustomAttribute could be used to associate a symbol attribute with a specific method. + } + + [Pure] + public bool IsTransient() + { + return InternalModule.IsTransientInternal(); + } + + #endregion + + #endregion + +#if !FEATURE_CORECLR + void _ModuleBuilder.GetTypeInfoCount(out uint pcTInfo) + { + throw new NotImplementedException(); + } + + void _ModuleBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) + { + throw new NotImplementedException(); + } + + void _ModuleBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) + { + throw new NotImplementedException(); + } + + void _ModuleBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) + { + throw new NotImplementedException(); + } +#endif + } +} |