Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// For each dynamic assembly there will be two AssemblyBuilder objects: the "internal"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obsolete comment

// AssemblyBuilder object and the "external" AssemblyBuilder object.
// 1. The "internal" object is the real assembly object that the VM creates and knows about. However,
// you can perform RefEmit operations on it only if you have its granted permission. From the AppDomain
// and other "internal" objects like the "internal" ModuleBuilders and runtime types, you can only
// get the "internal" objects. This is to prevent low-trust code from getting a hold of the dynamic
// AssemblyBuilder/ModuleBuilder/TypeBuilder/MethodBuilder/etc other people have created by simply
// enumerating the AppDomain and inject code in it.
// 2. The "external" object is merely an wrapper of the "internal" object and all operations on it
// are directed to the internal object. This is the one you get by calling DefineDynamicAssembly
// on AppDomain and the one you can always perform RefEmit operations on. You can get other "external"
// objects from the "external" AssemblyBuilder, ModuleBuilder, TypeBuilder, MethodBuilder, etc. Note
// that VM doesn't know about this object. So every time we call into the VM we need to pass in the
// "internal" object.
//
// "internal" and "external" ModuleBuilders are similar

using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.SymbolStore;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
Expand Down Expand Up @@ -75,7 +59,7 @@ internal ModuleBuilder GetModuleBuilder(RuntimeModule module)

internal AssemblyBuilder(AssemblyName name,
AssemblyBuilderAccess access,
ref StackCrawlMark stackMark,
Assembly? callingAssembly,
AssemblyLoadContext? assemblyLoadContext,
IEnumerable<CustomAttributeBuilder>? unsafeAssemblyAttributes)
{
Expand All @@ -87,6 +71,16 @@ internal AssemblyBuilder(AssemblyName name,
{
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)access), nameof(access));
}
if (callingAssembly == null)
{
// Called either from interop or async delegate invocation. Rejecting because we don't
// know how to set the correct permission on the new dynamic assembly.
throw new InvalidOperationException();
}
if (assemblyLoadContext == null)
{
assemblyLoadContext = AssemblyLoadContext.GetLoadContext(callingAssembly);
}

