source: webkit/trunk/Source/WTF/wtf/Assertions.cpp

Last change on this file was 278474, checked in by Devin Rousso, 4 weeks ago

Add a way to prefix output of WTFReportBacktrace to make log filtering easier
https://bugs.webkit.org/show_bug.cgi?id=226390

Reviewed by Megan Gardner.

Often times while debugging I add WTFLogAlways("<DR> ...") to various places as indicators
that "logic has reached here". This is especially useful when debugging iOS as unlike macOS
there's no console output from run-safari, meaning that I have to use system logging,
which is often a deluge of unrelated information. Having "<DR>" as a prefix makes filtering
through the system logging trivial as I can ignore logs that don't have it. Unfortunately,
WTFReportBacktrace does not have a way to add this prefix, so it becomes much harder to
find in the logs. This patch enables adding a prefix to each line of WTFReportBacktrace
via a new function WTFReportBactraceWithPrefix.

  • wtf/Assertions.h:
  • wtf/Assertions.cpp:

(WTFReportBacktraceWithPrefix): Added.
(WTFPrintBacktraceWithPrefix): Added.

  • wtf/StackTrace.h:

(WTF::StackTrace::StackTrace):

  • wtf/StackTrace.cpp:

(WTF::StackTrace::dump const):

  • Property svn:eol-style set to native
