Skip to content

Commit 22068a8

Browse files
authored
Refactor exception trackers (#96505)
* Refactor exception trackers to use common base class While fixing few loose ends related to debug code and the new exception handling, I have found that they were mostly caused by missing conditional code for the new EH ExInfo where only the ExceptionTracker was handled. So, I have decided to refactor the code a bit by extracting a base struct containing the members that are common to ExInfo and ExceptionTracker and that are used by the debugging related code. There was also a bit of unused code that I have found while making this change, so I have removed it. I obviously had to update the offsets that the managed code references in the ExInfo. Due to some debug only members of some of the structures used as ExInfo members, the offsets were initially different for Windows/Unix and Release/Debug builds. To prevent having to have separate offset values, I have added a little conditional padding to the ExInfo and modified the ExceptionFlags structure by removing the `m_debugFlags` that were holding only a single flag that can easily fit into the m_flags member and there is no reason for having it separate. * Unify m_pExInfo and m_pCurrentTracker * Fix a missing exclusion for new EH
1 parent ab8c3b8 commit 22068a8

File tree

15 files changed

+333
-589
lines changed

15 files changed

+333
-589
lines changed

src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,23 +150,23 @@ class AsmOffsets
150150
public const int SIZEOF__EHEnum = 0x20;
151151
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x228;
152152
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
153-
public const int OFFSETOF__ExInfo__m_pExContext = 8;
154-
public const int OFFSETOF__ExInfo__m_exception = 0x10;
155-
public const int OFFSETOF__ExInfo__m_kind = 0x18;
156-
public const int OFFSETOF__ExInfo__m_passNumber = 0x19;
157-
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x1c;
158-
public const int OFFSETOF__ExInfo__m_frameIter = 0x20;
153+
public const int OFFSETOF__ExInfo__m_pExContext = 0xc0;
154+
public const int OFFSETOF__ExInfo__m_exception = 0xc8;
155+
public const int OFFSETOF__ExInfo__m_kind = 0xd0;
156+
public const int OFFSETOF__ExInfo__m_passNumber = 0xd1;
157+
public const int OFFSETOF__ExInfo__m_idxCurClause = 0xd4;
158+
public const int OFFSETOF__ExInfo__m_frameIter = 0xe0;
159159
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
160160
#else // TARGET_64BIT
161161
public const int SIZEOF__EHEnum = 0x10;
162162
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x218;
163163
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
164-
public const int OFFSETOF__ExInfo__m_pExContext = 4;
165-
public const int OFFSETOF__ExInfo__m_exception = 8;
166-
public const int OFFSETOF__ExInfo__m_kind = 0xC;
167-
public const int OFFSETOF__ExInfo__m_passNumber = 0xD;
168-
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x10;
169-
public const int OFFSETOF__ExInfo__m_frameIter = 0x18;
164+
public const int OFFSETOF__ExInfo__m_pExContext = 0x70;
165+
public const int OFFSETOF__ExInfo__m_exception = 0x74;
166+
public const int OFFSETOF__ExInfo__m_kind = 0x78;
167+
public const int OFFSETOF__ExInfo__m_passNumber = 0x79;
168+
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x7C;
169+
public const int OFFSETOF__ExInfo__m_frameIter = 0x80;
170170
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
171171
#endif // TARGET_64BIT
172172

@@ -200,7 +200,7 @@ class AsmOffsets
200200
static_assert_no_msg(offsetof(StackFrameIterator, m_isRuntimeWrappedExceptions) == OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions);
201201
static_assert_no_msg(offsetof(StackFrameIterator, m_AdjustedControlPC) == OFFSETOF__StackFrameIterator__m_AdjustedControlPC);
202202
static_assert_no_msg(sizeof(ExtendedEHClauseEnumerator) == AsmOffsets::SIZEOF__EHEnum);
203-
static_assert_no_msg(offsetof(ExInfo, m_pPrevExInfo) == OFFSETOF__ExInfo__m_pPrevExInfo);
203+
static_assert_no_msg(offsetof(ExInfo, m_pPrevNestedInfo) == OFFSETOF__ExInfo__m_pPrevExInfo);
204204
static_assert_no_msg(offsetof(ExInfo, m_pExContext) == OFFSETOF__ExInfo__m_pExContext);
205205
static_assert_no_msg(offsetof(ExInfo, m_exception) == OFFSETOF__ExInfo__m_exception);
206206
static_assert_no_msg(offsetof(ExInfo, m_kind) == OFFSETOF__ExInfo__m_kind);

src/coreclr/debug/daccess/dacimpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3393,7 +3393,7 @@ class ClrDataFrame : public IXCLRDataFrame,
33933393
//----------------------------------------------------------------------------
33943394

33953395
#ifdef FEATURE_EH_FUNCLETS
3396-
typedef ExceptionTracker ClrDataExStateType;
3396+
typedef ExceptionTrackerBase ClrDataExStateType;
33973397
#else // FEATURE_EH_FUNCLETS
33983398
typedef ExInfo ClrDataExStateType;
33993399
#endif // FEATURE_EH_FUNCLETS

src/coreclr/debug/daccess/request.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3148,7 +3148,7 @@ ClrDataAccess::GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS
31483148
SOSDacEnter();
31493149

31503150
#ifdef FEATURE_EH_FUNCLETS
3151-
ExceptionTracker *pExData = PTR_ExceptionTracker(TO_TADDR(exception));
3151+
ExceptionTrackerBase *pExData = PTR_ExceptionTrackerBase(TO_TADDR(exception));
31523152
#else
31533153
ExInfo *pExData = PTR_ExInfo(TO_TADDR(exception));
31543154
#endif // FEATURE_EH_FUNCLETS

src/coreclr/vm/clrex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ void CLRException::HandlerState::SetupCatch(INDEBUG_COMMA(_In_z_ const char * sz
856856
}
857857

858858
#ifdef FEATURE_EH_FUNCLETS
859-
if (!DidCatchCxx())
859+
if (!DidCatchCxx() && !g_isNewExceptionHandlingEnabled)
860860
{
861861
// this must be done after the second pass has run, it does not
862862
// reference anything on the stack, so it is safe to run in an

src/coreclr/vm/eventtrace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2764,7 +2764,7 @@ VOID ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept
27642764
#ifndef FEATURE_EH_FUNCLETS
27652765
PTR_ExInfo pExInfo = NULL;
27662766
#else
2767-
PTR_ExceptionTracker pExInfo = NULL;
2767+
PTR_ExceptionTrackerBase pExInfo = NULL;
27682768
#endif //!FEATURE_EH_FUNCLETS
27692769
pExInfo = pExState->GetCurrentExceptionTracker();
27702770
_ASSERTE(pExInfo != NULL);

src/coreclr/vm/excep.cpp

Lines changed: 13 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -8659,11 +8659,7 @@ void SetupWatsonBucketsForUEF(BOOL fUseLastThrownObject)
86598659
// But if the tracker exists, simply copy the bucket details to the UE Watson Bucket
86608660
// tracker for use by the "WatsonLastChance" path.
86618661
BOOL fDoWeHaveWatsonBuckets = FALSE;
8662-
if ((pExState->GetCurrentExceptionTracker() != NULL)
8663-
#ifdef FEATURE_EH_FUNCLETS
8664-
|| (pExState->GetCurrentExInfo() != NULL)
8665-
#endif // FEATURE_EH_FUNCLETS
8666-
)
8662+
if (pExState->GetCurrentExceptionTracker() != NULL)
86678663
{
86688664
// Check the exception state if we have Watson bucket details
86698665
fDoWeHaveWatsonBuckets = pExState->GetFlags()->GotWatsonBucketDetails();
@@ -8850,8 +8846,8 @@ BOOL IsThrowableThreadAbortException(OBJECTREF oThrowable)
88508846
// If not specified, this will default to the current exception tracker active
88518847
// on the thread.
88528848
#if defined(FEATURE_EH_FUNCLETS)
8853-
PTR_ExceptionTracker GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable,
8854-
PTR_ExceptionTracker pStartingEHTracker)
8849+
PTR_ExceptionTrackerBase GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable,
8850+
PTR_ExceptionTrackerBase pStartingEHTracker)
88558851
#elif TARGET_X86
88568852
PTR_ExInfo GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable,
88578853
PTR_ExInfo pStartingEHTracker)
@@ -8873,7 +8869,7 @@ PTR_ExInfo GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable,
88738869

88748870
// Get the reference to the current exception tracker
88758871
#if defined(FEATURE_EH_FUNCLETS)
8876-
PTR_ExceptionTracker pEHTracker = (pStartingEHTracker != NULL) ? pStartingEHTracker : GetThread()->GetExceptionState()->GetCurrentExceptionTracker();
8872+
PTR_ExceptionTrackerBase pEHTracker = (pStartingEHTracker != NULL) ? pStartingEHTracker : GetThread()->GetExceptionState()->GetCurrentExceptionTracker();
88778873
#elif TARGET_X86
88788874
PTR_ExInfo pEHTracker = (pStartingEHTracker != NULL) ? pStartingEHTracker : GetThread()->GetExceptionState()->GetCurrentExceptionTracker();
88798875
#else // !(HOST_64BIT || TARGET_X86)
@@ -8951,8 +8947,8 @@ PTR_EHWatsonBucketTracker GetWatsonBucketTrackerForPreallocatedException(OBJECTR
89518947
// Find the reference to the exception tracker corresponding to the preallocated exception,
89528948
// starting the search from the current exception tracker (2nd arg of NULL specifies that).
89538949
#if defined(FEATURE_EH_FUNCLETS)
8954-
PTR_ExceptionTracker pEHTracker = NULL;
8955-
PTR_ExceptionTracker pPreviousEHTracker = NULL;
8950+
PTR_ExceptionTrackerBase pEHTracker = NULL;
8951+
PTR_ExceptionTrackerBase pPreviousEHTracker = NULL;
89568952

89578953
#elif TARGET_X86
89588954
PTR_ExInfo pEHTracker = NULL;
@@ -9360,17 +9356,7 @@ void SetupInitialThrowBucketDetails(UINT_PTR adjustedIp)
93609356
// being thrown, then get them.
93619357
ThreadExceptionState *pExState = pThread->GetExceptionState();
93629358

9363-
#ifdef FEATURE_EH_FUNCLETS
9364-
// Ensure that the exception tracker exists
9365-
if (g_isNewExceptionHandlingEnabled)
9366-
{
9367-
_ASSERTE(pExState->GetCurrentExInfo() != NULL);
9368-
}
9369-
else
9370-
#endif // FEATURE_EH_FUNCLETS
9371-
{
9372-
_ASSERTE(pExState->GetCurrentExceptionTracker() != NULL);
9373-
}
9359+
_ASSERTE(pExState->GetCurrentExceptionTracker() != NULL);
93749360

93759361
// Switch to COOP mode
93769362
GCX_COOP();
@@ -9395,17 +9381,7 @@ void SetupInitialThrowBucketDetails(UINT_PTR adjustedIp)
93959381

93969382
// Get the WatsonBucketTracker for the current exception
93979383
PTR_EHWatsonBucketTracker pWatsonBucketTracker;
9398-
#ifdef FEATURE_EH_FUNCLETS
9399-
if (g_isNewExceptionHandlingEnabled)
9400-
{
9401-
pWatsonBucketTracker = pExState->GetCurrentExInfo()->GetWatsonBucketTracker();
9402-
9403-
}
9404-
else
9405-
#endif // FEATURE_EH_FUNCLETS
9406-
{
9407-
pWatsonBucketTracker = pExState->GetCurrentExceptionTracker()->GetWatsonBucketTracker();
9408-
}
9384+
pWatsonBucketTracker = pExState->GetCurrentExceptionTracker()->GetWatsonBucketTracker();
94099385

94109386
// Get the innermost exception object (if any)
94119387
gc.oInnerMostExceptionThrowable = ((EXCEPTIONREF)gc.oCurrentThrowable)->GetBaseException();
@@ -10537,56 +10513,6 @@ void EHWatsonBucketTracker::CaptureUnhandledInfoForWatson(TypeOfReportedError to
1053710513
}
1053810514
#endif // !TARGET_UNIX
1053910515

10540-
// Given a throwable, this function will attempt to find an active EH tracker corresponding to it.
10541-
// If none found, it will return NULL
10542-
#ifdef FEATURE_EH_FUNCLETS
10543-
PTR_ExceptionTracker GetEHTrackerForException(OBJECTREF oThrowable, PTR_ExceptionTracker pStartingEHTracker)
10544-
#elif TARGET_X86
10545-
PTR_ExInfo GetEHTrackerForException(OBJECTREF oThrowable, PTR_ExInfo pStartingEHTracker)
10546-
#else
10547-
#error Unsupported platform
10548-
#endif
10549-
{
10550-
CONTRACTL
10551-
{
10552-
GC_NOTRIGGER;
10553-
MODE_COOPERATIVE;
10554-
NOTHROW;
10555-
PRECONDITION(GetThreadNULLOk() != NULL);
10556-
PRECONDITION(oThrowable != NULL);
10557-
}
10558-
CONTRACTL_END;
10559-
10560-
// Get the reference to the exception tracker to start with. If one has been provided to us,
10561-
// then use it. Otherwise, start from the current one.
10562-
#ifdef FEATURE_EH_FUNCLETS
10563-
PTR_ExceptionTracker pEHTracker = (pStartingEHTracker != NULL) ? pStartingEHTracker : GetThread()->GetExceptionState()->GetCurrentExceptionTracker();
10564-
#elif TARGET_X86
10565-
PTR_ExInfo pEHTracker = (pStartingEHTracker != NULL) ? pStartingEHTracker : GetThread()->GetExceptionState()->GetCurrentExceptionTracker();
10566-
#else
10567-
#error Unsupported platform
10568-
#endif
10569-
10570-
BOOL fFoundTracker = FALSE;
10571-
10572-
// Start walking the list to find the tracker corresponding
10573-
// to the exception object.
10574-
while (pEHTracker != NULL)
10575-
{
10576-
if (pEHTracker->GetThrowable() == oThrowable)
10577-
{
10578-
// found the tracker - break out.
10579-
fFoundTracker = TRUE;
10580-
break;
10581-
}
10582-
10583-
// move to the previous tracker...
10584-
pEHTracker = pEHTracker->GetPreviousExceptionTracker();
10585-
}
10586-
10587-
return fFoundTracker ? pEHTracker : NULL;
10588-
}
10589-
1059010516
// Given an exception code, this method returns a BOOL to indicate if the
1059110517
// code belongs to a corrupting exception or not.
1059210518
BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, OBJECTREF throwable)
@@ -10914,18 +10840,8 @@ void ExceptionNotifications::DeliverFirstChanceNotification()
1091410840
// processing for subsequent frames on the stack since FirstChance notification
1091510841
// will be delivered only when the exception is first thrown/rethrown.
1091610842
ThreadExceptionState *pCurTES = GetThread()->GetExceptionState();
10917-
#ifdef FEATURE_EH_FUNCLETS
10918-
if (g_isNewExceptionHandlingEnabled)
10919-
{
10920-
_ASSERTE(pCurTES->GetCurrentExInfo());
10921-
_ASSERTE(!(pCurTES->GetCurrentExInfo()->DeliveredFirstChanceNotification()));
10922-
}
10923-
else
10924-
#endif // FEATURE_EH_FUNCLETS
10925-
{
10926-
_ASSERTE(pCurTES->GetCurrentExceptionTracker());
10927-
_ASSERTE(!(pCurTES->GetCurrentExceptionTracker()->DeliveredFirstChanceNotification()));
10928-
}
10843+
_ASSERTE(pCurTES->GetCurrentExceptionTracker());
10844+
_ASSERTE(!(pCurTES->GetCurrentExceptionTracker()->DeliveredFirstChanceNotification()));
1092910845
{
1093010846
GCX_COOP();
1093110847
if (ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(FirstChanceExceptionHandler))
@@ -10941,18 +10857,8 @@ void ExceptionNotifications::DeliverFirstChanceNotification()
1094110857

1094210858
}
1094310859

10944-
#ifdef FEATURE_EH_FUNCLETS
10945-
if (g_isNewExceptionHandlingEnabled)
10946-
{
10947-
// Mark the exception info as having delivered the first chance notification
10948-
pCurTES->GetCurrentExInfo()->SetFirstChanceNotificationStatus(TRUE);
10949-
}
10950-
else
10951-
#endif // FEATURE_EH_FUNCLETS
10952-
{
10953-
// Mark the exception tracker as having delivered the first chance notification
10954-
pCurTES->GetCurrentExceptionTracker()->SetFirstChanceNotificationStatus(TRUE);
10955-
}
10860+
// Mark the exception tracker as having delivered the first chance notification
10861+
pCurTES->GetCurrentExceptionTracker()->SetFirstChanceNotificationStatus(TRUE);
1095610862
}
1095710863
}
1095810864

@@ -11044,7 +10950,7 @@ void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCur
1104410950
}
1104510951
#else // !FEATURE_EH_FUNCLETS
1104610952
// Get the active exception tracker
11047-
PTR_ExceptionTracker pCurEHTracker = pThread->GetExceptionState()->GetCurrentExceptionTracker();
10953+
PTR_ExceptionTracker pCurEHTracker = (PTR_ExceptionTracker)pThread->GetExceptionState()->GetCurrentExceptionTracker();
1104810954
_ASSERTE(pCurEHTracker != NULL);
1104910955

1105010956
// We will check if thread abort state needs to be reset only for the case of exception caught in

0 commit comments

Comments
 (0)