@@ -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,85 @@ 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
328
// Note: Do not merge this FCALL method with any other FailFast overloads.
291
329
// Watson uses the managed FailFast method with one String for crash dump bucketization.
292
- FCIMPL1 (VOID, SystemNative::FailFast, StringObject* refMessageUNSAFE )
330
+ extern " C " void QCALLTYPE Environment_FailFast (QCall::StackCrawlMarkHandle mark, QCall::StringHandleOnStack message )
293
331
{
294
- FCALL_CONTRACT ;
332
+ QCALL_CONTRACT ;
295
333
296
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE ;
334
+ BEGIN_QCALL ;
297
335
298
- HELPER_METHOD_FRAME_BEGIN_1 (refMessage );
336
+ GCX_COOP ( );
299
337
300
- // The HelperMethodFrame knows how to get the return address.
301
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ( );
338
+ STRINGREF refMessage = message. Get ();
339
+ GCPROTECT_BEGIN (refMessage );
302
340
303
341
// Call the actual worker to perform failfast
304
- GenericFailFast (refMessage, NULL , retaddr , NULL );
342
+ SystemNative:: GenericFailFast (refMessage, NULL , mark , NULL );
305
343
306
- HELPER_METHOD_FRAME_END ();
344
+ GCPROTECT_END ();
345
+
346
+ END_QCALL;
307
347
}
308
- FCIMPLEND
309
348
310
- FCIMPL2 (VOID, SystemNative::FailFastWithException, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE )
349
+ extern " C " void QCALLTYPE Environment_FailFastWithException (QCall::StackCrawlMarkHandle mark, QCall::StringHandleOnStack message, QCall::ObjectHandleOnStack exception )
311
350
{
312
- FCALL_CONTRACT ;
351
+ QCALL_CONTRACT ;
313
352
314
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE;
315
- EXCEPTIONREF refException = (EXCEPTIONREF)refExceptionUNSAFE;
353
+ BEGIN_QCALL;
316
354
317
- HELPER_METHOD_FRAME_BEGIN_2 (refMessage, refException);
355
+ GCX_COOP ();
356
+
357
+ struct
358
+ {
359
+ STRINGREF refMessage;
360
+ EXCEPTIONREF refException;
361
+ } gc;
362
+ gc.refMessage = message.Get ();
363
+ gc.refException = (EXCEPTIONREF)exception.Get ();
318
364
319
- // The HelperMethodFrame knows how to get the return address.
320
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ();
365
+ GCPROTECT_BEGIN (gc);
321
366
322
367
// Call the actual worker to perform failfast
323
- GenericFailFast (refMessage, refException, retaddr , NULL );
368
+ SystemNative:: GenericFailFast (gc. refMessage , gc. refException , mark , NULL );
324
369
325
- HELPER_METHOD_FRAME_END ();
370
+ GCPROTECT_END ();
371
+
372
+ END_QCALL;
326
373
}
327
- FCIMPLEND
328
374
329
- FCIMPL3 (VOID, SystemNative::FailFastWithExceptionAndSource, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE, StringObject* errorSourceUNSAFE )
375
+ extern " C " void QCALLTYPE Environment_FailFastWithExceptionAndSource (QCall::StackCrawlMarkHandle mark, QCall::StringHandleOnStack message, QCall::ObjectHandleOnStack exception, QCall::StringHandleOnStack errorSource )
330
376
{
331
- FCALL_CONTRACT ;
377
+ QCALL_CONTRACT ;
332
378
333
- STRINGREF refMessage = (STRINGREF)refMessageUNSAFE;
334
- EXCEPTIONREF refException = (EXCEPTIONREF)refExceptionUNSAFE;
335
- STRINGREF errorSource = (STRINGREF)errorSourceUNSAFE;
379
+ BEGIN_QCALL;
336
380
337
- HELPER_METHOD_FRAME_BEGIN_3 (refMessage, refException, errorSource);
381
+ GCX_COOP ();
382
+
383
+ struct
384
+ {
385
+ STRINGREF refMessage;
386
+ EXCEPTIONREF refException;
387
+ STRINGREF refErrorSource;
388
+ } gc;
389
+ gc.refMessage = message.Get ();
390
+ gc.refException = (EXCEPTIONREF)exception.Get ();
391
+ gc.refErrorSource = errorSource.Get ();
338
392
339
- // The HelperMethodFrame knows how to get the return address.
340
- UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS ();
393
+ GCPROTECT_BEGIN (gc);
341
394
342
395
// Call the actual worker to perform failfast
343
- GenericFailFast (refMessage, refException, retaddr, errorSource );
396
+ SystemNative:: GenericFailFast (gc. refMessage , gc. refException , mark, gc. refErrorSource );
344
397
345
- HELPER_METHOD_FRAME_END ();
398
+ GCPROTECT_END ();
399
+
400
+ END_QCALL;
346
401
}
347
- FCIMPLEND
348
402
349
403
FCIMPL0 (FC_BOOL_RET, SystemNative::IsServerGC)
350
404
{
0 commit comments