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
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 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
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 {
364 WTF_MAKE_FAST_ALLOCATED;
365public:
366 void accumulate(const String&);
367 void resetAccumulatedLogs();
368 String getAndResetAccumulatedLogs();
369
370private:
371 Lock accumulatorLock;
372 StringBuilder loggingAccumulator;
373};
374
375void WTFLoggingAccumulator::accumulate(const String& log)
376{
377 Locker<Lock> locker(accumulatorLock);
378 loggingAccumulator.append(log);
379}
380
381void WTFLoggingAccumulator::resetAccumulatedLogs()
382{
383 Locker<Lock> locker(accumulatorLock);
384 loggingAccumulator.clear();
385}
386
387String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
388{
389 Locker<Lock> locker(accumulatorLock);
390 String result = loggingAccumulator.toString();
391 loggingAccumulator.clear();
392 return result;
393}
394
395static 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
406void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
407{
408 channel->level = level;
409}
410
411bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
412{
413 return channel->level >= level && channel->state != WTFLogChannelState::Off;
414}
415
416void 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
434static 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
458void 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
468void 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
485void WTFLogAlwaysV(const char* format, va_list args)
486{
487 vprintf_stderr_with_trailing_newline(format, args);
488}
489
490void WTFLogAlways(const char* format, ...)
491{
492 va_list args;
493 va_start(args, format);
494 WTFLogAlwaysV(format, args);
495 va_end(args);
496}
497
498void 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
507WTFLogChannel* 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
518static 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
524void 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
572void 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
624void 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
637void 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
649void 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
660void 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
670void 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
679void 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
687void 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
696void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
697void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
698void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
699void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
700void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
701void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t) { CRASH(); }
702void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t) { CRASH(); }
703
704#endif // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
705
706namespace WTF {
707
708void resetAccumulatedLogs()
709{
710 loggingAccumulator().resetAccumulatedLogs();
711}
712
713String getAndResetAccumulatedLogs()
714{
715 return loggingAccumulator().getAndResetAccumulatedLogs();
716}
717
718} // namespace WTF
719