1fd898684cf1c104b536141491083c0c13aef35c
[platform/upstream/dotnet/runtime.git] / src / coreclr / vm / ceemain.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 // ===========================================================================
4 // File: CEEMAIN.CPP
5 // ===========================================================================
6 //
7
8 //
9 //
10 // The CLR code base uses a hyperlink feature of the HyperAddin plugin for Visual Studio. If you don't see
11 // 'HyperAddin' in your Visual Studio menu bar you don't have this support. To get it type
12 //
13 //     \\clrmain\tools\installCLRAddins
14 //
15 //  After installing HyperAddin, your first run of VS should be as an administrator so HyperAddin can update
16 //  some registry information.
17 //
18 //  At this point the code: prefixes become hyperlinks in Visual Studio and life is good. See
19 //  http://mswikis/clr/dev/Pages/CLR%20Team%20Commenting.aspx for more information
20 //
21 //  There is a bug associated with Visual Studio where it does not recognise the hyperlink if there is a ::
22 //  preceding it on the same line. Since C++ uses :: as a namespace separator, this can often mean that the
23 //  second hyperlink on a line does not work. To work around this it is better to use '.' instead of :: as
24 //  the namespace separators in code: hyperlinks.
25 //
26 // #StartHere
27 // #TableOfContents The .NET Runtime Table of contents
28 //
29 // This comment is mean to be a nexus that allows you to jump quickly to various interesting parts of the
30 // runtime.
31 //
32 // You can refer to product studio bugs using urls like the following
33 //     * http://bugcheck/bugs/DevDivBugs/2320.asp
34 //     * http://bugcheck/bugs/VSWhidbey/601210.asp
35 //
36 //  Dev10 Bugs can be added with URLs like the following (for Dev10 bug 671409)
37 //     * http://tkbgitvstfat01:8090/wi.aspx?id=671409
38 //
39 //*************************************************************************************************
40 //
41 // * Introduction to the runtime file:../../Documentation/botr/botr-faq.md
42 //
43 // #MajorDataStructures. The major data structures associated with the runtime are
44 //     * code:Thread (see file:threads.h#ThreadClass) - the additional thread state the runtime needs.
45 //     * code:AppDomain - The managed version of a process
46 //     * code:Assembly - The unit of deployment and versioning (may be several DLLs but often is only one).
47 //     * code:Module - represents a Module (DLL or EXE).
48 //     * code:MethodTable - represents the 'hot' part of a type (needed during normal execution)
49 //     * code:EEClass - represents the 'cold' part of a type (used during compilation, interop, ...)
50 //     * code:MethodDesc - represents a Method
51 //     * code:FieldDesc - represents a Field.
52 //     * code:Object - represents a object on the GC heap allocated with code:Alloc
53 //
54 // * ECMA specifications
55 //     * Partition I Concepts
56 //         http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20I%20Architecture.doc
57 //     * Partition II Meta Data
58 //         http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20II%20Metadata.doc
59 //     * Partition III IL
60 //         http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20III%20CIL.doc
61 //
62 //  * Serge Liden (worked on the CLR and owned ILASM / ILDASM for a long time wrote a good book on IL
63 //     * Expert .NET 2.0 IL Assembler  http://www.amazon.com/Expert-NET-2-0-IL-Assembler/dp/1590596463
64 //
65 // * This is also a pretty nice overview of what the CLR is at
66 //     http://msdn2.microsoft.com/en-us/netframework/aa497266.aspx
67 //
68 // * code:EEStartup - This routine must be called before any interesting runtime services are used. It is
69 //     invoked as part of mscorwks's DllMain logic.
70 // * code:#EEShutDown - Code called before we shut down the EE.
71 //
72 // * file:..\inc\corhdr.h#ManagedHeader - From a data structure point of view, this is the entry point into
73 //     the runtime. This is how all other data in the EXE are found.
74 //
75 // * code:ICorJitCompiler#EEToJitInterface - This is the interface from the EE to the Just in time (JIT)
76 //     compiler. The interface to the JIT is relatively simple (compileMethod), however the EE provides a
77 //     rich set of callbacks so the JIT can get all the information it needs. See also
78 //     file:../../Documentation/botr/ryujit-overview.md for general information on the JIT.
79 //
80 // * code:VirtualCallStubManager - This is the main class that implements interface dispatch
81 //
82 // * Precode - Every method needs entry point for other code to call even if that native code does not
83 //     actually exist yet. To support this methods can have code:Precode that is an entry point that exists
84 //     and will call the JIT compiler if the code does not yet exist.
85 //
86 //  * NGEN - NGen stands for Native code GENeration and it is the runtime way of precompiling IL and IL
87 //      Meta-data into native code and runtime data structures. At compilation time the most
88 //      fundamental data structures is the code:ZapNode which represents something that needs to go into the
89 //      NGEN image.
90 //
91 //   * What is cooperative / preemtive mode ? file:threads.h#CooperativeMode and
92 //       file:threads.h#SuspendingTheRuntime and file:../../Documentation/botr/threading.md
93 //   * Garbage collection - file:gc.cpp#Overview and file:../../Documentation/botr/garbage-collection.md
94 //   * code:AppDomain - The managed version of a process.
95 //   * Calling Into the runtime (FCALLs QCalls) file:../../Documentation/botr/corelib.md
96 //   * Exceptions - file:../../Documentation/botr/exceptions.md. The most important routine to start
97 //       with is code:COMPlusFrameHandler which is the routine that we hook up to get called when an unmanaged
98 //       exception happens.
99 //   * Assembly Loading file:../../Documentation/botr/type-loader.md
100 //   * Profiling file:../../Documentation/botr/profiling.md and file:../../Documentation/botr/profilability.md
101 //   * FCALLS QCALLS (calling into the runtime from managed code)
102 //       file:../../Documentation/botr/corelib.md
103 //   * Event Tracing for Windows
104 //     * file:../inc/eventtrace.h#EventTracing -
105 //     * This is the main file dealing with event tracing in CLR
106 //     * The implementation of this class is available in file:eventtrace.cpp
107 //     * file:../inc/eventtrace.h#CEtwTracer - This is the main class dealing with event tracing in CLR.
108 //         Follow the link for more information on how this feature has been implemented
109 //     * http://mswikis/clr/dev/Pages/CLR%20ETW%20Events%20Wiki.aspx - Follow the link for more information on how to
110 //         use this instrumentation feature.
111
112 // ----------------------------------------------------------------------------------------------------
113 // Features in the runtime that have been given hyperlinks
114 //
115 // * code:Nullable#NullableFeature - the Nullable<T> type has special runtime semantics associated with
116 //     boxing this describes this feature.
117
118 #include "common.h"
119
120 #include "vars.hpp"
121 #include "log.h"
122 #include "ceemain.h"
123 #include "clsload.hpp"
124 #include "object.h"
125 #include "hash.h"
126 #include "ecall.h"
127 #include "ceemain.h"
128 #include "dllimport.h"
129 #include "syncblk.h"
130 #include "eeconfig.h"
131 #include "stublink.h"
132 #include "method.hpp"
133 #include "codeman.h"
134 #include "frames.h"
135 #include "threads.h"
136 #include "stackwalk.h"
137 #include "gcheaputilities.h"
138 #include "interoputil.h"
139 #include "fieldmarshaler.h"
140 #include "dbginterface.h"
141 #include "eedbginterfaceimpl.h"
142 #include "debugdebugger.h"
143 #include "cordbpriv.h"
144 #include "comdelegate.h"
145 #include "appdomain.hpp"
146 #include "eventtrace.h"
147 #include "corhost.h"
148 #include "binder.h"
149 #include "olevariant.h"
150 #include "comcallablewrapper.h"
151 #include "../dlls/mscorrc/resource.h"
152 #include "util.hpp"
153 #include "shimload.h"
154 #include "comthreadpool.h"
155 #include "posterror.h"
156 #include "virtualcallstub.h"
157 #include "strongnameinternal.h"
158 #include "syncclean.hpp"
159 #include "debuginfostore.h"
160 #include "finalizerthread.h"
161 #include "threadsuspend.h"
162 #include "disassembler.h"
163 #include "jithost.h"
164 #include "pgo.h"
165
166 #ifndef TARGET_UNIX
167 #include "dwreport.h"
168 #endif // !TARGET_UNIX
169
170 #include "stringarraylist.h"
171 #include "stubhelpers.h"
172
173 #ifdef FEATURE_COMINTEROP
174 #include "runtimecallablewrapper.h"
175 #include "mngstdinterfaces.h"
176 #include "interoplibinterface.h"
177 #endif // FEATURE_COMINTEROP
178
179 #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
180 #include "olecontexthelpers.h"
181 #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
182
183 #ifdef PROFILING_SUPPORTED
184 #include "proftoeeinterfaceimpl.h"
185 #include "profilinghelper.h"
186 #endif // PROFILING_SUPPORTED
187
188 #ifdef FEATURE_INTERPRETER
189 #include "interpreter.h"
190 #endif // FEATURE_INTERPRETER
191
192 #ifdef FEATURE_PERFMAP
193 #include "perfmap.h"
194 #endif
195
196 #include "diagnosticserveradapter.h"
197 #include "eventpipeadapter.h"
198
199 #ifndef TARGET_UNIX
200 // Included for referencing __security_cookie
201 #include "process.h"
202 #endif // !TARGET_UNIX
203
204 #ifdef FEATURE_GDBJIT
205 #include "gdbjit.h"
206 #endif // FEATURE_GDBJIT
207
208 #include "genanalysis.h"
209
210 static int GetThreadUICultureId(_Out_ LocaleIDValue* pLocale);  // TODO: This shouldn't use the LCID.  We should rely on name instead
211
212 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames);
213
214 HRESULT EEStartup();
215
216
217 static void InitializeGarbageCollector();
218
219 #ifdef DEBUGGING_SUPPORTED
220 static void InitializeDebugger(void);
221 static void TerminateDebugger(void);
222 extern "C" HRESULT __cdecl CorDBGetInterface(DebugInterface** rcInterface);
223 #endif // DEBUGGING_SUPPORTED
224
225 // g_coreclr_embedded indicates that coreclr is linked directly into the program
226 // g_hostpolicy_embedded indicates that the hostpolicy library is linked directly into the executable
227 // Note: that it can happen that the hostpolicy is embedded but coreclr isn't (on Windows singlefilehost is built that way)
228 #ifdef CORECLR_EMBEDDED
229 bool g_coreclr_embedded = true;
230 bool g_hostpolicy_embedded = true; // We always embed hostpolicy if coreclr is also embedded
231 #else
232 bool g_coreclr_embedded = false;
233 bool g_hostpolicy_embedded = false; // In this case the value may come from a runtime property and may change
234 #endif
235
236 // Remember how the last startup of EE went.
237 HRESULT g_EEStartupStatus = S_OK;
238
239 // Flag indicating if the EE has been started.  This is set prior to initializing the default AppDomain, and so does not indicate that
240 // the EE is fully able to execute arbitrary managed code.  To ensure the EE is fully started, call EnsureEEStarted rather than just
241 // checking this flag.
242 Volatile<BOOL> g_fEEStarted = FALSE;
243
244 // The OS thread ID of the thread currently performing EE startup, or 0 if there is no such thread.
245 DWORD   g_dwStartupThreadId = 0;
246
247 // Event to synchronize EE shutdown.
248 static CLREvent * g_pEEShutDownEvent;
249
250 static DangerousNonHostedSpinLock g_EEStartupLock;
251
252 // ---------------------------------------------------------------------------
253 // %%Function: EnsureEEStarted()
254 //
255 // Description: Ensure the CLR is started.
256 // ---------------------------------------------------------------------------
257 HRESULT EnsureEEStarted()
258 {
259     CONTRACTL
260     {
261         NOTHROW;
262         GC_TRIGGERS;
263         MODE_PREEMPTIVE;
264         ENTRY_POINT;
265     }
266     CONTRACTL_END;
267
268     if (g_fEEShutDown)
269         return E_FAIL;
270
271     HRESULT hr = E_FAIL;
272
273     // On non x86 platforms, when we load CoreLib during EEStartup, we will
274     // re-enter _CorDllMain with a DLL_PROCESS_ATTACH for CoreLib. We are
275     // far enough in startup that this is allowed, however we don't want to
276     // re-start the startup code so we need to check to see if startup has
277     // been initiated or completed before we call EEStartup.
278     //
279     // We do however want to make sure other threads block until the EE is started,
280     // which we will do further down.
281     if (!g_fEEStarted)
282     {
283         // Initialize our configuration.
284         CLRConfig::Initialize();
285
286         BOOL bStarted=FALSE;
287
288         {
289             DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
290
291             // Now that we've acquired the lock, check again to make sure we aren't in
292             // the process of starting the CLR or that it hasn't already been fully started.
293             // At this point, if startup has been inited we don't have anything more to do.
294             // And if EEStartup already failed before, we don't do it again.
295             if (!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus))
296             {
297                 g_dwStartupThreadId = GetCurrentThreadId();
298
299                 EEStartup();
300                 bStarted=g_fEEStarted;
301                 hr = g_EEStartupStatus;
302
303                 g_dwStartupThreadId = 0;
304             }
305             else
306             {
307                 hr = g_EEStartupStatus;
308                 if (SUCCEEDED(g_EEStartupStatus))
309                 {
310                     hr = S_FALSE;
311                 }
312             }
313         }
314     }
315     else
316     {
317         //
318         // g_fEEStarted is TRUE, but startup may not be complete since we initialize the default AppDomain
319         // *after* setting that flag.  g_fEEStarted is set inside of g_EEStartupLock, and that lock is
320         // not released until the EE is really started - so we can quickly check whether the EE is definitely
321         // started by checking if that lock is currently held.  If it is not, then we know the other thread
322         // (that is actually doing the startup) has finished startup.  If it is currently held, then we
323         // need to wait for the other thread to release it, which we do by simply acquiring the lock ourselves.
324         //
325         // We do not want to do this blocking if we are the thread currently performing EE startup.  So we check
326         // that first.
327         //
328         // Note that the call to IsHeld here is an "acquire" barrier, as is acquiring the lock.  And the release of
329         // the lock by the other thread is a "release" barrier, due to the volatile semantics in the lock's
330         // implementation.  This assures us that once we observe the lock having been released, we are guaranteed
331         // to observe a fully-initialized EE.
332         //
333         // A note about thread affinity here: we're using the OS thread ID of the current thread without
334         // asking the host to pin us to this thread, as we did above.  We can get away with this, because we are
335         // only interested in a particular thread ID (that of the "startup" thread) and *that* particular thread
336         // is already affinitized by the code above.  So if we get that particular OS thread ID, we know for sure
337         // we are really the startup thread.
338         //
339         if (g_EEStartupLock.IsHeld() && g_dwStartupThreadId != GetCurrentThreadId())
340         {
341             DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
342         }
343
344         hr = g_EEStartupStatus;
345         if (SUCCEEDED(g_EEStartupStatus))
346         {
347             hr = S_FALSE;
348         }
349     }
350
351     return hr;
352 }
353
354
355
356 #ifndef TARGET_UNIX
357 // This is our Ctrl-C, Ctrl-Break, etc. handler.
358 static BOOL WINAPI DbgCtrlCHandler(DWORD dwCtrlType)
359 {
360     WRAPPER_NO_CONTRACT;
361
362 #if defined(DEBUGGING_SUPPORTED)
363     // Note that if a managed-debugger is attached, it's actually attached with the native
364     // debugging pipeline and it will get a control-c notifications via native debug events.
365     // However, if we let the native debugging pipeline handle the event and send the notification
366     // to the debugger, then we break pre-V4 behaviour because we intercept handlers registered
367     // in-process.  See Dev10 Bug 846455 for more information.
368     if (CORDebuggerAttached() &&
369         (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT))
370     {
371         return g_pDebugInterface->SendCtrlCToDebugger(dwCtrlType);
372     }
373     else
374 #endif // DEBUGGING_SUPPORTED
375     {
376         if (dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_SHUTDOWN_EVENT)
377         {
378             // Initiate shutdown so the ProcessExit handlers run
379             ForceEEShutdown(SCA_ReturnWhenShutdownComplete);
380         }
381
382         g_fInControlC = true;     // only for weakening assertions in checked build.
383         return FALSE;             // keep looking for a real handler.
384     }
385 }
386 #endif
387
388 // A host can specify that it only wants one version of hosting interface to be used.
389 BOOL g_singleVersionHosting;
390
391 #ifdef TARGET_WINDOWS
392 typedef BOOL(WINAPI* PINITIALIZECONTEXT2)(PVOID Buffer, DWORD ContextFlags, PCONTEXT* Context, PDWORD ContextLength, ULONG64 XStateCompactionMask);
393 PINITIALIZECONTEXT2 g_pfnInitializeContext2 = NULL;
394
395 #ifdef TARGET_X86
396 typedef VOID(__cdecl* PRTLRESTORECONTEXT)(PCONTEXT ContextRecord, struct _EXCEPTION_RECORD* ExceptionRecord);
397 PRTLRESTORECONTEXT g_pfnRtlRestoreContext = NULL;
398 #endif // TARGET_X86
399
400 void InitializeOptionalWindowsAPIPointers()
401 {
402     HMODULE hm = GetModuleHandleW(_T("kernel32.dll"));
403     g_pfnInitializeContext2 = (PINITIALIZECONTEXT2)GetProcAddress(hm, "InitializeContext2");
404
405 #ifdef TARGET_X86
406     hm = GetModuleHandleW(_T("ntdll.dll"));
407     g_pfnRtlRestoreContext = (PRTLRESTORECONTEXT)GetProcAddress(hm, "RtlRestoreContext");
408 #endif //TARGET_X86
409 }
410 #endif // TARGET_WINDOWS
411
412 void InitializeStartupFlags()
413 {
414     CONTRACTL {
415         NOTHROW;
416         GC_TRIGGERS;
417         MODE_ANY;
418     } CONTRACTL_END;
419
420     STARTUP_FLAGS flags = CorHost2::GetStartupFlags();
421
422
423     if (flags & STARTUP_CONCURRENT_GC)
424         g_IGCconcurrent = 1;
425     else
426         g_IGCconcurrent = 0;
427
428
429     g_heap_type = ((flags & STARTUP_SERVER_GC) && GetCurrentProcessCpuCount() > 1) ? GC_HEAP_SVR : GC_HEAP_WKS;
430     g_IGCHoardVM = (flags & STARTUP_HOARD_GC_VM) == 0 ? 0 : 1;
431 }
432
433 //-----------------------------------------------------------------------------
434
435 void InitGSCookie()
436 {
437     CONTRACTL
438     {
439         THROWS;
440         GC_NOTRIGGER;
441         MODE_ANY;
442     }
443     CONTRACTL_END;
444
445     volatile GSCookie * pGSCookiePtr = GetProcessGSCookiePtr();
446
447     // The GS cookie is stored in a read only data segment
448     DWORD oldProtection;
449     if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), PAGE_READWRITE, &oldProtection))
450     {
451         ThrowLastError();
452     }
453
454 #ifdef TARGET_UNIX
455     // PAL layer is unable to extract old protection for regions that were not allocated using VirtualAlloc
456     oldProtection = PAGE_READONLY;
457 #endif // TARGET_UNIX
458
459 #ifndef TARGET_UNIX
460     // The GSCookie cannot be in a writeable page
461     assert(((oldProtection & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|
462                               PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOMBINE)) == 0));
463
464     // Forces VC cookie to be initialized.
465     void * pf = &__security_check_cookie;
466     pf = NULL;
467
468     GSCookie val = (GSCookie)(__security_cookie ^ GetTickCount());
469 #else // !TARGET_UNIX
470     // REVIEW: Need something better for PAL...
471     GSCookie val = (GSCookie)GetTickCount();
472 #endif // !TARGET_UNIX
473
474 #ifdef _DEBUG
475     // In _DEBUG, always use the same value to make it easier to search for the cookie
476     val = (GSCookie) BIT64_ONLY(0x9ABCDEF012345678) NOT_BIT64(0x12345678);
477 #endif
478
479     // To test if it is initialized. Also for ICorMethodInfo::getGSCookie()
480     if (val == 0)
481         val ++;
482     *pGSCookiePtr = val;
483
484     if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), oldProtection, &oldProtection))
485     {
486         ThrowLastError();
487     }
488 }
489
490 Volatile<BOOL> g_bIsGarbageCollectorFullyInitialized = FALSE;
491
492 void SetGarbageCollectorFullyInitialized()
493 {
494     LIMITED_METHOD_CONTRACT;
495
496     g_bIsGarbageCollectorFullyInitialized = TRUE;
497 }
498
499 // Tells whether the garbage collector is fully initialized
500 // Stronger than IsGCHeapInitialized
501 BOOL IsGarbageCollectorFullyInitialized()
502 {
503     LIMITED_METHOD_CONTRACT;
504
505     return g_bIsGarbageCollectorFullyInitialized;
506 }
507
508 // ---------------------------------------------------------------------------
509 // %%Function: EEStartupHelper
510 //
511 // Returns:
512 //  S_OK                    - On success
513 //
514 // Description:
515 //  Reserved to initialize the EE runtime engine explicitly.
516 // ---------------------------------------------------------------------------
517
518 #ifndef IfFailGotoLog
519 #define IfFailGotoLog(EXPR, LABEL) \
520 do { \
521     hr = (EXPR);\
522     if(FAILED(hr)) { \
523         STRESS_LOG2(LF_STARTUP, LL_ALWAYS, "%s failed with code %x", #EXPR, hr);\
524         goto LABEL; \
525     } \
526     else \
527        STRESS_LOG1(LF_STARTUP, LL_ALWAYS, "%s completed", #EXPR);\
528 } while (0)
529 #endif
530
531 #ifndef IfFailGoLog
532 #define IfFailGoLog(EXPR) IfFailGotoLog(EXPR, ErrExit)
533 #endif
534
535
536 #ifdef TARGET_UNIX
537 void EESocketCleanupHelper(bool isExecutingOnAltStack)
538 {
539     CONTRACTL
540     {
541         GC_NOTRIGGER;
542         MODE_ANY;
543     } CONTRACTL_END;
544
545     if (isExecutingOnAltStack)
546     {
547         GetThread()->SetExecutingOnAltStack();
548     }
549
550     // Close the debugger transport socket first
551     if (g_pDebugInterface != NULL)
552     {
553         g_pDebugInterface->CleanupTransportSocket();
554     }
555
556     // Close the diagnostic server socket.
557 #ifdef FEATURE_PERFTRACING
558     DiagnosticServerAdapter::Shutdown();
559 #endif // FEATURE_PERFTRACING
560 }
561 #endif // TARGET_UNIX
562
563 void FatalErrorHandler(UINT errorCode, LPCWSTR pszMessage)
564 {
565     EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(errorCode, pszMessage);
566 }
567
568 void EEStartupHelper()
569 {
570     CONTRACTL
571     {
572         THROWS;
573         GC_TRIGGERS;
574         MODE_ANY;
575     } CONTRACTL_END;
576
577 #ifdef ENABLE_CONTRACTS_IMPL
578     {
579         extern void ContractRegressionCheck();
580         ContractRegressionCheck();
581     }
582 #endif
583
584     HRESULT hr = S_OK;
585     static ConfigDWORD breakOnEELoad;
586     EX_TRY
587     {
588         g_fEEInit = true;
589
590
591         // We cache the SystemInfo for anyone to use throughout the life of the EE.
592         GetSystemInfo(&g_SystemInfo);
593
594         // Set callbacks so that LoadStringRC knows which language our
595         // threads are in so that it can return the proper localized string.
596     // TODO: This shouldn't rely on the LCID (id), but only the name
597         SetResourceCultureCallbacks(GetThreadUICultureNames,
598         GetThreadUICultureId);
599
600 #ifndef TARGET_UNIX
601         ::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);
602 #endif
603
604 #ifdef HOST_WINDOWS
605         InitializeOptionalWindowsAPIPointers();
606 #endif // HOST_WINDOWS
607
608         // SString initialization
609         // This needs to be done before config because config uses SString::Empty()
610         SString::Startup();
611
612         IfFailGo(EEConfig::Setup());
613
614
615 #ifdef HOST_WINDOWS
616         InitializeCrashDump();
617
618 #endif // HOST_WINDOWS
619 #ifndef TARGET_UNIX
620         CPUGroupInfo::EnsureInitialized();
621 #endif // !TARGET_UNIX
622
623         // Initialize global configuration settings based on startup flags
624         // This needs to be done before the EE has started
625         InitializeStartupFlags();
626
627         IfFailGo(ExecutableAllocator::StaticInitialize(FatalErrorHandler));
628
629         Thread::StaticInitialize();
630
631         JITInlineTrackingMap::StaticInitialize();
632         MethodDescBackpatchInfoTracker::StaticInitialize();
633         CodeVersionManager::StaticInitialize();
634         TieredCompilationManager::StaticInitialize();
635         CallCountingManager::StaticInitialize();
636         OnStackReplacementManager::StaticInitialize();
637
638 #ifdef TARGET_UNIX
639         ExecutableAllocator::InitPreferredRange();
640 #else
641         {
642             // Record coreclr.dll geometry
643             PEDecoder pe(GetClrModuleBase());
644
645             g_runtimeLoadedBaseAddress = (SIZE_T)pe.GetBase();
646             g_runtimeVirtualSize = (SIZE_T)pe.GetVirtualSize();
647             ExecutableAllocator::InitLazyPreferredRange(g_runtimeLoadedBaseAddress, g_runtimeVirtualSize, GetRandomInt(64));
648         }
649 #endif // !TARGET_UNIX
650
651         InitThreadManager();
652         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "Returned successfully from InitThreadManager");
653
654 #ifdef FEATURE_PERFTRACING
655         // Initialize the event pipe.
656         EventPipeAdapter::Initialize();
657 #endif // FEATURE_PERFTRACING
658
659 #ifdef TARGET_UNIX
660         PAL_SetShutdownCallback(EESocketCleanupHelper);
661 #endif // TARGET_UNIX
662
663 #ifdef STRESS_LOG
664         if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StressLog, g_pConfig->StressLog()) != 0) {
665             unsigned facilities = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_LogFacility, LF_ALL);
666             unsigned level = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_LogLevel, LL_INFO1000);
667             unsigned bytesPerThread = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StressLogSize, STRESSLOG_CHUNK_SIZE * 4);
668             unsigned totalBytes = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TotalStressLogSize, STRESSLOG_CHUNK_SIZE * 1024);
669             CLRConfigStringHolder logFilename = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StressLogFilename);
670             StressLog::Initialize(facilities, level, bytesPerThread, totalBytes, GetClrModuleBase(), logFilename);
671             g_pStressLog = &StressLog::theLog;
672         }
673 #endif
674
675 #ifdef FEATURE_PERFTRACING
676         DiagnosticServerAdapter::Initialize();
677         DiagnosticServerAdapter::PauseForDiagnosticsMonitor();
678 #endif // FEATURE_PERFTRACING
679
680 #ifdef FEATURE_GDBJIT
681         // Initialize gdbjit
682         NotifyGdb::Initialize();
683 #endif // FEATURE_GDBJIT
684
685 #ifdef FEATURE_EVENT_TRACE
686         // Initialize event tracing early so we can trace CLR startup time events.
687         InitializeEventTracing();
688
689         // Fire the EE startup ETW event
690         ETWFireEvent(EEStartupStart_V1);
691 #endif // FEATURE_EVENT_TRACE
692
693         InitGSCookie();
694
695         Frame::Init();
696
697
698
699
700 #ifdef LOGGING
701         InitializeLogging();
702 #endif
703
704 #ifdef FEATURE_PERFMAP
705         PerfMap::Initialize();
706 #endif
707
708 #ifdef FEATURE_PGO
709         PgoManager::Initialize();
710 #endif
711
712         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Starting===================");
713
714 #ifndef TARGET_UNIX
715         IfFailGoLog(EnsureRtlFunctions());
716 #endif // !TARGET_UNIX
717         InitEventStore();
718
719         if (g_pConfig != NULL)
720         {
721             IfFailGoLog(g_pConfig->sync());
722         }
723
724         // Fire the runtime information ETW event
725         ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
726
727         if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 1)
728         {
729 #ifdef _DEBUG
730             _ASSERTE(!"Start loading EE!");
731 #else
732             DebugBreak();
733 #endif
734         }
735
736 #ifdef ENABLE_STARTUP_DELAY
737         PREFIX_ASSUME(NULL != g_pConfig);
738         if (g_pConfig->StartupDelayMS())
739         {
740             ClrSleepEx(g_pConfig->StartupDelayMS(), FALSE);
741         }
742 #endif
743
744 #if USE_DISASSEMBLER
745         if ((g_pConfig->GetGCStressLevel() & (EEConfig::GCSTRESS_INSTR_JIT | EEConfig::GCSTRESS_INSTR_NGEN)) != 0)
746         {
747             Disassembler::StaticInitialize();
748             if (!Disassembler::IsAvailable())
749             {
750                 fprintf(stderr, "External disassembler is not available.\n");
751                 IfFailGo(E_FAIL);
752             }
753         }
754 #endif // USE_DISASSEMBLER
755
756         // Monitors, Crsts, and SimpleRWLocks all use the same spin heuristics
757         // Cache the (potentially user-overridden) values now so they are accessible from asm routines
758         InitializeSpinConstants();
759
760 #ifdef FEATURE_INTERPRETER
761         Interpreter::Initialize();
762 #endif // FEATURE_INTERPRETER
763
764         StubManager::InitializeStubManagers();
765
766         // Set up the cor handle map. This map is used to load assemblies in
767         // memory instead of using the normal system load
768         PEImage::Startup();
769
770         AccessCheckOptions::Startup();
771
772         CoreLibBinder::Startup();
773
774         Stub::Init();
775         StubLinkerCPU::Init();
776         StubPrecode::StaticInitialize();
777         FixupPrecode::StaticInitialize();
778
779         InitializeGarbageCollector();
780
781         if (!GCHandleUtilities::GetGCHandleManager()->Initialize())
782         {
783             IfFailGo(E_OUTOFMEMORY);
784         }
785
786         g_pEEShutDownEvent = new CLREvent();
787         g_pEEShutDownEvent->CreateManualEvent(FALSE);
788
789         VirtualCallStubManager::InitStatic();
790
791
792         // Setup the domains. Threads are started in a default domain.
793
794         // Static initialization
795         BaseDomain::Attach();
796         SystemDomain::Attach();
797
798         // Start up the EE initializing all the global variables
799         ECall::Init();
800
801         COMDelegate::Init();
802
803         ExecutionManager::Init();
804
805         JitHost::Init();
806
807
808 #ifndef TARGET_UNIX
809         if (!RegisterOutOfProcessWatsonCallbacks())
810         {
811             IfFailGo(E_FAIL);
812         }
813 #endif // !TARGET_UNIX
814
815 #ifdef DEBUGGING_SUPPORTED
816         // Initialize the debugging services. This must be done before any
817         // EE thread objects are created, and before any classes or
818         // modules are loaded.
819         InitializeDebugger(); // throws on error
820 #endif // DEBUGGING_SUPPORTED
821
822 #ifdef PROFILING_SUPPORTED
823         // Initialize the profiling services.
824         hr = ProfilingAPIUtility::InitializeProfiling();
825
826         _ASSERTE(SUCCEEDED(hr));
827         IfFailGo(hr);
828 #endif // PROFILING_SUPPORTED
829
830         InitializeExceptionHandling();
831
832         //
833         // Install our global exception filter
834         //
835         if (!InstallUnhandledExceptionFilter())
836         {
837             IfFailGo(E_FAIL);
838         }
839
840         // throws on error
841         SetupThread();
842
843 #ifdef DEBUGGING_SUPPORTED
844         // Notify debugger once the first thread is created to finish initialization.
845         if (g_pDebugInterface != NULL)
846         {
847             g_pDebugInterface->StartupPhase2(GetThread());
848         }
849 #endif
850
851         InitPreStubManager();
852
853 #ifdef FEATURE_COMINTEROP
854         InitializeComInterop();
855 #endif // FEATURE_COMINTEROP
856
857         StubHelpers::Init();
858
859         // Before setting up the execution manager initialize the first part
860         // of the JIT helpers.
861         InitJITHelpers1();
862         InitJITHelpers2();
863
864         SyncBlockCache::Attach();
865
866         // Set up the sync block
867         SyncBlockCache::Start();
868
869         StackwalkCache::Init();
870
871         // This isn't done as part of InitializeGarbageCollector() above because it
872         // requires write barriers to have been set up on x86, which happens as part
873         // of InitJITHelpers1.
874         hr = g_pGCHeap->Initialize();
875         if (FAILED(hr))
876         {
877             LogErrorToHost("GC heap initialization failed with error 0x%08X", hr);
878         }
879
880         IfFailGo(hr);
881
882 #ifdef FEATURE_PERFTRACING
883         // Finish setting up rest of EventPipe - specifically enable SampleProfiler if it was requested at startup.
884         // SampleProfiler needs to cooperate with the GC which hasn't fully finished setting up in the first part of the
885         // EventPipe initialization, so this is done after the GC has been fully initialized.
886         EventPipeAdapter::FinishInitialize();
887 #endif // FEATURE_PERFTRACING
888         GenAnalysis::Initialize();
889
890         // This isn't done as part of InitializeGarbageCollector() above because thread
891         // creation requires AppDomains to have been set up.
892         FinalizerThread::FinalizerThreadCreate();
893
894         // Now we really have fully initialized the garbage collector
895         SetGarbageCollectorFullyInitialized();
896
897 #ifdef DEBUGGING_SUPPORTED
898         // Make a call to publish the DefaultDomain for the debugger
899         // This should be done before assemblies/modules are loaded into it (i.e. SystemDomain::Init)
900         // and after its OK to switch GC modes and synchronize for sending events to the debugger.
901         // @dbgtodo  synchronization: this can probably be simplified in V3
902         LOG((LF_CORDB | LF_SYNC | LF_STARTUP, LL_INFO1000, "EEStartup: adding default domain 0x%x\n",
903              SystemDomain::System()->DefaultDomain()));
904         SystemDomain::System()->PublishAppDomainAndInformDebugger(SystemDomain::System()->DefaultDomain());
905 #endif
906
907 #ifdef HAVE_GCCOVER
908         MethodDesc::Init();
909 #endif
910
911
912         Assembly::Initialize();
913
914         SystemDomain::System()->Init();
915
916 #ifdef PROFILING_SUPPORTED
917         // <TODO>This is to compensate for the DefaultDomain workaround contained in
918         // SystemDomain::Attach in which the first user domain is created before profiling
919         // services can be initialized.  Profiling services cannot be moved to before the
920         // workaround because it needs SetupThread to be called.</TODO>
921
922         SystemDomain::NotifyProfilerStartup();
923 #endif // PROFILING_SUPPORTED
924
925         g_fEEInit = false;
926
927         SystemDomain::System()->DefaultDomain()->LoadSystemAssemblies();
928
929         SystemDomain::System()->DefaultDomain()->SetupSharedStatics();
930
931 #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
932         // retrieve configured max size for the mini-metadata buffer (defaults to 64KB)
933         g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity);
934         // align up to GetOsPageSize(), with a maximum of 1 MB
935         g_MiniMetaDataBuffMaxSize = (DWORD) min(ALIGN_UP(g_MiniMetaDataBuffMaxSize, GetOsPageSize()), 1024 * 1024);
936         // allocate the buffer. this is never touched while the process is running, so it doesn't
937         // contribute to the process' working set. it is needed only as a "shadow" for a mini-metadata
938         // buffer that will be set up and reported / updated in the Watson process (the
939         // DacStreamsManager class coordinates this)
940         g_MiniMetaDataBuffAddress = (TADDR) ClrVirtualAlloc(NULL,
941                                                 g_MiniMetaDataBuffMaxSize, MEM_COMMIT, PAGE_READWRITE);
942 #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
943
944         g_fEEStarted = TRUE;
945         g_EEStartupStatus = S_OK;
946         hr = S_OK;
947         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Completed===================");
948
949
950 #ifdef _DEBUG
951
952         //if g_fEEStarted was false when we loaded the System Module, we did not run ExpandAll on it.  In
953         //this case, make sure we run ExpandAll here.  The rationale is that if we Jit before g_fEEStarted
954         //is true, we can't initialize Com, so we can't jit anything that uses Com types.  Also, it's
955         //probably not safe to Jit while g_fEEStarted is false.
956         //
957         //Also, if you run this it's possible we'll call CoInitialize, which defaults to MTA.  This might
958         //mess up an application that uses STA.  However, this mode is only supported for certain limited
959         //jit testing scenarios, so it can live with the limitation.
960         if (g_pConfig->ExpandModulesOnLoad())
961         {
962             SystemDomain::SystemModule()->ExpandAll();
963         }
964 #endif // _DEBUG
965
966
967 ErrExit: ;
968     }
969     EX_CATCH
970     {
971         hr = GET_EXCEPTION()->GetHR();
972     }
973     EX_END_CATCH(RethrowTerminalExceptionsWithInitCheck)
974
975     if (!g_fEEStarted) {
976         if (g_fEEInit)
977             g_fEEInit = false;
978
979         if (!FAILED(hr))
980             hr = E_FAIL;
981
982         g_EEStartupStatus = hr;
983     }
984
985     if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 2)
986     {
987 #ifdef _DEBUG
988         _ASSERTE(!"Done loading EE!");
989 #else
990         DebugBreak();
991 #endif
992     }
993
994 }
995
996 LONG FilterStartupException(PEXCEPTION_POINTERS p, PVOID pv)
997 {
998     CONTRACTL
999     {
1000         NOTHROW;
1001         GC_NOTRIGGER;
1002         MODE_ANY;
1003         PRECONDITION(CheckPointer(p));
1004         PRECONDITION(CheckPointer(pv));
1005     } CONTRACTL_END;
1006
1007     g_EEStartupStatus = (HRESULT)p->ExceptionRecord->ExceptionInformation[0];
1008
1009     // Make sure we got a failure code in this case
1010     if (!FAILED(g_EEStartupStatus))
1011         g_EEStartupStatus = E_FAIL;
1012
1013     // Initializations has failed so reset the g_fEEInit flag.
1014     g_fEEInit = false;
1015
1016     if (p->ExceptionRecord->ExceptionCode == BOOTUP_EXCEPTION_COMPLUS)
1017     {
1018         // Don't ever handle the exception in a checked build
1019 #ifndef _DEBUG
1020         return EXCEPTION_EXECUTE_HANDLER;
1021 #endif
1022     }
1023
1024     return EXCEPTION_CONTINUE_SEARCH;
1025 }
1026
1027 // EEStartup is responsible for all the one time initialization of the runtime.  Some of the highlights of
1028 // what it does include
1029 //     * Creates the default and shared, appdomains.
1030 //     * Loads System.Private.CoreLib and loads up the fundamental types (System.Object ...)
1031 //
1032 // see code:EEStartup#TableOfContents for more on the runtime in general.
1033 // see code:#EEShutdown for an analogous routine run during shutdown.
1034 //
1035 HRESULT EEStartup()
1036 {
1037     // Cannot use normal contracts here because of the PAL_TRY.
1038     STATIC_CONTRACT_NOTHROW;
1039
1040     _ASSERTE(!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus));
1041
1042     PAL_TRY(PVOID, p, NULL)
1043     {
1044         InitializeClrNotifications();
1045 #ifdef TARGET_UNIX
1046         InitializeJITNotificationTable();
1047         DacGlobals::Initialize();
1048 #endif
1049
1050         EEStartupHelper();
1051     }
1052     PAL_EXCEPT_FILTER (FilterStartupException)
1053     {
1054         // The filter should have set g_EEStartupStatus to a failure HRESULT.
1055         _ASSERTE(FAILED(g_EEStartupStatus));
1056     }
1057     PAL_ENDTRY
1058
1059     return g_EEStartupStatus;
1060 }
1061
1062
1063
1064 // ---------------------------------------------------------------------------
1065 // %%Function: ForceEEShutdown()
1066 //
1067 // Description: Force the EE to shutdown now.
1068 //
1069 // Note: returns when sca is SCA_ReturnWhenShutdownComplete.
1070 // ---------------------------------------------------------------------------
1071 void ForceEEShutdown(ShutdownCompleteAction sca)
1072 {
1073     WRAPPER_NO_CONTRACT;
1074
1075     // Don't bother to take the lock for this case.
1076
1077     STRESS_LOG0(LF_STARTUP, INFO3, "EEShutdown invoked from ForceEEShutdown");
1078     EEPolicy::HandleExitProcess(sca);
1079 }
1080
1081 void WaitForEndOfShutdown()
1082 {
1083     CONTRACTL{
1084         NOTHROW;
1085         GC_NOTRIGGER;
1086         MODE_PREEMPTIVE;
1087     } CONTRACTL_END;
1088
1089     // We are shutting down.  GC triggers does not have any effect now.
1090     CONTRACT_VIOLATION(GCViolation);
1091
1092     Thread *pThread = GetThreadNULLOk();
1093     // After a thread is blocked in WaitForEndOfShutdown, the thread should not enter runtime again,
1094     // and block at WaitForEndOfShutdown again.
1095     if (pThread)
1096     {
1097         _ASSERTE(!pThread->HasThreadStateNC(Thread::TSNC_BlockedForShutdown));
1098         pThread->SetThreadStateNC(Thread::TSNC_BlockedForShutdown);
1099     }
1100
1101     for (;;) g_pEEShutDownEvent->Wait(INFINITE, TRUE);
1102 }
1103
1104 // ---------------------------------------------------------------------------
1105 // Function: EEShutDownHelper(BOOL fIsDllUnloading)
1106 //
1107 // The real meat of shut down happens here.  See code:#EEShutDown for details, including
1108 // what fIsDllUnloading means.
1109 //
1110 void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
1111 {
1112     CONTRACTL
1113     {
1114         NOTHROW;
1115         GC_TRIGGERS;
1116         MODE_ANY;
1117     } CONTRACTL_END;
1118
1119     // Used later for a callback.
1120     CEEInfo ceeInf;
1121
1122 #ifdef FEATURE_PGO
1123     EX_TRY
1124     {
1125         PgoManager::Shutdown();
1126     }
1127     EX_CATCH
1128     {
1129     }
1130     EX_END_CATCH(SwallowAllExceptions);
1131 #endif
1132
1133     if (!fIsDllUnloading)
1134     {
1135         ETW::EnumerationLog::ProcessShutdown();
1136
1137 #ifdef FEATURE_PERFTRACING
1138         EventPipeAdapter::Shutdown();
1139         DiagnosticServerAdapter::Shutdown();
1140 #endif // FEATURE_PERFTRACING
1141     }
1142
1143 #if defined(FEATURE_COMINTEROP)
1144     // Get the current thread.
1145     Thread * pThisThread = GetThreadNULLOk();
1146 #endif
1147
1148     // If the process is detaching then set the global state.
1149     // This is used to get around FreeLibrary problems.
1150     if(fIsDllUnloading)
1151         g_fProcessDetach = true;
1152
1153     if (IsDbgHelperSpecialThread())
1154     {
1155         // Our debugger helper thread does not allow Thread object to be set up.
1156         // We should not run shutdown code on debugger helper thread.
1157         _ASSERTE(fIsDllUnloading);
1158         return;
1159     }
1160
1161     STRESS_LOG1(LF_STARTUP, LL_INFO10, "EEShutDown entered unloading = %d", fIsDllUnloading);
1162
1163 #ifdef _DEBUG
1164     if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnEEShutdown))
1165         _ASSERTE(!"Shutting down EE!");
1166 #endif
1167
1168 #ifdef DEBUGGING_SUPPORTED
1169     // This is a nasty, terrible, horrible thing. If we're being
1170     // called from our DLL main, then the odds are good that our DLL
1171     // main has been called as the result of some person calling
1172     // ExitProcess. That rips the debugger helper thread away very
1173     // ungracefully. This check is an attempt to recognize that case
1174     // and avoid the impending hang when attempting to get the helper
1175     // thread to do things for us.
1176     if ((g_pDebugInterface != NULL) && g_fProcessDetach)
1177         g_pDebugInterface->EarlyHelperThreadDeath();
1178 #endif // DEBUGGING_SUPPORTED
1179
1180     EX_TRY
1181     {
1182         ClrFlsSetThreadType(ThreadType_Shutdown);
1183
1184         if (fIsDllUnloading && g_fEEShutDown)
1185         {
1186             // I'm in the final shutdown and the first part has already been run.
1187             goto part2;
1188         }
1189
1190         // Indicate the EE is the shut down phase.
1191         g_fEEShutDown |= ShutDown_Start;
1192
1193         if (!g_fProcessDetach && !g_fFastExitProcess)
1194         {
1195             g_fEEShutDown |= ShutDown_Finalize1;
1196
1197             // Wait for the finalizer thread to deliver process exit event
1198             GCX_PREEMP();
1199             FinalizerThread::RaiseShutdownEvents();
1200         }
1201
1202         // Ok.  Let's stop the EE.
1203         if (!g_fProcessDetach)
1204         {
1205             // Convert key locks into "shutdown" mode. A lock in shutdown mode means:
1206             // - Only the finalizer/helper/shutdown threads will be able to take the lock.
1207             // - Any other thread that tries takes it will just get redirected to an endless WaitForEndOfShutdown().
1208             //
1209             // The only managed code that should run after this point is the finalizers for shutdown.
1210             // We convert locks needed for running + debugging such finalizers. Since such locks may need to be
1211             // juggled between multiple threads (finalizer/helper/shutdown), no single thread can take the
1212             // lock and not give it up.
1213             //
1214             // Each lock needs its own shutdown flag (they can't all be converted at once).
1215             // To avoid deadlocks, we need to convert locks in order of crst level (biggest first).
1216
1217             // Notify the debugger that we're going into shutdown to convert debugger-lock to shutdown.
1218             if (g_pDebugInterface != NULL)
1219             {
1220                 g_pDebugInterface->LockDebuggerForShutdown();
1221             }
1222
1223             // This call will convert the ThreadStoreLock into "shutdown" mode, just like the debugger lock above.
1224             g_fEEShutDown |= ShutDown_Finalize2;
1225         }
1226
1227 #ifdef FEATURE_EVENT_TRACE
1228         // Flush managed object allocation logging data.
1229         // We do this after finalization is complete and returning threads have been trapped, so that
1230         // no there will be no more managed allocations and no more GCs which will manipulate the
1231         // allocation sampling data structures.
1232         ETW::TypeSystemLog::FlushObjectAllocationEvents();
1233 #endif // FEATURE_EVENT_TRACE
1234
1235 #ifdef FEATURE_PERFMAP
1236         // Flush and close the perf map file.
1237         PerfMap::Disable();
1238 #endif
1239
1240         ceeInf.JitProcessShutdownWork();  // Do anything JIT-related that needs to happen at shutdown.
1241
1242 #ifdef FEATURE_INTERPRETER
1243         // This will check a flag and do nothing if not enabled.
1244         Interpreter::PrintPostMortemData();
1245 #endif // FEATURE_INTERPRETER
1246
1247 #ifdef PROFILING_SUPPORTED
1248         // If profiling is enabled, then notify of shutdown first so that the
1249         // profiler can make any last calls it needs to.  Do this only if we
1250         // are not detaching
1251
1252         // NOTE: We haven't stopped other threads at this point and nothing is stopping
1253         // callbacks from coming into the profiler even after Shutdown() has been called.
1254         // See https://github.com/dotnet/runtime/issues/11885 for an example of how that
1255         // happens.
1256         //
1257         // To prevent issues when profilers are attached we intentionally skip freeing the
1258         // profiler here. Since there is no guarantee that the profiler won't be accessed after
1259         // we free it (e.g. through callbacks or ELT hooks), we can't safely free the profiler.
1260         if (CORProfilerPresent())
1261         {
1262             // Don't call back in to the profiler if we are being torn down, it might be unloaded
1263             if (!fIsDllUnloading)
1264             {
1265                 BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
1266                 GCX_PREEMP();
1267                 (&g_profControlBlock)->Shutdown();
1268                 END_PROFILER_CALLBACK();
1269             }
1270
1271             g_fEEShutDown |= ShutDown_Profiler;
1272         }
1273 #endif // PROFILING_SUPPORTED
1274
1275
1276 #ifdef _DEBUG
1277         g_fEEShutDown |= ShutDown_SyncBlock;
1278 #endif
1279         {
1280             // From here on out we might call stuff that violates mode requirements, but we ignore these
1281             // because we are shutting down.
1282             CONTRACT_VIOLATION(ModeViolation);
1283
1284 #ifdef FEATURE_COMINTEROP
1285             // We need to call CoUninitialize in part one to ensure orderly shutdown of COM dlls.
1286             if (!g_fFastExitProcess)
1287             {
1288                 if (pThisThread!= NULL)
1289                 {
1290                     pThisThread->CoUninitialize();
1291                 }
1292             }
1293 #endif // FEATURE_COMINTEROP
1294         }
1295
1296         // This is the end of Part 1.
1297
1298 part2:
1299         // If process shutdown is in progress and Crst locks to be used in shutdown phase 2
1300         // are already in use, then skip phase 2. This will happen only when those locks
1301         // are orphaned. In Vista, the penalty for attempting to enter such locks is
1302         // instant process termination.
1303         if (g_fProcessDetach)
1304         {
1305             // The assert below is a bit too aggressive and has generally brought cases that have been race conditions
1306             // and not easily reproed to validate a bug. A typical race scenario is when there are two threads,
1307             // T1 and T2, with T2 having taken a lock (e.g. SystemDomain lock), the OS terminates
1308             // T2 for some reason. Later, when we enter the shutdown thread, we would assert on such
1309             // a lock leak, but there is not much we can do since the OS wont notify us prior to thread
1310             // termination. And this is not even a user bug.
1311             //
1312             // Converting it to a STRESS LOG to reduce noise, yet keep things in radar if they need
1313             // to be investigated.
1314             //_ASSERTE_MSG(g_ShutdownCrstUsageCount == 0, "Some locks to be taken during shutdown may already be orphaned!");
1315             if (g_ShutdownCrstUsageCount > 0)
1316             {
1317                 STRESS_LOG0(LF_STARTUP, LL_INFO10, "Some locks to be taken during shutdown may already be orphaned!");
1318                 goto lDone;
1319             }
1320         }
1321
1322         {
1323             CONTRACT_VIOLATION(ModeViolation);
1324
1325             // On the new plan, we only do the tear-down under the protection of the loader
1326             // lock -- after the OS has stopped all other threads.
1327             if (fIsDllUnloading && (g_fEEShutDown & ShutDown_Phase2) == 0)
1328             {
1329                 g_fEEShutDown |= ShutDown_Phase2;
1330
1331                 // Shutdown finalizer before we suspend all background threads. Otherwise we
1332                 // never get to finalize anything.
1333
1334                 // No longer process exceptions
1335                 g_fNoExceptions = true;
1336
1337                 // <TODO>@TODO: This does things which shouldn't occur in part 2.  Namely,
1338                 // calling managed dll main callbacks (AppDomain::SignalProcessDetach), and
1339                 // RemoveAppDomainFromIPC.
1340                 //
1341                 // (If we move those things to earlier, this can be called only if fShouldWeCleanup.)</TODO>
1342                 if (!g_fFastExitProcess)
1343                 {
1344                     SystemDomain::DetachBegin();
1345                 }
1346
1347
1348 #ifdef DEBUGGING_SUPPORTED
1349                 // Terminate the debugging services.
1350                 TerminateDebugger();
1351 #endif // DEBUGGING_SUPPORTED
1352
1353                 StubManager::TerminateStubManagers();
1354
1355 #ifdef FEATURE_INTERPRETER
1356                 Interpreter::Terminate();
1357 #endif // FEATURE_INTERPRETER
1358
1359                 //@TODO: find the right place for this
1360                 VirtualCallStubManager::UninitStatic();
1361
1362                 // Unregister our vectored exception and continue handlers from the OS.
1363                 // This will ensure that if any other DLL unload (after ours) has an exception,
1364                 // we wont attempt to process that exception (which could lead to various
1365                 // issues including AV in the runtime).
1366                 //
1367                 // This should be done:
1368                 //
1369                 // 1) As the last action during the shutdown so that any unexpected AVs
1370                 //    in the runtime during shutdown do result in FailFast in VEH.
1371                 //
1372                 // 2) Only when the runtime is processing DLL_PROCESS_DETACH.
1373                 CLRRemoveVectoredHandlers();
1374
1375 #if USE_DISASSEMBLER
1376                 Disassembler::StaticClose();
1377 #endif // USE_DISASSEMBLER
1378
1379                 WriteJitHelperCountToSTRESSLOG();
1380
1381                 STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutdown shutting down logging");
1382
1383 #if 0       // Dont clean up the stress log, so that even at process exit we have a log (after all the process is going away
1384                 if (!g_fFastExitProcess)
1385                     StressLog::Terminate(TRUE);
1386 #endif
1387
1388 #ifdef LOGGING
1389                 ShutdownLogging();
1390 #endif
1391                 GCHeapUtilities::GetGCHeap()->Shutdown();
1392             }
1393         }
1394
1395     lDone: ;
1396     }
1397     EX_CATCH
1398     {
1399     }
1400     EX_END_CATCH(SwallowAllExceptions);
1401
1402     ClrFlsClearThreadType(ThreadType_Shutdown);
1403     if (!g_fProcessDetach)
1404     {
1405         g_pEEShutDownEvent->Set();
1406     }
1407 }
1408
1409
1410 #ifdef FEATURE_COMINTEROP
1411
1412 BOOL IsThreadInSTA()
1413 {
1414     CONTRACTL
1415     {
1416         NOTHROW;
1417         GC_TRIGGERS;
1418         MODE_ANY;
1419     }
1420     CONTRACTL_END;
1421
1422     // If ole32.dll is not loaded
1423     if (WszGetModuleHandle(W("ole32.dll")) == NULL)
1424     {
1425         return FALSE;
1426     }
1427
1428     BOOL fInSTA = TRUE;
1429     // To be conservative, check if finalizer thread is around
1430     EX_TRY
1431     {
1432         Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread();
1433         if (!pFinalizerThread || pFinalizerThread->Join(0, FALSE) != WAIT_TIMEOUT)
1434         {
1435             fInSTA = FALSE;
1436         }
1437     }
1438     EX_CATCH
1439     {
1440     }
1441     EX_END_CATCH(SwallowAllExceptions);
1442
1443     if (!fInSTA)
1444     {
1445         return FALSE;
1446     }
1447
1448     THDTYPE type;
1449     HRESULT hr = S_OK;
1450
1451     hr = GetCurrentThreadTypeNT5(&type);
1452     if (hr == S_OK)
1453     {
1454         fInSTA = (type == THDTYPE_PROCESSMESSAGES) ? TRUE : FALSE;
1455
1456         // If we get back THDTYPE_PROCESSMESSAGES, we are guaranteed to
1457         // be an STA thread. If not, we are an MTA thread, however
1458         // we can't know if the thread has been explicitly set to MTA
1459         // (via a call to CoInitializeEx) or if it has been implicitly
1460         // made MTA (if it hasn't been CoInitializeEx'd but CoInitialize
1461         // has already been called on some other thread in the process.
1462     }
1463     else
1464     {
1465         // CoInitialize hasn't been called in the process yet so assume the current thread
1466         // is MTA.
1467         fInSTA = FALSE;
1468     }
1469
1470     return fInSTA;
1471 }
1472 #endif
1473
1474 // #EEShutDown
1475 //
1476 // Function: EEShutDown(BOOL fIsDllUnloading)
1477 //
1478 // Parameters:
1479 //    BOOL fIsDllUnloading:
1480 //         * TRUE => Called from CLR's DllMain (DLL_PROCESS_DETACH). Not safe point for
1481 //             full cleanup
1482 //         * FALSE => Called some other way (e.g., end of the CLR's main). Safe to do
1483 //             full cleanup.
1484 //
1485 // Description:
1486 //
1487 //     All ee shutdown stuff should be done here. EEShutDown is generally called in one
1488 //     of two ways:
1489 //     * 1. From code:EEPolicy::HandleExitProcess (via HandleExitProcessHelper), with
1490 //         fIsDllUnloading == FALSE. This code path is typically invoked by the CLR's
1491 //         main just falling through to the end. Full cleanup can be performed when
1492 //         EEShutDown is called this way.
1493 //     * 2. From CLR's DllMain (DLL_PROCESS_DETACH), with fIsDllUnloading == TRUE. When
1494 //         called this way, much cleanup code is unsafe to run, and is thus skipped.
1495 //
1496 // Actual shut down logic is factored out to EEShutDownHelper which may be called
1497 // directly by EEShutDown, or indirectly on another thread (see code:#STAShutDown).
1498 //
1499 // In order that callees may also know the value of fIsDllUnloading, EEShutDownHelper
1500 // sets g_fProcessDetach = fIsDllUnloading, and g_fProcessDetach may then be retrieved
1501 // via code:IsAtProcessExit.
1502 //
1503 // NOTE 1: Actually, g_fProcessDetach is set to TRUE if fIsDllUnloading is TRUE. But
1504 // g_fProcessDetach doesn't appear to be explicitly set to FALSE. (Apparently
1505 // g_fProcessDetach is implicitly initialized to FALSE as clr.dll is loaded.)
1506 //
1507 // NOTE 2: EEDllMain(DLL_PROCESS_DETACH) already sets g_fProcessDetach to TRUE, so it
1508 // appears EEShutDownHelper doesn't have to.
1509 //
1510 void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading)
1511 {
1512     CONTRACTL {
1513         NOTHROW;
1514         GC_TRIGGERS;
1515         MODE_ANY;
1516         PRECONDITION(g_fEEStarted);
1517     } CONTRACTL_END;
1518
1519     // If we have not started runtime successfully, it is not safe to call EEShutDown.
1520     if (!g_fEEStarted || g_fFastExitProcess == 2)
1521     {
1522         return;
1523     }
1524
1525     // We only do the first part of the shutdown once.
1526     static LONG OnlyOne = -1;
1527
1528     if (!fIsDllUnloading)
1529     {
1530         if (InterlockedIncrement(&OnlyOne) != 0)
1531         {
1532             // I'm in a regular shutdown -- but another thread got here first.
1533             // It's a race if I return from here -- I'll call ExitProcess next, and
1534             // rip things down while the first thread is half-way through a
1535             // nice cleanup.  Rather than do that, I should just wait until the
1536             // first thread calls ExitProcess().  I'll die a nice death when that
1537             // happens.
1538             GCX_PREEMP_NO_DTOR();
1539             WaitForEndOfShutdown();
1540             return;
1541         }
1542
1543 #ifdef FEATURE_MULTICOREJIT
1544         MulticoreJitManager::StopProfileAll();
1545 #endif
1546     }
1547
1548     if (GetThreadNULLOk())
1549     {
1550         GCX_COOP();
1551         EEShutDownHelper(fIsDllUnloading);
1552     }
1553     else
1554     {
1555         EEShutDownHelper(fIsDllUnloading);
1556     }
1557 }
1558
1559 // ---------------------------------------------------------------------------
1560 // %%Function: IsRuntimeActive()
1561 //
1562 // Parameters:
1563 //  none
1564 //
1565 // Returns:
1566 //  TRUE or FALSE
1567 //
1568 // Description: Indicates if the runtime is active or not. "Active" implies
1569 //              that the runtime has started and is in a position to run
1570 //              managed code.
1571 // ---------------------------------------------------------------------------
1572 BOOL IsRuntimeActive()
1573 {
1574     return (g_fEEStarted);
1575 }
1576
1577 //*****************************************************************************
1578 BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk)
1579 {
1580     CONTRACTL {
1581         if (fFromThunk) THROWS; else NOTHROW;
1582         WRAPPER(GC_TRIGGERS);
1583         MODE_ANY;
1584     } CONTRACTL_END;
1585
1586     // If we have a failure result, and we're called from a thunk,
1587     // then we need to throw an exception to communicate the error.
1588     if (FAILED(hr) && fFromThunk)
1589     {
1590         COMPlusThrowHR(hr);
1591     }
1592     return SUCCEEDED(hr);
1593 }
1594
1595 //
1596 // Initialize the Garbage Collector
1597 //
1598
1599 void InitializeGarbageCollector()
1600 {
1601     CONTRACTL{
1602         THROWS;
1603         GC_TRIGGERS;
1604         MODE_ANY;
1605     } CONTRACTL_END;
1606
1607     HRESULT hr;
1608
1609     // Build the special Free Object used by the Generational GC
1610     _ASSERT(g_pFreeObjectMethodTable == NULL);
1611     g_pFreeObjectMethodTable = (MethodTable *) new BYTE[sizeof(MethodTable)];
1612     ZeroMemory(g_pFreeObjectMethodTable, sizeof(MethodTable));
1613
1614     // As the flags in the method table indicate there are no pointers
1615     // in the object, there is no gc descriptor, and thus no need to adjust
1616     // the pointer to skip the gc descriptor.
1617
1618     g_pFreeObjectMethodTable->SetBaseSize(ARRAYBASE_BASESIZE);
1619     g_pFreeObjectMethodTable->SetComponentSize(1);
1620
1621     hr = GCHeapUtilities::LoadAndInitialize();
1622
1623     if (hr != S_OK)
1624     {
1625         LogErrorToHost("GC initialization failed with error 0x%08X", hr);
1626         ThrowHR(hr);
1627     }
1628
1629     // Apparently the Windows linker removes global variables if they are never
1630     // read from, which is a problem for g_gcDacGlobals since it's expected that
1631     // only the DAC will read from it. This forces the linker to include
1632     // g_gcDacGlobals.
1633     volatile void* _dummy = g_gcDacGlobals;
1634 }
1635
1636 /*****************************************************************************/
1637 /* This is here only so that if we get an exception we stop before we catch it */
1638 LONG DllMainFilter(PEXCEPTION_POINTERS p, PVOID pv)
1639 {
1640     LIMITED_METHOD_CONTRACT;
1641     _ASSERTE(!"Exception happened in mscorwks!DllMain!");
1642     return EXCEPTION_EXECUTE_HANDLER;
1643 }
1644
1645 #if !defined(CORECLR_EMBEDDED)
1646
1647 //*****************************************************************************
1648 // This is the part of the old-style DllMain that initializes the
1649 // stuff that the EE team works on. It's called from the real DllMain
1650 // up in MSCOREE land. Separating the DllMain tasks is simply for
1651 // convenience due to the dual build trees.
1652 //*****************************************************************************
1653 BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error.
1654     HINSTANCE   hInst,             // Instance handle of the loaded module.
1655     DWORD       dwReason,          // Reason for loading.
1656     LPVOID      lpReserved)        // Unused.
1657 {
1658     STATIC_CONTRACT_NOTHROW;
1659     STATIC_CONTRACT_GC_TRIGGERS;
1660
1661     // HRESULT hr;
1662     // BEGIN_EXTERNAL_ENTRYPOINT(&hr);
1663     // EE isn't spun up enough to use this macro
1664
1665     struct Param
1666     {
1667         HINSTANCE hInst;
1668         DWORD dwReason;
1669         LPVOID lpReserved;
1670     } param;
1671     param.hInst = hInst;
1672     param.dwReason = dwReason;
1673     param.lpReserved = lpReserved;
1674
1675     // Can't use PAL_TRY/EX_TRY here as they access the ClrDebugState which gets blown away as part of the
1676     // PROCESS_DETACH path. Must use special PAL_TRY_FOR_DLLMAIN, passing the reason were in the DllMain.
1677     PAL_TRY_FOR_DLLMAIN(Param *, pParam, &param, pParam->dwReason)
1678     {
1679
1680     switch (pParam->dwReason)
1681         {
1682             case DLL_PROCESS_DETACH:
1683             {
1684                 // lpReserved is NULL if we're here because someone called FreeLibrary
1685                 // and non-null if we're here because the process is exiting.
1686                 // Since nobody should ever be calling FreeLibrary on mscorwks.dll, lpReserved
1687                 // should always be non NULL.
1688                 _ASSERTE(pParam->lpReserved || !g_fEEStarted);
1689                 g_fProcessDetach = TRUE;
1690
1691                 if (g_fEEStarted)
1692                 {
1693                     if (GCHeapUtilities::IsGCInProgress())
1694                     {
1695                         g_fEEShutDown |= ShutDown_Phase2;
1696                         break;
1697                     }
1698
1699                     LOG((LF_STARTUP, INFO3, "EEShutDown invoked from EEDllMain"));
1700                     EEShutDown(TRUE); // shut down EE if it was started up
1701                 }
1702                 else
1703                 {
1704                     CLRRemoveVectoredHandlers();
1705                 }
1706                 break;
1707             }
1708         }
1709
1710     }
1711     PAL_EXCEPT_FILTER(DllMainFilter)
1712     {
1713     }
1714     PAL_ENDTRY;
1715
1716     return TRUE;
1717 }
1718
1719 #endif // !defined(CORECLR_EMBEDDED)
1720
1721 struct TlsDestructionMonitor
1722 {
1723     bool m_activated = false;
1724
1725     void Activate()
1726     {
1727         m_activated = true;
1728     }
1729
1730     ~TlsDestructionMonitor()
1731     {
1732         if (m_activated)
1733         {
1734             Thread* thread = GetThreadNULLOk();
1735             if (thread)
1736             {
1737 #ifdef FEATURE_COMINTEROP
1738                 // reset the CoInitialize state
1739                 // so we don't call CoUninitialize during thread detach
1740                 thread->ResetCoInitialized();
1741 #endif // FEATURE_COMINTEROP
1742                 // For case where thread calls ExitThread directly, we need to reset the
1743                 // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode.
1744                 // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode
1745                 if (thread->m_pFrame != FRAME_TOP)
1746                 {
1747 #ifdef _DEBUG
1748                     thread->m_GCOnTransitionsOK = FALSE;
1749 #endif
1750                     GCX_COOP_NO_DTOR();
1751                     thread->m_pFrame = FRAME_TOP;
1752                     GCX_COOP_NO_DTOR_END();
1753                 }
1754                 thread->DetachThread(TRUE);
1755             }
1756
1757             ThreadDetaching();
1758         }
1759     }
1760 };
1761
1762 // This thread local object is used to detect thread shutdown. Its destructor
1763 // is called when a thread is being shut down.
1764 thread_local TlsDestructionMonitor tls_destructionMonitor;
1765
1766 void EnsureTlsDestructionMonitor()
1767 {
1768     tls_destructionMonitor.Activate();
1769 }
1770
1771 #ifdef DEBUGGING_SUPPORTED
1772 //
1773 // InitializeDebugger initialized the Runtime-side COM+ Debugging Services
1774 //
1775 static void InitializeDebugger(void)
1776 {
1777     CONTRACTL
1778     {
1779         THROWS;
1780         GC_TRIGGERS;
1781         MODE_ANY;
1782     }
1783     CONTRACTL_END;
1784
1785     // Ensure that if we throw, we'll call TerminateDebugger to cleanup.
1786     // This makes our Init more atomic by avoiding partially-init states.
1787     class EnsureCleanup {
1788         BOOL    fNeedCleanup;
1789     public:
1790         EnsureCleanup()
1791         {
1792             fNeedCleanup = TRUE;
1793         }
1794
1795         void SuppressCleanup()
1796         {
1797             fNeedCleanup  = FALSE;
1798         }
1799
1800         ~EnsureCleanup()
1801         {
1802              STATIC_CONTRACT_NOTHROW;
1803              STATIC_CONTRACT_GC_NOTRIGGER;
1804              STATIC_CONTRACT_MODE_ANY;
1805
1806             if (fNeedCleanup)
1807             {
1808                 TerminateDebugger();
1809             }
1810         }
1811     } hCleanup;
1812
1813     HRESULT hr = S_OK;
1814
1815     LOG((LF_CORDB, LL_INFO10, "Initializing left-side debugging services.\n"));
1816
1817     FARPROC gi = (FARPROC) &CorDBGetInterface;
1818
1819     // Init the interface the EE provides to the debugger,
1820     // ask the debugger for its interface, and if all goes
1821     // well call Startup on the debugger.
1822     EEDbgInterfaceImpl::Init();
1823     _ASSERTE(g_pEEDbgInterfaceImpl != NULL); // throws on OOM
1824
1825     // This allocates the Debugger object.
1826     typedef HRESULT __cdecl CORDBGETINTERFACE(DebugInterface**);
1827     hr = ((CORDBGETINTERFACE*)gi)(&g_pDebugInterface);
1828     IfFailThrow(hr);
1829
1830     g_pDebugInterface->SetEEInterface(g_pEEDbgInterfaceImpl);
1831
1832     {
1833         hr = g_pDebugInterface->Startup(); // throw on error
1834         _ASSERTE(SUCCEEDED(hr));
1835
1836         //
1837         // If the debug pack is not installed, Startup will return S_FALSE
1838         // and we should cleanup and proceed without debugging support.
1839         //
1840         if (hr != S_OK)
1841         {
1842             return;
1843         }
1844     }
1845
1846
1847     LOG((LF_CORDB, LL_INFO10, "Left-side debugging services setup.\n"));
1848
1849     hCleanup.SuppressCleanup();
1850
1851     return;
1852 }
1853
1854
1855 //
1856 // TerminateDebugger shuts down the Runtime-side COM+ Debugging Services
1857 // InitializeDebugger will call this if it fails.
1858 // This may be called even if the debugger is partially initialized.
1859 // This can be called multiple times.
1860 //
1861 static void TerminateDebugger(void)
1862 {
1863     CONTRACTL
1864     {
1865         NOTHROW;
1866         GC_NOTRIGGER;
1867         MODE_ANY;
1868     }
1869     CONTRACTL_END;
1870
1871     LOG((LF_CORDB, LL_INFO10, "Shutting down left-side debugger services.\n"));
1872
1873     // If initialized failed really early, then we didn't even get the Debugger object.
1874     if (g_pDebugInterface != NULL)
1875     {
1876         // Notify the out-of-process debugger that shutdown of the in-process debugging support has begun. This is only
1877         // really used in interop debugging scenarios.
1878         g_pDebugInterface->ShutdownBegun();
1879
1880         // This will kill the helper thread, delete the Debugger object, and free all resources.
1881         g_pDebugInterface->StopDebugger();
1882     }
1883
1884     g_CORDebuggerControlFlags = DBCF_NORMAL_OPERATION;
1885
1886 }
1887
1888 #endif // DEBUGGING_SUPPORTED
1889
1890 #ifndef LOCALE_SPARENT
1891 #define LOCALE_SPARENT 0x0000006d
1892 #endif
1893
1894 // ---------------------------------------------------------------------------
1895 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
1896 // copy culture name into szBuffer and return length
1897 // ---------------------------------------------------------------------------
1898 extern BOOL g_fFatalErrorOccurredOnGCThread;
1899 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames)
1900 {
1901     CONTRACTL
1902     {
1903         NOTHROW;
1904         GC_NOTRIGGER;
1905         MODE_ANY;
1906         PRECONDITION(CheckPointer(pCultureNames));
1907     }
1908     CONTRACTL_END;
1909
1910     HRESULT hr = S_OK;
1911
1912     EX_TRY
1913     {
1914         InlineSString<LOCALE_NAME_MAX_LENGTH> sCulture;
1915         InlineSString<LOCALE_NAME_MAX_LENGTH> sParentCulture;
1916
1917 #if 0 // Enable and test if/once the unmanaged runtime is localized
1918         Thread * pThread = GetThreadNULLOk();
1919
1920         // When fatal errors have occurred our invariants around GC modes may be broken and attempting to transition to co-op may hang
1921         // indefinitely. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
1922         // getting localized with a non-default thread-specific culture.
1923         // A canonical stack trace that gets here is a fatal error in the GC that comes through:
1924         // coreclr.dll!GetThreadUICultureNames
1925         // coreclr.dll!CCompRC::LoadLibraryHelper
1926         // coreclr.dll!CCompRC::LoadLibrary
1927         // coreclr.dll!CCompRC::GetLibrary
1928         // coreclr.dll!CCompRC::LoadString
1929         // coreclr.dll!CCompRC::LoadString
1930         // coreclr.dll!SString::LoadResourceAndReturnHR
1931         // coreclr.dll!SString::LoadResourceAndReturnHR
1932         // coreclr.dll!SString::LoadResource
1933         // coreclr.dll!EventReporter::EventReporter
1934         // coreclr.dll!EEPolicy::LogFatalError
1935         // coreclr.dll!EEPolicy::HandleFatalError
1936         if (pThread != NULL && !g_fFatalErrorOccurredOnGCThread) {
1937
1938             // Switch to cooperative mode, since we'll be looking at managed objects
1939             // and we don't want them moving on us.
1940             GCX_COOP();
1941
1942             CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
1943
1944             if (pCurrentCulture != NULL)
1945             {
1946                 STRINGREF cultureName = pCurrentCulture->GetName();
1947
1948                 if (cultureName != NULL)
1949                 {
1950                     sCulture.Set(cultureName->GetBuffer(),cultureName->GetStringLength());
1951                 }
1952
1953                 CULTUREINFOBASEREF pParentCulture = pCurrentCulture->GetParent();
1954
1955                 if (pParentCulture != NULL)
1956                 {
1957                     STRINGREF parentCultureName = pParentCulture->GetName();
1958
1959                     if (parentCultureName != NULL)
1960                     {
1961                         sParentCulture.Set(parentCultureName->GetBuffer(),parentCultureName->GetStringLength());
1962                     }
1963
1964                 }
1965             }
1966         }
1967 #endif
1968
1969         // If the lazily-initialized cultureinfo structures aren't initialized yet, we'll
1970         // need to do the lookup the hard way.
1971         if (sCulture.IsEmpty() || sParentCulture.IsEmpty())
1972         {
1973             LocaleIDValue id ;
1974             int tmp; tmp = GetThreadUICultureId(&id);   // TODO: We should use the name instead
1975             _ASSERTE(tmp!=0 && id != UICULTUREID_DONTCARE);
1976             SIZE_T cchParentCultureName=LOCALE_NAME_MAX_LENGTH;
1977             sCulture.Set(id);
1978
1979 #ifndef TARGET_UNIX
1980             if (!::GetLocaleInfoEx((LPCWSTR)sCulture, LOCALE_SPARENT, sParentCulture.OpenUnicodeBuffer(static_cast<COUNT_T>(cchParentCultureName)),static_cast<int>(cchParentCultureName)))
1981             {
1982                 hr = HRESULT_FROM_GetLastError();
1983             }
1984             sParentCulture.CloseBuffer();
1985 #else // !TARGET_UNIX
1986             sParentCulture = sCulture;
1987 #endif // !TARGET_UNIX
1988         }
1989         // (LPCWSTR) to restrict the size to null terminated size
1990         pCultureNames->AppendIfNotThere((LPCWSTR)sCulture);
1991         // Disabling for Dev10 for consistency with managed resource lookup (see AppCompat bug notes in ResourceFallbackManager.cs)
1992         // Also, this is in the wrong order - put after the parent culture chain.
1993         //AddThreadPreferredUILanguages(pCultureNames);
1994         pCultureNames->AppendIfNotThere((LPCWSTR)sParentCulture);
1995         pCultureNames->Append(SString::Empty());
1996     }
1997     EX_CATCH
1998     {
1999         hr=E_OUTOFMEMORY;
2000     }
2001     EX_END_CATCH(SwallowAllExceptions);
2002
2003     return hr;
2004 }
2005
2006 // The exit code for the process is communicated in one of two ways.  If the
2007 // entrypoint returns an 'int' we take that.  Otherwise we take a latched
2008 // process exit code.  This can be modified by the app via System.SetExitCode().
2009 static INT32 LatchedExitCode;
2010
2011 void SetLatchedExitCode (INT32 code)
2012 {
2013     CONTRACTL
2014     {
2015         NOTHROW;
2016         GC_NOTRIGGER;
2017         MODE_ANY;
2018     }
2019     CONTRACTL_END;
2020
2021     STRESS_LOG1(LF_SYNC, LL_INFO10, "SetLatchedExitCode = %d\n", code);
2022     LatchedExitCode = code;
2023 }
2024
2025 INT32 GetLatchedExitCode (void)
2026 {
2027     LIMITED_METHOD_CONTRACT;
2028     return LatchedExitCode;
2029 }
2030
2031 // ---------------------------------------------------------------------------
2032 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2033 // Return an int uniquely describing which language this thread is using for ui.
2034 // ---------------------------------------------------------------------------
2035 static int GetThreadUICultureId(_Out_ LocaleIDValue* pLocale)
2036 {
2037     CONTRACTL{
2038         NOTHROW;
2039         GC_NOTRIGGER;
2040         MODE_ANY;
2041     } CONTRACTL_END;
2042
2043     _ASSERTE(sizeof(LocaleIDValue)/sizeof(WCHAR) >= LOCALE_NAME_MAX_LENGTH);
2044
2045     int Result = 0;
2046
2047     Thread * pThread = GetThreadNULLOk();
2048
2049 #if 0 // Enable and test if/once the unmanaged runtime is localized
2050     // When fatal errors have occurred our invariants around GC modes may be broken and attempting to transition to co-op may hang
2051     // indefinitely. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
2052     // getting localized with a non-default thread-specific culture.
2053     // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2054     // coreclr.dll!GetThreadUICultureNames
2055     // coreclr.dll!CCompRC::LoadLibraryHelper
2056     // coreclr.dll!CCompRC::LoadLibrary
2057     // coreclr.dll!CCompRC::GetLibrary
2058     // coreclr.dll!CCompRC::LoadString
2059     // coreclr.dll!CCompRC::LoadString
2060     // coreclr.dll!SString::LoadResourceAndReturnHR
2061     // coreclr.dll!SString::LoadResourceAndReturnHR
2062     // coreclr.dll!SString::LoadResource
2063     // coreclr.dll!EventReporter::EventReporter
2064     // coreclr.dll!EEPolicy::LogFatalError
2065     // coreclr.dll!EEPolicy::HandleFatalError
2066     if (pThread != NULL && !g_fFatalErrorOccurredOnGCThread)
2067     {
2068
2069         // Switch to cooperative mode, since we'll be looking at managed objects
2070         // and we don't want them moving on us.
2071         GCX_COOP();
2072
2073         CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2074
2075         if (pCurrentCulture != NULL)
2076         {
2077             STRINGREF currentCultureName = pCurrentCulture->GetName();
2078
2079             if (currentCultureName != NULL)
2080             {
2081                 int cchCurrentCultureNameResult = currentCultureName->GetStringLength();
2082                 if (cchCurrentCultureNameResult < LOCALE_NAME_MAX_LENGTH)
2083                 {
2084                     memcpy(*pLocale, currentCultureName->GetBuffer(), cchCurrentCultureNameResult*sizeof(WCHAR));
2085                     (*pLocale)[cchCurrentCultureNameResult]='\0';
2086                     Result=cchCurrentCultureNameResult;
2087                 }
2088             }
2089         }
2090     }
2091 #endif
2092     if (Result == 0)
2093     {
2094 #ifndef TARGET_UNIX
2095         // This thread isn't set up to use a non-default culture. Let's grab the default
2096         // one and return that.
2097
2098         Result = ::GetUserDefaultLocaleName(*pLocale, LOCALE_NAME_MAX_LENGTH);
2099
2100         _ASSERTE(Result != 0);
2101 #else // !TARGET_UNIX
2102         static const WCHAR enUS[] = W("en-US");
2103         memcpy(*pLocale, enUS, sizeof(enUS));
2104         Result = sizeof(enUS);
2105 #endif // !TARGET_UNIX
2106     }
2107     return Result;
2108 }
2109
2110 #ifdef ENABLE_CONTRACTS_IMPL
2111
2112 // Returns TRUE if any contract violation suppressions are in effect.
2113 BOOL AreAnyViolationBitsOn()
2114 {
2115     CONTRACTL
2116     {
2117         NOTHROW;
2118         GC_NOTRIGGER;
2119         MODE_ANY;
2120     }
2121     CONTRACTL_END;
2122     UINT_PTR violationMask = GetClrDebugState()->ViolationMask();
2123     violationMask &= ~((UINT_PTR)CanFreeMe);  //CanFreeMe is a borrowed bit and has nothing to do with violations
2124     if (violationMask & ((UINT_PTR)BadDebugState))
2125     {
2126         return FALSE;
2127     }
2128
2129     return violationMask != 0;
2130 }
2131
2132
2133 // This function is intentionally invoked inside a big CONTRACT_VIOLATION that turns on every violation
2134 // bit on the map. The dynamic contract at the beginning *should* turn off those violation bits.
2135 // The body of this function tests to see that it did exactly that. This is to prevent the VSWhidbey B#564831 fiasco
2136 // from ever recurring.
2137 void ContractRegressionCheckInner()
2138 {
2139     // DO NOT TURN THIS CONTRACT INTO A STATIC CONTRACT!!! The very purpose of this function
2140     // is to ensure that dynamic contracts disable outstanding contract violation bits.
2141     // This code only runs once at process startup so it's not going pooch the checked build perf.
2142     CONTRACTL
2143     {
2144         NOTHROW;
2145         GC_NOTRIGGER;
2146         FORBID_FAULT;
2147         LOADS_TYPE(CLASS_LOAD_BEGIN);
2148         CANNOT_TAKE_LOCK;
2149     }
2150     CONTRACTL_END
2151
2152     if (AreAnyViolationBitsOn())
2153     {
2154         // If we got here, the contract above FAILED to turn off one or more violation bits. This is a
2155         // huge diagnostics hole and must be fixed immediately.
2156         _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2157                    " being silently disabled across the runtime. Do not ignore this assert!"));
2158     }
2159 }
2160
2161 // This function executes once per process to ensure our CONTRACT_VIOLATION() mechanism
2162 // is properly scope-limited by nested contracts.
2163 void ContractRegressionCheck()
2164 {
2165     CONTRACTL
2166     {
2167         NOTHROW;
2168         GC_NOTRIGGER;
2169         MODE_ANY;
2170     }
2171     CONTRACTL_END;
2172
2173     {
2174         // DO NOT "FIX" THIS CONTRACT_VIOLATION!!!
2175         // The existence of this CONTRACT_VIOLATION is not a bug. This is debug-only code specifically written
2176         // to test the CONTRACT_VIOLATION mechanism itself. This is needed to prevent a regression of
2177         // B#564831 (which left a huge swath of contracts silently disabled for over six months)
2178         PERMANENT_CONTRACT_VIOLATION(ThrowsViolation
2179                                    | GCViolation
2180                                    | FaultViolation
2181                                    | LoadsTypeViolation
2182                                    | TakesLockViolation
2183                                    , ReasonContractInfrastructure
2184                                     );
2185         {
2186             FAULT_NOT_FATAL();
2187             ContractRegressionCheckInner();
2188         }
2189     }
2190
2191     if (AreAnyViolationBitsOn())
2192     {
2193         // If we got here, the CONTRACT_VIOLATION() holder left one or more violation bits turned ON
2194         // after we left its scope. This is a huge diagnostic hole and must be fixed immediately.
2195         _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2196                    " being silently disabled across the runtime. Do not ignore this assert!"));
2197     }
2198
2199 }
2200
2201 #endif // ENABLE_CONTRACTS_IMPL
2202