1/*
2 * Copyright (C) 2003, 2006, 2007, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef WTF_Assertions_h
27#define WTF_Assertions_h
28
29#include <wtf/Platform.h>
30
31/*
32 no namespaces because this file has to be includable from C and Objective-C
33
34 Note, this file uses many GCC extensions, but it should be compatible with
35 C, Objective C, C++, and Objective C++.
36
37 For non-debug builds, everything is disabled by default.
38 Defining any of the symbols explicitly prevents this from having any effect.
39*/
40
41#undef __STDC_FORMAT_MACROS
42#define __STDC_FORMAT_MACROS
43#include <inttypes.h>
44#include <stdarg.h>
45#include <stdbool.h>
46#include <stddef.h>
47#include <wtf/ExportMacros.h>
48
49#ifdef NDEBUG
50/* Disable ASSERT* macros in release mode. */
51#define ASSERTIONS_DISABLED_DEFAULT 1
52#else
53#define ASSERTIONS_DISABLED_DEFAULT 0
54#endif
55
56#ifndef BACKTRACE_DISABLED
57#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
58#endif
59
60#ifndef ASSERT_DISABLED
61#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
62#endif
63
64#ifndef ASSERT_MSG_DISABLED
65#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
66#endif
67
68#ifndef ASSERT_ARG_DISABLED
69#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
70#endif
71
72#ifndef FATAL_DISABLED
73#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
74#endif
75
76#ifndef ERROR_DISABLED
77#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
78#endif
79
80#ifndef LOG_DISABLED
81#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
82#endif
83
84#if COMPILER(GCC_OR_CLANG)
85#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
86#else
87#define WTF_PRETTY_FUNCTION __FUNCTION__
88#endif
89
90#if COMPILER(MINGW)
91/* By default MinGW emits warnings when C99 format attributes are used, even if __USE_MINGW_ANSI_STDIO is defined */
92#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(gnu_printf, formatStringArgument, extraArguments)))
93#elif COMPILER(GCC_OR_CLANG) && !defined(__OBJC__)
94/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
95 emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
96 the attribute when being used from Objective-C code in case it decides to use %@. */
97#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
98#else
99#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
100#endif
101
102#if PLATFORM(IOS)
103/* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
104#ifndef WTF_EXPORT_PRIVATE
105#define WTF_EXPORT_PRIVATE
106#endif
107#endif // PLATFORM(IOS)
108
109/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
110
111#ifdef __cplusplus
112extern "C" {
113#endif
114
115/* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
116
117 Use CRASH() in response to known, unrecoverable errors like out-of-memory.
118 Macro is enabled in both debug and release mode.
119 To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
120
121 Signals are ignored by the crash reporter on OS X so we must do better.
122*/
123#if COMPILER(GCC_OR_CLANG) || COMPILER(MSVC)
124#define NO_RETURN_DUE_TO_CRASH NO_RETURN
125#else
126#define NO_RETURN_DUE_TO_CRASH
127#endif
128
129typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState;
130
131typedef struct {
132 WTFLogChannelState state;
133 const char* name;
134} WTFLogChannel;
135
136WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
137WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
138WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
139WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
140WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
141WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
142WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
143WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
144WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
145WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
146WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
147WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
148
149WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
150WTF_EXPORT_PRIVATE void WTFReportBacktrace();
151WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
152
153typedef void (*WTFCrashHookFunction)();
154WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
155WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook();
156
157WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached();
158
159#ifndef CRASH
160
161#if defined(NDEBUG) && OS(DARWIN)
162#if CPU(X86_64) || CPU(X86)
163#define WTFBreakpointTrap() __asm__ volatile ("int3")
164#elif CPU(ARM_THUMB2)
165#define WTFBreakpointTrap() __asm__ volatile ("bkpt #0")
166#elif CPU(ARM64)
167#define WTFBreakpointTrap() __asm__ volatile ("brk #0")
168#else
169#error "Unsupported CPU".
170#endif
171
172// Crash with a SIGTRAP i.e EXC_BREAKPOINT.
173// We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
174// trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
175#define CRASH() do { \
176 WTFBreakpointTrap(); \
177 __builtin_unreachable(); \
178} while (0)
179#else
180#define CRASH() WTFCrash()
181#endif
182
183#endif // CRASH
184
185WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash();
186
187#ifndef CRASH_WITH_SECURITY_IMPLICATION
188#define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
189#endif
190
191WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication();
192
193#ifdef __cplusplus
194}
195#endif
196
197/* BACKTRACE
198
199 Print a backtrace to the same location as ASSERT messages.
200*/
201
202#if BACKTRACE_DISABLED
203
204#define BACKTRACE() ((void)0)
205
206#else
207
208#define BACKTRACE() do { \
209 WTFReportBacktrace(); \
210} while(false)
211
212#endif
213
214/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
215
216 These macros are compiled out of release builds.
217 Expressions inside them are evaluated in debug builds only.
218*/
219
220#if OS(WINDOWS)
221/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
222#undef ASSERT
223#endif
224
225#if ASSERT_DISABLED
226
227#define ASSERT(assertion) ((void)0)
228#define ASSERT_AT(assertion, file, line, function) ((void)0)
229#define ASSERT_NOT_REACHED() ((void)0)
230#define NO_RETURN_DUE_TO_ASSERT
231
232#define ASSERT_UNUSED(variable, assertion) ((void)variable)
233
234#if ENABLE(SECURITY_ASSERTIONS)
235#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
236 (!(assertion) ? \
237 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
238 CRASH_WITH_SECURITY_IMPLICATION()) : \
239 (void)0)
240
241#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
242#else
243#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
244#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
245#endif
246
247#else
248
249#define ASSERT(assertion) do { \
250 if (!(assertion)) { \
251 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
252 CRASH(); \
253 } \
254} while (0)
255
256#define ASSERT_AT(assertion, file, line, function) do { \
257 if (!(assertion)) { \
258 WTFReportAssertionFailure(file, line, function, #assertion); \
259 CRASH(); \
260 } \
261} while (0)
262
263#define ASSERT_NOT_REACHED() do { \
264 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
265 CRASH(); \
266} while (0)
267
268#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
269
270#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
271
272/* ASSERT_WITH_SECURITY_IMPLICATION
273
274 Failure of this assertion indicates a possible security vulnerability.
275 Class of vulnerabilities that it tests include bad casts, out of bounds
276 accesses, use-after-frees, etc. Please file a bug using the security
277 template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
278
279*/
280#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
281 (!(assertion) ? \
282 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
283 CRASH_WITH_SECURITY_IMPLICATION()) : \
284 (void)0)
285#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
286#endif
287
288/* ASSERT_WITH_MESSAGE */
289
290#if ASSERT_MSG_DISABLED
291#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
292#else
293#define ASSERT_WITH_MESSAGE(assertion, ...) do { \
294 if (!(assertion)) { \
295 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
296 CRASH(); \
297 } \
298} while (0)
299#endif
300
301/* ASSERT_WITH_MESSAGE_UNUSED */
302
303#if ASSERT_MSG_DISABLED
304#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
305#else
306#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
307 if (!(assertion)) { \
308 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
309 CRASH(); \
310 } \
311} while (0)
312#endif
313
314
315/* ASSERT_ARG */
316
317#if ASSERT_ARG_DISABLED
318
319#define ASSERT_ARG(argName, assertion) ((void)0)
320
321#else
322
323#define ASSERT_ARG(argName, assertion) do { \
324 if (!(assertion)) { \
325 WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
326 CRASH(); \
327 } \
328} while (0)
329
330#endif
331
332/* COMPILE_ASSERT */
333#ifndef COMPILE_ASSERT
334#if COMPILER_SUPPORTS(C_STATIC_ASSERT)
335/* Unlike static_assert below, this also works in plain C code. */
336#define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
337#else
338#define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
339#endif
340#endif
341
342/* FATAL */
343
344#if FATAL_DISABLED
345#define FATAL(...) ((void)0)
346#else
347#define FATAL(...) do { \
348 WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
349 CRASH(); \
350} while (0)
351#endif
352
353/* LOG_ERROR */
354
355#if ERROR_DISABLED
356#define LOG_ERROR(...) ((void)0)
357#else
358#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
359#endif
360
361/* LOG */
362
363#if LOG_DISABLED
364#define LOG(channel, ...) ((void)0)
365#else
366#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
367#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
368#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
369#endif
370
371/* LOG_VERBOSE */
372
373#if LOG_DISABLED
374#define LOG_VERBOSE(channel, ...) ((void)0)
375#else
376#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
377#endif
378
379/* RELEASE_ASSERT */
380
381#if ASSERT_DISABLED
382#define RELEASE_ASSERT(assertion) do { \
383 if (UNLIKELY(!(assertion))) \
384 CRASH(); \
385} while (0)
386#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
387#define RELEASE_ASSERT_NOT_REACHED() CRASH()
388#else
389#define RELEASE_ASSERT(assertion) ASSERT(assertion)
390#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
391#define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
392#endif
393
394/* UNREACHABLE_FOR_PLATFORM */
395
396#if COMPILER(CLANG)
397// This would be a macro except that its use of #pragma works best around
398// a function. Hence it uses macro naming convention.
399#pragma clang diagnostic push
400#pragma clang diagnostic ignored "-Wmissing-noreturn"
401static inline void UNREACHABLE_FOR_PLATFORM()
402{
403 RELEASE_ASSERT_NOT_REACHED();
404}
405#pragma clang diagnostic pop
406#else
407#define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
408#endif
409
410
411#endif /* WTF_Assertions_h */
412