4c80c6b9386b20ee73172ae13a47dc9fb93c5932
[WebKit-https.git] / Source / WTF / wtf / Assertions.cpp
1 /*
2  * Copyright (C) 2003-2017 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007-2009 Torch Mobile, Inc.
4  * Copyright (C) 2011 University of Szeged. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 // The vprintf_stderr_common function triggers this error in the Mac build.
29 // Feel free to remove this pragma if this file builds on Mac.
30 // According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
31 // we need to place this directive before any data or functions are defined.
32 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
33
34 #include "config.h"
35 #include "Assertions.h"
36
37 #include "Compiler.h"
38 #include <mutex>
39 #include <stdio.h>
40 #include <string.h>
41 #include <wtf/Lock.h>
42 #include <wtf/Locker.h>
43 #include <wtf/LoggingAccumulator.h>
44 #include <wtf/PrintStream.h>
45 #include <wtf/RetainPtr.h>
46 #include <wtf/StackTrace.h>
47 #include <wtf/StdLibExtras.h>
48 #include <wtf/StringExtras.h>
49 #include <wtf/text/CString.h>
50 #include <wtf/text/StringBuilder.h>
51 #include <wtf/text/WTFString.h>
52
53 #if HAVE(SIGNAL_H)
54 #include <signal.h>
55 #endif
56
57 #if USE(CF)
58 #include <CoreFoundation/CFString.h>
59 #if PLATFORM(COCOA)
60 #define USE_APPLE_SYSTEM_LOG 1
61 #include <asl.h>
62 #endif
63 #endif // USE(CF)
64
65 #if COMPILER(MSVC)
66 #include <crtdbg.h>
67 #endif
68
69 #if OS(WINDOWS)
70 #include <windows.h>
71 #endif
72
73 #if OS(DARWIN)
74 #include <sys/sysctl.h>
75 #include <unistd.h>
76 #endif
77
78 extern "C" {
79
80 static void logToStderr(const char* buffer)
81 {
82 #if USE(APPLE_SYSTEM_LOG)
83 #pragma clang diagnostic push
84 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
85     asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer);
86 #pragma clang diagnostic pop
87 #endif
88     fputs(buffer, stderr);
89 }
90
91 static const constexpr unsigned InitialBufferSize { 256 };
92
93 WTF_ATTRIBUTE_PRINTF(1, 0)
94 static void vprintf_stderr_common(const char* format, va_list args)
95 {
96 #if USE(CF) && !OS(WINDOWS)
97     if (strstr(format, "%@")) {
98         auto cfFormat = adoptCF(CFStringCreateWithCString(nullptr, format, kCFStringEncodingUTF8));
99
100 #if COMPILER(CLANG)
101 #pragma clang diagnostic push
102 #pragma clang diagnostic ignored "-Wformat-nonliteral"
103 #endif
104         auto str = adoptCF(CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfFormat.get(), args));
105 #if COMPILER(CLANG)
106 #pragma clang diagnostic pop
107 #endif
108         CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str.get()), kCFStringEncodingUTF8);
109         Vector<char, InitialBufferSize> buffer(length + 1);
110
111         CFStringGetCString(str.get(), buffer.data(), length, kCFStringEncodingUTF8);
112
113         logToStderr(buffer.data());
114         return;
115     }
116
117 #if USE(APPLE_SYSTEM_LOG)
118 #pragma clang diagnostic push
119 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
120     va_list copyOfArgs;
121     va_copy(copyOfArgs, args);
122     asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs);
123     va_end(copyOfArgs);
124 #pragma clang diagnostic pop
125 #endif
126
127     // Fall through to write to stderr in the same manner as other platforms.
128
129 #elif HAVE(ISDEBUGGERPRESENT)
130     if (IsDebuggerPresent()) {
131         size_t size = 1024;
132         Vector<char> buffer(size);
133         do {
134             buffer.grow(size);
135             if (vsnprintf(buffer.data(), size, format, args) != -1) {
136                 OutputDebugStringA(buffer.data());
137                 break;
138             }
139             size *= 2;
140         } while (size > 1024);
141     }
142 #endif
143     vfprintf(stderr, format, args);
144 }
145
146 #if COMPILER(GCC_OR_CLANG)
147 #pragma GCC diagnostic push
148 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
149 #endif
150
151 static void vprintf_stderr_with_prefix(const char* prefix, const char* format, va_list args)
152 {
153     size_t prefixLength = strlen(prefix);
154     size_t formatLength = strlen(format);
155     auto formatWithPrefix = std::make_unique<char[]>(prefixLength + formatLength + 1);
156     memcpy(formatWithPrefix.get(), prefix, prefixLength);
157     memcpy(formatWithPrefix.get() + prefixLength, format, formatLength);
158     formatWithPrefix[prefixLength + formatLength] = 0;
159
160     vprintf_stderr_common(formatWithPrefix.get(), args);
161 }
162
163 static void vprintf_stderr_with_trailing_newline(const char* format, va_list args)
164 {
165     size_t formatLength = strlen(format);
166     if (formatLength && format[formatLength - 1] == '\n') {
167         vprintf_stderr_common(format, args);
168         return;
169     }
170
171     auto formatWithNewline = std::make_unique<char[]>(formatLength + 2);
172     memcpy(formatWithNewline.get(), format, formatLength);
173     formatWithNewline[formatLength] = '\n';
174     formatWithNewline[formatLength + 1] = 0;
175
176     vprintf_stderr_common(formatWithNewline.get(), args);
177 }
178
179 #if COMPILER(GCC_OR_CLANG)
180 #pragma GCC diagnostic pop
181 #endif
182
183 WTF_ATTRIBUTE_PRINTF(1, 2)
184 static void printf_stderr_common(const char* format, ...)
185 {
186     va_list args;
187     va_start(args, format);
188     vprintf_stderr_common(format, args);
189     va_end(args);
190 }
191
192 static void printCallSite(const char* file, int line, const char* function)
193 {
194 #if OS(WINDOWS) && defined(_DEBUG)
195     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
196 #else
197     // By using this format, which matches the format used by MSVC for compiler errors, developers
198     // using Visual Studio can double-click the file/line number in the Output Window to have the
199     // editor navigate to that line of code. It seems fine for other developers, too.
200     printf_stderr_common("%s(%d) : %s\n", file, line, function);
201 #endif
202 }
203
204 void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
205 {
206     if (assertion)
207         printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
208     else
209         printf_stderr_common("SHOULD NEVER BE REACHED\n");
210     printCallSite(file, line, function);
211 }
212
213 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
214 {
215     va_list args;
216     va_start(args, format);
217     vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args);
218     va_end(args);
219     printf_stderr_common("\n%s\n", assertion);
220     printCallSite(file, line, function);
221 }
222
223 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
224 {
225     printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
226     printCallSite(file, line, function);
227 }
228
229 class CrashLogPrintStream : public PrintStream {
230 public:
231     WTF_ATTRIBUTE_PRINTF(2, 0)
232     void vprintf(const char* format, va_list argList) override
233     {
234         vprintf_stderr_common(format, argList);
235     }
236 };
237
238 void WTFReportBacktrace()
239 {
240     static const int framesToShow = 31;
241     static const int framesToSkip = 2;
242     void* samples[framesToShow + framesToSkip];
243     int frames = framesToShow + framesToSkip;
244
245     WTFGetBacktrace(samples, &frames);
246     WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip);
247 }
248
249 void WTFPrintBacktrace(void** stack, int size)
250 {
251     CrashLogPrintStream out;
252     StackTrace stackTrace(stack, size);
253     out.print(stackTrace);
254 }
255
256 static WTFCrashHookFunction globalHook = 0;
257
258 void WTFSetCrashHook(WTFCrashHookFunction function)
259 {
260     globalHook = function;
261 }
262
263 #if !defined(NDEBUG) || !OS(DARWIN)
264 void WTFCrash()
265 {
266     if (globalHook)
267         globalHook();
268
269     WTFReportBacktrace();
270 #if ASAN_ENABLED
271     __builtin_trap();
272 #else
273     *(int *)(uintptr_t)0xbbadbeef = 0;
274     // More reliable, but doesn't say BBADBEEF.
275 #if COMPILER(GCC_OR_CLANG)
276     __builtin_trap();
277 #else
278     ((void(*)())0)();
279 #endif // COMPILER(GCC_OR_CLANG)
280 #endif // ASAN_ENABLED
281 }
282 #else
283 // We need to keep WTFCrash() around (even on non-debug OS(DARWIN) builds) as a workaround
284 // for presently shipping (circa early 2016) SafariForWebKitDevelopment binaries which still
285 // expects to link to it.
286 void WTFCrash()
287 {
288     CRASH();
289 }
290 #endif // !defined(NDEBUG) || !OS(DARWIN)
291
292 void WTFCrashWithSecurityImplication()
293 {
294     CRASH();
295 }
296
297 #if HAVE(SIGNAL_H)
298 static NO_RETURN void dumpBacktraceSignalHandler(int sig)
299 {
300     WTFReportBacktrace();
301     exit(128 + sig);
302 }
303
304 static void installSignalHandlersForFatalErrors(void (*handler)(int))
305 {
306     signal(SIGILL, handler); //    4: illegal instruction (not reset when caught).
307     signal(SIGTRAP, handler); //   5: trace trap (not reset when caught).
308     signal(SIGFPE, handler); //    8: floating point exception.
309     signal(SIGBUS, handler); //   10: bus error.
310     signal(SIGSEGV, handler); //  11: segmentation violation.
311     signal(SIGSYS, handler); //   12: bad argument to system call.
312     signal(SIGPIPE, handler); //  13: write on a pipe with no reader.
313     signal(SIGXCPU, handler); //  24: exceeded CPU time limit.
314     signal(SIGXFSZ, handler); //  25: exceeded file size limit.
315 }
316
317 static void resetSignalHandlersForFatalErrors()
318 {
319     installSignalHandlersForFatalErrors(SIG_DFL);
320 }
321 #endif
322
323 void WTFInstallReportBacktraceOnCrashHook()
324 {
325 #if HAVE(SIGNAL_H)
326     // Needed otherwise we are going to dump the stack trace twice
327     // in case we hit an assertion.
328     WTFSetCrashHook(&resetSignalHandlersForFatalErrors);
329     installSignalHandlersForFatalErrors(&dumpBacktraceSignalHandler);
330 #endif
331 }
332
333 bool WTFIsDebuggerAttached()
334 {
335 #if OS(DARWIN)
336     struct kinfo_proc info;
337     int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
338     size_t size = sizeof(info);
339     if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &info, &size, nullptr, 0) == -1)
340         return false;
341     return info.kp_proc.p_flag & P_TRACED;
342 #else
343     return false;
344 #endif
345 }
346
347 void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
348 {
349     va_list args;
350     va_start(args, format);
351     vprintf_stderr_with_prefix("FATAL ERROR: ", format, args);
352     va_end(args);
353     printf_stderr_common("\n");
354     printCallSite(file, line, function);
355 }
356
357 void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
358 {
359     va_list args;
360     va_start(args, format);
361     vprintf_stderr_with_prefix("ERROR: ", format, args);
362     va_end(args);
363     printf_stderr_common("\n");
364     printCallSite(file, line, function);
365 }
366
367 class WTFLoggingAccumulator {
368 public:
369     void accumulate(const String&);
370     void resetAccumulatedLogs();
371     String getAndResetAccumulatedLogs();
372
373 private:
374     Lock accumulatorLock;
375     StringBuilder loggingAccumulator;
376 };
377
378 void WTFLoggingAccumulator::accumulate(const String& log)
379 {
380     Locker<Lock> locker(accumulatorLock);
381     loggingAccumulator.append(log);
382 }
383
384 void WTFLoggingAccumulator::resetAccumulatedLogs()
385 {
386     Locker<Lock> locker(accumulatorLock);
387     loggingAccumulator.clear();
388 }
389
390 String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
391 {
392     Locker<Lock> locker(accumulatorLock);
393     String result = loggingAccumulator.toString();
394     loggingAccumulator.clear();
395     return result;
396 }
397
398 static WTFLoggingAccumulator& loggingAccumulator()
399 {
400     static WTFLoggingAccumulator* accumulator;
401     static std::once_flag initializeAccumulatorOnce;
402     std::call_once(initializeAccumulatorOnce, [] {
403         accumulator = new WTFLoggingAccumulator;
404     });
405
406     return *accumulator;
407 }
408
409 void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
410 {
411     channel->level = level;
412 }
413
414 bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
415 {
416     return channel->level >= level && channel->state != WTFLogChannelOff;
417 }
418
419 void WTFLogWithLevel(WTFLogChannel* channel, WTFLogLevel level, const char* format, ...)
420 {
421     if (level != WTFLogLevelAlways && level > channel->level)
422         return;
423
424     if (channel->level != WTFLogLevelAlways && channel->state == WTFLogChannelOff)
425         return;
426
427     va_list args;
428     va_start(args, format);
429
430 #if COMPILER(CLANG)
431 #pragma clang diagnostic push
432 #pragma clang diagnostic ignored "-Wformat-nonliteral"
433 #endif
434     WTFLog(channel, format, args);
435 #if COMPILER(CLANG)
436 #pragma clang diagnostic pop
437 #endif
438
439     va_end(args);
440 }
441
442 void WTFLog(WTFLogChannel* channel, const char* format, ...)
443 {
444     if (channel->state == WTFLogChannelOff)
445         return;
446
447     if (channel->state == WTFLogChannelOn) {
448         va_list args;
449         va_start(args, format);
450         vprintf_stderr_with_trailing_newline(format, args);
451         va_end(args);
452         return;
453     }
454
455     ASSERT(channel->state == WTFLogChannelOnWithAccumulation);
456
457     va_list args;
458     va_start(args, format);
459
460 #if COMPILER(CLANG)
461 #pragma clang diagnostic push
462 #pragma clang diagnostic ignored "-Wformat-nonliteral"
463 #endif
464     String loggingString = String::format(format, args);
465 #if COMPILER(CLANG)
466 #pragma clang diagnostic pop
467 #endif
468
469     va_end(args);
470
471     if (!loggingString.endsWith('\n'))
472         loggingString.append('\n');
473
474     loggingAccumulator().accumulate(loggingString);
475
476     logToStderr(loggingString.utf8().data());
477 }
478
479 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
480 {
481     if (channel->state != WTFLogChannelOn)
482         return;
483
484     va_list args;
485     va_start(args, format);
486
487 #if COMPILER(CLANG)
488 #pragma clang diagnostic push
489 #pragma clang diagnostic ignored "-Wformat-nonliteral"
490 #endif
491     WTFLog(channel, format, args);
492 #if COMPILER(CLANG)
493 #pragma clang diagnostic pop
494 #endif
495
496     va_end(args);
497
498     printCallSite(file, line, function);
499 }
500
501 void WTFLogAlwaysV(const char* format, va_list args)
502 {
503     vprintf_stderr_with_trailing_newline(format, args);
504 }
505
506 void WTFLogAlways(const char* format, ...)
507 {
508     va_list args;
509     va_start(args, format);
510     WTFLogAlwaysV(format, args);
511     va_end(args);
512 }
513
514 void WTFLogAlwaysAndCrash(const char* format, ...)
515 {
516     va_list args;
517     va_start(args, format);
518     WTFLogAlwaysV(format, args);
519     va_end(args);
520     CRASH();
521 }
522
523 WTFLogChannel* WTFLogChannelByName(WTFLogChannel* channels[], size_t count, const char* name)
524 {
525     for (size_t i = 0; i < count; ++i) {
526         WTFLogChannel* channel = channels[i];
527         if (!strcasecmp(name, channel->name))
528             return channel;
529     }
530
531     return 0;
532 }
533
534 static void setStateOfAllChannels(WTFLogChannel* channels[], size_t channelCount, WTFLogChannelState state)
535 {
536     for (size_t i = 0; i < channelCount; ++i)
537         channels[i]->state = state;
538 }
539
540 void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t count, const char* logLevel)
541 {
542 #if !RELEASE_LOG_DISABLED
543     for (size_t i = 0; i < count; ++i) {
544         WTFLogChannel* channel = channels[i];
545         channel->osLogChannel = os_log_create(channel->subsystem, channel->name);
546     }
547 #endif
548
549     String logLevelString = logLevel;
550     Vector<String> components;
551     logLevelString.split(',', components);
552
553     for (size_t i = 0; i < components.size(); ++i) {
554         Vector<String> componentInfo;
555         components[i].split('=', componentInfo);
556         String component = componentInfo[0].stripWhiteSpace();
557
558         WTFLogChannelState logChannelState = WTFLogChannelOn;
559         if (component.startsWith('-')) {
560             logChannelState = WTFLogChannelOff;
561             component = component.substring(1);
562         }
563
564         if (equalLettersIgnoringASCIICase(component, "all")) {
565             setStateOfAllChannels(channels, count, logChannelState);
566             continue;
567         }
568
569         WTFLogLevel logChannelLevel = WTFLogLevelError;
570         if (componentInfo.size() > 1) {
571             String level = componentInfo[1].stripWhiteSpace();
572             if (equalLettersIgnoringASCIICase(level, "error"))
573                 logChannelLevel = WTFLogLevelError;
574             else if (equalLettersIgnoringASCIICase(level, "warning"))
575                 logChannelLevel = WTFLogLevelWarning;
576             else if (equalLettersIgnoringASCIICase(level, "info"))
577                 logChannelLevel = WTFLogLevelInfo;
578             else if (equalLettersIgnoringASCIICase(level, "debug"))
579                 logChannelLevel = WTFLogLevelDebug;
580             else
581                 WTFLogAlways("Unknown logging level: %s", level.utf8().data());
582         }
583
584         if (WTFLogChannel* channel = WTFLogChannelByName(channels, count, component.utf8().data())) {
585             channel->state = logChannelState;
586             channel->level = logChannelLevel;
587         } else
588             WTFLogAlways("Unknown logging channel: %s", component.utf8().data());
589     }
590 }
591
592 } // extern "C"
593
594 #if OS(DARWIN) && (CPU(X86_64) || CPU(ARM64))
595 #if CPU(X86_64)
596 #define STUFF_REGISTER_FOR_CRASH(reg, info) __asm__ volatile ("movq %0, %%" reg : : "r" (static_cast<uint64_t>(info)) : reg)
597
598 // This ordering was chosen to be consistent with JSC's JIT asserts. We probably shouldn't change this ordering
599 // since it would make tooling crash reports much harder. If, for whatever reason, we decide to change the ordering
600 // here we should update the abortWithuint64_t functions.
601 #define STUFF_FOR_CRASH_REGISTER1 "r11"
602 #define STUFF_FOR_CRASH_REGISTER2 "r10"
603 #define STUFF_FOR_CRASH_REGISTER3 "r9"
604 #define STUFF_FOR_CRASH_REGISTER4 "r8"
605 #define STUFF_FOR_CRASH_REGISTER5 "r15"
606
607 #elif CPU(ARM64) // CPU(X86_64)
608 #define STUFF_REGISTER_FOR_CRASH(reg, info) __asm__ volatile ("mov " reg ", %0" : : "r" (static_cast<uint64_t>(info)) : reg)
609
610 // See comment above on the ordering.
611 #define STUFF_FOR_CRASH_REGISTER1 "x16"
612 #define STUFF_FOR_CRASH_REGISTER2 "x17"
613 #define STUFF_FOR_CRASH_REGISTER3 "x18"
614 #define STUFF_FOR_CRASH_REGISTER4 "x19"
615 #define STUFF_FOR_CRASH_REGISTER5 "x20"
616
617 #endif // CPU(ARM64)
618
619 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4)
620 {
621     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
622     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
623     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
624     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
625     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER5, misc4);
626     CRASH();
627 }
628
629 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3)
630 {
631     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
632     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
633     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
634     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
635     CRASH();
636 }
637
638 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2)
639 {
640     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
641     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
642     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
643     CRASH();
644 }
645
646 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1)
647 {
648     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
649     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
650     CRASH();
651 }
652
653 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason)
654 {
655     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
656     CRASH();
657 }
658
659 void WTFCrashWithInfo(int, const char*, const char*, int)
660 {
661     CRASH();
662 }
663
664 #else
665
666 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
667 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
668 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
669 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t) { CRASH(); }
670 void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t) { CRASH(); }
671 void WTFCrashWithInfo(int, const char*, const char*, int) { CRASH(); }
672
673 #endif // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
674
675 namespace WTF {
676
677 void resetAccumulatedLogs()
678 {
679     loggingAccumulator().resetAccumulatedLogs();
680 }
681
682 String getAndResetAccumulatedLogs()
683 {
684     return loggingAccumulator().getAndResetAccumulatedLogs();
685 }
686
687 } // namespace WTF