Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,12 @@ class AsmOffsets
public const int SIZEOF__EHEnum = 0x20;
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x20;
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
public const int OFFSETOF__ExInfo__m_pExContext = 0xa8;
public const int OFFSETOF__ExInfo__m_exception = 0xb0;
public const int OFFSETOF__ExInfo__m_kind = 0xb8;
public const int OFFSETOF__ExInfo__m_passNumber = 0xb9;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0xbc;
public const int OFFSETOF__ExInfo__m_frameIter = 0xc0;
public const int OFFSETOF__ExInfo__m_pExContext = 0xa0;
public const int OFFSETOF__ExInfo__m_exception = 0xa8;
public const int OFFSETOF__ExInfo__m_kind = 0xb0;
public const int OFFSETOF__ExInfo__m_passNumber = 0xb1;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0xb4;
public const int OFFSETOF__ExInfo__m_frameIter = 0xb8;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
public const int OFFSETOF__ExInfo__m_pCatchHandler = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x48;
public const int OFFSETOF__ExInfo__m_handlingFrameSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x50;
Expand All @@ -217,12 +217,12 @@ class AsmOffsets
public const int SIZEOF__EHEnum = 0x10;
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x14;
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
public const int OFFSETOF__ExInfo__m_pExContext = 0x5c;
public const int OFFSETOF__ExInfo__m_exception = 0x60;
public const int OFFSETOF__ExInfo__m_kind = 0x64;
public const int OFFSETOF__ExInfo__m_passNumber = 0x65;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x68;
public const int OFFSETOF__ExInfo__m_frameIter = 0x6c;
public const int OFFSETOF__ExInfo__m_pExContext = 0x58;
public const int OFFSETOF__ExInfo__m_exception = 0x5c;
public const int OFFSETOF__ExInfo__m_kind = 0x60;
public const int OFFSETOF__ExInfo__m_passNumber = 0x61;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x64;
public const int OFFSETOF__ExInfo__m_frameIter = 0x68;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
public const int OFFSETOF__ExInfo__m_pCatchHandler = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x2c;
public const int OFFSETOF__ExInfo__m_handlingFrameSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x30;
Expand Down
12 changes: 7 additions & 5 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4817,9 +4817,9 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::HasUnhandledException(VMPTR_Threa
else
{
// most managed exceptions are just a throwable bound to a
// native exception. In that case this handle will be non-null
OBJECTHANDLE ohException = pThread->GetThrowableAsHandle();
if (ohException != (OBJECTHANDLE)NULL)
// native exception. In that case the exception will be non-null
OBJECTREF exception = pThread->GetExceptionState()->GetThrowable();
if (exception != NULL)
{
// during the UEF we set the unhandled bit, if it is set the exception
// was unhandled
Expand Down Expand Up @@ -4955,8 +4955,10 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetCurrentException(VMPTR_Thread

Thread * pThread = vmThread.GetDacPtr();

// OBJECTHANDLEs are really just TADDRs.
OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); // ohException can be NULL
// Get the exception handle. The exception object is stored directly in ExInfo::m_exception,
// but debugger APIs require a handle. Use m_LastThrownObjectHandle which is kept in sync
// via SafeSetThrowables.
OBJECTHANDLE ohException = pThread->m_LastThrownObjectHandle;

if (ohException == (OBJECTHANDLE)NULL)
{
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3397,6 +3397,13 @@ class ClrDataExceptionState : public IXCLRDataExceptionState
Thread* thread,
ULONG32 flags,
ClrDataExStateType* exInfo,
// Target address of a slot containing the exception Object*.
// This may be a GC handle table slot (e.g. m_LastThrownObjectHandle)
// or the address of ExInfo::m_exception on the target stack.
// Both are valid: the ExInfo lives on the stack which is captured
// in dumps and stable while the target thread is suspended. The
// slot has the same lifetime as the ExInfo — both become invalid
// when ExInfo::PopExInfos calls ReleaseResources.
OBJECTHANDLE throwable,
ClrDataExStateType* prevExInfo);
virtual ~ClrDataExceptionState(void);
Expand Down
47 changes: 21 additions & 26 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3308,7 +3308,7 @@ ClrDataAccess::GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS
}
else
{
*exceptionObject = TO_CDADDR(*PTR_TADDR(pExData->m_hThrowable));
*exceptionObject = dac_cast<TADDR>(pExData->m_exception);
*nextNestedException = PTR_HOST_TO_TADDR(pExData->m_pPrevNestedInfo);
}

Expand Down Expand Up @@ -4064,35 +4064,30 @@ HRESULT ClrDataAccess::GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBl
// By default, there are no buckets
PTR_VOID pBuckets = NULL;

// Get the handle to the throwble
OBJECTHANDLE ohThrowable = pThread->GetThrowableAsHandle();
if (ohThrowable != NULL)
// Get the current throwable
OBJECTREF oThrowable = pThread->GetExceptionState()->GetThrowable();
if (oThrowable != NULL)
{
// Get the object from handle and check if the throwable is preallocated or not
OBJECTREF oThrowable = ObjectFromHandle(ohThrowable);
if (oThrowable != NULL)
// Does the throwable have buckets?
U1ARRAYREF refWatsonBucketArray = ((EXCEPTIONREF)oThrowable)->GetWatsonBucketReference();
if (refWatsonBucketArray != NULL)
{
// Does the throwable have buckets?
U1ARRAYREF refWatsonBucketArray = ((EXCEPTIONREF)oThrowable)->GetWatsonBucketReference();
if (refWatsonBucketArray != NULL)
{
// Get the watson buckets from the throwable for non-preallocated
// exceptions
pBuckets = dac_cast<PTR_VOID>(refWatsonBucketArray->GetDataPtr());
}
else
// Get the watson buckets from the throwable for non-preallocated
// exceptions
pBuckets = dac_cast<PTR_VOID>(refWatsonBucketArray->GetDataPtr());
}
else
{
// This is a preallocated exception object - check if the UE Watson bucket tracker
// has any bucket details
pBuckets = pThread->GetExceptionState()->GetUEWatsonBucketTracker()->RetrieveWatsonBuckets();
if (pBuckets == NULL)
{
// This is a preallocated exception object - check if the UE Watson bucket tracker
// has any bucket details
pBuckets = pThread->GetExceptionState()->GetUEWatsonBucketTracker()->RetrieveWatsonBuckets();
if (pBuckets == NULL)
// Since the UE watson bucket tracker does not have them, look up the current
// exception tracker
if (pThread->GetExceptionState()->GetCurrentExceptionTracker() != NULL)
{
// Since the UE watson bucket tracker does not have them, look up the current
// exception tracker
if (pThread->GetExceptionState()->GetCurrentExceptionTracker() != NULL)
{
pBuckets = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetWatsonBucketTracker()->RetrieveWatsonBuckets();
}
pBuckets = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetWatsonBucketTracker()->RetrieveWatsonBuckets();
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions src/coreclr/debug/daccess/task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4556,13 +4556,17 @@ ClrDataExceptionState::GetPrevious(
{
if (m_prevExInfo)
{
// Pass the address of the ExInfo's m_exception field as the "handle".
// This is not a real GC handle — it is a target address of an OBJECTREF
// slot on the stack. It has the same lifetime as the ExInfo (both are
// invalidated by PopExInfos/ReleaseResources). See dacimpl.h comment.
*exState = new (nothrow)
ClrDataExceptionState(m_dac,
m_appDomain,
m_thread,
CLRDATA_EXCEPTION_DEFAULT,
m_prevExInfo,
m_prevExInfo->m_hThrowable,
(OBJECTHANDLE)dac_cast<TADDR>(&m_prevExInfo->m_exception),
m_prevExInfo->m_pPrevNestedInfo);
status = *exState ? S_OK : E_OUTOFMEMORY;
}
Expand Down Expand Up @@ -4920,13 +4924,15 @@ ClrDataExceptionState::NewFromThread(ClrDataAccess* dac,

exState = thread->GetExceptionState()->m_pCurrentTracker;

// Pass the address of the ExInfo's m_exception field as the "handle".
// See dacimpl.h comment on the throwable parameter.
exIf = new (nothrow)
ClrDataExceptionState(dac,
AppDomain::GetCurrentDomain(),
thread,
CLRDATA_EXCEPTION_DEFAULT,
exState,
exState->m_hThrowable,
(OBJECTHANDLE)dac_cast<TADDR>(&exState->m_exception),
exState->m_pPrevNestedInfo);
if (!exIf)
{
Expand Down
11 changes: 7 additions & 4 deletions src/coreclr/debug/ee/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7867,11 +7867,14 @@ BOOL Debugger::ShouldSendCatchHandlerFound(Thread* pThread)
else
{
BOOL forceSendCatchHandlerFound = FALSE;
OBJECTHANDLE objHandle = pThread->GetThrowableAsHandle();
OBJECTHANDLE retrievedHandle = m_pForceCatchHandlerFoundEventsTable->Lookup(objHandle); //destroy handle
if (retrievedHandle != NULL)
OBJECTHANDLE objHandle = pThread->m_LastThrownObjectHandle;
if (objHandle != NULL)
{
forceSendCatchHandlerFound = TRUE;
OBJECTHANDLE retrievedHandle = m_pForceCatchHandlerFoundEventsTable->Lookup(objHandle);
if (retrievedHandle != NULL)
{
forceSendCatchHandlerFound = TRUE;
}
}
return forceSendCatchHandlerFound;
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ CDAC_TYPE_END(Exception)
CDAC_TYPE_BEGIN(ExceptionInfo)
CDAC_TYPE_INDETERMINATE(ExceptionInfo)
CDAC_TYPE_FIELD(ExceptionInfo, T_POINTER, PreviousNestedInfo, offsetof(ExInfo, m_pPrevNestedInfo))
CDAC_TYPE_FIELD(ExceptionInfo, TYPE(ObjectHandle), ThrownObjectHandle, offsetof(ExInfo, m_hThrowable))
CDAC_TYPE_FIELD(ExceptionInfo, T_POINTER, ThrownObject, offsetof(ExInfo, m_exception))
CDAC_TYPE_FIELD(ExceptionInfo, T_UINT32, ExceptionFlags, cdac_data<ExInfo>::ExceptionFlagsValue)
CDAC_TYPE_FIELD(ExceptionInfo, T_POINTER, StackLowBound, cdac_data<ExInfo>::StackLowBound)
CDAC_TYPE_FIELD(ExceptionInfo, T_POINTER, StackHighBound, cdac_data<ExInfo>::StackHighBound)
Expand Down
31 changes: 9 additions & 22 deletions src/coreclr/vm/eedbginterfaceimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,16 @@ OBJECTHANDLE EEDbgInterfaceImpl::GetThreadException(Thread *pThread)
}
CONTRACTL_END;

OBJECTHANDLE oh = pThread->GetThrowableAsHandle();

if (oh != NULL)
// The exception object is stored directly in ExInfo::m_exception (no handle).
// Return m_LastThrownObjectHandle which is kept in sync via SafeSetThrowables
// before any debugger notification fires. Assert this invariant in debug builds.
#ifdef _DEBUG
ExInfo* pTracker = pThread->GetExceptionState()->GetCurrentExceptionTracker();
if (pTracker != NULL && pTracker->m_exception != NULL && pThread->m_LastThrownObjectHandle != NULL)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any case where we have the exception stashed in m_LastThrownObjectHandle, but the exception tracker does not exist anymore?

I am wondering why we need m_LastThrownObjectHandle with the complicated system to keep it in sync with the tracker.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, m_LastThrownObjectHandle is read after the tracker is gone by EX_CATCH block via CLRLastThrownObjectException.

For the debugger path you, the tracker IS alive, but we need the handle for the MODE_ANY contract (or modify it). Removing LTO entirely would require reworking CLRLastThrownObjectException.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janvorli Do you think it would be feasible to stop synchronizing m_LastThrownObjectHandle with pTracker->m_exception?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the m_LastThrownObjectHandle is needed to bridge the time when managed exception crosses runtime (on Windows also external native code). When SEH COM exception reaches a managed frame after the exception passed through native frames, the ProcessCLRException on Windows or the handler of the PAL_SEHException on Unix uses it to continue propagating the same managed exception object. It seems to me though that we could just create the handle (or set its value) when we are getting rid of the ExInfo. That would simplify the maintenance. But there may be some dragons hidden.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me though that we could just create the handle (or set its value) when we are getting rid of the ExInfo

Yes, it is what I meant.

{
return oh;
_ASSERTE(ObjectFromHandle(pThread->m_LastThrownObjectHandle) == pTracker->m_exception);
}

// Return the last thrown object if there's no current throwable.
// This logic is similar to UpdateCurrentThrowable().
#endif
return pThread->m_LastThrownObjectHandle;
}

Expand All @@ -261,21 +262,7 @@ bool EEDbgInterfaceImpl::IsThreadExceptionNull(Thread *pThread)
}
CONTRACTL_END;

//
// We're assuming that the handle on the
// thread is a strong handle and we're goona check it for
// NULL. We're also assuming something about the
// implementation of the handle here, too.
//
OBJECTHANDLE h = pThread->GetThrowableAsHandle();
if (h == NULL)
{
return true;
}

void *pThrowable = *((void**)h);

return (pThrowable == NULL);
return pThread->IsThrowableNull() && pThread->IsLastThrownObjectNull();
}

void EEDbgInterfaceImpl::ClearThreadException(Thread *pThread)
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/vm/eepolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,8 +789,7 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE
OBJECTHANDLE ohSO = CLRException::GetPreallocatedStackOverflowExceptionHandle();
if (ohSO != NULL)
{
pThread->SafeSetThrowables(ObjectFromHandle(ohSO)
DEBUG_ARG(ThreadExceptionState::STEC_CurrentTrackerEqualNullOkHackForFatalStackOverflow),
pThread->SafeSetThrowables(ObjectFromHandle(ohSO),
TRUE);
}
else
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/excep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1849,7 +1849,7 @@ BOOL IsInFirstFrameOfHandler(Thread *pThread, IJitManager *pJitManager, const ME
CONTRACTL_END;

// if don't have a throwable the aren't processing an exception
if (IsHandleNullUnchecked(pThread->GetThrowableAsHandle()))
if (pThread->IsThrowableNull())
return FALSE;

EH_CLAUSE_ENUMERATOR pEnumState;
Expand Down Expand Up @@ -2572,7 +2572,7 @@ void StackTraceInfo::AppendElement(OBJECTHANDLE hThrowable, UINT_PTR currentIP,
LOG((LF_EH, LL_INFO10000, "StackTraceInfo::AppendElement IP = %p, SP = %p, %s::%s\n", currentIP, currentSP, pFunc ? pFunc->m_pszDebugClassName : "", pFunc ? pFunc->m_pszDebugMethodName : "" ));

// Do not save stacktrace to preallocated exception. These are shared.
if (CLRException::IsPreallocatedExceptionHandle(hThrowable))
if (CLRException::IsPreallocatedExceptionObject(ObjectFromHandle(hThrowable)))
{
return;
}
Expand Down
28 changes: 14 additions & 14 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,9 @@ BOOL HandleHardwareException(PAL_SEHException* ex)
exInfo.TakeExceptionPointersOwnership(ex);
}

GCPROTECT_BEGIN(exInfo.m_exception);
// m_exception is GC-reported via ExInfo chain scanning in ScanStackRoots.
// Do NOT also GCPROTECT it — reporting the same location twice corrupts
// the GC's relocation logic (see clr-code-guide.md §2.1.5).
UnmanagedCallersOnlyCaller throwHwEx(METHOD__EH__RH_THROWHW_EX);

pThread->IncPreventAbort();
Expand All @@ -1457,8 +1459,6 @@ BOOL HandleHardwareException(PAL_SEHException* ex)

DispatchExSecondPass(&exInfo);

GCPROTECT_END();

UNREACHABLE();
}
else
Expand Down Expand Up @@ -1620,8 +1620,9 @@ VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT* pE
}
}

GCPROTECT_BEGIN(exInfo.m_exception);

// m_exception is GC-reported via ExInfo chain scanning in ScanStackRoots.
// Do NOT also GCPROTECT it — reporting the same location twice corrupts
// the GC's relocation logic (see clr-code-guide.md §2.1.5).
UnmanagedCallersOnlyCaller throwEx(METHOD__EH__RH_THROW_EX);

pThread->IncPreventAbort();
Expand All @@ -1631,7 +1632,6 @@ VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT* pE

DispatchExSecondPass(&exInfo);

GCPROTECT_END();
GCPROTECT_END();

UNREACHABLE();
Expand Down Expand Up @@ -1674,7 +1674,9 @@ VOID DECLSPEC_NORETURN DispatchRethrownManagedException(CONTEXT* pExceptionConte

ExInfo exInfo(pThread, pActiveExInfo->m_ptrs.ExceptionRecord, pExceptionContext, ExKind::None);

GCPROTECT_BEGIN(exInfo.m_exception);
// m_exception is GC-reported via ExInfo chain scanning in ScanStackRoots.
// Do NOT also GCPROTECT it — reporting the same location twice corrupts
// the GC's relocation logic (see clr-code-guide.md §2.1.5).
UnmanagedCallersOnlyCaller rethrow(METHOD__EH__RH_RETHROW);

pThread->IncPreventAbort();
Expand All @@ -1683,8 +1685,6 @@ VOID DECLSPEC_NORETURN DispatchRethrownManagedException(CONTEXT* pExceptionConte
rethrow.InvokeDirect(pActiveExInfo, &exInfo);
DispatchExSecondPass(&exInfo);

GCPROTECT_END();

UNREACHABLE();
}

Expand Down Expand Up @@ -2922,7 +2922,7 @@ ExInfo::StackRange::StackRange()
void ExInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
{
// ExInfo is embedded so don't enum 'this'.
OBJECTHANDLE_EnumMemoryRegions(m_hThrowable);
OBJECTREF_EnumMemoryRegions(m_exception);
m_ptrs.ExceptionRecord.EnumMem();
m_ptrs.ContextRecord.EnumMem();
}
Expand Down Expand Up @@ -2973,7 +2973,7 @@ extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack e
_ASSERTE(pMD == codeInfo.GetMethodDesc());
#endif // _DEBUG

StackTraceInfo::AppendElement(pExInfo->m_hThrowable, ip, sp, pMD, &pExInfo->m_frameIter.m_crawl);
StackTraceInfo::AppendElement((OBJECTHANDLE)&pExInfo->m_exception, ip, sp, pMD, &pExInfo->m_frameIter.m_crawl);
Comment thread
max-charlamb marked this conversation as resolved.
}
}

Expand Down Expand Up @@ -3772,7 +3772,7 @@ CLR_BOOL SfiInitWorker(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BO
if (pMD != NULL)
{
GCX_COOP();
StackTraceInfo::AppendElement(pExInfo->m_hThrowable, 0, GetRegdisplaySP(pExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pExInfo->m_frameIter.m_crawl);
StackTraceInfo::AppendElement((OBJECTHANDLE)&pExInfo->m_exception, 0, GetRegdisplaySP(pExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pExInfo->m_frameIter.m_crawl);

#if defined(DEBUGGING_SUPPORTED)
if (NotifyDebuggerOfStub(pThread, pFrame))
Expand Down Expand Up @@ -3954,7 +3954,7 @@ CLR_BOOL SfiNextWorker(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR
void* callbackCxt = NULL;
Interop::ManagedToNativeExceptionCallback callback = Interop::GetPropagatingExceptionCallback(
&codeInfo,
pTopExInfo->m_hThrowable,
pTopExInfo->m_exception,
&callbackCxt);

if (callback != NULL)
Expand Down Expand Up @@ -4091,7 +4091,7 @@ CLR_BOOL SfiNextWorker(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR
if (pMD != NULL)
{
GCX_COOP();
StackTraceInfo::AppendElement(pTopExInfo->m_hThrowable, 0, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl);
StackTraceInfo::AppendElement((OBJECTHANDLE)&pTopExInfo->m_exception, 0, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl);

#if defined(DEBUGGING_SUPPORTED)
if (NotifyDebuggerOfStub(pThread, pFrame))
Expand Down
Loading
Loading