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"
18 #include "product_version.h"
19 #include "eventtrace.h"
22 #include "dbginterface.h"
23 #include "peimagelayout.inl"
25 #include "invokeutil.h"
29 #include "strongnameinternal.h"
31 #include "../binder/inc/applicationcontext.hpp"
33 #include "clrprivbinderutil.h"
34 #include "../binder/inc/coreclrbindercommon.h"
40 #ifdef DEBUGGING_SUPPORTED
41 SVAL_IMPL_INIT(DWORD, PEFile, s_NGENDebugFlags, 0);
48 #ifndef DACCESS_COMPILE
50 // ================================================================================
51 // PEFile class - this is an abstract base class for PEModule and PEAssembly
52 // <TODO>@todo: rename TargetFile</TODO>
53 // ================================================================================
55 PEFile::PEFile(PEImage *identity, BOOL fCheckAuthenticodeSignature/*=TRUE*/) :
60 m_openedILimage(NULL),
63 m_fCanUseNativeImage(TRUE),
65 m_MDImportIsRW_Debugger_Use_Only(FALSE),
66 m_bHasPersistentMDImport(FALSE),
70 m_pMetadataLock(::new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)),
74 m_fStrongNameVerified(FALSE)
75 ,m_pHostAssembly(nullptr)
76 ,m_pFallbackLoadContextBinder(nullptr)
90 m_identity = identity;
92 if(identity->IsOpened())
94 //already opened, prepopulate
96 m_openedILimage = identity;
116 ReleaseMetadataInterfaces(TRUE);
121 #ifdef FEATURE_PREJIT
122 if (m_nativeImage != NULL)
124 MarkNativeImageInvalidIfOwned();
126 m_nativeImage->Release();
128 #endif //FEATURE_PREJIT
131 if (m_openedILimage != NULL)
132 m_openedILimage->Release();
133 if (m_identity != NULL)
134 m_identity->Release();
136 delete m_pMetadataLock;
138 if (m_pHostAssembly != NULL)
140 m_pHostAssembly->Release();
144 #ifndef DACCESS_COMPILE
145 void PEFile::ReleaseIL()
148 if (m_openedILimage!=NULL )
150 ReleaseMetadataInterfaces(TRUE, TRUE);
151 if (m_identity != NULL)
153 m_identity->Release();
156 m_openedILimage->Release();
157 m_openedILimage = NULL;
163 PEFile *PEFile::Open(PEImage *image)
167 PRECONDITION(image != NULL);
168 PRECONDITION(image->CheckFormat());
169 POSTCONDITION(RETVAL != NULL);
170 POSTCONDITION(!RETVAL->IsModule());
171 POSTCONDITION(!RETVAL->IsAssembly());
175 INJECT_FAULT(COMPlusThrowOM(););
179 PEFile *pFile = new PEFile(image, FALSE);
181 if (image->HasNTHeaders() && image->HasCorHeader())
182 pFile->OpenMDImport_Unsafe(); //no one else can see the object yet
185 pFile->m_debugName = image->GetPath();
186 pFile->m_debugName.Normalize();
187 pFile->m_pDebugName = pFile->m_debugName;
193 // ------------------------------------------------------------
194 // Loader support routines
195 // ------------------------------------------------------------
197 template<class T> void CoTaskFree(T *p)
208 NEW_WRAPPER_TEMPLATE1(CoTaskNewHolder, CoTaskFree<_TYPE>);
210 BOOL PEFile::CanLoadLibrary()
214 // Dynamic and resource modules don't need LoadLibrary.
215 if (IsDynamic() || IsResource()||IsLoaded())
218 // If we're been granted skip verification, OK
219 if (HasSkipVerification())
222 // Otherwise, we can only load if IL only.
228 //-----------------------------------------------------------------------------------------------------
229 // Catch attempts to load x64 assemblies on x86, etc.
230 //-----------------------------------------------------------------------------------------------------
231 static void ValidatePEFileMachineType(PEFile *peFile)
233 STANDARD_VM_CONTRACT;
235 if (peFile->IsIntrospectionOnly())
236 return; // ReflectionOnly assemblies permitted to violate CPU restrictions
238 if (peFile->IsDynamic())
239 return; // PEFiles for ReflectionEmit assemblies don't cache the machine type.
241 if (peFile->IsResource())
242 return; // PEFiles for resource assemblies don't cache the machine type.
244 if (peFile->HasNativeImage())
245 return; // If it passed the native binder, no need to do the check again esp. at the risk of inviting an IL page-in.
248 DWORD actualMachineType;
249 peFile->GetPEKindAndMachine(&peKind, &actualMachineType);
251 if (actualMachineType == IMAGE_FILE_MACHINE_I386 && ((peKind & (peILonly | pe32BitRequired)) == peILonly))
252 return; // Image is marked CPU-agnostic.
254 if (actualMachineType != IMAGE_FILE_MACHINE_NATIVE && actualMachineType != IMAGE_FILE_MACHINE_NATIVE_NI)
256 #ifdef _TARGET_AMD64_
257 // 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
258 // 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.
260 // 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.
261 // Or to put it another way, this #ifdef makes the (4.5 only) ValidatePEFileMachineType() a NOP for x64, hence preserving 4.0 compatibility.
262 if (actualMachineType == IMAGE_FILE_MACHINE_I386 || actualMachineType == IMAGE_FILE_MACHINE_IA64)
266 // Image has required machine that doesn't match the CLR.
268 if (peFile->IsAssembly())
269 ((PEAssembly*)peFile)->GetDisplayName(name);
271 name = StackSString(SString::Utf8, peFile->GetSimpleName());
273 COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode());
276 return; // If we got here, all is good.
279 void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load
284 POSTCONDITION(CheckLoaded());
289 // Catch attempts to load x64 assemblies on x86, etc.
290 ValidatePEFileMachineType(this);
292 // See if we've already loaded it.
293 if (CheckLoaded(allowNativeSkip))
298 // Note that we may be racing other threads here, in the case of domain neutral files
300 // Resource images are always flat.
303 GetILimage()->LoadNoMetaData(IsIntrospectionOnly());
308 if (!HasNativeImage() && (!GetILimage()->Has32BitNTHeaders()) && !IsIntrospectionOnly())
310 // Tried to load 64-bit assembly on 32-bit platform.
311 EEFileLoadException::Throw(this, COR_E_BADIMAGEFORMAT, NULL);
315 // Don't do this if we are unverifiable
316 if (!CanLoadLibrary())
317 ThrowHR(SECURITY_E_UNVERIFIABLE);
320 // We need contents now
321 if (!HasNativeImage())
326 if (IsIntrospectionOnly())
328 GetILimage()->LoadForIntrospection();
333 //---- Below this point, only do the things necessary for execution ----
334 _ASSERTE(!IsIntrospectionOnly());
336 #ifdef FEATURE_PREJIT
337 // For on-disk Dlls, we can call LoadLibrary
338 if (IsDll() && !((HasNativeImage()?m_nativeImage:GetILimage())->GetPath().IsEmpty()))
340 // Note that we may get a DllMain notification inside here.
341 if (allowNativeSkip && HasNativeImage())
343 m_nativeImage->Load();
344 if(!m_nativeImage->IsNativeILILOnly())
345 GetILimage()->Load(); // For IJW we have to load IL also...
348 GetILimage()->Load();
351 #endif // FEATURE_PREJIT
354 // Since we couldn't call LoadLibrary, we must be an IL only image
355 // or the image may still contain unfixed up stuff
356 // Note that we make an exception for CompilationDomains, since PEImage
357 // will map non-ILOnly images in a compilation domain.
358 if (!GetILimage()->IsILOnly() && !GetAppDomain()->IsCompilationDomain())
360 if (!GetILimage()->HasV1Metadata())
361 ThrowHR(COR_E_FIXUPSINEXE); // <TODO>@todo: better error</TODO>
366 // If we are already mapped, we can just use the current image.
367 #ifdef FEATURE_PREJIT
368 if (allowNativeSkip && HasNativeImage())
370 m_nativeImage->LoadFromMapped();
372 if( !m_nativeImage->IsNativeILILOnly())
373 GetILimage()->LoadFromMapped(); // For IJW we have to load IL also...
378 if (GetILimage()->IsFile())
379 GetILimage()->LoadFromMapped();
381 GetILimage()->LoadNoFile();
389 void PEFile::SetLoadedHMODULE(HMODULE hMod)
394 PRECONDITION(CheckPointer(hMod));
395 PRECONDITION(CanLoadLibrary());
396 POSTCONDITION(CheckLoaded());
400 INJECT_FAULT(COMPlusThrowOM(););
404 // See if the image is an internal PEImage.
405 GetILimage()->SetLoadedHMODULE(hMod);
411 void PEFile::DefineEmitScope(
417 PRECONDITION(CheckPointer(ppEmit));
418 POSTCONDITION(CheckPointer(*ppEmit));
422 INJECT_FAULT(COMPlusThrowOM(););
426 SafeComHolder<IMetaDataDispenserEx> pDispenser;
428 // Get the Dispenser interface.
429 MetaDataGetDispenser(
430 CLSID_CorMetaDataDispenser,
431 IID_IMetaDataDispenserEx,
432 (void **)&pDispenser);
433 if (pDispenser == NULL)
438 // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef
440 V_VT(&varOption) = VT_UI4;
441 V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile;
442 IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption));
444 // Set minimal MetaData size
445 V_VT(&varOption) = VT_UI4;
446 V_I4(&varOption) = MDInitialSizeMinimal;
447 IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption));
449 // turn on the thread safety!
450 V_I4(&varOption) = MDThreadSafetyOn;
451 IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption));
453 IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown **)ppEmit));
456 } // PEFile::DefineEmitScope
458 // ------------------------------------------------------------
460 // ------------------------------------------------------------
462 BOOL PEFile::Equals(PEFile *pFile)
467 PRECONDITION(CheckPointer(pFile));
475 // Same object is equal
480 // Execution and introspection files are NOT equal
481 if ( (!IsIntrospectionOnly()) != !(pFile->IsIntrospectionOnly()) )
486 // Different host assemblies cannot be equal unless they are associated with the same host binder
487 // It's ok if only one has a host binder because multiple threads can race to load the same assembly
488 // and that may cause temporary candidate PEAssembly objects that never get bound to a host assembly
489 // because another thread beats it; the losing thread will pick up the PEAssembly in the cache.
490 if (pFile->HasHostAssembly() && this->HasHostAssembly())
492 UINT_PTR fileBinderId = 0;
493 if (FAILED(pFile->GetHostAssembly()->GetBinderID(&fileBinderId)))
496 UINT_PTR thisBinderId = 0;
497 if (FAILED(this->GetHostAssembly()->GetBinderID(&thisBinderId)))
500 if (fileBinderId != thisBinderId)
505 // Same identity is equal
506 if (m_identity != NULL && pFile->m_identity != NULL
507 && m_identity->Equals(pFile->m_identity))
510 // Same image is equal
511 if (m_openedILimage != NULL && pFile->m_openedILimage != NULL
512 && m_openedILimage->Equals(pFile->m_openedILimage))
518 BOOL PEFile::Equals(PEImage *pImage)
523 PRECONDITION(CheckPointer(pImage));
530 // Same object is equal
531 if (pImage == m_identity || pImage == m_openedILimage)
534 #ifdef FEATURE_PREJIT
535 if(pImage == m_nativeImage)
538 // Same identity is equal
539 if (m_identity != NULL
540 && m_identity->Equals(pImage))
543 // Same image is equal
544 if (m_openedILimage != NULL
545 && m_openedILimage->Equals(pImage))
552 // ------------------------------------------------------------
553 // Descriptive strings
554 // ------------------------------------------------------------
556 void PEFile::GetCodeBaseOrName(SString &result)
564 INJECT_FAULT(COMPlusThrowOM(););
568 if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
570 result.Set(m_identity->GetPath());
572 else if (IsAssembly())
574 ((PEAssembly*)this)->GetCodeBase(result);
577 result.SetUTF8(GetSimpleName());
581 // ------------------------------------------------------------
583 // ------------------------------------------------------------
587 CHECK PEFile::CheckLoaded(BOOL bAllowNativeSkip/*=TRUE*/)
599 CHECK(IsLoaded(bAllowNativeSkip)
600 // We are allowed to skip LoadLibrary in most cases for ngen'ed IL only images
601 || (bAllowNativeSkip && HasNativeImage() && IsILOnly()));
607 // ------------------------------------------------------------
609 // ------------------------------------------------------------
611 PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize)
616 POSTCONDITION(CheckPointer(pSize, NULL_OK));
617 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
625 #ifdef FEATURE_PREJIT
626 if (HasNativeImageMetadata())
628 RETURN m_nativeImage->GetMetadata(pSize);
633 || !GetILimage()->HasNTHeaders()
634 || !GetILimage()->HasCorHeader())
642 RETURN GetILimage()->GetMetadata(pSize);
645 #endif // #ifndef DACCESS_COMPILE
647 PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize)
652 POSTCONDITION(CheckPointer(pSize, NULL_OK));
653 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
661 #ifdef FEATURE_PREJIT
662 if (HasNativeImageMetadata())
664 RETURN GetLoadedNative()->GetMetadata(pSize);
669 || !GetLoadedIL()->HasNTHeaders()
670 || !GetLoadedIL()->HasCorHeader())
678 RETURN GetLoadedIL()->GetMetadata(pSize);
682 TADDR PEFile::GetIL(RVA il)
687 PRECONDITION(il != 0);
688 PRECONDITION(!IsDynamic());
689 PRECONDITION(!IsResource());
690 #ifndef DACCESS_COMPILE
691 PRECONDITION(CheckLoaded());
693 POSTCONDITION(RETVAL != NULL);
701 PEImageLayout *image = NULL;
703 #ifdef FEATURE_PREJIT
704 // Note it is important to get the IL from the native image if
705 // available, since we are using the metadata from the native image
706 // which has different IL rva's.
707 if (HasNativeImageMetadata())
709 image = GetLoadedNative();
711 #ifndef DACCESS_COMPILE
712 // NGen images are trusted to be well-formed.
713 _ASSERTE(image->CheckILMethod(il));
717 #endif // FEATURE_PREJIT
719 image = GetLoadedIL();
721 #ifndef DACCESS_COMPILE
722 // Verify that the IL blob is valid before giving it out
723 if (!image->CheckILMethod(il))
724 COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL_RANGE);
728 RETURN image->GetRvaData(il);
731 #ifndef DACCESS_COMPILE
733 void PEFile::OpenImporter()
741 INJECT_FAULT(COMPlusThrowOM(););
745 // Make sure internal MD is in RW format.
746 ConvertMDInternalToReadWrite();
748 IMetaDataImport2 *pIMDImport = NULL;
749 IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
750 IID_IMetaDataImport2,
751 (void **)&pIMDImport));
753 // Atomically swap it into the field (release it if we lose the race)
754 if (FastInterlockCompareExchangePointer(&m_pImporter, pIMDImport, NULL) != NULL)
755 pIMDImport->Release();
758 void PEFile::ConvertMDInternalToReadWrite()
766 INJECT_FAULT(EX_THROW(EEMessageException, (E_OUTOFMEMORY)););
770 IMDInternalImport *pOld; // Old (current RO) value of internal import.
771 IMDInternalImport *pNew = NULL; // New (RW) value of internal import.
773 // Take a local copy of *ppImport. This may be a pointer to an RO
774 // or to an RW MDInternalXX.
776 IMetaDataImport *pIMDImport = m_pImporter;
777 if (pIMDImport != NULL)
779 HRESULT hr = GetMetaDataInternalInterfaceFromPublic(pIMDImport, IID_IMDInternalImport, (void **)&pNew);
782 EX_THROW(EEMessageException, (hr));
792 // If an RO, convert to an RW, return S_OK. If already RW, no conversion
793 // needed, return S_FALSE.
794 HRESULT hr = ConvertMDInternalImport(pOld, &pNew);
798 EX_THROW(EEMessageException, (hr));
801 // If no conversion took place, don't change pointers.
806 // Swap the pointers in a thread safe manner. If the contents of *ppImport
807 // equals pOld then no other thread got here first, and the old contents are
808 // replaced with pNew. The old contents are returned.
809 _ASSERTE(m_bHasPersistentMDImport);
810 if (FastInterlockCompareExchangePointer(&m_pMDImport, pNew, pOld) == pOld)
812 //if the debugger queries, it will now see that we have RW metadata
813 m_MDImportIsRW_Debugger_Use_Only = TRUE;
815 // Swapped -- get the metadata to hang onto the old Internal import.
816 HRESULT hr=m_pMDImport->SetUserContextData(pOld);
817 _ASSERTE(SUCCEEDED(hr)||!"Leaking old MDImport");
821 { // Some other thread finished first. Just free the results of this conversion.
826 void PEFile::ConvertMetadataToRWForEnC()
837 // This should only ever be called on EnC capable files.
838 // One can check this using Module::IsEditAndContinueCapable().
840 // This should only be called if we're debugging, stopped, and on the helper thread.
841 _ASSERTE(CORDebuggerAttached());
842 _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->ThisIsHelperThread());
843 _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->IsStopped());
845 // Convert the metadata to RW for Edit and Continue, properly replacing the metadata import interface pointer and
846 // properly preserving the old importer. This will be called before the EnC system tries to apply a delta to the module's
847 // metadata. ConvertMDInternalToReadWrite() does that quite nicely for us.
848 ConvertMDInternalToReadWrite();
851 void PEFile::OpenMDImport_Unsafe()
859 INJECT_FAULT(COMPlusThrowOM(););
863 if (m_pMDImport != NULL)
865 #ifdef FEATURE_PREJIT
866 if (m_nativeImage != NULL
867 && m_nativeImage->GetMDImport() != NULL
870 // Use native image for metadata
871 m_flags |= PEFILE_HAS_NATIVE_IMAGE_METADATA;
872 m_pMDImport=m_nativeImage->GetMDImport();
877 #ifdef FEATURE_PREJIT
878 m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
881 && GetILimage()->HasNTHeaders()
882 && GetILimage()->HasCorHeader())
884 m_pMDImport=GetILimage()->GetMDImport();
887 ThrowHR(COR_E_BADIMAGEFORMAT);
889 m_bHasPersistentMDImport=TRUE;
891 _ASSERTE(m_pMDImport);
892 m_pMDImport->AddRef();
895 void PEFile::OpenEmitter()
903 INJECT_FAULT(COMPlusThrowOM(););
907 // Make sure internal MD is in RW format.
908 ConvertMDInternalToReadWrite();
910 IMetaDataEmit *pIMDEmit = NULL;
911 IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
913 (void **)&pIMDEmit));
915 // Atomically swap it into the field (release it if we lose the race)
916 if (FastInterlockCompareExchangePointer(&m_pEmitter, pIMDEmit, NULL) != NULL)
921 void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor, BOOL bKeepNativeData/*=FALSE*/)
929 PRECONDITION(bDestructor||m_pMetadataLock->IsWriterLock());
932 _ASSERTE(bDestructor || !m_bHasPersistentMDImport);
934 if (m_pImporter != NULL)
936 m_pImporter->Release();
939 if (m_pEmitter != NULL)
941 m_pEmitter->Release();
945 if (m_pMDImport != NULL && (!bKeepNativeData || !HasNativeImage()))
947 m_pMDImport->Release();
953 // ------------------------------------------------------------
955 // ------------------------------------------------------------
957 // Note that most of these APIs are currently passed through
958 // to the main image. However, in the near future they will
959 // be rerouted to the native image in the prejitted case so
960 // we can avoid using the original IL image.
962 #endif //!DACCESS_COMPILE
964 #ifdef FEATURE_PREJIT
965 #ifndef DACCESS_COMPILE
966 // ------------------------------------------------------------
967 // Native image access
968 // ------------------------------------------------------------
970 void PEFile::SetNativeImage(PEImage *image)
975 PRECONDITION(!HasNativeImage());
980 _ASSERTE(image != NULL);
981 PREFIX_ASSUME(image != NULL);
983 if (image->GetLoadedLayout()->GetBase() != image->GetLoadedLayout()->GetPreferredBase())
985 ExternalLog(LL_WARNING,
986 W("Native image loaded at base address") LFMT_ADDR
987 W("rather than preferred address:") LFMT_ADDR ,
988 DBG_ADDR(image->GetLoadedLayout()->GetBase()),
989 DBG_ADDR(image->GetLoadedLayout()->GetPreferredBase()));
992 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
993 // In Apollo, first ask if we're supposed to be ignoring the prejitted code &
994 // structures in NGENd images. If so, bail now and do not set m_nativeImage. We've
995 // already set m_identity & m_openedILimage (possibly even pointing to the
996 // NGEN/Triton image), and will use those PEImages to find and JIT IL (even if they
997 // point to an NGENd/Tritonized image).
998 if (ShouldTreatNIAsMSIL())
1002 m_nativeImage = image;
1003 m_nativeImage->AddRef();
1004 m_nativeImage->Load();
1005 m_nativeImage->AllocateLazyCOWPages();
1007 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
1008 static ConfigDWORD configNGenReserveForJumpStubs;
1009 int percentReserveForJumpStubs = configNGenReserveForJumpStubs.val(CLRConfig::INTERNAL_NGenReserveForJumpStubs);
1010 if (percentReserveForJumpStubs != 0)
1012 PEImageLayout * pLayout = image->GetLoadedLayout();
1013 ExecutionManager::GetEEJitManager()->EnsureJumpStubReserve((BYTE *)pLayout->GetBase(), pLayout->GetVirtualSize(),
1014 percentReserveForJumpStubs * (pLayout->GetVirtualSize() / 100));
1018 ExternalLog(LL_INFO100, W("Attempting to use native image %s."), image->GetPath().GetUnicode());
1022 void PEFile::ClearNativeImage()
1027 PRECONDITION(HasNativeImage());
1028 POSTCONDITION(!HasNativeImage());
1032 INJECT_FAULT(COMPlusThrowOM(););
1036 ExternalLog(LL_WARNING, "Discarding native image.");
1039 MarkNativeImageInvalidIfOwned();
1043 SafeComHolderPreemp<IMDInternalImport> pOldImport=GetMDImportWithRef();
1044 SimpleWriteLockHolder lock(m_pMetadataLock);
1048 ReleaseMetadataInterfaces(FALSE);
1049 m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1051 m_nativeImage->Release();
1052 m_nativeImage = NULL;
1053 // Make sure our normal image is open
1054 EnsureImageOpened();
1056 // Reopen metadata from normal image
1061 RestoreMDImport(pOldImport);
1070 extern DWORD g_dwLogLevel;
1072 //===========================================================================================================
1073 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1074 //===========================================================================================================
1075 static void RuntimeVerifyVLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, va_list args)
1077 STANDARD_VM_CONTRACT;
1079 BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1080 BOOL fOutputToLogging = LoggingOn(LF_ZAP, level);
1082 StackSString message;
1083 message.VPrintf(fmt, args);
1085 if (fOutputToLogging)
1087 SString displayString = pLogAsm->DisplayString();
1088 LOG((LF_ZAP, level, "%s: \"%S\"\n", "ZAP", displayString.GetUnicode()));
1089 LOG((LF_ZAP, level, "%S", message.GetUnicode()));
1090 LOG((LF_ZAP, level, "\n"));
1093 if (fOutputToDebugger)
1095 SString displayString = pLogAsm->DisplayString();
1096 WszOutputDebugString(W("CLR:("));
1097 WszOutputDebugString(displayString.GetUnicode());
1098 WszOutputDebugString(W(") "));
1099 WszOutputDebugString(message);
1100 WszOutputDebugString(W("\n"));
1106 //===========================================================================================================
1107 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1108 //===========================================================================================================
1109 static void RuntimeVerifyLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, ...)
1111 STANDARD_VM_CONTRACT;
1113 // Avoid calling RuntimeVerifyVLog unless logging is on
1114 if ( ((level == LL_ERROR) && IsDebuggerPresent())
1115 || LoggingOn(LF_ZAP, level)
1119 va_start(args, fmt);
1121 RuntimeVerifyVLog(level, pLogAsm, fmt, args);
1127 //==============================================================================
1129 static const LPCWSTR CorCompileRuntimeDllNames[NUM_RUNTIME_DLLS] =
1131 MAKEDLLNAME_W(W("coreclr")),
1132 MAKEDLLNAME_W(W("clrjit"))
1136 LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id)
1144 INJECT_FAULT(COMPlusThrowOM(););
1149 return CorCompileRuntimeDllNames[id];
1152 #ifndef CROSSGEN_COMPILE
1154 //==============================================================================
1155 // Will always return a valid HMODULE for CLR_INFO, but will return NULL for NGEN_COMPILER_INFO
1156 // if the DLL has not yet been loaded (it does not try to cause a load).
1158 // Gets set by IJitManager::LoadJit (yes, this breaks the abstraction boundary).
1159 HMODULE s_ngenCompilerDll = NULL;
1161 extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id)
1169 INJECT_FAULT(COMPlusThrowOM(););
1173 // Currently special cased for every entry.
1174 static_assert_no_msg(NUM_RUNTIME_DLLS == 2);
1175 static_assert_no_msg(CORECLR_INFO == 0);
1177 HMODULE hMod = NULL;
1179 // Try to load the correct DLL
1183 hMod = GetCLRModule();
1187 COMPlusThrowNonLocalized(kExecutionEngineException,
1188 W("Invalid runtime DLL ID"));
1194 #endif // CROSSGEN_COMPILE
1196 //===========================================================================================================
1197 // Helper for RuntimeVerifyNativeImageVersion(). Compares the loaded clr.dll and clrjit.dll's against
1198 // the ones the native image was compiled against.
1199 //===========================================================================================================
1200 static BOOL RuntimeVerifyNativeImageTimestamps(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1202 STANDARD_VM_CONTRACT;
1208 //===========================================================================================================
1209 // Validates that an NI matches the running CLR, OS, CPU, etc. This is the entrypoint used by the CLR loader.
1211 //===========================================================================================================
1212 BOOL PEAssembly::CheckNativeImageVersion(PEImage *peimage)
1214 STANDARD_VM_CONTRACT;
1217 // Get the zap version header. Note that modules will not have version
1218 // headers - they add no additional versioning constraints from their
1221 PEImageLayoutHolder image=peimage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED);
1223 if (!image->HasNativeHeader())
1226 if (!image->CheckNativeHeaderVersion())
1228 // Wrong native image version is fatal error on CoreCLR
1229 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1232 CORCOMPILE_VERSION_INFO *info = image->GetNativeVersionInfo();
1236 LoggablePEAssembly logAsm(this);
1237 if (!RuntimeVerifyNativeImageVersion(info, &logAsm))
1239 // Wrong native image version is fatal error on CoreCLR
1240 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1243 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1247 // Require instrumented flags for mscorlib when collecting IBC data
1248 CorCompileConfigFlags instrumentationConfigFlags = (CorCompileConfigFlags) (configFlags & CORCOMPILE_CONFIG_INSTRUMENTATION);
1249 if ((info->wConfigFlags & instrumentationConfigFlags) != instrumentationConfigFlags)
1251 ExternalLog(LL_ERROR, "Instrumented native image for System.Private.CoreLib.dll expected.");
1252 ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1256 // Otherwise, match regardless of the instrumentation flags
1257 configFlags = (CorCompileConfigFlags) (configFlags & ~(CORCOMPILE_CONFIG_INSTRUMENTATION_NONE | CORCOMPILE_CONFIG_INSTRUMENTATION));
1259 if ((info->wConfigFlags & configFlags) != configFlags)
1268 //===========================================================================================================
1269 // Validates that an NI matches the running CLR, OS, CPU, etc.
1271 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1272 // while others check at CLR load time.
1274 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1275 // by a CLR object or Fusion object.
1276 //===========================================================================================================
1277 BOOL RuntimeVerifyNativeImageVersion(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1279 STANDARD_VM_CONTRACT;
1281 if (!RuntimeVerifyNativeImageTimestamps(info, pLogAsm))
1285 // Check that the EE version numbers are the same.
1288 if (info->wVersionMajor != VER_MAJORVERSION
1289 || info->wVersionMinor != VER_MINORVERSION
1290 || info->wVersionBuildNumber != VER_PRODUCTBUILD
1291 || info->wVersionPrivateBuildNumber != VER_PRODUCTBUILD_QFE)
1293 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("CLR version recorded in native image doesn't match the current CLR."));
1298 // Check checked/free status
1303 CORCOMPILE_BUILD_CHECKED
1305 CORCOMPILE_BUILD_FREE
1309 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Checked/free mismatch with native image."));
1317 if (info->wMachine != IMAGE_FILE_MACHINE_NATIVE_NI)
1319 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Processor type recorded in native image doesn't match this machine's processor."));
1323 #ifndef CROSSGEN_COMPILE
1325 // Check the processor specific ID
1328 CORINFO_CPU cpuInfo;
1329 GetSpecificCpuInfo(&cpuInfo);
1331 if (!IsCompatibleCpuInfo(&cpuInfo, &info->cpuInfo))
1333 RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Required CPU features recorded in native image don't match this machine's processor."));
1336 #endif // CROSSGEN_COMPILE
1340 // The zap is up to date.
1343 RuntimeVerifyLog(LL_INFO100, pLogAsm, W("Native image has correct version information."));
1347 #endif // !DACCESS_COMPILE
1350 CorCompileConfigFlags PEFile::GetNativeImageConfigFlags(BOOL fForceDebug/*=FALSE*/,
1351 BOOL fForceProfiling/*=FALSE*/,
1352 BOOL fForceInstrument/*=FALSE*/)
1354 LIMITED_METHOD_DAC_CONTRACT;
1356 CorCompileConfigFlags result = (CorCompileConfigFlags)0;
1360 #ifdef DEBUGGING_SUPPORTED
1361 // if these have been set, the take precedence over anything else
1362 if (s_NGENDebugFlags)
1364 if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG_NONE) != 0)
1366 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_NONE);
1370 if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG) != 0)
1372 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1377 #endif // DEBUGGING_SUPPORTED
1381 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1385 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_DEFAULT);
1391 #ifdef PROFILING_SUPPORTED
1392 if (fForceProfiling || CORProfilerUseProfileImages())
1394 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING);
1396 result = (CorCompileConfigFlags) (result & ~(CORCOMPILE_CONFIG_DEBUG_NONE|
1397 CORCOMPILE_CONFIG_DEBUG|
1398 CORCOMPILE_CONFIG_DEBUG_DEFAULT));
1401 #endif //PROFILING_SUPPORTED
1402 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING_NONE);
1405 #ifndef DACCESS_COMPILE
1406 BOOL instrumented = (!IsCompilationProcess() && g_pConfig->GetZapBBInstr());
1408 BOOL instrumented = FALSE;
1410 if (instrumented || fForceInstrument)
1412 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION);
1416 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION_NONE);
1419 // NOTE: Right now we are not taking instrumentation into account when binding.
1424 CorCompileConfigFlags PEFile::GetNativeImageConfigFlagsWithOverrides()
1426 LIMITED_METHOD_DAC_CONTRACT;
1428 BOOL fForceDebug, fForceProfiling, fForceInstrument;
1429 SystemDomain::GetCompilationOverrides(&fForceDebug,
1432 return PEFile::GetNativeImageConfigFlags(fForceDebug,
1437 #ifndef DACCESS_COMPILE
1441 //===========================================================================================================
1442 // Validates that a hard-dep matches the a parent NI's compile-time hard-dep.
1444 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1445 // while others check at CLR load time.
1447 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1448 // by a CLR object or Fusion object.
1450 //===========================================================================================================
1451 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_NGEN_SIGNATURE &ngenSigExpected,
1452 const CORCOMPILE_VERSION_INFO *pActual,
1453 LoggableAssembly *pLogAsm)
1455 STANDARD_VM_CONTRACT;
1457 if (ngenSigExpected != pActual->signature)
1459 // Signature did not match
1460 SString displayString = pLogAsm->DisplayString();
1461 RuntimeVerifyLog(LL_ERROR,
1463 W("Rejecting native image because native image dependency %s ")
1464 W("had a different identity than expected"),
1465 displayString.GetUnicode());
1471 // Wrapper function for use by parts of the runtime that actually have a CORCOMPILE_DEPENDENCY to work with.
1472 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_DEPENDENCY *pExpected,
1473 const CORCOMPILE_VERSION_INFO *pActual,
1474 LoggableAssembly *pLogAsm)
1476 WRAPPER_NO_CONTRACT;
1478 return RuntimeVerifyNativeImageDependency(pExpected->signNativeImage,
1483 #endif // !DACCESS_COMPILE
1485 #ifdef DEBUGGING_SUPPORTED
1487 // Called through ICorDebugAppDomain2::SetDesiredNGENCompilerFlags to specify
1488 // which kinds of ngen'd images fusion should load wrt debugging support
1489 // Overrides any previous settings
1491 void PEFile::SetNGENDebugFlags(BOOL fAllowOpt)
1503 s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG_NONE;
1505 s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG;
1509 // Called through ICorDebugAppDomain2::GetDesiredNGENCompilerFlags to determine
1510 // which kinds of ngen'd images fusion should load wrt debugging support
1512 void PEFile::GetNGENDebugFlags(BOOL *fAllowOpt)
1523 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1525 *fAllowOpt = ((configFlags & CORCOMPILE_CONFIG_DEBUG) == 0);
1527 #endif // DEBUGGING_SUPPORTED
1531 #ifndef DACCESS_COMPILE
1532 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1534 //---------------------------------------------------------------------------------------
1536 // Used in Apollo, this method determines whether profiling or debugging has requested
1537 // the runtime to provide debuggable / profileable code. In other CLR builds, this would
1538 // normally result in requiring the appropriate NGEN scenario be loaded (/Debug or
1539 // /Profile) and to JIT if unavailable. In Apollo, however, these NGEN scenarios are
1540 // never available, and even MSIL assemblies are often not available. So this function
1541 // tells its caller to use the NGENd assembly as if it were an MSIL assembly--ignore the
1542 // prejitted code and prebaked structures, and just JIT code and load classes from
1546 // nonzero iff NGENd images should be treated as MSIL images.
1550 BOOL PEFile::ShouldTreatNIAsMSIL()
1552 LIMITED_METHOD_CONTRACT;
1554 // Never use fragile native image content during ReadyToRun compilation. It would
1555 // produces non-version resilient images because of wrong cached values for
1556 // MethodTable::IsLayoutFixedInCurrentVersionBubble, etc.
1557 if (IsReadyToRunCompilation())
1560 // Ask profiling API & config vars whether NGENd images should be avoided
1562 if (!NGENImagesAllowed())
1565 // Ask profiling and debugging if they're requesting us to use ngen /Debug or
1566 // /Profile images (which aren't available under Apollo)
1568 CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1570 if ((configFlags & (CORCOMPILE_CONFIG_DEBUG | CORCOMPILE_CONFIG_PROFILING)) != 0)
1576 #endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1578 #endif //!DACCESS_COMPILE
1579 #endif // FEATURE_PREJIT
1581 #ifndef DACCESS_COMPILE
1583 // ------------------------------------------------------------
1585 // ------------------------------------------------------------
1587 void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource)
1595 INJECT_FAULT(ThrowOutOfMemory(););
1599 // NOTE: it's not clear whether to load this from m_image or m_loadedImage.
1600 // m_loadedImage is probably preferable, but this may be called by security
1601 // before the image is loaded.
1605 #ifdef FEATURE_PREJIT
1606 if (m_nativeImage != NULL)
1607 image = m_nativeImage;
1611 EnsureImageOpened();
1612 image = GetILimage();
1615 PEImageLayoutHolder theImage(image->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED));
1616 if (!theImage->CheckResource(dwOffset))
1617 ThrowHR(COR_E_BADIMAGEFORMAT);
1620 const void *resource = theImage->GetResource(dwOffset, &size);
1623 *pbInMemoryResource = (PBYTE) resource;
1626 // ------------------------------------------------------------
1628 // ------------------------------------------------------------
1631 PEFile::LoadAssembly(
1632 mdAssemblyRef kAssemblyRef,
1633 IMDInternalImport * pImport, // = NULL
1634 LPCUTF8 szWinRtTypeNamespace, // = NULL
1635 LPCUTF8 szWinRtTypeClassName) // = NULL
1637 CONTRACT(PEAssembly *)
1643 POSTCONDITION(CheckPointer(RETVAL));
1644 INJECT_FAULT(COMPlusThrowOM(););
1648 if (pImport == NULL)
1649 pImport = GetPersistentMDImport();
1651 if (((TypeFromToken(kAssemblyRef) != mdtAssembly) &&
1652 (TypeFromToken(kAssemblyRef) != mdtAssemblyRef)) ||
1653 (!pImport->IsValidToken(kAssemblyRef)))
1655 ThrowHR(COR_E_BADIMAGEFORMAT);
1660 spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(GetAssembly()), IsIntrospectionOnly());
1661 if (szWinRtTypeClassName != NULL)
1662 spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
1664 RETURN GetAppDomain()->BindAssemblySpec(&spec, TRUE, IsIntrospectionOnly());
1667 // ------------------------------------------------------------
1669 // ------------------------------------------------------------
1670 #ifdef FEATURE_PREJIT
1671 void PEFile::ExternalLog(DWORD facility, DWORD level, const WCHAR *fmt, ...)
1673 WRAPPER_NO_CONTRACT;
1676 va_start(args, fmt);
1678 ExternalVLog(facility, level, fmt, args);
1683 void PEFile::ExternalLog(DWORD level, const WCHAR *fmt, ...)
1685 WRAPPER_NO_CONTRACT;
1688 va_start(args, fmt);
1690 ExternalVLog(LF_ZAP, level, fmt, args);
1695 void PEFile::ExternalLog(DWORD level, const char *msg)
1697 WRAPPER_NO_CONTRACT;
1699 // It is OK to use %S here. We know that msg is ASCII-only.
1700 ExternalLog(level, W("%S"), msg);
1703 void PEFile::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
1712 BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1713 BOOL fOutputToLogging = LoggingOn(facility, level);
1715 if (!fOutputToDebugger && !fOutputToLogging)
1718 StackSString message;
1719 message.VPrintf(fmt, args);
1721 if (fOutputToLogging)
1723 if (GetMDImport() != NULL)
1724 LOG((facility, level, "%s: \"%s\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), GetSimpleName()));
1726 LOG((facility, level, "%s: \"%S\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), ((const WCHAR *)GetPath())));
1728 LOG((facility, level, "%S", message.GetUnicode()));
1729 LOG((facility, level, "\n"));
1732 if (fOutputToDebugger)
1734 WszOutputDebugString(W("CLR:("));
1736 StackSString codebase;
1737 GetCodeBaseOrName(codebase);
1738 WszOutputDebugString(codebase);
1740 WszOutputDebugString(W(") "));
1742 WszOutputDebugString(message);
1743 WszOutputDebugString(W("\n"));
1749 void PEFile::FlushExternalLog()
1751 LIMITED_METHOD_CONTRACT;
1755 BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource,
1756 PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef,
1757 LPCSTR *szFileName, DWORD *dwLocation,
1758 StackCrawlMark *pStackMark, BOOL fSkipSecurityCheck,
1759 BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain)
1766 INJECT_FAULT(COMPlusThrowOM(););
1767 WRAPPER(GC_TRIGGERS);
1773 DWORD dwResourceFlags;
1775 mdManifestResource mdResource;
1776 Assembly* pAssembly = NULL;
1777 PEFile* pPEFile = NULL;
1778 ReleaseHolder<IMDInternalImport> pImport (GetMDImportWithRef());
1779 if (SUCCEEDED(pImport->FindManifestResourceByName(szName, &mdResource)))
1782 IfFailThrow(pImport->GetManifestResourceProps(
1791 if (fSkipRaiseResolveEvent || pAppDomain == NULL)
1794 DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(GetAssembly());
1795 pAssembly = pAppDomain->RaiseResourceResolveEvent(pParentAssembly, szName);
1796 if (pAssembly == NULL)
1799 pDomainAssembly = pAssembly->GetDomainAssembly(pAppDomain);
1800 pPEFile = pDomainAssembly->GetFile();
1802 if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName(
1809 if (dwLocation != 0)
1811 if (pAssemblyRef != NULL)
1812 *pAssemblyRef = pDomainAssembly;
1814 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
1816 IfFailThrow(pPEFile->GetPersistentMDImport()->GetManifestResourceProps(
1825 switch(TypeFromToken(mdLinkRef)) {
1826 case mdtAssemblyRef:
1828 if (pDomainAssembly == NULL)
1832 spec.InitializeSpec(mdLinkRef, GetPersistentMDImport(), pDomainAssembly, pDomainAssembly->GetFile()->IsIntrospectionOnly());
1833 pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED);
1837 *pAssemblyRef = pDomainAssembly;
1839 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
1842 return pDomainAssembly->GetResource(szName,
1850 fSkipRaiseResolveEvent);
1854 if (mdLinkRef == mdFileNil)
1856 // The resource is embedded in the manifest file
1858 #ifndef CROSSGEN_COMPILE
1859 if (!IsMrPublic(dwResourceFlags) && pStackMark && !fSkipSecurityCheck)
1861 Assembly *pCallersAssembly = SystemDomain::GetCallersAssembly(pStackMark);
1863 if (pCallersAssembly && // full trust for interop
1864 (!pCallersAssembly->GetManifestFile()->Equals(this)))
1866 RefSecContext sCtx(AccessCheckOptions::kMemberAccess);
1868 AccessCheckOptions accessCheckOptions(
1869 AccessCheckOptions::kMemberAccess, /*accessCheckType*/
1870 NULL, /*pAccessContext*/
1871 FALSE, /*throwIfTargetIsInaccessible*/
1872 (MethodTable *) NULL /*pTargetMT*/
1875 // SL: return TRUE only if the caller is critical
1876 // Desktop: return TRUE only if demanding MemberAccess succeeds
1877 if (!accessCheckOptions.DemandMemberAccessOrFail(&sCtx, NULL, TRUE /*visibilityCheck*/))
1881 #endif // CROSSGEN_COMPILE
1884 *dwLocation = *dwLocation | 5; // ResourceLocation.embedded |
1886 // ResourceLocation.containedInManifestFile
1890 pPEFile->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource);
1897 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_IN_MANIFESTRES);
1901 void PEFile::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
1903 WRAPPER_NO_CONTRACT;
1905 if (IsResource() || IsDynamic())
1914 #ifdef FEATURE_PREJIT
1915 if (IsNativeLoaded())
1917 CONSISTENCY_CHECK(HasNativeImage());
1919 m_nativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
1922 #ifndef DACCESS_COMPILE
1923 if (!HasOpenedILimage())
1925 //don't want to touch the IL image unless we already have
1926 ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef();
1929 pNativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
1933 #endif // DACCESS_COMPILE
1934 #endif // FEATURE_PREJIT
1936 GetILimage()->GetPEKindAndMachine(pdwKind, pdwMachine);
1940 ULONG PEFile::GetILImageTimeDateStamp()
1950 #ifdef FEATURE_PREJIT
1951 if (IsNativeLoaded())
1953 CONSISTENCY_CHECK(HasNativeImage());
1955 // The IL image's time stamp is copied to the native image.
1956 CORCOMPILE_VERSION_INFO* pVersionInfo = GetLoadedNative()->GetNativeVersionInfoMaybeNull();
1957 if (pVersionInfo == NULL)
1963 return pVersionInfo->sourceAssembly.timeStamp;
1966 #endif // FEATURE_PREJIT
1968 return GetLoadedIL()->GetTimeDateStamp();
1972 // ================================================================================
1973 // PEAssembly class - a PEFile which represents an assembly
1974 // ================================================================================
1976 // Statics initialization.
1978 void PEAssembly::Attach()
1980 STANDARD_VM_CONTRACT;
1984 PEAssembly::PEAssembly(
1985 CoreBindResult* pBindResultInfo,
1986 IMetaDataEmit* pEmit,
1989 BOOL introspectionOnly/*=FALSE*/,
1990 PEImage * pPEImageIL /*= NULL*/,
1991 PEImage * pPEImageNI /*= NULL*/,
1992 ICLRPrivAssembly * pHostAssembly /*= NULL*/)
1994 : PEFile(pBindResultInfo ? (pBindResultInfo->GetPEImage() ? pBindResultInfo->GetPEImage() :
1995 (pBindResultInfo->HasNativeImage() ? pBindResultInfo->GetNativeImage() : NULL)
1996 ): pPEImageIL? pPEImageIL:(pPEImageNI? pPEImageNI:NULL), FALSE),
1997 m_creator(clr::SafeAddRef(creator)),
1998 m_bIsFromGAC(FALSE),
1999 m_bIsOnTpaList(FALSE)
2000 ,m_fProfileAssembly(0)
2005 PRECONDITION(CheckPointer(pEmit, NULL_OK));
2006 PRECONDITION(CheckPointer(creator, NULL_OK));
2007 PRECONDITION(pBindResultInfo == NULL || (pPEImageIL == NULL && pPEImageNI == NULL));
2012 if (introspectionOnly)
2014 if (!system) // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2016 m_flags |= PEFILE_INTROSPECTIONONLY;
2020 m_flags |= PEFILE_ASSEMBLY;
2022 m_flags |= PEFILE_SYSTEM;
2024 // We check the precondition above that either pBindResultInfo is null or both pPEImageIL and pPEImageNI are,
2025 // so we'll only get a max of one native image passed in.
2026 if (pPEImageNI != NULL)
2028 SetNativeImage(pPEImageNI);
2031 #ifdef FEATURE_PREJIT
2032 if (pBindResultInfo && pBindResultInfo->HasNativeImage())
2033 SetNativeImage(pBindResultInfo->GetNativeImage());
2036 // If we have no native image, we require a mapping for the file.
2037 if (!HasNativeImage() || !IsILOnly())
2038 EnsureImageOpened();
2040 // Initialize the status of the assembly being in the GAC, or being part of the TPA list, before
2041 // we start to do work (like strong name verification) that relies on those states to be valid.
2042 if(pBindResultInfo != nullptr)
2044 m_bIsFromGAC = pBindResultInfo->IsFromGAC();
2045 m_bIsOnTpaList = pBindResultInfo->IsOnTpaList();
2048 // Check security related stuff
2051 // Open metadata eagerly to minimize failure windows
2053 OpenMDImport_Unsafe(); //constructor, cannot race with anything
2056 _ASSERTE(!m_bHasPersistentMDImport);
2057 IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2058 (void **)&m_pMDImport));
2061 m_bHasPersistentMDImport=TRUE;
2062 m_MDImportIsRW_Debugger_Use_Only = TRUE;
2065 // m_pMDImport can be external
2066 // Make sure this is an assembly
2067 if (!m_pMDImport->IsValidToken(TokenFromRid(1, mdtAssembly)))
2068 ThrowHR(COR_E_ASSEMBLYEXPECTED);
2070 // Verify name eagerly
2071 LPCUTF8 szName = GetSimpleName();
2074 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2077 // Set the host assembly and binding context as the AssemblySpec initialization
2078 // for CoreCLR will expect to have it set.
2079 if (pHostAssembly != nullptr)
2081 m_pHostAssembly = clr::SafeAddRef(pHostAssembly);
2084 if(pBindResultInfo != nullptr)
2086 // Cannot have both pHostAssembly and a coreclr based bind
2087 _ASSERTE(pHostAssembly == nullptr);
2088 pBindResultInfo->GetBindAssembly(&m_pHostAssembly);
2092 GetCodeBaseOrName(m_debugName);
2093 m_debugName.Normalize();
2094 m_pDebugName = m_debugName;
2097 spec.InitializeSpec(this);
2099 spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
2100 ASM_DISPLAYF_CULTURE |
2101 ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
2102 m_sTextualIdentity);
2108 PEAssembly *PEAssembly::Open(
2109 PEAssembly * pParent,
2110 PEImage * pPEImageIL,
2111 PEImage * pPEImageNI,
2112 ICLRPrivAssembly * pHostAssembly,
2113 BOOL fIsIntrospectionOnly)
2115 STANDARD_VM_CONTRACT;
2117 PEAssembly * pPEAssembly = new PEAssembly(
2118 nullptr, // BindResult
2119 nullptr, // IMetaDataEmit
2120 pParent, // PEFile creator
2122 fIsIntrospectionOnly,
2131 PEAssembly::~PEAssembly()
2137 GC_TRIGGERS; // Fusion uses crsts on AddRef/Release
2143 if (m_creator != NULL)
2144 m_creator->Release();
2148 #ifndef DACCESS_COMPILE
2149 void PEAssembly::ReleaseIL()
2161 if (m_creator != NULL)
2163 m_creator->Release();
2167 PEFile::ReleaseIL();
2173 PEAssembly *PEAssembly::OpenSystem(IUnknown * pAppCtx)
2175 STANDARD_VM_CONTRACT;
2177 PEAssembly *result = NULL;
2181 result = DoOpenSystem(pAppCtx);
2185 Exception *ex = GET_EXCEPTION();
2187 // Rethrow non-transient exceptions as file load exceptions with proper
2190 if (!ex->IsTransient())
2191 EEFileLoadException::Throw(SystemDomain::System()->BaseLibrary(), ex->GetHR(), ex);
2198 PEAssembly *PEAssembly::DoOpenSystem(IUnknown * pAppCtx)
2200 CONTRACT(PEAssembly *)
2202 POSTCONDITION(CheckPointer(RETVAL));
2207 ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1);
2208 CoreBindResult bindResult;
2209 ReleaseHolder<ICLRPrivAssembly> pPrivAsm;
2210 IfFailThrow(CCoreCLRBinderHelper::BindToSystem(&pPrivAsm, !IsCompilationProcess() || g_fAllowNativeImages));
2211 if(pPrivAsm != NULL)
2213 bindResult.Init(pPrivAsm, TRUE, TRUE);
2216 RETURN new PEAssembly(&bindResult, NULL, NULL, TRUE, FALSE);
2220 #ifndef CROSSGEN_COMPILE
2222 PEAssembly *PEAssembly::OpenMemory(PEAssembly *pParentAssembly,
2223 const void *flat, COUNT_T size,
2224 BOOL isIntrospectionOnly/*=FALSE*/,
2225 CLRPrivBinderLoadFile* pBinderToUse)
2227 STANDARD_VM_CONTRACT;
2229 PEAssembly *result = NULL;
2233 result = DoOpenMemory(pParentAssembly, flat, size, isIntrospectionOnly, pBinderToUse);
2237 Exception *ex = GET_EXCEPTION();
2239 // Rethrow non-transient exceptions as file load exceptions with proper
2242 if (!ex->IsTransient())
2243 EEFileLoadException::Throw(pParentAssembly, flat, size, ex->GetHR(), ex);
2253 class DoOpenFlatStress : APIThreadStress
2256 PEAssembly *pParentAssembly;
2259 DoOpenFlatStress(PEAssembly *pParentAssembly, const void *flat, COUNT_T size)
2260 : pParentAssembly(pParentAssembly), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
2263 WRAPPER_NO_CONTRACT;
2264 PEAssemblyHolder result(PEAssembly::OpenMemory(pParentAssembly, flat, size, FALSE));
2269 PEAssembly *PEAssembly::DoOpenMemory(
2270 PEAssembly *pParentAssembly,
2273 BOOL isIntrospectionOnly,
2274 CLRPrivBinderLoadFile* pBinderToUse)
2276 CONTRACT(PEAssembly *)
2278 PRECONDITION(CheckPointer(flat));
2279 PRECONDITION(CheckOverflow(flat, size));
2280 PRECONDITION(CheckPointer(pParentAssembly));
2282 POSTCONDITION(CheckPointer(RETVAL));
2287 DoOpenFlatStress ts(pParentAssembly, flat, size);
2289 // Note that we must have a flat image stashed away for two reasons.
2290 // First, we need a private copy of the data which we can verify
2291 // before doing the mapping. And secondly, we can only compute
2292 // the strong name hash on a flat image.
2294 PEImageHolder image(PEImage::LoadFlat(flat, size));
2296 // Need to verify that this is a CLR assembly
2297 if (!image->CheckILFormat())
2298 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
2301 CoreBindResult bindResult;
2302 ReleaseHolder<ICLRPrivAssembly> assembly;
2303 IfFailThrow(CCoreCLRBinderHelper::GetAssemblyFromImage(image, NULL, &assembly));
2304 bindResult.Init(assembly,FALSE,FALSE);
2306 RETURN new PEAssembly(&bindResult, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
2308 #endif // !CROSSGEN_COMPILE
2312 PEAssembly* PEAssembly::Open(CoreBindResult* pBindResult,
2313 BOOL isSystem, BOOL isIntrospectionOnly)
2316 return new PEAssembly(pBindResult,NULL,NULL,isSystem,isIntrospectionOnly);
2321 PEAssembly *PEAssembly::Create(PEAssembly *pParentAssembly,
2322 IMetaDataAssemblyEmit *pAssemblyEmit,
2323 BOOL bIsIntrospectionOnly)
2325 CONTRACT(PEAssembly *)
2327 PRECONDITION(CheckPointer(pParentAssembly));
2328 PRECONDITION(CheckPointer(pAssemblyEmit));
2330 POSTCONDITION(CheckPointer(RETVAL));
2334 // Set up the metadata pointers in the PEAssembly. (This is the only identity
2336 SafeComHolder<IMetaDataEmit> pEmit;
2337 pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit);
2338 PEAssemblyHolder pFile(new PEAssembly(NULL, pEmit, pParentAssembly, FALSE, bIsIntrospectionOnly));
2339 RETURN pFile.Extract();
2343 #ifdef FEATURE_PREJIT
2346 void PEAssembly::SetNativeImage(PEImage * image)
2357 if (CheckNativeImageVersion(image))
2359 PEFile::SetNativeImage(image);
2361 //Enable this code if you want to make sure we never touch the flat layout in the presence of the
2363 //#if defined(_DEBUG)
2364 //find all the layouts in the il image and make sure we never touch them.
2365 unsigned ignored = 0;
2366 PTR_PEImageLayout layout = m_ILimage->GetLayout(PEImageLayout::LAYOUT_FLAT, 0);
2369 //cache a bunch of PE metadata in the PEDecoder
2370 m_ILimage->CheckILFormat();
2372 //we also need some of metadata (for the public key), so cache this too
2373 DWORD verifyOutputFlags;
2374 m_ILimage->VerifyStrongName(&verifyOutputFlags);
2375 //fudge this by a few pages to make sure we can still mess with the PE headers
2376 const size_t fudgeSize = 4096 * 4;
2377 ClrVirtualProtect((void*)(((char *)layout->GetBase()) + fudgeSize),
2378 layout->GetSize() - fudgeSize, 0, &ignored);
2385 ExternalLog(LL_WARNING, "Native image is not correct version.");
2389 #endif // FEATURE_PREJIT
2392 BOOL PEAssembly::IsSourceGAC()
2394 WRAPPER_NO_CONTRACT;
2395 return m_bIsFromGAC;
2399 #endif // #ifndef DACCESS_COMPILE
2403 #ifndef DACCESS_COMPILE
2406 // ------------------------------------------------------------
2408 // ------------------------------------------------------------
2410 void PEAssembly::VerifyStrongName()
2418 INJECT_FAULT(COMPlusThrowOM(););
2422 // If we've already done the signature checks, we don't need to do them again.
2423 if (m_fStrongNameVerified)
2428 // Without FUSION/GAC, we need to verify SN on all assemblies, except dynamic assemblies.
2432 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
2433 m_fStrongNameVerified = TRUE;
2437 // Next, verify the strong name, if necessary
2439 // Check format of image. Note we must delay this until after the GAC status has been
2440 // checked, to handle the case where we are not loading m_image.
2441 EnsureImageOpened();
2444 if (m_nativeImage == NULL && !GetILimage()->IsTrustedNativeImage())
2446 if (!GetILimage()->CheckILFormat())
2447 ThrowHR(COR_E_BADIMAGEFORMAT);
2450 // Check the strong name if present.
2451 if (IsIntrospectionOnly())
2453 // For introspection assemblies, we don't need to check strong names and we don't
2454 // need to do module hash checks.
2455 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
2459 // Runtime policy on CoreCLR is to skip verification of ALL assemblies
2460 m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
2461 m_fStrongNameVerified = TRUE;
2464 m_fStrongNameVerified = TRUE;
2467 BOOL PEAssembly::IsProfileAssembly()
2478 // For now, cache the result of the check below. This cache should be removed once/if the check below
2479 // becomes cheap (e.g. does not access metadata anymore).
2481 if (VolatileLoadWithoutBarrier(&m_fProfileAssembly) != 0)
2483 return m_fProfileAssembly > 0;
2487 // In order to be a platform (profile) assembly, you must be from a trusted location (TPA list)
2488 // If we are binding by TPA list and this assembly is on it, IsSourceGAC is true => Assembly is Profile
2489 // If the assembly is a WinMD, it is automatically trusted since all WinMD scenarios are full trust scenarios.
2491 // The check for Silverlight strongname platform assemblies is legacy backdoor. It was introduced by accidental abstraction leak
2492 // from the old Silverlight binder, people took advantage of it and we cannot easily get rid of it now. See DevDiv #710462.
2494 BOOL bProfileAssembly = IsSourceGAC() && (IsSystem() || m_bIsOnTpaList);
2496 m_fProfileAssembly = bProfileAssembly ? 1 : -1;
2497 return bProfileAssembly;
2500 // ------------------------------------------------------------
2501 // Descriptive strings
2502 // ------------------------------------------------------------
2504 // Effective path is the path of nearest parent (creator) assembly which has a nonempty path.
2506 const SString &PEAssembly::GetEffectivePath()
2517 PEAssembly *pAssembly = this;
2519 while (pAssembly->m_identity == NULL
2520 || pAssembly->m_identity->GetPath().IsEmpty())
2522 if (pAssembly->m_creator)
2523 pAssembly = pAssembly->m_creator->GetAssembly();
2524 else // Unmanaged exe which loads byte[]/IStream assemblies
2525 return SString::Empty();
2528 return pAssembly->m_identity->GetPath();
2532 // Codebase is the fusion codebase or path for the assembly. It is in URL format.
2533 // Note this may be obtained from the parent PEFile if we don't have a path or fusion
2536 // fCopiedName means to get the "shadow copied" path rather than the original path, if applicable
2537 void PEAssembly::GetCodeBase(SString &result, BOOL fCopiedName/*=FALSE*/)
2545 INJECT_FAULT(COMPlusThrowOM(););
2549 // All other cases use the file path.
2550 result.Set(GetEffectivePath());
2551 if (!result.IsEmpty())
2556 void PEAssembly::PathToUrl(SString &string)
2560 PRECONDITION(PEImage::CheckCanonicalFullPath(string));
2564 INJECT_FAULT(COMPlusThrowOM(););
2568 SString::Iterator i = string.Begin();
2570 #if !defined(PLATFORM_UNIX)
2571 if (i[0] == W('\\'))
2574 string.Insert(i, SL("file://"));
2575 string.Skip(i, SL("file://"));
2580 string.Insert(i, SL("file:///"));
2581 string.Skip(i, SL("file:///"));
2584 // Unix doesn't have a distinction between a network or a local path
2585 _ASSERTE( i[0] == W('\\') || i[0] == W('/'));
2586 SString sss(SString::Literal, W("file://"));
2587 string.Insert(i, sss);
2588 string.Skip(i, sss);
2591 while (string.Find(i, W('\\')))
2593 string.Replace(i, W('/'));
2597 void PEAssembly::UrlToPath(SString &string)
2606 SString::Iterator i = string.Begin();
2608 SString sss2(SString::Literal, W("file://"));
2609 #if !defined(PLATFORM_UNIX)
2610 SString sss3(SString::Literal, W("file:///"));
2611 if (string.MatchCaseInsensitive(i, sss3))
2612 string.Delete(i, 8);
2615 if (string.MatchCaseInsensitive(i, sss2))
2616 string.Delete(i, 7);
2618 while (string.Find(i, W('/')))
2620 string.Replace(i, W('\\'));
2626 BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i)
2628 #ifdef PLATFORM_UNIX
2629 SString::Iterator slash = i;
2630 SString::Iterator backSlash = i;
2631 BOOL foundSlash = path.FindBack(slash, '/');
2632 BOOL foundBackSlash = path.FindBack(backSlash, '\\');
2633 if (!foundSlash && !foundBackSlash)
2635 else if (foundSlash && !foundBackSlash)
2637 else if (!foundSlash && foundBackSlash)
2640 i = (backSlash > slash) ? backSlash : slash;
2643 return path.FindBack(i, '\\');
2644 #endif //PLATFORM_UNIX
2648 // ------------------------------------------------------------
2650 // ------------------------------------------------------------
2651 #ifdef FEATURE_PREJIT
2652 void PEAssembly::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
2661 PEFile::ExternalVLog(facility, level, fmt, args);
2667 void PEAssembly::FlushExternalLog()
2679 #endif //FEATURE_PREJIT
2680 // ------------------------------------------------------------
2682 // ------------------------------------------------------------
2684 HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
2689 PRECONDITION(CheckPointer(pMajor, NULL_OK));
2690 PRECONDITION(CheckPointer(pMinor, NULL_OK));
2691 PRECONDITION(CheckPointer(pBuild, NULL_OK));
2692 PRECONDITION(CheckPointer(pRevision, NULL_OK));
2694 WRAPPER(GC_TRIGGERS);
2699 AssemblyMetaDataInternal md;
2701 if (m_bHasPersistentMDImport)
2703 _ASSERTE(GetPersistentMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly)));
2704 IfFailRet(GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
2708 ReleaseHolder<IMDInternalImport> pImport(GetMDImportWithRef());
2709 _ASSERTE(pImport->IsValidToken(TokenFromRid(1, mdtAssembly)));
2710 IfFailRet(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
2714 *pMajor = md.usMajorVersion;
2716 *pMinor = md.usMinorVersion;
2718 *pBuild = md.usBuildNumber;
2719 if (pRevision != NULL)
2720 *pRevision = md.usRevisionNumber;
2727 void PEFile::EnsureImageOpened()
2729 WRAPPER_NO_CONTRACT;
2732 #ifdef FEATURE_PREJIT
2733 if(HasNativeImage())
2734 m_nativeImage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
2737 GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
2740 #endif // #ifndef DACCESS_COMPILE
2742 #ifdef DACCESS_COMPILE
2745 PEFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2747 WRAPPER_NO_CONTRACT;
2750 // sizeof(PEFile) == 0xb8
2752 EMEM_OUT(("MEM: %p PEFile\n", dac_cast<TADDR>(this)));
2755 // Not a big deal if it's NULL or fails.
2756 m_debugName.EnumMemoryRegions(flags);
2759 if (m_identity.IsValid())
2761 m_identity->EnumMemoryRegions(flags);
2763 if (GetILimage().IsValid())
2765 GetILimage()->EnumMemoryRegions(flags);
2767 #ifdef FEATURE_PREJIT
2768 if (m_nativeImage.IsValid())
2770 m_nativeImage->EnumMemoryRegions(flags);
2771 DacEnumHostDPtrMem(m_nativeImage->GetLoadedLayout()->GetNativeVersionInfo());
2777 PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2779 WRAPPER_NO_CONTRACT;
2781 PEFile::EnumMemoryRegions(flags);
2783 if (m_creator.IsValid())
2785 m_creator->EnumMemoryRegions(flags);
2789 #endif // #ifdef DACCESS_COMPILE
2792 //-------------------------------------------------------------------------------
2793 // Make best-case effort to obtain an image name for use in an error message.
2795 // This routine must expect to be called before the this object is fully loaded.
2796 // It can return an empty if the name isn't available or the object isn't initialized
2797 // enough to get a name, but it mustn't crash.
2798 //-------------------------------------------------------------------------------
2799 LPCWSTR PEFile::GetPathForErrorMessages()
2805 INJECT_FAULT(COMPlusThrowOM(););
2806 SUPPORTS_DAC_HOST_ONLY;
2812 return m_identity->GetPathForErrorMessages();
2821 #ifdef DACCESS_COMPILE
2822 TADDR PEFile::GetMDInternalRWAddress()
2824 if (!m_MDImportIsRW_Debugger_Use_Only)
2828 // This line of code is a bit scary, but it is correct for now at least...
2829 // 1) We are using 'm_pMDImport_Use_Accessor' directly, and not the accessor. The field is
2830 // named this way to prevent debugger code that wants a host implementation of IMDInternalImport
2831 // from accidentally trying to use this pointer. This pointer is a target pointer, not
2832 // a host pointer. However in this function we do want the target pointer, so the usage is
2834 // 2) ASSUMPTION: We are assuming that the only valid implementation of RW metadata is
2835 // MDInternalRW. If that ever changes we would need some way to disambiguate, and
2836 // probably this entire code path would need to be redesigned.
2837 // 3) ASSUMPTION: We are assuming that no pointer adjustment is required to convert between
2838 // IMDInternalImport*, IMDInternalImportENC* and MDInternalRW*. Ideally I was hoping to do this with a
2839 // static_cast<> but the compiler complains that the ENC<->RW is an unrelated conversion.
2840 return (TADDR) m_pMDImport_UseAccessor;
2845 // Returns the ICLRPrivBinder* instance associated with the PEFile
2846 PTR_ICLRPrivBinder PEFile::GetBindingContext()
2848 LIMITED_METHOD_CONTRACT;
2850 PTR_ICLRPrivBinder pBindingContext = NULL;
2852 // Mscorlib is always bound in context of the TPA Binder. However, since it gets loaded and published
2853 // during EEStartup *before* TPAbinder is initialized, we dont have a binding context to publish against.
2854 // Thus, we will always return NULL for its binding context.
2857 pBindingContext = dac_cast<PTR_ICLRPrivBinder>(GetHostAssembly());
2860 return pBindingContext;