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.
4 // --------------------------------------------------------------------------------
8 // --------------------------------------------------------------------------------
13 #include "strongname.h"
15 #include "eecontract.h"
16 #include "apithreadstress.h"
19 #include "fusionpriv.h"
22 #include "product_version.h"
23 #include "eventtrace.h"
26 #include "dbginterface.h"
27 #include "peimagelayout.inl"
29 #include "invokeutil.h"
33 #include "strongnameinternal.h"
35 #ifdef FEATURE_VERSIONING
36 #include "../binder/inc/applicationcontext.hpp"
39 #ifndef FEATURE_FUSION
40 #include "clrprivbinderutil.h"
41 #include "../binder/inc/coreclrbindercommon.h"
44 #ifdef FEATURE_CAS_POLICY
51 #ifdef DEBUGGING_SUPPORTED
52 SVAL_IMPL_INIT(DWORD, PEFile, s_NGENDebugFlags, 0);
58 #if defined(FEATURE_FUSION)
59 #include "clrprivbinderfusion.h"
60 #include "clrprivbinderappx.h"
61 #include "clrprivbinderloadfile.h"
64 #ifndef DACCESS_COMPILE
66 // ================================================================================
67 // PEFile class - this is an abstract base class for PEModule and PEAssembly
68 // <TODO>@todo: rename TargetFile</TODO>
69 // ================================================================================
71 PEFile::PEFile(PEImage *identity, BOOL fCheckAuthenticodeSignature/*=TRUE*/) :
76 m_openedILimage(NULL),
79 m_fCanUseNativeImage(TRUE),
81 m_MDImportIsRW_Debugger_Use_Only(FALSE),
82 m_bHasPersistentMDImport(FALSE),
86 m_pMetadataLock(::new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)),
90 m_fStrongNameVerified(FALSE)
91 #ifdef FEATURE_CAS_POLICY
93 m_fCheckedCertificate(FALSE)
94 ,m_pSecurityManager(NULL)
95 ,m_securityManagerLock(CrstPEFileSecurityManager)
96 #endif // FEATURE_CAS_POLICY
97 ,m_pHostAssembly(nullptr)
98 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
99 ,m_pFallbackLoadContextBinder(nullptr)
100 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
114 m_identity = identity;
116 if(identity->IsOpened())
118 //already opened, prepopulate
120 m_openedILimage = identity;
125 #ifdef FEATURE_CAS_POLICY
126 if (fCheckAuthenticodeSignature)
128 CheckAuthenticodeSignature();
130 #endif // FEATURE_CAS_POLICY
146 ReleaseMetadataInterfaces(TRUE);
151 #ifdef FEATURE_PREJIT
152 if (m_nativeImage != NULL)
154 MarkNativeImageInvalidIfOwned();
156 m_nativeImage->Release();
158 #endif //FEATURE_PREJIT
161 if (m_openedILimage != NULL)
162 m_openedILimage->Release();
163 if (m_identity != NULL)
164 m_identity->Release();
166 delete m_pMetadataLock;
167 #ifdef FEATURE_CAS_POLICY
168 if (m_pSecurityManager) {
169 m_pSecurityManager->Release();
170 m_pSecurityManager = NULL;
172 if (m_certificate && !g_pCertificateCache->Contains(m_certificate))
173 CoTaskMemFree(m_certificate);
174 #endif // FEATURE_CAS_POLICY
176 if (m_pHostAssembly != NULL)
178 m_pHostAssembly->Release();
182 #ifndef DACCESS_COMPILE
183 void PEFile::ReleaseIL()
186 if (m_openedILimage!=NULL )
188 ReleaseMetadataInterfaces(TRUE, TRUE);
189 if (m_identity != NULL)
191 m_identity->Release();
194 m_openedILimage->Release();
195 m_openedILimage = NULL;
201 PEFile *PEFile::Open(PEImage *image)
205 PRECONDITION(image != NULL);
206 PRECONDITION(image->CheckFormat());
207 POSTCONDITION(RETVAL != NULL);
208 POSTCONDITION(!RETVAL->IsModule());
209 POSTCONDITION(!RETVAL->IsAssembly());
213 INJECT_FAULT(COMPlusThrowOM(););
217 PEFile *pFile = new PEFile(image, FALSE);
219 if (image->HasNTHeaders() && image->HasCorHeader())
220 pFile->OpenMDImport_Unsafe(); //no one else can see the object yet
223 pFile->m_debugName = image->GetPath();
224 pFile->m_debugName.Normalize();
225 pFile->m_pDebugName = pFile->m_debugName;
231 // ------------------------------------------------------------
232 // Loader support routines
233 // ------------------------------------------------------------
235 template<class T> void CoTaskFree(T *p)
246 NEW_WRAPPER_TEMPLATE1(CoTaskNewHolder, CoTaskFree<_TYPE>);
248 BOOL PEFile::CanLoadLibrary()
252 // Dynamic and resource modules don't need LoadLibrary.
253 if (IsDynamic() || IsResource()||IsLoaded())
256 // If we're been granted skip verification, OK
257 if (HasSkipVerification())
260 // Otherwise, we can only load if IL only.
264 #ifdef FEATURE_MIXEDMODE
266 #ifndef CROSSGEN_COMPILE
268 // Returns TRUE if this file references managed CRT (msvcmNN*).
269 BOOL PEFile::ReferencesManagedCRT()
271 STANDARD_VM_CONTRACT;
273 IMDInternalImportHolder pImport = GetMDImport();
274 MDEnumHolder hEnum(pImport);
276 IfFailThrow(pImport->EnumInit(mdtModuleRef, mdTokenNil, &hEnum));
279 while (pImport->EnumNext(&hEnum, &tk))
281 // we are looking for "msvcmNN*"
283 IfFailThrow(pImport->GetModuleRefProps(tk, &szName));
285 if (_strnicmp(szName, "msvcm", 5) == 0 && isdigit(szName[5]) && isdigit(szName[6]))
294 void PEFile::CheckForDisallowedInProcSxSLoadWorker()
296 STANDARD_VM_CONTRACT;
298 // provide an opt-out switch for now
299 if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DisableIJWVersionCheck) != 0)
302 // ************************************************************************************************
303 // 1. See if this file should be checked
304 // The following checks filter out non-mixed mode assemblies that don't reference msvcmNN*. We only
305 // care about non-ILONLY images (IJW) or 2.0 C++/CLI pure images.
306 if (IsResource() || IsDynamic())
309 // check the metadata version string
311 PVOID pMetaData = (PVOID)GetMetadata(&size);
314 // No metadata section? Well somebody should have caught this earlier so report as
315 // ExecutionEngine rather than BIF.
316 EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
319 LPCSTR pVersion = NULL;
320 IfFailThrow(GetImageRuntimeVersionString(pMetaData, &pVersion));
323 unsigned uiMajor, uiMinor;
324 BOOL fLegacyImage = (sscanf_s(pVersion, "%c%u.%u", &chV, 1, &uiMajor, &uiMinor) == 3 && (chV == W('v') || chV == W('V')) && uiMajor <= 2);
326 // Note that having VTFixups properly working really is limited to non-ILONLY images. In particular,
327 // the shim does not even attempt to patch ILONLY images in any way with bootstrap thunks.
330 // all >2.0 ILONLY images are fine because >2.0 managed CRTs can be loaded in multiple runtimes
334 // legacy ILONLY images that don't reference the managed CRT are fine
335 if (!ReferencesManagedCRT())
339 // get the version of this runtime
340 WCHAR wzThisRuntimeVersion[_MAX_PATH];
341 DWORD cchVersion = COUNTOF(wzThisRuntimeVersion);
342 IfFailThrow(g_pCLRRuntime->GetVersionString(wzThisRuntimeVersion, &cchVersion));
344 // ************************************************************************************************
345 // 2. For legacy assemblies, verify that legacy APIs are/would be bound to this runtime
348 WCHAR wzAPIVersion[_MAX_PATH];
349 bool fLegacyAPIsAreBound = false;
351 { // Check if the legacy APIs have already been bound to us using the new hosting APIs.
352 ReleaseHolder<ICLRMetaHost> pMetaHost;
353 IfFailThrow(CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost));
355 ReleaseHolder<ICLRRuntimeInfo> pInfo;
356 // Returns S_FALSE when no runtime is currently bound, S_OK when one is.
357 HRESULT hr = pMetaHost->QueryLegacyV2RuntimeBinding(IID_ICLRRuntimeInfo, (LPVOID*)&pInfo);
361 { // Legacy APIs are bound, now check if they are bound to us.
362 fLegacyAPIsAreBound = true;
364 cchVersion = COUNTOF(wzAPIVersion);
365 IfFailThrow(pInfo->GetVersionString(wzAPIVersion, &cchVersion));
367 if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
368 { // This runtime is the one bound to the legacy APIs, ok to load legacy assembly.
375 #pragma warning(push)
376 #pragma warning(disable : 4996) // we are going to call deprecated APIs
378 // We need the above QueryLegacyV2RuntimeBinding check because GetRequestedRuntimeInfo will not take into
379 // account the current binding, which could have been set by the host rather than through an EXE config.
380 // If, however, the legacy APIs are not bound (indicated in fLegacyAPIsAreBound) then we can assume that
381 // the legacy APIs would bind using the equivalent of CorBindToRuntime(NULL) as a result of loading this
382 // legacy IJW assembly, and so we use GetRequestedRuntimeInfo to check without actually causing the bind.
383 // By avoiding causing the bind, we avoid a binding side effect in the failure case.
384 if (!fLegacyAPIsAreBound &&
385 SUCCEEDED(GetRequestedRuntimeInfo(NULL, NULL, NULL, 0, // pExe, pwszVersion, pConfigurationFile, startupFlags
386 RUNTIME_INFO_UPGRADE_VERSION | RUNTIME_INFO_DONT_RETURN_DIRECTORY | RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG,
387 NULL, 0, NULL, // pDirectory, dwDirectory, pdwDirectoryLength
388 wzAPIVersion, COUNTOF(wzAPIVersion), &cchVersion))) // pVersion, cchBuffer, pdwLength
390 if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
392 // it came back as this version - call CorBindToRuntime to actually bind it
393 ReleaseHolder<ICLRRuntimeHost> pHost;
394 IfFailThrow(CorBindToRuntime(wzAPIVersion, NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pHost));
396 // and verify that nobody beat us to it
397 IfFailThrow(GetCORVersion(wzAPIVersion, COUNTOF(wzAPIVersion), &cchVersion));
399 if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
401 // we have verified that when the assembly calls CorBindToRuntime(NULL),
402 // it will get this runtime, so we allow it to be loaded
411 MAKE_WIDEPTR_FROMUTF8(pwzVersion, pVersion);
413 ExternalLog(LF_LOADER, LL_ERROR, W("ERR: Rejecting IJW module built against %s because it could be loaded into another runtime in this process."), pwzVersion);
414 COMPlusThrow(kFileLoadException, IDS_EE_IJWLOAD_CROSSVERSION_DISALLOWED, pwzVersion, QUOTE_MACRO_L(VER_MAJORVERSION.VER_MINORVERSION));
417 // ************************************************************************************************
418 // 3. For 4.0+ assemblies, verify that it hasn't been loaded into another runtime
419 ReleaseHolder<ICLRRuntimeHostInternal> pRuntimeHostInternal;
420 IfFailThrow(g_pCLRRuntime->GetInterface(CLSID_CLRRuntimeHostInternal,
421 IID_ICLRRuntimeHostInternal,
422 &pRuntimeHostInternal));
424 PTR_VOID pModuleBase = GetLoadedIL()->GetBase();
426 ReleaseHolder<ICLRRuntimeInfo> pRuntimeInfo;
427 HRESULT hr = pRuntimeHostInternal->LockModuleForRuntime((BYTE *)pModuleBase, IID_ICLRRuntimeInfo, &pRuntimeInfo);
433 // this runtime was the first one to lock the module
437 // another runtime has loaded this module so we have to block the load
438 WCHAR wzLoadedRuntimeVersion[_MAX_PATH];
439 cchVersion = COUNTOF(wzLoadedRuntimeVersion);
440 IfFailThrow(pRuntimeInfo->GetVersionString(wzLoadedRuntimeVersion, &cchVersion));
442 ExternalLog(LF_LOADER, LL_ERROR, W("ERR: Rejecting IJW module because it is already loaded into runtime version %s in this process."), wzLoadedRuntimeVersion);
443 COMPlusThrow(kFileLoadException, IDS_EE_IJWLOAD_MULTIRUNTIME_DISALLOWED, wzThisRuntimeVersion, wzLoadedRuntimeVersion);
446 // We don't allow loading IJW and C++/CLI pure images built against <=2.0 if legacy APIs are not bound to this
447 // runtime. For IJW images built against >2.0, we don't allow the load if the image has already been loaded by
448 // another runtime in this process.
449 void PEFile::CheckForDisallowedInProcSxSLoad()
451 STANDARD_VM_CONTRACT;
453 // have we checked this one before?
454 if (!IsInProcSxSLoadVerified())
456 CheckForDisallowedInProcSxSLoadWorker();
458 // if no exception was thrown, remember the fact that we don't have to do the check again
459 SetInProcSxSLoadVerified();
463 #else // CROSSGEN_COMPILE
465 void PEFile::CheckForDisallowedInProcSxSLoad()
470 #endif // CROSSGEN_COMPILE
472 #endif // FEATURE_MIXEDMODE
475 //-----------------------------------------------------------------------------------------------------
476 // Catch attempts to load x64 assemblies on x86, etc.
477 //-----------------------------------------------------------------------------------------------------
478 static void ValidatePEFileMachineType(PEFile *peFile)
480 STANDARD_VM_CONTRACT;
482 if (peFile->IsIntrospectionOnly())
483 return; // ReflectionOnly assemblies permitted to violate CPU restrictions
485 if (peFile->IsDynamic())
486 return; // PEFiles for ReflectionEmit assemblies don't cache the machine type.
488 if (peFile->IsResource())
489 return; // PEFiles for resource assemblies don't cache the machine type.
491 if (peFile->HasNativeImage())
492 return; // If it passed the native binder, no need to do the check again esp. at the risk of inviting an IL page-in.
495 DWORD actualMachineType;
496 peFile->GetPEKindAndMachine(&peKind, &actualMachineType);
498 if (actualMachineType == IMAGE_FILE_MACHINE_I386 && ((peKind & (peILonly | pe32BitRequired)) == peILonly))
499 return; // Image is marked CPU-agnostic.
501 if (actualMachineType != IMAGE_FILE_MACHINE_NATIVE && actualMachineType != IMAGE_FILE_MACHINE_NATIVE_NI)
503 #ifdef _TARGET_AMD64_
504 // v4.0 64-bit compatibility workaround. The 64-bit v4.0 CLR's Reflection.Load(byte[]) api does not detect cpu-matches. We should consider fixing that in
505 // the next SxS release. In the meantime, this bypass will retain compat for 64-bit v4.0 CLR for target platforms that existed at the time.
507 // Though this bypass kicks in for all Load() flavors, the other Load() flavors did detect cpu-matches through various other code paths that still exist.
508 // Or to put it another way, this #ifdef makes the (4.5 only) ValidatePEFileMachineType() a NOP for x64, hence preserving 4.0 compatibility.
509 if (actualMachineType == IMAGE_FILE_MACHINE_I386 || actualMachineType == IMAGE_FILE_MACHINE_IA64)
513 // Image has required machine that doesn't match the CLR.
515 if (peFile->IsAssembly())
516 ((PEAssembly*)peFile)->GetDisplayName(name);
518 name = StackSString(SString::Utf8, peFile->GetSimpleName());
520 COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode());
523 return; // If we got here, all is good.
526 void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load
531 POSTCONDITION(CheckLoaded());
536 // Catch attempts to load x64 assemblies on x86, etc.
537 ValidatePEFileMachineType(this);
539 // See if we've already loaded it.
540 if (CheckLoaded(allowNativeSkip))
542 #ifdef FEATURE_MIXEDMODE
543 // Prevent loading C++/CLI images into multiple runtimes in the same process. Note that if ILOnly images
544 // stop being LoadLibrary'ed, the check for pure 2.0 C++/CLI images will need to be done somewhere else.
545 if (!IsIntrospectionOnly())
546 CheckForDisallowedInProcSxSLoad();
547 #endif // FEATURE_MIXEDMODE
551 // Note that we may be racing other threads here, in the case of domain neutral files
553 // Resource images are always flat.
556 GetILimage()->LoadNoMetaData(IsIntrospectionOnly());
561 if (!HasNativeImage() && (!GetILimage()->Has32BitNTHeaders()) && !IsIntrospectionOnly())
563 // Tried to load 64-bit assembly on 32-bit platform.
564 EEFileLoadException::Throw(this, COR_E_BADIMAGEFORMAT, NULL);
568 // Don't do this if we are unverifiable
569 if (!CanLoadLibrary())
570 ThrowHR(SECURITY_E_UNVERIFIABLE);
573 // We need contents now
574 if (!HasNativeImage())
579 if (IsIntrospectionOnly())
581 GetILimage()->LoadForIntrospection();
586 //---- Below this point, only do the things necessary for execution ----
587 _ASSERTE(!IsIntrospectionOnly());
589 #ifdef FEATURE_PREJIT
590 // For on-disk Dlls, we can call LoadLibrary
591 if (IsDll() && !((HasNativeImage()?m_nativeImage:GetILimage())->GetPath().IsEmpty()))
593 // Note that we may get a DllMain notification inside here.
594 if (allowNativeSkip && HasNativeImage())
596 m_nativeImage->Load();
597 if(!m_nativeImage->IsNativeILILOnly())
598 GetILimage()->Load(); // For IJW we have to load IL also...
601 GetILimage()->Load();
604 #endif // FEATURE_PREJIT
607 // Since we couldn't call LoadLibrary, we must be an IL only image
608 // or the image may still contain unfixed up stuff
609 // Note that we make an exception for CompilationDomains, since PEImage
610 // will map non-ILOnly images in a compilation domain.
611 if (!GetILimage()->IsILOnly() && !GetAppDomain()->IsCompilationDomain())
613 if (!GetILimage()->HasV1Metadata())
614 ThrowHR(COR_E_FIXUPSINEXE); // <TODO>@todo: better error</TODO>
619 // If we are already mapped, we can just use the current image.
620 #ifdef FEATURE_PREJIT
621 if (allowNativeSkip && HasNativeImage())
623 m_nativeImage->LoadFromMapped();
625 if( !m_nativeImage->IsNativeILILOnly())
626 GetILimage()->LoadFromMapped(); // For IJW we have to load IL also...
631 if (GetILimage()->IsFile())
632 GetILimage()->LoadFromMapped();
634 GetILimage()->LoadNoFile();
638 #ifdef FEATURE_MIXEDMODE
639 // Prevent loading C++/CLI images into multiple runtimes in the same process. Note that if ILOnly images
640 // stop being LoadLibrary'ed, the check for pure 2.0 C++/CLI images will need to be done somewhere else.
641 CheckForDisallowedInProcSxSLoad();
642 #endif // FEATURE_MIXEDMODE
647 void PEFile::SetLoadedHMODULE(HMODULE hMod)
652 PRECONDITION(CheckPointer(hMod));
653 PRECONDITION(CanLoadLibrary());
654 POSTCONDITION(CheckLoaded());
658 INJECT_FAULT(COMPlusThrowOM(););
662 // See if the image is an internal PEImage.
663 GetILimage()->SetLoadedHMODULE(hMod);
669 void PEFile::DefineEmitScope(
675 PRECONDITION(CheckPointer(ppEmit));
676 POSTCONDITION(CheckPointer(*ppEmit));
680 INJECT_FAULT(COMPlusThrowOM(););
684 SafeComHolder<IMetaDataDispenserEx> pDispenser;
686 // Get the Dispenser interface.
687 MetaDataGetDispenser(
688 CLSID_CorMetaDataDispenser,
689 IID_IMetaDataDispenserEx,
690 (void **)&pDispenser);
691 if (pDispenser == NULL)
696 // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef
698 V_VT(&varOption) = VT_UI4;
699 V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile;
700 IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption));
702 // Set minimal MetaData size
703 V_VT(&varOption) = VT_UI4;
704 V_I4(&varOption) = MDInitialSizeMinimal;
705 IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption));
707 // turn on the thread safety!
708 V_I4(&varOption) = MDThreadSafetyOn;
709 IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption));
711 IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown **)ppEmit));
714 } // PEFile::DefineEmitScope
716 // ------------------------------------------------------------
718 // ------------------------------------------------------------
720 BOOL PEFile::Equals(PEFile *pFile)
725 PRECONDITION(CheckPointer(pFile));
733 // Same object is equal
738 // Execution and introspection files are NOT equal
739 if ( (!IsIntrospectionOnly()) != !(pFile->IsIntrospectionOnly()) )
744 // Different host assemblies cannot be equal unless they are associated with the same host binder
745 // It's ok if only one has a host binder because multiple threads can race to load the same assembly
746 // and that may cause temporary candidate PEAssembly objects that never get bound to a host assembly
747 // because another thread beats it; the losing thread will pick up the PEAssembly in the cache.
748 if (pFile->HasHostAssembly() && this->HasHostAssembly())
750 UINT_PTR fileBinderId = 0;
751 if (FAILED(pFile->GetHostAssembly()->GetBinderID(&fileBinderId)))
754 UINT_PTR thisBinderId = 0;
755 if (FAILED(this->GetHostAssembly()->GetBinderID(&thisBinderId)))
758 if (fileBinderId != thisBinderId)
763 // Same identity is equal
764 if (m_identity != NULL && pFile->m_identity != NULL
765 && m_identity->Equals(pFile->m_identity))
768 // Same image is equal
769 if (m_openedILimage != NULL && pFile->m_openedILimage != NULL
770 && m_openedILimage->Equals(pFile->m_openedILimage))
776 BOOL PEFile::Equals(PEImage *pImage)
781 PRECONDITION(CheckPointer(pImage));
788 // Same object is equal
789 if (pImage == m_identity || pImage == m_openedILimage)
792 #ifdef FEATURE_PREJIT
793 if(pImage == m_nativeImage)
796 // Same identity is equal
797 if (m_identity != NULL
798 && m_identity->Equals(pImage))
801 // Same image is equal
802 if (m_openedILimage != NULL
803 && m_openedILimage->Equals(pImage))
810 // ------------------------------------------------------------
811 // Descriptive strings
812 // ------------------------------------------------------------
814 void PEFile::GetCodeBaseOrName(SString &result)
822 INJECT_FAULT(COMPlusThrowOM(););
826 if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
828 result.Set(m_identity->GetPath());
830 else if (IsAssembly())
832 ((PEAssembly*)this)->GetCodeBase(result);
835 result.SetUTF8(GetSimpleName());
838 #ifdef FEATURE_CAS_POLICY
840 // Returns security information for the assembly based on the codebase
841 void PEFile::GetSecurityIdentity(SString &codebase, SecZone *pdwZone, DWORD dwFlags, BYTE *pbUniqueID, DWORD *pcbUniqueID)
848 PRECONDITION(CheckPointer(pdwZone));
849 PRECONDITION(CheckPointer(pbUniqueID));
850 PRECONDITION(CheckPointer(pcbUniqueID));
856 ((PEAssembly*)this)->GetCodeBase(codebase);
858 else if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
860 codebase.Set(W("file:///"));
861 codebase.Append(m_identity->GetPath());
865 _ASSERTE( !"Unable to determine security identity" );
870 if(!codebase.IsEmpty())
874 InitializeSecurityManager();
876 // We have a class name, return a class factory for it
877 _ASSERTE(sizeof(SecZone) == sizeof(DWORD));
878 IfFailThrow(m_pSecurityManager->MapUrlToZone(codebase,
879 reinterpret_cast<DWORD *>(pdwZone),
882 if (*pdwZone>=NumZones)
883 IfFailThrow(SecurityPolicy::ApplyCustomZoneOverride(pdwZone));
885 IfFailThrow(m_pSecurityManager->GetSecurityId(codebase,
892 void PEFile::InitializeSecurityManager()
900 INJECT_FAULT(COMPlusThrowOM(););
905 if(m_pSecurityManager == NULL)
907 CrstHolder holder(&m_securityManagerLock);
908 if (m_pSecurityManager == NULL)
910 IfFailThrow(CoInternetCreateSecurityManager(NULL,
917 #endif // FEATURE_CAS_POLICY
919 // ------------------------------------------------------------
921 // ------------------------------------------------------------
925 CHECK PEFile::CheckLoaded(BOOL bAllowNativeSkip/*=TRUE*/)
937 CHECK(IsLoaded(bAllowNativeSkip)
938 // We are allowed to skip LoadLibrary in most cases for ngen'ed IL only images
939 || (bAllowNativeSkip && HasNativeImage() && IsILOnly()));
945 // ------------------------------------------------------------
947 // ------------------------------------------------------------
949 PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize)
954 POSTCONDITION(CheckPointer(pSize, NULL_OK));
955 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
963 #ifdef FEATURE_PREJIT
964 if (HasNativeImageMetadata())
966 RETURN m_nativeImage->GetMetadata(pSize);
971 || !GetILimage()->HasNTHeaders()
972 || !GetILimage()->HasCorHeader())
980 RETURN GetILimage()->GetMetadata(pSize);
983 #endif // #ifndef DACCESS_COMPILE
985 PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize)
990 POSTCONDITION(CheckPointer(pSize, NULL_OK));
991 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
999 #ifdef FEATURE_PREJIT
1000 if (HasNativeImageMetadata())
1002 RETURN GetLoadedNative()->GetMetadata(pSize);
1007 || !GetLoadedIL()->HasNTHeaders()
1008 || !GetLoadedIL()->HasCorHeader())
1016 RETURN GetLoadedIL()->GetMetadata(pSize);
1020 TADDR PEFile::GetIL(RVA il)
1025 PRECONDITION(il != 0);
1026 PRECONDITION(!IsDynamic());
1027 PRECONDITION(!IsResource());
1028 #ifndef DACCESS_COMPILE
1029 PRECONDITION(CheckLoaded());
1031 POSTCONDITION(RETVAL != NULL);
1039 PEImageLayout *image = NULL;
1041 #ifdef FEATURE_PREJIT
1042 // Note it is important to get the IL from the native image if
1043 // available, since we are using the metadata from the native image
1044 // which has different IL rva's.
1045 if (HasNativeImageMetadata())
1047 image = GetLoadedNative();
1049 #ifndef DACCESS_COMPILE
1050 // NGen images are trusted to be well-formed.
1051 _ASSERTE(image->CheckILMethod(il));
1055 #endif // FEATURE_PREJIT
1057 image = GetLoadedIL();
1059 #ifndef DACCESS_COMPILE
1060 // Verify that the IL blob is valid before giving it out
1061 if (!image->CheckILMethod(il))
1062 COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL_RANGE);
1066 RETURN image->GetRvaData(il);
1069 #ifndef DACCESS_COMPILE
1071 void PEFile::OpenImporter()
1079 INJECT_FAULT(COMPlusThrowOM(););
1083 // Make sure internal MD is in RW format.
1084 ConvertMDInternalToReadWrite();
1086 IMetaDataImport2 *pIMDImport = NULL;
1087 IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
1088 IID_IMetaDataImport2,
1089 (void **)&pIMDImport));
1091 // Atomically swap it into the field (release it if we lose the race)
1092 if (FastInterlockCompareExchangePointer(&m_pImporter, pIMDImport, NULL) != NULL)
1093 pIMDImport->Release();
1096 void PEFile::ConvertMDInternalToReadWrite()
1104 INJECT_FAULT(EX_THROW(EEMessageException, (E_OUTOFMEMORY)););
1108 IMDInternalImport *pOld; // Old (current RO) value of internal import.
1109 IMDInternalImport *pNew = NULL; // New (RW) value of internal import.
1111 // Take a local copy of *ppImport. This may be a pointer to an RO
1112 // or to an RW MDInternalXX.
1114 IMetaDataImport *pIMDImport = m_pImporter;
1115 if (pIMDImport != NULL)
1117 HRESULT hr = GetMetaDataInternalInterfaceFromPublic(pIMDImport, IID_IMDInternalImport, (void **)&pNew);
1120 EX_THROW(EEMessageException, (hr));
1130 // If an RO, convert to an RW, return S_OK. If already RW, no conversion
1131 // needed, return S_FALSE.
1132 HRESULT hr = ConvertMDInternalImport(pOld, &pNew);
1136 EX_THROW(EEMessageException, (hr));
1139 // If no conversion took place, don't change pointers.
1144 // Swap the pointers in a thread safe manner. If the contents of *ppImport
1145 // equals pOld then no other thread got here first, and the old contents are
1146 // replaced with pNew. The old contents are returned.
1147 _ASSERTE(m_bHasPersistentMDImport);
1148 if (FastInterlockCompareExchangePointer(&m_pMDImport, pNew, pOld) == pOld)
1150 //if the debugger queries, it will now see that we have RW metadata
1151 m_MDImportIsRW_Debugger_Use_Only = TRUE;
1153 // Swapped -- get the metadata to hang onto the old Internal import.
1154 HRESULT hr=m_pMDImport->SetUserContextData(pOld);
1155 _ASSERTE(SUCCEEDED(hr)||!"Leaking old MDImport");
1159 { // Some other thread finished first. Just free the results of this conversion.
1164 void PEFile::ConvertMetadataToRWForEnC()
1175 // This should only ever be called on EnC capable files.
1176 // One can check this using Module::IsEditAndContinueCapable().
1178 // This should only be called if we're debugging, stopped, and on the helper thread.
1179 _ASSERTE(CORDebuggerAttached());
1180 _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->ThisIsHelperThread());
1181 _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->IsStopped());
1183 // Convert the metadata to RW for Edit and Continue, properly replacing the metadata import interface pointer and
1184 // properly preserving the old importer. This will be called before the EnC system tries to apply a delta to the module's
1185 // metadata. ConvertMDInternalToReadWrite() does that quite nicely for us.
1186 ConvertMDInternalToReadWrite();
1189 void PEFile::OpenMDImport_Unsafe()
1197 INJECT_FAULT(COMPlusThrowOM(););
1201 if (m_pMDImport != NULL)
1203 #ifdef FEATURE_PREJIT
1204 if (m_nativeImage != NULL
1205 && m_nativeImage->GetMDImport() != NULL
1208 // Use native image for metadata
1209 m_flags |= PEFILE_HAS_NATIVE_IMAGE_METADATA;
1210 m_pMDImport=m_nativeImage->GetMDImport();
1215 #ifdef FEATURE_PREJIT
1216 m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1219 && GetILimage()->HasNTHeaders()
1220 && GetILimage()->HasCorHeader())
1222 m_pMDImport=GetILimage()->GetMDImport();
1225 ThrowHR(COR_E_BADIMAGEFORMAT);
1227 m_bHasPersistentMDImport=TRUE;
1229 _ASSERTE(m_pMDImport);
1230 m_pMDImport->AddRef();
1233 void PEFile::OpenEmitter()
1241 INJECT_FAULT(COMPlusThrowOM(););
1245 // Make sure internal MD is in RW format.
1246 ConvertMDInternalToReadWrite();
1248 IMetaDataEmit *pIMDEmit = NULL;
1249 IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
1251 (void **)&pIMDEmit));
1253 // Atomically swap it into the field (release it if we lose the race)
1254 if (FastInterlockCompareExchangePointer(&m_pEmitter, pIMDEmit, NULL) != NULL)
1255 pIMDEmit->Release();
1259 void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor, BOOL bKeepNativeData/*=FALSE*/)
1267 PRECONDITION(bDestructor||m_pMetadataLock->IsWriterLock());
1270 _ASSERTE(bDestructor || !m_bHasPersistentMDImport);
1272 if (m_pImporter != NULL)
1274 m_pImporter->Release();
1277 if (m_pEmitter != NULL)
1279 m_pEmitter->Release();
1283 if (m_pMDImport != NULL && (!bKeepNativeData || !HasNativeImage()))
1285 m_pMDImport->Release();
1290 #ifdef FEATURE_CAS_POLICY
1292 void PEFile::CheckAuthenticodeSignature()
1300 INJECT_FAULT(COMPlusThrowOM(););
1304 // Check any security signature in the header.
1306 // This publisher data can potentially be cached and passed back in via
1307 // PEAssembly::CreateDelayed.
1309 // HOWEVER - even if we cache it, the certificate still may need to be verified at
1310 // load time. The only real caching can be done when the COR_TRUST certificate is
1313 // (In the case where it is present, we could still theoretically
1314 // cache the certificate and re-verify it and at least avoid touching the image
1315 // again, however this path is not implemented yet, so this is TBD if we decide
1316 // it is an important case to optimize for.)
1318 if (!HasSecurityDirectory())
1320 LOG((LF_SECURITY, LL_INFO1000, "No certificates found in module\n"));
1322 else if(g_pConfig->GeneratePublisherEvidence())
1324 // <TODO>@todo: Just because we don't have a file path, doesn't mean we can't have a certicate (does it?)</TODO>
1325 if (!GetPath().IsEmpty())
1329 // Ignore any errors here - if we fail to validate a certificate, we just don't
1330 // include it as evidence.
1333 CoTaskNewHolder<COR_TRUST> pCor = NULL;
1334 // Failing to find a signature is OK.
1335 LPWSTR pFileName = (LPWSTR) GetPath().GetUnicode();
1336 DWORD dwAuthFlags = COR_NOUI|COR_NOPOLICY;
1338 HRESULT hr = ::GetPublisher(pFileName,
1345 if( SUCCEEDED(hr) ) {
1347 EnumCertificateAdditionFlags dwFlags = g_pCertificateCache->AddEntry(pCor, &index);
1349 case CacheSaturated:
1350 pCor.SuppressRelease();
1351 m_certificate = pCor.GetValue();
1355 pCor.SuppressRelease();
1358 m_certificate = g_pCertificateCache->GetEntry(index);
1359 _ASSERTE(m_certificate);
1367 LOG((LF_SECURITY, LL_INFO1000, "Assembly has an Authenticode signature, but Publisher evidence has been disabled.\n"));
1370 m_fCheckedCertificate = TRUE;
1373 HRESULT STDMETHODCALLTYPE
1374 GetPublisher(__in __in_z IN LPWSTR pwsFileName, // File name, this is required even with the handle
1375 IN HANDLE hFile, // Optional file name
1376 IN DWORD dwFlags, // COR_NOUI or COR_NOPOLICY
1377 OUT PCOR_TRUST *pInfo, // Returns a PCOR_TRUST (Use FreeM)
1378 OUT DWORD *dwInfo) // Size of pInfo.
1390 GUID gV2 = COREE_POLICY_PROVIDER;
1391 COR_POLICY_PROVIDER sCorPolicy;
1394 WINTRUST_FILE_INFO sWTFI;
1396 // Set up the COR trust provider
1397 memset(&sCorPolicy, 0, sizeof(COR_POLICY_PROVIDER));
1398 sCorPolicy.cbSize = sizeof(COR_POLICY_PROVIDER);
1400 // Set up the winverify provider structures
1401 memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
1402 memset(&sWTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
1404 sWTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
1405 sWTFI.hFile = hFile;
1406 sWTFI.pcwszFilePath = pwsFileName;
1408 sWTD.cbStruct = sizeof(WINTRUST_DATA);
1409 sWTD.pPolicyCallbackData = &sCorPolicy; // Add in the cor trust information!!
1410 if (dwFlags & COR_NOUI)
1412 sWTD.dwUIChoice = WTD_UI_NONE; // No bad UI is overridden in COR TRUST provider
1416 sWTD.dwUIChoice = WTD_UI_ALL; // No bad UI is overridden in COR TRUST provider
1418 sWTD.dwUnionChoice = WTD_CHOICE_FILE;
1419 sWTD.pFile = &sWTFI;
1421 // Set the policies for the VM (we have stolen VMBased and use it like a flag)
1423 sCorPolicy.VMBased = dwFlags;
1425 LeaveRuntimeHolder holder((size_t)WinVerifyTrust);
1427 // WinVerifyTrust calls mscorsecimpl.dll to do the policy check
1428 hr = WinVerifyTrust(GetFocus(), &gV2, &sWTD);
1430 *pInfo = sCorPolicy.pbCorTrust;
1431 *dwInfo = sCorPolicy.cbCorTrust;
1436 #endif // FEATURE_CAS_POLICY
1438 // ------------------------------------------------------------
1440 // ------------------------------------------------------------
1442 // Note that most of these APIs are currently passed through
1443 // to the main image. However, in the near future they will
1444 // be rerouted to the native image in the prejitted case so
1445 // we can avoid using the original IL image.
1447 #endif //!DACCESS_COMPILE
1449 #ifdef FEATURE_PREJIT
1450 #ifndef DACCESS_COMPILE
1451 // ------------------------------------------------------------
1452 // Native image access
1453 // ------------------------------------------------------------
1455 void PEFile::SetNativeImage(PEImage *image)
1460 PRECONDITION(!HasNativeImage());
1465 _ASSERTE(image != NULL);
1466 PREFIX_ASSUME(image != NULL);
1468 if (image->GetLoadedLayout()->GetBase() != image->GetLoadedLayout()->GetPreferredBase())
1470 ExternalLog(LL_WARNING,
1471 W("Native image loaded at base address") LFMT_ADDR
1472 W("rather than preferred address:") LFMT_ADDR ,
1473 DBG_ADDR(image->GetLoadedLayout()->GetBase()),
1474 DBG_ADDR(image->GetLoadedLayout()->GetPreferredBase()));
1477 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1478 // In Apollo, first ask if we're supposed to be ignoring the prejitted code &
1479 // structures in NGENd images. If so, bail now and do not set m_nativeImage. We've
1480 // already set m_identity & m_openedILimage (possibly even pointing to the
1481 // NGEN/Triton image), and will use those PEImages to find and JIT IL (even if they
1482 // point to an NGENd/Tritonized image).
1483 if (ShouldTreatNIAsMSIL())
1487 m_nativeImage = image;
1488 m_nativeImage->AddRef();
1489 m_nativeImage->Load();
1490 m_nativeImage->AllocateLazyCOWPages();
1492 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
1493 static ConfigDWORD configNGenReserveForJumpStubs;
1494 int percentReserveForJumpStubs = configNGenReserveForJumpStubs.val(CLRConfig::INTERNAL_NGenReserveForJumpStubs);
1495 if (percentReserveForJumpStubs != 0)
1497 PEImageLayout * pLayout = image->GetLoadedLayout();
1498 ExecutionManager::GetEEJitManager()->EnsureJumpStubReserve((BYTE *)pLayout->GetBase(), pLayout->GetVirtualSize(),
1499 percentReserveForJumpStubs * (pLayout->GetVirtualSize() / 100));
1503 ExternalLog(LL_INFO100, W("Attempting to use native image %s."), image->GetPath().GetUnicode());
1507 void PEFile::ClearNativeImage()
1512 PRECONDITION(HasNativeImage());
1513 POSTCONDITION(!HasNativeImage());
1517 INJECT_FAULT(COMPlusThrowOM(););
1521 ExternalLog(LL_WARNING, "Discarding native image.");
1524 MarkNativeImageInvalidIfOwned();
1528 SafeComHolderPreemp<IMDInternalImport> pOldImport=GetMDImportWithRef();
1529 SimpleWriteLockHolder lock(m_pMetadataLock);
1533 ReleaseMetadataInterfaces(FALSE);
1534 m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1536 m_nativeImage->Release();
1537 m_nativeImage = NULL;
1538 // Make sure our normal image is open
1539 EnsureImageOpened();
1541 // Reopen metadata from normal image
1546 RestoreMDImport(pOldImport);
1555 extern DWORD g_dwLogLevel;
1557 //===========================================================================================================
1558 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1559 //===========================================================================================================
1560 static void RuntimeVerifyVLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, va_list args)
1562 STANDARD_VM_CONTRACT;
1564 BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1565 BOOL fOutputToLogging = LoggingOn(LF_ZAP, level);
1567 StackSString message;
1568 message.VPrintf(fmt, args);
1570 if (fOutputToLogging)
1572 SString displayString = pLogAsm->DisplayString();
1573 LOG((LF_ZAP, level, "%s: \"%S\"\n", "ZAP", displayString.GetUnicode()));
1574 LOG((LF_ZAP, level, "%S", message.GetUnicode()));
1575 LOG((LF_ZAP, level, "\n"));
1578 if (fOutputToDebugger)
1580 SString displayString = pLogAsm->DisplayString();
1581 WszOutputDebugString(W("CLR:("));
1582 WszOutputDebugString(displayString.GetUnicode());
1583 WszOutputDebugString(W(") "));
1584 WszOutputDebugString(message);
1585 WszOutputDebugString(W("\n"));
1588 #ifdef FEATURE_FUSION
1589 IFusionBindLog *pFusionBindLog = pLogAsm->FusionBindLog();
1592 pFusionBindLog->LogMessage(0, FUSION_BIND_LOG_CATEGORY_NGEN, message);
1594 if (level == LL_ERROR) {
1595 pFusionBindLog->SetResultCode(FUSION_BIND_LOG_CATEGORY_NGEN, E_FAIL);
1596 pFusionBindLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_NGEN);
1597 pFusionBindLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_DEFAULT);
1600 #endif //FEATURE_FUSION
1604 //===========================================================================================================
1605 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1606 //===========================================================================================================
1607 static void RuntimeVerifyLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, ...)
1609 STANDARD_VM_CONTRACT;
1611 // Avoid calling RuntimeVerifyVLog unless logging is on
1612 if ( ((level == LL_ERROR) && IsDebuggerPresent())
1613 || LoggingOn(LF_ZAP, level)
1614 #ifdef FEATURE_FUSION
1615 || (pLogAsm->FusionBindLog() != NULL)
1620 va_start(args, fmt);
1622 RuntimeVerifyVLog(level, pLogAsm, fmt, args);
1628 //==============================================================================
1630 static const LPCWSTR CorCompileRuntimeDllNames[NUM_RUNTIME_DLLS] =
1632 MAKEDLLNAME_W(W("coreclr")),
1633 MAKEDLLNAME_W(W("clrjit"))
1637 LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id)
1645 INJECT_FAULT(COMPlusThrowOM(););
1650 return CorCompileRuntimeDllNames[id];
1653 #ifndef CROSSGEN_COMPILE
1655 //==============================================================================
1656 // Will always return a valid HMODULE for CLR_INFO, but will return NULL for NGEN_COMPILER_INFO
1657 // if the DLL has not yet been loaded (it does not try to cause a load).
1659 // Gets set by IJitManager::LoadJit (yes, this breaks the abstraction boundary).
1660 HMODULE s_ngenCompilerDll = NULL;
1662 extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id)
1670 INJECT_FAULT(COMPlusThrowOM(););
1674 // Currently special cased for every entry.
1675 static_assert_no_msg(NUM_RUNTIME_DLLS == 2);
1676 static_assert_no_msg(CORECLR_INFO == 0);
1678 HMODULE hMod = NULL;
1680 // Try to load the correct DLL
1684 hMod = GetCLRModule();
1688 COMPlusThrowNonLocalized(kExecutionEngineException,
1689 W("Invalid runtime DLL ID"));
1695 #endif // CROSSGEN_COMPILE
1697 //===========================================================================================================
1698 // Helper for RuntimeVerifyNativeImageVersion(). Compares the loaded clr.dll and clrjit.dll's against
1699 // the ones the native image was compiled against.
1700 //===========================================================================================================
1701 static BOOL RuntimeVerifyNativeImageTimestamps(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1703 STANDARD_VM_CONTRACT;
1709 //===========================================================================================================
1710 // Validates that an NI matches the running CLR, OS, CPU, etc. This is the entrypoint used by the CLR loader.
1712 //===========================================================================================================
1713 BOOL PEAssembly::CheckNativeImageVersion(PEImage *peimage)
1715 STANDARD_VM_CONTRACT;
1718 // Get the zap version header. Note that modules will not have version
1719 // headers - they add no additional versioning constraints from their
1722 PEImageLayoutHolder image=peimage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED);
1724 if (!image->HasNativeHeader())
1727 if (!image->CheckNativeHeaderVersion())
1729 // Wrong native image version is fatal error on CoreCLR
1730 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1733 CORCOMPILE_VERSION_INFO *info = image->GetNativeVersionInfo();
1737 LoggablePEAssembly logAsm(this);
1738 if (!RuntimeVerifyNativeImageVersion(info, &logAsm))
1740 // Wrong native image version is fatal error on CoreCLR
1741 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1744 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1748 // Require instrumented flags for mscorlib when collecting IBC data
1749 CorCompileConfigFlags instrumentationConfigFlags = (CorCompileConfigFlags) (configFlags & CORCOMPILE_CONFIG_INSTRUMENTATION);
1750 if ((info->wConfigFlags & instrumentationConfigFlags) != instrumentationConfigFlags)
1752 ExternalLog(LL_ERROR, "Instrumented native image for System.Private.CoreLib.dll expected.");
1753 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1757 // Otherwise, match regardless of the instrumentation flags
1758 configFlags = (CorCompileConfigFlags) (configFlags & ~(CORCOMPILE_CONFIG_INSTRUMENTATION_NONE | CORCOMPILE_CONFIG_INSTRUMENTATION));
1760 if ((info->wConfigFlags & configFlags) != configFlags)
1769 //===========================================================================================================
1770 // Validates that an NI matches the running CLR, OS, CPU, etc.
1772 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1773 // while others check at CLR load time.
1775 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1776 // by a CLR object or Fusion object.
1777 //===========================================================================================================
1778 BOOL RuntimeVerifyNativeImageVersion(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1780 STANDARD_VM_CONTRACT;
1782 if (!RuntimeVerifyNativeImageTimestamps(info, pLogAsm))
1786 // Check that the EE version numbers are the same.
1789 if (info->wVersionMajor != VER_MAJORVERSION
1790 || info->wVersionMinor != VER_MINORVERSION
1791 || info->wVersionBuildNumber != VER_PRODUCTBUILD
1792 || info->wVersionPrivateBuildNumber != VER_PRODUCTBUILD_QFE)
1794 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("CLR version recorded in native image doesn't match the current CLR."));
1799 // Check checked/free status
1804 CORCOMPILE_BUILD_CHECKED
1806 CORCOMPILE_BUILD_FREE
1810 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Checked/free mismatch with native image."));
1818 if (info->wMachine != IMAGE_FILE_MACHINE_NATIVE_NI)
1820 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Processor type recorded in native image doesn't match this machine's processor."));
1824 #ifndef CROSSGEN_COMPILE
1826 // Check the processor specific ID
1829 CORINFO_CPU cpuInfo;
1830 GetSpecificCpuInfo(&cpuInfo);
1832 if (!IsCompatibleCpuInfo(&cpuInfo, &info->cpuInfo))
1834 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Required CPU features recorded in native image don't match this machine's processor."));
1837 #endif // CROSSGEN_COMPILE
1841 // The zap is up to date.
1844 RuntimeVerifyLog(LL_INFO100, pLogAsm, W("Native image has correct version information."));
1848 #endif // !DACCESS_COMPILE
1851 CorCompileConfigFlags PEFile::GetNativeImageConfigFlags(BOOL fForceDebug/*=FALSE*/,
1852 BOOL fForceProfiling/*=FALSE*/,
1853 BOOL fForceInstrument/*=FALSE*/)
1855 LIMITED_METHOD_DAC_CONTRACT;
1857 CorCompileConfigFlags result = (CorCompileConfigFlags)0;
1861 #ifdef DEBUGGING_SUPPORTED
1862 // if these have been set, the take precedence over anything else
1863 if (s_NGENDebugFlags)
1865 if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG_NONE) != 0)
1867 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_NONE);
1871 if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG) != 0)
1873 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1878 #endif // DEBUGGING_SUPPORTED
1882 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1886 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_DEFAULT);
1892 #ifdef PROFILING_SUPPORTED
1893 if (fForceProfiling || CORProfilerUseProfileImages())
1895 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING);
1897 result = (CorCompileConfigFlags) (result & ~(CORCOMPILE_CONFIG_DEBUG_NONE|
1898 CORCOMPILE_CONFIG_DEBUG|
1899 CORCOMPILE_CONFIG_DEBUG_DEFAULT));
1902 #endif //PROFILING_SUPPORTED
1903 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING_NONE);
1906 #ifndef DACCESS_COMPILE
1907 BOOL instrumented = (!IsCompilationProcess() && g_pConfig->GetZapBBInstr());
1909 BOOL instrumented = FALSE;
1911 if (instrumented || fForceInstrument)
1913 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION);
1917 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION_NONE);
1920 // NOTE: Right now we are not taking instrumentation into account when binding.
1925 CorCompileConfigFlags PEFile::GetNativeImageConfigFlagsWithOverrides()
1927 LIMITED_METHOD_DAC_CONTRACT;
1929 BOOL fForceDebug, fForceProfiling, fForceInstrument;
1930 SystemDomain::GetCompilationOverrides(&fForceDebug,
1933 return PEFile::GetNativeImageConfigFlags(fForceDebug,
1938 #ifndef DACCESS_COMPILE
1942 //===========================================================================================================
1943 // Validates that a hard-dep matches the a parent NI's compile-time hard-dep.
1945 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1946 // while others check at CLR load time.
1948 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1949 // by a CLR object or Fusion object.
1951 //===========================================================================================================
1952 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_NGEN_SIGNATURE &ngenSigExpected,
1953 const CORCOMPILE_VERSION_INFO *pActual,
1954 LoggableAssembly *pLogAsm)
1956 STANDARD_VM_CONTRACT;
1958 if (ngenSigExpected != pActual->signature)
1960 // Signature did not match
1961 SString displayString = pLogAsm->DisplayString();
1962 RuntimeVerifyLog(LL_ERROR,
1964 W("Rejecting native image because native image dependency %s ")
1965 W("had a different identity than expected"),
1966 displayString.GetUnicode());
1967 #if (defined FEATURE_PREJIT) && (defined FEATURE_FUSION)
1968 if (pLogAsm->FusionBindLog())
1970 if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_PRIVATEFUSION_KEYWORD))
1972 pLogAsm->FusionBindLog()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY, pLogAsm->FusionAssemblyName());
1981 // Wrapper function for use by parts of the runtime that actually have a CORCOMPILE_DEPENDENCY to work with.
1982 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_DEPENDENCY *pExpected,
1983 const CORCOMPILE_VERSION_INFO *pActual,
1984 LoggableAssembly *pLogAsm)
1986 WRAPPER_NO_CONTRACT;
1988 return RuntimeVerifyNativeImageDependency(pExpected->signNativeImage,
1993 #endif // !DACCESS_COMPILE
1995 #ifdef DEBUGGING_SUPPORTED
1997 // Called through ICorDebugAppDomain2::SetDesiredNGENCompilerFlags to specify
1998 // which kinds of ngen'd images fusion should load wrt debugging support
1999 // Overrides any previous settings
2001 void PEFile::SetNGENDebugFlags(BOOL fAllowOpt)
2013 s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG_NONE;
2015 s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG;
2019 // Called through ICorDebugAppDomain2::GetDesiredNGENCompilerFlags to determine
2020 // which kinds of ngen'd images fusion should load wrt debugging support
2022 void PEFile::GetNGENDebugFlags(BOOL *fAllowOpt)
2033 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
2035 *fAllowOpt = ((configFlags & CORCOMPILE_CONFIG_DEBUG) == 0);
2037 #endif // DEBUGGING_SUPPORTED
2041 #ifndef DACCESS_COMPILE
2042 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2044 //---------------------------------------------------------------------------------------
2046 // Used in Apollo, this method determines whether profiling or debugging has requested
2047 // the runtime to provide debuggable / profileable code. In other CLR builds, this would
2048 // normally result in requiring the appropriate NGEN scenario be loaded (/Debug or
2049 // /Profile) and to JIT if unavailable. In Apollo, however, these NGEN scenarios are
2050 // never available, and even MSIL assemblies are often not available. So this function
2051 // tells its caller to use the NGENd assembly as if it were an MSIL assembly--ignore the
2052 // prejitted code and prebaked structures, and just JIT code and load classes from
2056 // nonzero iff NGENd images should be treated as MSIL images.
2060 BOOL PEFile::ShouldTreatNIAsMSIL()
2062 LIMITED_METHOD_CONTRACT;
2064 // Never use fragile native image content during ReadyToRun compilation. It would
2065 // produces non-version resilient images because of wrong cached values for
2066 // MethodTable::IsLayoutFixedInCurrentVersionBubble, etc.
2067 if (IsReadyToRunCompilation())
2070 // Ask profiling API & config vars whether NGENd images should be avoided
2072 if (!NGENImagesAllowed())
2075 // Ask profiling and debugging if they're requesting us to use ngen /Debug or
2076 // /Profile images (which aren't available under Apollo)
2078 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
2080 if ((configFlags & (CORCOMPILE_CONFIG_DEBUG | CORCOMPILE_CONFIG_PROFILING)) != 0)
2086 #endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2088 #endif //!DACCESS_COMPILE
2089 #endif // FEATURE_PREJIT
2091 #ifndef DACCESS_COMPILE
2093 // ------------------------------------------------------------
2095 // ------------------------------------------------------------
2097 void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource)
2105 INJECT_FAULT(ThrowOutOfMemory(););
2109 // NOTE: it's not clear whether to load this from m_image or m_loadedImage.
2110 // m_loadedImage is probably preferable, but this may be called by security
2111 // before the image is loaded.
2115 #ifdef FEATURE_PREJIT
2116 if (m_nativeImage != NULL)
2117 image = m_nativeImage;
2121 EnsureImageOpened();
2122 image = GetILimage();
2125 PEImageLayoutHolder theImage(image->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED));
2126 if (!theImage->CheckResource(dwOffset))
2127 ThrowHR(COR_E_BADIMAGEFORMAT);
2130 const void *resource = theImage->GetResource(dwOffset, &size);
2133 *pbInMemoryResource = (PBYTE) resource;
2136 // ------------------------------------------------------------
2138 // ------------------------------------------------------------
2141 PEFile::LoadAssembly(
2142 mdAssemblyRef kAssemblyRef,
2143 IMDInternalImport * pImport, // = NULL
2144 LPCUTF8 szWinRtTypeNamespace, // = NULL
2145 LPCUTF8 szWinRtTypeClassName) // = NULL
2147 CONTRACT(PEAssembly *)
2153 POSTCONDITION(CheckPointer(RETVAL));
2154 INJECT_FAULT(COMPlusThrowOM(););
2158 if (pImport == NULL)
2159 pImport = GetPersistentMDImport();
2161 if (((TypeFromToken(kAssemblyRef) != mdtAssembly) &&
2162 (TypeFromToken(kAssemblyRef) != mdtAssemblyRef)) ||
2163 (!pImport->IsValidToken(kAssemblyRef)))
2165 ThrowHR(COR_E_BADIMAGEFORMAT);
2170 spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(GetAssembly()), IsIntrospectionOnly());
2171 if (szWinRtTypeClassName != NULL)
2172 spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
2174 RETURN GetAppDomain()->BindAssemblySpec(&spec, TRUE, IsIntrospectionOnly());
2177 // ------------------------------------------------------------
2179 // ------------------------------------------------------------
2180 #ifdef FEATURE_PREJIT
2181 void PEFile::ExternalLog(DWORD facility, DWORD level, const WCHAR *fmt, ...)
2183 WRAPPER_NO_CONTRACT;
2186 va_start(args, fmt);
2188 ExternalVLog(facility, level, fmt, args);
2193 void PEFile::ExternalLog(DWORD level, const WCHAR *fmt, ...)
2195 WRAPPER_NO_CONTRACT;
2198 va_start(args, fmt);
2200 ExternalVLog(LF_ZAP, level, fmt, args);
2205 void PEFile::ExternalLog(DWORD level, const char *msg)
2207 WRAPPER_NO_CONTRACT;
2209 // It is OK to use %S here. We know that msg is ASCII-only.
2210 ExternalLog(level, W("%S"), msg);
2213 void PEFile::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
2222 BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
2223 BOOL fOutputToLogging = LoggingOn(facility, level);
2225 if (!fOutputToDebugger && !fOutputToLogging)
2228 StackSString message;
2229 message.VPrintf(fmt, args);
2231 if (fOutputToLogging)
2233 if (GetMDImport() != NULL)
2234 LOG((facility, level, "%s: \"%s\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), GetSimpleName()));
2236 LOG((facility, level, "%s: \"%S\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), ((const WCHAR *)GetPath())));
2238 LOG((facility, level, "%S", message.GetUnicode()));
2239 LOG((facility, level, "\n"));
2242 if (fOutputToDebugger)
2244 WszOutputDebugString(W("CLR:("));
2246 StackSString codebase;
2247 GetCodeBaseOrName(codebase);
2248 WszOutputDebugString(codebase);
2250 WszOutputDebugString(W(") "));
2252 WszOutputDebugString(message);
2253 WszOutputDebugString(W("\n"));
2259 void PEFile::FlushExternalLog()
2261 LIMITED_METHOD_CONTRACT;
2265 BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource,
2266 PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef,
2267 LPCSTR *szFileName, DWORD *dwLocation,
2268 StackCrawlMark *pStackMark, BOOL fSkipSecurityCheck,
2269 BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain)
2276 INJECT_FAULT(COMPlusThrowOM(););
2277 WRAPPER(GC_TRIGGERS);
2283 DWORD dwResourceFlags;
2285 mdManifestResource mdResource;
2286 Assembly* pAssembly = NULL;
2287 PEFile* pPEFile = NULL;
2288 ReleaseHolder<IMDInternalImport> pImport (GetMDImportWithRef());
2289 if (SUCCEEDED(pImport->FindManifestResourceByName(szName, &mdResource)))
2292 IfFailThrow(pImport->GetManifestResourceProps(
2301 if (fSkipRaiseResolveEvent || pAppDomain == NULL)
2304 DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(GetAssembly());
2305 pAssembly = pAppDomain->RaiseResourceResolveEvent(pParentAssembly, szName);
2306 if (pAssembly == NULL)
2309 pDomainAssembly = pAssembly->GetDomainAssembly(pAppDomain);
2310 pPEFile = pDomainAssembly->GetFile();
2312 if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName(
2319 if (dwLocation != 0)
2321 if (pAssemblyRef != NULL)
2322 *pAssemblyRef = pDomainAssembly;
2324 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
2326 IfFailThrow(pPEFile->GetPersistentMDImport()->GetManifestResourceProps(
2335 switch(TypeFromToken(mdLinkRef)) {
2336 case mdtAssemblyRef:
2338 if (pDomainAssembly == NULL)
2342 spec.InitializeSpec(mdLinkRef, GetPersistentMDImport(), pDomainAssembly, pDomainAssembly->GetFile()->IsIntrospectionOnly());
2343 pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED);
2347 *pAssemblyRef = pDomainAssembly;
2349 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
2352 return pDomainAssembly->GetResource(szName,
2360 fSkipRaiseResolveEvent);
2364 if (mdLinkRef == mdFileNil)
2366 // The resource is embedded in the manifest file
2368 #ifndef CROSSGEN_COMPILE
2369 if (!IsMrPublic(dwResourceFlags) && pStackMark && !fSkipSecurityCheck)
2371 Assembly *pCallersAssembly = SystemDomain::GetCallersAssembly(pStackMark);
2373 if (pCallersAssembly && // full trust for interop
2374 (!pCallersAssembly->GetManifestFile()->Equals(this)))
2376 RefSecContext sCtx(AccessCheckOptions::kMemberAccess);
2378 AccessCheckOptions accessCheckOptions(
2379 AccessCheckOptions::kMemberAccess, /*accessCheckType*/
2380 NULL, /*pAccessContext*/
2381 FALSE, /*throwIfTargetIsInaccessible*/
2382 (MethodTable *) NULL /*pTargetMT*/
2385 // SL: return TRUE only if the caller is critical
2386 // Desktop: return TRUE only if demanding MemberAccess succeeds
2387 if (!accessCheckOptions.DemandMemberAccessOrFail(&sCtx, NULL, TRUE /*visibilityCheck*/))
2391 #endif // CROSSGEN_COMPILE
2394 *dwLocation = *dwLocation | 5; // ResourceLocation.embedded |
2396 // ResourceLocation.containedInManifestFile
2400 pPEFile->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource);
2404 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2405 // The resource is either linked or embedded in a non-manifest-containing file
2406 if (pDomainAssembly == NULL)
2409 return pDomainAssembly->GetModuleResource(mdLinkRef, szName, cbResource,
2410 pbInMemoryResource, szFileName,
2411 dwLocation, IsMrPublic(dwResourceFlags),
2412 pStackMark, fSkipSecurityCheck);
2415 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
2418 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_IN_MANIFESTRES);
2422 void PEFile::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
2424 WRAPPER_NO_CONTRACT;
2426 if (IsResource() || IsDynamic())
2435 #ifdef FEATURE_PREJIT
2436 if (IsNativeLoaded())
2438 CONSISTENCY_CHECK(HasNativeImage());
2440 m_nativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
2443 #ifndef DACCESS_COMPILE
2444 if (!HasOpenedILimage())
2446 //don't want to touch the IL image unless we already have
2447 ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef();
2450 pNativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
2454 #endif // DACCESS_COMPILE
2455 #endif // FEATURE_PREJIT
2457 GetILimage()->GetPEKindAndMachine(pdwKind, pdwMachine);
2461 ULONG PEFile::GetILImageTimeDateStamp()
2471 #ifdef FEATURE_PREJIT
2472 if (IsNativeLoaded())
2474 CONSISTENCY_CHECK(HasNativeImage());
2476 // The IL image's time stamp is copied to the native image.
2477 CORCOMPILE_VERSION_INFO* pVersionInfo = GetLoadedNative()->GetNativeVersionInfoMaybeNull();
2478 if (pVersionInfo == NULL)
2484 return pVersionInfo->sourceAssembly.timeStamp;
2487 #endif // FEATURE_PREJIT
2489 return GetLoadedIL()->GetTimeDateStamp();
2492 #ifdef FEATURE_CAS_POLICY
2494 //---------------------------------------------------------------------------------------
2496 // Get a SafePEFileHandle for this PEFile
2499 SAFEHANDLE PEFile::GetSafeHandle()
2509 SAFEHANDLE objSafeHandle = NULL;
2511 GCPROTECT_BEGIN(objSafeHandle);
2513 objSafeHandle = (SAFEHANDLE)AllocateObject(MscorlibBinder::GetClass(CLASS__SAFE_PEFILE_HANDLE));
2514 CallDefaultConstructor(objSafeHandle);
2517 objSafeHandle->SetHandle(this);
2521 return objSafeHandle;
2524 #endif // FEATURE_CAS_POLICY
2526 // ================================================================================
2527 // PEAssembly class - a PEFile which represents an assembly
2528 // ================================================================================
2530 // Statics initialization.
2532 void PEAssembly::Attach()
2534 STANDARD_VM_CONTRACT;
2537 #ifdef FEATURE_FUSION
2538 PEAssembly::PEAssembly(PEImage *image,
2539 IMetaDataEmit *pEmit,
2540 IAssembly *pIAssembly,
2541 IBindResult *pNativeFusionAssembly,
2542 PEImage *pPEImageNI,
2543 IFusionBindLog *pFusionLog,
2544 IHostAssembly *pIHostAssembly,
2547 BOOL introspectionOnly/*=FALSE*/,
2548 ICLRPrivAssembly * pHostAssembly)
2549 : PEFile(image, FALSE),
2551 m_pFusionAssemblyName(NULL),
2552 m_pFusionAssembly(NULL),
2554 m_bFusionLogEnabled(TRUE),
2555 m_pIHostAssembly(NULL),
2556 m_pNativeAssemblyLocation(NULL),
2557 m_pNativeImageClosure(NULL),
2558 m_fStrongNameBypassed(FALSE)
2563 PRECONDITION(CheckPointer(image, NULL_OK));
2564 PRECONDITION(CheckPointer(pEmit, NULL_OK));
2565 PRECONDITION(image != NULL || pEmit != NULL);
2566 PRECONDITION(CheckPointer(pIAssembly, NULL_OK));
2567 PRECONDITION(CheckPointer(pFusionLog, NULL_OK));
2568 PRECONDITION(CheckPointer(pIHostAssembly, NULL_OK));
2569 PRECONDITION(CheckPointer(creator, NULL_OK));
2574 if (introspectionOnly)
2576 if (!system) // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2578 m_flags |= PEFILE_INTROSPECTIONONLY;
2579 #ifdef FEATURE_PREJIT
2580 SetCannotUseNativeImage();
2581 #endif // FEATURE_PREJIT
2587 m_pFusionAssembly = pIAssembly;
2588 pIAssembly->AddRef();
2590 IfFailThrow(pIAssembly->GetAssemblyNameDef(&m_pFusionAssemblyName));
2592 else if (pIHostAssembly)
2594 m_flags |= PEFILE_ISTREAM;
2595 #ifdef FEATURE_PREJIT
2596 m_fCanUseNativeImage = FALSE;
2597 #endif // FEATURE_PREJIT
2599 m_pIHostAssembly = pIHostAssembly;
2600 pIHostAssembly->AddRef();
2602 IfFailThrow(pIHostAssembly->GetAssemblyNameDef(&m_pFusionAssemblyName));
2607 m_pFusionLog = pFusionLog;
2608 pFusionLog->AddRef();
2613 m_creator = creator;
2617 m_flags |= PEFILE_ASSEMBLY;
2619 m_flags |= PEFILE_SYSTEM;
2621 #ifdef FEATURE_PREJIT
2622 // Find the native image
2625 if (pNativeFusionAssembly != NULL)
2626 SetNativeImage(pNativeFusionAssembly);
2628 // Only one of pNativeFusionAssembly and pPEImageNI may be set.
2629 _ASSERTE(!(pNativeFusionAssembly && pPEImageNI));
2631 if (pPEImageNI != NULL)
2632 this->PEFile::SetNativeImage(pPEImageNI);
2633 #endif // FEATURE_PREJIT
2635 // If we have no native image, we require a mapping for the file.
2636 if (!HasNativeImage() || !IsILOnly())
2637 EnsureImageOpened();
2639 // Open metadata eagerly to minimize failure windows
2641 OpenMDImport_Unsafe(); //constructor, cannot race with anything
2644 _ASSERTE(!m_bHasPersistentMDImport);
2645 IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2646 (void **)&m_pMDImport));
2649 m_bHasPersistentMDImport=TRUE;
2650 m_MDImportIsRW_Debugger_Use_Only = TRUE;
2653 // m_pMDImport can be external
2654 // Make sure this is an assembly
2655 if (!m_pMDImport->IsValidToken(TokenFromRid(1, mdtAssembly)))
2656 ThrowHR(COR_E_ASSEMBLYEXPECTED);
2658 // Make sure we perform security checks after we've obtained IMDInternalImport interface
2659 DoLoadSignatureChecks();
2661 // Verify name eagerly
2662 LPCUTF8 szName = GetSimpleName();
2665 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2668 #ifdef FEATURE_PREJIT
2669 if (IsResource() || IsDynamic())
2670 m_fCanUseNativeImage = FALSE;
2671 #endif // FEATURE_PREJIT
2673 if (m_pFusionAssembly)
2675 m_loadContext = m_pFusionAssembly->GetFusionLoadContext();
2676 m_pFusionAssembly->GetAssemblyLocation(&m_dwLocationFlags);
2678 else if (pHostAssembly != nullptr)
2680 m_loadContext = LOADCTX_TYPE_HOSTED;
2681 m_dwLocationFlags = ASMLOC_UNKNOWN;
2682 m_pHostAssembly = clr::SafeAddRef(pHostAssembly); // Should use SetHostAssembly(pHostAssembly) here
2686 m_loadContext = LOADCTX_TYPE_UNKNOWN;
2687 m_dwLocationFlags = ASMLOC_UNKNOWN;
2690 TESTHOOKCALL(CompletedNativeImageBind(image,szName,HasNativeImage()));
2693 GetCodeBaseOrName(m_debugName);
2694 m_debugName.Normalize();
2695 m_pDebugName = m_debugName;
2699 #else // FEATURE_FUSION
2701 PEAssembly::PEAssembly(
2702 CoreBindResult* pBindResultInfo,
2703 IMetaDataEmit* pEmit,
2706 BOOL introspectionOnly/*=FALSE*/,
2707 PEImage * pPEImageIL /*= NULL*/,
2708 PEImage * pPEImageNI /*= NULL*/,
2709 ICLRPrivAssembly * pHostAssembly /*= NULL*/)
2711 : PEFile(pBindResultInfo ? (pBindResultInfo->GetPEImage() ? pBindResultInfo->GetPEImage() :
2712 (pBindResultInfo->HasNativeImage() ? pBindResultInfo->GetNativeImage() : NULL)
2713 ): pPEImageIL? pPEImageIL:(pPEImageNI? pPEImageNI:NULL), FALSE),
2714 m_creator(clr::SafeAddRef(creator)),
2715 m_bIsFromGAC(FALSE),
2716 m_bIsOnTpaList(FALSE)
2717 ,m_fProfileAssembly(0)
2722 PRECONDITION(CheckPointer(pEmit, NULL_OK));
2723 PRECONDITION(CheckPointer(creator, NULL_OK));
2724 PRECONDITION(pBindResultInfo == NULL || (pPEImageIL == NULL && pPEImageNI == NULL));
2729 if (introspectionOnly)
2731 if (!system) // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2733 m_flags |= PEFILE_INTROSPECTIONONLY;
2737 m_flags |= PEFILE_ASSEMBLY;
2739 m_flags |= PEFILE_SYSTEM;
2741 // We check the precondition above that either pBindResultInfo is null or both pPEImageIL and pPEImageNI are,
2742 // so we'll only get a max of one native image passed in.
2743 if (pPEImageNI != NULL)
2745 SetNativeImage(pPEImageNI);
2748 #ifdef FEATURE_PREJIT
2749 if (pBindResultInfo && pBindResultInfo->HasNativeImage())
2750 SetNativeImage(pBindResultInfo->GetNativeImage());
2753 // If we have no native image, we require a mapping for the file.
2754 if (!HasNativeImage() || !IsILOnly())
2755 EnsureImageOpened();
2757 // Initialize the status of the assembly being in the GAC, or being part of the TPA list, before
2758 // we start to do work (like strong name verification) that relies on those states to be valid.
2759 if(pBindResultInfo != nullptr)
2761 m_bIsFromGAC = pBindResultInfo->IsFromGAC();
2762 m_bIsOnTpaList = pBindResultInfo->IsOnTpaList();
2765 // Check security related stuff
2768 // Open metadata eagerly to minimize failure windows
2770 OpenMDImport_Unsafe(); //constructor, cannot race with anything
2773 _ASSERTE(!m_bHasPersistentMDImport);
2774 IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2775 (void **)&m_pMDImport));
2778 m_bHasPersistentMDImport=TRUE;
2779 m_MDImportIsRW_Debugger_Use_Only = TRUE;
2782 // m_pMDImport can be external
2783 // Make sure this is an assembly
2784 if (!m_pMDImport->IsValidToken(TokenFromRid(1, mdtAssembly)))
2785 ThrowHR(COR_E_ASSEMBLYEXPECTED);
2787 // Verify name eagerly
2788 LPCUTF8 szName = GetSimpleName();
2791 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2794 // Set the host assembly and binding context as the AssemblySpec initialization
2795 // for CoreCLR will expect to have it set.
2796 if (pHostAssembly != nullptr)
2798 m_pHostAssembly = clr::SafeAddRef(pHostAssembly);
2801 if(pBindResultInfo != nullptr)
2803 // Cannot have both pHostAssembly and a coreclr based bind
2804 _ASSERTE(pHostAssembly == nullptr);
2805 pBindResultInfo->GetBindAssembly(&m_pHostAssembly);
2809 GetCodeBaseOrName(m_debugName);
2810 m_debugName.Normalize();
2811 m_pDebugName = m_debugName;
2814 spec.InitializeSpec(this);
2816 spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
2817 ASM_DISPLAYF_CULTURE |
2818 ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
2819 m_sTextualIdentity);
2822 #endif // FEATURE_FUSION
2825 #ifdef FEATURE_FUSION
2827 PEAssembly *PEAssembly::Open(
2828 PEAssembly *pParentAssembly,
2829 PEImage *pPEImageIL,
2830 BOOL isIntrospectionOnly)
2832 STANDARD_VM_CONTRACT;
2833 PEAssembly * pPEAssembly = new PEAssembly(
2834 pPEImageIL, // PEImage
2835 nullptr, // IMetaDataEmit
2836 nullptr, // IAssembly
2837 nullptr, // IBindResult pNativeFusionAssembly
2838 nullptr, // PEImage *pNIImage
2839 nullptr, // IFusionBindLog
2840 nullptr, // IHostAssembly
2841 pParentAssembly, // creator
2843 isIntrospectionOnly, // isIntrospectionOnly
2849 PEAssembly *PEAssembly::Open(
2850 PEAssembly * pParent,
2851 PEImage * pPEImageIL,
2852 PEImage * pPEImageNI,
2853 ICLRPrivAssembly * pHostAssembly,
2854 BOOL fIsIntrospectionOnly)
2856 STANDARD_VM_CONTRACT;
2857 PEAssembly * pPEAssembly = new PEAssembly(
2858 pPEImageIL, // PEImage
2859 nullptr, // IMetaDataEmit
2860 nullptr, // IAssembly
2861 nullptr, // IBindResult pNativeFusionAssembly
2862 pPEImageNI, // Native Image PEImage
2863 nullptr, // IFusionBindLog
2864 nullptr, // IHostAssembly
2867 fIsIntrospectionOnly,
2873 #else //FEATURE_FUSION
2875 PEAssembly *PEAssembly::Open(
2876 PEAssembly * pParent,
2877 PEImage * pPEImageIL,
2878 PEImage * pPEImageNI,
2879 ICLRPrivAssembly * pHostAssembly,
2880 BOOL fIsIntrospectionOnly)
2882 STANDARD_VM_CONTRACT;
2884 PEAssembly * pPEAssembly = new PEAssembly(
2885 nullptr, // BindResult
2886 nullptr, // IMetaDataEmit
2887 pParent, // PEFile creator
2889 fIsIntrospectionOnly,
2897 #endif // FEATURE_FUSION
2899 PEAssembly::~PEAssembly()
2905 GC_TRIGGERS; // Fusion uses crsts on AddRef/Release
2911 #ifdef FEATURE_FUSION
2912 if (m_pFusionAssemblyName != NULL)
2913 m_pFusionAssemblyName->Release();
2914 if (m_pFusionAssembly != NULL)
2915 m_pFusionAssembly->Release();
2916 if (m_pIHostAssembly != NULL)
2917 m_pIHostAssembly->Release();
2918 if (m_pNativeAssemblyLocation != NULL)
2920 m_pNativeAssemblyLocation->Release();
2922 if (m_pNativeImageClosure!=NULL)
2923 m_pNativeImageClosure->Release();
2924 if (m_pFusionLog != NULL)
2925 m_pFusionLog->Release();
2926 #endif // FEATURE_FUSION
2927 if (m_creator != NULL)
2928 m_creator->Release();
2932 #ifndef DACCESS_COMPILE
2933 void PEAssembly::ReleaseIL()
2945 #ifdef FEATURE_FUSION
2946 if (m_pFusionAssemblyName != NULL)
2948 m_pFusionAssemblyName->Release();
2949 m_pFusionAssemblyName=NULL;
2951 if (m_pFusionAssembly != NULL)
2953 m_pFusionAssembly->Release();
2954 m_pFusionAssembly=NULL;
2956 if (m_pIHostAssembly != NULL)
2958 m_pIHostAssembly->Release();
2959 m_pIHostAssembly=NULL;
2961 if (m_pNativeAssemblyLocation != NULL)
2963 m_pNativeAssemblyLocation->Release();
2964 m_pNativeAssemblyLocation=NULL;
2966 _ASSERTE(m_pNativeImageClosure==NULL);
2968 if (m_pFusionLog != NULL)
2970 m_pFusionLog->Release();
2973 #endif // FEATURE_FUSION
2974 if (m_creator != NULL)
2976 m_creator->Release();
2980 PEFile::ReleaseIL();
2986 #ifdef FEATURE_FUSION
2987 PEAssembly *PEAssembly::OpenSystem(IApplicationContext * pAppCtx)
2989 PEAssembly *PEAssembly::OpenSystem(IUnknown * pAppCtx)
2992 STANDARD_VM_CONTRACT;
2994 PEAssembly *result = NULL;
2998 result = DoOpenSystem(pAppCtx);
3002 Exception *ex = GET_EXCEPTION();
3004 // Rethrow non-transient exceptions as file load exceptions with proper
3007 if (!ex->IsTransient())
3008 EEFileLoadException::Throw(SystemDomain::System()->BaseLibrary(), ex->GetHR(), ex);
3015 #ifdef FEATURE_FUSION
3016 PEAssembly *PEAssembly::DoOpenSystem(IApplicationContext * pAppCtx)
3018 PEAssembly *PEAssembly::DoOpenSystem(IUnknown * pAppCtx)
3021 CONTRACT(PEAssembly *)
3023 POSTCONDITION(CheckPointer(RETVAL));
3028 #ifdef FEATURE_FUSION
3029 SafeComHolder<IAssemblyName> pName;
3030 IfFailThrow(CreateAssemblyNameObject(&pName, W("mscorlib"), 0, NULL));
3032 UINT64 publicKeyValue = I64(CONCAT_MACRO(0x, VER_ECMA_PUBLICKEY));
3033 BYTE publicKeyToken[8] =
3035 (BYTE) (publicKeyValue>>56),
3036 (BYTE) (publicKeyValue>>48),
3037 (BYTE) (publicKeyValue>>40),
3038 (BYTE) (publicKeyValue>>32),
3039 (BYTE) (publicKeyValue>>24),
3040 (BYTE) (publicKeyValue>>16),
3041 (BYTE) (publicKeyValue>>8),
3042 (BYTE) (publicKeyValue),
3045 IfFailThrow(pName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, publicKeyToken, sizeof(publicKeyToken)));
3047 USHORT version = VER_ASSEMBLYMAJORVERSION;
3048 IfFailThrow(pName->SetProperty(ASM_NAME_MAJOR_VERSION, &version, sizeof(version)));
3049 version = VER_ASSEMBLYMINORVERSION;
3050 IfFailThrow(pName->SetProperty(ASM_NAME_MINOR_VERSION, &version, sizeof(version)));
3051 version = VER_ASSEMBLYBUILD;
3052 IfFailThrow(pName->SetProperty(ASM_NAME_BUILD_NUMBER, &version, sizeof(version)));
3053 version = VER_ASSEMBLYBUILD_QFE;
3054 IfFailThrow(pName->SetProperty(ASM_NAME_REVISION_NUMBER, &version, sizeof(version)));
3056 IfFailThrow(pName->SetProperty(ASM_NAME_CULTURE, W(""), sizeof(WCHAR)));
3058 #ifdef FEATURE_PREJIT
3059 #ifdef PROFILING_SUPPORTED
3060 if (NGENImagesAllowed())
3062 // Binding flags, zap string
3063 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
3064 IfFailThrow(pName->SetProperty(ASM_NAME_CONFIG_MASK, &configFlags, sizeof(configFlags)));
3066 LPCWSTR configString = g_pConfig->ZapSet();
3067 IfFailThrow(pName->SetProperty(ASM_NAME_CUSTOM, (PVOID)configString,
3068 (DWORD) (wcslen(configString)+1)*sizeof(WCHAR)));
3070 // @TODO: Need some fuslogvw logging here
3072 #endif //PROFILING_SUPPORTED
3073 #endif // FEATURE_PREJIT
3075 SafeComHolder<IAssembly> pIAssembly;
3076 SafeComHolder<IBindResult> pNativeFusionAssembly;
3077 SafeComHolder<IFusionBindLog> pFusionLog;
3080 ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1);
3081 IfFailThrow(BindToSystem(pName, SystemDomain::System()->SystemDirectory(), NULL, pAppCtx, &pIAssembly, &pNativeFusionAssembly, &pFusionLog));
3085 FusionBind::GetAssemblyManifestModulePath(pIAssembly, path);
3087 // Open the image with no required mapping. This will be
3088 // promoted to a real open if we don't have a native image.
3089 PEImageHolder image (PEImage::OpenImage(path));
3091 PEAssembly* pPEAssembly = new PEAssembly(image, NULL, pIAssembly,pNativeFusionAssembly, NULL, pFusionLog, NULL, NULL, TRUE, FALSE);
3093 #ifdef FEATURE_APPX_BINDER
3094 if (AppX::IsAppXProcess())
3096 // Since mscorlib is loaded as a special case, create and assign an ICLRPrivAssembly for the new PEAssembly here.
3097 CLRPrivBinderAppX * pBinder = CLRPrivBinderAppX::GetOrCreateBinder();
3098 CLRPrivBinderFusion * pFusionBinder = pBinder->GetFusionBinder();
3100 pFusionBinder->BindMscorlib(pPEAssembly);
3105 #else // FEATURE_FUSION
3106 ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1);
3107 CoreBindResult bindResult;
3108 ReleaseHolder<ICLRPrivAssembly> pPrivAsm;
3109 IfFailThrow(CCoreCLRBinderHelper::BindToSystem(&pPrivAsm, !IsCompilationProcess() || g_fAllowNativeImages));
3110 if(pPrivAsm != NULL)
3112 bindResult.Init(pPrivAsm, TRUE, TRUE);
3115 RETURN new PEAssembly(&bindResult, NULL, NULL, TRUE, FALSE);
3116 #endif // FEATURE_FUSION
3119 #ifdef FEATURE_FUSION
3121 PEAssembly *PEAssembly::Open(IAssembly *pIAssembly,
3122 IBindResult *pNativeFusionAssembly,
3123 IFusionBindLog *pFusionLog/*=NULL*/,
3124 BOOL isSystemAssembly/*=FALSE*/,
3125 BOOL isIntrospectionOnly/*=FALSE*/)
3127 STANDARD_VM_CONTRACT;
3129 PEAssembly *result = NULL;
3132 result = DoOpen(pIAssembly, pNativeFusionAssembly, pFusionLog, isSystemAssembly, isIntrospectionOnly);
3136 Exception *ex = GET_EXCEPTION();
3138 // Rethrow non-transient exceptions as file load exceptions with proper
3140 if (!ex->IsTransient())
3141 EEFileLoadException::Throw(pIAssembly, NULL, ex->GetHR(), ex);
3149 class DoOpenIAssemblyStress : APIThreadStress
3152 IAssembly *pIAssembly;
3153 IBindResult *pNativeFusionAssembly;
3154 IFusionBindLog *pFusionLog;
3155 DoOpenIAssemblyStress(IAssembly *pIAssembly, IBindResult *pNativeFusionAssembly, IFusionBindLog *pFusionLog)
3156 : pIAssembly(pIAssembly), pNativeFusionAssembly(pNativeFusionAssembly),pFusionLog(pFusionLog) {LIMITED_METHOD_CONTRACT;}
3159 WRAPPER_NO_CONTRACT;
3160 PEAssemblyHolder result (PEAssembly::Open(pIAssembly, pNativeFusionAssembly, pFusionLog, FALSE, FALSE));
3165 PEAssembly *PEAssembly::DoOpen(IAssembly *pIAssembly,
3166 IBindResult *pNativeFusionAssembly,
3167 IFusionBindLog *pFusionLog,
3168 BOOL isSystemAssembly,
3169 BOOL isIntrospectionOnly/*=FALSE*/)
3171 CONTRACT(PEAssembly *)
3173 PRECONDITION(CheckPointer(pIAssembly));
3174 POSTCONDITION(CheckPointer(RETVAL));
3179 DoOpenIAssemblyStress ts(pIAssembly,pNativeFusionAssembly,pFusionLog);
3181 PEImageHolder image;
3184 FusionBind::GetAssemblyManifestModulePath(pIAssembly, path);
3186 // Open the image with no required mapping. This will be
3187 // promoted to a real open if we don't have a native image.
3188 image = PEImage::OpenImage(path, MDInternalImport_NoCache); // "identity" does not need to be cached
3190 PEAssemblyHolder assembly (new PEAssembly(image, NULL, pIAssembly, pNativeFusionAssembly, NULL, pFusionLog,
3191 NULL, NULL, isSystemAssembly, isIntrospectionOnly));
3193 RETURN assembly.Extract();
3197 PEAssembly *PEAssembly::Open(IHostAssembly *pIHostAssembly, BOOL isSystemAssembly, BOOL isIntrospectionOnly)
3199 STANDARD_VM_CONTRACT;
3201 PEAssembly *result = NULL;
3205 result = DoOpen(pIHostAssembly, isSystemAssembly, isIntrospectionOnly);
3209 Exception *ex = GET_EXCEPTION();
3211 // Rethrow non-transient exceptions as file load exceptions with proper
3214 if (!ex->IsTransient())
3215 EEFileLoadException::Throw(NULL, pIHostAssembly, ex->GetHR(), ex);
3222 class DoOpenIHostAssemblyStress : APIThreadStress
3225 IHostAssembly *pIHostAssembly;
3226 DoOpenIHostAssemblyStress(IHostAssembly *pIHostAssembly) :
3227 pIHostAssembly(pIHostAssembly) {LIMITED_METHOD_CONTRACT;}
3230 WRAPPER_NO_CONTRACT;
3231 PEAssemblyHolder result (PEAssembly::Open(pIHostAssembly, FALSE, FALSE));
3236 PEAssembly *PEAssembly::DoOpen(IHostAssembly *pIHostAssembly, BOOL isSystemAssembly,
3237 BOOL isIntrospectionOnly)
3239 CONTRACT(PEAssembly *)
3241 PRECONDITION(CheckPointer(pIHostAssembly));
3242 POSTCONDITION(CheckPointer(RETVAL));
3246 INJECT_FAULT(COMPlusThrowOM(););
3250 DoOpenIHostAssemblyStress ts(pIHostAssembly);
3253 IfFailThrow(pIHostAssembly->GetAssemblyId(&AssemblyId));
3255 PEImageHolder image(PEImage::FindById(AssemblyId, 0));
3257 PEAssemblyHolder assembly (new PEAssembly(image, NULL, NULL, NULL, NULL, NULL,
3258 pIHostAssembly, NULL, isSystemAssembly, isIntrospectionOnly));
3260 RETURN assembly.Extract();
3262 #endif // FEATURE_FUSION
3264 #ifndef CROSSGEN_COMPILE
3266 PEAssembly *PEAssembly::OpenMemory(PEAssembly *pParentAssembly,
3267 const void *flat, COUNT_T size,
3268 BOOL isIntrospectionOnly/*=FALSE*/,
3269 CLRPrivBinderLoadFile* pBinderToUse)
3271 STANDARD_VM_CONTRACT;
3273 PEAssembly *result = NULL;
3277 result = DoOpenMemory(pParentAssembly, flat, size, isIntrospectionOnly, pBinderToUse);
3281 Exception *ex = GET_EXCEPTION();
3283 // Rethrow non-transient exceptions as file load exceptions with proper
3286 if (!ex->IsTransient())
3287 EEFileLoadException::Throw(pParentAssembly, flat, size, ex->GetHR(), ex);
3297 class DoOpenFlatStress : APIThreadStress
3300 PEAssembly *pParentAssembly;
3303 DoOpenFlatStress(PEAssembly *pParentAssembly, const void *flat, COUNT_T size)
3304 : pParentAssembly(pParentAssembly), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
3307 WRAPPER_NO_CONTRACT;
3308 PEAssemblyHolder result(PEAssembly::OpenMemory(pParentAssembly, flat, size, FALSE));
3313 PEAssembly *PEAssembly::DoOpenMemory(
3314 PEAssembly *pParentAssembly,
3317 BOOL isIntrospectionOnly,
3318 CLRPrivBinderLoadFile* pBinderToUse)
3320 CONTRACT(PEAssembly *)
3322 PRECONDITION(CheckPointer(flat));
3323 PRECONDITION(CheckOverflow(flat, size));
3324 PRECONDITION(CheckPointer(pParentAssembly));
3326 POSTCONDITION(CheckPointer(RETVAL));
3331 DoOpenFlatStress ts(pParentAssembly, flat, size);
3333 // Note that we must have a flat image stashed away for two reasons.
3334 // First, we need a private copy of the data which we can verify
3335 // before doing the mapping. And secondly, we can only compute
3336 // the strong name hash on a flat image.
3338 PEImageHolder image(PEImage::LoadFlat(flat, size));
3340 // Need to verify that this is a CLR assembly
3341 if (!image->CheckILFormat())
3342 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
3345 #ifdef FEATURE_FUSION
3346 RETURN new PEAssembly(image, NULL, NULL, NULL, NULL, NULL, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
3348 CoreBindResult bindResult;
3349 ReleaseHolder<ICLRPrivAssembly> assembly;
3350 IfFailThrow(CCoreCLRBinderHelper::GetAssemblyFromImage(image, NULL, &assembly));
3351 bindResult.Init(assembly,FALSE,FALSE);
3353 RETURN new PEAssembly(&bindResult, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
3356 #endif // !CROSSGEN_COMPILE
3358 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
3359 // Use for main exe loading
3360 // This is also used for "spontaneous" (IJW) dll loading where
3361 // we need to deliver DllMain callbacks, but we should eliminate this case
3364 PEAssembly *PEAssembly::OpenHMODULE(HMODULE hMod,
3365 IAssembly *pFusionAssembly,
3366 IBindResult *pNativeFusionAssembly,
3367 IFusionBindLog *pFusionLog/*=NULL*/,
3368 BOOL isIntrospectionOnly/*=FALSE*/)
3370 STANDARD_VM_CONTRACT;
3372 PEAssembly *result = NULL;
3374 ETWOnStartup (OpenHModule_V1, OpenHModuleEnd_V1);
3378 result = DoOpenHMODULE(hMod, pFusionAssembly, pNativeFusionAssembly, pFusionLog, isIntrospectionOnly);
3382 Exception *ex = GET_EXCEPTION();
3384 // Rethrow non-transient exceptions as file load exceptions with proper
3386 if (!ex->IsTransient())
3387 EEFileLoadException::Throw(pFusionAssembly, NULL, ex->GetHR(), ex);
3394 class DoOpenHMODULEStress : APIThreadStress
3398 IAssembly *pFusionAssembly;
3399 IBindResult *pNativeFusionAssembly;
3400 IFusionBindLog *pFusionLog;
3401 DoOpenHMODULEStress(HMODULE hMod, IAssembly *pFusionAssembly, IBindResult *pNativeFusionAssembly, IFusionBindLog *pFusionLog)
3402 : hMod(hMod), pFusionAssembly(pFusionAssembly), pNativeFusionAssembly(pNativeFusionAssembly),pFusionLog(pFusionLog) {LIMITED_METHOD_CONTRACT;}
3405 WRAPPER_NO_CONTRACT;
3406 PEAssemblyHolder result(PEAssembly::OpenHMODULE(hMod, pFusionAssembly,pNativeFusionAssembly, pFusionLog, FALSE));
3411 PEAssembly *PEAssembly::DoOpenHMODULE(HMODULE hMod,
3412 IAssembly *pFusionAssembly,
3413 IBindResult *pNativeFusionAssembly,
3414 IFusionBindLog *pFusionLog,
3415 BOOL isIntrospectionOnly/*=FALSE*/)
3417 CONTRACT(PEAssembly *)
3419 PRECONDITION(CheckPointer(hMod));
3420 PRECONDITION(CheckPointer(pFusionAssembly));
3421 PRECONDITION(CheckPointer(pNativeFusionAssembly,NULL_OK));
3422 POSTCONDITION(CheckPointer(RETVAL));
3426 INJECT_FAULT(COMPlusThrowOM(););
3430 DoOpenHMODULEStress ts(hMod, pFusionAssembly, pNativeFusionAssembly, pFusionLog);
3432 PEImageHolder image(PEImage::LoadImage(hMod));
3434 RETURN new PEAssembly(image, NULL, pFusionAssembly, pNativeFusionAssembly, NULL, pFusionLog, NULL, NULL, FALSE, isIntrospectionOnly);
3436 #endif // FEATURE_MIXEDMODE && !CROSSGEN_COMPILE
3439 #ifndef FEATURE_FUSION
3440 PEAssembly* PEAssembly::Open(CoreBindResult* pBindResult,
3441 BOOL isSystem, BOOL isIntrospectionOnly)
3444 return new PEAssembly(pBindResult,NULL,NULL,isSystem,isIntrospectionOnly);
3450 PEAssembly *PEAssembly::Create(PEAssembly *pParentAssembly,
3451 IMetaDataAssemblyEmit *pAssemblyEmit,
3452 BOOL bIsIntrospectionOnly)
3454 CONTRACT(PEAssembly *)
3456 PRECONDITION(CheckPointer(pParentAssembly));
3457 PRECONDITION(CheckPointer(pAssemblyEmit));
3459 POSTCONDITION(CheckPointer(RETVAL));
3463 // Set up the metadata pointers in the PEAssembly. (This is the only identity
3465 SafeComHolder<IMetaDataEmit> pEmit;
3466 pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit);
3467 #ifdef FEATURE_FUSION
3468 ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
3469 if (pParentAssembly->HasHostAssembly())
3471 // Dynamic assemblies in AppX use their parent's ICLRPrivAssembly as the binding context.
3472 pPrivAssembly = clr::SafeAddRef(new CLRPrivBinderUtil::CLRPrivBinderAsAssemblyWrapper(
3473 pParentAssembly->GetHostAssembly()));
3476 PEAssemblyHolder pFile(new PEAssembly(
3477 NULL, pEmit, NULL, NULL, NULL, NULL, NULL, pParentAssembly,
3478 FALSE, bIsIntrospectionOnly,
3481 PEAssemblyHolder pFile(new PEAssembly(NULL, pEmit, pParentAssembly, FALSE, bIsIntrospectionOnly));
3483 RETURN pFile.Extract();
3487 #ifdef FEATURE_PREJIT
3489 #ifdef FEATURE_FUSION
3490 BOOL PEAssembly::HasEqualNativeClosure(DomainAssembly * pDomainAssembly)
3497 PRECONDITION(CheckPointer(pDomainAssembly));
3505 if (m_pNativeImageClosure == NULL)
3508 // ensure theclosures are walked
3509 IAssemblyBindingClosure * pClosure = pDomainAssembly->GetAssemblyBindingClosure(LEVEL_COMPLETE);
3510 _ASSERTE(pClosure != NULL);
3512 if (m_pNativeImageClosure->HasBeenWalked(LEVEL_COMPLETE) != S_OK )
3516 ENTER_DOMAIN_PTR(SystemDomain::System()->DefaultDomain(),ADV_DEFAULTAD);
3519 IfFailThrow(m_pNativeImageClosure->EnsureWalked(GetFusionAssembly(),GetAppDomain()->GetFusionContext(),LEVEL_COMPLETE));
3521 END_DOMAIN_TRANSITION;
3525 hr = pClosure->IsEqual(m_pNativeImageClosure);
3527 return (hr == S_OK);
3529 #endif //FEATURE_FUSION
3531 #ifdef FEATURE_FUSION
3532 void PEAssembly::SetNativeImage(IBindResult *pNativeFusionAssembly)
3542 WCHAR pwzPath[MAX_LONGPATH];
3543 DWORD dwCCPath = MAX_LONGPATH;
3544 ReleaseHolder<IAssemblyLocation> pIAssemblyLocation;
3546 IfFailThrow(pNativeFusionAssembly->GetAssemblyLocation(&pIAssemblyLocation));
3547 IfFailThrow(pIAssemblyLocation->GetPath(pwzPath, &dwCCPath));
3550 PEImageHolder image(PEImage::OpenImage(path));
3553 // For desktop dev11, this verification is now done at native binding time.
3554 _ASSERTE(CheckNativeImageVersion(image));
3556 PEFile::SetNativeImage(image);
3557 IfFailThrow(pNativeFusionAssembly->GetAssemblyLocation(&m_pNativeAssemblyLocation));
3559 #else //FEATURE_FUSION
3560 void PEAssembly::SetNativeImage(PEImage * image)
3571 if (CheckNativeImageVersion(image))
3573 PEFile::SetNativeImage(image);
3575 //Enable this code if you want to make sure we never touch the flat layout in the presence of the
3577 //#if defined(_DEBUG)
3578 //find all the layouts in the il image and make sure we never touch them.
3579 unsigned ignored = 0;
3580 PTR_PEImageLayout layout = m_ILimage->GetLayout(PEImageLayout::LAYOUT_FLAT, 0);
3583 //cache a bunch of PE metadata in the PEDecoder
3584 m_ILimage->CheckILFormat();
3586 //we also need some of metadata (for the public key), so cache this too
3587 DWORD verifyOutputFlags;
3588 m_ILimage->VerifyStrongName(&verifyOutputFlags);
3589 //fudge this by a few pages to make sure we can still mess with the PE headers
3590 const size_t fudgeSize = 4096 * 4;
3591 ClrVirtualProtect((void*)(((char *)layout->GetBase()) + fudgeSize),
3592 layout->GetSize() - fudgeSize, 0, &ignored);
3599 ExternalLog(LL_WARNING, "Native image is not correct version.");
3602 #endif //FEATURE_FUSION
3604 #ifdef FEATURE_FUSION
3605 void PEAssembly::ClearNativeImage()
3610 PRECONDITION(HasNativeImage());
3611 POSTCONDITION(!HasNativeImage());
3615 INJECT_FAULT(COMPlusThrowOM(););
3619 PEFile::ClearNativeImage();
3621 if (m_pNativeAssemblyLocation != NULL)
3622 m_pNativeAssemblyLocation->Release();
3623 m_pNativeAssemblyLocation = NULL;
3624 if (m_pNativeImageClosure != NULL)
3625 m_pNativeImageClosure->Release();
3626 m_pNativeImageClosure = NULL;
3629 #endif //FEATURE_FUSION
3630 #endif // FEATURE_PREJIT
3633 #ifdef FEATURE_FUSION
3634 BOOL PEAssembly::IsBindingCodeBase()
3642 INJECT_FAULT(COMPlusThrowOM(););
3646 if (m_pIHostAssembly != NULL)
3649 if (m_pFusionAssembly == NULL)
3650 return (!GetPath().IsEmpty());
3652 if (m_dwLocationFlags == ASMLOC_UNKNOWN)
3655 return ((m_dwLocationFlags & ASMLOC_CODEBASE_HINT) != 0);
3658 BOOL PEAssembly::IsSourceGAC()
3660 LIMITED_METHOD_CONTRACT;
3662 if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3667 return ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_GAC);
3670 BOOL PEAssembly::IsSourceDownloadCache()
3672 LIMITED_METHOD_CONTRACT;
3674 if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3679 return ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_DOWNLOAD_CACHE);
3682 #else // FEATURE_FUSION
3683 BOOL PEAssembly::IsSourceGAC()
3685 WRAPPER_NO_CONTRACT;
3686 return m_bIsFromGAC;
3689 #endif // FEATURE_FUSION
3691 #endif // #ifndef DACCESS_COMPILE
3693 #ifdef FEATURE_FUSION
3694 BOOL PEAssembly::IsContextLoad()
3696 LIMITED_METHOD_CONTRACT;
3697 if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3701 return (IsSystem() || (m_loadContext == LOADCTX_TYPE_DEFAULT));
3704 LOADCTX_TYPE PEAssembly::GetLoadContext()
3706 LIMITED_METHOD_CONTRACT;
3708 return m_loadContext;
3711 DWORD PEAssembly::GetLocationFlags()
3713 LIMITED_METHOD_CONTRACT;
3715 return m_dwLocationFlags;
3721 #ifndef DACCESS_COMPILE
3723 #ifdef FEATURE_FUSION
3724 PEKIND PEAssembly::GetFusionProcessorArchitecture()
3734 PEImage * pImage = NULL;
3736 #ifdef FEATURE_PREJIT
3737 pImage = m_nativeImage;
3741 pImage = GetILimage();
3743 return pImage->GetFusionProcessorArchitecture();
3746 IAssemblyName * PEAssembly::GetFusionAssemblyName()
3748 CONTRACT(IAssemblyName *)
3751 POSTCONDITION(CheckPointer(RETVAL));
3755 INJECT_FAULT(COMPlusThrowOM(););
3759 if (m_pFusionAssemblyName == NULL)
3762 spec.InitializeSpec(this);
3763 PEImage * pImage = GetILimage();
3765 #ifdef FEATURE_PREJIT
3766 if ((pImage != NULL) && !pImage->MDImportLoaded())
3767 pImage = m_nativeImage;
3772 spec.SetPEKIND(pImage->GetFusionProcessorArchitecture());
3777 IfFailThrow(spec.CreateFusionName(&m_pFusionAssemblyName, FALSE));
3780 RETURN m_pFusionAssemblyName;
3783 // This version of GetFusionAssemlyName that can be used to return the reference in a
3784 // NOTHROW/NOTRIGGER fashion. This is useful for scenarios where you dont want to invoke the THROWS/GCTRIGGERS
3785 // version when you know the name would have been created and is available.
3786 IAssemblyName * PEAssembly::GetFusionAssemblyNameNoCreate()
3788 LIMITED_METHOD_CONTRACT;
3790 return m_pFusionAssemblyName;
3793 IAssembly *PEAssembly::GetFusionAssembly()
3795 CONTRACT(IAssembly *)
3798 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3805 RETURN m_pFusionAssembly;
3808 IHostAssembly *PEAssembly::GetIHostAssembly()
3810 CONTRACT(IHostAssembly *)
3813 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3820 RETURN m_pIHostAssembly;
3823 IAssemblyLocation *PEAssembly::GetNativeAssemblyLocation()
3825 CONTRACT(IAssemblyLocation *)
3828 PRECONDITION(HasNativeImage());
3829 POSTCONDITION(CheckPointer(RETVAL));
3836 RETURN m_pNativeAssemblyLocation;
3838 #endif // FEATURE_FUSION
3840 // ------------------------------------------------------------
3842 // ------------------------------------------------------------
3844 void PEAssembly::VerifyStrongName()
3852 INJECT_FAULT(COMPlusThrowOM(););
3856 // If we've already done the signature checks, we don't need to do them again.
3857 if (m_fStrongNameVerified)
3862 #ifdef FEATURE_FUSION
3863 // System and dynamic assemblies don't need hash checks
3864 if (IsSystem() || IsDynamic())
3866 // Without FUSION/GAC, we need to verify SN on all assemblies, except dynamic assemblies.
3871 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3872 m_fStrongNameVerified = TRUE;
3876 // Next, verify the strong name, if necessary
3877 #ifdef FEATURE_FUSION
3878 // See if the assembly comes from a secure location
3879 IAssembly *pFusionAssembly = GetAssembly()->GetFusionAssembly();
3880 if (pFusionAssembly)
3883 IfFailThrow(pFusionAssembly->GetAssemblyLocation(&dwLocation));
3885 switch (dwLocation & ASMLOC_LOCATION_MASK)
3888 case ASMLOC_DOWNLOAD_CACHE:
3889 case ASMLOC_DEV_OVERRIDE:
3890 // Assemblies from the GAC or download cache have
3891 // already been verified by Fusion.
3892 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3893 m_fStrongNameVerified = TRUE;
3896 case ASMLOC_RUN_FROM_SOURCE:
3897 case ASMLOC_UNKNOWN:
3898 // For now, just verify these every time, we need to
3899 // cache the fact that at least one verification has
3900 // been performed (if strong name policy permits
3901 // caching of verification results)
3910 // Check format of image. Note we must delay this until after the GAC status has been
3911 // checked, to handle the case where we are not loading m_image.
3912 EnsureImageOpened();
3915 if (m_nativeImage == NULL && !GetILimage()->IsTrustedNativeImage())
3917 if (!GetILimage()->CheckILFormat())
3918 ThrowHR(COR_E_BADIMAGEFORMAT);
3921 // Check the strong name if present.
3922 if (IsIntrospectionOnly())
3924 // For introspection assemblies, we don't need to check strong names and we don't
3925 // need to do module hash checks.
3926 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3930 // Runtime policy on CoreCLR is to skip verification of ALL assemblies
3931 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3932 m_fStrongNameVerified = TRUE;
3935 m_fStrongNameVerified = TRUE;
3938 BOOL PEAssembly::IsProfileAssembly()
3949 // For now, cache the result of the check below. This cache should be removed once/if the check below
3950 // becomes cheap (e.g. does not access metadata anymore).
3952 if (VolatileLoadWithoutBarrier(&m_fProfileAssembly) != 0)
3954 return m_fProfileAssembly > 0;
3958 // In order to be a platform (profile) assembly, you must be from a trusted location (TPA list)
3959 // If we are binding by TPA list and this assembly is on it, IsSourceGAC is true => Assembly is Profile
3960 // If the assembly is a WinMD, it is automatically trusted since all WinMD scenarios are full trust scenarios.
3962 // The check for Silverlight strongname platform assemblies is legacy backdoor. It was introduced by accidental abstraction leak
3963 // from the old Silverlight binder, people took advantage of it and we cannot easily get rid of it now. See DevDiv #710462.
3965 BOOL bProfileAssembly = IsSourceGAC() && (IsSystem() || m_bIsOnTpaList);
3967 m_fProfileAssembly = bProfileAssembly ? 1 : -1;
3968 return bProfileAssembly;
3971 // ------------------------------------------------------------
3972 // Descriptive strings
3973 // ------------------------------------------------------------
3975 // Effective path is the path of nearest parent (creator) assembly which has a nonempty path.
3977 const SString &PEAssembly::GetEffectivePath()
3988 PEAssembly *pAssembly = this;
3990 while (pAssembly->m_identity == NULL
3991 || pAssembly->m_identity->GetPath().IsEmpty())
3993 if (pAssembly->m_creator)
3994 pAssembly = pAssembly->m_creator->GetAssembly();
3995 else // Unmanaged exe which loads byte[]/IStream assemblies
3996 return SString::Empty();
3999 return pAssembly->m_identity->GetPath();
4003 // Codebase is the fusion codebase or path for the assembly. It is in URL format.
4004 // Note this may be obtained from the parent PEFile if we don't have a path or fusion
4007 // fCopiedName means to get the "shadow copied" path rather than the original path, if applicable
4008 void PEAssembly::GetCodeBase(SString &result, BOOL fCopiedName/*=FALSE*/)
4016 INJECT_FAULT(COMPlusThrowOM(););
4019 #ifdef FEATURE_FUSION
4020 // For a copied name, we always use the actual file path rather than the fusion info
4021 if (!fCopiedName && m_pFusionAssembly)
4023 if ( ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_RUN_FROM_SOURCE) ||
4024 ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_DOWNLOAD_CACHE) )
4026 // Assemblies in the download cache or run from source should have
4027 // a proper codebase set in them.
4028 FusionBind::GetAssemblyNameStringProperty(GetFusionAssemblyName(),
4029 ASM_NAME_CODEBASE_URL,
4034 else if (m_pIHostAssembly)
4036 FusionBind::GetAssemblyNameStringProperty(GetFusionAssemblyName(),
4037 ASM_NAME_CODEBASE_URL,
4043 // All other cases use the file path.
4044 result.Set(GetEffectivePath());
4045 if (!result.IsEmpty())
4050 void PEAssembly::PathToUrl(SString &string)
4054 PRECONDITION(PEImage::CheckCanonicalFullPath(string));
4058 INJECT_FAULT(COMPlusThrowOM(););
4062 SString::Iterator i = string.Begin();
4064 #if !defined(PLATFORM_UNIX)
4065 if (i[0] == W('\\'))
4068 string.Insert(i, SL("file://"));
4069 string.Skip(i, SL("file://"));
4074 string.Insert(i, SL("file:///"));
4075 string.Skip(i, SL("file:///"));
4078 // Unix doesn't have a distinction between a network or a local path
4079 _ASSERTE( i[0] == W('\\') || i[0] == W('/'));
4080 SString sss(SString::Literal, W("file://"));
4081 string.Insert(i, sss);
4082 string.Skip(i, sss);
4085 while (string.Find(i, W('\\')))
4087 string.Replace(i, W('/'));
4091 void PEAssembly::UrlToPath(SString &string)
4100 SString::Iterator i = string.Begin();
4102 SString sss2(SString::Literal, W("file://"));
4103 #if !defined(PLATFORM_UNIX)
4104 SString sss3(SString::Literal, W("file:///"));
4105 if (string.MatchCaseInsensitive(i, sss3))
4106 string.Delete(i, 8);
4109 if (string.MatchCaseInsensitive(i, sss2))
4110 string.Delete(i, 7);
4112 while (string.Find(i, W('/')))
4114 string.Replace(i, W('\\'));
4120 BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i)
4122 #ifdef PLATFORM_UNIX
4123 SString::Iterator slash = i;
4124 SString::Iterator backSlash = i;
4125 BOOL foundSlash = path.FindBack(slash, '/');
4126 BOOL foundBackSlash = path.FindBack(backSlash, '\\');
4127 if (!foundSlash && !foundBackSlash)
4129 else if (foundSlash && !foundBackSlash)
4131 else if (!foundSlash && foundBackSlash)
4134 i = (backSlash > slash) ? backSlash : slash;
4137 return path.FindBack(i, '\\');
4138 #endif //PLATFORM_UNIX
4142 // ------------------------------------------------------------
4144 // ------------------------------------------------------------
4145 #ifdef FEATURE_PREJIT
4146 void PEAssembly::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
4155 PEFile::ExternalVLog(facility, level, fmt, args);
4157 #ifdef FEATURE_FUSION
4158 if (FusionLoggingEnabled())
4160 DWORD dwLogCategory = (facility == LF_ZAP ? FUSION_BIND_LOG_CATEGORY_NGEN : FUSION_BIND_LOG_CATEGORY_DEFAULT);
4162 StackSString message;
4163 message.VPrintf(fmt, args);
4164 m_pFusionLog->LogMessage(0, dwLogCategory, message);
4166 if (level == LL_ERROR) {
4167 m_pFusionLog->SetResultCode(dwLogCategory, E_FAIL);
4171 #endif //FEATURE_FUSION
4176 void PEAssembly::FlushExternalLog()
4185 #ifdef FEATURE_FUSION
4186 if (FusionLoggingEnabled()) {
4187 m_pFusionLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_NGEN);
4188 m_pFusionLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_DEFAULT);
4190 #endif //FEATURE_FUSION
4194 #endif //FEATURE_PREJIT
4195 // ------------------------------------------------------------
4197 // ------------------------------------------------------------
4199 HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
4204 PRECONDITION(CheckPointer(pMajor, NULL_OK));
4205 PRECONDITION(CheckPointer(pMinor, NULL_OK));
4206 PRECONDITION(CheckPointer(pBuild, NULL_OK));
4207 PRECONDITION(CheckPointer(pRevision, NULL_OK));
4209 WRAPPER(GC_TRIGGERS);
4214 AssemblyMetaDataInternal md;
4216 if (m_bHasPersistentMDImport)
4218 _ASSERTE(GetPersistentMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly)));
4219 IfFailRet(GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
4223 ReleaseHolder<IMDInternalImport> pImport(GetMDImportWithRef());
4224 _ASSERTE(pImport->IsValidToken(TokenFromRid(1, mdtAssembly)));
4225 IfFailRet(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
4229 *pMajor = md.usMajorVersion;
4231 *pMinor = md.usMinorVersion;
4233 *pBuild = md.usBuildNumber;
4234 if (pRevision != NULL)
4235 *pRevision = md.usRevisionNumber;
4240 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
4241 // ================================================================================
4242 // PEModule class - a PEFile which represents a satellite module
4243 // ================================================================================
4245 PEModule::PEModule(PEImage *image, PEAssembly *assembly, mdFile token, IMetaDataEmit *pEmit)
4253 PRECONDITION(CheckPointer(image, NULL_OK));
4254 PRECONDITION(CheckPointer(assembly));
4255 PRECONDITION(!IsNilToken(token));
4256 PRECONDITION(CheckPointer(pEmit, NULL_OK));
4257 PRECONDITION(image != NULL || pEmit != NULL);
4265 // get only the data which is required, here - flags
4266 // this helps avoid unnecessary memory touches
4267 IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, NULL, NULL, &flags));
4271 if (IsFfContainsMetaData(flags) && !image->CheckILFormat())
4272 ThrowHR(COR_E_BADIMAGEFORMAT);
4274 if (assembly->IsIStream())
4276 m_flags |= PEFILE_ISTREAM;
4277 #ifdef FEATURE_PREJIT
4278 m_fCanUseNativeImage = FALSE;
4285 m_assembly = assembly;
4287 m_flags |= PEFILE_MODULE;
4288 if (assembly->IsSystem())
4290 m_flags |= PEFILE_SYSTEM;
4294 if (assembly->IsIntrospectionOnly())
4296 m_flags |= PEFILE_INTROSPECTIONONLY;
4297 #ifdef FEATURE_PREJIT
4298 SetCannotUseNativeImage();
4304 // Verify module format. Note that some things have already happened:
4305 // - Fusion has verified the name matches the metadata
4306 // - PEimage has performed PE file format validation
4308 if (assembly->NeedsModuleHashChecks())
4312 IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, &hash, &size, NULL));
4314 if (!CheckHash(assembly->GetHashAlgId(), hash, size))
4315 ThrowHR(COR_E_MODULE_HASH_CHECK_FAILED);
4318 #if defined(FEATURE_PREJIT) && !defined(CROSSGEN_COMPILE)
4319 // Find the native image
4320 if (IsFfContainsMetaData(flags)
4321 && m_fCanUseNativeImage
4322 && assembly->HasNativeImage()
4323 && assembly->GetFusionAssembly() != NULL)
4325 IAssemblyLocation *pIAssemblyLocation = assembly->GetNativeAssemblyLocation();
4327 WCHAR wzPath[MAX_LONGPATH];
4328 WCHAR *pwzTemp = NULL;
4329 DWORD dwCCPath = MAX_LONGPATH;
4331 SString moduleName(SString::Utf8, GetSimpleName());
4333 // Compute the module path from the manifest module path
4334 IfFailThrow(pIAssemblyLocation->GetPath(wzPath, &dwCCPath));
4335 pwzTemp = PathFindFileName(wzPath);
4336 *pwzTemp = (WCHAR) 0x00;
4338 // <TODO>@todo: GetAppDomain????</TODO>
4340 path.Append((LPCWSTR) moduleName);
4342 SetNativeImage(path);
4344 #endif // FEATURE_PREJIT && !CROSSGEN_COMPILE
4347 GetCodeBaseOrName(m_debugName);
4348 m_pDebugName = m_debugName;
4351 if (IsFfContainsMetaData(flags))
4355 OpenMDImport_Unsafe(); //constructor. cannot race with anything
4359 _ASSERTE(!m_bHasPersistentMDImport);
4360 IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
4361 (void **)&m_pMDImport));
4364 m_bHasPersistentMDImport=TRUE;
4365 m_MDImportIsRW_Debugger_Use_Only = TRUE;
4368 // Fusion probably checks this, but we need to check this ourselves if
4369 // this file didn't come from Fusion
4370 if (!m_pMDImport->IsValidToken(m_pMDImport->GetModuleFromScope()))
4371 COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
4375 // Go ahead and "load" image since it is essentially a noop, but will enable
4376 // more operations on the module earlier in the loading process.
4379 #ifdef FEATURE_PREJIT
4380 if (IsResource() || IsDynamic())
4381 m_fCanUseNativeImage = FALSE;
4385 PEModule::~PEModule()
4395 m_assembly->Release();
4399 PEModule *PEModule::Open(PEAssembly *assembly, mdFile token,
4400 const SString &fileName)
4402 STANDARD_VM_CONTRACT;
4404 PEModule *result = NULL;
4408 result = DoOpen(assembly, token, fileName);
4412 Exception *ex = GET_EXCEPTION();
4414 // Rethrow non-transient exceptions as file load exceptions with proper
4417 if (!ex->IsTransient())
4418 EEFileLoadException::Throw(fileName, ex->GetHR(), ex);
4425 class DoOpenPathStress : APIThreadStress
4428 PEAssembly *assembly;
4430 const SString &fileName;
4431 DoOpenPathStress(PEAssembly *assembly, mdFile token,
4432 const SString &fileName)
4433 : assembly(assembly), token(token), fileName(fileName)
4435 WRAPPER_NO_CONTRACT;
4436 fileName.Normalize();
4440 WRAPPER_NO_CONTRACT;
4441 PEModuleHolder result(PEModule::Open(assembly, token, fileName));
4446 PEModule *PEModule::DoOpen(PEAssembly *assembly, mdFile token,
4447 const SString &fileName)
4449 CONTRACT(PEModule *)
4451 PRECONDITION(CheckPointer(assembly));
4452 PRECONDITION(CheckValue(fileName));
4453 PRECONDITION(!IsNilToken(token));
4454 PRECONDITION(!fileName.IsEmpty());
4455 POSTCONDITION(CheckPointer(RETVAL));
4460 DoOpenPathStress ts(assembly, token, fileName);
4462 // If this is a resource module, we must explicitly request a flat mapping
4464 IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, NULL, NULL, &flags));
4466 PEImageHolder image;
4467 #ifdef FEATURE_FUSION
4468 if (assembly->IsIStream())
4470 SafeComHolder<IHostAssemblyModuleImport> pModuleImport;
4471 IfFailThrow(assembly->GetIHostAssembly()->GetModuleByName(fileName, &pModuleImport));
4473 SafeComHolder<IStream> pIStream;
4474 IfFailThrow(pModuleImport->GetModuleStream(&pIStream));
4477 IfFailThrow(pModuleImport->GetModuleId(&dwModuleId));
4478 image = PEImage::OpenImage(pIStream, assembly->m_identity->m_StreamAsmId,
4479 dwModuleId, (flags & ffContainsNoMetaData));
4484 image = PEImage::OpenImage(fileName);
4487 if (flags & ffContainsNoMetaData)
4488 image->LoadNoMetaData(assembly->IsIntrospectionOnly());
4490 PEModuleHolder module(new PEModule(image, assembly, token, NULL));
4492 RETURN module.Extract();
4496 PEModule *PEModule::OpenMemory(PEAssembly *assembly, mdFile token,
4497 const void *flat, COUNT_T size)
4499 STANDARD_VM_CONTRACT;
4501 PEModule *result = NULL;
4505 result = DoOpenMemory(assembly, token, flat, size);
4509 Exception *ex = GET_EXCEPTION();
4511 // Rethrow non-transient exceptions as file load exceptions with proper
4513 if (!ex->IsTransient())
4514 EEFileLoadException::Throw(assembly, flat, size, ex->GetHR(), ex);
4521 class DoOpenTokenStress : APIThreadStress
4524 PEAssembly *assembly;
4528 DoOpenTokenStress(PEAssembly *assembly, mdFile token,
4529 const void *flat, COUNT_T size)
4530 : assembly(assembly), token(token), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
4533 WRAPPER_NO_CONTRACT;
4534 PEModuleHolder result(PEModule::OpenMemory(assembly, token, flat, size));
4538 // REVIEW: do we need to know the creator module which emitted the module (separately
4539 // from the assembly parent) for security reasons?
4541 PEModule *PEModule::DoOpenMemory(PEAssembly *assembly, mdFile token,
4542 const void *flat, COUNT_T size)
4544 CONTRACT(PEModule *)
4546 PRECONDITION(CheckPointer(assembly));
4547 PRECONDITION(!IsNilToken(token));
4548 PRECONDITION(CheckPointer(flat));
4549 POSTCONDITION(CheckPointer(RETVAL));
4553 INJECT_FAULT(COMPlusThrowOM(););
4557 DoOpenTokenStress ts(assembly, token, flat, size);
4559 PEImageHolder image(PEImage::LoadFlat(flat, size));
4561 RETURN new PEModule(image, assembly, token, NULL);
4565 PEModule *PEModule::Create(PEAssembly *assembly, mdFile token, IMetaDataEmit *pEmit)
4567 CONTRACT(PEModule *)
4569 PRECONDITION(CheckPointer(assembly));
4570 PRECONDITION(!IsNilToken(token));
4572 POSTCONDITION(CheckPointer(RETVAL));
4576 RETURN new PEModule(NULL, assembly, token, pEmit);
4579 // ------------------------------------------------------------
4581 // ------------------------------------------------------------
4582 #ifdef FEATURE_PREJIT
4583 void PEModule::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
4592 m_assembly->ExternalVLog(facility, level, fmt, args);
4597 void PEModule::FlushExternalLog()
4606 m_assembly->FlushExternalLog();
4611 // ------------------------------------------------------------
4612 // Loader support routines
4613 // ------------------------------------------------------------
4614 void PEModule::SetNativeImage(const SString &fullPath)
4619 PRECONDITION(CheckValue(fullPath));
4620 PRECONDITION(!fullPath.IsEmpty());
4625 PEImageHolder image(PEImage::OpenImage(fullPath));
4628 PEFile::SetNativeImage(image);
4630 #endif // FEATURE_PREJIT
4632 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
4635 void PEFile::EnsureImageOpened()
4637 WRAPPER_NO_CONTRACT;
4640 #ifdef FEATURE_PREJIT
4641 if(HasNativeImage())
4642 m_nativeImage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
4645 GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
4648 #endif // #ifndef DACCESS_COMPILE
4650 #ifdef DACCESS_COMPILE
4653 PEFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4655 WRAPPER_NO_CONTRACT;
4658 // sizeof(PEFile) == 0xb8
4660 EMEM_OUT(("MEM: %p PEFile\n", dac_cast<TADDR>(this)));
4663 // Not a big deal if it's NULL or fails.
4664 m_debugName.EnumMemoryRegions(flags);
4667 if (m_identity.IsValid())
4669 m_identity->EnumMemoryRegions(flags);
4671 if (GetILimage().IsValid())
4673 GetILimage()->EnumMemoryRegions(flags);
4675 #ifdef FEATURE_PREJIT
4676 if (m_nativeImage.IsValid())
4678 m_nativeImage->EnumMemoryRegions(flags);
4679 DacEnumHostDPtrMem(m_nativeImage->GetLoadedLayout()->GetNativeVersionInfo());
4685 PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4687 WRAPPER_NO_CONTRACT;
4689 PEFile::EnumMemoryRegions(flags);
4691 if (m_creator.IsValid())
4693 m_creator->EnumMemoryRegions(flags);
4697 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
4699 PEModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4701 WRAPPER_NO_CONTRACT;
4703 PEFile::EnumMemoryRegions(flags);
4705 if (m_assembly.IsValid())
4707 m_assembly->EnumMemoryRegions(flags);
4710 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
4711 #endif // #ifdef DACCESS_COMPILE
4714 //-------------------------------------------------------------------------------
4715 // Make best-case effort to obtain an image name for use in an error message.
4717 // This routine must expect to be called before the this object is fully loaded.
4718 // It can return an empty if the name isn't available or the object isn't initialized
4719 // enough to get a name, but it mustn't crash.
4720 //-------------------------------------------------------------------------------
4721 LPCWSTR PEFile::GetPathForErrorMessages()
4727 INJECT_FAULT(COMPlusThrowOM(););
4728 SUPPORTS_DAC_HOST_ONLY;
4734 return m_identity->GetPathForErrorMessages();
4743 #ifdef DACCESS_COMPILE
4744 TADDR PEFile::GetMDInternalRWAddress()
4746 if (!m_MDImportIsRW_Debugger_Use_Only)
4750 // This line of code is a bit scary, but it is correct for now at least...
4751 // 1) We are using 'm_pMDImport_Use_Accessor' directly, and not the accessor. The field is
4752 // named this way to prevent debugger code that wants a host implementation of IMDInternalImport
4753 // from accidentally trying to use this pointer. This pointer is a target pointer, not
4754 // a host pointer. However in this function we do want the target pointer, so the usage is
4756 // 2) ASSUMPTION: We are assuming that the only valid implementation of RW metadata is
4757 // MDInternalRW. If that ever changes we would need some way to disambiguate, and
4758 // probably this entire code path would need to be redesigned.
4759 // 3) ASSUMPTION: We are assuming that no pointer adjustment is required to convert between
4760 // IMDInternalImport*, IMDInternalImportENC* and MDInternalRW*. Ideally I was hoping to do this with a
4761 // static_cast<> but the compiler complains that the ENC<->RW is an unrelated conversion.
4762 return (TADDR) m_pMDImport_UseAccessor;
4767 // Returns the ICLRPrivBinder* instance associated with the PEFile
4768 PTR_ICLRPrivBinder PEFile::GetBindingContext()
4770 LIMITED_METHOD_CONTRACT;
4772 PTR_ICLRPrivBinder pBindingContext = NULL;
4774 // Mscorlib is always bound in context of the TPA Binder. However, since it gets loaded and published
4775 // during EEStartup *before* TPAbinder is initialized, we dont have a binding context to publish against.
4776 // Thus, we will always return NULL for its binding context.
4779 pBindingContext = dac_cast<PTR_ICLRPrivBinder>(GetHostAssembly());
4782 return pBindingContext;