|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// <OWNER>Microsoft</OWNER>
//
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
[ResourceExposure(ResourceScope.Machine)]
[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
char[] bFormat = strFormat.ToCharArray();
return SymbolType.FormCompoundType(bFormat, 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
[ResourceExposure(ResourceScope.Machine)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private extern static int GetStringConstant(RuntimeModule module, String str, int length);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private extern static void PreSavePEFile(RuntimeModule module, int portableExecutableKind, int imageFileMachine);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.Machine)]
[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
[ResourceExposure(ResourceScope.None)]
[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
[ResourceExposure(ResourceScope.Machine)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private extern static void SetModuleName(RuntimeModule module, String strModuleName);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
internal extern static void SetFieldRVAContent(RuntimeModule module, int fdToken, byte[] data, int length);
#if !FEATURE_PAL
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.Machine)]
[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
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private extern static void DefineNativeResourceBytes(RuntimeModule module,
byte[] pbResource, int cbResource,
int portableExecutableKind,
int imageFileMachine);
#endif
[System.Security.SecurityCritical] // auto-generated
internal void DefineNativeResource(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
{
#if !FEATURE_PAL
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);
}
#endif // !FEATURE_PAL
}
#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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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;
}
}
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
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];
System.Array.Copy(resource, m_moduleData.m_resourceBytes, resource.Length);
}
#if FEATURE_CORECLR
[System.Security.SecurityCritical] // auto-generated
#else
[System.Security.SecuritySafeCritical]
#endif
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
public void DefineUnmanagedResource(String resourceFileName)
{
lock(SyncRoot)
{
DefineUnmanagedResourceFileInternalNoLock(resourceFileName);
}
}
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
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
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
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];
Array.Copy(sigBytes, localSigBytes, 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
}
}
|