// Clone the name in case the caller modifies it underneath us.
name = (AssemblyName)name.Clone();
Expand All @@ -104,7 +98,6 @@ internal AssemblyBuilder(AssemblyName name,

RuntimeAssembly? retAssembly = null;
CreateDynamicAssembly(ObjectHandleOnStack.Create(ref name),
new StackCrawlMarkHandle(ref stackMark),
(int)access,
ObjectHandleOnStack.Create(ref assemblyLoadContext),
ObjectHandleOnStack.Create(ref retAssembly));
Expand Down Expand Up @@ -150,18 +143,12 @@ private void InitManifestModule()

#region DefineDynamicAssembly

/// <summary>
/// If an AssemblyName has a public key specified, the assembly is assumed
/// to have a strong name and a hash will be computed when the assembly
/// is saved.
/// </summary>
[DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod.
public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return InternalDefineDynamicAssembly(name,
access,
ref stackMark,
Assembly.GetCallingAssembly(),
AssemblyLoadContext.CurrentContextualReflectionContext,
null);
}
Expand All @@ -172,17 +159,15 @@ public static AssemblyBuilder DefineDynamicAssembly(
AssemblyBuilderAccess access,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return InternalDefineDynamicAssembly(name,
access,
ref stackMark,
Assembly.GetCallingAssembly(),
AssemblyLoadContext.CurrentContextualReflectionContext,
assemblyAttributes);
}

[GeneratedDllImport(RuntimeHelpers.QCall, EntryPoint = "AppDomain_CreateDynamicAssembly")]
private static partial void CreateDynamicAssembly(ObjectHandleOnStack name,
StackCrawlMarkHandle stackMark,
int access,
ObjectHandleOnStack assemblyLoadContext,
ObjectHandleOnStack retAssembly);
Expand All @@ -192,7 +177,7 @@ private static partial void CreateDynamicAssembly(ObjectHandleOnStack name,
internal static AssemblyBuilder InternalDefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
ref StackCrawlMark stackMark,
Assembly? callingAssembly,
AssemblyLoadContext? assemblyLoadContext,
IEnumerable<CustomAttributeBuilder>? unsafeAssemblyAttributes)
{
Expand All @@ -201,7 +186,7 @@ internal static AssemblyBuilder InternalDefineDynamicAssembly(
// We can only create dynamic assemblies in the current domain
return new AssemblyBuilder(name,
access,
ref stackMark,
callingAssembly,
assemblyLoadContext,
unsafeAssemblyAttributes);
}
Expand All @@ -215,7 +200,6 @@ internal static AssemblyBuilder InternalDefineDynamicAssembly(
/// modules within an Assembly with the same name. This dynamic module is
/// a transient module.
/// </summary>
[DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod.
public ModuleBuilder DefineDynamicModule(string name)
{
lock (SyncRoot)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Text;
using System.Threading;

Expand Down Expand Up @@ -234,12 +235,11 @@ private static RuntimeModule GetDynamicMethodsModule()
return s_anonymouslyHostedDynamicMethodsModule;

AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly");
StackCrawlMark stackMark = StackCrawlMark.LookForMe;

AssemblyBuilder assembly = AssemblyBuilder.InternalDefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.Run,
ref stackMark,
typeof(object).Assembly,
null,
null);

Expand Down
12 changes: 5 additions & 7 deletions src/coreclr/vm/appdomainnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
using namespace clr::fs;

// static
extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnStack assemblyName, QCall::StackCrawlMarkHandle stackMark, INT32 access, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly)
extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnStack assemblyName, INT32 access, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly)
{
QCALL_CONTRACT;

Expand All @@ -36,16 +36,14 @@ extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnS
args.loaderAllocator = NULL;

args.access = access;
args.stackMark = stackMark;

Assembly* pAssembly = nullptr;
AssemblyBinder* pBinder = nullptr;

if (assemblyLoadContext.Get() != NULL)
{
INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder();
pBinder = reinterpret_cast<AssemblyBinder*>(nativeAssemblyBinder);
}
_ASSERTE(assemblyLoadContext.Get() != NULL);

INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder();
pBinder = reinterpret_cast<AssemblyBinder*>(nativeAssemblyBinder);

pAssembly = Assembly::CreateDynamic(GetAppDomain(), pBinder, &args);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/appdomainnative.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ class AppDomainNative
static FCDECL1(Object*, GetOrInternString, StringObject* pStringUNSAFE);
static FCDECL1(Object*, IsStringInterned, StringObject* pString);
};
extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnStack assemblyName, QCall::StackCrawlMarkHandle stackMark, INT32 access, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly);
extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnStack assemblyName, INT32 access, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly);

#endif
53 changes: 2 additions & 51 deletions src/coreclr/vm/assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,15 +393,6 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C

Assembly *pRetVal = NULL;

MethodDesc *pmdEmitter = SystemDomain::GetCallersMethod(args->stackMark);

// Called either from interop or async delegate invocation. Rejecting because we don't
// know how to set the correct permission on the new dynamic assembly.
if (!pmdEmitter)
COMPlusThrow(kInvalidOperationException);

Assembly *pCallerAssembly = pmdEmitter->GetAssembly();

// First, we set up a pseudo-manifest file for the assembly.

// Set up the assembly name
Expand Down Expand Up @@ -510,48 +501,10 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C
IfFailThrow(pAssemblyEmit->DefineAssembly(publicKey, publicKey.GetSize(), ulHashAlgId,
name, &assemData, dwFlags,
&ma));
pPEAssembly = PEAssembly::Create(pCallerAssembly->GetPEAssembly(), pAssemblyEmit);

AssemblyBinder* pFallbackBinder = pBinder;

