1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 // This is a very basic direct output log implementation with no buffering.
17 //#define PW_LOG_MODULE_NAME "ASRT"
18 //#include "pw_log/log.h"
22 #include "pw_assert/options.h"
23 #include "pw_assert_basic/handler.h"
24 #include "pw_preprocessor/util.h"
25 #include "pw_string/string_builder.h"
26 #include "pw_sys_io/sys_io.h"
28 // If 1, call C's standard abort() function on assert failure.
29 #ifndef PW_ASSERT_BASIC_ABORT
30 #define PW_ASSERT_BASIC_ABORT 1
31 #endif // PW_ASSERT_BASIC_ABORT
33 // TODO(pwbug/17): Expose these through the config system.
34 #define PW_ASSERT_BASIC_SHOW_BANNER 1
35 #define PW_ASSERT_BASIC_USE_COLORS 1
37 // ANSI color constants to control the terminal. Not Windows compatible.
39 #if PW_ASSERT_BASIC_USE_COLORS
40 #define MAGENTA "\033[35m"
41 #define YELLOW "\033[33m"
42 #define RED "\033[31m"
43 #define GREEN "\033[32m"
44 #define BLUE "\033[96m"
45 #define BLACK "\033[30m"
46 #define YELLOW_BG "\033[43m"
47 #define WHITE_BG "\033[47m"
48 #define RED_BG "\033[41m"
49 #define BOLD "\033[1m"
50 #define RESET "\033[0m"
63 #endif // PW_ASSERT_BASIC_USE_COLORS
66 static const char* kCrashBanner[] = {
68 " ▄████▄ ██▀███ ▄▄▄ ██████ ██░ ██ ",
69 " ▒██▀ ▀█ ▓██ ▒ ██▒ ▒████▄ ▒██ ▒ ▓██░ ██▒ ",
70 " ▒▓█ 💥 ▄ ▓██ ░▄█ ▒ ▒██ ▀█▄ ░ ▓██▄ ▒██▀▀██░ ",
71 " ▒▓▓▄ ▄██▒ ▒██▀▀█▄ ░██▄▄▄▄██ ▒ ██▒ ░▓█ ░██ ",
72 " ▒ ▓███▀ ░ ░██▓ ▒██▒ ▓█ ▓██▒ ▒██████▒▒ ░▓█▒░██▓ ",
73 " ░ ░▒ ▒ ░ ░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒ ",
74 " ░ ▒ ░▒ ░ ▒░ ▒ ▒▒ ░ ░ ░▒ ░ ░ ▒ ░▒░ ░ ",
75 " ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ░░ ░ ",
76 " ░ ░ ░ ░ ░ ░ ░ ░ ░ ",
81 using pw::sys_io::WriteLine;
83 typedef pw::StringBuffer<150> Buffer;
85 extern "C" void pw_assert_basic_HandleFailure(const char* file_name,
87 const char* function_name,
90 // As a matter of usability, crashes should be visible; make it so.
91 #if PW_ASSERT_BASIC_SHOW_BANNER
93 for (const char* line : kCrashBanner) {
97 #endif // PW_ASSERT_BASIC_SHOW_BANNER
100 " Welp, that didn't go as planned. "
101 "It seems we crashed. Terribly sorry!");
103 WriteLine(YELLOW " CRASH MESSAGE" RESET);
109 va_start(args, format);
110 buffer.FormatVaList(format, args);
112 WriteLine(buffer.view());
115 if (file_name != nullptr && line_number != -1) {
117 WriteLine(YELLOW " CRASH FILE & LINE" RESET);
121 buffer.Format(" %s:%d", file_name, line_number);
122 WriteLine(buffer.view());
125 if (function_name != nullptr) {
127 WriteLine(YELLOW " CRASH FUNCTION" RESET);
131 buffer.Format(" %s", function_name);
132 WriteLine(buffer.view());
136 // TODO(pwbug/95): Perhaps surprisingly, this doesn't actually crash the
137 // device. At some point we'll have a reboot BSP function or similar, but for
138 // now this is acceptable since no one is using this basic backend.
139 if (!PW_ASSERT_BASIC_DISABLE_NORETURN) {
140 if (PW_ASSERT_BASIC_ABORT) {
144 WriteLine(MAGENTA " HANG TIME" RESET);
147 " ... until a debugger joins. System is waiting in a while(1)");
154 WriteLine(MAGENTA " NOTE: YOU ARE IN ASSERT BASIC TEST MODE" RESET);
156 WriteLine(" This build returns from the crash handler for testing.");
157 WriteLine(" If you see this message in production, your build is ");
158 WriteLine(" incorrectly configured. Search for");
159 WriteLine(" PW_ASSERT_BASIC_DISABLE_NORETURN to fix it.");