1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*============================================================
7 ** Header: Assembly.hpp
11 ** Purpose: Implements assembly (loader domain) architecture
14 ===========================================================*/
19 #include "exceptmacros.h"
20 #include "clsload.hpp"
23 #include "iceefilegen.h"
24 #include "cordbpriv.h"
25 #include "assemblyspec.hpp"
33 class ComDynamicWrite;
37 class ISharedSecurityDescriptor;
38 class SecurityTransparencyBehavior;
40 class AllocMemTracker;
41 class FriendAssemblyDescriptor;
43 // Bits in m_dwDynamicAssemblyAccess (see System.Reflection.Emit.AssemblyBuilderAccess.cs)
44 #define ASSEMBLY_ACCESS_RUN 0x01
45 #define ASSEMBLY_ACCESS_SAVE 0x02
46 #define ASSEMBLY_ACCESS_COLLECT 0x8
48 struct CreateDynamicAssemblyArgsGC
50 ASSEMBLYNAMEREF assemblyName;
51 LOADERALLOCATORREF loaderAllocator;
54 struct CreateDynamicAssemblyArgs : CreateDynamicAssemblyArgsGC
57 StackCrawlMark* stackMark;
60 // An assembly is the unit of deployment for managed code. Typically Assemblies are one to one with files
61 // (Modules), however this is not necessary, as an assembly can contain serveral files (typically you only
62 // do this so that you can resource-only modules that are national language specific)
64 // Conceptually Assemblies are loaded into code:AppDomain
66 // So in general an assemly is a list of code:Module, where a code:Module is 1-1 with a DLL or EXE file.
68 // One of the modules the code:Assembly.m_pManifest is special in that it knows about all the other
69 // modules in an assembly (often it is the only one).
73 friend class BaseDomain;
74 friend class SystemDomain;
75 friend class ClassLoader;
76 friend class AssemblyNative;
77 friend class AssemblySpec;
79 friend class AssemblyNameNative;
80 friend class ClrDataAccess;
83 Assembly(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible);
84 void Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator);
87 void Terminate( BOOL signalProfiler = TRUE );
89 static Assembly *Create(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator);
91 BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pManifestFile->IsSystem(); }
93 static Assembly *CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs *args);
95 MethodDesc *GetEntryPoint();
97 //****************************************************************************************
99 // Additional init tasks for Modules. This should probably be part of Module::Initialize()
100 // but there's at least one call to ReflectionModule::Create that is *not* followed by a
101 // PrepareModule call.
102 void PrepareModuleForAssembly(Module* module, AllocMemTracker *pamTracker);
104 // This is the final step of publishing a Module into an Assembly. This step cannot fail.
105 void PublishModuleIntoAssembly(Module *module);
107 #ifndef DACCESS_COMPILE
111 m_pManifest->SetIsTenured();
114 // CAUTION: This should only be used as backout code if an assembly is unsuccessfully
115 // added to the shared domain assembly map.
116 void UnsetIsTenured()
119 m_pManifest->UnsetIsTenured();
121 #endif // DACCESS_COMPILE
123 //****************************************************************************************
125 // Returns the class loader associated with the assembly.
126 ClassLoader* GetLoader()
128 LIMITED_METHOD_CONTRACT;
130 return m_pClassLoader;
133 // ------------------------------------------------------------
135 // ------------------------------------------------------------
143 // The preferred constructor. If you use this, you don't have to
144 // call Start() yourself
145 ModuleIterator(Assembly *pAssembly)
151 // When you don't have the Assembly at contruction time, use this
152 // constructor, and explicitly call Start() to begin the iteration.
155 LIMITED_METHOD_CONTRACT;
162 void Start(Assembly * pAssembly)
164 LIMITED_METHOD_CONTRACT;
167 m_pManifest = pAssembly->GetManifestModule();
173 LIMITED_METHOD_CONTRACT;
175 while (++m_i <= m_pManifest->GetFileMax())
177 if (GetModule() != NULL)
185 LIMITED_METHOD_CONTRACT;
187 return m_pManifest->LookupFile(TokenFromRid(m_i, mdtFile));
191 ModuleIterator IterateModules()
195 return ModuleIterator(this);
199 //****************************************************************************************
201 // Get the domain the assembly lives in.
202 PTR_BaseDomain Parent()
204 LIMITED_METHOD_CONTRACT;
208 // Sets the assemblies domain.
209 void SetParent(BaseDomain* pParent);
211 //-----------------------------------------------------------------------------------------
212 // EnsureActive ensures that the assembly is properly prepped in the current app domain
213 // for active uses like code execution, static field access, and instance allocation
214 //-----------------------------------------------------------------------------------------
215 #ifndef DACCESS_COMPILE
219 //-----------------------------------------------------------------------------------------
220 // CheckActivated is a check predicate which should be used in active use paths like code
221 // execution, static field access, and instance allocation
222 //-----------------------------------------------------------------------------------------
223 CHECK CheckActivated();
225 // Returns the parent domain if it is not the system area. Returns NULL if it is the
227 PTR_BaseDomain GetDomain();
228 PTR_LoaderAllocator GetLoaderAllocator() { LIMITED_METHOD_DAC_CONTRACT; return m_pLoaderAllocator; }
230 BOOL GetModuleZapFile(LPCWSTR name, SString &path);
233 LPCWSTR GetDebugName()
236 return GetManifestFile()->GetDebugName();
240 LPCUTF8 GetSimpleName()
243 return GetManifestFile()->GetSimpleName();
249 return GetManifestFile()->IsStrongNamed();
252 const void *GetPublicKey(DWORD *pcbPK)
255 return GetManifestFile()->GetPublicKey(pcbPK);
261 return GetManifestFile()->GetHashAlgId();
264 HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
267 return GetManifestFile()->GetVersion(pMajor, pMinor, pBuild, pRevision);
273 return GetManifestFile()->GetLocale();
279 return GetManifestFile()->GetFlags();
282 PTR_LoaderHeap GetLowFrequencyHeap();
283 PTR_LoaderHeap GetHighFrequencyHeap();
284 PTR_LoaderHeap GetStubHeap();
286 PTR_Module GetManifestModule()
288 LIMITED_METHOD_CONTRACT;
293 PTR_PEAssembly GetManifestFile()
295 LIMITED_METHOD_CONTRACT;
297 return m_pManifestFile;
300 IMDInternalImport* GetManifestImport()
304 return m_pManifestFile->GetPersistentMDImport();
307 HRESULT GetCustomAttribute(mdToken parentToken,
308 WellKnownAttribute attribute,
314 return GetManifestModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData);
317 #ifndef DACCESS_COMPILE
318 IMetaDataAssemblyImport* GetManifestAssemblyImporter()
321 return m_pManifestFile->GetAssemblyImporter();
323 #endif // DACCESS_COMPILE
325 mdAssembly GetManifestToken()
327 LIMITED_METHOD_CONTRACT;
329 return TokenFromRid(1, mdtAssembly);
332 #ifndef DACCESS_COMPILE
333 void GetDisplayName(SString &result, DWORD flags = 0)
337 return m_pManifestFile->GetDisplayName(result, flags);
339 #endif // DACCESS_COMPILE
341 void GetCodeBase(SString &result)
345 return m_pManifestFile->GetCodeBase(result);
348 OBJECTREF GetExposedObject();
350 DebuggerAssemblyControlFlags GetDebuggerInfoBits(void)
352 LIMITED_METHOD_CONTRACT;
354 return m_debuggerFlags;
357 void SetDebuggerInfoBits(DebuggerAssemblyControlFlags flags)
359 LIMITED_METHOD_CONTRACT;
361 m_debuggerFlags = flags;
366 LIMITED_METHOD_CONTRACT;
368 m_debuggerFlags = (DebuggerAssemblyControlFlags) (m_debuggerFlags | DACF_PDBS_COPIED);
373 return GetManifestFile()->HashIdentity();
376 BOOL IsDisabledPrivateReflection();
378 //****************************************************************************************
380 // Uses the given token to load a module or another assembly. Returns the module in
381 // which the implementation resides.
383 mdFile GetManifestFileToken(IMDInternalImport *pImport, mdFile kFile);
384 mdFile GetManifestFileToken(LPCSTR name);
387 // if loadFlag == Loader::Load => throw
388 // if loadFlag != Loader::Load => return NULL
389 Module *FindModuleByExportedType(mdExportedType mdType,
390 Loader::LoadFlag loadFlag,
394 static Module * FindModuleByTypeRef(Module * pModule,
396 Loader::LoadFlag loadFlag,
397 BOOL * pfNoResolutionScope);
399 Module *FindModuleByName(LPCSTR moduleName);
401 //****************************************************************************************
403 INT32 ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads);
405 //****************************************************************************************
409 #ifdef FEATURE_PREJIT
410 void DeleteNativeCodeRanges();
413 BOOL GetResource(LPCSTR szName, DWORD *cbResource,
414 PBYTE *pbInMemoryResource, Assembly **pAssemblyRef,
415 LPCSTR *szFileName, DWORD *dwLocation,
416 BOOL fSkipRaiseResolveEvent = FALSE);
418 //****************************************************************************************
419 #ifdef DACCESS_COMPILE
420 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
423 FORCEINLINE BOOL IsDynamic() { LIMITED_METHOD_CONTRACT; return m_isDynamic; }
424 FORCEINLINE BOOL IsCollectible() { LIMITED_METHOD_DAC_CONTRACT; return m_isCollectible; }
426 DWORD GetNextModuleIndex() { LIMITED_METHOD_CONTRACT; return m_nextAvailableModuleIndex++; }
428 void AddType(Module* pModule,
430 void AddExportedType(mdExportedType cl);
431 mdAssemblyRef AddAssemblyRef(Assembly *refedAssembly, IMetaDataAssemblyEmit *pAssemEmitter = NULL, BOOL fUsePublicKeyToken = TRUE);
433 //****************************************************************************************
435 DomainAssembly *GetDomainAssembly();
436 void SetDomainAssembly(DomainAssembly *pAssembly);
438 #if defined(FEATURE_COLLECTIBLE_TYPES) && !defined(DACCESS_COMPILE)
439 OBJECTHANDLE GetLoaderAllocatorObjectHandle() { WRAPPER_NO_CONTRACT; return GetLoaderAllocator()->GetLoaderAllocatorObjectHandle(); }
440 #endif // FEATURE_COLLECTIBLE_TYPES
442 BOOL IsSIMDVectorAssembly() { LIMITED_METHOD_DAC_CONTRACT; return m_fIsSIMDVectorAssembly; }
444 #if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN)
445 BOOL IsInstrumented();
446 BOOL IsInstrumentedHelper();
447 #endif // FEATURE_PREJIT
449 #ifdef FEATURE_COMINTEROP
450 static ITypeLib * const InvalidTypeLib;
452 // Get any cached ITypeLib* for the assembly.
453 ITypeLib *GetTypeLib();
455 // Try to set the ITypeLib*, if one is not already cached.
456 bool TrySetTypeLib(_In_ ITypeLib *pTlb);
457 #endif // FEATURE_COMINTEROP
459 #ifndef DACCESS_COMPILE
461 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszFullName, UINT resIDWhy);
463 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszNameSpace, LPCUTF8 pTypeName,
466 void DECLSPEC_NORETURN ThrowTypeLoadException(NameHandle *pName, UINT resIDWhy);
468 void DECLSPEC_NORETURN ThrowTypeLoadException(IMDInternalImport *pInternalImport,
472 void DECLSPEC_NORETURN ThrowTypeLoadException(IMDInternalImport *pInternalImport,
474 LPCUTF8 pszFieldOrMethodName,
477 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszNameSpace,
479 LPCUTF8 pszMethodName,
482 void DECLSPEC_NORETURN ThrowBadImageException(LPCUTF8 pszNameSpace,
486 #endif // #ifndef DACCESS_COMPILE
488 //****************************************************************************************
491 static BOOL FileNotFound(HRESULT hr);
493 //****************************************************************************************
494 // Is the given assembly a friend of this assembly?
495 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, FieldDesc *pFD);
496 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, MethodDesc *pMD);
497 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, MethodTable *pMT);
498 bool IgnoresAccessChecksTo(Assembly *pAccessedAssembly);
500 #ifdef FEATURE_COMINTEROP
501 bool IsImportedFromTypeLib()
504 return ((GetInteropAttributeMask() & INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB) != 0);
507 bool IsPIAOrImportedFromTypeLib()
510 return ((GetInteropAttributeMask() & (INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB | INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY)) != 0);
516 return ((GetInteropAttributeMask() & INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY) != 0);
519 // Does this assembly contain windows metadata
522 // Does this assembly contain windows metadata with managed implementation
523 bool IsManagedWinMD();
525 // Returns the IWinMDImport interface of the manifest module metadata or NULL if this assembly is not a .winmd
526 IWinMDImport *GetManifestWinMDImport();
531 #ifdef FEATURE_COMINTEROP
535 WinMDStatus_IsPureWinMD,
536 WinMDStatus_IsManagedWinMD,
537 WinMDStatus_IsNotWinMD
540 // Determine if the assembly is a pure Windows Metadata file, contians managed implementation, or is not
541 // Windows Metadata at all.
542 WinMDStatus GetWinMDStatus();
544 enum InteropAttributeStatus {
545 INTEROP_ATTRIBUTE_UNSET = 0,
546 INTEROP_ATTRIBUTE_CACHED = 1,
547 INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB = 2,
548 INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY = 4,
551 InteropAttributeStatus GetInteropAttributeMask()
553 LIMITED_METHOD_CONTRACT;
555 if (m_InteropAttributeStatus & INTEROP_ATTRIBUTE_CACHED)
556 return m_InteropAttributeStatus;
558 int mask = INTEROP_ATTRIBUTE_UNSET;
560 if (!IsWinMD()) // ignore classic COM interop CAs in .winmd
562 if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::ImportedFromTypeLib, NULL, 0) == S_OK)
563 mask |= INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB;
564 if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::PrimaryInteropAssembly, NULL, 0) == S_OK)
565 mask |= INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY;
570 mask |= INTEROP_ATTRIBUTE_CACHED;
571 m_InteropAttributeStatus = static_cast<InteropAttributeStatus>(mask);
574 return static_cast<InteropAttributeStatus>(mask);
576 #endif // FEATURE_INTEROP
580 //****************************************************************************************
582 void CacheManifestExportedTypes(AllocMemTracker *pamTracker);
583 void CacheManifestFiles();
585 void CacheFriendAssemblyInfo();
588 PTR_BaseDomain m_pDomain; // Parent Domain
589 PTR_ClassLoader m_pClassLoader; // Single Loader
593 PTR_MethodDesc m_pEntryPoint; // Method containing the entry point
594 PTR_Module m_pManifest;
595 PTR_PEAssembly m_pManifestFile;
597 FriendAssemblyDescriptor *m_pFriendAssemblyDescriptor;
600 #ifdef FEATURE_COLLECTIBLE_TYPES
601 BOOL m_isCollectible;
602 #endif // FEATURE_COLLECTIBLE_TYPES
603 DWORD m_nextAvailableModuleIndex;
604 PTR_LoaderAllocator m_pLoaderAllocator;
605 DWORD m_isDisabledPrivateReflection;
607 #ifdef FEATURE_COMINTEROP
608 // If a TypeLib is ever required for this module, cache the pointer here.
609 ITypeLib *m_pITypeLib;
610 InteropAttributeStatus m_InteropAttributeStatus;
612 WinMDStatus m_winMDStatus;
613 IWinMDImport *m_pManifestWinMDImport;
614 #endif // FEATURE_COMINTEROP
616 DebuggerAssemblyControlFlags m_debuggerFlags;
620 BOOL m_fIsSIMDVectorAssembly;
622 #if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN)
623 enum IsInstrumentedStatus {
624 IS_INSTRUMENTED_UNSET = 0,
625 IS_INSTRUMENTED_FALSE = 1,
626 IS_INSTRUMENTED_TRUE = 2,
628 IsInstrumentedStatus m_isInstrumentedStatus;
629 #endif // FEATURE_PREJIT
633 typedef Assembly::ModuleIterator ModuleIterator;
635 #ifndef DACCESS_COMPILE
637 //---------------------------------------------------------------------------------------
639 // FriendSecurityDescriptor contains information on which assemblies are friends of an assembly, as well as
640 // which individual internals are visible to those friend assemblies.
643 class FriendAssemblyDescriptor
646 ~FriendAssemblyDescriptor();
649 FriendAssemblyDescriptor *CreateFriendAssemblyDescriptor(PEAssembly *pAssembly);
651 //---------------------------------------------------------------------------------------
653 // Checks to see if an assembly has friend access to a particular member.
656 // pAccessingAssembly - the assembly requesting friend access
657 // pMember - the member that is attempting to be accessed
660 // true if friend access is allowed, false otherwise
663 // Template type T should be either FieldDesc, MethodDesc, or MethodTable.
667 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, T *pMember)
673 PRECONDITION(CheckPointer(pAccessingAssembly));
674 PRECONDITION(CheckPointer(pMember));
678 return IsAssemblyOnList(pAccessingAssembly, m_alFullAccessFriendAssemblies);
682 bool IgnoresAccessChecksTo(Assembly *pAccessedAssembly)
684 return IsAssemblyOnList(pAccessedAssembly, m_subjectAssemblies);
688 typedef AssemblySpec FriendAssemblyName_t;
689 typedef NewHolder<AssemblySpec> FriendAssemblyNameHolder;
691 ArrayList m_alFullAccessFriendAssemblies; // Friend assemblies which have access to all internals
692 ArrayList m_subjectAssemblies; // Subject assemblies which we will not perform access checks against
694 FriendAssemblyDescriptor();
696 void AddFriendAssembly(FriendAssemblyName_t *pFriendAssembly);
697 void AddSubjectAssembly(FriendAssemblyName_t *pSubjectAssembly);
700 bool IsAssemblyOnList(Assembly *pAssembly, const ArrayList &alAssemblyNames)
702 return IsAssemblyOnList(pAssembly->GetManifestFile(), alAssemblyNames);
706 bool IsAssemblyOnList(PEAssembly *pAssembly, const ArrayList &alAssemblyNames);
709 #endif // !DACCESS_COMPILE