Merge pull request #2277 from kouvel/FinalizerDeadlockUndo
[platform/upstream/coreclr.git] / src / debug / di / cordb.cpp
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 //
5 //*****************************************************************************
6 // CorDB.cpp
7 // 
8
9 //
10 // Dll* routines for entry points, and support for COM framework.  The class
11 // factory and other routines live in this module.
12 //
13 //*****************************************************************************
14 #include "stdafx.h"
15 #include "classfactory.h"
16 #include "corsym.h"
17 #include "contract.h"
18 #include "metadataexports.h"
19 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
20 #include "dbgtransportsession.h"
21 #include "dbgtransportmanager.h"
22 #endif // FEATURE_DBGIPC_TRANSPORT_DI
23
24 //********** Globals. *********************************************************
25 #ifndef FEATURE_PAL
26 HINSTANCE       g_hInst;                // Instance handle to this piece of code.
27 #endif
28
29 //-----------------------------------------------------------------------------
30 // SxS Versioning story for Mscordbi (ICorDebug + friends)
31 //-----------------------------------------------------------------------------
32
33 //-----------------------------------------------------------------------------
34 // In v1.0, we declared that mscordbi was a "shared" component, which means
35 // that we promised to provide it from now until the end of time. So every CLR implementation
36 // needs an Mscordbi that implements the everett guids for CorDebug + CorPublish.
37 //
38 // This works fine for CorPublish, which is truly shared.
39 // CorDebug however is "versioned" not "shared" - each version of the CLR has its own disjoint copy.
40 //
41 // Thus creating a CorDebug object requires a version parameter.
42 // CoCreateInstance doesn't have a the version param, so we use the new (v2.0+)
43 // shim interface CreateDebuggingInterfaceFromVersion.
44 //
45 // ** So in summary: **
46 // - Dlls don't do self-registration; they're registered by setup using .vrg files.
47 // - All CLR versions (past + future) must have the same registry footprint w.r.t mscordbi.
48 //     This just means that all CLRs have the same mscordbi.vrg file.
49 // - CorDebug is in fact versioned and each CLR version has its own copy.
50 // - In v1.0/1.1, CorDebug was a CoClass. In v2.0+, it is not a CoClass and is created via the
51 //     CreateDebuggingInterfaceFromVersion shim API, which takes a version parameter.
52 // - CorDebug must be SxS. V1.1 must only get the V1.1 version, and V2.0 must only get the V2.0 version.
53 //     V1.1: Clients will cocreate to get CorDebug. v1.1 will be the only mscordbi!DllGetClassObject
54 //           that provides a CorDebug, so CoCreateInstance will guarantee getting a v1.1 object.
55 //     V2.0: Clients use the new version-aware shim API, so it's not an issue.
56 //
57 // ** Preparing for Life in a Single-CLR world: **
58 // In Orcas (v3), we expect to run on single-CLR. There will only be 1 mscordbi, and it will service all versions.
59 // For whidbey (v2), we want to be able to flip a knob and pretend to be orcas (for testing purposes).
60 //
61 // Here's how to do that:
62 // - copy whidbey mscordbi & dac over the everett mscordbi.
63 // - When VS cocreates w/ the everett-guid, it will load the mscordbi on the everett path (
64 //   which will be whidbey dll), and ask for the everett guid.
65 // - re-add CorDebug to the g_CoClasses list.
66
67
68 //********** Locals. **********************************************************
69
70
71 //********** Code. ************************************************************
72
73
74 //*****************************************************************************
75 // Standard public helper to create a Cordb object (ICorDebug instance).
76 // This is used by the shim to get the Cordb object out of this module.
77 // This is the creation path for V2.0+ for CorDebug using the in-process debugging
78 // architecture (ICorDebug).  In CLR v4+ debugger may choose to use the out-of-process
79 // architecture to get an ICorDebugProcess directly (IClrDebugging::OpenVirtualProcess).
80 //
81 // This was used by the Mix07 release of Silverlight, but it didn't properly support versioning
82 // and we no longer support it's debugger protocol so we require callers to use 
83 // code:CoreCLRCreateCordbObject instead.
84 // 
85 // This is also still used on Mac - multi-instance debugging and debugger
86 // versioning isn't really implemented there yet.  This probably needs to change.
87 //*****************************************************************************
88 STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb)
89 {
90 #if defined(FEATURE_CORECLR) && !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM)
91     // This API should not be called for Windows CoreCLR unless we are doing interop-debugging
92     // (which is only supported internally).  Use code:CoreCLRCreateCordbObject instead.
93     if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0)
94     {
95         _ASSERTE(!"Deprecated entry point CreateCordbObject() is called on Windows CoreCLR\n");
96         return E_NOTIMPL;
97     }
98 #endif // FEATURE_CORECLR && !FEATURE_DBGIPC_TRANSPORT_DI
99
100     if (ppCordb == NULL)
101     {
102         return E_INVALIDARG;
103     }
104     if (iDebuggerVersion != CorDebugVersion_2_0 && iDebuggerVersion != CorDebugVersion_4_0)
105     {
106         return E_INVALIDARG;
107     }
108
109     return Cordb::CreateObject((CorDebugInterfaceVersion)iDebuggerVersion, IID_ICorDebug, (void **) ppCordb);
110 }
111
112 #if defined(FEATURE_CORECLR)
113 //
114 // Public API.  
115 // Telesto Creation path - only way to debug multi-instance.  
116 // This supercedes code:CreateCordbObject
117 // 
118 // Arguments:
119 //    iDebuggerVersion - version of ICorDebug interfaces that the debugger is requesting
120 //    pid - pid of debuggee that we're attaching to.
121 //    hmodTargetCLR - module handle to clr in target pid that we're attaching to.
122 //    ppCordb - (out) the resulting ICorDebug object.
123 //
124 // Notes:
125 //    It's inconsistent that this takes a (handle, pid) but hands back an ICorDebug instead of an ICorDebugProcess.
126 //    Callers will need to call *ppCordb->DebugActiveProcess(pid).
127 STDAPI CoreCLRCreateCordbObject(int iDebuggerVersion, DWORD pid, HMODULE hmodTargetCLR, IUnknown ** ppCordb)
128 {
129     if (ppCordb == NULL)
130     {
131         return E_INVALIDARG;
132     }
133     if ((iDebuggerVersion < CorDebugVersion_2_0) ||
134         (iDebuggerVersion > CorDebugLatestVersion))
135     {
136         return E_INVALIDARG;
137     }
138
139     //
140     // Create the ICorDebug object
141     // 
142     RSExtSmartPtr<ICorDebug> pCordb;
143     Cordb::CreateObject((CorDebugInterfaceVersion)iDebuggerVersion, IID_ICorDebug, (void **) &pCordb);
144
145     // @dbgtodo - we should stash the pid and validate that it's the same pid we're attaching to in ICorDebug::DebugActiveProcess.
146     
147     //
148     // Associate it with the target instance
149     //
150     HRESULT hr = static_cast<Cordb*>(pCordb.GetValue())->SetTargetCLR(hmodTargetCLR);
151     if (FAILED(hr))
152     {
153         return hr;
154     }
155
156     //
157     // Assign to out parameter.
158     // 
159     hr = pCordb->QueryInterface(IID_IUnknown, (void**) ppCordb);
160
161     // Implicit release of pUnk, pCordb
162     return hr;
163 }
164
165 #endif // FEATURE_CORECLR
166
167
168
169
170 //*****************************************************************************
171 // The main dll entry point for this module.  This routine is called by the
172 // OS when the dll gets loaded.  Control is simply deferred to the main code.
173 //*****************************************************************************
174 BOOL WINAPI DbgDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
175 {
176     // Save off the instance handle for later use.
177     switch (dwReason)
178     {
179
180         case DLL_PROCESS_ATTACH:
181         {
182 #ifndef FEATURE_PAL
183             g_hInst = hInstance;
184 #else
185             int err = PAL_InitializeDLL();
186             if(err != 0)
187             {
188                 return FALSE;
189             }
190 #endif
191
192 #if defined(_DEBUG)
193             static int BreakOnDILoad = -1;
194             if (BreakOnDILoad == -1)
195                 BreakOnDILoad = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnDILoad);
196
197             if (BreakOnDILoad)
198             {
199                 _ASSERTE(!"DI Loaded");
200             }
201 #endif
202
203 #if defined(LOGGING)
204             {
205                 WCHAR   rcFile[_MAX_PATH];
206                 WszGetModuleFileName(hInstance, rcFile, NumItems(rcFile));
207                 LOG((LF_CORDB, LL_INFO10000,
208                     "DI::DbgDllMain: load right side support from file '%s'\n",
209                      rcFile));
210             }
211 #endif
212
213 #ifdef RSCONTRACTS
214             // alloc a TLS slot
215             DbgRSThread::s_TlsSlot = TlsAlloc();
216             _ASSERTE(DbgRSThread::s_TlsSlot != TLS_OUT_OF_INDEXES);
217 #endif
218
219 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
220             g_pDbgTransportTarget = new (nothrow) DbgTransportTarget();
221             if (g_pDbgTransportTarget == NULL)
222                 return FALSE;
223
224             if (FAILED(g_pDbgTransportTarget->Init()))
225                 return FALSE;
226 #endif // FEATURE_DBGIPC_TRANSPORT_DI
227         }
228         break;
229
230         case DLL_THREAD_DETACH:
231         {
232 #ifdef STRESS_LOG
233             StressLog::ThreadDetach((ThreadStressLog*) ClrFlsGetValue(TlsIdx_StressLog));
234 #endif
235
236 #ifdef RSCONTRACTS
237             // DbgRSThread are lazily created when we call GetThread(),
238             // So we don't need to do anything in DLL_THREAD_ATTACH,
239             // But this is our only chance to destroy the thread object.
240             DbgRSThread * p = DbgRSThread::GetThread();
241
242             p->Destroy();
243 #endif
244         }
245         break;
246
247         case DLL_PROCESS_DETACH:
248         {
249 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
250             if (g_pDbgTransportTarget != NULL)
251             {
252                 g_pDbgTransportTarget->Shutdown();
253                 delete g_pDbgTransportTarget;
254                 g_pDbgTransportTarget = NULL;
255             }
256 #endif // FEATURE_DBGIPC_TRANSPORT_DI
257             
258 #ifdef RSCONTRACTS
259             TlsFree(DbgRSThread::s_TlsSlot);
260             DbgRSThread::s_TlsSlot = TLS_OUT_OF_INDEXES;
261 #endif
262         }
263         break;
264     }
265
266     return TRUE;
267 }
268
269
270 // The obsolete v1 CLSID - see comment above for details.
271 static const GUID CLSID_CorDebug_V1 = {0x6fef44d0,0x39e7,0x4c77, { 0xbe,0x8e,0xc9,0xf8,0xcf,0x98,0x86,0x30}};
272
273 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
274
275 // GUID for pipe-based debugging (Unix platforms)
276 const GUID CLSID_CorDebug_Telesto = {0x8bd1daae, 0x188e, 0x42f4, {0xb0, 0x09, 0x08, 0xfa, 0xfd, 0x17, 0x81, 0x3b}};
277
278 // The debug engine needs to implement an internal Visual Studio debugger interface (defined by the CPDE)
279 // which augments launch and attach requests so that we can obtain information from the port supplier (the
280 // network address of the target in our case). See RSPriv.h for the definition of the interface. (We have to
281 // hard code the IID and interface definition because VS does not export it, but it's not much of an issue
282 // since COM interfaces are completely immutable).
283 const GUID IID_IDebugRemoteCorDebug = {0x83C91210, 0xA34F, 0x427c, {0xB3, 0x5F, 0x79, 0xC3, 0x99, 0x5B, 0x3C, 0x14}};
284 #endif // FEATURE_DBGIPC_TRANSPORT_DI
285
286 //*****************************************************************************
287 // Called by COM to get a class factory for a given CLSID.  If it is one we
288 // support, instantiate a class factory object and prepare for create instance.
289 //*****************************************************************************
290 STDAPI DllGetClassObjectInternal(               // Return code.
291     REFCLSID    rclsid,                 // The class to desired.
292     REFIID      riid,                   // Interface wanted on class factory.
293     LPVOID FAR  *ppv)                   // Return interface pointer here.
294 {
295     HRESULT         hr;
296     CClassFactory   *pClassFactory;         // To create class factory object.
297     PFN_CREATE_OBJ  pfnCreateObject = NULL;
298
299
300 #if defined(FEATURE_DBG_PUBLISH)
301     if (rclsid == CLSID_CorpubPublish)
302     {
303         pfnCreateObject = CorpubPublish::CreateObject;
304     }
305     else
306 #endif
307 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
308     if (rclsid == CLSID_CorDebug_Telesto)
309     {
310         pfnCreateObject = Cordb::CreateObjectTelesto;
311     }
312 #else  // !FEATURE_DBGIPC_TRANSPORT_DI
313     if(rclsid == CLSID_CorDebug_V1)
314     {
315         if (0) // if (IsSingleCLR())
316         {
317             // Don't allow creating backwards objects until we ensure that the v2.0 Right-side
318             // is backwards compat. This may involve using CordbProcess::SupportsVersion to conditionally
319             // emulate old behavior.
320             // If emulating V1.0, QIs for V2.0 interfaces should fail.
321             _ASSERTE(!"Ensure that V2.0 RS is backwards compat");
322             pfnCreateObject = Cordb::CreateObjectV1;
323         }
324     }
325 #endif // FEATURE_DBGIPC_TRANSPORT_DI
326
327     if (pfnCreateObject == NULL)
328         return (CLASS_E_CLASSNOTAVAILABLE);
329
330     // Allocate the new factory object.  The ref count is set to 1 in the constructor.
331     pClassFactory = new (nothrow) CClassFactory(pfnCreateObject);
332     if (!pClassFactory)
333         return (E_OUTOFMEMORY);
334
335     // Pick the v-table based on the caller's request.
336     hr = pClassFactory->QueryInterface(riid, ppv);
337
338     // Always release the local reference, if QI failed it will be
339     // the only one and the object gets freed.
340     pClassFactory->Release();
341
342     return hr;
343 }
344
345 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
346 // In V2 we started hiding DllGetClassObject because activation was no longer performed through COM directly
347 // (we went through the shim). CoreCLR doesn't have a shim and we go back to the COM model so we re-expose
348 // DllGetClassObject to make that work.
349
350 STDAPI DllGetClassObject(               // Return code.
351     REFCLSID    rclsid,                 // The class to desired.
352     REFIID      riid,                   // Interface wanted on class factory.
353     LPVOID FAR  *ppv)                   // Return interface pointer here.
354 {
355     return DllGetClassObjectInternal(rclsid, riid, ppv);
356 }
357 #endif // FEATURE_DBGIPC_TRANSPORT_DI
358
359
360 //*****************************************************************************
361 //
362 //********** Class factory code.
363 //
364 //*****************************************************************************
365
366
367 //*****************************************************************************
368 // QueryInterface is called to pick a v-table on the co-class.
369 //*****************************************************************************
370 HRESULT STDMETHODCALLTYPE CClassFactory::QueryInterface(
371     REFIID      riid,
372     void        **ppvObject)
373 {
374     HRESULT     hr;
375
376     // Avoid confusion.
377     *ppvObject = NULL;
378
379     // Pick the right v-table based on the IID passed in.
380     if (riid == IID_IUnknown)
381         *ppvObject = (IUnknown *) this;
382     else if (riid == IID_IClassFactory)
383         *ppvObject = (IClassFactory *) this;
384
385     // If successful, add a reference for out pointer and return.
386     if (*ppvObject)
387     {
388         hr = S_OK;
389         AddRef();
390     }
391     else
392         hr = E_NOINTERFACE;
393     return (hr);
394 }
395
396
397 //*****************************************************************************
398 // CreateInstance is called to create a new instance of the coclass for which
399 // this class was created in the first place.  The returned pointer is the
400 // v-table matching the IID if there.
401 //*****************************************************************************
402 HRESULT STDMETHODCALLTYPE CClassFactory::CreateInstance(
403     IUnknown    *pUnkOuter,
404     REFIID      riid,
405     void        **ppvObject)
406 {
407     HRESULT     hr;
408
409     // Avoid confusion.
410     *ppvObject = NULL;
411     _ASSERTE(m_pfnCreateObject);
412
413     // Aggregation is not supported by these objects.
414     if (pUnkOuter)
415         return (CLASS_E_NOAGGREGATION);
416
417     // Ask the object to create an instance of itself, and check the iid.
418     hr = (*m_pfnCreateObject)(riid, ppvObject);
419     return (hr);
420 }
421
422
423 HRESULT STDMETHODCALLTYPE CClassFactory::LockServer(
424     BOOL        fLock)
425 {
426 //<TODO>@todo: hook up lock server logic.</TODO>
427     return (S_OK);
428 }
429
430
431 //*****************************************************************************
432 // This helper provides access to the instance handle of the loaded image.
433 //*****************************************************************************
434 #ifndef FEATURE_PAL
435 HINSTANCE GetModuleInst()
436 {
437     return g_hInst;
438 }
439 #endif
440
441
442 //-----------------------------------------------------------------------------
443 // Substitute for mscoree
444 // 
445 // Notes:
446 //    Mscordbi does not link with mscoree, provide a stub implementation. 
447 //    Callers are in dead-code paths, but we still need to provide a stub. Ideally, we'd factor
448 //    out the callers too and then we wouldn't need an E_NOTIMPL stub.
449 STDAPI GetRequestedRuntimeInfo(LPCWSTR pExe, 
450                                LPCWSTR pwszVersion, 
451                                LPCWSTR pConfigurationFile, 
452                                DWORD startupFlags, 
453                                DWORD runtimeInfoFlags, 
454                                __out_ecount_opt(dwDirectory) LPWSTR pDirectory, 
455                                DWORD dwDirectory, 
456                                DWORD *dwDirectoryLength, 
457                                __out_ecount_opt(cchBuffer)   LPWSTR pVersion, 
458                                DWORD cchBuffer, 
459                                DWORD* dwlength)
460 {
461     _ASSERTE(!"GetRequestedRuntimeInfo not impl");
462     return E_NOTIMPL;
463 }
464
465 //-----------------------------------------------------------------------------
466 // Replacement for legacy shim API GetCORRequiredVersion(...) used in linked libraries.
467 // Used in code:TiggerStorage::GetDefaultVersion#CallTo_CLRRuntimeHostInternal_GetImageVersionString.
468 // 
469 // Notes:
470 //   Mscordbi does not statically link to mscoree.dll.
471 //   This is used in EnC for IMetadataEmit2::GetSaveSize to computer size of header.
472 //   see code:TiggerStorage::GetDefaultVersion.
473 //   
474 //   Implemented by returning the version we're built for.  Mscordbi.dll has a tight coupling with
475 //   the CLR version, so this will match exactly the build version we're debugging.  
476 //   One potential caveat is that the build version doesn't necessarily match the install string
477 //   (eg. we may install as "v4.0.x86chk" but that's not captured in the build version).  But this should
478 //   be internal scenarios only, and shouldn't actually matter here.  If it did, we could instead get
479 //   the last components of the directory name the current mscordbi.dll is located in.
480 //     
481 HRESULT 
482 CLRRuntimeHostInternal_GetImageVersionString(
483     __out_ecount_part(*pcchBuffer, *pcchBuffer) LPWSTR wszBuffer, 
484     DWORD *pcchBuffer)
485 {
486     // Construct the cannoncial version string we're built as - eg. "v4.0.1234"
487     const WCHAR k_wszBuiltFor[] = W("v") VER_PRODUCTVERSION_NO_QFE_STR_L;
488
489     // Copy our buffer in
490     HRESULT hr = HRESULT_FROM_WIN32(wcscpy_s(wszBuffer, *pcchBuffer, k_wszBuiltFor));
491
492     // Hand out length regardless of success - like GetCORRequiredVersion
493     *pcchBuffer = _countof(k_wszBuiltFor);
494
495     return hr;
496 } // CLRRuntimeHostInternal_GetImageVersionString
497
498
499 #ifdef _TARGET_ARM_
500 BOOL
501 DbiGetThreadContext(HANDLE hThread,
502     DT_CONTEXT *lpContext)
503 {
504     // if we aren't local debugging this isn't going to work
505 #if !defined(_ARM_) || defined(FEATURE_DBGIPC_TRANSPORT_DI)
506     _ASSERTE(!"Can't use local GetThreadContext remotely, this needed to go to datatarget");
507     return FALSE;
508 #else
509     BOOL res = FALSE;
510     if (((ULONG)lpContext) & ~0x10)
511     {
512         CONTEXT *ctx = (CONTEXT*)_aligned_malloc(sizeof(CONTEXT), 16);
513         if (ctx)
514         {
515             ctx->ContextFlags = lpContext->ContextFlags;
516             if (::GetThreadContext(hThread, ctx))
517             {
518                 *lpContext = *(DT_CONTEXT*)ctx;
519                 res = TRUE;
520             }
521
522             _aligned_free(ctx);
523         }
524         else
525         {
526             // malloc does not set the last error, but the caller of GetThreadContext
527             // will expect it to be set on failure.
528             SetLastError(ERROR_OUTOFMEMORY);
529         }
530     }
531     else
532     {
533         res = ::GetThreadContext(hThread, (CONTEXT*)lpContext);
534     }
535     
536     return res;
537 #endif
538 }
539
540 BOOL
541 DbiSetThreadContext(HANDLE hThread,
542     const DT_CONTEXT *lpContext)
543 {
544 #if !defined(_ARM_) || defined(FEATURE_DBGIPC_TRANSPORT_DI)
545     _ASSERTE(!"Can't use local GetThreadContext remotely, this needed to go to datatarget");
546     return FALSE;
547 #else
548     BOOL res = FALSE;
549     if (((ULONG)lpContext) & ~0x10)
550     {
551         CONTEXT *ctx = (CONTEXT*)_aligned_malloc(sizeof(CONTEXT), 16);
552         if (ctx)
553         {
554             *ctx = *(CONTEXT*)lpContext;
555             res = ::SetThreadContext(hThread, ctx);
556             _aligned_free(ctx);
557         }   
558         else
559         {
560             // malloc does not set the last error, but the caller of SetThreadContext
561             // will expect it to be set on failure.
562             SetLastError(ERROR_OUTOFMEMORY);
563         }
564     }
565     else
566     {
567         res = ::SetThreadContext(hThread, (CONTEXT*)lpContext);
568     }
569     
570     return res;
571 #endif
572 }
573 #endif