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