Merge pull request #10823 from adityamandaleeka/move_variable_handle_creation
[platform/upstream/coreclr.git] / src / debug / di / localeventchannel.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
5 // File: LocalEventChannel.cpp
6 // 
7
8 //
9 // Implements the old-style event channel between two processes on a local Windows machine.  
10 //*****************************************************************************
11
12 #include "stdafx.h"
13 #include "eventchannel.h"
14
15
16 //---------------------------------------------------------------------------------------
17 //
18 // This is the implementation of the event channel for the normal case, where both the debugger and the
19 // debuggee are on the same Windows machine.  See code:IEventChannel for more information.
20 // 
21
22 class LocalEventChannel : public IEventChannel
23 {
24 public:
25     LocalEventChannel(CORDB_ADDRESS pLeftSideDCB, 
26                       DebuggerIPCControlBlock * pDCBBuffer, 
27                       ICorDebugMutableDataTarget * pMutableDataTarget);
28
29     // Inititalize the event channel.
30     virtual HRESULT Init(HANDLE hTargetProc);
31
32     // Called when the debugger is detaching.
33     virtual void Detach();
34
35     // Delete the event channel and clean up all the resources it owns.  This function can only be called once.
36     virtual void Delete();
37
38
39
40     // Update a single field with a value stored in the RS copy of the DCB.
41     virtual HRESULT UpdateLeftSideDCBField(void *rsFieldAddr, SIZE_T size);
42
43     // Update the entire RS copy of the debugger control block by reading the LS copy.
44     virtual HRESULT UpdateRightSideDCB();
45
46     // Get the pointer to the RS DCB.
47     virtual DebuggerIPCControlBlock * GetDCB();
48
49
50
51     // Check whether we need to wait for an acknowledgement from the LS after sending an IPC event.
52     virtual BOOL NeedToWaitForAck(DebuggerIPCEvent * pEvent);
53
54     // Get a handle to wait on after sending an IPC event to the LS.  The caller should call NeedToWaitForAck()
55     virtual HANDLE GetRightSideEventAckHandle();
56
57     // Clean up the state if the wait for an acknowledgement is unsuccessful.
58     virtual void   ClearEventForLeftSide();
59
60
61
62     // Send an IPC event to the LS.
63     virtual HRESULT SendEventToLeftSide(DebuggerIPCEvent * pEvent, SIZE_T eventSize);
64
65     // Get the reply from the LS for a previously sent IPC event.
66     virtual HRESULT GetReplyFromLeftSide(DebuggerIPCEvent * pReplyEvent, SIZE_T eventSize);
67
68
69
70     // Save an IPC event from the LS.  
71     // Used for transferring an IPC event from the native pipeline to the IPC event channel.
72     virtual HRESULT SaveEventFromLeftSide(DebuggerIPCEvent * pEventFromLeftSide);
73
74     // Get a saved IPC event from the LS.  
75     // Used for transferring an IPC event from the native pipeline to the IPC event channel.
76     virtual HRESULT GetEventFromLeftSide(DebuggerIPCEvent * pLocalManagedEvent);
77
78 private:
79     // Get a target buffer representing the area of the DebuggerIPCControlBlock on the helper thread that 
80     // holds information received from the LS as the result of an IPC event. 
81     TargetBuffer RemoteReceiveBuffer(SIZE_T size);
82
83     // Get a target buffer representing the area of the DebuggerIPCControlBlock on the helper thread that 
84     // holds information sent to the LS with an IPC event. 
85     TargetBuffer RemoteSendBuffer(SIZE_T size);
86
87     // write memory to the LS using the data target
88     HRESULT SafeWriteBuffer(TargetBuffer tb, const BYTE * pLocalBuffer);
89
90     // read memory from the LS using the data target
91     HRESULT SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer);
92
93     // duplicate a remote handle into the local process
94     HRESULT DuplicateHandleToLocalProcess(HANDLE * pLocalHandle, RemoteHANDLE * pRemoteHandle);
95
96     // target address of the DCB on the LS
97     CORDB_ADDRESS m_pLeftSideDCB;
98
99     // used to signal the to the LS that an event is available
100     HANDLE        m_rightSideEventAvailable;
101
102     // used by the LS to signal that the event is read
103     HANDLE        m_rightSideEventRead;
104
105     // handle of the debuggee process
106     HANDLE        m_hTargetProc;
107
108     // local buffer for the DCB on the RS
109     DebuggerIPCControlBlock * m_pDCBBuffer;
110
111     // data target used for cross-process memory reads and writes
112     RSExtSmartPtr<ICorDebugMutableDataTarget> m_pMutableDataTarget;
113 };
114
115 // Allocate and return an old-style event channel object for this target platform.
116 HRESULT NewEventChannelForThisPlatform(CORDB_ADDRESS pLeftSideDCB, 
117                                        ICorDebugMutableDataTarget * pMutableDataTarget, 
118                                        DWORD dwProcessId,
119                                        MachineInfo machineInfo,
120                                        IEventChannel ** ppEventChannel)
121 {
122     _ASSERTE(ppEventChannel != NULL);
123
124     LocalEventChannel *       pEventChannel = NULL;
125     DebuggerIPCControlBlock * pDCBBuffer    = NULL;
126
127     pDCBBuffer = new (nothrow) DebuggerIPCControlBlock;
128     if (pDCBBuffer == NULL)
129     {
130         return E_OUTOFMEMORY;
131     }
132
133     pEventChannel = new (nothrow) LocalEventChannel(pLeftSideDCB, pDCBBuffer, pMutableDataTarget);
134     if (pEventChannel == NULL)
135     {
136         delete pDCBBuffer;
137         return E_OUTOFMEMORY;
138     }
139
140     *ppEventChannel = pEventChannel;
141     return S_OK;
142 }
143
144 //-----------------------------------------------------------------------------
145 //
146 // This is the constructor.
147 //
148 // Arguments:
149 //    pLeftSideDCB       - target address of the DCB on the LS
150 //    pDCBBuffer         - local buffer for storing the DCB on the RS; the memory is owned by this class
151 //    pMutableDataTarget - data target for reading from and writing to the target process's address space
152 //
153
154 LocalEventChannel::LocalEventChannel(CORDB_ADDRESS pLeftSideDCB, 
155                                      DebuggerIPCControlBlock * pDCBBuffer,
156                                      ICorDebugMutableDataTarget * pMutableDataTarget)
157 {
158     m_pLeftSideDCB = pLeftSideDCB;
159     m_pDCBBuffer   = pDCBBuffer;
160
161     m_rightSideEventAvailable = NULL;
162     m_rightSideEventRead      = NULL;
163
164     m_pMutableDataTarget.Assign(pMutableDataTarget);
165 }
166
167 // Inititalize the event channel.
168 //
169 // virtual
170 HRESULT LocalEventChannel::Init(HANDLE hTargetProc)
171 {
172     HRESULT hr = E_FAIL;
173
174     m_hTargetProc = hTargetProc;
175
176     // Duplicate the handle of the RS process (i.e. the debugger) to the LS process's address space.
177     BOOL fSuccess = 
178         m_pDCBBuffer->m_rightSideProcessHandle.DuplicateToRemoteProcess(m_hTargetProc, GetCurrentProcess());
179     if (!fSuccess)
180     {
181         return HRESULT_FROM_GetLastError();
182     }
183
184     IfFailRet(UpdateLeftSideDCBField(&(m_pDCBBuffer->m_rightSideProcessHandle), 
185                                      sizeof(m_pDCBBuffer->m_rightSideProcessHandle)));
186
187     // Dup RSEA and RSER into this process if we don't already have them.
188     // On Launch, we don't have them yet, but on attach we do.
189     IfFailRet(DuplicateHandleToLocalProcess(&m_rightSideEventAvailable, 
190                                             &m_pDCBBuffer->m_rightSideEventAvailable));
191     IfFailRet(DuplicateHandleToLocalProcess(&m_rightSideEventRead, 
192                                             &m_pDCBBuffer->m_rightSideEventRead));
193
194     return S_OK;
195 }
196
197 // Called when the debugger is detaching.
198 //
199 // virtual
200 void LocalEventChannel::Detach()
201 {
202     // This averts a race condition wherein we'll detach, then reattach,
203     // and find these events in the still-signalled state.
204     if (m_rightSideEventAvailable != NULL)
205     {
206         ResetEvent(m_rightSideEventAvailable);
207     }
208     if (m_rightSideEventRead != NULL)
209     {
210         ResetEvent(m_rightSideEventRead);
211     }
212 }
213
214 // Delete the event channel and clean up all the resources it owns.  This function can only be called once.
215 // 
216 // virtual
217 void LocalEventChannel::Delete()
218 {
219     if (m_hTargetProc != NULL)
220     {
221         m_pDCBBuffer->m_rightSideProcessHandle.CloseInRemoteProcess(m_hTargetProc);
222         UpdateLeftSideDCBField(&(m_pDCBBuffer->m_rightSideProcessHandle), sizeof(m_pDCBBuffer->m_rightSideProcessHandle));
223         m_hTargetProc = NULL;
224     }
225
226     if (m_rightSideEventAvailable != NULL)
227     {
228         CloseHandle(m_rightSideEventAvailable);
229         m_rightSideEventAvailable = NULL;
230     }
231
232     if (m_rightSideEventRead!= NULL)
233     {
234         CloseHandle(m_rightSideEventRead);
235         m_rightSideEventRead = NULL;
236     }
237
238     if (m_pDCBBuffer != NULL)
239     {
240         delete m_pDCBBuffer;
241         m_pDCBBuffer = NULL;
242     }
243
244     if (m_pMutableDataTarget != NULL)
245     {
246         m_pMutableDataTarget.Clear();
247     }
248
249     delete this;
250 }
251
252 // Update a single field with a value stored in the RS copy of the DCB.
253 //
254 // virtual 
255 HRESULT LocalEventChannel::UpdateLeftSideDCBField(void * rsFieldAddr, SIZE_T size)
256 {
257     _ASSERTE(m_pDCBBuffer != NULL);
258     _ASSERTE(m_pLeftSideDCB  != NULL);
259
260     BYTE * pbRSFieldAddr = reinterpret_cast<BYTE *>(rsFieldAddr);
261     CORDB_ADDRESS lsFieldAddr = m_pLeftSideDCB + (pbRSFieldAddr - reinterpret_cast<BYTE *>(m_pDCBBuffer));
262     return SafeWriteBuffer(TargetBuffer(lsFieldAddr, (ULONG)size), const_cast<const BYTE *>(pbRSFieldAddr));
263 }
264
265 // Update the entire RS copy of the debugger control block by reading the LS copy.
266 //
267 // virtual 
268 HRESULT LocalEventChannel::UpdateRightSideDCB()
269 {
270     _ASSERTE(m_pDCBBuffer != NULL);
271     _ASSERTE(m_pLeftSideDCB  != NULL);
272
273     return SafeReadBuffer(TargetBuffer(m_pLeftSideDCB, sizeof(DebuggerIPCControlBlock)), 
274                           reinterpret_cast<BYTE *>(m_pDCBBuffer));
275 }
276
277 // Get the pointer to the RS DCB.
278 // 
279 // virtual 
280 DebuggerIPCControlBlock * LocalEventChannel::GetDCB()
281 {
282     return m_pDCBBuffer;
283 }
284
285
286 // Check whether we need to wait for an acknowledgement from the LS after sending an IPC event.
287 //
288 // virtual 
289 BOOL LocalEventChannel::NeedToWaitForAck(DebuggerIPCEvent * pEvent)
290 {
291     // On Windows, we need to wait for acknowledgement for every synchronous event.
292     return !pEvent->asyncSend;
293 }
294
295 // Get a handle to wait on after sending an IPC event to the LS.  The caller should call NeedToWaitForAck()
296 //
297 // virtual 
298 HANDLE LocalEventChannel::GetRightSideEventAckHandle()
299 {
300     return m_rightSideEventRead;
301 }
302
303 // Clean up the state if the wait for an acknowledgement is unsuccessful.
304 //
305 // virtual 
306 void LocalEventChannel::ClearEventForLeftSide()
307 {
308     ResetEvent(m_rightSideEventAvailable);
309 }
310
311 // Send an IPC event to the LS.
312 //
313 // virtual 
314 HRESULT LocalEventChannel::SendEventToLeftSide(DebuggerIPCEvent * pEvent, SIZE_T eventSize)
315 {
316     _ASSERTE(eventSize <= CorDBIPC_BUFFER_SIZE);
317
318     HRESULT hr       = E_FAIL;
319     BOOL    fSuccess = FALSE;
320
321     // Copy the event into the shared memory segment.
322     hr = SafeWriteBuffer(RemoteReceiveBuffer(eventSize), reinterpret_cast<BYTE *>(pEvent));
323     if (FAILED(hr))
324     {
325         return hr;
326     }
327
328     // Do some safety-checks for sending an Async-Event.
329 #if defined(_DEBUG)
330     {
331         // We can only send 1 event from RS-->LS at a time.
332         // For non-async events, this is obviously enforced. (since the events are blocking & serialized)
333         // If this is an AsyncSend, then our caller was responsible for making sure it
334         // was safe to send.
335         // There should be no other IPC event in the pipeline. This, both RSEA & RSER
336         // should be non-signaled. check that now.
337         // It's ok if these fail - we detect that below.
338         int res2 = ::WaitForSingleObject(m_rightSideEventAvailable, 0);
339         CONSISTENCY_CHECK_MSGF(res2 != WAIT_OBJECT_0, ("RSEA:%d", res2));
340
341         int res3 = ::WaitForSingleObject(m_rightSideEventRead, 0);
342         CONSISTENCY_CHECK_MSGF(res3 != WAIT_OBJECT_0, ("RSER:%d", res3));
343     }
344 #endif // _DEBUG
345
346     // Tell the runtime controller there is an event ready.
347     STRESS_LOG0(LF_CORDB, LL_INFO1000, "Set RSEA\n");
348     fSuccess = SetEvent(m_rightSideEventAvailable);
349
350     if (!fSuccess)
351     {
352         ThrowHR(HRESULT_FROM_GetLastError());
353     }
354
355     return S_OK;
356 }
357
358 // Get the reply from the LS for a previously sent IPC event.
359 //
360 // virtual 
361 HRESULT LocalEventChannel::GetReplyFromLeftSide(DebuggerIPCEvent * pReplyEvent, SIZE_T eventSize)
362 {
363     // Simply read the IPC event reply directly from the receive buffer on the LS.
364     return SafeReadBuffer(RemoteReceiveBuffer(eventSize), reinterpret_cast<BYTE *>(pReplyEvent));
365 }
366
367 // Save an IPC event from the LS.  
368 // Used for transferring an IPC event from the native pipeline to the IPC event channel.
369 //
370 // virtual
371 HRESULT LocalEventChannel::SaveEventFromLeftSide(DebuggerIPCEvent * pEventFromLeftSide)
372 {
373     // On Windows, when a thread raises a debug event through the native pipeline, the process is suspended.
374     // Thus, the LS IPC event will still be in the send buffer in the debuggee's address space.
375     // Since there is no chance the send buffer can be altered, we don't need to save the event.
376     // We can simply read from it.
377     return S_OK;
378 }
379
380 // Get a saved IPC event from the LS.  
381 // Used for transferring an IPC event from the native pipeline to the IPC event channel.
382 //
383 // virtual 
384 HRESULT LocalEventChannel::GetEventFromLeftSide(DebuggerIPCEvent * pLocalManagedEvent)
385 {
386     // See code:LocalEventChannel::SaveEventFromLeftSide.
387     // Make sure we are reading form the send buffer, not the receive buffer.
388     return SafeReadBuffer(RemoteSendBuffer(CorDBIPC_BUFFER_SIZE), reinterpret_cast<BYTE *>(pLocalManagedEvent));
389 }
390
391 //-----------------------------------------------------------------------------
392 //
393 // Get a target buffer representing the area of the DebuggerIPCControlBlock on the helper thread that 
394 // holds information received from the LS as the result of an IPC event. 
395 //
396 // Arguments:
397 //    size - size of the receive buffer
398 //
399 // Return Value:
400 //    a TargetBuffer representing the receive buffer on the LS
401 //
402
403 TargetBuffer LocalEventChannel::RemoteReceiveBuffer(SIZE_T size)
404 {
405     return TargetBuffer(m_pLeftSideDCB + offsetof(DebuggerIPCControlBlock, m_receiveBuffer), (ULONG)size);
406 }
407
408 //-----------------------------------------------------------------------------
409 //
410 // Get a target buffer representing the area of the DebuggerIPCControlBlock on the helper thread that 
411 // holds information sent to the LS with an IPC event. 
412 //
413 // Arguments:
414 //    size - size of the send buffer
415 //
416 // Return Value:
417 //    a TargetBuffer representing the send buffer on the LS
418 //
419
420 TargetBuffer LocalEventChannel::RemoteSendBuffer(SIZE_T size)
421 {
422     return TargetBuffer(m_pLeftSideDCB + offsetof(DebuggerIPCControlBlock, m_sendBuffer), (ULONG)size);
423 }
424
425 //-----------------------------------------------------------------------------
426 //
427 // Write memory to the LS using the data target.
428 //
429 // Arguments:
430 //    tb           - target address and size to be written to
431 //    pLocalBuffer - data to write
432 //
433 // Return Value:
434 //    S_OK if successful
435 //
436
437 HRESULT LocalEventChannel::SafeWriteBuffer(TargetBuffer tb, const BYTE * pLocalBuffer)
438 {
439     return m_pMutableDataTarget->WriteVirtual(tb.pAddress, pLocalBuffer, tb.cbSize);
440 }
441
442 //-----------------------------------------------------------------------------
443 //
444 // Read memory from the LS using the data target.
445 //
446 // Arguments:
447 //    tb           - target address and size to be read from
448 //    pLocalBuffer - buffer for storing the data read from the LS
449 //
450 // Return Value:
451 //    S_OK if the entire specified range is read successful
452 //
453
454 HRESULT LocalEventChannel::SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer)
455 {
456     ULONG32 cbRead;
457     HRESULT hr = m_pMutableDataTarget->ReadVirtual(tb.pAddress, pLocalBuffer, tb.cbSize, &cbRead);
458     if (FAILED(hr))
459     {
460         return CORDBG_E_READVIRTUAL_FAILURE;
461     }
462
463     if (cbRead != tb.cbSize)
464     {
465         return HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
466     }
467
468     return S_OK;
469 }
470
471 //-----------------------------------------------------------------------------
472 //
473 // Duplicate a remote handle into the local process.
474 //
475 // Arguments:
476 //    pLocalHandle  - out parameter; return the duplicated handle
477 //    pRemoteHandle - remote handle to be duplicated
478 //
479 // Return Value:
480 //    S_OK if successful
481 //
482 // Notes:
483 //    nop if pLocalHandle is already initialized
484 //
485
486 HRESULT LocalEventChannel::DuplicateHandleToLocalProcess(HANDLE * pLocalHandle, RemoteHANDLE * pRemoteHandle)
487 {
488     // Dup RSEA and RSER into this process if we don't already have them.
489     // On Launch, we don't have them yet, but on attach we do.
490     if (*pLocalHandle == NULL)
491     {
492         BOOL fSuccess = pRemoteHandle->DuplicateToLocalProcess(m_hTargetProc, pLocalHandle);
493         if (!fSuccess)
494         {            
495             return HRESULT_FROM_GetLastError();
496         }
497     }
498     return S_OK;
499 }