/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 | } |