9ab7809a256e6bc40000baddbd73e0b7f05407d2
[WebKit.git] / Source / WTF / wtf / Assertions.cpp
1 /*
2  * Copyright (C) 2003-2019 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 <wtf/Assertions.h>
36
37 #include <mutex>
38 #include <stdio.h>
39 #include <string.h>
40 #include <wtf/Compiler.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 namespace WTF {
78
79 WTF_ATTRIBUTE_PRINTF(1, 0) static String createWithFormatAndArguments(const char* format, va_list args)
80 {
81     va_list argsCopy;
82     va_copy(argsCopy, args);
83
84     ALLOW_NONLITERAL_FORMAT_BEGIN
85
86 #if USE(CF) && !OS(WINDOWS)
87     if (strstr(format, "%@")) {
88         auto cfFormat = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, format, kCFStringEncodingUTF8));
89         auto result = adoptCF(CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, nullptr, cfFormat.get(), args));
90         va_end(argsCopy);
91         return result.get();
92     }
93 #endif
94
95     // Do the format once to get the length.
96 #if COMPILER(MSVC)
97     int result = _vscprintf(format, args);
98 #else
99     char ch;
100     int result = vsnprintf(&ch, 1, format, args);
101 #endif
102
103     if (!result) {
104         va_end(argsCopy);
105         return emptyString();
106     }
107     if (result < 0) {
108         va_end(argsCopy);
109         return { };
110     }
111
112     Vector<char, 256> buffer;
113     unsigned length = result;
114     buffer.grow(length + 1);
115
116     // Now do the formatting again, guaranteed to fit.
117     vsnprintf(buffer.data(), buffer.size(), format, argsCopy);
118     va_end(argsCopy);
119
120     ALLOW_NONLITERAL_FORMAT_END
121
122     return StringImpl::create(reinterpret_cast<const LChar*>(buffer.data()), length);
123 }
124
125 }
126
127 extern "C" {
128
129 static void logToStderr(const char* buffer)
130 {
131 #if USE(APPLE_SYSTEM_LOG)
132     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
133     asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer);
134     ALLOW_DEPRECATED_DECLARATIONS_END
135 #endif
136     fputs(buffer, stderr);
137 }
138
139 WTF_ATTRIBUTE_PRINTF(1, 0)
140 static void vprintf_stderr_common(const char* format, va_list args)
141 {
142 #if USE(CF) && !OS(WINDOWS)
143     if (strstr(format, "%@")) {
144         auto cfFormat = adoptCF(CFStringCreateWithCString(nullptr, format, kCFStringEncodingUTF8));
145
146         ALLOW_NONLITERAL_FORMAT_BEGIN
147         auto str = adoptCF(CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfFormat.get(), args));
148         ALLOW_NONLITERAL_FORMAT_END
149         CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str.get()), kCFStringEncodingUTF8);
150         constexpr unsigned InitialBufferSize { 256 };
151         Vector<char, InitialBufferSize> buffer(length + 1);
152
153         CFStringGetCString(str.get(), buffer.data(), length, kCFStringEncodingUTF8);
154
155         logToStderr(buffer.data());
156         return;
157     }
158
159 #if USE(APPLE_SYSTEM_LOG)
160     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
161     va_list copyOfArgs;
162     va_copy(copyOfArgs, args);
163     asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs);
164     va_end(copyOfArgs);
165     ALLOW_DEPRECATED_DECLARATIONS_END
166 #endif
167
168     // Fall through to write to stderr in the same manner as other platforms.
169
170 #elif HAVE(ISDEBUGGERPRESENT)
171     if (IsDebuggerPresent()) {
172         size_t size = 1024;
173         Vector<char> buffer(size);
174         do {
175             buffer.grow(size);
176             if (vsnprintf(buffer.data(), size, format, args) != -1) {
177                 OutputDebugStringA(buffer.data());
178                 break;
179             }
180             size *= 2;
181         } while (size > 1024);
182     }
183 #endif
184     vfprintf(stderr, format, args);
185 }
186
187 ALLOW_NONLITERAL_FORMAT_BEGIN
188
189 static void vprintf_stderr_with_prefix(const char* prefix, const char* format, va_list args)
190 {
191     size_t prefixLength = strlen(prefix);
192     size_t formatLength = strlen(format);
193     Vector<char> formatWithPrefix(prefixLength + formatLength + 1);
194     memcpy(formatWithPrefix.data(), prefix, prefixLength);
195     memcpy(formatWithPrefix.data() + prefixLength, format, formatLength);
196     formatWithPrefix[prefixLength + formatLength] = 0;
197
198     vprintf_stderr_common(formatWithPrefix.data(), args);
199 }
200
201 static void vprintf_stderr_with_trailing_newline(const char* format, va_list args)
202 {
203     size_t formatLength = strlen(format);
204     if (formatLength && format[formatLength - 1] == '\n') {
205         vprintf_stderr_common(format, args);
206         return;
207     }
208
209     Vector<char> formatWithNewline(formatLength + 2);
210     memcpy(formatWithNewline.data(), format, formatLength);
211     formatWithNewline[formatLength] = '\n';
212     formatWithNewline[formatLength + 1] = 0;
213
214     vprintf_stderr_common(formatWithNewline.data(), args);
215 }
216
217 ALLOW_NONLITERAL_FORMAT_END
218
219 WTF_ATTRIBUTE_PRINTF(1, 2)
220 static void printf_stderr_common(const char* format, ...)
221 {
222     va_list args;
223     va_start(args, format);
224     vprintf_stderr_common(format, args);
225     va_end(args);
226 }
227
228 static void printCallSite(const char* file, int line, const char* function)
229 {
230 #if OS(WINDOWS) && defined(_DEBUG)
231     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
232 #else
233     // By using this format, which matches the format used by MSVC for compiler errors, developers
234     // using Visual Studio can double-click the file/line number in the Output Window to have the
235     // editor navigate to that line of code. It seems fine for other developers, too.
236     printf_stderr_common("%s(%d) : %s\n", file, line, function);
237 #endif
238 }
239
240 void WTFReportNotImplementedYet(const char* file, int line, const char* function)
241 {
242     printf_stderr_common("NOT IMPLEMENTED YET\n");
243     printCallSite(file, line, function);
244 }
245
246 void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
247 {
248     if (assertion)
249         printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
250     else
251         printf_stderr_common("SHOULD NEVER BE REACHED\n");
252     printCallSite(file, line, function);
253 }
254
255 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
256 {
257     va_list args;
258     va_start(args, format);
259     vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args);
260     va_end(args);
261     printf_stderr_common("\n%s\n", assertion);
262     printCallSite(file, line, function);
263 }
264
265 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
266 {
267     printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
268     printCallSite(file, line, function);
269 }
270
271 class CrashLogPrintStream : public PrintStream {
272 public:
273     WTF_ATTRIBUTE_PRINTF(2, 0)
274     void vprintf(const char* format, va_list argList) override
275     {
276         vprintf_stderr_common(format, argList);
277     }
278 };
279
280 void WTFReportBacktrace()
281 {
282     static constexpr int framesToShow = 31;
283     static constexpr int framesToSkip = 2;
284     void* samples[framesToShow + framesToSkip];
285     int frames = framesToShow + framesToSkip;
286
287     WTFGetBacktrace(samples, &frames);
288     WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip);
289 }
290
291 void WTFPrintBacktrace(void** stack, int size)
292 {
293     CrashLogPrintStream out;
294     StackTrace stackTrace(stack, size);
295     out.print(stackTrace);
296 }
297
298 #if !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
299 void WTFCrash()
300 {
301     WTFReportBacktrace();
302 #if ASAN_ENABLED
303     __builtin_trap();
304 #else
305     *(int *)(uintptr_t)0xbbadbeef = 0;
306     // More reliable, but doesn't say BBADBEEF.
307 #if COMPILER(GCC_COMPATIBLE)
308     __builtin_trap();
309 #else
310     ((void(*)())0)();
311 #endif // COMPILER(GCC_COMPATIBLE)
312 #endif // ASAN_ENABLED
313 }
314 #else
315 // We need to keep WTFCrash() around (even on non-debug OS(DARWIN) builds) as a workaround
316 // for presently shipping (circa early 2016) SafariForWebKitDevelopment binaries which still
317 // expects to link to it.
318 void WTFCrash()
319 {
320     CRASH();
321 }
322 #endif // !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
323
324 void WTFCrashWithSecurityImplication()
325 {
326     CRASH();
327 }
328
329 bool WTFIsDebuggerAttached()
330 {
331 #if OS(DARWIN)
332     struct kinfo_proc info;
333     int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
334     size_t size = sizeof(info);
335     if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &info, &size, nullptr, 0) == -1)
336         return false;
337     return info.kp_proc.p_flag & P_TRACED;
338 #else
339     return false;
340 #endif
341 }
342
343 void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
344 {
345     va_list args;
346     va_start(args, format);
347     vprintf_stderr_with_prefix("FATAL ERROR: ", format, args);
348     va_end(args);
349     printf_stderr_common("\n");
350     printCallSite(file, line, function);
351 }
352
353 void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
354 {
355     va_list args;
356     va_start(args, format);
357     vprintf_stderr_with_prefix("ERROR: ", format, args);
358     va_end(args);
359     printf_stderr_common("\n");
360     printCallSite(file, line, function);
361 }
362
363 class WTFLoggingAccumulator {
364     WTF_MAKE_FAST_ALLOCATED;
365 public:
366     void accumulate(const String&);
367     void resetAccumulatedLogs();
368     String getAndResetAccumulatedLogs();
369
370 private:
371     Lock accumulatorLock;
372     StringBuilder loggingAccumulator;
373 };
374
375 void WTFLoggingAccumulator::accumulate(const String& log)
376 {
377     Locker<Lock> locker(accumulatorLock);
378     loggingAccumulator.append(log);
379 }
380
381 void WTFLoggingAccumulator::resetAccumulatedLogs()
382 {
383     Locker<Lock> locker(accumulatorLock);
384     loggingAccumulator.clear();
385 }
386
387 String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
388 {
389     Locker<Lock> locker(accumulatorLock);
390     String result = loggingAccumulator.toString();
391     loggingAccumulator.clear();
392     return result;
393 }
394
395 static WTFLoggingAccumulator& loggingAccumulator()
396 {
397     static WTFLoggingAccumulator* accumulator;
398     static std::once_flag initializeAccumulatorOnce;
399     std::call_once(initializeAccumulatorOnce, [] {
400         accumulator = new WTFLoggingAccumulator;
401     });
402
403     return *accumulator;
404 }
405
406 void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
407 {
408     channel->level = level;
409 }
410
411 bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
412 {
413     return channel->level >= level && channel->state != WTFLogChannelState::Off;
414 }
415
416 void WTFLogWithLevel(WTFLogChannel* channel, WTFLogLevel level, const char* format, ...)
417 {
418     if (level != WTFLogLevel::Always && level > channel->level)
419         return;
420
421     if (channel->level != WTFLogLevel::Always && channel->state == WTFLogChannelState::Off)
422         return;
423
424     va_list args;
425     va_start(args, format);
426
427     ALLOW_NONLITERAL_FORMAT_BEGIN
428     WTFLog(channel, format, args);
429     ALLOW_NONLITERAL_FORMAT_END
430
431     va_end(args);
432 }
433
434 static void WTFLogVaList(WTFLogChannel* channel, const char* format, va_list args)
435 {
436     if (channel->state == WTFLogChannelState::Off)
437         return;
438
439     if (channel->state == WTFLogChannelState::On) {
440         vprintf_stderr_with_trailing_newline(format, args);
441         return;
442     }
443
444     ASSERT(channel->state == WTFLogChannelState::OnWithAccumulation);
445
446     ALLOW_NONLITERAL_FORMAT_BEGIN
447     String loggingString = WTF::createWithFormatAndArguments(format, args);
448     ALLOW_NONLITERAL_FORMAT_END
449
450     if (!loggingString.endsWith('\n'))
451         loggingString.append('\n');
452
453     loggingAccumulator().accumulate(loggingString);
454
455     logToStderr(loggingString.utf8().data());
456 }
457
458 void WTFLog(WTFLogChannel* channel, const char* format, ...)
459 {
460     va_list args;
461     va_start(args, format);
462
463     WTFLogVaList(channel, format, args);
464
465     va_end(args);
466 }
467
468 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
469 {
470     if (channel->state != WTFLogChannelState::On)
471         return;
472
473     va_list args;
474     va_start(args, format);
475
476     ALLOW_NONLITERAL_FORMAT_BEGIN
477     WTFLogVaList(channel, format, args);
478     ALLOW_NONLITERAL_FORMAT_END
479
480     va_end(args);
481
482     printCallSite(file, line, function);
483 }
484
485 void WTFLogAlwaysV(const char* format, va_list args)
486 {
487     vprintf_stderr_with_trailing_newline(format, args);
488 }
489
490 void WTFLogAlways(const char* format, ...)
491 {
492     va_list args;
493     va_start(args, format);
494     WTFLogAlwaysV(format, args);
495     va_end(args);
496 }
497
498 void WTFLogAlwaysAndCrash(const char* format, ...)
499 {
500     va_list args;
501     va_start(args, format);
502     WTFLogAlwaysV(format, args);
503     va_end(args);
504     CRASH();
505 }
506
507 WTFLogChannel* WTFLogChannelByName(WTFLogChannel* channels[], size_t count, const char* name)
508 {
509     for (size_t i = 0; i < count; ++i) {
510         WTFLogChannel* channel = channels[i];
511         if (equalIgnoringASCIICase(name, channel->name))
512             return channel;
513     }
514
515     return 0;
516 }
517
518 static void setStateOfAllChannels(WTFLogChannel* channels[], size_t channelCount, WTFLogChannelState state)
519 {
520     for (size_t i = 0; i < channelCount; ++i)
521         channels[i]->state = state;
522 }
523
524 void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t count, const char* logLevel)
525 {
526 #if !RELEASE_LOG_DISABLED
527     for (size_t i = 0; i < count; ++i) {
528         WTFLogChannel* channel = channels[i];
529         channel->osLogChannel = os_log_create(channel->subsystem, channel->name);
530     }
531 #endif
532
533     for (auto& logLevelComponent : String(logLevel).split(',')) {
534         Vector<String> componentInfo = logLevelComponent.split('=');
535         String component = componentInfo[0].stripWhiteSpace();
536
537         WTFLogChannelState logChannelState = WTFLogChannelState::On;
538         if (component.startsWith('-')) {
539             logChannelState = WTFLogChannelState::Off;
540             component = component.substring(1);
541         }
542
543         if (equalLettersIgnoringASCIICase(component, "all")) {
544             setStateOfAllChannels(channels, count, logChannelState);
545             continue;
546         }
547
548         WTFLogLevel logChannelLevel = WTFLogLevel::Error;
549         if (componentInfo.size() > 1) {
550             String level = componentInfo[1].stripWhiteSpace();
551             if (equalLettersIgnoringASCIICase(level, "error"))
552                 logChannelLevel = WTFLogLevel::Error;
553             else if (equalLettersIgnoringASCIICase(level, "warning"))
554                 logChannelLevel = WTFLogLevel::Warning;
555             else if (equalLettersIgnoringASCIICase(level, "info"))
556                 logChannelLevel = WTFLogLevel::Info;
557             else if (equalLettersIgnoringASCIICase(level, "debug"))
558                 logChannelLevel = WTFLogLevel::Debug;
559             else
560                 WTFLogAlways("Unknown logging level: %s", level.utf8().data());
561         }
562
563         if (WTFLogChannel* channel = WTFLogChannelByName(channels, count, component.utf8().data())) {
564             channel->state = logChannelState;
565             channel->level = logChannelLevel;
566         } else
567             WTFLogAlways("Unknown logging channel: %s", component.utf8().data());
568     }
569 }
570
571 #if !RELEASE_LOG_DISABLED
572 void WTFReleaseLogStackTrace(WTFLogChannel* channel)
573 {
574     auto stackTrace = WTF::StackTrace::captureStackTrace(30, 0);
575     if (stackTrace && stackTrace->stack()) {
576         auto stack = stackTrace->stack();
577         for (int frameNumber = 1; frameNumber < stackTrace->size(); ++frameNumber) {
578             auto stackFrame = stack[frameNumber];
579             auto demangled = WTF::StackTrace::demangle(stackFrame);
580             if (demangled && demangled->demangledName())
581                 os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->demangledName());
582             else if (demangled && demangled->mangledName())
583                 os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->mangledName());
584             else
585                 os_log(channel->osLogChannel, "%-3d %p", frameNumber, stackFrame);
586         }
587     }
588 }
589 #endif
590
591 } // extern "C"
592
593 #if OS(DARWIN) && (CPU(X86_64) || CPU(ARM64))
594 #if CPU(X86_64)
595
596 #define CRASH_INST "int3"
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 CRASH_GPR0 "r11"
602 #define CRASH_GPR1 "r10"
603 #define CRASH_GPR2 "r9"
604 #define CRASH_GPR3 "r8"
605 #define CRASH_GPR4 "r15"
606 #define CRASH_GPR5 "r14"
607 #define CRASH_GPR6 "r13"
608
609 #elif CPU(ARM64) // CPU(X86_64)
610
611 #define CRASH_INST "brk #0"
612
613 // See comment above on the ordering.
614 #define CRASH_GPR0 "x16"
615 #define CRASH_GPR1 "x17"
616 #define CRASH_GPR2 "x18"
617 #define CRASH_GPR3 "x19"
618 #define CRASH_GPR4 "x20"
619 #define CRASH_GPR5 "x21"
620 #define CRASH_GPR6 "x22"
621
622 #endif // CPU(ARM64)
623
624 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5, uint64_t misc6)
625 {
626     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
627     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
628     register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
629     register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
630     register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
631     register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
632     register uint64_t misc6GPR asm(CRASH_GPR6) = misc6;
633     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR), "r"(misc6GPR));
634     __builtin_unreachable();
635 }
636
637 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5)
638 {
639     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
640     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
641     register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
642     register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
643     register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
644     register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
645     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR));
646     __builtin_unreachable();
647 }
648
649 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4)
650 {
651     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
652     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
653     register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
654     register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
655     register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
656     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR));
657     __builtin_unreachable();
658 }
659
660 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3)
661 {
662     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
663     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
664     register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
665     register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
666     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR));
667     __builtin_unreachable();
668 }
669
670 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2)
671 {
672     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
673     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
674     register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
675     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR));
676     __builtin_unreachable();
677 }
678
679 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1)
680 {
681     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
682     register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
683     __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR));
684     __builtin_unreachable();
685 }
686
687 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason)
688 {
689     register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
690     __asm__ volatile (CRASH_INST : : "r"(reasonGPR));
691     __builtin_unreachable();
692 }
693
694 #else
695
696 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
697 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
698 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
699 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
700 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
701 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t) { CRASH(); }
702 void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t) { CRASH(); }
703
704 #endif // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
705
706 namespace WTF {
707
708 void resetAccumulatedLogs()
709 {
710     loggingAccumulator().resetAccumulatedLogs();
711 }
712
713 String getAndResetAccumulatedLogs()
714 {
715     return loggingAccumulator().getAndResetAccumulatedLogs();
716 }
717
718 } // namespace WTF