1/*
2 * Copyright (C) 2003-2019 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#pragma once
27
28#include <wtf/Platform.h>
29
30/*
31 no namespaces because this file has to be includable from C and Objective-C
32
33 Note, this file uses many GCC extensions, but it should be compatible with
34 C, Objective C, C++, and Objective C++.
35
36 For non-debug builds, everything is disabled by default except for "always
37 on" logging. Defining any of the symbols explicitly prevents this from
38 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 <stdlib.h>
48#include <wtf/ExportMacros.h>
49
50#if USE(OS_LOG)
51#include <os/log.h>
52#endif
53
54#ifdef __cplusplus
55#include <cstdlib>
56#include <type_traits>
57
58#if OS(WINDOWS)
59#if !COMPILER(GCC_COMPATIBLE)
60extern "C" void _ReadWriteBarrier(void);
61#pragma intrinsic(_ReadWriteBarrier)
62#endif
63#include <intrin.h>
64#endif
65#endif
66
67#ifdef NDEBUG
68/* Disable ASSERT* macros in release mode. */
69#define ASSERTIONS_DISABLED_DEFAULT 1
70#else
71#define ASSERTIONS_DISABLED_DEFAULT 0
72#endif
73
74#ifndef BACKTRACE_DISABLED
75#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
76#endif
77
78#ifndef ASSERT_DISABLED
79#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
80#endif
81
82#ifndef ASSERT_MSG_DISABLED
83#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
84#endif
85
86#ifndef ASSERT_ARG_DISABLED
87#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
88#endif
89
90#ifndef FATAL_DISABLED
91#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
92#endif
93
94#ifndef ERROR_DISABLED
95#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
96#endif
97
98#ifndef LOG_DISABLED
99#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
100#endif
101
102#ifndef RELEASE_LOG_DISABLED
103#define RELEASE_LOG_DISABLED !(USE(OS_LOG))
104#endif
105
106#if COMPILER(GCC_COMPATIBLE)
107#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
108#else
109#define WTF_PRETTY_FUNCTION __FUNCTION__
110#endif
111
112#if COMPILER(MINGW)
113/* By default MinGW emits warnings when C99 format attributes are used, even if __USE_MINGW_ANSI_STDIO is defined */
114#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(gnu_printf, formatStringArgument, extraArguments)))
115#elif COMPILER(GCC_COMPATIBLE) && !defined(__OBJC__)
116/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
117 emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
118 the attribute when being used from Objective-C code in case it decides to use %@. */
119#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
120#else
121#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
122#endif
123
124#if PLATFORM(IOS_FAMILY)
125/* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
126#ifndef WTF_EXPORT_PRIVATE
127#define WTF_EXPORT_PRIVATE
128#endif
129#endif // PLATFORM(IOS_FAMILY)
130
131/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
132
133#ifdef __cplusplus
134extern "C" {
135#endif
136
137/* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
138
139 Use CRASH() in response to known, unrecoverable errors like out-of-memory.
140 Macro is enabled in both debug and release mode.
141 To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
142
143 Signals are ignored by the crash reporter on OS X so we must do better.
144*/
145#if COMPILER(GCC_COMPATIBLE) || COMPILER(MSVC)
146#define NO_RETURN_DUE_TO_CRASH NO_RETURN
147#else
148#define NO_RETURN_DUE_TO_CRASH
149#endif
150
151#ifdef __cplusplus
152enum class WTFLogChannelState : uint8_t { Off, On, OnWithAccumulation };
153#undef Always
154enum class WTFLogLevel : uint8_t { Always, Error, Warning, Info, Debug };
155#else
156typedef uint8_t WTFLogChannelState;
157typedef uint8_t WTFLogLevel;
158#endif
159
160typedef struct {
161 WTFLogChannelState state;
162 const char* name;
163 WTFLogLevel level;
164#if !RELEASE_LOG_DISABLED
165 const char* subsystem;
166 __unsafe_unretained os_log_t osLogChannel;
167#endif
168} WTFLogChannel;
169
170#define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
171#define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
172#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
173#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
174
175#define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
176
177#define DECLARE_LOG_CHANNEL(name) \
178 extern WTFLogChannel LOG_CHANNEL(name);
179
180#if !defined(DEFINE_LOG_CHANNEL)
181#if RELEASE_LOG_DISABLED
182#define DEFINE_LOG_CHANNEL(name, subsystem) \
183 WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1 };
184#else
185#define DEFINE_LOG_CHANNEL(name, subsystem) \
186 WTFLogChannel LOG_CHANNEL(name) = { (WTFLogChannelState)0, #name, (WTFLogLevel)1, subsystem, OS_LOG_DEFAULT };
187#endif
188#endif
189
190WTF_EXPORT_PRIVATE void WTFReportNotImplementedYet(const char* file, int line, const char* function);
191WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
192WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
193WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
194WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
195WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
196WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
197WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
198WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
199WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
200WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
201WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
202WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
203WTF_EXPORT_PRIVATE void WTFLogWithLevel(WTFLogChannel*, WTFLogLevel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(3, 4);
204WTF_EXPORT_PRIVATE void WTFSetLogChannelLevel(WTFLogChannel*, WTFLogLevel);
205WTF_EXPORT_PRIVATE bool WTFWillLogWithLevel(WTFLogChannel*, WTFLogLevel);
206
207WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
208WTF_EXPORT_PRIVATE void WTFReportBacktrace(void);
209WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
210#if !RELEASE_LOG_DISABLED
211WTF_EXPORT_PRIVATE void WTFReleaseLogStackTrace(WTFLogChannel*);
212#endif
213
214WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached(void);
215
216#if COMPILER(MSVC)
217#define WTFBreakpointTrap() __debugbreak()
218#elif ASAN_ENABLED
219#define WTFBreakpointTrap() __builtin_trap()
220#elif CPU(X86_64) || CPU(X86)
221#define WTFBreakpointTrap() asm volatile ("int3")
222#elif CPU(ARM_THUMB2)
223#define WTFBreakpointTrap() asm volatile ("bkpt #0")
224#elif CPU(ARM64)
225#define WTFBreakpointTrap() asm volatile ("brk #0")
226#else
227#define WTFBreakpointTrap() WTFCrash() // Not implemented.
228#endif
229
230#if COMPILER(MSVC)
231#define WTFBreakpointTrapUnderConstexprContext() __debugbreak()
232#else
233#define WTFBreakpointTrapUnderConstexprContext() __builtin_trap()
234#endif
235
236#ifndef CRASH
237
238#if defined(NDEBUG) && (OS(DARWIN) || PLATFORM(PLAYSTATION))
239// Crash with a SIGTRAP i.e EXC_BREAKPOINT.
240// We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
241// trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
242#define CRASH() do { \
243 WTFBreakpointTrap(); \
244 __builtin_unreachable(); \
245} while (0)
246#define CRASH_UNDER_CONSTEXPR_CONTEXT() do { \
247 WTFBreakpointTrapUnderConstexprContext(); \
248 __builtin_unreachable(); \
249} while (0)
250#elif !ENABLE(DEVELOPER_MODE) && !OS(DARWIN)
251#ifdef __cplusplus
252#define CRASH() std::abort()
253#define CRASH_UNDER_CONSTEXPR_CONTEXT() std::abort()
254#else
255#define CRASH() abort()
256#define CRASH_UNDER_CONSTEXPR_CONTEXT() abort()
257#endif // __cplusplus
258#else
259#define CRASH() WTFCrash()
260#define CRASH_UNDER_CONSTEXPR_CONTEXT() WTFCrash()
261#endif
262
263#endif // !defined(CRASH)
264
265WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash(void);
266
267#ifndef CRASH_WITH_SECURITY_IMPLICATION
268#define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
269#endif
270
271WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication(void);
272
273#ifdef __cplusplus
274}
275#endif
276
277/* BACKTRACE
278
279 Print a backtrace to the same location as ASSERT messages.
280*/
281
282#if BACKTRACE_DISABLED
283
284#define BACKTRACE() ((void)0)
285
286#else
287
288#define BACKTRACE() do { \
289 WTFReportBacktrace(); \
290} while(false)
291
292#endif
293
294/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
295
296 These macros are compiled out of release builds.
297 Expressions inside them are evaluated in debug builds only.
298*/
299
300#if OS(WINDOWS)
301/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
302#undef ASSERT
303#endif
304
305#if ASSERT_DISABLED
306
307#define ASSERT(assertion, ...) ((void)0)
308#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ((void)0)
309#define ASSERT_AT(assertion, file, line, function) ((void)0)
310#define ASSERT_NOT_REACHED(...) ((void)0)
311#define ASSERT_NOT_IMPLEMENTED_YET() ((void)0)
312#define ASSERT_IMPLIES(condition, assertion) ((void)0)
313#define NO_RETURN_DUE_TO_ASSERT
314
315#define ASSERT_UNUSED(variable, assertion, ...) ((void)variable)
316
317#if ENABLE(SECURITY_ASSERTIONS)
318#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
319 (!(assertion) ? \
320 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
321 CRASH_WITH_SECURITY_IMPLICATION()) : \
322 (void)0)
323
324#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
325#else
326#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
327#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
328#endif
329
330#else
331
332#define ASSERT(assertion, ...) do { \
333 if (!(assertion)) { \
334 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
335 CRASH_WITH_INFO(__VA_ARGS__); \
336 } \
337} while (0)
338
339#define ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
340 if (!(assertion)) { \
341 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
342 CRASH_UNDER_CONSTEXPR_CONTEXT(); \
343 } \
344} while (0)
345
346#define ASSERT_AT(assertion, file, line, function) do { \
347 if (!(assertion)) { \
348 WTFReportAssertionFailure(file, line, function, #assertion); \
349 CRASH(); \
350 } \
351} while (0)
352
353#define ASSERT_NOT_REACHED(...) do { \
354 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
355 CRASH_WITH_INFO(__VA_ARGS__); \
356} while (0)
357
358#define ASSERT_NOT_IMPLEMENTED_YET() do { \
359 WTFReportNotImplementedYet(__FILE__, __LINE__, WTF_PRETTY_FUNCTION); \
360 CRASH(); \
361} while (0)
362
363#define ASSERT_IMPLIES(condition, assertion) do { \
364 if ((condition) && !(assertion)) { \
365 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition " => " #assertion); \
366 CRASH(); \
367 } \
368} while (0)
369
370#define ASSERT_UNUSED(variable, assertion, ...) ASSERT(assertion, __VA_ARGS__)
371
372#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
373
374/* ASSERT_WITH_SECURITY_IMPLICATION
375
376 Failure of this assertion indicates a possible security vulnerability.
377 Class of vulnerabilities that it tests include bad casts, out of bounds
378 accesses, use-after-frees, etc. Please file a bug using the security
379 template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
380
381*/
382#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
383 (!(assertion) ? \
384 (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
385 CRASH_WITH_SECURITY_IMPLICATION()) : \
386 (void)0)
387#define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
388#endif
389
390/* ASSERT_WITH_MESSAGE */
391
392#if ASSERT_MSG_DISABLED
393#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
394#else
395#define ASSERT_WITH_MESSAGE(assertion, ...) do { \
396 if (!(assertion)) { \
397 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
398 CRASH(); \
399 } \
400} while (0)
401#endif
402
403#ifdef __cplusplus
404constexpr bool assertionFailureDueToUnreachableCode = false;
405#define ASSERT_NOT_REACHED_WITH_MESSAGE(...) ASSERT_WITH_MESSAGE(assertionFailureDueToUnreachableCode, __VA_ARGS__)
406#endif
407
408/* ASSERT_WITH_MESSAGE_UNUSED */
409
410#if ASSERT_MSG_DISABLED
411#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
412#else
413#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
414 if (!(assertion)) { \
415 WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
416 CRASH(); \
417 } \
418} while (0)
419#endif
420
421
422/* ASSERT_ARG */
423
424#if ASSERT_ARG_DISABLED
425
426#define ASSERT_ARG(argName, assertion) ((void)0)
427
428#else
429
430#define ASSERT_ARG(argName, assertion) do { \
431 if (!(assertion)) { \
432 WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
433 CRASH(); \
434 } \
435} while (0)
436
437#endif
438
439/* COMPILE_ASSERT */
440#ifndef COMPILE_ASSERT
441#if COMPILER_SUPPORTS(C_STATIC_ASSERT)
442/* Unlike static_assert below, this also works in plain C code. */
443#define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
444#else
445#define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
446#endif
447#endif
448
449/* FATAL */
450
451#if FATAL_DISABLED
452#define FATAL(...) ((void)0)
453#else
454#define FATAL(...) do { \
455 WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
456 CRASH(); \
457} while (0)
458#endif
459
460/* LOG_ERROR */
461
462#if ERROR_DISABLED
463#define LOG_ERROR(...) ((void)0)
464#else
465#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
466#endif
467
468/* LOG */
469
470#if LOG_DISABLED
471#define LOG(channel, ...) ((void)0)
472#else
473#define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
474#endif
475
476/* LOG_VERBOSE */
477
478#if LOG_DISABLED
479#define LOG_VERBOSE(channel, ...) ((void)0)
480#else
481#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
482#endif
483
484/* LOG_WITH_LEVEL */
485
486#if LOG_DISABLED
487#define LOG_WITH_LEVEL(channel, level, ...) ((void)0)
488#else
489#define LOG_WITH_LEVEL(channel, level, ...) WTFLogWithLevel(&LOG_CHANNEL(channel), level, __VA_ARGS__)
490#endif
491
492/* RELEASE_LOG */
493
494#if RELEASE_LOG_DISABLED
495#define RELEASE_LOG(channel, ...) ((void)0)
496#define RELEASE_LOG_ERROR(channel, ...) LOG_ERROR(__VA_ARGS__)
497#define RELEASE_LOG_FAULT(channel, ...) LOG_ERROR(__VA_ARGS__)
498#define RELEASE_LOG_INFO(channel, ...) ((void)0)
499
500#define RELEASE_LOG_IF(isAllowed, channel, ...) ((void)0)
501#define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
502#define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) ((void)0)
503
504#define RELEASE_LOG_WITH_LEVEL(channel, level, ...) ((void)0)
505#define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, level, ...) do { if (isAllowed) RELEASE_LOG_WITH_LEVEL(channel, level, __VA_ARGS__); } while (0)
506
507#define RELEASE_LOG_STACKTRACE(channel) ((void)0)
508#else
509#define RELEASE_LOG(channel, ...) os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
510#define RELEASE_LOG_ERROR(channel, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
511#define RELEASE_LOG_FAULT(channel, ...) os_log_fault(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
512#define RELEASE_LOG_INFO(channel, ...) os_log_info(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__)
513
514#define RELEASE_LOG_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG( channel, __VA_ARGS__); } while (0)
515#define RELEASE_LOG_ERROR_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, __VA_ARGS__); } while (0)
516#define RELEASE_LOG_INFO_IF(isAllowed, channel, ...) do { if (isAllowed) RELEASE_LOG_INFO(channel, __VA_ARGS__); } while (0)
517
518#define RELEASE_LOG_WITH_LEVEL(channel, logLevel, ...) do { \
519 if (LOG_CHANNEL(channel).level >= (logLevel)) \
520 os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
521} while (0)
522
523#define RELEASE_LOG_WITH_LEVEL_IF(isAllowed, channel, logLevel, ...) do { \
524 if ((isAllowed) && LOG_CHANNEL(channel).level >= (logLevel)) \
525 os_log(LOG_CHANNEL(channel).osLogChannel, __VA_ARGS__); \
526} while (0)
527
528#define RELEASE_LOG_STACKTRACE(channel) WTFReleaseLogStackTrace(&LOG_CHANNEL(channel))
529#endif
530
531
532/* RELEASE_ASSERT */
533
534#if ASSERT_DISABLED
535#define RELEASE_ASSERT(assertion, ...) do { \
536 if (UNLIKELY(!(assertion))) \
537 CRASH_WITH_INFO(__VA_ARGS__); \
538} while (0)
539#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
540#define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) RELEASE_ASSERT(assertion)
541#define RELEASE_ASSERT_NOT_REACHED(...) CRASH_WITH_INFO(__VA_ARGS__)
542#define RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) do { \
543 if (UNLIKELY(!(assertion))) { \
544 CRASH_UNDER_CONSTEXPR_CONTEXT(); \
545 } \
546} while (0)
547#else
548#define RELEASE_ASSERT(assertion, ...) ASSERT(assertion, __VA_ARGS__)
549#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
550#define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
551#define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
552#define RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion) ASSERT_UNDER_CONSTEXPR_CONTEXT(assertion)
553#endif
554
555#ifdef __cplusplus
556#define RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE(...) RELEASE_ASSERT_WITH_MESSAGE(assertionFailureDueToUnreachableCode, __VA_ARGS__)
557
558// The combination of line, file, function, and counter should be a unique number per call to this crash. This tricks the compiler into not coalescing calls to WTFCrashWithInfo.
559// The easiest way to fill these values per translation unit is to pass __LINE__, __FILE__, WTF_PRETTY_FUNCTION, and __COUNTER__.
560WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5, uint64_t misc6);
561WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5);
562WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4);
563WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3);
564WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1, uint64_t misc2);
565WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason, uint64_t misc1);
566WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfoImpl(int line, const char* file, const char* function, int counter, uint64_t reason);
567NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void WTFCrashWithInfo(int line, const char* file, const char* function, int counter);
568
569template<typename T>
570ALWAYS_INLINE uint64_t wtfCrashArg(T* arg) { return reinterpret_cast<uintptr_t>(arg); }
571
572template<typename T>
573ALWAYS_INLINE uint64_t wtfCrashArg(T arg) { return arg; }
574
575template<typename T>
576NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason)
577{
578 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
579}
580
581template<typename T, typename U>
582NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1)
583{
584 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1));
585}
586
587template<typename T, typename U, typename V>
588NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2)
589{
590 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2));
591}
592
593template<typename T, typename U, typename V, typename W>
594NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3)
595{
596 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3));
597}
598
599template<typename T, typename U, typename V, typename W, typename X>
600NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4)
601{
602 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4));
603}
604
605template<typename T, typename U, typename V, typename W, typename X, typename Y>
606NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4, Y misc5)
607{
608 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4), wtfCrashArg(misc5));
609}
610
611template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
612NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char* file, const char* function, int counter, T reason, U misc1, V misc2, W misc3, X misc4, Y misc5, Z misc6)
613{
614 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason), wtfCrashArg(misc1), wtfCrashArg(misc2), wtfCrashArg(misc3), wtfCrashArg(misc4), wtfCrashArg(misc5), wtfCrashArg(misc6));
615}
616
617inline void WTFCrashWithInfo(int, const char*, const char*, int)
618#if COMPILER(CLANG)
619 __attribute__((optnone))
620#endif
621{
622 CRASH();
623}
624
625namespace WTF {
626inline void isIntegralOrPointerType() { }
627
628template<typename T, typename... Types>
629void isIntegralOrPointerType(T, Types... types)
630{
631 static_assert(std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value, "All types need to be bitwise_cast-able to integral type for logging");
632 isIntegralOrPointerType(types...);
633}
634}
635
636inline void compilerFenceForCrash()
637{
638#if OS(WINDOWS) && !COMPILER(GCC_COMPATIBLE)
639 _ReadWriteBarrier();
640#else
641 asm volatile("" ::: "memory");
642#endif
643}
644
645#ifndef CRASH_WITH_INFO
646// This is useful if you are going to stuff data into registers before crashing, like the
647// crashWithInfo functions below.
648#if COMPILER(CLANG) || COMPILER(MSVC)
649#define CRASH_WITH_INFO(...) do { \
650 WTF::isIntegralOrPointerType(__VA_ARGS__); \
651 compilerFenceForCrash(); \
652 WTFCrashWithInfo(__LINE__, __FILE__, WTF_PRETTY_FUNCTION, __COUNTER__, ##__VA_ARGS__); \
653 } while (false)
654#else
655// GCC does not allow ##__VA_ARGS__ unless GNU extensions are enabled (--std=gnu++NN instead of
656// --std=c++NN) and I think we don't want that, so we'll have a fallback path for GCC. Obviously
657// this will not actually succeed at getting the desired info into registers before crashing, but
658// it's just a fallback anyway.
659//
660// FIXME: When we enable C++20, we should replace ##__VA_ARGS__ with format __VA_OPT__(,) __VA_ARGS__
661// so that we can remove this fallback.
662inline NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(...)
663{
664 CRASH();
665}
666
667// We must define this here because CRASH_WITH_INFO() is not defined as a macro.
668// FIXME: Remove this when upgrading to C++20.
669inline NO_RETURN_DUE_TO_CRASH void CRASH_WITH_SECURITY_IMPLICATION_AND_INFO(...)
670{
671 CRASH();
672}
673#endif
674#endif // CRASH_WITH_INFO
675
676#ifndef CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
677#define CRASH_WITH_SECURITY_IMPLICATION_AND_INFO CRASH_WITH_INFO
678#endif // CRASH_WITH_SECURITY_IMPLICATION_AND_INFO
679
680#else /* not __cplusplus */
681
682#ifndef CRASH_WITH_INFO
683#define CRASH_WITH_INFO() CRASH()
684#endif
685
686#endif /* __cplusplus */
687
688/* UNREACHABLE_FOR_PLATFORM */
689
690#if COMPILER(CLANG)
691// This would be a macro except that its use of #pragma works best around
692// a function. Hence it uses macro naming convention.
693IGNORE_WARNINGS_BEGIN("missing-noreturn")
694static inline void UNREACHABLE_FOR_PLATFORM()
695{
696 // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
697 // going.
698 RELEASE_ASSERT_NOT_REACHED();
699}
700IGNORE_WARNINGS_END
701#else
702#define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
703#endif
704