16c66b516dc173947fc04632cb5b6abf17e2f049
[platform/upstream/coreclr.git] / src / vm / pefile.cpp
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 // --------------------------------------------------------------------------------
5 // PEFile.cpp
6 // 
7
8 // --------------------------------------------------------------------------------
9
10
11 #include "common.h"
12 #include "pefile.h"
13 #include "strongname.h"
14 #include "corperm.h"
15 #include "eecontract.h"
16 #include "apithreadstress.h"
17 #include "eeconfig.h"
18 #include "product_version.h"
19 #include "eventtrace.h"
20 #include "security.h"
21 #include "corperm.h"
22 #include "dbginterface.h"
23 #include "peimagelayout.inl"
24 #include "dlwrap.h"
25 #include "invokeutil.h"
26 #ifdef FEATURE_PREJIT
27 #include "compile.h"
28 #endif
29 #include "strongnameinternal.h"
30
31 #include "../binder/inc/applicationcontext.hpp"
32
33 #include "clrprivbinderutil.h"
34 #include "../binder/inc/coreclrbindercommon.h"
35
36
37 #ifdef FEATURE_PREJIT
38 #include "compile.h"
39
40 #ifdef DEBUGGING_SUPPORTED
41 SVAL_IMPL_INIT(DWORD, PEFile, s_NGENDebugFlags, 0);
42 #endif
43 #endif
44
45 #include "sha1.h"
46
47
48 #ifndef DACCESS_COMPILE
49
50 // ================================================================================
51 // PEFile class - this is an abstract base class for PEModule and PEAssembly
52 // <TODO>@todo: rename TargetFile</TODO>
53 // ================================================================================
54
55 PEFile::PEFile(PEImage *identity, BOOL fCheckAuthenticodeSignature/*=TRUE*/) :
56 #if _DEBUG
57     m_pDebugName(NULL),
58 #endif
59     m_identity(NULL),
60     m_openedILimage(NULL),
61 #ifdef FEATURE_PREJIT    
62     m_nativeImage(NULL),
63     m_fCanUseNativeImage(TRUE),
64 #endif
65     m_MDImportIsRW_Debugger_Use_Only(FALSE),
66     m_bHasPersistentMDImport(FALSE),
67     m_pMDImport(NULL),
68     m_pImporter(NULL),
69     m_pEmitter(NULL),
70     m_pMetadataLock(::new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)),
71     m_refCount(1),
72     m_hash(NULL),
73     m_flags(0),
74     m_fStrongNameVerified(FALSE)
75     ,m_pHostAssembly(nullptr)
76     ,m_pFallbackLoadContextBinder(nullptr)
77 {
78     CONTRACTL
79     {
80         CONSTRUCTOR_CHECK;
81         THROWS;
82         GC_TRIGGERS;
83         MODE_ANY;
84     }
85     CONTRACTL_END;
86
87     if (identity)
88     {
89         identity->AddRef();
90         m_identity = identity;
91
92         if(identity->IsOpened())
93         {
94             //already opened, prepopulate
95             identity->AddRef();
96             m_openedILimage = identity;
97         }
98     }
99
100
101 }
102
103
104
105 PEFile::~PEFile()
106 {
107     CONTRACTL
108     {
109         DESTRUCTOR_CHECK;
110         NOTHROW;
111         GC_TRIGGERS;
112         MODE_ANY;
113     }
114     CONTRACTL_END;
115     
116     ReleaseMetadataInterfaces(TRUE);
117     
118     if (m_hash != NULL)
119         delete m_hash;
120
121 #ifdef FEATURE_PREJIT
122     if (m_nativeImage != NULL)
123     {
124         MarkNativeImageInvalidIfOwned();
125
126         m_nativeImage->Release();
127     }
128 #endif //FEATURE_PREJIT
129
130
131     if (m_openedILimage != NULL)
132         m_openedILimage->Release();
133     if (m_identity != NULL)
134         m_identity->Release();
135     if (m_pMetadataLock)
136         delete m_pMetadataLock;
137
138     if (m_pHostAssembly != NULL)
139     {
140         m_pHostAssembly->Release();
141     }
142 }
143
144 #ifndef  DACCESS_COMPILE
145 void PEFile::ReleaseIL()
146 {
147     WRAPPER_NO_CONTRACT;
148     if (m_openedILimage!=NULL )
149     {
150         ReleaseMetadataInterfaces(TRUE, TRUE);
151         if (m_identity != NULL)
152         {
153             m_identity->Release();
154             m_identity=NULL;
155         }
156         m_openedILimage->Release();
157         m_openedILimage = NULL;
158     }
159 }
160 #endif
161
162 /* static */
163 PEFile *PEFile::Open(PEImage *image)
164 {
165     CONTRACT(PEFile *)
166     {
167         PRECONDITION(image != NULL);
168         PRECONDITION(image->CheckFormat());
169         POSTCONDITION(RETVAL != NULL);
170         POSTCONDITION(!RETVAL->IsModule());
171         POSTCONDITION(!RETVAL->IsAssembly());
172         THROWS;
173         GC_TRIGGERS;
174         MODE_ANY;
175         INJECT_FAULT(COMPlusThrowOM(););
176     }
177     CONTRACT_END;
178
179     PEFile *pFile = new PEFile(image, FALSE);
180
181     if (image->HasNTHeaders() && image->HasCorHeader())
182         pFile->OpenMDImport_Unsafe(); //no one else can see the object yet
183
184 #if _DEBUG
185     pFile->m_debugName = image->GetPath();
186     pFile->m_debugName.Normalize();
187     pFile->m_pDebugName = pFile->m_debugName;
188 #endif
189
190     RETURN pFile;
191 }
192
193 // ------------------------------------------------------------
194 // Loader support routines
195 // ------------------------------------------------------------
196
197 template<class T> void CoTaskFree(T *p)
198 {
199     if (p != NULL)
200     {
201         p->T::~T();
202
203         CoTaskMemFree(p);
204     }
205 }
206
207
208 NEW_WRAPPER_TEMPLATE1(CoTaskNewHolder, CoTaskFree<_TYPE>);
209
210 BOOL PEFile::CanLoadLibrary()
211 {
212     WRAPPER_NO_CONTRACT;
213
214     // Dynamic and resource modules don't need LoadLibrary.
215     if (IsDynamic() || IsResource()||IsLoaded())
216         return TRUE;
217
218     // If we're been granted skip verification, OK
219     if (HasSkipVerification())
220         return TRUE;
221
222     // Otherwise, we can only load if IL only.
223     return IsILOnly();
224 }
225
226
227
228 //-----------------------------------------------------------------------------------------------------
229 // Catch attempts to load x64 assemblies on x86, etc.
230 //-----------------------------------------------------------------------------------------------------
231 static void ValidatePEFileMachineType(PEFile *peFile)
232 {
233     STANDARD_VM_CONTRACT;
234
235     if (peFile->IsIntrospectionOnly())
236         return;    // ReflectionOnly assemblies permitted to violate CPU restrictions
237
238     if (peFile->IsDynamic())
239         return;    // PEFiles for ReflectionEmit assemblies don't cache the machine type.
240
241     if (peFile->IsResource())
242         return;    // PEFiles for resource assemblies don't cache the machine type.
243
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.
246
247     DWORD peKind;
248     DWORD actualMachineType;
249     peFile->GetPEKindAndMachine(&peKind, &actualMachineType);
250
251     if (actualMachineType == IMAGE_FILE_MACHINE_I386 && ((peKind & (peILonly | pe32BitRequired)) == peILonly))
252         return;    // Image is marked CPU-agnostic.
253
254     if (actualMachineType != IMAGE_FILE_MACHINE_NATIVE && actualMachineType != IMAGE_FILE_MACHINE_NATIVE_NI)
255     {
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.
259         //
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)
263             return;
264 #endif // _WIN64_
265
266         // Image has required machine that doesn't match the CLR.
267         StackSString name;
268         if (peFile->IsAssembly())
269             ((PEAssembly*)peFile)->GetDisplayName(name);
270         else
271             name = StackSString(SString::Utf8, peFile->GetSimpleName());
272
273         COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode());
274     }
275
276     return;   // If we got here, all is good.
277 }
278
279 void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load
280 {
281     CONTRACT_VOID
282     {
283         INSTANCE_CHECK;
284         POSTCONDITION(CheckLoaded());
285         STANDARD_VM_CHECK;
286     }
287     CONTRACT_END;
288
289     // Catch attempts to load x64 assemblies on x86, etc.
290     ValidatePEFileMachineType(this);
291
292     // See if we've already loaded it.
293     if (CheckLoaded(allowNativeSkip))
294     {
295         RETURN;
296     }
297
298     // Note that we may be racing other threads here, in the case of domain neutral files
299
300     // Resource images are always flat.
301     if (IsResource())
302     {
303         GetILimage()->LoadNoMetaData(IsIntrospectionOnly());
304         RETURN;
305     }
306
307 #if !defined(_WIN64)
308     if (!HasNativeImage() && (!GetILimage()->Has32BitNTHeaders()) && !IsIntrospectionOnly())
309     {
310         // Tried to load 64-bit assembly on 32-bit platform.
311         EEFileLoadException::Throw(this, COR_E_BADIMAGEFORMAT, NULL);
312     }
313 #endif
314
315     // Don't do this if we are unverifiable
316     if (!CanLoadLibrary())
317         ThrowHR(SECURITY_E_UNVERIFIABLE);
318
319
320     // We need contents now
321     if (!HasNativeImage())
322     {
323         EnsureImageOpened();
324     }
325
326     if (IsIntrospectionOnly())
327     {
328         GetILimage()->LoadForIntrospection();
329         RETURN;
330     }
331
332
333     //---- Below this point, only do the things necessary for execution ----
334     _ASSERTE(!IsIntrospectionOnly());
335
336 #ifdef FEATURE_PREJIT
337     // For on-disk Dlls, we can call LoadLibrary
338     if (IsDll() && !((HasNativeImage()?m_nativeImage:GetILimage())->GetPath().IsEmpty()))
339     {
340         // Note that we may get a DllMain notification inside here.
341         if (allowNativeSkip && HasNativeImage())
342         {
343             m_nativeImage->Load();
344             if(!m_nativeImage->IsNativeILILOnly())
345                 GetILimage()->Load();             // For IJW we have to load IL also...
346         }
347         else
348             GetILimage()->Load();
349     }
350     else
351 #endif // FEATURE_PREJIT
352     {
353
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())
359         {
360             if (!GetILimage()->HasV1Metadata())
361                 ThrowHR(COR_E_FIXUPSINEXE); // <TODO>@todo: better error</TODO>            
362         }
363
364
365
366         // If we are already mapped, we can just use the current image.
367 #ifdef FEATURE_PREJIT
368         if (allowNativeSkip && HasNativeImage())
369         {
370             m_nativeImage->LoadFromMapped();
371
372             if( !m_nativeImage->IsNativeILILOnly())
373                 GetILimage()->LoadFromMapped();        // For IJW we have to load IL also...
374         }
375         else
376 #endif
377         {
378             if (GetILimage()->IsFile())
379                 GetILimage()->LoadFromMapped();
380             else
381                 GetILimage()->LoadNoFile();
382         }
383     }
384
385
386     RETURN;
387 }
388
389 void PEFile::SetLoadedHMODULE(HMODULE hMod)
390 {
391     CONTRACT_VOID
392     {
393         INSTANCE_CHECK;
394         PRECONDITION(CheckPointer(hMod));
395         PRECONDITION(CanLoadLibrary());
396         POSTCONDITION(CheckLoaded());
397         THROWS;
398         GC_TRIGGERS;
399         MODE_ANY;
400         INJECT_FAULT(COMPlusThrowOM(););
401     }
402     CONTRACT_END;
403
404     // See if the image is an internal PEImage.
405     GetILimage()->SetLoadedHMODULE(hMod);
406
407     RETURN;
408 }
409
410 /* static */
411 void PEFile::DefineEmitScope(
412     GUID   iid, 
413     void **ppEmit)
414 {
415     CONTRACT_VOID
416     {
417         PRECONDITION(CheckPointer(ppEmit));
418         POSTCONDITION(CheckPointer(*ppEmit));
419         THROWS;
420         GC_TRIGGERS;
421         MODE_ANY;
422         INJECT_FAULT(COMPlusThrowOM(););
423     }
424     CONTRACT_END;
425     
426     SafeComHolder<IMetaDataDispenserEx> pDispenser;
427     
428     // Get the Dispenser interface.
429     MetaDataGetDispenser(
430         CLSID_CorMetaDataDispenser, 
431         IID_IMetaDataDispenserEx, 
432         (void **)&pDispenser);
433     if (pDispenser == NULL)
434     {
435         ThrowOutOfMemory();
436     }
437     
438     // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef
439     VARIANT varOption;
440     V_VT(&varOption) = VT_UI4;
441     V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile;
442     IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption));
443     
444     // Set minimal MetaData size
445     V_VT(&varOption) = VT_UI4;
446     V_I4(&varOption) = MDInitialSizeMinimal;
447     IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption));
448     
449     // turn on the thread safety!
450     V_I4(&varOption) = MDThreadSafetyOn;
451     IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption));
452     
453     IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown **)ppEmit));
454     
455     RETURN;
456 } // PEFile::DefineEmitScope
457
458 // ------------------------------------------------------------
459 // Identity
460 // ------------------------------------------------------------
461
462 BOOL PEFile::Equals(PEFile *pFile)
463 {
464     CONTRACTL
465     {
466         INSTANCE_CHECK;
467         PRECONDITION(CheckPointer(pFile));
468         GC_NOTRIGGER;
469         NOTHROW;
470         CANNOT_TAKE_LOCK;
471         MODE_ANY;
472     }
473     CONTRACTL_END;
474
475     // Same object is equal
476     if (pFile == this)
477         return TRUE;
478
479
480     // Execution and introspection files are NOT equal
481     if ( (!IsIntrospectionOnly()) != !(pFile->IsIntrospectionOnly()) )
482     {
483         return FALSE;
484     }
485
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())
491     {
492         UINT_PTR fileBinderId = 0;
493         if (FAILED(pFile->GetHostAssembly()->GetBinderID(&fileBinderId)))
494             return FALSE;
495
496         UINT_PTR thisBinderId = 0;
497         if (FAILED(this->GetHostAssembly()->GetBinderID(&thisBinderId)))
498             return FALSE;
499
500         if (fileBinderId != thisBinderId)
501             return FALSE;
502
503     }
504
505     // Same identity is equal
506     if (m_identity != NULL && pFile->m_identity != NULL
507         && m_identity->Equals(pFile->m_identity))
508         return TRUE;
509
510     // Same image is equal
511     if (m_openedILimage != NULL && pFile->m_openedILimage != NULL
512         && m_openedILimage->Equals(pFile->m_openedILimage))
513         return TRUE;
514
515     return FALSE;
516 }
517
518 BOOL PEFile::Equals(PEImage *pImage)
519 {
520     CONTRACTL
521     {
522         INSTANCE_CHECK;
523         PRECONDITION(CheckPointer(pImage));
524         GC_NOTRIGGER;
525         NOTHROW;
526         MODE_ANY;
527     }
528     CONTRACTL_END;
529
530     // Same object is equal
531     if (pImage == m_identity || pImage == m_openedILimage)
532         return TRUE;
533
534 #ifdef FEATURE_PREJIT
535     if(pImage == m_nativeImage)
536         return TRUE;
537 #endif    
538     // Same identity is equal
539     if (m_identity != NULL
540         && m_identity->Equals(pImage))
541         return TRUE;
542
543     // Same image is equal
544     if (m_openedILimage != NULL
545         && m_openedILimage->Equals(pImage))
546         return TRUE;
547
548
549     return FALSE;
550 }
551
552 // ------------------------------------------------------------
553 // Descriptive strings
554 // ------------------------------------------------------------
555
556 void PEFile::GetCodeBaseOrName(SString &result)
557 {
558     CONTRACTL
559     {
560         INSTANCE_CHECK;
561         THROWS;
562         GC_TRIGGERS;
563         MODE_ANY;
564         INJECT_FAULT(COMPlusThrowOM(););
565     }
566     CONTRACTL_END;
567
568     if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
569     {
570         result.Set(m_identity->GetPath());
571     }
572     else if (IsAssembly())
573     {
574         ((PEAssembly*)this)->GetCodeBase(result);
575     }
576     else
577         result.SetUTF8(GetSimpleName());
578 }
579
580
581 // ------------------------------------------------------------
582 // Checks
583 // ------------------------------------------------------------
584
585
586
587 CHECK PEFile::CheckLoaded(BOOL bAllowNativeSkip/*=TRUE*/)
588 {
589     CONTRACT_CHECK
590     {
591         INSTANCE_CHECK;
592         NOTHROW;
593         GC_NOTRIGGER;
594         SO_TOLERANT;
595         MODE_ANY;
596     }
597     CONTRACT_CHECK_END;
598
599     CHECK(IsLoaded(bAllowNativeSkip)
600           // We are allowed to skip LoadLibrary in most cases for ngen'ed IL only images
601           || (bAllowNativeSkip && HasNativeImage() && IsILOnly()));
602
603     CHECK_OK;
604 }
605
606
607 // ------------------------------------------------------------
608 // Metadata access
609 // ------------------------------------------------------------
610
611 PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize)
612 {
613     CONTRACT(PTR_CVOID)
614     {
615         INSTANCE_CHECK;
616         POSTCONDITION(CheckPointer(pSize, NULL_OK));
617         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
618         THROWS;
619         GC_TRIGGERS;
620         MODE_ANY;
621         SUPPORTS_DAC;
622     }
623     CONTRACT_END;
624
625 #ifdef FEATURE_PREJIT
626     if (HasNativeImageMetadata())
627     {
628         RETURN m_nativeImage->GetMetadata(pSize);
629     }
630 #endif
631
632     if (IsDynamic()
633          || !GetILimage()->HasNTHeaders()
634          || !GetILimage()->HasCorHeader())
635     {
636         if (pSize != NULL)
637             *pSize = 0;
638         RETURN NULL;
639     }
640     else
641     {
642         RETURN GetILimage()->GetMetadata(pSize);
643     }
644 }
645 #endif // #ifndef DACCESS_COMPILE
646
647 PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize)
648 {
649     CONTRACT(PTR_CVOID)
650     {
651         INSTANCE_CHECK;
652         POSTCONDITION(CheckPointer(pSize, NULL_OK));
653         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
654         NOTHROW;
655         GC_NOTRIGGER;
656         MODE_ANY;
657         SUPPORTS_DAC;
658     }
659     CONTRACT_END;
660
661 #ifdef FEATURE_PREJIT
662     if (HasNativeImageMetadata())
663     {
664         RETURN GetLoadedNative()->GetMetadata(pSize);
665     }
666 #endif
667
668     if (!HasLoadedIL() 
669          || !GetLoadedIL()->HasNTHeaders()
670          || !GetLoadedIL()->HasCorHeader())
671     {
672         if (pSize != NULL)
673             *pSize = 0;
674         RETURN NULL;
675     }
676     else
677     {
678         RETURN GetLoadedIL()->GetMetadata(pSize);
679     }
680 }
681
682 TADDR PEFile::GetIL(RVA il)
683 {
684     CONTRACT(TADDR)
685     {
686         INSTANCE_CHECK;
687         PRECONDITION(il != 0);
688         PRECONDITION(!IsDynamic());
689         PRECONDITION(!IsResource());
690 #ifndef DACCESS_COMPILE
691         PRECONDITION(CheckLoaded());
692 #endif
693         POSTCONDITION(RETVAL != NULL);
694         THROWS;
695         GC_NOTRIGGER;
696         MODE_ANY;
697         SUPPORTS_DAC;
698     }
699     CONTRACT_END;
700
701     PEImageLayout *image = NULL;
702
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())
708     {
709         image = GetLoadedNative();
710
711 #ifndef DACCESS_COMPILE
712         // NGen images are trusted to be well-formed.
713         _ASSERTE(image->CheckILMethod(il));
714 #endif
715     }
716     else
717 #endif // FEATURE_PREJIT
718     {
719         image = GetLoadedIL();
720
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);
725 #endif
726     }
727
728     RETURN image->GetRvaData(il);
729 }
730
731 #ifndef DACCESS_COMPILE
732
733 void PEFile::OpenImporter()
734 {
735     CONTRACTL
736     {
737         INSTANCE_CHECK;
738         THROWS;
739         GC_NOTRIGGER;
740         MODE_ANY;
741         INJECT_FAULT(COMPlusThrowOM(););
742     } 
743     CONTRACTL_END;
744
745     // Make sure internal MD is in RW format.
746     ConvertMDInternalToReadWrite();
747  
748     IMetaDataImport2 *pIMDImport = NULL;
749     IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(), 
750                                                        IID_IMetaDataImport2, 
751                                                        (void **)&pIMDImport));
752
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();
756 }
757
758 void PEFile::ConvertMDInternalToReadWrite()
759 {
760     CONTRACTL
761     {
762         INSTANCE_CHECK;
763         THROWS;
764         GC_NOTRIGGER;
765         MODE_ANY;
766         INJECT_FAULT(EX_THROW(EEMessageException, (E_OUTOFMEMORY)););
767     }
768     CONTRACTL_END;
769
770     IMDInternalImport *pOld;            // Old (current RO) value of internal import.
771     IMDInternalImport *pNew = NULL;     // New (RW) value of internal import.
772
773     // Take a local copy of *ppImport.  This may be a pointer to an RO
774     //  or to an RW MDInternalXX.
775     pOld = m_pMDImport;
776     IMetaDataImport *pIMDImport = m_pImporter;
777     if (pIMDImport != NULL)
778     {
779         HRESULT hr = GetMetaDataInternalInterfaceFromPublic(pIMDImport, IID_IMDInternalImport, (void **)&pNew);
780         if (FAILED(hr))
781         {
782             EX_THROW(EEMessageException, (hr));
783         }
784         if (pNew == pOld)
785         {
786             pNew->Release();
787             return;
788         }
789     }
790     else
791     {
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);
795
796         if (FAILED(hr))
797         {
798             EX_THROW(EEMessageException, (hr));
799         }
800
801         // If no conversion took place, don't change pointers.
802         if (hr == S_FALSE)
803             return;
804     }
805
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)
811     {   
812         //if the debugger queries, it will now see that we have RW metadata
813         m_MDImportIsRW_Debugger_Use_Only = TRUE;
814
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");
818         IfFailThrow(hr);
819     }
820     else
821     {   // Some other thread finished first.  Just free the results of this conversion.
822         pNew->Release();
823     }
824 }
825
826 void PEFile::ConvertMetadataToRWForEnC()
827 {
828     CONTRACTL
829     {
830         THROWS;
831         GC_NOTRIGGER;
832         SO_INTOLERANT;
833         MODE_ANY;
834     }
835     CONTRACTL_END;
836
837     // This should only ever be called on EnC capable files.
838     // One can check this using Module::IsEditAndContinueCapable().
839     
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());
844
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();
849 }
850
851 void PEFile::OpenMDImport_Unsafe()
852 {
853     CONTRACTL
854     {
855         INSTANCE_CHECK;
856         THROWS;
857         GC_TRIGGERS;
858         MODE_ANY;
859         INJECT_FAULT(COMPlusThrowOM(););
860     }
861     CONTRACTL_END;
862
863     if (m_pMDImport != NULL)
864         return;
865 #ifdef FEATURE_PREJIT    
866     if (m_nativeImage != NULL
867         && m_nativeImage->GetMDImport() != NULL
868         )
869     {
870         // Use native image for metadata
871         m_flags |= PEFILE_HAS_NATIVE_IMAGE_METADATA;
872         m_pMDImport=m_nativeImage->GetMDImport();
873     }
874     else
875 #endif
876     {
877 #ifdef FEATURE_PREJIT        
878         m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
879 #endif
880         if (!IsDynamic()
881            && GetILimage()->HasNTHeaders()
882              && GetILimage()->HasCorHeader())
883         {
884             m_pMDImport=GetILimage()->GetMDImport();
885         }
886         else
887             ThrowHR(COR_E_BADIMAGEFORMAT);
888
889         m_bHasPersistentMDImport=TRUE;
890     }
891     _ASSERTE(m_pMDImport);
892     m_pMDImport->AddRef();
893 }
894
895 void PEFile::OpenEmitter()
896 {
897     CONTRACTL
898     {
899         INSTANCE_CHECK;
900         THROWS;
901         GC_NOTRIGGER;
902         MODE_ANY;
903         INJECT_FAULT(COMPlusThrowOM(););
904     }
905     CONTRACTL_END;
906
907     // Make sure internal MD is in RW format.
908     ConvertMDInternalToReadWrite();
909
910     IMetaDataEmit *pIMDEmit = NULL;
911     IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
912                                                        IID_IMetaDataEmit,
913                                                        (void **)&pIMDEmit));
914
915     // Atomically swap it into the field (release it if we lose the race)
916     if (FastInterlockCompareExchangePointer(&m_pEmitter, pIMDEmit, NULL) != NULL)
917         pIMDEmit->Release();
918 }
919
920
921 void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor, BOOL bKeepNativeData/*=FALSE*/)
922 {
923     CONTRACTL
924     {
925         INSTANCE_CHECK;
926         NOTHROW;
927         GC_NOTRIGGER;
928         MODE_ANY;
929         PRECONDITION(bDestructor||m_pMetadataLock->IsWriterLock());
930     }
931     CONTRACTL_END;
932     _ASSERTE(bDestructor || !m_bHasPersistentMDImport);
933
934     if (m_pImporter != NULL)
935     {
936         m_pImporter->Release();
937         m_pImporter = NULL;
938     }
939     if (m_pEmitter != NULL)
940     {
941         m_pEmitter->Release();
942         m_pEmitter = NULL;
943     }
944
945     if (m_pMDImport != NULL && (!bKeepNativeData || !HasNativeImage()))
946     {
947         m_pMDImport->Release();
948         m_pMDImport=NULL;
949      }
950 }
951
952
953 // ------------------------------------------------------------
954 // PE file access
955 // ------------------------------------------------------------
956
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.
961
962 #endif //!DACCESS_COMPILE
963
964 #ifdef FEATURE_PREJIT
965 #ifndef DACCESS_COMPILE
966 // ------------------------------------------------------------
967 // Native image access
968 // ------------------------------------------------------------
969
970 void PEFile::SetNativeImage(PEImage *image)
971 {
972     CONTRACT_VOID
973     {
974         INSTANCE_CHECK;
975         PRECONDITION(!HasNativeImage());
976         STANDARD_VM_CHECK;
977     }
978     CONTRACT_END;
979
980     _ASSERTE(image != NULL);
981     PREFIX_ASSUME(image != NULL);
982
983     if (image->GetLoadedLayout()->GetBase() != image->GetLoadedLayout()->GetPreferredBase())
984     {
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()));
990     }
991
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())
999         RETURN;
1000 #endif
1001
1002     m_nativeImage = image;
1003     m_nativeImage->AddRef();
1004     m_nativeImage->Load();
1005     m_nativeImage->AllocateLazyCOWPages();
1006
1007 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
1008     static ConfigDWORD configNGenReserveForJumpStubs;
1009     int percentReserveForJumpStubs = configNGenReserveForJumpStubs.val(CLRConfig::INTERNAL_NGenReserveForJumpStubs);
1010     if (percentReserveForJumpStubs != 0)
1011     {
1012         PEImageLayout * pLayout = image->GetLoadedLayout();
1013         ExecutionManager::GetEEJitManager()->EnsureJumpStubReserve((BYTE *)pLayout->GetBase(), pLayout->GetVirtualSize(),
1014             percentReserveForJumpStubs * (pLayout->GetVirtualSize() / 100));
1015     }
1016 #endif
1017
1018     ExternalLog(LL_INFO100, W("Attempting to use native image %s."), image->GetPath().GetUnicode());
1019     RETURN;
1020 }
1021
1022 void PEFile::ClearNativeImage()
1023 {
1024     CONTRACT_VOID
1025     {
1026         INSTANCE_CHECK;
1027         PRECONDITION(HasNativeImage());
1028         POSTCONDITION(!HasNativeImage());
1029         THROWS;
1030         GC_TRIGGERS;
1031         MODE_ANY;
1032         INJECT_FAULT(COMPlusThrowOM(););
1033     }
1034     CONTRACT_END;
1035
1036     ExternalLog(LL_WARNING, "Discarding native image.");
1037
1038
1039     MarkNativeImageInvalidIfOwned();
1040
1041     {
1042         GCX_PREEMP();
1043         SafeComHolderPreemp<IMDInternalImport> pOldImport=GetMDImportWithRef();
1044         SimpleWriteLockHolder lock(m_pMetadataLock);
1045
1046         EX_TRY
1047         {
1048             ReleaseMetadataInterfaces(FALSE);
1049             m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1050             if (m_nativeImage)
1051                 m_nativeImage->Release();
1052             m_nativeImage = NULL;
1053             // Make sure our normal image is open
1054             EnsureImageOpened();
1055
1056             // Reopen metadata from normal image
1057             OpenMDImport();
1058         }
1059         EX_HOOK
1060         {
1061             RestoreMDImport(pOldImport);
1062         }
1063         EX_END_HOOK;
1064     }
1065
1066     RETURN;
1067 }
1068
1069
1070 extern DWORD g_dwLogLevel;
1071
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)
1076 {
1077     STANDARD_VM_CONTRACT;
1078
1079     BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1080     BOOL fOutputToLogging = LoggingOn(LF_ZAP, level);
1081
1082     StackSString message;
1083     message.VPrintf(fmt, args);
1084
1085     if (fOutputToLogging)
1086     {
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"));
1091     }
1092
1093     if (fOutputToDebugger)
1094     {
1095         SString displayString = pLogAsm->DisplayString();
1096         WszOutputDebugString(W("CLR:("));
1097         WszOutputDebugString(displayString.GetUnicode());
1098         WszOutputDebugString(W(") "));
1099         WszOutputDebugString(message);
1100         WszOutputDebugString(W("\n"));
1101     }
1102
1103 }
1104
1105
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, ...)
1110 {
1111     STANDARD_VM_CONTRACT;
1112
1113     // Avoid calling RuntimeVerifyVLog unless logging is on
1114     if (   ((level == LL_ERROR) && IsDebuggerPresent()) 
1115         || LoggingOn(LF_ZAP, level)
1116        ) 
1117     {
1118         va_list args;
1119         va_start(args, fmt);
1120
1121         RuntimeVerifyVLog(level, pLogAsm, fmt, args);
1122
1123         va_end(args);
1124     }
1125 }
1126
1127 //==============================================================================
1128
1129 static const LPCWSTR CorCompileRuntimeDllNames[NUM_RUNTIME_DLLS] =
1130 {
1131     MAKEDLLNAME_W(W("coreclr")),
1132     MAKEDLLNAME_W(W("clrjit"))
1133 };
1134
1135
1136 LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id)
1137 {
1138     CONTRACTL
1139     {
1140         THROWS;
1141         GC_TRIGGERS;
1142         MODE_ANY;
1143         SO_INTOLERANT;
1144         INJECT_FAULT(COMPlusThrowOM(););
1145     }
1146     CONTRACTL_END;
1147
1148
1149     return CorCompileRuntimeDllNames[id];
1150 }
1151
1152 #ifndef CROSSGEN_COMPILE
1153
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).
1157
1158 // Gets set by IJitManager::LoadJit (yes, this breaks the abstraction boundary).
1159 HMODULE s_ngenCompilerDll = NULL;
1160
1161 extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id)
1162 {
1163     CONTRACTL
1164     {
1165         THROWS;
1166         GC_NOTRIGGER;
1167         MODE_ANY;
1168         SO_INTOLERANT;
1169         INJECT_FAULT(COMPlusThrowOM(););
1170     }
1171     CONTRACTL_END;
1172
1173     // Currently special cased for every entry.
1174     static_assert_no_msg(NUM_RUNTIME_DLLS == 2);
1175     static_assert_no_msg(CORECLR_INFO == 0);
1176
1177     HMODULE hMod = NULL;
1178
1179     // Try to load the correct DLL
1180     switch (id)
1181     {
1182     case CORECLR_INFO:
1183         hMod = GetCLRModule();
1184         break;
1185
1186     default:
1187         COMPlusThrowNonLocalized(kExecutionEngineException,
1188             W("Invalid runtime DLL ID"));
1189         break;
1190     }
1191
1192     return hMod;
1193 }
1194 #endif // CROSSGEN_COMPILE
1195
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)
1201 {
1202     STANDARD_VM_CONTRACT;
1203
1204
1205     return TRUE;
1206 }
1207
1208 //===========================================================================================================
1209 // Validates that an NI matches the running CLR, OS, CPU, etc. This is the entrypoint used by the CLR loader.
1210 //
1211 //===========================================================================================================
1212 BOOL PEAssembly::CheckNativeImageVersion(PEImage *peimage)
1213 {
1214     STANDARD_VM_CONTRACT;
1215
1216     //
1217     // Get the zap version header. Note that modules will not have version
1218     // headers - they add no additional versioning constraints from their
1219     // assemblies.
1220     //
1221     PEImageLayoutHolder image=peimage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED);
1222
1223     if (!image->HasNativeHeader())
1224         return FALSE;
1225
1226     if (!image->CheckNativeHeaderVersion())
1227     {
1228         // Wrong native image version is fatal error on CoreCLR
1229         ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1230     }
1231
1232     CORCOMPILE_VERSION_INFO *info = image->GetNativeVersionInfo();
1233     if (info == NULL)
1234         return FALSE;
1235
1236     LoggablePEAssembly logAsm(this);
1237     if (!RuntimeVerifyNativeImageVersion(info, &logAsm))
1238     {
1239         // Wrong native image version is fatal error on CoreCLR
1240         ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1241     }
1242
1243     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1244
1245     if (IsSystem())
1246     {
1247         // Require instrumented flags for mscorlib when collecting IBC data
1248         CorCompileConfigFlags instrumentationConfigFlags = (CorCompileConfigFlags) (configFlags & CORCOMPILE_CONFIG_INSTRUMENTATION);
1249         if ((info->wConfigFlags & instrumentationConfigFlags) != instrumentationConfigFlags)
1250         {
1251             ExternalLog(LL_ERROR, "Instrumented native image for System.Private.CoreLib.dll expected.");
1252             ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1253         }
1254     }
1255
1256     // Otherwise, match regardless of the instrumentation flags
1257     configFlags = (CorCompileConfigFlags) (configFlags & ~(CORCOMPILE_CONFIG_INSTRUMENTATION_NONE | CORCOMPILE_CONFIG_INSTRUMENTATION));
1258
1259     if ((info->wConfigFlags & configFlags) != configFlags)
1260     {
1261         return FALSE;
1262     }
1263
1264     return TRUE;
1265 }
1266
1267
1268 //===========================================================================================================
1269 // Validates that an NI matches the running CLR, OS, CPU, etc.
1270 //
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.
1273 //
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)
1278 {
1279     STANDARD_VM_CONTRACT;
1280
1281     if (!RuntimeVerifyNativeImageTimestamps(info, pLogAsm))
1282         return FALSE;
1283
1284     //
1285     // Check that the EE version numbers are the same.
1286     //
1287  
1288     if (info->wVersionMajor != VER_MAJORVERSION
1289         || info->wVersionMinor != VER_MINORVERSION
1290         || info->wVersionBuildNumber != VER_PRODUCTBUILD
1291         || info->wVersionPrivateBuildNumber != VER_PRODUCTBUILD_QFE)
1292     {
1293         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("CLR version recorded in native image doesn't match the current CLR."));
1294         return FALSE;
1295     }
1296
1297     //
1298     // Check checked/free status
1299     //
1300
1301     if (info->wBuild !=
1302 #if _DEBUG
1303         CORCOMPILE_BUILD_CHECKED
1304 #else
1305         CORCOMPILE_BUILD_FREE
1306 #endif
1307         )
1308     {
1309         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Checked/free mismatch with native image."));
1310         return FALSE;
1311     }
1312
1313     //
1314     // Check processor
1315     //
1316
1317     if (info->wMachine != IMAGE_FILE_MACHINE_NATIVE_NI)
1318     {
1319         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Processor type recorded in native image doesn't match this machine's processor."));
1320         return FALSE;
1321     }
1322
1323 #ifndef CROSSGEN_COMPILE
1324     //
1325     // Check the processor specific ID
1326     //
1327
1328     CORINFO_CPU cpuInfo;
1329     GetSpecificCpuInfo(&cpuInfo);
1330
1331     if (!IsCompatibleCpuInfo(&cpuInfo, &info->cpuInfo))
1332     {
1333         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Required CPU features recorded in native image don't match this machine's processor."));
1334         return FALSE;
1335     }
1336 #endif // CROSSGEN_COMPILE
1337
1338
1339     //
1340     // The zap is up to date.
1341     //
1342
1343     RuntimeVerifyLog(LL_INFO100, pLogAsm, W("Native image has correct version information."));
1344     return TRUE;
1345 }
1346
1347 #endif // !DACCESS_COMPILE
1348
1349 /* static */
1350 CorCompileConfigFlags PEFile::GetNativeImageConfigFlags(BOOL fForceDebug/*=FALSE*/,
1351                                                         BOOL fForceProfiling/*=FALSE*/,
1352                                                         BOOL fForceInstrument/*=FALSE*/)
1353 {
1354     LIMITED_METHOD_DAC_CONTRACT;
1355
1356     CorCompileConfigFlags result = (CorCompileConfigFlags)0;
1357
1358     // Debugging
1359
1360 #ifdef DEBUGGING_SUPPORTED
1361     // if these have been set, the take precedence over anything else
1362     if (s_NGENDebugFlags)
1363     {
1364         if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG_NONE) != 0)
1365         {
1366             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_NONE);
1367         }
1368         else
1369         {
1370             if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG) != 0)
1371             {
1372                 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1373             }
1374         }
1375     }
1376     else
1377 #endif // DEBUGGING_SUPPORTED
1378     {
1379         if (fForceDebug)
1380         {
1381             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1382         }
1383         else
1384         {
1385             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_DEFAULT);
1386         }
1387     }
1388
1389     // Profiling
1390
1391 #ifdef PROFILING_SUPPORTED
1392     if (fForceProfiling || CORProfilerUseProfileImages())
1393     {
1394         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING);
1395
1396         result = (CorCompileConfigFlags) (result & ~(CORCOMPILE_CONFIG_DEBUG_NONE|
1397                                                      CORCOMPILE_CONFIG_DEBUG|
1398                                                      CORCOMPILE_CONFIG_DEBUG_DEFAULT));
1399     }
1400     else
1401 #endif //PROFILING_SUPPORTED
1402         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING_NONE);
1403
1404     // Instrumentation
1405 #ifndef DACCESS_COMPILE
1406     BOOL instrumented = (!IsCompilationProcess() && g_pConfig->GetZapBBInstr());
1407 #else
1408     BOOL instrumented = FALSE;
1409 #endif
1410     if (instrumented || fForceInstrument)
1411     {
1412         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION);
1413     }
1414     else
1415     {
1416         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION_NONE);
1417     }
1418
1419     // NOTE: Right now we are not taking instrumentation into account when binding.
1420
1421     return result;
1422 }
1423
1424 CorCompileConfigFlags PEFile::GetNativeImageConfigFlagsWithOverrides()
1425 {
1426     LIMITED_METHOD_DAC_CONTRACT;
1427
1428     BOOL fForceDebug, fForceProfiling, fForceInstrument;
1429     SystemDomain::GetCompilationOverrides(&fForceDebug,
1430                                           &fForceProfiling,
1431                                           &fForceInstrument);
1432     return PEFile::GetNativeImageConfigFlags(fForceDebug,
1433                                              fForceProfiling,
1434                                              fForceInstrument);
1435 }
1436
1437 #ifndef DACCESS_COMPILE
1438
1439
1440
1441 //===========================================================================================================
1442 // Validates that a hard-dep matches the a parent NI's compile-time hard-dep.
1443 //
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.
1446 //
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.
1449 //
1450 //===========================================================================================================
1451 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_NGEN_SIGNATURE &ngenSigExpected,
1452                                         const CORCOMPILE_VERSION_INFO *pActual,
1453                                         LoggableAssembly              *pLogAsm)
1454 {
1455     STANDARD_VM_CONTRACT;
1456
1457     if (ngenSigExpected != pActual->signature)
1458     {
1459         // Signature did not match
1460         SString displayString = pLogAsm->DisplayString();
1461         RuntimeVerifyLog(LL_ERROR,
1462                          pLogAsm,
1463                          W("Rejecting native image because native image dependency %s ")
1464                          W("had a different identity than expected"),
1465                          displayString.GetUnicode());
1466
1467         return FALSE;
1468     }
1469     return TRUE;
1470 }
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)
1475 {
1476     WRAPPER_NO_CONTRACT;
1477
1478     return RuntimeVerifyNativeImageDependency(pExpected->signNativeImage,
1479                                               pActual,
1480                                               pLogAsm);
1481 }
1482
1483 #endif // !DACCESS_COMPILE
1484
1485 #ifdef DEBUGGING_SUPPORTED
1486 //
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
1490 //
1491 void PEFile::SetNGENDebugFlags(BOOL fAllowOpt)
1492 {
1493     CONTRACTL
1494     {
1495         GC_NOTRIGGER;
1496         NOTHROW;
1497         MODE_ANY;
1498         SUPPORTS_DAC;
1499     }
1500     CONTRACTL_END;
1501
1502     if (fAllowOpt)
1503         s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG_NONE;
1504     else
1505         s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG;
1506     }
1507
1508 //
1509 // Called through ICorDebugAppDomain2::GetDesiredNGENCompilerFlags to determine
1510 // which kinds of ngen'd images fusion should load wrt debugging support
1511 //
1512 void PEFile::GetNGENDebugFlags(BOOL *fAllowOpt)
1513 {
1514     CONTRACTL
1515     {
1516         GC_NOTRIGGER;
1517         NOTHROW;
1518         MODE_ANY;
1519         SUPPORTS_DAC;
1520     }
1521     CONTRACTL_END;
1522
1523     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1524
1525     *fAllowOpt = ((configFlags & CORCOMPILE_CONFIG_DEBUG) == 0);
1526 }
1527 #endif // DEBUGGING_SUPPORTED
1528
1529
1530
1531 #ifndef DACCESS_COMPILE
1532 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1533
1534 //---------------------------------------------------------------------------------------
1535 //
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
1543 // scratch.
1544 //
1545 // Return Value:
1546 //      nonzero iff NGENd images should be treated as MSIL images.
1547 //
1548
1549 // static
1550 BOOL PEFile::ShouldTreatNIAsMSIL()
1551 {
1552     LIMITED_METHOD_CONTRACT;
1553
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())
1558         return TRUE;
1559
1560     // Ask profiling API & config vars whether NGENd images should be avoided
1561     // completely.
1562     if (!NGENImagesAllowed())
1563         return TRUE;
1564
1565     // Ask profiling and debugging if they're requesting us to use ngen /Debug or
1566     // /Profile images (which aren't available under Apollo)
1567
1568     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1569
1570     if ((configFlags & (CORCOMPILE_CONFIG_DEBUG | CORCOMPILE_CONFIG_PROFILING)) != 0)
1571         return TRUE;
1572
1573     return FALSE;
1574 }
1575
1576 #endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1577
1578 #endif  //!DACCESS_COMPILE
1579 #endif  // FEATURE_PREJIT
1580
1581 #ifndef DACCESS_COMPILE
1582
1583 // ------------------------------------------------------------
1584 // Resource access
1585 // ------------------------------------------------------------
1586
1587 void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource)
1588 {
1589     CONTRACTL
1590     {
1591         INSTANCE_CHECK;
1592         THROWS;
1593         GC_TRIGGERS;
1594         MODE_ANY;
1595         INJECT_FAULT(ThrowOutOfMemory(););
1596     }
1597     CONTRACTL_END;
1598
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.
1602
1603     PEImage *image;
1604
1605 #ifdef FEATURE_PREJIT
1606     if (m_nativeImage != NULL)
1607         image = m_nativeImage;
1608     else 
1609 #endif    
1610     {
1611         EnsureImageOpened();
1612         image = GetILimage();
1613     }
1614
1615     PEImageLayoutHolder theImage(image->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED));
1616     if (!theImage->CheckResource(dwOffset))
1617         ThrowHR(COR_E_BADIMAGEFORMAT);
1618
1619     COUNT_T size;
1620     const void *resource = theImage->GetResource(dwOffset, &size);
1621
1622     *cbResource = size;
1623     *pbInMemoryResource = (PBYTE) resource;
1624 }
1625
1626 // ------------------------------------------------------------
1627 // File loading
1628 // ------------------------------------------------------------
1629
1630 PEAssembly * 
1631 PEFile::LoadAssembly(
1632     mdAssemblyRef       kAssemblyRef,
1633     IMDInternalImport * pImport,                // = NULL
1634     LPCUTF8             szWinRtTypeNamespace,   // = NULL
1635     LPCUTF8             szWinRtTypeClassName)   // = NULL
1636 {
1637     CONTRACT(PEAssembly *)
1638     {
1639         INSTANCE_CHECK;
1640         THROWS;
1641         GC_TRIGGERS;
1642         MODE_ANY;
1643         POSTCONDITION(CheckPointer(RETVAL));
1644         INJECT_FAULT(COMPlusThrowOM(););
1645     }
1646     CONTRACT_END;
1647
1648     if (pImport == NULL)
1649         pImport = GetPersistentMDImport();
1650
1651     if (((TypeFromToken(kAssemblyRef) != mdtAssembly) && 
1652          (TypeFromToken(kAssemblyRef) != mdtAssemblyRef)) || 
1653         (!pImport->IsValidToken(kAssemblyRef)))
1654     {
1655         ThrowHR(COR_E_BADIMAGEFORMAT);
1656     }
1657     
1658     AssemblySpec spec;
1659     
1660     spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(GetAssembly()), IsIntrospectionOnly());
1661     if (szWinRtTypeClassName != NULL)
1662         spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
1663     
1664     RETURN GetAppDomain()->BindAssemblySpec(&spec, TRUE, IsIntrospectionOnly());
1665 }
1666
1667 // ------------------------------------------------------------
1668 // Logging
1669 // ------------------------------------------------------------
1670 #ifdef FEATURE_PREJIT
1671 void PEFile::ExternalLog(DWORD facility, DWORD level, const WCHAR *fmt, ...)
1672 {
1673     WRAPPER_NO_CONTRACT;
1674
1675     va_list args;
1676     va_start(args, fmt);
1677
1678     ExternalVLog(facility, level, fmt, args);
1679
1680     va_end(args);
1681 }
1682
1683 void PEFile::ExternalLog(DWORD level, const WCHAR *fmt, ...)
1684 {
1685     WRAPPER_NO_CONTRACT;
1686
1687     va_list args;
1688     va_start(args, fmt);
1689
1690     ExternalVLog(LF_ZAP, level, fmt, args);
1691
1692     va_end(args);
1693 }
1694
1695 void PEFile::ExternalLog(DWORD level, const char *msg)
1696 {
1697     WRAPPER_NO_CONTRACT;
1698
1699     // It is OK to use %S here. We know that msg is ASCII-only.
1700     ExternalLog(level, W("%S"), msg);
1701 }
1702
1703 void PEFile::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
1704 {
1705     CONTRACT_VOID
1706     {
1707         THROWS;
1708         GC_TRIGGERS;
1709     }
1710     CONTRACT_END;
1711
1712     BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1713     BOOL fOutputToLogging = LoggingOn(facility, level);
1714
1715     if (!fOutputToDebugger && !fOutputToLogging)
1716         return;
1717
1718     StackSString message;
1719     message.VPrintf(fmt, args);
1720
1721     if (fOutputToLogging)
1722     {
1723         if (GetMDImport() != NULL)
1724             LOG((facility, level, "%s: \"%s\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), GetSimpleName()));
1725         else
1726             LOG((facility, level, "%s: \"%S\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), ((const WCHAR *)GetPath())));
1727
1728         LOG((facility, level, "%S", message.GetUnicode()));
1729         LOG((facility, level, "\n"));
1730     }
1731
1732     if (fOutputToDebugger)
1733     {
1734         WszOutputDebugString(W("CLR:("));
1735
1736         StackSString codebase;
1737         GetCodeBaseOrName(codebase);
1738         WszOutputDebugString(codebase);
1739
1740         WszOutputDebugString(W(") "));
1741
1742         WszOutputDebugString(message);
1743         WszOutputDebugString(W("\n"));
1744     }
1745
1746     RETURN;
1747 }
1748
1749 void PEFile::FlushExternalLog()
1750 {
1751     LIMITED_METHOD_CONTRACT;
1752 }
1753 #endif
1754
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)
1760 {
1761     CONTRACTL
1762     {
1763         INSTANCE_CHECK;
1764         THROWS;
1765         MODE_ANY;
1766         INJECT_FAULT(COMPlusThrowOM(););
1767         WRAPPER(GC_TRIGGERS);
1768     }
1769     CONTRACTL_END;
1770
1771
1772     mdToken            mdLinkRef;
1773     DWORD              dwResourceFlags;
1774     DWORD              dwOffset;
1775     mdManifestResource mdResource;
1776     Assembly*          pAssembly = NULL;
1777     PEFile*            pPEFile = NULL;
1778     ReleaseHolder<IMDInternalImport> pImport (GetMDImportWithRef());
1779     if (SUCCEEDED(pImport->FindManifestResourceByName(szName, &mdResource)))
1780     {
1781         pPEFile = this;
1782         IfFailThrow(pImport->GetManifestResourceProps(
1783             mdResource, 
1784             NULL,           //&szName,
1785             &mdLinkRef, 
1786             &dwOffset, 
1787             &dwResourceFlags));
1788     }
1789     else
1790     {
1791         if (fSkipRaiseResolveEvent || pAppDomain == NULL)
1792             return FALSE;
1793
1794         DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(GetAssembly());
1795         pAssembly = pAppDomain->RaiseResourceResolveEvent(pParentAssembly, szName);
1796         if (pAssembly == NULL)
1797             return FALSE;
1798
1799         pDomainAssembly = pAssembly->GetDomainAssembly(pAppDomain);
1800         pPEFile = pDomainAssembly->GetFile();
1801
1802         if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName(
1803             szName,
1804             &mdResource)))
1805         {
1806             return FALSE;
1807         }
1808         
1809         if (dwLocation != 0)
1810         {
1811             if (pAssemblyRef != NULL)
1812                 *pAssemblyRef = pDomainAssembly;
1813             
1814             *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
1815         }
1816         IfFailThrow(pPEFile->GetPersistentMDImport()->GetManifestResourceProps(
1817             mdResource, 
1818             NULL,           //&szName,
1819             &mdLinkRef, 
1820             &dwOffset, 
1821             &dwResourceFlags));
1822     }
1823     
1824     
1825     switch(TypeFromToken(mdLinkRef)) {
1826     case mdtAssemblyRef:
1827         {
1828             if (pDomainAssembly == NULL)
1829                 return FALSE;
1830
1831             AssemblySpec spec;
1832             spec.InitializeSpec(mdLinkRef, GetPersistentMDImport(), pDomainAssembly, pDomainAssembly->GetFile()->IsIntrospectionOnly());
1833             pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED);
1834
1835             if (dwLocation) {
1836                 if (pAssemblyRef)
1837                     *pAssemblyRef = pDomainAssembly;
1838
1839                 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
1840             }
1841
1842             return pDomainAssembly->GetResource(szName,
1843                                                 cbResource,
1844                                                 pbInMemoryResource,
1845                                                 pAssemblyRef,
1846                                                 szFileName,
1847                                                 dwLocation,
1848                                                 pStackMark,
1849                                                 fSkipSecurityCheck,
1850                                                 fSkipRaiseResolveEvent);
1851         }
1852
1853     case mdtFile:
1854         if (mdLinkRef == mdFileNil)
1855         {
1856             // The resource is embedded in the manifest file
1857
1858 #ifndef CROSSGEN_COMPILE
1859             if (!IsMrPublic(dwResourceFlags) && pStackMark && !fSkipSecurityCheck)
1860             {
1861                 Assembly *pCallersAssembly = SystemDomain::GetCallersAssembly(pStackMark);
1862
1863                 if (pCallersAssembly &&  // full trust for interop
1864                     (!pCallersAssembly->GetManifestFile()->Equals(this)))
1865                 {
1866                     RefSecContext sCtx(AccessCheckOptions::kMemberAccess);
1867
1868                     AccessCheckOptions accessCheckOptions(
1869                         AccessCheckOptions::kMemberAccess,  /*accessCheckType*/
1870                         NULL,                               /*pAccessContext*/
1871                         FALSE,                              /*throwIfTargetIsInaccessible*/
1872                         (MethodTable *) NULL                /*pTargetMT*/
1873                         );
1874
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*/))
1878                         return FALSE;
1879                 }
1880             }
1881 #endif // CROSSGEN_COMPILE
1882
1883             if (dwLocation) {
1884                 *dwLocation = *dwLocation | 5; // ResourceLocation.embedded |
1885
1886                                                // ResourceLocation.containedInManifestFile
1887                 return TRUE;
1888             }
1889
1890             pPEFile->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource);
1891
1892             return TRUE;
1893         }
1894         return FALSE;
1895
1896     default:
1897         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_IN_MANIFESTRES);
1898     }
1899 }
1900
1901 void PEFile::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
1902 {
1903     WRAPPER_NO_CONTRACT;
1904
1905     if (IsResource() || IsDynamic())
1906     {
1907         if (pdwKind)
1908             *pdwKind = 0;
1909         if (pdwMachine)
1910             *pdwMachine = 0;
1911         return;
1912     }
1913
1914 #ifdef FEATURE_PREJIT
1915     if (IsNativeLoaded())
1916     {
1917         CONSISTENCY_CHECK(HasNativeImage());
1918
1919         m_nativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
1920         return;
1921     }
1922 #ifndef DACCESS_COMPILE
1923     if (!HasOpenedILimage())
1924     {
1925         //don't want to touch the IL image unless we already have
1926         ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef();
1927         if (pNativeImage)
1928         {
1929             pNativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
1930             return;
1931         }
1932     }
1933 #endif // DACCESS_COMPILE        
1934 #endif // FEATURE_PREJIT
1935
1936     GetILimage()->GetPEKindAndMachine(pdwKind, pdwMachine);
1937     return;
1938 }
1939
1940 ULONG PEFile::GetILImageTimeDateStamp()
1941 {
1942     CONTRACTL
1943     {
1944         NOTHROW;
1945         GC_NOTRIGGER;
1946         MODE_ANY;
1947     }
1948     CONTRACTL_END;
1949
1950 #ifdef FEATURE_PREJIT
1951     if (IsNativeLoaded())
1952     {
1953         CONSISTENCY_CHECK(HasNativeImage());
1954
1955         // The IL image's time stamp is copied to the native image.
1956         CORCOMPILE_VERSION_INFO* pVersionInfo = GetLoadedNative()->GetNativeVersionInfoMaybeNull();
1957         if (pVersionInfo == NULL)
1958         {
1959             return 0;
1960         }
1961         else
1962         {
1963             return pVersionInfo->sourceAssembly.timeStamp;
1964         }
1965     }
1966 #endif // FEATURE_PREJIT
1967
1968     return GetLoadedIL()->GetTimeDateStamp();
1969 }
1970
1971
1972 // ================================================================================
1973 // PEAssembly class - a PEFile which represents an assembly
1974 // ================================================================================
1975
1976 // Statics initialization.
1977 /* static */
1978 void PEAssembly::Attach()
1979 {
1980     STANDARD_VM_CONTRACT;
1981 }
1982
1983
1984 PEAssembly::PEAssembly(
1985                 CoreBindResult* pBindResultInfo, 
1986                 IMetaDataEmit* pEmit, 
1987                 PEFile *creator, 
1988                 BOOL system,
1989                 BOOL introspectionOnly/*=FALSE*/,
1990                 PEImage * pPEImageIL /*= NULL*/,
1991                 PEImage * pPEImageNI /*= NULL*/,
1992                 ICLRPrivAssembly * pHostAssembly /*= NULL*/)
1993
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)
2001 {
2002     CONTRACTL
2003     {
2004         CONSTRUCTOR_CHECK;
2005         PRECONDITION(CheckPointer(pEmit, NULL_OK));
2006         PRECONDITION(CheckPointer(creator, NULL_OK));
2007         PRECONDITION(pBindResultInfo == NULL || (pPEImageIL == NULL && pPEImageNI == NULL));
2008         STANDARD_VM_CHECK;
2009     }
2010     CONTRACTL_END;
2011
2012     if (introspectionOnly)
2013     {
2014         if (!system)  // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2015         {
2016             m_flags |= PEFILE_INTROSPECTIONONLY;
2017         }
2018     }
2019
2020     m_flags |= PEFILE_ASSEMBLY;
2021     if (system)
2022         m_flags |= PEFILE_SYSTEM;
2023
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)
2027     {
2028         SetNativeImage(pPEImageNI);
2029     }
2030
2031 #ifdef FEATURE_PREJIT
2032     if (pBindResultInfo && pBindResultInfo->HasNativeImage())
2033         SetNativeImage(pBindResultInfo->GetNativeImage());
2034 #endif
2035
2036     // If we have no native image, we require a mapping for the file.
2037     if (!HasNativeImage() || !IsILOnly())
2038         EnsureImageOpened();
2039
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)
2043     {
2044         m_bIsFromGAC = pBindResultInfo->IsFromGAC();
2045         m_bIsOnTpaList = pBindResultInfo->IsOnTpaList();
2046     }
2047
2048     // Check security related stuff
2049     VerifyStrongName();
2050
2051     // Open metadata eagerly to minimize failure windows
2052     if (pEmit == NULL)
2053         OpenMDImport_Unsafe(); //constructor, cannot race with anything
2054     else
2055     {
2056         _ASSERTE(!m_bHasPersistentMDImport);
2057         IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2058                                                            (void **)&m_pMDImport));
2059         m_pEmitter = pEmit;
2060         pEmit->AddRef();
2061         m_bHasPersistentMDImport=TRUE;
2062         m_MDImportIsRW_Debugger_Use_Only = TRUE;
2063     }
2064
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);
2069
2070     // Verify name eagerly
2071     LPCUTF8 szName = GetSimpleName();
2072     if (!*szName)
2073     {
2074         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2075     }
2076
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)
2080     {
2081         m_pHostAssembly = clr::SafeAddRef(pHostAssembly);
2082     }
2083
2084     if(pBindResultInfo != nullptr)
2085     {
2086         // Cannot have both pHostAssembly and a coreclr based bind
2087         _ASSERTE(pHostAssembly == nullptr);
2088         pBindResultInfo->GetBindAssembly(&m_pHostAssembly);
2089     }
2090     
2091 #if _DEBUG
2092     GetCodeBaseOrName(m_debugName);
2093     m_debugName.Normalize();
2094     m_pDebugName = m_debugName;
2095
2096     AssemblySpec spec;
2097     spec.InitializeSpec(this);
2098
2099     spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
2100                               ASM_DISPLAYF_CULTURE |
2101                               ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
2102                               m_sTextualIdentity);
2103 #endif
2104 }
2105
2106
2107
2108 PEAssembly *PEAssembly::Open(
2109     PEAssembly *       pParent,
2110     PEImage *          pPEImageIL, 
2111     PEImage *          pPEImageNI, 
2112     ICLRPrivAssembly * pHostAssembly, 
2113     BOOL               fIsIntrospectionOnly)
2114 {
2115     STANDARD_VM_CONTRACT;
2116
2117     PEAssembly * pPEAssembly = new PEAssembly(
2118         nullptr,        // BindResult
2119         nullptr,        // IMetaDataEmit
2120         pParent,        // PEFile creator
2121         FALSE,          // isSystem
2122         fIsIntrospectionOnly,
2123         pPEImageIL,
2124         pPEImageNI,
2125         pHostAssembly);
2126
2127     return pPEAssembly;
2128 }
2129
2130
2131 PEAssembly::~PEAssembly()
2132 {
2133     CONTRACTL
2134     {
2135         DESTRUCTOR_CHECK;
2136         NOTHROW;
2137         GC_TRIGGERS; // Fusion uses crsts on AddRef/Release
2138         MODE_ANY;
2139     }
2140     CONTRACTL_END;
2141
2142     GCX_PREEMP();
2143     if (m_creator != NULL)
2144         m_creator->Release();
2145
2146 }
2147
2148 #ifndef  DACCESS_COMPILE
2149 void PEAssembly::ReleaseIL()
2150 {
2151     CONTRACTL
2152     {
2153         INSTANCE_CHECK;
2154         NOTHROW;
2155         GC_TRIGGERS; 
2156         MODE_ANY;
2157     }
2158     CONTRACTL_END;
2159
2160     GCX_PREEMP();
2161     if (m_creator != NULL)
2162     {
2163         m_creator->Release();
2164         m_creator=NULL;
2165     }
2166
2167     PEFile::ReleaseIL();
2168 }
2169 #endif 
2170
2171 /* static */
2172
2173 PEAssembly *PEAssembly::OpenSystem(IUnknown * pAppCtx)
2174 {
2175     STANDARD_VM_CONTRACT;
2176
2177     PEAssembly *result = NULL;
2178
2179     EX_TRY
2180     {
2181         result = DoOpenSystem(pAppCtx);
2182     }
2183     EX_HOOK
2184     {
2185         Exception *ex = GET_EXCEPTION();
2186
2187         // Rethrow non-transient exceptions as file load exceptions with proper
2188         // context
2189
2190         if (!ex->IsTransient())
2191             EEFileLoadException::Throw(SystemDomain::System()->BaseLibrary(), ex->GetHR(), ex);
2192     }
2193     EX_END_HOOK;
2194     return result;
2195 }
2196
2197 /* static */
2198 PEAssembly *PEAssembly::DoOpenSystem(IUnknown * pAppCtx)
2199 {
2200     CONTRACT(PEAssembly *)
2201     {
2202         POSTCONDITION(CheckPointer(RETVAL));
2203         STANDARD_VM_CHECK;
2204     }
2205     CONTRACT_END;
2206
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)
2212     {
2213         bindResult.Init(pPrivAsm, TRUE, TRUE);
2214     }
2215
2216     RETURN new PEAssembly(&bindResult, NULL, NULL, TRUE, FALSE);
2217 }
2218
2219
2220 #ifndef CROSSGEN_COMPILE
2221 /* static */
2222 PEAssembly *PEAssembly::OpenMemory(PEAssembly *pParentAssembly,
2223                                    const void *flat, COUNT_T size,
2224                                    BOOL isIntrospectionOnly/*=FALSE*/,
2225                                    CLRPrivBinderLoadFile* pBinderToUse)
2226 {
2227     STANDARD_VM_CONTRACT;
2228
2229     PEAssembly *result = NULL;
2230
2231     EX_TRY
2232     {
2233         result = DoOpenMemory(pParentAssembly, flat, size, isIntrospectionOnly, pBinderToUse);
2234     }
2235     EX_HOOK
2236     {
2237         Exception *ex = GET_EXCEPTION();
2238
2239         // Rethrow non-transient exceptions as file load exceptions with proper
2240         // context
2241
2242         if (!ex->IsTransient())
2243             EEFileLoadException::Throw(pParentAssembly, flat, size, ex->GetHR(), ex);
2244     }
2245     EX_END_HOOK;
2246
2247     return result;
2248 }
2249
2250
2251 // Thread stress
2252
2253 class DoOpenFlatStress : APIThreadStress
2254 {
2255 public:
2256     PEAssembly *pParentAssembly;
2257     const void *flat;
2258     COUNT_T size;
2259     DoOpenFlatStress(PEAssembly *pParentAssembly, const void *flat, COUNT_T size)
2260         : pParentAssembly(pParentAssembly), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
2261     void Invoke()
2262     {
2263         WRAPPER_NO_CONTRACT;
2264         PEAssemblyHolder result(PEAssembly::OpenMemory(pParentAssembly, flat, size, FALSE));
2265     }
2266 };
2267
2268 /* static */
2269 PEAssembly *PEAssembly::DoOpenMemory(
2270     PEAssembly *pParentAssembly,
2271     const void *flat,
2272     COUNT_T size,
2273     BOOL isIntrospectionOnly,
2274     CLRPrivBinderLoadFile* pBinderToUse)
2275 {
2276     CONTRACT(PEAssembly *)
2277     {
2278         PRECONDITION(CheckPointer(flat));
2279         PRECONDITION(CheckOverflow(flat, size));
2280         PRECONDITION(CheckPointer(pParentAssembly));
2281         STANDARD_VM_CHECK;
2282         POSTCONDITION(CheckPointer(RETVAL));
2283     }
2284     CONTRACT_END;
2285
2286     // Thread stress
2287     DoOpenFlatStress ts(pParentAssembly, flat, size);
2288
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.
2293
2294     PEImageHolder image(PEImage::LoadFlat(flat, size));
2295
2296     // Need to verify that this is a CLR assembly
2297     if (!image->CheckILFormat())
2298         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
2299
2300
2301     CoreBindResult bindResult;
2302     ReleaseHolder<ICLRPrivAssembly> assembly;
2303     IfFailThrow(CCoreCLRBinderHelper::GetAssemblyFromImage(image, NULL, &assembly));
2304     bindResult.Init(assembly,FALSE,FALSE);
2305
2306     RETURN new PEAssembly(&bindResult, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
2307 }
2308 #endif // !CROSSGEN_COMPILE
2309
2310
2311
2312 PEAssembly* PEAssembly::Open(CoreBindResult* pBindResult,
2313                                    BOOL isSystem, BOOL isIntrospectionOnly)
2314 {
2315
2316     return new PEAssembly(pBindResult,NULL,NULL,isSystem,isIntrospectionOnly);
2317
2318 };
2319
2320 /* static */
2321 PEAssembly *PEAssembly::Create(PEAssembly *pParentAssembly,
2322                                IMetaDataAssemblyEmit *pAssemblyEmit,
2323                                BOOL bIsIntrospectionOnly)
2324 {
2325     CONTRACT(PEAssembly *)
2326     {
2327         PRECONDITION(CheckPointer(pParentAssembly));
2328         PRECONDITION(CheckPointer(pAssemblyEmit));
2329         STANDARD_VM_CHECK; 
2330         POSTCONDITION(CheckPointer(RETVAL));
2331     }
2332     CONTRACT_END;
2333
2334     // Set up the metadata pointers in the PEAssembly. (This is the only identity
2335     // we have.)
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();
2340 }
2341
2342
2343 #ifdef FEATURE_PREJIT
2344
2345
2346 void PEAssembly::SetNativeImage(PEImage * image)
2347 {
2348     CONTRACTL
2349     {
2350         INSTANCE_CHECK;
2351         STANDARD_VM_CHECK;
2352     }
2353     CONTRACTL_END;
2354
2355     image->Load();
2356
2357     if (CheckNativeImageVersion(image))
2358     {
2359         PEFile::SetNativeImage(image);
2360 #if 0
2361         //Enable this code if you want to make sure we never touch the flat layout in the presence of the
2362         //ngen image.
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);
2367         if (layout != NULL)
2368         {
2369             //cache a bunch of PE metadata in the PEDecoder
2370             m_ILimage->CheckILFormat();
2371
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);
2379             layout->Release();
2380         }
2381 #endif
2382     }
2383     else
2384     {
2385         ExternalLog(LL_WARNING, "Native image is not correct version.");
2386     }
2387 }
2388
2389 #endif  // FEATURE_PREJIT
2390
2391
2392 BOOL PEAssembly::IsSourceGAC()
2393 {
2394     WRAPPER_NO_CONTRACT;
2395     return m_bIsFromGAC;
2396 };
2397
2398
2399 #endif // #ifndef DACCESS_COMPILE
2400
2401
2402
2403 #ifndef DACCESS_COMPILE
2404
2405
2406 // ------------------------------------------------------------
2407 // Hash support
2408 // ------------------------------------------------------------
2409
2410 void PEAssembly::VerifyStrongName()
2411 {
2412     CONTRACTL
2413     {
2414         INSTANCE_CHECK;
2415         THROWS;
2416         GC_TRIGGERS;
2417         MODE_ANY;
2418         INJECT_FAULT(COMPlusThrowOM(););
2419     }
2420     CONTRACTL_END;
2421
2422     // If we've already done the signature checks, we don't need to do them again.
2423     if (m_fStrongNameVerified)
2424     {
2425         return;
2426     }
2427
2428     // Without FUSION/GAC, we need to verify SN on all assemblies, except dynamic assemblies.
2429     if (IsDynamic())
2430     {
2431
2432         m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
2433         m_fStrongNameVerified = TRUE;
2434         return;
2435     }
2436
2437     // Next, verify the strong name, if necessary
2438
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();
2442
2443
2444     if (m_nativeImage == NULL && !GetILimage()->IsTrustedNativeImage())
2445     {
2446         if (!GetILimage()->CheckILFormat())
2447             ThrowHR(COR_E_BADIMAGEFORMAT);
2448     }
2449
2450     // Check the strong name if present.
2451     if (IsIntrospectionOnly())
2452     {
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;
2456     }
2457     else
2458     {
2459         // Runtime policy on CoreCLR is to skip verification of ALL assemblies
2460         m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
2461         m_fStrongNameVerified = TRUE;
2462     }
2463
2464     m_fStrongNameVerified = TRUE;
2465 }
2466
2467 BOOL PEAssembly::IsProfileAssembly()
2468 {
2469     CONTRACTL
2470     {
2471         THROWS;
2472         GC_TRIGGERS;
2473         MODE_ANY;
2474     }
2475     CONTRACTL_END;
2476
2477     //
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).
2480     //
2481     if (VolatileLoadWithoutBarrier(&m_fProfileAssembly) != 0)
2482     {
2483         return m_fProfileAssembly > 0;
2484     }
2485
2486     //
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.
2490     //
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.
2493     //
2494     BOOL bProfileAssembly = IsSourceGAC() && (IsSystem() || m_bIsOnTpaList);
2495
2496     m_fProfileAssembly = bProfileAssembly ? 1 : -1;
2497     return bProfileAssembly;
2498 }
2499
2500 // ------------------------------------------------------------
2501 // Descriptive strings
2502 // ------------------------------------------------------------
2503
2504 // Effective path is the path of nearest parent (creator) assembly which has a nonempty path.
2505
2506 const SString &PEAssembly::GetEffectivePath()
2507 {
2508     CONTRACTL
2509     {
2510         INSTANCE_CHECK;
2511         NOTHROW;
2512         GC_NOTRIGGER;
2513         MODE_ANY;
2514     }
2515     CONTRACTL_END;
2516
2517     PEAssembly *pAssembly = this;
2518
2519     while (pAssembly->m_identity == NULL
2520            || pAssembly->m_identity->GetPath().IsEmpty())
2521     {
2522         if (pAssembly->m_creator)
2523             pAssembly = pAssembly->m_creator->GetAssembly();
2524         else // Unmanaged exe which loads byte[]/IStream assemblies
2525             return SString::Empty();
2526     }
2527
2528     return pAssembly->m_identity->GetPath();
2529 }
2530
2531
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
2534 // assembly.
2535 //
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*/)
2538 {
2539     CONTRACTL
2540     {
2541         INSTANCE_CHECK;
2542         THROWS;
2543         GC_TRIGGERS;
2544         MODE_ANY;
2545         INJECT_FAULT(COMPlusThrowOM(););
2546     }
2547     CONTRACTL_END;
2548
2549     // All other cases use the file path.
2550     result.Set(GetEffectivePath());
2551     if (!result.IsEmpty())
2552         PathToUrl(result);
2553 }
2554
2555 /* static */
2556 void PEAssembly::PathToUrl(SString &string)
2557 {
2558     CONTRACTL
2559     {
2560         PRECONDITION(PEImage::CheckCanonicalFullPath(string));
2561         THROWS;
2562         GC_NOTRIGGER;
2563         MODE_ANY;
2564         INJECT_FAULT(COMPlusThrowOM(););
2565     }
2566     CONTRACTL_END;
2567
2568     SString::Iterator i = string.Begin();
2569
2570 #if !defined(PLATFORM_UNIX)
2571     if (i[0] == W('\\'))
2572     {
2573         // Network path
2574         string.Insert(i, SL("file://"));
2575         string.Skip(i, SL("file://"));
2576     }
2577     else
2578     {
2579         // Disk path
2580         string.Insert(i, SL("file:///"));
2581         string.Skip(i, SL("file:///"));
2582     }
2583 #else
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);
2589 #endif
2590
2591     while (string.Find(i, W('\\')))
2592     {
2593         string.Replace(i, W('/'));
2594     }
2595 }
2596
2597 void PEAssembly::UrlToPath(SString &string)
2598 {
2599     CONTRACT_VOID
2600     {
2601         THROWS;
2602         GC_NOTRIGGER;
2603     }
2604     CONTRACT_END;
2605
2606     SString::Iterator i = string.Begin();
2607
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);
2613     else
2614 #endif
2615     if (string.MatchCaseInsensitive(i, sss2))
2616         string.Delete(i, 7);
2617
2618     while (string.Find(i, W('/')))
2619     {
2620         string.Replace(i, W('\\'));
2621     }
2622
2623     RETURN;
2624 }
2625
2626 BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i)
2627 {
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)
2634         return FALSE;
2635     else if (foundSlash && !foundBackSlash)
2636         i = slash;
2637     else if (!foundSlash && foundBackSlash)
2638         i = backSlash;
2639     else
2640         i = (backSlash > slash) ? backSlash : slash;
2641     return TRUE;
2642 #else
2643     return path.FindBack(i, '\\');
2644 #endif //PLATFORM_UNIX
2645 }
2646
2647
2648 // ------------------------------------------------------------
2649 // Logging
2650 // ------------------------------------------------------------
2651 #ifdef FEATURE_PREJIT
2652 void PEAssembly::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
2653 {
2654     CONTRACT_VOID
2655     {
2656         THROWS;
2657         GC_TRIGGERS;
2658     }
2659     CONTRACT_END;
2660
2661     PEFile::ExternalVLog(facility, level, fmt, args);
2662
2663
2664     RETURN;
2665 }
2666
2667 void PEAssembly::FlushExternalLog()
2668 {
2669     CONTRACT_VOID
2670     {
2671         THROWS;
2672         GC_TRIGGERS;
2673     }
2674     CONTRACT_END;
2675
2676
2677     RETURN;
2678 }
2679 #endif //FEATURE_PREJIT
2680 // ------------------------------------------------------------
2681 // Metadata access
2682 // ------------------------------------------------------------
2683
2684 HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
2685 {
2686     CONTRACTL
2687     {
2688         INSTANCE_CHECK;
2689         PRECONDITION(CheckPointer(pMajor, NULL_OK));
2690         PRECONDITION(CheckPointer(pMinor, NULL_OK));
2691         PRECONDITION(CheckPointer(pBuild, NULL_OK));
2692         PRECONDITION(CheckPointer(pRevision, NULL_OK));
2693         NOTHROW;
2694         WRAPPER(GC_TRIGGERS);
2695         MODE_ANY;
2696     }
2697     CONTRACTL_END;
2698
2699     AssemblyMetaDataInternal md;
2700     HRESULT hr = S_OK;;
2701     if (m_bHasPersistentMDImport)
2702     {
2703         _ASSERTE(GetPersistentMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly)));
2704         IfFailRet(GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
2705     }
2706     else
2707     {
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));
2711     }
2712     
2713     if (pMajor != NULL)
2714         *pMajor = md.usMajorVersion;
2715     if (pMinor != NULL)
2716         *pMinor = md.usMinorVersion;
2717     if (pBuild != NULL)
2718         *pBuild = md.usBuildNumber;
2719     if (pRevision != NULL)
2720         *pRevision = md.usRevisionNumber;
2721
2722     return hr;
2723 }
2724
2725
2726
2727 void PEFile::EnsureImageOpened()
2728 {
2729     WRAPPER_NO_CONTRACT;
2730     if (IsDynamic())
2731         return;
2732 #ifdef FEATURE_PREJIT    
2733     if(HasNativeImage())
2734         m_nativeImage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
2735     else
2736 #endif        
2737         GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
2738 }
2739
2740 #endif // #ifndef DACCESS_COMPILE
2741
2742 #ifdef DACCESS_COMPILE
2743
2744 void
2745 PEFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2746 {
2747     WRAPPER_NO_CONTRACT;
2748     SUPPORTS_DAC;
2749
2750     // sizeof(PEFile) == 0xb8
2751     DAC_ENUM_VTHIS();
2752     EMEM_OUT(("MEM: %p PEFile\n", dac_cast<TADDR>(this)));
2753
2754 #ifdef _DEBUG
2755     // Not a big deal if it's NULL or fails.
2756     m_debugName.EnumMemoryRegions(flags);
2757 #endif
2758
2759     if (m_identity.IsValid())
2760     {
2761         m_identity->EnumMemoryRegions(flags);
2762     }
2763     if (GetILimage().IsValid())
2764     {
2765         GetILimage()->EnumMemoryRegions(flags);
2766     }
2767 #ifdef FEATURE_PREJIT
2768     if (m_nativeImage.IsValid())
2769     {
2770         m_nativeImage->EnumMemoryRegions(flags);
2771         DacEnumHostDPtrMem(m_nativeImage->GetLoadedLayout()->GetNativeVersionInfo());
2772     }
2773 #endif
2774 }
2775
2776 void
2777 PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2778 {
2779     WRAPPER_NO_CONTRACT;
2780
2781     PEFile::EnumMemoryRegions(flags);
2782
2783     if (m_creator.IsValid())
2784     {
2785         m_creator->EnumMemoryRegions(flags);
2786     }
2787 }
2788
2789 #endif // #ifdef DACCESS_COMPILE
2790
2791
2792 //-------------------------------------------------------------------------------
2793 // Make best-case effort to obtain an image name for use in an error message.
2794 //
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()
2800 {
2801     CONTRACTL
2802     {
2803         THROWS;
2804         GC_TRIGGERS;
2805         INJECT_FAULT(COMPlusThrowOM(););
2806         SUPPORTS_DAC_HOST_ONLY;
2807     }
2808     CONTRACTL_END
2809
2810     if (!IsDynamic())
2811     {
2812         return m_identity->GetPathForErrorMessages();
2813     }
2814     else
2815     {
2816         return W("");
2817     }
2818 }
2819
2820
2821 #ifdef DACCESS_COMPILE
2822 TADDR PEFile::GetMDInternalRWAddress()
2823 {
2824     if (!m_MDImportIsRW_Debugger_Use_Only)
2825         return 0;
2826     else
2827     {
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
2833         //    accurate.
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;
2841     }
2842 }
2843 #endif
2844
2845 // Returns the ICLRPrivBinder* instance associated with the PEFile
2846 PTR_ICLRPrivBinder PEFile::GetBindingContext()
2847 {
2848     LIMITED_METHOD_CONTRACT;
2849     
2850     PTR_ICLRPrivBinder pBindingContext = NULL;
2851     
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.
2855     if (!IsSystem())
2856     {
2857         pBindingContext = dac_cast<PTR_ICLRPrivBinder>(GetHostAssembly());
2858     }
2859     
2860     return pBindingContext;
2861 }