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