diff options
Diffstat (limited to 'src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs')
-rw-r--r-- | src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs | 1039 |
1 files changed, 1039 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs new file mode 100644 index 0000000000..6f6b436706 --- /dev/null +++ b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs @@ -0,0 +1,1039 @@ +// 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; + using System.Collections.Generic; + using CultureInfo = System.Globalization.CultureInfo; + using System.Reflection; + using System.Security; + using System.Security.Permissions; + using System.Threading; + using System.Runtime.CompilerServices; + using System.Runtime.Versioning; + using System.Diagnostics.Contracts; + using System.Runtime.InteropServices; + + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class DynamicMethod : MethodInfo + { + private RuntimeType[] m_parameterTypes; + internal IRuntimeMethodInfo m_methodHandle; + private RuntimeType m_returnType; + private DynamicILGenerator m_ilGenerator; + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + private DynamicILInfo m_DynamicILInfo; + private bool m_fInitLocals; + private RuntimeModule m_module; + internal bool m_skipVisibility; + internal RuntimeType m_typeOwner; // can be null + + // We want the creator of the DynamicMethod to control who has access to the + // DynamicMethod (just like we do for delegates). However, a user can get to + // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc. + // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would + // not be able to bound access to the DynamicMethod. Hence, we need to ensure that + // we do not allow direct use of RTDynamicMethod. + private RTDynamicMethod m_dynMethod; + + // needed to keep the object alive during jitting + // assigned by the DynamicResolver ctor + internal DynamicResolver m_resolver; + + // Always false unless we are in an immersive (non dev mode) process. +#if FEATURE_APPX + private bool m_profileAPICheck; + + private RuntimeAssembly m_creatorAssembly; +#endif + + internal bool m_restrictedSkipVisibility; + // The context when the method was created. We use this to do the RestrictedMemberAccess checks. + // These checks are done when the method is compiled. This can happen at an arbitrary time, + // when CreateDelegate or Invoke is called, or when another DynamicMethod executes OpCodes.Call. + // We capture the creation context so that we can do the checks against the same context, + // irrespective of when the method gets compiled. Note that the DynamicMethod does not know when + // it is ready for use since there is not API which indictates that IL generation has completed. +#if FEATURE_COMPRESSEDSTACK + internal CompressedStack m_creationContext; +#endif // FEATURE_COMPRESSEDSTACK + private static volatile InternalModuleBuilder s_anonymouslyHostedDynamicMethodsModule; + private static readonly object s_anonymouslyHostedDynamicMethodsModuleLock = new object(); + + // + // class initialization (ctor and init) + // + + private DynamicMethod() { } + + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + null, // owner + null, // m + false, // skipVisibility + true, + ref stackMark); // transparentMethod + } + + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes, + bool restrictedSkipVisibility) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + null, // owner + null, // m + restrictedSkipVisibility, + true, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes, + Module m) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(m, ref stackMark, false); + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + null, // owner + m, // m + false, // skipVisibility + false, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes, + Module m, + bool skipVisibility) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(m, ref stackMark, skipVisibility); + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + null, // owner + m, // m + skipVisibility, + false, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + MethodAttributes attributes, + CallingConventions callingConvention, + Type returnType, + Type[] parameterTypes, + Module m, + bool skipVisibility) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(m, ref stackMark, skipVisibility); + Init(name, + attributes, + callingConvention, + returnType, + parameterTypes, + null, // owner + m, // m + skipVisibility, + false, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes, + Type owner) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(owner, ref stackMark, false); + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + owner, // owner + null, // m + false, // skipVisibility + false, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + Type returnType, + Type[] parameterTypes, + Type owner, + bool skipVisibility) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(owner, ref stackMark, skipVisibility); + Init(name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + returnType, + parameterTypes, + owner, // owner + null, // m + skipVisibility, + false, + ref stackMark); // transparentMethod + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #else + [System.Security.SecuritySafeCritical] + #endif + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public DynamicMethod(string name, + MethodAttributes attributes, + CallingConventions callingConvention, + Type returnType, + Type[] parameterTypes, + Type owner, + bool skipVisibility) { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + PerformSecurityCheck(owner, ref stackMark, skipVisibility); + Init(name, + attributes, + callingConvention, + returnType, + parameterTypes, + owner, // owner + null, // m + skipVisibility, + false, + ref stackMark); // transparentMethod + } + + // helpers for intialization + + static private void CheckConsistency(MethodAttributes attributes, CallingConventions callingConvention) { + // only static public for method attributes + if ((attributes & ~MethodAttributes.MemberAccessMask) != MethodAttributes.Static) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags")); + if ((attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags")); + Contract.EndContractBlock(); + + // only standard or varargs supported + if (callingConvention != CallingConventions.Standard && callingConvention != CallingConventions.VarArgs) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags")); + + // vararg is not supported at the moment + if (callingConvention == CallingConventions.VarArgs) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags")); + } + + // We create a transparent assembly to host DynamicMethods. Since the assembly does not have any + // non-public fields (or any fields at all), it is a safe anonymous assembly to host DynamicMethods + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + private static RuntimeModule GetDynamicMethodsModule() + { + if (s_anonymouslyHostedDynamicMethodsModule != null) + return s_anonymouslyHostedDynamicMethodsModule; + + lock (s_anonymouslyHostedDynamicMethodsModuleLock) + { + if (s_anonymouslyHostedDynamicMethodsModule != null) + return s_anonymouslyHostedDynamicMethodsModule; + + ConstructorInfo transparencyCtor = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes); + CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, EmptyArray<Object>.Value); + List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>(); + assemblyAttributes.Add(transparencyAttribute); +#if !FEATURE_CORECLR + // On the desktop, we need to use the security rule set level 1 for anonymously hosted + // dynamic methods. In level 2, transparency rules are strictly enforced, which leads to + // errors when a fully trusted application causes a dynamic method to be generated that tries + // to call a method with a LinkDemand or a SecurityCritical method. To retain compatibility + // with the v2.0 and v3.x frameworks, these calls should be allowed. + // + // If this rule set was not explicitly called out, then the anonymously hosted dynamic methods + // assembly would inherit the rule set from the creating assembly - which would cause it to + // be level 2 because mscorlib.dll is using the level 2 rules. + ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }); + CustomAttributeBuilder securityRulesAttribute = + new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level1 }); + assemblyAttributes.Add(securityRulesAttribute); +#endif // !FEATURE_CORECLR + + AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly"); + StackCrawlMark stackMark = StackCrawlMark.LookForMe; + + AssemblyBuilder assembly = AssemblyBuilder.InternalDefineDynamicAssembly( + assemblyName, + AssemblyBuilderAccess.Run, + null, null, null, null, null, + ref stackMark, + assemblyAttributes, + SecurityContextSource.CurrentAssembly); + + AppDomain.PublishAnonymouslyHostedDynamicMethodsAssembly(assembly.GetNativeHandle()); + + // this always gets the internal module. + s_anonymouslyHostedDynamicMethodsModule = (InternalModuleBuilder)assembly.ManifestModule; + } + + return s_anonymouslyHostedDynamicMethodsModule; + } + + [System.Security.SecurityCritical] // auto-generated + private unsafe void Init(String name, + MethodAttributes attributes, + CallingConventions callingConvention, + Type returnType, + Type[] signature, + Type owner, + Module m, + bool skipVisibility, + bool transparentMethod, + ref StackCrawlMark stackMark) + { + DynamicMethod.CheckConsistency(attributes, callingConvention); + + // check and store the signature + if (signature != null) { + m_parameterTypes = new RuntimeType[signature.Length]; + for (int i = 0; i < signature.Length; i++) { + if (signature[i] == null) + throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature")); + m_parameterTypes[i] = signature[i].UnderlyingSystemType as RuntimeType; + if ( m_parameterTypes[i] == null || !(m_parameterTypes[i] is RuntimeType) || m_parameterTypes[i] == (RuntimeType)typeof(void) ) + throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature")); + } + } + else { + m_parameterTypes = Array.Empty<RuntimeType>(); + } + + // check and store the return value + m_returnType = (returnType == null) ? (RuntimeType)typeof(void) : returnType.UnderlyingSystemType as RuntimeType; + if ( (m_returnType == null) || !(m_returnType is RuntimeType) || m_returnType.IsByRef ) + throw new NotSupportedException(Environment.GetResourceString("Arg_InvalidTypeInRetType")); + + if (transparentMethod) + { + Contract.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods"); + m_module = GetDynamicMethodsModule(); + if (skipVisibility) + { + m_restrictedSkipVisibility = true; + } + +#if FEATURE_COMPRESSEDSTACK + m_creationContext = CompressedStack.Capture(); +#endif // FEATURE_COMPRESSEDSTACK + } + else + { + Contract.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set"); + Contract.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly"); + Contract.Assert(m == null || owner == null, "m and owner cannot both be set"); + + if (m != null) + m_module = m.ModuleHandle.GetRuntimeModule(); // this returns the underlying module for all RuntimeModule and ModuleBuilder objects. + else + { + RuntimeType rtOwner = null; + if (owner != null) + rtOwner = owner.UnderlyingSystemType as RuntimeType; + + if (rtOwner != null) + { + if (rtOwner.HasElementType || rtOwner.ContainsGenericParameters + || rtOwner.IsGenericParameter || rtOwner.IsInterface) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeForDynamicMethod")); + + m_typeOwner = rtOwner; + m_module = rtOwner.GetRuntimeModule(); + } + } + + m_skipVisibility = skipVisibility; + } + + // initialize remaining fields + m_ilGenerator = null; + m_fInitLocals = true; + m_methodHandle = null; + + if (name == null) + throw new ArgumentNullException("name"); + +#if FEATURE_APPX + if (AppDomain.ProfileAPICheck) + { + if (m_creatorAssembly == null) + m_creatorAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark); + + if (m_creatorAssembly != null && !m_creatorAssembly.IsFrameworkAssembly()) + m_profileAPICheck = true; + } +#endif // FEATURE_APPX + + m_dynMethod = new RTDynamicMethod(this, name, attributes, callingConvention); + } + + [System.Security.SecurityCritical] // auto-generated + private void PerformSecurityCheck(Module m, ref StackCrawlMark stackMark, bool skipVisibility) + { + if (m == null) + throw new ArgumentNullException("m"); + Contract.EndContractBlock(); +#if !FEATURE_CORECLR + + RuntimeModule rtModule; + ModuleBuilder mb = m as ModuleBuilder; + if (mb != null) + rtModule = mb.InternalModule; + else + rtModule = m as RuntimeModule; + + if (rtModule == null) + { + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeModule"), "m"); + } + + // The user cannot explicitly use this assembly + if (rtModule == s_anonymouslyHostedDynamicMethodsModule) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"), "m"); + + // ask for member access if skip visibility + if (skipVisibility) + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); + +#if !FEATURE_CORECLR + // ask for control evidence if outside of the caller assembly + RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark); + m_creatorAssembly = callingType.GetRuntimeAssembly(); + if (m.Assembly != m_creatorAssembly) + { + // Demand the permissions of the assembly where the DynamicMethod will live + CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence, + m.Assembly.PermissionSet); + } +#else //FEATURE_CORECLR +#pragma warning disable 618 + new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); +#pragma warning restore 618 +#endif //FEATURE_CORECLR +#endif //!FEATURE_CORECLR + } + + [System.Security.SecurityCritical] // auto-generated + private void PerformSecurityCheck(Type owner, ref StackCrawlMark stackMark, bool skipVisibility) + { + if (owner == null) + throw new ArgumentNullException("owner"); +#if !FEATURE_CORECLR + + RuntimeType rtOwner = owner as RuntimeType; + if (rtOwner == null) + rtOwner = owner.UnderlyingSystemType as RuntimeType; + + if (rtOwner == null) + throw new ArgumentNullException("owner", Environment.GetResourceString("Argument_MustBeRuntimeType")); + + // get the type the call is coming from + RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark); + + // ask for member access if skip visibility + if (skipVisibility) + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); + else + { + // if the call is not coming from the same class ask for member access + if (callingType != rtOwner) + new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); + } +#if !FEATURE_CORECLR + m_creatorAssembly = callingType.GetRuntimeAssembly(); + + // ask for control evidence if outside of the caller module + if (rtOwner.Assembly != m_creatorAssembly) + { + // Demand the permissions of the assembly where the DynamicMethod will live + CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence, + owner.Assembly.PermissionSet); + } +#else //FEATURE_CORECLR +#pragma warning disable 618 + new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); +#pragma warning restore 618 +#endif //FEATURE_CORECLR +#endif //!FEATURE_CORECLR + } + + // + // Delegate and method creation + // + + [System.Security.SecuritySafeCritical] // auto-generated + [System.Runtime.InteropServices.ComVisible(true)] + public sealed override Delegate CreateDelegate(Type delegateType) { + if (m_restrictedSkipVisibility) + { + // Compile the method since accessibility checks are done as part of compilation. + GetMethodDescriptor(); + System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle); + } + + MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, null, GetMethodDescriptor()); + // stash this MethodInfo by brute force. + d.StoreDynamicMethod(GetMethodInfo()); + return d; + } + + [System.Security.SecuritySafeCritical] // auto-generated + [System.Runtime.InteropServices.ComVisible(true)] + public sealed override Delegate CreateDelegate(Type delegateType, Object target) { + if (m_restrictedSkipVisibility) + { + // Compile the method since accessibility checks are done as part of compilation + GetMethodDescriptor(); + System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle); + } + + MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, target, GetMethodDescriptor()); + // stash this MethodInfo by brute force. + d.StoreDynamicMethod(GetMethodInfo()); + return d; + } + +#if FEATURE_APPX + internal bool ProfileAPICheck + { + get + { + return m_profileAPICheck; + } + + [FriendAccessAllowed] + set + { + m_profileAPICheck = value; + } + } +#endif + + // This is guaranteed to return a valid handle + [System.Security.SecurityCritical] // auto-generated + internal unsafe RuntimeMethodHandle GetMethodDescriptor() { + if (m_methodHandle == null) { + lock (this) { + if (m_methodHandle == null) { + if (m_DynamicILInfo != null) + m_DynamicILInfo.GetCallableMethod(m_module, this); + else { + if (m_ilGenerator == null || m_ilGenerator.ILOffset == 0) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadEmptyMethodBody", Name)); + + m_ilGenerator.GetCallableMethod(m_module, this); + } + } + } + } + return new RuntimeMethodHandle(m_methodHandle); + } + + // + // MethodInfo api. They mostly forward to RTDynamicMethod + // + + public override String ToString() { return m_dynMethod.ToString(); } + + public override String Name { get { return m_dynMethod.Name; } } + + public override Type DeclaringType { get { return m_dynMethod.DeclaringType; } } + + public override Type ReflectedType { get { return m_dynMethod.ReflectedType; } } + + public override Module Module { get { return m_dynMethod.Module; } } + + // we cannot return a MethodHandle because we cannot track it via GC so this method is off limits + public override RuntimeMethodHandle MethodHandle { get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } } + + public override MethodAttributes Attributes { get { return m_dynMethod.Attributes; } } + + public override CallingConventions CallingConvention { get { return m_dynMethod.CallingConvention; } } + + public override MethodInfo GetBaseDefinition() { return this; } + + [Pure] + public override ParameterInfo[] GetParameters() { return m_dynMethod.GetParameters(); } + + public override MethodImplAttributes GetMethodImplementationFlags() { return m_dynMethod.GetMethodImplementationFlags(); } + + // + // Security transparency accessors + // + // Since the dynamic method may not be JITed yet, we don't always have the runtime method handle + // which is needed to determine the official runtime transparency status of the dynamic method. We + // fall back to saying that the dynamic method matches the transparency of its containing module + // until we get a JITed version, since dynamic methods cannot have attributes of their own. + // + + public override bool IsSecurityCritical + { + [SecuritySafeCritical] + get + { + if (m_methodHandle != null) + { + return RuntimeMethodHandle.IsSecurityCritical(m_methodHandle); + } + else if (m_typeOwner != null) + { + RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return assembly.IsAllSecurityCritical(); + } + else + { + RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return assembly.IsAllSecurityCritical(); + } + } + } + + public override bool IsSecuritySafeCritical + { + [SecuritySafeCritical] + get + { + if (m_methodHandle != null) + { + return RuntimeMethodHandle.IsSecuritySafeCritical(m_methodHandle); + } + else if (m_typeOwner != null) + { + RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return assembly.IsAllPublicAreaSecuritySafeCritical(); + } + else + { + RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return assembly.IsAllSecuritySafeCritical(); + } + } + } + + public override bool IsSecurityTransparent + { + [SecuritySafeCritical] + get + { + if (m_methodHandle != null) + { + return RuntimeMethodHandle.IsSecurityTransparent(m_methodHandle); + } + else if (m_typeOwner != null) + { + RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return !assembly.IsAllSecurityCritical(); + } + else + { + RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; + Contract.Assert(assembly != null); + + return !assembly.IsAllSecurityCritical(); + } + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) { + if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_CallToVarArg")); + Contract.EndContractBlock(); + + // + // We do not demand any permission here because the caller already has access + // to the current DynamicMethod object, and it could just as easily emit another + // Transparent DynamicMethod to call the current DynamicMethod. + // + + RuntimeMethodHandle method = GetMethodDescriptor(); + // ignore obj since it's a static method + + // create a signature object + Signature sig = new Signature( + this.m_methodHandle, m_parameterTypes, m_returnType, CallingConvention); + + + // verify arguments + int formalCount = sig.Arguments.Length; + int actualCount = (parameters != null) ? parameters.Length : 0; + if (formalCount != actualCount) + throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt")); + + // if we are here we passed all the previous checks. Time to look at the arguments + Object retValue = null; + if (actualCount > 0) + { + Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig); + retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false); + // copy out. This should be made only if ByRef are present. + for (int index = 0; index < arguments.Length; index++) + parameters[index] = arguments[index]; + } + else + { + retValue = RuntimeMethodHandle.InvokeMethod(null, null, sig, false); + } + + GC.KeepAlive(this); + return retValue; + } + + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return m_dynMethod.GetCustomAttributes(attributeType, inherit); + } + + public override Object[] GetCustomAttributes(bool inherit) { return m_dynMethod.GetCustomAttributes(inherit); } + + public override bool IsDefined(Type attributeType, bool inherit) { return m_dynMethod.IsDefined(attributeType, inherit); } + + public override Type ReturnType { get { return m_dynMethod.ReturnType; } } + + public override ParameterInfo ReturnParameter { get { return m_dynMethod.ReturnParameter; } } + + public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return m_dynMethod.ReturnTypeCustomAttributes; } } + + // + // DynamicMethod specific methods + // + + public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String parameterName) { + if (position < 0 || position > m_parameterTypes.Length) + throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence")); + position--; // it's 1 based. 0 is the return value + + if (position >= 0) { + ParameterInfo[] parameters = m_dynMethod.LoadParameters(); + parameters[position].SetName(parameterName); + parameters[position].SetAttributes(attributes); + } + return null; + } + + [System.Security.SecuritySafeCritical] // auto-generated + public DynamicILInfo GetDynamicILInfo() + { +#pragma warning disable 618 + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); +#pragma warning restore 618 + + if (m_DynamicILInfo != null) + return m_DynamicILInfo; + + return GetDynamicILInfo(new DynamicScope()); + } + + [System.Security.SecurityCritical] // auto-generated + internal DynamicILInfo GetDynamicILInfo(DynamicScope scope) + { + if (m_DynamicILInfo == null) + { + byte[] methodSignature = SignatureHelper.GetMethodSigHelper( + null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true); + m_DynamicILInfo = new DynamicILInfo(scope, this, methodSignature); + } + + return m_DynamicILInfo; + } + + public ILGenerator GetILGenerator() { + return GetILGenerator(64); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public ILGenerator GetILGenerator(int streamSize) + { + if (m_ilGenerator == null) + { + byte[] methodSignature = SignatureHelper.GetMethodSigHelper( + null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true); + m_ilGenerator = new DynamicILGenerator(this, methodSignature, streamSize); + } + return m_ilGenerator; + } + + public bool InitLocals { + get {return m_fInitLocals;} + set {m_fInitLocals = value;} + } + + // + // Internal API + // + + internal MethodInfo GetMethodInfo() { + return m_dynMethod; + } + + ////////////////////////////////////////////////////////////////////////////////////////////// + // RTDynamicMethod + // + // this is actually the real runtime instance of a method info that gets used for invocation + // We need this so we never leak the DynamicMethod out via an exception. + // This way the DynamicMethod creator is the only one responsible for DynamicMethod access, + // and can control exactly who gets access to it. + // + internal class RTDynamicMethod : MethodInfo { + + internal DynamicMethod m_owner; + ParameterInfo[] m_parameters; + String m_name; + MethodAttributes m_attributes; + CallingConventions m_callingConvention; + + // + // ctors + // + private RTDynamicMethod() {} + + internal RTDynamicMethod(DynamicMethod owner, String name, MethodAttributes attributes, CallingConventions callingConvention) { + m_owner = owner; + m_name = name; + m_attributes = attributes; + m_callingConvention = callingConvention; + } + + // + // MethodInfo api + // + public override String ToString() { + return ReturnType.FormatTypeName() + " " + FormatNameAndSig(); + } + + public override String Name { + get { return m_name; } + } + + public override Type DeclaringType { + get { return null; } + } + + public override Type ReflectedType { + get { return null; } + } + + public override Module Module { + get { return m_owner.m_module; } + } + + public override RuntimeMethodHandle MethodHandle { + get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } + } + + public override MethodAttributes Attributes { + get { return m_attributes; } + } + + public override CallingConventions CallingConvention { + get { return m_callingConvention; } + } + + public override MethodInfo GetBaseDefinition() { + return this; + } + + [Pure] + public override ParameterInfo[] GetParameters() { + ParameterInfo[] privateParameters = LoadParameters(); + ParameterInfo[] parameters = new ParameterInfo[privateParameters.Length]; + Array.Copy(privateParameters, 0, parameters, 0, privateParameters.Length); + return parameters; + } + + public override MethodImplAttributes GetMethodImplementationFlags() { + return MethodImplAttributes.IL | MethodImplAttributes.NoInlining; + } + + public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) { + // We want the creator of the DynamicMethod to control who has access to the + // DynamicMethod (just like we do for delegates). However, a user can get to + // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc. + // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would + // not be able to bound access to the DynamicMethod. Hence, we do not allow + // direct use of RTDynamicMethod. + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "this"); + } + + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + Contract.EndContractBlock(); + + if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) + return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) }; + else + return EmptyArray<Object>.Value; + } + + public override Object[] GetCustomAttributes(bool inherit) { + // support for MethodImplAttribute PCA + return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) }; + } + + public override bool IsDefined(Type attributeType, bool inherit) { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + Contract.EndContractBlock(); + + if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) + return true; + else + return false; + } + + public override bool IsSecurityCritical + { + get { return m_owner.IsSecurityCritical; } + } + + public override bool IsSecuritySafeCritical + { + get { return m_owner.IsSecuritySafeCritical; } + } + + public override bool IsSecurityTransparent + { + get { return m_owner.IsSecurityTransparent; } + } + + public override Type ReturnType + { + get + { + return m_owner.m_returnType; + } + } + + public override ParameterInfo ReturnParameter { + get { return null; } + } + + public override ICustomAttributeProvider ReturnTypeCustomAttributes { + get { return GetEmptyCAHolder(); } + } + + // + // private implementation + // + + internal ParameterInfo[] LoadParameters() { + if (m_parameters == null) { + Type[] parameterTypes = m_owner.m_parameterTypes; + ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length]; + for (int i = 0; i < parameterTypes.Length; i++) + parameters[i] = new RuntimeParameterInfo(this, null, parameterTypes[i], i); + if (m_parameters == null) + // should we interlockexchange? + m_parameters = parameters; + } + return m_parameters; + } + + // private implementation of CA for the return type + private ICustomAttributeProvider GetEmptyCAHolder() { + return new EmptyCAHolder(); + } + + /////////////////////////////////////////////////// + // EmptyCAHolder + private class EmptyCAHolder : ICustomAttributeProvider { + internal EmptyCAHolder() {} + + Object[] ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit) { + return EmptyArray<Object>.Value; + } + + Object[] ICustomAttributeProvider.GetCustomAttributes(bool inherit) { + return EmptyArray<Object>.Value; + } + + bool ICustomAttributeProvider.IsDefined (Type attributeType, bool inherit) { + return false; + } + } + + } + + } + +} + |