File size: 23.6 KB
Line 
1/*
2 * Copyright (C) 2003-2021 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#include "config.h"
29#include <wtf/Assertions.h>
30
31#include <mutex>
32#include <stdio.h>
33#include <string.h>
34#include <wtf/Compiler.h>
35#include <wtf/Lock.h>
36#include <wtf/Locker.h>
37#include <wtf/LoggingAccumulator.h>
38#include <wtf/PrintStream.h>
39#include <wtf/StackTrace.h>
40#include <wtf/WTFConfig.h>
41#include <wtf/text/CString.h>
42#include <wtf/text/StringBuilder.h>
43#include <wtf/text/WTFString.h>
44
45#if USE(CF)
46#include <CoreFoundation/CFString.h>
47#endif // USE(CF)
48
49#if COMPILER(MSVC)
50#include <crtdbg.h>
51#endif
52
53#if OS(WINDOWS)
54#include <windows.h>
55#endif
56
57#if OS(DARWIN)
58#include <sys/sysctl.h>
59#include <unistd.h>
60#endif
61
62#if USE(JOURNALD)
63#include <wtf/StringPrintStream.h>
64#endif
65
66#if PLATFORM(COCOA)
67#import <wtf/spi/cocoa/OSLogSPI.h>
68#endif
69
70namespace WTF {
71
72WTF_ATTRIBUTE_PRINTF(1, 0) static String createWithFormatAndArguments(const char* format, va_list args)
73{
74    va_list argsCopy;
75    va_copy(argsCopy, args);
76
77    ALLOW_NONLITERAL_FORMAT_BEGIN
78
79#if USE(CF) && !OS(WINDOWS)
80    if (strstr(format, "%@")) {
81        auto cfFormat = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, format, kCFStringEncodingUTF8));
82        auto result = adoptCF(CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, nullptr, cfFormat.get(), args));
83        va_end(argsCopy);
84        return result.get();
85    }
86#endif
87
88    // Do the format once to get the length.
89#if COMPILER(MSVC)
90    int result = _vscprintf(format, args);
91#else
92    char ch;
93    int result = vsnprintf(&ch, 1, format, args);
94#endif
95
96    if (!result) {
97        va_end(argsCopy);
98        return emptyString();
99    }
100    if (result < 0) {
101        va_end(argsCopy);
102        return { };
103    }
104
105    Vector<char, 256> buffer;
106    unsigned length = result;
107    buffer.grow(length + 1);
108
109    // Now do the formatting again, guaranteed to fit.
110    vsnprintf(buffer.data(), buffer.size(), format, argsCopy);
111    va_end(argsCopy);
112
113    ALLOW_NONLITERAL_FORMAT_END
114
115    return StringImpl::create(reinterpret_cast<const LChar*>(buffer.data()), length);
116}
117
118#if PLATFORM(COCOA)
119void disableForwardingVPrintfStdErrToOSLog()
120{
121    g_wtfConfig.disableForwardingVPrintfStdErrToOSLog = true;
122}
123#endif
124
125} // namespace WTF
126
127extern "C" {
128
129static void logToStderr(const char* buffer)
130{
131#if PLATFORM(COCOA)
132    os_log(OS_LOG_DEFAULT, "%s", buffer);
133#endif
134    fputs(buffer, stderr);
135}
136
137WTF_ATTRIBUTE_PRINTF(1, 0)
138static void vprintf_stderr_common(const char* format, va_list args)
139{
140#if USE(CF) && !OS(WINDOWS)
141    if (strstr(format, "%@")) {
142        auto cfFormat = adoptCF(CFStringCreateWithCString(nullptr, format, kCFStringEncodingUTF8));
143
144        ALLOW_NONLITERAL_FORMAT_BEGIN
145        auto str = adoptCF(CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfFormat.get(), args));
146        ALLOW_NONLITERAL_FORMAT_END
147        CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str.get()), kCFStringEncodingUTF8);
148        constexpr unsigned InitialBufferSize { 256 };
149        Vector<char, InitialBufferSize> buffer(length + 1);
150
151        CFStringGetCString(str.get(), buffer.data(), length, kCFStringEncodingUTF8);
152
153        logToStderr(buffer.data());
154        return;
155    }
156
157#if PLATFORM(COCOA)
158    if (!g_wtfConfig.disableForwardingVPrintfStdErrToOSLog) {
159        va_list copyOfArgs;
160        va_copy(copyOfArgs, args);
161        os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, format, copyOfArgs, __builtin_return_address(0));
162        va_end(copyOfArgs);
163    }
164#endif
165
166    // Fall through to write to stderr in the same manner as other platforms.
167
168#elif HAVE(ISDEBUGGERPRESENT)
169    if (IsDebuggerPresent()) {
170        size_t size = 1024;
171        Vector<char> buffer(size);
172        do {
173            buffer.grow(size);
174            if (vsnprintf(buffer.data(), size, format, args) != -1) {
175                OutputDebugStringA(buffer.data());
176                break;
177            }
178            size *= 2;
179        } while (size > 1024);
180    }
181#endif
182    vfprintf(stderr, format, args);
183}
184
185ALLOW_NONLITERAL_FORMAT_BEGIN
186
187WTF_ATTRIBUTE_PRINTF(2, 0)
188static void vprintf_stderr_with_prefix(const char* prefix, const char* format, va_list args)
189{
190    size_t prefixLength = strlen(prefix);
191    size_t formatLength = strlen(format);
192    Vector<char> formatWithPrefix(prefixLength + formatLength + 1);
193    memcpy(formatWithPrefix.data(), prefix, prefixLength);
194    memcpy(formatWithPrefix.data() + prefixLength, format, formatLength);
195    formatWithPrefix[prefixLength + formatLength] = 0;
196
197    vprintf_stderr_common(formatWithPrefix.data(), args);
198}
199
200WTF_ATTRIBUTE_PRINTF(1, 0)
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 final : public PrintStream {
272public:
273    WTF_ATTRIBUTE_PRINTF(2, 0)
274    void vprintf(const char* format, va_list argList) final
275    {
276        vprintf_stderr_common(format, argList);
277    }
278};
279
280void WTFReportBacktraceWithPrefix(const char* prefix)
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    WTFPrintBacktraceWithPrefix(samples + framesToSkip, frames - framesToSkip, prefix);
289}
290
291void WTFReportBacktrace()
292{
293    static constexpr int framesToShow = 31;
294    static constexpr int framesToSkip = 2;
295    void* samples[framesToShow + framesToSkip];
296    int frames = framesToShow + framesToSkip;
297
298    WTFGetBacktrace(samples, &frames);
299    WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip);
300}
301
302void WTFPrintBacktraceWithPrefix(void** stack, int size, const char* prefix)
303{
304    CrashLogPrintStream out;
305    StackTrace stackTrace(stack, size, prefix);
306    out.print(stackTrace);
307}
308
309void WTFPrintBacktrace(void** stack, int size)
310{
311    WTFPrintBacktraceWithPrefix(stack, size, "");
312}
313
314#if !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
315void WTFCrash()
316{
317    WTFReportBacktrace();
318#if ASAN_ENABLED
319    __builtin_trap();
320#else
321    *(int *)(uintptr_t)0xbbadbeef = 0;
322    // More reliable, but doesn't say BBADBEEF.
323#if COMPILER(GCC_COMPATIBLE)
324    __builtin_trap();
325#else
326    ((void(*)())nullptr)();
327#endif // COMPILER(GCC_COMPATIBLE)
328#endif // ASAN_ENABLED
329}
330#else
331// We need to keep WTFCrash() around (even on non-debug OS(DARWIN) builds) as a workaround
332// for presently shipping (circa early 2016) SafariForWebKitDevelopment binaries which still
333// expects to link to it.
334void WTFCrash()
335{
336    CRASH();
337}
338#endif // !defined(NDEBUG) || !(OS(DARWIN) || PLATFORM(PLAYSTATION))
339
340void WTFCrashWithSecurityImplication()
341{
342    CRASH();
343}
344
345bool WTFIsDebuggerAttached()
346{
347#if OS(DARWIN)
348    struct kinfo_proc info;
349    int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
350    size_t size = sizeof(info);
351    if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &info, &size, nullptr, 0) == -1)
352        return false;
353    return info.kp_proc.p_flag & P_TRACED;
354#else
355    return false;
356#endif
357}
358
359void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
360{
361    va_list args;
362    va_start(args, format);
363    vprintf_stderr_with_prefix("FATAL ERROR: ", format, args);
364    va_end(args);
365    printf_stderr_common("\n");
366    printCallSite(file, line, function);
367}
368
369void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
370{
371    va_list args;
372    va_start(args, format);
373    vprintf_stderr_with_prefix("ERROR: ", format, args);
374    va_end(args);
375    printf_stderr_common("\n");
376    printCallSite(file, line, function);
377}
378
379class WTFLoggingAccumulator {
380    WTF_MAKE_FAST_ALLOCATED;
381public:
382    void accumulate(const String&);
383    void resetAccumulatedLogs();
384    String getAndResetAccumulatedLogs();
385
386private:
387    Lock accumulatorLock;
388    StringBuilder loggingAccumulator WTF_GUARDED_BY_LOCK(accumulatorLock);
389};
390
391void WTFLoggingAccumulator::accumulate(const String& log)
392{
393    Locker locker { accumulatorLock };
394    loggingAccumulator.append(log);
395}
396
397void WTFLoggingAccumulator::resetAccumulatedLogs()
398{
399    Locker locker { accumulatorLock };
400    loggingAccumulator.clear();
401}
402
403String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
404{
405    Locker locker { accumulatorLock };
406    String result = loggingAccumulator.toString();
407    loggingAccumulator.clear();
408    return result;
409}
410
411static WTFLoggingAccumulator& loggingAccumulator()
412{
413    static WTFLoggingAccumulator* accumulator;
414    static std::once_flag initializeAccumulatorOnce;
415    std::call_once(initializeAccumulatorOnce, [] {
416        accumulator = new WTFLoggingAccumulator;
417    });
418
419    return *accumulator;
420}
421
422void WTFSetLogChannelLevel(WTFLogChannel* channel, WTFLogLevel level)
423{
424    channel->level = level;
425}
426
427bool WTFWillLogWithLevel(WTFLogChannel* channel, WTFLogLevel level)
428{
429    return channel->level >= level && channel->state != WTFLogChannelState::Off;
430}
431
432void WTFLogWithLevel(WTFLogChannel* channel, WTFLogLevel level, const char* format, ...)
433{
434    if (level != WTFLogLevel::Always && level > channel->level)
435        return;
436
437    if (channel->level != WTFLogLevel::Always && channel->state == WTFLogChannelState::Off)
438        return;
439
440    va_list args;
441    va_start(args, format);
442
443    ALLOW_NONLITERAL_FORMAT_BEGIN
444    WTFLog(channel, format, args);
445    ALLOW_NONLITERAL_FORMAT_END
446
447    va_end(args);
448}
449
450WTF_ATTRIBUTE_PRINTF(2, 0)
451static void WTFLogVaList(WTFLogChannel* channel, const char* format, va_list args)
452{
453    if (channel->state == WTFLogChannelState::Off)
454        return;
455
456    if (channel->state == WTFLogChannelState::On) {
457        vprintf_stderr_with_trailing_newline(format, args);
458        return;
459    }
460
461    ASSERT(channel->state == WTFLogChannelState::OnWithAccumulation);
462
463    ALLOW_NONLITERAL_FORMAT_BEGIN
464    String loggingString = WTF::createWithFormatAndArguments(format, args);
465    ALLOW_NONLITERAL_FORMAT_END
466
467    if (!loggingString.endsWith('\n'))
468        loggingString.append('\n');
469
470    loggingAccumulator().accumulate(loggingString);
471
472    logToStderr(loggingString.utf8().data());
473}
474
475void WTFLog(WTFLogChannel* channel, const char* format, ...)
476{
477    va_list args;
478    va_start(args, format);
479
480    WTFLogVaList(channel, format, args);
481
482    va_end(args);
483}
484
485void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
486{
487    if (channel->state != WTFLogChannelState::On)
488        return;
489
490    va_list args;
491    va_start(args, format);
492
493    ALLOW_NONLITERAL_FORMAT_BEGIN
494    WTFLogVaList(channel, format, args);
495    ALLOW_NONLITERAL_FORMAT_END
496
497    va_end(args);
498
499    printCallSite(file, line, function);
500}
501
502void WTFLogAlwaysV(const char* format, va_list args)
503{
504    vprintf_stderr_with_trailing_newline(format, args);
505}
506
507void WTFLogAlways(const char* format, ...)
508{
509    va_list args;
510    va_start(args, format);
511    WTFLogAlwaysV(format, args);
512    va_end(args);
513}
514
515void WTFLogAlwaysAndCrash(const char* format, ...)
516{
517    va_list args;
518    va_start(args, format);
519    WTFLogAlwaysV(format, args);
520    va_end(args);
521    CRASH();
522}
523
524WTFLogChannel* WTFLogChannelByName(WTFLogChannel* channels[], size_t count, const char* name)
525{
526    for (size_t i = 0; i < count; ++i) {
527        WTFLogChannel* channel = channels[i];
528        if (equalIgnoringASCIICase(name, channel->name))
529            return channel;
530    }
531
532    return nullptr;
533}
534
535static void setStateOfAllChannels(WTFLogChannel* channels[], size_t channelCount, WTFLogChannelState state)
536{
537    for (size_t i = 0; i < channelCount; ++i)
538        channels[i]->state = state;
539}
540
541void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t count, const char* logLevel)
542{
543#if USE(OS_LOG) && !RELEASE_LOG_DISABLED
544    for (size_t i = 0; i < count; ++i) {
545        WTFLogChannel* channel = channels[i];
546        channel->osLogChannel = os_log_create(channel->subsystem, channel->name);
547    }
548#endif
549
550    for (auto& logLevelComponent : String(logLevel).split(',')) {
551        Vector<String> componentInfo = logLevelComponent.split('=');
552        String component = componentInfo[0].stripWhiteSpace();
553
554        WTFLogChannelState logChannelState = WTFLogChannelState::On;
555        if (component.startsWith('-')) {
556            logChannelState = WTFLogChannelState::Off;
557            component = component.substring(1);
558        }
559
560        if (equalLettersIgnoringASCIICase(component, "all")) {
561            setStateOfAllChannels(channels, count, logChannelState);
562            continue;
563        }
564
565        WTFLogLevel logChannelLevel = WTFLogLevel::Error;
566        if (componentInfo.size() > 1) {
567            String level = componentInfo[1].stripWhiteSpace();
568            if (equalLettersIgnoringASCIICase(level, "error"))
569                logChannelLevel = WTFLogLevel::Error;
570            else if (equalLettersIgnoringASCIICase(level, "warning"))
571                logChannelLevel = WTFLogLevel::Warning;
572            else if (equalLettersIgnoringASCIICase(level, "info"))
573                logChannelLevel = WTFLogLevel::Info;
574            else if (equalLettersIgnoringASCIICase(level, "debug"))
575                logChannelLevel = WTFLogLevel::Debug;
576            else
577                WTFLogAlways("Unknown logging level: %s", level.utf8().data());
578        }
579
580        if (WTFLogChannel* channel = WTFLogChannelByName(channels, count, component.utf8().data())) {
581            channel->state = logChannelState;
582            channel->level = logChannelLevel;
583        } else
584            WTFLogAlways("Unknown logging channel: %s", component.utf8().data());
585    }
586}
587
588#if !RELEASE_LOG_DISABLED
589void WTFReleaseLogStackTrace(WTFLogChannel* channel)
590{
591    auto stackTrace = WTF::StackTrace::captureStackTrace(30, 0);
592    if (stackTrace && stackTrace->stack()) {
593        auto stack = stackTrace->stack();
594        for (int frameNumber = 1; frameNumber < stackTrace->size(); ++frameNumber) {
595            auto stackFrame = stack[frameNumber];
596            auto demangled = WTF::StackTrace::demangle(stackFrame);
597#if USE(OS_LOG)
598            if (demangled && demangled->demangledName())
599                os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->demangledName());
600            else if (demangled && demangled->mangledName())
601                os_log(channel->osLogChannel, "%-3d %p %{public}s", frameNumber, stackFrame, demangled->mangledName());
602            else
603                os_log(channel->osLogChannel, "%-3d %p", frameNumber, stackFrame);
604#elif USE(JOURNALD)
605            StringPrintStream out;
606            if (demangled && demangled->demangledName())
607                out.printf("%-3d %p %s", frameNumber, stackFrame, demangled->demangledName());
608            else if (demangled && demangled->mangledName())
609                out.printf("%-3d %p %s", frameNumber, stackFrame, demangled->mangledName());
610            else
611                out.printf("%-3d %p", frameNumber, stackFrame);
612            sd_journal_send("WEBKIT_SUBSYSTEM=%s", channel->subsystem, "WEBKIT_CHANNEL=%s", channel->name, "MESSAGE=%s", out.toCString().data(), nullptr);
613#endif
614        }
615    }
616}
617#endif
618
619} // extern "C"
620
621#if (OS(DARWIN) || PLATFORM(PLAYSTATION)) && (CPU(X86_64) || CPU(ARM64))
622#if CPU(X86_64)
623
624#define CRASH_INST "int3"
625
626// This ordering was chosen to be consistent with JSC's JIT asserts. We probably shouldn't change this ordering
627// since it would make tooling crash reports much harder. If, for whatever reason, we decide to change the ordering
628// here we should update the abortWithuint64_t functions.
629#define CRASH_GPR0 "r11"
630#define CRASH_GPR1 "r10"
631#define CRASH_GPR2 "r9"
632#define CRASH_GPR3 "r8"
633#define CRASH_GPR4 "r15"
634#define CRASH_GPR5 "r14"
635#define CRASH_GPR6 "r13"
636
637#elif CPU(ARM64) // CPU(X86_64)
638
639#define CRASH_INST "brk #0xc471"
640
641// See comment above on the ordering.
642#define CRASH_GPR0 "x16"
643#define CRASH_GPR1 "x17"
644#define CRASH_GPR2 "x18"
645#define CRASH_GPR3 "x19"
646#define CRASH_GPR4 "x20"
647#define CRASH_GPR5 "x21"
648#define CRASH_GPR6 "x22"
649
650#endif // CPU(ARM64)
651
652void 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)
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    register uint64_t misc6GPR asm(CRASH_GPR6) = misc6;
661    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR), "r"(misc6GPR));
662    __builtin_unreachable();
663}
664
665void 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)
666{
667    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
668    register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
669    register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
670    register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
671    register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
672    register uint64_t misc5GPR asm(CRASH_GPR5) = misc5;
673    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR), "r"(misc5GPR));
674    __builtin_unreachable();
675}
676
677void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3, uint64_t misc4)
678{
679    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
680    register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
681    register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
682    register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
683    register uint64_t misc4GPR asm(CRASH_GPR4) = misc4;
684    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR), "r"(misc4GPR));
685    __builtin_unreachable();
686}
687
688void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2, uint64_t misc3)
689{
690    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
691    register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
692    register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
693    register uint64_t misc3GPR asm(CRASH_GPR3) = misc3;
694    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR), "r"(misc3GPR));
695    __builtin_unreachable();
696}
697
698void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1, uint64_t misc2)
699{
700    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
701    register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
702    register uint64_t misc2GPR asm(CRASH_GPR2) = misc2;
703    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR), "r"(misc2GPR));
704    __builtin_unreachable();
705}
706
707void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason, uint64_t misc1)
708{
709    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
710    register uint64_t misc1GPR asm(CRASH_GPR1) = misc1;
711    __asm__ volatile (CRASH_INST : : "r"(reasonGPR), "r"(misc1GPR));
712    __builtin_unreachable();
713}
714
715void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t reason)
716{
717    register uint64_t reasonGPR asm(CRASH_GPR0) = reason;
718    __asm__ volatile (CRASH_INST : : "r"(reasonGPR));
719    __builtin_unreachable();
720}
721
722#else
723
724void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
725void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
726void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
727void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t, uint64_t) { CRASH(); }
728void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t, uint64_t) { CRASH(); }
729void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t, uint64_t) { CRASH(); }
730void WTFCrashWithInfoImpl(int, const char*, const char*, int, uint64_t) { CRASH(); }
731
732#endif // (OS(DARWIN) || PLATFORM(PLAYSTATION)) && (CPU(X64_64) || CPU(ARM64))
733
734namespace WTF {
735
736void resetAccumulatedLogs()
737{
738    loggingAccumulator().resetAccumulatedLogs();
739}
740
741String getAndResetAccumulatedLogs()
742{
743    return loggingAccumulator().getAndResetAccumulatedLogs();
744}
745
746} // namespace WTF
Note: See TracBrowser for help on using the repository browser.