Coverage Report

Created: 2026-07-25 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/AK/Assertions.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/Assertions.h>
8
#include <AK/Format.h>
9
#include <AK/Platform.h>
10
#include <AK/StringBuilder.h>
11
#include <AK/StringView.h>
12
13
#if (defined(AK_OS_LINUX) && defined(AK_LIBC_GLIBC)) || defined(AK_OS_BSD_GENERIC) || defined(AK_OS_SOLARIS) || defined(AK_OS_HAIKU) || defined(AK_OS_GNU_HURD)
14
#    define EXECINFO_BACKTRACE
15
#endif
16
17
0
#define PRINT_ERROR(s) (void)fputs((s), stderr)
18
19
#if defined(EXECINFO_BACKTRACE)
20
#    include <cxxabi.h>
21
#    include <execinfo.h>
22
#endif
23
24
#if defined(AK_OS_SERENITY)
25
#    define ERRORLN dbgln
26
#else
27
0
#    define ERRORLN warnln
28
#endif
29
30
#if !defined(KERNEL)
31
32
#    if defined(EXECINFO_BACKTRACE)
33
namespace {
34
ALWAYS_INLINE void dump_backtrace()
35
0
{
36
    // Grab symbols and dso name for up to 256 frames
37
0
    void* trace[256] = {};
38
0
    int const num_frames = backtrace(trace, array_size(trace));
39
0
    char** syms = backtrace_symbols(trace, num_frames);
40
41
0
    for (auto i = 0; i < num_frames; ++i) {
42
        // If there is a C++ symbol name in the line of the backtrace, demangle it
43
0
        StringView sym(syms[i], strlen(syms[i]));
44
0
        StringBuilder error_builder;
45
0
        if (auto idx = sym.find("_Z"sv); idx.has_value()) {
46
            // Play C games with the original string so we can print before and after the mangled symbol with a C API
47
            // We don't want to call dbgln() here on substring StringView because we might VERIFY() within AK::Format
48
0
            syms[i][idx.value() - 1] = '\0';
49
0
            error_builder.append(syms[i], strlen(syms[i]));
50
0
            error_builder.append(' ');
51
52
0
            auto sym_substring = sym.substring_view(idx.value());
53
0
            auto end_of_sym = sym_substring.find_any_of("+ "sv).value_or(sym_substring.length() - 1);
54
0
            syms[i][idx.value() + end_of_sym] = '\0';
55
56
0
            size_t buf_size = 128u;
57
0
            char* buf = static_cast<char*>(malloc(buf_size));
58
0
            auto* raw_str = &syms[i][idx.value()];
59
0
            buf = abi::__cxa_demangle(raw_str, buf, &buf_size, nullptr);
60
61
0
            auto* buf_to_print = buf ? buf : raw_str;
62
0
            error_builder.append(buf_to_print, strlen(buf_to_print));
63
0
            free(buf);
64
65
0
            error_builder.append(' ');
66
0
            auto* end_of_line = &syms[i][idx.value() + end_of_sym + 1];
67
0
            error_builder.append(end_of_line, strlen(end_of_line));
68
0
        } else {
69
0
            error_builder.append(sym);
70
0
        }
71
0
        error_builder.append('\n');
72
0
        error_builder.append('\0');
73
0
        PRINT_ERROR(error_builder.string_view().characters_without_null_termination());
74
0
    }
75
0
    free(syms);
76
0
}
77
}
78
#    endif
79
80
extern "C" {
81
82
void ak_verification_failed(char const* message)
83
0
{
84
#    if defined(AK_OS_SERENITY)
85
    bool colorize_output = true;
86
#    elif defined(AK_OS_WINDOWS)
87
    bool colorize_output = false;
88
#    else
89
0
    bool colorize_output = isatty(STDERR_FILENO) == 1;
90
0
#    endif
91
92
0
    if (colorize_output)
93
0
        ERRORLN("\033[31;1mVERIFICATION FAILED\033[0m: {}", message);
94
0
    else
95
0
        ERRORLN("VERIFICATION FAILED: {}", message);
96
97
0
#    if defined(EXECINFO_BACKTRACE)
98
0
    dump_backtrace();
99
0
#    endif
100
0
    __builtin_trap();
101
0
}
102
}
103
104
#endif