1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <stdarg.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
23*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h> // For isatty()
24*6dbdd20aSAndroid Build Coastguard Worker #endif
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Worker #include <atomic>
27*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/crash_keys.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_view.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "src/base/log_ring_buffer.h"
35*6dbdd20aSAndroid Build Coastguard Worker
36*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER() && PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
37*6dbdd20aSAndroid Build Coastguard Worker #include <android/set_abort_message.h>
38*6dbdd20aSAndroid Build Coastguard Worker #endif
39*6dbdd20aSAndroid Build Coastguard Worker
40*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
41*6dbdd20aSAndroid Build Coastguard Worker namespace base {
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker namespace {
44*6dbdd20aSAndroid Build Coastguard Worker const char kReset[] = "\x1b[0m";
45*6dbdd20aSAndroid Build Coastguard Worker const char kDefault[] = "\x1b[39m";
46*6dbdd20aSAndroid Build Coastguard Worker const char kDim[] = "\x1b[2m";
47*6dbdd20aSAndroid Build Coastguard Worker const char kRed[] = "\x1b[31m";
48*6dbdd20aSAndroid Build Coastguard Worker const char kBoldGreen[] = "\x1b[1m\x1b[32m";
49*6dbdd20aSAndroid Build Coastguard Worker const char kLightGray[] = "\x1b[90m";
50*6dbdd20aSAndroid Build Coastguard Worker
51*6dbdd20aSAndroid Build Coastguard Worker std::atomic<LogMessageCallback> g_log_callback{};
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_STDERR_CRASH_DUMP)
54*6dbdd20aSAndroid Build Coastguard Worker // __attribute__((constructor)) causes a static initializer that automagically
55*6dbdd20aSAndroid Build Coastguard Worker // early runs this function before the main().
56*6dbdd20aSAndroid Build Coastguard Worker void PERFETTO_EXPORT_COMPONENT __attribute__((constructor))
InitDebugCrashReporter()57*6dbdd20aSAndroid Build Coastguard Worker InitDebugCrashReporter() {
58*6dbdd20aSAndroid Build Coastguard Worker // This function is defined in debug_crash_stack_trace.cc.
59*6dbdd20aSAndroid Build Coastguard Worker // The dynamic initializer is in logging.cc because logging.cc is included
60*6dbdd20aSAndroid Build Coastguard Worker // in virtually any target that depends on base. Having it in
61*6dbdd20aSAndroid Build Coastguard Worker // debug_crash_stack_trace.cc would require figuring out -Wl,whole-archive
62*6dbdd20aSAndroid Build Coastguard Worker // which is not worth it.
63*6dbdd20aSAndroid Build Coastguard Worker EnableStacktraceOnCrashForDebug();
64*6dbdd20aSAndroid Build Coastguard Worker }
65*6dbdd20aSAndroid Build Coastguard Worker #endif
66*6dbdd20aSAndroid Build Coastguard Worker
67*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
68*6dbdd20aSAndroid Build Coastguard Worker LogRingBuffer g_log_ring_buffer{};
69*6dbdd20aSAndroid Build Coastguard Worker
70*6dbdd20aSAndroid Build Coastguard Worker // This is global to avoid allocating memory or growing too much the stack
71*6dbdd20aSAndroid Build Coastguard Worker // in MaybeSerializeLastLogsForCrashReporting(), which is called from
72*6dbdd20aSAndroid Build Coastguard Worker // arbitrary code paths hitting PERFETTO_CHECK()/FATAL().
73*6dbdd20aSAndroid Build Coastguard Worker char g_crash_buf[kLogRingBufEntries * kLogRingBufMsgLen];
74*6dbdd20aSAndroid Build Coastguard Worker #endif
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker } // namespace
77*6dbdd20aSAndroid Build Coastguard Worker
SetLogMessageCallback(LogMessageCallback callback)78*6dbdd20aSAndroid Build Coastguard Worker void SetLogMessageCallback(LogMessageCallback callback) {
79*6dbdd20aSAndroid Build Coastguard Worker g_log_callback.store(callback, std::memory_order_relaxed);
80*6dbdd20aSAndroid Build Coastguard Worker }
81*6dbdd20aSAndroid Build Coastguard Worker
LogMessage(LogLev level,const char * fname,int line,const char * fmt,...)82*6dbdd20aSAndroid Build Coastguard Worker void LogMessage(LogLev level,
83*6dbdd20aSAndroid Build Coastguard Worker const char* fname,
84*6dbdd20aSAndroid Build Coastguard Worker int line,
85*6dbdd20aSAndroid Build Coastguard Worker const char* fmt,
86*6dbdd20aSAndroid Build Coastguard Worker ...) {
87*6dbdd20aSAndroid Build Coastguard Worker char stack_buf[512];
88*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<char[]> large_buf;
89*6dbdd20aSAndroid Build Coastguard Worker char* log_msg = &stack_buf[0];
90*6dbdd20aSAndroid Build Coastguard Worker size_t log_msg_len = 0;
91*6dbdd20aSAndroid Build Coastguard Worker
92*6dbdd20aSAndroid Build Coastguard Worker // By default use a stack allocated buffer because most log messages are quite
93*6dbdd20aSAndroid Build Coastguard Worker // short. In rare cases they can be larger (e.g. --help). In those cases we
94*6dbdd20aSAndroid Build Coastguard Worker // pay the cost of allocating the buffer on the heap.
95*6dbdd20aSAndroid Build Coastguard Worker for (size_t max_len = sizeof(stack_buf);;) {
96*6dbdd20aSAndroid Build Coastguard Worker va_list args;
97*6dbdd20aSAndroid Build Coastguard Worker va_start(args, fmt);
98*6dbdd20aSAndroid Build Coastguard Worker int res = vsnprintf(log_msg, max_len, fmt, args);
99*6dbdd20aSAndroid Build Coastguard Worker va_end(args);
100*6dbdd20aSAndroid Build Coastguard Worker
101*6dbdd20aSAndroid Build Coastguard Worker // If for any reason the print fails, overwrite the message but still print
102*6dbdd20aSAndroid Build Coastguard Worker // it. The code below will attach the filename and line, which is still
103*6dbdd20aSAndroid Build Coastguard Worker // useful.
104*6dbdd20aSAndroid Build Coastguard Worker if (res < 0) {
105*6dbdd20aSAndroid Build Coastguard Worker snprintf(log_msg, max_len, "%s", "[printf format error]");
106*6dbdd20aSAndroid Build Coastguard Worker break;
107*6dbdd20aSAndroid Build Coastguard Worker }
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard Worker // if res == max_len, vsnprintf saturated the input buffer. Retry with a
110*6dbdd20aSAndroid Build Coastguard Worker // larger buffer in that case (within reasonable limits).
111*6dbdd20aSAndroid Build Coastguard Worker if (res < static_cast<int>(max_len) || max_len >= 128 * 1024) {
112*6dbdd20aSAndroid Build Coastguard Worker // In case of truncation vsnprintf returns the len that "would have been
113*6dbdd20aSAndroid Build Coastguard Worker // written if the string was longer", not the actual chars written.
114*6dbdd20aSAndroid Build Coastguard Worker log_msg_len = std::min(static_cast<size_t>(res), max_len - 1);
115*6dbdd20aSAndroid Build Coastguard Worker break;
116*6dbdd20aSAndroid Build Coastguard Worker }
117*6dbdd20aSAndroid Build Coastguard Worker max_len *= 4;
118*6dbdd20aSAndroid Build Coastguard Worker large_buf.reset(new char[max_len]);
119*6dbdd20aSAndroid Build Coastguard Worker log_msg = &large_buf[0];
120*6dbdd20aSAndroid Build Coastguard Worker }
121*6dbdd20aSAndroid Build Coastguard Worker
122*6dbdd20aSAndroid Build Coastguard Worker LogMessageCallback cb = g_log_callback.load(std::memory_order_relaxed);
123*6dbdd20aSAndroid Build Coastguard Worker if (cb) {
124*6dbdd20aSAndroid Build Coastguard Worker cb({level, line, fname, log_msg});
125*6dbdd20aSAndroid Build Coastguard Worker return;
126*6dbdd20aSAndroid Build Coastguard Worker }
127*6dbdd20aSAndroid Build Coastguard Worker
128*6dbdd20aSAndroid Build Coastguard Worker const char* color = kDefault;
129*6dbdd20aSAndroid Build Coastguard Worker switch (level) {
130*6dbdd20aSAndroid Build Coastguard Worker case kLogDebug:
131*6dbdd20aSAndroid Build Coastguard Worker color = kDim;
132*6dbdd20aSAndroid Build Coastguard Worker break;
133*6dbdd20aSAndroid Build Coastguard Worker case kLogInfo:
134*6dbdd20aSAndroid Build Coastguard Worker color = kDefault;
135*6dbdd20aSAndroid Build Coastguard Worker break;
136*6dbdd20aSAndroid Build Coastguard Worker case kLogImportant:
137*6dbdd20aSAndroid Build Coastguard Worker color = kBoldGreen;
138*6dbdd20aSAndroid Build Coastguard Worker break;
139*6dbdd20aSAndroid Build Coastguard Worker case kLogError:
140*6dbdd20aSAndroid Build Coastguard Worker color = kRed;
141*6dbdd20aSAndroid Build Coastguard Worker break;
142*6dbdd20aSAndroid Build Coastguard Worker }
143*6dbdd20aSAndroid Build Coastguard Worker
144*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
145*6dbdd20aSAndroid Build Coastguard Worker !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) && \
146*6dbdd20aSAndroid Build Coastguard Worker !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
147*6dbdd20aSAndroid Build Coastguard Worker static const bool use_colors = isatty(STDERR_FILENO);
148*6dbdd20aSAndroid Build Coastguard Worker #else
149*6dbdd20aSAndroid Build Coastguard Worker static const bool use_colors = false;
150*6dbdd20aSAndroid Build Coastguard Worker #endif
151*6dbdd20aSAndroid Build Coastguard Worker
152*6dbdd20aSAndroid Build Coastguard Worker // Formats file.cc:line as a space-padded fixed width string. If the file name
153*6dbdd20aSAndroid Build Coastguard Worker // |fname| is too long, truncate it on the left-hand side.
154*6dbdd20aSAndroid Build Coastguard Worker StackString<10> line_str("%d", line);
155*6dbdd20aSAndroid Build Coastguard Worker
156*6dbdd20aSAndroid Build Coastguard Worker // 24 will be the width of the file.cc:line column in the log event.
157*6dbdd20aSAndroid Build Coastguard Worker static constexpr size_t kMaxNameAndLine = 24;
158*6dbdd20aSAndroid Build Coastguard Worker size_t fname_len = strlen(fname);
159*6dbdd20aSAndroid Build Coastguard Worker size_t fname_max = kMaxNameAndLine - line_str.len() - 2; // 2 = ':' + '\0'.
160*6dbdd20aSAndroid Build Coastguard Worker size_t fname_offset = fname_len <= fname_max ? 0 : fname_len - fname_max;
161*6dbdd20aSAndroid Build Coastguard Worker StackString<kMaxNameAndLine> file_and_line(
162*6dbdd20aSAndroid Build Coastguard Worker "%*s:%s", static_cast<int>(fname_max), &fname[fname_offset],
163*6dbdd20aSAndroid Build Coastguard Worker line_str.c_str());
164*6dbdd20aSAndroid Build Coastguard Worker
165*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
166*6dbdd20aSAndroid Build Coastguard Worker // Logcat has already timestamping, don't re-emit it.
167*6dbdd20aSAndroid Build Coastguard Worker __android_log_print(int{ANDROID_LOG_DEBUG} + level, "perfetto", "%s %s",
168*6dbdd20aSAndroid Build Coastguard Worker file_and_line.c_str(), log_msg);
169*6dbdd20aSAndroid Build Coastguard Worker #endif
170*6dbdd20aSAndroid Build Coastguard Worker
171*6dbdd20aSAndroid Build Coastguard Worker // When printing on stderr, print also the timestamp. We don't really care
172*6dbdd20aSAndroid Build Coastguard Worker // about the actual time. We just need some reference clock that can be used
173*6dbdd20aSAndroid Build Coastguard Worker // to correlated events across differrent processses (e.g. traced and
174*6dbdd20aSAndroid Build Coastguard Worker // traced_probes). The wall time % 1000 is good enough.
175*6dbdd20aSAndroid Build Coastguard Worker uint32_t t_ms = static_cast<uint32_t>(GetWallTimeMs().count());
176*6dbdd20aSAndroid Build Coastguard Worker uint32_t t_sec = t_ms / 1000;
177*6dbdd20aSAndroid Build Coastguard Worker t_ms -= t_sec * 1000;
178*6dbdd20aSAndroid Build Coastguard Worker t_sec = t_sec % 1000;
179*6dbdd20aSAndroid Build Coastguard Worker StackString<32> timestamp("[%03u.%03u] ", t_sec, t_ms);
180*6dbdd20aSAndroid Build Coastguard Worker
181*6dbdd20aSAndroid Build Coastguard Worker if (use_colors) {
182*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "%s%s%s%s %s%s%s\n", kLightGray, timestamp.c_str(),
183*6dbdd20aSAndroid Build Coastguard Worker file_and_line.c_str(), kReset, color, log_msg, kReset);
184*6dbdd20aSAndroid Build Coastguard Worker } else {
185*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "%s%s %s\n", timestamp.c_str(), file_and_line.c_str(),
186*6dbdd20aSAndroid Build Coastguard Worker log_msg);
187*6dbdd20aSAndroid Build Coastguard Worker }
188*6dbdd20aSAndroid Build Coastguard Worker
189*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
190*6dbdd20aSAndroid Build Coastguard Worker // Append the message to the ring buffer for crash reporting postmortems.
191*6dbdd20aSAndroid Build Coastguard Worker StringView timestamp_sv = timestamp.string_view();
192*6dbdd20aSAndroid Build Coastguard Worker StringView file_and_line_sv = file_and_line.string_view();
193*6dbdd20aSAndroid Build Coastguard Worker StringView log_msg_sv(log_msg, static_cast<size_t>(log_msg_len));
194*6dbdd20aSAndroid Build Coastguard Worker g_log_ring_buffer.Append(timestamp_sv, file_and_line_sv, log_msg_sv);
195*6dbdd20aSAndroid Build Coastguard Worker #else
196*6dbdd20aSAndroid Build Coastguard Worker ignore_result(log_msg_len);
197*6dbdd20aSAndroid Build Coastguard Worker #endif
198*6dbdd20aSAndroid Build Coastguard Worker }
199*6dbdd20aSAndroid Build Coastguard Worker
200*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_ENABLE_LOG_RING_BUFFER()
MaybeSerializeLastLogsForCrashReporting()201*6dbdd20aSAndroid Build Coastguard Worker void MaybeSerializeLastLogsForCrashReporting() {
202*6dbdd20aSAndroid Build Coastguard Worker // Keep this function minimal. This is called from the watchdog thread, often
203*6dbdd20aSAndroid Build Coastguard Worker // when the system is thrashing.
204*6dbdd20aSAndroid Build Coastguard Worker
205*6dbdd20aSAndroid Build Coastguard Worker // This is racy because two threads could hit a CHECK/FATAL at the same time.
206*6dbdd20aSAndroid Build Coastguard Worker // But if that happens we have bigger problems, not worth designing around it.
207*6dbdd20aSAndroid Build Coastguard Worker // The behaviour is still defined in the race case (the string attached to
208*6dbdd20aSAndroid Build Coastguard Worker // the crash report will contain a mixture of log strings).
209*6dbdd20aSAndroid Build Coastguard Worker size_t wr = 0;
210*6dbdd20aSAndroid Build Coastguard Worker wr += SerializeCrashKeys(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
211*6dbdd20aSAndroid Build Coastguard Worker wr += g_log_ring_buffer.Read(&g_crash_buf[wr], sizeof(g_crash_buf) - wr);
212*6dbdd20aSAndroid Build Coastguard Worker
213*6dbdd20aSAndroid Build Coastguard Worker // Read() null-terminates the string properly. This is just to avoid UB when
214*6dbdd20aSAndroid Build Coastguard Worker // two threads race on each other (T1 writes a shorter string, T2
215*6dbdd20aSAndroid Build Coastguard Worker // overwrites the \0 writing a longer string. T1 continues here before T2
216*6dbdd20aSAndroid Build Coastguard Worker // finishes writing the longer string with the \0 -> boom.
217*6dbdd20aSAndroid Build Coastguard Worker g_crash_buf[sizeof(g_crash_buf) - 1] = '\0';
218*6dbdd20aSAndroid Build Coastguard Worker
219*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
220*6dbdd20aSAndroid Build Coastguard Worker // android_set_abort_message() will cause debuggerd to report the message
221*6dbdd20aSAndroid Build Coastguard Worker // in the tombstone and in the crash log in logcat.
222*6dbdd20aSAndroid Build Coastguard Worker // NOTE: android_set_abort_message() can be called only once. This should
223*6dbdd20aSAndroid Build Coastguard Worker // be called only when we are sure we are about to crash.
224*6dbdd20aSAndroid Build Coastguard Worker android_set_abort_message(g_crash_buf);
225*6dbdd20aSAndroid Build Coastguard Worker #else
226*6dbdd20aSAndroid Build Coastguard Worker // Print out the message on stderr on Linux/Mac/Win.
227*6dbdd20aSAndroid Build Coastguard Worker fputs("\n-----BEGIN PERFETTO PRE-CRASH LOG-----\n", stderr);
228*6dbdd20aSAndroid Build Coastguard Worker fputs(g_crash_buf, stderr);
229*6dbdd20aSAndroid Build Coastguard Worker fputs("\n-----END PERFETTO PRE-CRASH LOG-----\n", stderr);
230*6dbdd20aSAndroid Build Coastguard Worker #endif
231*6dbdd20aSAndroid Build Coastguard Worker }
232*6dbdd20aSAndroid Build Coastguard Worker #endif // PERFETTO_ENABLE_LOG_RING_BUFFER
233*6dbdd20aSAndroid Build Coastguard Worker
234*6dbdd20aSAndroid Build Coastguard Worker } // namespace base
235*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
236