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 <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
77namespace WTF {
78
79WTF_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
127extern "C" {
128
129static 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
139WTF_ATTRIBUTE_PRINTF(1, 0)
140static 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
187ALLOW_NONLITERAL_FORMAT_BEGIN
188
189static 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
201static 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
217ALLOW_NONLITERAL_FORMAT_END
218
219WTF_ATTRIBUTE_PRINTF(1, 2)
220static 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
228static 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
240void 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
246void 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
255void 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
265void 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
271class CrashLogPrintStream : public PrintStream {
272public:
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
280void WTFReportBacktrace()
281{
282 static const int framesToShow = 31;
283 static const 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
291void 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))
299void 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.
318void WTFCrash()
319{
320 CRASH();
321}
322#endif // !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
323
324void WTFCrashWithSecurityImplication()
325{
326 CRASH();
327}
328
329bool 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
343void 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
353void 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
363class WTFLoggingAccumulator {
364public:
365 void accumulate(const String&);
366 void resetAccumulatedLogs();
367 String getAndResetAccumulatedLogs();
368
369private:
370 Lock accumulatorLock;
371 StringBuilder loggingAccumulator;
372};
373
374void WTFLoggingAccumulator::accumulate(const String& log)
375{
376 Locker<Lock> locker(accumulatorLock);
377 loggingAccumulator.append(log);
378}
379
380void WTFLoggingAccumulator::resetAccumulatedLogs()
381{
382 Locker<Lock> locker(accumulatorLock);
383 loggingAccumulator.clear();
384}
385
386String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
387{
388 Locker<Lock> locker(accumulatorLock);
389 String result = loggingAccumulator.toString();
390 loggingAccumulator.clear();
391 return result;
392}
393
394static WTFLoggingAccumulator& loggingAccumulator()
395{
396 static WTFLoggingAccumulator* accumulator;
397 static std::once_flag initializeAccumulatorOnce;
398 std::call_once(initializeAccumulatorOnce, [] {
399 accumulator = new WTFLoggingAccumulator;
400 });
401
402 return *accumulator;
403}
404
405void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
406{
407 channel->level = level;
408}
409
410bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
411{
412 return channel->level >= level && channel->state != WTFLogChannelState::Off;
413}
414
415void WTFLogWithLevel(WTFLogChannel* channel, WTFLogLevel level, const char* format, ...)
416{
417 if (level != WTFLogLevel::Always && level > channel->level)
418 return;
419
420 if (channel->level != WTFLogLevel::Always && channel->state == WTFLogChannelState::Off)
421 return;
422
423 va_list args;
424 va_start(args, format);
425
426 ALLOW_NONLITERAL_FORMAT_BEGIN
427 WTFLog(channel, format, args);
428 ALLOW_NONLITERAL_FORMAT_END
429
430 va_end(args);
431}
432
433static void WTFLogVaList(WTFLogChannel* channel, const char* format, va_list args)
434{
435 if (channel->state == WTFLogChannelState::Off)
436 return;
437
438 if (channel->state == WTFLogChannelState::On) {
439 vprintf_stderr_with_trailing_newline(format, args);
440 return;
441 }
442
443 ASSERT(channel->state == WTFLogChannelState::OnWithAccumulation);
444
445 ALLOW_NONLITERAL_FORMAT_BEGIN
446 String loggingString = WTF::createWithFormatAndArguments(format, args);
447 ALLOW_NONLITERAL_FORMAT_END
448
449 if (!loggingString.endsWith('\n'))
450 loggingString.append('\n');
451
452 loggingAccumulator().accumulate(loggingString);
453
454 logToStderr(loggingString.utf8().data());
455}
456
457void WTFLog(WTFLogChannel* channel, const char* format, ...)
458{
459 va_list args;
460 va_start(args, format);
461
462 WTFLogVaList(channel, format, args);
463
464 va_end(args);
465}
466
467void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
468{
469 if (channel->state != WTFLogChannelState::On)
470 return;
471
472 va_list args;
473 va_start(args, format);
474
475 ALLOW_NONLITERAL_FORMAT_BEGIN
476 WTFLogVaList(channel, format, args);
477 ALLOW_NONLITERAL_FORMAT_END
478
479 va_end(args);
480
481 printCallSite(file, line, function);
482}
483
484void WTFLogAlwaysV(const char* format, va_list args)
485{
486 vprintf_stderr_with_trailing_newline(format, args);
487}
488
489void WTFLogAlways(const char* format, ...)
490{
491 va_list args;
492 va_start(args, format);
493 WTFLogAlwaysV(format, args);
494 va_end(args);
495}
496
497void WTFLogAlwaysAndCrash(const char* format, ...)
498{
499 va_list args;
500 va_start(args, format);
501 WTFLogAlwaysV(format, args);
502 va_end(args);
503 CRASH();
504}
505
506WTFLogChannel* WTFLogChannelByName(WTFLogChannel* channels[], size_t count, const char* name)
507{
508 for (size_t i = 0; i < count; ++i) {
509 WTFLogChannel* channel = channels[i];
510 if (equalIgnoringASCIICase(name, channel->name))
511 return channel;
512 }
513
514 return 0;
515}
516
517static void setStateOfAllChannels(WTFLogChannel* channels[], size_t channelCount, WTFLogChannelState state)
518{
519 for (size_t i = 0; i < channelCount; ++i)
520 channels[i]->state = state;
521}
522
523void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t count, const char* logLevel)
524{
525#if !RELEASE_LOG_DISABLED
526 for (size_t i = 0; i < count; ++i) {
527 WTFLogChannel* channel = channels[i];
528 channel->osLogChannel = os_log_create(channel->subsystem, channel->name);
529 }
530#endif
531
532 for (auto& logLevelComponent : String(logLevel).split(',')) {
533 Vector<String> componentInfo = logLevelComponent.split('=');
534 String component = componentInfo[0].stripWhiteSpace();
535
536 WTFLogChannelState logChannelState = WTFLogChannelState::On;
537 if (component.startsWith('-')) {
538 logChannelState = WTFLogChannelState::Off;
539 component = component.substring(1);
540 }
541
542 if (equalLettersIgnoringASCIICase(component, "all")) {
543 setStateOfAllChannels(channels, count, logChannelState);
544 continue;
545 }
546
547 WTFLogLevel logChannelLevel = WTFLogLevel::Error;
548 if (componentInfo.size() > 1) {
549 String level = componentInfo[1].stripWhiteSpace();
550 if (equalLettersIgnoringASCIICase(level, "error"))
551 logChannelLevel = WTFLogLevel::Error;
552 else if (equalLettersIgnoringASCIICase(level, "warning"))
553 logChannelLevel = WTFLogLevel::Warning;
554 else if (equalLettersIgnoringASCIICase(level, "info"))
555 logChannelLevel = WTFLogLevel::Info;
556 else if (equalLettersIgnoringASCIICase(level, "debug"))
557 logChannelLevel = WTFLogLevel::Debug;
558 else
559 WTFLogAlways("Unknown logging level: %s", level.utf8().data());
560 }
561
562 if (WTFLogChannel* channel = WTFLogChannelByName(channels, count, component.utf8().data())) {
563 channel->state = logChannelState;
564 channel->level = logChannelLevel;
565 } else
566 WTFLogAlways("Unknown logging channel: %s", component.utf8().data());
567 }
568}
569
570#if !RELEASE_LOG_DISABLED
571void WTFReleaseLogStackTrace(WTFLogChannel* channel)
572{
573 auto stackTrace = WTF::StackTrace::captureStackTrace(30, 0);
574 if (stackTrace && stackTrace->stack()) {
575 auto stack = stackTrace->stack();
576 for (int frameNumber = 1; frameNumber < stackTrace->size(); ++frameNumber) {
577 auto stackFrame = stack[frameNumber];
578 auto demangled = WTF::StackTrace::demangle(stackFrame);
579 if (demangled && demangled->demangledName())
580 os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->demangledName());
581 else if (demangled && demangled->mangledName())
582 os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->mangledName());
583 else
584 os_log(channel->osLogChannel, "%-3d %p", frameNumber, stackFrame);
585 }
586 }
587}
588#endif
589
590} // extern "C"
591
592#if OS(DARWIN) && (CPU(X86_64) || CPU(ARM64))
593#if CPU(X86_64)
594
595#define CRASH_INST "int3"
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 CRASH_GPR0 "r11"
601#define CRASH_GPR1 "r10"
602#define CRASH_GPR2 "r9"
603#define CRASH_GPR3 "r8"
604#define CRASH_GPR4 "r15"
605#define CRASH_GPR5 "r14"
606#define CRASH_GPR6 "r13"
607
608#elif CPU(ARM64) // CPU(X86_64)
609
610#define CRASH_INST "brk #0"
611
612// See comment above on the ordering.
613#define CRASH_GPR0 "x16"
614#define CRASH_GPR1 "x17"
615#define CRASH_GPR2 "x18"
616#define CRASH_GPR3 "x19"
617#define CRASH_GPR4 "x20"
618#define CRASH_GPR5 "x21"
619#define CRASH_GPR6 "x22"
620
621#endif // CPU(ARM64)
622
623void WTFCrashWithInfo(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)
624{
625 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
626 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
627 register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
628 register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
629 register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
630 register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
631 register uint64_t misc6GPR asm(CRASH_GPR6) = misc6;
632 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR), "r"(misc6GPR));
633 __builtin_unreachable();
634}
635
636void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4, uint64_t misc5)
637{
638 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
639 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
640 register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
641 register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
642 register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
643 register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
644 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR));
645 __builtin_unreachable();
646}
647
648void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4)
649{
650 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
651 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
652 register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
653 register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
654 register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
655 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR));
656 __builtin_unreachable();
657}
658
659void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3)
660{
661 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
662 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
663 register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
664 register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
665 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR));
666 __builtin_unreachable();
667}
668
669void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2)
670{
671 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
672 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
673 register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
674 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR));
675 __builtin_unreachable();
676}
677
678void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason, uint64_t misc1)
679{
680 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
681 register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
682 __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR));
683 __builtin_unreachable();
684}
685
686void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t reason)
687{
688 register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
689 __asm__ volatile (CRASH_INST : : "r"(reasonGPR));
690 __builtin_unreachable();
691}
692
693#else
694
695void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
696void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
697void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
698void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
699void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
700void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t, uint64_t) { CRASH(); }
701void WTFCrashWithInfo(int, const char*, const char*, int, uint64_t) { CRASH(); }
702
703#endif // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
704
705namespace WTF {
706
707void resetAccumulatedLogs()
708{
709 loggingAccumulator().resetAccumulatedLogs();
710}
711
712String getAndResetAccumulatedLogs()
713{
714 return loggingAccumulator().getAndResetAccumulatedLogs();
715}
716
717} // namespace WTF
718