Welcome to mirror list, hosted at ThFree Co, Russian Federation.

debugmacros.h « inc « coreclr « src - github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e6124828d769bcf1cba5abdd34e26031888e54c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//*****************************************************************************
// DebugMacros.h
//
// Wrappers for Debugging purposes.
//
//*****************************************************************************

#ifndef __DebugMacros_h__
#define __DebugMacros_h__

#include "stacktrace.h"
#include "debugmacrosext.h"
#include "palclr.h"

#undef _ASSERTE
#undef VERIFY

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#if defined(_DEBUG)

class SString;
bool GetStackTraceAtContext(SString & s, struct _CONTEXT * pContext);

void _cdecl DbgWriteEx(LPCTSTR szFmt, ...);
bool _DbgBreakCheck(LPCSTR szFile, int iLine, LPCSTR szExpr, BOOL fConstrained = FALSE);

extern VOID ANALYZER_NORETURN DbgAssertDialog(const char *szFile, int iLine, const char *szExpr);

#define TRACE_BUFF_SIZE (cchMaxAssertStackLevelStringLen * cfrMaxAssertStackLevels + cchMaxAssertExprLen + 1)
extern char g_szExprWithStack[TRACE_BUFF_SIZE];

extern int _DbgBreakCount;

#define PRE_ASSERTE         /* if you need to change modes before doing asserts override */
#define POST_ASSERTE        /* put it back */

#if !defined(_ASSERTE_MSG)
  #define _ASSERTE_MSG(expr, msg)                                           \
        do {                                                                \
             if (!(expr)) {                                                 \
                PRE_ASSERTE                                                 \
                DbgAssertDialog(__FILE__, __LINE__, msg);                   \
                POST_ASSERTE                                                \
             }                                                              \
        } while (0)
#endif // _ASSERTE_MSG

#if !defined(_ASSERTE)
  #define _ASSERTE(expr) _ASSERTE_MSG(expr, #expr)
#endif  // !_ASSERTE


#define VERIFY(stmt) _ASSERTE((stmt))

#define _ASSERTE_ALL_BUILDS(file, expr) _ASSERTE((expr))

#define FreeBuildDebugBreak() DebugBreak()

#else // !_DEBUG

#define _DbgBreakCount  0

#define _ASSERTE(expr) ((void)0)
#define _ASSERTE_MSG(expr, msg) ((void)0)
#define VERIFY(stmt) (void)(stmt)

void __FreeBuildDebugBreak();
void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr);

#define FreeBuildDebugBreak() __FreeBuildDebugBreak()

// At this point, EEPOLICY_HANDLE_FATAL_ERROR may or may not be defined. It will be defined
// if we are building the VM folder, but outside VM, its not necessarily defined.
//
// Thus, if EEPOLICY_HANDLE_FATAL_ERROR is not defined, we will call into __FreeBuildAssertFail,
// but if it is defined, we will use it.
//
// Failing here implies an error in the runtime - hence we use COR_E_EXECUTIONENGINE.

#ifdef EEPOLICY_HANDLE_FATAL_ERROR
#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
#else // !EEPOLICY_HANDLE_FATAL_ERROR
#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) __FreeBuildAssertFail(file, __LINE__, #expr);
#endif // EEPOLICY_HANDLE_FATAL_ERROR

#endif


#define ASSERT_AND_CHECK(x) {       \
    BOOL bResult = x;               \
    if (!bResult)                   \
    {                               \
        _ASSERTE(x);                \
        return FALSE;               \
    }                               \
}


#ifdef _DEBUG_IMPL

// A macro to execute a statement only in _DEBUG_IMPL.
#define DEBUG_IMPL_STMT(stmt) stmt

#define _ASSERTE_IMPL(expr) _ASSERTE((expr))

#if     defined(_M_IX86)
#if defined(_MSC_VER)
#define _DbgBreak() __asm { int 3 }
#elif defined(__GNUC__)
#define _DbgBreak() __asm__ ("int $3");
#else
#error Unknown compiler
#endif
#else
#define _DbgBreak() DebugBreak()
#endif

extern VOID DebBreak();
extern VOID DebBreakHr(HRESULT hr);

#ifndef IfFailGoto
#define IfFailGoto(EXPR, LABEL) \
do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); goto LABEL; } } while (0)
#endif

#ifndef IfFailRet
#define IfFailRet(EXPR) \
do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); return (hr); } } while (0)
#endif

#ifndef IfFailWin32Ret
#define IfFailWin32Ret(EXPR) \
do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); return hr;} } while (0)
#endif

#ifndef IfFailWin32Goto
#define IfFailWin32Goto(EXPR, LABEL) \
do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); goto LABEL; } } while (0)
#endif

#ifndef IfFailGo
#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)
#endif

#ifndef IfFailWin32Go
#define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit)
#endif

#else // _DEBUG_IMPL

#define _DbgBreak() {}

#define DEBUG_IMPL_STMT(stmt)

#define _ASSERTE_IMPL(expr)

#define IfFailGoto(EXPR, LABEL) \
do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0)

#define IfFailRet(EXPR) \
do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)

#define IfFailWin32Ret(EXPR) \
do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); return hr;} } while (0)

#define IfFailWin32Goto(EXPR, LABEL) \
do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); goto LABEL; } } while (0)

#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)

#define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit)

#endif // _DEBUG_IMPL


#define IfNullGoto(EXPR, LABEL) \
    do { if ((EXPR) == NULL) { OutOfMemory(); IfFailGoto(E_OUTOFMEMORY, LABEL); } } while (false)

#ifndef IfNullRet
#define IfNullRet(EXPR) \
    do { if ((EXPR) == NULL) { OutOfMemory(); return E_OUTOFMEMORY; } } while (false)
#endif //!IfNullRet

#define IfNullGo(EXPR) IfNullGoto(EXPR, ErrExit)

#ifdef __cplusplus
}

#endif // __cplusplus


#undef assert
#define assert _ASSERTE
#undef _ASSERT
#define _ASSERT _ASSERTE


#if defined(_DEBUG) && defined(HOST_WINDOWS)

// This function returns the EXE time stamp (effectively a random number)
// Under retail it always returns 0.  This is meant to be used in the
// RandomOnExe macro
unsigned DbgGetEXETimeStamp();

// returns true 'fractionOn' amount of the time using the EXE timestamp
// as the random number seed.  For example DbgRandomOnExe(.1) returns true 1/10
// of the time.  We use the line number so that different uses of DbgRandomOnExe
// will not be coorelated with each other (9973 is prime).  Returns false on a retail build
#define DbgRandomOnHashAndExe(hash, fractionOn) \
    (((DbgGetEXETimeStamp() * __LINE__ * ((hash) ? (hash) : 1)) % 9973) < \
     unsigned((fractionOn) * 9973))
#define DbgRandomOnExe(fractionOn) DbgRandomOnHashAndExe(0, fractionOn)
#define DbgRandomOnStringAndExe(string, fractionOn) DbgRandomOnHashAndExe(HashStringA(string), fractionOn)

#else

#define DbgGetEXETimeStamp() 0
#define DbgRandomOnHashAndExe(hash, fractionOn)  0
#define DbgRandomOnExe(fractionOn)  0
#define DbgRandomOnStringAndExe(fractionOn)  0

#endif // _DEBUG && !FEATUREPAL

#endif