Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / vm / domainfile.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 // DomainFile.cpp
6 //
7
8 // --------------------------------------------------------------------------------
9
10
11 #include "common.h"
12
13 // --------------------------------------------------------------------------------
14 // Headers
15 // --------------------------------------------------------------------------------
16
17 #include <shlwapi.h>
18
19 #include "security.h"
20 #include "securitymeta.h"
21 #include "invokeutil.h"
22 #include "eeconfig.h"
23 #include "dynamicmethod.h"
24 #include "field.h"
25 #include "dbginterface.h"
26 #include "eventtrace.h"
27
28 #ifdef FEATURE_PREJIT
29 #include <corcompile.h>
30 #include "compile.h"
31 #endif  // FEATURE_PREJIT
32
33 #include "umthunkhash.h"
34 #include "peimagelayout.inl"
35
36 #include "winrthelpers.h"
37
38 #ifdef FEATURE_PERFMAP
39 #include "perfmap.h"
40 #endif // FEATURE_PERFMAP
41
42 BOOL DomainAssembly::IsUnloading()
43 {
44     WRAPPER_NO_CONTRACT;
45     SUPPORTS_DAC;
46
47     BOOL fIsUnloading = FALSE;
48
49     fIsUnloading = this->GetAppDomain()->IsUnloading();
50
51     if (!fIsUnloading)
52     {
53         fIsUnloading = m_fDebuggerUnloadStarted;
54     }
55
56     return fIsUnloading;
57 }
58
59
60 #ifndef DACCESS_COMPILE
61 DomainFile::DomainFile(AppDomain *pDomain, PEFile *pFile)
62   : m_pDomain(pDomain),
63     m_pFile(pFile),
64     m_pOriginalFile(NULL),
65     m_pModule(NULL),
66     m_level(FILE_LOAD_CREATE),
67     m_pError(NULL),
68     m_notifyflags(NOT_NOTIFIED),
69     m_loading(TRUE),
70     m_pDynamicMethodTable(NULL),
71     m_pUMThunkHash(NULL),
72     m_bDisableActivationCheck(FALSE),
73     m_dwReasonForRejectingNativeImage(0)
74 {
75     CONTRACTL
76     {
77         CONSTRUCTOR_CHECK;
78         THROWS;  // From CreateHandle
79         GC_NOTRIGGER;
80         MODE_ANY;
81         FORBID_FAULT;
82     }
83     CONTRACTL_END;
84
85     m_hExposedModuleObject = NULL;
86     pFile->AddRef();
87 }
88
89 DomainFile::~DomainFile()
90 {
91     CONTRACTL
92     {
93         DESTRUCTOR_CHECK;
94         NOTHROW;
95         GC_TRIGGERS;
96         MODE_ANY;
97     }
98     CONTRACTL_END;
99
100     m_pFile->Release();
101     if(m_pOriginalFile)
102         m_pOriginalFile->Release();
103     if (m_pDynamicMethodTable)
104         m_pDynamicMethodTable->Destroy();
105 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
106     if (m_pUMThunkHash)
107         delete m_pUMThunkHash;
108 #endif
109     delete m_pError;
110 }
111
112 #endif //!DACCESS_COMPILE
113
114 LoaderAllocator * DomainFile::GetLoaderAllocator()
115 {
116     CONTRACTL
117     {
118         NOTHROW;
119         GC_NOTRIGGER;
120         SO_TOLERANT;
121         MODE_ANY;
122     }
123     CONTRACTL_END;
124     Assembly *pAssembly = GetDomainAssembly()->GetAssembly();
125     if ((pAssembly != NULL) && (pAssembly->IsCollectible()))
126     {
127         return pAssembly->GetLoaderAllocator();
128     }
129     else
130     {
131         return this->GetAppDomain()->GetLoaderAllocator();
132     }
133 }
134
135 #ifndef DACCESS_COMPILE
136
137 void DomainFile::ReleaseFiles()
138 {
139     WRAPPER_NO_CONTRACT;
140     Module* pModule=GetCurrentModule();
141     if(pModule)
142         pModule->StartUnload();
143
144     if (m_pFile)
145         m_pFile->ReleaseIL();
146     if(m_pOriginalFile)
147         m_pOriginalFile->ReleaseIL();
148
149     if(pModule)
150         pModule->ReleaseILData();
151 }
152
153 BOOL DomainFile::TryEnsureActive()
154 {
155     CONTRACT(BOOL)
156     {
157         INSTANCE_CHECK;
158         THROWS;
159         GC_TRIGGERS;
160     }
161     CONTRACT_END;
162
163     BOOL success = TRUE;
164
165     EX_TRY
166       {
167           EnsureActive();
168       }
169     EX_CATCH
170       {
171           success = FALSE;
172       }
173     EX_END_CATCH(RethrowTransientExceptions);
174
175     RETURN success;
176 }
177
178 // Optimization intended for EnsureLoadLevel only
179 #include <optsmallperfcritical.h>
180 void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel)
181 {
182     CONTRACT_VOID
183     {
184         INSTANCE_CHECK;
185         THROWS;
186         GC_TRIGGERS;
187     }
188     CONTRACT_END;
189
190     TRIGGERSGC ();
191     if (IsLoading())
192     {
193         this->GetAppDomain()->LoadDomainFile(this, targetLevel);
194
195         // Enforce the loading requirement.  Note that we may have a deadlock in which case we
196         // may be off by one which is OK.  (At this point if we are short of targetLevel we know
197         // we have done so because of reentrancy contraints.)
198
199         RequireLoadLevel((FileLoadLevel)(targetLevel-1));
200     }
201     else
202         ThrowIfError(targetLevel);
203
204     RETURN;
205 }
206 #include <optdefault.h>
207
208 void DomainFile::AttemptLoadLevel(FileLoadLevel targetLevel)
209 {
210     CONTRACT_VOID
211     {
212         INSTANCE_CHECK;
213         THROWS;
214         GC_TRIGGERS;
215     }
216     CONTRACT_END;
217
218     if (IsLoading())
219         this->GetAppDomain()->LoadDomainFile(this, targetLevel);
220     else
221         ThrowIfError(targetLevel);
222
223     RETURN;
224 }
225
226
227 CHECK DomainFile::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK)
228 {
229     CONTRACTL
230     {
231         INSTANCE_CHECK;
232         NOTHROW;
233         GC_NOTRIGGER;
234     }
235     CONTRACTL_END;
236
237     if (deadlockOK)
238     {
239 #ifndef CROSSGEN_COMPILE
240         // CheckLoading requires waiting on a host-breakable lock.
241         // Since this is only a checked-build assert and we've been
242         // living with it for a while, I'll leave it as is.
243         //@TODO: CHECK statements are *NOT* debug-only!!!
244         CONTRACT_VIOLATION(ThrowsViolation|GCViolation|TakesLockViolation);
245         CHECK(this->GetAppDomain()->CheckLoading(this, requiredLevel));
246 #endif
247     }
248     else
249     {
250         CHECK_MSG(m_level >= requiredLevel,
251                   "File not sufficiently loaded");
252     }
253
254     CHECK_OK;
255 }
256
257
258
259 void DomainFile::RequireLoadLevel(FileLoadLevel targetLevel)
260 {
261     CONTRACT_VOID
262     {
263         INSTANCE_CHECK;
264         THROWS;
265         GC_TRIGGERS;
266     }
267     CONTRACT_END;
268
269     if (GetLoadLevel() < targetLevel)
270     {
271         ThrowIfError(targetLevel);
272         ThrowHR(MSEE_E_ASSEMBLYLOADINPROGRESS); // @todo: better exception
273     }
274
275     RETURN;
276 }
277
278
279 void DomainFile::SetError(Exception *ex)
280 {
281     CONTRACT_VOID
282     {
283         PRECONDITION(!IsError());
284         PRECONDITION(ex != NULL);
285         INSTANCE_CHECK;
286         THROWS;
287         GC_TRIGGERS;
288         POSTCONDITION(IsError());
289     }
290     CONTRACT_END;
291
292     m_pError = new ExInfo(ex->DomainBoundClone());
293
294     GetCurrentModule()->NotifyEtwLoadFinished(ex->GetHR());
295
296     if (!IsProfilerNotified())
297     {
298         SetProfilerNotified();
299
300 #ifdef PROFILING_SUPPORTED
301         if (GetCurrentModule() != NULL
302             && !GetCurrentModule()->GetAssembly()->IsDomainNeutral())
303         {
304             // Only send errors for non-shared assemblies; other assemblies might be successfully completed
305             // in another app domain later.
306             GetCurrentModule()->NotifyProfilerLoadFinished(ex->GetHR());
307         }
308 #endif
309     }
310
311     RETURN;
312 }
313
314 void DomainFile::ThrowIfError(FileLoadLevel targetLevel)
315 {
316     CONTRACT_VOID
317     {
318         INSTANCE_CHECK;
319         MODE_ANY;
320         THROWS;
321         GC_TRIGGERS;
322     }
323     CONTRACT_END;
324
325     if (m_level < targetLevel)
326     {
327         if (m_pError)
328             m_pError->Throw();
329     }
330
331     RETURN;
332 }
333
334 CHECK DomainFile::CheckNoError(FileLoadLevel targetLevel)
335 {
336     LIMITED_METHOD_CONTRACT;
337     CHECK(m_level >= targetLevel
338           || !IsError());
339
340     CHECK_OK;
341 }
342
343 CHECK DomainFile::CheckLoaded()
344 {
345     CONTRACTL
346     {
347         INSTANCE_CHECK;
348         NOTHROW;
349         GC_NOTRIGGER;
350         MODE_ANY;
351     }
352     CONTRACTL_END;
353
354     CHECK_MSG(CheckNoError(FILE_LOADED), "DomainFile load resulted in an error");
355
356     if (IsLoaded())
357         CHECK_OK;
358
359     // Mscorlib is allowed to run managed code much earlier than other
360     // assemblies for bootstrapping purposes.  This is because it has no
361     // dependencies, security checks, and doesn't rely on loader notifications.
362
363     if (GetFile()->IsSystem())
364         CHECK_OK;
365
366     CHECK_MSG(GetFile()->CheckLoaded(), "PEFile has not been loaded");
367
368     CHECK_OK;
369 }
370
371 CHECK DomainFile::CheckActivated()
372 {
373     CONTRACTL
374     {
375         INSTANCE_CHECK;
376         NOTHROW;
377         GC_NOTRIGGER;
378         MODE_ANY;
379     }
380     CONTRACTL_END;
381
382     CHECK_MSG(CheckNoError(FILE_ACTIVE), "DomainFile load resulted in an error");
383
384     if (IsActive())
385         CHECK_OK;
386
387     // Mscorlib is allowed to run managed code much earlier than other
388     // assemblies for bootstrapping purposes.  This is because it has no
389     // dependencies, security checks, and doesn't rely on loader notifications.
390
391     if (GetFile()->IsSystem())
392         CHECK_OK;
393
394     CHECK_MSG(GetFile()->CheckLoaded(), "PEFile has not been loaded");
395     CHECK_MSG(IsLoaded(), "DomainFile has not been fully loaded");
396     CHECK_MSG(m_bDisableActivationCheck || CheckLoadLevel(FILE_ACTIVE), "File has not had execution verified");
397
398     CHECK_OK;
399 }
400
401 #endif //!DACCESS_COMPILE
402
403 DomainAssembly *DomainFile::GetDomainAssembly()
404 {
405     CONTRACTL
406     {
407         SUPPORTS_DAC;
408         NOTHROW;
409         GC_NOTRIGGER;
410         SO_TOLERANT;
411     }
412     CONTRACTL_END;
413
414 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
415     if (IsAssembly())
416     {
417         return dac_cast<PTR_DomainAssembly>(this);
418     }
419     else
420     {
421         return dac_cast<PTR_DomainModule>(this)->GetDomainAssembly();
422     }
423 #else
424     _ASSERTE(IsAssembly());
425     return (DomainAssembly *) this;
426 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
427 }
428
429 BOOL DomainFile::IsIntrospectionOnly()
430 {
431     WRAPPER_NO_CONTRACT;
432     return GetFile()->IsIntrospectionOnly();
433 }
434
435 // Return true iff the debugger should get notifications about this assembly.
436 //
437 // Notes:
438 //   The debuggee may be stopped while a DomainAssmebly is being initialized.  In this time window,
439 //   GetAssembly() may be NULL.  If that's the case, this function has to return FALSE.  Later on, when
440 //   the DomainAssembly is fully initialized, this function will return TRUE.  This is the only scenario
441 //   where this function is mutable.  In other words, a DomainAssembly can only change from being invisible
442 //   to visible, but NOT vice versa.  Once a DomainAssmebly is fully initialized, this function should be
443 //   immutable for an instance of a module. That ensures that the debugger gets consistent
444 //   notifications about it. It this value mutates, than the debugger may miss relevant notifications.
445 BOOL DomainAssembly::IsVisibleToDebugger()
446 {
447     WRAPPER_NO_CONTRACT;
448     SUPPORTS_DAC;
449
450     // If you can't run an assembly, then don't send notifications to the debugger.
451     // This check includeds IsIntrospectionOnly().
452     return ((GetAssembly() != NULL) ? GetAssembly()->HasRunAccess() : FALSE);
453 }
454
455 #ifndef DACCESS_COMPILE
456 #ifdef FEATURE_PREJIT
457 void DomainFile::ExternalLog(DWORD level, const WCHAR *fmt, ...)
458 {
459     WRAPPER_NO_CONTRACT;
460
461     va_list args;
462     va_start(args, fmt);
463
464     GetOriginalFile()->ExternalVLog(LF_ZAP, level, fmt, args);
465
466     va_end(args);
467 }
468
469 void DomainFile::ExternalLog(DWORD level, const char *msg)
470 {
471     WRAPPER_NO_CONTRACT;
472
473     GetOriginalFile()->ExternalLog(level, msg);
474 }
475 #endif
476
477 #ifndef CROSSGEN_COMPILE
478 //---------------------------------------------------------------------------------------
479 //
480 // Returns managed representation of the module (Module or ModuleBuilder).
481 // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases).
482 //
483 OBJECTREF DomainFile::GetExposedModuleObject()
484 {
485     CONTRACTL
486     {
487         INSTANCE_CHECK;
488         THROWS;
489         MODE_COOPERATIVE;
490         GC_TRIGGERS;
491     }
492     CONTRACTL_END;
493
494     LoaderAllocator * pLoaderAllocator = GetLoaderAllocator();
495
496     if (m_hExposedModuleObject == NULL)
497     {
498         // Atomically create a handle
499         LOADERHANDLE handle = pLoaderAllocator->AllocateHandle(NULL);
500
501         FastInterlockCompareExchangePointer(&m_hExposedModuleObject, handle, static_cast<LOADERHANDLE>(NULL));
502     }
503
504     if (pLoaderAllocator->GetHandleValue(m_hExposedModuleObject) == NULL)
505     {
506         REFLECTMODULEBASEREF refClass = NULL;
507
508         // Will be TRUE only if LoaderAllocator managed object was already collected and therefore we should
509         // return NULL
510         BOOL fIsLoaderAllocatorCollected = FALSE;
511
512         GCPROTECT_BEGIN(refClass);
513
514         if (GetFile()->IsDynamic())
515         {
516             refClass = (REFLECTMODULEBASEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__MODULE_BUILDER));
517         }
518         else
519         {
520             refClass = (REFLECTMODULEBASEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__MODULE));
521         }
522         refClass->SetModule(m_pModule);
523
524         // Attach the reference to the assembly to keep the LoaderAllocator for this collectible type
525         // alive as long as a reference to the module is kept alive.
526         if (GetModule()->GetAssembly() != NULL)
527         {
528             OBJECTREF refAssembly = GetModule()->GetAssembly()->GetExposedObject();
529             if ((refAssembly == NULL) && GetModule()->GetAssembly()->IsCollectible())
530             {
531                 fIsLoaderAllocatorCollected = TRUE;
532             }
533             refClass->SetAssembly(refAssembly);
534         }
535
536         pLoaderAllocator->CompareExchangeValueInHandle(m_hExposedModuleObject, (OBJECTREF)refClass, NULL);
537         GCPROTECT_END();
538
539         if (fIsLoaderAllocatorCollected)
540         {   // The LoaderAllocator managed object was already collected, we cannot re-create it
541             // Note: We did not publish the allocated Module/ModuleBuilder object, it will get collected
542             // by GC
543             return NULL;
544         }
545     }
546
547     return pLoaderAllocator->GetHandleValue(m_hExposedModuleObject);
548 } // DomainFile::GetExposedModuleObject
549 #endif // CROSSGEN_COMPILE
550
551 BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level)
552 {
553     STANDARD_VM_CONTRACT;
554
555     if (IsError())
556         return FALSE;
557
558     Thread *pThread;
559     pThread = GetThread();
560     _ASSERTE(pThread);
561     INTERIOR_STACK_PROBE_FOR(pThread, 8);
562
563     switch (level)
564     {
565     case FILE_LOAD_BEGIN:
566         Begin();
567         break;
568
569     case FILE_LOAD_FIND_NATIVE_IMAGE:
570 #ifdef FEATURE_PREJIT
571         FindNativeImage();
572 #endif
573         break;
574
575     case FILE_LOAD_VERIFY_NATIVE_IMAGE_DEPENDENCIES:
576 #ifdef FEATURE_PREJIT
577         VerifyNativeImageDependencies();
578 #endif
579         break;
580
581     case FILE_LOAD_ALLOCATE:
582         Allocate();
583         break;
584
585     case FILE_LOAD_ADD_DEPENDENCIES:
586         AddDependencies();
587         break;
588
589     case FILE_LOAD_PRE_LOADLIBRARY:
590         PreLoadLibrary();
591         break;
592
593     case FILE_LOAD_LOADLIBRARY:
594         LoadLibrary();
595         break;
596
597     case FILE_LOAD_POST_LOADLIBRARY:
598         PostLoadLibrary();
599         break;
600
601     case FILE_LOAD_EAGER_FIXUPS:
602         EagerFixups();
603         break;
604
605     case FILE_LOAD_VTABLE_FIXUPS:
606         VtableFixups();
607         break;
608
609     case FILE_LOAD_DELIVER_EVENTS:
610         DeliverSyncEvents();
611         break;
612
613     case FILE_LOADED:
614         FinishLoad();
615         break;
616
617     case FILE_LOAD_VERIFY_EXECUTION:
618         VerifyExecution();
619         break;
620
621     case FILE_ACTIVE:
622         Activate();
623         break;
624
625     default:
626         UNREACHABLE();
627     }
628
629     END_INTERIOR_STACK_PROBE;
630
631 #ifdef FEATURE_MULTICOREJIT
632     {
633         Module * pModule = GetModule();
634
635         if (pModule != NULL) // Should not triggle assert when module is NULL
636         {
637             this->GetAppDomain()->GetMulticoreJitManager().RecordModuleLoad(pModule, level);
638         }
639     }
640 #endif
641
642     return TRUE;
643 }
644
645 #ifdef FEATURE_PREJIT
646
647 void DomainFile::VerifyNativeImageDependencies(bool verifyOnly)
648 {
649     CONTRACTL
650     {
651         INSTANCE_CHECK;
652         STANDARD_VM_CHECK;
653         PRECONDITION(verifyOnly || (m_pDomain->GetDomainFileLoadLevel(this) ==
654                                     FILE_LOAD_FIND_NATIVE_IMAGE));
655     }
656     CONTRACTL_END;
657
658     // This function gets called multiple times. The first call is the real work.
659     // Subsequent calls are only to verify that everything still looks OK.
660     if (!verifyOnly)
661         ClearNativeImageStress();
662
663     if (!m_pFile->HasNativeImage())
664     {
665         CheckZapRequired();
666         return;
667     }
668
669     {
670     // Go through native dependencies & make sure they still have their prejit images after
671     // the security check.
672     // NOTE: we could theoretically do this without loading the dependencies, if we cache the
673     // COR_TRUST structures from the dependencies in the version information.
674     //
675     // Verify that all of our hard dependencies are loaded at the right base address.
676     // If not, abandon prejit image (or fix ours up)
677     // Also, if there are any hard dependencies, then our native image also needs to be
678     // loaded at the right base address
679
680     // Note: we will go through all of our dependencies, call Load on them, and check the base
681     // addresses & identity.
682     // It is important to note that all of those dependencies are also going to do the
683     // same thing, so we might conceivably check a base address as OK, and then have that image
684     // abandoned by that assembly during its VerifyNativeImageDependencies phase.
685     // However, we avoid this problem since the hard depedencies stored are a closure of the
686     // hard dependencies of an image.  This effectively means that our check here is a superset
687     // of the check that the dependencies will perform.  Even if we hit a dependency loop, we
688     // will still guarantee that we've examined all of our dependencies.
689
690     ReleaseHolder<PEImage> pNativeImage = m_pFile->GetNativeImageWithRef();
691     if(pNativeImage==NULL)
692     {
693         CheckZapRequired();
694         return;
695     }
696
697     PEImageLayout* pNativeLayout = pNativeImage->GetLoadedLayout();
698
699     // reuse same codepath for both manifest and non-manifest modules
700     ReleaseHolder<PEImage> pManifestNativeImage(NULL);
701
702     PEFile* pManifestFile = m_pFile;
703     PEImageLayout* pManifestNativeLayout = pNativeLayout;
704
705     if (!IsAssembly())
706     {
707         pManifestFile = GetDomainAssembly()->GetCurrentAssembly()
708             ->GetManifestModule()->GetFile();
709
710         pManifestNativeImage = pManifestFile->GetNativeImageWithRef();
711
712         if (pManifestNativeImage == NULL)
713         {
714             ExternalLog(LL_ERROR, "Rejecting native image because there is no "
715                 "ngen image for manifest module. Check why the manifest module "
716                 "does not have an ngen image");
717             m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_NoNiForManifestModule;
718             STRESS_LOG3(LF_ZAP,LL_INFO100,"Rejecting native file %p, because its manifest module %p has no NI - reason 0x%x\n",pNativeImage.GetValue(),pManifestFile,m_dwReasonForRejectingNativeImage);
719             goto NativeImageRejected;
720         }
721
722         return;
723     }
724
725     COUNT_T cDependencies;
726     CORCOMPILE_DEPENDENCY *pDependencies = pManifestNativeLayout->GetNativeDependencies(&cDependencies);
727
728     LOG((LF_ZAP, LL_INFO100, "ZAP: Checking native image dependencies for %S.\n",
729          pNativeImage->GetPath().GetUnicode()));
730
731     for (COUNT_T iDependency = 0; iDependency < cDependencies; iDependency++)
732     {
733         CORCOMPILE_DEPENDENCY *pDependency = &(pDependencies[iDependency]);
734
735         // Later, for domain neutral assemblies, we will also want to verify security policy
736         // in such cases, the prejit image should store the publisher info for the dependencies
737         // for us.
738
739         // If this is not a hard-bound dependency, then skip to the next dependency
740         if (pDependency->signNativeImage == INVALID_NGEN_SIGNATURE)
741             continue;
742
743
744         //
745         // CoreCLR hard binds to mscorlib.dll only. Avoid going through the full load.
746         //
747
748 #ifdef _DEBUG
749         AssemblySpec name;
750         name.InitializeSpec(pDependency->dwAssemblyRef,
751                             ((pManifestNativeImage != NULL) ? pManifestNativeImage : pNativeImage)->GetNativeMDImport(),
752                             GetDomainAssembly());
753         _ASSERTE(name.IsMscorlib());
754 #endif
755
756         PEAssembly * pDependencyFile = SystemDomain::SystemFile();
757  
758
759         ReleaseHolder<PEImage> pDependencyNativeImage = pDependencyFile->GetNativeImageWithRef();
760         if (pDependencyNativeImage == NULL)
761         {
762             ExternalLog(LL_ERROR, W("Rejecting native image because dependency %s is not native"),
763                         pDependencyFile->GetPath().GetUnicode());
764             m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_DependencyNotNative;
765             STRESS_LOG3(LF_ZAP,LL_INFO100,"Rejecting native file %p, because dependency %p is not NI - reason 0x%x\n",pNativeImage.GetValue(),pDependencyFile,m_dwReasonForRejectingNativeImage);
766             goto NativeImageRejected;
767         }
768
769 #ifndef FEATURE_FUSION // Fusion does this verification at native binding time.
770         PTR_PEImageLayout pDependencyNativeLayout = pDependencyNativeImage->GetLoadedLayout();
771         // Assert that the native image signature is as expected
772         // Fusion will ensure this
773         CORCOMPILE_VERSION_INFO * pDependencyNativeVersion =
774                 pDependencyNativeLayout->GetNativeVersionInfo();
775
776         LoggablePEAssembly logAsm(pDependencyFile);
777         if (!RuntimeVerifyNativeImageDependency(pDependency, pDependencyNativeVersion, &logAsm))
778             goto NativeImageRejected;
779 #endif
780     }
781     LOG((LF_ZAP, LL_INFO100, "ZAP: Native image dependencies for %S OK.\n",
782             pNativeImage->GetPath().GetUnicode()));
783
784     return;
785 }
786
787 NativeImageRejected:
788     m_pFile->ClearNativeImage();
789     m_pFile->SetCannotUseNativeImage();
790
791     CheckZapRequired();
792
793     return;
794 }
795
796 BOOL DomainFile::IsZapRequired()
797 {
798     CONTRACTL
799     {
800         INSTANCE_CHECK;
801         THROWS;
802         GC_TRIGGERS;
803         MODE_ANY;
804         INJECT_FAULT(COMPlusThrowOM(););
805     }
806     CONTRACTL_END;
807
808     if (!m_pFile->HasMetadata() || !g_pConfig->RequireZap(GetSimpleName()))
809         return FALSE;
810
811 #if defined(_DEBUG) && defined(FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS)
812     // If we're intentionally treating NIs as if they were MSIL assemblies, and the test
813     // is flexible enough to accept that (e.g., complus_zaprequired=2), then zaps are not
814     // required (i.e., it's ok for m_pFile->m_nativeImage to be NULL), but only if we
815     // loaded an actual NI to be treated as an IL assembly
816     if (PEFile::ShouldTreatNIAsMSIL())
817     {
818         // Since the RequireZap() call above returned true, we know that some level of
819         // zap requiredness was configured
820         _ASSERTE(g_pConfig->RequireZaps() != EEConfig::REQUIRE_ZAPS_NONE);
821
822         // If config uses this special value (2), zaps are not required, so long as
823         // we're using an actual NI as IL
824         if ((g_pConfig->RequireZaps() == EEConfig::REQUIRE_ZAPS_ALL_JIT_OK) &&
825             m_pFile->HasOpenedILimage() &&
826             m_pFile->GetOpenedILimage()->HasNativeHeader())
827         {
828             return FALSE;
829         }
830     }
831 #endif // defined(_DEBUG) && defined(FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS)
832
833     // Does this look like a resource-only assembly?  We assume an assembly is resource-only
834     // if it contains no TypeDef (other than the <Module> TypeDef) and no MethodDef.
835     // Note that pMD->GetCountWithTokenKind(mdtTypeDef) doesn't count the <Module> type.
836     IMDInternalImportHolder pMD = m_pFile->GetMDImport();
837     if (pMD->GetCountWithTokenKind(mdtTypeDef) == 0 && pMD->GetCountWithTokenKind(mdtMethodDef) == 0)
838         return FALSE;
839
840     DomainAssembly * pDomainAssembly = GetDomainAssembly();
841
842     // If the manifest module does not have an ngen image, the non-manifest
843     // modules cannot either
844     if (m_pFile->IsModule() && !pDomainAssembly->GetFile()->CanUseNativeImage())
845         m_pFile->SetCannotUseNativeImage();
846
847     // Some cases are not supported by design. They can never have a native image.
848     // So ignore such cases
849
850     if (!m_pFile->CanUseNativeImage() &&
851         g_pConfig->RequireZaps() == EEConfig::REQUIRE_ZAPS_SUPPORTED)
852         return FALSE;
853
854 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
855     if (IsCompilationProcess())
856     {
857         // Ignore the assembly being ngened.
858
859         bool fileIsBeingNGened = false;
860
861         if (this->GetAppDomain()->IsCompilationDomain())
862         {
863             Assembly * assemblyBeingNGened = this->GetAppDomain()->ToCompilationDomain()->GetTargetAssembly();
864             if (assemblyBeingNGened == NULL || assemblyBeingNGened == pDomainAssembly->GetCurrentAssembly())
865                 fileIsBeingNGened = true;
866         }
867         else if (IsSystem())
868         {
869             // mscorlib gets loaded before the CompilationDomain gets created.
870             // However, we may be ngening mscorlib itself
871             fileIsBeingNGened = true;
872         }
873
874         if (fileIsBeingNGened)
875             return FALSE;
876     }
877 #endif
878
879     return TRUE;
880 }
881
882 void DomainFile::CheckZapRequired()
883 {
884     CONTRACTL
885     {
886         INSTANCE_CHECK;
887         THROWS;
888         GC_TRIGGERS;
889         MODE_ANY;
890         INJECT_FAULT(COMPlusThrowOM(););
891     }
892     CONTRACTL_END;
893
894     if (m_pFile->HasNativeImage() || !IsZapRequired())
895         return;
896
897 #ifdef FEATURE_READYTORUN
898     if(m_pFile->GetLoaded()->HasReadyToRunHeader())
899         return;
900 #endif
901
902     // Flush any log messages
903     GetFile()->FlushExternalLog();
904
905     StackSString ss;
906     ss.Printf("ZapRequire: Could not get native image for %s.\n"
907               "Use FusLogVw.exe to check the reason.",
908               GetSimpleName());
909
910 #if defined(_DEBUG)
911     // Assert as some test may not check their error codes well. So throwing an
912     // exception may not cause a test failure (as it should).
913     StackScratchBuffer scratch;
914     DbgAssertDialog(__FILE__, __LINE__, (char*)ss.GetUTF8(scratch));
915 #endif // defined(_DEBUG)
916
917     COMPlusThrowNonLocalized(kFileNotFoundException, ss.GetUnicode());
918 }
919
920 // Discarding an ngen image can cause problems. For more coverage,
921 // this stress-mode discards ngen images even if not needed.
922
923 void DomainFile::ClearNativeImageStress()
924 {
925     WRAPPER_NO_CONTRACT;
926
927 #ifdef _DEBUG
928     static ConfigDWORD clearNativeImageStress;
929     DWORD stressPercentage = clearNativeImageStress.val(CLRConfig::INTERNAL_clearNativeImageStress);
930     _ASSERTE(stressPercentage <= 100);
931     if (stressPercentage == 0 || !GetFile()->HasNativeImage())
932         return;
933
934     // Note that discarding a native image can affect dependencies. So its not enough
935     // to only check DomainFile::IsZapRequired() here.
936     if (g_pConfig->RequireZaps() != EEConfig::REQUIRE_ZAPS_NONE)
937         return;
938
939     // Its OK to ClearNativeImage even for a shared assembly, as the current PEFile will
940     // be discarded if we decide to share the assembly. However, we always use the same
941     // PEFile for the system assembly. So discarding the native image in the current
942     // AppDomain will actually affect the system assembly in the shared domain, and other
943     // appdomains may have already committed to using its ngen image.
944     if (GetFile()->IsSystem() && !this->GetAppDomain()->IsDefaultDomain())
945         return;
946
947     if (g_IBCLogger.InstrEnabled())
948         return;
949
950     ULONG hash = HashStringA(GetSimpleName());
951
952     // Hash in the FileLoadLevel so that we make a different decision for every level.
953     FileLoadLevel fileLoadLevel = m_pDomain->GetDomainFileLoadLevel(this);
954     hash ^= ULONG(fileLoadLevel);
955     // We do not discard native images after this level
956     _ASSERTE(fileLoadLevel < FILE_LOAD_VERIFY_NATIVE_IMAGE_DEPENDENCIES);
957
958     // Different app-domains should make different decisions
959     hash ^= HashString(this->GetAppDomain()->GetFriendlyName());
960
961 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
962     // Since DbgRandomOnHashAndExe() is not so random under ngen.exe, also
963     // factor in the module being compiled
964     if (this->GetAppDomain()->IsCompilationDomain())
965     {
966         Module * module = this->GetAppDomain()->ToCompilationDomain()->GetTargetModule();
967         // Has the target module been set yet?
968         if (module)
969             hash ^= HashStringA(module->GetSimpleName());
970     }
971 #endif
972
973     if (DbgRandomOnHashAndExe(hash, float(stressPercentage)/100))
974     {
975         GetFile()->SetCannotUseNativeImage();
976         GetFile()->ClearNativeImage();
977         ExternalLog(LL_ERROR, "Rejecting native image for **clearNativeImageStress**");
978     }
979 #endif
980 }
981
982 #endif // FEATURE_PREJIT
983
984 void DomainFile::PreLoadLibrary()
985 {
986     CONTRACTL
987     {
988         INSTANCE_CHECK;
989         STANDARD_VM_CHECK;
990     }
991     CONTRACTL_END;
992
993     // Check skip verification for loading if required
994     if (!GetFile()->CanLoadLibrary())
995     {
996         DomainAssembly* pDomainAssembly = GetDomainAssembly();
997         if (pDomainAssembly->GetSecurityDescriptor()->IsResolved())
998         {
999             if (Security::CanSkipVerification(pDomainAssembly))
1000                 GetFile()->SetSkipVerification();
1001         }
1002         else
1003         {
1004             AppDomain *pAppDomain = this->GetAppDomain();
1005             PEFile *pFile = GetFile();
1006             _ASSERTE(pFile != NULL);
1007             PEImage *pImage = pFile->GetILimage();
1008             _ASSERTE(pImage != NULL);
1009             _ASSERTE(!pImage->IsFile());
1010             if (pImage->HasV1Metadata())
1011             {
1012                 // In V1 case, try to derive SkipVerification status from parents
1013                 do
1014                 {
1015                     PEAssembly * pAssembly = pFile->GetAssembly();
1016                     if (pAssembly == NULL)
1017                         break;
1018                     pFile = pAssembly->GetCreator();
1019                     if (pFile != NULL)
1020                     {
1021                         pAssembly = pFile->GetAssembly();
1022                         // Find matching DomainAssembly for the given PEAsssembly
1023                         // Perf: This does not scale
1024                         AssemblyIterationFlags flags =
1025                             (AssemblyIterationFlags) (kIncludeLoaded | kIncludeLoading | kIncludeExecution);
1026                         AppDomain::AssemblyIterator i = pAppDomain->IterateAssembliesEx(flags);
1027                         CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
1028
1029                         while (i.Next(pDomainAssembly.This()))
1030                         {
1031                             if ((pDomainAssembly != NULL) && (pDomainAssembly->GetFile() == pAssembly))
1032                             {
1033                                 break;
1034                             }
1035                         }
1036                         if (pDomainAssembly != NULL)
1037                         {
1038                             if (pDomainAssembly->GetSecurityDescriptor()->IsResolved())
1039                             {
1040                                 if (Security::CanSkipVerification(pDomainAssembly))
1041                                 {
1042                                     GetFile()->SetSkipVerification();
1043                                     break;
1044                                 }
1045                             }
1046                         }
1047                         else
1048                         {
1049                             // Potential Bug: Unable to find DomainAssembly for given PEAssembly
1050                             // In retail build gracefully exit loop
1051                             _ASSERTE(pDomainAssembly != NULL);
1052                             break;
1053                         }
1054                     }
1055                 }
1056                 while (pFile != NULL);
1057             }
1058         }
1059     }
1060 } // DomainFile::PreLoadLibrary
1061
1062 // Note that this is the sole loading function which must be called OUTSIDE THE LOCK, since
1063 // it will potentially involve the OS loader lock.
1064 void DomainFile::LoadLibrary()
1065 {
1066     CONTRACTL
1067     {
1068         INSTANCE_CHECK;
1069         STANDARD_VM_CHECK;
1070     }
1071     CONTRACTL_END;
1072
1073     Thread::LoadingFileHolder holder(GetThread());
1074     GetThread()->SetLoadingFile(this);
1075     GetFile()->LoadLibrary();
1076 }
1077
1078 void DomainFile::PostLoadLibrary()
1079 {
1080     CONTRACTL
1081     {
1082         INSTANCE_CHECK;
1083         // Note that GetFile()->LoadLibrary must be called before this OUTSIDE OF THE LOCKS
1084         PRECONDITION(GetFile()->CheckLoaded());
1085         STANDARD_VM_CHECK;
1086     }
1087     CONTRACTL_END;
1088
1089 #ifdef FEATURE_PREJIT
1090     if (GetFile()->HasNativeImage())
1091     {
1092         InsertIntoDomainFileWithNativeImageList();
1093     }
1094 #endif
1095 #ifdef PROFILING_SUPPORTED
1096     // After this point, it is possible to load types.
1097     // We need to notify the profiler now because the profiler may need to inject methods into
1098     // the module, and to do so reliably, it must have the chance to do so before
1099     // any types are loaded from the module.
1100     //
1101     // In the past we only allowed injecting types/methods on non-NGEN images so notifying here
1102     // worked ok, but for NGEN images this is pretty ugly. Rejitting often occurs in this callback,
1103     // but then during fixup the results of LoadedMethodDesc iterator would change and we would
1104     // need to re-iterate everything. Aside from Rejit other code often wasn't designed to handle
1105     // running before Fixup. A concrete example VS recently hit, calling GetClassLayout using
1106     // a MethodTable which doesn't need restore but its parent pointer isn't fixed up yet.
1107     // We've already set the rules so that profilers can't modify the member list of types in NGEN images
1108     // so it doesn't matter if types are pre-loaded. We only need the guarantee that code for the
1109     // loaded types won't execute yet. For NGEN images we deliver the load notification in
1110     // FILE_LOAD_DELIVER_EVENTS.
1111     if (!GetFile()->HasNativeImage())
1112     {
1113         if (!IsProfilerNotified())
1114         {
1115             SetProfilerNotified();
1116             GetCurrentModule()->NotifyProfilerLoadFinished(S_OK);
1117         }
1118     }
1119
1120 #endif
1121 }
1122
1123 void DomainFile::AddDependencies()
1124 {
1125     STANDARD_VM_CONTRACT;
1126
1127 #ifdef FEATURE_PREJIT
1128
1129     //
1130     // CoreCLR hard binds to mscorlib.dll only. No need to track hardbound dependencies.
1131     //
1132
1133 #endif // FEATURE_PREJIT
1134 }
1135
1136 void DomainFile::EagerFixups()
1137 {
1138     WRAPPER_NO_CONTRACT;
1139
1140 #ifdef FEATURE_PREJIT
1141     if (IsIntrospectionOnly())
1142         return; 
1143     
1144     if (GetCurrentModule()->HasNativeImage())
1145     {
1146         GetCurrentModule()->RunEagerFixups();
1147     }
1148 #ifdef FEATURE_READYTORUN
1149     else
1150     if (GetCurrentModule()->IsReadyToRun())
1151     {
1152 #ifndef CROSSGEN_COMPILE
1153         GetCurrentModule()->RunEagerFixups();
1154 #endif
1155
1156         PEImageLayout * pLayout = GetCurrentModule()->GetReadyToRunInfo()->GetImage();
1157
1158         TADDR base = dac_cast<TADDR>(pLayout->GetBase());
1159
1160         ExecutionManager::AddCodeRange(base, base + (TADDR)pLayout->GetVirtualSize(),
1161                                         ExecutionManager::GetReadyToRunJitManager(),
1162                                          RangeSection::RANGE_SECTION_READYTORUN,
1163                                          GetCurrentModule() /* (void *)pLayout */);
1164     }
1165 #endif // FEATURE_READYTORUN
1166
1167 #endif // FEATURE_PREJIT
1168 }
1169
1170 void DomainFile::VtableFixups()
1171 {
1172     WRAPPER_NO_CONTRACT;
1173
1174 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
1175     if (!GetCurrentModule()->IsResource())
1176         GetCurrentModule()->FixupVTables();
1177 #endif
1178 }
1179
1180 void DomainFile::FinishLoad()
1181 {
1182     CONTRACTL
1183     {
1184         INSTANCE_CHECK;
1185         STANDARD_VM_CHECK;
1186     }
1187     CONTRACTL_END;
1188
1189 #ifdef FEATURE_PREJIT
1190
1191     if (m_pFile->HasNativeImage())
1192     {
1193 #ifdef FEATURE_FUSION
1194         // <REVISIT_TODO>Because of bug 112034, we may commit to a native image even though
1195         // we should not have.</REVISIT_TODO>
1196
1197 // #ifdef _DEBUG
1198
1199         // Verify that the native image dependencies are still valid
1200         // Since we had already committed to using a native image, they cannot
1201         // be invalidated
1202         VerifyNativeImageDependencies(true);
1203         _ASSERTE(m_pFile->HasNativeImage());
1204
1205         if (!m_pFile->HasNativeImage())
1206         {
1207             STRESS_LOG1(LF_CODESHARING, LL_FATALERROR, "Incorrectly committed to using native image for %S",
1208                                                        m_pFile->GetPath().GetUnicode());
1209             EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
1210         }
1211 // #endif
1212
1213 #endif // FEATURE_FUSION
1214
1215         LOG((LF_ZAP, LL_INFO10, "Using native image %S.\n", m_pFile->GetPersistentNativeImage()->GetPath().GetUnicode()));
1216         ExternalLog(LL_INFO10, "Native image successfully used.");
1217
1218         // Inform metadata that it has been loaded from a native image
1219         // (and so there was an opportunity to check for or fix inconsistencies in the original IL metadata)
1220         m_pFile->GetMDImport()->SetVerifiedByTrustedSource(TRUE);
1221     }
1222
1223     // Are we absolutely required to use a native image?
1224     CheckZapRequired();
1225
1226 #if defined(FEATURE_COMINTEROP)
1227     // If this is a winmd file, ensure that the ngen reference namespace is loadable.
1228     // This is necessary as on the phone we don't check ngen image dependencies, and thus we can get in a situation 
1229     // where a winmd is loaded as a dependency of an ngen image, but the type used to build cross module references 
1230     // in winmd files isn't loaded.
1231     if (GetFile()->AsAssembly()->IsWindowsRuntime() && GetFile()->HasHostAssembly())
1232     {
1233         IMDInternalImport *pImport = GetFile()->GetPersistentMDImport();
1234         LPCSTR  szNameSpace;
1235         LPCSTR  szTypeName;
1236         // It does not make sense to pass the file name to recieve fake type name for empty WinMDs, because we would use the name 
1237         // for binding in next call to BindAssemblySpec which would fail for fake WinRT type name
1238         // We will throw/return the error instead and the caller will recognize it and react to it by not creating the ngen image - 
1239         // see code:Zapper::ComputeDependenciesInCurrentDomain
1240         if (SUCCEEDED(::GetFirstWinRTTypeDef(pImport, &szNameSpace, &szTypeName, NULL, NULL)))
1241         {
1242             // Build assembly spec to describe binding to that WinRT type.
1243             AssemblySpec spec;
1244             IfFailThrow(spec.Init("WindowsRuntimeAssemblyName, ContentType=WindowsRuntime"));
1245             spec.SetWindowsRuntimeType(szNameSpace, szTypeName);
1246
1247             // Bind to assembly using the CLRPriv binder infrastructure. (All WinRT loads are done through CLRPriv binders
1248             ReleaseHolder<IAssemblyName> pAssemblyName;
1249             IfFailThrow(spec.CreateFusionName(&pAssemblyName, FALSE, TRUE));
1250             ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
1251             IfFailThrow(GetFile()->GetHostAssembly()->BindAssemblyByName(pAssemblyName, &pPrivAssembly));
1252
1253             // Verify that we found this. If this invariant doesn't hold, then the ngen images that reference this winmd are be invalid.
1254             // ALSO, this winmd file is invalid as it doesn't follow spec about how it is distributed.
1255             if (GetAppDomain()->FindAssembly(pPrivAssembly) != this)
1256             {
1257                 ThrowHR(COR_E_BADIMAGEFORMAT);
1258             }
1259         }
1260     }
1261 #endif // defined(FEATURE_CORECLR) && defined(FEATURE_COMINTEROP)
1262 #endif // FEATURE_PREJIT
1263
1264     // Flush any log messages
1265 #ifdef FEATURE_PREJIT
1266     GetFile()->FlushExternalLog();
1267 #endif
1268     // Must set this a bit prematurely for the DAC stuff to work
1269     m_level = FILE_LOADED;
1270
1271     // Now the DAC can find this module by enumerating assemblies in a domain.
1272     DACNotify::DoModuleLoadNotification(m_pModule);
1273
1274 #if defined(DEBUGGING_SUPPORTED) && !defined(DACCESS_COMPILE)
1275     if (IsDebuggerNotified() && (g_pDebugInterface != NULL))
1276     {
1277         // We already notified dbgapi that this module was loading (via LoadModule()).
1278         // Now let the dbgapi know the module has reached FILE_LOADED, so it can do any
1279         // processing that needs to wait until this stage (e.g., binding breakpoints in
1280         // NGENd generics).
1281         g_pDebugInterface->LoadModuleFinished(m_pModule, m_pDomain);
1282     }
1283 #endif // defined(DEBUGGING_SUPPORTED) && !defined(DACCESS_COMPILE)
1284
1285     // Set a bit to indicate that the module has been loaded in some domain, and therefore
1286     // typeloads can involve types from this module. (Used for candidate instantiations.)
1287     GetModule()->SetIsReadyForTypeLoad();
1288
1289 #ifdef FEATURE_PERFMAP
1290     // Notify the perfmap of the IL image load.
1291     PerfMap::LogImageLoad(m_pFile);
1292 #endif
1293 }
1294
1295 void DomainFile::VerifyExecution()
1296 {
1297     CONTRACT_VOID
1298     {
1299         INSTANCE_CHECK;
1300         PRECONDITION(IsLoaded());
1301         STANDARD_VM_CHECK;
1302     }
1303     CONTRACT_END;
1304
1305     if (GetModule()->IsIntrospectionOnly())
1306     {
1307         // Throw an exception
1308         COMPlusThrow(kInvalidOperationException, IDS_EE_CODEEXECUTION_IN_INTROSPECTIVE_ASSEMBLY);
1309     }
1310
1311     if (GetModule()->GetAssembly()->IsSIMDVectorAssembly() && 
1312         !GetModule()->GetAssembly()->GetSecurityDescriptor()->IsFullyTrusted())
1313     {
1314         COMPlusThrow(kFileLoadException, IDS_EE_SIMD_PARTIAL_TRUST_DISALLOWED);
1315     }
1316
1317     if(GetFile()->PassiveDomainOnly())
1318     {
1319     // Remove path - location must be hidden for security purposes
1320         LPCWSTR path=GetFile()->GetPath();
1321         LPCWSTR pStart = wcsrchr(path, '\\');
1322         if (pStart != NULL)
1323             pStart++;
1324         else
1325             pStart = path;
1326         COMPlusThrow(kInvalidOperationException, IDS_EE_CODEEXECUTION_ASSEMBLY_FOR_PASSIVE_DOMAIN_ONLY,pStart);
1327     }
1328
1329     RETURN;
1330 }
1331
1332 void DomainFile::Activate()
1333 {
1334     CONTRACT_VOID
1335     {
1336         INSTANCE_CHECK;
1337         PRECONDITION(IsLoaded());
1338         STANDARD_VM_CHECK;
1339     }
1340     CONTRACT_END;
1341
1342     // If we are a module, ensure we've activated the assembly first.
1343
1344     if (!IsAssembly())
1345     {
1346         GetDomainAssembly()->EnsureActive();
1347     }
1348     else
1349     {
1350         // We cannot execute any code in this assembly until we know what exception plan it is on.
1351         // At the point of an exception's stack-crawl it is too late because we cannot tolerate a GC.
1352         // See PossiblyUnwrapThrowable and its callers.
1353         _ASSERTE(GetLoadedModule() == GetDomainAssembly()->GetLoadedAssembly()->GetManifestModule());
1354         GetLoadedModule()->IsRuntimeWrapExceptions();
1355     }
1356
1357     // Now activate any dependencies.
1358     // This will typically cause reentrancy of course.
1359
1360     if (!IsSingleAppDomain())
1361     {
1362         // increment the counter (see the comment in Module::AddActiveDependency)
1363         GetModule()->IncrementNumberOfActivations();
1364
1365 #ifdef FEATURE_LOADER_OPTIMIZATION
1366         AppDomain *pDomain = this->GetAppDomain();
1367         Module::DependencyIterator i = GetCurrentModule()->IterateActiveDependencies();
1368         STRESS_LOG2(LF_LOADER, LL_INFO100,"Activating module %p in AD %i",GetCurrentModule(),pDomain->GetId().m_dwId);
1369
1370         while (i.Next())
1371         {
1372             Module *pModule = i.GetDependency();
1373             DomainFile *pDomainFile = pModule->FindDomainFile(pDomain);
1374             if (pDomainFile == NULL)
1375                 pDomainFile = pDomain->LoadDomainNeutralModuleDependency(pModule, FILE_LOADED);
1376
1377             STRESS_LOG3(LF_LOADER, LL_INFO100,"Activating dependency %p -> %p, unconditional=%i",GetCurrentModule(),pModule,i.IsUnconditional());
1378
1379             if (i.IsUnconditional())
1380             {
1381                 // Let any failures propagate
1382                 pDomainFile->EnsureActive();
1383             }
1384             else
1385             {
1386                 // Enable triggers if we fail here
1387                 if (!pDomainFile->TryEnsureActive())
1388                     GetCurrentModule()->EnableModuleFailureTriggers(pModule, this->GetAppDomain());
1389             }
1390             STRESS_LOG3(LF_LOADER, LL_INFO100,"Activated dependency %p -> %p, unconditional=%i",GetCurrentModule(),pModule,i.IsUnconditional());
1391         }
1392 #endif
1393     }
1394
1395 #ifndef CROSSGEN_COMPILE
1396     if (m_pModule->CanExecuteCode())
1397     {
1398         //
1399         // Now call the module constructor.  Note that this might cause reentrancy;
1400         // this is fine and will be handled by the class cctor mechanism.
1401         //
1402
1403         MethodTable *pMT = m_pModule->GetGlobalMethodTable();
1404         if (pMT != NULL)
1405         {
1406             pMT->CheckRestore();
1407             m_bDisableActivationCheck=TRUE;
1408             pMT->CheckRunClassInitThrowing();
1409         }
1410         if (g_pConfig->VerifyModulesOnLoad())
1411         {
1412             m_pModule->VerifyAllMethods();
1413         }
1414 #ifdef _DEBUG
1415         if (g_pConfig->ExpandModulesOnLoad())
1416         {
1417             m_pModule->ExpandAll();
1418         }
1419 #endif //_DEBUG
1420     }
1421     else
1422     {
1423         // This exception does not need to be localized as it can only happen in
1424         // NGen and PEVerify, and we are not localizing those tools.
1425         _ASSERTE(this->GetAppDomain()->IsPassiveDomain());
1426         // This assert will fire if we attempt to run non-mscorlib code from within ngen
1427         // Current audits of the system indicate that this will never occur, but if it does
1428         // the exception below will prevent actual non-mscorlib code execution.
1429         _ASSERTE(!this->GetAppDomain()->IsCompilationDomain());
1430
1431         LPCWSTR message = W("You may be trying to evaluate a permission from an assembly ")
1432                           W("without FullTrust, or which cannot execute code for other reasons.");
1433         COMPlusThrowNonLocalized(kFileLoadException, message);
1434     }
1435 #endif // CROSSGEN_COMPILE
1436
1437     RETURN;
1438 }
1439
1440 #ifdef FEATURE_LOADER_OPTIMIZATION
1441 BOOL DomainFile::PropagateActivationInAppDomain(Module *pModuleFrom, Module *pModuleTo, AppDomain* pDomain)
1442 {
1443     CONTRACTL
1444     {
1445         PRECONDITION(CheckPointer(pModuleFrom));
1446         PRECONDITION(CheckPointer(pModuleTo));
1447         THROWS; // should only throw transient failures
1448         DISABLED(GC_TRIGGERS);
1449         MODE_ANY;
1450     }
1451     CONTRACTL_END;
1452
1453 #ifdef FEATURE_MULTICOREJIT
1454     // Reset the flag to allow managed code to be called in multicore JIT background thread from this routine
1455     ThreadStateNCStackHolder holder(-1, Thread::TSNC_CallingManagedCodeDisabled);
1456 #endif
1457
1458     BOOL completed=true;
1459     EX_TRY
1460     {
1461         GCX_COOP();
1462
1463         ENTER_DOMAIN_PTR(pDomain,ADV_ITERATOR); //iterator
1464         DomainFile *pDomainFileFrom = pModuleFrom->FindDomainFile(pDomain);
1465         if (pDomainFileFrom != NULL && pDomain->IsLoading(pDomainFileFrom, FILE_ACTIVE))
1466         {
1467             STRESS_LOG3(LF_LOADER, LL_INFO100,"Found DomainFile %p for module %p in AppDomain %i\n",pDomainFileFrom,pModuleFrom,pDomain->GetId().m_dwId);
1468             DomainFile *pDomainFileTo = pModuleTo->FindDomainFile(pDomain);
1469             if (pDomainFileTo == NULL)
1470                 pDomainFileTo = pDomain->LoadDomainNeutralModuleDependency(pModuleTo, FILE_LOADED);
1471
1472             if (!pDomainFileTo->TryEnsureActive())
1473                 pModuleFrom->EnableModuleFailureTriggers(pModuleTo, pDomain);
1474             else if (!pDomainFileTo->IsActive())
1475             {
1476                 // We are in a reentrant case
1477                 completed = FALSE;
1478             }
1479         }
1480         END_DOMAIN_TRANSITION;
1481     }
1482     EX_CATCH
1483     {
1484           if (!IsExceptionOfType(kAppDomainUnloadedException, GET_EXCEPTION()))
1485             EX_RETHROW;
1486     }
1487     EX_END_CATCH(SwallowAllExceptions)
1488     return completed;
1489 }
1490 #endif
1491
1492 // Returns TRUE if activation is completed for all app domains
1493 // static
1494 BOOL DomainFile::PropagateNewActivation(Module *pModuleFrom, Module *pModuleTo)
1495 {
1496     CONTRACTL
1497     {
1498         PRECONDITION(CheckPointer(pModuleFrom));
1499         PRECONDITION(CheckPointer(pModuleTo));
1500         THROWS; // should only throw transient failures
1501         GC_TRIGGERS;
1502         MODE_ANY;
1503     }
1504     CONTRACTL_END;
1505
1506     BOOL completed = TRUE;
1507 #ifdef FEATURE_LOADER_OPTIMIZATION
1508     if (pModuleFrom->GetAssembly()->IsDomainNeutral())
1509     {
1510         AppDomainIterator ai(TRUE);
1511         Thread *pThread = GetThread();
1512
1513         while (ai.Next())
1514         {
1515             STRESS_LOG3(LF_LOADER, LL_INFO100,"Attempting to propagate domain-neutral conditional module dependency %p -> %p to AppDomain %i\n",pModuleFrom,pModuleTo,ai.GetDomain()->GetId().m_dwId);
1516             // This is to minimize the chances of trying to run code in an appdomain that's shutting down.
1517             if (ai.GetDomain()->CanThreadEnter(pThread))
1518             {
1519                 completed &= PropagateActivationInAppDomain(pModuleFrom,pModuleTo,ai.GetDomain());
1520             }
1521         }
1522     }
1523     else
1524 #endif
1525     {
1526         AppDomain *pDomain = pModuleFrom->GetDomain()->AsAppDomain();
1527         DomainFile *pDomainFileFrom = pModuleFrom->GetDomainFile(pDomain);
1528         if (pDomain->IsLoading(pDomainFileFrom, FILE_ACTIVE))
1529         {
1530             // The dependency should already be loaded
1531             DomainFile *pDomainFileTo = pModuleTo->GetDomainFile(pDomain);
1532             if (!pDomainFileTo->TryEnsureActive())
1533                 pModuleFrom->EnableModuleFailureTriggers(pModuleTo, pDomain);
1534             else if (!pDomainFileTo->IsActive())
1535             {
1536                 // Reentrant case
1537                 completed = FALSE;
1538             }
1539         }
1540     }
1541
1542     return completed;
1543 }
1544
1545 // Checks that module has not been activated in any domain
1546 CHECK DomainFile::CheckUnactivatedInAllDomains(Module *pModule)
1547 {
1548     CONTRACTL
1549     {
1550         PRECONDITION(CheckPointer(pModule));
1551         THROWS;
1552         GC_TRIGGERS;
1553         MODE_ANY;
1554     }
1555     CONTRACTL_END;
1556
1557     if (pModule->GetAssembly()->IsDomainNeutral())
1558     {
1559         AppDomainIterator ai(TRUE);
1560
1561         while (ai.Next())
1562         {
1563             AppDomain *pDomain = ai.GetDomain();
1564             DomainFile *pDomainFile = pModule->FindDomainFile(pDomain);
1565             if (pDomainFile != NULL)
1566                 CHECK(!pDomainFile->IsActive());
1567         }
1568     }
1569     else
1570     {
1571         DomainFile *pDomainFile = pModule->FindDomainFile(pModule->GetDomain()->AsAppDomain());
1572         if (pDomainFile != NULL)
1573             CHECK(!pDomainFile->IsActive());
1574     }
1575
1576     CHECK_OK;
1577 }
1578
1579 #ifdef FEATURE_PREJIT
1580 DomainFile *DomainFile::FindNextDomainFileWithNativeImage()
1581 {
1582     LIMITED_METHOD_CONTRACT;
1583     return m_pNextDomainFileWithNativeImage;
1584 }
1585
1586 void DomainFile::InsertIntoDomainFileWithNativeImageList()
1587 {
1588     LIMITED_METHOD_CONTRACT;
1589
1590     while (true)
1591     {
1592         DomainFile *pLastDomainFileFoundWithNativeImage = m_pDomain->m_pDomainFileWithNativeImageList;
1593         m_pNextDomainFileWithNativeImage = pLastDomainFileFoundWithNativeImage;
1594         if (pLastDomainFileFoundWithNativeImage == InterlockedCompareExchangeT(&m_pDomain->m_pDomainFileWithNativeImageList, this, pLastDomainFileFoundWithNativeImage))
1595             break;
1596     }
1597 }
1598 #endif
1599
1600 //--------------------------------------------------------------------------------
1601 // DomainAssembly
1602 //--------------------------------------------------------------------------------
1603
1604 DomainAssembly::DomainAssembly(AppDomain *pDomain, PEFile *pFile, AssemblyLoadSecurity *pLoadSecurity, LoaderAllocator *pLoaderAllocator)
1605   : DomainFile(pDomain, pFile),
1606     m_pAssembly(NULL),
1607     m_debuggerFlags(DACF_NONE),
1608 #ifdef FEATURE_FUSION
1609     m_pAssemblyBindingClosure(NULL),
1610 #endif
1611     m_MissingDependenciesCheckStatus(CMD_Unknown),
1612     m_fSkipPolicyResolution(pLoadSecurity != NULL && !pLoadSecurity->ShouldResolvePolicy()),
1613     m_fDebuggerUnloadStarted(FALSE),
1614     m_fCollectible(pLoaderAllocator->IsCollectible()),
1615     m_fHostAssemblyPublished(false),
1616     m_fCalculatedShouldLoadDomainNeutral(false),
1617     m_fShouldLoadDomainNeutral(false)
1618 {
1619     CONTRACTL
1620     {
1621         CONSTRUCTOR_CHECK;
1622         STANDARD_VM_CHECK;
1623         INJECT_FAULT(COMPlusThrowOM(););
1624     }
1625     CONTRACTL_END;
1626
1627     pFile->ValidateForExecution();
1628
1629 #ifndef CROSSGEN_COMPILE
1630     if (m_fCollectible)
1631     {
1632         ((AssemblyLoaderAllocator *)pLoaderAllocator)->SetDomainAssembly(this);
1633     }
1634 #endif
1635
1636     // !!! backout
1637
1638     m_hExposedAssemblyObject = NULL;
1639
1640     NewHolder<IAssemblySecurityDescriptor> pSecurityDescriptorHolder(Security::CreateAssemblySecurityDescriptor(pDomain, this, pLoaderAllocator));
1641
1642     if (pLoadSecurity != NULL)
1643     {
1644 #ifdef FEATURE_CAS_POLICY
1645         // If this assembly had a file name specified, we aren't allowed to load from remote sources and we
1646         // aren't in CAS policy mode (which sandboxes remote assemblies automatically), then we need to do a
1647         // check on this assembly's zone of origin when creating it.
1648         if (pLoadSecurity->m_fCheckLoadFromRemoteSource &&
1649             !pLoadSecurity->m_fSuppressSecurityChecks &&
1650             !m_pDomain->GetSecurityDescriptor()->AllowsLoadsFromRemoteSources() &&
1651             !pFile->IsIntrospectionOnly())
1652         {
1653             SString strCodeBase;
1654             BYTE pbUniqueID[MAX_SIZE_SECURITY_ID];
1655             DWORD cbUniqueID = COUNTOF(pbUniqueID);
1656             SecZone dwZone = NoZone;
1657
1658             GetSecurityIdentity(strCodeBase,
1659                                 &dwZone,
1660                                 0,
1661                                 pbUniqueID,
1662                                 &cbUniqueID);
1663
1664             // Since loads from remote sources are not enabled for this assembly, we only want to allow the
1665             // load if any of the following conditions apply:
1666             //
1667             //  * The load is coming off the local machine
1668             //  * The load is coming from the intranet or a trusted site, and the code base is UNC.  (ie,
1669             //    don't allow HTTP loads off the local intranet
1670
1671             bool safeLoad = false;
1672             if (dwZone == LocalMachine)
1673             {
1674                 safeLoad = true;
1675             }
1676             else if (dwZone == Intranet || dwZone == Trusted)
1677             {
1678                 if (UrlIsFileUrl(strCodeBase.GetUnicode()))
1679                 {
1680                     safeLoad = true;
1681                 }
1682                 else if (PathIsUNC(strCodeBase.GetUnicode()))
1683                 {
1684                     safeLoad = true;
1685                 }
1686             }
1687
1688             if (!safeLoad)
1689             {
1690                 // We've tried to load an assembly from a location where it would have been sandboxed in legacy
1691                 // CAS situations, but the application hasn't indicated that this is a safe thing to do. In
1692                 // order to prevent accidental security holes by silently loading assemblies in full trust that
1693                 // an application expected to be sandboxed, we'll throw an exception instead.
1694                 //
1695                 // Since this exception can commonly occur with if the file is physically located on the
1696                 // hard drive, but has the mark of the web on it we'll also try to detect this mark and
1697                 // provide a customized error message if we find it.   We do that by re-evaluating the
1698                 // assembly's zone with the NOSAVEDFILECHECK flag, which ignores the mark of the web, and if
1699                 // that comes back as MyComputer we flag the assembly as having the mark of the web on it.
1700                 SecZone dwNoMotwZone = NoZone;
1701                 GetSecurityIdentity(strCodeBase, &dwNoMotwZone, MUTZ_NOSAVEDFILECHECK, pbUniqueID, &cbUniqueID);
1702
1703                 if (dwNoMotwZone == LocalMachine)
1704                 {
1705                     COMPlusThrow(kNotSupportedException, IDS_E_LOADFROM_REMOTE_SOURCE_MOTW);
1706                 }
1707                 else
1708                 {
1709                     COMPlusThrow(kNotSupportedException, IDS_E_LOADFROM_REMOTE_SOURCE);
1710                 }
1711             }
1712         }
1713 #endif // FEATURE_CAS_POLICY
1714
1715         if (GetFile()->IsSourceGAC())
1716         {
1717             // Assemblies in the GAC are not allowed to
1718             // specify additional evidence.  They must always follow default machine policy rules.
1719
1720             // So, we just ignore the evidence. (Ideally we would throw an error, but it would introduce app
1721             // compat issues.)
1722         }
1723         else
1724         {
1725 #ifdef FEATURE_FUSION
1726             // We do not support sharing behavior of ALWAYS when using evidence to load assemblies
1727             if (pDomain->GetSharePolicy() == AppDomain::SHARE_POLICY_ALWAYS
1728                 && ShouldLoadDomainNeutral())
1729             {
1730                 // Just because we have information about the loaded assembly's security doesn't mean that
1731                 // we're trying to override evidence, make sure we're not just trying to push a grant set
1732                 if (((pLoadSecurity->m_pEvidence != NULL) && (*pLoadSecurity->m_pEvidence != NULL)) ||
1733                     ((pLoadSecurity->m_pAdditionalEvidence != NULL) && (*pLoadSecurity->m_pAdditionalEvidence != NULL)))
1734                 {
1735                     // We may not be able to reduce sharing policy at this point, if we have already loaded
1736                     // some non-GAC assemblies as domain neutral.  For this case we must regrettably fail
1737                     // the whole operation.
1738                     if (!pDomain->ReduceSharePolicyFromAlways())
1739                     {
1740                         ThrowHR(COR_E_CANNOT_SPECIFY_EVIDENCE);
1741                     }
1742                 }
1743             }
1744 #endif
1745             {
1746                 GCX_COOP();
1747
1748 #ifdef FEATURE_CAS_POLICY
1749                 if (pLoadSecurity->m_pAdditionalEvidence != NULL)
1750                 {
1751                     if(*pLoadSecurity->m_pAdditionalEvidence != NULL)
1752                     {
1753                         pSecurityDescriptorHolder->SetAdditionalEvidence(*pLoadSecurity->m_pAdditionalEvidence);
1754                     }
1755                 }
1756                 else if (pLoadSecurity->m_pEvidence != NULL)
1757                 {
1758                     if (*pLoadSecurity->m_pEvidence != NULL)
1759                     {
1760                         pSecurityDescriptorHolder->SetEvidence(*pLoadSecurity->m_pEvidence);
1761                     }
1762                 }
1763 #endif // FEATURE_CAS_POLICY
1764
1765                 // If the assembly being loaded already knows its grant set (for instnace, it's being pushed
1766                 // from the loading assembly), then we can set that up now as well
1767                 if (!pLoadSecurity->ShouldResolvePolicy())
1768                 {
1769                     _ASSERTE(pLoadSecurity->m_pGrantSet != NULL);
1770
1771 #ifdef FEATURE_CAS_POLICY
1772                     // The permissions from an anonymously hosted dynamic method are fulltrust/transparent,
1773                     // so ensure we have full trust to pass that on to the new assembly
1774                     if(pLoadSecurity->m_fPropagatingAnonymouslyHostedDynamicMethodGrant &&
1775                        !CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_Security_DisableAnonymouslyHostedDynamicMethodCreatorSecurityCheck))
1776                     {
1777                         Security::SpecialDemand(SSWT_LATEBOUND_LINKDEMAND, SECURITY_FULL_TRUST);
1778                     }
1779 #endif // FEATURE_CAS_POLICY
1780
1781                     pSecurityDescriptorHolder->PropagatePermissionSet(
1782                                                       *pLoadSecurity->m_pGrantSet,
1783                                                       pLoadSecurity->m_pRefusedSet == NULL ? NULL : *pLoadSecurity->m_pRefusedSet,
1784                                                       pLoadSecurity->m_dwSpecialFlags);
1785                 }
1786             }
1787         }
1788     }
1789
1790     SetupDebuggingConfig();
1791
1792     // Add a Module iterator entry for this assembly.
1793     IfFailThrow(m_Modules.Append(this));
1794
1795     m_pSecurityDescriptor = pSecurityDescriptorHolder.Extract();
1796 }
1797
1798 DomainAssembly::~DomainAssembly()
1799 {
1800     CONTRACTL
1801     {
1802         DESTRUCTOR_CHECK;
1803         NOTHROW;
1804         GC_TRIGGERS;
1805         MODE_ANY;
1806         INJECT_FAULT(COMPlusThrowOM(););
1807     }
1808     CONTRACTL_END;
1809
1810     if (m_fHostAssemblyPublished)
1811     {
1812         // Remove association first.
1813         GetAppDomain()->UnPublishHostedAssembly(this);
1814     }
1815
1816     ModuleIterator i = IterateModules(kModIterIncludeLoading);
1817     while (i.Next())
1818     {
1819         if (i.GetDomainFile() != this)
1820             delete i.GetDomainFile();
1821     }
1822
1823     if (m_pAssembly != NULL && !m_pAssembly->IsDomainNeutral())
1824     {
1825         delete m_pAssembly;
1826     }
1827
1828     delete m_pSecurityDescriptor;
1829 }
1830
1831 void DomainAssembly::ReleaseFiles()
1832 {
1833     STANDARD_VM_CONTRACT;
1834
1835     if(m_pAssembly)
1836         m_pAssembly->StartUnload();
1837 #ifdef FEATURE_FUSION
1838     // release the old closure from the holder
1839     m_pAssemblyBindingClosure=NULL;
1840 #endif
1841     ModuleIterator i = IterateModules(kModIterIncludeLoading);
1842     while (i.Next())
1843     {
1844         if (i.GetDomainFile() != this)
1845              i.GetDomainFile()->ReleaseFiles();
1846     }
1847
1848     DomainFile::ReleaseFiles();
1849 }
1850
1851 void DomainAssembly::SetAssembly(Assembly* pAssembly)
1852 {
1853     STANDARD_VM_CONTRACT;
1854
1855     UpdatePEFile(pAssembly->GetManifestFile());
1856     _ASSERTE(pAssembly->GetManifestModule()->GetFile()==m_pFile);
1857     m_pAssembly = pAssembly;
1858     m_pModule = pAssembly->GetManifestModule();
1859
1860     pAssembly->SetDomainAssembly(this);
1861 }
1862
1863 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
1864 void DomainAssembly::AddModule(DomainModule *pModule)
1865 {
1866     CONTRACTL
1867     {
1868         INSTANCE_CHECK;
1869         THROWS;
1870         GC_TRIGGERS;
1871         MODE_ANY;
1872     }
1873     CONTRACTL_END;
1874
1875     DWORD index = RidFromToken(pModule->GetToken());
1876
1877     while (index >= m_Modules.GetCount())
1878         IfFailThrow(m_Modules.Append(NULL));
1879
1880     m_Modules.Set(index, pModule);
1881 }
1882 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
1883
1884 #ifndef CROSSGEN_COMPILE
1885 //---------------------------------------------------------------------------------------
1886 //
1887 // Returns managed representation of the assembly (Assembly or AssemblyBuilder).
1888 // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases).
1889 //
1890 OBJECTREF DomainAssembly::GetExposedAssemblyObject()
1891 {
1892     CONTRACTL
1893     {
1894         INSTANCE_CHECK;
1895         THROWS;
1896         MODE_COOPERATIVE;
1897         GC_TRIGGERS;
1898     }
1899     CONTRACTL_END;
1900
1901     LoaderAllocator * pLoaderAllocator = GetLoaderAllocator();
1902
1903     if (!pLoaderAllocator->IsManagedScoutAlive())
1904     {   // We already collected the managed scout, so we cannot re-create any managed objects
1905         // Note: This is an optimization, as the managed scout can be collected right after this check
1906         return NULL;
1907     }
1908
1909     if (m_hExposedAssemblyObject == NULL)
1910     {
1911         // Atomically create a handle
1912
1913         LOADERHANDLE handle = pLoaderAllocator->AllocateHandle(NULL);
1914
1915         FastInterlockCompareExchangePointer(&m_hExposedAssemblyObject, handle, static_cast<LOADERHANDLE>(NULL));
1916     }
1917
1918     if (pLoaderAllocator->GetHandleValue(m_hExposedAssemblyObject) == NULL)
1919     {
1920         ASSEMBLYREF   assemblyObj = NULL;
1921         MethodTable * pMT;
1922         if (GetFile()->IsDynamic())
1923         {
1924             // This is unnecessary because the managed InternalAssemblyBuilder object
1925             // should have already been created at the time of DefineDynamicAssembly
1926             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
1927             pMT = MscorlibBinder::GetClass(CLASS__INTERNAL_ASSEMBLY_BUILDER);
1928         }
1929         else
1930         {
1931             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
1932             pMT = MscorlibBinder::GetClass(CLASS__ASSEMBLY);
1933         }
1934
1935         // Will be TRUE only if LoaderAllocator managed object was already collected and therefore we should
1936         // return NULL
1937         BOOL fIsLoaderAllocatorCollected = FALSE;
1938
1939         // Create the assembly object
1940         GCPROTECT_BEGIN(assemblyObj);
1941         assemblyObj = (ASSEMBLYREF)AllocateObject(pMT);
1942
1943         assemblyObj->SetAssembly(this);
1944
1945         // Attach the reference to the assembly to keep the LoaderAllocator for this collectible type
1946         // alive as long as a reference to the assembly is kept alive.
1947         // Currently we overload the sync root field of the assembly to do so, but the overload is not necessary.
1948         if (GetAssembly() != NULL)
1949         {
1950             OBJECTREF refLA = GetAssembly()->GetLoaderAllocator()->GetExposedObject();
1951             if ((refLA == NULL) && GetAssembly()->GetLoaderAllocator()->IsCollectible())
1952             {   // The managed LoaderAllocator object was collected
1953                 fIsLoaderAllocatorCollected = TRUE;
1954             }
1955             assemblyObj->SetSyncRoot(refLA);
1956         }
1957
1958         if (!fIsLoaderAllocatorCollected)
1959         {   // We should not expose this value in case the LoaderAllocator managed object was already
1960             // collected
1961             pLoaderAllocator->CompareExchangeValueInHandle(m_hExposedAssemblyObject, (OBJECTREF)assemblyObj, NULL);
1962         }
1963         GCPROTECT_END();
1964
1965         if (fIsLoaderAllocatorCollected)
1966         {   // The LoaderAllocator managed object was already collected, we cannot re-create it
1967             // Note: We did not publish the allocated Assembly/AssmeblyBuilder object, it will get collected
1968             // by GC
1969             return NULL;
1970         }
1971     }
1972
1973     return pLoaderAllocator->GetHandleValue(m_hExposedAssemblyObject);
1974 } // DomainAssembly::GetExposedAssemblyObject
1975 #endif // CROSSGEN_COMPILE
1976
1977 #ifdef FEATURE_LOADER_OPTIMIZATION
1978
1979 #ifdef FEATURE_FUSION
1980 // This inner method exists to avoid EX_TRY calling _alloca repeatedly in the for loop below.
1981 DomainAssembly::CMDI_Result DomainAssembly::CheckMissingDependencyInner(IAssemblyBindingClosure* pClosure, DWORD idx)
1982 {
1983     CONTRACTL {
1984         INSTANCE_CHECK;
1985         THROWS;
1986         GC_TRIGGERS;
1987     } CONTRACTL_END;
1988
1989     SafeComHolder<IAssemblyName>  pAssemblyName;
1990     HRESULT hrBindFailure = S_OK;
1991     HRESULT hr = pClosure->GetNextFailureAssembly(idx, &pAssemblyName, &hrBindFailure);
1992     if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
1993     {
1994         return CMDI_End;
1995     }
1996
1997     IfFailThrow(hr);
1998
1999     CMDI_Result ret = CMDI_AssemblyResolveFailed;
2000     AssemblySpec spec;
2001     PEAssemblyHolder result;
2002
2003     EX_TRY
2004     {
2005         spec.InitializeSpec(pAssemblyName, this, FALSE);
2006         result = this->GetAppDomain()->TryResolveAssembly(&spec,FALSE);
2007
2008         if (result && result->CanUseWithBindingCache())
2009         {
2010             this->GetAppDomain()->AddFileToCache(&spec, result);
2011             ret = CMDI_AssemblyResolveSucceeded;
2012         }
2013         else
2014         {
2015             _ASSERTE(FAILED(hrBindFailure));
2016
2017             StackSString name;
2018             spec.GetFileOrDisplayName(0, name);
2019             NewHolder<EEFileLoadException> pEx(new EEFileLoadException(name, hrBindFailure));
2020             this->GetAppDomain()->AddExceptionToCache(&spec, pEx);
2021         }
2022     }
2023     EX_CATCH
2024     {
2025         // For compat reasons, we don't want to throw right now but make sure that we
2026         // cache the exception so that it can be thrown if/when we try to load the
2027         // further down the road. See VSW 528532 for more details.
2028     }
2029     EX_END_CATCH(RethrowTransientExceptions);
2030
2031     return ret;
2032 }
2033
2034
2035 // CheckMissingDependencies returns FALSE if any missing dependency would
2036 // successfully bind with an AssemblyResolve event. When this is the case, we
2037 // want to avoid sharing this assembly, since AssemblyResolve events are not
2038 // under our control, and therefore not predictable.
2039 CMD_State DomainAssembly::CheckMissingDependencies()
2040 {
2041     CONTRACTL {
2042         INSTANCE_CHECK;
2043         THROWS;
2044         GC_TRIGGERS;
2045     } CONTRACTL_END;
2046
2047     if (MissingDependenciesCheckDone())
2048         return m_MissingDependenciesCheckStatus;
2049
2050     if (this->GetAppDomain()->IsCompilationDomain())
2051     {
2052         // Compilation domains will never have resolve events.  Plus, this path
2053         // will sidestep the compilation domain's bind override, which will make
2054         // us skip over some dependencies.
2055         m_MissingDependenciesCheckStatus = CMD_NotNeeded;
2056         return m_MissingDependenciesCheckStatus;
2057     }
2058
2059     if (IsSystem())
2060     {
2061         m_MissingDependenciesCheckStatus = CMD_NotNeeded;
2062         return m_MissingDependenciesCheckStatus;
2063     }
2064
2065     GCX_PREEMP();
2066     IAssemblyBindingClosure * pClosure = GetAssemblyBindingClosure(LEVEL_COMPLETE);
2067
2068     if(pClosure == NULL)
2069     {
2070         // If the closure is empty, no need to iterate them.
2071         m_MissingDependenciesCheckStatus = CMD_NotNeeded;
2072         return m_MissingDependenciesCheckStatus;
2073     }
2074
2075     for (DWORD idx = 0;;idx++)
2076     {
2077         switch (CheckMissingDependencyInner(pClosure, idx))
2078         {
2079           case CMDI_AssemblyResolveSucceeded:
2080           {
2081             STRESS_LOG1(LF_CODESHARING,LL_INFO100,"Missing dependencies check FAILED, DomainAssembly=%p",this);
2082             m_MissingDependenciesCheckStatus = CMD_Resolved;
2083             return m_MissingDependenciesCheckStatus;
2084             break;
2085           }
2086
2087           case CMDI_End:
2088           {
2089             STRESS_LOG1(LF_CODESHARING,LL_INFO100,"Missing dependencies check SUCCESSFUL, DomainAssembly=%p",this);
2090             m_MissingDependenciesCheckStatus = CMD_IndeedMissing;
2091             return m_MissingDependenciesCheckStatus;
2092             break;
2093           }
2094
2095           case CMDI_AssemblyResolveFailed:
2096           {
2097             // Don't take any action, just continue the loop.
2098             break;
2099           }
2100         }
2101     }
2102 }
2103 #endif // FEATURE_FUSION
2104
2105 BOOL DomainAssembly::MissingDependenciesCheckDone()
2106 {
2107     return m_MissingDependenciesCheckStatus != CMD_Unknown;
2108 }
2109
2110 CMD_State DomainAssembly::CheckMissingDependencies()
2111 {
2112     //CoreCLR simply doesn't share if dependencies are missing
2113     return CMD_NotNeeded;
2114 }
2115
2116 #endif // FEATURE_LOADER_OPTIMIZATION
2117
2118 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2119 DomainFile* DomainAssembly::FindModule(PEFile *pFile, BOOL includeLoading)
2120 {
2121     CONTRACT (DomainFile*)
2122     {
2123         INSTANCE_CHECK;
2124         THROWS;
2125         GC_NOTRIGGER;
2126         MODE_ANY;
2127         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2128     }
2129     CONTRACT_END;
2130
2131     ModuleIterator i = IterateModules(includeLoading ? kModIterIncludeLoading : kModIterIncludeLoaded);
2132     while (i.Next())
2133     {
2134         if (i.GetDomainFile()->Equals(pFile))
2135             RETURN i.GetDomainFile();
2136     }
2137     RETURN NULL;
2138 }
2139 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
2140
2141 DomainFile* DomainAssembly::FindIJWModule(HMODULE hMod)
2142 {
2143     CONTRACT (DomainFile*)
2144     {
2145         INSTANCE_CHECK;
2146         THROWS;
2147         GC_NOTRIGGER;
2148         MODE_ANY;
2149         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2150     }
2151     CONTRACT_END;
2152
2153     ModuleIterator i = IterateModules(kModIterIncludeLoaded);
2154     while (i.Next())
2155     {
2156         PEFile *pFile = i.GetDomainFile()->GetFile();
2157
2158         if (   !pFile->IsResource()
2159             && !pFile->IsDynamic()
2160             && !pFile->IsILOnly()
2161             && pFile->GetIJWBase() == hMod)
2162         {
2163             RETURN i.GetDomainFile();
2164         }
2165     }
2166     RETURN NULL;
2167 }
2168
2169
2170 void DomainAssembly::Begin()
2171 {
2172     STANDARD_VM_CONTRACT;
2173
2174     {
2175         AppDomain::LoadLockHolder lock(m_pDomain);
2176         m_pDomain->AddAssembly(this);
2177     }
2178     // Make it possible to find this DomainAssembly object from associated ICLRPrivAssembly.
2179     GetAppDomain()->PublishHostedAssembly(this);
2180     m_fHostAssemblyPublished = true;
2181 }
2182
2183 #ifdef FEATURE_PREJIT
2184 void DomainAssembly::FindNativeImage()
2185 {
2186     CONTRACTL
2187     {
2188         INSTANCE_CHECK;
2189         STANDARD_VM_CHECK;
2190     }
2191     CONTRACTL_END;
2192
2193     // For non-Apollo builds (i.e., when FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS is
2194     // NOT defined), this is how we avoid use of NGEN when diagnostics requests it: By
2195     // clearing it out and forcing a load of the MSIL assembly. For Apollo builds
2196     // (FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS), though, this doesn't work, as we
2197     // don't have MSIL assemblies handy (particularly for Fx Assemblies), so we need to
2198     // keep the NGENd image loaded, but to treat it as if it were an MSIL assembly. See
2199     // code:PEFile::SetNativeImage.
2200 #ifndef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2201     if (!NGENImagesAllowed())
2202     {
2203         GetFile()->SetCannotUseNativeImage();
2204
2205         if (GetFile()->HasNativeImage())
2206             GetFile()->ClearNativeImage();
2207
2208         return;
2209     }
2210 #endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2211
2212
2213 #ifdef FEATURE_FUSION
2214     DomainAssembly * pDomainAssembly = GetDomainAssembly();
2215     if (pDomainAssembly->GetSecurityDescriptor()->HasAdditionalEvidence() ||
2216         !(pDomainAssembly->GetFile()->IsContextLoad() ||
2217         pDomainAssembly->GetFile()->HasHostAssembly()))
2218     {
2219         m_pFile->SetCannotUseNativeImage();
2220     }
2221 #endif //FEATURE_FUSION
2222
2223     ClearNativeImageStress();
2224
2225     // We already have an image - we just need to do a few more checks
2226
2227     if (GetFile()->HasNativeImage())
2228     {
2229 #if defined(_DEBUG)
2230         if (g_pConfig->ForbidZap(GetSimpleName()))
2231         {
2232             SString sbuf;
2233             StackScratchBuffer scratch;
2234             sbuf.Printf("COMPlus_NgenBind_ZapForbid violation: %s.", GetSimpleName());
2235             DbgAssertDialog(__FILE__, __LINE__, sbuf.GetUTF8(scratch));
2236         }
2237 #endif
2238
2239         ReleaseHolder<PEImage> pNativeImage = GetFile()->GetNativeImageWithRef();
2240
2241         if(!IsSystem() && !SystemDomain::System()->SystemFile()->HasNativeImage() && !CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NgenAllowMscorlibSoftbind))
2242         {
2243             m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_MscorlibNotNative;
2244             STRESS_LOG2(LF_ZAP,LL_INFO100,"Rejecting native file %p, because mscolib has not NI - reason 0x%x\n",pNativeImage.GetValue(),m_dwReasonForRejectingNativeImage);
2245             ExternalLog(LL_ERROR, "Rejecting native image because mscorlib does not have native image");
2246 #ifdef FEATURE_FUSION
2247             if(GetFile())
2248                 GetFile()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_SYSTEM_ASSEMBLY_NATIVEIMAGE_NOT_AVAILABLE, NULL);
2249 #endif
2250             GetFile()->ClearNativeImage();
2251
2252 #ifdef FEATURE_WINDOWSPHONE
2253             // On Phone, always through exceptions when we throw the NI out
2254             ThrowHR(CLR_E_BIND_SYS_ASM_NI_MISSING);
2255 #endif
2256         }
2257         else
2258         if (!CheckZapSecurity(pNativeImage))
2259         {
2260             m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_FailedSecurityCheck;
2261             STRESS_LOG2(LF_ZAP,LL_INFO100,"Rejecting native file %p, because security check failed - reason 0x%x\n",pNativeImage.GetValue(),m_dwReasonForRejectingNativeImage);
2262             ExternalLog(LL_ERROR, "Rejecting native image because it failed the security check. "
2263                 "The assembly's permissions must have changed since the time it was ngenned, "
2264                 "or it is running with a different security context.");
2265
2266 #ifdef FEATURE_FUSION
2267             if(GetFile())
2268                 GetFile()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_ASSEMBLY_HAS_DIFFERENT_GRANT, NULL);
2269 #endif
2270             GetFile()->ClearNativeImage();
2271
2272 #ifdef FEATURE_WINDOWSPHONE
2273             // On Phone, always through exceptions when we throw the NI out
2274             ThrowHR(CLR_E_BIND_NI_SECURITY_FAILURE);
2275 #endif
2276
2277         }
2278         else if (!CheckZapDependencyIdentities(pNativeImage))
2279         {
2280             m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_DependencyIdentityMismatch;
2281             STRESS_LOG2(LF_ZAP,LL_INFO100,"Rejecting native file %p, because dependency identity mismatch - reason 0x%x\n",pNativeImage.GetValue(),m_dwReasonForRejectingNativeImage);
2282             ExternalLog(LL_ERROR, "Rejecting native image because of identity mismatch "
2283                 "with one or more of its assembly dependencies. The assembly needs "
2284                 "to be ngenned again");
2285
2286 #ifdef FEATURE_FUSION
2287             if(GetFile())
2288                 GetFile()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY, NULL);
2289 #endif
2290             GetFile()->ClearNativeImage();
2291
2292 #ifdef FEATURE_WINDOWSPHONE
2293             // On Phone, always through exceptions when we throw the NI out
2294             ThrowHR(CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH);
2295 #endif
2296
2297         }
2298         else
2299         {
2300             // We can only use a native image for a single Module. If this is a domain-bound
2301             // load, we know that this means only a single load will use this image, so we can just
2302             // flag it as in use.
2303
2304             // If on the other hand, we are going to be domain neutral, we may have many loads use
2305             // the same native image.  Still, we only want to allow the native image to be used
2306             // by loads which are going to end up with the same Module.  So, we have to effectively
2307             // eagerly compute whether that will be the case eagerly, now.  To enable this computation,
2308             // we store the binding closure in the image.
2309
2310             Module *  pNativeModule = pNativeImage->GetLoadedLayout()->GetPersistedModuleImage();
2311             EnsureWritablePages(pNativeModule);
2312             PEFile ** ppNativeFile = (PEFile **) (PBYTE(pNativeModule) + Module::GetFileOffset());
2313             BOOL bExpectedToBeShared= ShouldLoadDomainNeutral();
2314             if (!bExpectedToBeShared)
2315             {
2316                 GetFile()->SetNativeImageUsedExclusively();
2317             }
2318 #ifdef FEATURE_FUSION
2319             else
2320             {
2321                 if (!IsSystem())
2322                 {
2323                     GetFile()->SetNativeImageClosure(GetAssemblyBindingClosure(LEVEL_STARTING));
2324                 }
2325             }
2326 #endif //FEATURE_FUSION
2327
2328             PEAssembly * pFile = (PEAssembly *)FastInterlockCompareExchangePointer((void **)ppNativeFile, (void *)GetFile(), (void *)NULL);
2329             STRESS_LOG3(LF_ZAP,LL_INFO100,"Attempted to set  new native file %p, old file was %p, location in the image=%p\n",GetFile(),pFile,ppNativeFile);
2330             if (pFile!=NULL && !IsSystem() &&
2331
2332                     ( !bExpectedToBeShared ||
2333                        pFile == PEFile::Dummy() ||
2334                        pFile->IsNativeImageUsedExclusively() ||
2335 #ifdef FEATURE_FUSION
2336                        !pFile->HasEqualNativeClosure(this) ||
2337 #endif //FEATURE_FUSION
2338                        !(GetFile()->GetPath().Equals(pFile->GetPath())))
2339
2340                 )
2341             {
2342                 // The non-shareable native image has already been used in this process by another Module.
2343                 // We have to abandon the native image.  (Note that it isn't enough to
2344                 // just abandon the preload image, since the code in the file will
2345                 // reference the image directly).
2346                 m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_CannotShareNiAssemblyNotDomainNeutral;
2347                 STRESS_LOG3(LF_ZAP,LL_INFO100,"Rejecting native file %p, because it is already used by file %p - reason 0x%x\n",GetFile(),pFile,m_dwReasonForRejectingNativeImage);
2348                 
2349                 ExternalLog(LL_WARNING, "ZAP: An ngen image of an assembly which "
2350                     "is not loaded as domain-neutral cannot be used in multiple appdomains "
2351                     "- abandoning ngen image. The assembly will be JIT-compiled in "
2352                     "the second appdomain. See System.LoaderOptimization.MultiDomain "
2353                     "for information about domain-neutral loading.");
2354 #ifdef FEATURE_FUSION
2355                 if(GetFile())
2356                     GetFile()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_ASSEMBLY_NOT_DOMAIN_NEUTRAL, NULL);
2357 #endif
2358                 GetFile()->ClearNativeImage();
2359
2360                 // We only support a (non-shared) native image to be used from a single
2361                 // AppDomain. Its not obvious if this is an implementation restriction,
2362                 // or if this should fail DomainFile::CheckZapRequired().
2363                 // We err on the side of conservativeness, so that multi-domain tests
2364                 // do not blow up in CheckZapRequired()
2365                 GetFile()->SetCannotUseNativeImage();
2366             }
2367             else
2368             {
2369                 //If we are the first and others can reuse us, we cannot go away
2370                 if ((pFile == NULL) && (!GetFile()->IsNativeImageUsedExclusively()))
2371                     GetFile()->AddRef();
2372
2373                 LOG((LF_ZAP, LL_INFO100, "ZAP: Found a candidate native image for %s\n", GetSimpleName()));
2374             }
2375         }
2376     }
2377
2378     if (!GetFile()->HasNativeImage())
2379     {
2380         //
2381         // Verify that the IL image is consistent with the NGen images loaded into appdomain
2382         //
2383
2384         AssemblySpec spec;
2385         spec.InitializeSpec(GetFile());
2386
2387         GUID mvid;
2388         GetFile()->GetMVID(&mvid);
2389
2390         GetAppDomain()->CheckForMismatchedNativeImages(&spec, &mvid);
2391     }
2392
2393     CheckZapRequired();
2394 }
2395 #endif // FEATURE_PREJIT
2396
2397 BOOL DomainAssembly::ShouldLoadDomainNeutral()
2398 {
2399     STANDARD_VM_CONTRACT;
2400
2401     if (m_fCalculatedShouldLoadDomainNeutral)
2402         return m_fShouldLoadDomainNeutral;
2403     
2404     m_fShouldLoadDomainNeutral = !!ShouldLoadDomainNeutralHelper();
2405     m_fCalculatedShouldLoadDomainNeutral = true;
2406
2407     return m_fShouldLoadDomainNeutral;
2408 }
2409
2410 BOOL DomainAssembly::ShouldLoadDomainNeutralHelper()
2411 {
2412     STANDARD_VM_CONTRACT;
2413
2414 #ifdef FEATURE_LOADER_OPTIMIZATION
2415
2416
2417     if (IsSystem())
2418         return TRUE;
2419
2420     if (IsSingleAppDomain())
2421         return FALSE;
2422
2423     if (GetFile()->IsDynamic())
2424         return FALSE;
2425
2426 #ifdef FEATURE_COMINTEROP
2427     if (GetFile()->IsWindowsRuntime())
2428         return FALSE;
2429 #endif
2430
2431     switch(this->GetAppDomain()->GetSharePolicy()) {
2432     case AppDomain::SHARE_POLICY_ALWAYS:
2433         return TRUE;
2434
2435     case AppDomain::SHARE_POLICY_GAC:
2436         return IsSystem();
2437
2438     case AppDomain::SHARE_POLICY_NEVER:
2439         return FALSE;
2440
2441     case AppDomain::SHARE_POLICY_UNSPECIFIED:
2442     case AppDomain::SHARE_POLICY_COUNT:
2443         break;
2444     }
2445     
2446     return FALSE; // No meaning in doing costly closure walk for CoreCLR.
2447
2448
2449 #else // FEATURE_LOADER_OPTIMIZATION
2450     return IsSystem();
2451 #endif // FEATURE_LOADER_OPTIMIZATION
2452 }
2453
2454 BOOL DomainAssembly::ShouldSkipPolicyResolution()
2455 {
2456     LIMITED_METHOD_CONTRACT;
2457     return m_fSkipPolicyResolution;
2458 }
2459
2460
2461 #if defined(FEATURE_LOADER_OPTIMIZATION) && defined(FEATURE_FUSION)
2462 //
2463 // Returns TRUE if the attempt to steal ownership of the native image succeeded, or if there are other
2464 // reasons for retrying load of the native image in the current appdomain.
2465 //
2466 // Returns FALSE if the native image should be rejected in the current appdomain.
2467 //
2468 static BOOL TryToStealSharedNativeImageOwnership(PEFile ** ppNativeImage, PEFile * pNativeFile, PEFile * pFile)
2469 {
2470     STANDARD_VM_CONTRACT;
2471
2472     if (pNativeFile == PEFile::Dummy())
2473     {
2474         // Nothing to steal anymore. Loading of the native image failed elsewhere.
2475         return FALSE;
2476     }
2477
2478     _ASSERTE(!pNativeFile->IsNativeImageUsedExclusively());
2479     _ASSERTE(!pFile->IsNativeImageUsedExclusively());
2480
2481     SharedDomain * pSharedDomain = SharedDomain::GetDomain();
2482
2483     // Take the lock so that nobody steals or creates Assembly object for this native image while we are stealing it
2484     SharedFileLockHolder pNativeFileLock(pSharedDomain, pNativeFile, TRUE);
2485
2486     if (pNativeFile != VolatileLoad(ppNativeImage))
2487     {
2488         // The ownership changed before we got a chance. Retry.
2489         return TRUE;
2490     }
2491
2492     SharedAssemblyLocator locator(pNativeFile->AsAssembly(), SharedAssemblyLocator::PEASSEMBLYEXACT);
2493     if (pSharedDomain->FindShareableAssembly(&locator))
2494     {
2495         // Another shared assembly (with different binding closure) uses this image, therefore we cannot use it
2496         return FALSE;
2497     }
2498
2499     BOOL success = InterlockedCompareExchangeT(ppNativeImage, pFile, pNativeFile) == pNativeFile;
2500
2501     // If others can reuse us, we cannot go away
2502     if (success)
2503         pFile->AddRef();
2504
2505     STRESS_LOG3(LF_ZAP,LL_INFO100,"Attempt to steal ownership from native file %p by %p success %d\n", pNativeFile, pFile, success);
2506
2507     return TRUE;
2508 }
2509 #endif // FEATURE_LOADER_OPTIMIZATION && FEATURE_FUSION
2510
2511 // This is where the decision whether an assembly is DomainNeutral (shared) nor not is made.
2512 void DomainAssembly::Allocate()
2513 {
2514     CONTRACTL
2515     {
2516         INSTANCE_CHECK;
2517         STANDARD_VM_CHECK;
2518         INJECT_FAULT(COMPlusThrowOM(););
2519     }
2520     CONTRACTL_END;
2521
2522     // Make sure the security system is happy with this assembly being loaded into the domain
2523     GetSecurityDescriptor()->CheckAllowAssemblyLoad();
2524
2525     AllocMemTracker   amTracker;
2526     AllocMemTracker * pamTracker = &amTracker;
2527     
2528     Assembly * pAssembly = m_pAssembly;
2529     
2530     if (pAssembly==NULL)
2531     {
2532         //! If you decide to remove "if" do not remove this brace: order is important here - in the case of an exception,
2533         //! the Assembly holder must destruct before the AllocMemTracker declared above.
2534
2535         NewHolder<Assembly> assemblyHolder(NULL);
2536
2537         // Determine whether we are supposed to load the assembly as a shared
2538         // assembly or into the app domain.
2539         if (ShouldLoadDomainNeutral())
2540         {
2541
2542 #ifdef FEATURE_LOADER_OPTIMIZATION
2543
2544 #ifdef FEATURE_FUSION
2545 Retry:
2546 #endif
2547
2548             // Try to find an existing shared version of the assembly which
2549             // is compatible with our domain.
2550
2551             SharedDomain * pSharedDomain = SharedDomain::GetDomain();
2552
2553             SIZE_T nInitialShareableAssemblyCount = pSharedDomain->GetShareableAssemblyCount();
2554             DWORD dwSwitchCount = 0;
2555
2556             SharedFileLockHolder pFileLock(pSharedDomain, GetFile(), FALSE);
2557
2558             if (IsSystem())
2559             {
2560                 pAssembly=SystemDomain::SystemAssembly();
2561             }
2562             else
2563             {
2564                 SharedAssemblyLocator locator(this);
2565                 pAssembly = pSharedDomain->FindShareableAssembly(&locator);
2566
2567                 if (pAssembly == NULL)
2568                 {
2569                     pFileLock.Acquire();
2570                     pAssembly = pSharedDomain->FindShareableAssembly(&locator);
2571                 }
2572             }
2573
2574             if (pAssembly == NULL)
2575             {
2576 #ifdef FEATURE_FUSION
2577                 // Final verification that we can use the ngen image.
2578                 //
2579                 // code:DomainAssembly::FindNativeImage checks the binding closures before declaring the native image as shareable candidate, 
2580                 // but the ultimate decisions about sharing happens inside code:Assembly::CanBeShared called from FindShareableAssembly above. 
2581                 // code:Assembly::CanBeShared checks more conditions than just binding closures. In particular, it also checks whether AssemblyResolve 
2582                 // event resolves any missing dependencies found in the binding closure - the assembly cannot be shared if it is the case.
2583                 // The end result is that same ngen image can get here in multiple domains in parallel, but it may not be shareable between all of them.
2584                 //
2585                 // We reconcile this conflict by checking whether there is somebody else conflicting with us. If it is, we will try to steal
2586                 // the ownership of the native image from the other guy and retry. The retry logic is required to prevent a perfectly valid
2587                 // native image being dropped on the floor just because of multiple appdomains raced to load it.
2588                 {
2589                     ReleaseHolder<PEImage> pNativeImage = GetFile()->GetNativeImageWithRef();
2590                     if ((pNativeImage != NULL) && (pNativeImage->GetLoadedLayout() != NULL))
2591                     {
2592                         Module * pNativeModule = pNativeImage->GetLoadedLayout()->GetPersistedModuleImage();
2593                         if (pNativeModule != NULL)
2594                         {
2595                             // The owner of the native module was set thread-safe in code:DomainAssembly::FindNativeImage
2596                             // However the final decision if we can share the native image is done in this function (see usage of code:FindShareableAssembly above)
2597                             PEFile ** ppNativeFile = (PEFile **) (PBYTE(pNativeModule) + Module::GetFileOffset());
2598                             PEFile * pNativeFile = VolatileLoad(ppNativeFile);
2599                             if (pNativeFile != GetFile())
2600                             {
2601                                 pFileLock.Release();
2602
2603                                 // Ensures that multiple threads won't fight with each other indefinitely
2604                                 __SwitchToThread(0, ++dwSwitchCount);
2605
2606                                 if (!TryToStealSharedNativeImageOwnership(ppNativeFile, pNativeFile, GetFile()))
2607                                 {
2608                                     // If a shared assembly got loaded in the mean time, retry all lookups again
2609                                     if (pSharedDomain->GetShareableAssemblyCount() != nInitialShareableAssemblyCount)
2610                                         goto Retry;
2611
2612                                     m_dwReasonForRejectingNativeImage = ReasonForRejectingNativeImage_NiAlreadyUsedInAnotherSharedAssembly;
2613                                     STRESS_LOG3(LF_ZAP,LL_INFO100,"Rejecting native file %p, because it is already used by shared file %p - reason 0x%x\n",GetFile(),pNativeFile,m_dwReasonForRejectingNativeImage);
2614                                     GetFile()->ClearNativeImage();
2615                                     GetFile()->SetCannotUseNativeImage();
2616                                 }
2617
2618                                 goto Retry;
2619                             }
2620                         }
2621                     }
2622                 }
2623 #endif // FEATURE_FUSION
2624
2625                 // We can now rely on the fact that our MDImport will not change so we can stop refcounting it.
2626                 GetFile()->MakeMDImportPersistent();
2627
2628                 // Go ahead and create new shared version of the assembly if possible
2629                 // <TODO> We will need to pass a valid OBJECREF* here in the future when we implement SCU </TODO>
2630                 assemblyHolder = pAssembly = Assembly::Create(pSharedDomain, GetFile(), GetDebuggerInfoBits(), FALSE, pamTracker, NULL);
2631
2632                 if (MissingDependenciesCheckDone())
2633                     pAssembly->SetMissingDependenciesCheckDone();
2634
2635                 // Compute the closure assembly dependencies
2636                 // of the code & layout of given assembly.
2637                 //
2638                 // An assembly has direct dependencies listed in its manifest.
2639                 //
2640                 // We do not in general also have all of those dependencies' dependencies in the manifest.
2641                 // After all, we may be only using a small portion of the assembly.
2642                 //
2643                 // However, since all dependent assemblies must also be shared (so that
2644                 // the shared data in this assembly can refer to it), we are in
2645                 // effect forced to behave as though we do have all of their dependencies.
2646                 // This is because the resulting shared assembly that we will depend on
2647                 // DOES have those dependencies, but we won't be able to validly share that
2648                 // assembly unless we match all of ITS dependencies, too.
2649 #ifdef FEATURE_FUSION
2650                 if ((this->GetAppDomain()->GetFusionContext() != NULL) && !IsSystem())
2651                 {
2652                     IAssemblyBindingClosure* pClosure = GetAssemblyBindingClosure(LEVEL_STARTING);
2653                     pAssembly->SetBindingClosure(pClosure);
2654                 }
2655 #endif // FEATURE_FUSION
2656                 // Sets the tenured bit atomically with the hash insert.
2657                 pSharedDomain->AddShareableAssembly(pAssembly);
2658             }
2659 #else // FEATURE_LOADER_OPTIMIZATION
2660             _ASSERTE(IsSystem());
2661             if (SystemDomain::SystemAssembly())
2662             {
2663                 pAssembly = SystemDomain::SystemAssembly();
2664             }
2665             else
2666             {
2667                 // We can now rely on the fact that our MDImport will not change so we can stop refcounting it.
2668                 GetFile()->MakeMDImportPersistent();
2669
2670                 // <TODO> We will need to pass a valid OBJECTREF* here in the future when we implement SCU </TODO>
2671                 SharedDomain * pSharedDomain = SharedDomain::GetDomain();
2672                 assemblyHolder = pAssembly = Assembly::Create(pSharedDomain, GetFile(), GetDebuggerInfoBits(), FALSE, pamTracker, NULL);
2673                 pAssembly->SetIsTenured();
2674             }
2675 #endif  // FEATURE_LOADER_OPTIMIZATION
2676         }
2677         else
2678         {
2679             // We can now rely on the fact that our MDImport will not change so we can stop refcounting it.
2680             GetFile()->MakeMDImportPersistent();
2681             
2682             // <TODO> We will need to pass a valid OBJECTREF* here in the future when we implement SCU </TODO>
2683             assemblyHolder = pAssembly = Assembly::Create(m_pDomain, GetFile(), GetDebuggerInfoBits(), FALSE, pamTracker, NULL);
2684             assemblyHolder->SetIsTenured();
2685         }
2686
2687
2688         //@todo! This is too early to be calling SuppressRelease. The right place to call it is below after
2689         // the CANNOTTHROWCOMPLUSEXCEPTION. Right now, we have to do this to unblock OOM injection testing quickly
2690         // as doing the right thing is nontrivial.
2691         pamTracker->SuppressRelease();
2692         assemblyHolder.SuppressRelease();
2693     }
2694
2695 #ifdef FEATURE_COMINTEROP
2696     // If we are in an AppX process we should prevent loading of PIA in the AppDomain.
2697     // This will ensure that we do not run into any compatibility issues in case a type has both a co-Class and a Winrt Class
2698     if (AppX::IsAppXProcess() && pAssembly->IsPIA())
2699     {
2700         COMPlusThrow(kNotSupportedException, W("NotSupported_PIAInAppxProcess"));
2701     }
2702 #endif
2703
2704     SetAssembly(pAssembly);
2705
2706 #ifdef FEATURE_PREJIT
2707     BOOL fInsertIntoAssemblySpecBindingCache = TRUE;
2708
2709     // Insert AssemblyDef details into AssemblySpecBindingCache if appropriate
2710
2711 #ifdef FEATURE_FUSION
2712     fInsertIntoAssemblySpecBindingCache = GetFile()->GetLoadContext() == LOADCTX_TYPE_DEFAULT;
2713 #endif
2714     
2715 #if defined(FEATURE_APPX_BINDER)
2716     fInsertIntoAssemblySpecBindingCache = fInsertIntoAssemblySpecBindingCache && !GetFile()->HasHostAssembly();
2717 #else
2718     fInsertIntoAssemblySpecBindingCache = fInsertIntoAssemblySpecBindingCache && GetFile()->CanUseWithBindingCache();
2719 #endif
2720
2721     if (fInsertIntoAssemblySpecBindingCache)
2722     {
2723         AssemblySpec specAssemblyDef;
2724         specAssemblyDef.InitializeSpec(GetFile());
2725         if (specAssemblyDef.IsStrongNamed() && specAssemblyDef.HasPublicKey())
2726         {
2727             specAssemblyDef.ConvertPublicKeyToToken();
2728         }
2729         m_pDomain->AddAssemblyToCache(&specAssemblyDef, this);
2730     }
2731 #endif
2732 } // DomainAssembly::Allocate
2733
2734 void DomainAssembly::DeliverAsyncEvents()
2735 {
2736     CONTRACTL
2737     {
2738         INSTANCE_CHECK;
2739         NOTHROW;
2740         GC_TRIGGERS;
2741         MODE_ANY;
2742         SO_INTOLERANT;
2743     }
2744     CONTRACTL_END;
2745
2746     OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE);
2747     m_pDomain->RaiseLoadingAssemblyEvent(this);
2748
2749 }
2750
2751
2752 void DomainAssembly::DeliverSyncEvents()
2753 {
2754     CONTRACTL
2755     {
2756         INSTANCE_CHECK;
2757         STANDARD_VM_CHECK;
2758     }
2759     CONTRACTL_END;
2760
2761     GetCurrentModule()->NotifyEtwLoadFinished(S_OK);
2762
2763     // We may be notified from inside the loader lock if we are delivering IJW events, so keep track.
2764 #ifdef PROFILING_SUPPORTED
2765     if (!IsProfilerNotified())
2766     {
2767         SetProfilerNotified();
2768         GetCurrentModule()->NotifyProfilerLoadFinished(S_OK);
2769     }
2770
2771 #endif
2772 #ifdef DEBUGGING_SUPPORTED
2773     GCX_COOP();
2774     if (!IsDebuggerNotified())
2775     {
2776         SetShouldNotifyDebugger();
2777
2778         if (m_pDomain->IsDebuggerAttached())
2779         {
2780             // If this is the first assembly in the AppDomain, it may be possible to get a better name than the
2781             // default.
2782             CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
2783             m_pDomain->m_Assemblies.Get(m_pDomain, 0, pDomainAssembly.This());
2784             if ((pDomainAssembly == this) && !m_pDomain->IsUserCreatedDomain())
2785                 m_pDomain->ResetFriendlyName();
2786         }
2787
2788         // Still work to do even if no debugger is attached.
2789         NotifyDebuggerLoad(ATTACH_ASSEMBLY_LOAD, FALSE);
2790
2791     }
2792 #endif // DEBUGGING_SUPPORTED
2793 } // DomainAssembly::DeliverSyncEvents
2794
2795 /*
2796   // The enum for dwLocation from managed code:
2797     public enum ResourceLocation
2798     {
2799         Embedded = 1,
2800         ContainedInAnotherAssembly = 2,
2801         ContainedInManifestFile = 4
2802     }
2803 */
2804
2805 BOOL DomainAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
2806                                  PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef,
2807                                  LPCSTR *szFileName, DWORD *dwLocation,
2808                                  StackCrawlMark *pStackMark, BOOL fSkipSecurityCheck,
2809                                  BOOL fSkipRaiseResolveEvent)
2810 {
2811     CONTRACTL
2812     {
2813         INSTANCE_CHECK;
2814         THROWS;
2815         MODE_ANY;
2816         INJECT_FAULT(COMPlusThrowOM(););
2817     }
2818     CONTRACTL_END;
2819
2820     return GetFile()->GetResource( szName,
2821                                    cbResource,
2822                                    pbInMemoryResource,
2823                                    pAssemblyRef,
2824                                    szFileName,
2825                                    dwLocation,
2826                                    pStackMark,
2827                                    fSkipSecurityCheck,
2828                                    fSkipRaiseResolveEvent,
2829                                    this,
2830                                    this->m_pDomain );
2831 }
2832
2833 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2834 BOOL DomainAssembly::GetModuleResource(mdFile mdResFile, LPCSTR szResName,
2835                                        DWORD *cbResource, PBYTE *pbInMemoryResource,
2836                                        LPCSTR *szFileName, DWORD *dwLocation,
2837                                        BOOL fIsPublic, StackCrawlMark *pStackMark,
2838                                        BOOL fSkipSecurityCheck)
2839 {
2840     CONTRACTL
2841     {
2842         INSTANCE_CHECK;
2843         THROWS;
2844         MODE_ANY;
2845         INJECT_FAULT(COMPlusThrowOM(););
2846     }
2847     CONTRACTL_END;
2848
2849     const char     *szName;
2850     DWORD           dwFlags;
2851     DomainFile     *pModule = NULL;
2852     DWORD           dwOffset = 0;
2853
2854     if (! ((TypeFromToken(mdResFile) == mdtFile) &&
2855            GetMDImport()->IsValidToken(mdResFile)) )
2856     {
2857         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_FILE_TOKEN);
2858     }
2859
2860     IfFailThrow(GetMDImport()->GetFileProps(
2861         mdResFile,
2862         &szName,
2863         NULL,
2864         NULL,
2865         &dwFlags));
2866
2867     if (IsFfContainsMetaData(dwFlags))
2868     {
2869         // The resource is embedded in a manifest-containing file.
2870         mdManifestResource mdResource;
2871         mdToken mdLinkRef;
2872         DWORD dwResourceFlags;
2873
2874         Module *pContainerModule = GetCurrentModule();
2875         // Use the real assembly with a rid map if possible
2876         if (pContainerModule != NULL)
2877             pModule = pContainerModule->LoadModule(m_pDomain, mdResFile, FALSE);
2878         else
2879         {
2880             PEModuleHolder pFile(GetAssembly()->LoadModule_AddRef(mdResFile, FALSE));
2881             pModule = m_pDomain->LoadDomainModule(this, pFile, FILE_LOADED);
2882         }
2883
2884         if (FAILED(pModule->GetMDImport()->FindManifestResourceByName(szResName,
2885                                                                       &mdResource)))
2886             return FALSE;
2887
2888         IfFailThrow(pModule->GetMDImport()->GetManifestResourceProps(
2889             mdResource,
2890             NULL, //&szName,
2891             &mdLinkRef,
2892             &dwOffset,
2893             &dwResourceFlags));
2894
2895         if (mdLinkRef != mdFileNil)
2896         {
2897             ThrowHR(COR_E_BADIMAGEFORMAT, BFA_CANT_GET_LINKREF);
2898         }
2899         fIsPublic = IsMrPublic(dwResourceFlags);
2900     }
2901
2902 #ifndef CROSSGEN_COMPILE
2903     if (!fIsPublic && pStackMark && !fSkipSecurityCheck)
2904     {
2905         Assembly *pCallersAssembly = SystemDomain::GetCallersAssembly(pStackMark);
2906         if (pCallersAssembly && // full trust for interop
2907             (!pCallersAssembly->GetManifestFile()->Equals(GetFile())))
2908         {
2909             RefSecContext sCtx(AccessCheckOptions::kMemberAccess);
2910
2911             AccessCheckOptions accessCheckOptions(
2912                 AccessCheckOptions::kMemberAccess,  /*accessCheckType*/
2913                 NULL,                               /*pAccessContext*/
2914                 FALSE,                              /*throwIfTargetIsInaccessible*/
2915                 (MethodTable *) NULL                /*pTargetMT*/
2916                 );
2917
2918             // SL: return TRUE only if the caller is critical
2919             // Desktop: return TRUE only if demanding MemberAccess succeeds
2920             if (!accessCheckOptions.DemandMemberAccessOrFail(&sCtx, NULL, TRUE /*visibilityCheck*/))
2921                 return FALSE;
2922         }
2923     }
2924 #endif // CROSSGEN_COMPILE
2925
2926     if (IsFfContainsMetaData(dwFlags)) {
2927         if (dwLocation) {
2928             *dwLocation = *dwLocation | 1; // ResourceLocation.embedded
2929             *szFileName = szName;
2930             return TRUE;
2931         }
2932
2933         pModule->GetFile()->GetEmbeddedResource(dwOffset, cbResource,
2934                                                 pbInMemoryResource);
2935
2936         return TRUE;
2937     }
2938
2939     // The resource is linked (it's in its own file)
2940     if (szFileName) {
2941         *szFileName = szName;
2942         return TRUE;
2943     }
2944
2945     Module *pContainerModule = GetCurrentModule();
2946
2947     // Use the real assembly with a rid map if possible
2948     if (pContainerModule != NULL)
2949         pModule = pContainerModule->LoadModule(m_pDomain, mdResFile);
2950     else
2951     {
2952         PEModuleHolder pFile(GetAssembly()->LoadModule_AddRef(mdResFile, TRUE));
2953         pModule = m_pDomain->LoadDomainModule(this, pFile, FILE_LOADED);
2954     }
2955
2956     COUNT_T size;
2957     const void *contents = pModule->GetFile()->GetManagedFileContents(&size);
2958
2959     *pbInMemoryResource = (BYTE *) contents;
2960     *cbResource = size;
2961
2962     return TRUE;
2963 }
2964 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
2965
2966 #ifdef FEATURE_PREJIT
2967
2968 // --------------------------------------------------------------------------------
2969 // Remember the timestamp of the CLR DLLs used to compile the ngen image.
2970 // These will be checked at runtime by PEFile::CheckNativeImageTimeStamp().
2971 //
2972
2973 void GetTimeStampsForNativeImage(CORCOMPILE_VERSION_INFO * pNativeVersionInfo)
2974 {
2975     CONTRACTL
2976     {
2977         STANDARD_VM_CHECK;
2978         PRECONDITION(::GetAppDomain()->IsCompilationDomain());
2979     }
2980     CONTRACTL_END;
2981
2982     // Do not store runtime timestamps into NGen image for cross-platform NGen determinism
2983 }
2984
2985 //
2986 // Which processor should ngen target?
2987 // This is needed when ngen wants to target for "reach" if the ngen images will be
2988 // used on other machines (the Operating System or the OEM build lab can do this).
2989 // It can also be used to reduce the testing matrix
2990 //
2991 void GetNGenCpuInfo(CORINFO_CPU * cpuInfo)
2992 {
2993     LIMITED_METHOD_CONTRACT;
2994
2995 #ifdef _TARGET_X86_
2996
2997     static CORINFO_CPU ngenCpuInfo =
2998         {
2999             (CPU_X86_PENTIUM_PRO << 8), // dwCPUType
3000             0x00000000,                 // dwFeatures
3001             0                           // dwExtendedFeatures
3002         };
3003
3004     // We always generate P3-compatible code on CoreCLR
3005     *cpuInfo = ngenCpuInfo;
3006
3007 #else // _TARGET_X86_
3008     cpuInfo->dwCPUType = 0;
3009     cpuInfo->dwFeatures = 0;
3010     cpuInfo->dwExtendedFeatures = 0;
3011 #endif // _TARGET_X86_
3012 }
3013
3014 // --------------------------------------------------------------------------------
3015
3016 void DomainAssembly::GetCurrentVersionInfo(CORCOMPILE_VERSION_INFO *pNativeVersionInfo)
3017 {
3018     CONTRACTL
3019     {
3020         INSTANCE_CHECK;
3021         STANDARD_VM_CHECK;
3022     }
3023     CONTRACTL_END;
3024
3025     // Clear memory so that we won't write random data into the zapped file
3026     ZeroMemory(pNativeVersionInfo, sizeof(CORCOMPILE_VERSION_INFO));
3027
3028     // Pick up any compilation directives for code flavor
3029
3030     BOOL fForceDebug, fForceProfiling, fForceInstrument;
3031     SystemDomain::GetCompilationOverrides(&fForceDebug,
3032                                           &fForceProfiling,
3033                                           &fForceInstrument);
3034
3035     OSVERSIONINFOW osInfo;
3036     osInfo.dwOSVersionInfoSize = sizeof(osInfo);
3037     if (!GetOSVersion(&osInfo))
3038         _ASSERTE(!"GetOSVersion failed");
3039
3040     _ASSERTE(osInfo.dwMajorVersion < 999);
3041     _ASSERTE(osInfo.dwMinorVersion < 999);
3042     pNativeVersionInfo->wOSPlatformID = (WORD) osInfo.dwPlatformId;
3043
3044     // The native images should be OS-version agnostic. Do not store the actual OS version for determinism.
3045     // pNativeVersionInfo->wOSMajorVersion = (WORD) osInfo.dwMajorVersion;
3046     pNativeVersionInfo->wOSMajorVersion = 4;
3047
3048     pNativeVersionInfo->wMachine = IMAGE_FILE_MACHINE_NATIVE_NI;
3049
3050     pNativeVersionInfo->wVersionMajor = VER_MAJORVERSION;
3051     pNativeVersionInfo->wVersionMinor = VER_MINORVERSION;
3052     pNativeVersionInfo->wVersionBuildNumber = VER_PRODUCTBUILD;
3053     pNativeVersionInfo->wVersionPrivateBuildNumber = VER_PRODUCTBUILD_QFE;
3054
3055     GetNGenCpuInfo(&pNativeVersionInfo->cpuInfo);
3056
3057 #if _DEBUG
3058     pNativeVersionInfo->wBuild = CORCOMPILE_BUILD_CHECKED;
3059 #else
3060     pNativeVersionInfo->wBuild = CORCOMPILE_BUILD_FREE;
3061 #endif
3062
3063 #ifdef DEBUGGING_SUPPORTED
3064     if (fForceDebug || !CORDebuggerAllowJITOpts(GetDebuggerInfoBits()))
3065     {
3066         pNativeVersionInfo->wCodegenFlags |= CORCOMPILE_CODEGEN_DEBUGGING;
3067         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_DEBUG;
3068     }
3069     else
3070 #endif // DEBUGGING_SUPPORTED
3071     {
3072         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_DEBUG_NONE;
3073     }
3074
3075 #if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED)
3076     if (fForceProfiling || CORProfilerUseProfileImages())
3077     {
3078         pNativeVersionInfo->wCodegenFlags |= CORCOMPILE_CODEGEN_PROFILING;
3079         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_PROFILING;
3080 #ifdef DEBUGGING_SUPPORTED
3081         // Note that we have hardwired profiling to also imply optimized debugging
3082         // info.  This cuts down on one permutation of prejit files.
3083         pNativeVersionInfo->wCodegenFlags &= ~CORCOMPILE_CODEGEN_DEBUGGING;
3084         pNativeVersionInfo->wConfigFlags &= ~(CORCOMPILE_CONFIG_DEBUG|
3085                                               CORCOMPILE_CONFIG_DEBUG_DEFAULT);
3086         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_DEBUG_NONE;
3087 #endif // DEBUGGING_SUPPORTED
3088     }
3089     else
3090 #endif // PROFILING_SUPPORTED_DATA || PROFILING_SUPPORTED
3091     {
3092         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_PROFILING_NONE;
3093     }
3094
3095 #ifdef DEBUGGING_SUPPORTED
3096
3097     // Note the default assembly flags (from the custom attributes & INI file) , so we can
3098     // set determine whether or not the current settings
3099     // match the "default" setting or not.
3100
3101     // Note that the INI file settings are considered a part of the
3102     // assembly, even though they could theoretically change between
3103     // ngen time and runtime.  It is just too expensive and awkward to
3104     // look up the INI file before binding to the native image at
3105     // runtime, so we effectively snapshot it at ngen time.
3106
3107     DWORD defaultFlags = ComputeDebuggingConfig();
3108
3109     if (CORDebuggerAllowJITOpts(defaultFlags))
3110     {
3111         // Default is optimized code
3112         if ((pNativeVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_DEBUGGING) == 0)
3113             pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_DEBUG_DEFAULT;
3114     }
3115     else
3116     {
3117         // Default is non-optimized debuggable code
3118         if ((pNativeVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_DEBUGGING) != 0)
3119             pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_DEBUG_DEFAULT;
3120     }
3121
3122 #endif // DEBUGGING_SUPPORTED
3123
3124     if (fForceInstrument || GetAssembly()->IsInstrumented())
3125     {
3126         pNativeVersionInfo->wCodegenFlags |= CORCOMPILE_CODEGEN_PROF_INSTRUMENTING;
3127         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_INSTRUMENTATION;
3128     }
3129     else
3130     {
3131         pNativeVersionInfo->wConfigFlags |= CORCOMPILE_CONFIG_INSTRUMENTATION_NONE;
3132     }
3133
3134
3135     GetTimeStampsForNativeImage(pNativeVersionInfo);
3136
3137     // Store signature of source assembly.
3138     GetOptimizedIdentitySignature(&pNativeVersionInfo->sourceAssembly);
3139
3140     // signature will is hash of the whole file. It is written by zapper.
3141     // IfFailThrow(CoCreateGuid(&pNativeVersionInfo->signature));
3142 }
3143
3144 void DomainAssembly::GetOptimizedIdentitySignature(CORCOMPILE_ASSEMBLY_SIGNATURE *pSignature)
3145 {
3146     CONTRACTL
3147     {
3148         INSTANCE_CHECK;
3149         THROWS;
3150         GC_TRIGGERS;
3151         MODE_ANY;
3152         INJECT_FAULT(COMPlusThrowOM(););
3153     }
3154     CONTRACTL_END;
3155
3156     //
3157     // Write the MVID into the version header.
3158     //
3159
3160     //
3161     // If this assembly has skip verification permission, then we store its
3162     // mvid.  If at load time the assembly still has skip verification
3163     // permission, then we can base the matches purely on mvid values and
3164     // skip the perf-heavy hashing of the file.
3165     //
3166
3167     //
3168     // The reason that we tell IsFullyTrusted to do a quick check
3169     // only is because that allows us make a determination for the most
3170     // common full trust scenarios (local machine) without actually
3171     // resolving policy and bringing in a whole list of assembly
3172     // dependencies.
3173     //
3174     ReleaseHolder<IMDInternalImport> scope (GetFile()->GetMDImportWithRef());
3175     IfFailThrow(scope->GetScopeProps(NULL, &pSignature->mvid));
3176
3177     // Use the NGen image if posssible. IL image does not even have to be present on CoreCLR.
3178     if (GetFile()->HasNativeImage())
3179     {
3180         PEImageHolder pNativeImage(GetFile()->GetNativeImageWithRef());
3181
3182         CORCOMPILE_VERSION_INFO* pVersionInfo = pNativeImage->GetLoadedLayout()->GetNativeVersionInfo();
3183         pSignature->timeStamp = pVersionInfo->sourceAssembly.timeStamp;
3184         pSignature->ilImageSize = pVersionInfo->sourceAssembly.ilImageSize;
3185  
3186         return;
3187     }
3188
3189     // Write the time stamp
3190     PEImageLayoutHolder ilLayout(GetFile()->GetAnyILWithRef());
3191     pSignature->timeStamp = ilLayout->GetTimeDateStamp();
3192     pSignature->ilImageSize = ilLayout->GetVirtualSize();
3193 }
3194
3195 BOOL DomainAssembly::CheckZapDependencyIdentities(PEImage *pNativeImage)
3196 {
3197     CONTRACTL
3198     {
3199         INSTANCE_CHECK;
3200         STANDARD_VM_CHECK;
3201     }
3202     CONTRACTL_END;
3203
3204     AssemblySpec spec;
3205     spec.InitializeSpec(this->GetFile());
3206
3207     // The assembly spec should have the binding context associated with it
3208     _ASSERTE(spec.GetBindingContext()  || spec.IsAssemblySpecForMscorlib());
3209     
3210     CORCOMPILE_VERSION_INFO *pVersionInfo = pNativeImage->GetLoadedLayout()->GetNativeVersionInfo();
3211
3212     // Check our own assembly first
3213     GetAppDomain()->CheckForMismatchedNativeImages(&spec, &pVersionInfo->sourceAssembly.mvid);
3214
3215     // Check MVID in metadata against MVID in CORCOMPILE_VERSION_INFO - important when metadata is loaded from IL instead of NI
3216     ReleaseHolder<IMDInternalImport> pImport(this->GetFile()->GetMDImportWithRef());
3217     GUID mvid;
3218     IfFailThrow(pImport->GetScopeProps(NULL, &mvid));
3219     GetAppDomain()->CheckForMismatchedNativeImages(&spec, &mvid);
3220
3221     // Now Check dependencies
3222     COUNT_T cDependencies;
3223     CORCOMPILE_DEPENDENCY *pDependencies = pNativeImage->GetLoadedLayout()->GetNativeDependencies(&cDependencies);
3224     CORCOMPILE_DEPENDENCY *pDependenciesEnd = pDependencies + cDependencies;
3225
3226     while (pDependencies < pDependenciesEnd)
3227     {
3228         if (pDependencies->dwAssemblyDef != mdAssemblyRefNil)
3229         {
3230             AssemblySpec name;
3231             name.InitializeSpec(pDependencies->dwAssemblyDef, pNativeImage->GetNativeMDImport(), this);
3232             
3233 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)            
3234             if (!name.IsAssemblySpecForMscorlib())
3235             {
3236                 // We just initialized the assembly spec for the NI dependency. This will not have binding context
3237                 // associated with it, so set it from that of the parent.
3238                 _ASSERTE(!name.GetBindingContext());
3239                 ICLRPrivBinder *pParentAssemblyBindingContext = name.GetBindingContextFromParentAssembly(name.GetAppDomain());
3240                 _ASSERTE(pParentAssemblyBindingContext);
3241                 name.SetBindingContext(pParentAssemblyBindingContext);
3242             }
3243 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
3244             
3245             GetAppDomain()->CheckForMismatchedNativeImages(&name, &pDependencies->signAssemblyDef.mvid);
3246         }
3247
3248         pDependencies++;
3249     }
3250
3251     return TRUE;
3252 }
3253
3254 BOOL DomainAssembly::CheckZapSecurity(PEImage *pNativeImage)
3255 {
3256     CONTRACTL
3257     {
3258         INSTANCE_CHECK;
3259         STANDARD_VM_CHECK;
3260     }
3261     CONTRACTL_END;
3262
3263     return TRUE;
3264 }
3265 #endif // FEATURE_PREJIT
3266
3267 #ifdef FEATURE_CAS_POLICY
3268 void DomainAssembly::InitializeSecurityManager()
3269 {
3270     CONTRACTL
3271     {
3272         INSTANCE_CHECK;
3273         THROWS;
3274         GC_NOTRIGGER;
3275         MODE_PREEMPTIVE;
3276         INJECT_FAULT(COMPlusThrowOM(););
3277     }
3278     CONTRACTL_END;
3279
3280     GetFile()->InitializeSecurityManager();
3281 }
3282 #endif // FEATURE_CAS_POLICY
3283
3284 #ifdef FEATURE_CAS_POLICY
3285 // Returns security information for the assembly based on the codebase
3286 void DomainAssembly::GetSecurityIdentity(SString &codebase,
3287                                          SecZone *pdwZone,
3288                                          DWORD dwFlags,
3289                                          BYTE *pbUniqueID,
3290                                          DWORD *pcbUniqueID)
3291 {
3292     CONTRACTL
3293     {
3294         INSTANCE_CHECK;
3295         THROWS;
3296         MODE_ANY;
3297         PRECONDITION(CheckPointer(pdwZone));
3298         PRECONDITION(CheckPointer(pbUniqueID));
3299         PRECONDITION(CheckPointer(pcbUniqueID));
3300     }
3301     CONTRACTL_END;
3302
3303     GetFile()->GetSecurityIdentity(codebase, pdwZone, dwFlags, pbUniqueID, pcbUniqueID);
3304 }
3305 #endif // FEATURE_CAS_POLICY
3306
3307 #ifdef FEATURE_FUSION
3308 IAssemblyBindingClosure* DomainAssembly::GetAssemblyBindingClosure(WALK_LEVEL level)
3309 {
3310     CONTRACT(IAssemblyBindingClosure *)
3311     {
3312         INSTANCE_CHECK;
3313         POSTCONDITION(CheckPointer(RETVAL,NULL_OK));
3314         //we could  return NULL instead of asserting but hitting code paths that call this for mscorlib is just wasting of cycles anyhow
3315         PRECONDITION(!IsSystem());
3316         THROWS;
3317         GC_TRIGGERS;
3318         MODE_ANY;
3319         INJECT_FAULT(COMPlusThrowOM(););
3320     }
3321     CONTRACT_END;
3322
3323     if (m_pAssemblyBindingClosure == NULL || m_pAssemblyBindingClosure->HasBeenWalked(level) == S_FALSE)
3324     {
3325         SafeComHolder<IAssemblyBindingClosure> pClosure;
3326         if (this->GetAppDomain()->GetFusionContext() == NULL)
3327         {
3328             _ASSERTE(IsSystem());
3329             RETURN NULL;
3330         }
3331         
3332         GCX_PREEMP();
3333
3334         ReleaseHolder<IBindResult> pWinRTBindResult;
3335         IUnknown * pUnk;
3336         
3337         if (GetFile()->IsIStream())
3338         {
3339             pUnk = GetFile()->GetIHostAssembly();
3340         }
3341         else if (GetFile()->IsWindowsRuntime())
3342         {   // It is .winmd file (WinRT assembly)
3343             IfFailThrow(CLRPrivAssemblyWinRT::GetIBindResult(GetFile()->GetHostAssembly(), &pWinRTBindResult));
3344             pUnk = pWinRTBindResult;
3345         }
3346         else
3347         {
3348             pUnk = GetFile()->GetFusionAssembly();
3349         }
3350
3351         if (m_pAssemblyBindingClosure == NULL)
3352         {
3353             IfFailThrow(this->GetAppDomain()->GetFusionContext()->GetAssemblyBindingClosure(pUnk, NULL, &pClosure));
3354             if (FastInterlockCompareExchangePointer<IAssemblyBindingClosure*>(&m_pAssemblyBindingClosure, pClosure.GetValue(), NULL) == NULL)
3355             {
3356                 pClosure.SuppressRelease();
3357             }
3358         }
3359         IfFailThrow(m_pAssemblyBindingClosure->EnsureWalked(pUnk, this->GetAppDomain()->GetFusionContext(), level));
3360     }
3361     RETURN m_pAssemblyBindingClosure;
3362 }
3363
3364 // This is used to determine if the binding closure of the assembly in question is in the GAC. Amongst other uses,
3365 // this is the MULTI_DOMAIN_HOST scenario.
3366 BOOL DomainAssembly::IsClosedInGAC()
3367 {
3368     CONTRACTL
3369     {
3370         INSTANCE_CHECK;
3371         THROWS;
3372         GC_TRIGGERS;
3373         MODE_ANY;
3374         INJECT_FAULT(COMPlusThrowOM(););
3375     }
3376     CONTRACTL_END;
3377
3378     if (IsSystem())
3379         return TRUE;
3380
3381     BOOL fIsWindowsRuntime = GetFile()->IsWindowsRuntime();
3382
3383     if (!GetFile()->IsSourceGAC() && !fIsWindowsRuntime)
3384         return FALSE;
3385
3386     // Do a binding closure that will help us determine if all the dependencies are in the GAC or not.
3387     IAssemblyBindingClosure * pClosure = GetAssemblyBindingClosure(LEVEL_GACCHECK);
3388     if (pClosure == NULL)
3389         return FALSE;
3390     
3391     // Once the closure is complete, determine if the dependencies are closed in the GAC (or not).
3392     HRESULT hr = pClosure->IsAllAssembliesInGAC();
3393     IfFailThrow(hr);
3394     
3395     return (hr == S_OK);
3396 }
3397
3398 BOOL DomainAssembly::MayHaveUnknownDependencies()
3399 {
3400     CONTRACTL
3401     {
3402         INSTANCE_CHECK;
3403         THROWS;
3404         GC_TRIGGERS;
3405         MODE_ANY;
3406         INJECT_FAULT(COMPlusThrowOM(););
3407     }
3408     CONTRACTL_END;
3409
3410     if (IsSystem())
3411         return FALSE;
3412     
3413     // Perform the binding closure walk to initialize state that will help us
3414     // determine if we have dependencies that could prevent code-sharing.
3415     IAssemblyBindingClosure * pClosure = GetAssemblyBindingClosure(LEVEL_WINRTCHECK);
3416     if (pClosure == NULL)
3417         return FALSE;
3418     
3419     HRESULT hr = pClosure->MayHaveUnknownDependencies();
3420     IfFailThrow(hr);
3421
3422     return (hr == S_OK);
3423 }
3424
3425 #endif // FEATURE_FUSION
3426
3427
3428 // <TODO>@todo Find a better place for these</TODO>
3429 #define DE_CUSTOM_VALUE_NAMESPACE        "System.Diagnostics"
3430 #define DE_DEBUGGABLE_ATTRIBUTE_NAME     "DebuggableAttribute"
3431
3432 // <TODO>@todo .INI file is a temporary workaround for Beta 1</TODO>
3433 #define DE_INI_FILE_SECTION_NAME          W(".NET Framework Debugging Control")
3434 #define DE_INI_FILE_KEY_TRACK_INFO        W("GenerateTrackingInfo")
3435 #define DE_INI_FILE_KEY_ALLOW_JIT_OPTS    W("AllowOptimize")
3436
3437 DWORD DomainAssembly::ComputeDebuggingConfig()
3438 {
3439     CONTRACTL
3440     {
3441         INSTANCE_CHECK;
3442         THROWS;
3443         WRAPPER(GC_TRIGGERS);
3444         MODE_ANY;
3445         INJECT_FAULT(COMPlusThrowOM(););
3446     }
3447     CONTRACTL_END;
3448
3449 #ifdef DEBUGGING_SUPPORTED
3450     DWORD dacfFlags = DACF_ALLOW_JIT_OPTS;
3451
3452     if (GetDebuggingOverrides(&dacfFlags))
3453     {
3454         dacfFlags |= DACF_USER_OVERRIDE;
3455     }
3456     else
3457     {
3458         IfFailThrow(GetDebuggingCustomAttributes(&dacfFlags));
3459     }
3460
3461     return dacfFlags;
3462 #else // !DEBUGGING_SUPPORTED
3463     return 0;
3464 #endif // DEBUGGING_SUPPORTED
3465 }
3466
3467 void DomainAssembly::SetupDebuggingConfig(void)
3468 {
3469     CONTRACTL
3470     {
3471         INSTANCE_CHECK;
3472         THROWS;
3473         WRAPPER(GC_TRIGGERS);
3474         MODE_ANY;
3475         INJECT_FAULT(COMPlusThrowOM(););
3476     }
3477     CONTRACTL_END;
3478
3479 #ifdef DEBUGGING_SUPPORTED
3480     DWORD dacfFlags = ComputeDebuggingConfig();
3481
3482     SetDebuggerInfoBits((DebuggerAssemblyControlFlags)dacfFlags);
3483
3484     LOG((LF_CORDB, LL_INFO10, "Assembly %S: bits=0x%x\n", GetDebugName(), GetDebuggerInfoBits()));
3485 #endif // DEBUGGING_SUPPORTED
3486 }
3487
3488 // The format for the (temporary) .INI file is:
3489
3490 // [.NET Framework Debugging Control]
3491 // GenerateTrackingInfo=<n> where n is 0 or 1
3492 // AllowOptimize=<n> where n is 0 or 1
3493
3494 // Where neither x nor y equal INVALID_INI_INT:
3495 #define INVALID_INI_INT (0xFFFF)
3496
3497 bool DomainAssembly::GetDebuggingOverrides(DWORD *pdwFlags)
3498 {
3499     CONTRACTL
3500     {
3501         INSTANCE_CHECK;
3502         THROWS;
3503         GC_NOTRIGGER;
3504         MODE_ANY;
3505         INJECT_FAULT(COMPlusThrowOM(););
3506     }
3507     CONTRACTL_END;
3508
3509     return false;
3510 }
3511
3512
3513 // For right now, we only check to see if the DebuggableAttribute is present - later may add fields/properties to the
3514 // attributes.
3515 HRESULT DomainAssembly::GetDebuggingCustomAttributes(DWORD *pdwFlags)
3516 {
3517     CONTRACTL
3518     {
3519         INSTANCE_CHECK;
3520         NOTHROW;
3521         WRAPPER(GC_TRIGGERS);
3522         MODE_ANY;
3523         FORBID_FAULT;
3524         PRECONDITION(CheckPointer(pdwFlags));
3525     }
3526     CONTRACTL_END;
3527
3528     HRESULT hr = S_OK;
3529
3530 #ifdef FEATURE_PREJIT
3531     ReleaseHolder<PEImage> pNativeImage=GetFile()->GetNativeImageWithRef();
3532     if (pNativeImage)
3533     {
3534         CORCOMPILE_VERSION_INFO * pVersion = pNativeImage->GetLoadedLayout()->GetNativeVersionInfo();
3535         PREFIX_ASSUME(pVersion != NULL);
3536
3537         WORD codegen = pVersion->wCodegenFlags;
3538
3539         if (codegen & CORCOMPILE_CODEGEN_DEBUGGING)
3540         {
3541             *pdwFlags &= (~DACF_ALLOW_JIT_OPTS);
3542         }
3543         else
3544         {
3545             *pdwFlags |= DACF_ALLOW_JIT_OPTS;
3546         }
3547
3548     }
3549     else
3550 #endif // FEATURE_PREJIT
3551     {
3552         ULONG size;
3553         BYTE *blob;
3554         mdModule mdMod;
3555         ReleaseHolder<IMDInternalImport> mdImport(GetFile()->GetMDImportWithRef());
3556         mdMod = mdImport->GetModuleFromScope();
3557         mdAssembly asTK = TokenFromRid(mdtAssembly, 1);
3558
3559         hr = mdImport->GetCustomAttributeByName(asTK,
3560                                                 DE_CUSTOM_VALUE_NAMESPACE
3561                                                 NAMESPACE_SEPARATOR_STR
3562                                                 DE_DEBUGGABLE_ATTRIBUTE_NAME,
3563                                                 (const void**)&blob,
3564                                                 &size);
3565
3566         // If there is no custom value, then there is no entrypoint defined.
3567         if (!(FAILED(hr) || hr == S_FALSE))
3568         {
3569             // We're expecting a 6 or 8 byte blob:
3570             //
3571             // 1, 0, enable tracking, disable opts, 0, 0
3572             if ((size == 6) || (size == 8))
3573             {
3574                 if (!((blob[0] == 1) && (blob[1] == 0)))
3575                 {
3576                     BAD_FORMAT_NOTHROW_ASSERT(!"Invalid blob format for custom attribute");
3577                     return COR_E_BADIMAGEFORMAT;
3578                 }
3579
3580                 if (blob[2] & 0x1)
3581                 {
3582                     *pdwFlags |= DACF_OBSOLETE_TRACK_JIT_INFO;
3583                 }
3584                 else
3585                 {
3586                     *pdwFlags &= (~DACF_OBSOLETE_TRACK_JIT_INFO);
3587                 }
3588
3589                 if (blob[2] & 0x2)
3590                 {
3591                     *pdwFlags |= DACF_IGNORE_PDBS;
3592                 }
3593                 else
3594                 {
3595                     *pdwFlags &= (~DACF_IGNORE_PDBS);
3596                 }
3597
3598
3599                 // For compatibility, we enable optimizations if the tracking byte is zero,
3600                 // even if disable opts is nonzero
3601                 if (((blob[2] & 0x1) == 0) || (blob[3] == 0))
3602                 {
3603                     *pdwFlags |= DACF_ALLOW_JIT_OPTS;
3604                 }
3605                 else
3606                 {
3607                     *pdwFlags &= (~DACF_ALLOW_JIT_OPTS);
3608                 }
3609
3610                 LOG((LF_CORDB, LL_INFO10, "Assembly %S: has %s=%d,%d bits = 0x%x\n", GetDebugName(),
3611                      DE_DEBUGGABLE_ATTRIBUTE_NAME,
3612                      blob[2], blob[3], *pdwFlags));
3613             }
3614         }
3615     }
3616
3617     return hr;
3618 }
3619
3620 BOOL DomainAssembly::NotifyDebuggerLoad(int flags, BOOL attaching)
3621 {
3622     WRAPPER_NO_CONTRACT;
3623
3624     BOOL result = FALSE;
3625
3626     if (!IsVisibleToDebugger())
3627         return FALSE;
3628
3629     // Debugger Attach is done totally out-of-process. Does not call code in-proc.
3630     _ASSERTE(!attaching);
3631
3632     // Make sure the debugger has been initialized.  See code:Debugger::Startup.
3633     if (g_pDebugInterface == NULL)
3634     {
3635         _ASSERTE(!CORDebuggerAttached());
3636         return FALSE;
3637     }
3638
3639     // There is still work we need to do even when no debugger is attached.
3640
3641     if (flags & ATTACH_ASSEMBLY_LOAD)
3642     {
3643         if (ShouldNotifyDebugger())
3644         {
3645             g_pDebugInterface->LoadAssembly(this);
3646         }
3647         result = TRUE;
3648     }
3649
3650     DomainModuleIterator i = IterateModules(kModIterIncludeLoading);
3651     while (i.Next())
3652     {
3653         DomainFile * pDomainFile = i.GetDomainFile();
3654         if(pDomainFile->ShouldNotifyDebugger())
3655         {
3656             result = result ||
3657                 pDomainFile->GetModule()->NotifyDebuggerLoad(this->GetAppDomain(), pDomainFile, flags, attaching);
3658         }
3659     }
3660     if( ShouldNotifyDebugger())
3661     {
3662            result|=m_pModule->NotifyDebuggerLoad(m_pDomain, this, ATTACH_MODULE_LOAD, attaching);
3663            SetDebuggerNotified();
3664     }
3665
3666
3667
3668     return result;
3669 }
3670
3671 void DomainAssembly::NotifyDebuggerUnload()
3672 {
3673     LIMITED_METHOD_CONTRACT;
3674
3675     if (!IsVisibleToDebugger())
3676         return;
3677
3678     if (!this->GetAppDomain()->IsDebuggerAttached())
3679         return;
3680
3681     m_fDebuggerUnloadStarted = TRUE;
3682
3683     // Dispatch module unloads for all modules. Debugger is resilient in case we haven't dispatched
3684     // a previous load event (such as if debugger attached after the modules was loaded).
3685     DomainModuleIterator i = IterateModules(kModIterIncludeLoading);
3686     while (i.Next())
3687     {
3688             i.GetDomainFile()->GetModule()->NotifyDebuggerUnload(this->GetAppDomain());
3689     }
3690
3691     g_pDebugInterface->UnloadAssembly(this);
3692
3693 }
3694
3695 // This will enumerate for static GC refs (but not thread static GC refs)
3696
3697 void DomainAssembly::EnumStaticGCRefs(promote_func* fn, ScanContext* sc)
3698 {
3699     CONTRACT_VOID
3700     {
3701         NOTHROW;
3702         GC_NOTRIGGER;
3703     }
3704     CONTRACT_END;
3705
3706     _ASSERTE(GCHeapUtilities::IsGCInProgress() &&
3707          GCHeapUtilities::IsServerHeap()   &&
3708          IsGCSpecialThread());
3709
3710     DomainModuleIterator i = IterateModules(kModIterIncludeLoaded);
3711     while (i.Next())
3712     {
3713         DomainFile* pDomainFile = i.GetDomainFile();
3714
3715         if (pDomainFile->IsActive())
3716         {
3717             // We guarantee that at this point the module has it's DomainLocalModule set up
3718             // , as we create it while we load the module
3719             _ASSERTE(pDomainFile->GetLoadedModule()->GetDomainLocalModule(this->GetAppDomain()));
3720             pDomainFile->GetLoadedModule()->EnumRegularStaticGCRefs(this->GetAppDomain(), fn, sc);
3721
3722             // We current to do not iterate over the ThreadLocalModules that correspond
3723             // to this Module. The GC discovers thread statics through the handle table.
3724         }
3725     }
3726
3727     RETURN;
3728 }
3729
3730
3731
3732 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
3733 //--------------------------------------------------------------------------------
3734 // DomainModule
3735 //--------------------------------------------------------------------------------
3736
3737 DomainModule::DomainModule(AppDomain *pDomain, DomainAssembly *pAssembly, PEFile *pFile)
3738   : DomainFile(pDomain, pFile),
3739     m_pDomainAssembly(pAssembly)
3740 {
3741     STANDARD_VM_CONTRACT;
3742 }
3743
3744 DomainModule::~DomainModule()
3745 {
3746     WRAPPER_NO_CONTRACT;
3747 }
3748
3749 void DomainModule::SetModule(Module* pModule)
3750 {
3751     STANDARD_VM_CONTRACT;
3752
3753     UpdatePEFile(pModule->GetFile());
3754     pModule->SetDomainFile(this);
3755     // SetDomainFile can throw and will unwind to DomainModule::Allocate at which
3756     // point pModule->Destruct will be called in the catch handler.  if we set
3757     // m_pModule = pModule before the call to SetDomainFile then we can end up with
3758     // a bad m_pModule pointer when SetDomainFile throws.  so we set m_pModule IIF
3759     // the call to SetDomainFile succeeds.
3760     m_pModule = pModule;
3761 }
3762
3763 void DomainModule::Begin()
3764 {
3765     STANDARD_VM_CONTRACT;
3766     m_pDomainAssembly->AddModule(this);
3767 }
3768
3769 #ifdef FEATURE_PREJIT
3770
3771 void DomainModule::FindNativeImage()
3772 {
3773     LIMITED_METHOD_CONTRACT;
3774
3775     // Resource files are never prejitted.
3776 }
3777
3778 #endif // FEATURE_PREJIT
3779
3780
3781 void DomainModule::Allocate()
3782 {
3783     CONTRACTL
3784     {
3785         INSTANCE_CHECK;
3786         STANDARD_VM_CHECK;
3787     }
3788     CONTRACTL_END;
3789
3790     // We can now rely on the fact that our MDImport will not change so we can stop refcounting it.
3791     GetFile()->MakeMDImportPersistent();
3792
3793     AllocMemTracker amTracker;
3794     AllocMemTracker *pamTracker = &amTracker;
3795
3796     Assembly *pAssembly = m_pDomainAssembly->GetCurrentAssembly();
3797     Module *pModule = NULL;
3798
3799     if (pAssembly->IsDomainNeutral())
3800     {
3801         // For shared assemblies, the module may be already in the assembly list, even
3802         // though we haven't loaded it here yet.
3803
3804         pModule = pAssembly->GetManifestModule()->GetModuleIfLoaded(GetToken(),FALSE, TRUE);
3805         if (pModule != NULL)
3806         {
3807             SetModule(pModule);
3808             return;
3809         }
3810         else
3811         {
3812 #ifdef FEATURE_LOADER_OPTIMIZATION
3813             SharedDomain *pSharedDomain = SharedDomain::GetDomain();
3814             SharedFileLockHolder pFileLock(pSharedDomain, GetFile());
3815 #else // FEATURE_LOADER_OPTIMIZATION
3816             _ASSERTE(IsSystem());
3817 #endif // FEATURE_LOADER_OPTIMIZATION
3818
3819             pModule = pAssembly->GetManifestModule()->GetModuleIfLoaded(GetToken(), FALSE, TRUE);
3820             if (pModule != NULL)
3821             {
3822                 SetModule(pModule);
3823                 return;
3824             }
3825             else
3826             {
3827                 pModule = Module::Create(pAssembly, GetToken(), m_pFile, pamTracker);
3828
3829                 EX_TRY
3830                 {
3831                     pAssembly->PrepareModuleForAssembly(pModule, pamTracker);
3832                     SetModule(pModule); //@todo: This innocent-looking call looks like a mixture of allocations and publishing code - it probably needs to be split.
3833                 }
3834                 EX_HOOK
3835                 {
3836                     //! It's critical we destruct the manifest Module prior to the AllocMemTracker used to initialize it.
3837                     //! Otherwise, we will leave dangling pointers inside the Module that Module::Destruct will attempt
3838                     //! to dereference.
3839                     pModule->Destruct();
3840                 }
3841                 EX_END_HOOK
3842
3843                 {
3844                     CANNOTTHROWCOMPLUSEXCEPTION();
3845                     FAULT_FORBID();
3846
3847                     //Cannot fail after this point.
3848                     pamTracker->SuppressRelease();
3849                     pModule->SetIsTenured();
3850
3851                     pAssembly->PublishModuleIntoAssembly(pModule);
3852
3853
3854
3855                     return;  // Explicit return to let you know you are NOT welcome to add code after the CANNOTTHROW/FAULT_FORBID expires
3856                 }
3857
3858
3859
3860             }
3861         }
3862
3863     }
3864     else
3865     {
3866         pModule = Module::Create(pAssembly, GetToken(), m_pFile, pamTracker);
3867         EX_TRY
3868         {
3869             pAssembly->PrepareModuleForAssembly(pModule, pamTracker);
3870             SetModule(pModule); //@todo: This innocent-looking call looks like a mixture of allocations and publishing code - it probably needs to be split.
3871         }
3872         EX_HOOK
3873         {
3874             //! It's critical we destruct the manifest Module prior to the AllocMemTracker used to initialize it.
3875             //! Otherwise, we will leave dangling pointers inside the Module that Module::Destruct will attempt
3876             //! to dereference.
3877             pModule->Destruct();
3878         }
3879         EX_END_HOOK
3880
3881
3882         {
3883             CANNOTTHROWCOMPLUSEXCEPTION();
3884             FAULT_FORBID();
3885
3886             //Cannot fail after this point.
3887             pamTracker->SuppressRelease();
3888             pModule->SetIsTenured();
3889             pAssembly->PublishModuleIntoAssembly(pModule);
3890
3891
3892             return;  // Explicit return to let you know you are NOT welcome to add code after the CANNOTTHROW/FAULT_FORBID expires
3893         }
3894
3895     }
3896
3897
3898 }
3899
3900
3901
3902 void DomainModule::DeliverAsyncEvents()
3903 {
3904     LIMITED_METHOD_CONTRACT;
3905     return;
3906 }
3907
3908 void DomainModule::DeliverSyncEvents()
3909 {
3910     CONTRACTL
3911     {
3912         INSTANCE_CHECK;
3913         THROWS;
3914         GC_TRIGGERS;
3915         MODE_ANY;
3916         INJECT_FAULT(COMPlusThrowOM(););
3917         SO_INTOLERANT;
3918     }
3919     CONTRACTL_END;
3920
3921     GetCurrentModule()->NotifyEtwLoadFinished(S_OK);
3922
3923 #ifdef PROFILING_SUPPORTED
3924     if (!IsProfilerNotified())
3925     {
3926         SetProfilerNotified();
3927         GetCurrentModule()->NotifyProfilerLoadFinished(S_OK);
3928     }
3929 #endif
3930
3931 #ifdef DEBUGGING_SUPPORTED
3932     GCX_COOP();
3933     if(!IsDebuggerNotified())
3934     {
3935         SetShouldNotifyDebugger();
3936         {
3937             // Always give the module a chance to notify the debugger. If no debugger is attached, the
3938             // module can skip out on the notification.
3939             m_pModule->NotifyDebuggerLoad(m_pDomain, this, ATTACH_MODULE_LOAD, FALSE);
3940             SetDebuggerNotified();
3941         }
3942     }
3943 #endif
3944 }
3945 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
3946
3947 #endif // #ifndef DACCESS_COMPILE
3948
3949 #ifdef DACCESS_COMPILE
3950
3951 void
3952 DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
3953 {
3954     SUPPORTS_DAC;
3955
3956     //sizeof(DomainFile) == 0x60
3957     DAC_ENUM_VTHIS();
3958
3959     // Modules are needed for all minidumps, but they are enumerated elsewhere
3960     // so we don't need to duplicate effort; thus we do noting with m_pModule.
3961
3962     // For MiniDumpNormal, we only want the file name.
3963     if (m_pFile.IsValid())
3964     {
3965         m_pFile->EnumMemoryRegions(flags);
3966     }
3967
3968     if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE
3969     && m_pDomain.IsValid())
3970     {
3971         m_pDomain->EnumMemoryRegions(flags, true);
3972     }
3973 }
3974
3975 void
3976 DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
3977 {
3978     SUPPORTS_DAC;
3979
3980     //sizeof(DomainAssembly) == 0xe0
3981     DAC_ENUM_VTHIS();
3982     DomainFile::EnumMemoryRegions(flags);
3983
3984     // For minidumps without full memory, we need to always be able to iterate over m_Modules.
3985     m_Modules.EnumMemoryRegions(flags);
3986
3987     if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE)
3988     {
3989         if (m_pAssembly.IsValid())
3990         {
3991             m_pAssembly->EnumMemoryRegions(flags);
3992         }
3993     }
3994 }
3995
3996 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
3997 void
3998 DomainModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
3999 {
4000     SUPPORTS_DAC;
4001     DomainFile::EnumMemoryRegions(flags);
4002     if (m_pDomainAssembly.IsValid())
4003     {
4004         m_pDomainAssembly->EnumMemoryRegions(flags);
4005     }
4006 }
4007 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
4008
4009 #endif // #ifdef DACCESS_COMPILE
4010
4011 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
4012 LPVOID DomainFile::GetUMThunk(LPVOID pManagedIp, PCCOR_SIGNATURE pSig, ULONG cSig)
4013 {
4014     CONTRACT (LPVOID)
4015     {
4016         INSTANCE_CHECK;
4017         THROWS;
4018         GC_TRIGGERS;
4019         MODE_ANY;
4020         INJECT_FAULT(COMPlusThrowOM());
4021         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4022     }
4023     CONTRACT_END
4024
4025
4026     if (m_pUMThunkHash == NULL)
4027     {
4028         UMThunkHash *pUMThunkHash = new UMThunkHash(GetModule(), this->GetAppDomain());
4029         if (FastInterlockCompareExchangePointer(&m_pUMThunkHash, pUMThunkHash, NULL) != NULL)
4030         {
4031             delete pUMThunkHash;
4032         }
4033     }
4034     RETURN m_pUMThunkHash->GetUMThunk(pManagedIp, pSig, cSig);
4035 }
4036 #endif // FEATURE_MIXEDMODE && !CROSSGEN_COMPILE