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// Contract.h
6//
7
8// ! I am the owner for issues in the contract *infrastructure*, not for every
9// ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine
10// ! CONTRACT_VIOLATION, you will become the new owner of this file.
11//--------------------------------------------------------------------------------
12// CONTRACTS - User Reference
13//
14// A CONTRACT is a container for a set of checked declarations about a
15// function. Besides giving developers a "laundry list" of checks to
16// make checking more complete, contracts compile these checks
17// as hidden annotations into the checked executable that our static scanner
18// uses to detect violations automatically.
19//
20// Contracts can be dynamic or static. Dynamic contracts perform runtime checks
21// as well as being visible to the static scanner. Static contracts generate no
22// runtime code but are still visible to the scanner. Dynamic contracts are
23// preferred unless perf or other considerations preclude them.
24//
25// The following annotations can appear in contracts:
26//
27//
28// THROWS an exception might be thrown out of the function
29// -or- NOTHROW an exception will NOT be thrown out of the function
30//
31//
32//
33// INJECT_FAULT(statement) function might require its caller to handle an OOM
34// -or- FAULT_FORBID function will NOT require its caller to handle an OOM
35//
36//
37//
38// GC_TRIGGERS the function can trigger a GC
39// -or- GC_NOTRIGGER the function will never trigger a GC provided its
40// called in coop mode.
41//
42//
43// MODE_COOPERATIVE the function requires Cooperative GC mode on entry
44// -or- MODE_PREEMPTIVE the function requires Preemptive GC mode on entry
45// -or- MODE_ANY the function can be entered in either mode
46//
47// LOADS_TYPE(level) the function promises not to load any types beyond "level"
48//
49// SO_INTOLERANT the function cannot tolerate an SO at any point and must run behind an
50// an SO probe via BEGIN_SO_INTOLERANT_XXX. This is the default. We want most
51// of our code to run behind an SO probe. The only time you need to explicitly
52// mark something as SO_INTOLERANT is if the static analysis tool incorrectly
53// flags it as an entry point.
54// -or- SO_TOLERANT the function can tolerate an SO. It either does not update any global state
55// that needs to be cleaned up should a random SO occur, or it protects those
56// updates behind an SO probe.
57// -or- SO_NOT_MAINLINE the function is not hardened to SO and should never run on a managed thread
58// where we need to be hardened to SO. You can use this for functions that run
59// only for ngen or Win9X etc.
60//
61// CAN_TAKE_LOCK the function has a code path that takes a lock
62// _or_ (CAN_TAKE_LOCK and CANNOT_RETAKE_LOCK)
63// the function has a code path that takes a lock, but never tries to reenter
64// locks held at the time this function was called.
65// -or- CANNOT_TAKE_LOCK the function will never allow a lock to be taken
66// -or- the default is WRAPPER(CAN_TAKE_LOCK). i.e., if any callees take locks,
67// then it's ok for this function to as well. If LIMITED_METHOD_CONTRACT is specified,
68// however, then CANNOT_TAKE_LOCK is assumed.
69//
70// EE_THREAD_NOT_REQUIRED the function does not assume an EE Thread object is available in TLS.
71// Either GetThread() is never called, or any code path that requires a Thread
72// has another code path that deals with the absence of a Thread. Any call to
73// to GetThread() must be bracketed with BEGIN_GETTHREAD_ALLOWED /
74// END_GETTHREAD_ALLOWED to avoid bogus asserts (the short-form
75// GetThreadNULLOk() may be used as well). However, this is only allowed if visual
76// inspection of the call site makes it patently obvious that the function deals
77// appropriately with the GetThread() == NULL case.
78// -or- EE_THREAD_REQUIRED the function requires an EE Thread object in TLS (i.e., GetThread() != NULL)
79// If this contract is used, we will ASSERT on entry to the function that
80// GetThread() != NULL.
81// -or- the default is DISABLED(EE_THREAD_REQUIRED). i.e., we do not assert
82// GetThread() != NULL on entry to the function and do not assert on any
83// unprotected uses of GetThread().
84// See code:GetThreadGenericFullCheck for info on how these
85// contracts are enforced.
86//
87// SUPPORTS_DAC The function has been written to be callable from out-of-process using DAC.
88// In builds where DACCESS_COMPILE is defined, such functions can only call
89// other such functions (and a few primitives like new). Functions that support
90// DAC must be carefully written to conform to the rules in daccess.h.
91//
92// SUPPORTS_DAC_HOST_ONLY The function and its call graph has been written to be callable from out of process
93// using DAC, but it differs from SUPPORTS_DAC in that these functions won't perform
94// any marshalling. Because it does no marshalling, SUPPORTS_DAC_HOST_ONLY functions
95// and their call graph won't be checked by DacCop. This should only be used by utility
96// functions which will never marshal anything.
97//
98// PRECONDITION(X) - generic CHECK or BOOL expression which should be true
99// on function entry
100//
101// POSTCONDITION(X) - generic CHECK or BOOL expression which should be true
102// on function entry. Note that variable RETVAL will be
103// available for use in the expression.
104//
105//
106// INSTANCE_CHECK - equivalent of:
107// PRECONDITION(CheckPointer(this));
108// POSTCONDITION(CheckInvariant(this));
109// INSTANCE_CHECK_NULL - equivalent of:
110// PRECONDITION(CheckPointer(this, NULL_OK));
111// POSTCONDITION(CheckInvariant(this, NULL_OK));
112// CONSTRUCTOR_CHECK - equivalent of:
113// POSTCONDITION(CheckPointer(this));
114// DESTRUCTOR_CHECK - equivalent of:
115// PRECONDITION(CheckPointer(this));
116//
117//
118//
119//
120// Contracts come in the following flavors:
121//
122// Dynamic:
123// CONTRACTL the standard version used for all dynamic contracts
124// except those including postconditions.
125//
126// CONTRACT(rettype) an uglier version of CONTRACTL that's unfortunately
127// needed to support postconditions. You must specify
128// the correct return type and it cannot be "void."
129// (Use CONTRACT_VOID instead) You must use the
130// RETURN macro rather than the "return" keyword.
131//
132// CONTRACT_VOID you can't supply "void" to a CONTRACT - use this
133// instead.
134//
135// Static:
136// LIMITED_METHOD_CONTRACT
137// A static contract equivalent to NOTHROW/GC_NOTRIGGER/FORBID_FAULT/MODE_ANY.
138// Use only for trivial functions that call only functions with LIMITED_METHOD_CONTRACTs
139// (as long as there is no cycle that may introduce infinite recursion).
140//
141// STATIC_CONTRACT_THROWS
142// STATIC_CONTRACT_NOTHROW
143// STATIC_CONTRACT_GC_TRIGGERS
144// STATIC_CONTRACT_GCNOTRIGGER
145// STATIC_CONTRACT_FAULT
146// STATIC_CONTRACT_FORBID_FAULT
147// STATIC_CONTRACT_SO_INTOLERANT
148// STATIC_CONTRACT_SO_TOLERANT
149// STATIC_CONTRACT_SO_NOT_MAINLINE
150// use to implement statically checkable contracts
151// when runtime contracts cannot be used.
152//
153//
154// WRAPPER(annotation)
155//
156// When a function does not explicitly caused a condition, use the WRAPPER macro around
157// the declaration. This implies that the function is dependent on the functions it calls
158// for its behaviour, and guarantees nothing.
159//
160//
161// CONTRACT_VIOLATION(violationmask):
162//
163// A bandaid used to suppress contract assertions. A contract violation
164// is always a bug and you're expected to remove it before shipping.
165// If a violation cannot be fixed immediately, however, it's better
166// to use this on the offending callsite than to disable a contract entirely.
167//
168// The violationmask can be one or more of the following OR'd together.
169//
170// ThrowsViolation
171// GCViolation
172// ModeViolation
173// FaultViolation
174// SOToleranceViolation
175// FaultNotFatal
176// HostViolation
177// LoadsTypeViolation
178// TakesLockViolation
179//
180// The associated assertion will be suppressed until you leave the scope
181// containing the CONTRACT_VIOLATION. Note, however, that any called
182// function that redeclares the associated annotation reinstates
183// the assert for the scope of *its* call. This prevents a CONTRACT_VIOLATION
184// placed at the root of a calltree from decimating our entire protection.
185//
186//
187// PERMANENT_CONTRACT_VIOLATION(violationmask, permanentContractViolationReason):
188//
189// Like a CONTRACT_VIOLATION but also indicates that the violation was a deliberate decision
190// and we don't plan on removing the violation in the next release. The reason
191// for the violation should be given as the second parameter to the macro. Reasons
192// are currently for documentation purposes only and do not have an effect on the binary.
193// Valid values are listed below in the definition of PermanentContractViolationReason.
194//
195//
196// CONDITIONAL_CONTRACT_VIOLATION(violationmask, condition):
197//
198// Similar to CONTRACT_VIOLATION, but only suppresses the contract if the
199// condition evaluates to non-zero. The need for this macro should be very
200// rare, but it can be useful if a contract should be suppressed based on a
201// condition known only at run-time. For example, if a particular test causes
202// call sequences never expected by real scenarios, you may want to suppress
203// resulting violations, but only when that test is run.
204//
205// WRAPPER_NO_CONTRACT
206//
207// A do-nothing contract used by functions that trivially wrap another.
208//
209//
210// "LEGACY" stuff - these features have been mostly superceded by better solutions
211// so their use should be discouraged.
212//
213//
214// DISABLED(annotation)
215//
216// Indicates that a condition is supposed to be checked but is being suppressed
217// due to some temporary bug. The more surgical CONTRACT_VIOLATION is
218// preferred over DISABLED.
219//
220// UNCHECKED(annotation)
221//
222// Indicates that a condition is supposed to be checked but is being suppressed
223// due for perf reasons. Use STATIC_CONTRACT over this.
224//
225//
226// Default values:
227// If you don't specify certain annotaions, you get defaults.
228// - THROWS/NOTHROW defaults to THROWS
229// - GCTRIGGERS/GCNOTRIGGER defaults to GCTRIGGERS within the VM directory
230// and to no check otherwise
231// - INJECT/FORBID_FAULT defaults to no check
232// - MODE defaults to MODE_ANY
233//
234// The problem is that defaults don't work well with static contracts.
235// The scanner will always treat a missing annotation as DISABLED.
236// New code should not rely on defaults. Explicitly state your invariants.
237//
238//
239//--------------------------------------------------------------------------------
240
241
242
243
244#ifndef CONTRACT_H_
245#define CONTRACT_H_
246
247#ifdef _MSC_VER
248#pragma warning(disable:4189) //local variable is initialized but not referenced
249#endif
250
251
252// We only enable contracts in _DEBUG builds
253#if defined(_DEBUG) && !defined(DISABLE_CONTRACTS)
254#define ENABLE_CONTRACTS_DATA
255#endif
256
257// Also, we won't enable contracts if this is a DAC build.
258// @ARMTODO: Disable for ARM for now, contracts slow down the debug build far too much
259#if defined(ENABLE_CONTRACTS_DATA) && !defined(DACCESS_COMPILE) && !defined(CROSS_COMPILE) && !defined(_TARGET_ARM_)
260#define ENABLE_CONTRACTS
261#endif
262
263// Finally, only define the implementaiton parts of contracts if this isn't a DAC build.
264#if defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS)
265#define ENABLE_CONTRACTS_IMPL
266#endif
267
268#include "specstrings.h"
269#include "clrtypes.h"
270#include "malloc.h"
271#include "check.h"
272#include "debugreturn.h"
273#include "staticcontract.h"
274
275#ifdef ENABLE_CONTRACTS_DATA
276
277#include "eh.h"
278
279// We chain these onto a stack to give us a stack trace of contract assertions (useful
280// when the bug report doesn't contain valid symbols)
281
282struct ContractStackRecord
283{
284 ContractStackRecord *m_pNext;
285 const char *m_szFunction;
286 const char *m_szFile;
287 int m_lineNum;
288 UINT m_testmask; // Bitmask of Contract::TestEnum bitsf
289 const char *m_construct; // The syntactic construct that pushed this thing
290};
291
292class CrstBase;
293
294// The next few enums / structs are used to keep track of all kinds of locks
295// currently taken by the current thread (crsts, spinlocks, CLR critical sections).
296// Across the VM, there are still multiple counts of locks. The lock counts in these
297// contract structs are used to verify consistency of lock take/release in EE code, and
298// for contracts. Both user and EE locks are tracked here, but it's EE code consistency
299// we're verifying. The Thread object keeps its own counts as well, primarily of user
300// locks for implementing thread abort & escalation policy. We tried to have the Thread
301// counts also be used for consistency checking, but that doesn't work. Thread counters
302// have the following behavior that hurts our internal consistency checks:
303// - They only count user locks.
304// - Counters are reset & restored as we leave and return to AppDomains
305
306// An array of these is stored in DbgStateLockData::m_rgTakenLockInfos
307// to remember which locks we've taken. If you hit an assert that
308// indicates we're exiting locks in the wrong order, or that locks were
309// taken when we expected none to be taken, then you can use
310// DbgStateLockData::m_rgTakenLockInfos to see the locks we know about.
311struct TakenLockInfo
312{
313 // Generally, this will be a pointer to the lock, but really it's just
314 // a value that identifies which lock is taken. Ya see, sometimes we don't
315 // have a lock pointer handy (e.g., if the lock is based on a GC object,
316 // which has no persistent object pointer we can use). Look at the source
317 // indicated by m_szFile / m_lineNum to see what was specified as m_pvLock.
318 //
319 // A common case is that the lock is just a Crst, so to aid debugging, we
320 // also include a statically typed version of this pointer (m_pCrstBase) just
321 // for Crsts. Again, you'll want look at m_szFile / m_lineNum to see how to
322 // interpret this union.
323 union
324 {
325 void * m_pvLock;
326 CrstBase * m_pCrstBase;
327 };
328
329 // File & line of the *LOCK_TAKEN* macro that added this lock to our list
330 const char * m_szFile;
331 int m_lineNum;
332};
333
334enum DbgStateLockType
335{
336 // EE locks (used to sync EE structures). These do not include
337 // CRST_HOST_BREAKABLE Crsts, and are thus not held while managed
338 // code runs
339 kDbgStateLockType_EE,
340
341 // CRST_HOST_BREAKABLE Crsts. These can be held while arbitrary
342 // managed code runs.
343 kDbgStateLockType_HostBreakableCrst,
344
345 // User locks (e.g., Monitor.Enter, ReaderWriterLock class)
346 kDbgStateLockType_User,
347
348 // add more lock types here
349
350 kDbgStateLockType_Count
351};
352
353// This keeps track of how many locks, and which locks, are currently owned
354// by the current thread. There is one instance of this structure per
355// thread (no EE Thread object required). This is in contrast to the
356// ClrDebugState structure, which is instantiated once per function
357// on the stack. Reason is that ClrDebugState resets its state on exit
358// of function (Contract destructor reinstates previous ClrDebugState), whereas
359// we want DbgStateLockData to persist across function enters & exits.
360struct DbgStateLockData
361{
362 // When a lock is taken, we keep track of its pointer and file/line# when it
363 // was added in a static-size array DbgStateLockData::m_rgTakenLockInfos. This is
364 // the size of that array, and therefore indicates the maximum number of locks we
365 // expect one thread to hold at the same time. If we should exceed this limit,
366 // we'll lose this data for the latter locks that exceed this limit
367 // (though still maintaining an accurate *count* of locks).
368 static const int kMaxAllowedSimultaneousLocks = 20;
369
370 // Count of locks taken, separately by type
371 UINT m_rgcLocksTaken[kDbgStateLockType_Count];
372
373 // List of the specific locks that have been taken (all DbgStateLockTypes
374 // intermingled), in the order they were taken. If we exceed the elements
375 // in the array, we just won't track the latter locks in here (though they are
376 // included in the counts above)
377 TakenLockInfo m_rgTakenLockInfos[kMaxAllowedSimultaneousLocks];
378
379 void SetStartingValues();
380 void LockTaken(DbgStateLockType dbgStateLockType,
381 UINT cEntrances,
382 void * pvLock,
383 __in_z const char * szFunction,
384 __in_z const char * szFile,
385 int lineNum);
386 void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock);
387 UINT GetLockCount(DbgStateLockType dbgStateLockType);
388 UINT GetCombinedLockCount();
389};
390
391// This struct contains all lock contract information. It is created and destroyed along with
392// ClrDebugState. m_pLockData points to a DbgStateLockData object that is allocated per thread
393// and persists across function enters and exists.
394struct DbgStateLockState
395{
396private:
397 // Count of locks taken at the time the function with CANNOT_RETAKE_LOCK contract
398 // was called
399 UINT m_cLocksEnteringCannotRetakeLock;
400
401 DbgStateLockData * m_pLockData; // How many and which locks are currently taken on this thread
402
403public:
404 void SetStartingValues();
405 void OnEnterCannotRetakeLockFunction();
406 BOOL IsLockRetaken(void * pvLock);
407 BOOL IsSafeToRelease(UINT cReleases);
408 void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData);
409 DbgStateLockData * GetDbgStateLockData();
410};
411
412
413#define CONTRACT_BITMASK_OK_TO_THROW 0x1 << 0
414#define CONTRACT_BITMASK_FAULT_FORBID 0x1 << 1
415#define CONTRACT_BITMASK_HOSTCALLS 0x1 << 2
416#define CONTRACT_BITMASK_SOTOLERANT 0x1 << 3
417#define CONTRACT_BITMASK_DEBUGONLY 0x1 << 4
418#define CONTRACT_BITMASK_SONOTMAINLINE 0x1 << 5
419#define CONTRACT_BITMASK_ALLOWGETTHREAD 0x1 << 6
420#define CONTRACT_BITMASK_OK_TO_LOCK 0x1 << 7
421#define CONTRACT_BITMASK_OK_TO_RETAKE_LOCK 0x1 << 8
422
423
424#define CONTRACT_BITMASK_IS_SET(whichbit) ((m_flags & (whichbit)) != 0)
425#define CONTRACT_BITMASK_SET(whichbit) (m_flags |= (whichbit))
426#define CONTRACT_BITMASK_RESET(whichbit) (m_flags &= ~(whichbit))
427#define CONTRACT_BITMASK_UPDATE(whichbit, value) ((value)?CONTRACT_BITMASK_SET(whichbit):CONTRACT_BITMASK_RESET(whichbit))
428
429
430// Stored in the FLS under TlsIdx_ClrDebugState.
431struct ClrDebugState
432{
433private:
434 UINT_PTR m_flags;
435 UINT_PTR m_violationmask; // Current CONTRACT_VIOLATIONS in effect
436 ContractStackRecord *m_pContractStackTrace;
437 UINT m_GCNoTriggerCount;
438 UINT m_GCForbidCount;
439 UINT m_maxLoadTypeLevel; // taken from enum ClassLoadLevel
440 BOOL m_allowGetThread; // TRUE if GetThread() is ok in this scope
441#ifdef FEATURE_STACK_PROBE //StackMarkerStack required only when SO infrastructure is enabled
442 /* Used to validate backout stack consumption required for StackOverflow infrastructure */
443 StackMarkerStack m_StackMarkerStack; // The stack of stack markers
444#endif
445 DbgStateLockState m_LockState;
446
447public:
448 // Use an explicit Init rather than ctor as we don't want automatic
449 // construction of the ClrDebugState embedded inside the contract.
450 void SetStartingValues()
451 {
452 m_violationmask = 0; // No violations allowed
453
454 // Default is we're in a THROWS scope. This is not ideal, but there are
455 // just too many places that I'd have to go clean up right now
456 // (hundreds) in order to make this FALSE by default.
457 // Faults not forbidden (an unfortunate default but
458 // we'd never get this debug infrastructure bootstrapped otherwise.)
459 // We start out in SO-tolerant mode and must probe before entering SO-intolerant
460 // any global state updates.
461 // Initial mode is non-debug until we say otherwise
462 // Everthing defaults to mainline
463 // By default, GetThread() is perfectly fine to call
464 // By default, it's ok to take a lock (or call someone who does)
465 m_flags = CONTRACT_BITMASK_OK_TO_THROW|
466 CONTRACT_BITMASK_HOSTCALLS|
467 CONTRACT_BITMASK_SOTOLERANT|
468 CONTRACT_BITMASK_ALLOWGETTHREAD|
469 CONTRACT_BITMASK_OK_TO_LOCK|
470 CONTRACT_BITMASK_OK_TO_RETAKE_LOCK;
471
472 m_pContractStackTrace = NULL; // At top of stack, no contracts in force
473 m_GCNoTriggerCount = 0;
474 m_GCForbidCount = 0;
475
476 m_maxLoadTypeLevel = ((UINT)(-1)); // ideally CLASS_LOAD_LEVEL_FINAL but we don't have access to that #define, so
477 // the max integer value will do as a substitute.
478
479 m_allowGetThread = TRUE; // By default, GetThread() is perfectly fine to call
480
481#ifdef FEATURE_STACK_PROBE
482 m_StackMarkerStack.Init();
483#endif
484
485 m_LockState.SetStartingValues();
486 }
487
488 void CheckOkayToThrow(__in_z const char *szFunction, __in_z const char *szFile, int lineNum); // Asserts if its not okay to throw.
489 BOOL CheckOkayToThrowNoAssert(); // Returns if OK to throw
490
491 //--//
492
493 UINT_PTR* ViolationMaskPtr()
494 {
495 return &m_violationmask;
496 }
497
498 UINT_PTR ViolationMask()
499 {
500 return m_violationmask;
501 }
502
503 void ViolationMaskSet( UINT_PTR value )
504 {
505 m_violationmask |= value;
506 }
507
508 void ViolationMaskReset( UINT_PTR value )
509 {
510 m_violationmask &= ~value;
511 }
512
513 //--//
514
515 BOOL IsOkToThrow()
516 {
517 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW);
518 }
519
520 void SetOkToThrow()
521 {
522 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_THROW);
523 }
524
525 BOOL SetOkToThrow( BOOL value )
526 {
527 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW);
528 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_THROW, value);
529 return prevState;
530 }
531
532 void ResetOkToThrow()
533 {
534 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_THROW);
535 }
536 //--//
537
538 BOOL IsFaultForbid()
539 {
540 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID);
541 }
542
543
544 void SetFaultForbid()
545 {
546 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_FAULT_FORBID);
547 }
548
549 BOOL SetFaultForbid(BOOL value)
550 {
551 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID);
552 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_FAULT_FORBID, value);
553 return prevState;
554 }
555
556 void ResetFaultForbid()
557 {
558 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_FAULT_FORBID);
559 }
560
561 //--//
562 BOOL IsHostCaller()
563 {
564 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS);
565 }
566
567 void SetHostCaller()
568 {
569 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_HOSTCALLS);
570 }
571
572
573 BOOL SetHostCaller(BOOL value)
574 {
575 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS);
576 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_HOSTCALLS,value);
577 return prevState;
578 }
579
580 void ResetHostCaller()
581 {
582 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_HOSTCALLS);
583 }
584
585#ifdef FEATURE_STACK_PROBE //SO contract functions only required when SO infrastructure is enabled
586 //--//
587 BOOL IsSOTolerant()
588 {
589 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_SOTOLERANT);
590 }
591
592 void SetSOTolerance()
593 {
594 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_SOTOLERANT);
595 }
596
597 BOOL SetSOTolerance(BOOL tolerance)
598 {
599 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_SOTOLERANT);
600 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_SOTOLERANT,tolerance);
601 return prevState;
602 }
603
604 void ResetSOTolerance()
605 {
606 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_SOTOLERANT);
607 }
608
609#endif
610
611 //--//
612 BOOL IsDebugOnly()
613 {
614 STATIC_CONTRACT_WRAPPER;
615 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY);
616 }
617
618 void SetDebugOnly()
619 {
620 STATIC_CONTRACT_WRAPPER;
621 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_DEBUGONLY);
622 }
623
624 BOOL SetDebugOnly(BOOL value)
625 {
626 STATIC_CONTRACT_WRAPPER;
627 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY);
628 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_DEBUGONLY,value);
629 return prevState;
630 }
631
632 void ResetDebugOnly()
633 {
634 STATIC_CONTRACT_LIMITED_METHOD;
635 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_DEBUGONLY);
636 }
637
638 #ifdef FEATURE_STACK_PROBE
639 //--//
640 BOOL IsSONotMainline()
641 {
642 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_SONOTMAINLINE);
643 }
644
645 void SetSONotMainline()
646 {
647 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_SONOTMAINLINE);
648 }
649
650 BOOL SetSONotMainline(BOOL value)
651 {
652 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_SONOTMAINLINE);
653 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_SONOTMAINLINE,value);
654 return prevState;
655 }
656
657 void ResetSONotMainline()
658 {
659 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_SONOTMAINLINE);
660 }
661#endif
662
663 //--//
664 BOOL IsGetThreadAllowed()
665 {
666 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_ALLOWGETTHREAD);
667
668 }
669 void SetGetThreadAllowed()
670 {
671 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_ALLOWGETTHREAD);
672 }
673
674
675 BOOL SetGetThreadAllowed(BOOL value)
676 {
677 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_ALLOWGETTHREAD);
678 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_ALLOWGETTHREAD,value);
679 return prevState;
680 }
681
682 void ResetGetThreadAllowed()
683 {
684 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_ALLOWGETTHREAD);
685 }
686
687 //--//
688 BOOL IsOkToLock()
689 {
690 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK);
691 }
692
693 void SetOkToLock()
694 {
695 CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_LOCK);
696 }
697
698 BOOL SetOkToLock( BOOL value )
699 {
700 BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK);
701 CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_LOCK, value);
702 return prevState;
703 }
704
705 void ResetOkToLock()
706 {
707 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_LOCK);
708 }
709
710 //--//
711 BOOL IsOkToRetakeLock()
712 {
713 return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK);
714 }
715
716 void ResetOkToRetakeLock()
717 {
718 CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK);
719 }
720
721
722 //--//
723 void LinkContractStackTrace( ContractStackRecord* pContractStackTrace )
724 {
725 pContractStackTrace->m_pNext = m_pContractStackTrace;
726
727 m_pContractStackTrace = pContractStackTrace;
728 }
729
730 ContractStackRecord* GetContractStackTrace()
731 {
732 return m_pContractStackTrace;
733 }
734
735 void SetContractStackTrace(ContractStackRecord* pContractStackTrace )
736 {
737 m_pContractStackTrace = pContractStackTrace;
738 }
739
740 //--//
741
742 UINT GetGCNoTriggerCount()
743 {
744 return m_GCNoTriggerCount;
745 }
746
747 void DecrementGCNoTriggerCount()
748 {
749 m_GCNoTriggerCount--;
750 }
751
752 void IncrementGCNoTriggerCount()
753 {
754 m_GCNoTriggerCount++;
755 }
756
757
758 UINT GetGCForbidCount()
759 {
760 return m_GCForbidCount;
761 }
762
763 void DecrementGCForbidCount()
764 {
765 m_GCForbidCount--;
766 }
767
768 void IncrementGCForbidCount()
769 {
770 m_GCForbidCount++;
771 }
772
773 UINT GetMaxLoadTypeLevel()
774 {
775 return m_maxLoadTypeLevel;
776 }
777
778 void SetMaxLoadTypeLevel(UINT newLevel)
779 {
780 m_maxLoadTypeLevel = newLevel;
781 }
782
783 //--//
784
785 void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData)
786 {
787 m_LockState.SetDbgStateLockData(pDbgStateLockData);
788 }
789
790 DbgStateLockData * GetDbgStateLockData()
791 {
792 return m_LockState.GetDbgStateLockData();
793 }
794
795 void OnEnterCannotRetakeLockFunction()
796 {
797 m_LockState.OnEnterCannotRetakeLockFunction();
798 }
799
800#ifdef FEATURE_STACK_PROBE //SO contract functions only required when SO infrastructure is enabled
801 BOOL IsSOIntolerant()
802 {
803 return !IsSOTolerant();
804 }
805
806 BOOL BeginSOTolerant()
807 {
808 return SetSOTolerance(TRUE);
809 }
810
811 BOOL BeginSOIntolerant()
812 {
813 return SetSOTolerance(FALSE);
814 }
815
816
817 void CheckIfSOIntolerantOK(const char *szFunction, const char *szFile, int lineNum);
818
819
820
821
822
823 //--//
824
825 StackMarkerStack& GetStackMarkerStack()
826 {
827 return m_StackMarkerStack;
828 }
829#endif
830
831 void CheckOkayToLock(__in_z const char *szFunction, __in_z const char *szFile, int lineNum); // Asserts if its not okay to lock
832 BOOL CheckOkayToLockNoAssert(); // Returns if OK to lock
833 void LockTaken(DbgStateLockType dbgStateLockType,
834 UINT cEntrances,
835 void * pvLock,
836 __in_z const char * szFunction,
837 __in_z const char * szFile,
838 int lineNum);
839 void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock);
840 UINT GetLockCount(DbgStateLockType dbgStateLockType);
841 UINT GetCombinedLockCount();
842};
843
844#endif // ENABLE_CONTRACTS
845
846#ifdef ENABLE_CONTRACTS_IMPL
847// Create ClrDebugState.
848// This routine is not allowed to return NULL. If it can't allocate the memory needed,
849// it should return a pointer to a global static ClrDebugState that indicates
850// that debug assertions should be skipped.
851ClrDebugState *CLRInitDebugState();
852ClrDebugState *GetClrDebugState(BOOL fAlloc = TRUE);
853
854
855// This function returns a ClrDebugState if one has been created, but will not create one itself.
856inline ClrDebugState *CheckClrDebugState()
857{
858 STATIC_CONTRACT_LIMITED_METHOD;
859 STATIC_CONTRACT_SO_TOLERANT;
860 ClrDebugState *ret = (ClrDebugState*)ClrFlsGetValue(TlsIdx_ClrDebugState);
861 return ret;
862}
863
864void CONTRACT_ASSERT(const char *szElaboration,
865 UINT whichTest,
866 UINT whichTestMask,
867 const char *szFunction,
868 const char *szFile,
869 int lineNum
870 );
871
872#endif
873
874// This needs to be defined up here b/c it is used by ASSERT_CHECK which is used by the contract impl
875#ifdef _DEBUG
876#ifdef ENTER_DEBUG_ONLY_CODE
877#undef ENTER_DEBUG_ONLY_CODE
878#endif
879#ifdef LEAVE_DEBUG_ONLY_CODE
880#undef LEAVE_DEBUG_ONLY_CODE
881#endif
882
883#ifdef ENABLE_CONTRACTS_IMPL
884// This can only appear in a debug function so don't define it non-debug
885class DebugOnlyCodeHolder
886{
887public:
888 // We use GetClrDebugState on entry, but CheckClrDebugState on Leave
889 // That way we make sure to create one if we need to set state, but
890 // we don't recreated one on exit if its been deleted.
891 DEBUG_NOINLINE void Enter()
892 {
893 SCAN_SCOPE_BEGIN;
894 STATIC_CONTRACT_DEBUG_ONLY;
895
896 m_pClrDebugState = GetClrDebugState();
897 if (m_pClrDebugState)
898 {
899 m_oldDebugOnlyValue = m_pClrDebugState->IsDebugOnly();
900 m_pClrDebugState->SetDebugOnly();
901 }
902 }
903
904 DEBUG_NOINLINE void Leave()
905 {
906 SCAN_SCOPE_END;
907 STATIC_CONTRACT_DEBUG_ONLY;
908
909 m_pClrDebugState = CheckClrDebugState();
910 if (m_pClrDebugState)
911 {
912 m_pClrDebugState->SetDebugOnly( m_oldDebugOnlyValue );
913 }
914 }
915
916private:
917BOOL m_oldDebugOnlyValue;
918ClrDebugState *m_pClrDebugState;
919};
920
921#define ENTER_DEBUG_ONLY_CODE \
922 DebugOnlyCodeHolder __debugOnlyCodeHolder; \
923 __debugOnlyCodeHolder.Enter();
924
925#define LEAVE_DEBUG_ONLY_CODE \
926 __debugOnlyCodeHolder.Leave();
927
928
929class AutoCleanupDebugOnlyCodeHolder : public DebugOnlyCodeHolder
930{
931public:
932 DEBUG_NOINLINE AutoCleanupDebugOnlyCodeHolder()
933 {
934 SCAN_SCOPE_BEGIN;
935 STATIC_CONTRACT_DEBUG_ONLY;
936
937 Enter();
938 };
939
940 DEBUG_NOINLINE ~AutoCleanupDebugOnlyCodeHolder()
941 {
942 SCAN_SCOPE_END;
943
944 Leave();
945 };
946};
947
948#define DEBUG_ONLY_FUNCTION \
949 STATIC_CONTRACT_DEBUG_ONLY; \
950 AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder;
951
952#define DEBUG_ONLY_REGION() \
953 AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder;
954
955
956#define BEGIN_DEBUG_ONLY_CODE \
957 { \
958 AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder;
959
960#define END_DEBUG_ONLY_CODE \
961 }
962
963#else // ENABLE_CONTRACTS_IMPL
964#define DEBUG_ONLY_FUNCTION STATIC_CONTRACT_DEBUG_ONLY
965#define DEBUG_ONLY_REGION()
966#define BEGIN_DEBUG_ONLY_CODE
967#define END_DEBUG_ONLY_CODE
968#define ENTER_DEBUG_ONLY_CODE
969#define LEAVE_DEBUG_ONLY_CODE
970#endif
971
972#else // _DEBUG
973#define DEBUG_ONLY_REGION()
974#endif
975
976
977#ifdef ENABLE_CONTRACTS_IMPL
978
979// These helpers encapsulate our access to our FLS debug state. To improve
980// contract perf, we'll soon move these to a private alloced block
981// so we can reuse the pointer instead of constantly refetching it.
982// Thus, these helpers are just to bridge this transition.
983inline LPVOID GetViolationMask()
984{
985 ClrDebugState *pState = CheckClrDebugState();
986 if (pState)
987 {
988 return (LPVOID)pState->ViolationMask();
989 }
990 else
991 {
992 return 0;
993 }
994}
995
996// This is the default binding of the MAYBETEMPLATE identifier,
997// used in the RETURN macro
998template <int DUMMY>
999class ___maybetemplate
1000{
1001 public:
1002 FORCEINLINE void *operator new (size_t size)
1003 {
1004 return NULL;
1005 }
1006};
1007
1008// This is an abstract base class for contracts. The main reason we have this is so that the dtor for many derived class can
1009// be performant. If this class was not abstract and had a dtor, then the dtor for the derived class adds EH overhead (even if the derived
1010// class did not anything special in its dtor)
1011class BaseContract
1012{
1013 // Really private, but used by macros
1014 public:
1015
1016 // We use a single integer to specify all the settings for intrinsic tests
1017 // such as THROWS and GC_TRIGGERS. The compiler should be able to fold all
1018 // these clauses into a single constant.
1019 //
1020 // The value "0" is significant as this is what the entire mask will be initialized to
1021 // in the absence of any clauses. Hence, whichever value is assigned "0" will be the
1022 // default setting for the test.
1023 //
1024 // Also, there must be a "disabled" setting for each category in order to support
1025 // the DISABLED macro.
1026 enum TestEnum
1027 {
1028 THROWS_Mask = 0x00000003,
1029 THROWS_Yes = 0x00000000, // the default
1030 THROWS_No = 0x00000001,
1031 THROWS_Disabled = 0x00000002,
1032
1033 GC_Mask = 0x0000000C,
1034 GC_Triggers = 0x00000000, // the default
1035 GC_NoTrigger = 0x00000004,
1036 GC_Disabled = 0x00000008,
1037
1038 FAULT_Mask = 0x00000030,
1039 FAULT_Disabled = 0x00000000, // the default
1040 FAULT_Inject = 0x00000010,
1041 FAULT_Forbid = 0x00000020,
1042
1043 MODE_Mask = 0x000000C0,
1044 MODE_Disabled = 0x00000000, // the default
1045 MODE_Preempt = 0x00000040,
1046 MODE_Coop = 0x00000080,
1047
1048 // The following are used to assert the type of global state update being done by the function.
1049 // This is used by the SO infrastructure to detect if we are probing properly. A CLR process will
1050 // run in one of two states: SO-tolerant or SO-intolerant. In SO-tolerant mode, an SO is OK and we
1051 // will not corrupt any global state. However, we cannot allow an SO to occur in SO-intolerant code
1052 // because we might end up with our global state being corrupted.
1053 //
1054 // When we enter the EE from any entry point, we will begin in SO-tolerant mode and must probe for sufficient
1055 // stack before entering SO-intolerant code. We will tell the differnce between SO-tolerant and SO-intolerant code
1056 // by contract annotations on that function: SO_TOLERANT and SO_INTOLERANT.
1057
1058 // We enter the EE in SO_TOLERANT mode. All entry point functions into the EE must be marked as SO_TOLERANT and
1059 // and must probe before calling an SO-intolerant function. We have a static analsysis tool that ensures that every
1060 // entry point is tagged as SO_TOLERANT and that it probes before calling an SO_TOLERANT function.
1061
1062 // By default, all unannotated functions in the EE are SO_INTOLERANT which means that they must run behind a probe.
1063 // Our contract checking will verify this at runtime. We only need to annotate a function explicilty as SO_INTOLERANT
1064 // to tell our static analysis tool that they are not entry points (if it can't find a caller for a function, it assumes that the
1065 // function is an entry point and should be marked SO_INTOLERANT.)
1066
1067 SO_TOLERANCE_Mask = 0x00000300,
1068 SO_TOLERANT_No = 0x00000000, // the default.
1069 SO_TOLERANT_Yes = 0x00000100,
1070 SO_TOLERANCE_Disabled = 0x00000200,
1071
1072 DEBUG_ONLY_Yes = 0x00000400, // code runs under debug only
1073
1074 SO_MAINLINE_No = 0x00000800, // code is not part of our mainline SO scenario
1075
1076 // Any place where we can't safely call into the host should have a HOST_NoCalls contract
1077 HOST_Mask = 0x00003000,
1078 HOST_Calls = 0x00002000,
1079 HOST_NoCalls = 0x00001000,
1080 HOST_Disabled = 0x00000000, // the default
1081
1082 // This enforces the EE_THREAD_NOT_REQUIRED contract by clearing
1083 // ClrDebugState::m_allowGetThread in its scope. That causes raw calls
1084 // to GetThread() to assert, unless inside a temporary "don't worry it's ok" scope
1085 // via BEGIN/END_GETTHREAD_ALLOWED. Useful for enforcing our docs that
1086 // state certain unmanaged API entrypoints (e.g., some from profiling API)
1087 // are callable without an EE Thread in TLS.
1088 EE_THREAD_Mask = 0x0000C000,
1089 EE_THREAD_Disabled = 0x00000000, // the default
1090 EE_THREAD_Required = 0x00004000,
1091 EE_THREAD_Not_Required = 0x00008000,
1092
1093 // These enforce the CAN_TAKE_LOCK / CANNOT_TAKE_LOCK contracts
1094 CAN_TAKE_LOCK_Mask = 0x00060000,
1095 CAN_TAKE_LOCK_Yes = 0x00020000,
1096 CAN_TAKE_LOCK_No = 0x00040000,
1097 CAN_TAKE_LOCK_Disabled = 0x00000000, // the default
1098
1099 // These enforce the CANNOT_RETAKE_LOCK contract
1100 CAN_RETAKE_LOCK_No = 0x00080000,
1101 CAN_RETAKE_LOCK_No_Disabled = 0x00000000, // the default
1102
1103 PRECONDITION_Used = 0x00010000, // a PRECONDITION appeared inside the contract
1104
1105 // IMPORTANT!!! LOADS_TYPE_Mask and LOADS_TYPE_Shift must be kept in sync.
1106 LOADS_TYPE_Mask = 0x00f00000, // the max loadstype level + 1 ("+1" because 0 is reserved for the default which is "disabled")
1107 LOADS_TYPE_Shift = 20, // # of bits to right-shift to get loadstype bits to rightmost position.
1108 LOADS_TYPE_Disabled = 0x00000000, // the default
1109
1110 ALL_Disabled = THROWS_Disabled|GC_Disabled|FAULT_Disabled|MODE_Disabled|LOADS_TYPE_Disabled|
1111 SO_TOLERANCE_Disabled|HOST_Disabled|EE_THREAD_Disabled|CAN_TAKE_LOCK_Disabled|CAN_RETAKE_LOCK_No_Disabled
1112
1113 };
1114
1115 enum Operation
1116 {
1117 Setup = 0x01,
1118 Preconditions = 0x02,
1119 Postconditions = 0x04,
1120 };
1121
1122
1123 __declspec(nothrow) BaseContract() : m_pClrDebugState(NULL), m_testmask(0)
1124 {
1125 }
1126 __declspec(nothrow) void Restore()
1127 {
1128 // m_pClrDebugState is setup in BaseContract::DoChecks. If an SO happens after the
1129 // BaseContract object is constructed but before DoChecks is invoked, m_pClrDebugState
1130 // will remain NULL (which is what it is set to in the BaseContract ctor).
1131 //
1132 // Thus, we should check for it being NULL before dereferencing it.
1133 if (m_pClrDebugState)
1134 {
1135 // Backout all changes to debug state.
1136 *m_pClrDebugState = m_IncomingClrDebugState;
1137 }
1138 }
1139
1140 void DoChecks(UINT testmask, __in_z const char *szFunction, __in_z const char *szFile, int lineNum);
1141 void Disable()
1142 {
1143 }
1144 BOOL CheckFaultInjection();
1145
1146 protected:
1147 UINT m_testmask;
1148 // Override this function in any derived class to indicate that you have defined a destructor for that class
1149 // and that dtor calls Restore()
1150 virtual void DestructorDefinedThatCallsRestore() = 0;
1151
1152
1153 protected:
1154 ClrDebugState *m_pClrDebugState;
1155 ClrDebugState m_IncomingClrDebugState;
1156
1157 ContractStackRecord m_contractStackRecord;
1158
1159 public:
1160 // --------------------------------------------------------------------------------
1161 // These classes and declarations are used to implement our fake return keyword.
1162 // --------------------------------------------------------------------------------
1163
1164 // ___box is used to protect the "detected" return value from being combined with other parts
1165 // of the return expression after we have processed it. This can happen if the return
1166 // expression is a non-parenthesized expression with an operator of lower precedence than
1167 // ">".
1168 //
1169 // If you have such a case (and see this class listed in an error message),
1170 // parenthesize your return value expression.
1171 template <typename T>
1172 class Box__USE_PARENS_WITH_THIS_EXPRESSION
1173 {
1174 const T &value;
1175
1176 public:
1177
1178 FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION(const T &value)
1179 : value(value)
1180 {
1181 }
1182
1183 FORCEINLINE const T& Unbox()
1184 {
1185 return value;
1186 }
1187 };
1188
1189 // PseudoTemplate is a class which can be instantated with a template-like syntax, resulting
1190 // in an expression which simply boxes a following value in a Box
1191
1192 template <typename T>
1193 class PseudoTemplate
1194 {
1195 public:
1196 FORCEINLINE void *operator new (size_t size)
1197 {
1198 return NULL;
1199 }
1200
1201 FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION<T> operator>(const T &value)
1202 {
1203 return Box__USE_PARENS_WITH_THIS_EXPRESSION<T>(value);
1204 }
1205
1206 FORCEINLINE PseudoTemplate operator<(int dummy)
1207 {
1208 return PseudoTemplate();
1209 }
1210 };
1211
1212 // Returner is used to assign the return value to the RETVAL local. Note the use of
1213 // operator , because of its low precedence.
1214
1215 template <typename RETURNTYPE>
1216 class Returner
1217 {
1218 RETURNTYPE &m_value;
1219 BOOL m_got;
1220 public:
1221
1222 FORCEINLINE Returner(RETURNTYPE &value)
1223 : m_value(value),
1224 m_got(FALSE)
1225 {
1226 }
1227
1228 template <typename T>
1229 FORCEINLINE RETURNTYPE operator,(Box__USE_PARENS_WITH_THIS_EXPRESSION<T> value)
1230 {
1231 m_value = value.Unbox();
1232 m_got = TRUE;
1233 return m_value;
1234 }
1235
1236 FORCEINLINE void operator,(___maybetemplate<0> &dummy)
1237 {
1238 m_got = TRUE;
1239 }
1240
1241 FORCEINLINE BOOL GotReturn()
1242 {
1243 return m_got;
1244 }
1245 };
1246
1247 // This type ensures that postconditions were run via RETURN or RETURN_VOID
1248 class RanPostconditions
1249 {
1250 public:
1251 bool ran;
1252 int count;
1253 const char *function;
1254
1255 FORCEINLINE RanPostconditions(const char *function)
1256 : ran(false),
1257 count(0),
1258 function(function)
1259 {
1260 }
1261
1262 FORCEINLINE int operator++()
1263 {
1264 return ++count;
1265 }
1266
1267 FORCEINLINE ~RanPostconditions()
1268 {
1269 // Note: __uncaught_exception() is not a perfect check. It will return TRUE during any exception
1270 // processing. So, if there is a contract called from an exception filter (like our
1271 // COMPlusFrameHandler) then it will return TRUE and the saftey check below will not be performed.
1272 if (!__uncaught_exception())
1273 ASSERT_CHECK(count == 0 || ran, function, "Didn't run postconditions - be sure to use RETURN at the end of the function");
1274 }
1275
1276 };
1277
1278 // Set contract enforcement level
1279 static void SetUnconditionalContractEnforcement(BOOL enforceUnconditionally);
1280
1281 // Check contract enforcement
1282 static BOOL EnforceContract();
1283
1284 private:
1285 static BOOL s_alwaysEnforceContracts;
1286};
1287
1288class Contract: public BaseContract
1289{
1290 // Have to override this function in any derived class to indicate that a valid destructor is defined for this class
1291 virtual void DestructorDefinedThatCallsRestore(){}
1292
1293 public:
1294 __declspec(nothrow) ~Contract()
1295 {
1296 Restore();
1297 }
1298};
1299
1300#endif // ENABLE_CONTRACTS_IMPL
1301
1302
1303#ifdef _DEBUG
1304
1305// Valid parameters for CONTRACT_VIOLATION macro
1306enum ContractViolationBits
1307{
1308 ThrowsViolation = 0x00000001, // suppress THROW tags in this scope
1309 GCViolation = 0x00000002, // suppress GCTRIGGER tags in this scope
1310 ModeViolation = 0x00000004, // suppress MODE_PREEMP and MODE_COOP tags in this scope
1311 FaultViolation = 0x00000008, // suppress INJECT_FAULT assertions in this scope
1312 FaultNotFatal = 0x00000010, // suppress INJECT_FAULT but not fault injection by harness
1313 SOToleranceViolation = 0x00000020, // suppress SO_TOLERANCE tags in this scope
1314 LoadsTypeViolation = 0x00000040, // suppress LOADS_TYPE tags in this scope
1315 TakesLockViolation = 0x00000080, // suppress CAN_TAKE_LOCK tags in this scope
1316 HostViolation = 0x00000100, // suppress HOST_CALLS tags in this scope
1317 EEThreadViolation = 0x00000200, // suppress EE_THREAD_REQUIRED tags in this scope
1318
1319 //These are not violation bits. We steal some bits out of the violation mask to serve as
1320 // general flag bits.
1321 CanFreeMe = 0x00010000, // If this bit is ON, the ClrDebugState was allocated by
1322 // a version of utilcode that registers an Fls Callback to free
1323 // the state. If this bit is OFF, the ClrDebugState was allocated
1324 // by an old version of utilcode that doesn't. (And you can't
1325 // assume that the old utilcode used the same allocator as the new utilcode.)
1326 // (Most likely, this is because you are using an older shim with
1327 // a newer mscorwks.dll)
1328 //
1329 // The Fls callback must only attempt to free debugstates that
1330 // have this bit on.
1331
1332 BadDebugState = 0x00020000, // If we OOM creating the ClrDebugState, we return a pointer to
1333 // a static ClrDebugState that has this bit turned on. (We don't
1334 // want to slow down contracts with null tests everywhere.)
1335 // Other than this specific bit, all other fields of the DebugState
1336 // must be considered trash. You can stomp on them and you can bit-test them
1337 // but you can't throw up any asserts based on them and you certainly
1338 // can't deref any pointers stored in the bad DebugState.
1339
1340 AllViolation = 0xFFFFFFFF,
1341};
1342
1343#endif
1344
1345#ifdef ENABLE_CONTRACTS_IMPL
1346
1347// Global variables allow PRECONDITION and POSTCONDITION to be used outside contracts
1348static const BaseContract::Operation ___op = (Contract::Operation) (Contract::Preconditions
1349 |Contract::Postconditions);
1350enum {
1351 ___disabled = 0
1352};
1353
1354static UINT ___testmask;
1355
1356// End of global variables
1357
1358static int ___ran;
1359
1360class __SafeToUsePostCondition {
1361public:
1362 static int safe_to_use_postcondition() {return 0;};
1363};
1364
1365class __YouCannotUseAPostConditionHere {
1366private:
1367 static int safe_to_use_postcondition() {return 0;};
1368};
1369
1370typedef __SafeToUsePostCondition __PostConditionOK;
1371
1372// Uncomment the following line to disable runtime contracts completely - PRE/POST conditions will still be present
1373//#define __FORCE_NORUNTIME_CONTRACTS__ 1
1374
1375#ifndef __FORCE_NORUNTIME_CONTRACTS__
1376
1377#define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \
1378 _returntype RETVAL; \
1379 _contracttype ___contract; \
1380 Contract::Returner<_returntype> ___returner(RETVAL); \
1381 Contract::RanPostconditions ___ran(__FUNCTION__); \
1382 Contract::Operation ___op = Contract::Setup; \
1383 BOOL ___contract_enabled = FALSE; \
1384 DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \
1385 ___contract_enabled = Contract::EnforceContract(); \
1386 enum {___disabled = 0}; \
1387 if (!___contract_enabled) \
1388 ___contract.Disable(); \
1389 else \
1390 { \
1391 enum { ___CheckMustBeInside_CONTRACT = 1 }; \
1392 if (0) \
1393 { \
1394 /* If you see an "unreferenced label" warning with this name, */\
1395 /* Be sure that you have a RETURN at the end of your */ \
1396 /* CONTRACT_VOID function */ \
1397 ___run_postconditions_DID_YOU_FORGET_A_RETURN: \
1398 if (___contract_enabled) \
1399 { \
1400 ___op = Contract::Postconditions; \
1401 ___ran.ran = true; \
1402 } \
1403 else \
1404 { \
1405 DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \
1406 ___run_return: \
1407 return _returnexp; \
1408 DEBUG_OK_TO_RETURN_END(CONTRACT) \
1409 } \
1410 } \
1411 if (0) \
1412 { \
1413 ___run_preconditions: \
1414 ___op = Contract::Preconditions; \
1415 } \
1416 UINT ___testmask = 0; \
1417
1418#define CONTRACTL_SETUP(_contracttype) \
1419 _contracttype ___contract; \
1420 BOOL ___contract_enabled = Contract::EnforceContract(); \
1421 enum {___disabled = 0}; \
1422 if (!___contract_enabled) \
1423 ___contract.Disable(); \
1424 else \
1425 { \
1426 typedef __YouCannotUseAPostConditionHere __PostConditionOK; \
1427 enum { ___CheckMustBeInside_CONTRACT = 1 }; \
1428 Contract::Operation ___op = Contract::Setup; \
1429 enum {___disabled = 0}; \
1430 if (0) \
1431 { \
1432 ___run_preconditions: \
1433 ___op = Contract::Preconditions; \
1434 } \
1435 if (0) \
1436 { \
1437 /* define for CONTRACT_END even though we can't get here */ \
1438 ___run_return: \
1439 UNREACHABLE(); \
1440 } \
1441 UINT ___testmask = 0; \
1442
1443#else // #ifndef __FORCE_NORUNTIME_CONTRACTS__
1444
1445#define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \
1446 _returntype RETVAL; \
1447 Contract::Returner<_returntype> ___returner(RETVAL); \
1448 Contract::RanPostconditions ___ran(__FUNCTION__); \
1449 Contract::Operation ___op = Contract::Setup; \
1450 DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \
1451 BOOL ___contract_enabled = Contract::EnforceContract(); \
1452 enum {___disabled = 0}; \
1453 { \
1454 enum { ___CheckMustBeInside_CONTRACT = 1 }; \
1455 if (0) \
1456 { \
1457 /* If you see an "unreferenced label" warning with this name, */\
1458 /* Be sure that you have a RETURN at the end of your */ \
1459 /* CONTRACT_VOID function */ \
1460 ___run_postconditions_DID_YOU_FORGET_A_RETURN: \
1461 if (___contract_enabled) \
1462 { \
1463 ___op = Contract::Postconditions; \
1464 ___ran.ran = true; \
1465 } \
1466 else \
1467 { \
1468 DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \
1469 ___run_return: \
1470 return _returnexp; \
1471 DEBUG_OK_TO_RETURN_END(CONTRACT) \
1472 } \
1473 } \
1474 if (0) \
1475 { \
1476 ___run_preconditions: \
1477 ___op = Contract::Preconditions; \
1478 } \
1479 UINT ___testmask = 0; \
1480
1481
1482
1483
1484#define CONTRACTL_SETUP(_contracttype) \
1485 BOOL ___contract_enabled = Contract::EnforceContract(); \
1486 enum {___disabled = 0}; \
1487 { \
1488 typedef __YouCannotUseAPostConditionHere __PostConditionOK; \
1489 enum { ___CheckMustBeInside_CONTRACT = 1 }; \
1490 Contract::Operation ___op = Contract::Setup; \
1491 enum {___disabled = 0}; \
1492 if (0) \
1493 { \
1494 ___run_preconditions: \
1495 ___op = Contract::Preconditions; \
1496 } \
1497 if (0) \
1498 { \
1499 /* define for CONTRACT_END even though we can't get here */ \
1500 ___run_return: \
1501 UNREACHABLE(); \
1502 } \
1503 UINT ___testmask = 0; \
1504
1505#endif // __FORCE_NORUNTIME_CONTRACTS__
1506
1507
1508#define CUSTOM_CONTRACT(_contracttype, _returntype) \
1509 typedef Contract::PseudoTemplate<_returntype> ___maybetemplate; \
1510 CONTRACT_SETUP(_contracttype, _returntype, RETVAL)
1511
1512#define CUSTOM_CONTRACT_VOID(_contracttype) \
1513 CONTRACT_SETUP(_contracttype, int, ;)
1514
1515#define CUSTOM_CONTRACTL(_contracttype) \
1516 CONTRACTL_SETUP(_contracttype)
1517
1518// Although this thing only needs to run in the Setup phase, we'll let it
1519// run unconditionally. This way, the compiler will see a sequence like this:
1520//
1521// THROWS; GC_TRIGGERS; FORBID_FAULT ==>
1522//
1523// ___testmask |= constant
1524// ___testmask |= constant
1525// ___testmask |= constant
1526//
1527// and be able to fold all these into a single constant at runtime.
1528//
1529#define REQUEST_TEST(thetest, todisable) (___testmask |= (___CheckMustBeInside_CONTRACT, (___disabled ? (todisable) : (thetest))))
1530
1531
1532#define INJECT_FAULT(_statement) \
1533 do \
1534 { \
1535 STATIC_CONTRACT_FAULT; \
1536 REQUEST_TEST(Contract::FAULT_Inject, Contract::FAULT_Disabled); \
1537 if (0) \
1538 { \
1539 _statement; \
1540 } \
1541 } \
1542 while(0) \
1543
1544
1545#define FORBID_FAULT do { STATIC_CONTRACT_FORBID_FAULT; REQUEST_TEST(Contract::FAULT_Forbid, Contract::FAULT_Disabled); } while(0)
1546
1547#define THROWS do { STATIC_CONTRACT_THROWS; REQUEST_TEST(Contract::THROWS_Yes, Contract::THROWS_Disabled); } while(0)
1548
1549#define NOTHROW do { STATIC_CONTRACT_NOTHROW; REQUEST_TEST(Contract::THROWS_No, Contract::THROWS_Disabled); } while(0) \
1550
1551#define ENTRY_POINT do { STATIC_CONTRACT_ENTRY_POINT; REQUEST_TEST(Contract::SO_TOLERANT_Yes, Contract::SO_TOLERANCE_Disabled); } while(0)
1552
1553#define LOADS_TYPE(maxlevel) do { REQUEST_TEST( ((maxlevel) + 1) << Contract::LOADS_TYPE_Shift, Contract::LOADS_TYPE_Disabled ); } while(0)
1554
1555#define SO_TOLERANT do { STATIC_CONTRACT_SO_TOLERANT; REQUEST_TEST(Contract::SO_TOLERANT_Yes, Contract::SO_TOLERANCE_Disabled); } while(0)
1556
1557#define SO_INTOLERANT do { STATIC_CONTRACT_SO_INTOLERANT; REQUEST_TEST(Contract::SO_TOLERANT_No, Contract::SO_TOLERANCE_Disabled); } while(0)
1558
1559#define SO_NOT_MAINLINE do { STATIC_CONTRACT_SO_NOT_MAINLINE; REQUEST_TEST(Contract::SO_MAINLINE_No, 0); } while (0)
1560
1561#define CAN_TAKE_LOCK do { STATIC_CONTRACT_CAN_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_Yes, Contract::CAN_TAKE_LOCK_Disabled); } while(0)
1562
1563#define CANNOT_TAKE_LOCK do { STATIC_CONTRACT_CANNOT_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_No, Contract::CAN_TAKE_LOCK_Disabled); } while(0)
1564
1565#define CANNOT_RETAKE_LOCK do { REQUEST_TEST(Contract::CAN_RETAKE_LOCK_No, Contract::CAN_RETAKE_LOCK_No_Disabled); } while(0)
1566
1567#define DEBUG_ONLY do { STATIC_CONTRACT_DEBUG_ONLY; REQUEST_TEST(Contract::DEBUG_ONLY_Yes, 0); } while (0)
1568
1569#ifndef __DISABLE_PREPOST_CONDITIONS__
1570#define PRECONDITION_MSG(_expression, _message) \
1571 do \
1572 { \
1573 enum { ___CheckMustBeInside_CONTRACT = 1 }; \
1574 REQUEST_TEST(Contract::PRECONDITION_Used, 0); \
1575 if ((___op&Contract::Preconditions) && !___disabled) \
1576 ASSERT_CHECK(_expression, _message, "Precondition failure"); \
1577 } \
1578 while(0)
1579
1580
1581#define PRECONDITION(_expression) \
1582 PRECONDITION_MSG(_expression, NULL)
1583
1584#define POSTCONDITION_MSG(_expression, _message) \
1585 ++___ran; \
1586 if ((!(0 && __PostConditionOK::safe_to_use_postcondition())) && \
1587 (___op&Contract::Postconditions) && \
1588 !___disabled) \
1589 { \
1590 ASSERT_CHECK(_expression, _message, "Postcondition failure"); \
1591 }
1592
1593#define POSTCONDITION(_expression) \
1594 POSTCONDITION_MSG(_expression, NULL)
1595
1596#define INSTANCE_CHECK \
1597 ___CheckMustBeInside_CONTRACT; \
1598 if ((___op&Contract::Preconditions) && !___disabled) \
1599 ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure"); \
1600 ++___ran; \
1601 if ((___op&Contract::Postconditions) && !___disabled) \
1602 ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure");
1603
1604#define INSTANCE_CHECK_NULL \
1605 ___CheckMustBeInside_CONTRACT; \
1606 if ((___op&Contract::Preconditions) && !___disabled) \
1607 ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance precheck failure"); \
1608 ++___ran; \
1609 if ((___op&Contract::Postconditions) && !___disabled) \
1610 ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance postcheck failure");
1611
1612#define CONSTRUCTOR_CHECK \
1613 ___CheckMustBeInside_CONTRACT; \
1614 ++___ran; \
1615 if ((___op&Contract::Postconditions) && !___disabled) \
1616 ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure");
1617
1618#define DESTRUCTOR_CHECK \
1619 ___CheckMustBeInside_CONTRACT; \
1620 NOTHROW; \
1621 if ((___op&Contract::Preconditions) && !___disabled) \
1622 ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure");
1623#else // __DISABLE_PREPOST_CONDITIONS__
1624
1625
1626#define PRECONDITION_MSG(_expression, _message) do { } while(0)
1627#define PRECONDITION(_expression) do { } while(0)
1628#define POSTCONDITION_MSG(_expression, _message) do { } while(0)
1629#define POSTCONDITION(_expression) do { } while(0)
1630#define INSTANCE_CHECK
1631#define INSTANCE_CHECK_NULL
1632#define CONSTRUCTOR_CHECK
1633#define DESTRUCTOR_CHECK
1634
1635#endif // __DISABLE_PREPOST_CONDITIONS__
1636
1637#define UNCHECKED(thecheck) \
1638 do { \
1639 ANNOTATION_UNCHECKED(thecheck); \
1640 enum {___disabled = 1 }; \
1641 thecheck; \
1642 } while(0)
1643
1644#define DISABLED(thecheck) UNCHECKED(thecheck)
1645
1646#define WRAPPER(thecheck) UNCHECKED(thecheck)
1647
1648// This keyword is redundant but it's handy for reducing the nuisance editing you
1649// have to when repeatedly enabling and disabling contract items while debugging.
1650// You shouldn't check in code that explicitly uses ENABLED.
1651#define ENABLED(_check) _check
1652
1653
1654#ifndef __FORCE_NORUNTIME_CONTRACTS__
1655#define CONTRACTL_END \
1656 if (___op & Contract::Setup) \
1657 { \
1658 ___contract.DoChecks(___testmask, __FUNCTION__, __FILE__, __LINE__); \
1659 if (___testmask & Contract::PRECONDITION_Used) \
1660 { \
1661 goto ___run_preconditions; \
1662 } \
1663 } \
1664 else if (___op & Contract::Postconditions) \
1665 { \
1666 goto ___run_return; \
1667 } \
1668 ___CheckMustBeInside_CONTRACT; \
1669 }
1670
1671#else
1672
1673#define CONTRACTL_END \
1674 if (___op & Contract::Setup) \
1675 { \
1676 if (___testmask & Contract::PRECONDITION_Used) \
1677 { \
1678 goto ___run_preconditions; \
1679 } \
1680 } \
1681 else if (___op & Contract::Postconditions) \
1682 { \
1683 goto ___run_return; \
1684 } \
1685 ___CheckMustBeInside_CONTRACT; \
1686 } \
1687
1688#endif // __FORCE_NORUNTIME_CONTRACTS__
1689
1690#define CONTRACT_END CONTRACTL_END \
1691 DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \
1692
1693
1694// The final expression in the RETURN macro deserves special explanation (or something.)
1695// The expression is constructed so as to be syntactically ambiguous, depending on whether
1696// __maybetemplate is a template or not. If it is a template, the expression is syntactically
1697// correct as-is. If it is not, the angle brackets are interpreted as
1698// less than & greater than, and the expression is incomplete. This is the point - we can
1699// choose whether we need an expression or not based on the context in which the macro is used.
1700// This allows the same RETURN macro to be used both in value-returning and void-returning
1701// contracts.
1702//
1703// The "__returner ," portion of the expression is used instead of "RETVAL =", since ","
1704// has lower precedence than "=". (Ain't overloaded operators fun.)
1705//
1706// Also note that the < and > operators on the non-template version of __maybetemplate
1707// are overridden to "box" the return value in a special type and pass it
1708// through to the __returner's "," operator. This is so we can detect a case where an
1709// operator with lower precedence than ">" is in the return expression - in such a case we
1710// will get a type error message, which instructs that parens be placed around the return
1711// value expression.
1712
1713#define RETURN_BODY \
1714 if (___returner.GotReturn()) \
1715 goto ___run_postconditions_DID_YOU_FORGET_A_RETURN; \
1716 else \
1717 ___returner, * new ___maybetemplate < 0 >
1718
1719
1720// We have two versions of the RETURN macro. CONTRACT_RETURN is for use inside the CONTRACT
1721// scope where it is OK to return this way, even though the CONTRACT macro itself does not
1722// allow a return. RETURN is for use inside the function body where it might not be OK
1723// to return and we need to ensure that we don't allow a return where one should not happen
1724//
1725#define RETURN \
1726 while (DEBUG_ASSURE_SAFE_TO_RETURN, TRUE) \
1727 RETURN_BODY \
1728
1729#define RETURN_VOID \
1730 RETURN
1731
1732#define CONTRACT_RETURN \
1733 while (___CheckMustBeInside_CONTRACT, TRUE) \
1734 RETURN_BODY \
1735
1736#define CONTRACT_RETURN_VOID \
1737 CONTRACT_RETURN \
1738
1739#if 0
1740#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \
1741 { \
1742 _contracttype ___contract; \
1743 STATIC_CONTRACT_LEAF; \
1744 ___contract.DoChecks(Contract::THROWS_No|Contract::GC_NoTrigger|Contract::MODE_Disabled|Contract::FAULT_Disabled); \
1745 /* Should add some assertion mechanism to ensure no other contracts are called */ \
1746 }
1747#else
1748#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \
1749 { \
1750 STATIC_CONTRACT_LEAF; \
1751 }
1752#endif
1753
1754#define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \
1755 { \
1756 /* Should add some assertion mechanism to ensure one other contract is called */ \
1757 STATIC_CONTRACT_WRAPPER; \
1758 }
1759
1760#define CONTRACT_THROWS() \
1761 { \
1762 ::GetClrDebugState()->CheckOkayToThrow(__FUNCTION__, __FILE__, __LINE__); \
1763 }
1764
1765#define CONTRACT_THROWSEX(__func, __file, __line) \
1766 { \
1767 ::GetClrDebugState()->CheckOkayToThrow(__func, __file, __line); \
1768 }
1769
1770#else // ENABLE_CONTRACTS_IMPL
1771#define CUSTOM_CONTRACT(_contracttype, _returntype) if (0) { struct YouCannotUseThisHere { int x; }; // This temporary typedef allows retail use of
1772#define CUSTOM_CONTRACT_VOID(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // FORBIDGC_LOADER_USE_ENABLED
1773#define CUSTOM_CONTRACTL(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // inside contracts and asserts but nowhere else.
1774
1775#define INJECT_FAULT(_statement)
1776#define FORBID_FAULT
1777#define THROWS
1778#define NOTHROW
1779#define CAN_TAKE_LOCK
1780#define CANNOT_TAKE_LOCK
1781#define CANNOT_RETAKE_LOCK
1782#define LOADS_TYPE(maxlevel)
1783#define SO_TOLERANT
1784#define SO_INTOLERANT
1785#define SO_NOT_MAINLINE
1786#define ENTRY_POINT
1787
1788#ifdef _DEBUG
1789// This can only appear in a debug function so don't define it non-debug
1790#define DEBUG_ONLY STATIC_CONTRACT_DEBUG_ONLY
1791#else
1792#define DEBUG_ONLY
1793#endif
1794
1795#define PRECONDITION_MSG(_expression, _message) do { } while(0)
1796#define PRECONDITION(_expression) do { } while(0)
1797#define POSTCONDITION_MSG(_expression, _message) do { } while(0)
1798#define POSTCONDITION(_expression) do { } while(0)
1799#define INSTANCE_CHECK
1800#define INSTANCE_CHECK_NULL
1801#define CONSTRUCTOR_CHECK
1802#define DESTRUCTOR_CHECK
1803#define UNCHECKED(thecheck)
1804#define DISABLED(thecheck)
1805#define WRAPPER(thecheck)
1806#define ENABLED(_check)
1807#define CONTRACT_END }
1808#define CONTRACTL_END }
1809
1810#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \
1811 { \
1812 /* Should add some assertion mechanism to ensure one other contract is called */ \
1813 STATIC_CONTRACT_LEAF; \
1814 }
1815#define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \
1816 { \
1817 /* Should add some assertion mechanism to ensure one other contract is called */ \
1818 STATIC_CONTRACT_WRAPPER; \
1819 }
1820
1821
1822#define RETURN return
1823#define RETURN_VOID RETURN
1824
1825#define CONTRACT_THROWS()
1826#define CONTRACT_THROWSEX(__func, __file, __line)
1827
1828#endif // ENABLE_CONTRACTS_IMPL
1829
1830
1831#define CONTRACT(_returntype) CUSTOM_CONTRACT(Contract, _returntype)
1832#define CONTRACT_VOID CUSTOM_CONTRACT_VOID(Contract)
1833#define CONTRACTL CUSTOM_CONTRACTL(Contract)
1834
1835// See description near the top of the file
1836#define LIMITED_METHOD_CONTRACT CUSTOM_LIMITED_METHOD_CONTRACT(Contract)
1837
1838#define WRAPPER_NO_CONTRACT CUSTOM_WRAPPER_NO_CONTRACT(Contract)
1839
1840// GC_NOTRIGGER allowed but not currently enforced at runtime
1841#define GC_NOTRIGGER STATIC_CONTRACT_GC_NOTRIGGER
1842#define GC_TRIGGERS static_assert(false, "TriggersGC not supported in utilcode contracts")
1843
1844#ifdef ENABLE_CONTRACTS_IMPL
1845template <UINT_PTR VIOLATION_MASK>
1846class ContractViolationHolder
1847{
1848public:
1849 ContractViolationHolder()
1850 {
1851 m_pviolationmask = NULL;
1852 m_oldviolationmask = 0;
1853 }
1854
1855 DEBUG_NOINLINE void Enter();
1856
1857 DEBUG_NOINLINE void Leave()
1858 {
1859 SCAN_SCOPE_END;
1860 LeaveInternal();
1861 };
1862
1863protected:
1864 // We require that violationMask is passed as a parameter here to hopefully defeat the
1865 // compiler's desire to fold all the Enter and Ctor implementations together.
1866 FORCEINLINE void EnterInternal(UINT_PTR violationMask)
1867 {
1868 _ASSERTE(0 == (violationMask & ~(ThrowsViolation | GCViolation | ModeViolation | FaultViolation |
1869 FaultNotFatal | SOToleranceViolation | HostViolation |
1870 TakesLockViolation | LoadsTypeViolation)) ||
1871 violationMask == AllViolation);
1872
1873 m_pviolationmask = GetClrDebugState()->ViolationMaskPtr();
1874 m_oldviolationmask = *m_pviolationmask;
1875 *m_pviolationmask = (m_oldviolationmask | violationMask);
1876 };
1877
1878 FORCEINLINE void LeaveInternal()
1879 {
1880 // This can be used in places where our debug state has been destroyed, so check for it first.
1881 if (CheckClrDebugState())
1882 {
1883 _ASSERTE(m_pviolationmask != NULL);
1884 *m_pviolationmask = m_oldviolationmask;
1885 }
1886 };
1887
1888 UINT_PTR *m_pviolationmask;
1889 UINT_PTR m_oldviolationmask;
1890};
1891
1892template <UINT_PTR VIOLATION_MASK>
1893class AutoCleanupContractViolationHolder : ContractViolationHolder<VIOLATION_MASK>
1894{
1895public:
1896 DEBUG_NOINLINE AutoCleanupContractViolationHolder(BOOL fEnterViolation = TRUE);
1897
1898 DEBUG_NOINLINE ~AutoCleanupContractViolationHolder()
1899 {
1900 SCAN_SCOPE_END;
1901 this->LeaveInternal();
1902 };
1903};
1904
1905#endif // ENABLE_CONTRACTS_IMPL
1906
1907#ifdef ENABLE_CONTRACTS_IMPL
1908#define BEGIN_CONTRACT_VIOLATION(violationmask) \
1909 { \
1910 ContractViolationHolder<violationmask> __violationHolder_onlyOneAllowedPerScope; \
1911 __violationHolder_onlyOneAllowedPerScope.Enter(); \
1912 DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \
1913
1914// Use this to jump out prematurely from a violation. Used for EH
1915// when the function might not return
1916#define RESET_CONTRACT_VIOLATION() \
1917 __violationHolder_onlyOneAllowedPerScope.Leave(); \
1918
1919#define END_CONTRACT_VIOLATION \
1920 DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \
1921 __violationHolder_onlyOneAllowedPerScope.Leave(); \
1922 } \
1923
1924// See description near the top of the file
1925#define CONTRACT_VIOLATION(violationMask) \
1926 AutoCleanupContractViolationHolder<violationMask> __violationHolder_onlyOneAllowedPerScope;
1927
1928
1929// Reasons for having the violation. Use one of these values as an additional parameter to
1930// E.g. PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonContractInfrastructure)
1931// New values and explanations can be added when needed.
1932enum PermanentContractViolationReason
1933{
1934 ReasonContractInfrastructure, // This violation is there for contract test or infrastructure purposes.
1935 ReasonDebugOnly, // Code path doesn't occur on retail builds
1936 ReasonNonShippingCode, // Code runs in undocumented non-shipping feature
1937 ReasonIBC, // Code runs in IBC scenarios only and the violation is safe.
1938 ReasonNGEN, // Code runs in NGEN scenarios only and the violation is safe.
1939 ReasonProfilerCallout, // Profiler implementers are guaranteed not to throw.
1940 ReasonUnsupportedForSQLF1Profiling, // This code path violates HOST_NOCALLS, but that's ok b/c SQL will never
1941 // invoke it, and thus SQL/F1 profiling (the primary reason to enforce
1942 // HOST_NOCALLS) is not in danger.
1943 ReasonRuntimeReentrancy, // e.g. SafeQueryInterface
1944 ReasonShutdownOnly, // Code path only runs as part of Shutdown and the violation is safe.
1945 ReasonSOTolerance, // We would like to redesign SO contracts anyways
1946 ReasonStartupOnly, // Code path only runs as part of Startup and the violation is safe.
1947 ReasonWorkaroundForScanBug, // Violation is needed because of a bug in SCAN
1948 ReasonProfilerAsyncCannotRetakeLock, // Profiler may call this from redirected thread, causing a CANNOT_TAKE_LOCK
1949 // violation, but the scope is still protected with CANNOT_RETAKE_LOCK
1950 ReasonILStubWillNotThrow, // Specially-crafted reverse COM IL stubs will not throw
1951};
1952
1953// See the discussion near the top of the file on the use of PERMANENT_CONTRACT_VIOLATION
1954// The reasonEnum is currently only used for documentation and searchability. Here
1955// we have the compiler check for a typo.
1956#define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum) \
1957 if (0) \
1958 PermanentContractViolationReason reason = reasonEnum; \
1959 CONTRACT_VIOLATION(violationMask)
1960
1961#define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition) \
1962 AutoCleanupContractViolationHolder<violationMask> __violationHolder_onlyOneAllowedPerScope((condition));
1963
1964#else
1965#define BEGIN_CONTRACT_VIOLATION(violationmask)
1966#define RESET_CONTRACT_VIOLATION()
1967#define END_CONTRACT_VIOLATION
1968#define CONTRACT_VIOLATION(violationmask)
1969#define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition)
1970#define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum)
1971#endif
1972
1973
1974
1975#ifdef ENABLE_CONTRACTS_IMPL
1976// Holder for setting up a faultforbid region
1977class FaultForbidHolder
1978{
1979 public:
1980 DEBUG_NOINLINE FaultForbidHolder(BOOL fConditional, BOOL fAlloc, const char *szFunction, const char *szFile, int lineNum)
1981 {
1982 SCAN_SCOPE_BEGIN;
1983 STATIC_CONTRACT_FORBID_FAULT;
1984
1985 m_fConditional = fConditional;
1986 if (m_fConditional)
1987 {
1988 m_pClrDebugState = GetClrDebugState(fAlloc);
1989
1990 //
1991 // If we fail to get a debug state, then we must not be allocating and
1992 // we simply no-op this holder.
1993 //
1994 if (m_pClrDebugState == NULL)
1995 {
1996 _ASSERTE(!fAlloc);
1997 m_fConditional = FALSE;
1998 return;
1999 }
2000
2001 m_oldClrDebugState = *m_pClrDebugState;
2002
2003 m_pClrDebugState->ViolationMaskReset( FaultViolation|FaultNotFatal );
2004 m_pClrDebugState->SetFaultForbid();
2005
2006 m_ContractStackRecord.m_szFunction = szFunction;
2007 m_ContractStackRecord.m_szFile = szFile;
2008 m_ContractStackRecord.m_lineNum = lineNum;
2009 m_ContractStackRecord.m_testmask = (Contract::ALL_Disabled & ~((UINT)(Contract::FAULT_Mask))) | Contract::FAULT_Forbid;
2010 m_ContractStackRecord.m_construct = "FAULT_FORBID";
2011 m_pClrDebugState->LinkContractStackTrace( &m_ContractStackRecord );
2012 }
2013 }
2014
2015 DEBUG_NOINLINE ~FaultForbidHolder()
2016 {
2017 SCAN_SCOPE_END;
2018
2019 if (m_fConditional)
2020 {
2021 *m_pClrDebugState = m_oldClrDebugState;
2022 }
2023 }
2024
2025 private:
2026 ClrDebugState *m_pClrDebugState;
2027 ClrDebugState m_oldClrDebugState;
2028 BOOL m_fConditional;
2029 ContractStackRecord m_ContractStackRecord;
2030
2031};
2032#endif // ENABLE_CONTRACTS_IMPL
2033
2034
2035#ifdef ENABLE_CONTRACTS_IMPL
2036
2037#define FAULT_FORBID() FaultForbidHolder _ffh(TRUE, TRUE, __FUNCTION__, __FILE__, __LINE__);
2038#define FAULT_FORBID_NO_ALLOC() FaultForbidHolder _ffh(TRUE, FALSE, __FUNCTION__, __FILE__, __LINE__);
2039#define MAYBE_FAULT_FORBID(cond) FaultForbidHolder _ffh(cond, TRUE, __FUNCTION__, __FILE__, __LINE__);
2040#define MAYBE_FAULT_FORBID_NO_ALLOC(cond) FaultForbidHolder _ffh(cond, FALSE, __FUNCTION__, __FILE__, __LINE__);
2041
2042#else // ENABLE_CONTRACTS_IMPL
2043
2044#define FAULT_FORBID() ;
2045#define FAULT_FORBID_NO_ALLOC() ;
2046#define MAYBE_FAULT_FORBID(cond) ;
2047#define MAYBE_FAULT_FORBID_NO_ALLOC(cond) ;
2048
2049#endif // ENABLE_CONTRACTS_IMPL
2050
2051
2052#ifdef ENABLE_CONTRACTS_IMPL
2053
2054inline BOOL AreFaultsForbiddenHelper()
2055{
2056 STATIC_CONTRACT_DEBUG_ONLY;
2057 STATIC_CONTRACT_NOTHROW;
2058
2059 ClrDebugState *pClrDebugState = CheckClrDebugState();
2060 if (!pClrDebugState)
2061 {
2062 // By default, faults are not forbidden. Not the most desirable default
2063 // but we'd never get this debug infrastructure bootstrapped otherwise.
2064 return FALSE;
2065 }
2066 else
2067 {
2068 return pClrDebugState->IsFaultForbid() && (!(pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState)));
2069 }
2070}
2071
2072#define ARE_FAULTS_FORBIDDEN() AreFaultsForbiddenHelper()
2073#else
2074
2075// If you got an error about ARE_FAULTS_FORBIDDEN being undefined, it's because you tried
2076// to use this predicate in a free build outside of a CONTRACT or ASSERT.
2077//
2078#define ARE_FAULTS_FORBIDDEN() (sizeof(YouCannotUseThisHere) != 0)
2079#endif
2080
2081
2082// This allows a fault-forbid region to invoke a non-mandatory allocation, such as for the
2083// purpose of growing a lookaside cache (if the allocation fails, the code can abandon the
2084// cache growing operation without negative effect.)
2085//
2086// Although it's implemented using CONTRACT_VIOLATION(), it's not a bug to have this in the code.
2087//
2088// It *is* a bug to use this to hide a situation where an OOM is genuinely fatal but not handled.
2089#define FAULT_NOT_FATAL() CONTRACT_VIOLATION(FaultNotFatal)
2090
2091
2092
2093#ifdef ENABLE_CONTRACTS_IMPL
2094
2095//------------------------------------------------------------------------------------
2096// Underlying class support for TRIGGERS_TYPE_LOAD and OVERRIDE_TYPE_LOAD_LEVEL_LIMIT.
2097// Don't reference this class directly. Use the macros.
2098//------------------------------------------------------------------------------------
2099class LoadsTypeHolder
2100{
2101 public:
2102 LoadsTypeHolder(BOOL fConditional,
2103 UINT newLevel,
2104 BOOL fEnforceLevelChangeDirection,
2105 const char *szFunction,
2106 const char *szFile,
2107 int lineNum
2108 );
2109
2110 ~LoadsTypeHolder();
2111
2112 private:
2113 ClrDebugState *m_pClrDebugState;
2114 ClrDebugState m_oldClrDebugState;
2115 BOOL m_fConditional;
2116 ContractStackRecord m_contractStackRecord;
2117
2118};
2119
2120#endif // ENABLE_CONTRACTS_IMPL
2121
2122
2123//------------------------------------------------------------------------------------
2124// TRIGGERS_TYPE_LOAD(newLevel)
2125// Works just LOADS_TYPE in contracts but lets you protect individual scopes
2126//
2127// OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel)
2128// Sets a new limit just like TRIGGERS_TYPE_LOAD but does not restrict you
2129// to decreasing the limit. Only the loader should use this and only when it
2130// can prove structurally that no recursion will occur as a result.
2131//------------------------------------------------------------------------------------
2132#ifdef ENABLE_CONTRACTS_IMPL
2133
2134#define TRIGGERS_TYPE_LOAD(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__);
2135#define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__);
2136#define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__);
2137#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__);
2138
2139#else // ENABLE_CONTRACTS_IMPL
2140
2141#define TRIGGERS_TYPE_LOAD(newLevel)
2142#define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable)
2143#define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel)
2144#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable)
2145
2146#endif // ENABLE_CONTRACTS_IMPL
2147
2148
2149
2150#ifdef ENABLE_CONTRACTS_IMPL
2151class PAL_TryMarker
2152{
2153public:
2154 DEBUG_NOINLINE void Enter();
2155 DEBUG_NOINLINE void Leave();
2156};
2157
2158#define PAL_ENTER_THROWS_REGION \
2159 PAL_TryMarker __throwsHolder_onlyOneAllowedPerScope; \
2160 __throwsHolder_onlyOneAllowedPerScope.Enter();
2161
2162#define PAL_LEAVE_THROWS_REGION \
2163 __throwsHolder_onlyOneAllowedPerScope.Leave();
2164
2165// This sets up a marker that says its okay to throw on this thread. This is not a public macro, and should only be
2166// used from within the implementation of various try/catch macros.
2167class ClrTryMarkerHolder
2168{
2169public:
2170 DEBUG_NOINLINE ClrTryMarkerHolder()
2171 {
2172 SCAN_SCOPE_BEGIN;
2173 STATIC_CONTRACT_THROWS;
2174
2175 m_pClrDebugState = GetClrDebugState();
2176 m_oldOkayToThrowValue = m_pClrDebugState->IsOkToThrow();
2177 m_pClrDebugState->SetOkToThrow();
2178 }
2179
2180 DEBUG_NOINLINE ~ClrTryMarkerHolder()
2181 {
2182 SCAN_SCOPE_END;
2183
2184 m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue );
2185 }
2186
2187private:
2188 BOOL m_oldOkayToThrowValue;
2189 ClrDebugState *m_pClrDebugState;
2190};
2191
2192#define CLR_TRY_MARKER() ClrTryMarkerHolder ___tryMarkerHolder;
2193
2194#else // ENABLE_CONTRACTS_IMPL
2195
2196#define CLR_TRY_MARKER()
2197#define PAL_ENTER_THROWS_REGION
2198#define PAL_LEAVE_THROWS_REGION
2199
2200#endif
2201
2202#ifdef ENABLE_CONTRACTS_IMPL
2203// Note: This routine will create a ClrDebugState if called for the first time.
2204// It cannot return NULL (see comment for InitClrDebugState).
2205inline ClrDebugState *GetClrDebugState(BOOL fAlloc)
2206{
2207 STATIC_CONTRACT_LIMITED_METHOD;
2208 STATIC_CONTRACT_SO_NOT_MAINLINE;
2209
2210 ClrDebugState *pState = CheckClrDebugState();
2211
2212 if (pState)
2213 {
2214 return pState;
2215 }
2216
2217 if (fAlloc)
2218 {
2219 return CLRInitDebugState();
2220 }
2221
2222 return NULL;
2223}
2224#endif // ENABLE_CONTRACTS_IMPL
2225
2226#ifdef FEATURE_STACK_PROBE
2227
2228#ifdef ENABLE_CONTRACTS_IMPL
2229class SONotMainlineHolder
2230{
2231 public:
2232 DEBUG_NOINLINE void Enter()
2233 {
2234 SCAN_SCOPE_BEGIN;
2235 STATIC_CONTRACT_SO_NOT_MAINLINE;
2236
2237 m_pClrDebugState = GetClrDebugState();
2238 if (m_pClrDebugState)
2239 {
2240 m_oldSONotMainlineValue = m_pClrDebugState->IsSONotMainline();
2241 m_pClrDebugState->SetSONotMainline();
2242 }
2243 }
2244
2245 DEBUG_NOINLINE void Leave()
2246 {
2247 SCAN_SCOPE_END;
2248
2249 m_pClrDebugState = CheckClrDebugState();
2250 if (m_pClrDebugState)
2251 {
2252 m_pClrDebugState->SetSONotMainline( m_oldSONotMainlineValue );
2253 }
2254 }
2255
2256 private:
2257 BOOL m_oldSONotMainlineValue;
2258 ClrDebugState *m_pClrDebugState;
2259};
2260
2261#define ENTER_SO_NOT_MAINLINE_CODE \
2262 SONotMainlineHolder __soNotMainlineHolder; \
2263 __soNotMainlineHolder.Enter();
2264
2265#define LEAVE_SO_NOT_MAINLINE_CODE \
2266 __soNotMainlineHolder.Leave();
2267
2268
2269class AutoCleanupSONotMainlineHolder : public SONotMainlineHolder
2270{
2271 public:
2272 DEBUG_NOINLINE AutoCleanupSONotMainlineHolder()
2273 {
2274 SCAN_SCOPE_BEGIN;
2275 STATIC_CONTRACT_SO_NOT_MAINLINE;
2276
2277 Enter();
2278 }
2279
2280 DEBUG_NOINLINE ~AutoCleanupSONotMainlineHolder()
2281 {
2282 SCAN_SCOPE_END;
2283
2284 Leave();
2285 }
2286};
2287
2288#define SO_NOT_MAINLINE_FUNCTION \
2289 AutoCleanupSONotMainlineHolder __soNotMainlineHolder;
2290
2291#define SO_NOT_MAINLINE_REGION() \
2292 AutoCleanupSONotMainlineHolder __soNotMainlineHolder;
2293
2294#else // ENABLE_CONTRACTS_IMPL
2295#define SO_NOT_MAINLINE_FUNCTION STATIC_CONTRACT_SO_NOT_MAINLINE
2296#define SO_NOT_MAINLINE_REGION() STATIC_CONTRACT_SO_NOT_MAINLINE
2297#define ENTER_SO_NOT_MAINLINE_CODE
2298#define LEAVE_SO_NOT_MAINLINE_CODE
2299#endif
2300
2301#else // FEATURE_STACK_PROBE
2302
2303#define SO_NOT_MAINLINE_FUNCTION
2304#define SO_NOT_MAINLINE_REGION()
2305#define ENTER_SO_NOT_MAINLINE_CODE
2306#define LEAVE_SO_NOT_MAINLINE_CODE
2307
2308#endif // FEATURE_STACK_PROBE
2309
2310#ifdef ENABLE_CONTRACTS_IMPL
2311
2312class HostNoCallHolder
2313{
2314 public:
2315 DEBUG_NOINLINE HostNoCallHolder()
2316 {
2317 SCAN_SCOPE_BEGIN;
2318 STATIC_CONTRACT_HOST_NOCALLS;
2319
2320 m_clrDebugState = GetClrDebugState();
2321 m_previousState = m_clrDebugState->SetHostCaller(FALSE);
2322 }
2323
2324 DEBUG_NOINLINE ~HostNoCallHolder()
2325 {
2326 SCAN_SCOPE_END;
2327
2328 m_clrDebugState->SetHostCaller(m_previousState);
2329 }
2330
2331 private:
2332 BOOL m_previousState;
2333 ClrDebugState* m_clrDebugState;
2334
2335};
2336
2337#define BEGIN_HOST_NOCALL_CODE \
2338 { \
2339 HostNoCallHolder __hostNoCallHolder; \
2340 CantAllocHolder __cantAlloc;
2341
2342#define END_HOST_NOCALL_CODE \
2343 }
2344
2345#else // ENABLE_CONTRACTS_IMPL
2346#define BEGIN_HOST_NOCALL_CODE \
2347 { \
2348 CantAllocHolder __cantAlloc; \
2349
2350#define END_HOST_NOCALL_CODE \
2351 }
2352#endif
2353
2354#ifdef ENABLE_CONTRACTS_IMPL
2355
2356class GetThreadAllowedHolder
2357{
2358 public:
2359 GetThreadAllowedHolder(BOOL newState)
2360 {
2361 m_clrDebugState = ::GetClrDebugState();
2362 m_previousState = m_clrDebugState->SetGetThreadAllowed(newState);
2363 }
2364
2365 ~GetThreadAllowedHolder()
2366 {
2367 m_clrDebugState->SetGetThreadAllowed(m_previousState);
2368 }
2369
2370private:
2371 BOOL m_previousState;
2372 ClrDebugState* m_clrDebugState;
2373};
2374
2375// When in an EE_THREAD_NOT_REQUIRED contracted scope, it's expected that the
2376// function does not assume an EE Thread object is available in TLS. Either
2377// GetThread() is never called, or any code path that requires a Thread
2378// has another code path that deals with the absence of a Thread. Any call to
2379// to GetThread() must be bracketed with BEGIN_GETTHREAD_ALLOWED /
2380// END_GETTHREAD_ALLOWED to avoid bogus asserts (the short-form
2381// GetThreadNULLOk() may be used as well). However, this is only allowed if visual
2382// inspection of the call site makes it patently obvious that the function deals
2383// appropriately with the GetThread() == NULL case (or that case has already been
2384// dealt with and control has exited before the BEGIN_GETTHREAD_ALLOWED /
2385// END_GETTHREAD_ALLOWED block.
2386//
2387// These use holder objects, which causes the compiler to generate EH code and prevent
2388// inlining. So try to avoid these in small, downstream functions (like inline
2389// EE Thread member functions). Use the _IN_NO_THROW_REGION variants below instead.
2390
2391#define BEGIN_GETTHREAD_ALLOWED \
2392 { \
2393 GetThreadAllowedHolder __getThreadAllowedHolder(TRUE); \
2394
2395#define END_GETTHREAD_ALLOWED \
2396 }
2397
2398// These are lighter-weight versions of BEGIN_GETTHREAD_ALLOWED /
2399// END_GETTHREAD_ALLOWED. These don't use holders, so be sure only to
2400// use these to bracket code that won't throw exceptions
2401#define BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION \
2402 { \
2403 ClrDebugState * __clrDebugState = ::GetClrDebugState(); \
2404 BOOL __previousState = __clrDebugState->SetGetThreadAllowed(TRUE); \
2405
2406#define END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION \
2407 __clrDebugState->SetGetThreadAllowed(__previousState); \
2408 }
2409
2410#else // ENABLE_CONTRACTS_IMPL
2411#define BEGIN_GETTHREAD_ALLOWED
2412#define END_GETTHREAD_ALLOWED
2413#define BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION
2414#define END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION
2415#endif
2416
2417#if defined(ENABLE_CONTRACTS_IMPL)
2418
2419// Macros to indicate we're taking or releasing locks
2420
2421// Most general macros, not used directly
2422#define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) \
2423 ::GetClrDebugState()->LockTaken((dbgStateLockType), (cEntrances), (void*) (pvLock), __FUNCTION__, __FILE__, __LINE__)
2424#define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) \
2425 ::GetClrDebugState()->LockReleased((dbgStateLockType), (cExits), (void*) (pvLock))
2426
2427// Use these only if you need to force multiple entrances or exits in a single
2428// line (e.g., to restore the lock to a previous state). CRWLock in vm\rwlock.cpp does this
2429#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \
2430 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, cEntrances, pvLock)
2431#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \
2432 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, cExits, pvLock)
2433#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) \
2434 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cEntrances, pvLock)
2435#define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) \
2436 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cExits, pvLock)
2437#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \
2438 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, cEntrances, pvLock)
2439#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \
2440 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, cExits, pvLock)
2441
2442// These are most typically used
2443#define EE_LOCK_TAKEN(pvLock) \
2444 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, 1, pvLock)
2445#define EE_LOCK_RELEASED(pvLock) \
2446 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, 1, pvLock)
2447#define HOST_BREAKABLE_CRST_TAKEN(pvLock) \
2448 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock)
2449#define HOST_BREAKABLE_CRST_RELEASED(pvLock) \
2450 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock)
2451#define USER_LOCK_TAKEN(pvLock) \
2452 LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, 1, pvLock)
2453#define USER_LOCK_RELEASED(pvLock) \
2454 LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, 1, pvLock)
2455
2456#else // defined(ENABLE_CONTRACTS_IMPL)
2457
2458#define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock)
2459#define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock)
2460#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock)
2461#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock)
2462#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock)
2463#define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock)
2464#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock)
2465#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock)
2466#define EE_LOCK_TAKEN(pvLock)
2467#define EE_LOCK_RELEASED(pvLock)
2468#define HOST_BREAKABLE_CRST_TAKEN(pvLock)
2469#define HOST_BREAKABLE_CRST_RELEASED(pvLock)
2470#define USER_LOCK_TAKEN(pvLock)
2471#define USER_LOCK_RELEASED(pvLock)
2472
2473#endif // defined(ENABLE_CONTRACTS_IMPL)
2474
2475#if defined(ENABLE_CONTRACTS_IMPL)
2476
2477// Abbreviation for an assert that is only considered if there is a valid
2478// ClrDebugState available. Useful if you want to assert based on the value
2479// of GetDbgStateLockCount(), where a return of 0 (the default if there is no
2480// valid ClrDebugState available) would cause your assert to fire. The variable
2481// __pClrDebugState is set to the current ClrDebugState, and may be used within
2482// your assert expression
2483#define ASSERT_UNLESS_NO_DEBUG_STATE(e) \
2484 { \
2485 ClrDebugState * __pClrDebugState = GetClrDebugState(); \
2486 _ASSERTE(((__pClrDebugState->ViolationMask() & BadDebugState) != 0) || (e)); \
2487 }
2488
2489#else // defined(ENABLE_CONTRACTS_IMPL)
2490
2491#define ASSERT_UNLESS_NO_DEBUG_STATE(e)
2492
2493#endif // defined(ENABLE_CONTRACTS_IMPL)
2494
2495
2496//-----------------------------------------------------------------------------
2497// Debug support to ensure that nobody calls New on the helper thread.
2498// This is for interop debugging.
2499// They should be using the InteropSafe heap.
2500// Having this in the meantime allows us to
2501// assert that the helper thread never calls new, and maintain a finite list of
2502// exceptions (bugs).
2503// Eventually, all those bugs should be fixed this holder can be completely removed.
2504//
2505// It is also the case that we disallow allocations when any thread is OS suspended
2506// This happens for a short time when we are suspending the EE. We supress both
2507// of these.
2508//
2509// @todo- ideally this would be rolled into the ContractViolation.
2510// also, we'd have contract bit for whether APIs can be called on the helper thread.
2511// @todo - if we really wanted to be strict, we should make this per-thread.
2512//-----------------------------------------------------------------------------
2513#ifdef ENABLE_CONTRACTS_IMPL
2514extern Volatile<LONG> g_DbgSuppressAllocationAsserts;
2515#define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE CounterHolder _AllowNewOnHelperHolder(&g_DbgSuppressAllocationAsserts);
2516#else
2517// Nothing in retail since this holder just disabled an assert.
2518#define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE
2519#endif
2520
2521
2522//-----------------------------------------------------------------------------
2523// Support for contracts in DAC builds
2524//
2525// At the moment, most of the contract system is disabled in DAC builds.
2526// We do however want some simple static contracts in order to support static
2527// analysis tools that run on mscordacwks.dll like DacCop.
2528// Note that we want these static contracts in both DEBUG and retail builds.
2529// We also already get simple static contracts like WRAPPER and LEAF.
2530//
2531//-----------------------------------------------------------------------------
2532#if defined(DACCESS_COMPILE)
2533
2534// SUPPORTS_DAC is an annotation that says the function is designed to be used in DAC builds.
2535// This enables full DacCop analysis on the function, including verifying that all functions that are
2536// called also support DAC.
2537#define SUPPORTS_DAC do { STATIC_CONTRACT_SUPPORTS_DAC; } while(0)
2538
2539// Normally a function can be annotated just with WRAPPER_NO_CONTRACT, which (in addition to the normal
2540// contract meaning) indicates to DacCop that the function should be considered to support DAC when
2541// it is called from a supports-dac function. This is to avoid having to add a DAC-specific contract
2542// to all the trivial one-line wrapper functions we have.
2543// However, we occasionally want these semantics even for functions which are not appropriate to label
2544// as WRAPPER_NO_CONTRACT. For example, a template function may support DAC for certain template arguments,
2545// but not others (due to the functions it calls). We want to ensure that when such a function is called
2546// in a DAC code path, analysis is enabled on that particular instantiation including checking all of the
2547// call targets specific to this template instantiation. But we don't want to require that the call targets
2548// for ALL instantiations support dac, since we may not even be using them in DAC code paths. Ideally we'd
2549// remove any such code from the DAC build, but this will take time.
2550#define SUPPORTS_DAC_WRAPPER do { STATIC_CONTRACT_WRAPPER; } while(0)
2551
2552// SUPPORTS_DAC_HOST_ONLY indicates that a function is allowed to be called in DAC builds, but rather
2553// than being a normal DAC function which operates on marshalled data, it is a host-only utility function
2554// that knows nothing about DAC and operates solely on the host. For example, DbgAssertDialog is a utility
2555// function for popping assert dialogs - there is nothing DAC-specific about this. Ideally such utility
2556// functions would be confined to their own library which had no access to DAC functionality, and which
2557// is not analyzed by DacCop. At the moment splitting utilcode into two variations like this is too
2558// painful, but we hope to do it in the future (primarily to support functions which can be used in either
2559// DAC or host-only mode).
2560// WARNING: This contract disables DacCop analysis on the function and any functions it calls, so it
2561// should be used very carefully.
2562#define SUPPORTS_DAC_HOST_ONLY do { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; } while(0)
2563
2564#else
2565#define SUPPORTS_DAC
2566#define SUPPORTS_DAC_HOST_ONLY
2567#define SUPPORTS_DAC_WRAPPER
2568#endif // DACCESS_COMPILE
2569
2570// LIMITED_METHOD_DAC_CONTRACT is a shortcut for LIMITED_METHOD_CONTRACT and SUPPORTS_DAC. Usefull for one-line inline functions.
2571#define LIMITED_METHOD_DAC_CONTRACT LIMITED_METHOD_CONTRACT; SUPPORTS_DAC
2572
2573//
2574// The default contract is the recommended contract for ordinary code.
2575// The ordinary code can throw or trigger GC any time, does not operate
2576// on raw object refs, etc.
2577//
2578
2579#define STANDARD_VM_CHECK \
2580 THROWS; \
2581 SO_INTOLERANT; \
2582
2583#define STANDARD_VM_CONTRACT \
2584 CONTRACTL \
2585 { \
2586 STANDARD_VM_CHECK; \
2587 } \
2588 CONTRACTL_END; \
2589
2590#define STATIC_STANDARD_VM_CONTRACT \
2591 STATIC_CONTRACT_THROWS; \
2592 STATIC_CONTRACT_GC_TRIGGERS; \
2593 STATIC_CONTRACT_MODE_PREEMPTIVE; \
2594 STATIC_CONTRACT_SO_INTOLERANT
2595
2596#define AFTER_CONTRACTS
2597#include "volatile.h"
2598
2599#endif // CONTRACT_H_
2600