@@ -133,6 +133,38 @@ extern "C" INT32 QCALLTYPE Environment_GetProcessorCount()
133
133
return processorCount;
134
134
}
135
135
136
+ struct FindFailFastCallerStruct {
137
+ StackCrawlMark* pStackMark;
138
+ UINT_PTR retAddress;
139
+ };
140
+
141
+ // This method is called by the GetMethod function and will crawl backward
142
+ // up the stack for integer methods.
143
+ static StackWalkAction FindFailFastCallerCallback (CrawlFrame* frame, VOID* data) {
144
+ CONTRACTL
145
+ {
146
+ NOTHROW;
147
+ GC_NOTRIGGER;
148
+ MODE_ANY;
149
+ }
150
+ CONTRACTL_END;
151
+
152
+ FindFailFastCallerStruct* pFindCaller = (FindFailFastCallerStruct*) data;
153
+
154
+ // The check here is between the address of a local variable
155
+ // (the stack mark) and a pointer to the EIP for a frame
156
+ // (which is actually the pointer to the return address to the
157
+ // function from the previous frame). So we'll actually notice
158
+ // which frame the stack mark was in one frame later. This is
159
+ // fine since we only implement LookForMyCaller.
160
+ _ASSERTE (*pFindCaller->pStackMark == LookForMyCaller);
161
+ if (!frame->IsInCalleesFrames (pFindCaller->pStackMark ))
162
+ return SWA_CONTINUE;
163
+
164
+ pFindCaller->retAddress = GetControlPC (frame->GetRegisterSet ());
165
+ return SWA_ABORT;
166
+ }
167
+
136
168
// FailFast is supported in BCL.small as internal to support failing fast in places where EEE used to be thrown.
137
169
//
138
170
// Static message buffer used by SystemNative::FailFast to avoid reliance on a
@@ -143,9 +175,10 @@ WCHAR *g_pFailFastBuffer = g_szFailFastBuffer;
143
175
144
176
#define FAIL_FAST_STATIC_BUFFER_LENGTH (sizeof (g_szFailFastBuffer) / sizeof (WCHAR))
145
177
146
- // This is the common code for FailFast processing that is wrapped by the two
178
+
179
+ // This is the common code for FailFast processing that is wrapped by the
147
180
// FailFast FCalls below.
148
- void SystemNative::GenericFailFast (STRINGREF refMesgString, EXCEPTIONREF refExceptionForWatsonBucketing, UINT_PTR retAddress , STRINGREF refErrorSourceString)
181
+ void SystemNative::GenericFailFast (STRINGREF refMesgString, EXCEPTIONREF refExceptionForWatsonBucketing, StackCrawlMark* stackMark , STRINGREF refErrorSourceString)
149
182
{
150
183
CONTRACTL
151
184
{
@@ -166,6 +199,11 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce
166
199
167
200
GCPROTECT_BEGIN (gc);
168
201
202
+ FindFailFastCallerStruct findCallerData;
203
+ findCallerData.pStackMark = stackMark;
204
+ findCallerData.retAddress = 0 ;
205
+ StackWalkFunctions (GetThread (), FindFailFastCallerCallback, &findCallerData);
206
+
169
207
// Managed code injected FailFast maps onto the unmanaged version
170
208
// (EEPolicy::HandleFatalError) in the following manner: the exit code is
171
209
// always set to COR_E_FAILFAST and the address passed (usually a failing
@@ -267,7 +305,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce
267
305
{
268
306
PTR_EHWatsonBucketTracker pUEWatsonBucketTracker = pThread->GetExceptionState ()->GetUEWatsonBucketTracker ();
269
307
_ASSERTE (pUEWatsonBucketTracker != NULL );
270
- pUEWatsonBucketTracker->SaveIpForWatsonBucket (retAddress);
308
+ pUEWatsonBucketTracker->SaveIpForWatsonBucket (findCallerData. retAddress );
271
309
pUEWatsonBucketTracker->CaptureUnhandledInfoForWatson (TypeOfReportedError::FatalError, pThread, NULL );
272
310
if (pUEWatsonBucketTracker->RetrieveWatsonBuckets () == NULL )
273
311
{
@@ -282,69 +320,28 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce
282
320
if (gc.refExceptionForWatsonBucketing != NULL )
283
321
pThread->SetLastThrownObject (gc.refExceptionForWatsonBucketing );
284
322
285
- EEPolicy::HandleFatalError (COR_E_FAILFAST, retAddress, pszMessage, NULL , errorSourceString, argExceptionString);
323
+ EEPolicy::HandleFatalError (COR_E_FAILFAST, findCallerData. retAddress , pszMessage, NULL , errorSourceString, argExceptionString);
286
324
287
325
GCPROTECT_END ();
288
326
}
289
327
290
- // Note: Do not merge this FCALL method with any other FailFast overloads.
291
- // Watson uses the managed FailFast method with one String for crash dump bucketization.
292
- FCIMPL1 (VOID, SystemNative::FailFast, StringObject* refMessageUNSAFE)
293
- {
294
- FCALL_CONTRACT;
295
-
296
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE;
297
-
298
- HELPER_METHOD_FRAME_BEGIN_1 (refMessage);
299
-
300
- // The HelperMethodFrame knows how to get the return address.
301
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ();
302
-
303
- // Call the actual worker to perform failfast
304
- GenericFailFast (refMessage, NULL , retaddr, NULL );
305
-
306
- HELPER_METHOD_FRAME_END ();
307
- }
308
- FCIMPLEND
309
-
310
- FCIMPL2 (VOID, SystemNative::FailFastWithException, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE)
311
- {
312
- FCALL_CONTRACT;
313
-
314
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE;
315
- EXCEPTIONREF refException = (EXCEPTIONREF)refExceptionUNSAFE;
316
-
317
- HELPER_METHOD_FRAME_BEGIN_2 (refMessage, refException);
318
-
319
- // The HelperMethodFrame knows how to get the return address.
320
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ();
321
-
322
- // Call the actual worker to perform failfast
323
- GenericFailFast (refMessage, refException, retaddr, NULL );
324
-
325
- HELPER_METHOD_FRAME_END ();
326
- }
327
- FCIMPLEND
328
-
329
- FCIMPL3 (VOID, SystemNative::FailFastWithExceptionAndSource, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE, StringObject* errorSourceUNSAFE)
328
+ extern " C" void QCALLTYPE Environment_FailFast (QCall::StackCrawlMarkHandle mark, QCall::StringHandleOnStack message, QCall::ObjectHandleOnStack exception, QCall::StringHandleOnStack errorSource)
330
329
{
331
- FCALL_CONTRACT;
332
-
333
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE;
334
- EXCEPTIONREF refException = (EXCEPTIONREF)refExceptionUNSAFE;
335
- STRINGREF errorSource = (STRINGREF)errorSourceUNSAFE;
330
+ QCALL_CONTRACT;
336
331
337
- HELPER_METHOD_FRAME_BEGIN_3 (refMessage, refException, errorSource) ;
332
+ BEGIN_QCALL ;
338
333
339
- // The HelperMethodFrame knows how to get the return address.
340
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ();
334
+ GCX_COOP ();
335
+
336
+ STRINGREF refMessage = message.Get ();
337
+ EXCEPTIONREF refException = (EXCEPTIONREF)exception.Get ();
338
+ STRINGREF refErrorSource = errorSource.Get ();
341
339
342
340
// Call the actual worker to perform failfast
343
- GenericFailFast (refMessage, refException, retaddr, errorSource );
341
+ SystemNative:: GenericFailFast (refMessage, refException, mark, refErrorSource );
344
342
345
- HELPER_METHOD_FRAME_END () ;
343
+ END_QCALL ;
346
344
}
347
- FCIMPLEND
348
345
349
346
FCIMPL0 (FC_BOOL_RET, SystemNative::IsServerGC)
350
347
{
0 commit comments