1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// File: debugger.cpp
6//
7
8//
9// Debugger runtime controller routines.
10//
11//*****************************************************************************
12
13#include "stdafx.h"
14#include "debugdebugger.h"
15#include "../inc/common.h"
16#include "perflog.h"
17#include "eeconfig.h" // This is here even for retail & free builds...
18#include "../../dlls/mscorrc/resource.h"
19
20#include "vars.hpp"
21#include <limits.h>
22#include "ilformatter.h"
23#include "typeparse.h"
24#include "debuginfostore.h"
25#include "generics.h"
26#include "../../vm/methoditer.h"
27#include "../../vm/encee.h"
28#include "../../vm/dwreport.h"
29#include "../../vm/eepolicy.h"
30#include "../../vm/excep.h"
31#if defined(FEATURE_DBGIPC_TRANSPORT_VM)
32#include "dbgtransportsession.h"
33#endif // FEATURE_DBGIPC_TRANSPORT_VM
34
35#ifdef TEST_DATA_CONSISTENCY
36#include "datatest.h"
37#endif // TEST_DATA_CONSISTENCY
38
39#include "dbgenginemetrics.h"
40
41#include "../../vm/rejit.h"
42
43#include "threadsuspend.h"
44
45
46#ifdef DEBUGGING_SUPPORTED
47
48#ifdef _DEBUG
49// Reg key. We can set this and then any debugger-lazy-init code will assert.
50// This helps track down places where we're caching in debugger stuff in a
51// non-debugger scenario.
52bool g_DbgShouldntUseDebugger = false;
53#endif
54
55
56/* ------------------------------------------------------------------------ *
57 * Global variables
58 * ------------------------------------------------------------------------ */
59
60GPTR_IMPL(Debugger, g_pDebugger);
61GPTR_IMPL(EEDebugInterface, g_pEEInterface);
62SVAL_IMPL_INIT(BOOL, Debugger, s_fCanChangeNgenFlags, TRUE);
63
64// This is a public export so debuggers can read and determine if the coreclr
65// process is waiting for JIT debugging attach.
66GVAL_IMPL_INIT(ULONG, CLRJitAttachState, 0);
67
68bool g_EnableSIS = false;
69
70// The following instances are used for invoking overloaded new/delete
71InteropSafe interopsafe;
72InteropSafeExecutable interopsafeEXEC;
73
74#ifndef DACCESS_COMPILE
75
76DebuggerRCThread *g_pRCThread = NULL;
77
78#ifndef _PREFAST_
79// Do some compile time checking on the events in DbgIpcEventTypes.h
80// No one ever calls this. But the compiler should still compile it,
81// and that should be sufficient.
82void DoCompileTimeCheckOnDbgIpcEventTypes()
83{
84 _ASSERTE(!"Don't call this function. It just does compile time checking\n");
85
86 // We use the C_ASSERT macro here to get a compile-time assert.
87
88 // Make sure we don't have any duplicate numbers.
89 // The switch statements in the main loops won't always catch this
90 // since we may not switch on all events.
91
92 // store Type-0 in const local vars, so we can use them for bounds checking
93 // Create local vars with the val from Type1 & Type2. If there are any
94 // collisions, then the variables' names will collide at compile time.
95 #define IPC_EVENT_TYPE0(type, val) const int e_##type = val;
96 #define IPC_EVENT_TYPE1(type, val) int T_##val; T_##val = 0;
97 #define IPC_EVENT_TYPE2(type, val) int T_##val; T_##val = 0;
98 #include "dbgipceventtypes.h"
99 #undef IPC_EVENT_TYPE2
100 #undef IPC_EVENT_TYPE1
101 #undef IPC_EVENT_TYPE0
102
103 // Ensure that all identifiers are unique and are matched with
104 // integer values.
105 #define IPC_EVENT_TYPE0(type, val) int T2_##type; T2_##type = val;
106 #define IPC_EVENT_TYPE1(type, val) int T2_##type; T2_##type = val;
107 #define IPC_EVENT_TYPE2(type, val) int T2_##type; T2_##type = val;
108 #include "dbgipceventtypes.h"
109 #undef IPC_EVENT_TYPE2
110 #undef IPC_EVENT_TYPE1
111 #undef IPC_EVENT_TYPE0
112
113 // Make sure all values are subset of the bits specified by DB_IPCE_TYPE_MASK
114 #define IPC_EVENT_TYPE0(type, val)
115 #define IPC_EVENT_TYPE1(type, val) C_ASSERT((val & e_DB_IPCE_TYPE_MASK) == val);
116 #define IPC_EVENT_TYPE2(type, val) C_ASSERT((val & e_DB_IPCE_TYPE_MASK) == val);
117 #include "dbgipceventtypes.h"
118 #undef IPC_EVENT_TYPE2
119 #undef IPC_EVENT_TYPE1
120 #undef IPC_EVENT_TYPE0
121
122 // Make sure that no value is DB_IPCE_INVALID_EVENT
123 #define IPC_EVENT_TYPE0(type, val)
124 #define IPC_EVENT_TYPE1(type, val) C_ASSERT(val != e_DB_IPCE_INVALID_EVENT);
125 #define IPC_EVENT_TYPE2(type, val) C_ASSERT(val != e_DB_IPCE_INVALID_EVENT);
126 #include "dbgipceventtypes.h"
127 #undef IPC_EVENT_TYPE2
128 #undef IPC_EVENT_TYPE1
129 #undef IPC_EVENT_TYPE0
130
131 // Make sure first-last values are well structured.
132 static_assert_no_msg(e_DB_IPCE_RUNTIME_FIRST < e_DB_IPCE_RUNTIME_LAST);
133 static_assert_no_msg(e_DB_IPCE_DEBUGGER_FIRST < e_DB_IPCE_DEBUGGER_LAST);
134
135 // Make sure that event ranges don't overlap.
136 // This check is simplified because L->R events come before R<-L
137 static_assert_no_msg(e_DB_IPCE_RUNTIME_LAST < e_DB_IPCE_DEBUGGER_FIRST);
138
139
140 // Make sure values are in the proper ranges
141 // Type1 should be in the Runtime range, Type2 in the Debugger range.
142 #define IPC_EVENT_TYPE0(type, val)
143 #define IPC_EVENT_TYPE1(type, val) C_ASSERT((e_DB_IPCE_RUNTIME_FIRST <= val) && (val < e_DB_IPCE_RUNTIME_LAST));
144 #define IPC_EVENT_TYPE2(type, val) C_ASSERT((e_DB_IPCE_DEBUGGER_FIRST <= val) && (val < e_DB_IPCE_DEBUGGER_LAST));
145 #include "dbgipceventtypes.h"
146 #undef IPC_EVENT_TYPE2
147 #undef IPC_EVENT_TYPE1
148 #undef IPC_EVENT_TYPE0
149
150 // Make sure that events are in increasing order
151 // It's ok if the events skip numbers.
152 // This is a more specific check than the range check above.
153
154 /* Expands to look like this:
155 const bool f = (
156 first <=
157 10) && (10 <
158 11) && (11 <
159 12) && (12 <
160 last)
161 static_assert_no_msg(f);
162 */
163
164 const bool f1 = (
165 (e_DB_IPCE_RUNTIME_FIRST <=
166 #define IPC_EVENT_TYPE0(type, val)
167 #define IPC_EVENT_TYPE1(type, val) val) && (val <
168 #define IPC_EVENT_TYPE2(type, val)
169 #include "dbgipceventtypes.h"
170 #undef IPC_EVENT_TYPE2
171 #undef IPC_EVENT_TYPE1
172 #undef IPC_EVENT_TYPE0
173 e_DB_IPCE_RUNTIME_LAST)
174 );
175 static_assert_no_msg(f1);
176
177 const bool f2 = (
178 (e_DB_IPCE_DEBUGGER_FIRST <=
179 #define IPC_EVENT_TYPE0(type, val)
180 #define IPC_EVENT_TYPE1(type, val)
181 #define IPC_EVENT_TYPE2(type, val) val) && (val <
182 #include "dbgipceventtypes.h"
183 #undef IPC_EVENT_TYPE2
184 #undef IPC_EVENT_TYPE1
185 #undef IPC_EVENT_TYPE0
186 e_DB_IPCE_DEBUGGER_LAST)
187 );
188 static_assert_no_msg(f2);
189
190} // end checks
191#endif // _PREFAST_
192
193//-----------------------------------------------------------------------------
194// Ctor for AtSafePlaceHolder
195AtSafePlaceHolder::AtSafePlaceHolder(Thread * pThread)
196{
197 _ASSERTE(pThread != NULL);
198 if (!g_pDebugger->IsThreadAtSafePlace(pThread))
199 {
200 m_pThreadAtUnsafePlace = pThread;
201 g_pDebugger->IncThreadsAtUnsafePlaces();
202 }
203 else
204 {
205 m_pThreadAtUnsafePlace = NULL;
206 }
207}
208
209//-----------------------------------------------------------------------------
210// Dtor for AtSafePlaceHolder
211AtSafePlaceHolder::~AtSafePlaceHolder()
212{
213 Clear();
214}
215
216//-----------------------------------------------------------------------------
217// Returns true if this adjusted the unsafe counter
218bool AtSafePlaceHolder::IsAtUnsafePlace()
219{
220 return m_pThreadAtUnsafePlace != NULL;
221}
222
223//-----------------------------------------------------------------------------
224// Clear the holder.
225// Notes:
226// This can be called multiple times.
227// Calling this makes the dtor a nop.
228void AtSafePlaceHolder::Clear()
229{
230 if (m_pThreadAtUnsafePlace != NULL)
231 {
232 // The thread is still at an unsafe place.
233 // We're clearing the flag to avoid the Dtor() calling DecThreads again.
234 m_pThreadAtUnsafePlace = NULL;
235 g_pDebugger->DecThreadsAtUnsafePlaces();
236 }
237}
238
239//-----------------------------------------------------------------------------
240// Is the guard page missing on this thread?
241// Should only be called for managed threads handling a managed exception.
242// If we're handling a stack overflow (ie, missing guard page), then another
243// stack overflow will instantly terminate the process. In that case, do stack
244// intensive stuff on the helper thread (which has lots of stack space). Only
245// problem is that if the faulting thread has a lock, the helper thread may
246// get stuck.
247// Serves as a hint whether we want to do a favor on the
248// faulting thread (preferred) or the helper thread (if low stack).
249// See whidbey issue 127436.
250//-----------------------------------------------------------------------------
251bool IsGuardPageGone()
252{
253 CONTRACTL
254 {
255 NOTHROW;
256 GC_NOTRIGGER;
257 }
258 CONTRACTL_END;
259
260 Thread * pThread = g_pEEInterface->GetThread();
261
262 // We're not going to be called for a unmanaged exception.
263 // Should always have a managed thread, but just in case something really
264 // crazy happens, it's not worth an AV. (since this is just being used as a hint)
265 if (pThread == NULL)
266 {
267 return false;
268 }
269
270 // Don't use pThread->IsGuardPageGone(), it's not accurate here.
271 bool fGuardPageGone = (pThread->DetermineIfGuardPagePresent() == FALSE);
272 LOG((LF_CORDB, LL_INFO1000000, "D::IsGuardPageGone=%d\n", fGuardPageGone));
273 return fGuardPageGone;
274}
275
276//-----------------------------------------------------------------------------
277// LSPTR_XYZ is a type-safe wrapper around an opaque reference type XYZ in the left-side.
278// But TypeHandles are value-types that can't be directly converted into a pointer.
279// Thus converting between LSPTR_XYZ and TypeHandles requires some extra glue.
280// The following conversions are valid:
281// LSPTR_XYZ <--> XYZ* (via Set/UnWrap methods)
282// TypeHandle <--> void* (via AsPtr() and FromPtr()).
283// so we can't directly convert between LSPTR_TYPEHANDLE and TypeHandle.
284// We must do: TypeHandle <--> void* <--> XYZ <--> LSPTR_XYZ
285// So LSPTR_TYPEHANDLE is actually for TypeHandleDummyPtr, and then we unsafe cast
286// that to a void* to use w/ AsPtr() and FromPtr() to convert to TypeHandles.
287// @todo- it would be nice to have these happen automatically w/ Set & UnWrap.
288//-----------------------------------------------------------------------------
289
290// helper class to do conversion above.
291class TypeHandleDummyPtr
292{
293private:
294 TypeHandleDummyPtr() { }; // should never actually create this.
295 void * data;
296};
297
298// Convert: VMPTR_TYPEHANDLE --> TypeHandle
299TypeHandle GetTypeHandle(VMPTR_TypeHandle ptr)
300{
301 return TypeHandle::FromPtr(ptr.GetRawPtr());
302}
303
304// Convert: TypeHandle --> LSPTR_TYPEHANDLE
305VMPTR_TypeHandle WrapTypeHandle(TypeHandle th)
306{
307 return VMPTR_TypeHandle::MakePtr(reinterpret_cast<TypeHandle *> (th.AsPtr()));
308}
309
310extern void WaitForEndOfShutdown();
311
312
313// Get the Canary structure which can sniff if the helper thread is safe to run.
314HelperCanary * Debugger::GetCanary()
315{
316 return g_pRCThread->GetCanary();
317}
318
319// IMPORTANT!!!!!
320// Do not call Lock and Unlock directly. Because you might not unlock
321// if exception takes place. Use DebuggerLockHolder instead!!!
322// Only AcquireDebuggerLock can call directly.
323//
324void Debugger::DoNotCallDirectlyPrivateLock(void)
325{
326 WRAPPER_NO_CONTRACT;
327
328 LOG((LF_CORDB,LL_INFO10000, "D::Lock acquire attempt by 0x%x\n",
329 GetCurrentThreadId()));
330
331 // Debugger lock is larger than both Controller & debugger-data locks.
332 // So we should never try to take the D lock if we hold either of the others.
333
334
335 // Lock becomes no-op in late shutdown.
336 if (g_fProcessDetach)
337 {
338 return;
339 }
340
341
342 //
343 // If the debugger has been disabled by the runtime, this means that it should block
344 // all threads that are trying to travel thru the debugger. We do this by blocking
345 // threads as they try and take the debugger lock.
346 //
347 if (m_fDisabled)
348 {
349 __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
350 _ASSERTE (!"Can not reach here");
351 }
352
353 m_mutex.Enter();
354
355 //
356 // If we were blocked on the lock and the debugging facilities got disabled
357 // while we were waiting, release the lock and park this thread.
358 //
359 if (m_fDisabled)
360 {
361 m_mutex.Leave();
362 __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
363 _ASSERTE (!"Can not reach here");
364 }
365
366 //
367 // Now check if we are in a shutdown case...
368 //
369 Thread * pThread;
370 bool fIsCooperative;
371 BEGIN_GETTHREAD_ALLOWED;
372 pThread = g_pEEInterface->GetThread();
373 fIsCooperative = (pThread != NULL) && (pThread->PreemptiveGCDisabled());
374 END_GETTHREAD_ALLOWED;
375 if (m_fShutdownMode && !fIsCooperative)
376 {
377 // The big fear is that some other random thread will take the debugger-lock and then block on something else,
378 // and thus prevent the helper/finalizer threads from taking the debugger-lock in shutdown scenarios.
379 //
380 // If we're in shutdown mode, then some locks (like the Thread-Store-Lock) get special semantics.
381 // Only helper / finalizer / shutdown threads can actually take these locks.
382 // Other threads that try to take them will just get parked and block forever.
383 // This is ok b/c the only threads that need to run at this point are the Finalizer and Helper threads.
384 //
385 // We need to be in preemptive to block for shutdown, so we don't do this block in Coop mode.
386 // Fortunately, it's safe to take this lock in coop mode because we know the thread can't block
387 // on anything interesting because we're in a GC-forbid region (see crst flags).
388 m_mutex.ReleaseAndBlockForShutdownIfNotSpecialThread();
389 }
390
391
392
393#ifdef _DEBUG
394 _ASSERTE(m_mutexCount >= 0);
395
396 if (m_mutexCount>0)
397 {
398 if (pThread)
399 {
400 // mamaged thread
401 _ASSERTE(m_mutexOwner == GetThreadIdHelper(pThread));
402 }
403 else
404 {
405 // unmanaged thread
406 _ASSERTE(m_mutexOwner == GetCurrentThreadId());
407 }
408 }
409
410 m_mutexCount++;
411 if (pThread)
412 {
413 m_mutexOwner = GetThreadIdHelper(pThread);
414 }
415 else
416 {
417 // unmanaged thread
418 m_mutexOwner = GetCurrentThreadId();
419 }
420
421 if (m_mutexCount == 1)
422 {
423 LOG((LF_CORDB,LL_INFO10000, "D::Lock acquired by 0x%x\n", m_mutexOwner));
424 }
425#endif
426
427}
428
429// See comment above.
430// Only ReleaseDebuggerLock can call directly.
431void Debugger::DoNotCallDirectlyPrivateUnlock(void)
432{
433 WRAPPER_NO_CONTRACT;
434
435 // Controller lock is "smaller" than debugger lock.
436
437
438 if (!g_fProcessDetach)
439 {
440#ifdef _DEBUG
441 if (m_mutexCount == 1)
442 LOG((LF_CORDB,LL_INFO10000, "D::Unlock released by 0x%x\n",
443 m_mutexOwner));
444
445 if(0 == --m_mutexCount)
446 m_mutexOwner = 0;
447
448 _ASSERTE( m_mutexCount >= 0);
449#endif
450 m_mutex.Leave();
451
452 //
453 // If the debugger has been disabled by the runtime, this means that it should block
454 // all threads that are trying to travel thru the debugger. We do this by blocking
455 // threads also as they leave the debugger lock.
456 //
457 if (m_fDisabled)
458 {
459 __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
460 _ASSERTE (!"Can not reach here");
461 }
462
463 }
464}
465
466#ifdef TEST_DATA_CONSISTENCY
467
468// ---------------------------------------------------------------------------------
469// Implementations for DataTest member functions
470// ---------------------------------------------------------------------------------
471
472// Send an event to the RS to signal that it should test to determine if a crst is held.
473// This is for testing purposes only.
474// Arguments:
475// input: pCrst - the lock to test
476// fOkToTake - true iff the LS does NOT currently hold the lock
477// output: none
478// Notes: The RS will throw if the lock is held. The code that tests the lock will catch the
479// exception and assert if throwing was not the correct thing to do (determined via the
480// boolean). See the case for DB_IPCE_TEST_CRST in code:CordbProcess::RawDispatchEvent.
481//
482void DataTest::SendDbgCrstEvent(Crst * pCrst, bool fOkToTake)
483{
484 DebuggerIPCEvent * pLockEvent = g_pDebugger->m_pRCThread->GetIPCEventSendBuffer();
485
486 g_pDebugger->InitIPCEvent(pLockEvent, DB_IPCE_TEST_CRST);
487
488 pLockEvent->TestCrstData.vmCrst.SetRawPtr(pCrst);
489 pLockEvent->TestCrstData.fOkToTake = fOkToTake;
490
491 g_pDebugger->SendRawEvent(pLockEvent);
492
493} // DataTest::SendDbgCrstEvent
494
495// Send an event to the RS to signal that it should test to determine if a SimpleRWLock is held.
496// This is for testing purposes only.
497// Arguments:
498// input: pRWLock - the lock to test
499// fOkToTake - true iff the LS does NOT currently hold the lock
500// output: none
501// Note: The RS will throw if the lock is held. The code that tests the lock will catch the
502// exception and assert if throwing was not the correct thing to do (determined via the
503// boolean). See the case for DB_IPCE_TEST_RWLOCK in code:CordbProcess::RawDispatchEvent.
504//
505void DataTest::SendDbgRWLockEvent(SimpleRWLock * pRWLock, bool okToTake)
506{
507 DebuggerIPCEvent * pLockEvent = g_pDebugger->m_pRCThread->GetIPCEventSendBuffer();
508
509 g_pDebugger->InitIPCEvent(pLockEvent, DB_IPCE_TEST_RWLOCK);
510
511 pLockEvent->TestRWLockData.vmRWLock.SetRawPtr(pRWLock);
512 pLockEvent->TestRWLockData.fOkToTake = okToTake;
513
514 g_pDebugger->SendRawEvent(pLockEvent);
515} // DataTest::SendDbgRWLockEvent
516
517// Takes a series of locks in various ways and signals the RS to test the locks at interesting
518// points to ensure we reliably detect when the LS holds a lock. If in the course of inspection, the
519// DAC needs to execute a code path where the LS holds a lock, we assume that the locked data is in
520// an inconsistent state. In this situation, we don't want to report information about this data, so
521// we throw an exception.
522// This is for testing purposes only.
523//
524// Arguments: none
525// Return Value: none
526// Notes: See code:CordbProcess::RawDispatchEvent for the RS part of this test and code:Debugger::Startup
527// for the LS invocation of the test.
528// The environment variable TestDataConsistency must be set to 1 to make this test run.
529void DataTest::TestDataSafety()
530{
531 const bool okToTake = true;
532
533 SendDbgCrstEvent(&m_crst1, okToTake);
534 {
535 CrstHolder ch1(&m_crst1);
536 SendDbgCrstEvent(&m_crst1, !okToTake);
537 {
538 CrstHolder ch2(&m_crst2);
539 SendDbgCrstEvent(&m_crst2, !okToTake);
540 SendDbgCrstEvent(&m_crst1, !okToTake);
541 }
542 SendDbgCrstEvent(&m_crst2, okToTake);
543 SendDbgCrstEvent(&m_crst1, !okToTake);
544 }
545 SendDbgCrstEvent(&m_crst1, okToTake);
546
547 {
548 SendDbgRWLockEvent(&m_rwLock, okToTake);
549 SimpleReadLockHolder readLock(&m_rwLock);
550 SendDbgRWLockEvent(&m_rwLock, okToTake);
551 }
552 SendDbgRWLockEvent(&m_rwLock, okToTake);
553 {
554 SimpleWriteLockHolder readLock(&m_rwLock);
555 SendDbgRWLockEvent(&m_rwLock, !okToTake);
556 }
557
558} // DataTest::TestDataSafety
559
560#endif // TEST_DATA_CONSISTENCY
561
562#if _DEBUG
563static DebugEventCounter g_debugEventCounter;
564static int g_iDbgRuntimeCounter[DBG_RUNTIME_MAX];
565static int g_iDbgDebuggerCounter[DBG_DEBUGGER_MAX];
566
567void DoAssertOnType(DebuggerIPCEventType event, int count)
568{
569 WRAPPER_NO_CONTRACT;
570
571 // check to see if we need fire the assertion or not.
572 if ((event & 0x0300) == 0x0100)
573 {
574 // use the Runtime array
575 if (g_iDbgRuntimeCounter[event & 0x00ff] == count)
576 {
577 char tmpStr[256];
578 _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!",
579 IPCENames::GetName(event), count);
580
581 // fire the assertion
582 DbgAssertDialog(__FILE__, __LINE__, tmpStr);
583 }
584 }
585 // check to see if we need fire the assertion or not.
586 else if ((event & 0x0300) == 0x0200)
587 {
588 // use the Runtime array
589 if (g_iDbgDebuggerCounter[event & 0x00ff] == count)
590 {
591 char tmpStr[256];
592 _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!",
593 IPCENames::GetName(event), count);
594
595 // fire the assertion
596 DbgAssertDialog(__FILE__, __LINE__, tmpStr);
597 }
598 }
599
600}
601void DbgLogHelper(DebuggerIPCEventType event)
602{
603 WRAPPER_NO_CONTRACT;
604
605 switch (event)
606 {
607// we don't need to handle event type 0
608#define IPC_EVENT_TYPE0(type, val)
609#define IPC_EVENT_TYPE1(type, val) case type: {\
610 g_debugEventCounter.m_iDebugCount_##type++; \
611 DoAssertOnType(type, g_debugEventCounter.m_iDebugCount_##type); \
612 break; \
613 }
614#define IPC_EVENT_TYPE2(type, val) case type: { \
615 g_debugEventCounter.m_iDebugCount_##type++; \
616 DoAssertOnType(type, g_debugEventCounter.m_iDebugCount_##type); \
617 break; \
618 }
619#include "dbgipceventtypes.h"
620#undef IPC_EVENT_TYPE2
621#undef IPC_EVENT_TYPE1
622#undef IPC_EVENT_TYPE0
623 default:
624 break;
625 }
626}
627#endif // _DEBUG
628
629
630
631
632
633
634
635
636
637/* ------------------------------------------------------------------------ *
638 * DLL export routine
639 * ------------------------------------------------------------------------ */
640
641Debugger *CreateDebugger(void)
642{
643 Debugger *pDebugger = NULL;
644
645 EX_TRY
646 {
647 pDebugger = new (nothrow) Debugger();
648 }
649 EX_CATCH
650 {
651 if (pDebugger != NULL)
652 {
653 delete pDebugger;
654 pDebugger = NULL;
655 }
656 }
657 EX_END_CATCH(RethrowTerminalExceptions);
658
659 return pDebugger;
660}
661
662//
663// CorDBGetInterface is exported to the Runtime so that it can call
664// the Runtime Controller.
665//
666extern "C"{
667HRESULT __cdecl CorDBGetInterface(DebugInterface** rcInterface)
668{
669 CONTRACT(HRESULT)
670 {
671 NOTHROW; // use HRESULTS instead
672 GC_NOTRIGGER;
673 POSTCONDITION(FAILED(RETVAL) || (rcInterface == NULL) || (*rcInterface != NULL));
674 }
675 CONTRACT_END;
676
677 HRESULT hr = S_OK;
678
679 if (rcInterface != NULL)
680 {
681 if (g_pDebugger == NULL)
682 {
683 LOG((LF_CORDB, LL_INFO10,
684 "CorDBGetInterface: initializing debugger.\n"));
685
686 g_pDebugger = CreateDebugger();
687 TRACE_ALLOC(g_pDebugger);
688
689 if (g_pDebugger == NULL)
690 hr = E_OUTOFMEMORY;
691 }
692
693 *rcInterface = g_pDebugger;
694 }
695
696 RETURN hr;
697}
698}
699
700//-----------------------------------------------------------------------------
701// Send a pre-init IPC event and block.
702// We assume the IPC event has already been initialized. There's nothing special
703// here; it just used the standard formula for sending an IPC event to the RS.
704// This should match up w/ the description in SENDIPCEVENT_BEGIN.
705//-----------------------------------------------------------------------------
706void Debugger::SendSimpleIPCEventAndBlock()
707{
708 CONTRACTL
709 {
710 SO_NOT_MAINLINE;
711 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
712 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
713 }
714 CONTRACTL_END;
715
716 // BEGIN will acquire the lock (END will release it). While blocking, the
717 // debugger may have detached though, so we need to check for that.
718 _ASSERTE(ThreadHoldsLock());
719
720 if (CORDebuggerAttached())
721 {
722 m_pRCThread->SendIPCEvent();
723
724 // Stop all Runtime threads
725 this->TrapAllRuntimeThreads();
726 }
727}
728
729//-----------------------------------------------------------------------------
730// Get context from a thread in managed code.
731// See header for exact semantics.
732//-----------------------------------------------------------------------------
733CONTEXT * GetManagedStoppedCtx(Thread * pThread)
734{
735 WRAPPER_NO_CONTRACT;
736
737 _ASSERTE(pThread != NULL);
738
739 // We may be stopped or live.
740
741 // If we're stopped at an interop-hijack, we'll have a filter context,
742 // but we'd better not be redirected for a managed-suspension hijack.
743 if (pThread->GetInteropDebuggingHijacked())
744 {
745 _ASSERTE(!ISREDIRECTEDTHREAD(pThread));
746 return NULL;
747 }
748
749 // Check if we have a filter ctx. This should only be for managed-code.
750 // We're stopped at some exception (likely an int3 or single-step).
751 // Can't have both filter ctx + redirected ctx.
752 CONTEXT *pCtx = g_pEEInterface->GetThreadFilterContext(pThread);
753 if (pCtx != NULL)
754 {
755 _ASSERTE(!ISREDIRECTEDTHREAD(pThread));
756 return pCtx;
757 }
758
759 if (ISREDIRECTEDTHREAD(pThread))
760 {
761 pCtx = GETREDIRECTEDCONTEXT(pThread);
762 _ASSERTE(pCtx != NULL);
763 return pCtx;
764 }
765
766 // Not stopped somewhere in managed code.
767 return NULL;
768}
769
770//-----------------------------------------------------------------------------
771// See header for exact semantics.
772// Never NULL. (Caller guarantees this is active.)
773//-----------------------------------------------------------------------------
774CONTEXT * GetManagedLiveCtx(Thread * pThread)
775{
776 LIMITED_METHOD_CONTRACT;
777
778 _ASSERTE(pThread != NULL);
779
780 // We should never be on the helper thread, we should only be inspecting our own thread.
781 // We're in some Controller's Filter after hitting an exception.
782 // We're not stopped.
783 //_ASSERTE(!g_pDebugger->IsStopped()); <-- @todo - this fires, need to find out why.
784 _ASSERTE(GetThread() == pThread);
785
786 CONTEXT *pCtx = g_pEEInterface->GetThreadFilterContext(pThread);
787
788 // Note that we may be in a M2U hijack. So we can't assert !pThread->GetInteropDebuggingHijacked()
789 _ASSERTE(!ISREDIRECTEDTHREAD(pThread));
790 _ASSERTE(pCtx);
791
792 return pCtx;
793}
794
795// Attempt to validate a GC handle.
796HRESULT ValidateGCHandle(OBJECTHANDLE oh)
797{
798 // The only real way to do this is to Enumerate all GC handles in the handle table.
799 // That's too expensive. So we'll use a similar workaround that we use in ValidateObject.
800 // This will err on the side off returning True for invalid handles.
801
802 CONTRACTL
803 {
804 SO_NOT_MAINLINE;
805 NOTHROW;
806 GC_NOTRIGGER;
807 }
808 CONTRACTL_END;
809
810 HRESULT hr = S_OK;
811
812 EX_TRY
813 {
814 // Use AVInRuntimeImplOkHolder.
815 AVInRuntimeImplOkayHolder AVOkay;
816
817 // This may throw if the Object Handle is invalid.
818 Object * objPtr = *((Object**) oh);
819
820 // NULL is certinally valid...
821 if (objPtr != NULL)
822 {
823 if (!objPtr->ValidateObjectWithPossibleAV())
824 {
825 LOG((LF_CORDB, LL_INFO10000, "GAV: object methodtable-class invariant doesn't hold.\n"));
826 hr = E_INVALIDARG;
827 goto LExit;
828 }
829 }
830
831 LExit: ;
832 }
833 EX_CATCH
834 {
835 LOG((LF_CORDB, LL_INFO10000, "GAV: exception indicated ref is bad.\n"));
836 hr = E_INVALIDARG;
837 }
838 EX_END_CATCH(SwallowAllExceptions);
839
840 return hr;
841}
842
843
844// Validate an object. Returns E_INVALIDARG or S_OK.
845HRESULT ValidateObject(Object *objPtr)
846{
847 CONTRACTL
848 {
849 SO_NOT_MAINLINE;
850 NOTHROW;
851 GC_NOTRIGGER;
852 }
853 CONTRACTL_END;
854
855 HRESULT hr = S_OK;
856
857 EX_TRY
858 {
859 // Use AVInRuntimeImplOkHolder.
860 AVInRuntimeImplOkayHolder AVOkay;
861
862 // NULL is certinally valid...
863 if (objPtr != NULL)
864 {
865 if (!objPtr->ValidateObjectWithPossibleAV())
866 {
867 LOG((LF_CORDB, LL_INFO10000, "GAV: object methodtable-class invariant doesn't hold.\n"));
868 hr = E_INVALIDARG;
869 goto LExit;
870 }
871 }
872
873 LExit: ;
874 }
875 EX_CATCH
876 {
877 LOG((LF_CORDB, LL_INFO10000, "GAV: exception indicated ref is bad.\n"));
878 hr = E_INVALIDARG;
879 }
880 EX_END_CATCH(SwallowAllExceptions);
881
882 return hr;
883} // ValidateObject
884
885
886#ifdef FEATURE_DBGIPC_TRANSPORT_VM
887void
888ShutdownTransport()
889{
890 if (g_pDbgTransport != NULL)
891 {
892 g_pDbgTransport->Shutdown();
893 g_pDbgTransport = NULL;
894 }
895}
896
897void
898AbortTransport()
899{
900 if (g_pDbgTransport != NULL)
901 {
902 g_pDbgTransport->AbortConnection();
903 }
904}
905#endif // FEATURE_DBGIPC_TRANSPORT_VM
906
907
908/* ------------------------------------------------------------------------ *
909 * Debugger routines
910 * ------------------------------------------------------------------------ */
911
912//
913// a Debugger object represents the global state of the debugger program.
914//
915
916//
917// Constructor & Destructor
918//
919
920/******************************************************************************
921 *
922 ******************************************************************************/
923Debugger::Debugger()
924 :
925 m_fLeftSideInitialized(FALSE),
926#ifdef _DEBUG
927 m_mutexCount(0),
928#endif //_DEBUG
929 m_pRCThread(NULL),
930 m_trappingRuntimeThreads(FALSE),
931 m_stopped(FALSE),
932 m_unrecoverableError(FALSE),
933 m_ignoreThreadDetach(FALSE),
934 m_pMethodInfos(NULL),
935 m_mutex(CrstDebuggerMutex, (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_REENTRANCY | CRST_DEBUGGER_THREAD)),
936#ifdef _DEBUG
937 m_mutexOwner(0),
938 m_tidLockedForEventSending(0),
939#endif //_DEBUG
940 m_threadsAtUnsafePlaces(0),
941 m_jitAttachInProgress(FALSE),
942 m_launchingDebugger(FALSE),
943 m_LoggingEnabled(TRUE),
944 m_pAppDomainCB(NULL),
945 m_dClassLoadCallbackCount(0),
946 m_pModules(NULL),
947 m_RSRequestedSync(FALSE),
948 m_sendExceptionsOutsideOfJMC(TRUE),
949 m_pIDbgThreadControl(NULL),
950 m_forceNonInterceptable(FALSE),
951 m_pLazyData(NULL),
952 m_defines(_defines),
953 m_isBlockedOnGarbageCollectionEvent(FALSE),
954 m_willBlockOnGarbageCollectionEvent(FALSE),
955 m_isGarbageCollectionEventsEnabled(FALSE),
956 m_isGarbageCollectionEventsEnabledLatch(FALSE)
957{
958 CONTRACTL
959 {
960 SO_INTOLERANT;
961 WRAPPER(THROWS);
962 WRAPPER(GC_TRIGGERS);
963 CONSTRUCTOR_CHECK;
964 }
965 CONTRACTL_END;
966
967 m_fShutdownMode = false;
968 m_fDisabled = false;
969 m_rgHijackFunction = NULL;
970
971#ifdef _DEBUG
972 InitDebugEventCounting();
973#endif
974
975 m_processId = GetCurrentProcessId();
976
977 // Initialize these in ctor because we free them in dtor.
978 // And we can't set them to some safe uninited value (like NULL).
979
980
981
982 //------------------------------------------------------------------------------
983 // Metadata data structure version numbers
984 //
985 // 1 - initial state of the layouts ( .Net 4.5.2 )
986 //
987 // as data structure layouts change, add a new version number
988 // and comment the changes
989 m_mdDataStructureVersion = 1;
990
991}
992
993/******************************************************************************
994 *
995 ******************************************************************************/
996Debugger::~Debugger()
997{
998 CONTRACTL
999 {
1000 NOTHROW;
1001 GC_NOTRIGGER;
1002 DESTRUCTOR_CHECK;
1003 SO_INTOLERANT;
1004 }
1005 CONTRACTL_END;
1006
1007 // We explicitly leak the debugger object on shutdown. See Debugger::StopDebugger for details.
1008 _ASSERTE(!"Debugger dtor should not be called.");
1009}
1010
1011#if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
1012typedef void (*PFN_HIJACK_FUNCTION) (void);
1013
1014// Given the start address and the end address of a function, return a MemoryRange for the function.
1015inline MemoryRange GetMemoryRangeForFunction(PFN_HIJACK_FUNCTION pfnStart, PFN_HIJACK_FUNCTION pfnEnd)
1016{
1017 PCODE pfnStartAddress = (PCODE)GetEEFuncEntryPoint(pfnStart);
1018 PCODE pfnEndAddress = (PCODE)GetEEFuncEntryPoint(pfnEnd);
1019 return MemoryRange(dac_cast<PTR_VOID>(pfnStartAddress), (pfnEndAddress - pfnStartAddress));
1020}
1021
1022// static
1023MemoryRange Debugger::s_hijackFunction[kMaxHijackFunctions] =
1024 {GetMemoryRangeForFunction(ExceptionHijack, ExceptionHijackEnd),
1025 GetMemoryRangeForFunction(RedirectedHandledJITCaseForGCThreadControl_Stub,
1026 RedirectedHandledJITCaseForGCThreadControl_StubEnd),
1027 GetMemoryRangeForFunction(RedirectedHandledJITCaseForDbgThreadControl_Stub,
1028 RedirectedHandledJITCaseForDbgThreadControl_StubEnd),
1029 GetMemoryRangeForFunction(RedirectedHandledJITCaseForUserSuspend_Stub,
1030 RedirectedHandledJITCaseForUserSuspend_StubEnd)
1031#if defined(HAVE_GCCOVER) && defined(_TARGET_AMD64_)
1032 ,
1033 GetMemoryRangeForFunction(RedirectedHandledJITCaseForGCStress_Stub,
1034 RedirectedHandledJITCaseForGCStress_StubEnd)
1035#endif // HAVE_GCCOVER && _TARGET_AMD64_
1036 };
1037#endif // FEATURE_HIJACK && !PLATFORM_UNIX
1038
1039// Save the necessary information for the debugger to recognize an IP in one of the thread redirection
1040// functions.
1041void Debugger::InitializeHijackFunctionAddress()
1042{
1043#if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
1044 // Advertise hijack address for the DD Hijack primitive
1045 m_rgHijackFunction = Debugger::s_hijackFunction;
1046#endif // FEATURE_HIJACK && !PLATFORM_UNIX
1047}
1048
1049// For debug-only builds, we'll have a debugging feature to count
1050// the number of ipc events and break on a specific number.
1051// Initialize the stuff to do that.
1052void Debugger::InitDebugEventCounting()
1053{
1054 CONTRACTL
1055 {
1056 SO_INTOLERANT;
1057 NOTHROW;
1058 GC_NOTRIGGER;
1059 }
1060 CONTRACTL_END;
1061#ifdef _DEBUG
1062 // initialize the debug event counter structure to zero
1063 memset(&g_debugEventCounter, 0, sizeof(DebugEventCounter));
1064 memset(&g_iDbgRuntimeCounter, 0, DBG_RUNTIME_MAX*sizeof(int));
1065 memset(&g_iDbgDebuggerCounter, 0, DBG_DEBUGGER_MAX*sizeof(int));
1066
1067 // retrieve the possible counter for break point
1068 LPWSTR wstrValue = NULL;
1069 // The string value is of the following format
1070 // <Event Name>=Count;<Event Name>=Count;....;
1071 // The string must end with ;
1072 if ((wstrValue = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DebuggerBreakPoint)) != NULL)
1073 {
1074 LPSTR strValue;
1075 int cbReq;
1076 cbReq = WszWideCharToMultiByte(CP_UTF8, 0, wstrValue,-1, 0,0, 0,0);
1077
1078 strValue = new (nothrow) char[cbReq+1];
1079 // This is a debug only thingy, if it fails, not worth taking
1080 // down the process.
1081 if (strValue == NULL)
1082 return;
1083
1084
1085 // now translate the unicode to ansi string
1086 WszWideCharToMultiByte(CP_UTF8, 0, wstrValue, -1, strValue, cbReq+1, 0,0);
1087 char *szEnd = (char *)strchr(strValue, ';');
1088 char *szStart = strValue;
1089 while (szEnd != NULL)
1090 {
1091 // Found a key value
1092 char *szNameEnd = strchr(szStart, '=');
1093 int iCount;
1094 DebuggerIPCEventType eventType;
1095 if (szNameEnd != NULL)
1096 {
1097 // This is a well form key
1098 *szNameEnd = '\0';
1099 *szEnd = '\0';
1100
1101 // now szStart is the key name null terminated. Translate the counter into integer.
1102 iCount = atoi(szNameEnd+1);
1103 if (iCount != 0)
1104 {
1105 eventType = IPCENames::GetEventType(szStart);
1106
1107 if (eventType < DB_IPCE_DEBUGGER_FIRST)
1108 {
1109 // use the runtime one
1110 g_iDbgRuntimeCounter[eventType & 0x00ff] = iCount;
1111 }
1112 else if (eventType < DB_IPCE_DEBUGGER_LAST)
1113 {
1114 // use the debugger one
1115 g_iDbgDebuggerCounter[eventType & 0x00ff] = iCount;
1116 }
1117 else
1118 _ASSERTE(!"Unknown Event Type");
1119 }
1120 }
1121 szStart = szEnd + 1;
1122 // try to find next key value
1123 szEnd = (char *)strchr(szStart, ';');
1124 }
1125
1126 // free the ansi buffer
1127 delete [] strValue;
1128 REGUTIL::FreeConfigString(wstrValue);
1129 }
1130#endif // _DEBUG
1131}
1132
1133
1134// This is a notification from the EE it's about to go to fiber mode.
1135// This is given *before* it actually goes to fiber mode.
1136HRESULT Debugger::SetFiberMode(bool isFiberMode)
1137{
1138 CONTRACTL
1139 {
1140 NOTHROW;
1141 GC_NOTRIGGER;
1142
1143 // Notifications from EE never come on helper worker.
1144 PRECONDITION(!ThisIsHelperThreadWorker());
1145 }
1146 CONTRACTL_END;
1147
1148
1149 Thread * pThread = ::GetThread();
1150
1151 m_pRCThread->m_pDCB->m_bHostingInFiber = isFiberMode;
1152
1153 // If there is a debugger already attached, then we have a big problem. As of V2.0, the debugger
1154 // does not support debugging processes with fibers in them. We set the unrecoverable state to
1155 // indicate that we're in a bad state now. The debugger will notice this, and take appropiate action.
1156 if (isFiberMode && CORDebuggerAttached())
1157 {
1158 LOG((LF_CORDB, LL_INFO10, "Thread has entered fiber mode while debugger attached.\n"));
1159
1160 EX_TRY
1161 {
1162 // We send up a MDA for two reasons: 1) we want to give the user some chance to see what went wrong,
1163 // and 2) we want to get the Right Side to notice that we're in an unrecoverable error state now.
1164
1165 SString szName(W("DebuggerFiberModeNotSupported"));
1166 SString szDescription;
1167 szDescription.LoadResource(CCompRC::Debugging, MDARC_DEBUGGER_FIBER_MODE_NOT_SUPPORTED);
1168 SString szXML(W(""));
1169
1170 // Sending any debug event will be a GC violation.
1171 // However, if we're enabling fiber-mode while a debugger is attached, we're already doomed.
1172 // Deadlocks and AVs are just around the corner. A Gc-violation is the least of our worries.
1173 // We want to at least notify the debugger at all costs.
1174 CONTRACT_VIOLATION(GCViolation);
1175
1176 // As soon as we set unrecoverable error in the LS, the RS will pick it up and basically shut down.
1177 // It won't dispatch any events. So we fire the MDA first, and then set unrecoverable error.
1178 SendMDANotification(pThread, &szName, &szDescription, &szXML, (CorDebugMDAFlags) 0, FALSE);
1179
1180 CORDBDebuggerSetUnrecoverableError(this, CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS, false);
1181
1182 // Fire the MDA again just to force the RS to sniff the LS and pick up that we're in an unrecoverable error.
1183 // No harm done from dispatching an MDA twice. And
1184 SendMDANotification(pThread, &szName, &szDescription, &szXML, (CorDebugMDAFlags) 0, FALSE);
1185
1186 }
1187 EX_CATCH
1188 {
1189 LOG((LF_CORDB, LL_INFO10, "Error sending MDA regarding fiber mode.\n"));
1190 }
1191 EX_END_CATCH(SwallowAllExceptions);
1192 }
1193
1194 return S_OK;
1195}
1196
1197// Checks if the MethodInfos table has been allocated, and if not does so.
1198// Throw on failure, so we always return
1199HRESULT Debugger::CheckInitMethodInfoTable()
1200{
1201 CONTRACTL
1202 {
1203 SO_INTOLERANT;
1204 NOTHROW;
1205 GC_NOTRIGGER;
1206 }
1207 CONTRACTL_END;
1208
1209 if (m_pMethodInfos == NULL)
1210 {
1211 DebuggerMethodInfoTable *pMethodInfos = NULL;
1212
1213 EX_TRY
1214 {
1215 pMethodInfos = new (interopsafe) DebuggerMethodInfoTable();
1216 }
1217 EX_CATCH
1218 {
1219 pMethodInfos = NULL;
1220 }
1221 EX_END_CATCH(RethrowTerminalExceptions);
1222
1223
1224 if (pMethodInfos == NULL)
1225 {
1226 return E_OUTOFMEMORY;
1227 }
1228
1229 if (InterlockedCompareExchangeT(&m_pMethodInfos, pMethodInfos, NULL) != NULL)
1230 {
1231 DeleteInteropSafe(pMethodInfos);
1232 }
1233 }
1234
1235 return S_OK;
1236}
1237
1238// Checks if the m_pModules table has been allocated, and if not does so.
1239HRESULT Debugger::CheckInitModuleTable()
1240{
1241 CONTRACT(HRESULT)
1242 {
1243 NOTHROW;
1244 GC_NOTRIGGER;
1245 POSTCONDITION(m_pModules != NULL);
1246 }
1247 CONTRACT_END;
1248
1249 if (m_pModules == NULL)
1250 {
1251 DebuggerModuleTable *pModules = new (interopsafe, nothrow) DebuggerModuleTable();
1252
1253 if (pModules == NULL)
1254 {
1255 RETURN (E_OUTOFMEMORY);
1256 }
1257
1258 if (InterlockedCompareExchangeT(&m_pModules, pModules, NULL) != NULL)
1259 {
1260 DeleteInteropSafe(pModules);
1261 }
1262 }
1263
1264 RETURN (S_OK);
1265}
1266
1267// Checks if the m_pModules table has been allocated, and if not does so.
1268HRESULT Debugger::CheckInitPendingFuncEvalTable()
1269{
1270 CONTRACT(HRESULT)
1271 {
1272 NOTHROW;
1273 GC_NOTRIGGER;
1274 POSTCONDITION(GetPendingEvals() != NULL);
1275 }
1276 CONTRACT_END;
1277
1278#ifndef DACCESS_COMPILE
1279
1280 if (GetPendingEvals() == NULL)
1281 {
1282 DebuggerPendingFuncEvalTable *pPendingEvals = new (interopsafe, nothrow) DebuggerPendingFuncEvalTable();
1283
1284 if (pPendingEvals == NULL)
1285 {
1286 RETURN(E_OUTOFMEMORY);
1287 }
1288
1289 // Since we're setting, we need an LValue and not just an accessor.
1290 if (InterlockedCompareExchangeT(&(GetLazyData()->m_pPendingEvals), pPendingEvals, NULL) != NULL)
1291 {
1292 DeleteInteropSafe(pPendingEvals);
1293 }
1294 }
1295#endif
1296
1297 RETURN (S_OK);
1298}
1299
1300
1301#ifdef _DEBUG_DMI_TABLE
1302// Returns the number of (official) entries in the table
1303ULONG DebuggerMethodInfoTable::CheckDmiTable(void)
1304{
1305 LIMITED_METHOD_CONTRACT;
1306
1307 ULONG cApparent = 0;
1308 ULONG cOfficial = 0;
1309
1310 if (NULL != m_pcEntries)
1311 {
1312 DebuggerMethodInfoEntry *dcp;
1313 int i = 0;
1314 while (i++ <m_iEntries)
1315 {
1316 dcp = (DebuggerMethodInfoEntry*)&(((DebuggerMethodInfoEntry *)m_pcEntries)[i]);
1317 if(dcp->pFD != 0 &&
1318 dcp->pFD != (MethodDesc*)0xcdcdcdcd &&
1319 dcp->mi != NULL)
1320 {
1321 cApparent++;
1322
1323 _ASSERTE( dcp->pFD == dcp->mi->m_fd );
1324 LOG((LF_CORDB, LL_INFO1000, "DMIT::CDT:Entry:0x%p mi:0x%p\nPrevs:\n",
1325 dcp, dcp->mi));
1326 DebuggerMethodInfo *dmi = dcp->mi->m_prevMethodInfo;
1327
1328 while(dmi != NULL)
1329 {
1330 LOG((LF_CORDB, LL_INFO1000, "\t0x%p\n", dmi));
1331 dmi = dmi->m_prevMethodInfo;
1332 }
1333 dmi = dcp->mi->m_nextMethodInfo;
1334
1335 LOG((LF_CORDB, LL_INFO1000, "Nexts:\n", dmi));
1336 while(dmi != NULL)
1337 {
1338 LOG((LF_CORDB, LL_INFO1000, "\t0x%p\n", dmi));
1339 dmi = dmi->m_nextMethodInfo;
1340 }
1341
1342 LOG((LF_CORDB, LL_INFO1000, "DMIT::CDT:DONE\n",
1343 dcp, dcp->mi));
1344 }
1345 }
1346
1347 if (m_piBuckets == 0)
1348 {
1349 LOG((LF_CORDB, LL_INFO1000, "DMIT::CDT: The table is officially empty!\n"));
1350 return cOfficial;
1351 }
1352
1353 LOG((LF_CORDB, LL_INFO1000, "DMIT::CDT:Looking for official entries:\n"));
1354
1355 ULONG iNext = m_piBuckets[0];
1356 ULONG iBucket = 1;
1357 HASHENTRY *psEntry = NULL;
1358 while (TRUE)
1359 {
1360 while (iNext != UINT32_MAX)
1361 {
1362 cOfficial++;
1363
1364 psEntry = EntryPtr(iNext);
1365 dcp = ((DebuggerMethodInfoEntry *)psEntry);
1366
1367 LOG((LF_CORDB, LL_INFO1000, "\tEntry:0x%p mi:0x%p @idx:0x%x @bucket:0x%x\n",
1368 dcp, dcp->mi, iNext, iBucket));
1369
1370 iNext = psEntry->iNext;
1371 }
1372
1373 // Advance to the next bucket.
1374 if (iBucket < m_iBuckets)
1375 iNext = m_piBuckets[iBucket++];
1376 else
1377 break;
1378 }
1379
1380 LOG((LF_CORDB, LL_INFO1000, "DMIT::CDT:Finished official entries: ****************"));
1381 }
1382
1383 return cOfficial;
1384}
1385#endif // _DEBUG_DMI_TABLE
1386
1387
1388//---------------------------------------------------------------------------------------
1389//
1390// Class constructor for DebuggerEval. This is the supporting data structure for
1391// func-eval tracking.
1392//
1393// Arguments:
1394// pContext - The context to return to when done with this eval.
1395// pEvalInfo - Contains all the important information, such as parameters, type args, method.
1396// fInException - TRUE if the thread for the eval is currently in an exception notification.
1397//
1398DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEvalInfo, bool fInException)
1399{
1400 WRAPPER_NO_CONTRACT;
1401
1402 // Allocate the breakpoint instruction info in executable memory.
1403 m_bpInfoSegment = new (interopsafeEXEC, nothrow) DebuggerEvalBreakpointInfoSegment(this);
1404
1405 // This must be non-zero so that the saved opcode is non-zero, and on IA64 we want it to be 0x16
1406 // so that we can have a breakpoint instruction in any slot in the bundle.
1407 m_bpInfoSegment->m_breakpointInstruction[0] = 0x16;
1408#if defined(_TARGET_ARM_)
1409 USHORT *bp = (USHORT*)&m_bpInfoSegment->m_breakpointInstruction;
1410 *bp = CORDbg_BREAK_INSTRUCTION;
1411#endif // _TARGET_ARM_
1412 m_thread = pEvalInfo->vmThreadToken.GetRawPtr();
1413 m_evalType = pEvalInfo->funcEvalType;
1414 m_methodToken = pEvalInfo->funcMetadataToken;
1415 m_classToken = pEvalInfo->funcClassMetadataToken;
1416
1417 // Note: we can't rely on just the DebuggerModule* or AppDomain* because the AppDomain
1418 // could get unloaded between now and when the funceval actually starts. So we stash an
1419 // AppDomain ID which is safe to use after the AD is unloaded. It's only safe to
1420 // use the DebuggerModule* after we've verified the ADID is still valid (i.e. by entering that domain).
1421 m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainFile);
1422
1423 if (m_debuggerModule == NULL)
1424 {
1425 // We have no associated code.
1426 _ASSERTE((m_evalType == DB_IPCE_FET_NEW_STRING) || (m_evalType == DB_IPCE_FET_NEW_ARRAY));
1427
1428 // We'll just do the creation in whatever domain the thread is already in.
1429 // It's conceivable that we might want to allow the caller to specify a specific domain, but
1430 // ICorDebug provides the debugger with no was to specify the domain.
1431 m_appDomainId = m_thread->GetDomain()->GetId();
1432 }
1433 else
1434 {
1435 m_appDomainId = m_debuggerModule->GetAppDomain()->GetId();
1436 }
1437
1438 m_funcEvalKey = pEvalInfo->funcEvalKey;
1439 m_argCount = pEvalInfo->argCount;
1440 m_targetCodeAddr = NULL;
1441 m_stringSize = pEvalInfo->stringSize;
1442 m_arrayRank = pEvalInfo->arrayRank;
1443 m_genericArgsCount = pEvalInfo->genericArgsCount;
1444 m_genericArgsNodeCount = pEvalInfo->genericArgsNodeCount;
1445 m_successful = false;
1446 m_argData = NULL;
1447 memset(m_result, 0, sizeof(m_result));
1448 m_md = NULL;
1449 m_resultType = TypeHandle();
1450 m_aborting = FE_ABORT_NONE;
1451 m_aborted = false;
1452 m_completed = false;
1453 m_evalDuringException = fInException;
1454 m_rethrowAbortException = false;
1455 m_retValueBoxing = Debugger::NoValueTypeBoxing;
1456 m_requester = (Thread::ThreadAbortRequester)0;
1457 m_vmObjectHandle = VMPTR_OBJECTHANDLE::NullPtr();
1458
1459 // Copy the thread's context.
1460 if (pContext == NULL)
1461 {
1462 memset(&m_context, 0, sizeof(m_context));
1463 }
1464 else
1465 {
1466 memcpy(&m_context, pContext, sizeof(m_context));
1467 }
1468}
1469
1470//---------------------------------------------------------------------------------------
1471//
1472// This constructor is only used when setting up an eval to re-abort a thread.
1473//
1474// Arguments:
1475// pContext - The context to return to when done with this eval.
1476// pThread - The thread to re-abort.
1477// requester - The type of abort to throw.
1478//
1479DebuggerEval::DebuggerEval(CONTEXT * pContext, Thread * pThread, Thread::ThreadAbortRequester requester)
1480{
1481 WRAPPER_NO_CONTRACT;
1482
1483 // Allocate the breakpoint instruction info in executable memory.
1484 m_bpInfoSegment = new (interopsafeEXEC, nothrow) DebuggerEvalBreakpointInfoSegment(this);
1485
1486 // This must be non-zero so that the saved opcode is non-zero, and on IA64 we want it to be 0x16
1487 // so that we can have a breakpoint instruction in any slot in the bundle.
1488 m_bpInfoSegment->m_breakpointInstruction[0] = 0x16;
1489 m_thread = pThread;
1490 m_evalType = DB_IPCE_FET_RE_ABORT;
1491 m_methodToken = mdMethodDefNil;
1492 m_classToken = mdTypeDefNil;
1493 m_debuggerModule = NULL;
1494 m_funcEvalKey = RSPTR_CORDBEVAL::NullPtr();
1495 m_argCount = 0;
1496 m_stringSize = 0;
1497 m_arrayRank = 0;
1498 m_genericArgsCount = 0;
1499 m_genericArgsNodeCount = 0;
1500 m_successful = false;
1501 m_argData = NULL;
1502 m_targetCodeAddr = NULL;
1503 memset(m_result, 0, sizeof(m_result));
1504 m_md = NULL;
1505 m_resultType = TypeHandle();
1506 m_aborting = FE_ABORT_NONE;
1507 m_aborted = false;
1508 m_completed = false;
1509 m_evalDuringException = false;
1510 m_rethrowAbortException = false;
1511 m_retValueBoxing = Debugger::NoValueTypeBoxing;
1512 m_requester = requester;
1513
1514 if (pContext == NULL)
1515 {
1516 memset(&m_context, 0, sizeof(m_context));
1517 }
1518 else
1519 {
1520 memcpy(&m_context, pContext, sizeof(m_context));
1521 }
1522}
1523
1524
1525#ifdef _DEBUG
1526// Thread proc for interop stress coverage. Have an unmanaged thread
1527// that just loops throwing native exceptions. This can test corner cases
1528// such as getting an native exception while the runtime is synced.
1529DWORD WINAPI DbgInteropStressProc(void * lpParameter)
1530{
1531 LIMITED_METHOD_CONTRACT;
1532
1533 int i = 0;
1534 int zero = 0;
1535
1536
1537 // This will ensure that the compiler doesn't flag our 1/0 exception below at compile-time.
1538 if (lpParameter != NULL)
1539 {
1540 zero = 1;
1541 }
1542
1543 // Note that this thread is a non-runtime thread. So it can't take any CLR locks
1544 // or do anything else that may block the helper thread.
1545 // (Log statements take CLR locks).
1546 while(true)
1547 {
1548 i++;
1549
1550 if ((i % 10) != 0)
1551 {
1552 // Generate an in-band event.
1553 PAL_CPP_TRY
1554 {
1555 // Throw a handled exception. Don't use an AV since that's pretty special.
1556 *(int*)lpParameter = 1 / zero;
1557 }
1558 PAL_CPP_CATCH_ALL
1559 {
1560 }
1561 PAL_CPP_ENDTRY
1562 }
1563 else
1564 {
1565 // Generate the occasional oob-event.
1566 WszOutputDebugString(W("Ping from DbgInteropStressProc"));
1567 }
1568
1569 // This helps parallelize if we have a lot of threads, and keeps us from
1570 // chewing too much CPU time.
1571 ClrSleepEx(2000,FALSE);
1572 ClrSleepEx(GetRandomInt(1000), FALSE);
1573 }
1574
1575 return 0;
1576}
1577
1578// ThreadProc that does everything in a can't stop region.
1579DWORD WINAPI DbgInteropCantStopStressProc(void * lpParameter)
1580{
1581 WRAPPER_NO_CONTRACT;
1582
1583 // This will mark us as a can't stop region.
1584 ClrFlsSetThreadType (ThreadType_DbgHelper);
1585
1586 return DbgInteropStressProc(lpParameter);
1587}
1588
1589// Generate lots of OOB events.
1590DWORD WINAPI DbgInteropDummyStressProc(void * lpParameter)
1591{
1592 LIMITED_METHOD_CONTRACT;
1593
1594 ClrSleepEx(1,FALSE);
1595 return 0;
1596}
1597
1598DWORD WINAPI DbgInteropOOBStressProc(void * lpParameter)
1599{
1600 WRAPPER_NO_CONTRACT;
1601
1602 int i = 0;
1603 while(true)
1604 {
1605 i++;
1606 if (i % 10 == 1)
1607 {
1608 // Create a dummy thread. That generates 2 oob events
1609 // (1 for create, 1 for destroy)
1610 DWORD id;
1611 ::CreateThread(NULL, 0, DbgInteropDummyStressProc, NULL, 0, &id);
1612 }
1613 else
1614 {
1615 // Generate the occasional oob-event.
1616 WszOutputDebugString(W("OOB ping from "));
1617 }
1618
1619 ClrSleepEx(3000, FALSE);
1620 }
1621
1622 return 0;
1623}
1624
1625// List of the different possible stress procs.
1626LPTHREAD_START_ROUTINE g_pStressProcs[] =
1627{
1628 DbgInteropOOBStressProc,
1629 DbgInteropCantStopStressProc,
1630 DbgInteropStressProc
1631};
1632#endif
1633
1634
1635DebuggerHeap * Debugger::GetInteropSafeHeap()
1636{
1637 CONTRACTL
1638 {
1639 SO_INTOLERANT;
1640 THROWS;
1641 GC_NOTRIGGER;
1642 }
1643 CONTRACTL_END;
1644
1645 // Lazily initialize our heap.
1646 if (!m_heap.IsInit())
1647 {
1648 _ASSERTE(!"InteropSafe Heap should have already been initialized in LazyInit");
1649
1650 // Just in case we miss it in retail, convert to OOM here:
1651 ThrowOutOfMemory();
1652 }
1653
1654 return &m_heap;
1655}
1656
1657DebuggerHeap * Debugger::GetInteropSafeHeap_NoThrow()
1658{
1659 CONTRACTL
1660 {
1661 SO_INTOLERANT;
1662 NOTHROW;
1663 GC_NOTRIGGER;
1664 }
1665 CONTRACTL_END;
1666
1667 // Lazily initialize our heap.
1668 if (!m_heap.IsInit())
1669 {
1670 _ASSERTE(!"InteropSafe Heap should have already been initialized in LazyInit");
1671
1672 // Just in case we miss it in retail, convert to OOM here:
1673 return NULL;
1674 }
1675 return &m_heap;
1676}
1677
1678DebuggerHeap * Debugger::GetInteropSafeExecutableHeap()
1679{
1680 CONTRACTL
1681 {
1682 SO_INTOLERANT;
1683 THROWS;
1684 GC_NOTRIGGER;
1685 }
1686 CONTRACTL_END;
1687
1688 // Lazily initialize our heap.
1689 if (!m_executableHeap.IsInit())
1690 {
1691 _ASSERTE(!"InteropSafe Executable Heap should have already been initialized in LazyInit");
1692
1693 // Just in case we miss it in retail, convert to OOM here:
1694 ThrowOutOfMemory();
1695 }
1696
1697 return &m_executableHeap;
1698}
1699
1700DebuggerHeap * Debugger::GetInteropSafeExecutableHeap_NoThrow()
1701{
1702 CONTRACTL
1703 {
1704 SO_INTOLERANT;
1705 NOTHROW;
1706 GC_NOTRIGGER;
1707 }
1708 CONTRACTL_END;
1709
1710 // Lazily initialize our heap.
1711 if (!m_executableHeap.IsInit())
1712 {
1713 _ASSERTE(!"InteropSafe Executable Heap should have already been initialized in LazyInit");
1714
1715 // Just in case we miss it in retail, convert to OOM here:
1716 return NULL;
1717 }
1718 return &m_executableHeap;
1719}
1720
1721//---------------------------------------------------------------------------------------
1722//
1723// Notify potential debugger that the runtime has started up
1724//
1725//
1726// Assumptions:
1727// Called during startup path
1728//
1729// Notes:
1730// If no debugger is attached, this does nothing.
1731//
1732//---------------------------------------------------------------------------------------
1733void Debugger::RaiseStartupNotification()
1734{
1735 // Right-side will read this field from OOP via DAC-primitive to determine attach or launch case.
1736 // We do an interlocked increment to gaurantee this is an atomic memory write, and to ensure
1737 // that it's flushed from any CPU cache into memory.
1738 InterlockedIncrement(&m_fLeftSideInitialized);
1739
1740#ifndef FEATURE_DBGIPC_TRANSPORT_VM
1741 // If we are remote debugging, don't send the event now if a debugger is not attached. No one will be
1742 // listening, and we will fail. However, we still want to initialize the variable above.
1743 DebuggerIPCEvent startupEvent;
1744 InitIPCEvent(&startupEvent, DB_IPCE_LEFTSIDE_STARTUP, NULL, VMPTR_AppDomain::NullPtr());
1745
1746 SendRawEvent(&startupEvent);
1747
1748 // RS will set flags from OOP while we're stopped at the event if it wants to attach.
1749#endif // FEATURE_DBGIPC_TRANSPORT_VM
1750}
1751
1752
1753//---------------------------------------------------------------------------------------
1754//
1755// Sends a raw managed debug event to the debugger.
1756//
1757// Arguments:
1758// pManagedEvent - managed debug event
1759//
1760//
1761// Notes:
1762// This can be called even if a debugger is not attached.
1763// The entire process will get frozen by the debugger once we send. The debugger
1764// needs to resume the process. It may detach as well.
1765// See code:IsEventDebuggerNotification for decoding this event. These methods must stay in sync.
1766// The debugger process reads the events via code:CordbProcess.CopyManagedEventFromTarget.
1767//
1768//---------------------------------------------------------------------------------------
1769void Debugger::SendRawEvent(const DebuggerIPCEvent * pManagedEvent)
1770{
1771#if defined(FEATURE_DBGIPC_TRANSPORT_VM)
1772 HRESULT hr = g_pDbgTransport->SendDebugEvent(const_cast<DebuggerIPCEvent *>(pManagedEvent));
1773
1774 if (FAILED(hr))
1775 {
1776 _ASSERTE(!"Failed to send debugger event");
1777
1778 STRESS_LOG1(LF_CORDB, LL_INFO1000, "D::SendIPCEvent Error on Send with 0x%x\n", hr);
1779 UnrecoverableError(hr,
1780 0,
1781 FILE_DEBUG,
1782 LINE_DEBUG,
1783 false);
1784
1785 // @dbgtodo Mac - what can we do here?
1786 }
1787#else
1788 // We get to send an array of ULONG_PTRs as data with the notification.
1789 // The debugger can then use ReadProcessMemory to read through this array.
1790 ULONG_PTR rgData [] = {
1791 CLRDBG_EXCEPTION_DATA_CHECKSUM,
1792 (ULONG_PTR) g_pMSCorEE,
1793 (ULONG_PTR) pManagedEvent
1794 };
1795
1796 // If no debugger attached, then don't bother raising a 1st-chance exception because nobody will sniff it.
1797 // @dbgtodo iDNA: in iDNA case, the recorder may sniff it.
1798 if (!IsDebuggerPresent())
1799 {
1800 return;
1801 }
1802
1803 //
1804 // Physically send the event via an OS Exception. We're using exceptions as a notification
1805 // mechanism on top of the OS native debugging pipeline.
1806 // @dbgtodo cross-plat - this needs to be cross-plat.
1807 //
1808 EX_TRY
1809 {
1810 const DWORD dwFlags = 0; // continuable (eg, Debugger can continue GH)
1811 RaiseException(CLRDBG_NOTIFICATION_EXCEPTION_CODE, dwFlags, NumItems(rgData), rgData);
1812
1813 // If debugger continues "GH" (DBG_CONTINUE), then we land here.
1814 // This is the expected path for a well-behaved ICorDebug debugger.
1815 }
1816 EX_CATCH
1817 {
1818 // If no debugger is attached, or if the debugger continues "GN" (DBG_EXCEPTION_NOT_HANDLED), then we land here.
1819 // A naive (not-ICorDebug aware) native-debugger won't handle the exception and so land us here.
1820 // We may also get here if a debugger detaches at the Exception notification
1821 // (and thus implicitly continues GN).
1822 }
1823 EX_END_CATCH(SwallowAllExceptions);
1824#endif // FEATURE_DBGIPC_TRANSPORT_VM
1825}
1826
1827//---------------------------------------------------------------------------------------
1828// Send a createProcess event to give the RS a chance to do SetDesiredNGENFlags
1829//
1830// Arguments:
1831// pDbgLockHolder - lock holder.
1832//
1833// Assumptions:
1834// Lock is initially held. This will toggle the lock to send an IPC event.
1835// This will start a synchronization.
1836//
1837// Notes:
1838// In V2, this also gives the RS a chance to intialize the IPC protocol.
1839// Spefically, this needs to be sent before the LS can send a sync-complete.
1840//---------------------------------------------------------------------------------------
1841void Debugger::SendCreateProcess(DebuggerLockHolder * pDbgLockHolder)
1842{
1843 pDbgLockHolder->Release();
1844
1845 // Encourage helper thread to spin up so that we're in a consistent state.
1846 PollWaitingForHelper();
1847
1848 // we don't need to use SENDIPCEVENT_BEGIN/END macros that perform the debug-suspend aware checks,
1849 // as this code executes on the startup path...
1850 SENDIPCEVENT_RAW_BEGIN(pDbgLockHolder);
1851
1852 // Send a CreateProcess event.
1853 // @dbgtodo pipeline - eliminate these reasons for needing a CreateProcess event (part of pipeline feature crew)
1854 // This will let the RS know that the IPC block is up + ready, and then the RS can read it.
1855 // The RS will then update the DCB with enough information so that we can send the sync-complete.
1856 // (such as letting us know whether we're interop-debugging or not).
1857 DebuggerIPCEvent event;
1858 InitIPCEvent(&event, DB_IPCE_CREATE_PROCESS, NULL, VMPTR_AppDomain::NullPtr());
1859 SendRawEvent(&event);
1860
1861 // @dbgtodo inspection- it doesn't really make sense to sync on a CreateProcess. We only have 1 thread
1862 // in the CLR and we know exactly what state we're in and we can ensure that we're synchronized.
1863 // For V3,RS should be able to treat a CreateProcess like a synchronized.
1864 // Remove this in V3 as we make SetDesiredNgenFlags operate OOP.
1865 TrapAllRuntimeThreads();
1866
1867 // Must have a thread object so that we ensure that we will actually block here.
1868 // This ensures the debuggee is actually stopped at startup, and
1869 // this gives the debugger a chance to call SetDesiredNGENFlags before we
1870 // set s_fCanChangeNgenFlags to FALSE.
1871 _ASSERTE(GetThread() != NULL);
1872 SENDIPCEVENT_RAW_END;
1873
1874 pDbgLockHolder->Acquire();
1875}
1876
1877#if !defined(FEATURE_PAL)
1878
1879HANDLE g_hContinueStartupEvent = INVALID_HANDLE_VALUE;
1880
1881CLR_ENGINE_METRICS g_CLREngineMetrics = {
1882 sizeof(CLR_ENGINE_METRICS),
1883 CorDebugVersion_4_0,
1884 &g_hContinueStartupEvent};
1885
1886#define StartupNotifyEventNamePrefix W("TelestoStartupEvent_")
1887const int cchEventNameBufferSize = sizeof(StartupNotifyEventNamePrefix)/sizeof(WCHAR) + 8; // + hex DWORD (8). NULL terminator is included in sizeof(StartupNotifyEventNamePrefix)
1888HANDLE OpenStartupNotificationEvent()
1889{
1890 DWORD debuggeePID = GetCurrentProcessId();
1891 WCHAR szEventName[cchEventNameBufferSize];
1892 swprintf_s(szEventName, cchEventNameBufferSize, StartupNotifyEventNamePrefix W("%08x"), debuggeePID);
1893
1894 return WszOpenEvent(MAXIMUM_ALLOWED | SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, szEventName);
1895}
1896
1897void NotifyDebuggerOfStartup()
1898{
1899 // Create the continue event first so that we guarantee that any
1900 // enumeration of this process will get back a valid continue event
1901 // the instant we signal the startup notification event.
1902
1903 CONSISTENCY_CHECK(INVALID_HANDLE_VALUE == g_hContinueStartupEvent);
1904 g_hContinueStartupEvent = WszCreateEvent(NULL, TRUE, FALSE, NULL);
1905 CONSISTENCY_CHECK(INVALID_HANDLE_VALUE != g_hContinueStartupEvent); // we reserve this value for error conditions in EnumerateCLRs
1906
1907 HANDLE startupEvent = OpenStartupNotificationEvent();
1908 if (startupEvent != NULL)
1909 {
1910 // signal notification event
1911 SetEvent(startupEvent);
1912 CloseHandle(startupEvent);
1913 startupEvent = NULL;
1914
1915 // wait on continue startup event
1916 // The debugger may attach to us while we're blocked here.
1917 WaitForSingleObject(g_hContinueStartupEvent, INFINITE);
1918 }
1919
1920 CloseHandle(g_hContinueStartupEvent);
1921 g_hContinueStartupEvent = NULL;
1922}
1923
1924#endif // !FEATURE_PAL
1925
1926//---------------------------------------------------------------------------------------
1927//
1928// Initialize Left-Side debugger object
1929//
1930// Return Value:
1931// S_OK on successs. May also throw.
1932//
1933// Assumptions:
1934// This is called in the startup path.
1935//
1936// Notes:
1937// Startup initializes any necessary debugger objects, including creating
1938// and starting the Runtime Controller thread. Once the RC thread is started
1939// and we return successfully, the Debugger object can expect to have its
1940// event handlers called.
1941//
1942//---------------------------------------------------------------------------------------
1943HRESULT Debugger::Startup(void)
1944{
1945 CONTRACTL
1946 {
1947 SO_INTOLERANT;
1948 THROWS;
1949 GC_TRIGGERS;
1950 }
1951 CONTRACTL_END;
1952
1953 HRESULT hr = S_OK;
1954
1955 _ASSERTE(g_pEEInterface != NULL);
1956
1957#if !defined(FEATURE_PAL)
1958 // This may block while an attach occurs.
1959 NotifyDebuggerOfStartup();
1960#endif // !FEATURE_PAL
1961 {
1962 DebuggerLockHolder dbgLockHolder(this);
1963
1964 // Stubs in Stacktraces are always enabled.
1965 g_EnableSIS = true;
1966
1967 // We can get extra Interop-debugging test coverage by having some auxillary unmanaged
1968 // threads running and throwing debug events. Keep these stress procs separate so that
1969 // we can focus on certain problem areas.
1970 #ifdef _DEBUG
1971 g_DbgShouldntUseDebugger = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgNoDebugger) != 0;
1972
1973
1974 // Creates random thread procs.
1975 DWORD dwRegVal = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgExtraThreads);
1976 DWORD dwId;
1977 DWORD i;
1978
1979 if (dwRegVal > 0)
1980 {
1981 for (i = 0; i < dwRegVal; i++)
1982 {
1983 int iProc = GetRandomInt(NumItems(g_pStressProcs));
1984 LPTHREAD_START_ROUTINE pStartRoutine = g_pStressProcs[iProc];
1985 ::CreateThread(NULL, 0, pStartRoutine, NULL, 0, &dwId);
1986 LOG((LF_CORDB, LL_INFO1000, "Created random thread (%d) with tid=0x%x\n", i, dwId));
1987 }
1988 }
1989
1990 dwRegVal = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgExtraThreadsIB);
1991 if (dwRegVal > 0)
1992 {
1993 for (i = 0; i < dwRegVal; i++)
1994 {
1995 ::CreateThread(NULL, 0, DbgInteropStressProc, NULL, 0, &dwId);
1996 LOG((LF_CORDB, LL_INFO1000, "Created extra thread (%d) with tid=0x%x\n", i, dwId));
1997 }
1998 }
1999
2000 dwRegVal = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgExtraThreadsCantStop);
2001 if (dwRegVal > 0)
2002 {
2003 for (i = 0; i < dwRegVal; i++)
2004 {
2005 ::CreateThread(NULL, 0, DbgInteropCantStopStressProc, NULL, 0, &dwId);
2006 LOG((LF_CORDB, LL_INFO1000, "Created extra thread 'can't-stop' (%d) with tid=0x%x\n", i, dwId));
2007 }
2008 }
2009
2010 dwRegVal = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgExtraThreadsOOB);
2011 if (dwRegVal > 0)
2012 {
2013 for (i = 0; i < dwRegVal; i++)
2014 {
2015 ::CreateThread(NULL, 0, DbgInteropOOBStressProc, NULL, 0, &dwId);
2016 LOG((LF_CORDB, LL_INFO1000, "Created extra thread OOB (%d) with tid=0x%x\n", i, dwId));
2017 }
2018 }
2019 #endif
2020
2021 #ifdef FEATURE_PAL
2022 PAL_InitializeDebug();
2023 #endif // FEATURE_PAL
2024
2025 // Lazily initialize the interop-safe heap
2026
2027 // Must be done before the RC thread is initialized.
2028 // @dbgtodo - In V2, LS was lazily initialized; but was eagerly pre-initialized if launched by debugger.
2029 // (This was for perf reasons). But we don't want Launch vs. Attach checks in the LS, so we now always
2030 // init. As we move more to OOP, this init will become cheaper.
2031 {
2032 LazyInit();
2033 DebuggerController::Initialize();
2034 }
2035
2036 InitializeHijackFunctionAddress();
2037
2038 // Also initialize the AppDomainEnumerationIPCBlock
2039 #if !defined(FEATURE_IPCMAN) || defined(FEATURE_DBGIPC_TRANSPORT_VM)
2040 m_pAppDomainCB = new (nothrow) AppDomainEnumerationIPCBlock();
2041 #else
2042 m_pAppDomainCB = g_pIPCManagerInterface->GetAppDomainBlock();
2043 #endif
2044
2045 if (m_pAppDomainCB == NULL)
2046 {
2047 LOG((LF_CORDB, LL_INFO100, "D::S: Failed to get AppDomain IPC block from IPCManager.\n"));
2048 ThrowHR(E_FAIL);
2049 }
2050
2051 hr = InitAppDomainIPC();
2052 _ASSERTE(SUCCEEDED(hr)); // throws on error.
2053
2054 // Allows the debugger (and profiler) diagnostics to be disabled so resources like
2055 // the named pipes and semaphores are not created.
2056 if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableDiagnostics) == 0)
2057 {
2058 return S_OK;
2059 }
2060
2061 // Create the runtime controller thread, a.k.a, the debug helper thread.
2062 // Don't use the interop-safe heap b/c we don't want to lazily create it.
2063 m_pRCThread = new DebuggerRCThread(this);
2064 _ASSERTE(m_pRCThread != NULL); // throws on oom
2065 TRACE_ALLOC(m_pRCThread);
2066
2067 hr = m_pRCThread->Init();
2068 _ASSERTE(SUCCEEDED(hr)); // throws on error
2069
2070 #if defined(FEATURE_DBGIPC_TRANSPORT_VM)
2071 // Create transport session and initialize it.
2072 g_pDbgTransport = new DbgTransportSession();
2073 hr = g_pDbgTransport->Init(m_pRCThread->GetDCB(), m_pAppDomainCB);
2074 if (FAILED(hr))
2075 {
2076 ShutdownTransport();
2077 ThrowHR(hr);
2078 }
2079 #ifdef FEATURE_PAL
2080 PAL_SetShutdownCallback(AbortTransport);
2081 #endif // FEATURE_PAL
2082 #endif // FEATURE_DBGIPC_TRANSPORT_VM
2083
2084 RaiseStartupNotification();
2085
2086 // See if we need to spin up the helper thread now, rather than later.
2087 DebuggerIPCControlBlock* pIPCControlBlock = m_pRCThread->GetDCB();
2088 (void)pIPCControlBlock; //prevent "unused variable" error from GCC
2089
2090 _ASSERTE(pIPCControlBlock != NULL);
2091 _ASSERTE(!pIPCControlBlock->m_rightSideShouldCreateHelperThread);
2092 {
2093 // Create the win32 thread for the helper and let it run free.
2094 hr = m_pRCThread->Start();
2095
2096 // convert failure to exception as with old contract
2097 if (FAILED(hr))
2098 {
2099 ThrowHR(hr);
2100 }
2101
2102 LOG((LF_CORDB, LL_EVERYTHING, "Start was successful\n"));
2103 }
2104
2105 #ifdef TEST_DATA_CONSISTENCY
2106 // if we have set the environment variable TestDataConsistency, run the data consistency test.
2107 // See code:DataTest::TestDataSafety for more information
2108 if ((g_pConfig != NULL) && (g_pConfig->TestDataConsistency() == true))
2109 {
2110 DataTest dt;
2111 dt.TestDataSafety();
2112 }
2113 #endif
2114 }
2115
2116#ifdef FEATURE_PAL
2117 // Signal the debugger (via dbgshim) and wait until it is ready for us to
2118 // continue. This needs to be outside the lock and after the transport is
2119 // initialized.
2120 if (PAL_NotifyRuntimeStarted())
2121 {
2122 // The runtime was successfully launched and attached so mark it now
2123 // so no notifications are missed especially the initial module load
2124 // which would cause debuggers problems with reliable setting breakpoints
2125 // in startup code or Main.
2126 MarkDebuggerAttachedInternal();
2127 }
2128#endif // FEATURE_PAL
2129
2130 // We don't bother changing this process's permission.
2131 // A managed debugger will have the SE_DEBUG permission which will allow it to open our process handle,
2132 // even if we're a guest account.
2133
2134 return hr;
2135}
2136
2137//---------------------------------------------------------------------------------------
2138// Finishes startup once we have a Thread object.
2139//
2140// Arguments:
2141// pThread - the current thread. Must be non-null
2142//
2143// Notes:
2144// Most debugger initialization is done in code:Debugger.Startup,
2145// However, debugger can't block on synchronization without a Thread object,
2146// so sending IPC events must wait until after we have a thread object.
2147//---------------------------------------------------------------------------------------
2148HRESULT Debugger::StartupPhase2(Thread * pThread)
2149{
2150 CONTRACTL
2151 {
2152 SO_INTOLERANT;
2153 THROWS;
2154 GC_TRIGGERS;
2155 }
2156 CONTRACTL_END;
2157
2158 HRESULT hr = S_OK;
2159
2160 // Must have a thread so that we can block
2161 _ASSERTE(pThread != NULL);
2162
2163 DebuggerLockHolder dbgLockHolder(this);
2164
2165 // @dbgtodo - This may need to change when we remove SetupSyncEvent...
2166 // If we're launching, then sync now so that the RS gets an early chance to dispatch the CreateProcess event.
2167 // This is especially important b/c certain portions of the ICorDebugAPI (like setting ngen flags) are only
2168 // valid during the CreateProcess callback in the launch case.
2169 // We need to send the callback early enough so those APIs can set the flags before they're actually used.
2170 // We also ensure the debugger is actually attached.
2171 if (SUCCEEDED(hr) && CORDebuggerAttached())
2172 {
2173 StartCanaryThread();
2174 SendCreateProcess(&dbgLockHolder); // toggles lock
2175 }
2176
2177 // After returning from debugger startup we assume that the runtime might start using the NGEN flags to make
2178 // binding decisions. From now on the debugger can not influence NGEN binding policy
2179 // Use volatile store to guarantee make the value visible to the DAC (the store can be optimized out otherwise)
2180 VolatileStoreWithoutBarrier(&s_fCanChangeNgenFlags, FALSE);
2181
2182 // Must release the lock (which would be done at the end of this method anyways) so that
2183 // the helper thread can do the jit-attach.
2184 dbgLockHolder.Release();
2185
2186
2187#ifdef _DEBUG
2188 // Give chance for stress harnesses to launch a managed debugger when a managed app starts up.
2189 // This lets us run a set of managed apps under a debugger.
2190 if (!CORDebuggerAttached())
2191 {
2192 #define DBG_ATTACH_ON_STARTUP_ENV_VAR W("COMPlus_DbgAttachOnStartup")
2193 PathString temp;
2194 // We explicitly just check the env because we don't want a switch this invasive to be global.
2195 DWORD fAttach = WszGetEnvironmentVariable(DBG_ATTACH_ON_STARTUP_ENV_VAR, temp) > 0;
2196
2197 if (fAttach)
2198 {
2199 // Remove the env var from our process so that the debugger we spin up won't inherit it.
2200 // Else, if the debugger is managed, we'll have an infinite recursion.
2201 BOOL fOk = WszSetEnvironmentVariable(DBG_ATTACH_ON_STARTUP_ENV_VAR, NULL);
2202
2203 if (fOk)
2204 {
2205 // We've already created the helper thread (which can service the attach request)
2206 // So just do a normal jit-attach now.
2207
2208 SString szName(W("DebuggerStressStartup"));
2209 SString szDescription(W("MDA used for debugger-stress scenario. This is fired to trigger a jit-attach")
2210 W("to allow us to attach a debugger to any managed app that starts up.")
2211 W("This MDA is only fired when the 'DbgAttachOnStartup' COM+ knob/reg-key is set on checked builds."));
2212 SString szXML(W("<xml>See the description</xml>"));
2213
2214 SendMDANotification(
2215 NULL, // NULL b/c we don't have a thread yet
2216 &szName,
2217 &szDescription,
2218 &szXML,
2219 ((CorDebugMDAFlags) 0 ),
2220 TRUE // this will force the jit-attach
2221 );
2222 }
2223 }
2224 }
2225#endif
2226
2227
2228 return hr;
2229}
2230
2231
2232//---------------------------------------------------------------------------------------
2233//
2234// Public entrypoint into the debugger to force the lazy data to be initialized at a
2235// controlled point in time. This is useful for those callers into the debugger (e.g.,
2236// ETW rundown) that know they will need the lazy data initialized but cannot afford to
2237// have it initialized unpredictably or inside a lock.
2238//
2239// This may be called more than once, and will know to initialize the lazy data only
2240// once.
2241//
2242
2243void Debugger::InitializeLazyDataIfNecessary()
2244{
2245 CONTRACTL
2246 {
2247 SO_NOT_MAINLINE;
2248 THROWS;
2249 GC_TRIGGERS;
2250 }
2251 CONTRACTL_END;
2252
2253 if (!HasLazyData())
2254 {
2255 DebuggerLockHolder lockHolder(this);
2256 LazyInit(); // throws
2257 }
2258}
2259
2260
2261/******************************************************************************
2262Lazy initialize stuff once we know we are debugging.
2263This reduces the startup cost in the non-debugging case.
2264
2265We can do this at a bunch of random strategic places.
2266 ******************************************************************************/
2267
2268HRESULT Debugger::LazyInitWrapper()
2269{
2270 CONTRACTL
2271 {
2272 SO_INTOLERANT;
2273 NOTHROW;
2274 GC_NOTRIGGER;
2275 PRECONDITION(ThisMaybeHelperThread());
2276 }
2277 CONTRACTL_END;
2278
2279 HRESULT hr = S_OK;
2280
2281 // Do lazy initialization now.
2282 EX_TRY
2283 {
2284 LazyInit(); // throws on errors.
2285 }
2286 EX_CATCH
2287 {
2288 Exception *_ex = GET_EXCEPTION();
2289 hr = _ex->GetHR();
2290 STRESS_LOG1(LF_CORDB, LL_ALWAYS, "LazyInit failed w/ hr:0x%08x\n", hr);
2291 }
2292 EX_END_CATCH(SwallowAllExceptions);
2293
2294 return hr;
2295}
2296
2297void Debugger::LazyInit()
2298{
2299 CONTRACTL
2300 {
2301 SO_INTOLERANT;
2302 THROWS;
2303 GC_NOTRIGGER;
2304 PRECONDITION(ThreadHoldsLock()); // ensure we're serialized, requires GC_NOTRIGGER
2305
2306 PRECONDITION(ThisMaybeHelperThread());
2307 }
2308 CONTRACTL_END;
2309
2310 // Have knob that catches places where we lazy init.
2311 _ASSERTE(!g_DbgShouldntUseDebugger);
2312
2313 // If we're already init, then bail.
2314 if (m_pLazyData != NULL)
2315 {
2316 return;
2317 }
2318
2319
2320
2321
2322 // Lazily create our heap.
2323 HRESULT hr = m_heap.Init(FALSE);
2324 IfFailThrow(hr);
2325
2326 hr = m_executableHeap.Init(TRUE);
2327 IfFailThrow(hr);
2328
2329 m_pLazyData = new (interopsafe) DebuggerLazyInit();
2330 _ASSERTE(m_pLazyData != NULL); // throws on oom.
2331
2332 m_pLazyData->Init();
2333
2334}
2335
2336HelperThreadFavor::HelperThreadFavor() :
2337 m_fpFavor(NULL),
2338 m_pFavorData(NULL),
2339 m_FavorReadEvent(NULL),
2340 m_FavorLock(CrstDebuggerFavorLock, CRST_DEFAULT),
2341 m_FavorAvailableEvent(NULL)
2342{
2343}
2344
2345void HelperThreadFavor::Init()
2346{
2347 CONTRACTL
2348 {
2349 SO_INTOLERANT;
2350 THROWS;
2351 GC_NOTRIGGER;
2352 PRECONDITION(ThisMaybeHelperThread());
2353 }
2354 CONTRACTL_END;
2355
2356 // Create events for managing favors.
2357 m_FavorReadEvent = CreateWin32EventOrThrow(NULL, kAutoResetEvent, FALSE);
2358 m_FavorAvailableEvent = CreateWin32EventOrThrow(NULL, kAutoResetEvent, FALSE);
2359}
2360
2361
2362
2363DebuggerLazyInit::DebuggerLazyInit() :
2364 m_pPendingEvals(NULL),
2365 // @TODO: a-meicht
2366 // Major clean up needed for giving the right flag
2367 // There are cases where DebuggerDataLock is taken by managed thread and unmanaged trhead is also trying to take it.
2368 // It could cause deadlock if we toggle GC upon taking lock.
2369 // Unfortunately UNSAFE_COOPGC is not enough. There is a code path in Jit comipling that we are in GC Preemptive
2370 // enabled. workaround by orring the unsafe_anymode flag. But we really need to do proper clean up.
2371 //
2372 // NOTE: If this ever gets fixed, you should replace CALLED_IN_DEBUGGERDATALOCK_HOLDER_SCOPE_MAY_GC_TRIGGERS_CONTRACT
2373 // with appropriate contracts at each site.
2374 //
2375 m_DebuggerDataLock(CrstDebuggerJitInfo, (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_REENTRANCY | CRST_DEBUGGER_THREAD)),
2376 m_CtrlCMutex(NULL),
2377 m_exAttachEvent(NULL),
2378 m_exUnmanagedAttachEvent(NULL),
2379 m_garbageCollectionBlockerEvent(NULL),
2380 m_DebuggerHandlingCtrlC(NULL)
2381{
2382}
2383
2384void DebuggerLazyInit::Init()
2385{
2386 CONTRACTL
2387 {
2388 SO_INTOLERANT;
2389 THROWS;
2390 GC_NOTRIGGER;
2391 PRECONDITION(ThisMaybeHelperThread());
2392 }
2393 CONTRACTL_END;
2394
2395 // Caller ensures this isn't double-called.
2396
2397 // This event is only used in the unmanaged attach case. We must mark this event handle as inheritable.
2398 // Otherwise, the unmanaged debugger won't be able to notify us.
2399 //
2400 // Note that PAL currently doesn't support specifying the security attributes when creating an event, so
2401 // unmanaged attach for unhandled exceptions is broken on PAL.
2402 SECURITY_ATTRIBUTES* pSA = NULL;
2403 SECURITY_ATTRIBUTES secAttrib;
2404 secAttrib.nLength = sizeof(secAttrib);
2405 secAttrib.lpSecurityDescriptor = NULL;
2406 secAttrib.bInheritHandle = TRUE;
2407
2408 pSA = &secAttrib;
2409
2410 // Create some synchronization events...
2411 // these events stay signaled all the time except when an attach is in progress
2412 m_exAttachEvent = CreateWin32EventOrThrow(NULL, kManualResetEvent, TRUE);
2413 m_exUnmanagedAttachEvent = CreateWin32EventOrThrow(pSA, kManualResetEvent, TRUE);
2414
2415 m_CtrlCMutex = CreateWin32EventOrThrow(NULL, kAutoResetEvent, FALSE);
2416 m_DebuggerHandlingCtrlC = FALSE;
2417
2418 m_garbageCollectionBlockerEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2419
2420 // Let the helper thread lazy init stuff too.
2421 m_RCThread.Init();
2422}
2423
2424
2425DebuggerLazyInit::~DebuggerLazyInit()
2426{
2427 {
2428 USHORT cBlobs = m_pMemBlobs.Count();
2429 void **rgpBlobs = m_pMemBlobs.Table();
2430
2431 for (int i = 0; i < cBlobs; i++)
2432 {
2433 g_pDebugger->ReleaseRemoteBuffer(rgpBlobs[i], false);
2434 }
2435 }
2436
2437 if (m_pPendingEvals)
2438 {
2439 DeleteInteropSafe(m_pPendingEvals);
2440 m_pPendingEvals = NULL;
2441 }
2442
2443 if (m_CtrlCMutex != NULL)
2444 {
2445 CloseHandle(m_CtrlCMutex);
2446 }
2447
2448 if (m_exAttachEvent != NULL)
2449 {
2450 CloseHandle(m_exAttachEvent);
2451 }
2452
2453 if (m_exUnmanagedAttachEvent != NULL)
2454 {
2455 CloseHandle(m_exUnmanagedAttachEvent);
2456 }
2457
2458 if (m_garbageCollectionBlockerEvent != NULL)
2459 {
2460 CloseHandle(m_garbageCollectionBlockerEvent);
2461 }
2462}
2463
2464
2465//
2466// RequestFavor gets the debugger helper thread to call a function. It's
2467// typically called when the current thread can't call the function directly,
2468// e.g, there isn't enough stack space.
2469//
2470// RequestFavor can be called in stack-overflow scenarios and thus explicitly
2471// avoids any lazy initialization.
2472// It blocks until the favor callback completes.
2473//
2474// Parameters:
2475// fp - a non-null Favour callback function
2476// pData - the parameter passed to the favor callback function. This can be any value.
2477//
2478// Return values:
2479// S_OK if the function succeeds, else a failure HRESULT
2480//
2481
2482HRESULT Debugger::RequestFavor(FAVORCALLBACK fp, void * pData)
2483{
2484 CONTRACTL
2485 {
2486 SO_INTOLERANT;
2487 NOTHROW;
2488 GC_TRIGGERS;
2489 PRECONDITION(fp != NULL);
2490 }
2491 CONTRACTL_END;
2492
2493 if (m_pRCThread == NULL ||
2494 m_pRCThread->GetRCThreadId() == GetCurrentThreadId())
2495 {
2496 // Since favors are only used internally, we know that the helper should alway be up and ready
2497 // to handle them. Also, since favors can be used in low-stack scenarios, there's not any
2498 // extra initialization needed for them.
2499 _ASSERTE(!"Helper not initialized for favors.");
2500 return E_UNEXPECTED;
2501 }
2502
2503 m_pRCThread->DoFavor(fp, pData);
2504 return S_OK;
2505}
2506
2507/******************************************************************************
2508// Called to set the interface that the Runtime exposes to us.
2509 ******************************************************************************/
2510void Debugger::SetEEInterface(EEDebugInterface* i)
2511{
2512 LIMITED_METHOD_CONTRACT;
2513
2514 // @@@
2515
2516 // Implements DebugInterface API
2517
2518 g_pEEInterface = i;
2519
2520}
2521
2522
2523/******************************************************************************
2524// Called to shut down the debugger. This stops the RC thread and cleans
2525// the object up.
2526 ******************************************************************************/
2527void Debugger::StopDebugger(void)
2528{
2529 CONTRACTL
2530 {
2531 SO_INTOLERANT;
2532 NOTHROW;
2533 GC_NOTRIGGER;
2534 }
2535 CONTRACTL_END;
2536
2537 // Leak almost everything on process exit. The OS will clean it up anyways and trying to
2538 // clean it up ourselves is just one more place we may AV / deadlock.
2539
2540#if defined(FEATURE_DBGIPC_TRANSPORT_VM)
2541 ShutdownTransport();
2542#endif // FEATURE_DBGIPC_TRANSPORT_VM
2543
2544 // Ping the helper thread to exit. This will also prevent the helper from servicing new requests.
2545 if (m_pRCThread != NULL)
2546 {
2547 m_pRCThread->AsyncStop();
2548 }
2549
2550 // Also clean up the AppDomain stuff since this is cross-process.
2551 TerminateAppDomainIPC ();
2552
2553 //
2554 // Tell the VM to clear out all references to the debugger before we start cleaning up,
2555 // so that nothing will reference (accidentally) through the partially cleaned up debugger.
2556 //
2557 // NOTE: we cannot clear out g_pDebugger before the delete call because the
2558 // stuff in delete (particularly deleteinteropsafe) needs to look at it.
2559 //
2560 g_pEEInterface->ClearAllDebugInterfaceReferences();
2561 g_pDebugger = NULL;
2562}
2563
2564
2565/* ------------------------------------------------------------------------ *
2566 * JIT Interface routines
2567 * ------------------------------------------------------------------------ */
2568
2569
2570/******************************************************************************
2571 *
2572 ******************************************************************************/
2573DebuggerMethodInfo *Debugger::CreateMethodInfo(Module *module, mdMethodDef md)
2574{
2575 CONTRACTL
2576 {
2577 SO_INTOLERANT;
2578 THROWS;
2579 GC_NOTRIGGER;
2580
2581 PRECONDITION(HasDebuggerDataLock());
2582 }
2583 CONTRACTL_END;
2584
2585
2586 // <TODO>@todo perf: creating these on the heap is slow. We should use a
2587 // pool and create them out of there since we never free them
2588 // until the AD is unloaded.</TODO>
2589 //
2590 DebuggerMethodInfo *mi = new (interopsafe) DebuggerMethodInfo(module, md);
2591 _ASSERTE(mi != NULL); // throws on oom error
2592
2593 TRACE_ALLOC(mi);
2594
2595 LOG((LF_CORDB, LL_INFO100000, "D::CreateMethodInfo module=%p, token=0x%08x, info=%p\n",
2596 module, md, mi));
2597
2598 //
2599 // Lock a mutex when changing the table.
2600 //
2601 //@TODO : _ASSERTE(EnC);
2602 HRESULT hr;
2603 hr =InsertToMethodInfoList(mi);
2604
2605 if (FAILED(hr))
2606 {
2607 LOG((LF_CORDB, LL_EVERYTHING, "IAHOL Failed!!\n"));
2608 DeleteInteropSafe(mi);
2609 return NULL;
2610 }
2611 return mi;
2612
2613}
2614
2615
2616
2617
2618
2619/******************************************************************************
2620// void Debugger::JITComplete(): JITComplete is called by
2621// the jit interface when the JIT completes, successfully or not.
2622//
2623// MethodDesc* fd: MethodDesc of the code that's been JITted
2624// BYTE* newAddress: The address of that the method begins at.
2625// If newAddress is NULL then the JIT failed. Remember that this
2626// gets called before the start address of the MethodDesc gets set,
2627// and so methods like GetFunctionAddress & GetFunctionSize won't work.
2628//
2629// <TODO>@Todo If we're passed 0 for the newAddress param, the jit has been
2630// cancelled & should be undone.</TODO>
2631 ******************************************************************************/
2632void Debugger::JITComplete(MethodDesc* fd, TADDR newAddress)
2633{
2634
2635 CONTRACTL
2636 {
2637 SO_INTOLERANT;
2638 THROWS;
2639 PRECONDITION(!HasDebuggerDataLock());
2640 PRECONDITION(newAddress != NULL);
2641 CALLED_IN_DEBUGGERDATALOCK_HOLDER_SCOPE_MAY_GC_TRIGGERS_CONTRACT;
2642 }
2643 CONTRACTL_END;
2644
2645 LOG((LF_CORDB, LL_INFO100000, "D::JITComplete: md:0x%x (%s::%s), address:0x%x.\n",
2646 fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2647 newAddress));
2648
2649#ifdef _TARGET_ARM_
2650 newAddress = newAddress|THUMB_CODE;
2651#endif
2652
2653 // @@@
2654 // Can be called on managed thread only
2655 // This API Implements DebugInterface
2656
2657 if (CORDebuggerAttached())
2658 {
2659 // Populate the debugger's cache of DJIs. Normally we can do this lazily,
2660 // the only reason we do it here is b/c the MethodDesc is not yet officially marked as "jitted",
2661 // and so we can't lazily create it yet. Furthermore, the binding operations may need the DJIs.
2662 //
2663 // This also gives the debugger a chance to know if new JMC methods are coming.
2664 DebuggerMethodInfo * dmi = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
2665 if (dmi == NULL)
2666 {
2667 goto Exit;
2668 }
2669 BOOL jiWasCreated = FALSE;
2670 DebuggerJitInfo * ji = dmi->CreateInitAndAddJitInfo(fd, newAddress, &jiWasCreated);
2671 if (!jiWasCreated)
2672 {
2673 // we've already been notified about this code, no work remains.
2674 // The JIT is occasionally asked to generate code for the same
2675 // method on two threads. When this occurs both threads will
2676 // return the same code pointer and this callback is invoked
2677 // multiple times.
2678 LOG((LF_CORDB, LL_INFO1000000, "D::JITComplete: md:0x%x (%s::%s), address:0x%x. Already created\n",
2679 fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2680 newAddress));
2681 goto Exit;
2682 }
2683
2684 LOG((LF_CORDB, LL_INFO1000000, "D::JITComplete: md:0x%x (%s::%s), address:0x%x. Created ji:0x%x\n",
2685 fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2686 newAddress, ji));
2687
2688 // Bind any IL patches to the newly jitted native code.
2689 HRESULT hr;
2690 hr = MapAndBindFunctionPatches(ji, fd, (CORDB_ADDRESS_TYPE *)newAddress);
2691 _ASSERTE(SUCCEEDED(hr));
2692 }
2693
2694 LOG((LF_CORDB, LL_EVERYTHING, "JitComplete completed successfully\n"));
2695
2696Exit:
2697 ;
2698}
2699
2700/******************************************************************************
2701// Get the number of fixed arguments to a function, i.e., the explicit args and the "this" pointer.
2702// This does not include other implicit arguments or varargs. This is used to compute a variable ID
2703// (see comment in CordbJITILFrame::ILVariableToNative for more detail)
2704// fVarArg is not used when this is called by Debugger::GetAndSendJITInfo, thus it has a default value.
2705// The return value is not used when this is called by Debugger::getVars.
2706 ******************************************************************************/
2707SIZE_T Debugger::GetArgCount(MethodDesc *fd,BOOL *fVarArg /* = NULL */)
2708{
2709 CONTRACTL
2710 {
2711 SO_INTOLERANT;
2712 THROWS;
2713 GC_NOTRIGGER;
2714 }
2715 CONTRACTL_END;
2716
2717 // Create a MetaSig for the given method's sig. (Easier than
2718 // picking the sig apart ourselves.)
2719 PCCOR_SIGNATURE pCallSig;
2720 DWORD cbCallSigSize;
2721
2722 fd->GetSig(&pCallSig, &cbCallSigSize);
2723
2724 if (pCallSig == NULL)
2725 {
2726 // Sig should only be null if the image is corrupted. (Even for lightweight-codegen)
2727 // We expect the jit+verifier to catch this, so that we never land here.
2728 // But just in case ...
2729 CONSISTENCY_CHECK_MSGF(false, ("Corrupted image, null sig.(%s::%s)", fd->m_pszDebugClassName, fd->m_pszDebugMethodName));
2730 return 0;
2731 }
2732
2733 MetaSig msig(pCallSig, cbCallSigSize, g_pEEInterface->MethodDescGetModule(fd), NULL, MetaSig::sigMember);
2734
2735 // Get the arg count.
2736 UINT32 NumArguments = msig.NumFixedArgs();
2737
2738 // Account for the 'this' argument.
2739 if (!(g_pEEInterface->MethodDescIsStatic(fd)))
2740 NumArguments++;
2741
2742 // Is this a VarArg's function?
2743 if (msig.IsVarArg() && fVarArg != NULL)
2744 {
2745 *fVarArg = true;
2746 }
2747
2748 return NumArguments;
2749}
2750
2751#endif // #ifndef DACCESS_COMPILE
2752
2753
2754
2755
2756
2757/******************************************************************************
2758 DebuggerJitInfo * Debugger::GetJitInfo(): GetJitInfo
2759 will return a pointer to a DebuggerJitInfo. If the DJI
2760 doesn't exist, or it does exist, but the method has actually
2761 been pitched (and the caller wants pitched methods filtered out),
2762 then we'll return NULL.
2763
2764 Note: This will also create a DMI for if one does not exist for this DJI.
2765
2766 MethodDesc* fd: MethodDesc for the method we're interested in.
2767 CORDB_ADDRESS_TYPE * pbAddr: Address within the code, to indicate which
2768 version we want. If this is NULL, then we want the
2769 head of the DebuggerJitInfo list, whether it's been
2770 JITted or not.
2771 ******************************************************************************/
2772
2773
2774// Get a DJI from an address.
2775DebuggerJitInfo *Debugger::GetJitInfoFromAddr(TADDR addr)
2776{
2777 WRAPPER_NO_CONTRACT;
2778
2779 MethodDesc *fd;
2780 fd = g_pEEInterface->GetNativeCodeMethodDesc(addr);
2781 _ASSERTE(fd);
2782
2783 return GetJitInfo(fd, (const BYTE*) addr, NULL);
2784}
2785
2786// Get a DJI for a Native MD (MD for a native function).
2787// In the EnC scenario, the MethodDesc refers to the most recent method.
2788// This is very dangerous since there may be multiple versions alive at the same time.
2789// This will give back the wrong DJI if we're lookikng for a stale method desc.
2790// @todo - can a caller possibly use this correctly?
2791DebuggerJitInfo *Debugger::GetLatestJitInfoFromMethodDesc(MethodDesc * pMethodDesc)
2792{
2793 WRAPPER_NO_CONTRACT;
2794
2795 _ASSERTE(pMethodDesc != NULL);
2796 // We'd love to assert that we're jitted; but since this may be in the JitComplete
2797 // callback path, we can't be sure.
2798
2799 return GetJitInfoWorker(pMethodDesc, NULL, NULL);
2800}
2801
2802
2803DebuggerJitInfo *Debugger::GetJitInfo(MethodDesc *fd, const BYTE *pbAddr, DebuggerMethodInfo **pMethInfo )
2804{
2805 CONTRACTL
2806 {
2807 SO_INTOLERANT;
2808 THROWS;
2809 GC_NOTRIGGER;
2810 PRECONDITION(!g_pDebugger->HasDebuggerDataLock());
2811 }
2812 CONTRACTL_END;
2813
2814 // Address should be non-null and in range of MethodDesc. This lets us tell which EnC version.
2815 _ASSERTE(pbAddr != NULL);
2816
2817 return GetJitInfoWorker(fd, pbAddr, pMethInfo);
2818
2819}
2820
2821// Internal worker to GetJitInfo. Doesn't validate parameters.
2822DebuggerJitInfo *Debugger::GetJitInfoWorker(MethodDesc *fd, const BYTE *pbAddr, DebuggerMethodInfo **pMethInfo)
2823{
2824
2825 DebuggerMethodInfo *dmi = NULL;
2826 DebuggerJitInfo *dji = NULL;
2827
2828 // If we have a null MethodDesc - we're not going to get a jit-info. Do this check once at the top
2829 // rather than littered throughout the rest of this function.
2830 if (fd == NULL)
2831 {
2832 LOG((LF_CORDB, LL_EVERYTHING, "Debugger::GetJitInfo, addr=0x%p - null fd - returning null\n", pbAddr));
2833 return NULL;
2834 }
2835 else
2836 {
2837 CONSISTENCY_CHECK_MSGF(!fd->IsWrapperStub(), ("Can't get Jit-info for wrapper MDesc,'%s'", fd->m_pszDebugMethodName));
2838 }
2839
2840 // The debugger doesn't track Lightweight-codegen methods b/c they have no metadata.
2841 if (fd->IsDynamicMethod())
2842 {
2843 return NULL;
2844 }
2845
2846
2847 // initialize our out param
2848 if (pMethInfo)
2849 {
2850 *pMethInfo = NULL;
2851 }
2852
2853 LOG((LF_CORDB, LL_EVERYTHING, "Debugger::GetJitInfo called\n"));
2854 // CHECK_DJI_TABLE_DEBUGGER;
2855
2856 // Find the DJI via the DMI
2857 //
2858 // One way to improve the perf, both in terms of memory usage, number of allocations
2859 // and lookup speeds would be to have the first JitInfo inline in the MethodInfo
2860 // struct. After all, we never want to have a MethodInfo in the table without an
2861 // associated JitInfo, and this should bring us back very close to the old situation
2862 // in terms of perf. But correctness comes first, and perf later...
2863 // CHECK_DMI_TABLE;
2864 dmi = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
2865
2866 if (dmi == NULL)
2867 {
2868 // If we can't create the DMI, we won't be able to create the DJI.
2869 return NULL;
2870 }
2871
2872 // TODO: Currently, this method does not handle code versioning properly (at least in some profiler scenarios), it may need
2873 // to take pbAddr into account and lazily create a DJI for that particular version of the method.
2874
2875 // This may take the lock and lazily create an entry, so we do it up front.
2876 dji = dmi->GetLatestJitInfo(fd);
2877
2878
2879 DebuggerDataLockHolder debuggerDataLockHolder(this);
2880
2881 // Note the call to GetLatestJitInfo() will lazily create the first DJI if we don't already have one.
2882 for (; dji != NULL; dji = dji->m_prevJitInfo)
2883 {
2884 if (PTR_TO_TADDR(dji->m_fd) == PTR_HOST_TO_TADDR(fd))
2885 {
2886 break;
2887 }
2888 }
2889 LOG((LF_CORDB, LL_INFO1000, "D::GJI: for md:0x%x (%s::%s), got dmi:0x%x.\n",
2890 fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2891 dmi));
2892
2893
2894
2895
2896 // Log stuff - fd may be null; so we don't want to AV in the log.
2897
2898 LOG((LF_CORDB, LL_INFO1000, "D::GJI: for md:0x%x (%s::%s), got dmi:0x%x, dji:0x%x, latest dji:0x%x, latest fd:0x%x, prev dji:0x%x\n",
2899 fd, fd->m_pszDebugClassName, fd->m_pszDebugMethodName,
2900 dmi, dji, (dmi ? dmi->GetLatestJitInfo_NoCreate() : 0),
2901 ((dmi && dmi->GetLatestJitInfo_NoCreate()) ? dmi->GetLatestJitInfo_NoCreate()->m_fd:0),
2902 (dji?dji->m_prevJitInfo:0)));
2903
2904 if ((dji != NULL) && (pbAddr != NULL))
2905 {
2906 dji = dji->GetJitInfoByAddress(pbAddr);
2907
2908 // XXX Microsoft - dac doesn't support stub tracing
2909 // so this just results in not-impl exceptions.
2910#ifndef DACCESS_COMPILE
2911 if (dji == NULL) //may have been given address of a thunk
2912 {
2913 LOG((LF_CORDB,LL_INFO1000,"Couldn't find a DJI by address 0x%p, "
2914 "so it might be a stub or thunk\n", pbAddr));
2915 TraceDestination trace;
2916
2917 g_pEEInterface->TraceStub((const BYTE *)pbAddr, &trace);
2918
2919 if ((trace.GetTraceType() == TRACE_MANAGED) && (pbAddr != (const BYTE *)trace.GetAddress()))
2920 {
2921 LOG((LF_CORDB,LL_INFO1000,"Address thru thunk"
2922 ": 0x%p\n", trace.GetAddress()));
2923 dji = GetJitInfo(fd, dac_cast<PTR_CBYTE>(trace.GetAddress()));
2924 }
2925#ifdef LOGGING
2926 else
2927 {
2928 _ASSERTE(trace.GetTraceType() != TRACE_UNJITTED_METHOD ||
2929 (fd == trace.GetMethodDesc()));
2930 LOG((LF_CORDB,LL_INFO1000,"Address not thunked - "
2931 "must be to unJITted method, or normal managed "
2932 "method lacking a DJI!\n"));
2933 }
2934#endif //LOGGING
2935 }
2936#endif // #ifndef DACCESS_COMPILE
2937 }
2938
2939 if (pMethInfo)
2940 {
2941 *pMethInfo = dmi;
2942 }
2943
2944 // DebuggerDataLockHolder out of scope - release implied
2945
2946 return dji;
2947}
2948
2949DebuggerMethodInfo *Debugger::GetOrCreateMethodInfo(Module *pModule, mdMethodDef token)
2950{
2951 CONTRACTL
2952 {
2953 SO_INTOLERANT;
2954 SUPPORTS_DAC;
2955 THROWS;
2956 GC_NOTRIGGER;
2957 }
2958 CONTRACTL_END;
2959
2960 DebuggerMethodInfo *info = NULL;
2961
2962 // When dump debugging, we don't expect to have a lock,
2963 // nor would it be useful for anything.
2964 ALLOW_DATATARGET_MISSING_MEMORY(
2965 // In case we don't have already, take it now.
2966 DebuggerDataLockHolder debuggerDataLockHolder(this);
2967 );
2968
2969 if (m_pMethodInfos != NULL)
2970 {
2971 info = m_pMethodInfos->GetMethodInfo(pModule, token);
2972 }
2973
2974 // dac checks ngen'ed image content first, so
2975 // if we didn't find information it doesn't exist.
2976#ifndef DACCESS_COMPILE
2977 if (info == NULL)
2978 {
2979 info = CreateMethodInfo(pModule, token);
2980
2981 LOG((LF_CORDB, LL_INFO1000, "D::GOCMI: created DMI for mdToken:0x%x, dmi:0x%x\n",
2982 token, info));
2983 }
2984#endif // #ifndef DACCESS_COMPILE
2985
2986
2987 if (info == NULL)
2988 {
2989 // This should only happen in an oom scenario. It would be nice to throw here.
2990 STRESS_LOG2(LF_CORDB, LL_EVERYTHING, "OOM - Failed to allocate DJI (0x%p, 0x%x)\n", pModule, token);
2991 }
2992
2993 // DebuggerDataLockHolder out of scope - release implied
2994 return info;
2995}
2996
2997
2998#ifndef DACCESS_COMPILE
2999
3000/******************************************************************************
3001 * GetILToNativeMapping returns a map from IL offsets to native
3002 * offsets for this code. An array of COR_PROF_IL_TO_NATIVE_MAP
3003 * structs will be returned, and some of the ilOffsets in this array
3004 * may be the values specified in CorDebugIlToNativeMappingTypes.
3005 ******************************************************************************/
3006HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cMap,
3007 ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[])
3008{
3009 CONTRACTL
3010 {
3011 SO_NOT_MAINLINE;
3012 THROWS;
3013 GC_TRIGGERS_FROM_GETJITINFO;
3014 }
3015 CONTRACTL_END;
3016
3017#ifdef PROFILING_SUPPORTED
3018 // At this point, we're pulling in the debugger.
3019 if (!HasLazyData())
3020 {
3021 DebuggerLockHolder lockHolder(this);
3022 LazyInit(); // throws
3023 }
3024
3025 // Get the JIT info by functionId.
3026
3027 // This function is unsafe to use during EnC because the MethodDesc doesn't tell
3028 // us which version is being requested.
3029 // However, this function is only used by the profiler, and you can't profile with EnC,
3030 // which means that getting the latest jit-info is still correct.
3031#if defined(PROFILING_SUPPORTED)
3032 _ASSERTE(CORProfilerPresent());
3033#endif // PROFILING_SUPPORTED
3034
3035 MethodDesc *fd = g_pEEInterface->GetNativeCodeMethodDesc(pNativeCodeStartAddress);
3036 if (fd == NULL || fd->IsWrapperStub() || fd->IsDynamicMethod())
3037 {
3038 return E_FAIL;
3039 }
3040
3041 DebuggerMethodInfo *pDMI = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
3042 if (pDMI == NULL)
3043 {
3044 return E_FAIL;
3045 }
3046
3047 DebuggerJitInfo *pDJI = pDMI->FindOrCreateInitAndAddJitInfo(fd, pNativeCodeStartAddress);
3048
3049 // Dunno what went wrong
3050 if (pDJI == NULL)
3051 return (E_FAIL);
3052
3053 // If they gave us space to copy into...
3054 if (map != NULL)
3055 {
3056 // Only copy as much as either they gave us or we have to copy.
3057 ULONG32 cpyCount = min(cMap, pDJI->GetSequenceMapCount());
3058
3059 // Read the map right out of the Left Side.
3060 if (cpyCount > 0)
3061 ExportILToNativeMap(cpyCount,
3062 map,
3063 pDJI->GetSequenceMap(),
3064 pDJI->m_sizeOfCode);
3065 }
3066
3067 // Return the true count of entries
3068 if (pcMap)
3069 {
3070 *pcMap = pDJI->GetSequenceMapCount();
3071 }
3072
3073 return (S_OK);
3074#else
3075 return E_NOTIMPL;
3076#endif
3077}
3078
3079
3080//---------------------------------------------------------------------------------------
3081//
3082// This is morally the same as GetILToNativeMapping, except the output is in a different
3083// format, to better facilitate sending the ETW ILToNativeMap events.
3084//
3085// Arguments:
3086// pMD - MethodDesc whose IL-to-native map will be returned
3087// cMapMax - Max number of map entries to return. Although
3088// this function handles the allocation of the returned
3089// array, the caller still wants to limit how big this
3090// can get, since ETW itself has limits on how big
3091// events can get
3092// pcMap - [out] Number of entries returned in each output parallel array (next
3093// two parameters).
3094// prguiILOffset - [out] Array of IL offsets. This function allocates, caller must free.
3095// prguiNativeOffset - [out] Array of the starting native offsets that correspond
3096// to each (*prguiILOffset)[i]. This function allocates,
3097// caller must free.
3098//
3099// Return Value:
3100// HRESULT indicating success or failure.
3101//
3102// Notes:
3103// * This function assumes lazy data has already been initialized (in order to
3104// ensure that this doesn't trigger or take the large debugger mutex). So
3105// callers must guarantee they call InitializeLazyDataIfNecessary() first.
3106// * Either this function fails, and (*prguiILOffset) & (*prguiNativeOffset) will be
3107// untouched OR this function succeeds and (*prguiILOffset) & (*prguiNativeOffset)
3108// will both be non-NULL, set to the parallel arrays this function allocated.
3109// * If this function returns success, then the caller must free (*prguiILOffset) and
3110// (*prguiNativeOffset)
3111// * (*prguiILOffset) and (*prguiNativeOffset) are parallel arrays, such that
3112// (*prguiILOffset)[i] corresponds to (*prguiNativeOffset)[i] for each 0 <= i < *pcMap
3113// * If EnC is enabled, this function will return the IL-to-native mapping for the latest
3114// EnC version of the function. This may not be what the profiler wants, but EnC
3115// + ETW-map events is not a typical combination, and this is consistent with
3116// other ETW events like JittingStarted or MethodLoad, which also fire multiple
3117// events for the same MethodDesc (each time it's EnC'd), with each event
3118// corresponding to the most recent EnC version at the time.
3119//
3120
3121HRESULT Debugger::GetILToNativeMappingIntoArrays(
3122 MethodDesc * pMethodDesc,
3123 PCODE pCode,
3124 USHORT cMapMax,
3125 USHORT * pcMap,
3126 UINT ** prguiILOffset,
3127 UINT ** prguiNativeOffset)
3128{
3129 CONTRACTL
3130 {
3131 SO_NOT_MAINLINE;
3132 THROWS;
3133 GC_NOTRIGGER;
3134 }
3135 CONTRACTL_END;
3136
3137 _ASSERTE(pcMap != NULL);
3138 _ASSERTE(prguiILOffset != NULL);
3139 _ASSERTE(prguiNativeOffset != NULL);
3140
3141 // Any caller of GetILToNativeMappingIntoArrays had better call
3142 // InitializeLazyDataIfNecessary first!
3143 _ASSERTE(HasLazyData());
3144
3145 // Get the JIT info by functionId.
3146
3147 DebuggerJitInfo * pDJI = GetJitInfo(pMethodDesc, (const BYTE *)pCode);
3148
3149 // Dunno what went wrong
3150 if (pDJI == NULL)
3151 return E_FAIL;
3152
3153 ULONG32 cMap = min(cMapMax, pDJI->GetSequenceMapCount());
3154 DebuggerILToNativeMap * rgMapInt = pDJI->GetSequenceMap();
3155
3156 NewArrayHolder<UINT> rguiILOffsetTemp = new (nothrow) UINT[cMap];
3157 if (rguiILOffsetTemp == NULL)
3158 return E_OUTOFMEMORY;
3159
3160 NewArrayHolder<UINT> rguiNativeOffsetTemp = new (nothrow) UINT[cMap];
3161 if (rguiNativeOffsetTemp == NULL)
3162 return E_OUTOFMEMORY;
3163
3164 for (ULONG32 iMap=0; iMap < cMap; iMap++)
3165 {
3166 rguiILOffsetTemp[iMap] = rgMapInt[iMap].ilOffset;
3167 rguiNativeOffsetTemp[iMap] = rgMapInt[iMap].nativeStartOffset;
3168 }
3169
3170 // Since cMap is the min of cMapMax (and something else) and cMapMax is a USHORT,
3171 // then cMap must fit in a USHORT as well
3172 _ASSERTE(FitsIn<USHORT>(cMap));
3173 *pcMap = (USHORT) cMap;
3174 *prguiILOffset = rguiILOffsetTemp.Extract();
3175 *prguiNativeOffset = rguiNativeOffsetTemp.Extract();
3176
3177 return S_OK;
3178}
3179
3180
3181
3182
3183#endif // #ifndef DACCESS_COMPILE
3184
3185/******************************************************************************
3186 *
3187 ******************************************************************************/
3188CodeRegionInfo CodeRegionInfo::GetCodeRegionInfo(DebuggerJitInfo *dji, MethodDesc *md, PTR_CORDB_ADDRESS_TYPE addr)
3189{
3190 CONTRACTL
3191 {
3192 SO_INTOLERANT;
3193 NOTHROW;
3194 GC_NOTRIGGER;
3195 SUPPORTS_DAC;
3196 MODE_ANY;
3197 }
3198 CONTRACTL_END;
3199
3200 if (dji && dji->m_addrOfCode)
3201 {
3202 LOG((LF_CORDB, LL_EVERYTHING, "CRI::GCRI: simple case\n"));
3203 return dji->m_codeRegionInfo;
3204 }
3205 else
3206 {
3207 LOG((LF_CORDB, LL_EVERYTHING, "CRI::GCRI: more complex case\n"));
3208 CodeRegionInfo codeRegionInfo;
3209
3210 // Use method desc from dji if present
3211 if (dji && dji->m_fd)
3212 {
3213 _ASSERTE(!md || md == dji->m_fd);
3214 md = dji->m_fd;
3215 }
3216
3217 if (!addr)
3218 {
3219 _ASSERTE(md);
3220 addr = dac_cast<PTR_CORDB_ADDRESS_TYPE>(g_pEEInterface->GetFunctionAddress(md));
3221 }
3222 else
3223 {
3224 _ASSERTE(!md ||
3225 (addr == dac_cast<PTR_CORDB_ADDRESS_TYPE>(g_pEEInterface->GetFunctionAddress(md))));
3226 }
3227
3228 if (addr)
3229 {
3230 PCODE pCode = PINSTRToPCODE(dac_cast<TADDR>(addr));
3231 codeRegionInfo.InitializeFromStartAddress(pCode);
3232 }
3233
3234 return codeRegionInfo;
3235 }
3236}
3237
3238
3239#ifndef DACCESS_COMPILE
3240/******************************************************************************
3241// Helper function for getBoundaries to get around AMD64 compiler and
3242// contract holders with PAL_TRY in the same function.
3243 ******************************************************************************/
3244void Debugger::getBoundariesHelper(MethodDesc * md,
3245 unsigned int *cILOffsets,
3246 DWORD **pILOffsets)
3247{
3248 //
3249 // CANNOT ADD A CONTRACT HERE. Contract is in getBoundaries
3250 //
3251
3252 //
3253 // Grab the JIT info struct for this method. Create if needed, as this
3254 // may be called before JITComplete.
3255 //
3256 DebuggerMethodInfo *dmi = NULL;
3257 dmi = GetOrCreateMethodInfo(md->GetModule(), md->GetMemberDef());
3258
3259 if (dmi != NULL)
3260 {
3261 LOG((LF_CORDB,LL_INFO10000,"De::NGB: Got dmi 0x%x\n",dmi));
3262
3263#if defined(FEATURE_ISYM_READER)
3264 // Note: we need to make sure to enable preemptive GC here just in case we block in the symbol reader.
3265 GCX_PREEMP_EEINTERFACE();
3266
3267 Module *pModule = md->GetModule();
3268 (void)pModule; //prevent "unused variable" error from GCC
3269 _ASSERTE(pModule != NULL);
3270
3271 SafeComHolder<ISymUnmanagedReader> pReader(pModule->GetISymUnmanagedReader());
3272
3273 // If we got a reader, use it.
3274 if (pReader != NULL)
3275 {
3276 // Grab the sym reader's method.
3277 ISymUnmanagedMethod *pISymMethod;
3278
3279 HRESULT hr = pReader->GetMethod(md->GetMemberDef(),
3280 &pISymMethod);
3281
3282 ULONG32 n = 0;
3283
3284 if (SUCCEEDED(hr))
3285 {
3286 // Get the count of sequence points.
3287 hr = pISymMethod->GetSequencePointCount(&n);
3288 _ASSERTE(SUCCEEDED(hr));
3289
3290
3291 LOG((LF_CORDB, LL_INFO100000,
3292 "D::NGB: Reader seq pt count is %d\n", n));
3293
3294 ULONG32 *p;
3295
3296 if (n > 0)
3297 {
3298 ULONG32 dummy;
3299
3300 p = new ULONG32[n];
3301 _ASSERTE(p != NULL); // throws on oom errror
3302
3303 hr = pISymMethod->GetSequencePoints(n, &dummy,
3304 p, NULL, NULL, NULL,
3305 NULL, NULL);
3306 _ASSERTE(SUCCEEDED(hr));
3307 _ASSERTE(dummy == n);
3308
3309 *pILOffsets = (DWORD*)p;
3310
3311 // Translate the IL offets based on an
3312 // instrumented IL map if one exists.
3313 if (dmi->HasInstrumentedILMap())
3314 {
3315 InstrumentedILOffsetMapping mapping =
3316 dmi->GetRuntimeModule()->GetInstrumentedILOffsetMapping(dmi->m_token);
3317
3318 for (SIZE_T i = 0; i < n; i++)
3319 {
3320 int origOffset = *p;
3321
3322 *p = dmi->TranslateToInstIL(
3323 &mapping,
3324 origOffset,
3325 bOriginalToInstrumented);
3326
3327 LOG((LF_CORDB, LL_INFO100000,
3328 "D::NGB: 0x%04x (Real IL:0x%x)\n",
3329 origOffset, *p));
3330
3331 p++;
3332 }
3333 }
3334#ifdef LOGGING
3335 else
3336 {
3337 for (SIZE_T i = 0; i < n; i++)
3338 {
3339 LOG((LF_CORDB, LL_INFO100000,
3340 "D::NGB: 0x%04x \n", *p));
3341 p++;
3342 }
3343 }
3344#endif
3345 }
3346 else
3347 *pILOffsets = NULL;
3348
3349 pISymMethod->Release();
3350 }
3351 else
3352 {
3353
3354 *pILOffsets = NULL;
3355
3356 LOG((LF_CORDB, LL_INFO10000,
3357 "De::NGB: failed to find method 0x%x in sym reader.\n",
3358 md->GetMemberDef()));
3359 }
3360
3361 *cILOffsets = n;
3362 }
3363 else
3364 {
3365 LOG((LF_CORDB, LL_INFO100000, "D::NGB: no reader.\n"));
3366 }
3367
3368#else // FEATURE_ISYM_READER
3369 // We don't have ISymUnmanagedReader. Pretend there are no sequence points.
3370 *cILOffsets = 0;
3371#endif // FEATURE_ISYM_READER
3372 }
3373
3374 LOG((LF_CORDB, LL_INFO100000, "D::NGB: cILOffsets=%d\n", *cILOffsets));
3375 return;
3376}
3377#endif
3378
3379/******************************************************************************
3380// Use an ISymUnmanagedReader to get method sequence points.
3381 ******************************************************************************/
3382void Debugger::getBoundaries(MethodDesc * md,
3383 unsigned int *cILOffsets,
3384 DWORD **pILOffsets,
3385 ICorDebugInfo::BoundaryTypes *implicitBoundaries)
3386{
3387#ifndef DACCESS_COMPILE
3388 CONTRACTL
3389 {
3390 SO_INTOLERANT;
3391 THROWS;
3392 GC_TRIGGERS;
3393 }
3394 CONTRACTL_END;
3395
3396 // May be here even when a debugger is not attached.
3397
3398 // @@@
3399 // Implements DebugInterface API
3400
3401 *cILOffsets = 0;
3402 *pILOffsets = NULL;
3403 *implicitBoundaries = ICorDebugInfo::DEFAULT_BOUNDARIES;
3404 // If there has been an unrecoverable Left Side error, then we
3405 // just pretend that there are no boundaries.
3406 if (CORDBUnrecoverableError(this))
3407 {
3408 return;
3409 }
3410
3411 // LCG methods have their own resolution scope that is seperate from a module
3412 // so they shouldn't have their symbols looked up in the module PDB. Right now
3413 // LCG methods have no symbols so we can just early out, but if they ever
3414 // had some symbols attached we would need a different way of getting to them.
3415 // See Dev10 issue 728519
3416 if(md->IsLCGMethod())
3417 {
3418 return;
3419 }
3420
3421 // If JIT optimizations are allowed for the module this function
3422 // lives in, then don't grab specific boundaries from the symbol
3423 // store since any boundaries we give the JIT will be pretty much
3424 // ignored anyway.
3425 if (!CORDisableJITOptimizations(md->GetModule()->GetDebuggerInfoBits()))
3426 {
3427 *implicitBoundaries = ICorDebugInfo::BoundaryTypes(ICorDebugInfo::STACK_EMPTY_BOUNDARIES |
3428 ICorDebugInfo::CALL_SITE_BOUNDARIES);
3429
3430 return;
3431 }
3432
3433 Module* pModule = md->GetModule();
3434 DWORD dwBits = pModule->GetDebuggerInfoBits();
3435 if ((dwBits & DACF_IGNORE_PDBS) != 0)
3436 {
3437 //
3438 // If told to explicitly ignore PDBs for this function, then bail now.
3439 //
3440 return;
3441 }
3442
3443 if( !pModule->IsSymbolReadingEnabled() )
3444 {
3445 // Symbol reading is disabled for this module, so bail out early (for efficiency only)
3446 return;
3447 }
3448
3449 if (pModule == SystemDomain::SystemModule())
3450 {
3451 // We don't look up PDBs for mscorlib. This is not quite right, but avoids
3452 // a bootstrapping problem. When an EXE loads, it has the option of setting
3453 // the COM apartment model to STA if we need to. It is important that no
3454 // other Coinitialize happens before this. Since loading the PDB reader uses
3455 // com we can not come first. However managed code IS run before the COM
3456 // apartment model is set, and thus we have a problem since this code is
3457 // called for when JITTing managed code. We avoid the problem by just
3458 // bailing for mscorlib.
3459 return;
3460 }
3461
3462 // At this point, we're pulling in the debugger.
3463 if (!HasLazyData())
3464 {
3465 DebuggerLockHolder lockHolder(this);
3466 LazyInit(); // throws
3467 }
3468
3469 getBoundariesHelper(md, cILOffsets, pILOffsets);
3470
3471#else
3472 DacNotImpl();
3473#endif // #ifndef DACCESS_COMPILE
3474}
3475
3476
3477/******************************************************************************
3478 *
3479 ******************************************************************************/
3480void Debugger::getVars(MethodDesc * md, ULONG32 *cVars, ICorDebugInfo::ILVarInfo **vars,
3481 bool *extendOthers)
3482{
3483#ifndef DACCESS_COMPILE
3484 CONTRACTL
3485 {
3486 SO_INTOLERANT;
3487 THROWS;
3488 GC_TRIGGERS_FROM_GETJITINFO;
3489 PRECONDITION(!ThisIsHelperThreadWorker());
3490 }
3491 CONTRACTL_END;
3492
3493
3494
3495 // At worst return no information
3496 *cVars = 0;
3497 *vars = NULL;
3498
3499 // Just tell the JIT to extend everything.
3500 // Note that if optimizations are enabled, the native compilers are
3501 // free to ingore *extendOthers
3502 *extendOthers = true;
3503
3504 DWORD bits = md->GetModule()->GetDebuggerInfoBits();
3505
3506 if (CORDBUnrecoverableError(this))
3507 goto Exit;
3508
3509 if (CORDisableJITOptimizations(bits))
3510// if (!CORDebuggerAllowJITOpts(bits))
3511 {
3512 //
3513 // @TODO: Do we really need this code since *extendOthers==true?
3514 //
3515
3516 // Is this a vararg function?
3517 BOOL fVarArg = false;
3518 GetArgCount(md, &fVarArg);
3519
3520 if (fVarArg)
3521 {
3522 COR_ILMETHOD *ilMethod = g_pEEInterface->MethodDescGetILHeader(md);
3523
3524 if (ilMethod)
3525 {
3526 // It is, so we need to tell the JIT to give us the
3527 // varags handle.
3528 ICorDebugInfo::ILVarInfo *p = new ICorDebugInfo::ILVarInfo[1];
3529 _ASSERTE(p != NULL); // throws on oom error
3530
3531 COR_ILMETHOD_DECODER header(ilMethod);
3532 unsigned int ilCodeSize = header.GetCodeSize();
3533
3534 p->startOffset = 0;
3535 p->endOffset = ilCodeSize;
3536 p->varNumber = (DWORD) ICorDebugInfo::VARARGS_HND_ILNUM;
3537
3538 *cVars = 1;
3539 *vars = p;
3540 }
3541 }
3542 }
3543
3544 LOG((LF_CORDB, LL_INFO100000, "D::gV: cVars=%d, extendOthers=%d\n",
3545 *cVars, *extendOthers));
3546
3547Exit:
3548 ;
3549#else
3550 DacNotImpl();
3551#endif // #ifndef DACCESS_COMPILE
3552}
3553
3554
3555#ifndef DACCESS_COMPILE
3556
3557// If we have a varargs function, we can't set the IP (we don't know how to pack/unpack the arguments), so if we
3558// call SetIP with fCanSetIPOnly = true, we need to check for that.
3559// Arguments:
3560// input: nEntries - number of entries in varNativeInfo
3561// varNativeInfo - array of entries describing the args and locals for the function
3562// output: true iff the function has varargs
3563BOOL Debugger::IsVarArgsFunction(unsigned int nEntries, PTR_NativeVarInfo varNativeInfo)
3564{
3565 for (unsigned int i = 0; i < nEntries; ++i)
3566 {
3567 if (varNativeInfo[i].loc.vlType == ICorDebugInfo::VLT_FIXED_VA)
3568 {
3569 return TRUE;
3570 }
3571 }
3572 return FALSE;
3573}
3574
3575// We want to keep the 'worst' HRESULT - if one has failed (..._E_...) & the
3576// other hasn't, take the failing one. If they've both/neither failed, then
3577// it doesn't matter which we take.
3578// Note that this macro favors retaining the first argument
3579#define WORST_HR(hr1,hr2) (FAILED(hr1)?hr1:hr2)
3580/******************************************************************************
3581 *
3582 ******************************************************************************/
3583HRESULT Debugger::SetIP( bool fCanSetIPOnly, Thread *thread,Module *module,
3584 mdMethodDef mdMeth, DebuggerJitInfo* dji,
3585 SIZE_T offsetILTo, BOOL fIsIL)
3586{
3587 CONTRACTL
3588 {
3589 SO_NOT_MAINLINE;
3590 NOTHROW;
3591 GC_NOTRIGGER;
3592 PRECONDITION(CheckPointer(thread));
3593 PRECONDITION(CheckPointer(module));
3594 PRECONDITION(mdMeth != mdMethodDefNil);
3595 }
3596 CONTRACTL_END;
3597
3598#ifdef _DEBUG
3599 static ConfigDWORD breakOnSetIP;
3600 if (breakOnSetIP.val(CLRConfig::INTERNAL_DbgBreakOnSetIP)) _ASSERTE(!"DbgBreakOnSetIP");
3601#endif
3602
3603 HRESULT hr = S_OK;
3604 HRESULT hrAdvise = S_OK;
3605
3606 DWORD offsetILFrom;
3607 CorDebugMappingResult map;
3608 DWORD whichIgnore;
3609
3610 ControllerStackInfo csi;
3611
3612 BOOL exact;
3613 SIZE_T offsetNatTo;
3614
3615 PCODE pbDest = NULL;
3616 BYTE *pbBase = NULL;
3617 CONTEXT *pCtx = NULL;
3618 DWORD dwSize = 0;
3619 SIZE_T *rgVal1 = NULL;
3620 SIZE_T *rgVal2 = NULL;
3621 BYTE **pVCs = NULL;
3622
3623 LOG((LF_CORDB, LL_INFO1000, "D::SIP: In SetIP ==> fCanSetIPOnly:0x%x <==!\n", fCanSetIPOnly));
3624
3625 CodeVersionManager *pCodeVersionManager = module->GetCodeVersionManager();
3626 {
3627 CodeVersionManager::TableLockHolder lock(pCodeVersionManager);
3628 ILCodeVersion ilCodeVersion = pCodeVersionManager->GetActiveILCodeVersion(module, mdMeth);
3629 if (!ilCodeVersion.IsDefaultVersion())
3630 {
3631 return CORDBG_E_SET_IP_IMPOSSIBLE;
3632 }
3633 }
3634
3635 pCtx = GetManagedStoppedCtx(thread);
3636
3637 // If we can't get a context, then we can't possibly be a in a good place
3638 // to do a setip.
3639 if (pCtx == NULL)
3640 {
3641 return CORDBG_S_BAD_START_SEQUENCE_POINT;
3642 }
3643
3644 // Implicit Caveat: We need to be the active frame.
3645 // We can safely take a stack trace because the thread is synchronized.
3646 StackTraceTicket ticket(thread);
3647 csi.GetStackInfo(ticket, thread, LEAF_MOST_FRAME, NULL);
3648
3649 ULONG offsetNatFrom = csi.m_activeFrame.relOffset;
3650#if defined(WIN64EXCEPTIONS)
3651 if (csi.m_activeFrame.IsFuncletFrame())
3652 {
3653 offsetNatFrom = (ULONG)((SIZE_T)GetControlPC(&(csi.m_activeFrame.registers)) -
3654 (SIZE_T)(dji->m_addrOfCode));
3655 }
3656#endif // WIN64EXCEPTIONS
3657
3658 _ASSERTE(dji != NULL);
3659
3660 // On WIN64 platforms, it's important to use the total size of the
3661 // parent method and the funclets below (i.e. m_sizeOfCode). Don't use
3662 // the size of the individual funclets or the parent method.
3663 pbBase = (BYTE*)CORDB_ADDRESS_TO_PTR(dji->m_addrOfCode);
3664 dwSize = (DWORD)dji->m_sizeOfCode;
3665#if defined(WIN64EXCEPTIONS)
3666 // Currently, method offsets are not bigger than 4 bytes even on WIN64.
3667 // Assert that it is so here.
3668 _ASSERTE((SIZE_T)dwSize == dji->m_sizeOfCode);
3669#endif // WIN64EXCEPTIONS
3670
3671
3672 // Create our structure for analyzing this.
3673 // <TODO>@PERF: optimize - hold on to this so we don't rebuild it for both
3674 // CanSetIP & SetIP.</TODO>
3675 int cFunclet = 0;
3676 const DWORD * rgFunclet = NULL;
3677#if defined(WIN64EXCEPTIONS)
3678 cFunclet = dji->GetFuncletCount();
3679 rgFunclet = dji->m_rgFunclet;
3680#endif // WIN64EXCEPTIONS
3681
3682 EHRangeTree* pEHRT = new (nothrow) EHRangeTree(csi.m_activeFrame.pIJM,
3683 csi.m_activeFrame.MethodToken,
3684 dwSize,
3685 cFunclet,
3686 rgFunclet);
3687
3688 // To maintain the current semantics, we will check the following right before SetIPFromSrcToDst() is called
3689 // (instead of checking them now):
3690 // 1) pEHRT == NULL
3691 // 2) FAILED(pEHRT->m_hrInit)
3692
3693
3694 {
3695 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Got version info fine\n"));
3696
3697 // Caveat: we need to start from a sequence point
3698 offsetILFrom = dji->MapNativeOffsetToIL(offsetNatFrom,
3699 &map, &whichIgnore);
3700 if ( !(map & MAPPING_EXACT) )
3701 {
3702 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Starting native offset is bad!\n"));
3703 hrAdvise = WORST_HR(hrAdvise, CORDBG_S_BAD_START_SEQUENCE_POINT);
3704 }
3705 else
3706 { // exact IL mapping
3707
3708 if (!(dji->GetSrcTypeFromILOffset(offsetILFrom) & ICorDebugInfo::STACK_EMPTY))
3709 {
3710 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Starting offset isn't stack empty!\n"));
3711 hrAdvise = WORST_HR(hrAdvise, CORDBG_S_BAD_START_SEQUENCE_POINT);
3712 }
3713 }
3714
3715 // Caveat: we need to go to a sequence point
3716 if (fIsIL )
3717 {
3718#if defined(WIN64EXCEPTIONS)
3719 int funcletIndexFrom = dji->GetFuncletIndex((CORDB_ADDRESS)offsetNatFrom, DebuggerJitInfo::GFIM_BYOFFSET);
3720 offsetNatTo = dji->MapILOffsetToNativeForSetIP(offsetILTo, funcletIndexFrom, pEHRT, &exact);
3721#else // WIN64EXCEPTIONS
3722 DebuggerJitInfo::ILToNativeOffsetIterator it;
3723 dji->InitILToNativeOffsetIterator(it, offsetILTo);
3724 offsetNatTo = it.CurrentAssertOnlyOne(&exact);
3725#endif // WIN64EXCEPTIONS
3726
3727 if (!exact)
3728 {
3729 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Dest (via IL offset) is bad!\n"));
3730 hrAdvise = WORST_HR(hrAdvise, CORDBG_S_BAD_END_SEQUENCE_POINT);
3731 }
3732 }
3733 else
3734 {
3735 offsetNatTo = offsetILTo;
3736 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Dest of 0x%p (via native "
3737 "offset) is fine!\n", offsetNatTo));
3738 }
3739
3740 CorDebugMappingResult mapping;
3741 DWORD which;
3742 offsetILTo = dji->MapNativeOffsetToIL(offsetNatTo, &mapping, &which);
3743
3744 // We only want to perhaps return CORDBG_S_BAD_END_SEQUENCE_POINT if
3745 // we're not already returning CORDBG_S_BAD_START_SEQUENCE_POINT.
3746 if (hr != CORDBG_S_BAD_START_SEQUENCE_POINT)
3747 {
3748 if ( !(mapping & MAPPING_EXACT) )
3749 {
3750 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Ending native offset is bad!\n"));
3751 hrAdvise = WORST_HR(hrAdvise, CORDBG_S_BAD_END_SEQUENCE_POINT);
3752 }
3753 else
3754 {
3755 // <NOTE WIN64>
3756 // All duplicate sequence points (ones with the same IL offset) should have the same SourceTypes.
3757 // </NOTE WIN64>
3758 if (!(dji->GetSrcTypeFromILOffset(offsetILTo) & ICorDebugInfo::STACK_EMPTY))
3759 {
3760 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Ending offset isn't a sequence"
3761 " point, or not stack empty!\n"));
3762 hrAdvise = WORST_HR(hrAdvise, CORDBG_S_BAD_END_SEQUENCE_POINT);
3763 }
3764 }
3765 }
3766
3767 // Once we finally have a native offset, it had better be in range.
3768 if (offsetNatTo >= dwSize)
3769 {
3770 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Code out of range! offsetNatTo = 0x%x, dwSize=0x%x\n", offsetNatTo, dwSize));
3771 hrAdvise = E_INVALIDARG;
3772 goto LExit;
3773 }
3774
3775 pbDest = CodeRegionInfo::GetCodeRegionInfo(dji).OffsetToAddress(offsetNatTo);
3776 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Dest is 0x%p\n", pbDest));
3777
3778 // Don't allow SetIP if the source or target is cold (SetIPFromSrcToDst does not
3779 // correctly handle this case).
3780 if (!CodeRegionInfo::GetCodeRegionInfo(dji).IsOffsetHot(offsetNatTo) ||
3781 !CodeRegionInfo::GetCodeRegionInfo(dji).IsOffsetHot(offsetNatFrom))
3782 {
3783 hrAdvise = WORST_HR(hrAdvise, CORDBG_E_SET_IP_IMPOSSIBLE);
3784 goto LExit;
3785 }
3786 }
3787
3788 if (!fCanSetIPOnly)
3789 {
3790 hr = ShuffleVariablesGet(dji,
3791 offsetNatFrom,
3792 pCtx,
3793 &rgVal1,
3794 &rgVal2,
3795 &pVCs);
3796 LOG((LF_CORDB|LF_ENC,
3797 LL_INFO10000,
3798 "D::SIP: rgVal1 0x%X, rgVal2 0x%X\n",
3799 rgVal1,
3800 rgVal2));
3801
3802 if (FAILED(hr))
3803 {
3804 // This will only fail fatally, so exit.
3805 hrAdvise = WORST_HR(hrAdvise, hr);
3806 goto LExit;
3807 }
3808 }
3809 else // fCanSetIPOnly
3810 {
3811 if (IsVarArgsFunction(dji->GetVarNativeInfoCount(), dji->GetVarNativeInfo()))
3812 {
3813 hrAdvise = E_INVALIDARG;
3814 goto LExit;
3815 }
3816 }
3817
3818
3819 if (pEHRT == NULL)
3820 {
3821 hr = E_OUTOFMEMORY;
3822 }
3823 else if (FAILED(pEHRT->m_hrInit))
3824 {
3825 hr = pEHRT->m_hrInit;
3826 }
3827 else
3828 {
3829 //
3830 // This is a known, ok, violation. END_EXCEPTION_GLUE has a call to GetThrowable in it, but
3831 // we will never hit it because we are passing in NULL below. This is to satisfy the static
3832 // contract analyzer.
3833 //
3834 CONTRACT_VIOLATION(GCViolation);
3835
3836 EX_TRY
3837 {
3838 hr =g_pEEInterface->SetIPFromSrcToDst(thread,
3839 pbBase,
3840 offsetNatFrom,
3841 (DWORD)offsetNatTo,
3842 fCanSetIPOnly,
3843 &(csi.m_activeFrame.registers),
3844 pCtx,
3845 (void *)dji,
3846 pEHRT);
3847 }
3848 EX_CATCH
3849 {
3850 }
3851 EX_END_CATCH(SwallowAllExceptions);
3852
3853 }
3854
3855 // Get the return code, if any
3856 if (hr != S_OK)
3857 {
3858 hrAdvise = WORST_HR(hrAdvise, hr);
3859 goto LExit;
3860 }
3861
3862 // If we really want to do this, we'll have to put the
3863 // variables into their new locations.
3864 if (!fCanSetIPOnly && !FAILED(hrAdvise))
3865 {
3866 // TODO: We should zero out any registers which have now become live GC roots,
3867 // but which aren't tracked variables (i.e. they are JIT temporaries). Such registers may
3868 // have garbage left over in them, and we don't want the GC to try and dereference them
3869 // as object references. However, we can't easily tell here which of the callee-saved regs
3870 // are used in this method and therefore safe to clear.
3871 //
3872
3873 hr = ShuffleVariablesSet(dji,
3874 offsetNatTo,
3875 pCtx,
3876 &rgVal1,
3877 &rgVal2,
3878 pVCs);
3879
3880
3881 if (hr != S_OK)
3882 {
3883 hrAdvise = WORST_HR(hrAdvise, hr);
3884 goto LExit;
3885 }
3886
3887 _ASSERTE(pbDest != NULL);
3888
3889 ::SetIP(pCtx, pbDest);
3890
3891 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Set IP to be 0x%p\n", GetIP(pCtx)));
3892 }
3893
3894
3895LExit:
3896 if (rgVal1 != NULL)
3897 {
3898 DeleteInteropSafe(rgVal1);
3899 }
3900
3901 if (rgVal2 != NULL)
3902 {
3903 DeleteInteropSafe(rgVal2);
3904 }
3905
3906 if (pEHRT != NULL)
3907 {
3908 delete pEHRT;
3909 }
3910
3911 LOG((LF_CORDB, LL_INFO1000, "D::SIP:Returning 0x%x\n", hr));
3912 return hrAdvise;
3913}
3914
3915#include "nativevaraccessors.h"
3916
3917/******************************************************************************
3918 *
3919 ******************************************************************************/
3920
3921HRESULT Debugger::ShuffleVariablesGet(DebuggerJitInfo *dji,
3922 SIZE_T offsetFrom,
3923 CONTEXT *pCtx,
3924 SIZE_T **prgVal1,
3925 SIZE_T **prgVal2,
3926 BYTE ***prgpVCs)
3927{
3928 CONTRACTL
3929 {
3930 SO_NOT_MAINLINE;
3931 NOTHROW;
3932 GC_NOTRIGGER;
3933 PRECONDITION(CheckPointer(dji));
3934 PRECONDITION(CheckPointer(pCtx));
3935 PRECONDITION(CheckPointer(prgVal1));
3936 PRECONDITION(CheckPointer(prgVal2));
3937 PRECONDITION(dji->m_sizeOfCode >= offsetFrom);
3938 }
3939 CONTRACTL_END;
3940
3941 LONG cVariables = 0;
3942 DWORD i;
3943
3944 //
3945 // Find the largest variable number
3946 //
3947 for (i = 0; i < dji->GetVarNativeInfoCount(); i++)
3948 {
3949 if ((LONG)(dji->GetVarNativeInfo()[i].varNumber) > cVariables)
3950 {
3951 cVariables = (LONG)(dji->GetVarNativeInfo()[i].varNumber);
3952 }
3953 }
3954
3955 HRESULT hr = S_OK;
3956
3957 //
3958 // cVariables is a zero-based count of the number of variables. Increment it.
3959 //
3960 cVariables++;
3961
3962 SIZE_T *rgVal1 = new (interopsafe, nothrow) SIZE_T[cVariables + unsigned(-ICorDebugInfo::UNKNOWN_ILNUM)];
3963
3964 SIZE_T *rgVal2 = NULL;
3965
3966 if (rgVal1 == NULL)
3967 {
3968 hr = E_OUTOFMEMORY;
3969 goto LExit;
3970 }
3971
3972 rgVal2 = new (interopsafe, nothrow) SIZE_T[cVariables + unsigned(-ICorDebugInfo::UNKNOWN_ILNUM)];
3973
3974 if (rgVal2 == NULL)
3975 {
3976 hr = E_OUTOFMEMORY;
3977 goto LExit;
3978 }
3979
3980 memset(rgVal1, 0, sizeof(SIZE_T) * (cVariables + unsigned(-ICorDebugInfo::UNKNOWN_ILNUM)));
3981 memset(rgVal2, 0, sizeof(SIZE_T) * (cVariables + unsigned(-ICorDebugInfo::UNKNOWN_ILNUM)));
3982
3983 LOG((LF_CORDB|LF_ENC,
3984 LL_INFO10000,
3985 "D::SVG cVariables %d, hiddens %d, rgVal1 0x%X, rgVal2 0x%X\n",
3986 cVariables,
3987 unsigned(-ICorDebugInfo::UNKNOWN_ILNUM),
3988 rgVal1,
3989 rgVal2));
3990
3991 GetVariablesFromOffset(dji->m_fd,
3992 dji->GetVarNativeInfoCount(),
3993 dji->GetVarNativeInfo(),
3994 offsetFrom,
3995 pCtx,
3996 rgVal1,
3997 rgVal2,
3998 cVariables + unsigned(-ICorDebugInfo::UNKNOWN_ILNUM),
3999 prgpVCs);
4000
4001
4002LExit:
4003 if (!FAILED(hr))
4004 {
4005 (*prgVal1) = rgVal1;
4006 (*prgVal2) = rgVal2;
4007 }
4008 else
4009 {
4010 LOG((LF_CORDB, LL_INFO100, "D::SVG: something went wrong hr=0x%x!", hr));
4011
4012 (*prgVal1) = NULL;
4013 (*prgVal2) = NULL;
4014
4015 if (rgVal1 != NULL)
4016 delete[] rgVal1;
4017
4018 if (rgVal2 != NULL)
4019 delete[] rgVal2;
4020 }
4021
4022 return hr;
4023}
4024
4025/******************************************************************************
4026 *
4027 ******************************************************************************/
4028HRESULT Debugger::ShuffleVariablesSet(DebuggerJitInfo *dji,
4029 SIZE_T offsetTo,
4030 CONTEXT *pCtx,
4031 SIZE_T **prgVal1,
4032 SIZE_T **prgVal2,
4033 BYTE **rgpVCs)
4034{
4035 CONTRACTL
4036 {
4037 SO_NOT_MAINLINE;
4038 NOTHROW;
4039 GC_NOTRIGGER;
4040 PRECONDITION(CheckPointer(dji));
4041 PRECONDITION(CheckPointer(pCtx));
4042 PRECONDITION(CheckPointer(prgVal1));
4043 PRECONDITION(CheckPointer(prgVal2));
4044 PRECONDITION(dji->m_sizeOfCode >= offsetTo);
4045 }
4046 CONTRACTL_END;
4047
4048 LOG((LF_CORDB|LF_ENC,
4049 LL_INFO10000,
4050 "D::SVS: rgVal1 0x%X, rgVal2 0x%X\n",
4051 (*prgVal1),
4052 (*prgVal2)));
4053
4054 HRESULT hr = SetVariablesAtOffset(dji->m_fd,
4055 dji->GetVarNativeInfoCount(),
4056 dji->GetVarNativeInfo(),
4057 offsetTo,
4058 pCtx,
4059 *prgVal1,
4060 *prgVal2,
4061 rgpVCs);
4062
4063 LOG((LF_CORDB|LF_ENC,
4064 LL_INFO100000,
4065 "D::SVS deleting rgVal1 0x%X, rgVal2 0x%X\n",
4066 (*prgVal1),
4067 (*prgVal2)));
4068
4069 DeleteInteropSafe(*prgVal1);
4070 (*prgVal1) = NULL;
4071 DeleteInteropSafe(*prgVal2);
4072 (*prgVal2) = NULL;
4073 return hr;
4074}
4075
4076//
4077// This class is used by Get and SetVariablesFromOffsets to manage a frameHelper
4078// list for the arguments and locals corresponding to each varNativeInfo. The first
4079// four are hidden args, but the remainder will all have a corresponding entry
4080// in the argument or local signature list.
4081//
4082// The structure of the array varNativeInfo contains home information for each variable
4083// at various points in the function. Thus, you have to search for the proper native offset
4084// (IP) in the varNativeInfo, and then find the correct varNumber in that native offset to
4085// find the correct home information.
4086//
4087// Important to note is that the JIT has hidden args that have varNumbers that are negative.
4088// Thus we cannot use varNumber as a strict index into our holder arrays, and instead shift
4089// indexes before indexing into our holder arrays.
4090//
4091// The hidden args are a fixed-sized array given by the value of 0-UNKNOWN_ILNUM. These are used
4092// to pass cookies about the arguments (var args, generics, retarg buffer etc.) to the function.
4093// The real arguments and locals are as one would expect.
4094//
4095
4096class GetSetFrameHelper
4097{
4098public:
4099 GetSetFrameHelper();
4100 ~GetSetFrameHelper();
4101
4102 HRESULT Init(MethodDesc* pMD);
4103
4104 bool GetValueClassSizeOfVar(int varNum, ICorDebugInfo::VarLocType varType, SIZE_T* pSize);
4105 int ShiftIndexForHiddens(int varNum);
4106
4107private:
4108 MethodDesc* m_pMD;
4109 SIZE_T* m_rgSize;
4110 CorElementType* m_rgElemType;
4111 ULONG m_numArgs;
4112 ULONG m_numTotalVars;
4113
4114 SIZE_T GetValueClassSize(MetaSig* pSig);
4115
4116 static SIZE_T GetSizeOfElement(CorElementType cet);
4117};
4118
4119//
4120// GetSetFrameHelper::GetSetFrameHelper()
4121//
4122// This is the constructor. It just initailizes all member variables.
4123//
4124// parameters: none
4125//
4126// return value: none
4127//
4128GetSetFrameHelper::GetSetFrameHelper() : m_pMD(NULL), m_rgSize(NULL), m_rgElemType(NULL),
4129 m_numArgs(0), m_numTotalVars(0)
4130{
4131 LIMITED_METHOD_CONTRACT;
4132}
4133
4134//
4135// GetSetFrameHelper::Init()
4136//
4137// This method extracts the element type and the size of the arguments and locals of the method we are doing
4138// the SetIP on and stores this information in instance variables.
4139//
4140// parameters: pMD - MethodDesc of the method we are doing the SetIP on
4141//
4142// return value: S_OK or E_OUTOFMEMORY
4143//
4144HRESULT
4145GetSetFrameHelper::Init(MethodDesc *pMD)
4146{
4147 CONTRACTL
4148 {
4149 SO_NOT_MAINLINE;
4150 NOTHROW;
4151 GC_NOTRIGGER;
4152 MODE_ANY;
4153 PRECONDITION(CheckPointer(pMD));
4154 }
4155 CONTRACTL_END;
4156
4157 HRESULT hr = S_OK;
4158 COR_ILMETHOD* pILHeader = NULL;
4159 m_pMD = pMD;
4160 MetaSig *pLocSig = NULL;
4161 MetaSig *pArgSig = NULL;
4162
4163 m_rgSize = NULL;
4164 m_rgElemType = NULL;
4165
4166 // Initialize decoderOldIL before checking the method argument signature.
4167 EX_TRY
4168 {
4169 pILHeader = pMD->GetILHeader();
4170 }
4171 EX_CATCH_HRESULT(hr);
4172 if (FAILED(hr))
4173 return hr;
4174
4175 COR_ILMETHOD_DECODER decoderOldIL(pILHeader);
4176 mdSignature mdLocalSig = (decoderOldIL.GetLocalVarSigTok()) ? (decoderOldIL.GetLocalVarSigTok()):
4177 (mdSignatureNil);
4178
4179 PCCOR_SIGNATURE pCallSig;
4180 DWORD cbCallSigSize;
4181
4182 pMD->GetSig(&pCallSig, &cbCallSigSize);
4183
4184 if (pCallSig != NULL)
4185 {
4186 // Yes, we do need to pass in the text because this might be generic function!
4187 SigTypeContext tmpContext(pMD);
4188
4189 pArgSig = new (interopsafe, nothrow) MetaSig(pCallSig,
4190 cbCallSigSize,
4191 pMD->GetModule(),
4192 &tmpContext,
4193 MetaSig::sigMember);
4194
4195 if (pArgSig == NULL)
4196 {
4197 IfFailGo(E_OUTOFMEMORY);
4198 }
4199
4200 m_numArgs = pArgSig->NumFixedArgs();
4201
4202 if (pArgSig->HasThis())
4203 {
4204 m_numArgs++;
4205 }
4206
4207 // <TODO>
4208 // What should we do in this case?
4209 // </TODO>
4210 /*
4211 if (argSig.IsVarArg())
4212 m_numArgs++;
4213 */
4214 }
4215
4216 // allocation of pArgSig succeeded
4217 ULONG cbSig;
4218 PCCOR_SIGNATURE pLocalSig;
4219 pLocalSig = NULL;
4220 if (mdLocalSig != mdSignatureNil)
4221 {
4222 IfFailGo(pMD->GetModule()->GetMDImport()->GetSigFromToken(mdLocalSig, &cbSig, &pLocalSig));
4223 }
4224 if (pLocalSig != NULL)
4225 {
4226 SigTypeContext tmpContext(pMD);
4227 pLocSig = new (interopsafe, nothrow) MetaSig(pLocalSig,
4228 cbSig,
4229 pMD->GetModule(),
4230 &tmpContext,
4231 MetaSig::sigLocalVars);
4232
4233 if (pLocSig == NULL)
4234 {
4235 IfFailGo(E_OUTOFMEMORY);
4236 }
4237 }
4238
4239 // allocation of pLocalSig succeeded
4240 m_numTotalVars = m_numArgs + (pLocSig != NULL ? pLocSig->NumFixedArgs() : 0);
4241
4242 if (m_numTotalVars > 0)
4243 {
4244 m_rgSize = new (interopsafe, nothrow) SIZE_T[m_numTotalVars];
4245 m_rgElemType = new (interopsafe, nothrow) CorElementType[m_numTotalVars];
4246
4247 if ((m_rgSize == NULL) || (m_rgElemType == NULL))
4248 {
4249 IfFailGo(E_OUTOFMEMORY);
4250 }
4251 else
4252 {
4253 // allocation of m_rgSize and m_rgElemType succeeded
4254 for (ULONG i = 0; i < m_numTotalVars; i++)
4255 {
4256 // Choose the correct signature to walk.
4257 MetaSig *pCur = NULL;
4258 if (i < m_numArgs)
4259 {
4260 pCur = pArgSig;
4261 }
4262 else
4263 {
4264 pCur = pLocSig;
4265 }
4266
4267 // The "this" argument isn't stored in the signature, so we have to
4268 // check for it manually.
4269 if (i == 0 && pCur->HasThis())
4270 {
4271 _ASSERTE(pCur == pArgSig);
4272
4273 m_rgElemType[i] = ELEMENT_TYPE_CLASS;
4274 m_rgSize[i] = sizeof(SIZE_T);
4275 }
4276 else
4277 {
4278 m_rgElemType[i] = pCur->NextArg();
4279
4280 if (m_rgElemType[i] == ELEMENT_TYPE_VALUETYPE)
4281 {
4282 m_rgSize[i] = GetValueClassSize(pCur);
4283 }
4284 else
4285 {
4286 m_rgSize[i] = GetSetFrameHelper::GetSizeOfElement(m_rgElemType[i]);
4287 }
4288
4289 LOG((LF_CORDB, LL_INFO10000, "GSFH::I: var 0x%x is of type %x, size:0x%x\n",
4290 i, m_rgElemType[i], m_rgSize[i]));
4291 }
4292 }
4293 } // allocation of m_rgSize and m_rgElemType succeeded
4294 } // if there are variables to take care of
4295
4296ErrExit:
4297 // clean up
4298 if (pArgSig != NULL)
4299 {
4300 DeleteInteropSafe(pArgSig);
4301 }
4302
4303 if (pLocSig != NULL)
4304 {
4305 DeleteInteropSafe(pLocSig);
4306 }
4307
4308 if (FAILED(hr))
4309 {
4310 if (m_rgSize != NULL)
4311 {
4312 DeleteInteropSafe(m_rgSize);
4313 }
4314
4315 if (m_rgElemType != NULL)
4316 {
4317 DeleteInteropSafe((int*)m_rgElemType);
4318 }
4319 }
4320
4321 return hr;
4322} // GetSetFrameHelper::Init
4323
4324//
4325// GetSetFrameHelper::~GetSetFrameHelper()
4326//
4327// This is the destructor. It checks the two arrays we have allocated and frees the memory accordingly.
4328//
4329// parameters: none
4330//
4331// return value: none
4332//
4333GetSetFrameHelper::~GetSetFrameHelper()
4334{
4335 CONTRACTL
4336 {
4337 SO_NOT_MAINLINE;
4338 NOTHROW;
4339 GC_NOTRIGGER;
4340 MODE_ANY;
4341 }
4342 CONTRACTL_END;
4343
4344 if (m_rgSize)
4345 {
4346 DeleteInteropSafe(m_rgSize);
4347 }
4348
4349 if (m_rgElemType)
4350 {
4351 DeleteInteropSafe((int*)m_rgElemType);
4352 }
4353}
4354
4355//
4356// GetSetFrameHelper::GetSizeOfElement()
4357//
4358// Given a CorElementType, this function returns the size of this type.
4359// Note that this function doesn't handle ELEMENT_TYPE_VALUETYPE. Use GetValueClassSize() instead.
4360//
4361// parameters: cet - the CorElementType of the argument/local we are dealing with
4362//
4363// return value: the size of the argument/local
4364//
4365// static
4366SIZE_T GetSetFrameHelper::GetSizeOfElement(CorElementType cet)
4367{
4368 CONTRACTL
4369 {
4370 SO_NOT_MAINLINE;
4371 NOTHROW;
4372 GC_NOTRIGGER;
4373 MODE_ANY;
4374 PRECONDITION(cet != ELEMENT_TYPE_VALUETYPE);
4375 }
4376 CONTRACTL_END;
4377
4378 if (!CorIsPrimitiveType(cet))
4379 {
4380 return sizeof(SIZE_T);
4381 }
4382 else
4383 {
4384 switch (cet)
4385 {
4386 case ELEMENT_TYPE_I8:
4387 case ELEMENT_TYPE_U8:
4388#if defined(_WIN64)
4389 case ELEMENT_TYPE_I:
4390 case ELEMENT_TYPE_U:
4391#endif // _WIN64
4392 case ELEMENT_TYPE_R8:
4393 return 8;
4394
4395 case ELEMENT_TYPE_I4:
4396 case ELEMENT_TYPE_U4:
4397#if !defined(_WIN64)
4398 case ELEMENT_TYPE_I:
4399 case ELEMENT_TYPE_U:
4400#endif // !_WIN64
4401 case ELEMENT_TYPE_R4:
4402 return 4;
4403
4404 case ELEMENT_TYPE_I2:
4405 case ELEMENT_TYPE_U2:
4406 case ELEMENT_TYPE_CHAR:
4407 return 2;
4408
4409 case ELEMENT_TYPE_I1:
4410 case ELEMENT_TYPE_U1:
4411 case ELEMENT_TYPE_BOOLEAN:
4412 return 1;
4413
4414 case ELEMENT_TYPE_VOID:
4415 case ELEMENT_TYPE_END:
4416 _ASSERTE(!"debugger.cpp - Check this code path\n");
4417 return 0;
4418
4419 case ELEMENT_TYPE_STRING:
4420 return sizeof(SIZE_T);
4421
4422 default:
4423 _ASSERTE(!"debugger.cpp - Check this code path\n");
4424 return sizeof(SIZE_T);
4425 }
4426 }
4427}
4428
4429//
4430// GetSetFrameHelper::GetValueClassSize()
4431//
4432// Given a MetaSig pointer to the signature of a value type, this function returns its size.
4433//
4434// parameters: pSig - MetaSig pointer to the signature of a value type
4435//
4436// return value: the size of this value type
4437//
4438SIZE_T GetSetFrameHelper::GetValueClassSize(MetaSig* pSig)
4439{
4440 CONTRACTL
4441 {
4442 SO_NOT_MAINLINE;
4443 NOTHROW;
4444 GC_NOTRIGGER;
4445 PRECONDITION(CheckPointer(pSig));
4446 }
4447 CONTRACTL_END;
4448
4449 // We need to determine the number of bytes for this value-type.
4450 SigPointer sp = pSig->GetArgProps();
4451
4452 TypeHandle vcType = TypeHandle();
4453 {
4454 // Lookup operations run the class loader in non-load mode.
4455 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
4456
4457 // This will return Null if type is not restored
4458 // @todo : is this what we want?
4459 SigTypeContext typeContext(m_pMD);
4460 vcType = sp.GetTypeHandleThrowing(m_pMD->GetModule(),
4461 &typeContext,
4462 // == FailIfNotLoaded
4463 ClassLoader::DontLoadTypes);
4464 }
4465 // We need to know the size of the class in bytes. This means:
4466 // - we need a specific instantiation (since that affects size)
4467 // - but we don't care if it's shared (since it will be the same size either way)
4468 _ASSERTE(!vcType.IsNull() && vcType.IsValueType());
4469
4470 return (vcType.GetMethodTable()->GetAlignedNumInstanceFieldBytes());
4471}
4472
4473//
4474// GetSetFrameHelper::GetValueClassSizeOfVar()
4475//
4476// This method retrieves the size of the variable saved in the array m_rgSize. Also, it returns true
4477// if the variable is a value type.
4478//
4479// parameters: varNum - the variable number (arguments come before locals)
4480// varType - the type of variable home
4481// pSize - [out] the size
4482//
4483// return value: whether this variable is a value type
4484//
4485bool GetSetFrameHelper::GetValueClassSizeOfVar(int varNum, ICorDebugInfo::VarLocType varType, SIZE_T* pSize)
4486{
4487 CONTRACTL
4488 {
4489 SO_NOT_MAINLINE;
4490 NOTHROW;
4491 GC_NOTRIGGER;
4492 MODE_ANY;
4493 PRECONDITION(varType != ICorDebugInfo::VLT_FIXED_VA);
4494 PRECONDITION(pSize != NULL);
4495 }
4496 CONTRACTL_END;
4497
4498 // preliminary checking
4499 if (varNum < 0)
4500 {
4501 // Make sure this is one of the secret parameters (e.g. VASigCookie, generics context, etc.).
4502 _ASSERTE(varNum > (int)ICorDebugInfo::MAX_ILNUM);
4503
4504 *pSize = sizeof(LPVOID);
4505 return false;
4506 }
4507
4508 // This check is only safe after we make sure that varNum is not negative.
4509 if ((UINT)varNum >= m_numTotalVars)
4510 {
4511 _ASSERTE(!"invalid variable index encountered during setip");
4512 *pSize = 0;
4513 return false;
4514 }
4515
4516 CorElementType cet = m_rgElemType[varNum];
4517 *pSize = m_rgSize[varNum];
4518
4519 if ((cet != ELEMENT_TYPE_VALUETYPE) ||
4520 (varType == ICorDebugInfo::VLT_REG) ||
4521 (varType == ICorDebugInfo::VLT_REG_REG) ||
4522 (varType == ICorDebugInfo::VLT_REG_STK) ||
4523 (varType == ICorDebugInfo::VLT_STK_REG))
4524 {
4525 return false;
4526 }
4527 else
4528 {
4529 return true;
4530 }
4531}
4532
4533int GetSetFrameHelper::ShiftIndexForHiddens(int varNum)
4534{
4535 LIMITED_METHOD_CONTRACT;
4536
4537 //
4538 // Need to shift them up so are appropriate index for rgVal arrays
4539 //
4540 return varNum - ICorDebugInfo::UNKNOWN_ILNUM;
4541}
4542
4543// Helper method pair to grab all, then set all, variables at a given
4544// point in a routine.
4545// NOTE: GetVariablesFromOffset and SetVariablesAtOffset are
4546// very similar - modifying one will probably need to be reflected in the other...
4547// rgVal1 and rgVal2 are preallocated by callers with estimated size.
4548// We pass in the size of the allocation in rRgValeSize. The safe index will be rgVal1[0..uRgValSize - 1]
4549//
4550HRESULT Debugger::GetVariablesFromOffset(MethodDesc *pMD,
4551 UINT varNativeInfoCount,
4552 ICorDebugInfo::NativeVarInfo *varNativeInfo,
4553 SIZE_T offsetFrom,
4554 CONTEXT *pCtx,
4555 SIZE_T *rgVal1,
4556 SIZE_T *rgVal2,
4557 UINT uRgValSize, // number of elements of the preallocated rgVal1 and rgVal2
4558 BYTE ***rgpVCs)
4559{
4560 // @todo - convert this to throwing w/ holders. It will be cleaner.
4561 CONTRACTL
4562 {
4563 SO_NOT_MAINLINE;
4564 NOTHROW;
4565 GC_NOTRIGGER;
4566 PRECONDITION(CheckPointer(rgpVCs));
4567 PRECONDITION(CheckPointer(pCtx));
4568 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(varNativeInfo));
4569 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(rgVal1));
4570 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(rgVal2));
4571 // This may or may not be called on the helper thread.
4572 }
4573 CONTRACTL_END;
4574
4575 *rgpVCs = NULL;
4576 // if there are no locals, well, we are done!
4577
4578 if (varNativeInfoCount == 0)
4579 {
4580 return S_OK;
4581 }
4582
4583 memset( rgVal1, 0, sizeof(SIZE_T)*uRgValSize);
4584 memset( rgVal2, 0, sizeof(SIZE_T)*uRgValSize);
4585
4586 LOG((LF_CORDB|LF_ENC, LL_INFO10000, "D::GVFO: %s::%s, infoCount:0x%x, from:0x%p\n",
4587 pMD->m_pszDebugClassName,
4588 pMD->m_pszDebugMethodName,
4589 varNativeInfoCount,
4590 offsetFrom));
4591
4592 GetSetFrameHelper frameHelper;
4593 HRESULT hr = frameHelper.Init(pMD);
4594 if (FAILED(hr))
4595 {
4596 return hr;
4597 }
4598 // preallocate enough to hold all possible valueclass args & locals
4599 // sure this is more than we need, but not a big deal and better
4600 // than having to crawl through the frameHelper and count
4601 ULONG cValueClasses = 0;
4602 BYTE **rgpValueClasses = new (interopsafe, nothrow) BYTE *[varNativeInfoCount];
4603 if (rgpValueClasses == NULL)
4604 {
4605 return E_OUTOFMEMORY;
4606 }
4607 memset(rgpValueClasses, 0, sizeof(BYTE *)*varNativeInfoCount);
4608
4609 hr = S_OK;
4610
4611 LOG((LF_CORDB|LF_ENC,
4612 LL_INFO10000,
4613 "D::GVFO rgVal1 0x%X, rgVal2 0x%X\n",
4614 rgVal1,
4615 rgVal2));
4616
4617 // Now go through the full array and save off each arg and local
4618 for (UINT i = 0; i< varNativeInfoCount;i++)
4619 {
4620 // Ignore variables not live at offsetFrom
4621 //
4622 // #VarLife
4623 //
4624 // The condition below is a little strange. If a var is alive when this is true:
4625 //
4626 // startOffset <= offsetFrom < endOffset
4627 //
4628 // Then you'd expect the negated expression below to be:
4629 //
4630 // startOffset > offsetFrom || endOffset <= offsetFrom
4631 //
4632 // instead of what we're doing ("<" instead of "<="):
4633 //
4634 // startOffset > offsetFrom || endOffset < offsetFrom
4635 //
4636 // I'm not sure if the condition below is a mistake, or if it's intentionally
4637 // mirroring a workaround from FindNativeInfoInILVariableArray() (Debug\DI\module.cpp)
4638 // to deal with optimized code. So I'm leaving it alone for now. See
4639 // code:FindNativeInfoInILVariableArray for more info on this workaround.
4640 if ((varNativeInfo[i].startOffset > offsetFrom) ||
4641 (varNativeInfo[i].endOffset < offsetFrom) ||
4642 (varNativeInfo[i].loc.vlType == ICorDebugInfo::VLT_INVALID))
4643 {
4644 LOG((LF_CORDB|LF_ENC,LL_INFO10000, "D::GVFO [%2d] invalid\n", i));
4645 continue;
4646 }
4647
4648 SIZE_T cbClass;
4649 bool isVC = frameHelper.GetValueClassSizeOfVar(varNativeInfo[i].varNumber,
4650 varNativeInfo[i].loc.vlType,
4651 &cbClass);
4652
4653 if (!isVC)
4654 {
4655 int rgValIndex = frameHelper.ShiftIndexForHiddens(varNativeInfo[i].varNumber);
4656
4657 _ASSERTE(rgValIndex >= 0 && rgValIndex < (int)uRgValSize);
4658
4659 BOOL res = GetNativeVarVal(varNativeInfo[i].loc,
4660 pCtx,
4661 rgVal1 + rgValIndex,
4662 rgVal2 + rgValIndex
4663 WIN64_ARG(cbClass));
4664
4665 LOG((LF_CORDB|LF_ENC,LL_INFO10000,
4666 "D::GVFO [%2d] varnum %d, nonVC type %x, addr %8.8x: %8.8x;%8.8x\n",
4667 i,
4668 varNativeInfo[i].varNumber,
4669 varNativeInfo[i].loc.vlType,
4670 NativeVarStackAddr(varNativeInfo[i].loc, pCtx),
4671 rgVal1[rgValIndex],
4672 rgVal2[rgValIndex]));
4673
4674 if (res == TRUE)
4675 {
4676 continue;
4677 }
4678
4679 _ASSERTE(res == TRUE);
4680 hr = E_FAIL;
4681 break;
4682 }
4683
4684 // it's definately a value class
4685 // Make space for it - note that it uses the VC index, NOT the variable index
4686 _ASSERTE(cbClass != 0);
4687 rgpValueClasses[cValueClasses] = new (interopsafe, nothrow) BYTE[cbClass];
4688 if (rgpValueClasses[cValueClasses] == NULL)
4689 {
4690 hr = E_OUTOFMEMORY;
4691 break;
4692 }
4693 memcpy(rgpValueClasses[cValueClasses],
4694 NativeVarStackAddr(varNativeInfo[i].loc, pCtx),
4695 cbClass);
4696
4697 // Move index up.
4698 cValueClasses++;
4699#ifdef _DEBUG
4700 LOG((LF_CORDB|LF_ENC,LL_INFO10000,
4701 "D::GVFO [%2d] varnum %d, VC len %d, addr %8.8x, sample: %8.8x%8.8x\n",
4702 i,
4703 varNativeInfo[i].varNumber,
4704 cbClass,
4705 NativeVarStackAddr(varNativeInfo[i].loc, pCtx),
4706 (rgpValueClasses[cValueClasses-1])[0], (rgpValueClasses[cValueClasses-1])[1]));
4707#endif
4708 }
4709
4710 LOG((LF_CORDB|LF_ENC, LL_INFO10000, "D::GVFO: returning %8.8x\n", hr));
4711 if (SUCCEEDED(hr))
4712 {
4713 (*rgpVCs) = rgpValueClasses;
4714 return hr;
4715 }
4716
4717 // We failed for some reason
4718 if (rgpValueClasses != NULL)
4719 { // free any memory we allocated for VCs here
4720 while(cValueClasses > 0)
4721 {
4722 --cValueClasses;
4723 DeleteInteropSafe(rgpValueClasses[cValueClasses]); // OK to delete NULL
4724 }
4725 DeleteInteropSafe(rgpValueClasses);
4726 rgpValueClasses = NULL;
4727 }
4728 return hr;
4729}
4730
4731// NOTE: GetVariablesFromOffset and SetVariablesAtOffset are
4732// very similar - modifying one will probably need to be reflected in the other...
4733HRESULT Debugger::SetVariablesAtOffset(MethodDesc *pMD,
4734 UINT varNativeInfoCount,
4735 ICorDebugInfo::NativeVarInfo *varNativeInfo,
4736 SIZE_T offsetTo,
4737 CONTEXT *pCtx,
4738 SIZE_T *rgVal1,
4739 SIZE_T *rgVal2,
4740 BYTE **rgpVCs)
4741{
4742 CONTRACTL
4743 {
4744 SO_NOT_MAINLINE;
4745 NOTHROW;
4746 GC_NOTRIGGER;
4747 PRECONDITION(CheckPointer(pCtx));
4748 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(rgpVCs));
4749 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(varNativeInfo));
4750 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(rgVal1));
4751 PRECONDITION(varNativeInfoCount == 0 || CheckPointer(rgVal2));
4752 // This may or may not be called on the helper thread.
4753 }
4754 CONTRACTL_END;
4755
4756 LOG((LF_CORDB|LF_ENC, LL_INFO10000, "D::SVAO: %s::%s, infoCount:0x%x, to:0x%p\n",
4757 pMD->m_pszDebugClassName,
4758 pMD->m_pszDebugMethodName,
4759 varNativeInfoCount,
4760 offsetTo));
4761
4762 if (varNativeInfoCount == 0)
4763 {
4764 return S_OK;
4765 }
4766
4767 GetSetFrameHelper frameHelper;
4768 HRESULT hr = frameHelper.Init(pMD);
4769 if (FAILED(hr))
4770 {
4771 return hr;
4772 }
4773
4774 ULONG iVC = 0;
4775 hr = S_OK;
4776
4777 // Note that since we obtain all the variables in the first loop, we
4778 // can now splatter those variables into their new locations
4779 // willy-nilly, without the fear that variable locations that have
4780 // been swapped might accidentally overwrite a variable value.
4781 for (UINT i = 0;i< varNativeInfoCount;i++)
4782 {
4783 // Ignore variables not live at offsetTo
4784 //
4785 // If this IF condition looks wrong to you, see
4786 // code:Debugger::GetVariablesFromOffset#VarLife for more info
4787 if ((varNativeInfo[i].startOffset > offsetTo) ||
4788 (varNativeInfo[i].endOffset < offsetTo) ||
4789 (varNativeInfo[i].loc.vlType == ICorDebugInfo::VLT_INVALID))
4790 {
4791 LOG((LF_CORDB|LF_ENC,LL_INFO10000, "D::SVAO [%2d] invalid\n", i));
4792 continue;
4793 }
4794
4795 SIZE_T cbClass;
4796 bool isVC = frameHelper.GetValueClassSizeOfVar(varNativeInfo[i].varNumber,
4797 varNativeInfo[i].loc.vlType,
4798 &cbClass);
4799
4800 if (!isVC)
4801 {
4802 int rgValIndex = frameHelper.ShiftIndexForHiddens(varNativeInfo[i].varNumber);
4803
4804 _ASSERTE(rgValIndex >= 0);
4805
4806 BOOL res = SetNativeVarVal(varNativeInfo[i].loc,
4807 pCtx,
4808 rgVal1[rgValIndex],
4809 rgVal2[rgValIndex]
4810 WIN64_ARG(cbClass));
4811
4812 LOG((LF_CORDB|LF_ENC,LL_INFO10000,
4813 "D::SVAO [%2d] varnum %d, nonVC type %x, addr %8.8x: %8.8x;%8.8x\n",
4814 i,
4815 varNativeInfo[i].varNumber,
4816 varNativeInfo[i].loc.vlType,
4817 NativeVarStackAddr(varNativeInfo[i].loc, pCtx),
4818 rgVal1[rgValIndex],
4819 rgVal2[rgValIndex]));
4820
4821 if (res == TRUE)
4822 {
4823 continue;
4824 }
4825 _ASSERTE(res == TRUE);
4826 hr = E_FAIL;
4827 break;
4828 }
4829
4830 // It's definately a value class.
4831 _ASSERTE(cbClass != 0);
4832 if (rgpVCs[iVC] == NULL)
4833 {
4834 // it's new in scope, so just clear it
4835 memset(NativeVarStackAddr(varNativeInfo[i].loc, pCtx), 0, cbClass);
4836 LOG((LF_CORDB|LF_ENC,LL_INFO10000, "D::SVAO [%2d] varnum %d, new VC len %d, addr %8.8x\n",
4837 i,
4838 varNativeInfo[i].varNumber,
4839 cbClass,
4840 NativeVarStackAddr(varNativeInfo[i].loc, pCtx)));
4841 continue;
4842 }
4843 // it's a pre-existing VC, so copy it
4844 memmove(NativeVarStackAddr(varNativeInfo[i].loc, pCtx), rgpVCs[iVC], cbClass);
4845#ifdef _DEBUG
4846 LOG((LF_CORDB|LF_ENC,LL_INFO10000,
4847 "D::SVAO [%2d] varnum %d, VC len %d, addr: %8.8x sample: %8.8x%8.8x\n",
4848 i,
4849 varNativeInfo[i].varNumber,
4850 cbClass,
4851 NativeVarStackAddr(varNativeInfo[i].loc, pCtx),
4852 rgpVCs[iVC][0],
4853 rgpVCs[iVC][1]));
4854#endif
4855 // Now get rid of the memory
4856 DeleteInteropSafe(rgpVCs[iVC]);
4857 rgpVCs[iVC] = NULL;
4858 iVC++;
4859 }
4860
4861 LOG((LF_CORDB|LF_ENC, LL_INFO10000, "D::SVAO: returning %8.8x\n", hr));
4862
4863 if (rgpVCs != NULL)
4864 {
4865 DeleteInteropSafe(rgpVCs);
4866 }
4867
4868 return hr;
4869}
4870
4871BOOL IsDuplicatePatch(SIZE_T *rgEntries,
4872 ULONG cEntries,
4873 SIZE_T Entry )
4874{
4875 LIMITED_METHOD_CONTRACT;
4876
4877 for( ULONG i = 0; i < cEntries;i++)
4878 {
4879 if (rgEntries[i] == Entry)
4880 return TRUE;
4881 }
4882 return FALSE;
4883}
4884
4885
4886/******************************************************************************
4887// HRESULT Debugger::MapAndBindFunctionBreakpoints(): For each breakpoint
4888// that we've set in any version of the existing function,
4889// set a correponding breakpoint in the new function if we haven't moved
4890// the patch to the new version already.
4891//
4892// This must be done _AFTER_ the MethodDesc has been udpated
4893// with the new address (ie, when GetFunctionAddress pFD returns
4894// the address of the new EnC code)
4895//
4896// Parameters:
4897// djiNew - this is the DJI created in D::JitComplete.
4898// If djiNew == NULL iff we aren't tracking debug-info.
4899// fd - the method desc that we're binding too.
4900// addrOfCode - address of the native blob of code we just jitted
4901//
4902// <TODO>@todo Replace array with hashtable for improved efficiency</TODO>
4903// <TODO>@todo Need to factor code,so that we can selectively map forward DFK(ilOFfset) BPs</TODO>
4904 ******************************************************************************/
4905HRESULT Debugger::MapAndBindFunctionPatches(DebuggerJitInfo *djiNew,
4906 MethodDesc * fd,
4907 CORDB_ADDRESS_TYPE *addrOfCode)
4908{
4909 // @@@
4910 // Internal helper API. Can be called from Debugger or Controller.
4911 //
4912
4913 CONTRACTL
4914 {
4915 SO_NOT_MAINLINE;
4916 THROWS;
4917 CALLED_IN_DEBUGGERDATALOCK_HOLDER_SCOPE_MAY_GC_TRIGGERS_CONTRACT;
4918 PRECONDITION(!djiNew || djiNew->m_fd == fd);
4919 }
4920 CONTRACTL_END;
4921
4922 HRESULT hr = S_OK;
4923 HASHFIND hf;
4924 SIZE_T *pidTableEntry = NULL;
4925 SIZE_T pidInCaseTableMoves;
4926 Module *pModule = g_pEEInterface->MethodDescGetModule(fd);
4927 mdMethodDef md = fd->GetMemberDef();
4928
4929 LOG((LF_CORDB,LL_INFO10000,"D::MABFP: All BPs will be mapped to "
4930 "Ver:0x%04x (DJI:0x%08x)\n", djiNew?djiNew->m_methodInfo->GetCurrentEnCVersion():0, djiNew));
4931
4932 // We need to traverse the patch list while under the controller lock (small lock).
4933 // But we can only send BreakpointSetErros while under the debugger lock (big lock).
4934 // So to avoid a lock violation, we queue any errors we find under the small lock,
4935 // and then send the whole list when under the big lock.
4936 PATCH_UNORDERED_ARRAY listUnbindablePatches;
4937
4938
4939 // First lock the patch table so it doesn't move while we're
4940 // examining it.
4941 LOG((LF_CORDB,LL_INFO10000, "D::MABFP: About to lock patch table\n"));
4942 {
4943 DebuggerController::ControllerLockHolder ch;
4944
4945 // Manipulate tables AFTER lock's been acquired.
4946 DebuggerPatchTable *pPatchTable = DebuggerController::GetPatchTable();
4947 GetBPMappingDuplicates()->Clear(); //dups are tracked per-version
4948
4949 for (DebuggerControllerPatch *dcp = pPatchTable->GetFirstPatch(&hf);
4950 dcp != NULL;
4951 dcp = pPatchTable->GetNextPatch( &hf ))
4952 {
4953
4954 LOG((LF_CORDB, LL_INFO10000, "D::MABFP: got patch 0x%p\n", dcp));
4955
4956 // Only copy over breakpoints that are in this method
4957 // Ideally we'd have a per-method index since there can be a lot of patches
4958 // when the EnCBreakpoint patches are included.
4959 if (dcp->key.module != pModule || dcp->key.md != md)
4960 {
4961 LOG((LF_CORDB, LL_INFO10000, "Patch not in this method\n"));
4962 continue;
4963 }
4964
4965 // If the patch only applies in certain generic instances, don't bind it
4966 // elsewhere.
4967 if(dcp->pMethodDescFilter != NULL && dcp->pMethodDescFilter != djiNew->m_fd)
4968 {
4969 LOG((LF_CORDB, LL_INFO10000, "Patch not in this generic instance\n"));
4970 continue;
4971 }
4972
4973
4974 // Do not copy over slave breakpoint patches. Instead place a new slave
4975 // based off the master.
4976 if (dcp->IsILSlavePatch())
4977 {
4978 LOG((LF_CORDB, LL_INFO10000, "Not copying over slave breakpoint patch\n"));
4979 continue;
4980 }
4981
4982 // If the patch is already bound, then we don't want to try to rebind it.
4983 // Eg. It may be bound to a different generic method instantiation.
4984 if (dcp->IsBound())
4985 {
4986 LOG((LF_CORDB, LL_INFO10000, "Skipping already bound patch\n"));
4987 continue;
4988 }
4989
4990 // Only apply breakpoint patches that are for this version.
4991 // If the patch doesn't have a particular EnCVersion available from its data then
4992 // we're (probably) not tracking JIT info.
4993 if (dcp->IsBreakpointPatch() && dcp->HasEnCVersion() && djiNew && dcp->GetEnCVersion() != djiNew->m_encVersion)
4994 {
4995 LOG((LF_CORDB, LL_INFO10000, "Not applying breakpoint patch to new version\n"));
4996 continue;
4997 }
4998
4999 // Only apply breakpoint and stepper patches
5000 //
5001 // The DJI gets deleted as part of the Unbind/Rebind process in MovedCode.
5002 // This is to signal that we should not skip here.
5003 // <NICE> under exactly what scenarios (EnC, code pitching etc.) will this apply?... </NICE>
5004 // <NICE> can't we be a little clearer about why we don't want to bind the patch in this arcane situation?</NICE>
5005 if (dcp->HasDJI() && !dcp->IsBreakpointPatch() && !dcp->IsStepperPatch())
5006 {
5007 LOG((LF_CORDB, LL_INFO10000, "Neither stepper nor BP but we have valid a DJI (i.e. the DJI hasn't been deleted as part of the Unbind/MovedCode/Rebind mess)! - getting next patch!\n"));
5008 continue;
5009 }
5010
5011 // Now check if we're tracking JIT info or not
5012 if (djiNew == NULL)
5013 {
5014 // This means we put a patch in a method w/ no debug info.
5015 _ASSERTE(dcp->IsBreakpointPatch() ||
5016 dcp->IsStepperPatch() ||
5017 dcp->controller->GetDCType() == DEBUGGER_CONTROLLER_THREAD_STARTER);
5018
5019 // W/o Debug-info, We can only patch native offsets, and only at the start of the method (native offset 0).
5020 // <TODO> Why can't we patch other native offsets??
5021 // Maybe b/c we don't know if we're patching
5022 // in the middle of an instruction. Though that's not a
5023 // strict requirement.</TODO>
5024 // We can't even do a IL-offset 0 because that's after the prolog and w/o the debug-info,
5025 // we don't know where the prolog ends.
5026 // Failing this assert is arguably an API misusage - the debugger should have enabled
5027 // jit-tracking if they wanted to put bps at offsets other than native:0.
5028 if (dcp->IsNativePatch() && (dcp->offset == 0))
5029 {
5030 DebuggerController::g_patches->BindPatch(dcp, addrOfCode);
5031 DebuggerController::ActivatePatch(dcp);
5032 }
5033 else
5034 {
5035 // IF a debugger calls EnableJitDebugging(true, ...) in the module-load callback,
5036 // we should never get here.
5037 *(listUnbindablePatches.AppendThrowing()) = dcp;
5038 }
5039
5040 }
5041 else
5042 {
5043 pidInCaseTableMoves = dcp->pid;
5044
5045 // If we've already mapped this one to the current version,
5046 // don't map it again.
5047 LOG((LF_CORDB,LL_INFO10000,"D::MABFP: Checking if 0x%x is a dup...",
5048 pidInCaseTableMoves));
5049
5050 if ( IsDuplicatePatch(GetBPMappingDuplicates()->Table(),
5051 GetBPMappingDuplicates()->Count(),
5052 pidInCaseTableMoves) )
5053 {
5054 LOG((LF_CORDB,LL_INFO10000,"it is!\n"));
5055 continue;
5056 }
5057 LOG((LF_CORDB,LL_INFO10000,"nope!\n"));
5058
5059 // Attempt mapping from patch to new version of code, and
5060 // we don't care if it turns out that there isn't a mapping.
5061 // <TODO>@todo-postponed: EnC: Make sure that this doesn't cause
5062 // the patch-table to shift.</TODO>
5063 hr = MapPatchToDJI( dcp, djiNew );
5064 if (CORDBG_E_CODE_NOT_AVAILABLE == hr )
5065 {
5066 *(listUnbindablePatches.AppendThrowing()) = dcp;
5067 hr = S_OK;
5068 }
5069
5070 if (FAILED(hr))
5071 break;
5072
5073 //Remember the patch id to prevent duplication later
5074 pidTableEntry = GetBPMappingDuplicates()->Append();
5075 if (NULL == pidTableEntry)
5076 {
5077 hr = E_OUTOFMEMORY;
5078 break;
5079 }
5080
5081 *pidTableEntry = pidInCaseTableMoves;
5082 LOG((LF_CORDB,LL_INFO10000,"D::MABFP Adding 0x%x to list of "
5083 "already mapped patches\n", pidInCaseTableMoves));
5084 }
5085 }
5086
5087 // unlock controller lock before sending events.
5088 }
5089 LOG((LF_CORDB,LL_INFO10000, "D::MABFP: Unlocked patch table\n"));
5090
5091
5092 // Now send any Breakpoint bind error events.
5093 if (listUnbindablePatches.Count() > 0)
5094 {
5095 LockAndSendBreakpointSetError(&listUnbindablePatches);
5096 }
5097
5098 return hr;
5099}
5100
5101/******************************************************************************
5102// HRESULT Debugger::MapPatchToDJI(): Maps the given
5103// patch to the corresponding location at the new address.
5104// We assume that the new code has been JITTed.
5105// Returns: CORDBG_E_CODE_NOT_AVAILABLE - Indicates that a mapping wasn't
5106// available, and thus no patch was placed. The caller may or may
5107// not care.
5108 ******************************************************************************/
5109HRESULT Debugger::MapPatchToDJI( DebuggerControllerPatch *dcp,DebuggerJitInfo *djiTo)
5110{
5111 CONTRACTL
5112 {
5113 SO_NOT_MAINLINE;
5114 THROWS;
5115 CALLED_IN_DEBUGGERDATALOCK_HOLDER_SCOPE_MAY_GC_TRIGGERS_CONTRACT;
5116 PRECONDITION(djiTo != NULL);
5117 PRECONDITION(djiTo->m_jitComplete == true);
5118 }
5119 CONTRACTL_END;
5120
5121 _ASSERTE(DebuggerController::HasLock());
5122#ifdef _DEBUG
5123 static BOOL shouldBreak = -1;
5124 if (shouldBreak == -1)
5125 shouldBreak = UnsafeGetConfigDWORD(CLRConfig::INTERNAL_DbgBreakOnMapPatchToDJI);
5126
5127 if (shouldBreak > 0) {
5128 _ASSERTE(!"DbgBreakOnMatchPatchToDJI");
5129 }
5130#endif
5131
5132 LOG((LF_CORDB, LL_EVERYTHING, "Calling MapPatchToDJI\n"));
5133
5134 // We shouldn't have been asked to map an already bound patch
5135 _ASSERTE( !dcp->IsBound() );
5136 if ( dcp->IsBound() )
5137 {
5138 return S_OK;
5139 }
5140
5141 // If the patch has no DJI then we're doing a UnbindFunctionPatches/RebindFunctionPatches. Either
5142 // way, we simply want the most recent version. In the absence of EnC we should have djiCur == djiTo.
5143 DebuggerJitInfo *djiCur = dcp->HasDJI() ? dcp->GetDJI() : djiTo;
5144 PREFIX_ASSUME(djiCur != NULL);
5145
5146 // If the source and destination are the same version, then this method
5147 // decays into BindFunctionPatch's BindPatch function
5148 if (djiCur->m_encVersion == djiTo->m_encVersion)
5149 {
5150 // If the patch is a "master" then make a new "slave" patch instead of
5151 // binding the old one. This is to stop us mucking with the master breakpoint patch
5152 // which we may need to bind several times for generic code.
5153 if (dcp->IsILMasterPatch())
5154 {
5155 LOG((LF_CORDB, LL_EVERYTHING, "Add, Bind, Activate new patch from master patch\n"));
5156 if (dcp->controller->AddBindAndActivateILSlavePatch(dcp, djiTo))
5157 {
5158 LOG((LF_CORDB, LL_INFO1000, "Add, Bind Activate went fine!\n" ));
5159 return S_OK;
5160 }
5161 else
5162 {
5163 LOG((LF_CORDB, LL_INFO1000, "Didn't work for some reason!\n"));
5164
5165 // Caller can track this HR and send error.
5166 return CORDBG_E_CODE_NOT_AVAILABLE;
5167 }
5168 }
5169 else
5170 {
5171 // <TODO>
5172 // We could actually have a native managed patch here. This patch is probably added
5173 // as a result of tracing a patch. See if we can eliminate the need for this code path
5174 // </TODO>
5175 _ASSERTE( dcp->GetKind() == PATCH_KIND_NATIVE_MANAGED );
5176
5177 // We have an unbound native patch (eg. for PatchTrace), lets try to bind and activate it
5178 dcp->SetDJI(djiTo);
5179 LOG((LF_CORDB, LL_EVERYTHING, "trying to bind patch... could be problem\n"));
5180 if (DebuggerController::BindPatch(dcp, djiTo->m_fd, NULL))
5181 {
5182 DebuggerController::ActivatePatch(dcp);
5183 LOG((LF_CORDB, LL_INFO1000, "Application went fine!\n" ));
5184 return S_OK;
5185 }
5186 else
5187 {
5188 LOG((LF_CORDB, LL_INFO1000, "Didn't apply for some reason!\n"));
5189
5190 // Caller can track this HR and send error.
5191 return CORDBG_E_CODE_NOT_AVAILABLE;
5192 }
5193 }
5194 }
5195
5196 // Breakpoint patches never get mapped over
5197 _ASSERTE(!dcp->IsBreakpointPatch());
5198
5199 return S_OK;
5200}
5201
5202
5203/* ------------------------------------------------------------------------ *
5204 * EE Interface routines
5205 * ------------------------------------------------------------------------ */
5206
5207//
5208// SendSyncCompleteIPCEvent sends a Sync Complete event to the Right Side.
5209//
5210void Debugger::SendSyncCompleteIPCEvent(bool isEESuspendedForGC)
5211{
5212 CONTRACTL
5213 {
5214 SO_NOT_MAINLINE;
5215 NOTHROW;
5216 GC_NOTRIGGER;
5217 PRECONDITION(ThreadHoldsLock());
5218
5219 // Anyone sending the synccomplete must hold the TSL.
5220 PRECONDITION(ThreadStore::HoldingThreadStore() || g_fProcessDetach);
5221
5222 // The sync complete is now only sent on a helper thread.
5223 if (!isEESuspendedForGC)
5224 {
5225 PRECONDITION(ThisIsHelperThreadWorker());
5226 }
5227 MODE_COOPERATIVE;
5228
5229 // We had better be trapping Runtime threads and not stopped yet.
5230 if (isEESuspendedForGC)
5231 {
5232 PRECONDITION(m_stopped);
5233 }
5234 else
5235 {
5236 PRECONDITION(m_stopped && m_trappingRuntimeThreads);
5237 }
5238 }
5239 CONTRACTL_END;
5240
5241 // @@@
5242 // Internal helper API.
5243 // This is to send Sync Complete event to RightSide.
5244 // We should have hold the debugger lock
5245 //
5246
5247 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::SSCIPCE: sync complete.\n");
5248
5249 // Synchronizing while in in rude shutdown should be extremely rare b/c we don't
5250 // TART in rude shutdown. Shutdown must have started after we started to sync.
5251 // We know we're not on the shutdown thread here.
5252 // And we also know we can't block the shutdown thread (b/c it has the TSL and will
5253 // get a free pass through the GC toggles that normally block threads for debugging).
5254 if (g_fProcessDetach)
5255 {
5256 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::SSCIPCE: Skipping for shutdown.\n");
5257 return;
5258 }
5259
5260 // If we're not marked as attached yet, then do that now.
5261 // This can be safely called multiple times.
5262 // This can happen in the normal attach case. The Right-side sends an async-break,
5263 // but we don't want to be considered attach until we've actually gotten our first synchronization.
5264 // Else threads may slip forward during attach and send debug events while we're tyring to attach.
5265 MarkDebuggerAttachedInternal();
5266
5267 DebuggerIPCControlBlock * pDCB;
5268 pDCB = m_pRCThread->GetDCB();
5269 (void)pDCB; //prevent "unused variable" error from GCC
5270
5271 PREFIX_ASSUME(pDCB != NULL); // must have DCB by the time we're sending IPC events.
5272#ifdef FEATURE_INTEROP_DEBUGGING
5273 // The synccomplete can't be the first IPC event over. That's b/c the LS needs to know
5274 // if we're interop-debugging and the RS needs to know special addresses for interop-debugging
5275 // (like flares). All of this info is in the DCB.
5276 if (pDCB->m_rightSideIsWin32Debugger)
5277 {
5278
5279 // If the Right Side is the win32 debugger of this process, then we need to throw a special breakpoint exception
5280 // here instead of sending the sync complete event. The Right Side treats this the same as a sync complete
5281 // event, but its also able to suspend unmanaged threads quickly.
5282 // This also prevents races between sending the sync-complete and getting a native debug event
5283 // (since the sync-complete becomes a native debug event, and all native debug events are serialized).
5284 //
5285 // Note: we reset the syncThreadIsLockFree event before sending the sync complete flare. This thread will set
5286 // this event once its released the debugger lock. This will prevent the Right Side from suspending this thread
5287 // until it has released the debugger lock.
5288 Debugger::NotifyRightSideOfSyncComplete();
5289 }
5290 else
5291#endif // FEATURE_INTEROP_DEBUGGING
5292 {
5293 STRESS_LOG0(LF_CORDB, LL_EVERYTHING, "GetIPCEventSendBuffer called in SendSyncCompleteIPCEvent\n");
5294 // Send the Sync Complete event to the Right Side
5295 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
5296 InitIPCEvent(ipce, DB_IPCE_SYNC_COMPLETE);
5297
5298 m_pRCThread->SendIPCEvent();
5299 }
5300}
5301
5302//
5303// Lookup or create a DebuggerModule for the given pDomainFile.
5304//
5305// Arguments:
5306// pDomainFile - non-null domain file.
5307//
5308// Returns:
5309// DebuggerModule instance for the given domain file. May be lazily created.
5310//
5311// Notes:
5312// @dbgtodo JMC - this should go away when we get rid of DebuggerModule.
5313//
5314
5315DebuggerModule * Debugger::LookupOrCreateModule(DomainFile * pDomainFile)
5316{
5317 _ASSERTE(pDomainFile != NULL);
5318 LOG((LF_CORDB, LL_INFO1000, "D::LOCM df=0x%x\n", pDomainFile));
5319 DebuggerModule * pDModule = LookupOrCreateModule(pDomainFile->GetModule(), pDomainFile->GetAppDomain());
5320 LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pDomainFile->GetModule(), pDomainFile->GetAppDomain(), pDModule));
5321 _ASSERTE(pDModule != NULL);
5322 _ASSERTE(pDModule->GetDomainFile() == pDomainFile);
5323
5324 return pDModule;
5325}
5326
5327// Overloaded Wrapper around for VMPTR_DomainFile-->DomainFile*
5328//
5329// Arguments:
5330// vmDomainFile - VMPTR cookie for a domain file. This can be NullPtr().
5331//
5332// Returns:
5333// Debugger Module instance for the given domain file. May be lazily created.
5334//
5335// Notes:
5336// VMPTR comes from IPC events
5337DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
5338{
5339 DomainFile * pDomainFile = vmDomainFile.GetRawPtr();
5340 if (pDomainFile == NULL)
5341 {
5342 return NULL;
5343 }
5344 return LookupOrCreateModule(pDomainFile);
5345}
5346
5347// Lookup or create a DebuggerModule for the given (Module, AppDomain) pair.
5348//
5349// Arguments:
5350// pModule - required runtime module. May be domain netural.
5351// pAppDomain - required appdomain that the module is in.
5352//
5353// Returns:
5354// Debugger Module isntance for the given domain file. May be lazily created.
5355//
5356DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppDomain)
5357{
5358 CONTRACTL
5359 {
5360 SO_NOT_MAINLINE;
5361 NOTHROW;
5362 GC_NOTRIGGER;
5363 }
5364 CONTRACTL_END;
5365
5366 LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x\n", pModule, pAppDomain));
5367
5368 // DebuggerModules are relative to a specific AppDomain so we should always be looking up a module /
5369 // AppDomain pair.
5370 _ASSERTE( pModule != NULL );
5371 _ASSERTE( pAppDomain != NULL );
5372
5373 // This is called from all over. We just need to lock in order to lookup. We don't need
5374 // the lock when actually using the DebuggerModule (since it won't be unloaded as long as there is a thread
5375 // in that appdomain). Many of our callers already have this lock, many don't.
5376 // We can take the lock anyways because it's reentrant.
5377 DebuggerDataLockHolder ch(g_pDebugger); // need to traverse module list
5378
5379 // if this is a module belonging to the system assembly, then scan
5380 // the complete list of DebuggerModules looking for the one
5381 // with a matching appdomain id
5382 // it.
5383
5384 DebuggerModule* dmod = NULL;
5385
5386 if (m_pModules != NULL)
5387 {
5388 dmod = m_pModules->GetModule(pModule);
5389 }
5390
5391 // If it doesn't exist, create it.
5392 if (dmod == NULL)
5393 {
5394 HRESULT hr = S_OK;
5395 EX_TRY
5396 {
5397 DomainFile * pDomainFile = pModule->FindDomainFile(pAppDomain);
5398 SIMPLIFYING_ASSUMPTION(pDomainFile != NULL);
5399 dmod = AddDebuggerModule(pDomainFile); // throws
5400 }
5401 EX_CATCH_HRESULT(hr);
5402 SIMPLIFYING_ASSUMPTION(dmod != NULL); // may not be true in OOM cases; but LS doesn't handle OOM.
5403 }
5404
5405 // The module must be in the AppDomain that was requested
5406 _ASSERTE( (dmod == NULL) || (dmod->GetAppDomain() == pAppDomain) );
5407
5408 LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pModule, pAppDomain, dmod));
5409 return dmod;
5410}
5411
5412// Create a new DebuggerModule object
5413//
5414// Arguments:
5415// pDomainFile- runtime domain file to create debugger module object around
5416//
5417// Returns:
5418// New instnace of a DebuggerModule. Throws on failure.
5419//
5420DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile)
5421{
5422 CONTRACTL
5423 {
5424 THROWS;
5425 GC_NOTRIGGER;
5426 }
5427 CONTRACTL_END;
5428
5429 LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainFile));
5430 DebuggerDataLockHolder chInfo(this);
5431
5432 Module * pRuntimeModule = pDomainFile->GetCurrentModule();
5433 AppDomain * pAppDomain = pDomainFile->GetAppDomain();
5434
5435 HRESULT hr = CheckInitModuleTable();
5436 IfFailThrow(hr);
5437
5438 DebuggerModule* pModule = new (interopsafe) DebuggerModule(pRuntimeModule, pDomainFile, pAppDomain);
5439 _ASSERTE(pModule != NULL); // throws on oom
5440
5441 TRACE_ALLOC(pModule);
5442
5443 m_pModules->AddModule(pModule); // throws
5444 // @dbgtodo inspection/exceptions - this may leak module in OOM case. LS is not OOM resilient; and we
5445 // expect to get rid of DebuggerModule anyways.
5446
5447 LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x -> dm=0x%x\n", pDomainFile, pModule));
5448 return pModule;
5449}
5450
5451//
5452// TrapAllRuntimeThreads causes every Runtime thread that is executing
5453// in the EE to trap and send the at safe point event to the RC thread as
5454// soon as possible. It also sets the EE up so that Runtime threads that
5455// are outside of the EE will trap when they try to re-enter.
5456//
5457// @TODO::
5458// Neither pDbgLockHolder nor pAppDomain are used.
5459void Debugger::TrapAllRuntimeThreads()
5460{
5461 CONTRACTL
5462 {
5463 SO_NOT_MAINLINE;
5464 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
5465 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
5466
5467 // We acquired the lock b/c we're in a scope between LFES & UFES.
5468 PRECONDITION(ThreadHoldsLock());
5469
5470 // This should never be called on a Temporary Helper thread.
5471 PRECONDITION(IsDbgHelperSpecialThread() ||
5472 (g_pEEInterface->GetThread() == NULL) ||
5473 !g_pEEInterface->IsPreemptiveGCDisabled());
5474 }
5475 CONTRACTL_END;
5476
5477#if !defined(FEATURE_DBGIPC_TRANSPORT_VM)
5478 // Only sync if RS requested it.
5479 if (!m_RSRequestedSync)
5480 {
5481 return;
5482 }
5483 m_RSRequestedSync = FALSE;
5484#endif
5485
5486 // If we're doing shutdown, then don't bother trying to communicate w/ the RS.
5487 // If we're not the thread doing shutdown, then we may be asynchronously killed by the OS.
5488 // If we are the thread in shutdown, don't TART b/c that may block and do complicated stuff.
5489 if (g_fProcessDetach)
5490 {
5491 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::TART: Skipping for shutdown.\n");
5492 return;
5493 }
5494
5495
5496 // Only try to start trapping if we're not already trapping.
5497 if (m_trappingRuntimeThreads == FALSE)
5498 {
5499 bool fSuspended;
5500
5501 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::TART: Trapping all Runtime threads.\n");
5502
5503 // There's no way that we should be stopped and still trying to call this function.
5504 _ASSERTE(!m_stopped);
5505
5506 // Mark that we're trapping now.
5507 m_trappingRuntimeThreads = TRUE;
5508
5509 // Take the thread store lock.
5510 assert(ThreadStore::HoldingThreadStore());
5511
5512 // We start the suspension here, and let the helper thread finish it.
5513 // If there's no helper thread, then we need to do helper duty.
5514 {
5515 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
5516 fSuspended = g_pEEInterface->StartSuspendForDebug(NULL, TRUE);
5517 }
5518
5519 // We tell the RC Thread to check for other threads now and then and help them get synchronized. (This
5520 // is similar to what is done when suspending threads for GC with the HandledJITCase() function.)
5521
5522 // This does not block.
5523 // Pinging this will waken the helper thread (or temp H. thread) and tell it to sweep & send
5524 // the sync complete.
5525 m_pRCThread->WatchForStragglers();
5526
5527 // It's possible we may not have a real helper thread.
5528 // - on startup in dllmain, helper is blocked on DllMain loader lock.
5529 // - on shutdown, helper has been removed on us.
5530 // In those cases, we need somebody to send the sync-complete, and handle
5531 // managed events, and wait for the continue. So we pretend to be the helper thread.
5532 STRESS_LOG0(LF_CORDB, LL_EVERYTHING, "D::SSCIPCE: Calling IsRCThreadReady()\n");
5533
5534 // We must check the helper thread status while under the lock.
5535 _ASSERTE(ThreadHoldsLock());
5536 // If we failed to suspend, then that means we must have multiple managed threads.
5537 // That means that our helper is not blocked on starting up, thus we can wait infinite on it.
5538 // Thus we don't need to do helper duty if the suspend fails.
5539 bool fShouldDoHelperDuty = !m_pRCThread->IsRCThreadReady() && fSuspended;
5540 if (fShouldDoHelperDuty && !g_fProcessDetach)
5541 {
5542 // In V1.0, we had the assumption that if the helper thread isn't ready yet, then we're in
5543 // a state that SuspendForDebug will succeed on the first try, and thus we'll
5544 // never call Sweep when doing helper thread duty.
5545 _ASSERTE(fSuspended);
5546
5547 // This call will do a ton of work, it will toggle the lock,
5548 // and it will block until we receive a continue!
5549 DoHelperThreadDuty();
5550
5551 // We will have released the TSL after the call to continue.
5552 }
5553 _ASSERTE(ThreadHoldsLock()); // still hold the lock. (though it may have been toggled)
5554 }
5555}
5556
5557
5558//
5559// ReleaseAllRuntimeThreads releases all Runtime threads that may be
5560// stopped after trapping and sending the at safe point event.
5561//
5562void Debugger::ReleaseAllRuntimeThreads(AppDomain *pAppDomain)
5563{
5564 CONTRACTL
5565 {
5566 SO_NOT_MAINLINE;
5567 NOTHROW;
5568 GC_NOTRIGGER;
5569
5570 // We acquired the lock b/c we're in a scope between LFES & UFES.
5571 PRECONDITION(ThreadHoldsLock());
5572
5573 // Currently, this is only done on a helper thread.
5574 PRECONDITION(ThisIsHelperThreadWorker());
5575
5576 // Make sure that we were stopped...
5577 PRECONDITION(m_trappingRuntimeThreads && m_stopped);
5578 }
5579 CONTRACTL_END;
5580
5581 //<TODO>@todo APPD if we want true isolation, remove this & finish the work</TODO>
5582 pAppDomain = NULL;
5583
5584 STRESS_LOG1(LF_CORDB, LL_INFO10000, "D::RART: Releasing all Runtime threads"
5585 "for AppD 0x%x.\n", pAppDomain);
5586
5587 // Mark that we're on our way now...
5588 m_trappingRuntimeThreads = FALSE;
5589 m_stopped = FALSE;
5590
5591 // Go ahead and resume the Runtime threads.
5592 g_pEEInterface->ResumeFromDebug(pAppDomain);
5593}
5594
5595// Given a method, get's its EnC version number. 1 if the method is not EnCed.
5596// Note that MethodDescs are reused between versions so this will give us
5597// the most recent EnC number.
5598int Debugger::GetMethodEncNumber(MethodDesc * pMethod)
5599{
5600 CONTRACTL
5601 {
5602 SO_NOT_MAINLINE;
5603 THROWS;
5604 GC_NOTRIGGER;
5605 }
5606 CONTRACTL_END;
5607
5608 DebuggerJitInfo * dji = GetLatestJitInfoFromMethodDesc(pMethod);
5609 if (dji == NULL)
5610 {
5611 // If there's no DJI, couldn't have been EnCed.
5612 return 1;
5613 }
5614 return (int) dji->m_encVersion;
5615}
5616
5617
5618bool Debugger::IsJMCMethod(Module* pModule, mdMethodDef tkMethod)
5619{
5620 CONTRACTL
5621 {
5622 SO_NOT_MAINLINE;
5623 THROWS;
5624 GC_NOTRIGGER;
5625 MODE_ANY;
5626 PRECONDITION(CORDebuggerAttached());
5627 }
5628 CONTRACTL_END;
5629
5630#ifdef _DEBUG
5631 Crst crstDbg(CrstIsJMCMethod, CRST_UNSAFE_ANYMODE);
5632 PRECONDITION(crstDbg.IsSafeToTake());
5633#endif
5634
5635 DebuggerMethodInfo *pInfo = GetOrCreateMethodInfo(pModule, tkMethod);
5636
5637 if (pInfo == NULL)
5638 return false;
5639
5640 return pInfo->IsJMCFunction();
5641}
5642
5643/******************************************************************************
5644 * Called by Runtime when on a 1st chance Native Exception.
5645 * This is likely when we hit a breakpoint / single-step.
5646 * This is called for all native exceptions (except COM+) on managed threads,
5647 * regardless of whether the debugger is attached.
5648 ******************************************************************************/
5649bool Debugger::FirstChanceNativeException(EXCEPTION_RECORD *exception,
5650 CONTEXT *context,
5651 DWORD code,
5652 Thread *thread)
5653{
5654
5655 // @@@
5656 // Implement DebugInterface
5657 // Can be called from EE exception code. Or from our M2UHandoffHijackFilter
5658 // must be on managed thread.
5659
5660 CONTRACTL
5661 {
5662 SO_TOLERANT;
5663 NOTHROW;
5664
5665 // No clear GC_triggers semantics here. See DispatchNativeException.
5666 WRAPPER(GC_TRIGGERS);
5667 MODE_ANY;
5668
5669 PRECONDITION(CheckPointer(exception));
5670 PRECONDITION(CheckPointer(context));
5671 PRECONDITION(CheckPointer(thread));
5672 }
5673 CONTRACTL_END;
5674
5675
5676 // Ignore any notification exceptions sent from code:Debugger.SendRawEvent.
5677 // This is not a common case, but could happen in some cases described
5678 // in SendRawEvent. Either way, Left-Side and VM should just ignore these.
5679 if (IsEventDebuggerNotification(exception, PTR_TO_CORDB_ADDRESS(g_pMSCorEE)))
5680 {
5681 return true;
5682 }
5683
5684 bool retVal;
5685
5686 // Don't stop for native debugging anywhere inside our inproc-Filters.
5687 CantStopHolder hHolder;
5688
5689 if (!CORDBUnrecoverableError(this))
5690 {
5691 retVal = DebuggerController::DispatchNativeException(exception, context,
5692 code, thread);
5693 }
5694 else
5695 {
5696 retVal = false;
5697 }
5698
5699 return retVal;
5700}
5701
5702/******************************************************************************
5703 *
5704 ******************************************************************************/
5705PRD_TYPE Debugger::GetPatchedOpcode(CORDB_ADDRESS_TYPE *ip)
5706{
5707 WRAPPER_NO_CONTRACT;
5708
5709 if (!CORDBUnrecoverableError(this))
5710 {
5711 return DebuggerController::GetPatchedOpcode(ip);
5712 }
5713 else
5714 {
5715 PRD_TYPE mt;
5716 InitializePRD(&mt);
5717 return mt;
5718 }
5719}
5720
5721/******************************************************************************
5722 *
5723 ******************************************************************************/
5724BOOL Debugger::CheckGetPatchedOpcode(CORDB_ADDRESS_TYPE *address, /*OUT*/ PRD_TYPE *pOpcode)
5725{
5726 WRAPPER_NO_CONTRACT;
5727 CONSISTENCY_CHECK(CheckPointer(address));
5728 CONSISTENCY_CHECK(CheckPointer(pOpcode));
5729
5730 if (CORDebuggerAttached() && !CORDBUnrecoverableError(this))
5731 {
5732 return DebuggerController::CheckGetPatchedOpcode(address, pOpcode);
5733 }
5734 else
5735 {
5736 InitializePRD(pOpcode);
5737 return FALSE;
5738 }
5739}
5740
5741/******************************************************************************
5742 *
5743 ******************************************************************************/
5744void Debugger::TraceCall(const BYTE *code)
5745{
5746 CONTRACTL
5747 {
5748 // We're being called right before we call managed code. Can't trigger
5749 // because there may be unprotected args on the stack.
5750 MODE_COOPERATIVE;
5751 GC_NOTRIGGER;
5752
5753 NOTHROW;
5754 }
5755 CONTRACTL_END;
5756
5757
5758 Thread * pCurThread = g_pEEInterface->GetThread();
5759 // Ensure we never even think about running managed code on the helper thread.
5760 _ASSERTE(!ThisIsHelperThreadWorker() || !"You're running managed code on the helper thread");
5761
5762 // One threat is that our helper thread may be forced to execute a managed DLL main.
5763 // In that case, it's before the helper thread proc is even executed, so our conventional
5764 // IsHelperThread() checks are inadequate.
5765 _ASSERTE((GetCurrentThreadId() != g_pRCThread->m_DbgHelperThreadOSTid) || !"You're running managed code on the helper thread");
5766
5767 _ASSERTE((g_pEEInterface->GetThreadFilterContext(pCurThread) == NULL) || !"Shouldn't run managed code w/ Filter-Context set");
5768
5769 if (!CORDBUnrecoverableError(this))
5770 {
5771 // There are situations where our callers can't tolerate us throwing.
5772 EX_TRY
5773 {
5774 // Since we have a try catch and the debugger code can deal properly with
5775 // faults occuring inside DebuggerController::DispatchTraceCall, we can safely
5776 // establish a FAULT_NOT_FATAL region. This is required since some callers can't
5777 // tolerate faults.
5778 FAULT_NOT_FATAL();
5779
5780 DebuggerController::DispatchTraceCall(pCurThread, code);
5781 }
5782 EX_CATCH
5783 {
5784 // We're being called for our benefit, not our callers. So if we fail,
5785 // they don't care.
5786 // Failure for us means that some steppers may miss their notification
5787 // for entering managed code.
5788 LOG((LF_CORDB, LL_INFO10000, "Debugger::TraceCall - inside catch, %p\n", code));
5789 }
5790 EX_END_CATCH(SwallowAllExceptions);
5791 }
5792}
5793
5794/******************************************************************************
5795 * For Just-My-Code (aka Just-User-Code).
5796 * Invoked from a probe in managed code when we enter a user method and
5797 * the flag (set by GetJMCFlagAddr) for that method is != 0.
5798 * pIP - the ip within the method, right after the prolog.
5799 * sp - stack pointer (frame pointer on x86) for the managed method we're entering.
5800 * bsp - backing store pointer for the managed method we're entering
5801 ******************************************************************************/
5802void Debugger::OnMethodEnter(void * pIP)
5803{
5804 CONTRACTL
5805 {
5806 THROWS;
5807 GC_NOTRIGGER;
5808 SO_NOT_MAINLINE;
5809 }
5810 CONTRACTL_END;
5811
5812 LOG((LF_CORDB, LL_INFO1000000, "D::OnMethodEnter(ip=%p)\n", pIP));
5813
5814 if (!CORDebuggerAttached())
5815 {
5816 LOG((LF_CORDB, LL_INFO1000000, "D::OnMethodEnter returning since debugger attached.\n"));
5817 return;
5818 }
5819 FramePointer fp = LEAF_MOST_FRAME;
5820 DebuggerController::DispatchMethodEnter(pIP, fp);
5821}
5822/******************************************************************************
5823 * GetJMCFlagAddr
5824 * Provide an address of the flag that the JMC probes use to decide whether
5825 * or not to call TriggerMethodEnter.
5826 * Called for each method that we jit.
5827 * md - method desc for the JMC probe
5828 * returns an address of a flag that the probe can use.
5829 ******************************************************************************/
5830DWORD* Debugger::GetJMCFlagAddr(Module * pModule)
5831{
5832 CONTRACTL
5833 {
5834 NOTHROW;
5835 GC_NOTRIGGER;
5836 SO_TOLERANT;
5837 PRECONDITION(CheckPointer(pModule));
5838 }
5839 CONTRACTL_END;
5840
5841 // This callback will be invoked whenever we jit debuggable code.
5842 // A debugger may not be attached yet, but we still need someplace
5843 // to store this dword.
5844 // Use the EE's module, because it's always around, even if a debugger
5845 // is attached or not.
5846 return &(pModule->m_dwDebuggerJMCProbeCount);
5847}
5848
5849/******************************************************************************
5850 * Updates the JMC flag on all the EE modules.
5851 * We can do this as often as we'd like - though it's a perf hit.
5852 ******************************************************************************/
5853void Debugger::UpdateAllModuleJMCFlag(bool fStatus)
5854{
5855 CONTRACTL
5856 {
5857 NOTHROW;
5858 GC_NOTRIGGER;
5859 }
5860 CONTRACTL_END;
5861
5862 LOG((LF_CORDB, LL_INFO1000000, "D::UpdateModuleJMCFlag to %d\n", fStatus));
5863
5864 _ASSERTE(HasDebuggerDataLock());
5865
5866 // Loop through each module.
5867 // The module table is lazily allocated. As soon as we set JMC status on any module, that will cause an
5868 // allocation of the module table. So if the table isn't allocated no module has JMC set,
5869 // and so there is nothing to update.
5870 if (m_pModules != NULL)
5871 {
5872 HASHFIND f;
5873 for (DebuggerModule * m = m_pModules->GetFirstModule(&f);
5874 m != NULL;
5875 m = m_pModules->GetNextModule(&f))
5876 {
5877 // the primary module may get called multiple times, but that's ok.
5878 UpdateModuleJMCFlag(m->GetRuntimeModule(), fStatus);
5879 } // end for all modules.
5880 }
5881}
5882
5883/******************************************************************************
5884 * Updates the JMC flag on the given Primary module
5885 * We can do this as often as we'd like - though it's a perf hit.
5886 * If we've only changed methods in a single module, then we can just call this.
5887 * If we do a more global thing (Such as enable MethodEnter), then that could
5888 * affect all modules, so we use the UpdateAllModuleJMCFlag helper.
5889 ******************************************************************************/
5890void Debugger::UpdateModuleJMCFlag(Module * pRuntimeModule, bool fStatus)
5891{
5892 CONTRACTL
5893 {
5894 NOTHROW;
5895 GC_NOTRIGGER;
5896 }
5897 CONTRACTL_END;
5898
5899 _ASSERTE(HasDebuggerDataLock());
5900
5901
5902 DWORD * pFlag = &(pRuntimeModule->m_dwDebuggerJMCProbeCount);
5903 _ASSERTE(pFlag != NULL);
5904
5905 if (pRuntimeModule->HasAnyJMCFunctions())
5906 {
5907 // If this is a user-code module, then update the JMC flag
5908 // the probes look at so that we get MethodEnter callbacks.
5909 *pFlag = fStatus;
5910
5911 LOG((LF_CORDB, LL_EVERYTHING, "D::UpdateModuleJMCFlag, module %p is user code\n", pRuntimeModule));
5912 } else {
5913 LOG((LF_CORDB, LL_EVERYTHING, "D::UpdateModuleJMCFlag, module %p is not-user code\n", pRuntimeModule));
5914
5915 // if non-user code, flag should be 0 so that we don't waste
5916 // cycles in the callbacks.
5917 _ASSERTE(*pFlag == 0);
5918 }
5919}
5920
5921// This sets the JMC status for the entire module.
5922// fStatus - default status for whole module
5923void Debugger::SetModuleDefaultJMCStatus(Module * pRuntimeModule, bool fStatus)
5924{
5925 CONTRACTL
5926 {
5927 SO_NOT_MAINLINE;
5928 NOTHROW;
5929 GC_NOTRIGGER;
5930 PRECONDITION(ThisIsHelperThreadWorker());
5931 }
5932 CONTRACTL_END;
5933
5934 LOG((LF_CORDB, LL_INFO100000, "DM::SetJMCStatus, status=%d, this=%p\n", fStatus, this));
5935
5936 // Ensure that all active DMIs have our status.
5937 // All new DMIs can lookup their status from us.
5938 // This should also update the module count of active JMC DMI's.
5939 DebuggerMethodInfoTable * pTable = g_pDebugger->GetMethodInfoTable();
5940
5941 if (pTable != NULL)
5942 {
5943 Debugger::DebuggerDataLockHolder debuggerDataLockHolder(g_pDebugger);
5944 HASHFIND info;
5945
5946 for (DebuggerMethodInfo *dmi = pTable->GetFirstMethodInfo(&info);
5947 dmi != NULL;
5948 dmi = pTable->GetNextMethodInfo(&info))
5949 {
5950 if (dmi->GetRuntimeModule() == pRuntimeModule)
5951 {
5952 // This DMI is in this module, so update its status
5953 dmi->SetJMCStatus(fStatus);
5954 }
5955 }
5956 }
5957
5958 pRuntimeModule->SetJMCStatus(fStatus);
5959
5960#ifdef _DEBUG
5961 // If we're disabling JMC in this module, then we shouldn't
5962 // have any active JMC functions.
5963 if (!fStatus)
5964 {
5965 _ASSERTE(!pRuntimeModule->HasAnyJMCFunctions());
5966 }
5967#endif
5968}
5969
5970/******************************************************************************
5971 * Called by GC to determine if it's safe to do a GC.
5972 ******************************************************************************/
5973bool Debugger::ThreadsAtUnsafePlaces(void)
5974{
5975 LIMITED_METHOD_CONTRACT;
5976
5977 // If we're in shutdown mode, then all other threads are parked.
5978 // Even if they claim to be at unsafe regions, they're still safe to do a GC. They won't touch
5979 // their stacks.
5980 if (m_fShutdownMode)
5981 {
5982 if (m_threadsAtUnsafePlaces > 0)
5983 {
5984 STRESS_LOG1(LF_CORDB, LL_INFO10000, "D::TAUP: Claiming safety in shutdown mode.%d\n", m_threadsAtUnsafePlaces);
5985 }
5986 return false;
5987 }
5988
5989
5990 return (m_threadsAtUnsafePlaces != 0);
5991}
5992
5993void Debugger::SuspendForGarbageCollectionStarted()
5994{
5995 CONTRACTL
5996 {
5997 NOTHROW;
5998 GC_NOTRIGGER;
5999 }
6000 CONTRACTL_END;
6001
6002 this->m_isGarbageCollectionEventsEnabledLatch = this->m_isGarbageCollectionEventsEnabled;
6003 this->m_willBlockOnGarbageCollectionEvent = this->m_isGarbageCollectionEventsEnabledLatch;
6004}
6005
6006void Debugger::SuspendForGarbageCollectionCompleted()
6007{
6008 CONTRACTL
6009 {
6010 NOTHROW;
6011 GC_NOTRIGGER;
6012 }
6013 CONTRACTL_END;
6014
6015 if (!CORDebuggerAttached() || !this->m_isGarbageCollectionEventsEnabledLatch)
6016 {
6017 return;
6018 }
6019 this->m_isBlockedOnGarbageCollectionEvent = TRUE;
6020
6021 Thread* pThread = GetThread();
6022
6023 if (CORDBUnrecoverableError(this))
6024 return;
6025
6026 {
6027 Debugger::DebuggerLockHolder dbgLockHolder(this);
6028
6029 DebuggerIPCEvent* ipce1 = m_pRCThread->GetIPCEventSendBuffer();
6030 InitIPCEvent(ipce1,
6031 DB_IPCE_BEFORE_GARBAGE_COLLECTION,
6032 pThread,
6033 pThread->GetDomain());
6034
6035 m_pRCThread->SendIPCEvent();
6036 this->SuspendComplete(true);
6037 }
6038
6039 WaitForSingleObject(this->GetGarbageCollectionBlockerEvent(), INFINITE);
6040 ResetEvent(this->GetGarbageCollectionBlockerEvent());
6041}
6042
6043void Debugger::ResumeForGarbageCollectionStarted()
6044{
6045 CONTRACTL
6046 {
6047 NOTHROW;
6048 GC_NOTRIGGER;
6049 }
6050 CONTRACTL_END;
6051
6052 if (!CORDebuggerAttached() || !this->m_isGarbageCollectionEventsEnabledLatch)
6053 {
6054 return;
6055 }
6056
6057 Thread* pThread = GetThread();
6058
6059 if (CORDBUnrecoverableError(this))
6060 return;
6061
6062 {
6063 Debugger::DebuggerLockHolder dbgLockHolder(this);
6064
6065 DebuggerIPCEvent* ipce1 = m_pRCThread->GetIPCEventSendBuffer();
6066 InitIPCEvent(ipce1,
6067 DB_IPCE_AFTER_GARBAGE_COLLECTION,
6068 pThread,
6069 pThread->GetDomain());
6070
6071 m_pRCThread->SendIPCEvent();
6072 this->SuspendComplete(true);
6073 }
6074
6075 WaitForSingleObject(this->GetGarbageCollectionBlockerEvent(), INFINITE);
6076 ResetEvent(this->GetGarbageCollectionBlockerEvent());
6077 this->m_isBlockedOnGarbageCollectionEvent = FALSE;
6078 this->m_willBlockOnGarbageCollectionEvent = FALSE;
6079}
6080
6081#ifdef FEATURE_DATABREAKPOINT
6082void Debugger::SendDataBreakpoint(Thread *thread, CONTEXT *context,
6083 DebuggerDataBreakpoint *breakpoint)
6084{
6085 CONTRACTL
6086 {
6087 NOTHROW;
6088 GC_NOTRIGGER;
6089 }
6090 CONTRACTL_END;
6091
6092 if (CORDBUnrecoverableError(this))
6093 return;
6094
6095#ifdef _DEBUG
6096 static BOOL shouldBreak = -1;
6097 if (shouldBreak == -1)
6098 shouldBreak = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgBreakOnSendBreakpoint);
6099
6100 if (shouldBreak > 0) {
6101 _ASSERTE(!"DbgBreakOnSendBreakpoint");
6102 }
6103#endif
6104
6105 LOG((LF_CORDB, LL_INFO10000, "D::SDB: breakpoint BP:0x%x\n", breakpoint));
6106
6107 _ASSERTE((g_pEEInterface->GetThread() &&
6108 !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) ||
6109 g_fInControlC);
6110
6111 _ASSERTE(ThreadHoldsLock());
6112
6113 // Send a breakpoint event to the Right Side
6114 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6115 memcpy(&(ipce->DataBreakpointData.context), context, sizeof(CONTEXT));
6116 InitIPCEvent(ipce,
6117 DB_IPCE_DATA_BREAKPOINT,
6118 thread,
6119 thread->GetDomain());
6120 //_ASSERTE(breakpoint->m_pAppDomain == ipce->vmAppDomain.GetRawPtr());
6121
6122 m_pRCThread->SendIPCEvent();
6123}
6124#endif
6125
6126//
6127// SendBreakpoint is called by Runtime threads to send that they've
6128// hit a breakpoint to the Right Side.
6129//
6130void Debugger::SendBreakpoint(Thread *thread, CONTEXT *context,
6131 DebuggerBreakpoint *breakpoint)
6132{
6133 CONTRACTL
6134 {
6135 NOTHROW;
6136 GC_NOTRIGGER;
6137 }
6138 CONTRACTL_END;
6139
6140 if (CORDBUnrecoverableError(this))
6141 return;
6142
6143#ifdef _DEBUG
6144 static BOOL shouldBreak = -1;
6145 if (shouldBreak == -1)
6146 shouldBreak = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgBreakOnSendBreakpoint);
6147
6148 if (shouldBreak > 0) {
6149 _ASSERTE(!"DbgBreakOnSendBreakpoint");
6150 }
6151#endif
6152
6153 LOG((LF_CORDB, LL_INFO10000, "D::SB: breakpoint BP:0x%x\n", breakpoint));
6154
6155 _ASSERTE((g_pEEInterface->GetThread() &&
6156 !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) ||
6157 g_fInControlC);
6158
6159 _ASSERTE(ThreadHoldsLock());
6160
6161 // Send a breakpoint event to the Right Side
6162 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6163 InitIPCEvent(ipce,
6164 DB_IPCE_BREAKPOINT,
6165 thread,
6166 thread->GetDomain());
6167 ipce->BreakpointData.breakpointToken.Set(breakpoint);
6168 _ASSERTE( breakpoint->m_pAppDomain == ipce->vmAppDomain.GetRawPtr());
6169
6170 m_pRCThread->SendIPCEvent();
6171}
6172
6173
6174//---------------------------------------------------------------------------------------
6175// Send a user breakpoint event for this thread and sycnhronize the process.
6176//
6177// Arguments:
6178// pThread - non-null thread to send user breakpoint event for.
6179//
6180// Notes:
6181// Can't assume that a debugger is attached (since it may detach before we get the lock).
6182void Debugger::SendUserBreakpointAndSynchronize(Thread * pThread)
6183{
6184 AtSafePlaceHolder unsafePlaceHolder(pThread);
6185
6186 SENDIPCEVENT_BEGIN(this, pThread);
6187
6188 // Actually send the event
6189 if (CORDebuggerAttached())
6190 {
6191 SendRawUserBreakpoint(pThread);
6192 TrapAllRuntimeThreads();
6193 }
6194
6195 SENDIPCEVENT_END;
6196}
6197
6198//---------------------------------------------------------------------------------------
6199//
6200// SendRawUserBreakpoint is called by Runtime threads to send that
6201// they've hit a user breakpoint to the Right Side. This is the event
6202// send only part, since it can be called from a few different places.
6203//
6204// Arguments:
6205// pThread - [in] managed thread where user break point takes place.
6206// mus be curernt thread.
6207//
6208void Debugger::SendRawUserBreakpoint(Thread * pThread)
6209{
6210 CONTRACTL
6211 {
6212 NOTHROW;
6213 GC_NOTRIGGER;
6214 MODE_PREEMPTIVE;
6215
6216 PRECONDITION(pThread == GetThread());
6217
6218 PRECONDITION(ThreadHoldsLock());
6219
6220 // Debugger must have been attached to get us to this point.
6221 // We hold the Debugger-lock, so debugger could not have detached from
6222 // underneath us either.
6223 PRECONDITION(CORDebuggerAttached());
6224 }
6225 CONTRACTL_END;
6226
6227 if (CORDBUnrecoverableError(this))
6228 return;
6229
6230 LOG((LF_CORDB, LL_INFO10000, "D::SRUB: user breakpoint\n"));
6231
6232
6233
6234 // Send a breakpoint event to the Right Side
6235 DebuggerIPCEvent* pEvent = m_pRCThread->GetIPCEventSendBuffer();
6236 InitIPCEvent(pEvent,
6237 DB_IPCE_USER_BREAKPOINT,
6238 pThread,
6239 pThread->GetDomain());
6240
6241 m_pRCThread->SendIPCEvent();
6242}
6243
6244//
6245// SendInterceptExceptionComplete is called by Runtime threads to send that
6246// they've completed intercepting an exception to the Right Side. This is the event
6247// send only part, since it can be called from a few different places.
6248//
6249void Debugger::SendInterceptExceptionComplete(Thread *thread)
6250{
6251 CONTRACTL
6252 {
6253 NOTHROW;
6254 GC_NOTRIGGER;
6255 }
6256 CONTRACTL_END;
6257
6258 if (CORDBUnrecoverableError(this))
6259 return;
6260
6261 LOG((LF_CORDB, LL_INFO10000, "D::SIEC: breakpoint\n"));
6262
6263 _ASSERTE(!g_pEEInterface->IsPreemptiveGCDisabled());
6264 _ASSERTE(ThreadHoldsLock());
6265
6266 // Send a breakpoint event to the Right Side
6267 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6268 InitIPCEvent(ipce,
6269 DB_IPCE_INTERCEPT_EXCEPTION_COMPLETE,
6270 thread,
6271 thread->GetDomain());
6272
6273 m_pRCThread->SendIPCEvent();
6274}
6275
6276
6277
6278//
6279// SendStep is called by Runtime threads to send that they've
6280// completed a step to the Right Side.
6281//
6282void Debugger::SendStep(Thread *thread, CONTEXT *context,
6283 DebuggerStepper *stepper,
6284 CorDebugStepReason reason)
6285{
6286 CONTRACTL
6287 {
6288 NOTHROW;
6289 GC_NOTRIGGER;
6290 }
6291 CONTRACTL_END;
6292
6293 if (CORDBUnrecoverableError(this))
6294 return;
6295
6296 LOG((LF_CORDB, LL_INFO10000, "D::SS: step:token:0x%p reason:0x%x\n",
6297 stepper, reason));
6298
6299 _ASSERTE((g_pEEInterface->GetThread() &&
6300 !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) ||
6301 g_fInControlC);
6302
6303 _ASSERTE(ThreadHoldsLock());
6304
6305 // Send a step event to the Right Side
6306 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6307 InitIPCEvent(ipce,
6308 DB_IPCE_STEP_COMPLETE,
6309 thread,
6310 thread->GetDomain());
6311 ipce->StepData.stepperToken.Set(stepper);
6312 ipce->StepData.reason = reason;
6313 m_pRCThread->SendIPCEvent();
6314}
6315
6316//-------------------------------------------------------------------------------------------------
6317// Send an EnC remap opportunity and block until it is continued.
6318//
6319// dji - current method information
6320// currentIP - IL offset within that method
6321// resumeIP - address of a SIZE_T that the RS will write to cross-process if they take the
6322// remap opportunity. *resumeIP is untouched if the RS does not remap.
6323//-------------------------------------------------------------------------------------------------
6324void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, SIZE_T *resumeIP)
6325{
6326 CONTRACTL
6327 {
6328 NOTHROW;
6329 GC_TRIGGERS; // From SendIPCEvent
6330 PRECONDITION(dji != NULL);
6331 }
6332 CONTRACTL_END;
6333
6334
6335 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE:\n"));
6336
6337 if (CORDBUnrecoverableError(this))
6338 return;
6339
6340 MethodDesc * pFD = dji->m_fd;
6341
6342 // Note that the debugger lock is reentrant, so we may or may not hold it already.
6343 Thread *thread = g_pEEInterface->GetThread();
6344 SENDIPCEVENT_BEGIN(this, thread);
6345
6346 // Send an EnC remap event to the Right Side.
6347 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6348 InitIPCEvent(ipce,
6349 DB_IPCE_ENC_REMAP,
6350 thread,
6351 thread->GetDomain());
6352
6353 ipce->EnCRemap.currentVersionNumber = dji->m_encVersion;
6354 ipce->EnCRemap.resumeVersionNumber = dji->m_methodInfo->GetCurrentEnCVersion();;
6355 ipce->EnCRemap.currentILOffset = currentIP;
6356 ipce->EnCRemap.resumeILOffset = resumeIP;
6357 ipce->EnCRemap.funcMetadataToken = pFD->GetMemberDef();
6358
6359 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: token 0x%x, from version %d to %d\n",
6360 ipce->EnCRemap.funcMetadataToken, ipce->EnCRemap.currentVersionNumber, ipce->EnCRemap.resumeVersionNumber));
6361
6362 Module *pRuntimeModule = pFD->GetModule();
6363
6364 DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain());
6365 ipce->EnCRemap.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL));
6366
6367 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: %s::%s "
6368 "dmod:0x%x, methodDef:0x%x \n",
6369 pFD->m_pszDebugClassName, pFD->m_pszDebugMethodName,
6370 pDModule,
6371 ipce->EnCRemap.funcMetadataToken));
6372
6373 // IPC event is now initialized, so we can send it over.
6374 SendSimpleIPCEventAndBlock();
6375
6376 // This will block on the continue
6377 SENDIPCEVENT_END;
6378
6379 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: done\n"));
6380
6381}
6382
6383// Send the RemapComplete event and block until the debugger Continues
6384// pFD - specifies the method in which we've remapped into
6385void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pFD)
6386{
6387 CONTRACTL
6388 {
6389 NOTHROW;
6390 GC_TRIGGERS;
6391 }
6392 CONTRACTL_END;
6393
6394 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE:\n"));
6395
6396 if (CORDBUnrecoverableError(this))
6397 return;
6398
6399 Thread *thread = g_pEEInterface->GetThread();
6400 // Note that the debugger lock is reentrant, so we may or may not hold it already.
6401 SENDIPCEVENT_BEGIN(this, thread);
6402
6403 EX_TRY
6404 {
6405 // Ensure the DJI for the latest version of this method has been pre-created.
6406 // It's not clear whether this is necessary or not, but it shouldn't hurt since
6407 // we're going to need to create it anyway since we'll be debugging inside it.
6408 DebuggerJitInfo *dji = g_pDebugger->GetLatestJitInfoFromMethodDesc(pFD);
6409 (void)dji; //prevent "unused variable" error from GCC
6410 _ASSERTE( dji != NULL );
6411 }
6412 EX_CATCH
6413 {
6414 // GetLatestJitInfo could throw on OOM, but the debugger isn't resiliant to OOM.
6415 // I'm not aware of any other legitimate reason why it may throw, so we'll ASSERT
6416 // if it fails.
6417 _ASSERTE(!"Unexpected exception from Debugger::GetLatestJitInfoFromMethodDesc on EnC remap complete");
6418 }
6419 EX_END_CATCH(RethrowTerminalExceptions);
6420
6421 // Send an EnC remap complete event to the Right Side.
6422 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6423 InitIPCEvent(ipce,
6424 DB_IPCE_ENC_REMAP_COMPLETE,
6425 thread,
6426 thread->GetDomain());
6427
6428
6429 ipce->EnCRemapComplete.funcMetadataToken = pFD->GetMemberDef();
6430
6431 Module *pRuntimeModule = pFD->GetModule();
6432
6433 DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain());
6434 ipce->EnCRemapComplete.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL));
6435
6436
6437 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRC: %s::%s "
6438 "dmod:0x%x, methodDef:0x%x \n",
6439 pFD->m_pszDebugClassName, pFD->m_pszDebugMethodName,
6440 pDModule,
6441 ipce->EnCRemap.funcMetadataToken));
6442
6443 // IPC event is now initialized, so we can send it over.
6444 SendSimpleIPCEventAndBlock();
6445
6446 // This will block on the continue
6447 SENDIPCEVENT_END;
6448
6449 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRC: done\n"));
6450
6451}
6452//
6453// This function sends a notification to the RS about a specific update that has occurred as part of
6454// applying an Edit and Continue. We send notification only for function add/update and field add.
6455// At this point, the EE is already stopped for handling an EnC ApplyChanges operation, so no need
6456// to take locks etc.
6457//
6458void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType,
6459 Module * pModule,
6460 mdToken memberToken,
6461 mdTypeDef classToken,
6462 SIZE_T enCVersion)
6463{
6464 CONTRACTL
6465 {
6466 NOTHROW;
6467 GC_NOTRIGGER;
6468 }
6469 CONTRACTL_END;
6470
6471 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCUFE:\n"));
6472
6473 _ASSERTE(eventType == DB_IPCE_ENC_UPDATE_FUNCTION ||
6474 eventType == DB_IPCE_ENC_ADD_FUNCTION ||
6475 eventType== DB_IPCE_ENC_ADD_FIELD);
6476
6477 if (CORDBUnrecoverableError(this))
6478 return;
6479
6480 // Send an EnC UpdateFunction event to the Right Side.
6481 DebuggerIPCEvent* event = m_pRCThread->GetIPCEventSendBuffer();
6482 InitIPCEvent(event,
6483 eventType,
6484 NULL,
6485 NULL);
6486
6487 event->EnCUpdate.newVersionNumber = enCVersion;
6488 event->EnCUpdate.memberMetadataToken = memberToken;
6489 // we have to pass the class token across to the RS because we cannot look it up over
6490 // there based on the added field/method because the metadata on the RS will not yet
6491 // have the changes applied, so the token will not exist in its metadata and we have
6492 // no way to find it.
6493 event->EnCUpdate.classMetadataToken = classToken;
6494
6495 _ASSERTE(pModule);
6496 // we don't support shared assemblies, so must have an appdomain
6497 _ASSERTE(pModule->GetDomain()->IsAppDomain());
6498
6499 DebuggerModule * pDModule = LookupOrCreateModule(pModule, pModule->GetDomain()->AsAppDomain());
6500 event->EnCUpdate.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL));
6501
6502 m_pRCThread->SendIPCEvent();
6503
6504 LOG((LF_CORDB, LL_INFO10000, "D::LASEnCUE: done\n"));
6505
6506}
6507
6508
6509//
6510// Send a BreakpointSetError event to the Right Side if the given patch is for a breakpoint. Note: we don't care if this
6511// fails, there is nothing we can do about it anyway, and the breakpoint just wont hit.
6512//
6513void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbindablePatches)
6514{
6515 CONTRACTL
6516 {
6517 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
6518 GC_TRIGGERS;
6519 }
6520 CONTRACTL_END;
6521
6522 _ASSERTE(listUnbindablePatches != NULL);
6523
6524 if (CORDBUnrecoverableError(this))
6525 return;
6526
6527
6528 ULONG count = listUnbindablePatches->Count();
6529 _ASSERTE(count > 0); // must send at least 1 event.
6530
6531
6532 Thread *thread = g_pEEInterface->GetThread();
6533 // Note that the debugger lock is reentrant, so we may or may not hold it already.
6534 SENDIPCEVENT_BEGIN(this, thread);
6535
6536 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
6537
6538 for(ULONG i = 0; i < count; i++)
6539 {
6540 DebuggerControllerPatch *patch = listUnbindablePatches->Table()[i];
6541 _ASSERTE(patch != NULL);
6542
6543 // Only do this for breakpoint controllers
6544 DebuggerController *controller = patch->controller;
6545
6546 if (controller->GetDCType() != DEBUGGER_CONTROLLER_BREAKPOINT)
6547 {
6548 continue;
6549 }
6550
6551 LOG((LF_CORDB, LL_INFO10000, "D::LASBSE:\n"));
6552
6553 // Send a breakpoint set error event to the Right Side.
6554 InitIPCEvent(ipce, DB_IPCE_BREAKPOINT_SET_ERROR, thread, thread->GetDomain());
6555
6556 ipce->BreakpointSetErrorData.breakpointToken.Set(static_cast<DebuggerBreakpoint*> (controller));
6557
6558 // IPC event is now initialized, so we can send it over.
6559 m_pRCThread->SendIPCEvent();
6560 }
6561
6562 // Stop all Runtime threads
6563 TrapAllRuntimeThreads();
6564
6565 // This will block on the continue
6566 SENDIPCEVENT_END;
6567
6568}
6569
6570//
6571// Called from the controller to lock the debugger for event
6572// sending. This is called before controller events are sent, like
6573// breakpoint, step complete, and thread started.
6574//
6575// Note that it's possible that the debugger detached (and destroyed our IPC
6576// events) while we're waiting for our turn.
6577// So Callers should check for that case.
6578void Debugger::LockForEventSending(DebuggerLockHolder *dbgLockHolder)
6579{
6580 CONTRACTL
6581 {
6582 NOTHROW;
6583 GC_NOTRIGGER;
6584 MODE_PREEMPTIVE;
6585 }
6586 CONTRACTL_END;
6587
6588 // @todo - Force our parents to bump up the stop-count. That way they can
6589 // guarantee it's balanced.
6590 IncCantStopCount();
6591 _ASSERTE(IsInCantStopRegion());
6592
6593 // What we need is for caller to get the debugger lock
6594 if (dbgLockHolder != NULL)
6595 {
6596 dbgLockHolder->Acquire();
6597 }
6598
6599#ifdef _DEBUG
6600 // Track our TID. We're not re-entrant.
6601 //_ASSERTE(m_tidLockedForEventSending == 0);
6602 m_tidLockedForEventSending = GetCurrentThreadId();
6603#endif
6604
6605}
6606
6607//
6608// Called from the controller to unlock the debugger from event
6609// sending. This is called after controller events are sent, like
6610// breakpoint, step complete, and thread started.
6611//
6612void Debugger::UnlockFromEventSending(DebuggerLockHolder *dbgLockHolder)
6613{
6614 CONTRACTL
6615 {
6616 NOTHROW;
6617 GC_NOTRIGGER;
6618 MODE_PREEMPTIVE;
6619 }
6620 CONTRACTL_END;
6621
6622#ifdef _DEBUG
6623 //_ASSERTE(m_tidLockedForEventSending == GetCurrentThreadId());
6624 m_tidLockedForEventSending = 0;
6625#endif
6626 if (dbgLockHolder != NULL)
6627 {
6628 dbgLockHolder->Release();
6629 }
6630 // @todo - Force our parents to bump up the stop-count. That way they can
6631 // guarantee it's balanced.
6632 _ASSERTE(IsInCantStopRegion());
6633 DecCantStopCount();
6634}
6635
6636
6637//
6638// Called from the controller after all events have been sent for a
6639// thread to sync the process.
6640//
6641void Debugger::SyncAllThreads(DebuggerLockHolder *dbgLockHolder)
6642{
6643 CONTRACTL
6644 {
6645 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
6646 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
6647 }
6648 CONTRACTL_END;
6649
6650 if (CORDBUnrecoverableError(this))
6651 return;
6652
6653 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::SAT: sync all threads.\n");
6654
6655 Thread *pThread = g_pEEInterface->GetThread();
6656 (void)pThread; //prevent "unused variable" error from GCC
6657 _ASSERTE((pThread &&
6658 !pThread->m_fPreemptiveGCDisabled) ||
6659 g_fInControlC);
6660
6661 _ASSERTE(ThreadHoldsLock());
6662
6663 // Stop all Runtime threads
6664 TrapAllRuntimeThreads();
6665}
6666
6667//---------------------------------------------------------------------------------------
6668// Launch a debugger and then trigger a breakpoint (either managed or native)
6669//
6670// Arguments:
6671// useManagedBPForManagedAttach - TRUE if we should stop with a managed breakpoint
6672// when managed attached, FALSE if we should always
6673// stop with a native breakpoint
6674// pThread - the managed thread that attempts to launch the registered debugger
6675// pExceptionInfo - the unhandled exception info
6676// explicitUserRequest - TRUE if this attach is caused by a call to the Debugger.Launch() API.
6677//
6678// Returns:
6679// S_OK on success. Else failure.
6680//
6681// Notes:
6682// This function doesn't try to stop the launched native debugger by calling DebugBreak().
6683// It sends a breakpoint event only for managed debuggers.
6684//
6685HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo,
6686 BOOL useManagedBPForManagedAttach, BOOL explicitUserRequest)
6687{
6688 WRAPPER_NO_CONTRACT;
6689
6690 LOG((LF_CORDB, LL_INFO10000, "D::LDFU: Attaching Debugger.\n"));
6691
6692 //
6693 // Initiate a jit attach
6694 //
6695 JitAttach(pThread, pExceptionInfo, useManagedBPForManagedAttach, explicitUserRequest);
6696
6697 if (useManagedBPForManagedAttach)
6698 {
6699 if(CORDebuggerAttached() && (g_pEEInterface->GetThread() != NULL))
6700 {
6701 //
6702 // Send a managed-breakpoint.
6703 //
6704 SendUserBreakpointAndSynchronize(g_pEEInterface->GetThread());
6705 }
6706 else if (!CORDebuggerAttached() && IsDebuggerPresent())
6707 {
6708 //
6709 // If the registered debugger is not a managed debugger, send a native breakpoint
6710 //
6711 DebugBreak();
6712 }
6713 }
6714 else if(!useManagedBPForManagedAttach)
6715 {
6716 //
6717 // Send a native breakpoint
6718 //
6719 DebugBreak();
6720 }
6721
6722 if (!IsDebuggerPresent())
6723 {
6724 LOG((LF_CORDB, LL_ERROR, "D::LDFU: Failed to launch the debugger.\n"));
6725 }
6726
6727 return S_OK;
6728}
6729
6730
6731// The following JDI structures will be passed to a debugger on Vista. Because we do not know when the debugger
6732// will be done looking at them, and there is at most one debugger attaching to the process, we always set them
6733// once and leave them set without the risk of clobbering something we care about.
6734JIT_DEBUG_INFO Debugger::s_DebuggerLaunchJitInfo = {0};
6735EXCEPTION_RECORD Debugger::s_DebuggerLaunchJitInfoExceptionRecord = {0};
6736CONTEXT Debugger::s_DebuggerLaunchJitInfoContext = {0};
6737
6738//----------------------------------------------------------------------------
6739//
6740// InitDebuggerLaunchJitInfo - initialize JDI structure on Vista
6741//
6742// Arguments:
6743// pThread - the managed thread with the unhandled excpetion
6744// pExceptionInfo - unhandled exception info
6745//
6746// Return Value:
6747// None
6748//
6749//----------------------------------------------------------------------------
6750void Debugger::InitDebuggerLaunchJitInfo(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo)
6751{
6752 LIMITED_METHOD_CONTRACT;
6753
6754 _ASSERTE((pExceptionInfo != NULL) &&
6755 (pExceptionInfo->ContextRecord != NULL) &&
6756 (pExceptionInfo->ExceptionRecord != NULL));
6757
6758 if ((pExceptionInfo == NULL) || (pExceptionInfo->ContextRecord == NULL) || (pExceptionInfo->ExceptionRecord == NULL))
6759 {
6760 return;
6761 }
6762
6763 s_DebuggerLaunchJitInfoExceptionRecord = *pExceptionInfo->ExceptionRecord;
6764 s_DebuggerLaunchJitInfoContext = *pExceptionInfo->ContextRecord;
6765
6766 s_DebuggerLaunchJitInfo.dwSize = sizeof(s_DebuggerLaunchJitInfo);
6767 s_DebuggerLaunchJitInfo.dwThreadID = pThread == NULL ? GetCurrentThreadId() : pThread->GetOSThreadId();
6768 s_DebuggerLaunchJitInfo.lpExceptionRecord = reinterpret_cast<ULONG64>(&s_DebuggerLaunchJitInfoExceptionRecord);
6769 s_DebuggerLaunchJitInfo.lpContextRecord = reinterpret_cast<ULONG64>(&s_DebuggerLaunchJitInfoContext);
6770 s_DebuggerLaunchJitInfo.lpExceptionAddress = s_DebuggerLaunchJitInfoExceptionRecord.ExceptionAddress != NULL ?
6771 reinterpret_cast<ULONG64>(s_DebuggerLaunchJitInfoExceptionRecord.ExceptionAddress) :
6772 reinterpret_cast<ULONG64>(reinterpret_cast<PVOID>(GetIP(pExceptionInfo->ContextRecord)));
6773
6774#if defined(_TARGET_X86_)
6775 s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
6776#elif defined(_TARGET_AMD64_)
6777 s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
6778#elif defined(_TARGET_ARM_)
6779 s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM;
6780#elif defined(_TARGET_ARM64_)
6781 s_DebuggerLaunchJitInfo.dwProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64;
6782#else
6783#error Unknown processor.
6784#endif
6785}
6786
6787
6788//----------------------------------------------------------------------------
6789//
6790// GetDebuggerLaunchJitInfo - retrieve the initialized JDI structure on Vista
6791//
6792// Arguments:
6793// None
6794//
6795// Return Value:
6796// JIT_DEBUG_INFO * - pointer to JDI structure
6797//
6798//----------------------------------------------------------------------------
6799JIT_DEBUG_INFO * Debugger::GetDebuggerLaunchJitInfo(void)
6800{
6801 LIMITED_METHOD_CONTRACT;
6802
6803 _ASSERTE((s_DebuggerLaunchJitInfo.lpExceptionAddress != NULL) &&
6804 (s_DebuggerLaunchJitInfo.lpExceptionRecord != NULL) &&
6805 (s_DebuggerLaunchJitInfo.lpContextRecord != NULL) &&
6806 (((EXCEPTION_RECORD *)(s_DebuggerLaunchJitInfo.lpExceptionRecord))->ExceptionAddress != NULL));
6807
6808 return &s_DebuggerLaunchJitInfo;
6809}
6810#endif // !DACCESS_COMPILE
6811
6812
6813// This function checks the registry for the debug launch setting upon encountering an exception or breakpoint.
6814DebuggerLaunchSetting Debugger::GetDbgJITDebugLaunchSetting()
6815{
6816 CONTRACTL
6817 {
6818 NOTHROW;
6819 GC_NOTRIGGER;
6820 }
6821 CONTRACTL_END;
6822
6823#if FEATURE_PAL
6824 DebuggerLaunchSetting setting = DLS_ATTACH_DEBUGGER;
6825#else
6826 BOOL bAuto = FALSE;
6827
6828 DebuggerLaunchSetting setting = DLS_ASK_USER;
6829
6830 DWORD cchDbgFormat = MAX_LONGPATH;
6831 INDEBUG(DWORD cchOldDbgFormat = cchDbgFormat);
6832
6833#if defined(DACCESS_COMPILE)
6834 WCHAR * wszDbgFormat = new (nothrow) WCHAR[cchDbgFormat];
6835#else
6836 WCHAR * wszDbgFormat = new (interopsafe, nothrow) WCHAR[cchDbgFormat];
6837#endif // DACCESS_COMPILE
6838
6839 if (wszDbgFormat == NULL)
6840 {
6841 return setting;
6842 }
6843
6844 HRESULT hr = GetDebuggerSettingInfoWorker(wszDbgFormat, &cchDbgFormat, &bAuto);
6845 while (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
6846 {
6847 _ASSERTE(cchDbgFormat > cchOldDbgFormat);
6848 INDEBUG(cchOldDbgFormat = cchDbgFormat);
6849
6850#if defined(DACCESS_COMPILE)
6851 delete [] wszDbgFormat;
6852 wszDbgFormat = new (nothrow) WCHAR[cchDbgFormat];
6853#else
6854 DeleteInteropSafe(wszDbgFormat);
6855 wszDbgFormat = new (interopsafe, nothrow) WCHAR[cchDbgFormat];
6856#endif // DACCESS_COMPILE
6857
6858 if (wszDbgFormat == NULL)
6859 {
6860 return setting;
6861 }
6862
6863 hr = GetDebuggerSettingInfoWorker(wszDbgFormat, &cchDbgFormat, &bAuto);
6864 }
6865
6866#if defined(DACCESS_COMPILE)
6867 delete [] wszDbgFormat;
6868#else
6869 DeleteInteropSafe(wszDbgFormat);
6870#endif // DACCESS_COMPILE
6871
6872 if (SUCCEEDED(hr) && bAuto)
6873 {
6874 setting = DLS_ATTACH_DEBUGGER;
6875 }
6876#endif // FEATURE_PAL
6877
6878 return setting;
6879}
6880
6881// Returns a bitfield reflecting the managed debugging state at the time of
6882// the jit attach.
6883CLR_DEBUGGING_PROCESS_FLAGS Debugger::GetAttachStateFlags()
6884{
6885 LIMITED_METHOD_DAC_CONTRACT;
6886 ULONG flags = CLRJitAttachState;
6887 return (CLR_DEBUGGING_PROCESS_FLAGS)flags;
6888}
6889
6890#ifndef DACCESS_COMPILE
6891//-----------------------------------------------------------------------------
6892// Get the full launch string for a jit debugger.
6893//
6894// If a jit-debugger is registed, then writes string into pStrArgsBuf and
6895// return true.
6896//
6897// If no jit-debugger is registered, then return false.
6898//
6899// Throws on error (like OOM).
6900//-----------------------------------------------------------------------------
6901bool Debugger::GetCompleteDebuggerLaunchString(SString * pStrArgsBuf)
6902{
6903 CONTRACTL
6904 {
6905 THROWS;
6906 GC_NOTRIGGER;
6907 }
6908 CONTRACTL_END;
6909
6910#ifndef FEATURE_PAL
6911 DWORD pid = GetCurrentProcessId();
6912
6913 SString ssDebuggerString;
6914 GetDebuggerSettingInfo(ssDebuggerString, NULL);
6915
6916 if (ssDebuggerString.IsEmpty())
6917 {
6918 // No jit-debugger available. Don't make one up.
6919 return false;
6920 }
6921
6922 // There is no security concern to expect that the debug string we retrieve from HKLM follows a certain
6923 // format because changing HKLM keys requires admin priviledge. Padding with zeros is not a security mitigation,
6924 // but rather a forward looking compability measure. If future verions of Windows introduces more parameters for
6925 // JIT debugger launch, it is preferrable to pass zeros than other random values for those unsupported parameters.
6926 pStrArgsBuf->Printf(ssDebuggerString, pid, GetUnmanagedAttachEvent(), GetDebuggerLaunchJitInfo(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
6927
6928 return true;
6929#else // !FEATURE_PAL
6930 return false;
6931#endif // !FEATURE_PAL
6932}
6933
6934// Proxy code for EDA
6935struct EnsureDebuggerAttachedParams
6936{
6937 Debugger * m_pThis;
6938 HRESULT m_retval;
6939 PROCESS_INFORMATION * m_pProcessInfo;
6940 EnsureDebuggerAttachedParams() :
6941 m_pThis(NULL), m_retval(E_FAIL), m_pProcessInfo(NULL) {LIMITED_METHOD_CONTRACT; }
6942};
6943
6944// This is called by the helper thread
6945void EDAHelperStub(EnsureDebuggerAttachedParams * p)
6946{
6947 WRAPPER_NO_CONTRACT;
6948
6949 p->m_retval = p->m_pThis->EDAHelper(p->m_pProcessInfo);
6950}
6951
6952// This gets called just like the normal version, but it sends the call over to the helper thread
6953HRESULT Debugger::EDAHelperProxy(PROCESS_INFORMATION * pProcessInfo)
6954{
6955 CONTRACTL
6956 {
6957 NOTHROW;
6958 GC_TRIGGERS;
6959 }
6960 CONTRACTL_END;
6961
6962 _ASSERTE(!ThisIsHelperThreadWorker());
6963 _ASSERTE(ThreadHoldsLock());
6964
6965 HRESULT hr = LazyInitWrapper();
6966 if (FAILED(hr))
6967 {
6968 // We already stress logged this case.
6969 return hr;
6970 }
6971
6972
6973 if (!IsGuardPageGone())
6974 {
6975 return EDAHelper(pProcessInfo);
6976 }
6977
6978 EnsureDebuggerAttachedParams p;
6979 p.m_pThis = this;
6980 p.m_pProcessInfo = pProcessInfo;
6981
6982 LOG((LF_CORDB, LL_INFO1000000, "D::EDAHelperProxy\n"));
6983 m_pRCThread->DoFavor((FAVORCALLBACK) EDAHelperStub, &p);
6984 LOG((LF_CORDB, LL_INFO1000000, "D::EDAHelperProxy return\n"));
6985
6986 return p.m_retval;
6987}
6988
6989// E_ABORT - if the attach was declined
6990// S_OK - Jit-attach successfully started
6991HRESULT Debugger::EDAHelper(PROCESS_INFORMATION *pProcessInfo)
6992{
6993 CONTRACTL
6994 {
6995 NOTHROW;
6996 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
6997
6998 PRECONDITION(ThisMaybeHelperThread()); // on helper if stackoverflow.
6999 }
7000 CONTRACTL_END;
7001
7002#ifndef FEATURE_PAL
7003 LOG((LF_CORDB, LL_INFO10000, "D::EDA: thread 0x%x is launching the debugger.\n", GetCurrentThreadId()));
7004
7005 _ASSERTE(HasLazyData());
7006
7007 // Another potential hang. This may get run on the helper if we have a stack overflow.
7008 // Hopefully the odds of 1 thread hitting a stack overflow while another is stuck holding the heap
7009 // lock is very small.
7010 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
7011
7012 BOOL fCreateSucceeded = FALSE;
7013
7014 StackSString strDbgCommand;
7015 const WCHAR * wszDbgCommand = NULL;
7016 SString strCurrentDir;
7017 const WCHAR * wszCurrentDir = NULL;
7018
7019 EX_TRY
7020 {
7021
7022 // Get the debugger to launch. The returned string is via the strDbgCommand out param. Throws on error.
7023 bool fHasDebugger = GetCompleteDebuggerLaunchString(&strDbgCommand);
7024 if (fHasDebugger)
7025 {
7026 wszDbgCommand = strDbgCommand.GetUnicode();
7027 _ASSERTE(wszDbgCommand != NULL); // would have thrown on oom.
7028
7029 LOG((LF_CORDB, LL_INFO10000, "D::EDA: launching with command [%S]\n", wszDbgCommand));
7030
7031 ClrGetCurrentDirectory(strCurrentDir);
7032 wszCurrentDir = strCurrentDir.GetUnicode();
7033 }
7034 }
7035 EX_CATCH
7036 {
7037 }
7038 EX_END_CATCH(SwallowAllExceptions);
7039
7040 STARTUPINFOW startupInfo = {0};
7041 startupInfo.cb = sizeof(STARTUPINFOW);
7042
7043 DWORD errCreate = 0;
7044
7045 if (wszDbgCommand != NULL)
7046 {
7047 // Create the debugger process
7048 // When we are launching an debugger, we need to let the child process inherit our handles.
7049 // This is necessary for the debugger to signal us that the attach is complete.
7050 fCreateSucceeded = WszCreateProcess(NULL, const_cast<WCHAR*> (wszDbgCommand),
7051 NULL, NULL,
7052 TRUE,
7053 CREATE_NEW_CONSOLE,
7054 NULL, wszCurrentDir,
7055 &startupInfo,
7056 pProcessInfo);
7057 errCreate = GetLastError();
7058 }
7059
7060 if (!fCreateSucceeded)
7061 {
7062 LOG((LF_CORDB, LL_INFO10000, "D::EDA: debugger did not launch successfully.\n"));
7063 return E_ABORT;
7064 }
7065
7066 LOG((LF_CORDB, LL_INFO10000, "D::EDA: debugger launched successfully.\n"));
7067 return S_OK;
7068#else // !FEATURE_PAL
7069 return E_ABORT;
7070#endif // !FEATURE_PAL
7071}
7072
7073// ---------------------------------------------------------------------------------------------------------------------
7074// This function decides who wins the race for any jit attach and marks the appropriate state that a jit
7075// attach is in progress.
7076//
7077// Arguments
7078// willSendManagedEvent - indicates whether or not we plan to send a managed debug event after the jit attach
7079// explicitUserRequest - TRUE if this attach is caused by a call to the Debugger.Launch() API.
7080//
7081// Returns
7082// TRUE - if some other thread already has jit attach in progress -> this thread should block until that is complete
7083// FALSE - this is the first thread to jit attach -> this thread should launch the debugger
7084//
7085//
7086BOOL Debugger::PreJitAttach(BOOL willSendManagedEvent, BOOL willLaunchDebugger, BOOL explicitUserRequest)
7087{
7088 CONTRACTL
7089 {
7090 NOTHROW;
7091 GC_NOTRIGGER;
7092 MODE_PREEMPTIVE;
7093 PRECONDITION(!ThisIsHelperThreadWorker());
7094 }
7095 CONTRACTL_END;
7096
7097 LOG( (LF_CORDB, LL_INFO10000, "D::PreJA: Entering\n") );
7098
7099 // Multiple threads may be calling this, so need to take the lock.
7100 if(!m_jitAttachInProgress)
7101 {
7102 // TODO: This is a known deadlock! Debugger::PreJitAttach is called during WatsonLastChance.
7103 // If the event (exception/crash) happens while this thread is holding the ThreadStore
7104 // lock, we may deadlock if another thread holds the DebuggerMutex and is waiting on
7105 // the ThreadStore lock. The DebuggerMutex has to be broken into two smaller locks
7106 // so that you can take that lock here when holding the ThreadStore lock.
7107 DebuggerLockHolder dbgLockHolder(this);
7108
7109 if (!m_jitAttachInProgress)
7110 {
7111 m_jitAttachInProgress = TRUE;
7112 m_launchingDebugger = willLaunchDebugger;
7113 CLRJitAttachState = (willSendManagedEvent ? CLR_DEBUGGING_MANAGED_EVENT_PENDING : 0) | (explicitUserRequest ? CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH : 0);
7114 ResetEvent(GetUnmanagedAttachEvent());
7115 ResetEvent(GetAttachEvent());
7116 LOG( (LF_CORDB, LL_INFO10000, "D::PreJA: Leaving - first thread\n") );
7117 return TRUE;
7118 }
7119 }
7120
7121 LOG( (LF_CORDB, LL_INFO10000, "D::PreJA: Leaving - following thread\n") );
7122 return FALSE;
7123}
7124
7125//---------------------------------------------------------------------------------------------------------------------
7126// This function gets the jit debugger launched and waits for the native attach to complete
7127// Make sure you called PreJitAttach and it returned TRUE before you call this
7128//
7129// Arguments:
7130// pThread - the managed thread with the unhandled excpetion
7131// pExceptionInfo - the unhandled exception info
7132//
7133// Returns:
7134// S_OK if the debugger was launched successfully and a failing HRESULT otherwise
7135//
7136HRESULT Debugger::LaunchJitDebuggerAndNativeAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo)
7137{
7138 CONTRACTL
7139 {
7140 NOTHROW;
7141 GC_TRIGGERS;
7142 MODE_PREEMPTIVE;
7143 PRECONDITION(!ThisIsHelperThreadWorker());
7144 }
7145 CONTRACTL_END;
7146
7147 // You need to have called PreJitAttach first to determine which thread gets to launch the debugger
7148 _ASSERTE(m_jitAttachInProgress);
7149
7150 LOG( (LF_CORDB, LL_INFO10000, "D::LJDANA: Entering\n") );
7151 PROCESS_INFORMATION processInfo = {0};
7152 DebuggerLockHolder dbgLockHolder(this);
7153
7154 // <TODO>
7155 // If the JIT debugger failed to launch or if there is no JIT debugger, EDAHelperProxy will
7156 // switch to preemptive GC mode to display a dialog to the user indicating the JIT debugger
7157 // was unavailable. There are some rare cases where this could cause a deadlock with the
7158 // debugger lock; however these are rare enough that fixing this doesn't meet the bar for
7159 // Whidbey at this point. We might want to revisit this later however.
7160 // </TODO>
7161 CONTRACT_VIOLATION(GCViolation);
7162
7163 {
7164 LOG((LF_CORDB, LL_INFO1000, "D::EDA: Initialize JDI.\n"));
7165
7166 EXCEPTION_POINTERS exceptionPointer;
7167 EXCEPTION_RECORD exceptionRecord;
7168 CONTEXT context;
7169
7170 if (pExceptionInfo == NULL)
7171 {
7172 ZeroMemory(&exceptionPointer, sizeof(exceptionPointer));
7173 ZeroMemory(&exceptionRecord, sizeof(exceptionRecord));
7174 ZeroMemory(&context, sizeof(context));
7175
7176 context.ContextFlags = CONTEXT_CONTROL;
7177 ClrCaptureContext(&context);
7178
7179 exceptionRecord.ExceptionAddress = reinterpret_cast<PVOID>(GetIP(&context));
7180 exceptionPointer.ContextRecord = &context;
7181 exceptionPointer.ExceptionRecord = &exceptionRecord;
7182
7183 pExceptionInfo = &exceptionPointer;
7184 }
7185
7186 InitDebuggerLaunchJitInfo(pThread, pExceptionInfo);
7187 }
7188
7189 // This will make the CreateProcess call to create the debugger process.
7190 // We then expect that the debugger process will turn around and attach to us.
7191 HRESULT hr = EDAHelperProxy(&processInfo);
7192 if(FAILED(hr))
7193 {
7194 return hr;
7195 }
7196
7197 LOG((LF_CORDB, LL_INFO10000, "D::LJDANA: waiting on m_exUnmanagedAttachEvent and debugger's process handle\n"));
7198 DWORD dwHandles = 2;
7199 HANDLE arrHandles[2];
7200 arrHandles[0] = GetUnmanagedAttachEvent();
7201 arrHandles[1] = processInfo.hProcess;
7202
7203 // Let the helper thread do the attach logic for us and wait for the
7204 // attach event. Must release the lock before blocking on a wait.
7205 dbgLockHolder.Release();
7206
7207 // Wait for one or the other to be set. Multiple threads could be waiting here.
7208 // The events are manual events, so when they go high, all threads will be released.
7209 DWORD res = WaitForMultipleObjectsEx(dwHandles, arrHandles, FALSE, INFINITE, FALSE);
7210
7211 // We no long need to keep handles to the debugger process.
7212 CloseHandle(processInfo.hProcess);
7213 CloseHandle(processInfo.hThread);
7214
7215 // Indicate to the caller that the attach was aborted
7216 if (res == WAIT_OBJECT_0 + 1)
7217 {
7218 LOG((LF_CORDB, LL_INFO10000, "D::LJDANA: Debugger process is unexpectedly terminated!\n"));
7219 return E_FAIL;
7220 }
7221
7222 // Otherwise, attach was successful (Note, only native attach is done so far)
7223 _ASSERTE((res == WAIT_OBJECT_0) && "WaitForMultipleObjectsEx failed!");
7224 LOG( (LF_CORDB, LL_INFO10000, "D::LJDANA: Leaving\n") );
7225 return S_OK;
7226
7227}
7228
7229// Blocks until the debugger completes jit attach
7230void Debugger::WaitForDebuggerAttach()
7231{
7232 LIMITED_METHOD_CONTRACT;
7233
7234 LOG( (LF_CORDB, LL_INFO10000, "D::WFDA:Entering\n") );
7235
7236 // if this thread previously called LaunchDebuggerAndNativeAttach then this wait is spurious,
7237 // the event is still set and it continues immediately. If this is an auxilliary thread however
7238 // then the wait is necessary
7239 // If we are not launching the debugger (e.g. unhandled exception on Win7), then we should not
7240 // wait on the unmanaged attach event. If the debugger is launched by the OS, then the unmanaged
7241 // attach event passed to the debugger is created by the OS, not by us, so our event will never
7242 // be signaled.
7243 if (m_launchingDebugger)
7244 {
7245 WaitForSingleObject(GetUnmanagedAttachEvent(), INFINITE);
7246 }
7247
7248 // Wait until the pending managed debugger attach is completed
7249 if (CORDebuggerPendingAttach() && !CORDebuggerAttached())
7250 {
7251 LOG( (LF_CORDB, LL_INFO10000, "D::WFDA: Waiting for managed attach too\n") );
7252 WaitForSingleObject(GetAttachEvent(), INFINITE);
7253 }
7254
7255 // We can't reset the event here because some threads may
7256 // be just about to wait on it. If we reset it before the
7257 // other threads hit the wait, they'll block.
7258
7259 // We have an innate race here that can't easily fix. The best
7260 // we can do is have a super small window (by moving the reset as
7261 // far out this making it very unlikely that a thread will
7262 // hit the window.
7263
7264 LOG( (LF_CORDB, LL_INFO10000, "D::WFDA: Leaving\n") );
7265}
7266
7267// Cleans up after jit attach is complete
7268void Debugger::PostJitAttach()
7269{
7270 CONTRACTL
7271 {
7272 NOTHROW;
7273 GC_NOTRIGGER;
7274 MODE_PREEMPTIVE;
7275 PRECONDITION(!ThisIsHelperThreadWorker());
7276 }
7277 CONTRACTL_END;
7278
7279 LOG( (LF_CORDB, LL_INFO10000, "D::PostJA: Entering\n") );
7280 // Multiple threads may be calling this, so need to take the lock.
7281 DebuggerLockHolder dbgLockHolder(this);
7282
7283 // clear the attaching flags which allows other threads to initiate jit attach if needed
7284 m_jitAttachInProgress = FALSE;
7285 m_launchingDebugger = FALSE;
7286 CLRJitAttachState = 0;
7287
7288 // set the attaching events to unblock other threads waiting on this attach
7289 // regardless of whether or not it completed
7290 SetEvent(GetUnmanagedAttachEvent());
7291 SetEvent(GetAttachEvent());
7292 LOG( (LF_CORDB, LL_INFO10000, "D::PostJA: Leaving\n") );
7293}
7294
7295//---------------------------------------------------------------------------------------
7296// Launches a debugger and blocks waiting for it to either attach or abort the attach.
7297//
7298// Arguments:
7299// pThread - the managed thread with the unhandled excpetion
7300// pExceptionInfo - the unhandled exception info
7301// willSendManagedEvent - TRUE if after getting attached we will send a managed debug event
7302// explicitUserRequest - TRUE if this attach is caused by a call to the Debugger.Launch() API.
7303//
7304// Returns:
7305// None. Callers can requery if a debugger is attached.
7306//
7307// Assumptions:
7308// This may be called by multiple threads, each firing their own debug events. This function will handle locking.
7309// Thus this could block for an arbitrary length of time:
7310// - may need to prompt the user to decide if an attach occurs.
7311// - may block waiting for a debugger to attach.
7312//
7313// Notes:
7314// The launch string is retrieved from code:GetDebuggerSettingInfo.
7315// This will not do a sync-complete. Instead, the caller can send a debug event (the jit-attach
7316// event, such as a User-breakpoint or unhandled exception) and that can send a sync-complete,
7317// just as if the debugger was always attached. This ensures that the jit-attach event is in the
7318// same callback queue as any faked-up events that the Right-side Shim creates.
7319//
7320void Debugger::JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL willSendManagedEvent, BOOL explicitUserRequest)
7321{
7322 CONTRACTL
7323 {
7324 NOTHROW;
7325 GC_TRIGGERS;
7326 MODE_ANY;
7327
7328 PRECONDITION(!ThisIsHelperThreadWorker()); // Must be a managed thread
7329 }
7330 CONTRACTL_END;
7331
7332 // Don't do anything if there is a native debugger already attached or the debugging support has been disabled.
7333 if (IsDebuggerPresent() || m_pRCThread == NULL)
7334 return;
7335
7336 GCX_PREEMP_EEINTERFACE_TOGGLE_IFTHREAD();
7337
7338 EnsureDebuggerAttached(pThread, pExceptionInfo, willSendManagedEvent, explicitUserRequest);
7339}
7340
7341//-----------------------------------------------------------------------------
7342// Ensure that a debugger is attached. Will jit-attach if needed.
7343//
7344// Arguments
7345// pThread - the managed thread with the unhandled excpetion
7346// pExceptionInfo - the unhandled exception info
7347// willSendManagedEvent - true if after getting (or staying) attached we will send
7348// a managed debug event
7349// explicitUserRequest - true if this attach is caused by a call to the
7350// Debugger.Launch() API.
7351//
7352// Returns:
7353// None. Either a debugger is attached or it is not.
7354//
7355// Notes:
7356// There are several intermediate possible outcomes:
7357// - Debugger already attached before this was called.
7358// - JIT-atttach debugger spawned, and attached successfully.
7359// - JIT-attach debugger spawned, but declined to attach.
7360// - Failed to spawn jit-attach debugger.
7361//
7362// Ultimately, the only thing that matters at the end is whether a debugger
7363// is now attached, which is retreived via CORDebuggerAttached().
7364//-----------------------------------------------------------------------------
7365void Debugger::EnsureDebuggerAttached(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL willSendManagedEvent, BOOL explicitUserRequest)
7366{
7367 CONTRACTL
7368 {
7369 NOTHROW;
7370 GC_TRIGGERS;
7371 MODE_PREEMPTIVE;
7372 PRECONDITION(!ThisIsHelperThreadWorker());
7373 }
7374 CONTRACTL_END;
7375
7376 LOG( (LF_CORDB,LL_INFO10000,"D::EDA\n") );
7377
7378 HRESULT hr = S_OK;
7379
7380 // We could be in three states:
7381 // 1) no debugger attached
7382 // 2) native attached but not managed (yet?)
7383 // 3) native attached and managed
7384
7385
7386 // There is a race condition here that can be hit if multiple threads
7387 // were to trigger jit attach at the right time
7388 // Thread 1 starts jit attach
7389 // Thread 2 also starts jit attach and gets to waiting for the attach complete
7390 // Thread 1 rapidly completes the jit attach then starts it again
7391 // Thread 2 may still be waiting from the first jit attach at this point
7392 //
7393 // Note that this isn't all that bad because if the debugger hasn't actually detached
7394 // in the middle then the second jit attach will complete almost instantly and thread 2
7395 // is unblocked. If the debugger did detach in the middle then it seems reasonable for
7396 // thread 2 to continue to wait until until the debugger is attached once again for the
7397 // second attach. Basically if one jit attach completes and restarts fast enough it might
7398 // just go unnoticed by some threads and it will be as if it never happened. Doesn't seem
7399 // that bad as long as we know another jit attach is again in progress.
7400
7401 BOOL startedJitAttach = FALSE;
7402
7403 // First check to see if we need to launch the debugger ourselves
7404 if(PreJitAttach(willSendManagedEvent, TRUE, explicitUserRequest))
7405 {
7406 // if the debugger is already attached then we can't launch one
7407 // and whatever attach state we are in is just what we get
7408 if(IsDebuggerPresent())
7409 {
7410 // unblock other threads waiting on our attach and clean up
7411 PostJitAttach();
7412 return;
7413 }
7414 else
7415 {
7416 hr = LaunchJitDebuggerAndNativeAttach(pThread, pExceptionInfo);
7417 if(FAILED(hr))
7418 {
7419 // unblock other threads waiting on our attach and clean up
7420 PostJitAttach();
7421 return;
7422 }
7423 }
7424 startedJitAttach = TRUE;
7425 }
7426
7427 // at this point someone should have launched the native debugger and
7428 // it is somewhere between not attached and attach complete
7429 // (it might have even been completely attached before this function even started)
7430 // step 2 - wait for the attach to complete
7431 WaitForDebuggerAttach();
7432
7433 // step 3 - if we initiated then we also cleanup
7434 if(startedJitAttach)
7435 PostJitAttach();
7436 LOG( (LF_CORDB, LL_INFO10000, "D::EDA:Leaving\n") );
7437}
7438
7439
7440// Proxy code for AttachDebuggerForBreakpoint
7441// Structure used in the proxy function callback
7442struct SendExceptionOnHelperThreadParams
7443{
7444 Debugger *m_pThis;
7445 HRESULT m_retval;
7446 Thread *m_pThread;
7447 OBJECTHANDLE m_exceptionHandle;
7448 bool m_continuable;
7449 FramePointer m_framePointer;
7450 SIZE_T m_nOffset;
7451 CorDebugExceptionCallbackType m_eventType;
7452 DWORD m_dwFlags;
7453
7454
7455 SendExceptionOnHelperThreadParams() :
7456 m_pThis(NULL),
7457 m_retval(S_OK),
7458 m_pThread(NULL)
7459 {LIMITED_METHOD_CONTRACT; }
7460};
7461
7462//**************************************************************************
7463// This function sends Exception and ExceptionCallback2 event.
7464//
7465// Arguments:
7466// pThread : managed thread which exception takes place
7467// exceptionHandle : handle to the managed exception object (usually
7468// something derived from System.Exception)
7469// fContinuable : true iff continuable
7470// framePointer : frame pointer associated with callback.
7471// nOffset : il offset associated with callback.
7472// eventType : type of callback
7473// dwFlags : additional flags (see CorDebugExceptionFlags).
7474//
7475// Returns:
7476// S_OK on sucess. Else some error. May also throw.
7477//
7478// Notes:
7479// This is a helper for code:Debugger.SendExceptionEventsWorker.
7480// See code:Debugger.SendException for more details about parameters.
7481// This is always called on a managed thread (never the helper thread)
7482// This will synchronize and block.
7483//**************************************************************************
7484HRESULT Debugger::SendExceptionHelperAndBlock(
7485 Thread *pThread,
7486 OBJECTHANDLE exceptionHandle,
7487 bool fContinuable,
7488 FramePointer framePointer,
7489 SIZE_T nOffset,
7490 CorDebugExceptionCallbackType eventType,
7491 DWORD dwFlags)
7492
7493{
7494 CONTRACTL
7495 {
7496 THROWS;
7497 GC_TRIGGERS;
7498 MODE_ANY;
7499
7500 PRECONDITION(CheckPointer(pThread));
7501 }
7502 CONTRACTL_END;
7503
7504 HRESULT hr = S_OK;
7505
7506 // This is a normal event to send from LS to RS
7507 SENDIPCEVENT_BEGIN(this, pThread);
7508
7509 // This function can be called on helper thread or managed thread.
7510 // However, we should be holding locks upon entry
7511
7512 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
7513
7514 //
7515 // Send pre-Whidbey EXCEPTION IPC event.
7516 //
7517 InitIPCEvent(ipce, DB_IPCE_EXCEPTION, pThread, pThread->GetDomain());
7518
7519 ipce->Exception.vmExceptionHandle.SetRawPtr(exceptionHandle);
7520 ipce->Exception.firstChance = (eventType == DEBUG_EXCEPTION_FIRST_CHANCE);
7521 ipce->Exception.continuable = fContinuable;
7522 hr = m_pRCThread->SendIPCEvent();
7523
7524 _ASSERTE(SUCCEEDED(hr) && "D::SE: Send ExceptionCallback event failed.");
7525
7526 //
7527 // Send Whidbey EXCEPTION IPC event.
7528 //
7529 InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain());
7530
7531 ipce->ExceptionCallback2.framePointer = framePointer;
7532 ipce->ExceptionCallback2.eventType = eventType;
7533 ipce->ExceptionCallback2.nOffset = nOffset;
7534 ipce->ExceptionCallback2.dwFlags = dwFlags;
7535 ipce->ExceptionCallback2.vmExceptionHandle.SetRawPtr(exceptionHandle);
7536
7537 LOG((LF_CORDB, LL_INFO10000, "D::SE: sending ExceptionCallback2 event"));
7538 hr = m_pRCThread->SendIPCEvent();
7539
7540 if (eventType == DEBUG_EXCEPTION_FIRST_CHANCE)
7541 {
7542 pThread->GetExceptionState()->GetFlags()->SetSentDebugFirstChance();
7543 }
7544 else
7545 {
7546 _ASSERTE(eventType == DEBUG_EXCEPTION_UNHANDLED);
7547 }
7548
7549 _ASSERTE(SUCCEEDED(hr) && "D::SE: Send ExceptionCallback2 event failed.");
7550
7551 if (SUCCEEDED(hr))
7552 {
7553 // Stop all Runtime threads
7554 TrapAllRuntimeThreads();
7555 }
7556
7557 // Let other Runtime threads handle their events.
7558 SENDIPCEVENT_END;
7559
7560 return hr;
7561
7562}
7563
7564// Send various first-chance / unhandled exception events.
7565//
7566// Assumptions:
7567// Caller has already determined that we want to send exception events.
7568//
7569// Notes:
7570// This is a helper function for code:Debugger.SendException
7571void Debugger::SendExceptionEventsWorker(
7572 Thread * pThread,
7573 bool fFirstChance,
7574 bool fIsInterceptable,
7575 bool fContinuable,
7576 SIZE_T currentIP,
7577 FramePointer framePointer,
7578 bool atSafePlace)
7579{
7580 HRESULT hr = S_OK;
7581
7582 ThreadExceptionState* pExState = pThread->GetExceptionState();
7583 //
7584 // Figure out parameters to the IPC events.
7585 //
7586 const BYTE *ip;
7587
7588 SIZE_T nOffset = (SIZE_T)ICorDebugInfo::NO_MAPPING;
7589 DebuggerMethodInfo *pDebugMethodInfo = NULL;
7590
7591 // If we're passed a zero IP or SP, then go to the ThreadExceptionState on the thread to get the data. Note:
7592 // we can only do this if there is a context in the pExState. There are cases (most notably the
7593 // EEPolicy::HandleFatalError case) where we don't have that. So we just leave the IP/SP 0.
7594 if ((currentIP == 0) && (pExState->GetContextRecord() != NULL))
7595 {
7596 ip = (BYTE *)GetIP(pExState->GetContextRecord());
7597 }
7598 else
7599 {
7600 ip = (BYTE *)currentIP;
7601 }
7602
7603 if (g_pEEInterface->IsManagedNativeCode(ip))
7604 {
7605
7606 MethodDesc *pMethodDesc = g_pEEInterface->GetNativeCodeMethodDesc(PCODE(ip));
7607 _ASSERTE(pMethodDesc != NULL);
7608
7609 if (pMethodDesc != NULL)
7610 {
7611 DebuggerJitInfo *pDebugJitInfo = GetJitInfo(pMethodDesc, ip, &pDebugMethodInfo);
7612
7613 if (pDebugJitInfo != NULL)
7614 {
7615 SIZE_T nativeOffset = CodeRegionInfo::GetCodeRegionInfo(pDebugJitInfo, pMethodDesc).AddressToOffset(ip);
7616 CorDebugMappingResult mapResult;
7617 DWORD which;
7618
7619 nOffset = pDebugJitInfo->MapNativeOffsetToIL(nativeOffset, &mapResult, &which);
7620 }
7621 }
7622 }
7623
7624 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
7625
7626 if (fFirstChance)
7627 {
7628 // We can call into this method when there is no exception in progress to alert
7629 // the debugger to a stack overflow, however that case should never specify first
7630 // chance. An exception must be in progress to check the flags on the exception state
7631 _ASSERTE(pThread->IsExceptionInProgress());
7632
7633 //
7634 // Send the first chance exception if we have not already and if it is not suppressed
7635 //
7636 if (m_sendExceptionsOutsideOfJMC && !pExState->GetFlags()->SentDebugFirstChance())
7637 {
7638 // Blocking here is especially important so that the debugger can mark any code as JMC.
7639 hr = SendExceptionHelperAndBlock(
7640 pThread,
7641 g_pEEInterface->GetThreadException(pThread),
7642 fContinuable,
7643 framePointer,
7644 nOffset,
7645 DEBUG_EXCEPTION_FIRST_CHANCE,
7646 fIsInterceptable ? DEBUG_EXCEPTION_CAN_BE_INTERCEPTED : 0);
7647
7648 {
7649 // Toggle GC into COOP to block this thread.
7650 GCX_COOP_EEINTERFACE();
7651
7652 //
7653 // If we weren't at a safe place when we enabled PGC, then go ahead and unmark that fact now that we've successfully
7654 // disabled.
7655 //
7656 if (!atSafePlace)
7657 {
7658 g_pDebugger->DecThreadsAtUnsafePlaces();
7659 }
7660
7661 ProcessAnyPendingEvals(pThread);
7662
7663 //
7664 // If we weren't at a safe place, increment the unsafe count before we enable preemptive mode.
7665 //
7666 if (!atSafePlace)
7667 {
7668 g_pDebugger->IncThreadsAtUnsafePlaces();
7669 }
7670 } // end of GCX_CCOP_EEINTERFACE();
7671 } //end if (m_sendExceptionsOutsideOfJMC && !SentDebugFirstChance())
7672
7673 //
7674 // If this is a JMC function, then we send a USER's first chance as well.
7675 //
7676 if ((pDebugMethodInfo != NULL) &&
7677 pDebugMethodInfo->IsJMCFunction() &&
7678 !pExState->GetFlags()->SentDebugUserFirstChance())
7679 {
7680 SENDIPCEVENT_BEGIN(this, pThread);
7681
7682 InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain());
7683
7684 ipce->ExceptionCallback2.framePointer = framePointer;
7685 ipce->ExceptionCallback2.eventType = DEBUG_EXCEPTION_USER_FIRST_CHANCE;
7686 ipce->ExceptionCallback2.nOffset = nOffset;
7687 ipce->ExceptionCallback2.dwFlags = fIsInterceptable ? DEBUG_EXCEPTION_CAN_BE_INTERCEPTED : 0;
7688 ipce->ExceptionCallback2.vmExceptionHandle.SetRawPtr(g_pEEInterface->GetThreadException(pThread));
7689
7690 LOG((LF_CORDB, LL_INFO10000, "D::SE: sending ExceptionCallback2 (USER FIRST CHANCE)"));
7691 hr = m_pRCThread->SendIPCEvent();
7692
7693 _ASSERTE(SUCCEEDED(hr) && "D::SE: Send ExceptionCallback2 (User) event failed.");
7694
7695 if (SUCCEEDED(hr))
7696 {
7697 // Stop all Runtime threads
7698 TrapAllRuntimeThreads();
7699 }
7700
7701 pExState->GetFlags()->SetSentDebugUserFirstChance();
7702
7703 // Let other Runtime threads handle their events.
7704 SENDIPCEVENT_END;
7705
7706 } // end if (!SentDebugUserFirstChance)
7707
7708 } // end if (firstChance)
7709 else
7710 {
7711 // unhandled exception case
7712 // if there is no exception in progress then we are sending a fake exception object
7713 // as an indication of a fatal error (stack overflow). In this case it is illegal
7714 // to read GetFlags() from the exception state.
7715 // else if there is an exception in progress we only want to send the notification if
7716 // we did not already send a CHF, previous unhandled, or unwind begin notification
7717 BOOL sendNotification = TRUE;
7718 if(pThread->IsExceptionInProgress())
7719 {
7720 sendNotification = !pExState->GetFlags()->DebugCatchHandlerFound() &&
7721 !pExState->GetFlags()->SentDebugUnhandled() &&
7722 !pExState->GetFlags()->SentDebugUnwindBegin();
7723 }
7724
7725 if(sendNotification)
7726 {
7727 hr = SendExceptionHelperAndBlock(
7728 pThread,
7729 g_pEEInterface->GetThreadException(pThread),
7730 fContinuable,
7731 LEAF_MOST_FRAME,
7732 (SIZE_T)ICorDebugInfo::NO_MAPPING,
7733 DEBUG_EXCEPTION_UNHANDLED,
7734 fIsInterceptable ? DEBUG_EXCEPTION_CAN_BE_INTERCEPTED : 0);
7735
7736 if(pThread->IsExceptionInProgress())
7737 {
7738 pExState->GetFlags()->SetSentDebugUnhandled();
7739 }
7740 }
7741
7742 } // end if (!firstChance)
7743}
7744
7745//
7746// SendException is called by Runtime threads to send that they've hit an Managed exception to the Right Side.
7747// This may block this thread and suspend the debuggee, and let the debugger inspect us.
7748//
7749// The thread's throwable should be set so that the debugger can inspect the current exception.
7750// It does not report native exceptions in native code (which is consistent because those don't have a
7751// managed exception object).
7752//
7753// This may kick off a jit-attach (in which case fAttaching==true), and so may be called even when no debugger
7754// is yet involved.
7755//
7756// Parameters:
7757// pThread - the thread throwing the exception.
7758// fFirstChance - true if this is a first chance exception. False if this is an unhandled exception.
7759// currentIP - absolute native address of the exception if it is from managed code. If this is 0, we try to find it
7760// based off the thread's current exception state.
7761// currentSP - stack pointer of the exception. This will get converted into a FramePointer and then used by the debugger
7762// to identify which stack frame threw the exception.
7763// currentBSP - additional information for IA64 only to identify the stack frame.
7764// fContinuable - not used.
7765// fAttaching - true iff this exception may initiate a jit-attach. In the common case, if this is true, then
7766// CorDebuggerAttached() is false. However, since a debugger can attach at any time, it's possible
7767// for another debugger to race against the jit-attach and win. Thus this may err on the side of being true.
7768// fForceNonInterceptable - This is used to determine if the exception is continuable (ie "Interceptible",
7769// we can handle a DB_IPCE_INTERCEPT_EXCEPTION event for it). If true, then the exception can not be continued.
7770// If false, we get continuation status from the exception properties of the current thread.
7771//
7772// Returns:
7773// S_OK on success (common case by far).
7774// propogates other errors.
7775//
7776HRESULT Debugger::SendException(Thread *pThread,
7777 bool fFirstChance,
7778 SIZE_T currentIP,
7779 SIZE_T currentSP,
7780 bool fContinuable, // not used by RS.
7781 bool fAttaching,
7782 bool fForceNonInterceptable,
7783 EXCEPTION_POINTERS * pExceptionInfo)
7784{
7785 CONTRACTL
7786 {
7787 THROWS;
7788 GC_TRIGGERS;
7789
7790 MODE_ANY;
7791
7792 PRECONDITION(HasLazyData());
7793 PRECONDITION(CheckPointer(pThread));
7794 PRECONDITION((pThread->GetFilterContext() == NULL) || !fFirstChance);
7795 }
7796 CONTRACTL_END;
7797
7798 LOG((LF_CORDB, LL_INFO10000, "D::SendException\n"));
7799
7800 if (CORDBUnrecoverableError(this))
7801 {
7802 return (E_FAIL);
7803 }
7804
7805 // Mark if we're at an unsafe place.
7806 AtSafePlaceHolder unsafePlaceHolder(pThread);
7807
7808 // Grab the exception name from the current exception object to pass to the JIT attach.
7809 bool fIsInterceptable;
7810
7811 if (fForceNonInterceptable)
7812 {
7813 fIsInterceptable = false;
7814 m_forceNonInterceptable = true;
7815 }
7816 else
7817 {
7818 fIsInterceptable = IsInterceptableException(pThread);
7819 m_forceNonInterceptable = false;
7820 }
7821
7822 ThreadExceptionState* pExState = pThread->GetExceptionState();
7823 BOOL managedEventNeeded = ((!fFirstChance) ||
7824 (fFirstChance && (!pExState->GetFlags()->SentDebugFirstChance() || !pExState->GetFlags()->SentDebugUserFirstChance())));
7825
7826 // There must be a managed exception object to send a managed exception event
7827 if (g_pEEInterface->IsThreadExceptionNull(pThread) && (pThread->LastThrownObjectHandle() == NULL))
7828 {
7829 managedEventNeeded = FALSE;
7830 }
7831
7832 if (fAttaching)
7833 {
7834 JitAttach(pThread, pExceptionInfo, managedEventNeeded, FALSE);
7835 // If the jit-attach occurred, CORDebuggerAttached() may now be true and we can
7836 // just act as if a debugger was always attached.
7837 }
7838
7839 if(managedEventNeeded)
7840 {
7841 {
7842 // We have to send enabled, so enable now.
7843 GCX_PREEMP_EEINTERFACE();
7844
7845 // Send the exception events. Even in jit-attach case, we should now be fully attached.
7846 if (CORDebuggerAttached())
7847 {
7848 // Initialize frame-pointer associated with exception notification.
7849 LPVOID stackPointer;
7850 if ((currentSP == 0) && (pExState->GetContextRecord() != NULL))
7851 {
7852 stackPointer = dac_cast<PTR_VOID>(GetSP(pExState->GetContextRecord()));
7853 }
7854 else
7855 {
7856 stackPointer = (LPVOID)currentSP;
7857 }
7858 FramePointer framePointer = FramePointer::MakeFramePointer(stackPointer);
7859
7860
7861 // Do the real work of sending the events
7862 SendExceptionEventsWorker(
7863 pThread,
7864 fFirstChance,
7865 fIsInterceptable,
7866 fContinuable,
7867 currentIP,
7868 framePointer,
7869 !unsafePlaceHolder.IsAtUnsafePlace());
7870 }
7871 else
7872 {
7873 LOG((LF_CORDB,LL_INFO100, "D:SE: Skipping SendIPCEvent because not supposed to send anything, or RS detached.\n"));
7874 }
7875 }
7876
7877 // If we weren't at a safe place when we switched to PREEMPTIVE, then go ahead and unmark that fact now
7878 // that we're successfully back in COOPERATIVE mode.
7879 unsafePlaceHolder.Clear();
7880
7881 {
7882 GCX_COOP_EEINTERFACE();
7883 ProcessAnyPendingEvals(pThread);
7884 }
7885 }
7886
7887 if (CORDebuggerAttached())
7888 {
7889 return S_FALSE;
7890 }
7891 else
7892 {
7893 return S_OK;
7894 }
7895}
7896
7897
7898/*
7899 * ProcessAnyPendingEvals
7900 *
7901 * This function checks for, and then processes, any pending func-evals.
7902 *
7903 * Parameters:
7904 * pThread - The thread to process.
7905 *
7906 * Returns:
7907 * None.
7908 *
7909 */
7910void Debugger::ProcessAnyPendingEvals(Thread *pThread)
7911{
7912 CONTRACTL
7913 {
7914 THROWS;
7915 GC_TRIGGERS;
7916 MODE_COOPERATIVE;
7917 }
7918 CONTRACTL_END;
7919
7920#ifndef DACCESS_COMPILE
7921
7922 // If no debugger is attached, then no evals to process.
7923 // We may get here in oom situations during jit-attach, so we'll check now and be safe.
7924 if (!CORDebuggerAttached())
7925 {
7926 return;
7927 }
7928
7929 //
7930 // Note: if there is a filter context installed, we may need remove it, do the eval, then put it back. I'm not 100%
7931 // sure which yet... it kinda depends on whether or not we really need the filter context updated due to a
7932 // collection during the func eval...
7933 //
7934 // If we need to do a func eval on this thread, then there will be a pending eval registered for this thread. We'll
7935 // loop so long as there are pending evals registered. We block in FuncEvalHijackWorker after sending up the
7936 // FuncEvalComplete event, so if the user asks for another func eval then there will be a new pending eval when we
7937 // loop and check again.
7938 //
7939 DebuggerPendingFuncEval *pfe;
7940
7941 while (GetPendingEvals() != NULL && (pfe = GetPendingEvals()->GetPendingEval(pThread)) != NULL)
7942 {
7943 DebuggerEval *pDE = pfe->pDE;
7944
7945 _ASSERTE(pDE->m_evalDuringException);
7946 _ASSERTE(pDE->m_thread == GetThread());
7947
7948 // Remove the pending eval from the hash. This ensures that if we take a first chance exception during the eval
7949 // that we can do another nested eval properly.
7950 GetPendingEvals()->RemovePendingEval(pThread);
7951
7952 // Go ahead and do the pending func eval. pDE is invalid after this.
7953 void *ret;
7954 ret = ::FuncEvalHijackWorker(pDE);
7955
7956
7957 // The return value should be NULL when FuncEvalHijackWorker is called as part of an exception.
7958 _ASSERTE(ret == NULL);
7959 }
7960
7961 // If we need to re-throw a ThreadAbortException, go ahead and do it now.
7962 if (GetThread()->m_StateNC & Thread::TSNC_DebuggerReAbort)
7963 {
7964 // Now clear the bit else we'll see it again when we process the Exception notification
7965 // from this upcoming UserAbort exception.
7966 pThread->ResetThreadStateNC(Thread::TSNC_DebuggerReAbort);
7967 pThread->UserAbort(Thread::TAR_Thread, EEPolicy::TA_Safe, INFINITE, Thread::UAC_Normal);
7968 }
7969
7970#endif
7971
7972}
7973
7974
7975/*
7976 * FirstChanceManagedException is called by Runtime threads when crawling the managed stack frame
7977 * for a handler for the exception. It is called for each managed call on the stack.
7978 *
7979 * Parameters:
7980 * pThread - The thread the exception is occurring on.
7981 * currentIP - the IP in the current stack frame.
7982 * currentSP - the SP in the current stack frame.
7983 *
7984 * Returns:
7985 * Always FALSE.
7986 *
7987 */
7988bool Debugger::FirstChanceManagedException(Thread *pThread, SIZE_T currentIP, SIZE_T currentSP)
7989{
7990
7991 // @@@
7992 // Implement DebugInterface
7993 // Can only be called from EE/exception
7994 // must be on managed thread.
7995
7996 CONTRACTL
7997 {
7998 THROWS;
7999 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8000
8001 PRECONDITION(CORDebuggerAttached());
8002 }
8003 CONTRACTL_END;
8004
8005 LOG((LF_CORDB, LL_INFO10000, "D::FCE: First chance exception, TID:0x%x, \n", GetThreadIdHelper(pThread)));
8006
8007 _ASSERTE(GetThread() != NULL);
8008
8009#ifdef _DEBUG
8010 static ConfigDWORD d_fce;
8011 if (d_fce.val(CLRConfig::INTERNAL_D__FCE))
8012 _ASSERTE(!"Stop in Debugger::FirstChanceManagedException?");
8013#endif
8014
8015 SendException(pThread, TRUE, currentIP, currentSP, FALSE, FALSE, FALSE, NULL);
8016
8017 return false;
8018}
8019
8020
8021/*
8022 * FirstChanceManagedExceptionCatcherFound is called by Runtime threads when crawling the
8023 * managed stack frame and a handler for the exception is found.
8024 *
8025 * Parameters:
8026 * pThread - The thread the exception is occurring on.
8027 * pTct - Contains the function information that has the catch clause.
8028 * pEHClause - Contains the native offset information of the catch clause.
8029 *
8030 * Returns:
8031 * None.
8032 *
8033 */
8034void Debugger::FirstChanceManagedExceptionCatcherFound(Thread *pThread,
8035 MethodDesc *pMD, TADDR pMethodAddr,
8036 BYTE *currentSP,
8037 EE_ILEXCEPTION_CLAUSE *pEHClause)
8038{
8039
8040 CONTRACTL
8041 {
8042 THROWS;
8043 GC_TRIGGERS_FROM_GETJITINFO;
8044 MODE_ANY;
8045 }
8046 CONTRACTL_END;
8047
8048 // @@@
8049 // Implements DebugInterface
8050 // Call by EE/exception. Must be on managed thread
8051 _ASSERTE(GetThread() != NULL);
8052
8053 // Quick check.
8054 if (!CORDebuggerAttached())
8055 {
8056 return;
8057 }
8058
8059 // Compute the offset
8060
8061 DWORD nOffset = (DWORD)(SIZE_T)ICorDebugInfo::NO_MAPPING;
8062 DebuggerMethodInfo *pDebugMethodInfo = NULL;
8063 DebuggerJitInfo *pDebugJitInfo = NULL;
8064 bool isInJMCFunction = false;
8065
8066 if (pMD != NULL)
8067 {
8068 _ASSERTE(!pMD->IsILStub());
8069
8070 pDebugJitInfo = GetJitInfo(pMD, (const BYTE *) pMethodAddr, &pDebugMethodInfo);
8071 if (pDebugMethodInfo != NULL)
8072 {
8073 isInJMCFunction = pDebugMethodInfo->IsJMCFunction();
8074 }
8075 }
8076
8077 // Here we check if debugger opted-out of receiving exception related events from outside of JMC methods
8078 // or this exception ever crossed JMC frame (in this case we have already sent user first chance event)
8079 if (m_sendExceptionsOutsideOfJMC ||
8080 isInJMCFunction ||
8081 pThread->GetExceptionState()->GetFlags()->SentDebugUserFirstChance())
8082 {
8083 if (pDebugJitInfo != NULL)
8084 {
8085 CorDebugMappingResult mapResult;
8086 DWORD which;
8087
8088 // Map the native instruction to the IL instruction.
8089 // Be sure to skip past the prolog on amd64/arm to get the right IL
8090 // instruction (on x86 there will not be a prolog as x86 does not use
8091 // funclets).
8092 nOffset = pDebugJitInfo->MapNativeOffsetToIL(
8093 pEHClause->HandlerStartPC,
8094 &mapResult,
8095 &which,
8096 TRUE
8097 );
8098 }
8099
8100 bool fIsInterceptable = IsInterceptableException(pThread);
8101 m_forceNonInterceptable = false;
8102 DWORD dwFlags = fIsInterceptable ? DEBUG_EXCEPTION_CAN_BE_INTERCEPTED : 0;
8103
8104 FramePointer fp = FramePointer::MakeFramePointer(currentSP);
8105 SendCatchHandlerFound(pThread, fp, nOffset, dwFlags);
8106 }
8107
8108 // flag that we catch handler found so that we won't send other mutually exclusive events
8109 // such as unwind begin or unhandled
8110 pThread->GetExceptionState()->GetFlags()->SetDebugCatchHandlerFound();
8111}
8112
8113// Filter to trigger CHF callback
8114// Notify of a catch-handler found callback.
8115LONG Debugger::NotifyOfCHFFilter(EXCEPTION_POINTERS* pExceptionPointers, PVOID pData)
8116{
8117 CONTRACTL
8118 {
8119 if ((GetThread() == NULL) || g_pEEInterface->IsThreadExceptionNull(GetThread()))
8120 {
8121 NOTHROW;
8122 GC_NOTRIGGER;
8123 }
8124 else
8125 {
8126 THROWS;
8127 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8128 }
8129 MODE_ANY;
8130 }
8131 CONTRACTL_END;
8132
8133 SCAN_IGNORE_TRIGGER; // Scan can't handle conditional contracts.
8134
8135 // @@@
8136 // Implements DebugInterface
8137 // Can only be called from EE
8138
8139 // If no debugger is attached, then don't bother sending the events.
8140 // This can't kick off a jit-attach.
8141 if (!CORDebuggerAttached())
8142 {
8143 return EXCEPTION_CONTINUE_SEARCH;
8144 }
8145
8146 //
8147 // If this exception has never bubbled thru to managed code, then there is no
8148 // useful information for the debugger and, in fact, it may be a completely
8149 // internally handled runtime exception, so we should do nothing.
8150 //
8151 if ((GetThread() == NULL) || g_pEEInterface->IsThreadExceptionNull(GetThread()))
8152 {
8153 return EXCEPTION_CONTINUE_SEARCH;
8154 }
8155
8156 // Caller must pass in the stack address. This should match up w/ a Frame.
8157 BYTE * pCatcherStackAddr = (BYTE*) pData;
8158
8159 // If we don't have any catcher frame, then use ebp from the context.
8160 if (pData == NULL)
8161 {
8162 pCatcherStackAddr = (BYTE*) GetFP(pExceptionPointers->ContextRecord);
8163 }
8164 else
8165 {
8166#ifdef _DEBUG
8167 _ASSERTE(pData != NULL);
8168 {
8169 // We want the CHF stack addr to match w/ the Internal Frame Cordbg sees
8170 // in the stacktrace.
8171 // The Internal Frame comes from an EE Frame. This means that the CHF stack
8172 // addr must match that EE Frame exactly. Let's check that now.
8173
8174 Frame * pFrame = reinterpret_cast<Frame*>(pData);
8175 // Calling a virtual method will enforce that we have a valid Frame. ;)
8176 // If we got passed in a random catch address, then when we cast to a Frame
8177 // the vtable pointer will be bogus and this call will AV.
8178 Frame::ETransitionType e;
8179 e = pFrame->GetTransitionType();
8180 }
8181#endif
8182 }
8183
8184 // @todo - when Stubs-In-Stacktraces is always enabled, remove this.
8185 if (!g_EnableSIS)
8186 {
8187 return EXCEPTION_CONTINUE_SEARCH;
8188 }
8189
8190 // Stubs don't have an IL offset.
8191 const SIZE_T offset = (SIZE_T)ICorDebugInfo::NO_MAPPING;
8192 Thread *pThread = GetThread();
8193 DWORD dwFlags = IsInterceptableException(pThread) ? DEBUG_EXCEPTION_CAN_BE_INTERCEPTED : 0;
8194 m_forceNonInterceptable = false;
8195
8196 FramePointer fp = FramePointer::MakeFramePointer(pCatcherStackAddr);
8197
8198 //
8199 // If we have not sent a first-chance notification, do so now.
8200 //
8201 ThreadExceptionState* pExState = pThread->GetExceptionState();
8202
8203 if (!pExState->GetFlags()->SentDebugFirstChance())
8204 {
8205 SendException(pThread,
8206 TRUE, // first-chance
8207 (SIZE_T)(GetIP(pExceptionPointers->ContextRecord)), // IP
8208 (SIZE_T)pCatcherStackAddr, // SP
8209 FALSE, // fContinuable
8210 FALSE, // attaching
8211 TRUE, // ForceNonInterceptable since we are transition stub, the first and last place
8212 // that will see this exception.
8213 pExceptionPointers);
8214 }
8215
8216 // Here we check if debugger opted-out of receiving exception related events from outside of JMC methods
8217 // or this exception ever crossed JMC frame (in this case we have already sent user first chance event)
8218 if (m_sendExceptionsOutsideOfJMC || pExState->GetFlags()->SentDebugUserFirstChance())
8219 {
8220 SendCatchHandlerFound(pThread, fp, offset, dwFlags);
8221 }
8222
8223 // flag that we catch handler found so that we won't send other mutually exclusive events
8224 // such as unwind begin or unhandled
8225 pExState->GetFlags()->SetDebugCatchHandlerFound();
8226
8227#ifdef DEBUGGING_SUPPORTED
8228#ifdef DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
8229 if ( (pThread != NULL) &&
8230 (pThread->IsExceptionInProgress()) &&
8231 (pThread->GetExceptionState()->GetFlags()->DebuggerInterceptInfo()) )
8232 {
8233 //
8234 // The debugger wants to intercept this exception. It may return in a failure case,
8235 // in which case we want to continue thru this path.
8236 //
8237 ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_CHAIN_END) pExceptionPointers->ExceptionRecord);
8238 }
8239#endif // DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
8240#endif // DEBUGGING_SUPPORTED
8241
8242 return EXCEPTION_CONTINUE_SEARCH;
8243}
8244
8245
8246// Actually send the catch handler found event.
8247// This can be used to send CHF for both regular managed catchers as well
8248// as stubs that catch (Func-eval, COM-Interop, AppDomains)
8249void Debugger::SendCatchHandlerFound(
8250 Thread * pThread,
8251 FramePointer fp,
8252 SIZE_T nOffset,
8253 DWORD dwFlags
8254)
8255{
8256
8257 CONTRACTL
8258 {
8259 THROWS;
8260 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8261 MODE_ANY;
8262 }
8263 CONTRACTL_END;
8264
8265 LOG((LF_CORDB, LL_INFO10000, "D::FirstChanceManagedExceptionCatcherFound\n"));
8266
8267 if (pThread == NULL)
8268 {
8269 _ASSERTE(!"Bad parameter");
8270 LOG((LF_CORDB, LL_INFO10000, "D::FirstChanceManagedExceptionCatcherFound - Bad parameter.\n"));
8271 return;
8272 }
8273
8274 if (CORDBUnrecoverableError(this))
8275 {
8276 return;
8277 }
8278
8279 //
8280 // Mark if we're at an unsafe place.
8281 //
8282 AtSafePlaceHolder unsafePlaceHolder(pThread);
8283
8284 {
8285 GCX_COOP_EEINTERFACE();
8286
8287 {
8288 SENDIPCEVENT_BEGIN(this, pThread);
8289
8290 if (CORDebuggerAttached() &&
8291 !pThread->GetExceptionState()->GetFlags()->DebugCatchHandlerFound() &&
8292 !pThread->GetExceptionState()->GetFlags()->SentDebugUnhandled() &&
8293 !pThread->GetExceptionState()->GetFlags()->SentDebugUnwindBegin())
8294 {
8295 HRESULT hr;
8296
8297 //
8298 // Figure out parameters to the IPC events.
8299 //
8300 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
8301
8302 //
8303 // Send Whidbey EXCEPTION IPC event.
8304 //
8305 InitIPCEvent(ipce, DB_IPCE_EXCEPTION_CALLBACK2, pThread, pThread->GetDomain());
8306
8307 ipce->ExceptionCallback2.framePointer = fp;
8308 ipce->ExceptionCallback2.eventType = DEBUG_EXCEPTION_CATCH_HANDLER_FOUND;
8309 ipce->ExceptionCallback2.nOffset = nOffset;
8310 ipce->ExceptionCallback2.dwFlags = dwFlags;
8311 ipce->ExceptionCallback2.vmExceptionHandle.SetRawPtr(g_pEEInterface->GetThreadException(pThread));
8312
8313 LOG((LF_CORDB, LL_INFO10000, "D::FCMECF: sending ExceptionCallback2"));
8314 hr = m_pRCThread->SendIPCEvent();
8315
8316 _ASSERTE(SUCCEEDED(hr) && "D::FCMECF: Send ExceptionCallback2 event failed.");
8317
8318 //
8319 // Stop all Runtime threads
8320 //
8321 TrapAllRuntimeThreads();
8322
8323 } // end if (!Attached)
8324 else
8325 {
8326 LOG((LF_CORDB,LL_INFO1000, "D:FCMECF: Skipping SendIPCEvent because RS detached.\n"));
8327 }
8328
8329 //
8330 // Let other Runtime threads handle their events.
8331 //
8332 SENDIPCEVENT_END;
8333 }
8334
8335 //
8336 // If we weren't at a safe place when we enabled PGC, then go ahead and unmark that fact now that we've successfully
8337 // disabled.
8338 //
8339 unsafePlaceHolder.Clear();
8340
8341 ProcessAnyPendingEvals(pThread);
8342 } // end of GCX_COOP_EEINTERFACE();
8343
8344 return;
8345}
8346
8347/*
8348 * ManagedExceptionUnwindBegin is called by Runtime threads when crawling the
8349 * managed stack frame and unwinding them.
8350 *
8351 * Parameters:
8352 * pThread - The thread the unwind is occurring on.
8353 *
8354 * Returns:
8355 * None.
8356 *
8357 */
8358void Debugger::ManagedExceptionUnwindBegin(Thread *pThread)
8359{
8360 CONTRACTL
8361 {
8362 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
8363 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8364 }
8365 CONTRACTL_END;
8366
8367 // @@@
8368 // Implements DebugInterface
8369 // Can only be called on managed threads
8370 //
8371
8372 LOG((LF_CORDB, LL_INFO10000, "D::ManagedExceptionUnwindBegin\n"));
8373
8374 if (pThread == NULL)
8375 {
8376 _ASSERTE(!"Bad parameter");
8377 LOG((LF_CORDB, LL_INFO10000, "D::ManagedExceptionUnwindBegin - Bad parameter.\n"));
8378 return;
8379 }
8380
8381 if (CORDBUnrecoverableError(this))
8382 {
8383 return;
8384 }
8385
8386 //
8387 // Mark if we're at an unsafe place.
8388 //
8389 AtSafePlaceHolder unsafePlaceHolder(pThread);
8390 {
8391 GCX_COOP_EEINTERFACE();
8392
8393 {
8394 SENDIPCEVENT_BEGIN(this, pThread);
8395
8396 if (CORDebuggerAttached() &&
8397 !pThread->GetExceptionState()->GetFlags()->SentDebugUnwindBegin() &&
8398 !pThread->GetExceptionState()->GetFlags()->DebugCatchHandlerFound() &&
8399 !pThread->GetExceptionState()->GetFlags()->SentDebugUnhandled())
8400 {
8401 HRESULT hr;
8402
8403 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
8404
8405 //
8406 // Send Whidbey EXCEPTION IPC event.
8407 //
8408 InitIPCEvent(ipce, DB_IPCE_EXCEPTION_UNWIND, pThread, pThread->GetDomain());
8409
8410 ipce->ExceptionUnwind.eventType = DEBUG_EXCEPTION_UNWIND_BEGIN;
8411 ipce->ExceptionUnwind.dwFlags = 0;
8412
8413 LOG((LF_CORDB, LL_INFO10000, "D::MEUB: sending ExceptionUnwind event"));
8414 hr = m_pRCThread->SendIPCEvent();
8415
8416 _ASSERTE(SUCCEEDED(hr) && "D::MEUB: Send ExceptionUnwind event failed.");
8417
8418 pThread->GetExceptionState()->GetFlags()->SetSentDebugUnwindBegin();
8419
8420 //
8421 // Stop all Runtime threads
8422 //
8423 TrapAllRuntimeThreads();
8424
8425 } // end if (!Attached)
8426
8427 //
8428 // Let other Runtime threads handle their events.
8429 //
8430 SENDIPCEVENT_END;
8431 }
8432
8433 //
8434 // If we weren't at a safe place when we enabled PGC, then go ahead and unmark that fact now that we've successfully
8435 // disabled.
8436 //
8437 unsafePlaceHolder.Clear();
8438 }
8439
8440 return;
8441}
8442
8443/*
8444 * DeleteInterceptContext
8445 *
8446 * This function is called by the VM to release any debugger specific information for an
8447 * exception object. It is called when the VM releases its internal exception stuff, i.e.
8448 * ExInfo on X86 and ExceptionTracker on WIN64.
8449 *
8450 *
8451 * Parameters:
8452 * pContext - Debugger specific context.
8453 *
8454 * Returns:
8455 * None.
8456 *
8457 * Notes:
8458 * pContext is just a pointer to a DebuggerContinuableExceptionBreakpoint.
8459 *
8460 */
8461void Debugger::DeleteInterceptContext(void *pContext)
8462{
8463 LIMITED_METHOD_CONTRACT;
8464
8465 DebuggerContinuableExceptionBreakpoint *pBp = (DebuggerContinuableExceptionBreakpoint *)pContext;
8466
8467 if (pBp != NULL)
8468 {
8469 DeleteInteropSafe(pBp);
8470 }
8471}
8472
8473
8474// Get the frame point for an exception handler
8475FramePointer GetHandlerFramePointer(BYTE *pStack)
8476{
8477 FramePointer handlerFP;
8478
8479#if !defined(_TARGET_ARM_) && !defined(_TARGET_ARM64_)
8480 // Refer to the comment in DispatchUnwind() to see why we have to add
8481 // sizeof(LPVOID) to the handler ebp.
8482 handlerFP = FramePointer::MakeFramePointer(LPVOID(pStack + sizeof(void*)));
8483#else
8484 // ARM is similar to IA64 in that it uses the establisher frame as the
8485 // handler. in this case we don't need to add sizeof(void*) to the FP.
8486 handlerFP = FramePointer::MakeFramePointer((LPVOID)pStack);
8487#endif // _TARGET_ARM_
8488
8489 return handlerFP;
8490}
8491
8492//
8493// ExceptionFilter is called by the Runtime threads when an exception
8494// is being processed.
8495// - fd - MethodDesc of filter function
8496// - pMethodAddr - any address inside of the method. This lets us resolve exactly which version
8497// of the method is being executed (for EnC)
8498// - offset - native offset to handler.
8499// - pStack, pBStore - stack pointers.
8500//
8501void Debugger::ExceptionFilter(MethodDesc *fd, TADDR pMethodAddr, SIZE_T offset, BYTE *pStack)
8502{
8503 CONTRACTL
8504 {
8505 MODE_COOPERATIVE;
8506 NOTHROW;
8507 GC_NOTRIGGER;
8508
8509 PRECONDITION(!IsDbgHelperSpecialThread());
8510 }
8511 CONTRACTL_END;
8512
8513 LOG((LF_CORDB,LL_INFO10000, "D::EF: pStack:0x%x MD: %s::%s, offset:0x%x\n",
8514 pStack, fd->m_pszDebugClassName, fd->m_pszDebugMethodName, offset));
8515
8516 //
8517 // !!! Need to think through logic for when to step through filter code -
8518 // perhaps only during a "step in".
8519 //
8520
8521 //
8522 // !!! Eventually there may be some weird mechanics introduced for
8523 // returning from the filter that we have to understand. For now we should
8524 // be able to proceed normally.
8525 //
8526
8527 FramePointer handlerFP;
8528 handlerFP = GetHandlerFramePointer(pStack);
8529
8530 DebuggerJitInfo * pDJI = NULL;
8531 EX_TRY
8532 {
8533 pDJI = GetJitInfo(fd, (const BYTE *) pMethodAddr);
8534 }
8535 EX_CATCH
8536 {
8537 }
8538 EX_END_CATCH(SwallowAllExceptions);
8539
8540 if (!fd->IsDynamicMethod() && (pDJI == NULL))
8541 {
8542 // The only way we shouldn't have a DJI is from a dynamic method or from oom (which the LS doesn't handle).
8543 _ASSERTE(!"Debugger doesn't support OOM scenarios.");
8544 return;
8545 }
8546
8547 DebuggerController::DispatchUnwind(g_pEEInterface->GetThread(),
8548 fd, pDJI, offset, handlerFP, STEP_EXCEPTION_FILTER);
8549}
8550
8551
8552//
8553// ExceptionHandle is called by Runtime threads when an exception is
8554// being handled.
8555// - fd - MethodDesc of filter function
8556// - pMethodAddr - any address inside of the method. This lets us resolve exactly which version
8557// of the method is being executed (for EnC)
8558// - offset - native offset to handler.
8559// - pStack, pBStore - stack pointers.
8560//
8561void Debugger::ExceptionHandle(MethodDesc *fd, TADDR pMethodAddr, SIZE_T offset, BYTE *pStack)
8562{
8563 CONTRACTL
8564 {
8565 MODE_COOPERATIVE;
8566 NOTHROW;
8567 GC_NOTRIGGER;
8568
8569 PRECONDITION(!IsDbgHelperSpecialThread());
8570 }
8571 CONTRACTL_END;
8572
8573
8574 FramePointer handlerFP;
8575 handlerFP = GetHandlerFramePointer(pStack);
8576
8577 DebuggerJitInfo * pDJI = NULL;
8578 EX_TRY
8579 {
8580 pDJI = GetJitInfo(fd, (const BYTE *) pMethodAddr);
8581 }
8582 EX_CATCH
8583 {
8584 }
8585 EX_END_CATCH(SwallowAllExceptions);
8586
8587 if (!fd->IsDynamicMethod() && (pDJI == NULL))
8588 {
8589 // The only way we shouldn't have a DJI is from a dynamic method or from oom (which the LS doesn't handle).
8590 _ASSERTE(!"Debugger doesn't support OOM scenarios.");
8591 return;
8592 }
8593
8594
8595 DebuggerController::DispatchUnwind(g_pEEInterface->GetThread(),
8596 fd, pDJI, offset, handlerFP, STEP_EXCEPTION_HANDLER);
8597}
8598
8599BOOL Debugger::ShouldAutoAttach()
8600{
8601 CONTRACTL
8602 {
8603 NOTHROW;
8604 GC_NOTRIGGER;
8605 }
8606 CONTRACTL_END;
8607
8608 _ASSERTE(!CORDebuggerAttached());
8609
8610 // We're relying on the caller to determine the
8611
8612 LOG((LF_CORDB, LL_INFO1000000, "D::SAD\n"));
8613
8614 // Check if the user has specified a seting in the registry about what he
8615 // wants done when an unhandled exception occurs.
8616 DebuggerLaunchSetting dls = GetDbgJITDebugLaunchSetting();
8617
8618 return (dls == DLS_ATTACH_DEBUGGER);
8619
8620 // @TODO cache the debugger launch setting.
8621
8622}
8623
8624BOOL Debugger::FallbackJITAttachPrompt()
8625{
8626 _ASSERTE(!CORDebuggerAttached());
8627 return (ATTACH_YES == this->ShouldAttachDebuggerProxy(false));
8628}
8629
8630void Debugger::MarkDebuggerAttachedInternal()
8631{
8632 LIMITED_METHOD_CONTRACT;
8633
8634 // Attach is complete now.
8635 LOG((LF_CORDB, LL_INFO10000, "D::FEDA: Attach Complete!\n"));
8636 g_pEEInterface->MarkDebuggerAttached();
8637
8638 _ASSERTE(HasLazyData());
8639}
8640void Debugger::MarkDebuggerUnattachedInternal()
8641{
8642 LIMITED_METHOD_CONTRACT;
8643
8644 _ASSERTE(HasLazyData());
8645
8646 g_pEEInterface->MarkDebuggerUnattached();
8647}
8648
8649//-----------------------------------------------------------------------------
8650// Favor to do lazy initialization on helper thread.
8651// This is needed to allow lazy intialization in Stack Overflow scenarios.
8652// We may or may not already be initialized.
8653//-----------------------------------------------------------------------------
8654void LazyInitFavor(void *)
8655{
8656 CONTRACTL
8657 {
8658 NOTHROW;
8659 MODE_ANY;
8660 }
8661 CONTRACTL_END;
8662 Debugger::DebuggerLockHolder dbgLockHolder(g_pDebugger);
8663 HRESULT hr;
8664 hr = g_pDebugger->LazyInitWrapper();
8665 (void)hr; //prevent "unused variable" error from GCC
8666
8667 // On checked builds, warn that we're hitting a scenario that debugging doesn't support.
8668 _ASSERTE(SUCCEEDED(hr) || !"Couldn't initialize lazy data for LastChanceManagedException");
8669}
8670
8671/******************************************************************************
8672 *
8673 ******************************************************************************/
8674LONG Debugger::LastChanceManagedException(EXCEPTION_POINTERS * pExceptionInfo,
8675 Thread *pThread,
8676 BOOL jitAttachRequested)
8677{
8678 CONTRACTL
8679 {
8680 NOTHROW;
8681 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8682 MODE_ANY;
8683 }
8684 CONTRACTL_END;
8685
8686 // @@@
8687 // Implements DebugInterface.
8688 // Can be run only on managed thread.
8689
8690 LOG((LF_CORDB, LL_INFO10000, "D::LastChanceManagedException\n"));
8691
8692 // Don't stop for native debugging anywhere inside our inproc-Filters.
8693 CantStopHolder hHolder;
8694
8695 EXCEPTION_RECORD * pExceptionRecord = pExceptionInfo->ExceptionRecord;
8696 CONTEXT * pContext = pExceptionInfo->ContextRecord;
8697
8698 // You're allowed to call this function with a NULL exception record and context. If you do, then its assumed
8699 // that we want to head right down to asking the user if they want to attach a debugger. No need to try to
8700 // dispatch the exception to the debugger controllers. You have to pass NULL for both the exception record and
8701 // the context, though. They're a pair. Both have to be NULL, or both have to be valid.
8702 _ASSERTE(((pExceptionRecord != NULL) && (pContext != NULL)) ||
8703 ((pExceptionRecord == NULL) && (pContext == NULL)));
8704
8705 if (CORDBUnrecoverableError(this))
8706 {
8707 return ExceptionContinueSearch;
8708 }
8709
8710 // We don't do anything on the second pass
8711 if ((pExceptionRecord != NULL) && ((pExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING) != 0))
8712 {
8713 return ExceptionContinueSearch;
8714 }
8715
8716 // Let the controllers have a chance at it - this may be the only handler which can catch the exception if this
8717 // is a native patch.
8718
8719 if ((pThread != NULL) &&
8720 (pContext != NULL) &&
8721 CORDebuggerAttached() &&
8722 DebuggerController::DispatchNativeException(pExceptionRecord,
8723 pContext,
8724 pExceptionRecord->ExceptionCode,
8725 pThread))
8726 {
8727 return ExceptionContinueExecution;
8728 }
8729
8730 // Otherwise, run our last chance exception logic
8731 ATTACH_ACTION action;
8732 action = ATTACH_NO;
8733
8734 if (CORDebuggerAttached() || jitAttachRequested)
8735 {
8736 LOG((LF_CORDB, LL_INFO10000, "D::BEH ... debugger attached.\n"));
8737
8738 Thread *thread = g_pEEInterface->GetThread();
8739 _ASSERTE((thread != NULL) && (thread == pThread));
8740
8741 // ExceptionFlags is 0 for continuable, EXCEPTION_NONCONTINUABLE otherwise. Note that if we don't have an
8742 // exception record, then we assume this is a non-continuable exception.
8743 bool continuable = (pExceptionRecord != NULL) && (pExceptionRecord->ExceptionFlags == 0);
8744
8745 LOG((LF_CORDB, LL_INFO10000, "D::BEH ... sending exception.\n"));
8746
8747 HRESULT hr = E_FAIL;
8748
8749 // In the jit-attach case, lazy-init. We may be in a stack-overflow, so do it via a favor to avoid
8750 // using this thread's stack space.
8751 if (jitAttachRequested)
8752 {
8753 m_pRCThread->DoFavor((FAVORCALLBACK) LazyInitFavor, NULL);
8754 }
8755
8756 // The only way we don't have lazy data at this point is in an OOM scenario, which
8757 // the debugger doesn't support.
8758 if (!HasLazyData())
8759 {
8760 return ExceptionContinueSearch;
8761 }
8762
8763
8764 // In Whidbey, we used to set the filter CONTEXT when we hit an unhandled exception while doing
8765 // mixed-mode debugging. This helps the debugger walk the stack since it can skip the leaf
8766 // portion of the stack (including stack frames in the runtime) and start the stackwalk at the
8767 // faulting stack frame. The code to set the filter CONTEXT is in a hijack function which is only
8768 // used during mixed-mode debugging.
8769 if (m_pRCThread->GetDCB()->m_rightSideIsWin32Debugger)
8770 {
8771 GCX_COOP();
8772
8773 _ASSERTE(thread->GetFilterContext() == NULL);
8774 thread->SetFilterContext(pExceptionInfo->ContextRecord);
8775 }
8776 EX_TRY
8777 {
8778 // We pass the attaching status to SendException so that it knows
8779 // whether to attach a debugger or not. We should really do the
8780 // attach stuff out here and not bother with the flag.
8781 hr = SendException(thread,
8782 FALSE,
8783 ((pContext != NULL) ? (SIZE_T)GetIP(pContext) : NULL),
8784 ((pContext != NULL) ? (SIZE_T)GetSP(pContext) : NULL),
8785 continuable,
8786 !!jitAttachRequested, // If we are JIT attaching on an unhandled exceptioin, we force
8787 !!jitAttachRequested, // the exception to be uninterceptable.
8788 pExceptionInfo);
8789 }
8790 EX_CATCH
8791 {
8792 }
8793 EX_END_CATCH(SwallowAllExceptions);
8794 if (m_pRCThread->GetDCB()->m_rightSideIsWin32Debugger)
8795 {
8796 GCX_COOP();
8797
8798 thread->SetFilterContext(NULL);
8799 }
8800 }
8801 else
8802 {
8803 // Note: we don't do anything on NO or TERMINATE. We just return to the exception logic, which will abort the
8804 // app or not depending on what the CLR impl decides is appropiate.
8805 _ASSERTE(action == ATTACH_TERMINATE || action == ATTACH_NO);
8806 }
8807
8808 return ExceptionContinueSearch;
8809}
8810
8811//
8812// NotifyUserOfFault notifies the user of a fault (unhandled exception
8813// or user breakpoint) in the process, giving them the option to
8814// attach a debugger or terminate the application.
8815//
8816int Debugger::NotifyUserOfFault(bool userBreakpoint, DebuggerLaunchSetting dls)
8817{
8818 LOG((LF_CORDB, LL_INFO1000000, "D::NotifyUserOfFault\n"));
8819
8820 CONTRACTL
8821 {
8822 NOTHROW;
8823 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;;
8824 MODE_PREEMPTIVE;
8825 }
8826 CONTRACTL_END;
8827
8828 int result = IDCANCEL;
8829
8830 if (!CORDebuggerAttached())
8831 {
8832 DWORD pid;
8833 DWORD tid;
8834
8835 pid = GetCurrentProcessId();
8836 tid = GetCurrentThreadId();
8837
8838 DWORD flags = 0;
8839 UINT resIDMessage = 0;
8840
8841 if (userBreakpoint)
8842 {
8843 resIDMessage = IDS_DEBUG_USER_BREAKPOINT_MSG;
8844 flags |= MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION;
8845 }
8846 else
8847 {
8848 resIDMessage = IDS_DEBUG_UNHANDLED_EXCEPTION_MSG;
8849 flags |= MB_OKCANCEL | MB_ICONEXCLAMATION;
8850 }
8851
8852 {
8853 // Another potential hang. This may get run on the helper if we have a stack overflow.
8854 // Hopefully the odds of 1 thread hitting a stack overflow while another is stuck holding the heap
8855 // lock is very small.
8856 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
8857
8858 result = MessageBox(resIDMessage, IDS_DEBUG_SERVICE_CAPTION,
8859 flags, TRUE, TRUE, pid, pid, tid, tid);
8860 }
8861 }
8862
8863 LOG((LF_CORDB, LL_INFO1000000, "D::NotifyUserOfFault left\n"));
8864 return result;
8865}
8866
8867
8868// Proxy for ShouldAttachDebugger
8869struct ShouldAttachDebuggerParams {
8870 Debugger* m_pThis;
8871 bool m_fIsUserBreakpoint;
8872 Debugger::ATTACH_ACTION m_retval;
8873};
8874
8875// This is called by the helper thread
8876void ShouldAttachDebuggerStub(ShouldAttachDebuggerParams * p)
8877{
8878 WRAPPER_NO_CONTRACT;
8879
8880 p->m_retval = p->m_pThis->ShouldAttachDebugger(p->m_fIsUserBreakpoint);
8881}
8882
8883// This gets called just like the normal version, but it sends the call over to the helper thread
8884Debugger::ATTACH_ACTION Debugger::ShouldAttachDebuggerProxy(bool fIsUserBreakpoint)
8885{
8886 CONTRACTL
8887 {
8888 NOTHROW;
8889 GC_TRIGGERS;
8890 }
8891 CONTRACTL_END;
8892
8893 if (!HasLazyData())
8894 {
8895 DebuggerLockHolder lockHolder(this);
8896 HRESULT hr = LazyInitWrapper();
8897 if (FAILED(hr))
8898 {
8899 // We already stress logged this case.
8900 return ATTACH_NO;
8901 }
8902 }
8903
8904
8905 if (!IsGuardPageGone())
8906 return ShouldAttachDebugger(fIsUserBreakpoint);
8907
8908 ShouldAttachDebuggerParams p;
8909 p.m_pThis = this;
8910 p.m_fIsUserBreakpoint = fIsUserBreakpoint;
8911
8912 LOG((LF_CORDB, LL_INFO1000000, "D::SADProxy\n"));
8913 m_pRCThread->DoFavor((FAVORCALLBACK) ShouldAttachDebuggerStub, &p);
8914 LOG((LF_CORDB, LL_INFO1000000, "D::SADProxy return %d\n", p.m_retval));
8915
8916 return p.m_retval;
8917}
8918
8919//---------------------------------------------------------------------------------------
8920// Do policy to determine if we should attach a debugger.
8921//
8922// Arguments:
8923// fIsUserBreakpoint - true iff this is in response to a user-breakpoint, else false.
8924//
8925// Returns:
8926// Action to perform based off policy.
8927// ATTACH_NO if a debugger is already attached.
8928Debugger::ATTACH_ACTION Debugger::ShouldAttachDebugger(bool fIsUserBreakpoint)
8929{
8930 CONTRACTL
8931 {
8932 NOTHROW;
8933 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
8934 MODE_ANY;
8935 }
8936 CONTRACTL_END;
8937
8938
8939 LOG((LF_CORDB, LL_INFO1000000, "D::SAD\n"));
8940
8941 // If the debugger is already attached, not necessary to re-attach
8942 if (CORDebuggerAttached())
8943 {
8944 return ATTACH_NO;
8945 }
8946
8947 // Check if the user has specified a seting in the registry about what he wants done when an unhandled exception
8948 // occurs.
8949 DebuggerLaunchSetting dls = GetDbgJITDebugLaunchSetting();
8950
8951
8952 if (dls == DLS_ATTACH_DEBUGGER)
8953 {
8954 return ATTACH_YES;
8955 }
8956 else
8957 {
8958 // Only ask the user once if they wish to attach a debugger. This is because LastChanceManagedException can be called
8959 // twice, which causes ShouldAttachDebugger to be called twice, which causes the user to have to answer twice.
8960 static BOOL s_fHasAlreadyAsked = FALSE;
8961 static ATTACH_ACTION s_action;
8962
8963
8964 // This lock is also part of the above workaround.
8965 // Must go to preemptive to take this lock since we'll trigger down the road.
8966 GCX_PREEMP();
8967 DebuggerLockHolder lockHolder(this);
8968
8969 // We always want to ask about user breakpoints!
8970 if (!s_fHasAlreadyAsked || fIsUserBreakpoint)
8971 {
8972 if (!fIsUserBreakpoint)
8973 s_fHasAlreadyAsked = TRUE;
8974
8975 // While we could theoretically run into a deadlock if another thread
8976 // which acquires the debugger lock in cooperative GC mode is blocked
8977 // on this thread while it is running arbitrary user code out of the
8978 // MessageBox message pump, given that this codepath will only be used
8979 // on Win9x and that the chances of this happenning are quite slim,
8980 // for Whidbey a GCViolation is acceptable.
8981 CONTRACT_VIOLATION(GCViolation);
8982
8983 // Ask the user if they want to attach
8984 int iRes = NotifyUserOfFault(fIsUserBreakpoint, dls);
8985
8986 // If it's a user-defined breakpoint, they must hit Retry to launch
8987 // the debugger. If it's an unhandled exception, user must press
8988 // Cancel to attach the debugger.
8989 if ((iRes == IDCANCEL) || (iRes == IDRETRY))
8990 s_action = ATTACH_YES;
8991
8992 else if ((iRes == IDABORT) || (iRes == IDOK))
8993 s_action = ATTACH_TERMINATE;
8994
8995 else
8996 s_action = ATTACH_NO;
8997 }
8998
8999 // dbgLockHolder goes out of scope - implicit Release
9000 return s_action;
9001 }
9002}
9003
9004
9005//---------------------------------------------------------------------------------------
9006// SendUserBreakpoint is called by Runtime threads to send that they've hit
9007// a user breakpoint to the Right Side.
9008//
9009// Parameters:
9010// thread - managed thread that the breakpoint is on
9011//
9012// Notes:
9013// A user breakpoint is generally triggered by a call to System.Diagnostics.Debugger.Break.
9014// This can be very common. VB's 'stop' statement compiles to a Debugger.Break call.
9015// Some other CLR facilities (MDAs) may call this directly too.
9016//
9017// This may trigger a Jit attach.
9018// If the debugger is already attached, this will issue a step-out so that the UserBreakpoint
9019// appears to come from the callsite.
9020void Debugger::SendUserBreakpoint(Thread * thread)
9021{
9022 CONTRACTL
9023 {
9024 THROWS;
9025 GC_TRIGGERS;
9026 MODE_ANY;
9027
9028 PRECONDITION(thread != NULL);
9029 PRECONDITION(thread == ::GetThread());
9030 }
9031 CONTRACTL_END;
9032
9033
9034#ifdef _DEBUG
9035 // For testing Watson, we want a consistent way to be able to generate a
9036 // Fatal Execution Error
9037 // So we have a debug-only knob in this particular managed call that can be used
9038 // to artificially inject the error.
9039 // This is only for testing.
9040 static int fDbgInjectFEE = -1;
9041
9042 if (fDbgInjectFEE == -1)
9043 fDbgInjectFEE = UnsafeGetConfigDWORD(CLRConfig::INTERNAL_DbgInjectFEE);
9044
9045 if (fDbgInjectFEE)
9046 {
9047 STRESS_LOG0(LF_CORDB, LL_INFO10000, "Debugger posting bogus FEE b/c knob DbgInjectFEE is set.\n");
9048 EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
9049 // These never return.
9050 }
9051#endif
9052
9053 if (CORDBUnrecoverableError(this))
9054 {
9055 return;
9056 }
9057
9058 // UserBreakpoint behaves differently if we're under a debugger vs. a jit-attach.
9059 // If we're under the debugger, it does an additional step-out to get us back to the call site.
9060
9061 // If already attached, then do a step-out and send the userbreak event.
9062 if (CORDebuggerAttached())
9063 {
9064 // A debugger is already attached, so setup a DebuggerUserBreakpoint controller to get us out of the helper
9065 // that got us here. The DebuggerUserBreakpoint will call AttachDebuggerForBreakpoint for us when we're out
9066 // of the helper. The controller will delete itself when its done its work.
9067 DebuggerUserBreakpoint::HandleDebugBreak(thread);
9068 return;
9069 }
9070
9071 ATTACH_ACTION dbgAction = ShouldAttachDebugger(true);
9072
9073 // No debugger is attached. Consider a JIT attach.
9074 // This will do ShouldAttachDebugger() and wait for the results.
9075 // - It may terminate if the user requested that.
9076 // - It may do a full jit-attach.
9077 if (dbgAction == ATTACH_YES)
9078 {
9079 JitAttach(thread, NULL, TRUE, FALSE);
9080 }
9081 else if (dbgAction == ATTACH_TERMINATE)
9082 {
9083 // ATTACH_TERMINATE indicates the the user wants to terminate the app.
9084 LOG((LF_CORDB, LL_INFO10000, "D::SUB: terminating this process due to user request\n"));
9085
9086 // Should this go through the host?
9087 TerminateProcess(GetCurrentProcess(), 0);
9088 _ASSERTE(!"Should never reach this point.");
9089 }
9090 else
9091 {
9092 _ASSERTE(dbgAction == ATTACH_NO);
9093 }
9094
9095 if (CORDebuggerAttached())
9096 {
9097 // On jit-attach, we just send the UserBreak event. Don't do an extra step-out.
9098 SendUserBreakpointAndSynchronize(thread);
9099 }
9100 else if (IsDebuggerPresent())
9101 {
9102 DebugBreak();
9103 }
9104}
9105
9106
9107// void Debugger::ThreadCreated(): ThreadCreated is called when
9108// a new Runtime thread has been created, but before its ever seen
9109// managed code. This is a callback invoked by the EE into the Debugger.
9110// This will create a DebuggerThreadStarter patch, which will set
9111// a patch at the first instruction in the managed code. When we hit
9112// that patch, the DebuggerThreadStarter will invoke ThreadStarted, below.
9113//
9114// Thread* pRuntimeThread: The EE Thread object representing the
9115// runtime thread that has just been created.
9116void Debugger::ThreadCreated(Thread* pRuntimeThread)
9117{
9118 CONTRACTL
9119 {
9120 NOTHROW;
9121 GC_NOTRIGGER;
9122 }
9123 CONTRACTL_END;
9124
9125 // @@@
9126 // This function implements the DebugInterface. But it is also called from Attach
9127 // logic internally.
9128 //
9129
9130 if (CORDBUnrecoverableError(this))
9131 return;
9132
9133 LOG((LF_CORDB, LL_INFO100, "D::TC: thread created for 0x%x. ******\n",
9134 GetThreadIdHelper(pRuntimeThread)));
9135
9136 // Sanity check the thread.
9137 _ASSERTE(pRuntimeThread != NULL);
9138 _ASSERTE(pRuntimeThread->GetThreadId() != 0);
9139
9140
9141 // Create a thread starter and enable its WillEnterManaged code
9142 // callback. This will cause the starter to trigger once the
9143 // thread has hit managed code, which will cause
9144 // Debugger::ThreadStarted() to be called. NOTE: the starter will
9145 // be deleted automatically when its done its work.
9146 DebuggerThreadStarter *starter = new (interopsafe, nothrow) DebuggerThreadStarter(pRuntimeThread);
9147
9148 if (starter == NULL)
9149 {
9150 CORDBDebuggerSetUnrecoverableWin32Error(this, 0, false);
9151 return;
9152 }
9153
9154 starter->EnableTraceCall(LEAF_MOST_FRAME);
9155}
9156
9157
9158// void Debugger::ThreadStarted(): ThreadStarted is called when
9159// a new Runtime thread has reached its first managed code. This is
9160// called by the DebuggerThreadStarter patch's SendEvent method.
9161//
9162// Thread* pRuntimeThread: The EE Thread object representing the
9163// runtime thread that has just hit managed code.
9164void Debugger::ThreadStarted(Thread* pRuntimeThread)
9165{
9166 CONTRACTL
9167 {
9168 NOTHROW;
9169 GC_NOTRIGGER;
9170 }
9171 CONTRACTL_END;
9172
9173 // @@@
9174 // This method implemented DebugInterface but it is also called from Controller
9175
9176 if (CORDBUnrecoverableError(this))
9177 return;
9178
9179 LOG((LF_CORDB, LL_INFO100, "D::TS: thread attach : ID=%#x AD:%#x\n",
9180 GetThreadIdHelper(pRuntimeThread), pRuntimeThread->GetDomain()));
9181
9182 // We just need to send a VMPTR_Thread. The RS will get everything else it needs from DAC.
9183 //
9184
9185 _ASSERTE((g_pEEInterface->GetThread() &&
9186 !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) ||
9187 g_fInControlC);
9188 _ASSERTE(ThreadHoldsLock());
9189
9190 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
9191 InitIPCEvent(ipce,
9192 DB_IPCE_THREAD_ATTACH,
9193 pRuntimeThread,
9194 pRuntimeThread->GetDomain());
9195
9196
9197 m_pRCThread->SendIPCEvent();
9198
9199 //
9200 // Well, if this thread got created _after_ we started sync'ing
9201 // then its Runtime thread flags don't have the fact that there
9202 // is a debug suspend pending. We need to call over to the
9203 // Runtime and set the flag in the thread now...
9204 //
9205 if (m_trappingRuntimeThreads)
9206 {
9207 g_pEEInterface->MarkThreadForDebugSuspend(pRuntimeThread);
9208 }
9209}
9210
9211
9212//---------------------------------------------------------------------------------------
9213//
9214// DetachThread is called by Runtime threads when they are completing
9215// their execution and about to be destroyed.
9216//
9217// Arguments:
9218// pRuntimeThread - Pointer to the runtime's thread object to detach.
9219//
9220// Return Value:
9221// None
9222//
9223//---------------------------------------------------------------------------------------
9224void Debugger::DetachThread(Thread *pRuntimeThread)
9225{
9226 CONTRACTL
9227 {
9228 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9229 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9230 }
9231 CONTRACTL_END;
9232
9233 if (CORDBUnrecoverableError(this))
9234 {
9235 return;
9236 }
9237
9238 if (m_ignoreThreadDetach)
9239 {
9240 return;
9241 }
9242
9243 _ASSERTE (pRuntimeThread != NULL);
9244
9245
9246 LOG((LF_CORDB, LL_INFO100, "D::DT: thread detach : ID=%#x AD:%#x.\n",
9247 GetThreadIdHelper(pRuntimeThread), pRuntimeThread->GetDomain()));
9248
9249
9250 // We may be killing a thread before the Thread-starter fired.
9251 // So check (and cancel) any outstanding thread-starters.
9252 // If we don't, this old thread starter may conflict w/ a new thread-starter
9253 // if AppDomains or EE Thread's get recycled.
9254 DebuggerController::CancelOutstandingThreadStarter(pRuntimeThread);
9255
9256 // Controller lock is bigger than debugger lock.
9257 // Don't take debugger lock before the CancelOutStandingThreadStarter function.
9258 SENDIPCEVENT_BEGIN(this, pRuntimeThread);
9259
9260 if (CORDebuggerAttached())
9261 {
9262 // Send a detach thread event to the Right Side.
9263 DebuggerIPCEvent * pEvent = m_pRCThread->GetIPCEventSendBuffer();
9264
9265 InitIPCEvent(pEvent,
9266 DB_IPCE_THREAD_DETACH,
9267 pRuntimeThread,
9268 pRuntimeThread->GetDomain());
9269
9270 m_pRCThread->SendIPCEvent();
9271
9272 // Stop all Runtime threads
9273 TrapAllRuntimeThreads();
9274
9275 // This prevents a race condition where we blocked on the Lock()
9276 // above while another thread was sending an event and while we
9277 // were blocked the debugger suspended us and so we wouldn't be
9278 // resumed after the suspension about to happen below.
9279 pRuntimeThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
9280 }
9281 else
9282 {
9283 LOG((LF_CORDB,LL_INFO1000, "D::DT: Skipping SendIPCEvent because RS detached."));
9284 }
9285
9286 SENDIPCEVENT_END;
9287}
9288
9289
9290//
9291// SuspendComplete is called when the last Runtime thread reaches a safe point in response to having its trap flags set.
9292// This may be called on either the real helper thread or someone doing helper thread duty.
9293//
9294// It could also be called for sending garbage collection events (see DebuggerRCThread::SendIPCEvent for more about the
9295// thread mode associated with the events)
9296//
9297BOOL Debugger::SuspendComplete(bool isEESuspendedForGC)
9298{
9299 CONTRACTL
9300 {
9301 NOTHROW;
9302 if (isEESuspendedForGC) { GC_NOTRIGGER; } else { GC_TRIGGERS; }
9303 // This will is conceptually mode-cooperative.
9304 // But we haven't marked the runtime as stopped yet (m_stopped), so the contract
9305 // subsystem doesn't realize it yet.
9306 DISABLED(MODE_COOPERATIVE);
9307 }
9308 CONTRACTL_END;
9309
9310 // @@@
9311 // Call from RCThread::MainLoop and TemporaryHelperThreadMainLoop.
9312 // when all threads suspended. Can happen on managed thread or helper thread.
9313 // If happen on managed thread, it must be doing the helper thread duty.
9314 //
9315
9316 _ASSERTE(ThreadStore::HoldingThreadStore() || g_fProcessDetach);
9317
9318 // We should be holding debugger lock m_mutex.
9319 _ASSERTE(ThreadHoldsLock());
9320
9321 // We can't throw here (we're in the middle of the runtime suspension logic).
9322 // But things below us throw. So we catch the exception, but then what state are we in?
9323
9324 if (!isEESuspendedForGC) {_ASSERTE((!g_pEEInterface->GetThread() || !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) || g_fInControlC); }
9325 if (!isEESuspendedForGC) { _ASSERTE(ThisIsHelperThreadWorker()); }
9326
9327 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::SC: suspension complete\n");
9328
9329 // We have suspended runtime.
9330
9331 // We're stopped now. Marking m_stopped allows us to use MODE_COOPERATIVE contracts.
9332 if (isEESuspendedForGC)
9333 {
9334 _ASSERTE(!m_stopped);
9335 }
9336 else
9337 {
9338 _ASSERTE(!m_stopped && m_trappingRuntimeThreads);
9339 }
9340 m_stopped = true;
9341
9342
9343 // Send the sync complete event to the Right Side.
9344 {
9345 // If we fail to send the SyncComplete, what do we do?
9346 CONTRACT_VIOLATION(ThrowsViolation);
9347
9348 SendSyncCompleteIPCEvent(isEESuspendedForGC); // sets m_stopped = true...
9349 }
9350
9351 // Everything in the next scope is meant to mimic what we do UnlockForEventSending minus EnableEventHandling.
9352 // We do the EEH part when we get the Continue event.
9353 {
9354#ifdef _DEBUG
9355 //_ASSERTE(m_tidLockedForEventSending == GetCurrentThreadId());
9356 m_tidLockedForEventSending = 0;
9357#endif
9358
9359 //
9360 // Event handling is re-enabled by the RCThread in response to a
9361 // continue message from the Right Side.
9362
9363 }
9364
9365 // @todo - what should we do if this function failed?
9366 return TRUE;
9367}
9368
9369
9370
9371
9372//---------------------------------------------------------------------------------------
9373//
9374// Debugger::SendCreateAppDomainEvent - notify the RS of an AppDomain
9375//
9376// Arguments:
9377// pRuntimeAppdomain - pointer to the AppDomain
9378//
9379// Return Value:
9380// None
9381//
9382// Notes:
9383// This is used to notify the debugger of either a newly created
9384// AppDomain (when fAttaching is FALSE) or of existing AppDomains
9385// at attach time (fAttaching is TRUE). In both cases, this should
9386// be called before any LoadModule/LoadAssembly events are sent for
9387// this domain. Otherwise the RS will get an event for an AppDomain
9388// it doesn't recognize and ASSERT.
9389//
9390// For the non-attach case this means there is no need to enumerate
9391// the assemblies/modules in an AppDomain after sending this event
9392// because we know there won't be any.
9393//
9394
9395void Debugger::SendCreateAppDomainEvent(AppDomain * pRuntimeAppDomain)
9396{
9397 CONTRACTL
9398 {
9399 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9400 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9401
9402 MODE_COOPERATIVE;
9403 }
9404 CONTRACTL_END;
9405
9406 if (CORDBUnrecoverableError(this))
9407 {
9408 return;
9409 }
9410
9411 STRESS_LOG2(LF_CORDB, LL_INFO10000, "D::SCADE: AppDomain creation:%#08x, %#08x\n",
9412 pRuntimeAppDomain, pRuntimeAppDomain->GetId().m_dwId);
9413
9414
9415
9416 Thread *pThread = g_pEEInterface->GetThread();
9417 SENDIPCEVENT_BEGIN(this, pThread);
9418
9419
9420
9421 // We may have detached while waiting in LockForEventSending,
9422 // in which case we can't send the event.
9423 if (CORDebuggerAttached())
9424 {
9425 // Send a create appdomain event to the Right Side.
9426 DebuggerIPCEvent * pEvent = m_pRCThread->GetIPCEventSendBuffer();
9427
9428 InitIPCEvent(pEvent,
9429 DB_IPCE_CREATE_APP_DOMAIN,
9430 pThread,
9431 pRuntimeAppDomain);
9432
9433 // Only send a pointer to the AppDomain, the RS will get everything else via DAC.
9434 pEvent->AppDomainData.vmAppDomain.SetRawPtr(pRuntimeAppDomain);
9435 m_pRCThread->SendIPCEvent();
9436
9437 TrapAllRuntimeThreads();
9438 }
9439
9440 // Let other Runtime threads handle their events.
9441 SENDIPCEVENT_END;
9442
9443}
9444
9445
9446
9447
9448//
9449// SendExitAppDomainEvent is called when an app domain is destroyed.
9450//
9451void Debugger::SendExitAppDomainEvent(AppDomain* pRuntimeAppDomain)
9452{
9453 CONTRACTL
9454 {
9455 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9456 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9457 }
9458 CONTRACTL_END;
9459
9460 if (CORDBUnrecoverableError(this))
9461 return;
9462
9463 LOG((LF_CORDB, LL_INFO100, "D::EAD: Exit AppDomain 0x%08x.\n",
9464 pRuntimeAppDomain));
9465
9466 STRESS_LOG3(LF_CORDB, LL_INFO10000, "D::EAD: AppDomain exit:%#08x, %#08x, %#08x\n",
9467 pRuntimeAppDomain, pRuntimeAppDomain->GetId().m_dwId, CORDebuggerAttached());
9468
9469 Thread *thread = g_pEEInterface->GetThread();
9470 // Prevent other Runtime threads from handling events.
9471 SENDIPCEVENT_BEGIN(this, thread);
9472
9473 if (CORDebuggerAttached())
9474 {
9475 if (pRuntimeAppDomain->IsDefaultDomain() )
9476 {
9477 // The Debugger expects to never get an unload event for the default Domain.
9478 // Currently we should never get here because g_fProcessDetach will be true by
9479 // the time this method is called. However, we'd like to know if this ever changes
9480 _ASSERTE(!"Trying to deliver notification of unload for default domain" );
9481 return;
9482 }
9483
9484 // Send the exit appdomain event to the Right Side.
9485 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
9486 InitIPCEvent(ipce,
9487 DB_IPCE_EXIT_APP_DOMAIN,
9488 thread,
9489 pRuntimeAppDomain);
9490 m_pRCThread->SendIPCEvent();
9491
9492 // Delete any left over modules for this appdomain.
9493 // Note that we're doing this under the lock.
9494 if (m_pModules != NULL)
9495 {
9496 DebuggerDataLockHolder ch(this);
9497 m_pModules->RemoveModules(pRuntimeAppDomain);
9498 }
9499
9500 // Stop all Runtime threads
9501 TrapAllRuntimeThreads();
9502 }
9503 else
9504 {
9505 LOG((LF_CORDB,LL_INFO1000, "D::EAD: Skipping SendIPCEvent because RS detached."));
9506 }
9507
9508 SENDIPCEVENT_END;
9509}
9510
9511
9512
9513//
9514// LoadAssembly is called when a new Assembly gets loaded.
9515//
9516void Debugger::LoadAssembly(DomainAssembly * pDomainAssembly)
9517{
9518 CONTRACTL
9519 {
9520 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9521 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9522 }
9523 CONTRACTL_END;
9524
9525 if (CORDBUnrecoverableError(this))
9526 return;
9527
9528 LOG((LF_CORDB, LL_INFO100, "D::LA: Load Assembly Asy:0x%p AD:0x%p which:%ls\n",
9529 pDomainAssembly, pDomainAssembly->GetAppDomain(), pDomainAssembly->GetAssembly()->GetDebugName() ));
9530
9531 if (!CORDebuggerAttached())
9532 {
9533 return;
9534 }
9535
9536 Thread *pThread = g_pEEInterface->GetThread();
9537 SENDIPCEVENT_BEGIN(this, pThread)
9538
9539
9540 if (CORDebuggerAttached())
9541 {
9542 // Send a load assembly event to the Right Side.
9543 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
9544 InitIPCEvent(ipce,
9545 DB_IPCE_LOAD_ASSEMBLY,
9546 pThread,
9547 pDomainAssembly->GetAppDomain());
9548
9549 ipce->AssemblyData.vmDomainAssembly.SetRawPtr(pDomainAssembly);
9550
9551 m_pRCThread->SendIPCEvent();
9552 }
9553 else
9554 {
9555 LOG((LF_CORDB,LL_INFO1000, "D::LA: Skipping SendIPCEvent because RS detached."));
9556 }
9557
9558 // Stop all Runtime threads
9559 if (CORDebuggerAttached())
9560 {
9561 TrapAllRuntimeThreads();
9562 }
9563
9564 SENDIPCEVENT_END;
9565}
9566
9567
9568
9569//
9570// UnloadAssembly is called when a Runtime thread unloads an assembly.
9571//
9572void Debugger::UnloadAssembly(DomainAssembly * pDomainAssembly)
9573{
9574 CONTRACTL
9575 {
9576 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9577 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9578 }
9579 CONTRACTL_END;
9580
9581 if (CORDBUnrecoverableError(this))
9582 return;
9583
9584 LOG((LF_CORDB, LL_INFO100, "D::UA: Unload Assembly Asy:0x%p AD:0x%p which:%ls\n",
9585 pDomainAssembly, pDomainAssembly->GetAppDomain(), pDomainAssembly->GetAssembly()->GetDebugName() ));
9586
9587 Thread *thread = g_pEEInterface->GetThread();
9588 // Note that the debugger lock is reentrant, so we may or may not hold it already.
9589 SENDIPCEVENT_BEGIN(this, thread);
9590
9591 // Send the unload assembly event to the Right Side.
9592 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
9593
9594 InitIPCEvent(ipce,
9595 DB_IPCE_UNLOAD_ASSEMBLY,
9596 thread,
9597 pDomainAssembly->GetAppDomain());
9598 ipce->AssemblyData.vmDomainAssembly.SetRawPtr(pDomainAssembly);
9599
9600 SendSimpleIPCEventAndBlock();
9601
9602 // This will block on the continue
9603 SENDIPCEVENT_END;
9604
9605}
9606
9607
9608
9609
9610//
9611// LoadModule is called when a Runtime thread loads a new module and a debugger
9612// is attached. This also includes when a domain-neutral module is "loaded" into
9613// a new domain.
9614//
9615// TODO: remove pszModuleName and perhaps other args.
9616void Debugger::LoadModule(Module* pRuntimeModule,
9617 LPCWSTR pszModuleName, // module file name.
9618 DWORD dwModuleName, // length of pszModuleName in chars, not including null.
9619 Assembly *pAssembly,
9620 AppDomain *pAppDomain,
9621 DomainFile * pDomainFile,
9622 BOOL fAttaching)
9623{
9624
9625 CONTRACTL
9626 {
9627 NOTHROW; // not protected for Throws.
9628 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9629 }
9630 CONTRACTL_END;
9631
9632 // @@@@
9633 // Implement DebugInterface but can be called internally as well.
9634 // This can be called by EE loading module or when we are attaching called by IteratingAppDomainForAttaching
9635 //
9636 _ASSERTE(!fAttaching);
9637
9638 if (CORDBUnrecoverableError(this))
9639 return;
9640
9641 // If this is a dynamic module, then it's part of a multi-module assembly. The manifest
9642 // module within the assembly contains metadata for all the module names in the assembly.
9643 // When a new dynamic module is created, the manifest module's metadata is updated to
9644 // include the new module (see code:Assembly.CreateDynamicModule).
9645 // So we need to update the RS's copy of the metadata. One place the manifest module's
9646 // metadata gets used is in code:DacDbiInterfaceImpl.GetModuleSimpleName
9647 //
9648 // See code:ReflectionModule.CaptureModuleMetaDataToMemory for why we send the metadata-refresh here.
9649 if (pRuntimeModule->IsReflection() && !pRuntimeModule->IsManifest() && !fAttaching)
9650 {
9651 HRESULT hr = S_OK;
9652 EX_TRY
9653 {
9654 // The loader lookups may throw or togggle GC mode, so do them inside a TRY/Catch and
9655 // outside any debugger locks.
9656 Module * pManifestModule = pRuntimeModule->GetAssembly()->GetManifestModule();
9657
9658 _ASSERTE(pManifestModule != pRuntimeModule);
9659 _ASSERTE(pManifestModule->IsManifest());
9660 _ASSERTE(pManifestModule->GetAssembly() == pRuntimeModule->GetAssembly());
9661
9662 DomainFile * pManifestDomainFile = pManifestModule->GetDomainFile(pAppDomain);
9663
9664 DebuggerLockHolder dbgLockHolder(this);
9665
9666 // Raise the debug event.
9667 // This still tells the debugger that the manifest module metadata is invalid and needs to
9668 // be refreshed.
9669 DebuggerIPCEvent eventMetadataUpdate;
9670 InitIPCEvent(&eventMetadataUpdate, DB_IPCE_METADATA_UPDATE, NULL, pAppDomain);
9671
9672 eventMetadataUpdate.MetadataUpdateData.vmDomainFile.SetRawPtr(pManifestDomainFile);
9673
9674 SendRawEvent(&eventMetadataUpdate);
9675 }
9676 EX_CATCH_HRESULT(hr);
9677 SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
9678 }
9679
9680
9681 DebuggerModule * module = NULL;
9682
9683 Thread *pThread = g_pEEInterface->GetThread();
9684 SENDIPCEVENT_BEGIN(this, pThread);
9685
9686
9687
9688 DebuggerIPCEvent* ipce = NULL;
9689
9690 // Don't create new record if already loaded. We do still want to send the ModuleLoad event, however.
9691 // The RS has logic to ignore duplicate ModuleLoad events. We have to send what could possibly be a dup, though,
9692 // due to some really nasty issues with getting proper assembly and module load events from the loader when dealing
9693 // with shared assemblies.
9694 module = LookupOrCreateModule(pDomainFile);
9695 _ASSERTE(module != NULL);
9696
9697
9698 // During a real LoadModule event, debugger can change jit flags.
9699 // Can't do this during a fake event sent on attach.
9700 // This is cleared after we send the LoadModule event.
9701 module->SetCanChangeJitFlags(true);
9702
9703
9704 // @dbgtodo inspection - Check whether the DomainFile we get is consistent with the Module and AppDomain we get.
9705 // We should simply things when we actually get rid of DebuggerModule, possibly by just passing the
9706 // DomainFile around.
9707 _ASSERTE(module->GetDomainFile() == pDomainFile);
9708 _ASSERTE(module->GetAppDomain() == pDomainFile->GetAppDomain());
9709 _ASSERTE(module->GetRuntimeModule() == pDomainFile->GetModule());
9710
9711 // Send a load module event to the Right Side.
9712 ipce = m_pRCThread->GetIPCEventSendBuffer();
9713 InitIPCEvent(ipce,DB_IPCE_LOAD_MODULE, pThread, pAppDomain);
9714
9715 ipce->LoadModuleData.vmDomainFile.SetRawPtr(pDomainFile);
9716
9717 m_pRCThread->SendIPCEvent();
9718
9719 {
9720 // Stop all Runtime threads
9721 HRESULT hr = S_OK;
9722 EX_TRY
9723 {
9724 TrapAllRuntimeThreads();
9725 }
9726 EX_CATCH_HRESULT(hr); // @dbgtodo synchronization - catch exception and go on to restore state.
9727 // Synchronization feature crew needs to figure out what happens to TrapAllRuntimeThreads().
9728 }
9729
9730 SENDIPCEVENT_END;
9731
9732 // need to update pdb stream for SQL passed in pdb stream
9733 // regardless attach or not.
9734 //
9735 if (pRuntimeModule->IsIStream())
9736 {
9737 // Just ignore failures. Caller was just sending a debug event and we don't
9738 // want that to interop non-debugging functionality.
9739 HRESULT hr = S_OK;
9740 EX_TRY
9741 {
9742 SendUpdateModuleSymsEventAndBlock(pRuntimeModule, pAppDomain);
9743 }
9744 EX_CATCH_HRESULT(hr);
9745 }
9746
9747 // Now that we're done with the load module event, can no longer change Jit flags.
9748 module->SetCanChangeJitFlags(false);
9749}
9750
9751
9752//---------------------------------------------------------------------------------------
9753//
9754// Special LS-only notification that a module has reached the FILE_LOADED level. For now
9755// this is only useful to bind breakpoints in generic instantiations from NGENd modules
9756// that we couldn't bind earlier (at LoadModule notification time) because the method
9757// iterator refuses to consider modules earlier than the FILE_LOADED level. Normally
9758// generic instantiations would have their breakpoints bound when they get JITted, but in
9759// the case of NGEN that may never happen, so we need to bind them here.
9760//
9761// Arguments:
9762// * pRuntimeModule - Module that just loaded
9763// * pAppDomain - AD into which the Module was loaded
9764//
9765// Assumptions:
9766// This is called during the loading process, and blocks that process from
9767// completing. The module has reached the FILE_LOADED stage, but typically not yet
9768// the IsReadyForTypeLoad stage.
9769//
9770
9771void Debugger::LoadModuleFinished(Module * pRuntimeModule, AppDomain * pAppDomain)
9772{
9773 CONTRACTL
9774 {
9775 SUPPORTS_DAC;
9776 STANDARD_VM_CHECK;
9777 }
9778 CONTRACTL_END;
9779
9780 _ASSERTE(pRuntimeModule != NULL);
9781 _ASSERTE(pAppDomain != NULL);
9782
9783 if (CORDBUnrecoverableError(this))
9784 return;
9785
9786 // Just as an optimization, skip binding breakpoints if there's no debugger attached.
9787 // If a debugger attaches at some point after here, it will be able to bind patches
9788 // by making the request at that time. If a debugger detaches at some point after
9789 // here, there's no harm in having extra patches bound.
9790 if (!CORDebuggerAttached())
9791 return;
9792
9793 // For now, this notification only does interesting work if the module that loaded is
9794 // an NGENd module, because all we care about in this notification is ensuring NGENd
9795 // methods get breakpoints bound on them
9796 if (!pRuntimeModule->HasNativeImage())
9797 return;
9798
9799 // This notification is called just before MODULE_READY_FOR_TYPELOAD gets set. But
9800 // for shared modules (loaded into multiple domains), MODULE_READY_FOR_TYPELOAD has
9801 // already been set if this module was already loaded into an earlier domain. For
9802 // such cases, there's no need to bind breakpoints now because the module has already
9803 // been fully loaded into at least one domain, and breakpoint binding has already
9804 // been done for us
9805 if (pRuntimeModule->IsReadyForTypeLoad())
9806 return;
9807
9808#ifdef _DEBUG
9809 {
9810 // This notification is called once the module is loaded
9811 DomainFile * pDomainFile = pRuntimeModule->FindDomainFile(pAppDomain);
9812 _ASSERTE((pDomainFile != NULL) && (pDomainFile->GetLoadLevel() >= FILE_LOADED));
9813 }
9814#endif // _DEBUG
9815
9816 // Find all IL Master patches for this module, and bind & activate their
9817 // corresponding slave patches.
9818 {
9819 DebuggerController::ControllerLockHolder ch;
9820
9821 HASHFIND info;
9822 DebuggerPatchTable * pTable = DebuggerController::GetPatchTable();
9823
9824 for (DebuggerControllerPatch * pMasterPatchCur = pTable->GetFirstPatch(&info);
9825 pMasterPatchCur != NULL;
9826 pMasterPatchCur = pTable->GetNextPatch(&info))
9827 {
9828 if (!pMasterPatchCur->IsILMasterPatch())
9829 continue;
9830
9831 DebuggerMethodInfo *dmi = GetOrCreateMethodInfo(pMasterPatchCur->key.module, pMasterPatchCur->key.md);
9832
9833 // Found a relevant IL master patch. Now bind all corresponding slave patches
9834 // that belong to this Module
9835 DebuggerMethodInfo::DJIIterator it;
9836 dmi->IterateAllDJIs(pAppDomain, pRuntimeModule, pMasterPatchCur->pMethodDescFilter, &it);
9837 for (; !it.IsAtEnd(); it.Next())
9838 {
9839 DebuggerJitInfo *dji = it.Current();
9840 _ASSERTE(dji->m_jitComplete);
9841
9842 if (dji->m_encVersion != pMasterPatchCur->GetEnCVersion())
9843 continue;
9844
9845 // Do we already have a slave for this DJI & Controller? If so, no need
9846 // to add another one
9847 BOOL fSlaveExists = FALSE;
9848 HASHFIND f;
9849 for (DebuggerControllerPatch * pSlavePatchCur = pTable->GetFirstPatch(&f);
9850 pSlavePatchCur != NULL;
9851 pSlavePatchCur = pTable->GetNextPatch(&f))
9852 {
9853 if (pSlavePatchCur->IsILSlavePatch() &&
9854 (pSlavePatchCur->GetDJI() == dji) &&
9855 (pSlavePatchCur->controller == pMasterPatchCur->controller))
9856 {
9857 fSlaveExists = TRUE;
9858 break;
9859 }
9860 }
9861
9862 if (fSlaveExists)
9863 continue;
9864
9865 pMasterPatchCur->controller->AddBindAndActivateILSlavePatch(pMasterPatchCur, dji);
9866 }
9867 }
9868 }
9869}
9870
9871
9872// Send the raw event for Updating symbols. Debugger must query for contents from out-of-process
9873//
9874// Arguments:
9875// pRuntimeModule - required, module to send symbols for. May be domain neutral.
9876// pAppDomain - required, appdomain that module is in.
9877//
9878// Notes:
9879// This is just a ping event. Debugger must query for actual symbol contents.
9880// This keeps the launch + attach cases identical.
9881// This just sends the raw event and does not synchronize the runtime.
9882// Use code:Debugger.SendUpdateModuleSymsEventAndBlock for that.
9883void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *pAppDomain)
9884{
9885 CONTRACTL
9886 {
9887 NOTHROW;
9888 GC_NOTRIGGER;
9889 MODE_PREEMPTIVE;
9890
9891 PRECONDITION(ThreadHoldsLock());
9892
9893 // Debugger must have been attached to get us to this point.
9894 // We hold the Debugger-lock, so debugger could not have detached from
9895 // underneath us either.
9896 PRECONDITION(CORDebuggerAttached());
9897 }
9898 CONTRACTL_END;
9899
9900 if (CORDBUnrecoverableError(this))
9901 return;
9902
9903 // This event is used to trigger the ICorDebugManagedCallback::UpdateModuleSymbols
9904 // callback. That callback is defined to pass a PDB stream, and so we still use this
9905 // only for legacy compatibility reasons when we've actually got PDB symbols.
9906 // New clients know they must request a new symbol reader after ClassLoad events.
9907 if (pRuntimeModule->GetInMemorySymbolStreamFormat() != eSymbolFormatPDB)
9908 return; // Non-PDB symbols
9909
9910 DebuggerModule* module = LookupOrCreateModule(pRuntimeModule, pAppDomain);
9911 PREFIX_ASSUME(module != NULL);
9912
9913 DebuggerIPCEvent* ipce = NULL;
9914 ipce = m_pRCThread->GetIPCEventSendBuffer();
9915 InitIPCEvent(ipce, DB_IPCE_UPDATE_MODULE_SYMS,
9916 g_pEEInterface->GetThread(),
9917 pAppDomain);
9918
9919 ipce->UpdateModuleSymsData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL));
9920
9921 m_pRCThread->SendIPCEvent();
9922}
9923
9924//
9925// UpdateModuleSyms is called when the symbols for a module need to be
9926// sent to the Right Side because they've changed.
9927//
9928// Arguments:
9929// pRuntimeModule - required, module to send symbols for. May be domain neutral.
9930// pAppDomain - required, appdomain that module is in.
9931//
9932//
9933// Notes:
9934// This will send the event (via code:Debugger.SendRawUpdateModuleSymsEvent) and then synchronize
9935// the runtime waiting for a continue.
9936//
9937// This should only be called in cases where we reasonably expect to send symbols.
9938// However, this may not send symbols if the symbols aren't available.
9939void Debugger::SendUpdateModuleSymsEventAndBlock(Module* pRuntimeModule, AppDomain *pAppDomain)
9940{
9941 CONTRACTL
9942 {
9943 THROWS;
9944 GC_TRIGGERS;
9945 MODE_ANY;
9946 }
9947 CONTRACTL_END;
9948
9949 if (CORDBUnrecoverableError(this) || !CORDebuggerAttached())
9950 {
9951 return;
9952 }
9953
9954 CGrowableStream * pStream = pRuntimeModule->GetInMemorySymbolStream();
9955 LOG((LF_CORDB, LL_INFO10000, "D::UMS: update module syms RuntimeModule:0x%08x CGrowableStream:0x%08x\n", pRuntimeModule, pStream));
9956 if (pStream == NULL)
9957 {
9958 // No in-memory Pdb available.
9959 STRESS_LOG1(LF_CORDB, LL_INFO10000, "No syms available %p", pRuntimeModule);
9960 return;
9961 }
9962
9963 SENDIPCEVENT_BEGIN(this, g_pEEInterface->GetThread()); // toggles to preemptive
9964
9965 // Actually send the event
9966 if (CORDebuggerAttached())
9967 {
9968 SendRawUpdateModuleSymsEvent(pRuntimeModule, pAppDomain);
9969 TrapAllRuntimeThreads();
9970 }
9971
9972 SENDIPCEVENT_END;
9973}
9974
9975
9976//
9977// UnloadModule is called by the Runtime for each module (including shared ones)
9978// in an AppDomain that is being unloaded, when a debugger is attached.
9979// In the EE, a module may be domain-neutral and therefore shared across all AppDomains.
9980// We abstract this detail away in the Debugger and consider each such EE module to correspond
9981// to multiple "Debugger Module" instances (one per AppDomain).
9982// Therefore, this doesn't necessarily mean the runtime is unloading the module, just
9983// that the Debugger should consider it's (per-AppDomain) DebuggerModule to be unloaded.
9984//
9985void Debugger::UnloadModule(Module* pRuntimeModule,
9986 AppDomain *pAppDomain)
9987{
9988 CONTRACTL
9989 {
9990 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
9991 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
9992 }
9993 CONTRACTL_END;
9994
9995 // @@@@
9996 // implements DebugInterface.
9997 // can only called by EE on Module::NotifyDebuggerUnload
9998 //
9999
10000 if (CORDBUnrecoverableError(this))
10001 return;
10002
10003
10004
10005 LOG((LF_CORDB, LL_INFO100, "D::UM: unload module Mod:%#08x AD:%#08x runtimeMod:%#08x modName:%ls\n",
10006 LookupOrCreateModule(pRuntimeModule, pAppDomain), pAppDomain, pRuntimeModule, pRuntimeModule->GetDebugName()));
10007
10008
10009 Thread *thread = g_pEEInterface->GetThread();
10010 SENDIPCEVENT_BEGIN(this, thread);
10011
10012 if (CORDebuggerAttached())
10013 {
10014
10015 DebuggerModule* module = LookupOrCreateModule(pRuntimeModule, pAppDomain);
10016 if (module == NULL)
10017 {
10018 LOG((LF_CORDB, LL_INFO100, "D::UM: module already unloaded AD:%#08x runtimeMod:%#08x modName:%ls\n",
10019 pAppDomain, pRuntimeModule, pRuntimeModule->GetDebugName()));
10020 goto LExit;
10021 }
10022 _ASSERTE(module != NULL);
10023
10024 STRESS_LOG3(LF_CORDB, LL_INFO10000, "D::UM: Unloading Mod:%#08x, %#08x, %#08x\n",
10025 pRuntimeModule, pAppDomain, pRuntimeModule->IsIStream());
10026
10027 // Note: the appdomain the module was loaded in must match the appdomain we're unloading it from. If it doesn't,
10028 // then we've either found the wrong DebuggerModule in LookupModule or we were passed bad data.
10029 _ASSERTE(module->GetAppDomain() == pAppDomain);
10030
10031 // Send the unload module event to the Right Side.
10032 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
10033 InitIPCEvent(ipce, DB_IPCE_UNLOAD_MODULE, thread, pAppDomain);
10034 ipce->UnloadModuleData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL));
10035 ipce->UnloadModuleData.debuggerAssemblyToken.Set(pRuntimeModule->GetClassLoader()->GetAssembly());
10036 m_pRCThread->SendIPCEvent();
10037
10038 //
10039 // Cleanup the module (only for resources consumed when a debugger is attached)
10040 //
10041
10042 // Remove all patches that apply to this module/AppDomain combination
10043 AppDomain* domainToRemovePatchesIn = NULL; // all domains by default
10044
10045 // Note that we'll explicitly NOT delete DebuggerControllers, so that
10046 // the Right Side can delete them later.
10047 DebuggerController::RemovePatchesFromModule(pRuntimeModule, domainToRemovePatchesIn);
10048
10049 // Deactive all JMC functions in this module. We don't do this for shared assemblies
10050 // because JMC status is not maintained on a per-AppDomain basis and we don't
10051 // want to change the JMC behavior of the module in other domains.
10052 LOG((LF_CORDB, LL_EVERYTHING, "Setting all JMC methods to false:\n"));
10053 DebuggerDataLockHolder debuggerDataLockHolder(this);
10054 DebuggerMethodInfoTable * pTable = GetMethodInfoTable();
10055 if (pTable != NULL)
10056 {
10057 HASHFIND info;
10058
10059 for (DebuggerMethodInfo *dmi = pTable->GetFirstMethodInfo(&info);
10060 dmi != NULL;
10061 dmi = pTable->GetNextMethodInfo(&info))
10062 {
10063 if (dmi->m_module == pRuntimeModule)
10064 {
10065 dmi->SetJMCStatus(false);
10066 }
10067 }
10068 }
10069 LOG((LF_CORDB, LL_EVERYTHING, "Done clearing JMC methods!\n"));
10070
10071 // Delete the Left Side representation of the module.
10072 if (m_pModules != NULL)
10073 {
10074 DebuggerDataLockHolder chInfo(this);
10075 m_pModules->RemoveModule(pRuntimeModule, pAppDomain);
10076 }
10077
10078 // Stop all Runtime threads
10079 TrapAllRuntimeThreads();
10080 }
10081 else
10082 {
10083 LOG((LF_CORDB,LL_INFO1000, "D::UM: Skipping SendIPCEvent because RS detached."));
10084 }
10085
10086LExit:
10087 SENDIPCEVENT_END;
10088}
10089
10090// Called when this module is completely gone from ALL AppDomains, regardless of
10091// whether a debugger is attached.
10092// Note that this doesn't get called until after the ADUnload is complete, which happens
10093// asyncronously in Whidbey (and won't happen at all if the process shuts down first).
10094// This is normally not called only domain-neutral assemblies because they can't be unloaded.
10095// However, it may be called if the loader fails to completely load a domain-neutral assembly.
10096void Debugger::DestructModule(Module *pModule)
10097{
10098 CONTRACTL
10099 {
10100 NOTHROW;
10101 GC_NOTRIGGER;
10102 }
10103 CONTRACTL_END;
10104
10105 LOG((LF_CORDB, LL_INFO100, "D::DM: destruct module runtimeMod:%#08x modName:%ls\n",
10106 pModule, pModule->GetDebugName()));
10107
10108 // @@@
10109 // Implements DebugInterface.
10110 // It is called for Module::Destruct. We do not need to send any IPC event.
10111
10112 DebuggerLockHolder dbgLockHolder(this);
10113
10114 // We should have removed all patches at AD unload time (or detach time if the
10115 // debugger detached).
10116 _ASSERTE( !DebuggerController::ModuleHasPatches(pModule) );
10117
10118 // Do module clean-up that applies even when no debugger is attached.
10119 // Ideally, we might like to do this cleanup more eagerly and detministically,
10120 // but we don't currently get any early AD unload callback from the loader
10121 // when no debugger is attached. Perhaps we should make the loader
10122 // call this callback earlier.
10123 RemoveModuleReferences(pModule);
10124}
10125
10126
10127// Internal helper to remove all the DJIs / DMIs and other references for a given Module.
10128// If we don't remove the DJIs / DMIs, then we're subject to recycling bugs because the underlying
10129// MethodDescs will get removed. Thus we'll look up a new MD and it will pull up an old DMI that matched
10130// the old MD. Now the DMI and MD are out of sync and it's downhill from there.
10131// Note that DMIs may be used (and need cleanup) even when no debugger is attached.
10132void Debugger::RemoveModuleReferences( Module* pModule )
10133{
10134 _ASSERTE( ThreadHoldsLock() );
10135
10136 // We want to remove all references to the module from the various
10137 // tables. It's not just possible, but probable, that the module
10138 // will be re-loaded at the exact same address, and in that case,
10139 // we'll have piles of entries in our DJI table that mistakenly
10140 // match this new module.
10141 // Note that this doesn't apply to domain neutral assemblies, that only
10142 // get unloaded when the process dies. We won't be reclaiming their
10143 // DJIs/patches b/c the process is going to die, so we'll reclaim
10144 // the memory when the various hashtables are unloaded.
10145
10146 if (m_pMethodInfos != NULL)
10147 {
10148 HRESULT hr = S_OK;
10149 if (!HasLazyData())
10150 {
10151 hr = LazyInitWrapper();
10152 }
10153
10154 if (SUCCEEDED(hr))
10155 {
10156 DebuggerDataLockHolder debuggerDataLockHolder(this);
10157
10158 m_pMethodInfos->ClearMethodsOfModule(pModule);
10159
10160 // DebuggerDataLockHolder out of scope - release implied
10161 }
10162 }
10163}
10164
10165//---------------------------------------------------------------------------------------
10166//
10167// SendClassLoadUnloadEvent - notify the RS of a class either loading or unloading.
10168//
10169// Arguments:
10170//
10171// fAttaching - true if a debugger is in the process of attaching
10172//
10173// Return Value:
10174// None
10175//
10176//---------------------------------------------------------------------------------------
10177void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken,
10178 DebuggerModule * pClassDebuggerModule,
10179 Assembly *pAssembly,
10180 AppDomain *pAppDomain,
10181 BOOL fIsLoadEvent)
10182{
10183 CONTRACTL
10184 {
10185 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
10186 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
10187 }
10188 CONTRACTL_END;
10189
10190
10191 LOG((LF_CORDB,LL_INFO10000, "D::SCLUE: Tok:0x%x isLoad:0x%x Mod:%#08x AD:%#08x\n",
10192 classMetadataToken, fIsLoadEvent, pClassDebuggerModule, pAppDomain));
10193
10194 DebuggerIPCEvent * pEvent = m_pRCThread->GetIPCEventSendBuffer();
10195
10196 BOOL fIsReflection = pClassDebuggerModule->GetRuntimeModule()->IsReflection();
10197
10198 if (fIsLoadEvent == TRUE)
10199 {
10200 // We need to update Metadata before Symbols (since symbols depend on metadata)
10201 // It's debatable which needs to come first: Class Load or Sym update.
10202 // V1.1 sent Sym Update first so that binding at the class load has the latest symbols.
10203 // However, The Class Load may need to be in sync with updating new metadata,
10204 // and that has to come before the Sym update.
10205 InitIPCEvent(pEvent, DB_IPCE_LOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain);
10206
10207 pEvent->LoadClass.classMetadataToken = classMetadataToken;
10208 pEvent->LoadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL));
10209 pEvent->LoadClass.classDebuggerAssemblyToken.Set(pAssembly);
10210
10211
10212 // For class loads in dynamic modules, RS knows that the metadata has now grown and is invalid.
10213 // RS will re-fetch new metadata from out-of-process.
10214 }
10215 else
10216 {
10217 InitIPCEvent(pEvent, DB_IPCE_UNLOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain);
10218
10219 pEvent->UnloadClass.classMetadataToken = classMetadataToken;
10220 pEvent->UnloadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL));
10221 pEvent->UnloadClass.classDebuggerAssemblyToken.Set(pAssembly);
10222 }
10223
10224 m_pRCThread->SendIPCEvent();
10225
10226 if (fIsLoadEvent && fIsReflection)
10227 {
10228 // Send the raw event, but don't actually sync and block the runtime.
10229 SendRawUpdateModuleSymsEvent(pClassDebuggerModule->GetRuntimeModule(), pAppDomain);
10230 }
10231
10232}
10233
10234
10235
10236/******************************************************************************
10237 *
10238 ******************************************************************************/
10239BOOL Debugger::SendSystemClassLoadUnloadEvent(mdTypeDef classMetadataToken,
10240 Module *classModule,
10241 BOOL fIsLoadEvent)
10242{
10243 CONTRACTL
10244 {
10245 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
10246 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
10247 }
10248 CONTRACTL_END;
10249
10250 if (!m_dClassLoadCallbackCount)
10251 {
10252 return FALSE;
10253 }
10254
10255 BOOL fRetVal = FALSE;
10256
10257 Assembly *pAssembly = classModule->GetAssembly();
10258
10259 if (!m_pAppDomainCB->Lock())
10260 return (FALSE);
10261
10262 AppDomainInfo *pADInfo = m_pAppDomainCB->FindFirst();
10263
10264 while (pADInfo != NULL)
10265 {
10266 AppDomain *pAppDomain = pADInfo->m_pAppDomain;
10267 _ASSERTE(pAppDomain != NULL);
10268
10269 // Only notify for app domains where the module has been fully loaded already
10270 // We used to make a different check here domain->ContainsAssembly() but that
10271 // triggers too early in the loading process. FindDomainFile will not become
10272 // non-NULL until the module is fully loaded into the domain which is what we
10273 // want.
10274 if (classModule->FindDomainFile(pAppDomain) != NULL )
10275 {
10276 // Find the Left Side module that this class belongs in.
10277 DebuggerModule* pModule = LookupOrCreateModule(classModule, pAppDomain);
10278 _ASSERTE(pModule != NULL);
10279
10280 // Only send a class load event if they're enabled for this module.
10281 if (pModule && pModule->ClassLoadCallbacksEnabled())
10282 {
10283 SendClassLoadUnloadEvent(classMetadataToken,
10284 pModule,
10285 pAssembly,
10286 pAppDomain,
10287 fIsLoadEvent);
10288 fRetVal = TRUE;
10289 }
10290 }
10291
10292 pADInfo = m_pAppDomainCB->FindNext(pADInfo);
10293 }
10294
10295 m_pAppDomainCB->Unlock();
10296
10297 return fRetVal;
10298}
10299
10300
10301//
10302// LoadClass is called when a Runtime thread loads a new Class.
10303// Returns TRUE if an event is sent, FALSE otherwise
10304BOOL Debugger::LoadClass(TypeHandle th,
10305 mdTypeDef classMetadataToken,
10306 Module *classModule,
10307 AppDomain *pAppDomain)
10308{
10309 CONTRACTL
10310 {
10311 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
10312 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
10313 }
10314 CONTRACTL_END;
10315
10316 // @@@
10317 // Implements DebugInterface
10318 // This can be called by EE/Loader when class is loaded.
10319 //
10320
10321 BOOL fRetVal = FALSE;
10322
10323 if (CORDBUnrecoverableError(this))
10324 return FALSE;
10325
10326 // Note that pAppDomain may be null. The AppDomain isn't used here, and doesn't make a lot of sense since
10327 // we may be delivering the notification for a class in an assembly which is loaded into multiple AppDomains. We
10328 // handle this in SendSystemClassLoadUnloadEvent below by looping through all AppDomains and dispatching
10329 // events for each that contain this assembly.
10330
10331 LOG((LF_CORDB, LL_INFO10000, "D::LC: load class Tok:%#08x Mod:%#08x AD:%#08x classMod:%#08x modName:%ls\n",
10332 classMetadataToken, (pAppDomain == NULL) ? NULL : LookupOrCreateModule(classModule, pAppDomain),
10333 pAppDomain, classModule, classModule->GetDebugName()));
10334
10335 //
10336 // If we're attaching, then we only need to send the event. We
10337 // don't need to disable event handling or lock the debugger
10338 // object.
10339 //
10340 SENDIPCEVENT_BEGIN(this, g_pEEInterface->GetThread());
10341
10342 if (CORDebuggerAttached())
10343 {
10344 fRetVal = SendSystemClassLoadUnloadEvent(classMetadataToken, classModule, TRUE);
10345
10346 if (fRetVal == TRUE)
10347 {
10348 // Stop all Runtime threads
10349 TrapAllRuntimeThreads();
10350 }
10351 }
10352 else
10353 {
10354 LOG((LF_CORDB,LL_INFO1000, "D::LC: Skipping SendIPCEvent because RS detached."));
10355 }
10356
10357 SENDIPCEVENT_END;
10358
10359 return fRetVal;
10360}
10361
10362
10363//
10364// UnloadClass is called when a Runtime thread unloads a Class.
10365//
10366void Debugger::UnloadClass(mdTypeDef classMetadataToken,
10367 Module *classModule,
10368 AppDomain *pAppDomain)
10369{
10370 CONTRACTL
10371 {
10372 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
10373 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
10374 }
10375 CONTRACTL_END;
10376
10377 // @@@
10378 // Implements DebugInterface
10379 // Can only be called from EE
10380
10381 if (CORDBUnrecoverableError(this))
10382 {
10383 return;
10384 }
10385
10386 LOG((LF_CORDB, LL_INFO10000, "D::UC: unload class Tok:0x%08x Mod:%#08x AD:%#08x runtimeMod:%#08x modName:%ls\n",
10387 classMetadataToken, LookupOrCreateModule(classModule, pAppDomain), pAppDomain, classModule, classModule->GetDebugName()));
10388
10389 Assembly *pAssembly = classModule->GetClassLoader()->GetAssembly();
10390 DebuggerModule *pModule = LookupOrCreateModule(classModule, pAppDomain);
10391
10392 if ((pModule == NULL) || !pModule->ClassLoadCallbacksEnabled())
10393 {
10394 return;
10395 }
10396
10397 SENDIPCEVENT_BEGIN(this, g_pEEInterface->GetThread());
10398
10399 if (CORDebuggerAttached())
10400 {
10401 _ASSERTE((pAppDomain != NULL) && (pAssembly != NULL) && (pModule != NULL));
10402
10403 SendClassLoadUnloadEvent(classMetadataToken, pModule, pAssembly, pAppDomain, FALSE);
10404
10405 // Stop all Runtime threads
10406 TrapAllRuntimeThreads();
10407 }
10408 else
10409 {
10410 LOG((LF_CORDB,LL_INFO1000, "D::UC: Skipping SendIPCEvent because RS detached."));
10411 }
10412
10413 // Let other Runtime threads handle their events.
10414 SENDIPCEVENT_END;
10415
10416}
10417
10418/******************************************************************************
10419 *
10420 ******************************************************************************/
10421void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE)
10422{
10423 CONTRACTL
10424 {
10425 THROWS;
10426 GC_NOTRIGGER;
10427 }
10428 CONTRACTL_END;
10429
10430#ifndef DACCESS_COMPILE
10431
10432 if (CORDBUnrecoverableError(this))
10433 return;
10434
10435 LOG((LF_CORDB, LL_INFO1000, "D::FEC: func eval complete pDE:%p evalType:%d %s %s\n",
10436 pDE, pDE->m_evalType, pDE->m_successful ? "Success" : "Fail", pDE->m_aborted ? "Abort" : "Completed"));
10437
10438
10439 _ASSERTE(pDE->m_completed);
10440 _ASSERTE((g_pEEInterface->GetThread() && !g_pEEInterface->GetThread()->m_fPreemptiveGCDisabled) || g_fInControlC);
10441 _ASSERTE(ThreadHoldsLock());
10442
10443 // If we need to rethrow a ThreadAbortException then set the thread's state so we remember that.
10444 if (pDE->m_rethrowAbortException)
10445 {
10446 pThread->SetThreadStateNC(Thread::TSNC_DebuggerReAbort);
10447 }
10448
10449
10450 //
10451 // Get the domain that the result is valid in. The RS will cache this in the ICorDebugValue
10452 // Note: it's possible that the AppDomain has (or is about to be) unloaded, which could lead to a
10453 // crash when we use the DebuggerModule. Ideally we'd only be using AppDomain IDs here.
10454 // We can't easily convert our ADID to an AppDomain* (SystemDomain::GetAppDomainFromId)
10455 // because we can't proove that that the AppDomain* would be valid (not unloaded).
10456 //
10457 AppDomain *pDomain = pThread->GetDomain();
10458 AppDomain *pResultDomain = ((pDE->m_debuggerModule == NULL) ? pDomain : pDE->m_debuggerModule->GetAppDomain());
10459 _ASSERTE( pResultDomain->GetId() == pDE->m_appDomainId );
10460
10461 // Send a func eval complete event to the Right Side.
10462 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
10463 InitIPCEvent(ipce, DB_IPCE_FUNC_EVAL_COMPLETE, pThread, pDomain);
10464
10465 ipce->FuncEvalComplete.funcEvalKey = pDE->m_funcEvalKey;
10466 ipce->FuncEvalComplete.successful = pDE->m_successful;
10467 ipce->FuncEvalComplete.aborted = pDE->m_aborted;
10468 ipce->FuncEvalComplete.resultAddr = pDE->m_result;
10469 ipce->FuncEvalComplete.vmAppDomain.SetRawPtr(pResultDomain);
10470 ipce->FuncEvalComplete.vmObjectHandle = pDE->m_vmObjectHandle;
10471
10472 LOG((LF_CORDB, LL_INFO1000, "D::FEC: TypeHandle is %p\n", pDE->m_resultType.AsPtr()));
10473
10474 Debugger::TypeHandleToExpandedTypeInfo(pDE->m_retValueBoxing, // whether return values get boxed or not depends on the particular FuncEval we're doing...
10475 pResultDomain,
10476 pDE->m_resultType,
10477 &ipce->FuncEvalComplete.resultType);
10478
10479 _ASSERTE(ipce->FuncEvalComplete.resultType.elementType != ELEMENT_TYPE_VALUETYPE);
10480
10481 // We must adjust the result address to point to the right place
10482 ipce->FuncEvalComplete.resultAddr = ArgSlotEndianessFixup((ARG_SLOT*)ipce->FuncEvalComplete.resultAddr,
10483 GetSizeForCorElementType(ipce->FuncEvalComplete.resultType.elementType));
10484
10485 LOG((LF_CORDB, LL_INFO1000, "D::FEC: returned el %04x resultAddr %p\n",
10486 ipce->FuncEvalComplete.resultType.elementType, ipce->FuncEvalComplete.resultAddr));
10487
10488 m_pRCThread->SendIPCEvent();
10489
10490#endif
10491}
10492
10493/******************************************************************************
10494 *
10495 ******************************************************************************/
10496bool Debugger::ResumeThreads(AppDomain* pAppDomain)
10497{
10498 CONTRACTL
10499 {
10500 NOTHROW;
10501 GC_NOTRIGGER;
10502 PRECONDITION(ThisIsHelperThreadWorker());
10503 }
10504 CONTRACTL_END;
10505
10506 // Okay, mark that we're not stopped anymore and let the
10507 // Runtime threads go...
10508 ReleaseAllRuntimeThreads(pAppDomain);
10509
10510 // Return that we've continued the process.
10511 return true;
10512}
10513
10514
10515class CodeBuffer
10516{
10517public:
10518
10519 BYTE *getCodeBuffer(DebuggerJitInfo *dji)
10520 {
10521 CONTRACTL
10522 {
10523 NOTHROW;
10524 GC_NOTRIGGER;
10525 }
10526 CONTRACTL_END;
10527
10528 CodeRegionInfo codeRegionInfo = CodeRegionInfo::GetCodeRegionInfo(dji);
10529
10530 if (codeRegionInfo.getAddrOfColdCode())
10531 {
10532 _ASSERTE(codeRegionInfo.getSizeOfHotCode() != 0);
10533 _ASSERTE(codeRegionInfo.getSizeOfColdCode() != 0);
10534 S_SIZE_T totalSize = S_SIZE_T( codeRegionInfo.getSizeOfHotCode() ) +
10535 S_SIZE_T( codeRegionInfo.getSizeOfColdCode() );
10536 if ( totalSize.IsOverflow() )
10537 {
10538 _ASSERTE(0 && "Buffer overflow error in getCodeBuffer");
10539 return NULL;
10540 }
10541
10542 BYTE *code = (BYTE *) buffer.AllocNoThrow( totalSize.Value() );
10543 if (code)
10544 {
10545 memcpy(code,
10546 (void *) codeRegionInfo.getAddrOfHotCode(),
10547 codeRegionInfo.getSizeOfHotCode());
10548
10549 memcpy(code + codeRegionInfo.getSizeOfHotCode(),
10550 (void *) codeRegionInfo.getAddrOfColdCode(),
10551 codeRegionInfo.getSizeOfColdCode());
10552
10553 // Now patch the control transfer instructions
10554 }
10555
10556 return code;
10557 }
10558 else
10559 {
10560 return dac_cast<PTR_BYTE>(codeRegionInfo.getAddrOfHotCode());
10561 }
10562 }
10563private:
10564
10565 CQuickBytes buffer;
10566};
10567
10568
10569//---------------------------------------------------------------------------------------
10570//
10571// Called on the helper thread to serialize metadata so it can be read out-of-process.
10572//
10573// Arguments:
10574// pModule - module that needs metadata serialization
10575// countBytes - out value, holds the number of bytes which were allocated in the
10576// serialized buffer
10577//
10578// Return Value:
10579// A pointer to a serialized buffer of metadata. The caller should free this bufer using
10580// DeleteInteropSafe
10581//
10582// Assumptions:
10583// This is called on the helper-thread, or a thread pretending to be the helper-thread.
10584// For any synchronous message, the debuggee should be synchronized. The only async
10585// messages are Attach and Async-Break.
10586//
10587//
10588//---------------------------------------------------------------------------------------
10589BYTE* Debugger::SerializeModuleMetaData(Module * pModule, DWORD * countBytes)
10590{
10591 CONTRACTL
10592 {
10593 THROWS;
10594 GC_NOTRIGGER;
10595 }
10596 CONTRACTL_END;
10597
10598 LOG((LF_CORDB, LL_INFO10000, "Debugger::SMMD called\n"));
10599
10600 // Do not release the emitter. This is a weak reference.
10601 IMetaDataEmit *pEmitter = pModule->GetEmitter();
10602 _ASSERTE(pEmitter != NULL);
10603
10604 HRESULT hr;
10605 BYTE* metadataBuffer = NULL;
10606 ReleaseHolder<IMDInternalEmit> pInternalEmitter;
10607 ULONG originalUpdateMode;
10608 hr = pEmitter->QueryInterface(IID_IMDInternalEmit, (void **)&pInternalEmitter);
10609 if(FAILED(hr))
10610 {
10611 LOG((LF_CORDB, LL_INFO10, "Debugger::SMMD pEmitter doesn't support IID_IMDInternalEmit hr=0x%x\n", hr));
10612 ThrowHR(hr);
10613 }
10614 _ASSERTE(pInternalEmitter != NULL);
10615
10616 hr = pInternalEmitter->SetMDUpdateMode(MDUpdateExtension, &originalUpdateMode);
10617 if(FAILED(hr))
10618 {
10619 LOG((LF_CORDB, LL_INFO10, "Debugger::SMMD SetMDUpdateMode failed hr=0x%x\n", hr));
10620 ThrowHR(hr);
10621 }
10622 _ASSERTE(originalUpdateMode == MDUpdateFull);
10623
10624 hr = pEmitter->GetSaveSize(cssQuick, countBytes);
10625 if(FAILED(hr))
10626 {
10627 LOG((LF_CORDB, LL_INFO10, "Debugger::SMMD GetSaveSize failed hr=0x%x\n", hr));
10628 pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
10629 ThrowHR(hr);
10630 }
10631
10632 EX_TRY
10633 {
10634 metadataBuffer = new (interopsafe) BYTE[*countBytes];
10635 }
10636 EX_CATCH
10637 {
10638 LOG((LF_CORDB, LL_INFO10, "Debugger::SMMD Allocation failed\n"));
10639 pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
10640 EX_RETHROW;
10641 }
10642 EX_END_CATCH(SwallowAllExceptions);
10643 _ASSERTE(metadataBuffer != NULL); // allocation would throw first
10644
10645 // Caller ensures serialization that guarantees that the metadata doesn't grow underneath us.
10646 hr = pEmitter->SaveToMemory(metadataBuffer, *countBytes);
10647 if(FAILED(hr))
10648 {
10649 LOG((LF_CORDB, LL_INFO10, "Debugger::SMMD SaveToMemory failed hr=0x%x\n", hr));
10650 DeleteInteropSafe(metadataBuffer);
10651 pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
10652 ThrowHR(hr);
10653 }
10654
10655 pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
10656 LOG((LF_CORDB, LL_INFO10000, "Debugger::SMMD exiting\n"));
10657 return metadataBuffer;
10658}
10659
10660//---------------------------------------------------------------------------------------
10661//
10662// Handle an IPC event from the Debugger.
10663//
10664// Arguments:
10665// event - IPC event to handle.
10666//
10667// Return Value:
10668// True if the event was a continue. Else false.
10669//
10670// Assumptions:
10671// This is called on the helper-thread, or a thread pretending to be the helper-thread.
10672// For any synchronous message, the debuggee should be synchronized. The only async
10673// messages are Attach and Async-Break.
10674//
10675// Notes:
10676// HandleIPCEvent is called by the RC thread in response to an event
10677// from the Debugger Interface. No other IPC events, nor any Runtime
10678// events will come in until this method returns. Returns true if this
10679// was a Continue event.
10680//
10681// If this function is called on native debugger helper thread, we will
10682// handle everything. However if this is called on managed thread doing
10683// helper thread duty, we will fail on operation since we are mainly
10684// waiting for CONTINUE message from the RS.
10685//
10686//
10687//---------------------------------------------------------------------------------------
10688
10689#ifdef _PREFAST_
10690#pragma warning(push)
10691#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10692#endif
10693bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
10694{
10695 CONTRACTL
10696 {
10697 THROWS;
10698 if (g_pEEInterface->GetThread() != NULL) { GC_TRIGGERS; } else { GC_NOTRIGGER; }
10699
10700 PRECONDITION(ThisIsHelperThreadWorker());
10701
10702 if (m_stopped)
10703 {
10704 MODE_COOPERATIVE;
10705 }
10706 else
10707 {
10708 MODE_ANY;
10709 }
10710 }
10711 CONTRACTL_END;
10712
10713 // If we're the temporary helper thread, then we may reject certain operations.
10714 bool temporaryHelp = ThisIsTempHelperThread();
10715
10716
10717#ifdef _DEBUG
10718 // This reg key allows us to test our unhandled event filter installed in HandleIPCEventWrapper
10719 // to make sure it works properly.
10720 static int s_fDbgFaultInHandleIPCEvent = -1;
10721 if (s_fDbgFaultInHandleIPCEvent == -1)
10722 {
10723 s_fDbgFaultInHandleIPCEvent = UnsafeGetConfigDWORD(CLRConfig::INTERNAL_DbgFaultInHandleIPCEvent);
10724 }
10725
10726 // If we need to fault, let's generate an access violation.
10727 if (s_fDbgFaultInHandleIPCEvent)
10728 {
10729 *((volatile BYTE *)0) = 0;
10730 }
10731#endif
10732
10733 BOOL fSuccess;
10734 bool fContinue = false;
10735 HRESULT hr = S_OK;
10736
10737 LOG((LF_CORDB, LL_INFO10000, "D::HIPCE: got %s\n", IPCENames::GetName(pEvent->type)));
10738 DbgLog((DebuggerIPCEventType)(pEvent->type & DB_IPCE_TYPE_MASK));
10739
10740 // As for runtime is considered stopped, it means that managed threads will not
10741 // execute anymore managed code. However, these threads may be still running for
10742 // unmanaged code. So it is not true that we do not need to hold the lock while processing
10743 // synchrnoized event.
10744 //
10745 // The worst of all, it is the special case where user break point and exception can
10746 // be sent as part of attach if debugger was launched by managed app.
10747 //
10748 DebuggerLockHolder dbgLockHolder(this, FALSE);
10749 bool lockedThreadStore = false;
10750
10751 if ((pEvent->type & DB_IPCE_TYPE_MASK) == DB_IPCE_ASYNC_BREAK ||
10752 (pEvent->type & DB_IPCE_TYPE_MASK) == DB_IPCE_ATTACHING ||
10753 this->m_willBlockOnGarbageCollectionEvent)
10754 {
10755 if (!this->m_willBlockOnGarbageCollectionEvent && !this->m_stopped)
10756 {
10757 lockedThreadStore = true;
10758 ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_FOR_DEBUGGER);
10759 }
10760 dbgLockHolder.Acquire();
10761 }
10762 else
10763 {
10764 _ASSERTE(m_stopped);
10765 _ASSERTE(ThreadHoldsLock());
10766 }
10767
10768
10769 switch (pEvent->type & DB_IPCE_TYPE_MASK)
10770 {
10771
10772 case DB_IPCE_ATTACHING:
10773 // In V3, Attach is atomic, meaning that there isn't a complex handshake back and forth between LS + RS.
10774 // the RS sends a single-attaching event and attaches at the first response from the Left-side.
10775 StartCanaryThread();
10776
10777 // In V3 after attaching event was handled we iterate throughout all ADs and made shadow copies of PDBs in the BIN directories.
10778 // After all AppDomain, DomainAssembly and modules iteration was available in out-of-proccess model in V4 the code that enables
10779 // PDBs to be copied was not called at attach time.
10780 // Eliminating PDBs copying side effect is an issue: Dev10 #927143
10781 EX_TRY
10782 {
10783 IterateAppDomainsForPdbs();
10784 }
10785 EX_CATCH_HRESULT(hr); // ignore failures
10786
10787 if (m_jitAttachInProgress)
10788 {
10789 // For jit-attach, mark that we're attached now.
10790 // This lets callers to code:Debugger.JitAttach check the flag and
10791 // send the jit-attach event just like a normal event.
10792 MarkDebuggerAttachedInternal();
10793
10794 // set the managed attach event so that waiting threads can continue
10795 VERIFY(SetEvent(GetAttachEvent()));
10796 break;
10797 }
10798
10799 VERIFY(SetEvent(GetAttachEvent()));
10800
10801 //
10802 // For regular (non-jit) attach, fall through to do an async break.
10803 //
10804
10805 case DB_IPCE_ASYNC_BREAK:
10806 {
10807 if (temporaryHelp)
10808 {
10809 // Don't support async break on temporary helper thread.
10810 // Well, this function does not return HR. So this means that
10811 // ASYNC_BREAK event will be catching silently while we are
10812 // doing helper thread duty!
10813 //
10814 hr = CORDBG_E_NOTREADY;
10815 }
10816 else
10817 {
10818 // not synchornized. We get debugger lock upon the function entry
10819 _ASSERTE(ThreadHoldsLock());
10820
10821 // Simply trap all Runtime threads if we're not already trying to.
10822 if (!m_willBlockOnGarbageCollectionEvent && !m_trappingRuntimeThreads)
10823 {
10824 // If the RS sent an Async-break, then that's an explicit request.
10825 m_RSRequestedSync = TRUE;
10826 TrapAllRuntimeThreads(); // Non-blocking...
10827 }
10828 }
10829 break;
10830 }
10831
10832 case DB_IPCE_CONTINUE:
10833 {
10834 if (this->m_isBlockedOnGarbageCollectionEvent)
10835 {
10836 this->m_stopped = false;
10837 SetEvent(this->GetGarbageCollectionBlockerEvent());
10838 }
10839 else
10840 {
10841 fContinue = ResumeThreads(pEvent->vmAppDomain.GetRawPtr());
10842
10843 //
10844 // Go ahead and release the TSL now that we're continuing. This ensures that we've held
10845 // the thread store lock the entire time the Runtime was just stopped.
10846 //
10847 ThreadSuspend::UnlockThreadStore(FALSE, ThreadSuspend::SUSPEND_FOR_DEBUGGER);
10848 }
10849 GetCanary()->ClearCache();
10850 break;
10851 }
10852
10853 case DB_IPCE_BREAKPOINT_ADD:
10854 {
10855
10856 //
10857 // Currently, we can't create a breakpoint before a
10858 // function desc is available.
10859 // Also, we can't know if a breakpoint is ok
10860 // prior to the method being JITted.
10861 //
10862
10863 _ASSERTE(hr == S_OK);
10864 DebuggerBreakpoint * pDebuggerBP = NULL;
10865
10866 DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->BreakpointData.vmDomainFile);
10867 Module * pModule = pDebuggerModule->GetRuntimeModule();
10868 DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->BreakpointData.funcMetadataToken);
10869 MethodDesc * pMethodDesc = pEvent->BreakpointData.nativeCodeMethodDescToken.UnWrap();
10870
10871 DebuggerJitInfo * pDJI = NULL;
10872 if ((pMethodDesc != NULL) && (pDMI != NULL))
10873 {
10874 pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pMethodDesc, NULL /* startAddr */);
10875 }
10876
10877 {
10878 // If we haven't been either JITted or EnC'd yet, then
10879 // we'll put a patch in by offset, implicitly relative
10880 // to the first version of the code.
10881
10882 pDebuggerBP = new (interopsafe, nothrow) DebuggerBreakpoint(pModule,
10883 pEvent->BreakpointData.funcMetadataToken,
10884 pEvent->vmAppDomain.GetRawPtr(),
10885 pEvent->BreakpointData.offset,
10886 !pEvent->BreakpointData.isIL,
10887 pEvent->BreakpointData.encVersion,
10888 pMethodDesc,
10889 pDJI,
10890 pEvent->BreakpointData.nativeCodeMethodDescToken == NULL,
10891 &fSuccess);
10892
10893 TRACE_ALLOC(pDebuggerBP);
10894
10895 if ((pDebuggerBP != NULL) && !fSuccess)
10896 {
10897 DeleteInteropSafe(pDebuggerBP);
10898 pDebuggerBP = NULL;
10899 hr = CORDBG_E_UNABLE_TO_SET_BREAKPOINT;
10900 }
10901 }
10902
10903 if ((pDebuggerBP == NULL) && !FAILED(hr))
10904 {
10905 hr = E_OUTOFMEMORY;
10906 }
10907
10908 LOG((LF_CORDB,LL_INFO10000,"\tBP Add: BPTOK:"
10909 "0x%x, tok=0x%08x, offset=0x%x, isIL=%d dm=0x%x m=0x%x\n",
10910 pDebuggerBP,
10911 pEvent->BreakpointData.funcMetadataToken,
10912 pEvent->BreakpointData.offset,
10913 pEvent->BreakpointData.isIL,
10914 pDebuggerModule,
10915 pModule));
10916
10917 //
10918 // We're using a two-way event here, so we place the
10919 // result event into the _receive_ buffer, not the send
10920 // buffer.
10921 //
10922
10923 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
10924
10925 InitIPCEvent(pIPCResult,
10926 DB_IPCE_BREAKPOINT_ADD_RESULT,
10927 g_pEEInterface->GetThread(),
10928 pEvent->vmAppDomain);
10929
10930 pIPCResult->BreakpointData.breakpointToken.Set(pDebuggerBP);
10931 pIPCResult->hr = hr;
10932
10933 m_pRCThread->SendIPCReply();
10934 }
10935 break;
10936
10937 case DB_IPCE_STEP:
10938 {
10939 LOG((LF_CORDB,LL_INFO10000, "D::HIPCE: stepIn:0x%x frmTok:0x%x"
10940 "StepIn:0x%x RangeIL:0x%x RangeCount:0x%x MapStop:0x%x "
10941 "InterceptStop:0x%x AppD:0x%x\n",
10942 pEvent->StepData.stepIn,
10943 pEvent->StepData.frameToken.GetSPValue(),
10944 pEvent->StepData.stepIn,
10945 pEvent->StepData.rangeIL,
10946 pEvent->StepData.rangeCount,
10947 pEvent->StepData.rgfMappingStop,
10948 pEvent->StepData.rgfInterceptStop,
10949 pEvent->vmAppDomain.GetRawPtr()));
10950
10951 // <TODO>@todo memory allocation - bad if we're synced</TODO>
10952 Thread * pThread = pEvent->StepData.vmThreadToken.GetRawPtr();
10953 AppDomain * pAppDomain = pEvent->vmAppDomain.GetRawPtr();
10954
10955 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
10956
10957 InitIPCEvent(pIPCResult,
10958 DB_IPCE_STEP_RESULT,
10959 pThread,
10960 pEvent->vmAppDomain);
10961
10962 if (temporaryHelp)
10963 {
10964 // Can't step on the temporary helper thread.
10965 pIPCResult->hr = CORDBG_E_NOTREADY;
10966 }
10967 else
10968 {
10969 DebuggerStepper * pStepper;
10970
10971 if (pEvent->StepData.IsJMCStop)
10972 {
10973 pStepper = new (interopsafe, nothrow) DebuggerJMCStepper(pThread,
10974 pEvent->StepData.rgfMappingStop,
10975 pEvent->StepData.rgfInterceptStop,
10976 pAppDomain);
10977 }
10978 else
10979 {
10980 pStepper = new (interopsafe, nothrow) DebuggerStepper(pThread,
10981 pEvent->StepData.rgfMappingStop,
10982 pEvent->StepData.rgfInterceptStop,
10983 pAppDomain);
10984 }
10985
10986 if (pStepper == NULL)
10987 {
10988 pIPCResult->hr = E_OUTOFMEMORY;
10989
10990 m_pRCThread->SendIPCReply();
10991
10992 break;
10993 }
10994 TRACE_ALLOC(pStepper);
10995
10996 unsigned int cRanges = pEvent->StepData.totalRangeCount;
10997
10998 _ASSERTE(cRanges == 0 || ((cRanges > 0) && (cRanges == pEvent->StepData.rangeCount)));
10999
11000 if (!pStepper->Step(pEvent->StepData.frameToken,
11001 pEvent->StepData.stepIn,
11002 &(pEvent->StepData.range),
11003 cRanges,
11004 ((cRanges > 0) ? pEvent->StepData.rangeIL : false)))
11005 {
11006 pIPCResult->hr = E_OUTOFMEMORY;
11007
11008 m_pRCThread->SendIPCReply();
11009
11010 DeleteInteropSafe(pStepper);
11011 break;
11012 }
11013
11014 pIPCResult->StepData.stepperToken.Set(pStepper);
11015
11016
11017 } // end normal step case.
11018
11019
11020 m_pRCThread->SendIPCReply();
11021 }
11022 break;
11023
11024 case DB_IPCE_STEP_OUT:
11025 {
11026 // <TODO>@todo memory allocation - bad if we're synced</TODO>
11027 Thread * pThread = pEvent->StepData.vmThreadToken.GetRawPtr();
11028 AppDomain * pAppDomain = pEvent->vmAppDomain.GetRawPtr();
11029
11030 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
11031
11032 InitIPCEvent(pIPCResult,
11033 DB_IPCE_STEP_RESULT,
11034 pThread,
11035 pAppDomain);
11036
11037 if (temporaryHelp)
11038 {
11039 // Can't step on the temporary helper thread.
11040 pIPCResult->hr = CORDBG_E_NOTREADY;
11041 }
11042 else
11043 {
11044 DebuggerStepper * pStepper;
11045
11046 if (pEvent->StepData.IsJMCStop)
11047 {
11048 pStepper = new (interopsafe, nothrow) DebuggerJMCStepper(pThread,
11049 pEvent->StepData.rgfMappingStop,
11050 pEvent->StepData.rgfInterceptStop,
11051 pAppDomain);
11052 }
11053 else
11054 {
11055 pStepper = new (interopsafe, nothrow) DebuggerStepper(pThread,
11056 pEvent->StepData.rgfMappingStop,
11057 pEvent->StepData.rgfInterceptStop,
11058 pAppDomain);
11059 }
11060
11061
11062 if (pStepper == NULL)
11063 {
11064 pIPCResult->hr = E_OUTOFMEMORY;
11065 m_pRCThread->SendIPCReply();
11066
11067 break;
11068 }
11069
11070 TRACE_ALLOC(pStepper);
11071
11072 // Safe to stack trace b/c we're stopped.
11073 StackTraceTicket ticket(pThread);
11074
11075 pStepper->StepOut(pEvent->StepData.frameToken, ticket);
11076
11077 pIPCResult->StepData.stepperToken.Set(pStepper);
11078 }
11079
11080 m_pRCThread->SendIPCReply();
11081 }
11082 break;
11083
11084 case DB_IPCE_BREAKPOINT_REMOVE:
11085 {
11086 // <TODO>@todo memory allocation - bad if we're synced</TODO>
11087
11088 DebuggerBreakpoint * pDebuggerBP = pEvent->BreakpointData.breakpointToken.UnWrap();
11089
11090 pDebuggerBP->Delete();
11091 }
11092 break;
11093
11094 case DB_IPCE_STEP_CANCEL:
11095 {
11096 // <TODO>@todo memory allocation - bad if we're synced</TODO>
11097 LOG((LF_CORDB,LL_INFO10000, "D:HIPCE:Got STEP_CANCEL for stepper 0x%p\n",
11098 pEvent->StepData.stepperToken.UnWrap()));
11099
11100 DebuggerStepper * pStepper = pEvent->StepData.stepperToken.UnWrap();
11101
11102 pStepper->Delete();
11103 }
11104 break;
11105
11106 case DB_IPCE_SET_ALL_DEBUG_STATE:
11107 {
11108 Thread * pThread = pEvent->SetAllDebugState.vmThreadToken.GetRawPtr();
11109 CorDebugThreadState debugState = pEvent->SetAllDebugState.debugState;
11110
11111 LOG((LF_CORDB,LL_INFO10000,"HandleIPCE: SetAllDebugState: except thread 0x%08x (ID:0x%x) to state 0x%x\n",
11112 pThread,
11113 (pThread != NULL) ? GetThreadIdHelper(pThread) : 0,
11114 debugState));
11115
11116 if (!g_fProcessDetach)
11117 {
11118 g_pEEInterface->SetAllDebugState(pThread, debugState);
11119 }
11120
11121 STRESS_LOG1(LF_CORDB,LL_INFO10000,"HandleIPC: Got 0x%x back from SetAllDebugState\n", hr);
11122
11123 // Just send back an HR.
11124 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
11125
11126 PREFIX_ASSUME(pIPCResult != NULL);
11127
11128 InitIPCEvent(pIPCResult, DB_IPCE_SET_DEBUG_STATE_RESULT, NULL, NULL);
11129
11130 pIPCResult->hr = S_OK;
11131
11132 m_pRCThread->SendIPCReply();
11133 }
11134 break;
11135
11136 case DB_IPCE_GET_GCHANDLE_INFO:
11137 // Given an unvalidated GC-handle, find out all the info about it to view the object
11138 // at the other end
11139 {
11140 OBJECTHANDLE objectHandle = pEvent->GetGCHandleInfo.GCHandle.GetRawPtr();
11141
11142 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
11143
11144 PREFIX_ASSUME(pIPCResult != NULL);
11145
11146 InitIPCEvent(pIPCResult, DB_IPCE_GET_GCHANDLE_INFO_RESULT, NULL, NULL);
11147
11148 bool fValid = SUCCEEDED(ValidateGCHandle(objectHandle));
11149
11150 AppDomain * pAppDomain = NULL;
11151
11152 if(fValid)
11153 {
11154 // Get the appdomain
11155 IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
11156 ADIndex appDomainIndex = ADIndex(reinterpret_cast<DWORD>(mgr->GetHandleContext(objectHandle)));
11157 pAppDomain = SystemDomain::GetAppDomainAtIndex(appDomainIndex);
11158
11159 _ASSERTE(pAppDomain != NULL);
11160 }
11161
11162 pIPCResult->hr = S_OK;
11163 pIPCResult->GetGCHandleInfoResult.vmAppDomain.SetRawPtr(pAppDomain);
11164 pIPCResult->GetGCHandleInfoResult.fValid = fValid;
11165
11166 m_pRCThread->SendIPCReply();
11167
11168 }
11169 break;
11170
11171 case DB_IPCE_GET_BUFFER:
11172 {
11173 GetAndSendBuffer(m_pRCThread, pEvent->GetBuffer.bufSize);
11174 }
11175 break;
11176
11177 case DB_IPCE_RELEASE_BUFFER:
11178 {
11179 SendReleaseBuffer(m_pRCThread, pEvent->ReleaseBuffer.pBuffer);
11180 }
11181 break;
11182#ifdef EnC_SUPPORTED
11183 case DB_IPCE_APPLY_CHANGES:
11184 {
11185 LOG((LF_ENC, LL_INFO100, "D::HIPCE: DB_IPCE_APPLY_CHANGES 1\n"));
11186
11187 DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->ApplyChanges.vmDomainFile);
11188 //
11189 // @todo handle error.
11190 //
11191 hr = ApplyChangesAndSendResult(pDebuggerModule,
11192 pEvent->ApplyChanges.cbDeltaMetadata,
11193 (BYTE*) CORDB_ADDRESS_TO_PTR(pEvent->ApplyChanges.pDeltaMetadata),
11194 pEvent->ApplyChanges.cbDeltaIL,
11195 (BYTE*) CORDB_ADDRESS_TO_PTR(pEvent->ApplyChanges.pDeltaIL));
11196
11197 LOG((LF_ENC, LL_INFO100, "D::HIPCE: DB_IPCE_APPLY_CHANGES 2\n"));
11198 }
11199 break;
11200#endif // EnC_SUPPORTED
11201
11202 case DB_IPCE_SET_CLASS_LOAD_FLAG:
11203 {
11204 DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainFile);
11205
11206 _ASSERTE(pDebuggerModule != NULL);
11207
11208 LOG((LF_CORDB, LL_INFO10000,
11209 "D::HIPCE: class load flag is %d for module 0x%p\n",
11210 pEvent->SetClassLoad.flag,
11211 pDebuggerModule));
11212
11213 pDebuggerModule->EnableClassLoadCallbacks((BOOL)pEvent->SetClassLoad.flag);
11214 }
11215 break;
11216
11217 case DB_IPCE_IS_TRANSITION_STUB:
11218 GetAndSendTransitionStubInfo((CORDB_ADDRESS_TYPE*)pEvent->IsTransitionStub.address);
11219 break;
11220
11221 case DB_IPCE_MODIFY_LOGSWITCH:
11222 g_pEEInterface->DebuggerModifyingLogSwitch (pEvent->LogSwitchSettingMessage.iLevel,
11223 pEvent->LogSwitchSettingMessage.szSwitchName.GetString());
11224
11225 break;
11226
11227 case DB_IPCE_ENABLE_LOG_MESSAGES:
11228 {
11229 bool fOnOff = pEvent->LogSwitchSettingMessage.iLevel ? true : false;
11230 EnableLogMessages (fOnOff);
11231 }
11232 break;
11233
11234 case DB_IPCE_SET_IP:
11235
11236 {
11237 // This is a synchronous event (reply required)
11238 DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
11239
11240 // Don't have an explicit reply msg
11241 InitIPCReply(pIPCResult, DB_IPCE_SET_IP);
11242
11243 if (temporaryHelp)
11244 {
11245 pIPCResult->hr = CORDBG_E_NOTREADY;
11246 }
11247 else if (!g_fProcessDetach)
11248 {
11249 //
11250 // Since this pointer is coming from the RS, it may be NULL or something
11251 // unexpected in an OOM situation. Quickly just sanity check them.
11252 //
11253 Thread * pThread = pEvent->SetIP.vmThreadToken.GetRawPtr();
11254 Module * pModule = pEvent->SetIP.vmDomainFile.GetRawPtr()->GetModule();
11255
11256 // Get the DJI for this function
11257 DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->SetIP.mdMethod);
11258 DebuggerJitInfo * pDJI = NULL;
11259 if (pDMI != NULL)
11260 {
11261 // In the EnC case, if we look for an older version, we need to find the DJI by starting
11262 // address, rather than just by MethodDesc. In the case of generics, we may need to create a DJI, so we
11263 pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pEvent->SetIP.vmMethodDesc.GetRawPtr(),
11264 PINSTRToPCODE((TADDR)pEvent->SetIP.startAddress));
11265 }
11266
11267 if ((pDJI != NULL) && (pThread != NULL) && (pModule != NULL))
11268 {
11269 CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&(pIPCResult->hr), GetCanary());
11270
11271 if (SUCCEEDED(pIPCResult->hr))
11272 {
11273 pIPCResult->hr = SetIP(pEvent->SetIP.fCanSetIPOnly,
11274 pThread,
11275 pModule,
11276 pEvent->SetIP.mdMethod,
11277 pDJI,
11278 pEvent->SetIP.offset,
11279 pEvent->SetIP.fIsIL
11280 );
11281 }
11282 }
11283 else
11284 {
11285 pIPCResult->hr = E_INVALIDARG;
11286 }
11287 }
11288 else
11289 {
11290 pIPCResult->hr = S_OK;
11291 }
11292
11293 // Send the result
11294 m_pRCThread->SendIPCReply();
11295 }
11296 break;
11297
11298 case DB_IPCE_DETACH_FROM_PROCESS:
11299 LOG((LF_CORDB, LL_INFO10000, "Detaching from process!\n"));
11300
11301 // Delete all controllers (remove patches etc.)
11302 DebuggerController::DeleteAllControllers();
11303 // Note that we'd like to be able to do this assert here
11304 // _ASSERTE(DebuggerController::GetNumberOfPatches() == 0);
11305 // However controllers may get queued for deletion if there is outstanding
11306 // work and so we can't gaurentee the deletion will complete now.
11307 // @dbgtodo inspection: This shouldn't be an issue in the complete V3 architecture
11308
11309 MarkDebuggerUnattachedInternal();
11310
11311 m_pRCThread->RightSideDetach();
11312
11313
11314 // Clear JMC status
11315 {
11316 LOG((LF_CORDB, LL_EVERYTHING, "Setting all JMC methods to false:\n"));
11317 // On detach, set all DMI's JMC status to false.
11318 // We have to do this b/c we clear the DebuggerModules and allocated
11319 // new ones on re-attach; and the DMI & DM need to be in sync
11320 // (in this case, agreeing that JMC-status = false).
11321 // This also syncs the EE modules and disables all JMC probes.
11322 DebuggerMethodInfoTable * pMethodInfoTable = g_pDebugger->GetMethodInfoTable();
11323
11324 if (pMethodInfoTable != NULL)
11325 {
11326 HASHFIND hashFind;
11327 DebuggerDataLockHolder debuggerDataLockHolder(this);
11328
11329 for (DebuggerMethodInfo * pMethodInfo = pMethodInfoTable->GetFirstMethodInfo(&hashFind);
11330 pMethodInfo != NULL;
11331 pMethodInfo = pMethodInfoTable->GetNextMethodInfo(&hashFind))
11332 {
11333 pMethodInfo->SetJMCStatus(false);
11334 }
11335 }
11336 LOG((LF_CORDB, LL_EVERYTHING, "Done clearing JMC methods!\n"));
11337 }
11338
11339 // Clean up the hash of DebuggerModules
11340 // This method is overridden to also free all DebuggerModule objects
11341 if (m_pModules != NULL)
11342 {
11343
11344 // Removes all DebuggerModules
11345 DebuggerDataLockHolder ch(this);
11346 m_pModules->Clear();
11347
11348 }
11349
11350 // Reply to the detach message before we release any Runtime threads. This ensures that the debugger will get
11351 // the detach reply before the process exits if the main thread is near exiting.
11352 m_pRCThread->SendIPCReply();
11353
11354 if (this->m_isBlockedOnGarbageCollectionEvent)
11355 {
11356 this->m_stopped = FALSE;
11357 SetEvent(this->GetGarbageCollectionBlockerEvent());
11358 }
11359 else
11360 {
11361 // Let the process run free now... there is no debugger to bother it anymore.
11362 fContinue = ResumeThreads(pEvent->vmAppDomain.GetRawPtr());
11363
11364 //
11365 // Go ahead and release the TSL now that we're continuing. This ensures that we've held
11366 // the thread store lock the entire time the Runtime was just stopped.
11367 //
11368 ThreadSuspend::UnlockThreadStore(FALSE, ThreadSuspend::SUSPEND_FOR_DEBUGGER);
11369 }
11370
11371 break;
11372
11373#ifndef DACCESS_COMPILE
11374
11375 case DB_IPCE_FUNC_EVAL:
11376 {
11377 // This is a synchronous event (reply required)
11378 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11379
11380 Thread * pThread = pEvent->FuncEval.vmThreadToken.GetRawPtr();
11381
11382 InitIPCEvent(pEvent, DB_IPCE_FUNC_EVAL_SETUP_RESULT, pThread, pThread->GetDomain());
11383
11384 BYTE * pbArgDataArea = NULL;
11385 DebuggerEval * pDebuggerEvalKey = NULL;
11386
11387 pEvent->hr = FuncEvalSetup(&(pEvent->FuncEval), &pbArgDataArea, &pDebuggerEvalKey);
11388
11389 // Send the result of how the func eval setup went.
11390 pEvent->FuncEvalSetupComplete.argDataArea = PTR_TO_CORDB_ADDRESS(pbArgDataArea);
11391 pEvent->FuncEvalSetupComplete.debuggerEvalKey.Set(pDebuggerEvalKey);
11392
11393 m_pRCThread->SendIPCReply();
11394 }
11395
11396 break;
11397
11398#endif
11399
11400 case DB_IPCE_SET_REFERENCE:
11401 {
11402 // This is a synchronous event (reply required)
11403 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11404
11405 InitIPCReply(pEvent, DB_IPCE_SET_REFERENCE_RESULT);
11406
11407 pEvent->hr = SetReference(pEvent->SetReference.objectRefAddress,
11408 pEvent->SetReference.vmObjectHandle,
11409 pEvent->SetReference.newReference);
11410
11411 // Send the result of how the set reference went.
11412 m_pRCThread->SendIPCReply();
11413 }
11414 break;
11415
11416 case DB_IPCE_SET_VALUE_CLASS:
11417 {
11418 // This is a synchronous event (reply required)
11419 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11420
11421 InitIPCReply(pEvent, DB_IPCE_SET_VALUE_CLASS_RESULT);
11422
11423 pEvent->hr = SetValueClass(pEvent->SetValueClass.oldData,
11424 pEvent->SetValueClass.newData,
11425 &pEvent->SetValueClass.type);
11426
11427 // Send the result of how the set reference went.
11428 m_pRCThread->SendIPCReply();
11429 }
11430 break;
11431
11432 case DB_IPCE_GET_THREAD_FOR_TASKID:
11433 {
11434 Thread *pThreadRet = NULL;
11435
11436 // This is a synchronous event (reply required)
11437 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11438
11439 InitIPCReply(pEvent, DB_IPCE_GET_THREAD_FOR_TASKID_RESULT);
11440
11441 pEvent->GetThreadForTaskIdResult.vmThreadToken.SetRawPtr(pThreadRet);
11442 pEvent->hr = S_OK;
11443
11444 m_pRCThread->SendIPCReply();
11445 }
11446 break;
11447
11448 case DB_IPCE_CREATE_HANDLE:
11449 {
11450 Object * pObject = (Object*)pEvent->CreateHandle.objectToken;
11451 OBJECTREF objref = ObjectToOBJECTREF(pObject);
11452 AppDomain * pAppDomain = pEvent->vmAppDomain.GetRawPtr();
11453 BOOL fStrong = pEvent->CreateHandle.fStrong;
11454 OBJECTHANDLE objectHandle;
11455
11456 // This is a synchronous event (reply required)
11457 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11458
11459 InitIPCReply(pEvent, DB_IPCE_CREATE_HANDLE_RESULT);
11460
11461 {
11462 // Handle creation may need to allocate memory.
11463 // The API specifically limits the number of handls Cordbg can create,
11464 // so we could preallocate and fail allocating anything beyond that.
11465 CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&(pEvent->hr), GetCanary());
11466
11467 if (SUCCEEDED(pEvent->hr))
11468 {
11469 if (fStrong == TRUE)
11470 {
11471 // create strong handle
11472 objectHandle = pAppDomain->CreateStrongHandle(objref);
11473 }
11474 else
11475 {
11476 // create the weak long handle
11477 objectHandle = pAppDomain->CreateLongWeakHandle(objref);
11478 }
11479 pEvent->CreateHandleResult.vmObjectHandle.SetRawPtr(objectHandle);
11480 }
11481 }
11482
11483 m_pRCThread->SendIPCReply();
11484 break;
11485 }
11486
11487 case DB_IPCE_DISPOSE_HANDLE:
11488 {
11489 // DISPOSE an object handle
11490 OBJECTHANDLE objectHandle = pEvent->DisposeHandle.vmObjectHandle.GetRawPtr();
11491
11492 if (pEvent->DisposeHandle.fStrong == TRUE)
11493 {
11494 DestroyStrongHandle(objectHandle);
11495 }
11496 else
11497 {
11498 DestroyLongWeakHandle(objectHandle);
11499 }
11500 break;
11501 }
11502
11503#ifndef DACCESS_COMPILE
11504
11505 case DB_IPCE_FUNC_EVAL_ABORT:
11506 {
11507 LOG((LF_CORDB, LL_INFO1000, "D::HIPCE: Got FuncEvalAbort for pDE:%08x\n",
11508 pEvent->FuncEvalAbort.debuggerEvalKey.UnWrap()));
11509
11510 // This is a synchronous event (reply required)
11511
11512 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11513 InitIPCReply(pEvent,DB_IPCE_FUNC_EVAL_ABORT_RESULT);
11514
11515 pEvent->hr = FuncEvalAbort(pEvent->FuncEvalAbort.debuggerEvalKey.UnWrap());
11516
11517 m_pRCThread->SendIPCReply();
11518 }
11519 break;
11520
11521 case DB_IPCE_FUNC_EVAL_RUDE_ABORT:
11522 {
11523 LOG((LF_CORDB, LL_INFO1000, "D::HIPCE: Got FuncEvalRudeAbort for pDE:%08x\n",
11524 pEvent->FuncEvalRudeAbort.debuggerEvalKey.UnWrap()));
11525
11526 // This is a synchronous event (reply required)
11527
11528 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11529
11530 InitIPCReply(pEvent, DB_IPCE_FUNC_EVAL_RUDE_ABORT_RESULT);
11531
11532 pEvent->hr = FuncEvalRudeAbort(pEvent->FuncEvalRudeAbort.debuggerEvalKey.UnWrap());
11533
11534 m_pRCThread->SendIPCReply();
11535 }
11536 break;
11537
11538 case DB_IPCE_FUNC_EVAL_CLEANUP:
11539
11540 // This is a synchronous event (reply required)
11541
11542 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11543
11544 InitIPCReply(pEvent,DB_IPCE_FUNC_EVAL_CLEANUP_RESULT);
11545
11546 pEvent->hr = FuncEvalCleanup(pEvent->FuncEvalCleanup.debuggerEvalKey.UnWrap());
11547
11548 m_pRCThread->SendIPCReply();
11549
11550 break;
11551
11552#endif
11553
11554 case DB_IPCE_CONTROL_C_EVENT_RESULT:
11555 {
11556 // store the result of whether the event has been handled by the debugger and
11557 // wake up the thread waiting for the result
11558 SetDebuggerHandlingCtrlC(pEvent->hr == S_OK);
11559 VERIFY(SetEvent(GetCtrlCMutex()));
11560 }
11561 break;
11562
11563 // Set the JMC status on invididual methods
11564 case DB_IPCE_SET_METHOD_JMC_STATUS:
11565 {
11566 // Get the info out of the event
11567 DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile);
11568 Module * pModule = pDebuggerModule->GetRuntimeModule();
11569
11570 bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0);
11571
11572 mdMethodDef token = pEvent->SetJMCFunctionStatus.funcMetadataToken;
11573
11574 // Prepare reply
11575 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11576
11577 InitIPCEvent(pEvent, DB_IPCE_SET_METHOD_JMC_STATUS_RESULT, NULL, NULL);
11578
11579 pEvent->hr = S_OK;
11580
11581 if (pDebuggerModule->HasAnyOptimizedCode() && fStatus)
11582 {
11583 // If there's optimized code, then we can't be set JMC status to true.
11584 // That's because JMC probes are not injected in optimized code, and we
11585 // need a JMC probe to have a JMC function.
11586 pEvent->hr = CORDBG_E_CANT_SET_TO_JMC;
11587 }
11588 else
11589 {
11590 DebuggerDataLockHolder debuggerDataLockHolder(this);
11591 // This may be called on an unjitted method, so we may
11592 // have to create the MethodInfo.
11593 DebuggerMethodInfo * pMethodInfo = GetOrCreateMethodInfo(pModule, token);
11594
11595 if (pMethodInfo == NULL)
11596 {
11597 pEvent->hr = E_OUTOFMEMORY;
11598 }
11599 else
11600 {
11601 // Update the storage on the LS
11602 pMethodInfo->SetJMCStatus(fStatus);
11603 }
11604 }
11605
11606 // Send reply
11607 m_pRCThread->SendIPCReply();
11608 }
11609 break;
11610
11611 // Get the JMC status on a given function
11612 case DB_IPCE_GET_METHOD_JMC_STATUS:
11613 {
11614 // Get the method
11615 DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile);
11616
11617 Module * pModule = pDebuggerModule->GetRuntimeModule();
11618
11619 mdMethodDef token = pEvent->SetJMCFunctionStatus.funcMetadataToken;
11620
11621 // Init reply
11622 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11623 InitIPCEvent(pEvent, DB_IPCE_GET_METHOD_JMC_STATUS_RESULT, NULL, NULL);
11624
11625 //
11626 // This may be called on an unjitted method, so we may
11627 // have to create the MethodInfo.
11628 //
11629 DebuggerMethodInfo * pMethodInfo = GetOrCreateMethodInfo(pModule, token);
11630
11631 if (pMethodInfo == NULL)
11632 {
11633 pEvent->hr = E_OUTOFMEMORY;
11634 }
11635 else
11636 {
11637 bool fStatus = pMethodInfo->IsJMCFunction();
11638 pEvent->SetJMCFunctionStatus.dwStatus = fStatus;
11639 pEvent->hr = S_OK;
11640 }
11641
11642 m_pRCThread->SendIPCReply();
11643 }
11644 break;
11645
11646 case DB_IPCE_SET_MODULE_JMC_STATUS:
11647 {
11648 // Get data out of event
11649 DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile);
11650
11651 bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0);
11652
11653 // Prepare reply
11654 pEvent = m_pRCThread->GetIPCEventReceiveBuffer();
11655
11656 InitIPCReply(pEvent, DB_IPCE_SET_MODULE_JMC_STATUS_RESULT);
11657
11658 pEvent->hr = S_OK;
11659
11660 if (pDebuggerModule->HasAnyOptimizedCode() && fStatus)
11661 {
11662 // If there's optimized code, then we can't be set JMC status to true.
11663 // That's because JMC probes are not injected in optimized code, and we
11664 // need a JMC probe to have a JMC function.
11665 pEvent->hr = CORDBG_E_CANT_SET_TO_JMC;
11666 }
11667 else
11668 {
11669 g_pDebugger->SetModuleDefaultJMCStatus(pDebuggerModule->GetRuntimeModule(), fStatus);
11670 }
11671
11672
11673
11674 // Send reply
11675 m_pRCThread->SendIPCReply();
11676 }
11677 break;
11678
11679
11680 case DB_IPCE_INTERCEPT_EXCEPTION:
11681 GetAndSendInterceptCommand(pEvent);
11682 break;
11683
11684 case DB_IPCE_RESOLVE_UPDATE_METADATA_1:
11685 {
11686
11687 LOG((LF_CORDB, LL_INFO10000, "D::HIPCE Handling DB_IPCE_RESOLVE_UPDATE_METADATA_1\n"));
11688 // This isn't ideal - Making SerializeModuleMetaData not call new is hard,
11689 // but the odds of trying to load a module after a thread is stopped w/
11690 // the heap lock should be pretty low.
11691 // All of the metadata calls can violate this and call new.
11692 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
11693
11694 Module * pModule = pEvent->MetadataUpdateRequest.vmModule.GetRawPtr();
11695 LOG((LF_CORDB, LL_INFO100000, "D::HIPCE Got module 0x%x\n", pModule));
11696
11697 DWORD countBytes = 0;
11698
11699 // This will allocate memory. Debugger will then copy from here and send a
11700 // DB_IPCE_RESOLVE_UPDATE_METADATA_2 to free this memory.
11701 BYTE* pData = NULL;
11702 EX_TRY
11703 {
11704 LOG((LF_CORDB, LL_INFO100000, "D::HIPCE Calling SerializeModuleMetaData\n"));
11705 pData = SerializeModuleMetaData(pModule, &countBytes);
11706
11707 }
11708 EX_CATCH_HRESULT(hr);
11709
11710 LOG((LF_CORDB, LL_INFO100000, "D::HIPCE hr is 0x%x\n", hr));
11711
11712 DebuggerIPCEvent * pResult = m_pRCThread->GetIPCEventReceiveBuffer();
11713 InitIPCEvent(pResult, DB_IPCE_RESOLVE_UPDATE_METADATA_1_RESULT, NULL, NULL);
11714
11715 pResult->MetadataUpdateRequest.pMetadataStart = pData;
11716 pResult->MetadataUpdateRequest.nMetadataSize = countBytes;
11717 pResult->hr = hr;
11718 LOG((LF_CORDB, LL_INFO1000000, "D::HIPCE metadataStart=0x%x, nMetadataSize=0x%x\n", pData, countBytes));
11719
11720 m_pRCThread->SendIPCReply();
11721 LOG((LF_CORDB, LL_INFO1000000, "D::HIPCE reply sent\n"));
11722 }
11723 break;
11724
11725 case DB_IPCE_RESOLVE_UPDATE_METADATA_2:
11726 {
11727 // Delete memory allocated with DB_IPCE_RESOLVE_UPDATE_METADATA_1.
11728 BYTE * pData = (BYTE *) pEvent->MetadataUpdateRequest.pMetadataStart;
11729 DeleteInteropSafe(pData);
11730
11731 DebuggerIPCEvent * pResult = m_pRCThread->GetIPCEventReceiveBuffer();
11732 InitIPCEvent(pResult, DB_IPCE_RESOLVE_UPDATE_METADATA_2_RESULT, NULL, NULL);
11733 pResult->hr = S_OK;
11734 m_pRCThread->SendIPCReply();
11735 }
11736
11737 break;
11738
11739 default:
11740 // We should never get an event that we don't know about.
11741 CONSISTENCY_CHECK_MSGF(false, ("Unknown Debug-Event on LS:id=0x%08x.", pEvent->type));
11742 LOG((LF_CORDB, LL_INFO10000, "Unknown event type: 0x%08x\n",
11743 pEvent->type));
11744 }
11745
11746 STRESS_LOG0(LF_CORDB, LL_INFO10000, "D::HIPCE: finished handling event\n");
11747
11748 if (lockedThreadStore)
11749 {
11750 ThreadSuspend::UnlockThreadStore(FALSE, ThreadSuspend::SUSPEND_FOR_DEBUGGER);
11751 }
11752 // dbgLockHolder goes out of scope - implicit Release
11753 return fContinue;
11754}
11755#ifdef _PREFAST_
11756#pragma warning(pop)
11757#endif
11758
11759/*
11760 * GetAndSendInterceptCommand
11761 *
11762 * This function processes an INTERCEPT_EXCEPTION IPC event, sending the appropriate response.
11763 *
11764 * Parameters:
11765 * event - the event to process.
11766 *
11767 * Returns:
11768 * hr - HRESULT.
11769 *
11770 */
11771HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event)
11772{
11773 CONTRACTL
11774 {
11775 THROWS;
11776 GC_TRIGGERS_FROM_GETJITINFO;
11777 }
11778 CONTRACTL_END;
11779
11780 HRESULT hr = S_OK;
11781
11782 _ASSERTE((event->type & DB_IPCE_TYPE_MASK) == DB_IPCE_INTERCEPT_EXCEPTION);
11783
11784 //
11785 // Simple state validation first.
11786 //
11787 Thread *pThread = event->InterceptException.vmThreadToken.GetRawPtr();
11788
11789 if ((pThread != NULL) &&
11790 !m_forceNonInterceptable &&
11791 IsInterceptableException(pThread))
11792 {
11793 ThreadExceptionState* pExState = pThread->GetExceptionState();
11794
11795 // We can only have one interception going on at any given time.
11796 if (!pExState->GetFlags()->DebuggerInterceptInfo())
11797 {
11798 //
11799 // Now start processing the parameters from the event.
11800 //
11801 FramePointer targetFramePointer = event->InterceptException.frameToken;
11802
11803 ControllerStackInfo csi;
11804
11805 // Safe because we're stopped.
11806 StackTraceTicket ticket(pThread);
11807 csi.GetStackInfo(ticket, pThread, targetFramePointer, NULL);
11808
11809 if (csi.m_targetFrameFound)
11810 {
11811 //
11812 // If the target frame is below the point where the current exception was
11813 // thrown from, then we should reject this interception command. This
11814 // can happen in a func-eval during an exception callback, or during a
11815 // breakpoint in a filter function. Or it can just be a user error.
11816 //
11817 CONTEXT* pContext = pExState->GetContextRecord();
11818
11819 // This is an approximation on IA64, where we should use the caller SP instead of
11820 // the current SP. However, if the targetFramePointer is valid, the comparison should
11821 // still work. targetFramePointer should be valid because it ultimately comes from a
11822 // full stackwalk.
11823 FramePointer excepFramePointer = FramePointer::MakeFramePointer(GetSP(pContext));
11824
11825 if (IsCloserToRoot(excepFramePointer, targetFramePointer))
11826 {
11827 hr = CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE;
11828 goto LSendResponse;
11829 }
11830
11831
11832 //
11833 // If the instruction that faulted is not in this managed code, at the leaf
11834 // frame, then the IP is actually the return address from the managed or
11835 // unmanaged function that really did fault. Thus, we actually want the
11836 // IP of the call instruction. I fake this by simply subtracting 1 from
11837 // the IP, which is close enough approximation for the search below.
11838 //
11839 if (pExState->GetContextRecord() != NULL)
11840 {
11841 // If the faulting instruction is not in managed code, then the interception frame
11842 // must be non-leaf.
11843 if (!g_pEEInterface->IsManagedNativeCode((BYTE *)(GetIP(pExState->GetContextRecord()))))
11844 {
11845 csi.m_activeFrame.relOffset--;
11846 }
11847 else
11848 {
11849 MethodDesc *pMethodDesc = g_pEEInterface->GetNativeCodeMethodDesc(dac_cast<PCODE>(GetIP(pExState->GetContextRecord())));
11850
11851 // check if the interception frame is the leaf frame
11852 if ((pMethodDesc == NULL) ||
11853 (pMethodDesc != csi.m_activeFrame.md) ||
11854 (GetSP(pExState->GetContextRecord()) != GetRegdisplaySP(&(csi.m_activeFrame.registers))))
11855 {
11856 csi.m_activeFrame.relOffset--;
11857 }
11858 }
11859 }
11860
11861 //
11862 // Now adjust the IP to be the previous zero-stack depth sequence point.
11863 //
11864 SIZE_T foundOffset = 0;
11865 DebuggerJitInfo *pJitInfo = csi.m_activeFrame.GetJitInfoFromFrame();
11866
11867 if (pJitInfo != NULL)
11868 {
11869 ICorDebugInfo::SourceTypes src;
11870
11871 ULONG relOffset = csi.m_activeFrame.relOffset;
11872
11873#if defined(WIN64EXCEPTIONS)
11874 int funcletIndex = PARENT_METHOD_INDEX;
11875
11876 // For funclets, we need to make sure that the stack empty sequence point we use is
11877 // in the same funclet as the current offset.
11878 if (csi.m_activeFrame.IsFuncletFrame())
11879 {
11880 funcletIndex = pJitInfo->GetFuncletIndex(relOffset, DebuggerJitInfo::GFIM_BYOFFSET);
11881 }
11882
11883 // Refer to the loop using pMap below.
11884 DebuggerILToNativeMap* pMap = NULL;
11885#endif // WIN64EXCEPTIONS
11886
11887 for (unsigned int i = 0; i < pJitInfo->GetSequenceMapCount(); i++)
11888 {
11889 SIZE_T startOffset = pJitInfo->GetSequenceMap()[i].nativeStartOffset;
11890
11891 if (DbgIsSpecialILOffset(pJitInfo->GetSequenceMap()[i].ilOffset))
11892 {
11893 LOG((LF_CORDB, LL_INFO10000,
11894 "D::HIPCE: not placing breakpoint at special offset 0x%x\n", startOffset));
11895 continue;
11896 }
11897
11898 if ((i >= 1) && (startOffset == pJitInfo->GetSequenceMap()[i-1].nativeStartOffset))
11899 {
11900 LOG((LF_CORDB, LL_INFO10000,
11901 "D::HIPCE: not placing redundant breakpoint at duplicate offset 0x%x\n", startOffset));
11902 continue;
11903 }
11904
11905 if (startOffset > relOffset)
11906 {
11907 LOG((LF_CORDB, LL_INFO10000,
11908 "D::HIPCE: Stopping scan for breakpoint at offset 0x%x\n", startOffset));
11909 continue;
11910 }
11911
11912 src = pJitInfo->GetSequenceMap()[i].source;
11913
11914 if (!(src & ICorDebugInfo::STACK_EMPTY))
11915 {
11916 LOG((LF_CORDB, LL_INFO10000, "D::HIPCE: not placing E&C breakpoint at offset "
11917 "0x%x b/c not STACK_EMPTY:it's 0x%x\n", startOffset, src));
11918 continue;
11919 }
11920
11921 if ((foundOffset < startOffset) && (startOffset <= relOffset)
11922#if defined(WIN64EXCEPTIONS)
11923 // Check if we are still in the same funclet.
11924 && (funcletIndex == pJitInfo->GetFuncletIndex(startOffset, DebuggerJitInfo::GFIM_BYOFFSET))
11925#endif // WIN64EXCEPTIONS
11926 )
11927 {
11928 LOG((LF_CORDB, LL_INFO10000, "D::HIPCE: updating breakpoint at native offset 0x%x\n",
11929 startOffset));
11930 foundOffset = startOffset;
11931#if defined(WIN64EXCEPTIONS)
11932 // Save the map entry for modification later.
11933 pMap = &(pJitInfo->GetSequenceMap()[i]);
11934#endif // WIN64EXCEPTIONS
11935 }
11936 }
11937
11938#if defined(WIN64EXCEPTIONS)
11939 // This is nasty. Starting recently we could have multiple sequence points with the same IL offset
11940 // in the SAME funclet/parent method (previously different sequence points with the same IL offset
11941 // imply that they are in different funclet/parent method). Fortunately, we only run into this
11942 // if we have a loop which throws a range check failed exception. The code for throwing the
11943 // exception executes out of line (this is JIT-specific, of course). The following loop makes sure
11944 // that when we interecept the exception, we intercept it at the smallest native offset instead
11945 // of intercepting it right before we throw the exception.
11946 for (/* no initialization */; pMap > pJitInfo->GetSequenceMap() ; pMap--)
11947 {
11948 if (pMap->ilOffset == (pMap-1)->ilOffset)
11949 {
11950 foundOffset = (pMap-1)->nativeStartOffset;
11951 }
11952 else
11953 {
11954 break;
11955 }
11956 }
11957 _ASSERTE(foundOffset < relOffset);
11958#endif // WIN64EXCEPTIONS
11959
11960 //
11961 // Set up a breakpoint on the intercept IP
11962 //
11963 DebuggerContinuableExceptionBreakpoint *pBreakpoint;
11964
11965 pBreakpoint = new (interopsafe, nothrow) DebuggerContinuableExceptionBreakpoint(pThread,
11966 foundOffset,
11967 pJitInfo,
11968 csi.m_activeFrame.currentAppDomain
11969 );
11970
11971 if (pBreakpoint != NULL)
11972 {
11973 //
11974 // Set up the VM side of intercepting.
11975 //
11976 if (pExState->GetDebuggerState()->SetDebuggerInterceptInfo(csi.m_activeFrame.pIJM,
11977 pThread,
11978 csi.m_activeFrame.MethodToken,
11979 csi.m_activeFrame.md,
11980 foundOffset,
11981#if defined (_TARGET_ARM_ )|| defined (_TARGET_ARM64_ )
11982 // ARM requires the caller stack pointer, not the current stack pointer
11983 CallerStackFrame::FromRegDisplay(&(csi.m_activeFrame.registers)),
11984#else
11985 StackFrame::FromRegDisplay(&(csi.m_activeFrame.registers)),
11986#endif
11987 pExState->GetFlags()
11988 ))
11989 {
11990 //
11991 // Make sure no more exception callbacks come thru.
11992 //
11993 pExState->GetFlags()->SetSentDebugFirstChance();
11994 pExState->GetFlags()->SetSentDebugUserFirstChance();
11995 pExState->GetFlags()->SetSentDebugUnwindBegin();
11996
11997 //
11998 // Save off this breakpoint, so that if the exception gets unwound before we hit
11999 // the breakpoint - the exception info can call back to remove it.
12000 //
12001 pExState->GetDebuggerState()->SetDebuggerInterceptContext((void *)pBreakpoint);
12002
12003 hr = S_OK;
12004 }
12005 else // VM could not set up for intercept
12006 {
12007 DeleteInteropSafe(pBreakpoint);
12008 hr = E_INVALIDARG;
12009 }
12010
12011 }
12012 else // could not allocate for breakpoint
12013 {
12014 hr = E_OUTOFMEMORY;
12015 }
12016
12017 }
12018 else // could not get JitInfo
12019 {
12020 hr = E_FAIL;
12021 }
12022
12023 }
12024 else // target frame not found.
12025 {
12026 hr = E_INVALIDARG;
12027 }
12028
12029 }
12030 else // already set up for an intercept.
12031 {
12032 hr = CORDBG_E_INTERCEPT_FRAME_ALREADY_SET;
12033 }
12034
12035 }
12036 else if (pThread == NULL)
12037 {
12038 hr = E_INVALIDARG; // pThread is NULL.
12039 }
12040 else
12041 {
12042 hr = CORDBG_E_NONINTERCEPTABLE_EXCEPTION;
12043 }
12044
12045LSendResponse:
12046
12047 //
12048 // Prepare reply
12049 //
12050 event = m_pRCThread->GetIPCEventReceiveBuffer();
12051 InitIPCReply(event, DB_IPCE_INTERCEPT_EXCEPTION_RESULT);
12052 event->hr = hr;
12053
12054 //
12055 // Send reply
12056 //
12057 m_pRCThread->SendIPCReply();
12058
12059 return hr;
12060}
12061
12062// Poll & wait for the real helper thread to come up.
12063// It's possible that the helper thread is blocked by DllMain, and so we can't
12064// Wait infinite. If this poll does timeout, then it just means we're likely
12065// go do helper duty instead of have the real helper do it.
12066void Debugger::PollWaitingForHelper()
12067{
12068
12069 LOG((LF_CORDB, LL_INFO10000, "PollWaitingForHelper() start\n"));
12070
12071 DebuggerIPCControlBlock * pDCB = g_pRCThread->GetDCB();
12072
12073 PREFIX_ASSUME(pDCB != NULL);
12074
12075 int nTotalMSToWait = 8 * 1000;
12076
12077 // Spin waiting for either the real helper thread or a temp. to be ready.
12078 // This should never timeout unless the helper is blocked on the loader lock.
12079 while (!pDCB->m_helperThreadId && !pDCB->m_temporaryHelperThreadId)
12080 {
12081 STRESS_LOG1(LF_CORDB,LL_INFO1000, "PollWaitForHelper. %d\n", nTotalMSToWait);
12082
12083 // If we hold the lock, we'll block the helper thread and this poll is not useful
12084 _ASSERTE(!ThreadHoldsLock());
12085
12086 const DWORD dwTime = 50;
12087 ClrSleepEx(dwTime, FALSE);
12088 nTotalMSToWait -= dwTime;
12089
12090 if (nTotalMSToWait <= 0)
12091 {
12092 LOG((LF_CORDB, LL_INFO10000, "PollWaitingForHelper() timeout\n"));
12093 return;
12094 }
12095 }
12096
12097 LOG((LF_CORDB, LL_INFO10000, "PollWaitingForHelper() succeed\n"));
12098 return;
12099}
12100
12101
12102
12103
12104void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, DebuggerIPCE_BasicTypeData *res)
12105{
12106 CONTRACTL
12107 {
12108 THROWS;
12109 GC_NOTRIGGER;
12110 }
12111 CONTRACTL_END;
12112
12113 LOG((LF_CORDB, LL_INFO10000, "D::THTBTI: converting left-side type handle to basic right-side type info, ELEMENT_TYPE: %d.\n", th.GetSignatureCorElementType()));
12114 // GetSignatureCorElementType returns E_T_CLASS for E_T_STRING... :-(
12115 if (th.IsNull())
12116 {
12117 res->elementType = ELEMENT_TYPE_VOID;
12118 }
12119 else if (th.GetMethodTable() == g_pObjectClass)
12120 {
12121 res->elementType = ELEMENT_TYPE_OBJECT;
12122 }
12123 else if (th.GetMethodTable() == g_pStringClass)
12124 {
12125 res->elementType = ELEMENT_TYPE_STRING;
12126 }
12127 else
12128 {
12129 res->elementType = th.GetSignatureCorElementType();
12130 }
12131
12132 switch (res->elementType)
12133 {
12134 case ELEMENT_TYPE_ARRAY:
12135 case ELEMENT_TYPE_SZARRAY:
12136 case ELEMENT_TYPE_PTR:
12137 case ELEMENT_TYPE_FNPTR:
12138 case ELEMENT_TYPE_BYREF:
12139 res->vmTypeHandle = WrapTypeHandle(th);
12140 res->metadataToken = mdTokenNil;
12141 res->vmDomainFile.SetRawPtr(NULL);
12142 break;
12143
12144 case ELEMENT_TYPE_CLASS:
12145 case ELEMENT_TYPE_VALUETYPE:
12146 {
12147 res->vmTypeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr();
12148 // only set if instantiated
12149 res->metadataToken = th.GetCl();
12150 DebuggerModule * pDModule = LookupOrCreateModule(th.GetModule(), pAppDomain);
12151 res->vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL));
12152 break;
12153 }
12154
12155 default:
12156 res->vmTypeHandle = VMPTR_TypeHandle::NullPtr();
12157 res->metadataToken = mdTokenNil;
12158 res->vmDomainFile.SetRawPtr(NULL);
12159 break;
12160 }
12161 return;
12162}
12163
12164void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed,
12165 AppDomain *pAppDomain,
12166 TypeHandle th,
12167 DebuggerIPCE_ExpandedTypeData *res)
12168{
12169 CONTRACTL
12170 {
12171 THROWS;
12172 GC_NOTRIGGER;
12173 }
12174 CONTRACTL_END;
12175
12176 if (th.IsNull())
12177 {
12178 res->elementType = ELEMENT_TYPE_VOID;
12179 }
12180 else if (th.GetMethodTable() == g_pObjectClass)
12181 {
12182 res->elementType = ELEMENT_TYPE_OBJECT;
12183 }
12184 else if (th.GetMethodTable() == g_pStringClass)
12185 {
12186 res->elementType = ELEMENT_TYPE_STRING;
12187 }
12188 else
12189 {
12190 LOG((LF_CORDB, LL_INFO10000, "D::THTETI: converting left-side type handle to expanded right-side type info, ELEMENT_TYPE: %d.\n", th.GetSignatureCorElementType()));
12191 // GetSignatureCorElementType returns E_T_CLASS for E_T_STRING... :-(
12192 res->elementType = th.GetSignatureCorElementType();
12193 }
12194
12195 switch (res->elementType)
12196 {
12197 case ELEMENT_TYPE_ARRAY:
12198 case ELEMENT_TYPE_SZARRAY:
12199 _ASSERTE(th.IsArray());
12200 res->ArrayTypeData.arrayRank = th.AsArray()->GetRank();
12201 TypeHandleToBasicTypeInfo(pAppDomain,
12202 th.AsArray()->GetArrayElementTypeHandle(),
12203 &(res->ArrayTypeData.arrayTypeArg));
12204 break;
12205
12206 case ELEMENT_TYPE_PTR:
12207 case ELEMENT_TYPE_BYREF:
12208 if (boxed == AllBoxed)
12209 {
12210 res->elementType = ELEMENT_TYPE_CLASS;
12211 goto treatAllValuesAsBoxed;
12212 }
12213 _ASSERTE(th.IsTypeDesc());
12214 TypeHandleToBasicTypeInfo(pAppDomain,
12215 th.AsTypeDesc()->GetTypeParam(),
12216 &(res->UnaryTypeData.unaryTypeArg));
12217 break;
12218
12219 case ELEMENT_TYPE_VALUETYPE:
12220 if (boxed == OnlyPrimitivesUnboxed || boxed == AllBoxed)
12221 res->elementType = ELEMENT_TYPE_CLASS;
12222 // drop through
12223
12224 case ELEMENT_TYPE_CLASS:
12225 {
12226treatAllValuesAsBoxed:
12227 res->ClassTypeData.typeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); // only set if instantiated
12228 res->ClassTypeData.metadataToken = th.GetCl();
12229 DebuggerModule * pModule = LookupOrCreateModule(th.GetModule(), pAppDomain);
12230 res->ClassTypeData.vmDomainFile.SetRawPtr((pModule ? pModule->GetDomainFile() : NULL));
12231 _ASSERTE(!res->ClassTypeData.vmDomainFile.IsNull());
12232 break;
12233 }
12234
12235 case ELEMENT_TYPE_FNPTR:
12236 {
12237 if (boxed == AllBoxed)
12238 {
12239 res->elementType = ELEMENT_TYPE_CLASS;
12240 goto treatAllValuesAsBoxed;
12241 }
12242 res->NaryTypeData.typeHandle = WrapTypeHandle(th);
12243 break;
12244 }
12245 default:
12246 // The element type is sufficient, unless the type is effectively a "boxed"
12247 // primitive value type...
12248 if (boxed == AllBoxed)
12249 {
12250 res->elementType = ELEMENT_TYPE_CLASS;
12251 goto treatAllValuesAsBoxed;
12252 }
12253 break;
12254 }
12255 LOG((LF_CORDB, LL_INFO10000, "D::THTETI: converted left-side type handle to expanded right-side type info, res->ClassTypeData.typeHandle = 0x%08x.\n", res->ClassTypeData.typeHandle.GetRawPtr()));
12256 return;
12257}
12258
12259
12260HRESULT Debugger::BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData *data, TypeHandle *pRes)
12261{
12262 CONTRACTL
12263 {
12264 NOTHROW;
12265 GC_NOTRIGGER;
12266 }
12267 CONTRACTL_END;
12268
12269 LOG((LF_CORDB, LL_INFO10000, "D::BTITTH: expanding basic right-side type to left-side type, ELEMENT_TYPE: %d.\n", data->elementType));
12270 *pRes = TypeHandle();
12271 TypeHandle th;
12272 switch (data->elementType)
12273 {
12274 case ELEMENT_TYPE_ARRAY:
12275 case ELEMENT_TYPE_SZARRAY:
12276 case ELEMENT_TYPE_PTR:
12277 case ELEMENT_TYPE_BYREF:
12278 _ASSERTE(!data->vmTypeHandle.IsNull());
12279 th = GetTypeHandle(data->vmTypeHandle);
12280 break;
12281
12282 case ELEMENT_TYPE_CLASS:
12283 case ELEMENT_TYPE_VALUETYPE:
12284 {
12285 if (!data->vmTypeHandle.IsNull())
12286 {
12287 th = GetTypeHandle(data->vmTypeHandle);
12288 }
12289 else
12290 {
12291 DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->vmDomainFile);
12292
12293 th = g_pEEInterface->FindLoadedClass(pDebuggerModule->GetRuntimeModule(), data->metadataToken);
12294 if (th.IsNull())
12295 {
12296 LOG((LF_CORDB, LL_INFO10000, "D::ETITTH: class isn't loaded.\n"));
12297 return CORDBG_E_CLASS_NOT_LOADED;
12298 }
12299
12300 _ASSERTE(th.GetNumGenericArgs() == 0);
12301 }
12302 break;
12303 }
12304
12305 case ELEMENT_TYPE_FNPTR:
12306 {
12307 _ASSERTE(!data->vmTypeHandle.IsNull());
12308 th = GetTypeHandle(data->vmTypeHandle);
12309 break;
12310 }
12311
12312 default:
12313 th = g_pEEInterface->FindLoadedElementType(data->elementType);
12314 break;
12315 }
12316 if (th.IsNull())
12317 return CORDBG_E_CLASS_NOT_LOADED;
12318 *pRes = th;
12319 return S_OK;
12320}
12321
12322// Iterate through the type argument data, creating type handles as we go.
12323void Debugger::TypeDataWalk::ReadTypeHandles(unsigned int nTypeArgs, TypeHandle *ppResults)
12324{
12325 WRAPPER_NO_CONTRACT;
12326
12327 for (unsigned int i = 0; i < nTypeArgs; i++)
12328 ppResults[i] = ReadTypeHandle();
12329 }
12330
12331TypeHandle Debugger::TypeDataWalk::ReadInstantiation(Module *pModule, mdTypeDef tok, unsigned int nTypeArgs)
12332{
12333 WRAPPER_NO_CONTRACT;
12334
12335 DWORD dwAllocSize;
12336 if (!ClrSafeInt<DWORD>::multiply(nTypeArgs, sizeof(TypeHandle), dwAllocSize))
12337 {
12338 ThrowHR(COR_E_OVERFLOW);
12339 }
12340 TypeHandle * inst = (TypeHandle *) _alloca(dwAllocSize);
12341 ReadTypeHandles(nTypeArgs, inst) ;
12342 TypeHandle th = g_pEEInterface->LoadInstantiation(pModule, tok, nTypeArgs, inst);
12343 if (th.IsNull())
12344 COMPlusThrow(kArgumentException, W("Argument_InvalidGenericArg"));
12345 return th;
12346}
12347
12348TypeHandle Debugger::TypeDataWalk::ReadTypeHandle()
12349{
12350 CONTRACTL
12351 {
12352 THROWS;
12353 GC_TRIGGERS;
12354 }
12355 CONTRACTL_END;
12356
12357 DebuggerIPCE_TypeArgData * data = ReadOne();
12358 if (!data)
12359 COMPlusThrow(kArgumentException, W("Argument_InvalidGenericArg"));
12360
12361 LOG((LF_CORDB, LL_INFO10000, "D::ETITTH: expanding right-side type to left-side type, ELEMENT_TYPE: %d.\n", data->data.elementType));
12362
12363 TypeHandle th;
12364 CorElementType et = data->data.elementType;
12365 switch (et)
12366 {
12367 case ELEMENT_TYPE_ARRAY:
12368 case ELEMENT_TYPE_SZARRAY:
12369 case ELEMENT_TYPE_PTR:
12370 case ELEMENT_TYPE_BYREF:
12371 if(data->numTypeArgs == 1)
12372 {
12373 TypeHandle typar = ReadTypeHandle();
12374 switch (et)
12375 {
12376 case ELEMENT_TYPE_ARRAY:
12377 case ELEMENT_TYPE_SZARRAY:
12378 th = g_pEEInterface->LoadArrayType(data->data.elementType, typar, data->data.ArrayTypeData.arrayRank);
12379 break;
12380 case ELEMENT_TYPE_PTR:
12381 case ELEMENT_TYPE_BYREF:
12382 th = g_pEEInterface->LoadPointerOrByrefType(data->data.elementType, typar);
12383 break;
12384 default:
12385 _ASSERTE(0);
12386 }
12387 }
12388 break;
12389
12390 case ELEMENT_TYPE_CLASS:
12391 case ELEMENT_TYPE_VALUETYPE:
12392 {
12393 DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->data.ClassTypeData.vmDomainFile);
12394 th = ReadInstantiation(pDebuggerModule->GetRuntimeModule(), data->data.ClassTypeData.metadataToken, data->numTypeArgs);
12395 break;
12396 }
12397
12398 case ELEMENT_TYPE_FNPTR:
12399 {
12400 SIZE_T cbAllocSize;
12401 if ((!ClrSafeInt<SIZE_T>::multiply(data->numTypeArgs, sizeof(TypeHandle), cbAllocSize)) ||
12402 (cbAllocSize != (size_t)(cbAllocSize)))
12403 {
12404 _ASSERTE(COR_E_OVERFLOW);
12405 cbAllocSize = UINT_MAX;
12406 }
12407 TypeHandle * inst = (TypeHandle *) _alloca(cbAllocSize);
12408 ReadTypeHandles(data->numTypeArgs, inst) ;
12409 th = g_pEEInterface->LoadFnptrType(inst, data->numTypeArgs);
12410 break;
12411 }
12412
12413 default:
12414 th = g_pEEInterface->LoadElementType(data->data.elementType);
12415 break;
12416 }
12417 if (th.IsNull())
12418 COMPlusThrow(kArgumentNullException, W("ArgumentNull_Type"));
12419 return th;
12420
12421}
12422
12423//
12424// GetAndSendTransitionStubInfo figures out if an address is a stub
12425// address and sends the result back to the right side.
12426//
12427void Debugger::GetAndSendTransitionStubInfo(CORDB_ADDRESS_TYPE *stubAddress)
12428{
12429 CONTRACTL
12430 {
12431 NOTHROW;
12432 GC_NOTRIGGER;
12433 }
12434 CONTRACTL_END;
12435
12436 LOG((LF_CORDB, LL_INFO10000, "D::GASTSI: IsTransitionStub. Addr=0x%08x\n", stubAddress));
12437
12438 bool result = false;
12439
12440 result = g_pEEInterface->IsStub((const BYTE *)stubAddress);
12441
12442
12443 // If its not a stub, then maybe its an address in mscoree?
12444 if (result == false)
12445 {
12446 result = (IsIPInModule(g_pMSCorEE, (PCODE)stubAddress) == TRUE);
12447 }
12448
12449 // This is a synchronous event (reply required)
12450 DebuggerIPCEvent *event = m_pRCThread->GetIPCEventReceiveBuffer();
12451 InitIPCEvent(event, DB_IPCE_IS_TRANSITION_STUB_RESULT, NULL, NULL);
12452 event->IsTransitionStubResult.isStub = result;
12453
12454 // Send the result
12455 m_pRCThread->SendIPCReply();
12456}
12457
12458/*
12459 * A generic request for a buffer in the left-side for use by the right-side
12460 *
12461 * This is a synchronous event (reply required).
12462 */
12463HRESULT Debugger::GetAndSendBuffer(DebuggerRCThread* rcThread, ULONG bufSize)
12464{
12465 CONTRACTL
12466 {
12467 NOTHROW;
12468 GC_NOTRIGGER;
12469 }
12470 CONTRACTL_END;
12471
12472 // This is a synchronous event (reply required)
12473 DebuggerIPCEvent* event = rcThread->GetIPCEventReceiveBuffer();
12474 PREFIX_ASSUME(event != NULL);
12475 InitIPCEvent(event, DB_IPCE_GET_BUFFER_RESULT, NULL, NULL);
12476
12477 // Allocate the buffer
12478 event->GetBufferResult.hr = AllocateRemoteBuffer( bufSize, &event->GetBufferResult.pBuffer );
12479
12480 // Send the result
12481 return rcThread->SendIPCReply();
12482}
12483
12484/*
12485 * Allocate a buffer in the left-side for use by the right-side
12486 */
12487HRESULT Debugger::AllocateRemoteBuffer( ULONG bufSize, void **ppBuffer )
12488 {
12489 CONTRACTL
12490 {
12491 NOTHROW;
12492 GC_NOTRIGGER;
12493 }
12494 CONTRACTL_END;
12495
12496 // The call to Append below will call CUnorderedArray, which will call unsafe New.
12497 HRESULT hr;
12498 CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());
12499 if( FAILED(hr) )
12500 {
12501 return hr;
12502 }
12503
12504 // Actually allocate the buffer
12505 BYTE* pBuffer = new (interopsafe, nothrow) BYTE[bufSize];
12506
12507 LOG((LF_CORDB, LL_EVERYTHING, "D::ARB: new'd 0x%x\n", *ppBuffer));
12508
12509 // Check for out of memory error
12510 if (pBuffer == NULL)
12511 {
12512 return E_OUTOFMEMORY;
12513 }
12514
12515 // Track the allocation so we can free it later
12516 void **ppNextBlob = GetMemBlobs()->Append();
12517 if( ppNextBlob == NULL )
12518 {
12519 DeleteInteropSafe( pBuffer );
12520 return E_OUTOFMEMORY;
12521 }
12522 *ppNextBlob = pBuffer;
12523
12524 // Return the allocated memory
12525 *ppBuffer = pBuffer;
12526 return S_OK;
12527}
12528
12529/*
12530 * Used to release a previously-requested buffer
12531 *
12532 * This is a synchronous event (reply required).
12533 */
12534HRESULT Debugger::SendReleaseBuffer(DebuggerRCThread* rcThread, void *pBuffer)
12535{
12536 CONTRACTL
12537 {
12538 NOTHROW;
12539 GC_NOTRIGGER;
12540 }
12541 CONTRACTL_END;
12542
12543 LOG((LF_CORDB,LL_INFO10000, "D::SRB for buffer 0x%x\n", pBuffer));
12544
12545 // This is a synchronous event (reply required)
12546 DebuggerIPCEvent* event = rcThread->GetIPCEventReceiveBuffer();
12547 PREFIX_ASSUME(event != NULL);
12548 InitIPCEvent(event, DB_IPCE_RELEASE_BUFFER_RESULT, NULL, NULL);
12549
12550 _ASSERTE(pBuffer != NULL);
12551
12552 // Free the memory
12553 ReleaseRemoteBuffer(pBuffer, true);
12554
12555 // Indicate success in reply
12556 event->ReleaseBufferResult.hr = S_OK;
12557
12558 // Send the result
12559 return rcThread->SendIPCReply();
12560}
12561
12562
12563//
12564// Used to delete the buffer previously-requested by the right side.
12565// We've factored the code since both the ~Debugger and SendReleaseBuffer
12566// methods do this.
12567//
12568HRESULT Debugger::ReleaseRemoteBuffer(void *pBuffer, bool removeFromBlobList)
12569{
12570 CONTRACTL
12571 {
12572 NOTHROW;
12573 GC_NOTRIGGER;
12574 }
12575 CONTRACTL_END;
12576
12577 LOG((LF_CORDB, LL_EVERYTHING, "D::RRB: Releasing RS-alloc'd buffer 0x%x\n", pBuffer));
12578
12579 // Remove the buffer from the blob list if necessary.
12580 if (removeFromBlobList)
12581 {
12582 USHORT cBlobs = GetMemBlobs()->Count();
12583 void **rgpBlobs = GetMemBlobs()->Table();
12584
12585 USHORT i;
12586 for (i = 0; i < cBlobs; i++)
12587 {
12588 if (rgpBlobs[i] == pBuffer)
12589 {
12590 GetMemBlobs()->DeleteByIndex(i);
12591 break;
12592 }
12593 }
12594
12595 // We should have found a match. All buffers passed to ReleaseRemoteBuffer
12596 // should have been allocated with AllocateRemoteBuffer and not yet freed.
12597 _ASSERTE( i < cBlobs );
12598 }
12599
12600 // Delete the buffer. (Need cast for GCC template support)
12601 DeleteInteropSafe( (BYTE*)pBuffer );
12602
12603 return S_OK;
12604}
12605
12606//
12607// UnrecoverableError causes the Left Side to enter a state where no more
12608// debugging can occur and we leave around enough information for the
12609// Right Side to tell what happened.
12610//
12611void Debugger::UnrecoverableError(HRESULT errorHR,
12612 unsigned int errorCode,
12613 const char *errorFile,
12614 unsigned int errorLine,
12615 bool exitThread)
12616{
12617 CONTRACTL
12618 {
12619 NOTHROW;
12620 GC_NOTRIGGER;
12621 }
12622 CONTRACTL_END;
12623
12624 LOG((LF_CORDB, LL_INFO10,
12625 "Unrecoverable error: hr=0x%08x, code=%d, file=%s, line=%d\n",
12626 errorHR, errorCode, errorFile, errorLine));
12627
12628 //
12629 // Setting this will ensure that not much else happens...
12630 //
12631 m_unrecoverableError = TRUE;
12632
12633 //
12634 // Fill out the control block with the error.
12635 // in-proc will find out when the function fails
12636 //
12637 DebuggerIPCControlBlock *pDCB = m_pRCThread->GetDCB();
12638
12639 PREFIX_ASSUME(pDCB != NULL);
12640
12641 pDCB->m_errorHR = errorHR;
12642 pDCB->m_errorCode = errorCode;
12643
12644 //
12645 // If we're told to, exit the thread.
12646 //
12647 if (exitThread)
12648 {
12649 LOG((LF_CORDB, LL_INFO10,
12650 "Thread exiting due to unrecoverable error.\n"));
12651 ExitThread(errorHR);
12652 }
12653}
12654
12655//
12656// Callback for IsThreadAtSafePlace's stack walk.
12657//
12658StackWalkAction Debugger::AtSafePlaceStackWalkCallback(CrawlFrame *pCF,
12659 VOID* data)
12660{
12661 CONTRACTL
12662 {
12663 NOTHROW;
12664 GC_NOTRIGGER;
12665
12666 PRECONDITION(CheckPointer(pCF));
12667 PRECONDITION(CheckPointer(data));
12668 }
12669 CONTRACTL_END;
12670
12671 bool *atSafePlace = (bool*)data;
12672 LOG((LF_CORDB, LL_INFO100000, "D:AtSafePlaceStackWalkCallback\n"));
12673
12674 if (pCF->IsFrameless() && pCF->IsActiveFunc())
12675 {
12676 LOG((LF_CORDB, LL_INFO1000000, "D:AtSafePlaceStackWalkCallback, IsFrameLess() and IsActiveFunc()\n"));
12677 if (g_pEEInterface->CrawlFrameIsGcSafe(pCF))
12678 {
12679 LOG((LF_CORDB, LL_INFO1000000, "D:AtSafePlaceStackWalkCallback - TRUE: CrawlFrameIsGcSafe()\n"));
12680 *atSafePlace = true;
12681 }
12682 }
12683 return SWA_ABORT;
12684}
12685
12686//
12687// Determine, via a quick one frame stack walk, if a given thread is
12688// in a gc safe place.
12689//
12690bool Debugger::IsThreadAtSafePlaceWorker(Thread *thread)
12691{
12692 CONTRACTL
12693 {
12694 NOTHROW;
12695 GC_NOTRIGGER;
12696
12697 PRECONDITION(CheckPointer(thread));
12698 }
12699 CONTRACTL_END;
12700
12701 bool atSafePlace = false;
12702
12703 // Setup our register display.
12704 REGDISPLAY rd;
12705 CONTEXT *context = g_pEEInterface->GetThreadFilterContext(thread);
12706
12707 _ASSERTE(!(g_pEEInterface->GetThreadFilterContext(thread) && ISREDIRECTEDTHREAD(thread)));
12708 if (context != NULL)
12709 {
12710 g_pEEInterface->InitRegDisplay(thread, &rd, context, TRUE);
12711 }
12712 else
12713 {
12714 CONTEXT ctx;
12715 ZeroMemory(&rd, sizeof(rd));
12716 ZeroMemory(&ctx, sizeof(ctx));
12717#if defined(_TARGET_X86_) && !defined(WIN64EXCEPTIONS)
12718 rd.ControlPC = ctx.Eip;
12719 rd.PCTAddr = (TADDR)&(ctx.Eip);
12720#else
12721 FillRegDisplay(&rd, &ctx);
12722#endif
12723
12724 if (ISREDIRECTEDTHREAD(thread))
12725 {
12726 thread->GetFrame()->UpdateRegDisplay(&rd);
12727 }
12728 }
12729
12730 // Do the walk. If it fails, we don't care, because we default
12731 // atSafePlace to false.
12732 g_pEEInterface->StackWalkFramesEx(
12733 thread,
12734 &rd,
12735 Debugger::AtSafePlaceStackWalkCallback,
12736 (VOID*)(&atSafePlace),
12737 QUICKUNWIND | HANDLESKIPPEDFRAMES |
12738 DISABLE_MISSING_FRAME_DETECTION | SKIP_GSCOOKIE_CHECK);
12739
12740#ifdef LOGGING
12741 if (!atSafePlace)
12742 LOG((LF_CORDB | LF_GC, LL_INFO1000,
12743 "Thread 0x%x is not at a safe place.\n",
12744 GetThreadIdHelper(thread)));
12745#endif
12746
12747 return atSafePlace;
12748}
12749
12750bool Debugger::IsThreadAtSafePlace(Thread *thread)
12751{
12752 CONTRACTL
12753 {
12754 NOTHROW;
12755 GC_NOTRIGGER;
12756
12757 PRECONDITION(CheckPointer(thread));
12758 }
12759 CONTRACTL_END;
12760
12761
12762 if (m_fShutdownMode)
12763 {
12764 return true;
12765 }
12766
12767 // <TODO>
12768 //
12769 // Make sure this fix is evaluated when doing real work for debugging SO handling.
12770 //
12771 // On the Stack Overflow code path calling IsThreadAtSafePlaceWorker as it is
12772 // currently implemented is way too stack intensive. For now we cheat and just
12773 // say that if a thread is in the middle of handling a SO it is NOT at a safe
12774 // place. This is a reasonably safe assumption to make and hopefully shouldn't
12775 // result in deadlocking the debugger.
12776 if ( (thread->IsExceptionInProgress()) &&
12777 (g_pEEInterface->GetThreadException(thread) == CLRException::GetPreallocatedStackOverflowExceptionHandle()) )
12778 {
12779 return false;
12780 }
12781 // </TODO>
12782 else
12783 {
12784 return IsThreadAtSafePlaceWorker(thread);
12785 }
12786}
12787
12788//-----------------------------------------------------------------------------
12789// Get the complete user state flags.
12790// This will collect flags both from the EE and from the LS.
12791// This is the real implementation of the RS's ICorDebugThread::GetUserState().
12792//
12793// Parameters:
12794// pThread - non-null thread to get state for.
12795//
12796// Returns: a CorDebugUserState flags enum describing state.
12797//-----------------------------------------------------------------------------
12798CorDebugUserState Debugger::GetFullUserState(Thread *pThread)
12799{
12800 CONTRACTL
12801 {
12802 NOTHROW;
12803 GC_NOTRIGGER;
12804 PRECONDITION(CheckPointer(pThread));
12805 }
12806 CONTRACTL_END;
12807
12808 CorDebugUserState state = g_pEEInterface->GetPartialUserState(pThread);
12809
12810 bool fSafe = IsThreadAtSafePlace(pThread);
12811 if (!fSafe)
12812 {
12813 state = (CorDebugUserState) (state | USER_UNSAFE_POINT);
12814 }
12815
12816 return state;
12817}
12818
12819/******************************************************************************
12820 *
12821 * Helper for debugger to get an unique thread id
12822 *
12823 ******************************************************************************/
12824DWORD Debugger::GetThreadIdHelper(Thread *pThread)
12825{
12826 WRAPPER_NO_CONTRACT;
12827
12828 return pThread->GetOSThreadId();
12829}
12830
12831//-----------------------------------------------------------------------------
12832// Called by EnC during remapping to get information about the local vars.
12833// EnC will then use this to set values in the new version to their corresponding
12834// values from the old version.
12835//
12836// Returns a pointer to the debugger's copies of the maps. Caller
12837// does not own the memory provided via vars outparameter.
12838//-----------------------------------------------------------------------------
12839void Debugger::GetVarInfo(MethodDesc * fd, // [IN] method of interest
12840 void *DebuggerVersionToken, // [IN] which edit version
12841 SIZE_T * cVars, // [OUT] size of 'vars'
12842 const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored
12843 )
12844{
12845 CONTRACTL
12846 {
12847 THROWS;
12848 GC_TRIGGERS_FROM_GETJITINFO;
12849 }
12850 CONTRACTL_END;
12851
12852 DebuggerJitInfo * ji = (DebuggerJitInfo *)DebuggerVersionToken;
12853
12854 // If we didn't supply a DJI, then we're asking for the most recent version.
12855 if (ji == NULL)
12856 {
12857 ji = GetLatestJitInfoFromMethodDesc(fd);
12858 }
12859 _ASSERTE(fd == ji->m_fd);
12860
12861 PREFIX_ASSUME(ji != NULL);
12862
12863 *vars = ji->GetVarNativeInfo();
12864 *cVars = ji->GetVarNativeInfoCount();
12865}
12866
12867#include "openum.h"
12868
12869#ifdef EnC_SUPPORTED
12870
12871//---------------------------------------------------------------------------------------
12872//
12873// Apply an EnC edit to the CLR datastructures and send the result event to the
12874// debugger right-side.
12875//
12876// Arguments:
12877// pDebuggerModule - the module in which the edit should occur
12878// cbMetadata - the number of bytes in pMetadata
12879// pMetadata - pointer to the delta metadata
12880// cbIL - the number of bytes in pIL
12881// pIL - pointer to the delta IL
12882//
12883// Return Value:
12884//
12885// Assumptions:
12886//
12887// Notes:
12888//
12889// This is just the first half of processing an EnC request (hot swapping). This updates
12890// the metadata and other CLR data structures to reflect the edit, but does not directly
12891// affect code which is currently running. In order to achieve on-stack replacement
12892// (remap of running code), we mine all old methods with "EnC remap breakpoints"
12893// (instances of DebuggerEnCBreakpoint) at many sequence points. When one of those
12894// breakpoints is hit, we give the debugger a RemapOpportunity event and give it a
12895// chance to remap the execution to the new version of the method.
12896//
12897
12898HRESULT Debugger::ApplyChangesAndSendResult(DebuggerModule * pDebuggerModule,
12899 DWORD cbMetadata,
12900 BYTE *pMetadata,
12901 DWORD cbIL,
12902 BYTE *pIL)
12903{
12904 CONTRACTL
12905 {
12906 THROWS;
12907 GC_NOTRIGGER;
12908 }
12909 CONTRACTL_END;
12910
12911 // @todo - if EnC never works w/ interop, caller New on the helper thread may be ok.
12912 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
12913
12914 HRESULT hr = S_OK;
12915
12916 LOG((LF_ENC, LL_INFO100, "Debugger::ApplyChangesAndSendResult\n"));
12917
12918 Module *pModule = pDebuggerModule->GetRuntimeModule();
12919 if (! pModule->IsEditAndContinueEnabled())
12920 {
12921 hr = CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED;
12922 }
12923 else
12924 {
12925 // Violation with the following call stack:
12926 // CONTRACT in MethodTableBuilder::InitMethodDesc
12927 // CONTRACT in EEClass::AddMethod
12928 // CONTRACT in EditAndContinueModule::AddMethod
12929 // CONTRACT in EditAndContinueModule::ApplyEditAndContinue
12930 // CONTRACT in EEDbgInterfaceImpl::EnCApplyChanges
12931 // VIOLATED--> CONTRACT in Debugger::ApplyChangesAndSendResult
12932 CONTRACT_VIOLATION(GCViolation);
12933
12934 // Tell the VM to apply the edit
12935 hr = g_pEEInterface->EnCApplyChanges(
12936 (EditAndContinueModule*)pModule, cbMetadata, pMetadata, cbIL, pIL);
12937 }
12938
12939 LOG((LF_ENC, LL_INFO100, "Debugger::ApplyChangesAndSendResult 2\n"));
12940
12941 DebuggerIPCEvent* event = m_pRCThread->GetIPCEventSendBuffer();
12942 InitIPCEvent(event,
12943 DB_IPCE_APPLY_CHANGES_RESULT,
12944 NULL,
12945 NULL);
12946
12947 event->ApplyChangesResult.hr = hr;
12948
12949 // Send the result
12950 return m_pRCThread->SendIPCEvent();
12951}
12952
12953//
12954// This structure is used to hold a list of the sequence points in a function and
12955// determine which should have remap breakpoints applied to them for EnC
12956//
12957class EnCSequencePointHelper
12958{
12959public:
12960 // Calculates remap info given the supplied JitInfo
12961 EnCSequencePointHelper(DebuggerJitInfo *pJitInfo);
12962 ~EnCSequencePointHelper();
12963
12964 // Returns true if the specified sequence point (given by it's index in the
12965 // sequence point table in the JitInfo) should get an EnC remap breakpoint.
12966 BOOL ShouldSetRemapBreakpoint(unsigned int offsetIndex);
12967
12968private:
12969 DebuggerJitInfo *m_pJitInfo;
12970
12971 DebugOffsetToHandlerInfo *m_pOffsetToHandlerInfo;
12972};
12973
12974//
12975// Goes through the list of sequence points for a function and determines whether or not each
12976// is a valid Remap Breakpoint location (not in a special offset, must be empty stack, and not in a handler.
12977//
12978EnCSequencePointHelper::EnCSequencePointHelper(DebuggerJitInfo *pJitInfo)
12979 : m_pOffsetToHandlerInfo(NULL),
12980 m_pJitInfo(pJitInfo)
12981{
12982 CONTRACTL
12983 {
12984 THROWS;
12985 GC_NOTRIGGER;
12986 }
12987 CONTRACTL_END;
12988
12989 if (m_pJitInfo->GetSequenceMapCount() == 0)
12990 {
12991 return;
12992 }
12993
12994 // Construct a list of native offsets we may want to place EnC breakpoints at
12995 m_pOffsetToHandlerInfo = new DebugOffsetToHandlerInfo[m_pJitInfo->GetSequenceMapCount()];
12996 for (unsigned int i = 0; i < m_pJitInfo->GetSequenceMapCount(); i++)
12997 {
12998 // By default this slot is unused. We want the indexes in m_pOffsetToHandlerInfo
12999 // to correspond to the indexes of m_pJitInfo->GetSequenceMapCount, so we rely
13000 // on a -1 offset to indicate that a DebuggerOffsetToHandlerInfo is unused.
13001 // However, it would be cleaner and permit a simpler API to the EE if we just
13002 // had an array mapping the offsets instead.
13003 m_pOffsetToHandlerInfo[i].offset = (SIZE_T) -1;
13004 m_pOffsetToHandlerInfo[i].isInFilterOrHandler = FALSE;
13005
13006 SIZE_T offset = m_pJitInfo->GetSequenceMap()[i].nativeStartOffset;
13007
13008 // Check if this is a "special" IL offset, such as representing the prolog or eppilog,
13009 // or other region not directly mapped to native code.
13010 if (DbgIsSpecialILOffset(pJitInfo->GetSequenceMap()[i].ilOffset))
13011 {
13012 LOG((LF_ENC, LL_INFO10000,
13013 "D::UF: not placing E&C breakpoint at special offset 0x%x (IL: 0x%x)\n",
13014 offset, m_pJitInfo->GetSequenceMap()[i].ilOffset));
13015 continue;
13016 }
13017
13018 // Skip duplicate sequence points
13019 if (i >=1 && offset == pJitInfo->GetSequenceMap()[i-1].nativeStartOffset)
13020 {
13021 LOG((LF_ENC, LL_INFO10000,
13022 "D::UF: not placing redundant E&C "
13023 "breakpoint at duplicate offset 0x%x (IL: 0x%x)\n",
13024 offset, m_pJitInfo->GetSequenceMap()[i].ilOffset));
13025 continue;
13026 }
13027
13028 // Skip sequence points that aren't due to the evaluation stack being empty
13029 // We can only remap at stack-empty points (since we don't have a mapping for
13030 // contents of the evaluation stack).
13031 if (!(pJitInfo->GetSequenceMap()[i].source & ICorDebugInfo::STACK_EMPTY))
13032 {
13033 LOG((LF_ENC, LL_INFO10000,
13034 "D::UF: not placing E&C breakpoint at offset "
13035 "0x%x (IL: 0x%x) b/c not STACK_EMPTY:it's 0x%x\n", offset,
13036 m_pJitInfo->GetSequenceMap()[i].ilOffset, pJitInfo->GetSequenceMap()[i].source));
13037 continue;
13038 }
13039
13040 // So far this sequence point looks good, so store it's native offset so we can get
13041 // EH information about it from the EE.
13042 LOG((LF_ENC, LL_INFO10000,
13043 "D::UF: possibly placing E&C breakpoint at offset "
13044 "0x%x (IL: 0x%x)\n", offset, m_pJitInfo->GetSequenceMap()[i].ilOffset));
13045 m_pOffsetToHandlerInfo[i].offset = m_pJitInfo->GetSequenceMap()[i].nativeStartOffset;
13046
13047 }
13048
13049 // Ask the EE to fill in the isInFilterOrHandler bit for the native offsets we're interested in
13050 g_pEEInterface->DetermineIfOffsetsInFilterOrHandler(
13051 (BYTE *)pJitInfo->m_addrOfCode, m_pOffsetToHandlerInfo, m_pJitInfo->GetSequenceMapCount());
13052}
13053
13054EnCSequencePointHelper::~EnCSequencePointHelper()
13055{
13056 CONTRACTL
13057 {
13058 THROWS;
13059 GC_NOTRIGGER;
13060 }
13061 CONTRACTL_END;
13062
13063 if (m_pOffsetToHandlerInfo)
13064 {
13065 delete m_pOffsetToHandlerInfo;
13066 }
13067}
13068
13069//
13070// Returns if we should set a remap breakpoint at a given offset. We only set them at 0-depth stack
13071// and not when inside a handler, either finally, filter, or catch
13072//
13073BOOL EnCSequencePointHelper::ShouldSetRemapBreakpoint(unsigned int offsetIndex)
13074{
13075 CONTRACTL
13076 {
13077 NOTHROW;
13078 GC_NOTRIGGER;
13079 MODE_ANY;
13080 CANNOT_TAKE_LOCK;
13081 }
13082 CONTRACTL_END;
13083
13084 {
13085 // GetSequenceMapCount calls LazyInitBounds() which can eventually
13086 // call ExecutionManager::IncrementReader
13087 CONTRACT_VIOLATION(TakesLockViolation);
13088 _ASSERTE(offsetIndex <= m_pJitInfo->GetSequenceMapCount());
13089 }
13090
13091 // If this slot is unused (offset -1), we excluded it early
13092 if (m_pOffsetToHandlerInfo[offsetIndex].offset == (SIZE_T) -1)
13093 {
13094 return FALSE;
13095 }
13096
13097 // Otherwise, check the isInFilterOrHandler bit
13098 if (m_pOffsetToHandlerInfo[offsetIndex].isInFilterOrHandler)
13099 {
13100 LOG((LF_ENC, LL_INFO10000,
13101 "D::UF: not placing E&C breakpoint in filter/handler at offset 0x%x\n",
13102 m_pOffsetToHandlerInfo[offsetIndex].offset));
13103 return FALSE;
13104 }
13105
13106 return TRUE;
13107}
13108
13109
13110//-----------------------------------------------------------------------------
13111// For each function that's EnC-ed, the EE will call either UpdateFunction
13112// (if the function already is loaded + jitted) or AddFunction
13113//
13114// This is called before the EE updates the MethodDesc, so pMD does not yet
13115// point to the version we'll be remapping to.
13116//-----------------------------------------------------------------------------
13117HRESULT Debugger::UpdateFunction(MethodDesc* pMD, SIZE_T encVersion)
13118{
13119 CONTRACTL
13120 {
13121 THROWS;
13122 GC_TRIGGERS_FROM_GETJITINFO;
13123 PRECONDITION(ThisIsHelperThread()); // guarantees we're serialized.
13124 PRECONDITION(IsStopped());
13125 }
13126 CONTRACTL_END;
13127
13128 LOG((LF_CORDB, LL_INFO10000, "D::UF: updating "
13129 "%s::%s to version %d\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, encVersion));
13130
13131 // tell the RS that this function has been updated so that it can create new CorDBFunction
13132 Module *pModule = g_pEEInterface->MethodDescGetModule(pMD);
13133 _ASSERTE(pModule != NULL);
13134 mdToken methodDef = pMD->GetMemberDef();
13135 SendEnCUpdateEvent(DB_IPCE_ENC_UPDATE_FUNCTION,
13136 pModule,
13137 methodDef,
13138 pMD->GetMethodTable()->GetCl(),
13139 encVersion);
13140
13141 DebuggerMethodInfo *dmi = GetOrCreateMethodInfo(pModule, methodDef);
13142 if (dmi == NULL)
13143 {
13144 return E_OUTOFMEMORY;
13145 }
13146
13147 // The DMI always holds the most current EnC version number. We always JIT the most
13148 // current version of the function, so when we do see a JitBegin we will create a new
13149 // dji for it and stash the current version there. We don't want to change the current
13150 // jit info because it has to maintain the version for the code it corresponds to.
13151 dmi->SetCurrentEnCVersion(encVersion);
13152
13153 // This is called before the MethodDesc is updated to point to the new function.
13154 // So this call will get the most recent old function.
13155 DebuggerJitInfo *pJitInfo = GetLatestJitInfoFromMethodDesc(pMD);
13156
13157 if (pJitInfo == NULL )
13158 {
13159 LOG((LF_CORDB,LL_INFO10000,"Unable to get DJI by recently "
13160 "D::UF: JITted version number (it hasn't been jitted yet),"
13161 "which is fine\n"));
13162 return S_OK;
13163 }
13164
13165 //
13166 // Mine the old version of the method with patches so that we can provide
13167 // remap opportunities whenever the old version of the method is executed.
13168 //
13169
13170 if (pJitInfo->m_encBreakpointsApplied)
13171 {
13172 LOG((LF_CORDB,LL_INFO10000,"D::UF: Breakpoints already applied\n"));
13173 return S_OK;
13174 }
13175
13176 LOG((LF_CORDB,LL_INFO10000,"D::UF: Applying breakpoints\n"));
13177
13178 // We only place the patches if we have jit info for this
13179 // function, i.e., its already been jitted. Otherwise, the EE will
13180 // pickup the new method on the next JIT anyway.
13181
13182 EnCSequencePointHelper sequencePointHelper(pJitInfo);
13183
13184 // For each offset in the IL->Native map, set a new EnC breakpoint on the
13185 // ones that we know could be remap points.
13186 for (unsigned int i = 0; i < pJitInfo->GetSequenceMapCount(); i++)
13187 {
13188 // Skip if this isn't a valid remap point (eg. is in an exception handler)
13189 if (! sequencePointHelper.ShouldSetRemapBreakpoint(i))
13190 {
13191 continue;
13192 }
13193
13194 SIZE_T offset = pJitInfo->GetSequenceMap()[i].nativeStartOffset;
13195
13196 LOG((LF_CORDB, LL_INFO10000,
13197 "D::UF: placing E&C breakpoint at native offset 0x%x\n",
13198 offset));
13199
13200 DebuggerEnCBreakpoint *bp;
13201
13202 // Create and activate a new EnC remap breakpoint here in the old version of the method
13203 bp = new (interopsafe) DebuggerEnCBreakpoint( offset,
13204 pJitInfo,
13205 DebuggerEnCBreakpoint::REMAP_PENDING,
13206 (AppDomain *)pModule->GetDomain());
13207
13208 _ASSERTE(bp != NULL);
13209 }
13210
13211 pJitInfo->m_encBreakpointsApplied = true;
13212
13213 return S_OK;
13214}
13215
13216// Called to update a function that hasn't yet been loaded (and so we don't have a MethodDesc).
13217// This may be updating an existing function on a type that hasn't been loaded
13218// or adding a new function to a type that hasn't been loaded.
13219// We need to notify the debugger so that it can properly track version info.
13220HRESULT Debugger::UpdateNotYetLoadedFunction(mdMethodDef token, Module * pModule, SIZE_T encVersion)
13221{
13222 CONTRACTL
13223 {
13224 THROWS;
13225 GC_NOTRIGGER;
13226
13227 PRECONDITION(ThisIsHelperThread());
13228 PRECONDITION(ThreadHoldsLock()); // must have lock since we're on helper and stopped.
13229 }
13230 CONTRACTL_END;
13231
13232 DebuggerMethodInfo *dmi = GetOrCreateMethodInfo(pModule, token);
13233 if (! dmi)
13234 {
13235 return E_OUTOFMEMORY;
13236 }
13237 dmi->SetCurrentEnCVersion(encVersion);
13238
13239
13240 // Must tell the RS that this function has been added so that it can create new CorDBFunction.
13241 mdTypeDef classToken = 0;
13242
13243 HRESULT hr = pModule->GetMDImport()->GetParentToken(token, &classToken);
13244 if (FAILED(hr))
13245 {
13246 // We never expect this to actually fail, but just in case it does for some other crazy reason,
13247 // we'll return before we AV.
13248 CONSISTENCY_CHECK_MSGF(false, ("Class lookup failed:mdToken:0x%08x, pModule=%p. hr=0x%08x\n", token, pModule, hr));
13249 return hr;
13250 }
13251
13252 SendEnCUpdateEvent(DB_IPCE_ENC_ADD_FUNCTION, pModule, token, classToken, encVersion);
13253
13254
13255 return S_OK;
13256}
13257
13258// Called to add a new function when the type has been loaded already.
13259// This is effectively the same as above, except that we're given a
13260// MethodDesc instead of a module and token.
13261// This should probably be merged into a single method since the caller
13262// should always have a module and token available in both cases.
13263HRESULT Debugger::AddFunction(MethodDesc* pMD, SIZE_T encVersion)
13264{
13265 CONTRACTL
13266 {
13267 THROWS;
13268 GC_NOTRIGGER;
13269
13270 PRECONDITION(ThisIsHelperThread());
13271 PRECONDITION(ThreadHoldsLock()); // must have lock since we're on helper and stopped.
13272 }
13273 CONTRACTL_END;
13274
13275 DebuggerDataLockHolder debuggerDataLockHolder(this);
13276
13277 LOG((LF_CORDB, LL_INFO10000, "D::AF: adding "
13278 "%s::%s to version %d\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, encVersion));
13279
13280 _ASSERTE(pMD != NULL);
13281 Module *pModule = g_pEEInterface->MethodDescGetModule(pMD);
13282 _ASSERTE(pModule != NULL);
13283 mdToken methodDef = pMD->GetMemberDef();
13284
13285 // tell the RS that this function has been added so that it can create new CorDBFunction
13286 SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FUNCTION,
13287 pModule,
13288 methodDef,
13289 pMD->GetMethodTable()->GetCl(),
13290 encVersion);
13291
13292 DebuggerMethodInfo *dmi = CreateMethodInfo(pModule, methodDef);
13293 if (! dmi)
13294 {
13295 return E_OUTOFMEMORY;
13296 }
13297 dmi->SetCurrentEnCVersion(encVersion);
13298
13299 return S_OK;
13300}
13301
13302// Invoke when a field is added to a class using EnC
13303HRESULT Debugger::AddField(FieldDesc* pFD, SIZE_T encVersion)
13304{
13305 CONTRACTL
13306 {
13307 NOTHROW;
13308 GC_NOTRIGGER;
13309 }
13310 CONTRACTL_END;
13311
13312 LOG((LF_CORDB, LL_INFO10000, "D::AFld: adding "
13313 "%8.8d::%8.8d to version %d\n", pFD->GetApproxEnclosingMethodTable()->GetCl(), pFD->GetMemberDef(), encVersion));
13314
13315 // tell the RS that this field has been added so that it can update it's structures
13316 SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FIELD,
13317 pFD->GetModule(),
13318 pFD->GetMemberDef(),
13319 pFD->GetApproxEnclosingMethodTable()->GetCl(),
13320 encVersion);
13321
13322 return S_OK;
13323}
13324
13325//
13326// RemapComplete is called when we are just about to resume into
13327// the function so that we can setup our breakpoint to trigger
13328// a call to the RemapComplete callback once the function is actually
13329// on the stack. We need to wait until the function is jitted before
13330// we can add the trigger, which doesn't happen until we call
13331// ResumeInUpdatedFunction in the VM
13332//
13333// addr is address within the given function, which we use to determine
13334// exact EnC version.
13335//
13336HRESULT Debugger::RemapComplete(MethodDesc* pMD, TADDR addr, SIZE_T nativeOffset)
13337{
13338 CONTRACTL
13339 {
13340 THROWS;
13341 GC_TRIGGERS_FROM_GETJITINFO;
13342 }
13343 CONTRACTL_END;
13344
13345 _ASSERTE(pMD != NULL);
13346 _ASSERTE(addr != NULL);
13347
13348 LOG((LF_CORDB, LL_INFO10000, "D::RC: installed remap complete patch for "
13349 "%s::%s to version %d\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
13350
13351 DebuggerMethodInfo *dmi = GetOrCreateMethodInfo(pMD->GetModule(), pMD->GetMemberDef());
13352
13353 if (dmi == NULL)
13354 {
13355 return E_OUTOFMEMORY;
13356 }
13357
13358 DebuggerJitInfo *pJitInfo = GetJitInfo(pMD, (const BYTE *) addr);
13359
13360 if (pJitInfo == NULL)
13361 {
13362 _ASSERTE(!"Debugger doesn't handle OOM");
13363 return E_OUTOFMEMORY;
13364 }
13365 _ASSERTE(pJitInfo->m_addrOfCode + nativeOffset == addr);
13366
13367 DebuggerEnCBreakpoint *bp;
13368
13369 // Create and activate a new REMAP_COMPLETE EnC breakpoint to let us know when
13370 // the EE has completed the remap process.
13371 // This will be deleted when the patch is hit.
13372 bp = new (interopsafe, nothrow) DebuggerEnCBreakpoint( nativeOffset,
13373 pJitInfo,
13374 DebuggerEnCBreakpoint::REMAP_COMPLETE,
13375 (AppDomain *)pMD->GetModule()->GetDomain());
13376 if (bp == NULL)
13377 {
13378 return E_OUTOFMEMORY;
13379 }
13380
13381 return S_OK;
13382}
13383
13384//-----------------------------------------------------------------------------
13385// Called by EnC stuff to map an IL offset to a native offset for the given
13386// method described by (pMD, nativeFnxStart).
13387//
13388// pMD - methoddesc for method being remapped
13389// ilOffset - incoming offset in old method to remap.
13390// nativeFnxStart - address of new function. This can be used to find the DJI
13391// for the new method.
13392// nativeOffset - outparameter for native linear offset relative to start address.
13393//-----------------------------------------------------------------------------
13394
13395HRESULT Debugger::MapILInfoToCurrentNative(MethodDesc *pMD,
13396 SIZE_T ilOffset,
13397 TADDR nativeFnxStart,
13398 SIZE_T *nativeOffset)
13399{
13400 CONTRACTL
13401 {
13402 THROWS;
13403 GC_TRIGGERS_FROM_GETJITINFO;
13404 PRECONDITION(nativeOffset != NULL);
13405 PRECONDITION(CheckPointer(pMD));
13406 PRECONDITION(nativeFnxStart != NULL);
13407 }
13408 CONTRACTL_END;
13409
13410 _ASSERTE(HasLazyData()); // only used for EnC, should have already inited.
13411
13412
13413 LOG((LF_CORDB, LL_INFO1000000, "D::MILITCN: %s::%s ilOff:0x%x, "
13414 ", natFnx:0x%x dji:0x%x\n", pMD->m_pszDebugClassName,
13415 pMD->m_pszDebugMethodName, ilOffset, nativeFnxStart));
13416
13417 *nativeOffset = 0;
13418 DebuggerJitInfo *djiTo = GetJitInfo( pMD, (const BYTE *)nativeFnxStart);
13419 if (djiTo == NULL)
13420 {
13421 _ASSERTE(!"No DJI in EnC case: should only happen on oom. Debugger doesn't support OOM.");
13422 return E_FAIL;
13423 }
13424
13425 DebuggerJitInfo::ILToNativeOffsetIterator it;
13426 djiTo->InitILToNativeOffsetIterator(it, ilOffset);
13427 *nativeOffset = it.CurrentAssertOnlyOne(NULL);
13428 return S_OK;
13429}
13430
13431#endif // EnC_SUPPORTED
13432
13433//---------------------------------------------------------------------------------------
13434// Hijack worker stub called from asm stub. This can then delegate to other hijacks.
13435//
13436// Arguments:
13437// pContext - context from which we were hijacked. Always non-null.
13438// pRecord - exception record if hijacked from an exception event.
13439// Else null (if hijacked from a managed IP).
13440// reason - hijack reason. Use this to delegate to the proper hijack stub.
13441// pData - arbitrary data for the hijack to use. (eg, such as a DebuggerEval object)
13442//
13443// Returns:
13444// This does not return. Instead it restores this threads context to pContext.
13445//
13446// Assumptions:
13447// If hijacked at an exception event, the debugger must have cleared the exception.
13448//
13449// Notes:
13450// The debugger hijacked the thread to get us here via the DacDbi Hijack primitive.
13451// This is called from a hand coded asm stub.
13452//
13453void STDCALL ExceptionHijackWorker(
13454 CONTEXT * pContext,
13455 EXCEPTION_RECORD * pRecord,
13456 EHijackReason::EHijackReason reason,
13457 void * pData)
13458{
13459 STRESS_LOG0(LF_CORDB,LL_INFO100, "D::EHW: Enter ExceptionHijackWorker\n");
13460
13461 // We could have many different reasons for hijacking. Switch and invoke the proper hijacker.
13462 switch(reason)
13463 {
13464 case EHijackReason::kUnhandledException:
13465 STRESS_LOG0(LF_CORDB,LL_INFO10, "D::EHW: Calling g_pDebugger->UnhandledHijackWorker()\n");
13466 _ASSERTE(pData == NULL);
13467 g_pDebugger->UnhandledHijackWorker(pContext, pRecord);
13468 break;
13469#ifdef FEATURE_INTEROP_DEBUGGING
13470 case EHijackReason::kM2UHandoff:
13471 _ASSERTE(pData == NULL);
13472 g_pDebugger->M2UHandoffHijackWorker(pContext, pRecord);
13473 break;
13474 case EHijackReason::kFirstChanceSuspend:
13475 _ASSERTE(pData == NULL);
13476 g_pDebugger->FirstChanceSuspendHijackWorker(pContext, pRecord);
13477 break;
13478 case EHijackReason::kGenericHijack:
13479 _ASSERTE(pData == NULL);
13480 g_pDebugger->GenericHijackFunc();
13481 break;
13482#endif
13483 default:
13484 CONSISTENCY_CHECK_MSGF(false, ("Unrecognized Hijack code: %d", reason));
13485 }
13486
13487 // Currently, no Hijack actually returns yet.
13488 UNREACHABLE();
13489
13490 // If we return to this point, then we'll restore ourselves.
13491 // We've got the context that we were hijacked from, so we should be able to just
13492 // call SetThreadContext on ourself to fix us.
13493}
13494
13495#if defined(WIN64EXCEPTIONS) && !defined(FEATURE_PAL)
13496
13497#if defined(_TARGET_AMD64_)
13498// ----------------------------------------------------------------------------
13499// EmptyPersonalityRoutine
13500//
13501// Description:
13502// This personality routine is used to work around a limitation of the OS unwinder when we return
13503// ExceptionCollidedUnwind.
13504// See code:ExceptionHijackPersonalityRoutine for more information.
13505//
13506// Arguments:
13507// * pExceptionRecord - not used
13508// * MemoryStackFp - not used
13509// * BackingStoreFp - not used
13510// * pContextRecord - not used
13511// * pDispatcherContext - not used
13512// * GlobalPointer - not used
13513//
13514// Return Value:
13515// Always return ExceptionContinueSearch.
13516//
13517
13518EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord,
13519 IN ULONG64 MemoryStackFp,
13520 IN OUT PCONTEXT pContextRecord,
13521 IN OUT PDISPATCHER_CONTEXT pDispatcherContext)
13522{
13523 LIMITED_METHOD_CONTRACT;
13524 return ExceptionContinueSearch;
13525}
13526#endif // _TARGET_AMD64_
13527
13528//---------------------------------------------------------------------------------------
13529// Personality routine for unwinder the assembly hijack stub on 64-bit.
13530//
13531// Arguments:
13532// standard Personality routine signature.
13533//
13534// Assumptions:
13535// This is caleld by the OS exception logic during exception handling.
13536//
13537// Notes:
13538// We just need 1 personality routine for the tiny assembly hijack stub.
13539// All the C++ code invoked by the stub is ok.
13540//
13541// This needs to fetch the original context that this thread was hijacked from
13542// (which the hijack pushed onto the stack) and pass that back to the OS. This lets
13543// ths OS unwind out of the hijack.
13544//
13545// This function should only be executed if an unhandled exception is intercepted by a managed debugger.
13546// Otherwise there should never be a 2nd pass exception dispatch crossing the hijack stub.
13547//
13548// The basic idea here is straightforward. The OS does an exception dispatch and hit our hijack stub.
13549// Since the hijack stub is not unwindable, we need a personality routine to restore the CONTEXT and
13550// tell the OS to continue the dispatch with that CONTEXT by returning ExceptionCollidedUnwind.
13551//
13552// However, empricially, the OS expects that when we return ExceptionCollidedUnwind, the function
13553// represented by the CONTEXT has a personality routine. The OS will actually AV if we return a NULL
13554// personality routine.
13555//
13556// On AMD64, we work around this by using an empty personality routine.
13557
13558EXTERN_C EXCEPTION_DISPOSITION
13559ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord
13560 WIN64_ARG(IN ULONG64 MemoryStackFp)
13561 NOT_WIN64_ARG(IN ULONG32 MemoryStackFp),
13562 IN OUT PCONTEXT pContextRecord,
13563 IN OUT PDISPATCHER_CONTEXT pDispatcherContext
13564 )
13565{
13566#if defined(_TARGET_AMD64_)
13567 CONTEXT * pHijackContext = NULL;
13568
13569 // Get the 1st parameter (the Context) from hijack worker.
13570 // EstablisherFrame points to the stack slot 8 bytes above the
13571 // return address to the ExceptionHijack. This would contain the
13572 // parameters passed to ExceptionHijackWorker, which is marked
13573 // STDCALL, but the x64 calling convention lets the
13574 // ExceptionHijackWorker use that stack space, resulting in the
13575 // context being overwritten. Instead, we get the context from the
13576 // previous stack frame, which contains the arguments to
13577 // ExceptionHijack, placed there by the debugger in
13578 // DacDbiInterfaceImpl::Hijack. This works because ExceptionHijack
13579 // allocates exactly 4 stack slots.
13580 pHijackContext = *reinterpret_cast<CONTEXT **>(pDispatcherContext->EstablisherFrame + 0x20);
13581
13582 // This copies pHijackContext into pDispatcherContext, which the OS can then
13583 // use to walk the stack.
13584 FixupDispatcherContext(pDispatcherContext, pHijackContext, pContextRecord, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine);
13585#else
13586 _ASSERTE(!"NYI - ExceptionHijackPersonalityRoutine()");
13587#endif
13588
13589 // Returning ExceptionCollidedUnwind will cause the OS to take our new context record and
13590 // dispatcher context and restart the exception dispatching on this call frame, which is
13591 // exactly the behavior we want.
13592 return ExceptionCollidedUnwind;
13593}
13594#endif // WIN64EXCEPTIONS && !FEATURE_PAL
13595
13596
13597// UEF Prototype from excep.cpp
13598LONG InternalUnhandledExceptionFilter_Worker(EXCEPTION_POINTERS *pExceptionInfo);
13599
13600//---------------------------------------------------------------------------------------
13601// Hijack for a 2nd-chance exception. Will invoke the CLR's UEF.
13602//
13603// Arguments:
13604// pContext - context that this thread was hijacked from.
13605// pRecord - exception record of the exception that this was hijacked at.
13606// pData - random data.
13607// Notes:
13608// When under a native-debugger, the OS does not invoking the Unhandled Exception Filter (UEF).
13609// It dispatches a 2nd-chance Exception event instead.
13610// However, the CLR's UEF does lots of useful work (like dispatching the 2nd-chance managed exception,
13611// allowing func-eval on 2nd-chance, and allowing intercepting unhandled exceptions).
13612// So we'll emulate the OS behavior here by invoking the CLR's UEF directly.
13613//
13614void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRecord)
13615{
13616 CONTRACTL
13617 {
13618 // The ultimate protection shield is that this hijack can be executed under the same circumstances
13619 // as a top-level UEF that pinvokes into managed code
13620 // - That means we're GC-triggers safe
13621 // - that means that we can crawl the stack. (1st-pass EH logic ensures this).
13622 // We need to be GC-triggers because this may invoke a func-eval.
13623 GC_TRIGGERS;
13624
13625 // Don't throw out of a hijack! There's nobody left to catch this.
13626 NOTHROW;
13627
13628 // We expect to always be in preemptive here by the time we get this unhandled notification.
13629 // We know this is true because a native UEF is preemptive.
13630 // More detail:
13631 // 1) If we got here from a software exception (eg, Throw from C#), then the jit helper
13632 // toggled us to preemptive before calling RaiseException().
13633 // 2) If we got here from a hardware exception in managed code, then the 1st-pass already did
13634 // some magic to get us into preemptive. On x86, this is magic. On 64-bit, it did some magic
13635 // to push a Faulting-Exception-Frame and rethrow the exception as a software exception.
13636 MODE_PREEMPTIVE;
13637
13638
13639 PRECONDITION(CheckPointer(pContext));
13640 PRECONDITION(CheckPointer(pRecord));
13641 }
13642 CONTRACTL_END;
13643
13644 EXCEPTION_POINTERS exceptionInfo;
13645 exceptionInfo.ContextRecord = pContext;
13646 exceptionInfo.ExceptionRecord = pRecord;
13647
13648 // Snag the Runtime thread. Since we're hijacking a managed exception, we should always have one.
13649 Thread * pThread = g_pEEInterface->GetThread();
13650 (void)pThread; //prevent "unused variable" error from GCC
13651 _ASSERTE(pThread != NULL);
13652
13653 BOOL fSOException = FALSE;
13654
13655 if ((pRecord != NULL) &&
13656 (pRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
13657 {
13658 fSOException = TRUE;
13659 }
13660
13661 // because we hijack here during jit attach invoked by the OS we need to make sure that the debugger is completely
13662 // attached before continuing. If we ever hijacked here when an attach was not in progress this function returns
13663 // immediately so no problems there.
13664 WaitForDebuggerAttach();
13665 PostJitAttach();
13666
13667 // On Win7 WatsonLastChance returns CONTINUE_SEARCH for unhandled exceptions execpt stack overflow, and
13668 // lets OS launch debuggers for us. Before the unhandled exception reaches the OS, CLR UEF has already
13669 // processed this unhandled exception. Thus, we should not call into CLR UEF again if it is the case.
13670 if (pThread &&
13671 (pThread->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException) ||
13672 pThread->HasThreadStateNC(Thread::TSNC_AppDomainContainUnhandled) ||
13673 fSOException))
13674 {
13675
13676 FrameWithCookie<FaultingExceptionFrame> fef;
13677#if defined(WIN64EXCEPTIONS)
13678 *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie();
13679#endif // WIN64EXCEPTIONS
13680 if ((pContext != NULL) && fSOException)
13681 {
13682 GCX_COOP(); // Must be cooperative to modify frame chain.
13683
13684 // EEPolicy::HandleFatalStackOverflow pushes a FaultingExceptionFrame on the stack after SO
13685 // exception. Our hijack code runs in the exception context, and overwrites the stack space
13686 // after SO excpetion, so this frame was popped out before invoking RaiseFailFast. We need to
13687 // put it back here for running func-eval code.
13688 // This cumbersome code should be removed once SO synchronization is moved to be completely
13689 // out-of-process.
13690 fef.InitAndLink(pContext);
13691 }
13692
13693 STRESS_LOG0(LF_CORDB, LL_INFO10, "D::EHW: Calling NotifyDebuggerLastChance\n");
13694 NotifyDebuggerLastChance(pThread, &exceptionInfo, TRUE);
13695
13696 // Continuing from a second chance managed exception causes the process to exit.
13697 TerminateProcess(GetCurrentProcess(), 0);
13698 }
13699
13700 // Since this is a unhandled managed exception:
13701 // - we always have a Thread* object.
13702 // - we always have a throwable
13703 // - we executed through the 1st-pass of the EH logic. This means the 1st-pass could do work
13704 // to enforce certain invariants (like the ones listed here, or ensuring the thread can be crawled)
13705
13706 // Need to call the CLR's UEF. This will do all the key work including:
13707 // - send the managed 2nd-chance exception event.
13708 // - deal with synchronization.
13709 // - allow func-evals.
13710 // - deal with interception.
13711
13712 // If intercepted, then this never returns. It will manually invoke the unwinders and fix the context.
13713
13714 // InternalUnhandledExceptionFilter_Worker has a throws contract, but should not be throwing in any
13715 // conditions we care about. This hijack should never throw, so catch everything.
13716 HRESULT hrIgnore;
13717 EX_TRY
13718 {
13719 InternalUnhandledExceptionFilter_Worker(&exceptionInfo);
13720 }
13721 EX_CATCH_HRESULT(hrIgnore);
13722
13723 // Continuing from a second chance managed exception causes the process to exit.
13724 TerminateProcess(GetCurrentProcess(), 0);
13725}
13726
13727#ifdef FEATURE_INTEROP_DEBUGGING
13728//
13729// This is the handler function that is put in place of a thread's top-most SEH handler function when it is hijacked by
13730// the Right Side during an unmanaged first chance exception.
13731//
13732typedef EXCEPTION_DISPOSITION (__cdecl *SEHHandler)(EXCEPTION_RECORD *pExceptionRecord,
13733 EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame,
13734 CONTEXT *pContext,
13735 void *DispatcherContext);
13736#define DOSPEW 0
13737
13738#if DOSPEW
13739#define SPEW(s) s
13740#else
13741#define SPEW(s)
13742#endif
13743
13744
13745
13746
13747//-----------------------------------------------------------------------------
13748// Hijack when we have a M2U handoff.
13749// This happens when we do a step-out from Managed-->Unmanaged, and so we hit a managed patch in Native code.
13750// This also happens when a managed stepper does a step-in to unmanaged code.
13751// Since we're in native code, there's no CPFH, and so we have to hijack.
13752// @todo- could this be removed? Step-out to native is illegal in v2.0, and do existing
13753// CLR filters catch the step-in patch?
13754// @dbgtodo controller/stepping - this will be completely unneeded in V3 when all stepping is oop
13755//-----------------------------------------------------------------------------
13756VOID Debugger::M2UHandoffHijackWorker(CONTEXT *pContext,
13757 EXCEPTION_RECORD *pExceptionRecord)
13758{
13759 // We must use a static contract here because the function does not return normally
13760 STATIC_CONTRACT_NOTHROW;
13761 STATIC_CONTRACT_GC_TRIGGERS; // from sending managed event
13762 STATIC_CONTRACT_MODE_PREEMPTIVE; // we're in umanaged code.
13763 SO_NOT_MAINLINE_FUNCTION;
13764
13765
13766 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Context=0x%p exception record=0x%p\n",
13767 pContext, pExceptionRecord));
13768
13769 // We should only be here for a BP
13770 _ASSERTE(pExceptionRecord->ExceptionCode == STATUS_BREAKPOINT);
13771
13772 // Get the current runtime thread. This is only an optimized TLS access.
13773 // Since we're coming off a managed-step, we should always have a thread.
13774 Thread *pEEThread = g_pEEInterface->GetThread();
13775 _ASSERTE(pEEThread != NULL);
13776
13777 _ASSERTE(!pEEThread->GetInteropDebuggingHijacked());
13778 pEEThread->SetInteropDebuggingHijacked(TRUE);
13779
13780 //win32 has a weird property where EIP points after the BP in the debug event
13781 //so we are adjusting it to point at the BP
13782 CORDbgAdjustPCForBreakInstruction((DT_CONTEXT*)pContext);
13783 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Context ip set to 0x%p\n", GetIP(pContext)));
13784
13785 _ASSERTE(!ISREDIRECTEDTHREAD(pEEThread));
13786
13787 // Don't bother setting FilterContext here because we already pass it to FirstChanceNativeException.
13788 // Shortcut right to our dispatch native exception logic, there may be no COMPlusFrameHandler in place!
13789 EX_TRY
13790 {
13791 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Calling FirstChanceNativeException\n"));
13792 bool okay;
13793 okay = g_pDebugger->FirstChanceNativeException(pExceptionRecord,
13794 pContext,
13795 pExceptionRecord->ExceptionCode,
13796 pEEThread);
13797 _ASSERTE(okay == true);
13798 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: FirstChanceNativeException returned\n"));
13799 }
13800 EX_CATCH
13801 {
13802 // It would be really bad if somebody threw here. We're actually outside of managed code,
13803 // so there's not a lot we can do besides just swallow the exception and hope for the best.
13804 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: ERROR! FirstChanceNativeException threw an exception\n"));
13805 }
13806 EX_END_CATCH(SwallowAllExceptions);
13807
13808 _ASSERTE(!ISREDIRECTEDTHREAD(pEEThread));
13809 _ASSERTE(pEEThread->GetInteropDebuggingHijacked());
13810 pEEThread->SetInteropDebuggingHijacked(FALSE);
13811
13812 // This signal will be received by the RS and it will use SetThreadContext
13813 // to clear away the entire hijack frame. This function does not return.
13814 LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Flaring hijack complete\n"));
13815 SignalHijackComplete();
13816
13817 _ASSERTE(!"UNREACHABLE");
13818}
13819
13820//-----------------------------------------------------------------------------
13821// This hijack is run after receiving an IB event that we don't know how the
13822// debugger will want to continue. Under the covers we clear the event and divert
13823// execution here where we block until the debugger decides whether or not to clear
13824// the event. At that point we exit this hijack and the LS diverts execution back
13825// to the offending instruction.
13826// We don't know:
13827// - whether we have an EE-thread?
13828// - how we're going to continue this (handled / not-handled).
13829//
13830// But we do know that:
13831// - this exception does not belong to the CLR.
13832// - this thread is not in cooperative mode.
13833//-----------------------------------------------------------------------------
13834LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
13835 EXCEPTION_RECORD *pExceptionRecord)
13836{
13837 // if we aren't set up to do interop debugging this function should just bail out
13838 if(m_pRCThread == NULL)
13839 return EXCEPTION_CONTINUE_SEARCH;
13840
13841 DebuggerIPCControlBlock *pDCB = m_pRCThread->GetDCB();
13842 if(pDCB == NULL)
13843 return EXCEPTION_CONTINUE_SEARCH;
13844
13845 if (!pDCB->m_rightSideIsWin32Debugger)
13846 return EXCEPTION_CONTINUE_SEARCH;
13847
13848 // at this point we know that there is an interop debugger attached. This makes it safe to send
13849 // flares
13850#if DOSPEW
13851 DWORD tid = GetCurrentThreadId();
13852#endif
13853
13854 SPEW(fprintf(stderr, "0x%x D::FCHF: in first chance hijack filter.\n", tid));
13855 SPEW(fprintf(stderr, "0x%x D::FCHF: pExceptionRecord=0x%p (%d), pContext=0x%p (%d)\n", tid, pExceptionRecord, sizeof(EXCEPTION_RECORD),
13856 pContext, sizeof(CONTEXT)));
13857#if defined(_TARGET_AMD64_)
13858 SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%p, Rip=0x%p, Rsp=0x%p, EFlags=0x%08x\n",
13859 tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Rip, pContext->Rsp,
13860 pContext->EFlags));
13861#elif defined(_TARGET_X86_)
13862 SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Eip=0x%08x, Esp=0x%08x, EFlags=0x%08x\n",
13863 tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Eip, pContext->Esp,
13864 pContext->EFlags));
13865#elif defined(_TARGET_ARM64_)
13866 SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Pc=0x%p, Sp=0x%p, EFlags=0x%08x\n",
13867 tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Pc, pContext->Sp,
13868 pContext->EFlags));
13869#endif
13870
13871 // This memory is used as IPC during the hijack. We will place a pointer to this in
13872 // the EE debugger word (a TLS slot that works even on the debugger break-in thread)
13873 // and then the RS can write info into the memory.
13874 DebuggerIPCFirstChanceData fcd;
13875
13876 // Accessing through the volatile pointer to fend off some potential compiler optimizations.
13877 // If the debugger changes that data from OOP we need to see those updates
13878 volatile DebuggerIPCFirstChanceData* pFcd = &fcd;
13879
13880 // The Windows native break in thread does not have TLS storage allocated.
13881 bool debuggerBreakInThread = (NtCurrentTeb()->ThreadLocalStoragePointer == NULL);
13882 {
13883 // Hijack filters are always in the can't stop range.
13884 // The RS knows this b/c it knows which threads it hijacked.
13885 // Bump up the CS counter so that any further calls in the LS can see this too.
13886 // (This makes places where we assert that we're in a CS region happy).
13887 CantStopHolder hCantStop(!debuggerBreakInThread);
13888
13889 // Get the current runtime thread. This is only an optimized TLS access.
13890 Thread *pEEThread = debuggerBreakInThread ? NULL : g_pEEInterface->GetThread();
13891
13892 // Hook up the memory so RS can get to it
13893 fcd.pLeftSideContext.Set((DT_CONTEXT*)pContext);
13894 fcd.action = HIJACK_ACTION_EXIT_UNHANDLED;
13895 fcd.debugCounter = 0;
13896
13897 SPEW(fprintf(stderr, "0x%x D::FCHF: Set debugger word to 0x%p.\n", tid, pFcd));
13898 g_pEEInterface->SetThreadDebuggerWord((VOID*)pFcd);
13899
13900 // Signal the RS to tell us what to do
13901 SPEW(fprintf(stderr, "0x%x D::FCHF: Signaling hijack started.\n", tid));
13902 SignalHijackStarted();
13903 SPEW(fprintf(stderr, "0x%x D::FCHF: Signaling hijack started complete. DebugCounter=0x%x\n", tid, pFcd->debugCounter));
13904
13905 if (pFcd->action == HIJACK_ACTION_WAIT)
13906 {
13907 // This exception does NOT belong to the CLR.
13908 // If we belong to the CLR, then we either:
13909 // - were a M2U transition, in which case we should be in a different Hijack
13910 // - were a CLR exception in CLR code, in which case we should have continued and let the inproc handlers get it.
13911 SPEW(fprintf(stderr, "0x%x D::FCHF: exception does not belong to the Runtime, pEEThread=0x%p, pContext=0x%p\n",
13912 tid, pEEThread, pContext));
13913
13914 if (pEEThread != NULL)
13915 {
13916 _ASSERTE(!pEEThread->GetInteropDebuggingHijacked()); // hijack is not re-entrant.
13917 pEEThread->SetInteropDebuggingHijacked(TRUE);
13918
13919 // Setting the FilterContext must be done in cooperative mode (since it's like pushing a Frame onto the Frame chain).
13920 // Thus we have a violation. We don't really need the filter context specifically here, we're just using
13921 // it for legacy purposes as a way to stash the context of the original exception (that this thread was hijacked from).
13922 // @todo - use another way to store the context indepedent of the Filter context.
13923 CONTRACT_VIOLATION(ModeViolation);
13924 _ASSERTE(g_pEEInterface->GetThreadFilterContext(pEEThread) == NULL);
13925 g_pEEInterface->SetThreadFilterContext(pEEThread, pContext);
13926 }
13927
13928 // Wait for the continue. We may / may not have an EE Thread for this, (and we're definitely
13929 // not doing fiber-mode debugging), so just use a raw win32 API, and not some fancy fiber-safe call.
13930 SPEW(fprintf(stderr, "0x%x D::FCHF: waiting for continue.\n", tid));
13931 DWORD ret = WaitForSingleObject(g_pDebugger->m_pRCThread->GetDCB()->m_leftSideUnmanagedWaitEvent, INFINITE);
13932 SPEW(fprintf(stderr, "0x%x D::FCHF: waiting for continue complete.\n", tid));
13933
13934 if (ret != WAIT_OBJECT_0)
13935 {
13936 SPEW(fprintf(stderr, "0x%x D::FCHF: wait failed!\n", tid));
13937 }
13938
13939 if (pEEThread != NULL)
13940 {
13941 _ASSERTE(pEEThread->GetInteropDebuggingHijacked());
13942 pEEThread->SetInteropDebuggingHijacked(FALSE);
13943 _ASSERTE(!ISREDIRECTEDTHREAD(pEEThread));
13944
13945 // See violation above.
13946 CONTRACT_VIOLATION(ModeViolation);
13947 g_pEEInterface->SetThreadFilterContext(pEEThread, NULL);
13948 _ASSERTE(g_pEEInterface->GetThreadFilterContext(pEEThread) == NULL);
13949 }
13950 }
13951
13952 SPEW(fprintf(stderr, "0x%x D::FCHF: signaling HijackComplete.\n", tid));
13953 SignalHijackComplete();
13954 SPEW(fprintf(stderr, "0x%x D::FCHF: done signaling HijackComplete. DebugCounter=0x%x\n", tid, pFcd->debugCounter));
13955
13956 // we should know what we are about to do now
13957 _ASSERTE(pFcd->action != HIJACK_ACTION_WAIT);
13958
13959 // cleanup from above
13960 SPEW(fprintf(stderr, "0x%x D::FCHF: set debugger word = NULL.\n", tid));
13961 g_pEEInterface->SetThreadDebuggerWord(NULL);
13962
13963 } // end can't stop region
13964
13965 if (pFcd->action == HIJACK_ACTION_EXIT_HANDLED)
13966 {
13967 SPEW(fprintf(stderr, "0x%x D::FCHF: exiting with CONTINUE_EXECUTION\n", tid));
13968 return EXCEPTION_CONTINUE_EXECUTION;
13969 }
13970 else
13971 {
13972 SPEW(fprintf(stderr, "0x%x D::FCHF: exiting with CONTINUE_SEARCH\n", tid));
13973 _ASSERTE(pFcd->action == HIJACK_ACTION_EXIT_UNHANDLED);
13974 return EXCEPTION_CONTINUE_SEARCH;
13975 }
13976}
13977
13978#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
13979void GenericHijackFuncHelper()
13980{
13981#if DOSPEW
13982 DWORD tid = GetCurrentThreadId();
13983#endif
13984
13985 // The Windows native break in thread does not have TLS storage allocated.
13986 bool debuggerBreakInThread = (NtCurrentTeb()->ThreadLocalStoragePointer == NULL);
13987
13988 // Hijack filters are always in the can't stop range.
13989 // The RS knows this b/c it knows which threads it hijacked.
13990 // Bump up the CS counter so that any further calls in the LS can see this too.
13991 // (This makes places where we assert that we're in a CS region happy).
13992 CantStopHolder hCantStop(!debuggerBreakInThread);
13993
13994 SPEW(fprintf(stderr, "0x%x D::GHF: in generic hijack.\n", tid));
13995
13996 // There is no need to setup any context pointer or interact with the Right Side in anyway. We simply wait for
13997 // the continue event to be set.
13998 SPEW(fprintf(stderr, "0x%x D::GHF: waiting for continue.\n", tid));
13999
14000 // If this thread has an EE thread and that EE thread has preemptive gc disabled, then mark that there is a
14001 // thread at an unsafe place and enable pgc. This will allow us to sync even with this thread hijacked.
14002 bool disabled = false;
14003
14004 Thread *pEEThread = debuggerBreakInThread ? NULL : g_pEEInterface->GetThread();
14005
14006 if (pEEThread != NULL)
14007 {
14008 disabled = g_pEEInterface->IsPreemptiveGCDisabled();
14009 _ASSERTE(!disabled);
14010
14011 _ASSERTE(!pEEThread->GetInteropDebuggingHijacked());
14012 pEEThread->SetInteropDebuggingHijacked(TRUE);
14013 }
14014
14015 DWORD ret = WaitForSingleObject(g_pRCThread->GetDCB()->m_leftSideUnmanagedWaitEvent,
14016 INFINITE);
14017
14018 if (ret != WAIT_OBJECT_0)
14019 {
14020 SPEW(fprintf(stderr, "0x%x D::GHF: wait failed!\n", tid));
14021 }
14022
14023 // Get the continue type. Non-zero means that the exception was not cleared by the Right Side and therefore has
14024 // not been handled. Zero means that the exception has been cleared. (Presumably, the debugger altered the
14025 // thread's context before clearing the exception, so continuing will give a different result.)
14026 DWORD continueType = 0;
14027
14028 void* threadDebuggerWord = g_pEEInterface->GetThreadDebuggerWord();
14029
14030 if (pEEThread != NULL)
14031 {
14032 // We've got a Thread ptr, so get the continue type out of the thread's debugger word.
14033 continueType = (DWORD)threadDebuggerWord;
14034
14035 _ASSERTE(pEEThread->GetInteropDebuggingHijacked());
14036 pEEThread->SetInteropDebuggingHijacked(FALSE);
14037 }
14038 else if (threadDebuggerWord != NULL)
14039 {
14040 continueType = 1;
14041 g_pEEInterface->SetThreadDebuggerWord(NULL);
14042 }
14043
14044 SPEW(fprintf(stderr, "0x%x D::GHF: continued with %d.\n", tid, continueType));
14045
14046 if (continueType)
14047 {
14048 SPEW(fprintf(stderr, "0x%x D::GHF: calling ExitProcess\n", tid));
14049
14050 // Continuing from a second chance exception without clearing the exception causes the process to
14051 // exit. Note: the continue type will only be non-zero if this hijack was setup for a second chance
14052 // exception. If the hijack was setup for another type of debug event, then we'll never get here.
14053 //
14054 // We explicitly terminate the process directly instead of going through any escalation policy because:
14055 // 1) that's what a native-only debugger would do. Interop and Native-only should be the same.
14056 // 2) there's no CLR escalation policy anyways for *native* unhandled exceptions.
14057 // 3) The escalation policy may do lots of extra confusing work (like fire MDAs) that can only cause
14058 // us grief.
14059 TerminateProcess(GetCurrentProcess(), 0);
14060 }
14061
14062 SPEW(fprintf(stderr, "0x%x D::GHF: signaling continue...\n", tid));
14063}
14064#endif
14065
14066
14067//
14068// This is the function that a thread is hijacked to by the Right Side during a variety of debug events. This function
14069// must be naked.
14070//
14071#if defined(_TARGET_X86_)
14072__declspec(naked)
14073#endif // defined (_x86_)
14074void Debugger::GenericHijackFunc(void)
14075{
14076#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
14077
14078#if defined(_TARGET_X86_)
14079 _asm
14080 {
14081 push ebp
14082 mov ebp,esp
14083 sub esp,__LOCAL_SIZE
14084 }
14085#endif
14086 // We can't have C++ classes w/ dtors in a declspec naked, so just have call into a helper.
14087 GenericHijackFuncHelper();
14088
14089#if defined(_TARGET_X86_)
14090 _asm
14091 {
14092 mov esp,ebp
14093 pop ebp
14094 }
14095#endif
14096
14097 // This signals the Right Side that this thread is ready to have its context restored.
14098 ExceptionNotForRuntime();
14099
14100#else
14101 _ASSERTE(!"@todo - port GenericHijackFunc");
14102#endif // defined (_x86_)
14103
14104 _ASSERTE(!"Should never get here (Debugger::GenericHijackFunc)");
14105}
14106
14107
14108
14109
14110//#ifdef _TARGET_X86_
14111//
14112// This is the function that is called when we determine that a first chance exception hijack has
14113// begun and memory is prepared for the RS to tell the LS what to do
14114//
14115void Debugger::SignalHijackStarted(void)
14116{
14117 WRAPPER_NO_CONTRACT;
14118
14119#if defined(FEATURE_INTEROP_DEBUGGING)
14120 SignalHijackStartedFlare();
14121#else
14122 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14123#endif
14124}
14125
14126//
14127// This is the function that is called when we determine that a first chance exception really belongs to the Runtime,
14128// and that that exception is due to a managed->unmanaged transition. This notifies the Right Side of this and the Right
14129// Side fixes up the thread's execution state from there, making sure to remember that it needs to continue to hide the
14130// hijack state of the thread.
14131//
14132void Debugger::ExceptionForRuntimeHandoffStart(void)
14133{
14134 WRAPPER_NO_CONTRACT;
14135
14136#if defined(FEATURE_INTEROP_DEBUGGING)
14137 ExceptionForRuntimeHandoffStartFlare();
14138#else
14139 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14140#endif
14141
14142}
14143
14144//
14145// This is the function that is called when the original handler returns after we've determined that an exception was
14146// due to a managed->unmanaged transition. This notifies the Right Side of this and the Right Side fixes up the thread's
14147// execution state from there, making sure to turn off its flag indicating that the thread's hijack state should still
14148// be hidden.
14149//
14150void Debugger::ExceptionForRuntimeHandoffComplete(void)
14151{
14152 WRAPPER_NO_CONTRACT;
14153
14154#if defined(FEATURE_INTEROP_DEBUGGING)
14155 ExceptionForRuntimeHandoffCompleteFlare();
14156#else
14157 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14158#endif
14159
14160}
14161
14162//
14163// This signals the RS that a hijack function is ready to return. This will cause the RS to restore
14164// the thread context
14165//
14166void Debugger::SignalHijackComplete(void)
14167{
14168 WRAPPER_NO_CONTRACT;
14169
14170#if defined(FEATURE_INTEROP_DEBUGGING)
14171 SignalHijackCompleteFlare();
14172#else
14173 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14174#endif
14175
14176}
14177
14178//
14179// This is the function that is called when we determine that a first chance exception does not belong to the
14180// Runtime. This notifies the Right Side of this and the Right Side fixes up the thread's execution state from there.
14181//
14182void Debugger::ExceptionNotForRuntime(void)
14183{
14184 WRAPPER_NO_CONTRACT;
14185
14186#if defined(FEATURE_INTEROP_DEBUGGING)
14187 ExceptionNotForRuntimeFlare();
14188#else
14189 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14190#endif
14191}
14192
14193//
14194// This is the function that is called when we want to send a sync complete event to the Right Side when it is the Win32
14195// debugger of this process. This notifies the Right Side of this and the Right Side fixes up the thread's execution
14196// state from there.
14197//
14198void Debugger::NotifyRightSideOfSyncComplete(void)
14199{
14200 WRAPPER_NO_CONTRACT;
14201 STRESS_LOG0(LF_CORDB, LL_INFO100000, "D::NRSOSC: Sending flare...\n");
14202#if defined(FEATURE_INTEROP_DEBUGGING)
14203 NotifyRightSideOfSyncCompleteFlare();
14204#else
14205 _ASSERTE(!"@todo - port the flares to the platform your running on.");
14206#endif
14207 STRESS_LOG0(LF_CORDB, LL_INFO100000, "D::NRSOSC: Flare sent\n");
14208}
14209
14210#endif // FEATURE_INTEROP_DEBUGGING
14211
14212/******************************************************************************
14213 *
14214 ******************************************************************************/
14215bool Debugger::GetILOffsetFromNative (MethodDesc *pFunc, const BYTE *pbAddr,
14216 DWORD nativeOffset, DWORD *ilOffset)
14217{
14218 CONTRACTL
14219 {
14220 THROWS;
14221 GC_TRIGGERS_FROM_GETJITINFO;
14222 }
14223 CONTRACTL_END;
14224
14225 _ASSERTE(pFunc != NULL);
14226 _ASSERTE(pbAddr != NULL);
14227
14228 if (!HasLazyData())
14229 {
14230 DebuggerLockHolder dbgLockHolder(this);
14231 // This is an entry path into the debugger, so make sure we're inited.
14232 LazyInit();
14233 }
14234
14235 // Sometimes we'll get called w/ an instantiating stub MD.
14236 if (pFunc->IsWrapperStub())
14237 {
14238 pFunc = pFunc->GetWrappedMethodDesc();
14239 }
14240
14241 if (pFunc->IsDynamicMethod())
14242 {
14243 return false;
14244 }
14245
14246 DebuggerMethodInfo *methodInfo = GetOrCreateMethodInfo(pFunc->GetModule(), pFunc->GetMemberDef());
14247 if (methodInfo == NULL)
14248 {
14249 return false;
14250 }
14251
14252 PCODE methodStartAddress = g_pEEInterface->GetNativeCodeStartAddress((PCODE)pbAddr);
14253 if (methodStartAddress == NULL)
14254 {
14255 return false;
14256 }
14257
14258 DebuggerJitInfo *jitInfo = methodInfo->FindOrCreateInitAndAddJitInfo(pFunc, methodStartAddress);
14259 if (jitInfo == NULL)
14260 {
14261 return false;
14262 }
14263
14264 CorDebugMappingResult map;
14265 DWORD whichIDontCare;
14266 *ilOffset = jitInfo->MapNativeOffsetToIL(
14267 nativeOffset,
14268 &map,
14269 &whichIDontCare);
14270 return true;
14271}
14272
14273/******************************************************************************
14274 *
14275 ******************************************************************************/
14276DWORD Debugger::GetHelperThreadID(void )
14277{
14278 LIMITED_METHOD_CONTRACT;
14279
14280 return m_pRCThread ? m_pRCThread->GetDCB()->m_temporaryHelperThreadId : 0;
14281}
14282
14283
14284// HRESULT Debugger::InsertToMethodInfoList(): Make sure
14285// that there's only one head of the the list of DebuggerMethodInfos
14286// for the (implicitly) given MethodDef/Module pair.
14287HRESULT
14288Debugger::InsertToMethodInfoList( DebuggerMethodInfo *dmi )
14289{
14290 CONTRACTL
14291 {
14292 THROWS;
14293 GC_NOTRIGGER;
14294 }
14295 CONTRACTL_END;
14296
14297 LOG((LF_CORDB,LL_INFO10000,"D:IAHOL DMI: dmi:0x%08x\n", dmi));
14298
14299 HRESULT hr = S_OK;
14300
14301 _ASSERTE(dmi != NULL);
14302
14303 _ASSERTE(HasDebuggerDataLock());
14304
14305 // CHECK_DJI_TABLE_DEBUGGER;
14306
14307 hr = CheckInitMethodInfoTable();
14308
14309 if (FAILED(hr)) {
14310 return (hr);
14311 }
14312
14313 DebuggerMethodInfo *dmiPrev = m_pMethodInfos->GetMethodInfo(dmi->m_module, dmi->m_token);
14314
14315 _ASSERTE((dmiPrev == NULL) || ((dmi->m_token == dmiPrev->m_token) && (dmi->m_module == dmiPrev->m_module)));
14316
14317 LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: current head of dmi list:0x%08x\n",dmiPrev));
14318
14319 if (dmiPrev != NULL)
14320 {
14321 dmi->m_prevMethodInfo = dmiPrev;
14322 dmiPrev->m_nextMethodInfo = dmi;
14323
14324 _ASSERTE(dmi->m_module != NULL);
14325 hr = m_pMethodInfos->OverwriteMethodInfo(dmi->m_module,
14326 dmi->m_token,
14327 dmi,
14328 FALSE);
14329
14330 LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: DMI version 0x%04x for token 0x%08x\n",
14331 dmi->GetCurrentEnCVersion(),dmi->m_token));
14332 }
14333 else
14334 {
14335 LOG((LF_CORDB, LL_EVERYTHING, "AddMethodInfo being called in D:IAHOL\n"));
14336 hr = m_pMethodInfos->AddMethodInfo(dmi->m_module,
14337 dmi->m_token,
14338 dmi);
14339 }
14340#ifdef _DEBUG
14341 dmiPrev = m_pMethodInfos->GetMethodInfo(dmi->m_module, dmi->m_token);
14342 LOG((LF_CORDB,LL_INFO10000,"D:IAHOL: new head of dmi list:0x%08x\n",
14343 dmiPrev));
14344#endif //_DEBUG
14345
14346 // DebuggerDataLockHolder out of scope - release implied
14347 return hr;
14348}
14349
14350//-----------------------------------------------------------------------------
14351// Helper to get an SString through the IPC buffer.
14352// We do this by putting the SString data into a LS_RS_buffer object,
14353// and then the RS reads it out as soon as it's queued.
14354// It's very very important that the SString's buffer is around while we send the event.
14355// So we pass the SString by reference in case there's an implicit conversion (because
14356// we don't want to do the conversion on a temporary object and then lose that object).
14357//-----------------------------------------------------------------------------
14358void SetLSBufferFromSString(Ls_Rs_StringBuffer * pBuffer, SString & str)
14359{
14360 // Copy string contents (+1 for null terminator) into a LS_RS_Buffer.
14361 // Then the RS can pull it out as a null-terminated string.
14362 pBuffer->SetLsData(
14363 (BYTE*) str.GetUnicode(),
14364 (str.GetCount() +1)* sizeof(WCHAR)
14365 );
14366}
14367
14368//*************************************************************
14369// structure that we to marshal MDA Notification event data.
14370//*************************************************************
14371struct SendMDANotificationParams
14372{
14373 Thread * m_pThread; // may be NULL. Lets us send on behalf of other threads.
14374
14375 // Pass SStrings by ptr in case to guarantee that they're shared (in case we internally modify their storage).
14376 SString * m_szName;
14377 SString * m_szDescription;
14378 SString * m_szXML;
14379 CorDebugMDAFlags m_flags;
14380
14381 SendMDANotificationParams(
14382 Thread * pThread, // may be NULL. Lets us send on behalf of other threads.
14383 SString * szName,
14384 SString * szDescription,
14385 SString * szXML,
14386 CorDebugMDAFlags flags
14387 ) :
14388 m_pThread(pThread),
14389 m_szName(szName),
14390 m_szDescription(szDescription),
14391 m_szXML(szXML),
14392 m_flags(flags)
14393 {
14394 LIMITED_METHOD_CONTRACT;
14395 }
14396
14397};
14398
14399//-----------------------------------------------------------------------------
14400// Actually send the MDA event. (Could be on any thread)
14401// Parameters:
14402// params - data to initialize the IPC event.
14403//-----------------------------------------------------------------------------
14404void Debugger::SendRawMDANotification(
14405 SendMDANotificationParams * params
14406)
14407{
14408 // Send the unload assembly event to the Right Side.
14409 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
14410
14411 Thread * pThread = params->m_pThread;
14412 AppDomain *pAppDomain = (pThread != NULL) ? pThread->GetDomain() : NULL;
14413
14414 InitIPCEvent(ipce,
14415 DB_IPCE_MDA_NOTIFICATION,
14416 pThread,
14417 pAppDomain);
14418
14419 SetLSBufferFromSString(&ipce->MDANotification.szName, *(params->m_szName));
14420 SetLSBufferFromSString(&ipce->MDANotification.szDescription, *(params->m_szDescription));
14421 SetLSBufferFromSString(&ipce->MDANotification.szXml, *(params->m_szXML));
14422 ipce->MDANotification.dwOSThreadId = GetCurrentThreadId();
14423 ipce->MDANotification.flags = params->m_flags;
14424
14425 m_pRCThread->SendIPCEvent();
14426}
14427
14428//-----------------------------------------------------------------------------
14429// Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side.
14430// Called by EE to send a MDA debug event. This will block on the debug event
14431// until the RS continues us.
14432// Debugger may or may not be attached. If bAttached, then this
14433// will trigger a jitattach as well.
14434// See MDA documentation for what szName, szDescription + szXML should look like.
14435// The debugger just passes them through.
14436//
14437// Parameters:
14438// pThread - thread for debug event. May be null.
14439// szName - short name of MDA.
14440// szDescription - full description of MDA.
14441// szXML - xml string for MDA.
14442// bAttach - do a JIT-attach
14443//-----------------------------------------------------------------------------
14444void Debugger::SendMDANotification(
14445 Thread * pThread, // may be NULL. Lets us send on behalf of other threads.
14446 SString * szName,
14447 SString * szDescription,
14448 SString * szXML,
14449 CorDebugMDAFlags flags,
14450 BOOL bAttach
14451)
14452{
14453 CONTRACTL
14454 {
14455 THROWS;
14456 GC_TRIGGERS;
14457 MODE_ANY;
14458 }
14459 CONTRACTL_END;
14460
14461 PREFIX_ASSUME(szName != NULL);
14462 PREFIX_ASSUME(szDescription != NULL);
14463 PREFIX_ASSUME(szXML != NULL);
14464
14465 // Note: we normally don't send events like this when there is an unrecoverable error. However,
14466 // if a host attempts to setup fiber mode on a thread, then we'll set an unrecoverable error
14467 // and use an MDA to 1) tell the user and 2) get the Right Side to notice the unrecoverable error.
14468 // Therefore, we'll go ahead and send a MDA event if the unrecoverable error is
14469 // CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS.
14470 DebuggerIPCControlBlock *pDCB = m_pRCThread->GetDCB();
14471
14472
14473 // If the MDA is ocuring very early in startup before the DCB is setup, then bail.
14474 if (pDCB == NULL)
14475 {
14476 return;
14477 }
14478
14479 if (CORDBUnrecoverableError(this) && (pDCB->m_errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS))
14480 {
14481 return;
14482 }
14483
14484 // Validate flags. Make sure that folks don't start passing flags that we don't handle.
14485 // If pThread != current thread, caller should either pass in MDA_FLAG_SLIP or guarantee
14486 // that pThread is not slipping.
14487 _ASSERTE((flags & ~(MDA_FLAG_SLIP)) == 0);
14488
14489 // Helper thread should not be triggering MDAs. The helper thread is executing code in a very constrained
14490 // and controlled region and shouldn't be able to do anything dangerous.
14491 // If we revise this in the future, we should probably just post the event to the RS w/ use the MDA_FLAG_SLIP flag,
14492 // and then not bother suspending the runtime. The RS will get it on its next event.
14493 // The jit-attach logic below assumes we're not on the helper. (If we are on the helper, then a debugger should already
14494 // be attached)
14495 if (ThisIsHelperThreadWorker())
14496 {
14497 CONSISTENCY_CHECK_MSGF(false, ("MDA '%s' fired on *helper* thread.\r\nDesc:%s",
14498 szName->GetUnicode(), szDescription->GetUnicode()
14499 ));
14500
14501 // If for some reason we're wrong about the assert above, we'll just ignore the MDA (rather than potentially deadlock)
14502 return;
14503 }
14504
14505 // Public entry point into the debugger. May cause a jit-attach, so we may need to be lazily-init.
14506 if (!HasLazyData())
14507 {
14508 DebuggerLockHolder dbgLockHolder(this);
14509 // This is an entry path into the debugger, so make sure we're inited.
14510 LazyInit();
14511 }
14512
14513
14514 // Cases:
14515 // 1) Debugger already attached, send event normally (ignore severity)
14516 // 2) No debugger attached, Non-severe probe - ignore.
14517 // 3) No debugger attached, Severe-probe - do a jit-attach.
14518 bool fTryJitAttach = bAttach == TRUE;
14519
14520 // Check case #2 - no debugger, and no jit-attach. Early opt out.
14521 if (!CORDebuggerAttached() && !fTryJitAttach)
14522 {
14523 return;
14524 }
14525
14526 if (pThread == NULL)
14527 {
14528 // If there's no thread object, then we're not blocking after the event,
14529 // and thus this probe may slip.
14530 flags = (CorDebugMDAFlags) (flags | MDA_FLAG_SLIP);
14531 }
14532
14533 {
14534 GCX_PREEMP_EEINTERFACE_TOGGLE_IFTHREAD();
14535
14536 // For "Severe" probes, we'll do a jit attach dialog
14537 if (fTryJitAttach)
14538 {
14539 // May return:
14540 // - S_OK if we do a jit-attach,
14541 // - S_FALSE if a debugger is already attached.
14542 // - Error in other cases..
14543
14544 JitAttach(pThread, NULL, TRUE, FALSE);
14545 }
14546
14547 // Debugger may be attached now...
14548 if (CORDebuggerAttached())
14549 {
14550 SendMDANotificationParams params(pThread, szName, szDescription, szXML, flags);
14551
14552 // Non-attach case. Send like normal event.
14553 // This includes if someone launch the debugger during the meantime.
14554 // just send the event
14555 SENDIPCEVENT_BEGIN(this, pThread);
14556
14557 // Send Log message event to the Right Side
14558 SendRawMDANotification(&params);
14559
14560 // Stop all Runtime threads
14561 // Even if we don't have a managed thead object, this will catch us at the next good spot.
14562 TrapAllRuntimeThreads();
14563
14564 // Let other Runtime threads handle their events.
14565 SENDIPCEVENT_END;
14566 }
14567 } // end of GCX_PREEMP_EEINTERFACE_TOGGLE()
14568}
14569
14570//*************************************************************
14571// This method sends a log message over to the right side for the debugger to log it.
14572//
14573// The CLR doesn't assign any semantics to the level or cateogory values.
14574// The BCL has a level convention (LoggingLevels enum), but this isn't exposed publicly,
14575// so we shouldn't base our behavior on it in any way.
14576//*************************************************************
14577void Debugger::SendLogMessage(int iLevel,
14578 SString * pSwitchName,
14579 SString * pMessage)
14580{
14581 CONTRACTL
14582 {
14583 GC_TRIGGERS;
14584 THROWS;
14585 }
14586 CONTRACTL_END;
14587
14588 LOG((LF_CORDB, LL_INFO10000, "D::SLM: Sending log message.\n"));
14589
14590 // Send the message only if the debugger is attached to this appdomain.
14591 // Note the the debugger may detach at any time, so we'll have to check
14592 // this again after we get the lock.
14593 AppDomain *pAppDomain = g_pEEInterface->GetThread()->GetDomain();
14594
14595 if (!CORDebuggerAttached())
14596 {
14597 return;
14598 }
14599
14600 Thread *pThread = g_pEEInterface->GetThread();
14601 SENDIPCEVENT_BEGIN(this, pThread);
14602
14603 // Send Log message event to the Right Side
14604 SendRawLogMessage(
14605 pThread,
14606 pAppDomain,
14607 iLevel,
14608 pSwitchName,
14609 pMessage);
14610
14611 // Stop all Runtime threads
14612 TrapAllRuntimeThreads();
14613
14614 // Let other Runtime threads handle their events.
14615 SENDIPCEVENT_END;
14616}
14617
14618
14619//*************************************************************
14620//
14621// Helper function to just send LogMessage event. Can be called on either
14622// helper thread or managed thread.
14623//
14624//*************************************************************
14625void Debugger::SendRawLogMessage(
14626 Thread *pThread,
14627 AppDomain *pAppDomain,
14628 int iLevel,
14629 SString * pCategory,
14630 SString * pMessage
14631)
14632{
14633 DebuggerIPCEvent* ipce;
14634
14635
14636 // We should have hold debugger lock
14637 // This can happen on either native helper thread or managed thread
14638 _ASSERTE(ThreadHoldsLock());
14639
14640 // It's possible that the debugger dettached while we were waiting
14641 // for our lock. Check again and abort the event if it did.
14642 if (!CORDebuggerAttached())
14643 {
14644 return;
14645 }
14646
14647 ipce = m_pRCThread->GetIPCEventSendBuffer();
14648
14649 // Send a LogMessage event to the Right Side
14650 InitIPCEvent(ipce,
14651 DB_IPCE_FIRST_LOG_MESSAGE,
14652 pThread,
14653 pAppDomain);
14654
14655 ipce->FirstLogMessage.iLevel = iLevel;
14656 ipce->FirstLogMessage.szCategory.SetString(pCategory->GetUnicode());
14657 SetLSBufferFromSString(&ipce->FirstLogMessage.szContent, *pMessage);
14658
14659 m_pRCThread->SendIPCEvent();
14660}
14661
14662
14663// This function sends a message to the right side informing it about
14664// the creation/modification of a LogSwitch
14665void Debugger::SendLogSwitchSetting(int iLevel,
14666 int iReason,
14667 __in_z LPCWSTR pLogSwitchName,
14668 __in_z LPCWSTR pParentSwitchName)
14669{
14670 CONTRACTL
14671 {
14672 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
14673 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
14674 }
14675 CONTRACTL_END;
14676
14677 LOG((LF_CORDB, LL_INFO1000, "D::SLSS: Sending log switch message switch=%S parent=%S.\n",
14678 pLogSwitchName, pParentSwitchName));
14679
14680 // Send the message only if the debugger is attached to this appdomain.
14681 if (!CORDebuggerAttached())
14682 {
14683 return;
14684 }
14685
14686 Thread *pThread = g_pEEInterface->GetThread();
14687 SENDIPCEVENT_BEGIN(this, pThread);
14688
14689 if (CORDebuggerAttached())
14690 {
14691 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
14692 InitIPCEvent(ipce,
14693 DB_IPCE_LOGSWITCH_SET_MESSAGE,
14694 pThread,
14695 pThread->GetDomain());
14696
14697 ipce->LogSwitchSettingMessage.iLevel = iLevel;
14698 ipce->LogSwitchSettingMessage.iReason = iReason;
14699
14700
14701 ipce->LogSwitchSettingMessage.szSwitchName.SetString(pLogSwitchName);
14702
14703 if (pParentSwitchName == NULL)
14704 {
14705 pParentSwitchName = W("");
14706 }
14707
14708 ipce->LogSwitchSettingMessage.szParentSwitchName.SetString(pParentSwitchName);
14709
14710 m_pRCThread->SendIPCEvent();
14711
14712 // Stop all Runtime threads
14713 TrapAllRuntimeThreads();
14714 }
14715 else
14716 {
14717 LOG((LF_CORDB,LL_INFO1000, "D::SLSS: Skipping SendIPCEvent because RS detached."));
14718 }
14719
14720 SENDIPCEVENT_END;
14721}
14722
14723// send a custom debugger notification to the RS
14724// Arguments:
14725// input: pThread - thread on which the notification occurred
14726// pDomain - domain file for the domain in which the notification occurred
14727// classToken - metadata token for the type of the notification object
14728void Debugger::SendCustomDebuggerNotification(Thread * pThread,
14729 DomainFile * pDomain,
14730 mdTypeDef classToken)
14731{
14732 CONTRACTL
14733 {
14734 GC_TRIGGERS;
14735 THROWS;
14736 }
14737 CONTRACTL_END;
14738
14739 LOG((LF_CORDB, LL_INFO10000, "D::SLM: Sending log message.\n"));
14740
14741 // Send the message only if the debugger is attached to this appdomain.
14742 // Note the the debugger may detach at any time, so we'll have to check
14743 // this again after we get the lock.
14744 if (!CORDebuggerAttached())
14745 {
14746 return;
14747 }
14748
14749 Thread *curThread = g_pEEInterface->GetThread();
14750 SENDIPCEVENT_BEGIN(this, curThread);
14751
14752 if (CORDebuggerAttached())
14753 {
14754 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
14755 InitIPCEvent(ipce,
14756 DB_IPCE_CUSTOM_NOTIFICATION,
14757 curThread,
14758 curThread->GetDomain());
14759
14760 VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::MakePtr(pDomain);
14761
14762 ipce->CustomNotification.classToken = classToken;
14763 ipce->CustomNotification.vmDomainFile = vmDomainFile;
14764
14765
14766 m_pRCThread->SendIPCEvent();
14767
14768 // Stop all Runtime threads
14769 TrapAllRuntimeThreads();
14770 }
14771 else
14772 {
14773 LOG((LF_CORDB,LL_INFO1000, "D::SCDN: Skipping SendIPCEvent because RS detached."));
14774 }
14775
14776 SENDIPCEVENT_END;
14777}
14778
14779
14780//-----------------------------------------------------------------------------
14781//
14782// Add the AppDomain to the list stored in the IPC block. It adds the id and
14783// the name.
14784//
14785// Arguments:
14786// pAppDomain - The runtime app domain object to add.
14787//
14788// Return Value:
14789// S_OK on success, else detailed error code.
14790//
14791HRESULT Debugger::AddAppDomainToIPC(AppDomain *pAppDomain)
14792{
14793 CONTRACTL
14794 {
14795 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
14796 GC_TRIGGERS;
14797 MODE_ANY;
14798 }
14799 CONTRACTL_END;
14800
14801 HRESULT hr = S_OK;
14802 LPCWSTR szName = NULL;
14803
14804 LOG((LF_CORDB, LL_INFO100, "D::AADTIPC: Executing AADTIPC for AppDomain 0x%08x (0x%x).\n",
14805 pAppDomain,
14806 pAppDomain->GetId().m_dwId));
14807
14808 STRESS_LOG2(LF_CORDB, LL_INFO10000, "D::AADTIPC: AddAppDomainToIPC:%#08x, %#08x\n",
14809 pAppDomain, pAppDomain->GetId().m_dwId);
14810
14811
14812
14813 _ASSERTE(m_pAppDomainCB->m_iTotalSlots > 0);
14814 _ASSERTE(m_pAppDomainCB->m_rgListOfAppDomains != NULL);
14815
14816 {
14817 //
14818 // We need to synchronize this routine with the attach logic. The "normal"
14819 // attach case uses the HelperThread and TrapAllRuntimeThreads to synchronize
14820 // the runtime before sending any of the events (including AppDomainCreates)
14821 // to the right-side. Thus, we can synchronize with this case by forcing us
14822 // to go co-operative. If we were already co-op, then the helper thread will
14823 // wait to start the attach until all co-op threads are paused. If we were
14824 // pre-emptive, then going co-op will suspend us until the HelperThread finishes.
14825 //
14826 // The second case is under the IPC event for ATTACHING, which is where there are
14827 // zero app domains, so it is considered an 'early attach' case. To synchronize
14828 // with this we have to grab and hold the AppDomainDB lock.
14829 //
14830
14831 GCX_COOP();
14832
14833 // Lock the list
14834 if (!m_pAppDomainCB->Lock())
14835 {
14836 return E_FAIL;
14837 }
14838
14839 // Get a free entry from the list
14840 AppDomainInfo *pAppDomainInfo = m_pAppDomainCB->GetFreeEntry();
14841
14842 // Function returns NULL if the list is full and a realloc failed.
14843 if (!pAppDomainInfo)
14844 {
14845 hr = E_OUTOFMEMORY;
14846 goto LErrExit;
14847 }
14848
14849 // copy the ID
14850 pAppDomainInfo->m_id = pAppDomain->GetId().m_dwId;
14851
14852 // Now set the AppDomainName.
14853
14854 /*
14855 * TODO :
14856 *
14857 * Make sure that returning NULL here does not result in a catastrophic
14858 * failure.
14859 *
14860 * GetFriendlyNameNoThrow may call SetFriendlyName, which may call
14861 * UpdateAppDomainEntryInIPC. There is no recursive death, however, because
14862 * the AppDomainInfo object does not contain a pointer to the app domain
14863 * yet.
14864 */
14865 szName = pAppDomain->GetFriendlyNameForDebugger();
14866 pAppDomainInfo->SetName(szName);
14867
14868 // Save on to the appdomain pointer
14869 pAppDomainInfo->m_pAppDomain = pAppDomain;
14870
14871 // bump the used slot count
14872 m_pAppDomainCB->m_iNumOfUsedSlots++;
14873
14874LErrExit:
14875 // UnLock the list
14876 m_pAppDomainCB->Unlock();
14877
14878 // Send event to debugger if one is attached.
14879 if (CORDebuggerAttached())
14880 {
14881 SendCreateAppDomainEvent(pAppDomain);
14882 }
14883 }
14884
14885 return hr;
14886}
14887
14888
14889/******************************************************************************
14890 * Remove the AppDomain from the list stored in the IPC block and send an ExitAppDomain
14891 * event to the debugger if attached.
14892 ******************************************************************************/
14893HRESULT Debugger::RemoveAppDomainFromIPC (AppDomain *pAppDomain)
14894{
14895 CONTRACTL
14896 {
14897 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
14898 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
14899 SO_INTOLERANT;
14900 }
14901 CONTRACTL_END;
14902
14903 HRESULT hr = E_FAIL;
14904
14905 LOG((LF_CORDB, LL_INFO100, "D::RADFIPC: Executing RADFIPC for AppDomain 0x%08x (0x%x).\n",
14906 pAppDomain,
14907 pAppDomain->GetId().m_dwId));
14908
14909 // if none of the slots are occupied, then simply return.
14910 if (m_pAppDomainCB->m_iNumOfUsedSlots == 0)
14911 return hr;
14912
14913 // Lock the list
14914 if (!m_pAppDomainCB->Lock())
14915 return (E_FAIL);
14916
14917
14918 // Look for the entry
14919 AppDomainInfo *pADInfo = m_pAppDomainCB->FindEntry(pAppDomain);
14920
14921 // Shouldn't be trying to remove an appdomain that was never added
14922 if (!pADInfo)
14923 {
14924 // We'd like to assert this, but there is a small window where we may have
14925 // called AppDomain::Init (and so it's fair game to call Stop, and hence come here),
14926 // but not yet published the app domain.
14927 // _ASSERTE(!"D::RADFIPC: trying to remove an AppDomain that was never added");
14928 hr = (E_FAIL);
14929 goto ErrExit;
14930 }
14931
14932 // Release the entry
14933 m_pAppDomainCB->FreeEntry(pADInfo);
14934
14935ErrExit:
14936 // UnLock the list
14937 m_pAppDomainCB->Unlock();
14938
14939 // send event to debugger if one is attached
14940 if (CORDebuggerAttached())
14941 {
14942 SendExitAppDomainEvent(pAppDomain);
14943 }
14944
14945 return hr;
14946}
14947
14948/******************************************************************************
14949 * Update the AppDomain in the list stored in the IPC block.
14950 ******************************************************************************/
14951HRESULT Debugger::UpdateAppDomainEntryInIPC(AppDomain *pAppDomain)
14952{
14953 CONTRACTL
14954 {
14955 NOTHROW;
14956 if (GetThread()) { GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
14957 SO_INTOLERANT;
14958 }
14959 CONTRACTL_END;
14960
14961 HRESULT hr = S_OK;
14962 LPCWSTR szName = NULL;
14963
14964 LOG((LF_CORDB, LL_INFO100,
14965 "D::UADEIIPC: Executing UpdateAppDomainEntryInIPC ad:0x%x.\n",
14966 pAppDomain));
14967
14968 // if none of the slots are occupied, then simply return.
14969 if (m_pAppDomainCB->m_iNumOfUsedSlots == 0)
14970 return (E_FAIL);
14971
14972 // Lock the list
14973 if (!m_pAppDomainCB->Lock())
14974 return (E_FAIL);
14975
14976 // Look up the info entry
14977 AppDomainInfo *pADInfo = m_pAppDomainCB->FindEntry(pAppDomain);
14978
14979 if (!pADInfo)
14980 {
14981 hr = E_FAIL;
14982 goto ErrExit;
14983 }
14984
14985 // Update the name only if new name is non-null
14986 szName = pADInfo->m_pAppDomain->GetFriendlyNameForDebugger();
14987 pADInfo->SetName(szName);
14988
14989 LOG((LF_CORDB, LL_INFO100,
14990 "D::UADEIIPC: New name:%ls (AD:0x%x)\n", pADInfo->m_szAppDomainName,
14991 pAppDomain));
14992
14993ErrExit:
14994 // UnLock the list
14995 m_pAppDomainCB->Unlock();
14996
14997 return hr;
14998}
14999
15000HRESULT Debugger::CopyModulePdb(Module* pRuntimeModule)
15001{
15002 CONTRACTL
15003 {
15004 THROWS;
15005 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
15006 SO_NOT_MAINLINE;
15007
15008 PRECONDITION(ThisIsHelperThread());
15009 MODE_ANY;
15010 }
15011 CONTRACTL_END;
15012
15013 if (!pRuntimeModule->IsVisibleToDebugger())
15014 {
15015 return S_OK;
15016 }
15017
15018 HRESULT hr = S_OK;
15019
15020 return hr;
15021}
15022
15023/******************************************************************************
15024 * When attaching to a process, this is called to enumerate all of the
15025 * AppDomains currently in the process and allow modules pdbs to be copied over to the shadow dir maintaining out V2 in-proc behaviour.
15026 ******************************************************************************/
15027HRESULT Debugger::IterateAppDomainsForPdbs()
15028{
15029 CONTRACTL
15030 {
15031 THROWS;
15032 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
15033 SO_NOT_MAINLINE;
15034
15035 PRECONDITION(ThisIsHelperThread());
15036 MODE_ANY;
15037 }
15038 CONTRACTL_END;
15039
15040 STRESS_LOG0(LF_CORDB, LL_INFO100, "Entered function IterateAppDomainsForPdbs()\n");
15041 HRESULT hr = S_OK;
15042
15043 // Lock the list
15044 if (!m_pAppDomainCB->Lock())
15045 return (E_FAIL);
15046
15047 // Iterate through the app domains
15048 AppDomainInfo *pADInfo = m_pAppDomainCB->FindFirst();
15049
15050 while (pADInfo)
15051 {
15052 STRESS_LOG3(LF_CORDB, LL_INFO100, "Iterating over domain %#08x AD:%#08x %ls\n", pADInfo->m_pAppDomain->GetId().m_dwId, pADInfo->m_pAppDomain, pADInfo->m_szAppDomainName);
15053
15054 AppDomain::AssemblyIterator i;
15055 i = pADInfo->m_pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution));
15056 CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
15057 while (i.Next(pDomainAssembly.This()))
15058 {
15059 if (!pDomainAssembly->IsVisibleToDebugger())
15060 continue;
15061
15062 DomainAssembly::ModuleIterator j = pDomainAssembly->IterateModules(kModIterIncludeLoading);
15063 while (j.Next())
15064 {
15065 DomainFile * pDomainFile = j.GetDomainFile();
15066 if (!pDomainFile->ShouldNotifyDebugger())
15067 continue;
15068
15069 Module* pRuntimeModule = pDomainFile->GetModule();
15070 CopyModulePdb(pRuntimeModule);
15071 }
15072 if (pDomainAssembly->ShouldNotifyDebugger())
15073 {
15074 CopyModulePdb(pDomainAssembly->GetModule());
15075 }
15076 }
15077
15078 // Get the next appdomain in the list
15079 pADInfo = m_pAppDomainCB->FindNext(pADInfo);
15080 }
15081
15082 // Unlock the list
15083 m_pAppDomainCB->Unlock();
15084
15085 STRESS_LOG0(LF_CORDB, LL_INFO100, "Exiting function IterateAppDomainsForPdbs\n");
15086
15087 return hr;
15088}
15089
15090
15091/******************************************************************************
15092 *
15093 ******************************************************************************/
15094HRESULT Debugger::InitAppDomainIPC(void)
15095{
15096 CONTRACTL
15097 {
15098 THROWS;
15099 GC_NOTRIGGER;
15100 SO_INTOLERANT;
15101
15102 PRECONDITION(CheckPointer(m_pAppDomainCB));
15103 }
15104 CONTRACTL_END;
15105
15106 // Ensure that if we throw here, the Terminate will get called and cleanup all resources.
15107 // This will make Init an atomic operation - it either fully inits or fully fails.
15108 class EnsureCleanup
15109 {
15110 Debugger * m_pThis;
15111
15112 public:
15113 EnsureCleanup(Debugger * pThis)
15114 {
15115 m_pThis = pThis;
15116 }
15117
15118 void SupressCleanup()
15119 {
15120 m_pThis = NULL;
15121 }
15122
15123 ~EnsureCleanup()
15124 {
15125 if (m_pThis != NULL)
15126 {
15127 m_pThis->TerminateAppDomainIPC();
15128 }
15129 }
15130 } hEnsureCleanup(this);
15131
15132 DWORD dwStrLen = 0;
15133 SString szExeName;
15134 int i;
15135
15136 // all fields in the object can be zero initialized.
15137 // If we throw, before fully initializing this, then cleanup won't try to free
15138 // uninited values.
15139 ZeroMemory(m_pAppDomainCB, sizeof(*m_pAppDomainCB));
15140
15141 // Create a mutex to allow the Left and Right Sides to properly
15142 // synchronize. The Right Side will spin until m_hMutex is valid,
15143 // then it will acquire it before accessing the data.
15144 HandleHolder hMutex(WszCreateMutex(NULL, TRUE/*hold*/, NULL));
15145 if (hMutex == NULL)
15146 {
15147 ThrowLastError();
15148 }
15149 if (!m_pAppDomainCB->m_hMutex.SetLocal(hMutex))
15150 {
15151 ThrowLastError();
15152 }
15153 hMutex.SuppressRelease();
15154
15155 m_pAppDomainCB->m_iSizeInBytes = INITIAL_APP_DOMAIN_INFO_LIST_SIZE *
15156 sizeof (AppDomainInfo);
15157
15158 // Number of slots in AppDomainListElement array
15159 m_pAppDomainCB->m_rgListOfAppDomains = new AppDomainInfo[INITIAL_APP_DOMAIN_INFO_LIST_SIZE];
15160 _ASSERTE(m_pAppDomainCB->m_rgListOfAppDomains != NULL); // throws on oom
15161
15162
15163 m_pAppDomainCB->m_iTotalSlots = INITIAL_APP_DOMAIN_INFO_LIST_SIZE;
15164
15165 // Initialize each AppDomainListElement
15166 for (i = 0; i < INITIAL_APP_DOMAIN_INFO_LIST_SIZE; i++)
15167 {
15168 m_pAppDomainCB->m_rgListOfAppDomains[i].FreeEntry();
15169 }
15170
15171 // also initialize the process name
15172 dwStrLen = WszGetModuleFileName(NULL,
15173 szExeName);
15174
15175
15176 // If we couldn't get the name, then use a nice default.
15177 if (dwStrLen == 0)
15178 {
15179 szExeName.Set(W("<NoProcessName>"));
15180 dwStrLen = szExeName.GetCount();
15181 }
15182
15183 // If we got the name, copy it into a buffer. dwStrLen is the
15184 // count of characters in the name, not including the null
15185 // terminator.
15186 m_pAppDomainCB->m_szProcessName = new WCHAR[dwStrLen + 1];
15187 _ASSERTE(m_pAppDomainCB->m_szProcessName != NULL); // throws on oom
15188
15189 wcscpy_s(m_pAppDomainCB->m_szProcessName, dwStrLen + 1, szExeName);
15190
15191 // Add 1 to the string length so the Right Side will copy out the
15192 // null terminator, too.
15193 m_pAppDomainCB->m_iProcessNameLengthInBytes = (dwStrLen + 1) * sizeof(WCHAR);
15194
15195 if (m_pAppDomainCB->m_hMutex != NULL)
15196 {
15197 m_pAppDomainCB->Unlock();
15198 }
15199
15200 hEnsureCleanup.SupressCleanup();
15201 return S_OK;
15202}
15203
15204/******************************************************************************
15205 * Unitialize the AppDomain IPC block
15206 * Returns:
15207 * S_OK -if fully unitialized
15208 * E_FAIL - if we can't get ownership of the block, and thus no unitialization
15209 * work is done.
15210 ******************************************************************************/
15211HRESULT Debugger::TerminateAppDomainIPC(void)
15212{
15213 CONTRACTL
15214 {
15215 NOTHROW;
15216 GC_NOTRIGGER;
15217 SO_INTOLERANT;
15218 }
15219 CONTRACTL_END;
15220
15221 // If we have no AppDomain block, then we can consider it's already terminated.
15222 if (m_pAppDomainCB == NULL)
15223 return S_OK;
15224
15225 HRESULT hr = S_OK;
15226
15227 // Lock the list
15228 // If there's no mutex, then we're in a partially created state.
15229 // This means InitAppDomainIPC failed halfway through. But we're still thread safe
15230 // since other threads can't access us if we don't have the mutex.
15231 if ((m_pAppDomainCB->m_hMutex != NULL) && !m_pAppDomainCB->Lock())
15232 {
15233 // The callers don't check our return value, we may want to know when we can't gracefully clean up
15234 LOG((LF_CORDB, LL_INFO10, "Debugger::TerminateAppDomainIPC: Failed to get AppDomain IPC lock, not cleaning up.\n"));
15235
15236 // If the lock is valid, but we can't get it, then we can't really
15237 // uninitialize since someone else is using the block.
15238 return (E_FAIL);
15239 }
15240
15241 // The shared IPC segment could still be around after the debugger
15242 // object has been destroyed during process shutdown. So, reset
15243 // the UsedSlots count to 0 so that any out of process clients
15244 // enumeratingthe app domains in this process see 0 AppDomains.
15245 m_pAppDomainCB->m_iNumOfUsedSlots = 0;
15246 m_pAppDomainCB->m_iTotalSlots = 0;
15247
15248 // Now delete the memory allocated for AppDomainInfo array
15249 delete [] m_pAppDomainCB->m_rgListOfAppDomains;
15250 m_pAppDomainCB->m_rgListOfAppDomains = NULL;
15251
15252 delete [] m_pAppDomainCB->m_szProcessName;
15253 m_pAppDomainCB->m_szProcessName = NULL;
15254 m_pAppDomainCB->m_iProcessNameLengthInBytes = 0;
15255
15256 // Set the mutex handle to NULL.
15257 // If the Right Side acquires the mutex, it will verify
15258 // that the handle is still not NULL. If it is, then it knows it
15259 // really lost.
15260 RemoteHANDLE m = m_pAppDomainCB->m_hMutex;
15261 m_pAppDomainCB->m_hMutex.m_hLocal = NULL;
15262
15263 // And bring us back to a fully unintialized state.
15264 ZeroMemory(m_pAppDomainCB, sizeof(*m_pAppDomainCB));
15265
15266 // We're done. release and close the mutex. Note that this must be done
15267 // after we clear it out above to ensure there is no race condition.
15268 if( m != NULL )
15269 {
15270 VERIFY(ReleaseMutex(m));
15271 m.Close();
15272 }
15273
15274 return hr;
15275}
15276
15277
15278#ifndef DACCESS_COMPILE
15279
15280//
15281// FuncEvalSetup sets up a function evaluation for the given method on the given thread.
15282//
15283HRESULT Debugger::FuncEvalSetup(DebuggerIPCE_FuncEvalInfo *pEvalInfo,
15284 BYTE **argDataArea,
15285 DebuggerEval **debuggerEvalKey)
15286{
15287 CONTRACTL
15288 {
15289 NOTHROW;
15290 GC_NOTRIGGER;
15291 SO_NOT_MAINLINE;
15292 }
15293 CONTRACTL_END;
15294
15295 Thread *pThread = pEvalInfo->vmThreadToken.GetRawPtr();
15296
15297
15298 //
15299 // If TS_AbortRequested (which may have been set by a pending FuncEvalAbort),
15300 // we will not be able to do a new func-eval
15301 //
15302 // <TODO>@TODO: Remember the current value of m_State, reset m_State as appropriate,
15303 // do the new func-eval, and then set m_State to the original value</TODO>
15304 if (pThread->m_State & Thread::TS_AbortRequested)
15305 return CORDBG_E_FUNC_EVAL_BAD_START_POINT;
15306
15307 if (g_fProcessDetach)
15308 return CORDBG_E_FUNC_EVAL_BAD_START_POINT;
15309
15310 // If there is no guard page on this thread, then we've taken a stack overflow exception and can't run managed
15311 // code on this thread. Therefore, we can't do a func eval on this thread.
15312 if (!pThread->DetermineIfGuardPagePresent())
15313 {
15314 return CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW;
15315 }
15316
15317 bool fInException = pEvalInfo->evalDuringException;
15318
15319 // The thread has to be at a GC safe place for now, just in case the func eval causes a collection. Processing an
15320 // exception also counts as a "safe place." Eventually, we'd like to have to avoid this check and eval anyway, but
15321 // that's a way's off...
15322 if (!fInException && !g_pDebugger->IsThreadAtSafePlace(pThread))
15323 return CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT;
15324
15325 // For now, we assume that the target thread must be stopped in managed code due to a single step or a
15326 // breakpoint. Being stopped while sending a first or second chance exception is also valid, and there may or may
15327 // not be a filter context when we do a func eval from such places. This will loosen over time, eventually allowing
15328 // threads that are stopped anywhere in managed code to perform func evals.
15329 CONTEXT *filterContext = GetManagedStoppedCtx(pThread);
15330
15331 if (filterContext == NULL && !fInException)
15332 {
15333 return CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT;
15334 }
15335
15336 // Create a DebuggerEval to hold info about this eval while its in progress. Constructor copies the thread's
15337 // CONTEXT.
15338 DebuggerEval *pDE = new (interopsafe, nothrow) DebuggerEval(filterContext, pEvalInfo, fInException);
15339
15340 if (pDE == NULL)
15341 {
15342 return E_OUTOFMEMORY;
15343 }
15344 else if (!pDE->Init())
15345 {
15346 // We fail to change the m_breakpointInstruction field to PAGE_EXECUTE_READWRITE permission.
15347 return E_FAIL;
15348 }
15349
15350 SIZE_T argDataAreaSize = 0;
15351
15352 argDataAreaSize += pEvalInfo->genericArgsNodeCount * sizeof(DebuggerIPCE_TypeArgData);
15353
15354 if ((pEvalInfo->funcEvalType == DB_IPCE_FET_NORMAL) ||
15355 (pEvalInfo->funcEvalType == DB_IPCE_FET_NEW_OBJECT) ||
15356 (pEvalInfo->funcEvalType == DB_IPCE_FET_NEW_OBJECT_NC))
15357 argDataAreaSize += pEvalInfo->argCount * sizeof(DebuggerIPCE_FuncEvalArgData);
15358 else if (pEvalInfo->funcEvalType == DB_IPCE_FET_NEW_STRING)
15359 argDataAreaSize += pEvalInfo->stringSize;
15360 else if (pEvalInfo->funcEvalType == DB_IPCE_FET_NEW_ARRAY)
15361 argDataAreaSize += pEvalInfo->arrayRank * sizeof(SIZE_T);
15362
15363 if (argDataAreaSize > 0)
15364 {
15365 pDE->m_argData = new (interopsafe, nothrow) BYTE[argDataAreaSize];
15366
15367 if (pDE->m_argData == NULL)
15368 {
15369 DeleteInteropSafeExecutable(pDE);
15370 return E_OUTOFMEMORY;
15371 }
15372
15373 // Pass back the address of the argument data area so the right side can write to it for us.
15374 *argDataArea = pDE->m_argData;
15375 }
15376
15377 // Set the thread's IP (in the filter context) to our hijack function if we're stopped due to a breakpoint or single
15378 // step.
15379 if (!fInException)
15380 {
15381 _ASSERTE(filterContext != NULL);
15382
15383 ::SetIP(filterContext, (UINT_PTR)GetEEFuncEntryPoint(::FuncEvalHijack));
15384
15385 // Don't be fooled into thinking you can push things onto the thread's stack now. If the thread is stopped at a
15386 // breakpoint or from a single step, then its really suspended in the SEH filter. ESP in the thread's CONTEXT,
15387 // therefore, points into the middle of the thread's current stack. So we pass things we need in the hijack in
15388 // the thread's registers.
15389
15390 // Set the first argument to point to the DebuggerEval.
15391#if defined(_TARGET_X86_)
15392 filterContext->Eax = (DWORD)pDE;
15393#elif defined(_TARGET_AMD64_)
15394#ifdef UNIX_AMD64_ABI
15395 filterContext->Rdi = (SIZE_T)pDE;
15396#else // UNIX_AMD64_ABI
15397 filterContext->Rcx = (SIZE_T)pDE;
15398#endif // !UNIX_AMD64_ABI
15399#elif defined(_TARGET_ARM_)
15400 filterContext->R0 = (DWORD)pDE;
15401#elif defined(_TARGET_ARM64_)
15402 filterContext->X0 = (SIZE_T)pDE;
15403#else
15404 PORTABILITY_ASSERT("Debugger::FuncEvalSetup is not implemented on this platform.");
15405#endif
15406
15407 //
15408 // To prevent GCs until the func-eval gets a chance to run, we increment the counter here.
15409 // We only need to do this if we have changed the filter CONTEXT, since the stack will be unwalkable
15410 // in this case.
15411 //
15412 g_pDebugger->IncThreadsAtUnsafePlaces();
15413 }
15414 else
15415 {
15416 HRESULT hr = CheckInitPendingFuncEvalTable();
15417
15418 if (FAILED(hr))
15419 {
15420 DeleteInteropSafeExecutable(pDE); // Note this runs the destructor for DebuggerEval, which releases its internal buffers
15421 return (hr);
15422 }
15423 // If we're in an exception, then add a pending eval for this thread. This will cause us to perform the func
15424 // eval when the user continues the process after the current exception event.
15425 GetPendingEvals()->AddPendingEval(pDE->m_thread, pDE);
15426 }
15427
15428
15429 // Return that all went well. Tracing the stack at this point should not show that the func eval is setup, but it
15430 // will show a wrong IP, so it shouldn't be done.
15431 *debuggerEvalKey = pDE;
15432
15433 LOG((LF_CORDB, LL_INFO100000, "D:FES for pDE:%08x evalType:%d on thread %#x, id=0x%x\n",
15434 pDE, pDE->m_evalType, pThread, GetThreadIdHelper(pThread)));
15435
15436 return S_OK;
15437}
15438
15439//
15440// FuncEvalSetupReAbort sets up a function evaluation specifically to rethrow a ThreadAbortException on the given
15441// thread.
15442//
15443HRESULT Debugger::FuncEvalSetupReAbort(Thread *pThread, Thread::ThreadAbortRequester requester)
15444{
15445 CONTRACTL
15446 {
15447 NOTHROW;
15448 GC_NOTRIGGER;
15449 SO_NOT_MAINLINE;
15450 }
15451 CONTRACTL_END;
15452
15453 LOG((LF_CORDB, LL_INFO1000,
15454 "D::FESRA: performing reabort on thread %#x, id=0x%x\n",
15455 pThread, GetThreadIdHelper(pThread)));
15456
15457 // The thread has to be at a GC safe place. It should be, since this is only done in response to a previous eval
15458 // completing with a ThreadAbortException.
15459 if (!g_pDebugger->IsThreadAtSafePlace(pThread))
15460 return CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT;
15461
15462 // Grab the filter context.
15463 CONTEXT *filterContext = GetManagedStoppedCtx(pThread);
15464
15465 if (filterContext == NULL)
15466 {
15467 return CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT;
15468 }
15469
15470 // Create a DebuggerEval to hold info about this eval while its in progress. Constructor copies the thread's
15471 // CONTEXT.
15472 DebuggerEval *pDE = new (interopsafe, nothrow) DebuggerEval(filterContext, pThread, requester);
15473
15474 if (pDE == NULL)
15475 {
15476 return E_OUTOFMEMORY;
15477 }
15478 else if (!pDE->Init())
15479 {
15480 // We fail to change the m_breakpointInstruction field to PAGE_EXECUTE_READWRITE permission.
15481 return E_FAIL;
15482 }
15483
15484 // Set the thread's IP (in the filter context) to our hijack function.
15485 _ASSERTE(filterContext != NULL);
15486
15487 ::SetIP(filterContext, (UINT_PTR)GetEEFuncEntryPoint(::FuncEvalHijack));
15488
15489#ifdef _TARGET_X86_ // reliance on filterContext->Eip & Eax
15490 // Set EAX to point to the DebuggerEval.
15491 filterContext->Eax = (DWORD)pDE;
15492#elif defined(_TARGET_AMD64_)
15493 // Set RCX to point to the DebuggerEval.
15494 filterContext->Rcx = (SIZE_T)pDE;
15495#elif defined(_TARGET_ARM_)
15496 filterContext->R0 = (DWORD)pDE;
15497#elif defined(_TARGET_ARM64_)
15498 filterContext->X0 = (SIZE_T)pDE;
15499#else
15500 PORTABILITY_ASSERT("FuncEvalSetupReAbort (Debugger.cpp) is not implemented on this platform.");
15501#endif
15502
15503 // Now clear the bit requesting a re-abort
15504 pThread->ResetThreadStateNC(Thread::TSNC_DebuggerReAbort);
15505
15506 g_pDebugger->IncThreadsAtUnsafePlaces();
15507
15508 // Return that all went well. Tracing the stack at this point should not show that the func eval is setup, but it
15509 // will show a wrong IP, so it shouldn't be done.
15510
15511 return S_OK;
15512}
15513
15514//
15515// FuncEvalAbort: Does a gentle abort of a func-eval already in progress.
15516// Because this type of abort waits for the thread to get to a good state,
15517// it may never return, or may time out.
15518//
15519
15520//
15521// Wait at most 0.5 seconds.
15522//
15523#define FUNC_EVAL_DEFAULT_TIMEOUT_VALUE 500
15524
15525HRESULT
15526Debugger::FuncEvalAbort(
15527 DebuggerEval *debuggerEvalKey
15528 )
15529{
15530 CONTRACTL
15531 {
15532 THROWS;
15533 GC_NOTRIGGER;
15534 }
15535 CONTRACTL_END;
15536
15537 DebuggerEval *pDE = (DebuggerEval*) debuggerEvalKey;
15538 HRESULT hr = S_OK;
15539 CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());
15540 if (FAILED(hr))
15541 {
15542 return hr;
15543 }
15544
15545
15546 if (pDE->m_aborting == DebuggerEval::FE_ABORT_NONE)
15547 {
15548 // Remember that we're aborting this func eval.
15549 pDE->m_aborting = DebuggerEval::FE_ABORT_NORMAL;
15550
15551 LOG((LF_CORDB, LL_INFO1000,
15552 "D::FEA: performing UserAbort on thread %#x, id=0x%x\n",
15553 pDE->m_thread, GetThreadIdHelper(pDE->m_thread)));
15554
15555 if (!g_fProcessDetach && !pDE->m_completed)
15556 {
15557 //
15558 // Perform a stop on the thread that the eval is running on.
15559 // This will cause a ThreadAbortException to be thrown on the thread.
15560 //
15561 EX_TRY
15562 {
15563 hr = pDE->m_thread->UserAbort(Thread::TAR_FuncEval, EEPolicy::TA_Safe, (DWORD)FUNC_EVAL_DEFAULT_TIMEOUT_VALUE, Thread::UAC_Normal);
15564 if (hr == HRESULT_FROM_WIN32(ERROR_TIMEOUT))
15565 {
15566 hr = S_OK;
15567 }
15568 }
15569 EX_CATCH
15570 {
15571 _ASSERTE(!"Unknown exception from UserAbort(), not expected");
15572 }
15573 EX_END_CATCH(EX_RETHROW);
15574
15575 }
15576
15577 LOG((LF_CORDB, LL_INFO1000, "D::FEA: UserAbort complete.\n"));
15578 }
15579
15580 return hr;
15581}
15582
15583//
15584// FuncEvalRudeAbort: Does a rude abort of a func-eval in progress. This
15585// leaves the thread in an undetermined state.
15586//
15587HRESULT
15588Debugger::FuncEvalRudeAbort(
15589 DebuggerEval *debuggerEvalKey
15590 )
15591{
15592 CONTRACTL
15593 {
15594 THROWS;
15595 GC_NOTRIGGER;
15596 SO_NOT_MAINLINE;
15597 }
15598 CONTRACTL_END;
15599
15600 HRESULT hr = S_OK;
15601 CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());
15602 if (FAILED(hr))
15603 {
15604 return hr;
15605 }
15606
15607
15608 DebuggerEval *pDE = debuggerEvalKey;
15609
15610
15611 if (!(pDE->m_aborting & DebuggerEval::FE_ABORT_RUDE))
15612 {
15613 //
15614 // Remember that we're aborting this func eval.
15615 //
15616 pDE->m_aborting = (DebuggerEval::FUNC_EVAL_ABORT_TYPE)(pDE->m_aborting | DebuggerEval::FE_ABORT_RUDE);
15617
15618 LOG((LF_CORDB, LL_INFO1000,
15619 "D::FEA: performing RudeAbort on thread %#x, id=0x%x\n",
15620 pDE->m_thread, Debugger::GetThreadIdHelper(pDE->m_thread)));
15621
15622 if (!g_fProcessDetach && !pDE->m_completed)
15623 {
15624 //
15625 // Perform a stop on the thread that the eval is running on.
15626 // This will cause a ThreadAbortException to be thrown on the thread.
15627 //
15628 EX_TRY
15629 {
15630 hr = pDE->m_thread->UserAbort(Thread::TAR_FuncEval, EEPolicy::TA_Rude, (DWORD)FUNC_EVAL_DEFAULT_TIMEOUT_VALUE, Thread::UAC_Normal);
15631 if (hr == HRESULT_FROM_WIN32(ERROR_TIMEOUT))
15632 {
15633 hr = S_OK;
15634 }
15635 }
15636 EX_CATCH
15637 {
15638 _ASSERTE(!"Unknown exception from UserAbort(), not expected");
15639 EX_RETHROW;
15640 }
15641 EX_END_CATCH(RethrowTerminalExceptions);
15642 }
15643
15644 LOG((LF_CORDB, LL_INFO1000, "D::FEA: RudeAbort complete.\n"));
15645 }
15646
15647 return hr;
15648}
15649
15650//
15651// FuncEvalCleanup cleans up after a function evaluation is released.
15652//
15653HRESULT Debugger::FuncEvalCleanup(DebuggerEval *debuggerEvalKey)
15654{
15655 LIMITED_METHOD_CONTRACT;
15656
15657 DebuggerEval *pDE = debuggerEvalKey;
15658
15659 _ASSERTE(pDE->m_completed);
15660
15661 LOG((LF_CORDB, LL_INFO1000, "D::FEC: pDE:%08x 0x%08x, id=0x%x\n",
15662 pDE, pDE->m_thread, GetThreadIdHelper(pDE->m_thread)));
15663
15664 DeleteInteropSafeExecutable(pDE->m_bpInfoSegment);
15665 DeleteInteropSafe(pDE);
15666
15667 return S_OK;
15668}
15669
15670#endif // ifndef DACCESS_COMPILE
15671
15672//
15673// SetReference sets an object reference for the Right Side,
15674// respecting the write barrier for references that are in the heap.
15675//
15676HRESULT Debugger::SetReference(void *objectRefAddress,
15677 VMPTR_OBJECTHANDLE vmObjectHandle,
15678 void *newReference)
15679{
15680 CONTRACTL
15681 {
15682 NOTHROW;
15683 GC_NOTRIGGER;
15684 }
15685 CONTRACTL_END;
15686
15687 HRESULT hr = S_OK;
15688
15689 hr = ValidateObject((Object *)newReference);
15690 if (FAILED(hr))
15691 {
15692 return hr;
15693 }
15694
15695
15696 // If the object ref isn't in a handle, then go ahead and use
15697 // SetObjectReference.
15698 if (vmObjectHandle.IsNull())
15699 {
15700 OBJECTREF *dst = (OBJECTREF*)objectRefAddress;
15701 OBJECTREF src = *((OBJECTREF*)&newReference);
15702
15703 SetObjectReferenceUnchecked(dst, src);
15704 }
15705 else
15706 {
15707
15708 // If the object reference to set is inside of a handle, then
15709 // fixup the handle.
15710 OBJECTHANDLE h = vmObjectHandle.GetRawPtr();
15711 OBJECTREF src = *((OBJECTREF*)&newReference);
15712
15713 IGCHandleManager* mgr = GCHandleUtilities::GetGCHandleManager();
15714 mgr->StoreObjectInHandle(h, OBJECTREFToObject(src));
15715 }
15716
15717 return S_OK;
15718}
15719
15720//
15721// SetValueClass sets a value class for the Right Side, respecting the write barrier for references that are embedded
15722// within in the value class.
15723//
15724HRESULT Debugger::SetValueClass(void *oldData, void *newData, DebuggerIPCE_BasicTypeData * type)
15725{
15726 CONTRACTL
15727 {
15728 NOTHROW;
15729 GC_NOTRIGGER;
15730 }
15731 CONTRACTL_END;
15732
15733 HRESULT hr = S_OK;
15734
15735 TypeHandle th;
15736 hr = BasicTypeInfoToTypeHandle(type, &th);
15737
15738 if (FAILED(hr))
15739 return CORDBG_E_CLASS_NOT_LOADED;
15740
15741 // Update the value class.
15742 CopyValueClassUnchecked(oldData, newData, th.GetMethodTable());
15743
15744 // Free the buffer that is holding the new data. This is a buffer that was created in response to a GET_BUFFER
15745 // message, so we release it with ReleaseRemoteBuffer.
15746 ReleaseRemoteBuffer((BYTE*)newData, true);
15747
15748 return hr;
15749}
15750
15751/******************************************************************************
15752 *
15753 ******************************************************************************/
15754HRESULT Debugger::SetILInstrumentedCodeMap(MethodDesc *fd,
15755 BOOL fStartJit,
15756 ULONG32 cILMapEntries,
15757 COR_IL_MAP rgILMapEntries[])
15758{
15759 CONTRACTL
15760 {
15761 THROWS;
15762 GC_TRIGGERS_FROM_GETJITINFO;
15763 }
15764 CONTRACTL_END;
15765
15766 if (!HasLazyData())
15767 {
15768 DebuggerLockHolder dbgLockHolder(this);
15769 // This is an entry path into the debugger, so make sure we're inited.
15770 LazyInit();
15771 }
15772
15773 DebuggerMethodInfo * dmi = GetOrCreateMethodInfo(fd->GetModule(), fd->GetMemberDef());
15774 if (dmi == NULL)
15775 {
15776 return E_OUTOFMEMORY;
15777 }
15778
15779 dmi->SetInstrumentedILMap(rgILMapEntries, cILMapEntries);
15780
15781 return S_OK;
15782}
15783
15784//
15785// EarlyHelperThreadDeath handles the case where the helper
15786// thread has been ripped out from underneath of us by
15787// ExitProcess or TerminateProcess. These calls are bad, whacking
15788// all threads except the caller in the process. This can happen, for
15789// instance, when an app calls ExitProcess. All threads are wacked,
15790// the main thread calls all DLL main's, and the EE starts shutting
15791// down in its DLL main with the helper thread terminated.
15792//
15793void Debugger::EarlyHelperThreadDeath(void)
15794{
15795 WRAPPER_NO_CONTRACT;
15796
15797 if (m_pRCThread)
15798 m_pRCThread->EarlyHelperThreadDeath();
15799}
15800
15801//
15802// This tells the debugger that shutdown of the in-proc debugging services has begun. We need to know this during
15803// managed/unmanaged debugging so we can stop doing certian things to the process (like hijacking threads.)
15804//
15805void Debugger::ShutdownBegun(void)
15806{
15807 CONTRACTL
15808 {
15809 NOTHROW;
15810 GC_NOTRIGGER;
15811 SO_INTOLERANT;
15812 }
15813 CONTRACTL_END;
15814
15815
15816 // Shouldn't be Debugger-stopped if we're shutting down.
15817 // However, shutdown can occur in preemptive mode. Thus if the RS does an AsyncBreak late
15818 // enough, then the LS will appear to be stopped but may still shutdown.
15819 // Since the debuggee can exit asynchronously at any time (eg, suppose somebody forcefully
15820 // kills it with taskman), this doesn't introduce a new case.
15821 // That aside, it would be great to be able to assert this:
15822 //_ASSERTE(!IsStopped());
15823
15824 if (m_pRCThread != NULL)
15825 {
15826 DebuggerIPCControlBlock *dcb = m_pRCThread->GetDCB();
15827
15828 if ((dcb != NULL) && (dcb->m_rightSideIsWin32Debugger))
15829 dcb->m_shutdownBegun = true;
15830 }
15831}
15832
15833/*
15834 * LockDebuggerForShutdown
15835 *
15836 * This routine is used during shutdown to tell the in-process portion of the
15837 * debugger to synchronize with any threads that are currently using the
15838 * debugging facilities such that no more threads will run debugging services.
15839 *
15840 * This is accomplished by transitioning the debugger lock in to a state where
15841 * it will block all threads, except for the finalizer, shutdown, and helper thread.
15842 */
15843void Debugger::LockDebuggerForShutdown(void)
15844{
15845#ifndef DACCESS_COMPILE
15846
15847 CONTRACTL
15848 {
15849 NOTHROW;
15850 GC_NOTRIGGER;
15851 SO_INTOLERANT;
15852 MODE_ANY;
15853 }
15854 CONTRACTL_END;
15855
15856 DebuggerLockHolder dbgLockHolder(this);
15857
15858 // Shouldn't be Debugger-stopped if we're shutting down.
15859 // However, shutdown can occur in preemptive mode. Thus if the RS does an AsyncBreak late
15860 // enough, then the LS will appear to be stopped but may still shutdown.
15861 // Since the debuggee can exit asynchronously at any time (eg, suppose somebody forcefully
15862 // kills it with taskman), this doesn't introduce a new case.
15863 // That aside, it would be great to be able to assert this:
15864 //_ASSERTE(!IsStopped());
15865
15866 // After setting this flag, nonspecial threads will not be able to
15867 // take the debugger lock.
15868 m_fShutdownMode = true;
15869
15870 m_ignoreThreadDetach = TRUE;
15871#else
15872 DacNotImpl();
15873#endif
15874}
15875
15876
15877/*
15878 * DisableDebugger
15879 *
15880 * This routine is used by the EE to inform the debugger that it should block all
15881 * threads from executing as soon as it can. Any thread entering the debugger can
15882 * block infinitely, as well.
15883 *
15884 * This is accomplished by transitioning the debugger lock into a mode where it will
15885 * block all threads infinitely rather than taking the lock.
15886 *
15887 */
15888void Debugger::DisableDebugger(void)
15889{
15890#ifndef DACCESS_COMPILE
15891
15892 CONTRACTL
15893 {
15894 NOTHROW;
15895 GC_NOTRIGGER;
15896 SO_INTOLERANT;
15897 PRECONDITION(ThisMaybeHelperThread());
15898 }
15899 CONTRACTL_END;
15900
15901 m_fDisabled = true;
15902
15903 CORDBDebuggerSetUnrecoverableError(this, CORDBG_E_DEBUGGING_DISABLED, false);
15904
15905#else
15906 DacNotImpl();
15907#endif
15908}
15909
15910
15911/****************************************************************************
15912 * This will perform the duties of the helper thread if none already exists.
15913 * This is called in the case that the loader lock is held and so no new
15914 * threads can be spun up to be the helper thread, so the existing thread
15915 * must be the helper thread until a new one can spin up.
15916 * This is also called in the shutdown case (g_fProcessDetach==true) and our
15917 * helper may have already been blown away.
15918 ***************************************************************************/
15919void Debugger::DoHelperThreadDuty()
15920{
15921 CONTRACTL
15922 {
15923 SO_NOT_MAINLINE;
15924 THROWS;
15925 WRAPPER(GC_TRIGGERS);
15926 }
15927 CONTRACTL_END;
15928
15929 // This should not be a real helper thread.
15930 _ASSERTE(!IsDbgHelperSpecialThread());
15931 _ASSERTE(ThreadHoldsLock());
15932
15933 // We may be here in the shutdown case (only if the shutdown started after we got here).
15934 // We'll get killed randomly anyways, so not much we can do.
15935
15936 // These assumptions are based off us being called from TART.
15937 _ASSERTE(ThreadStore::HoldingThreadStore() || g_fProcessDetach); // got this from TART
15938 _ASSERTE(m_trappingRuntimeThreads); // We're only called from TART.
15939 _ASSERTE(!m_stopped); // we haven't sent the sync-complete yet.
15940
15941 // Can't have 2 threads doing helper duty.
15942 _ASSERTE(m_pRCThread->GetDCB()->m_temporaryHelperThreadId == 0);
15943
15944 LOG((LF_CORDB, LL_INFO1000,
15945 "D::SSCIPCE: helper thread is not ready, doing helper "
15946 "thread duty...\n"));
15947
15948 // We're the temporary helper thread now.
15949 DWORD dwMyTID = GetCurrentThreadId();
15950 m_pRCThread->GetDCB()->m_temporaryHelperThreadId = dwMyTID;
15951
15952 // Make sure the helper thread has something to wait on while
15953 // we're trying to be the helper thread.
15954 VERIFY(ResetEvent(m_pRCThread->GetHelperThreadCanGoEvent()));
15955
15956 // We have not sent the sync-complete flare yet.
15957
15958 // Now that we've synchronized, we'll eventually send the sync-complete. But we're currently within the
15959 // scope of sombody already sending an event. So unlock from that event so that we can send the sync-complete.
15960 // Don't release the debugger lock
15961 //
15962 UnlockFromEventSending(NULL);
15963
15964 // We are the temporary helper thread. We will not deal with everything! But just pump for
15965 // continue.
15966 //
15967 m_pRCThread->TemporaryHelperThreadMainLoop();
15968
15969 // We do not need to relock it since we never release it.
15970 LockForEventSending(NULL);
15971 _ASSERTE(ThreadHoldsLock());
15972
15973
15974 STRESS_LOG1(LF_CORDB, LL_INFO1000,
15975 "D::SSCIPCE: done doing helper thread duty. "
15976 "Current helper thread id=0x%x\n",
15977 m_pRCThread->GetDCB()->m_helperThreadId);
15978
15979 // We're not the temporary helper thread anymore.
15980 _ASSERTE(m_pRCThread->GetDCB()->m_temporaryHelperThreadId == dwMyTID);
15981 m_pRCThread->GetDCB()->m_temporaryHelperThreadId = 0;
15982
15983 // Let the helper thread go if its waiting on us.
15984 VERIFY(SetEvent(m_pRCThread->GetHelperThreadCanGoEvent()));
15985}
15986
15987
15988
15989// This function is called from the EE to notify the right side
15990// whenever the name of a thread or AppDomain changes
15991//
15992// Notes:
15993// This just sends a ping event to notify that the name has been changed.
15994// It does not send the actual updated name. Instead, the debugger can query for the name.
15995//
15996// For an AppDomain name change:
15997// - pAppDoamin != NULL
15998// - name retrieved via ICorDebugAppDomain::GetName
15999//
16000// For a Thread name change:
16001// - pAppDomain == NULL, pThread != NULL
16002// - name retrieved via a func-eval of Thread::get_Name
16003HRESULT Debugger::NameChangeEvent(AppDomain *pAppDomain, Thread *pThread)
16004{
16005 CONTRACTL
16006 {
16007 SO_NOT_MAINLINE;
16008 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
16009 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
16010 }
16011 CONTRACTL_END;
16012
16013 // Don't try to send one of these if the thread really isn't setup
16014 // yet. This can happen when initially setting up an app domain,
16015 // before the appdomain create event has been sent. Since the app
16016 // domain create event hasn't been sent yet in this case, its okay
16017 // to do this...
16018 if (g_pEEInterface->GetThread() == NULL)
16019 return S_OK;
16020
16021 // Skip if thread doesn't yet have native ID.
16022 // This can easily happen if an app sets Thread.Name before it calls Thread.Start.
16023 // Since this is just a ping-event, it's ignorable. The debugger can query the thread name at Thread.Start in this case.
16024 // This emulates whidbey semantics.
16025 if (pThread != NULL)
16026 {
16027 if (pThread->GetOSThreadId() == 0)
16028 {
16029 return S_OK;
16030 }
16031 }
16032
16033 LOG((LF_CORDB, LL_INFO1000, "D::NCE: Sending NameChangeEvent 0x%x 0x%x\n",
16034 pAppDomain, pThread));
16035
16036 Thread *curThread = g_pEEInterface->GetThread();
16037 SENDIPCEVENT_BEGIN(this, curThread);
16038
16039 if (CORDebuggerAttached())
16040 {
16041
16042 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
16043 InitIPCEvent(ipce,
16044 DB_IPCE_NAME_CHANGE,
16045 curThread,
16046 curThread->GetDomain());
16047
16048
16049 if (pAppDomain)
16050 {
16051 ipce->NameChange.eventType = APP_DOMAIN_NAME_CHANGE;
16052 ipce->NameChange.vmAppDomain.SetRawPtr(pAppDomain);
16053 }
16054 else
16055 {
16056 // Thread Name
16057 ipce->NameChange.eventType = THREAD_NAME_CHANGE;
16058 _ASSERTE (pThread);
16059 ipce->NameChange.vmThread.SetRawPtr(pThread);
16060 }
16061
16062 m_pRCThread->SendIPCEvent();
16063
16064 // Stop all Runtime threads
16065 TrapAllRuntimeThreads();
16066 }
16067 else
16068 {
16069 LOG((LF_CORDB,LL_INFO1000, "D::NCE: Skipping SendIPCEvent because RS detached."));
16070 }
16071
16072 SENDIPCEVENT_END;
16073
16074 return S_OK;
16075
16076}
16077
16078//---------------------------------------------------------------------------------------
16079//
16080// Send an event to the RS indicating that there's a Ctrl-C or Ctrl-Break.
16081//
16082// Arguments:
16083// dwCtrlType - represents the type of the event (Ctrl-C or Ctrl-Break)
16084//
16085// Return Value:
16086// Return TRUE if the event has been handled by the debugger.
16087//
16088
16089BOOL Debugger::SendCtrlCToDebugger(DWORD dwCtrlType)
16090{
16091 CONTRACTL
16092 {
16093 SO_NOT_MAINLINE;
16094 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
16095 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
16096 }
16097 CONTRACTL_END;
16098
16099 LOG((LF_CORDB, LL_INFO1000, "D::SCCTD: Sending CtrlC Event 0x%x\n", dwCtrlType));
16100
16101 // Prevent other Runtime threads from handling events.
16102 Thread *pThread = g_pEEInterface->GetThread();
16103 SENDIPCEVENT_BEGIN(this, pThread);
16104
16105 if (CORDebuggerAttached())
16106 {
16107 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
16108 InitIPCEvent(ipce,
16109 DB_IPCE_CONTROL_C_EVENT,
16110 pThread,
16111 NULL);
16112
16113 // The RS doesn't do anything with dwCtrlType
16114 m_pRCThread->SendIPCEvent();
16115
16116 // Stop all Runtime threads
16117 TrapAllRuntimeThreads();
16118 }
16119 else
16120 {
16121 LOG((LF_CORDB,LL_INFO1000, "D::SCCTD: Skipping SendIPCEvent because RS detached."));
16122 }
16123
16124 SENDIPCEVENT_END;
16125
16126 // now wait for notification from the right side about whether or not
16127 // the out-of-proc debugger is handling ControlC events.
16128 ::WaitForSingleObject(GetCtrlCMutex(), INFINITE);
16129
16130 return GetDebuggerHandlingCtrlC();
16131}
16132
16133// Allows the debugger to keep an up to date list of special threads
16134HRESULT Debugger::UpdateSpecialThreadList(DWORD cThreadArrayLength,
16135 DWORD *rgdwThreadIDArray)
16136{
16137 LIMITED_METHOD_CONTRACT;
16138
16139 _ASSERTE(g_pRCThread != NULL);
16140
16141 DebuggerIPCControlBlock *pIPC = g_pRCThread->GetDCB();
16142 _ASSERTE(pIPC);
16143
16144 if (!pIPC)
16145 return (E_FAIL);
16146
16147 // Save the thread list information, and mark the dirty bit so
16148 // the right side knows.
16149 pIPC->m_specialThreadList = rgdwThreadIDArray;
16150 pIPC->m_specialThreadListLength = cThreadArrayLength;
16151 pIPC->m_specialThreadListDirty = true;
16152
16153 return (S_OK);
16154}
16155
16156// Updates the pointer for the debugger services
16157void Debugger::SetIDbgThreadControl(IDebuggerThreadControl *pIDbgThreadControl)
16158{
16159 CONTRACTL
16160 {
16161 SO_NOT_MAINLINE;
16162 NOTHROW;
16163 GC_NOTRIGGER;
16164 }
16165 CONTRACTL_END;
16166 if (m_pIDbgThreadControl)
16167 m_pIDbgThreadControl->Release();
16168
16169 m_pIDbgThreadControl = pIDbgThreadControl;
16170
16171 if (m_pIDbgThreadControl)
16172 m_pIDbgThreadControl->AddRef();
16173}
16174
16175//
16176// If a thread is Win32 suspended right after hitting a breakpoint instruction, but before the OS has transitioned the
16177// thread over to the user-level exception dispatching logic, then we may see the IP pointing after the breakpoint
16178// instruction. There are times when the Runtime will use the IP to try to determine what code as run in the prolog or
16179// epilog, most notably when unwinding a frame. If the thread is suspended in such a case, then the unwind will believe
16180// that the instruction that the breakpoint replaced has really been executed, which is not true. This confuses the
16181// unwinding logic. This function is called from Thread::HandledJITCase() to help us recgonize when this may have
16182// happened and allow us to skip the unwind and abort the HandledJITCase.
16183//
16184// The criteria is this:
16185//
16186// 1) If a debugger is attached.
16187//
16188// 2) If the instruction before the IP is a breakpoint instruction.
16189//
16190// 3) If the IP is in the prolog or epilog of a managed function.
16191//
16192BOOL Debugger::IsThreadContextInvalid(Thread *pThread)
16193{
16194 CONTRACTL
16195 {
16196 SO_NOT_MAINLINE;
16197 NOTHROW;
16198 GC_NOTRIGGER;
16199 }
16200 CONTRACTL_END;
16201
16202 BOOL invalid = FALSE;
16203
16204 // Get the thread context.
16205 CONTEXT ctx;
16206 ctx.ContextFlags = CONTEXT_CONTROL;
16207 BOOL success = pThread->GetThreadContext(&ctx);
16208
16209 if (success)
16210 {
16211 // Check single-step flag
16212 if (IsSSFlagEnabled(reinterpret_cast<DT_CONTEXT *>(&ctx) ARM_ARG(pThread)))
16213 {
16214 // Can't hijack a thread whose SS-flag is set. This could lead to races
16215 // with the thread taking the SS-exception.
16216 // The debugger's controller filters will poll for GC to avoid starvation.
16217 STRESS_LOG0(LF_CORDB, LL_EVERYTHING, "HJC - Hardware trace flag applied\n");
16218 return TRUE;
16219 }
16220 }
16221
16222 if (success)
16223 {
16224#ifdef _TARGET_X86_
16225 // Grab Eip - 1
16226 LPVOID address = (((BYTE*)GetIP(&ctx)) - 1);
16227
16228 EX_TRY
16229 {
16230 // Use AVInRuntimeImplOkHolder.
16231 AVInRuntimeImplOkayHolder AVOkay;
16232
16233 // Is it a breakpoint?
16234 if (AddressIsBreakpoint((CORDB_ADDRESS_TYPE*)address))
16235 {
16236 size_t prologSize; // Unused...
16237 if (g_pEEInterface->IsInPrologOrEpilog((BYTE*)GetIP(&ctx), &prologSize))
16238 {
16239 LOG((LF_CORDB, LL_INFO1000, "D::ITCI: thread is after a BP and in prolog or epilog.\n"));
16240 invalid = TRUE;
16241 }
16242 }
16243 }
16244 EX_CATCH
16245 {
16246 // If we fault trying to read the byte before EIP, then we know that its not a breakpoint.
16247 // Do nothing. The default return value is FALSE.
16248 }
16249 EX_END_CATCH(SwallowAllExceptions);
16250#else // _TARGET_X86_
16251 // Non-x86 can detect whether the thread is suspended after an exception is hit but before
16252 // the kernel has dispatched the exception to user mode by trap frame reporting.
16253 // See Thread::IsContextSafeToRedirect().
16254#endif // _TARGET_X86_
16255 }
16256 else
16257 {
16258 // If we can't get the context, then its definetly invalid... ;)
16259 LOG((LF_CORDB, LL_INFO1000, "D::ITCI: couldn't get thread's context!\n"));
16260 invalid = TRUE;
16261 }
16262
16263 return invalid;
16264}
16265
16266
16267// notification when a SQL connection begins
16268void Debugger::CreateConnection(CONNID dwConnectionId, __in_z WCHAR *wzName)
16269{
16270 CONTRACTL
16271 {
16272 SO_NOT_MAINLINE;
16273 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
16274 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
16275 }
16276 CONTRACTL_END;
16277
16278 LOG((LF_CORDB,LL_INFO1000, "D::CreateConnection %d\n.", dwConnectionId));
16279
16280 if (CORDBUnrecoverableError(this))
16281 return;
16282
16283 Thread *pThread = g_pEEInterface->GetThread();
16284 SENDIPCEVENT_BEGIN(this, pThread);
16285
16286 if (CORDebuggerAttached())
16287 {
16288 DebuggerIPCEvent* ipce;
16289
16290 // Send a update module syns event to the Right Side.
16291 ipce = m_pRCThread->GetIPCEventSendBuffer();
16292 InitIPCEvent(ipce, DB_IPCE_CREATE_CONNECTION,
16293 pThread,
16294 NULL);
16295 ipce->CreateConnection.connectionId = dwConnectionId;
16296 _ASSERTE(wzName != NULL);
16297 ipce->CreateConnection.wzConnectionName.SetString(wzName);
16298
16299 m_pRCThread->SendIPCEvent();
16300 }
16301 else
16302 {
16303 LOG((LF_CORDB,LL_INFO1000, "D::CreateConnection: Skipping SendIPCEvent because RS detached."));
16304 }
16305
16306 // Stop all Runtime threads if we actually sent an event
16307 if (CORDebuggerAttached())
16308 {
16309 TrapAllRuntimeThreads();
16310 }
16311
16312 SENDIPCEVENT_END;
16313}
16314
16315// notification when a SQL connection ends
16316void Debugger::DestroyConnection(CONNID dwConnectionId)
16317{
16318 CONTRACTL
16319 {
16320 SO_NOT_MAINLINE;
16321 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
16322 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
16323 }
16324 CONTRACTL_END;
16325
16326 LOG((LF_CORDB,LL_INFO1000, "D::DestroyConnection %d\n.", dwConnectionId));
16327
16328 if (CORDBUnrecoverableError(this))
16329 return;
16330
16331 Thread *thread = g_pEEInterface->GetThread();
16332 // Note that the debugger lock is reentrant, so we may or may not hold it already.
16333 SENDIPCEVENT_BEGIN(this, thread);
16334
16335 // Send a update module syns event to the Right Side.
16336 DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
16337 InitIPCEvent(ipce, DB_IPCE_DESTROY_CONNECTION,
16338 thread,
16339 NULL);
16340 ipce->ConnectionChange.connectionId = dwConnectionId;
16341
16342 // IPC event is now initialized, so we can send it over.
16343 SendSimpleIPCEventAndBlock();
16344
16345 // This will block on the continue
16346 SENDIPCEVENT_END;
16347
16348}
16349
16350// notification for SQL connection changes
16351void Debugger::ChangeConnection(CONNID dwConnectionId)
16352{
16353 CONTRACTL
16354 {
16355 SO_NOT_MAINLINE;
16356 MAY_DO_HELPER_THREAD_DUTY_THROWS_CONTRACT;
16357 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
16358 }
16359 CONTRACTL_END;
16360
16361 LOG((LF_CORDB,LL_INFO1000, "D::ChangeConnection %d\n.", dwConnectionId));
16362
16363 if (CORDBUnrecoverableError(this))
16364 return;
16365
16366 Thread *pThread = g_pEEInterface->GetThread();
16367 SENDIPCEVENT_BEGIN(this, pThread);
16368
16369 if (CORDebuggerAttached())
16370 {
16371 DebuggerIPCEvent* ipce;
16372
16373 // Send a update module syns event to the Right Side.
16374 ipce = m_pRCThread->GetIPCEventSendBuffer();
16375 InitIPCEvent(ipce, DB_IPCE_CHANGE_CONNECTION,
16376 pThread,
16377 NULL);
16378 ipce->ConnectionChange.connectionId = dwConnectionId;
16379 m_pRCThread->SendIPCEvent();
16380 }
16381 else
16382 {
16383 LOG((LF_CORDB,LL_INFO1000, "D::ChangeConnection: Skipping SendIPCEvent because RS detached."));
16384 }
16385
16386 // Stop all Runtime threads if we actually sent an event
16387 if (CORDebuggerAttached())
16388 {
16389 TrapAllRuntimeThreads();
16390 }
16391
16392 SENDIPCEVENT_END;
16393}
16394
16395
16396//
16397// Are we the helper thread?
16398// Some important things about running on the helper thread:
16399// - there's only 1, so guaranteed to be thread-safe.
16400// - we'll never run managed code.
16401// - therefore, Never GC.
16402// - It listens for events from the RS.
16403// - It's the only thread to send a sync complete.
16404//
16405bool ThisIsHelperThreadWorker(void)
16406{
16407 CONTRACTL
16408 {
16409 NOTHROW;
16410 GC_NOTRIGGER;
16411 SO_TOLERANT;
16412 }
16413 CONTRACTL_END;
16414
16415 // This can
16416 Thread * pThread;
16417 pThread = GetThreadNULLOk();
16418
16419 // First check for a real helper thread. This will do a FLS access.
16420 bool fIsHelperThread = !!IsDbgHelperSpecialThread();
16421 if (fIsHelperThread)
16422 {
16423 // If we're on the real helper thread, we never run managed code
16424 // and so we'd better not have an EE thread object.
16425 _ASSERTE((pThread == NULL) || !"The helper thread should not being running managed code.\n"
16426 "Are you running managed code inside the dllmain? If so, your scenario is invalid and this"
16427 "assert is only the tip of the iceberg.\n");
16428 return true;
16429 }
16430
16431 // Even if we're not on the real helper thread, we may still be on a thread
16432 // pretending to be the helper. (Helper Duty, etc).
16433 DWORD id = GetCurrentThreadId();
16434
16435 // Check for temporary helper thread.
16436 if (ThisIsTempHelperThread(id))
16437 {
16438 return true;
16439 }
16440
16441 return false;
16442}
16443
16444//
16445// Make call to the static method.
16446// This is exposed to the contracts susbsystem so that the helper thread can call
16447// things on MODE_COOPERATIVE.
16448//
16449bool Debugger::ThisIsHelperThread(void)
16450{
16451 WRAPPER_NO_CONTRACT;
16452
16453 return ThisIsHelperThreadWorker();
16454}
16455
16456// Check if we're the temporary helper thread. Have 2 forms of this, 1 that assumes the current
16457// thread (but has the overhead of an extra call to GetCurrentThreadId() if we laready know the tid.
16458bool ThisIsTempHelperThread()
16459{
16460 WRAPPER_NO_CONTRACT;
16461
16462 DWORD id = GetCurrentThreadId();
16463 return ThisIsTempHelperThread(id);
16464}
16465
16466bool ThisIsTempHelperThread(DWORD tid)
16467{
16468 WRAPPER_NO_CONTRACT;
16469
16470 // If helper thread class isn't created, then there's no helper thread.
16471 // No one is doing helper thread duty either.
16472 // It's also possible we're in a shutdown case and have already deleted the
16473 // data for the helper thread.
16474 if (g_pRCThread != NULL)
16475 {
16476 // May be the temporary helper thread...
16477 DebuggerIPCControlBlock * pBlock = g_pRCThread->GetDCB();
16478 if (pBlock != NULL)
16479 {
16480 DWORD idTemp = pBlock->m_temporaryHelperThreadId;
16481
16482 if (tid == idTemp)
16483 {
16484 return true;
16485 }
16486 }
16487 }
16488 return false;
16489
16490}
16491
16492
16493// This function is called when host call ICLRSecurityAttributeManager::setDacl.
16494// It will redacl our SSE, RSEA, RSER events.
16495HRESULT Debugger::ReDaclEvents(PSECURITY_DESCRIPTOR securityDescriptor)
16496{
16497 WRAPPER_NO_CONTRACT;
16498
16499 return m_pRCThread->ReDaclEvents(securityDescriptor);
16500}
16501
16502/* static */
16503void Debugger::AcquireDebuggerDataLock(Debugger *pDebugger)
16504{
16505 WRAPPER_NO_CONTRACT;
16506
16507 if (!g_fProcessDetach)
16508 {
16509 pDebugger->GetDebuggerDataLock()->Enter();
16510 }
16511}
16512
16513/* static */
16514void Debugger::ReleaseDebuggerDataLock(Debugger *pDebugger)
16515{
16516 WRAPPER_NO_CONTRACT;
16517
16518 if (!g_fProcessDetach)
16519 {
16520 pDebugger->GetDebuggerDataLock()->Leave();
16521 }
16522}
16523
16524
16525#else // DACCESS_COMPILE
16526
16527// determine whether the LS holds the data lock. If it does, we will assume the locked data is in an
16528// inconsistent state and will throw an exception. The DAC will execute this if we are executing code
16529// that takes the lock.
16530// Arguments: input: pDebugger - the LS debugger data structure
16531/* static */
16532void Debugger::AcquireDebuggerDataLock(Debugger *pDebugger)
16533{
16534 SUPPORTS_DAC;
16535
16536 if (pDebugger->GetDebuggerDataLock()->GetEnterCount() != 0)
16537 {
16538 ThrowHR(CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
16539 }
16540}
16541
16542void Debugger::ReleaseDebuggerDataLock(Debugger *pDebugger)
16543{
16544}
16545#endif // DACCESS_COMPILE
16546
16547/* ------------------------------------------------------------------------ *
16548 * Functions for DebuggerHeap executable memory allocations
16549 * ------------------------------------------------------------------------ */
16550
16551DebuggerHeapExecutableMemoryAllocator::~DebuggerHeapExecutableMemoryAllocator()
16552{
16553 while (m_pages != NULL)
16554 {
16555 DebuggerHeapExecutableMemoryPage *temp = m_pages->GetNextPage();
16556
16557 // Free this page
16558 INDEBUG(BOOL ret =) VirtualFree(m_pages, 0, MEM_RELEASE);
16559 ASSERT(ret == TRUE);
16560
16561 m_pages = temp;
16562 }
16563
16564 ASSERT(m_pages == NULL);
16565}
16566
16567void* DebuggerHeapExecutableMemoryAllocator::Allocate(DWORD numberOfBytes)
16568{
16569 if (numberOfBytes > DBG_MAX_EXECUTABLE_ALLOC_SIZE)
16570 {
16571 ASSERT(!"Allocating more than DBG_MAX_EXECUTABLE_ALLOC_SIZE at once is unsupported and breaks our assumptions.");
16572 return NULL;
16573 }
16574
16575 if (numberOfBytes == 0)
16576 {
16577 // Should we allocate anything in this case?
16578 ASSERT(!"Allocate called with 0 for numberOfBytes!");
16579 return NULL;
16580 }
16581
16582 CrstHolder execMemAllocCrstHolder(&m_execMemAllocMutex);
16583
16584 int chunkToUse = -1;
16585 DebuggerHeapExecutableMemoryPage *pageToAllocateOn = NULL;
16586 for (DebuggerHeapExecutableMemoryPage *currPage = m_pages; currPage != NULL; currPage = currPage->GetNextPage())
16587 {
16588 if (CheckPageForAvailability(currPage, &chunkToUse))
16589 {
16590 pageToAllocateOn = currPage;
16591 break;
16592 }
16593 }
16594
16595 if (pageToAllocateOn == NULL)
16596 {
16597 // No existing page had availability, so create a new page and use that.
16598 pageToAllocateOn = AddNewPage();
16599 if (pageToAllocateOn == NULL)
16600 {
16601 ASSERT(!"Call to AddNewPage failed!");
16602 return NULL;
16603 }
16604
16605 if (!CheckPageForAvailability(pageToAllocateOn, &chunkToUse))
16606 {
16607 ASSERT(!"No availability on new page?");
16608 return NULL;
16609 }
16610 }
16611
16612 return ChangePageUsage(pageToAllocateOn, chunkToUse, ChangePageUsageAction::ALLOCATE);
16613}
16614
16615int DebuggerHeapExecutableMemoryAllocator::Free(void* addr)
16616{
16617 ASSERT(addr != NULL);
16618
16619 CrstHolder execMemAllocCrstHolder(&m_execMemAllocMutex);
16620
16621 DebuggerHeapExecutableMemoryPage *pageToFreeIn = static_cast<DebuggerHeapExecutableMemoryChunk*>(addr)->data.startOfPage;
16622
16623 if (pageToFreeIn == NULL)
16624 {
16625 ASSERT(!"Couldn't locate page in which to free!");
16626 return -1;
16627 }
16628
16629 int chunkNum = static_cast<DebuggerHeapExecutableMemoryChunk*>(addr)->data.chunkNumber;
16630
16631 // Sanity check: assert that the address really represents the start of a chunk.
16632 ASSERT(((uint64_t)addr - (uint64_t)pageToFreeIn) % 64 == 0);
16633
16634 ChangePageUsage(pageToFreeIn, chunkNum, ChangePageUsageAction::FREE);
16635
16636 return 0;
16637}
16638
16639DebuggerHeapExecutableMemoryPage* DebuggerHeapExecutableMemoryAllocator::AddNewPage()
16640{
16641 void* newPageAddr = VirtualAlloc(NULL, sizeof(DebuggerHeapExecutableMemoryPage), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
16642
16643 DebuggerHeapExecutableMemoryPage *newPage = new (newPageAddr) DebuggerHeapExecutableMemoryPage;
16644 newPage->SetNextPage(m_pages);
16645
16646 // Add the new page to the linked list of pages
16647 m_pages = newPage;
16648 return newPage;
16649}
16650
16651bool DebuggerHeapExecutableMemoryAllocator::CheckPageForAvailability(DebuggerHeapExecutableMemoryPage* page, /* _Out_ */ int* chunkToUse)
16652{
16653 uint64_t occupancy = page->GetPageOccupancy();
16654 bool available = occupancy != UINT64_MAX;
16655
16656 if (!available)
16657 {
16658 if (chunkToUse)
16659 {
16660 *chunkToUse = -1;
16661 }
16662
16663 return false;
16664 }
16665
16666 if (chunkToUse)
16667 {
16668 // Start i at 62 because first chunk is reserved
16669 for (int i = 62; i >= 0; i--)
16670 {
16671 uint64_t mask = ((uint64_t)1 << i);
16672 if ((mask & occupancy) == 0)
16673 {
16674 *chunkToUse = 64 - i - 1;
16675 break;
16676 }
16677 }
16678 }
16679
16680 return true;
16681}
16682
16683void* DebuggerHeapExecutableMemoryAllocator::ChangePageUsage(DebuggerHeapExecutableMemoryPage* page, int chunkNumber, ChangePageUsageAction action)
16684{
16685 ASSERT(action == ChangePageUsageAction::ALLOCATE || action == ChangePageUsageAction::FREE);
16686
16687 uint64_t mask = (uint64_t)0x1 << (64 - chunkNumber - 1);
16688
16689 uint64_t prevOccupancy = page->GetPageOccupancy();
16690 uint64_t newOccupancy = (action == ChangePageUsageAction::ALLOCATE) ? (prevOccupancy | mask) : (prevOccupancy ^ mask);
16691 page->SetPageOccupancy(newOccupancy);
16692
16693 return page->GetPointerToChunk(chunkNumber);
16694}
16695
16696/* ------------------------------------------------------------------------ *
16697 * DebuggerHeap impl
16698 * ------------------------------------------------------------------------ */
16699
16700DebuggerHeap::DebuggerHeap()
16701{
16702#ifdef USE_INTEROPSAFE_HEAP
16703 m_hHeap = NULL;
16704#endif
16705 m_fExecutable = FALSE;
16706}
16707
16708DebuggerHeap::~DebuggerHeap()
16709{
16710 CONTRACTL
16711 {
16712 SO_INTOLERANT;
16713 NOTHROW;
16714 GC_NOTRIGGER;
16715 }
16716 CONTRACTL_END;
16717
16718 Destroy();
16719}
16720
16721void DebuggerHeap::Destroy()
16722{
16723#ifdef USE_INTEROPSAFE_HEAP
16724 if (IsInit())
16725 {
16726 ::HeapDestroy(m_hHeap);
16727 m_hHeap = NULL;
16728 }
16729#endif
16730#ifdef FEATURE_PAL
16731 if (m_execMemAllocator != NULL)
16732 {
16733 delete m_execMemAllocator;
16734 }
16735#endif
16736}
16737
16738bool DebuggerHeap::IsInit()
16739{
16740 LIMITED_METHOD_CONTRACT;
16741#ifdef USE_INTEROPSAFE_HEAP
16742 return m_hHeap != NULL;
16743#else
16744 return true;
16745#endif
16746}
16747
16748HRESULT DebuggerHeap::Init(BOOL fExecutable)
16749{
16750 CONTRACTL
16751 {
16752 SO_INTOLERANT;
16753 NOTHROW;
16754 GC_NOTRIGGER;
16755 }
16756 CONTRACTL_END;
16757
16758 // Have knob catch if we don't want to lazy init the debugger.
16759 _ASSERTE(!g_DbgShouldntUseDebugger);
16760 m_fExecutable = fExecutable;
16761
16762#ifdef USE_INTEROPSAFE_HEAP
16763 // If already inited, then we're done.
16764 // We normally don't double-init. However, we may oom between when we allocate the heap and when we do other initialization.
16765 // We don't worry about backout code to free the heap. Rather, we'll just leave it alive and nop if we try to allocate it again.
16766 if (IsInit())
16767 {
16768 return S_OK;
16769 }
16770
16771#ifndef HEAP_CREATE_ENABLE_EXECUTE
16772#define HEAP_CREATE_ENABLE_EXECUTE 0x00040000 // winnt create heap with executable pages
16773#endif
16774
16775 // Create a standard, grow-able, thread-safe heap.
16776 DWORD dwFlags = ((fExecutable == TRUE)? HEAP_CREATE_ENABLE_EXECUTE : 0);
16777 m_hHeap = ::HeapCreate(dwFlags, 0, 0);
16778 if (m_hHeap == NULL)
16779 {
16780 return HRESULT_FROM_GetLastError();
16781 }
16782#endif
16783
16784#ifdef FEATURE_PAL
16785 m_execMemAllocator = new (nothrow) DebuggerHeapExecutableMemoryAllocator();
16786 ASSERT(m_execMemAllocator != NULL);
16787 if (m_execMemAllocator == NULL)
16788 {
16789 return E_OUTOFMEMORY;
16790 }
16791#endif
16792
16793 return S_OK;
16794}
16795
16796// Only use canaries on x86 b/c they throw of alignment on Ia64.
16797#if defined(_DEBUG) && defined(_TARGET_X86_)
16798#define USE_INTEROPSAFE_CANARY
16799#endif
16800
16801#ifdef USE_INTEROPSAFE_CANARY
16802// Small header to to prefix interop-heap blocks.
16803// This lets us enforce that we don't delete interopheap data from a non-interop heap.
16804struct InteropHeapCanary
16805{
16806 ULONGLONG m_canary;
16807
16808 // Raw address - this is what the heap alloc + free routines use.
16809 // User address - this is what the user sees after we adjust the raw address for the canary
16810
16811 // Given a raw address to an allocated block, get the canary + mark it.
16812 static InteropHeapCanary * GetFromRawAddr(void * pStart)
16813 {
16814 _ASSERTE(pStart != NULL);
16815 InteropHeapCanary * p = (InteropHeapCanary*) pStart;
16816 p->Mark();
16817 return p;
16818 }
16819
16820 // Get the raw address from this canary.
16821 void * GetRawAddr()
16822 {
16823 return (void*) this;
16824 }
16825
16826 // Get a canary from a start address.
16827 static InteropHeapCanary * GetFromUserAddr(void * pStart)
16828 {
16829 _ASSERTE(pStart != NULL);
16830 InteropHeapCanary * p = ((InteropHeapCanary*) pStart)-1;
16831 p->Check();
16832 return p;
16833 }
16834 void * GetUserAddr()
16835 {
16836 this->Check();
16837 return (void*) (this + 1);
16838 }
16839
16840protected:
16841 void Check()
16842 {
16843 CONSISTENCY_CHECK_MSGF((m_canary == kInteropHeapCookie),
16844 ("Using InteropSafe delete on non-interopsafe allocated memory.\n"));
16845 }
16846 void Mark()
16847 {
16848 m_canary = kInteropHeapCookie;
16849 }
16850 static const ULONGLONG kInteropHeapCookie = 0x12345678;
16851};
16852#endif // USE_INTEROPSAFE_CANARY
16853
16854void *DebuggerHeap::Alloc(DWORD size)
16855{
16856 CONTRACTL
16857 {
16858 SO_INTOLERANT;
16859 NOTHROW;
16860 GC_NOTRIGGER;
16861 }
16862 CONTRACTL_END;
16863
16864#ifdef USE_INTEROPSAFE_CANARY
16865 // Make sure we allocate enough space for the canary at the start.
16866 size += sizeof(InteropHeapCanary);
16867#endif
16868
16869 void *ret;
16870#ifdef USE_INTEROPSAFE_HEAP
16871 _ASSERTE(m_hHeap != NULL);
16872 ret = ::HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, size);
16873#else // USE_INTEROPSAFE_HEAP
16874
16875 bool allocateOnHeap = true;
16876 HANDLE hExecutableHeap = NULL;
16877
16878#ifdef FEATURE_PAL
16879 if (m_fExecutable)
16880 {
16881 allocateOnHeap = false;
16882 ret = m_execMemAllocator->Allocate(size);
16883 }
16884 else
16885 {
16886 hExecutableHeap = ClrGetProcessHeap();
16887 }
16888#else // FEATURE_PAL
16889 hExecutableHeap = ClrGetProcessExecutableHeap();
16890#endif
16891
16892 if (allocateOnHeap)
16893 {
16894 if (hExecutableHeap == NULL)
16895 {
16896 return NULL;
16897 }
16898
16899 ret = ClrHeapAlloc(hExecutableHeap, NULL, S_SIZE_T(size));
16900 }
16901
16902#endif // USE_INTEROPSAFE_HEAP
16903
16904#ifdef USE_INTEROPSAFE_CANARY
16905 if (ret == NULL)
16906 {
16907 return NULL;
16908 }
16909 InteropHeapCanary * pCanary = InteropHeapCanary::GetFromRawAddr(ret);
16910 ret = pCanary->GetUserAddr();
16911#endif
16912
16913 return ret;
16914}
16915
16916// Realloc memory.
16917// If this fails, the original memory is still valid.
16918void *DebuggerHeap::Realloc(void *pMem, DWORD newSize, DWORD oldSize)
16919{
16920 CONTRACTL
16921 {
16922 SO_NOT_MAINLINE;
16923 NOTHROW;
16924 GC_NOTRIGGER;
16925 }
16926 CONTRACTL_END;
16927
16928 _ASSERTE(pMem != NULL);
16929 _ASSERTE(newSize != 0);
16930 _ASSERTE(oldSize != 0);
16931
16932#if defined(USE_INTEROPSAFE_HEAP) && !defined(USE_INTEROPSAFE_CANARY) && !defined(FEATURE_PAL)
16933 // No canaries in this case.
16934 // Call into realloc.
16935 void *ret;
16936
16937 _ASSERTE(m_hHeap != NULL);
16938 ret = ::HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, pMem, newSize);
16939#else
16940 // impl Realloc on top of alloc & free.
16941 void *ret;
16942
16943 ret = this->Alloc(newSize);
16944 if (ret == NULL)
16945 {
16946 // Not supposed to free original memory in failure condition.
16947 return NULL;
16948 }
16949
16950 memcpy(ret, pMem, oldSize);
16951 this->Free(pMem);
16952#endif
16953
16954 return ret;
16955}
16956
16957void DebuggerHeap::Free(void *pMem)
16958{
16959 CONTRACTL
16960 {
16961 SO_INTOLERANT;
16962 NOTHROW;
16963 GC_NOTRIGGER;
16964 }
16965 CONTRACTL_END;
16966
16967#ifdef USE_INTEROPSAFE_CANARY
16968 // Check for canary
16969
16970 if (pMem != NULL)
16971 {
16972 InteropHeapCanary * pCanary = InteropHeapCanary::GetFromUserAddr(pMem);
16973 pMem = pCanary->GetRawAddr();
16974 }
16975#endif
16976
16977#ifdef USE_INTEROPSAFE_HEAP
16978 if (pMem != NULL)
16979 {
16980 _ASSERTE(m_hHeap != NULL);
16981 ::HeapFree(m_hHeap, 0, pMem);
16982 }
16983#else
16984 if (pMem != NULL)
16985 {
16986#ifndef FEATURE_PAL
16987 HANDLE hProcessExecutableHeap = ClrGetProcessExecutableHeap();
16988 _ASSERTE(hProcessExecutableHeap != NULL);
16989 ClrHeapFree(hProcessExecutableHeap, NULL, pMem);
16990#else // !FEATURE_PAL
16991 if(!m_fExecutable)
16992 {
16993 HANDLE hProcessHeap = ClrGetProcessHeap();
16994 _ASSERTE(hProcessHeap != NULL);
16995 ClrHeapFree(hProcessHeap, NULL, pMem);
16996 }
16997 else
16998 {
16999 INDEBUG(int ret =) m_execMemAllocator->Free(pMem);
17000 _ASSERTE(ret == 0);
17001 }
17002#endif // !FEATURE_PAL
17003 }
17004#endif
17005}
17006
17007#ifndef DACCESS_COMPILE
17008
17009
17010// Undef this so we can call them from the EE versions.
17011#undef UtilMessageBoxVA
17012
17013// Message box API for the left side of the debugger. This API handles calls from the
17014// debugger helper thread as well as from normal EE threads. It is the only one that
17015// should be used from inside the debugger left side.
17016int Debugger::MessageBox(
17017 UINT uText, // Resource Identifier for Text message
17018 UINT uCaption, // Resource Identifier for Caption
17019 UINT uType, // Style of MessageBox
17020 BOOL displayForNonInteractive, // Display even if the process is running non interactive
17021 BOOL showFileNameInTitle, // Flag to show FileName in Caption
17022 ...) // Additional Arguments
17023{
17024 CONTRACTL
17025 {
17026 MAY_DO_HELPER_THREAD_DUTY_GC_TRIGGERS_CONTRACT;
17027 MODE_PREEMPTIVE;
17028 NOTHROW;
17029
17030 PRECONDITION(ThisMaybeHelperThread());
17031 }
17032 CONTRACTL_END;
17033
17034 va_list marker;
17035 va_start(marker, showFileNameInTitle);
17036
17037 // Add the MB_TASKMODAL style to indicate that the dialog should be displayed on top of the windows
17038 // owned by the current thread and should prevent interaction with them until dismissed.
17039 uType |= MB_TASKMODAL;
17040
17041 int result = UtilMessageBoxVA(NULL, uText, uCaption, uType, displayForNonInteractive, showFileNameInTitle, marker);
17042 va_end( marker );
17043
17044 return result;
17045}
17046
17047// Redefine this to an error just in case code is added after this point in the file.
17048#define UtilMessageBoxVA __error("Use g_pDebugger->MessageBox from inside the left side of the debugger")
17049
17050#else // DACCESS_COMPILE
17051void
17052Debugger::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
17053{
17054 DAC_ENUM_VTHIS();
17055 SUPPORTS_DAC;
17056 _ASSERTE(m_rgHijackFunction != NULL);
17057
17058 if ( flags != CLRDATA_ENUM_MEM_TRIAGE)
17059 {
17060 if (m_pMethodInfos.IsValid())
17061 {
17062 m_pMethodInfos->EnumMemoryRegions(flags);
17063 }
17064
17065 DacEnumMemoryRegion(dac_cast<TADDR>(m_pLazyData),
17066 sizeof(DebuggerLazyInit));
17067 }
17068
17069 // Needed for stack walking from an initial native context. If the debugger can find the
17070 // on-disk image of clr.dll, then this is not necessary.
17071 DacEnumMemoryRegion(dac_cast<TADDR>(m_rgHijackFunction), sizeof(MemoryRange)*kMaxHijackFunctions);
17072}
17073
17074
17075// This code doesn't hang out in Frame/TransitionFrame/FuncEvalFrame::EnumMemoryRegions() like it would
17076// for other normal VM objects because we don't want to have code in VM directly referencing LS types.
17077// Frames.h's FuncEvalFrame simply does a forward decl of DebuggerEval and gets away with it because it
17078// never does anything but a cast of a TADDR.
17079void
17080Debugger::EnumMemoryRegionsIfFuncEvalFrame(CLRDataEnumMemoryFlags flags, Frame * pFrame)
17081{
17082 SUPPORTS_DAC;
17083
17084 if ((pFrame != NULL) && (pFrame->GetFrameType() == Frame::TYPE_FUNC_EVAL))
17085 {
17086 FuncEvalFrame * pFEF = dac_cast<PTR_FuncEvalFrame>(pFrame);
17087 DebuggerEval * pDE = pFEF->GetDebuggerEval();
17088
17089 if (pDE != NULL)
17090 {
17091 DacEnumMemoryRegion(dac_cast<TADDR>(pDE), sizeof(DebuggerEval), true);
17092
17093 if (pDE->m_debuggerModule != NULL)
17094 DacEnumMemoryRegion(dac_cast<TADDR>(pDE->m_debuggerModule), sizeof(DebuggerModule), true);
17095 }
17096 }
17097}
17098
17099#endif // #ifdef DACCESS_COMPILE
17100
17101#ifndef DACCESS_COMPILE
17102void Debugger::StartCanaryThread()
17103{
17104 // we need to already have the rcthread running and the pointer stored
17105 _ASSERTE(m_pRCThread != NULL && g_pRCThread == m_pRCThread);
17106 _ASSERTE(m_pRCThread->GetDCB() != NULL);
17107 _ASSERTE(GetCanary() != NULL);
17108
17109 GetCanary()->Init();
17110}
17111#endif // DACCESS_COMPILE
17112
17113#endif //DEBUGGING_SUPPORTED
17114