// If ALC is not specified
if (pFallbackBinder == nullptr)
{
// Dynamically created modules (aka RefEmit assemblies) do not have a LoadContext associated with them since they are not bound
// using an actual binder. As a result, we will assume the same binding/loadcontext information for the dynamic assembly as its
// caller/creator to ensure that any assembly loads triggered by the dynamic assembly are resolved using the intended load context.
//
// If the creator assembly has a HostAssembly associated with it, then use it for binding. Otherwise, the creator is dynamic
// and will have a fallback load context binder associated with it.

// There is always a manifest file - wehther working with static or dynamic assemblies.
PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetPEAssembly();
_ASSERTE(pCallerAssemblyManifestFile != NULL);

if (!pCallerAssemblyManifestFile->IsDynamic())
{
// Static assemblies with do not have fallback load context
_ASSERTE(pCallerAssemblyManifestFile->GetFallbackBinder() == nullptr);

// Fetch the binder from the host assembly
PTR_BINDER_SPACE_Assembly pCallerAssemblyHostAssembly = pCallerAssemblyManifestFile->GetHostAssembly();
_ASSERTE(pCallerAssemblyHostAssembly != nullptr);

pFallbackBinder = pCallerAssemblyHostAssembly->GetBinder();
}
else
{
// Creator assembly is dynamic too, so use its fallback load context for the one
// we are creating.
pFallbackBinder = pCallerAssemblyManifestFile->GetFallbackBinder();
}
}

// At this point, we should have a fallback load context binder to work with
_ASSERTE(pFallbackBinder != nullptr);
pPEAssembly = PEAssembly::Create(pAssemblyEmit);

// Set it as the fallback load context binder for the dynamic assembly being created
pPEAssembly->SetFallbackBinder(pFallbackBinder);
pPEAssembly->SetFallbackBinder(pBinder);
}

NewHolder<DomainAssembly> pDomainAssembly;
Expand Down Expand Up @@ -620,8 +573,6 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C
pAssem = Assembly::Create(pDomain, pPEAssembly, pDomainAssembly->GetDebuggerInfoBits(), pLoaderAllocator->IsCollectible(), pamTracker, pLoaderAllocator);

ReflectionModule* pModule = (ReflectionModule*) pAssem->GetModule();
pModule->SetCreatingAssembly( pCallerAssembly );


if (createdNewAssemblyLoaderAllocator)
{
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/assembly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ struct CreateDynamicAssemblyArgsGC
struct CreateDynamicAssemblyArgs : CreateDynamicAssemblyArgsGC
{
INT32 access;
StackCrawlMark* stackMark;
};

// An assembly is the unit of deployment for managed code.
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/vm/assemblynative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma

// Set the caller's assembly to be CoreLib
DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly();
PEAssembly *pParentAssembly = pCallersAssembly->GetPEAssembly();

// Initialize the AssemblySpec
AssemblySpec spec;
Expand All @@ -168,7 +167,7 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma
COMPlusThrowHR(COR_E_FILELOAD, dwMessageID, name);
}

PEAssemblyHolder pPEAssembly(PEAssembly::Open(pParentAssembly, pAssembly->GetPEImage(), pAssembly));
PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->GetPEImage(), pAssembly));
bindOperation.SetResult(pPEAssembly.GetValue());

DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/ceeload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6925,7 +6925,6 @@ ReflectionModule::ReflectionModule(Assembly *pAssembly, mdFile token, PEAssembly

m_pInMemoryWriter = NULL;
m_sdataSection = NULL;
m_pCreatingAssembly = NULL;
m_pCeeFileGen = NULL;
m_pDynamicMetadata = NULL;
}
Expand Down
15 changes: 0 additions & 15 deletions src/coreclr/vm/ceeload.h
Original file line number Diff line number Diff line change
Expand Up @@ -2174,7 +2174,6 @@ class ReflectionModule : public Module
protected:
ICeeGenInternal * m_pCeeFileGen;
private:
Assembly *m_pCreatingAssembly;
RefClassWriter *m_pInMemoryWriter;


Expand Down Expand Up @@ -2211,20 +2210,6 @@ class ReflectionModule : public Module
virtual TADDR GetIL(RVA target);
virtual PTR_VOID GetRvaField(RVA rva);

Assembly* GetCreatingAssembly( void )
{
LIMITED_METHOD_CONTRACT;

return m_pCreatingAssembly;
}

void SetCreatingAssembly( Assembly* assembly )
{
LIMITED_METHOD_CONTRACT;

m_pCreatingAssembly = assembly;
}

ICeeGenInternal *GetCeeGen() {LIMITED_METHOD_CONTRACT; return m_pCeeFileGen; }

RefClassWriter *GetClassWriter()
Expand Down
Loading