blob: 688bafa332e460ef13f140f76c16b00dcda71b38 [file] [edit]
/*
* Copyright (C) 2003-2025 Apple Inc. All rights reserved.
* Copyright (C) 2007-2009 Torch Mobile, Inc.
* Copyright (C) 2011 University of Szeged. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <wtf/Assertions.h>
#include <stdio.h>
#include <string.h>
#include <wtf/Compiler.h>
#include <wtf/Lock.h>
#include <wtf/Locker.h>
#include <wtf/LoggingAccumulator.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/PrintStream.h>
#include <wtf/StackTrace.h>
#include <wtf/StdLibExtras.h>
#include <wtf/WTFConfig.h>
#include <wtf/text/CString.h>
#include <wtf/text/MakeString.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringCommon.h>
#include <wtf/text/WTFString.h>
#if USE(CF)
#include <CoreFoundation/CFString.h>
#endif // USE(CF)
#if OS(WINDOWS)
#include <crtdbg.h>
#include <windows.h>
#endif
#if OS(DARWIN)
#include <array>
#include <sys/sysctl.h>
#include <unistd.h>
#include <wtf/OSObjectPtr.h>
#endif
#if ENABLE(JOURNALD_LOG)
#include <stdlib.h>
#include <unistd.h>
#endif
#if !RELEASE_LOG_DISABLED && !USE(OS_LOG)
#include <wtf/StringPrintStream.h>
#endif
#if PLATFORM(COCOA)
#import <wtf/spi/cocoa/OSLogSPI.h>
#endif
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
namespace WTF {
WTF_ATTRIBUTE_NSSTRING(1, 0)
static String createWithFormatAndArguments(const char* format, va_list args)
{
va_list argsCopy;
va_copy(argsCopy, args);
auto formatSpan = unsafeSpan(format);
ALLOW_NONLITERAL_FORMAT_BEGIN
#if USE(CF)
if (contains(formatSpan, "%@"_span)) {
auto cfFormat = adoptCF(CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, format, kCFStringEncodingUTF8, kCFAllocatorNull));
auto result = adoptCF(CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, nullptr, cfFormat.get(), args));
va_end(argsCopy);
return result.get();
}
#endif
// Do the format once to get the length.
#if OS(WINDOWS)
int result = _vscprintf(formatSpan.data(), args);
#else
char ch;
int result = vsnprintf(&ch, 1, formatSpan.data(), args);
#endif
if (!result) {
va_end(argsCopy);
return emptyString();
}
if (result < 0) {
va_end(argsCopy);
return { };
}
Vector<char, 256> buffer;
buffer.grow(result + 1);
// Now do the formatting again, guaranteed to fit.
vsnprintf(buffer.mutableSpan().data(), buffer.size(), formatSpan.data(), argsCopy);
va_end(argsCopy);
ALLOW_NONLITERAL_FORMAT_END
return StringImpl::create(buffer.subspan(0, buffer.size() - 1));
}
#if PLATFORM(COCOA) || OS(ANDROID)
void disableForwardingVPrintfStdErrToOSLog()
{
g_wtfConfig.disableForwardingVPrintfStdErrToOSLog = true;
}
#endif
} // namespace WTF
extern "C" {
#if PLATFORM(COCOA)
static os_log_t webkitSubsystemForGenericOSLog()
{
SUPPRESS_RETAINPTR_CTOR_ADOPT static NeverDestroyed<OSObjectPtr<os_log_t>> subsystem = adoptOSObject(os_log_create(LOG_CHANNEL_WEBKIT_SUBSYSTEM, "Generic"));
return subsystem.get().get();
}
#endif
static void logToStderr([[maybe_unused]] WTFLogChannel* channel, const char* buffer)
{
#if PLATFORM(COCOA)
os_log(channel ? channel->osLogChannel : webkitSubsystemForGenericOSLog(), "%s", buffer);
#elif OS(ANDROID)
__android_log_write(ANDROID_LOG_VERBOSE, LOG_CHANNEL_WEBKIT_SUBSYSTEM, buffer);
#endif
fputs(buffer, stderr);
}
WTF_ATTRIBUTE_NSSTRING(2, 0)
static void vprintf_stderr_common([[maybe_unused]] WTFLogChannel* channel, const char* format, va_list args)
{
auto formatSpan = unsafeSpan(format);
ALLOW_NONLITERAL_FORMAT_BEGIN
#if USE(CF)
if (contains(formatSpan, "%@"_span)) {
auto cfFormat = adoptCF(CFStringCreateWithCStringNoCopy(nullptr, format, kCFStringEncodingUTF8, kCFAllocatorNull));
auto str = adoptCF(CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfFormat.get(), args));
CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str.get()), kCFStringEncodingUTF8);
constexpr unsigned InitialBufferSize { 256 };
Vector<char, InitialBufferSize> buffer(length + 1);
CFStringGetCString(str.get(), buffer.mutableSpan().data(), length, kCFStringEncodingUTF8);
logToStderr(channel, buffer.span().data());
return;
}
#if PLATFORM(COCOA)
if (!g_wtfConfig.disableForwardingVPrintfStdErrToOSLog) {
os_log_t osLogChannel = channel ? channel->osLogChannel : webkitSubsystemForGenericOSLog();
va_list copyOfArgs;
va_copy(copyOfArgs, args);
os_log_with_args(osLogChannel, OS_LOG_TYPE_DEFAULT, formatSpan.data(), copyOfArgs, __builtin_return_address(0));
va_end(copyOfArgs);
}
#endif
#if OS(ANDROID)
if (!g_wtfConfig.disableForwardingVPrintfStdErrToOSLog) {
va_list copyOfArgs;
va_copy(copyOfArgs, args);
__android_log_vprint(ANDROID_LOG_ERROR, LOG_CHANNEL_WEBKIT_SUBSYSTEM, formatSpan.data(), copyOfArgs);
va_end(copyOfArgs);
}
#endif
// Fall through to write to stderr in the same manner as other platforms.
#elif HAVE(ISDEBUGGERPRESENT)
if (IsDebuggerPresent()) {
size_t size = 1024;
Vector<char> buffer(size);
do {
buffer.grow(size);
if (vsnprintf(buffer.mutableSpan().data(), size, formatSpan.data(), args) != -1) {
OutputDebugStringA(buffer.span().data());
break;
}
size *= 2;
} while (size > 1024);
}
#endif
vfprintf(stderr, formatSpan.data(), args);
ALLOW_NONLITERAL_FORMAT_END
}
WTF_ATTRIBUTE_NSSTRING(2, 0)
static void vprintf_stderr_with_prefix(const char* rawPrefix, const char* rawFormat, va_list args)
{
auto prefix = unsafeSpan(rawPrefix);
auto format = unsafeSpan(rawFormat);
Vector<char> formatWithPrefix(prefix.size() + format.size() + 1);
memcpySpan(formatWithPrefix.mutableSpan(), prefix);
memcpySpan(formatWithPrefix.mutableSpan().subspan(prefix.size()), format);
formatWithPrefix[prefix.size() + format.size()] = 0;
ALLOW_NONLITERAL_FORMAT_BEGIN
vprintf_stderr_common(nullptr, formatWithPrefix.span().data(), args);
ALLOW_NONLITERAL_FORMAT_END
}
WTF_ATTRIBUTE_NSSTRING(2, 0)
static void vprintf_stderr_with_trailing_newline(WTFLogChannel* channel, const char* rawFormat, va_list args)
{
auto format = unsafeSpan(rawFormat);
if (!format.empty() && format.back() == '\n') {
vprintf_stderr_common(channel, rawFormat, args);
return;
}
Vector<char> formatWithNewline(format.size() + 2);
memcpySpan(formatWithNewline.mutableSpan(), format);
formatWithNewline[format.size()] = '\n';
formatWithNewline[format.size() + 1] = 0;
ALLOW_NONLITERAL_FORMAT_BEGIN
vprintf_stderr_common(channel, formatWithNewline.span().data(), args);
ALLOW_NONLITERAL_FORMAT_END
}
WTF_ATTRIBUTE_NSSTRING(1, 2)
static void printf_stderr_common(const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf_stderr_common(nullptr, format, args);
va_end(args);
}
static void printCallSite(const char* file, int line, const char* function)
{
#if OS(WINDOWS) && defined(_DEBUG)
_CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
#else
// By using this format, which matches the format used by MSVC for compiler errors, developers
// using Visual Studio can double-click the file/line number in the Output Window to have the
// editor navigate to that line of code. It seems fine for other developers, too.
printf_stderr_common("%s(%d) : %s\n", file, line, function);
#endif
}
void WTFReportNotImplementedYet(const char* file, int line, const char* function)
{
printf_stderr_common("NOT IMPLEMENTED YET\n");
printCallSite(file, line, function);
}
void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
{
if (assertion)
printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
else
printf_stderr_common("SHOULD NEVER BE REACHED\n");
printCallSite(file, line, function);
}
void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args);
va_end(args);
printf_stderr_common("\n%s\n", assertion);
printCallSite(file, line, function);
}
void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
{
printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
printCallSite(file, line, function);
}
class CrashLogPrintStream final : public PrintStream {
public:
WTF_ATTRIBUTE_NSSTRING(2, 0)
void vprintf(const char* format, va_list argList) final
{
vprintf_stderr_common(nullptr, format, argList);
}
};
void WTFReportBacktraceWithPrefix(const char* prefix)
{
CrashLogPrintStream out;
WTFReportBacktraceWithPrefixAndPrintStream(out, prefix);
}
static constexpr int kDefaultFramesToShow = 31;
static constexpr int kDefaultFramesToSkip = 2;
void WTFReportBacktraceWithStackDepth(int framesToShow)
{
WTFReportBacktraceWithPrefixAndStackDepth("", framesToShow);
}
void WTFReportBacktraceWithPrefixAndStackDepth(const char* prefix, int framesToShow)
{
int frames = framesToShow + kDefaultFramesToSkip;
Vector<void*> samples(frames);
WTFGetBacktrace(samples.mutableSpan().data(), &frames);
CrashLogPrintStream out;
if (frames > kDefaultFramesToSkip)
WTFPrintBacktraceWithPrefixAndPrintStream(out, samples.subspan(kDefaultFramesToSkip, frames - kDefaultFramesToSkip), prefix);
else
out.print("%sno stacktrace available", prefix);
}
void WTFReportBacktraceWithPrefixAndPrintStream(PrintStream& out, const char* prefix)
{
std::array<void*, kDefaultFramesToShow + kDefaultFramesToSkip> samples;
int frames = samples.size();
WTFGetBacktrace(samples.data(), &frames);
if (frames > kDefaultFramesToSkip)
WTFPrintBacktraceWithPrefixAndPrintStream(out, std::span { samples }.subspan(kDefaultFramesToSkip, frames - kDefaultFramesToSkip), prefix);
else
out.print("%sno stacktrace available", prefix);
}
void WTFReportBacktrace()
{
std::array<void*, kDefaultFramesToShow + kDefaultFramesToSkip> samples;
int frames = kDefaultFramesToShow + kDefaultFramesToSkip;
WTFGetBacktrace(samples.data(), &frames);
if (frames > kDefaultFramesToSkip)
WTFPrintBacktrace(std::span { samples }.subspan(kDefaultFramesToSkip, frames - kDefaultFramesToSkip));
else
CrashLogPrintStream { }.print("no stacktrace available");
}
void WTFPrintBacktraceWithPrefixAndPrintStream(PrintStream& out, std::span<void* const> stack, const char* prefix)
{
out.print(StackTracePrinter { stack, prefix });
}
void WTFPrintBacktrace(std::span<void* const> stack)
{
CrashLogPrintStream out;
WTFPrintBacktraceWithPrefixAndPrintStream(out, stack, "");
}
#if !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
void WTFCrash()
{
#if ASAN_ENABLED
__builtin_trap();
#elif OS(DARWIN) && CPU(ARM64)
WTFBreakpointTrap();
__builtin_trap(); // Suppress NO_RETURN_DUE_TO_CRASH warning.
#else
*(int *)(uintptr_t)0xbbadbeef = 0;
// More reliable, but doesn't say BBADBEEF.
__builtin_trap();
#endif // ASAN_ENABLED
}
#else
// We need to keep WTFCrash() around (even on non-debug OS(DARWIN) builds) as a workaround
// for presently shipping (circa early 2016) SafariForWebKitDevelopment binaries which still
// expects to link to it.
void WTFCrash()
{
CRASH();
}
#endif // !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
#if ENABLE(CONJECTURE_ASSERT)
int wtfConjectureAssertIsEnabled = 0;
void WTFCrashDueToConjectureAssert(const char* file, int line, const char* function, const char* assertion)
{
printf_stderr_common("CONJECTURE ASSERTION FAILED: %s\n", assertion);
printCallSite(file, line, function);
WTFReportBacktrace();
CRASH();
}
#endif
void WTFCrashWithSecurityImplication()
{
CRASH();
}
bool WTFIsDebuggerAttached()
{
#if OS(DARWIN)
struct kinfo_proc info;
std::array mib { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
size_t size = sizeof(info);
if (sysctl(mib.data(), mib.size(), &info, &size, nullptr, 0) == -1)
return false;
return info.kp_proc.p_flag & P_TRACED;
#else
return false;
#endif
}
void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf_stderr_with_prefix("FATAL ERROR: ", format, args);
va_end(args);
printf_stderr_common("\n");
printCallSite(file, line, function);
}
void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf_stderr_with_prefix("ERROR: ", format, args);
va_end(args);
printf_stderr_common("\n");
printCallSite(file, line, function);
}
class WTFLoggingAccumulator {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED(WTFLoggingAccumulator);
public:
void accumulate(const String&);
void resetAccumulatedLogs();
String getAndResetAccumulatedLogs();
private:
Lock accumulatorLock;
StringBuilder loggingAccumulator WTF_GUARDED_BY_LOCK(accumulatorLock);
};
void WTFLoggingAccumulator::accumulate(const String& log)
{
Locker locker { accumulatorLock };
loggingAccumulator.append(log);
}
void WTFLoggingAccumulator::resetAccumulatedLogs()
{
Locker locker { accumulatorLock };
loggingAccumulator.clear();
}
String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
{
Locker locker { accumulatorLock };
String result = loggingAccumulator.toString();
loggingAccumulator.clear();
return result;
}
static WTFLoggingAccumulator& loggingAccumulator()
{
static NeverDestroyed<UniqueRef<WTFLoggingAccumulator>> accumulator = makeUniqueRef<WTFLoggingAccumulator>();
return accumulator.get();
}
void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
{
channel->level = level;
}
bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
{
return channel->level >= level && channel->state != WTFLogChannelState::Off;
}
#if ENABLE(JOURNALD_LOG)
bool WTFShouldLogToJournal()
{
static const bool shouldLogToJournal = [] {
if (const char* output = getenv("WEBKIT_DEBUG_OUTPUT")) {
auto outputSpan = unsafeSpan(output);
if (equalSpans(outputSpan, "stderr"_span))
return false;
if (equalSpans(outputSpan, "journal"_span))
return true;
WTFLogAlways("Unknown WEBKIT_DEBUG_OUTPUT value '%s', expected 'journal' or 'stderr'.", output);
}
// sd_journal_send() returns success even when journald is not running:
// https://man.archlinux.org/man/sd_journal_send_with_location.3.en#RETURN_VALUE
return !access("/run/systemd/journal/socket", F_OK);
}();
return shouldLogToJournal;
}
#endif // ENABLE(JOURNALD_LOG)
void WTFLogWithLevel(WTFLogChannel* channel, WTFLogLevel level, const char* format, ...)
{
if (level != WTFLogLevel::Always && level > channel->level)
return;
if (channel->level != WTFLogLevel::Always && channel->state == WTFLogChannelState::Off)
return;
va_list args;
va_start(args, format);
ALLOW_NONLITERAL_FORMAT_BEGIN
WTFLog(channel, format, args);
ALLOW_NONLITERAL_FORMAT_END
va_end(args);
}
WTF_ATTRIBUTE_NSSTRING(2, 0)
static void WTFLogVaList(WTFLogChannel* channel, const char* format, va_list args)
{
if (channel->state == WTFLogChannelState::Off)
return;
if (channel->state == WTFLogChannelState::On) {
vprintf_stderr_with_trailing_newline(channel, format, args);
return;
}
ASSERT(channel->state == WTFLogChannelState::OnWithAccumulation);
ALLOW_NONLITERAL_FORMAT_BEGIN
String loggingString = WTF::createWithFormatAndArguments(format, args);
ALLOW_NONLITERAL_FORMAT_END
if (!loggingString.endsWith('\n'))
loggingString = makeString(loggingString, '\n');
loggingAccumulator().accumulate(loggingString);
logToStderr(channel, loggingString.utf8().data());
}
void WTFLog(WTFLogChannel* channel, const char* format, ...)
{
va_list args;
va_start(args, format);
WTFLogVaList(channel, format, args);
va_end(args);
}
void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
{
if (channel->state != WTFLogChannelState::On)
return;
va_list args;
va_start(args, format);
ALLOW_NONLITERAL_FORMAT_BEGIN
WTFLogVaList(channel, format, args);
ALLOW_NONLITERAL_FORMAT_END
va_end(args);
printCallSite(file, line, function);
}
void WTFLogAlwaysV(const char* format, va_list args)
{
vprintf_stderr_with_trailing_newline(nullptr, format, args);
}
void WTFLogAlways(const char* format, ...)
{
va_list args;
va_start(args, format);
WTFLogAlwaysV(format, args);
va_end(args);
}
void WTFLogAlwaysAndCrash(const char* format, ...)
{
va_list args;
va_start(args, format);
WTFLogAlwaysV(format, args);
va_end(args);
CRASH();
}
WTFLogChannel* WTFLogChannelByName(WTFLogChannel* channels[], size_t count, const char* name)
{
for (size_t i = 0; i < count; ++i) {
WTFLogChannel* channel = channels[i];
if (equalIgnoringASCIICase(name, channel->name))
return channel;
}
return nullptr;
}
static void NODELETE setStateOfAllChannels(WTFLogChannel* channels[], size_t channelCount, WTFLogChannelState state)
{
for (size_t i = 0; i < channelCount; ++i)
channels[i]->state = state;
}
void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t count, const char* logLevel)
{
#if USE(OS_LOG) && !RELEASE_LOG_DISABLED
for (size_t i = 0; i < count; ++i) {
WTFLogChannel* channel = channels[i];
channel->osLogChannel = os_log_create(LOG_CHANNEL_WEBKIT_SUBSYSTEM, channel->name);
}
#endif
for (auto logLevelComponent : StringView::fromLatin1(logLevel).split(',')) {
auto componentInfo = logLevelComponent.split('=');
auto it = componentInfo.begin();
if (it == componentInfo.end())
continue;
auto component = (*it).trim(isUnicodeCompatibleASCIIWhitespace<char16_t>);
WTFLogChannelState logChannelState = WTFLogChannelState::On;
if (component.startsWith('-')) {
logChannelState = WTFLogChannelState::Off;
component = component.substring(1);
}
if (equalLettersIgnoringASCIICase(component, "all"_s)) {
setStateOfAllChannels(channels, count, logChannelState);
continue;
}
WTFLogLevel logChannelLevel = WTFLogLevel::Error;
if (++it != componentInfo.end()) {
auto level = (*it).trim(isUnicodeCompatibleASCIIWhitespace<char16_t>);
if (equalLettersIgnoringASCIICase(level, "error"_s))
logChannelLevel = WTFLogLevel::Error;
else if (equalLettersIgnoringASCIICase(level, "warning"_s))
logChannelLevel = WTFLogLevel::Warning;
else if (equalLettersIgnoringASCIICase(level, "info"_s))
logChannelLevel = WTFLogLevel::Info;
else if (equalLettersIgnoringASCIICase(level, "debug"_s))
logChannelLevel = WTFLogLevel::Debug;
else
WTFLogAlways("Unknown logging level: %s", level.utf8().data());
}
if (WTFLogChannel* channel = WTFLogChannelByName(channels, count, component.utf8().data())) {
channel->state = logChannelState;
channel->level = logChannelLevel;
} else
WTFLogAlways("Unknown logging channel: %s", component.utf8().data());
}
}
} // extern "C"
#if !ASAN_ENABLED && (OS(DARWIN) || PLATFORM(PLAYSTATION)) && (CPU(X86_64) || CPU(ARM64))
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1, UCPURegister misc2, UCPURegister misc3, UCPURegister misc4, UCPURegister misc5, UCPURegister misc6)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
register UCPURegister misc2GPR __asm__(CRASH_GPR2) = misc2;
register UCPURegister misc3GPR __asm__(CRASH_GPR3) = misc3;
register UCPURegister misc4GPR __asm__(CRASH_GPR4) = misc4;
register UCPURegister misc5GPR __asm__(CRASH_GPR5) = misc5;
register UCPURegister misc6GPR __asm__(CRASH_GPR6) = misc6;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR), "r"(misc6GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1, UCPURegister misc2, UCPURegister misc3, UCPURegister misc4, UCPURegister misc5)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
register UCPURegister misc2GPR __asm__(CRASH_GPR2) = misc2;
register UCPURegister misc3GPR __asm__(CRASH_GPR3) = misc3;
register UCPURegister misc4GPR __asm__(CRASH_GPR4) = misc4;
register UCPURegister misc5GPR __asm__(CRASH_GPR5) = misc5;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1, UCPURegister misc2, UCPURegister misc3, UCPURegister misc4)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
register UCPURegister misc2GPR __asm__(CRASH_GPR2) = misc2;
register UCPURegister misc3GPR __asm__(CRASH_GPR3) = misc3;
register UCPURegister misc4GPR __asm__(CRASH_GPR4) = misc4;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1, UCPURegister misc2, UCPURegister misc3)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
register UCPURegister misc2GPR __asm__(CRASH_GPR2) = misc2;
register UCPURegister misc3GPR __asm__(CRASH_GPR3) = misc3;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1, UCPURegister misc2)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
register UCPURegister misc2GPR __asm__(CRASH_GPR2) = misc2;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason, UCPURegister misc1)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
register UCPURegister misc1GPR __asm__(CRASH_GPR1) = misc1;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR));
__builtin_unreachable();
}
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister reason)
{
register UCPURegister reasonGPR __asm__(CRASH_GPR0) = reason;
__asm__ volatile (WTF_FATAL_CRASH_INST : : "r"(reasonGPR));
__builtin_unreachable();
}
#else
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister, UCPURegister, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister, UCPURegister) { CRASH(); }
void WTFCrashWithInfoImpl(int, const char*, const char*, UCPURegister) { CRASH(); }
#endif // (OS(DARWIN) || PLATFORM(PLAYSTATION)) && (CPU(X64_64) || CPU(ARM64))
namespace WTF {
void resetAccumulatedLogs()
{
loggingAccumulator().resetAccumulatedLogs();
}
String getAndResetAccumulatedLogs()
{
return loggingAccumulator().getAndResetAccumulatedLogs();
}
} // namespace WTF
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END