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// RsStackWalk.cpp
6//
7
8//
9// This file contains the implementation of the V3 managed stackwalking API.
10//
11// ======================================================================================
12
13#include "stdafx.h"
14#include "primitives.h"
15
16
17//---------------------------------------------------------------------------------------
18//
19// Constructor for CordbStackWalk.
20//
21// Arguments:
22// pCordbThread - the thread on which this stackwalker is created
23//
24
25CordbStackWalk::CordbStackWalk(CordbThread * pCordbThread)
26 : CordbBase(pCordbThread->GetProcess(), 0, enumCordbStackWalk),
27 m_pCordbThread(pCordbThread),
28 m_pSFIHandle(NULL),
29 m_cachedSetContextFlag(SET_CONTEXT_FLAG_ACTIVE_FRAME),
30 m_cachedHR(S_OK),
31 m_fIsOneFrameAhead(false)
32{
33 m_pCachedFrame.Clear();
34}
35
36void CordbStackWalk::Init()
37{
38 CordbProcess * pProcess = GetProcess();
39 m_lastSyncFlushCounter = pProcess->m_flushCounter;
40
41 IDacDbiInterface * pDAC = pProcess->GetDAC();
42 pDAC->CreateStackWalk(m_pCordbThread->m_vmThreadToken,
43 &m_context,
44 &m_pSFIHandle);
45
46 // see the function header of code:CordbStackWalk::CheckForLegacyHijackCase
47 CheckForLegacyHijackCase();
48
49 // Add itself to the neuter list.
50 m_pCordbThread->GetRefreshStackNeuterList()->Add(GetProcess(), this);
51}
52
53// ----------------------------------------------------------------------------
54// CordbStackWalk::CheckForLegacyHijackCase
55//
56// Description:
57// @dbgtodo legacy interop debugging - In the case of an unhandled hardware exception, the
58// thread will be hijacked to code:Debugger::GenericHijackFunc, which the stackwalker doesn't know how to
59// unwind. We can teach the stackwalker to recognize that hijack stub, but since it's going to be deprecated
60// anyway, it's not worth the effort. So we check for the hijack CONTEXT here and use it as the CONTEXT. This
61// check should be removed when we are completely
62// out-of-process.
63//
64
65void CordbStackWalk::CheckForLegacyHijackCase()
66{
67#if defined(FEATURE_INTEROP_DEBUGGING)
68 CordbProcess * pProcess = GetProcess();
69
70 // Only do this if we have a shim and we are interop-debugging.
71 if ((pProcess->GetShim() != NULL) &&
72 pProcess->IsInteropDebugging())
73 {
74 // And only if we have a CordbUnmanagedThread and we are hijacked to code:Debugger::GenericHijackFunc
75 CordbUnmanagedThread * pUT = pProcess->GetUnmanagedThread(m_pCordbThread->GetVolatileOSThreadID());
76 if (pUT != NULL)
77 {
78 if (pUT->IsFirstChanceHijacked() || pUT->IsGenericHijacked())
79 {
80 // The GetThreadContext function hides the effects of hijacking and returns the unhijacked context
81 m_context.ContextFlags = DT_CONTEXT_FULL;
82 pUT->GetThreadContext(&m_context);
83 IDacDbiInterface * pDAC = GetProcess()->GetDAC();
84 pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken,
85 m_pSFIHandle,
86 SET_CONTEXT_FLAG_ACTIVE_FRAME,
87 &m_context);
88 }
89 }
90 }
91#endif // FEATURE_INTEROP_DEBUGGING
92}
93
94//---------------------------------------------------------------------------------------
95//
96// Destructor for CordbStackWalk.
97//
98// Notes:
99// We don't really need to do anything here since the CordbStackWalk should have been neutered already.
100//
101
102CordbStackWalk::~CordbStackWalk()
103{
104 _ASSERTE(IsNeutered());
105}
106
107//---------------------------------------------------------------------------------------
108//
109// This function resets all the state on a CordbStackWalk and releases all the memory.
110// It is used for neutering and refreshing.
111//
112
113void CordbStackWalk::DeleteAll()
114{
115 _ASSERTE(GetProcess()->GetProcessLock()->HasLock());
116
117 // delete allocated memory
118 if (m_pSFIHandle)
119 {
120 HRESULT hr = S_OK;
121 EX_TRY
122 {
123#if defined(FEATURE_DBGIPC_TRANSPORT_DI)
124 // For Mac debugging, it's not safe to call into the DAC once
125 // code:INativeEventPipeline::TerminateProcess is called. This is because the transport will not
126 // work anymore. The sole purpose of calling DeleteStackWalk() is to release the resources and
127 // memory allocated for the stackwalk. In the remote debugging case, the memory is allocated in
128 // the debuggee process. If the process is already terminated, then it's ok to skip the call.
129 if (!GetProcess()->m_exiting)
130#endif // FEATURE_DBGIPC_TRANSPORT_DI
131 {
132 // This Delete call shouldn't actually throw. Worst case, the DDImpl leaked memory.
133 GetProcess()->GetDAC()->DeleteStackWalk(m_pSFIHandle);
134 }
135 }
136 EX_CATCH_HRESULT(hr);
137 SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
138 m_pSFIHandle = NULL;
139 }
140
141 // clear out the cached frame
142 m_pCachedFrame.Clear();
143 m_cachedHR = S_OK;
144 m_fIsOneFrameAhead = false;
145}
146
147//---------------------------------------------------------------------------------------
148//
149// Release all memory used by the stackwalker.
150//
151//
152// Notes:
153// CordbStackWalk is neutered by CordbThread or CleanupStack().
154//
155
156void CordbStackWalk::Neuter()
157{
158 if (IsNeutered())
159 {
160 return;
161 }
162
163 DeleteAll();
164 CordbBase::Neuter();
165}
166
167// standard QI function
168HRESULT CordbStackWalk::QueryInterface(REFIID id, void **pInterface)
169{
170 if (id == IID_ICorDebugStackWalk)
171 {
172 *pInterface = static_cast<ICorDebugStackWalk*>(this);
173 }
174 else if (id == IID_IUnknown)
175 {
176 *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugStackWalk*>(this));
177 }
178 else
179 {
180 *pInterface = NULL;
181 return E_NOINTERFACE;
182 }
183
184 ExternalAddRef();
185 return S_OK;
186}
187
188//---------------------------------------------------------------------------------------
189//
190// Refreshes all the state stored on the CordbStackWalk. This is necessary because sending IPC events to
191// the LS flushes the DAC cache, and m_pSFIHandle is allocated entirely in DAC memory. So, we keep track
192// of whether we have sent an IPC event and refresh the CordbStackWalk if necessary.
193//
194// Notes:
195// Throws on error.
196//
197
198void CordbStackWalk::RefreshIfNeeded()
199{
200 CordbProcess * pProcess = GetProcess();
201 _ASSERTE(pProcess->GetProcessLock()->HasLock());
202
203 // check if we need to refresh
204 if (m_lastSyncFlushCounter != pProcess->m_flushCounter)
205 {
206 // Make a local copy of the CONTEXT here. DeleteAll() will delete the CONTEXT on the cached frame,
207 // and CreateStackWalk() actually uses the CONTEXT buffer we pass to it.
208 DT_CONTEXT ctx;
209 if (m_fIsOneFrameAhead)
210 {
211 ctx = *(m_pCachedFrame->GetContext());
212 }
213 else
214 {
215 ctx = m_context;
216 }
217
218 // clear all the state
219 DeleteAll();
220
221 // create a new stackwalk handle
222 pProcess->GetDAC()->CreateStackWalk(m_pCordbThread->m_vmThreadToken,
223 &m_context,
224 &m_pSFIHandle);
225
226 // advance the stackwalker to where we originally were
227 SetContextWorker(m_cachedSetContextFlag, sizeof(DT_CONTEXT), reinterpret_cast<BYTE *>(&ctx));
228
229 // update the sync counter
230 m_lastSyncFlushCounter = pProcess->m_flushCounter;
231 }
232} // CordbStackWalk::RefreshIfNeeded()
233
234//---------------------------------------------------------------------------------------
235//
236// Retrieves the CONTEXT of the current frame.
237//
238// Arguments:
239// contextFlags - context flags used to determine the required size for the buffer
240// contextBufSize - size of the CONTEXT buffer
241// pContextSize - out parameter; returns the size required for the CONTEXT buffer
242// pbContextBuf - the CONTEXT buffer
243//
244// Return Value:
245// Return S_OK on success.
246// Return CORDBG_E_PAST_END_OF_STACK if we are already at the end of the stack.
247// Return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if the buffer is too small.
248// Return E_FAIL on other failures.
249//
250
251HRESULT CordbStackWalk::GetContext(ULONG32 contextFlags,
252 ULONG32 contextBufSize,
253 ULONG32 * pContextSize,
254 BYTE pbContextBuf[])
255{
256 HRESULT hr = S_OK;
257 PUBLIC_REENTRANT_API_BEGIN(this)
258 {
259 RefreshIfNeeded();
260
261 // set the required size for the CONTEXT buffer
262 if (pContextSize != NULL)
263 {
264 *pContextSize = ContextSizeForFlags(contextFlags);
265 }
266
267 // If all the user wants to know is the CONTEXT size, then we are done.
268 if ((contextBufSize != 0) && (pbContextBuf != NULL))
269 {
270 if (contextBufSize < 4)
271 {
272 ThrowWin32(ERROR_INSUFFICIENT_BUFFER);
273 }
274
275 DT_CONTEXT * pContext = reinterpret_cast<DT_CONTEXT *>(pbContextBuf);
276
277 // Some helper functions that examine the context expect the flags to be initialized.
278 pContext->ContextFlags = contextFlags;
279
280 // check the size of the incoming buffer
281 if (!CheckContextSizeForBuffer(contextBufSize, pbContextBuf))
282 {
283 ThrowWin32(ERROR_INSUFFICIENT_BUFFER);
284 }
285
286 // Check if we are one frame ahead. If so, returned the CONTEXT on the cached frame.
287 if (m_fIsOneFrameAhead)
288 {
289 if (m_pCachedFrame != NULL)
290 {
291 const DT_CONTEXT * pSrcContext = m_pCachedFrame->GetContext();
292 _ASSERTE(pSrcContext);
293 CORDbgCopyThreadContext(pContext, pSrcContext);
294 }
295 else
296 {
297 // We encountered a problem when we were trying to initialize the CordbNativeFrame.
298 // However, the problem occurred after we have unwound the current frame.
299 // What do we do here? We don't have the CONTEXT anymore.
300 _ASSERTE(FAILED(m_cachedHR));
301 ThrowHR(m_cachedHR);
302 }
303 }
304 else
305 {
306 // No easy way out in this case. We have to call the DDI.
307 IDacDbiInterface * pDAC = GetProcess()->GetDAC();
308
309 IDacDbiInterface::FrameType ft = pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, NULL);
310 if (ft == IDacDbiInterface::kInvalid)
311 {
312 ThrowHR(E_FAIL);
313 }
314 else if (ft == IDacDbiInterface::kAtEndOfStack)
315 {
316 ThrowHR(CORDBG_E_PAST_END_OF_STACK);
317 }
318 else if (ft == IDacDbiInterface::kExplicitFrame)
319 {
320 ThrowHR(CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME);
321 }
322 else
323 {
324 // We always store the current CONTEXT, so just copy it into the buffer.
325 CORDbgCopyThreadContext(pContext, &m_context);
326 }
327 }
328 }
329 }
330 PUBLIC_REENTRANT_API_END(hr);
331 return hr;
332}
333
334//---------------------------------------------------------------------------------------
335//
336// Set the stackwalker to the specified CONTEXT.
337//
338// Arguments:
339// flag - context flags used to determine the size of the CONTEXT
340// contextSize - the size of the CONTEXT
341// context - the CONTEXT as a byte array
342//
343// Return Value:
344// Return S_OK on success.
345// Return E_INVALIDARG if context is NULL
346// Return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if the CONTEXT is too small.
347// Return E_FAIL on other failures.
348//
349
350HRESULT CordbStackWalk::SetContext(CorDebugSetContextFlag flag, ULONG32 contextSize, BYTE context[])
351{
352 HRESULT hr = S_OK;
353 PUBLIC_REENTRANT_API_BEGIN(this)
354 {
355 RefreshIfNeeded();
356 SetContextWorker(flag, contextSize, context);
357 }
358 PUBLIC_REENTRANT_API_END(hr);
359 return hr;
360}
361
362//---------------------------------------------------------------------------------------
363//
364// Refer to the comment for code:CordbStackWalk::SetContext
365//
366
367void CordbStackWalk::SetContextWorker(CorDebugSetContextFlag flag, ULONG32 contextSize, BYTE context[])
368{
369 if (context == NULL)
370 {
371 ThrowHR(E_INVALIDARG);
372 }
373
374 if (!CheckContextSizeForBuffer(contextSize, context))
375 {
376 ThrowWin32(ERROR_INSUFFICIENT_BUFFER);
377 }
378
379 // invalidate the cache
380 m_pCachedFrame.Clear();
381 m_cachedHR = S_OK;
382 m_fIsOneFrameAhead = false;
383
384 DT_CONTEXT * pSrcContext = reinterpret_cast<DT_CONTEXT *>(context);
385
386 // Check the incoming CONTEXT using a temporary CONTEXT buffer before updating our real CONTEXT buffer.
387 // The incoming CONTEXT is not required to have all the bits set in its CONTEXT flags, so only update
388 // the registers specified by the CONTEXT flags. Note that CORDbgCopyThreadContext() honours the CONTEXT
389 // flags on both the source and the destination CONTEXTs when it copies them.
390 DT_CONTEXT tmpCtx = m_context;
391 tmpCtx.ContextFlags |= pSrcContext->ContextFlags;
392 CORDbgCopyThreadContext(&tmpCtx, pSrcContext);
393
394 IDacDbiInterface * pDAC = GetProcess()->GetDAC();
395 IfFailThrow(pDAC->CheckContext(m_pCordbThread->m_vmThreadToken, &tmpCtx));
396
397 // At this point we have done all of our checks to verify that the incoming CONTEXT is sane, so we can
398 // update our internal CONTEXT buffer.
399 m_context = tmpCtx;
400 m_cachedSetContextFlag = flag;
401
402 pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken,
403 m_pSFIHandle,
404 flag,
405 &m_context);
406}
407
408//---------------------------------------------------------------------------------------
409//
410// Helper to perform all the necessary operations when we unwind, including:
411// 1) Unwind
412// 2) Save the new unwound CONTEXT
413//
414// Return Value:
415// Return TRUE if we successfully unwind to the next frame.
416// Return FALSE if there is no more frame to walk.
417// Throw on error.
418//
419
420BOOL CordbStackWalk::UnwindStackFrame()
421{
422 CordbProcess * pProcess = GetProcess();
423 _ASSERTE(pProcess->GetProcessLock()->HasLock());
424
425 IDacDbiInterface * pDAC = pProcess->GetDAC();
426 BOOL retVal = pDAC->UnwindStackWalkFrame(m_pSFIHandle);
427
428 // Now that we have unwound, make sure we update the CONTEXT buffer to reflect the current stack frame.
429 // This call is safe regardless of whether the unwind is successful or not.
430 pDAC->GetStackWalkCurrentContext(m_pSFIHandle, &m_context);
431
432 return retVal;
433} // CordbStackWalk::UnwindStackWalkFrame
434
435//---------------------------------------------------------------------------------------
436//
437// Unwind the stackwalker to the next frame.
438//
439// Return Value:
440// Return S_OK on success.
441// Return CORDBG_E_FAIL_TO_UNWIND_FRAME if the unwind fails.
442// Return CORDBG_S_AT_END_OF_STACK if we have reached the end of the stack as a result of this unwind.
443// Return CORDBG_E_PAST_END_OF_STACK if we are already at the end of the stack to begin with.
444//
445
446HRESULT CordbStackWalk::Next()
447{
448 HRESULT hr = S_OK;
449 PUBLIC_REENTRANT_API_BEGIN(this)
450 {
451 RefreshIfNeeded();
452 if (m_fIsOneFrameAhead)
453 {
454 // We have already unwound to the next frame when we materialize the CordbNativeFrame
455 // for the current frame. So we just need to clear the cache because we are already at
456 // the next frame.
457 if (m_pCachedFrame != NULL)
458 {
459 m_pCachedFrame.Clear();
460 }
461 m_cachedHR = S_OK;
462 m_fIsOneFrameAhead = false;
463 }
464 else
465 {
466 IDacDbiInterface * pDAC = GetProcess()->GetDAC();
467 IDacDbiInterface::FrameType ft = IDacDbiInterface::kInvalid;
468
469 ft = pDAC->GetStackWalkCurrentFrameInfo(this->m_pSFIHandle, NULL);
470 if (ft == IDacDbiInterface::kAtEndOfStack)
471 {
472 ThrowHR(CORDBG_E_PAST_END_OF_STACK);
473 }
474
475 // update the cahced flag to indicate that we have reached an unwind CONTEXT
476 m_cachedSetContextFlag = SET_CONTEXT_FLAG_UNWIND_FRAME;
477
478 if (UnwindStackFrame())
479 {
480 hr = S_OK;
481 }
482 else
483 {
484 hr = CORDBG_S_AT_END_OF_STACK;
485 }
486 }
487 }
488 PUBLIC_REENTRANT_API_END(hr);
489 return hr;
490}
491
492//---------------------------------------------------------------------------------------
493//
494// Retrieves an ICDFrame corresponding to the current frame:
495// Stopped At Out Parameter Return Value
496// ---------- ------------- ------------
497// explicit frame CordbInternalFrame S_OK
498// managed stack frame CordbNativeFrame S_OK
499// native stack frame NULL S_FALSE
500//
501// Arguments:
502// ppFrame - out parameter; return the ICDFrame
503//
504// Return Value:
505// On success return the HRs above.
506// Return CORDBG_E_PAST_END_OF_STACK if we are already at the end of the stack.
507// Return E_INVALIDARG if ppFrame is NULL
508// Return E_FAIL on other errors.
509//
510// Notes:
511// This is just a wrapper with an EX_TRY/EX_CATCH_HRESULT for GetFrameWorker().
512//
513
514HRESULT CordbStackWalk::GetFrame(ICorDebugFrame ** ppFrame)
515{
516 HRESULT hr = S_OK;
517 PUBLIC_REENTRANT_API_NO_LOCK_BEGIN(this)
518 {
519 ATT_REQUIRE_STOPPED_MAY_FAIL_OR_THROW(GetProcess(), ThrowHR);
520 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
521
522 RefreshIfNeeded();
523 hr = GetFrameWorker(ppFrame);
524 }
525 PUBLIC_REENTRANT_API_END(hr);
526
527 if (FAILED(hr))
528 {
529 if (m_fIsOneFrameAhead && (m_pCachedFrame == NULL))
530 {
531 // We encountered a problem when we try to materialize a CordbNativeFrame.
532 // Cache the failure HR so that we can return it later if the caller
533 // calls GetFrame() again or GetContext().
534 m_cachedHR = hr;
535 }
536 }
537
538 return hr;
539}
540
541//---------------------------------------------------------------------------------------
542//
543// Refer to the comment for code:CordbStackWalk::GetFrame
544//
545
546HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame)
547{
548 _ASSERTE(GetProcess()->GetProcessLock()->HasLock());
549
550 if (ppFrame == NULL)
551 {
552 ThrowHR(E_INVALIDARG);
553 }
554 *ppFrame = NULL;
555
556 RSInitHolder<CordbFrame> pResultFrame(NULL);
557
558 if (m_fIsOneFrameAhead)
559 {
560 if (m_pCachedFrame != NULL)
561 {
562 pResultFrame.Assign(m_pCachedFrame);
563 pResultFrame.TransferOwnershipExternal(ppFrame);
564 return S_OK;
565 }
566 else
567 {
568 // We encountered a problem when we were trying to initialize the CordbNativeFrame.
569 // However, the problem occurred after we have unwound the current frame.
570 // Whatever error code we return, it should be the same one GetContext() returns.
571 _ASSERTE(FAILED(m_cachedHR));
572 ThrowHR(m_cachedHR);
573 }
574 }
575
576 IDacDbiInterface * pDAC = NULL;
577 DebuggerIPCE_STRData frameData;
578 ZeroMemory(&frameData, sizeof(frameData));
579 IDacDbiInterface::FrameType ft = IDacDbiInterface::kInvalid;
580
581 pDAC = GetProcess()->GetDAC();
582 ft = pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, &frameData);
583
584 if (ft == IDacDbiInterface::kInvalid)
585 {
586 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - invalid stackwalker (%p)", this);
587 ThrowHR(E_FAIL);
588 }
589 else if (ft == IDacDbiInterface::kAtEndOfStack)
590 {
591 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - past end of stack (%p)", this);
592 ThrowHR(CORDBG_E_PAST_END_OF_STACK);
593 }
594 else if (ft == IDacDbiInterface::kNativeStackFrame)
595 {
596 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - native stack frame (%p)", this);
597 return S_FALSE;
598 }
599 else if (ft == IDacDbiInterface::kExplicitFrame)
600 {
601 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - explicit frame (%p)", this);
602
603 // We no longer expect to get internal frames by unwinding.
604 GetProcess()->TargetConsistencyCheck(false);
605 }
606 else if (ft == IDacDbiInterface::kManagedStackFrame)
607 {
608 _ASSERTE(frameData.eType == DebuggerIPCE_STRData::cMethodFrame);
609
610 HRESULT hr = S_OK;
611
612 // In order to find the FramePointer on x86, we need to unwind to the next frame.
613 // Technically, only x86 needs to do this, because the x86 runtime stackwalker doesn't uwnind
614 // one frame ahead of time. However, we are doing this on all platforms to keep things simple.
615 BOOL fSuccess = UnwindStackFrame();
616 (void)fSuccess; //prevent "unused variable" error from GCC
617 _ASSERTE(fSuccess);
618
619 m_fIsOneFrameAhead = true;
620#if defined(DBG_TARGET_X86)
621 frameData.fp = pDAC->GetFramePointer(m_pSFIHandle);
622#endif // DBG_TARGET_X86
623
624 // currentFuncData contains general information about the method.
625 // It has no information about any particular jitted instance of the method.
626 DebuggerIPCE_FuncData * pFuncData = &(frameData.v.funcData);
627
628 // currentJITFuncData contains information about the current jitted instance of the method
629 // on the stack.
630 DebuggerIPCE_JITFuncData * pJITFuncData = &(frameData.v.jitFuncData);
631
632 // Lookup the appdomain that the thread was in when it was executing code for this frame. We pass this
633 // to the frame when we create it so we can properly resolve locals in that frame later.
634 CordbAppDomain * pCurrentAppDomain = GetProcess()->LookupOrCreateAppDomain(frameData.vmCurrentAppDomainToken);
635 _ASSERTE(pCurrentAppDomain != NULL);
636
637 // Lookup the module
638 CordbModule* pModule = pCurrentAppDomain->LookupOrCreateModule(pFuncData->vmDomainFile);
639 PREFIX_ASSUME(pModule != NULL);
640
641 // Create or look up a CordbNativeCode. There is one for each jitted instance of a method,
642 // and we may have multiple instances because of generics.
643 CordbNativeCode * pNativeCode = pModule->LookupOrCreateNativeCode(pFuncData->funcMetadataToken,
644 pJITFuncData->vmNativeCodeMethodDescToken,
645 pJITFuncData->nativeStartAddressPtr);
646 IfFailThrow(hr);
647
648 // The native code object will create the function object if needed
649 CordbFunction * pFunction = pNativeCode->GetFunction();
650
651 // A CordbFunction is theoretically the uninstantiated method, yet for back-compat we allow
652 // debuggers to assume that it corresponds to exactly 1 native code blob. In order for
653 // an open generic function to know what native code to give back, we attach an arbitrary
654 // native code that we located through code inspection.
655 // Note that not all CordbFunction objects get created via stack traces because you can also
656 // create them by name. In that case you still won't get code for Open generic functions
657 // because we will never have attached one and the lookup by token is insufficient. This
658 // behavior mimics our 2.0 debugging behavior though so its not a regression.
659 pFunction->NotifyCodeCreated(pNativeCode);
660
661 IfFailThrow(hr);
662
663 _ASSERTE((pFunction != NULL) && (pNativeCode != NULL));
664
665 // initialize the auxiliary info required for funclets
666 CordbMiscFrame miscFrame(pJITFuncData);
667
668 // Create the native frame.
669 CordbNativeFrame* pNativeFrame = new CordbNativeFrame(m_pCordbThread,
670 frameData.fp,
671 pNativeCode,
672 pJITFuncData->nativeOffset,
673 &(frameData.rd),
674 frameData.v.taAmbientESP,
675 !!frameData.quicklyUnwound,
676 pCurrentAppDomain,
677 &miscFrame,
678 &(frameData.ctx));
679
680 pResultFrame.Assign(static_cast<CordbFrame *>(pNativeFrame));
681 m_pCachedFrame.Assign(static_cast<CordbFrame *>(pNativeFrame));
682
683 // @dbgtodo dynamic language debugging
684 // If we are dealing with a dynamic method (e.g. an IL stub, a LCG method, etc.),
685 // then we don't have the metadata or the debug info (sequence points, etc.).
686 // This means that we can't do anything meaningful with a CordbJITILFrame anyway,
687 // so let's not create the CordbJITILFrame at all. Note that methods created with
688 // RefEmit are okay, i.e. they have metadata.
689
690 // The check for IsNativeImpl() != CordbFunction::kNativeOnly catches an odd profiler
691 // case. A profiler can rewrite assemblies at load time so that a P/invoke becomes a
692 // regular managed method. mscordbi isn't yet designed to handle runtime metadata
693 // changes, so it still thinks the method is a p/invoke. If we only relied on
694 // frameData.v.fNoMetadata which is populated by the DAC, that will report
695 // FALSE (the method does have metadata/IL now). However pNativeCode->LoadNativeInfo
696 // is going to check DBI's metadata and calculate this is a p/invoke, which will
697 // throw an exception that the method isn't IL.
698 // Ideally we probably want to expose the profiler's change to the method,
699 // however that will take significant work. Part of that is correctly detecting and
700 // updating metadata in DBI, part is determinging if/how the debugger is notified,
701 // and part is auditing mscordbi to ensure that anything we cached based on the
702 // old metadata is correctly invalidated.
703 // Since this is a late fix going into a controlled servicing release I have
704 // opted for a much narrower fix. Doing the check for IsNativeImpl() != CordbFunction::kNativeOnly
705 // will continue to treat our new method as though it was a p/invoke, and the
706 // debugger will not provide IL for it. The debugger can't inspect within the profiler
707 // modified method, but at least the error won't leak out to interfere with inspection
708 // of the callstack as a whole.
709 if (!frameData.v.fNoMetadata &&
710 pNativeCode->GetFunction()->IsNativeImpl() != CordbFunction::kNativeOnly)
711 {
712 pNativeCode->LoadNativeInfo();
713
714 // By design, when a managed exception occurs we return the sequence point containing the faulting
715 // instruction in the leaf frame. In the past we didn't always achieve this,
716 // but we are being more deliberate about this behavior now.
717
718 // If jsutAfterILThrow is true, it means nativeOffset points to the return address of IL_Throw
719 // (or another JIT exception helper) after an exception has been thrown.
720 // In such cases we want to adjust nativeOffset, so it will point an actual exception callsite.
721 // By subtracting STACKWALK_CONTROLPC_ADJUST_OFFSET from nativeOffset you can get
722 // an address somewhere inside CALL instruction.
723 // This ensures more consistent placement of exception line highlighting in Visual Studio
724 DWORD nativeOffsetToMap = pJITFuncData->jsutAfterILThrow ?
725 (DWORD)pJITFuncData->nativeOffset - STACKWALK_CONTROLPC_ADJUST_OFFSET :
726 (DWORD)pJITFuncData->nativeOffset;
727 CorDebugMappingResult mappingType;
728 ULONG uILOffset = pNativeCode->GetSequencePoints()->MapNativeOffsetToIL(
729 nativeOffsetToMap,
730 &mappingType);
731
732 // Find or create the IL Code, and the pJITILFrame.
733 RSExtSmartPtr<CordbILCode> pCode;
734
735 // The code for populating CordbFunction ILCode looks really bizzare... it appears to only grab the
736 // correct version of the IL if that is still the current EnC version yet it is populated deliberately
737 // late bound at which point the latest version may be different. In fact even here the latest version
738 // could already be different, but this is no worse than what the code used to do
739 hr = pFunction->GetILCode(&pCode);
740 IfFailThrow(hr);
741 _ASSERTE(pCode != NULL);
742
743 // We populate the code for ReJit eagerly to make sure we still have it if the profiler removes the
744 // instrumentation later. Of course the only way it will still be accessible to our caller is if he
745 // saves a pointer to the ILCode.
746 // I'm not sure if ignoring rejit for mini-dumps is the right call long term, but we aren't doing
747 // anything special to collect the memory at dump time so we better be prepared to not fetch it here.
748 // We'll attempt to treat it as not being instrumented, though I suspect the abstraction is leaky.
749 RSSmartPtr<CordbReJitILCode> pReJitCode;
750 EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
751 {
752 VMPTR_NativeCodeVersionNode vmNativeCodeVersionNode = VMPTR_NativeCodeVersionNode::NullPtr();
753 IfFailThrow(GetProcess()->GetDAC()->GetNativeCodeVersionNode(pJITFuncData->vmNativeCodeMethodDescToken, pJITFuncData->nativeStartAddressPtr, &vmNativeCodeVersionNode));
754 if (!vmNativeCodeVersionNode.IsNull())
755 {
756 VMPTR_ILCodeVersionNode vmILCodeVersionNode = VMPTR_ILCodeVersionNode::NullPtr();
757 IfFailThrow(GetProcess()->GetDAC()->GetILCodeVersionNode(vmNativeCodeVersionNode, &vmILCodeVersionNode));
758 if (!vmILCodeVersionNode.IsNull())
759 {
760 IfFailThrow(pFunction->LookupOrCreateReJitILCode(vmILCodeVersionNode, &pReJitCode));
761 }
762 }
763 }
764 EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY
765
766
767
768 RSInitHolder<CordbJITILFrame> pJITILFrame(new CordbJITILFrame(pNativeFrame,
769 pCode,
770 uILOffset,
771 mappingType,
772 frameData.v.exactGenericArgsToken,
773 frameData.v.dwExactGenericArgsTokenIndex,
774 !!frameData.v.fVarArgs,
775 pReJitCode));
776
777 // Initialize the frame. This is a nop if the method is not a vararg method.
778 hr = pJITILFrame->Init();
779 IfFailThrow(hr);
780
781 pNativeFrame->m_JITILFrame.Assign(pJITILFrame);
782 pJITILFrame.ClearAndMarkDontNeuter();
783 }
784
785 STRESS_LOG3(LF_CORDB, LL_INFO1000, "CSW::GFW - managed stack frame (%p): CNF - 0x%p, CJILF - 0x%p",
786 this, pNativeFrame, pNativeFrame->m_JITILFrame.GetValue());
787 } // kManagedStackFrame
788 else if (ft == IDacDbiInterface::kNativeRuntimeUnwindableStackFrame)
789 {
790 _ASSERTE(frameData.eType == DebuggerIPCE_STRData::cRuntimeNativeFrame);
791
792 // In order to find the FramePointer on x86, we need to unwind to the next frame.
793 // Technically, only x86 needs to do this, because the x86 runtime stackwalker doesn't uwnind
794 // one frame ahead of time. However, we are doing this on all platforms to keep things simple.
795 BOOL fSuccess = UnwindStackFrame();
796 (void)fSuccess; //prevent "unused variable" error from GCC
797 _ASSERTE(fSuccess);
798
799 m_fIsOneFrameAhead = true;
800#if defined(DBG_TARGET_X86)
801 frameData.fp = pDAC->GetFramePointer(m_pSFIHandle);
802#endif // DBG_TARGET_X86
803
804 // Lookup the appdomain that the thread was in when it was executing code for this frame. We pass this
805 // to the frame when we create it so we can properly resolve locals in that frame later.
806 CordbAppDomain * pCurrentAppDomain =
807 GetProcess()->LookupOrCreateAppDomain(frameData.vmCurrentAppDomainToken);
808 _ASSERTE(pCurrentAppDomain != NULL);
809
810 CordbRuntimeUnwindableFrame * pRuntimeFrame = new CordbRuntimeUnwindableFrame(m_pCordbThread,
811 frameData.fp,
812 pCurrentAppDomain,
813 &(frameData.ctx));
814
815 pResultFrame.Assign(static_cast<CordbFrame *>(pRuntimeFrame));
816 m_pCachedFrame.Assign(static_cast<CordbFrame *>(pRuntimeFrame));
817
818 STRESS_LOG2(LF_CORDB, LL_INFO1000, "CSW::GFW - runtime unwindable stack frame (%p): 0x%p",
819 this, pRuntimeFrame);
820 }
821
822 pResultFrame.TransferOwnershipExternal(ppFrame);
823
824 return S_OK;
825}
826