Coverage Report

Created: 2024-07-09 06:09

/proc/self/cwd/pw_assert_basic/basic_handler.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2021 The Pigweed Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4
// use this file except in compliance with the License. You may obtain a copy of
5
// the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
// License for the specific language governing permissions and limitations under
13
// the License.
14
15
// This is a very basic direct output log implementation with no buffering.
16
17
// #define PW_LOG_MODULE_NAME "ASRT"
18
// #include "pw_log/log.h"
19
20
#include <cstdio>
21
#include <cstring>
22
23
#include "pw_assert/config.h"
24
#include "pw_assert_basic/handler.h"
25
#include "pw_preprocessor/util.h"
26
#include "pw_string/string_builder.h"
27
#include "pw_sys_io/sys_io.h"
28
29
// ANSI color constants to control the terminal. Not Windows compatible.
30
// clang-format off
31
#if PW_ASSERT_BASIC_USE_COLORS
32
0
#define MAGENTA   "\033[35m"
33
0
#define YELLOW    "\033[33m"
34
0
#define RED       "\033[31m"
35
#define GREEN     "\033[32m"
36
#define BLUE      "\033[96m"
37
#define BLACK     "\033[30m"
38
#define YELLOW_BG "\033[43m"
39
#define WHITE_BG  "\033[47m"
40
#define RED_BG    "\033[41m"
41
#define BOLD      "\033[1m"
42
0
#define RESET     "\033[0m"
43
#else
44
#define MAGENTA   ""
45
#define YELLOW    ""
46
#define RED       ""
47
#define GREEN     ""
48
#define BLUE      ""
49
#define BLACK     ""
50
#define YELLOW_BG ""
51
#define WHITE_BG  ""
52
#define RED_BG    ""
53
#define BOLD      ""
54
#define RESET     ""
55
#endif  // PW_ASSERT_BASIC_USE_COLORS
56
// clang-format on
57
58
static const char* kCrashBanner[] = {
59
    " ",
60
    "   ▄████▄      ██▀███      ▄▄▄           ██████     ██░ ██    ",
61
    "  ▒██▀ ▀█     ▓██ ▒ ██▒   ▒████▄       ▒██    ▒    ▓██░ ██▒   ",
62
    "  ▒▓█ 💥 ▄    ▓██ ░▄█ ▒   ▒██  ▀█▄     ░ ▓██▄      ▒██▀▀██░   ",
63
    "  ▒▓▓▄ ▄██▒   ▒██▀▀█▄     ░██▄▄▄▄██      ▒   ██▒   ░▓█ ░██    ",
64
    "  ▒ ▓███▀ ░   ░██▓ ▒██▒    ▓█   ▓██▒   ▒██████▒▒   ░▓█▒░██▓   ",
65
    "  ░ ░▒ ▒  ░   ░ ▒▓ ░▒▓░    ▒▒   ▓▒█░   ▒ ▒▓▒ ▒ ░    ▒ ░░▒░▒   ",
66
    "    ░  ▒        ░▒ ░ ▒░     ▒   ▒▒ ░   ░ ░▒  ░ ░    ▒ ░▒░ ░   ",
67
    "  ░             ░░   ░      ░   ▒      ░  ░  ░      ░  ░░ ░   ",
68
    "  ░ ░            ░              ░  ░         ░      ░  ░  ░   ",
69
    "  ░",
70
    " ",
71
};
72
73
0
static void WriteLine(std::string_view s) {
74
0
  pw::sys_io::WriteLine(s)
75
0
      .IgnoreError();  // TODO: b/242598609 - Handle Status properly
76
0
}
77
78
typedef pw::StringBuffer<150> Buffer;
79
80
extern "C" void pw_assert_basic_HandleFailure(const char* file_name,
81
                                              int line_number,
82
                                              const char* function_name,
83
                                              const char* format,
84
0
                                              ...) {
85
  // As a matter of usability, crashes should be visible; make it so.
86
0
#if PW_ASSERT_BASIC_SHOW_BANNER
87
0
  WriteLine(RED);
88
0
  for (const char* line : kCrashBanner) {
89
0
    WriteLine(line);
90
0
  }
91
0
  WriteLine(RESET);
92
0
#endif  // PW_ASSERT_BASIC_SHOW_BANNER
93
94
0
  WriteLine(
95
0
      "  Welp, that didn't go as planned. "
96
0
      "It seems we crashed. Terribly sorry!");
97
0
  WriteLine("");
98
0
  WriteLine(YELLOW "  CRASH MESSAGE" RESET);
99
0
  WriteLine("");
100
0
  {
101
0
    Buffer buffer;
102
0
    buffer << "     ";
103
0
    va_list args;
104
0
    va_start(args, format);
105
0
    buffer.FormatVaList(format, args);
106
0
    va_end(args);
107
0
    WriteLine(buffer.view());
108
0
  }
109
110
0
  if (file_name != nullptr && line_number != -1) {
111
0
    WriteLine("");
112
0
    WriteLine(YELLOW "  CRASH FILE & LINE" RESET);
113
0
    WriteLine("");
114
0
    {
115
0
      Buffer buffer;
116
0
      buffer.Format("     %s:%d", file_name, line_number);
117
0
      WriteLine(buffer.view());
118
0
    }
119
0
  }
120
0
  if (function_name != nullptr) {
121
0
    WriteLine("");
122
0
    WriteLine(YELLOW "  CRASH FUNCTION" RESET);
123
0
    WriteLine("");
124
0
    {
125
0
      Buffer buffer;
126
0
      buffer.Format("     %s", function_name);
127
0
      WriteLine(buffer.view());
128
0
    }
129
0
  }
130
131
  // TODO(pwbug/95): Perhaps surprisingly, this doesn't actually crash the
132
  // device. At some point we'll have a reboot BSP function or similar, but for
133
  // now this is acceptable since no one is using this basic backend.
134
0
  if (!PW_ASSERT_BASIC_DISABLE_NORETURN) {
135
0
#if (PW_ASSERT_BASIC_ACTION == PW_ASSERT_BASIC_ACTION_ABORT)
136
    // abort() doesn't flush stderr/stdout, so manually flush them before
137
    // aborting. abort() is preferred to exit(1) because debuggers catch it.
138
0
    std::fflush(stderr);
139
0
    std::fflush(stdout);
140
0
    std::abort();
141
#elif (PW_ASSERT_BASIC_ACTION == PW_ASSERT_BASIC_ACTION_EXIT)
142
    // Use _Exit to not run destructors or atexit hooks in case they cause
143
    // further crashes.
144
    std::_Exit(-1);
145
#elif (PW_ASSERT_BASIC_ACTION == PW_ASSERT_BASIC_ACTION_LOOP)
146
    WriteLine("");
147
    WriteLine(MAGENTA "  HANG TIME" RESET);
148
    WriteLine("");
149
    WriteLine(
150
        "     ... until a debugger joins. System is waiting in a while(1)");
151
    while (true) {
152
    }
153
#else
154
#error PW_ASSERT_BASIC_ACTION Must be set to valid option.
155
#endif
156
0
    PW_UNREACHABLE;
157
0
  } else {
158
0
    WriteLine("");
159
0
    WriteLine(MAGENTA "  NOTE: YOU ARE IN ASSERT BASIC TEST MODE" RESET);
160
0
    WriteLine("");
161
0
    WriteLine("     This build returns from the crash handler for testing.");
162
0
    WriteLine("     If you see this message in production, your build is ");
163
0
    WriteLine("     incorrectly configured. Search for");
164
0
    WriteLine("     PW_ASSERT_BASIC_DISABLE_NORETURN to fix it.");
165
0
    WriteLine("");
166
0
  }
167
0
}