blob: e6a64f59862ef93b75d0e6f0e0600cc6144b7338 [file] [log] [blame]
Keir Mierle3cee8792020-01-22 17:08:13 -08001// Copyright 2020 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 "pw_assert_basic/assert_basic.h"
21
22#include <cstring>
23
Ewout van Bekkume4d7b692020-10-15 13:12:30 -070024#include "pw_assert/options.h"
Keir Mierle3cee8792020-01-22 17:08:13 -080025#include "pw_preprocessor/util.h"
26#include "pw_string/string_builder.h"
Armando Montanezf7a5a742020-03-02 14:58:59 -080027#include "pw_sys_io/sys_io.h"
Keir Mierle3cee8792020-01-22 17:08:13 -080028
Keir Mierle52e4acc2020-04-15 21:20:21 -070029// If 1, call C's standard abort() function on assert failure.
30#ifndef PW_ASSERT_BASIC_ABORT
31#define PW_ASSERT_BASIC_ABORT 1
32#endif // PW_ASSERT_BASIC_ABORT
33
Keir Mierle3cee8792020-01-22 17:08:13 -080034// TODO(pwbug/17): Expose these through the config system.
35#define PW_ASSERT_BASIC_SHOW_BANNER 1
36#define PW_ASSERT_BASIC_USE_COLORS 1
37
38// ANSI color constants to control the terminal. Not Windows compatible.
39// clang-format off
40#if PW_ASSERT_BASIC_USE_COLORS
41#define MAGENTA "\033[35m"
42#define YELLOW "\033[33m"
43#define RED "\033[31m"
44#define GREEN "\033[32m"
45#define BLUE "\033[96m"
46#define BLACK "\033[30m"
47#define YELLOW_BG "\033[43m"
48#define WHITE_BG "\033[47m"
49#define RED_BG "\033[41m"
50#define BOLD "\033[1m"
51#define RESET "\033[0m"
52#else
53#define MAGENTA ""
54#define YELLOW ""
55#define RED ""
56#define GREEN ""
57#define BLUE ""
58#define BLACK ""
59#define YELLOW_BG ""
60#define WHITE_BG ""
61#define RED_BG ""
62#define BOLD ""
63#define RESET ""
64#endif // PW_ASSERT_BASIC_USE_COLORS
65// clang-format on
66
67static const char* kCrashBanner[] = {
68 " ",
69 " ▄████▄ ██▀███ ▄▄▄ ██████ ██░ ██ ",
70 " ▒██▀ ▀█ ▓██ ▒ ██▒ ▒████▄ ▒██ ▒ ▓██░ ██▒ ",
71 " ▒▓█ 💥 ▄ ▓██ ░▄█ ▒ ▒██ ▀█▄ ░ ▓██▄ ▒██▀▀██░ ",
72 " ▒▓▓▄ ▄██▒ ▒██▀▀█▄ ░██▄▄▄▄██ ▒ ██▒ ░▓█ ░██ ",
73 " ▒ ▓███▀ ░ ░██▓ ▒██▒ ▓█ ▓██▒ ▒██████▒▒ ░▓█▒░██▓ ",
74 " ░ ░▒ ▒ ░ ░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒ ",
75 " ░ ▒ ░▒ ░ ▒░ ▒ ▒▒ ░ ░ ░▒ ░ ░ ▒ ░▒░ ░ ",
76 " ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ░░ ░ ",
77 " ░ ░ ░ ░ ░ ░ ░ ░ ░ ",
78 " ░",
79 " ",
80};
81
Armando Montanezf7a5a742020-03-02 14:58:59 -080082using pw::sys_io::WriteLine;
Keir Mierle3cee8792020-01-22 17:08:13 -080083
84typedef pw::StringBuffer<150> Buffer;
85
86extern "C" void pw_Crash(const char* file_name,
87 int line_number,
88 const char* function_name,
89 const char* message,
90 ...) {
91 // As a matter of usability, crashes should be visible; make it so.
92#if PW_ASSERT_BASIC_SHOW_BANNER
93 WriteLine(RED);
94 for (const char* line : kCrashBanner) {
95 WriteLine(line);
96 }
97 WriteLine(RESET);
98#endif // PW_ASSERT_BASIC_SHOW_BANNER
99
100 WriteLine(
101 " Welp, that didn't go as planned. "
102 "It seems we crashed. Terribly sorry!");
103 WriteLine("");
104 WriteLine(YELLOW " CRASH MESSAGE" RESET);
105 WriteLine("");
106 {
107 Buffer buffer;
108 buffer << " ";
109 va_list args;
110 va_start(args, message);
111 buffer.FormatVaList(message, args);
112 va_end(args);
Armando Montanezf7a5a742020-03-02 14:58:59 -0800113 WriteLine(buffer.view());
Keir Mierle3cee8792020-01-22 17:08:13 -0800114 }
115
116 WriteLine("");
117 WriteLine(YELLOW " CRASH FILE & LINE" RESET);
118 WriteLine("");
119 {
120 Buffer buffer;
121 buffer.Format(" %s:%d", file_name, line_number);
122 WriteLine(buffer.view());
123 }
124 WriteLine("");
125 WriteLine(YELLOW " CRASH FUNCTION" RESET);
126 WriteLine("");
127 {
128 Buffer buffer;
129 buffer.Format(" %s", function_name);
130 WriteLine(buffer.view());
131 }
132 WriteLine("");
133
134 // TODO(pwbug/95): Perhaps surprisingly, this doesn't actually crash the
135 // device. At some point we'll have a reboot BSP function or similar, but for
136 // now this is acceptable since no one is using this basic backend.
137 if (!PW_ASSERT_BASIC_DISABLE_NORETURN) {
Keir Mierle52e4acc2020-04-15 21:20:21 -0700138 if (PW_ASSERT_BASIC_ABORT) {
139 abort();
140 } else {
141 WriteLine(MAGENTA " HANG TIME" RESET);
142 WriteLine("");
143 WriteLine(
144 " ... until a debugger joins. System is waiting in a while(1)");
145 while (1) {
146 }
Keir Mierle3cee8792020-01-22 17:08:13 -0800147 }
148 PW_UNREACHABLE;
149 } else {
150 WriteLine(MAGENTA " NOTE: YOU ARE IN ASSERT BASIC TEST MODE" RESET);
151 WriteLine("");
152 WriteLine(" This build returns from the crash handler for testing.");
153 WriteLine(" If you see this message in production, your build is ");
154 WriteLine(" incorrectly configured. Search for");
155 WriteLine(" PW_ASSERT_BASIC_DISABLE_NORETURN to fix it.");
156 WriteLine("");
157 }
158}
Keir Mierle854adec2020-09-03 14:07:19 -0700159
Wyatt Heplerdd3e8812020-09-29 11:14:28 -0700160extern "C" void pw_assert_HandleFailure(void) {
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700161#if PW_ASSERT_ENABLE_DEBUG
Keir Mierle854adec2020-09-03 14:07:19 -0700162 pw_Crash("", 0, "", "Crash: PW_ASSERT() or PW_DASSERT() failure");
163#else
164 pw_Crash("", 0, "", "Crash: PW_ASSERT() failure. Note: PW_DASSERT disabled");
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700165#endif // PW_ASSERT_ENABLE_DEBUG
Keir Mierle854adec2020-09-03 14:07:19 -0700166}