1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <errno.h>
8*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
9*6777b538SAndroid Build Coastguard Worker #include <signal.h>
10*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
11*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
12*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
13*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
14*6777b538SAndroid Build Coastguard Worker #include <string.h>
15*6777b538SAndroid Build Coastguard Worker #include <sys/param.h>
16*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
17*6777b538SAndroid Build Coastguard Worker #include <sys/syscall.h>
18*6777b538SAndroid Build Coastguard Worker #include <sys/types.h>
19*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker #include <algorithm>
22*6777b538SAndroid Build Coastguard Worker #include <map>
23*6777b538SAndroid Build Coastguard Worker #include <memory>
24*6777b538SAndroid Build Coastguard Worker #include <ostream>
25*6777b538SAndroid Build Coastguard Worker #include <string>
26*6777b538SAndroid Build Coastguard Worker #include <tuple>
27*6777b538SAndroid Build Coastguard Worker #include <vector>
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
30*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker // Controls whether `dladdr(...)` is used to print the callstack. This is
33*6777b538SAndroid Build Coastguard Worker // only used on iOS Official build where `backtrace_symbols(...)` prints
34*6777b538SAndroid Build Coastguard Worker // misleading symbols (as the binary is stripped).
35*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS) && defined(OFFICIAL_BUILD)
36*6777b538SAndroid Build Coastguard Worker #define HAVE_DLADDR
37*6777b538SAndroid Build Coastguard Worker #include <dlfcn.h>
38*6777b538SAndroid Build Coastguard Worker #endif
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker // Surprisingly, uClibc defines __GLIBC__ in some build configs, but
41*6777b538SAndroid Build Coastguard Worker // execinfo.h and backtrace(3) are really only present in glibc and in macOS
42*6777b538SAndroid Build Coastguard Worker // libc.
43*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE) || \
44*6777b538SAndroid Build Coastguard Worker (defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__AIX))
45*6777b538SAndroid Build Coastguard Worker #define HAVE_BACKTRACE
46*6777b538SAndroid Build Coastguard Worker #include <execinfo.h>
47*6777b538SAndroid Build Coastguard Worker #endif
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker // Controls whether to include code to demangle C++ symbols.
50*6777b538SAndroid Build Coastguard Worker #if !defined(USE_SYMBOLIZE) && defined(HAVE_BACKTRACE) && !defined(HAVE_DLADDR)
51*6777b538SAndroid Build Coastguard Worker #define DEMANGLE_SYMBOLS
52*6777b538SAndroid Build Coastguard Worker #endif
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker #if defined(DEMANGLE_SYMBOLS)
55*6777b538SAndroid Build Coastguard Worker #include <cxxabi.h>
56*6777b538SAndroid Build Coastguard Worker #endif
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
59*6777b538SAndroid Build Coastguard Worker #include <AvailabilityMacros.h>
60*6777b538SAndroid Build Coastguard Worker #endif
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
63*6777b538SAndroid Build Coastguard Worker #include <sys/prctl.h>
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker #include "base/debug/proc_maps_linux.h"
66*6777b538SAndroid Build Coastguard Worker #endif
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker #include "base/cfi_buildflags.h"
69*6777b538SAndroid Build Coastguard Worker #include "base/debug/debugger.h"
70*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
71*6777b538SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
72*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
73*6777b538SAndroid Build Coastguard Worker #include "base/memory/free_deleter.h"
74*6777b538SAndroid Build Coastguard Worker #include "base/memory/singleton.h"
75*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
76*6777b538SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
77*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
78*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
79*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker #if defined(USE_SYMBOLIZE)
82*6777b538SAndroid Build Coastguard Worker #include "base/third_party/symbolize/symbolize.h" // nogncheck
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_STACK_TRACE_LINE_NUMBERS)
85*6777b538SAndroid Build Coastguard Worker #include "base/debug/dwarf_line_no.h" // nogncheck
86*6777b538SAndroid Build Coastguard Worker #endif
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker #endif
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker namespace base {
91*6777b538SAndroid Build Coastguard Worker namespace debug {
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker namespace {
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker volatile sig_atomic_t in_signal_handler = 0;
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
98*6777b538SAndroid Build Coastguard Worker bool (*try_handle_signal)(int, siginfo_t*, void*) = nullptr;
99*6777b538SAndroid Build Coastguard Worker #endif
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker #if defined(DEMANGLE_SYMBOLS)
102*6777b538SAndroid Build Coastguard Worker // The prefix used for mangled symbols, per the Itanium C++ ABI:
103*6777b538SAndroid Build Coastguard Worker // http://www.codesourcery.com/cxx-abi/abi.html#mangling
104*6777b538SAndroid Build Coastguard Worker const char kMangledSymbolPrefix[] = "_Z";
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker // Characters that can be used for symbols, generated by Ruby:
107*6777b538SAndroid Build Coastguard Worker // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
108*6777b538SAndroid Build Coastguard Worker const char kSymbolCharacters[] =
109*6777b538SAndroid Build Coastguard Worker "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker // Demangles C++ symbols in the given text. Example:
112*6777b538SAndroid Build Coastguard Worker //
113*6777b538SAndroid Build Coastguard Worker // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
114*6777b538SAndroid Build Coastguard Worker // =>
115*6777b538SAndroid Build Coastguard Worker // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
DemangleSymbols(std::string * text)116*6777b538SAndroid Build Coastguard Worker void DemangleSymbols(std::string* text) {
117*6777b538SAndroid Build Coastguard Worker // Note: code in this function is NOT async-signal safe (std::string uses
118*6777b538SAndroid Build Coastguard Worker // malloc internally).
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker std::string::size_type search_from = 0;
121*6777b538SAndroid Build Coastguard Worker while (search_from < text->size()) {
122*6777b538SAndroid Build Coastguard Worker // Look for the start of a mangled symbol, from search_from.
123*6777b538SAndroid Build Coastguard Worker std::string::size_type mangled_start =
124*6777b538SAndroid Build Coastguard Worker text->find(kMangledSymbolPrefix, search_from);
125*6777b538SAndroid Build Coastguard Worker if (mangled_start == std::string::npos) {
126*6777b538SAndroid Build Coastguard Worker break; // Mangled symbol not found.
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker // Look for the end of the mangled symbol.
130*6777b538SAndroid Build Coastguard Worker std::string::size_type mangled_end =
131*6777b538SAndroid Build Coastguard Worker text->find_first_not_of(kSymbolCharacters, mangled_start);
132*6777b538SAndroid Build Coastguard Worker if (mangled_end == std::string::npos) {
133*6777b538SAndroid Build Coastguard Worker mangled_end = text->size();
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker std::string mangled_symbol =
136*6777b538SAndroid Build Coastguard Worker text->substr(mangled_start, mangled_end - mangled_start);
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker // Try to demangle the mangled symbol candidate.
139*6777b538SAndroid Build Coastguard Worker int status = 0;
140*6777b538SAndroid Build Coastguard Worker std::unique_ptr<char, base::FreeDeleter> demangled_symbol(
141*6777b538SAndroid Build Coastguard Worker abi::__cxa_demangle(mangled_symbol.c_str(), nullptr, 0, &status));
142*6777b538SAndroid Build Coastguard Worker if (status == 0) { // Demangling is successful.
143*6777b538SAndroid Build Coastguard Worker // Remove the mangled symbol.
144*6777b538SAndroid Build Coastguard Worker text->erase(mangled_start, mangled_end - mangled_start);
145*6777b538SAndroid Build Coastguard Worker // Insert the demangled symbol.
146*6777b538SAndroid Build Coastguard Worker text->insert(mangled_start, demangled_symbol.get());
147*6777b538SAndroid Build Coastguard Worker // Next time, we'll start right after the demangled symbol we inserted.
148*6777b538SAndroid Build Coastguard Worker search_from = mangled_start + strlen(demangled_symbol.get());
149*6777b538SAndroid Build Coastguard Worker } else {
150*6777b538SAndroid Build Coastguard Worker // Failed to demangle. Retry after the "_Z" we just found.
151*6777b538SAndroid Build Coastguard Worker search_from = mangled_start + 2;
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker #endif // defined(DEMANGLE_SYMBOLS)
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker class BacktraceOutputHandler {
158*6777b538SAndroid Build Coastguard Worker public:
159*6777b538SAndroid Build Coastguard Worker virtual void HandleOutput(const char* output) = 0;
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker protected:
162*6777b538SAndroid Build Coastguard Worker virtual ~BacktraceOutputHandler() = default;
163*6777b538SAndroid Build Coastguard Worker };
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_BACKTRACE)
OutputPointer(const void * pointer,BacktraceOutputHandler * handler)166*6777b538SAndroid Build Coastguard Worker void OutputPointer(const void* pointer, BacktraceOutputHandler* handler) {
167*6777b538SAndroid Build Coastguard Worker // This should be more than enough to store a 64-bit number in hex:
168*6777b538SAndroid Build Coastguard Worker // 16 hex digits + 1 for null-terminator.
169*6777b538SAndroid Build Coastguard Worker char buf[17] = { '\0' };
170*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("0x");
171*6777b538SAndroid Build Coastguard Worker internal::itoa_r(reinterpret_cast<intptr_t>(pointer),
172*6777b538SAndroid Build Coastguard Worker buf, sizeof(buf), 16, 12);
173*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(buf);
174*6777b538SAndroid Build Coastguard Worker }
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_DLADDR) || defined(USE_SYMBOLIZE)
OutputValue(size_t value,BacktraceOutputHandler * handler)177*6777b538SAndroid Build Coastguard Worker void OutputValue(size_t value, BacktraceOutputHandler* handler) {
178*6777b538SAndroid Build Coastguard Worker // Max unsigned 64-bit number in decimal has 20 digits (18446744073709551615).
179*6777b538SAndroid Build Coastguard Worker // Hence, 30 digits should be more than enough to represent it in decimal
180*6777b538SAndroid Build Coastguard Worker // (including the null-terminator).
181*6777b538SAndroid Build Coastguard Worker char buf[30] = { '\0' };
182*6777b538SAndroid Build Coastguard Worker internal::itoa_r(static_cast<intptr_t>(value), buf, sizeof(buf), 10, 1);
183*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(buf);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker #endif // defined(HAVE_DLADDR) || defined(USE_SYMBOLIZE)
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker #if defined(USE_SYMBOLIZE)
OutputFrameId(size_t frame_id,BacktraceOutputHandler * handler)188*6777b538SAndroid Build Coastguard Worker void OutputFrameId(size_t frame_id, BacktraceOutputHandler* handler) {
189*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("#");
190*6777b538SAndroid Build Coastguard Worker OutputValue(frame_id, handler);
191*6777b538SAndroid Build Coastguard Worker }
192*6777b538SAndroid Build Coastguard Worker #endif // defined(USE_SYMBOLIZE)
193*6777b538SAndroid Build Coastguard Worker
ProcessBacktrace(const void * const * trace,size_t size,cstring_view prefix_string,BacktraceOutputHandler * handler)194*6777b538SAndroid Build Coastguard Worker void ProcessBacktrace(const void* const* trace,
195*6777b538SAndroid Build Coastguard Worker size_t size,
196*6777b538SAndroid Build Coastguard Worker cstring_view prefix_string,
197*6777b538SAndroid Build Coastguard Worker BacktraceOutputHandler* handler) {
198*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
199*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
200*6777b538SAndroid Build Coastguard Worker
201*6777b538SAndroid Build Coastguard Worker #if defined(USE_SYMBOLIZE)
202*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_STACK_TRACE_LINE_NUMBERS)
203*6777b538SAndroid Build Coastguard Worker uint64_t cu_offsets[StackTrace::kMaxTraces] = {};
204*6777b538SAndroid Build Coastguard Worker GetDwarfCompileUnitOffsets(trace, cu_offsets, size);
205*6777b538SAndroid Build Coastguard Worker #endif
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
208*6777b538SAndroid Build Coastguard Worker if (!prefix_string.empty())
209*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(prefix_string.c_str());
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker OutputFrameId(i, handler);
212*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" ");
213*6777b538SAndroid Build Coastguard Worker OutputPointer(trace[i], handler);
214*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" ");
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker char buf[1024] = {'\0'};
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker // Subtract by one as return address of function may be in the next
219*6777b538SAndroid Build Coastguard Worker // function when a function is annotated as noreturn.
220*6777b538SAndroid Build Coastguard Worker const void* address = static_cast<const char*>(trace[i]) - 1;
221*6777b538SAndroid Build Coastguard Worker if (google::Symbolize(const_cast<void*>(address), buf, sizeof(buf))) {
222*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(buf);
223*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_STACK_TRACE_LINE_NUMBERS)
224*6777b538SAndroid Build Coastguard Worker // Only output the source line number if the offset was found. Otherwise,
225*6777b538SAndroid Build Coastguard Worker // it takes far too long in debug mode when there are lots of symbols.
226*6777b538SAndroid Build Coastguard Worker if (GetDwarfSourceLineNumber(address, cu_offsets[i], &buf[0],
227*6777b538SAndroid Build Coastguard Worker sizeof(buf))) {
228*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" [");
229*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(buf);
230*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("]");
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker #endif
233*6777b538SAndroid Build Coastguard Worker } else {
234*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("<unknown>");
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("\n");
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker #else
240*6777b538SAndroid Build Coastguard Worker bool printed = false;
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker // Below part is async-signal unsafe (uses malloc), so execute it only
243*6777b538SAndroid Build Coastguard Worker // when we are not executing the signal handler.
244*6777b538SAndroid Build Coastguard Worker if (in_signal_handler == 0 && IsValueInRangeForNumericType<int>(size)) {
245*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_DLADDR)
246*6777b538SAndroid Build Coastguard Worker Dl_info dl_info;
247*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
248*6777b538SAndroid Build Coastguard Worker if (!prefix_string.empty()) {
249*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(prefix_string.c_str());
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker
252*6777b538SAndroid Build Coastguard Worker OutputValue(i, handler);
253*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" ");
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker const bool dl_info_found = dladdr(trace[i], &dl_info) != 0;
256*6777b538SAndroid Build Coastguard Worker if (dl_info_found) {
257*6777b538SAndroid Build Coastguard Worker const char* last_sep = strrchr(dl_info.dli_fname, '/');
258*6777b538SAndroid Build Coastguard Worker const char* basename = last_sep ? last_sep + 1 : dl_info.dli_fname;
259*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(basename);
260*6777b538SAndroid Build Coastguard Worker } else {
261*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("???");
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" ");
264*6777b538SAndroid Build Coastguard Worker OutputPointer(trace[i], handler);
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("\n");
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker printed = true;
269*6777b538SAndroid Build Coastguard Worker #else // defined(HAVE_DLADDR)
270*6777b538SAndroid Build Coastguard Worker std::unique_ptr<char*, FreeDeleter> trace_symbols(backtrace_symbols(
271*6777b538SAndroid Build Coastguard Worker const_cast<void* const*>(trace), static_cast<int>(size)));
272*6777b538SAndroid Build Coastguard Worker if (trace_symbols.get()) {
273*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
274*6777b538SAndroid Build Coastguard Worker std::string trace_symbol = trace_symbols.get()[i];
275*6777b538SAndroid Build Coastguard Worker DemangleSymbols(&trace_symbol);
276*6777b538SAndroid Build Coastguard Worker if (!prefix_string.empty())
277*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(prefix_string.c_str());
278*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(trace_symbol.c_str());
279*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("\n");
280*6777b538SAndroid Build Coastguard Worker }
281*6777b538SAndroid Build Coastguard Worker
282*6777b538SAndroid Build Coastguard Worker printed = true;
283*6777b538SAndroid Build Coastguard Worker }
284*6777b538SAndroid Build Coastguard Worker #endif // defined(HAVE_DLADDR)
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker if (!printed) {
288*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
289*6777b538SAndroid Build Coastguard Worker handler->HandleOutput(" [");
290*6777b538SAndroid Build Coastguard Worker OutputPointer(trace[i], handler);
291*6777b538SAndroid Build Coastguard Worker handler->HandleOutput("]\n");
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker }
294*6777b538SAndroid Build Coastguard Worker #endif // defined(USE_SYMBOLIZE)
295*6777b538SAndroid Build Coastguard Worker }
296*6777b538SAndroid Build Coastguard Worker #endif // defined(HAVE_BACKTRACE)
297*6777b538SAndroid Build Coastguard Worker
PrintToStderr(const char * output)298*6777b538SAndroid Build Coastguard Worker void PrintToStderr(const char* output) {
299*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
300*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
301*6777b538SAndroid Build Coastguard Worker std::ignore = HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)));
302*6777b538SAndroid Build Coastguard Worker }
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
AlarmSignalHandler(int signal,siginfo_t * info,void * void_context)305*6777b538SAndroid Build Coastguard Worker void AlarmSignalHandler(int signal, siginfo_t* info, void* void_context) {
306*6777b538SAndroid Build Coastguard Worker // We have seen rare cases on AMD linux where the default signal handler
307*6777b538SAndroid Build Coastguard Worker // either does not run or a thread (Probably an AMD driver thread) prevents
308*6777b538SAndroid Build Coastguard Worker // the termination of the gpu process. We catch this case when the alarm fires
309*6777b538SAndroid Build Coastguard Worker // and then call exit_group() to kill all threads of the process. This has
310*6777b538SAndroid Build Coastguard Worker // resolved the zombie gpu process issues we have seen on our context lost
311*6777b538SAndroid Build Coastguard Worker // test.
312*6777b538SAndroid Build Coastguard Worker // Note that many different calls were tried to kill the process when it is in
313*6777b538SAndroid Build Coastguard Worker // this state. Only 'exit_group' was found to cause termination and it is
314*6777b538SAndroid Build Coastguard Worker // speculated that only this works because only this exit kills all threads in
315*6777b538SAndroid Build Coastguard Worker // the process (not simply the current thread).
316*6777b538SAndroid Build Coastguard Worker // See: http://crbug.com/1396451.
317*6777b538SAndroid Build Coastguard Worker PrintToStderr(
318*6777b538SAndroid Build Coastguard Worker "Warning: Default signal handler failed to terminate process.\n");
319*6777b538SAndroid Build Coastguard Worker PrintToStderr("Calling exit_group() directly to prevent timeout.\n");
320*6777b538SAndroid Build Coastguard Worker // See: https://man7.org/linux/man-pages/man2/exit_group.2.html
321*6777b538SAndroid Build Coastguard Worker syscall(SYS_exit_group, EXIT_FAILURE);
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) ||
324*6777b538SAndroid Build Coastguard Worker // BUILDFLAG(IS_CHROMEOS)
325*6777b538SAndroid Build Coastguard Worker
StackDumpSignalHandler(int signal,siginfo_t * info,void * void_context)326*6777b538SAndroid Build Coastguard Worker void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) {
327*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe.
328*6777b538SAndroid Build Coastguard Worker // NO malloc or stdio is allowed here.
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
331*6777b538SAndroid Build Coastguard Worker // Give a registered callback a chance to recover from this signal
332*6777b538SAndroid Build Coastguard Worker //
333*6777b538SAndroid Build Coastguard Worker // V8 uses guard regions to guarantee memory safety in WebAssembly. This means
334*6777b538SAndroid Build Coastguard Worker // some signals might be expected if they originate from Wasm code while
335*6777b538SAndroid Build Coastguard Worker // accessing the guard region. We give V8 the chance to handle and recover
336*6777b538SAndroid Build Coastguard Worker // from these signals first.
337*6777b538SAndroid Build Coastguard Worker if (try_handle_signal != nullptr &&
338*6777b538SAndroid Build Coastguard Worker try_handle_signal(signal, info, void_context)) {
339*6777b538SAndroid Build Coastguard Worker // The first chance handler took care of this. The SA_RESETHAND flag
340*6777b538SAndroid Build Coastguard Worker // replaced this signal handler upon entry, but we want to stay
341*6777b538SAndroid Build Coastguard Worker // installed. Thus, we reinstall ourselves before returning.
342*6777b538SAndroid Build Coastguard Worker struct sigaction action;
343*6777b538SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
344*6777b538SAndroid Build Coastguard Worker action.sa_flags = static_cast<int>(SA_RESETHAND | SA_SIGINFO);
345*6777b538SAndroid Build Coastguard Worker action.sa_sigaction = &StackDumpSignalHandler;
346*6777b538SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker sigaction(signal, &action, nullptr);
349*6777b538SAndroid Build Coastguard Worker return;
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker #endif
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker // Do not take the "in signal handler" code path on Mac in a DCHECK-enabled
354*6777b538SAndroid Build Coastguard Worker // build, as this prevents seeing a useful (symbolized) stack trace on a crash
355*6777b538SAndroid Build Coastguard Worker // or DCHECK() failure. While it may not be fully safe to run the stack symbol
356*6777b538SAndroid Build Coastguard Worker // printing code, in practice it's better to provide meaningful stack traces -
357*6777b538SAndroid Build Coastguard Worker // and the risk is low given we're likely crashing already.
358*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_APPLE) || !DCHECK_IS_ON()
359*6777b538SAndroid Build Coastguard Worker // Record the fact that we are in the signal handler now, so that the rest
360*6777b538SAndroid Build Coastguard Worker // of StackTrace can behave in an async-signal-safe manner.
361*6777b538SAndroid Build Coastguard Worker in_signal_handler = 1;
362*6777b538SAndroid Build Coastguard Worker #endif
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker if (BeingDebugged())
365*6777b538SAndroid Build Coastguard Worker BreakDebugger();
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker PrintToStderr("Received signal ");
368*6777b538SAndroid Build Coastguard Worker char buf[1024] = { 0 };
369*6777b538SAndroid Build Coastguard Worker internal::itoa_r(signal, buf, sizeof(buf), 10, 0);
370*6777b538SAndroid Build Coastguard Worker PrintToStderr(buf);
371*6777b538SAndroid Build Coastguard Worker if (signal == SIGBUS) {
372*6777b538SAndroid Build Coastguard Worker if (info->si_code == BUS_ADRALN)
373*6777b538SAndroid Build Coastguard Worker PrintToStderr(" BUS_ADRALN ");
374*6777b538SAndroid Build Coastguard Worker else if (info->si_code == BUS_ADRERR)
375*6777b538SAndroid Build Coastguard Worker PrintToStderr(" BUS_ADRERR ");
376*6777b538SAndroid Build Coastguard Worker else if (info->si_code == BUS_OBJERR)
377*6777b538SAndroid Build Coastguard Worker PrintToStderr(" BUS_OBJERR ");
378*6777b538SAndroid Build Coastguard Worker else
379*6777b538SAndroid Build Coastguard Worker PrintToStderr(" <unknown> ");
380*6777b538SAndroid Build Coastguard Worker } else if (signal == SIGFPE) {
381*6777b538SAndroid Build Coastguard Worker if (info->si_code == FPE_FLTDIV)
382*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTDIV ");
383*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_FLTINV)
384*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTINV ");
385*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_FLTOVF)
386*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTOVF ");
387*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_FLTRES)
388*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTRES ");
389*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_FLTSUB)
390*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTSUB ");
391*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_FLTUND)
392*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_FLTUND ");
393*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_INTDIV)
394*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_INTDIV ");
395*6777b538SAndroid Build Coastguard Worker else if (info->si_code == FPE_INTOVF)
396*6777b538SAndroid Build Coastguard Worker PrintToStderr(" FPE_INTOVF ");
397*6777b538SAndroid Build Coastguard Worker else
398*6777b538SAndroid Build Coastguard Worker PrintToStderr(" <unknown> ");
399*6777b538SAndroid Build Coastguard Worker } else if (signal == SIGILL) {
400*6777b538SAndroid Build Coastguard Worker if (info->si_code == ILL_BADSTK)
401*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_BADSTK ");
402*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_COPROC)
403*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_COPROC ");
404*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_ILLOPN)
405*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_ILLOPN ");
406*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_ILLADR)
407*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_ILLADR ");
408*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_ILLTRP)
409*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_ILLTRP ");
410*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_PRVOPC)
411*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_PRVOPC ");
412*6777b538SAndroid Build Coastguard Worker else if (info->si_code == ILL_PRVREG)
413*6777b538SAndroid Build Coastguard Worker PrintToStderr(" ILL_PRVREG ");
414*6777b538SAndroid Build Coastguard Worker else
415*6777b538SAndroid Build Coastguard Worker PrintToStderr(" <unknown> ");
416*6777b538SAndroid Build Coastguard Worker } else if (signal == SIGSEGV) {
417*6777b538SAndroid Build Coastguard Worker if (info->si_code == SEGV_MAPERR)
418*6777b538SAndroid Build Coastguard Worker PrintToStderr(" SEGV_MAPERR ");
419*6777b538SAndroid Build Coastguard Worker else if (info->si_code == SEGV_ACCERR)
420*6777b538SAndroid Build Coastguard Worker PrintToStderr(" SEGV_ACCERR ");
421*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64) && \
422*6777b538SAndroid Build Coastguard Worker (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS))
423*6777b538SAndroid Build Coastguard Worker else if (info->si_code == SI_KERNEL)
424*6777b538SAndroid Build Coastguard Worker PrintToStderr(" SI_KERNEL");
425*6777b538SAndroid Build Coastguard Worker #endif
426*6777b538SAndroid Build Coastguard Worker else
427*6777b538SAndroid Build Coastguard Worker PrintToStderr(" <unknown> ");
428*6777b538SAndroid Build Coastguard Worker }
429*6777b538SAndroid Build Coastguard Worker if (signal == SIGBUS || signal == SIGFPE ||
430*6777b538SAndroid Build Coastguard Worker signal == SIGILL || signal == SIGSEGV) {
431*6777b538SAndroid Build Coastguard Worker internal::itoa_r(reinterpret_cast<intptr_t>(info->si_addr),
432*6777b538SAndroid Build Coastguard Worker buf, sizeof(buf), 16, 12);
433*6777b538SAndroid Build Coastguard Worker PrintToStderr(buf);
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker PrintToStderr("\n");
436*6777b538SAndroid Build Coastguard Worker
437*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(CFI_ENFORCEMENT_TRAP)
438*6777b538SAndroid Build Coastguard Worker if (signal == SIGILL && info->si_code == ILL_ILLOPN) {
439*6777b538SAndroid Build Coastguard Worker PrintToStderr(
440*6777b538SAndroid Build Coastguard Worker "CFI: Most likely a control flow integrity violation; for more "
441*6777b538SAndroid Build Coastguard Worker "information see:\n");
442*6777b538SAndroid Build Coastguard Worker PrintToStderr(
443*6777b538SAndroid Build Coastguard Worker "https://www.chromium.org/developers/testing/control-flow-integrity\n");
444*6777b538SAndroid Build Coastguard Worker }
445*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(CFI_ENFORCEMENT_TRAP)
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_64) && \
448*6777b538SAndroid Build Coastguard Worker (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS))
449*6777b538SAndroid Build Coastguard Worker if (signal == SIGSEGV && info->si_code == SI_KERNEL) {
450*6777b538SAndroid Build Coastguard Worker PrintToStderr(
451*6777b538SAndroid Build Coastguard Worker " Possibly a General Protection Fault, can be due to a non-canonical "
452*6777b538SAndroid Build Coastguard Worker "address dereference. See \"Intel 64 and IA-32 Architectures Software "
453*6777b538SAndroid Build Coastguard Worker "Developer’s Manual\", Volume 1, Section 3.3.7.1.\n");
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker #endif
456*6777b538SAndroid Build Coastguard Worker
457*6777b538SAndroid Build Coastguard Worker debug::StackTrace().Print();
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
460*6777b538SAndroid Build Coastguard Worker #if ARCH_CPU_X86_FAMILY
461*6777b538SAndroid Build Coastguard Worker ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context);
462*6777b538SAndroid Build Coastguard Worker const struct {
463*6777b538SAndroid Build Coastguard Worker const char* label;
464*6777b538SAndroid Build Coastguard Worker greg_t value;
465*6777b538SAndroid Build Coastguard Worker } registers[] = {
466*6777b538SAndroid Build Coastguard Worker #if ARCH_CPU_32_BITS
467*6777b538SAndroid Build Coastguard Worker { " gs: ", context->uc_mcontext.gregs[REG_GS] },
468*6777b538SAndroid Build Coastguard Worker { " fs: ", context->uc_mcontext.gregs[REG_FS] },
469*6777b538SAndroid Build Coastguard Worker { " es: ", context->uc_mcontext.gregs[REG_ES] },
470*6777b538SAndroid Build Coastguard Worker { " ds: ", context->uc_mcontext.gregs[REG_DS] },
471*6777b538SAndroid Build Coastguard Worker { " edi: ", context->uc_mcontext.gregs[REG_EDI] },
472*6777b538SAndroid Build Coastguard Worker { " esi: ", context->uc_mcontext.gregs[REG_ESI] },
473*6777b538SAndroid Build Coastguard Worker { " ebp: ", context->uc_mcontext.gregs[REG_EBP] },
474*6777b538SAndroid Build Coastguard Worker { " esp: ", context->uc_mcontext.gregs[REG_ESP] },
475*6777b538SAndroid Build Coastguard Worker { " ebx: ", context->uc_mcontext.gregs[REG_EBX] },
476*6777b538SAndroid Build Coastguard Worker { " edx: ", context->uc_mcontext.gregs[REG_EDX] },
477*6777b538SAndroid Build Coastguard Worker { " ecx: ", context->uc_mcontext.gregs[REG_ECX] },
478*6777b538SAndroid Build Coastguard Worker { " eax: ", context->uc_mcontext.gregs[REG_EAX] },
479*6777b538SAndroid Build Coastguard Worker { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] },
480*6777b538SAndroid Build Coastguard Worker { " err: ", context->uc_mcontext.gregs[REG_ERR] },
481*6777b538SAndroid Build Coastguard Worker { " ip: ", context->uc_mcontext.gregs[REG_EIP] },
482*6777b538SAndroid Build Coastguard Worker { " cs: ", context->uc_mcontext.gregs[REG_CS] },
483*6777b538SAndroid Build Coastguard Worker { " efl: ", context->uc_mcontext.gregs[REG_EFL] },
484*6777b538SAndroid Build Coastguard Worker { " usp: ", context->uc_mcontext.gregs[REG_UESP] },
485*6777b538SAndroid Build Coastguard Worker { " ss: ", context->uc_mcontext.gregs[REG_SS] },
486*6777b538SAndroid Build Coastguard Worker #elif ARCH_CPU_64_BITS
487*6777b538SAndroid Build Coastguard Worker { " r8: ", context->uc_mcontext.gregs[REG_R8] },
488*6777b538SAndroid Build Coastguard Worker { " r9: ", context->uc_mcontext.gregs[REG_R9] },
489*6777b538SAndroid Build Coastguard Worker { " r10: ", context->uc_mcontext.gregs[REG_R10] },
490*6777b538SAndroid Build Coastguard Worker { " r11: ", context->uc_mcontext.gregs[REG_R11] },
491*6777b538SAndroid Build Coastguard Worker { " r12: ", context->uc_mcontext.gregs[REG_R12] },
492*6777b538SAndroid Build Coastguard Worker { " r13: ", context->uc_mcontext.gregs[REG_R13] },
493*6777b538SAndroid Build Coastguard Worker { " r14: ", context->uc_mcontext.gregs[REG_R14] },
494*6777b538SAndroid Build Coastguard Worker { " r15: ", context->uc_mcontext.gregs[REG_R15] },
495*6777b538SAndroid Build Coastguard Worker { " di: ", context->uc_mcontext.gregs[REG_RDI] },
496*6777b538SAndroid Build Coastguard Worker { " si: ", context->uc_mcontext.gregs[REG_RSI] },
497*6777b538SAndroid Build Coastguard Worker { " bp: ", context->uc_mcontext.gregs[REG_RBP] },
498*6777b538SAndroid Build Coastguard Worker { " bx: ", context->uc_mcontext.gregs[REG_RBX] },
499*6777b538SAndroid Build Coastguard Worker { " dx: ", context->uc_mcontext.gregs[REG_RDX] },
500*6777b538SAndroid Build Coastguard Worker { " ax: ", context->uc_mcontext.gregs[REG_RAX] },
501*6777b538SAndroid Build Coastguard Worker { " cx: ", context->uc_mcontext.gregs[REG_RCX] },
502*6777b538SAndroid Build Coastguard Worker { " sp: ", context->uc_mcontext.gregs[REG_RSP] },
503*6777b538SAndroid Build Coastguard Worker { " ip: ", context->uc_mcontext.gregs[REG_RIP] },
504*6777b538SAndroid Build Coastguard Worker { " efl: ", context->uc_mcontext.gregs[REG_EFL] },
505*6777b538SAndroid Build Coastguard Worker { " cgf: ", context->uc_mcontext.gregs[REG_CSGSFS] },
506*6777b538SAndroid Build Coastguard Worker { " erf: ", context->uc_mcontext.gregs[REG_ERR] },
507*6777b538SAndroid Build Coastguard Worker { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] },
508*6777b538SAndroid Build Coastguard Worker { " msk: ", context->uc_mcontext.gregs[REG_OLDMASK] },
509*6777b538SAndroid Build Coastguard Worker { " cr2: ", context->uc_mcontext.gregs[REG_CR2] },
510*6777b538SAndroid Build Coastguard Worker #endif // ARCH_CPU_32_BITS
511*6777b538SAndroid Build Coastguard Worker };
512*6777b538SAndroid Build Coastguard Worker
513*6777b538SAndroid Build Coastguard Worker #if ARCH_CPU_32_BITS
514*6777b538SAndroid Build Coastguard Worker const int kRegisterPadding = 8;
515*6777b538SAndroid Build Coastguard Worker #elif ARCH_CPU_64_BITS
516*6777b538SAndroid Build Coastguard Worker const int kRegisterPadding = 16;
517*6777b538SAndroid Build Coastguard Worker #endif
518*6777b538SAndroid Build Coastguard Worker
519*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(registers); i++) {
520*6777b538SAndroid Build Coastguard Worker PrintToStderr(registers[i].label);
521*6777b538SAndroid Build Coastguard Worker internal::itoa_r(registers[i].value, buf, sizeof(buf),
522*6777b538SAndroid Build Coastguard Worker 16, kRegisterPadding);
523*6777b538SAndroid Build Coastguard Worker PrintToStderr(buf);
524*6777b538SAndroid Build Coastguard Worker
525*6777b538SAndroid Build Coastguard Worker if ((i + 1) % 4 == 0)
526*6777b538SAndroid Build Coastguard Worker PrintToStderr("\n");
527*6777b538SAndroid Build Coastguard Worker }
528*6777b538SAndroid Build Coastguard Worker PrintToStderr("\n");
529*6777b538SAndroid Build Coastguard Worker #endif // ARCH_CPU_X86_FAMILY
530*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
531*6777b538SAndroid Build Coastguard Worker
532*6777b538SAndroid Build Coastguard Worker PrintToStderr("[end of stack trace]\n");
533*6777b538SAndroid Build Coastguard Worker
534*6777b538SAndroid Build Coastguard Worker if (::signal(signal, SIG_DFL) == SIG_ERR) {
535*6777b538SAndroid Build Coastguard Worker _exit(EXIT_FAILURE);
536*6777b538SAndroid Build Coastguard Worker }
537*6777b538SAndroid Build Coastguard Worker
538*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
539*6777b538SAndroid Build Coastguard Worker // Set an alarm to trigger in case the default handler does not terminate
540*6777b538SAndroid Build Coastguard Worker // the process. See 'AlarmSignalHandler' for more details.
541*6777b538SAndroid Build Coastguard Worker struct sigaction action;
542*6777b538SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
543*6777b538SAndroid Build Coastguard Worker action.sa_flags = static_cast<int>(SA_RESETHAND);
544*6777b538SAndroid Build Coastguard Worker action.sa_sigaction = &AlarmSignalHandler;
545*6777b538SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
546*6777b538SAndroid Build Coastguard Worker sigaction(SIGALRM, &action, nullptr);
547*6777b538SAndroid Build Coastguard Worker // 'alarm' function is signal handler safe.
548*6777b538SAndroid Build Coastguard Worker // https://man7.org/linux/man-pages/man7/signal-safety.7.html
549*6777b538SAndroid Build Coastguard Worker // This delay is set to be long enough for the real signal handler to fire but
550*6777b538SAndroid Build Coastguard Worker // shorter than chrome's process watchdog timer.
551*6777b538SAndroid Build Coastguard Worker constexpr unsigned int kAlarmSignalDelaySeconds = 5;
552*6777b538SAndroid Build Coastguard Worker alarm(kAlarmSignalDelaySeconds);
553*6777b538SAndroid Build Coastguard Worker
554*6777b538SAndroid Build Coastguard Worker // The following is mostly from
555*6777b538SAndroid Build Coastguard Worker // third_party/crashpad/crashpad/util/posix/signals.cc as re-raising signals
556*6777b538SAndroid Build Coastguard Worker // is complicated.
557*6777b538SAndroid Build Coastguard Worker
558*6777b538SAndroid Build Coastguard Worker // If we can raise a signal with siginfo on this platform, do so. This ensures
559*6777b538SAndroid Build Coastguard Worker // that we preserve the siginfo information for asynchronous signals (i.e.
560*6777b538SAndroid Build Coastguard Worker // signals that do not re-raise autonomously), such as signals delivered via
561*6777b538SAndroid Build Coastguard Worker // kill() and asynchronous hardware faults such as SEGV_MTEAERR, which would
562*6777b538SAndroid Build Coastguard Worker // otherwise be lost when re-raising the signal via raise().
563*6777b538SAndroid Build Coastguard Worker long retval = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid),
564*6777b538SAndroid Build Coastguard Worker info->si_signo, info);
565*6777b538SAndroid Build Coastguard Worker if (retval == 0) {
566*6777b538SAndroid Build Coastguard Worker return;
567*6777b538SAndroid Build Coastguard Worker }
568*6777b538SAndroid Build Coastguard Worker
569*6777b538SAndroid Build Coastguard Worker // Kernels without commit 66dd34ad31e5 ("signal: allow to send any siginfo to
570*6777b538SAndroid Build Coastguard Worker // itself"), which was first released in kernel version 3.9, did not permit a
571*6777b538SAndroid Build Coastguard Worker // process to send arbitrary signals to itself, and will reject the
572*6777b538SAndroid Build Coastguard Worker // rt_tgsigqueueinfo syscall with EPERM. If that happens, follow the non-Linux
573*6777b538SAndroid Build Coastguard Worker // code path. Any other errno is unexpected and will cause us to exit.
574*6777b538SAndroid Build Coastguard Worker if (errno != EPERM) {
575*6777b538SAndroid Build Coastguard Worker _exit(EXIT_FAILURE);
576*6777b538SAndroid Build Coastguard Worker }
577*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) ||
578*6777b538SAndroid Build Coastguard Worker // BUILDFLAG(IS_CHROMEOS)
579*6777b538SAndroid Build Coastguard Worker
580*6777b538SAndroid Build Coastguard Worker // Explicitly re-raise the signal even if it might have re-raised itself on
581*6777b538SAndroid Build Coastguard Worker // return. Because signal handlers normally execute with their signal blocked,
582*6777b538SAndroid Build Coastguard Worker // this raise() cannot immediately deliver the signal. Delivery is deferred
583*6777b538SAndroid Build Coastguard Worker // until the signal handler returns and the signal becomes unblocked. The
584*6777b538SAndroid Build Coastguard Worker // re-raised signal will appear with the same context as where it was
585*6777b538SAndroid Build Coastguard Worker // initially triggered.
586*6777b538SAndroid Build Coastguard Worker if (raise(signal) != 0) {
587*6777b538SAndroid Build Coastguard Worker _exit(EXIT_FAILURE);
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker }
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker class PrintBacktraceOutputHandler : public BacktraceOutputHandler {
592*6777b538SAndroid Build Coastguard Worker public:
593*6777b538SAndroid Build Coastguard Worker PrintBacktraceOutputHandler() = default;
594*6777b538SAndroid Build Coastguard Worker
595*6777b538SAndroid Build Coastguard Worker PrintBacktraceOutputHandler(const PrintBacktraceOutputHandler&) = delete;
596*6777b538SAndroid Build Coastguard Worker PrintBacktraceOutputHandler& operator=(const PrintBacktraceOutputHandler&) =
597*6777b538SAndroid Build Coastguard Worker delete;
598*6777b538SAndroid Build Coastguard Worker
HandleOutput(const char * output)599*6777b538SAndroid Build Coastguard Worker void HandleOutput(const char* output) override {
600*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
601*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
602*6777b538SAndroid Build Coastguard Worker PrintToStderr(output);
603*6777b538SAndroid Build Coastguard Worker }
604*6777b538SAndroid Build Coastguard Worker };
605*6777b538SAndroid Build Coastguard Worker
606*6777b538SAndroid Build Coastguard Worker class StreamBacktraceOutputHandler : public BacktraceOutputHandler {
607*6777b538SAndroid Build Coastguard Worker public:
StreamBacktraceOutputHandler(std::ostream * os)608*6777b538SAndroid Build Coastguard Worker explicit StreamBacktraceOutputHandler(std::ostream* os) : os_(os) {
609*6777b538SAndroid Build Coastguard Worker }
610*6777b538SAndroid Build Coastguard Worker
611*6777b538SAndroid Build Coastguard Worker StreamBacktraceOutputHandler(const StreamBacktraceOutputHandler&) = delete;
612*6777b538SAndroid Build Coastguard Worker StreamBacktraceOutputHandler& operator=(const StreamBacktraceOutputHandler&) =
613*6777b538SAndroid Build Coastguard Worker delete;
614*6777b538SAndroid Build Coastguard Worker
HandleOutput(const char * output)615*6777b538SAndroid Build Coastguard Worker void HandleOutput(const char* output) override { (*os_) << output; }
616*6777b538SAndroid Build Coastguard Worker
617*6777b538SAndroid Build Coastguard Worker private:
618*6777b538SAndroid Build Coastguard Worker raw_ptr<std::ostream> os_;
619*6777b538SAndroid Build Coastguard Worker };
620*6777b538SAndroid Build Coastguard Worker
WarmUpBacktrace()621*6777b538SAndroid Build Coastguard Worker void WarmUpBacktrace() {
622*6777b538SAndroid Build Coastguard Worker // Warm up stack trace infrastructure. It turns out that on the first
623*6777b538SAndroid Build Coastguard Worker // call glibc initializes some internal data structures using pthread_once,
624*6777b538SAndroid Build Coastguard Worker // and even backtrace() can call malloc(), leading to hangs.
625*6777b538SAndroid Build Coastguard Worker //
626*6777b538SAndroid Build Coastguard Worker // Example stack trace snippet (with tcmalloc):
627*6777b538SAndroid Build Coastguard Worker //
628*6777b538SAndroid Build Coastguard Worker // #8 0x0000000000a173b5 in tc_malloc
629*6777b538SAndroid Build Coastguard Worker // at ./third_party/tcmalloc/chromium/src/debugallocation.cc:1161
630*6777b538SAndroid Build Coastguard Worker // #9 0x00007ffff7de7900 in _dl_map_object_deps at dl-deps.c:517
631*6777b538SAndroid Build Coastguard Worker // #10 0x00007ffff7ded8a9 in dl_open_worker at dl-open.c:262
632*6777b538SAndroid Build Coastguard Worker // #11 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
633*6777b538SAndroid Build Coastguard Worker // #12 0x00007ffff7ded31a in _dl_open (file=0x7ffff625e298 "libgcc_s.so.1")
634*6777b538SAndroid Build Coastguard Worker // at dl-open.c:639
635*6777b538SAndroid Build Coastguard Worker // #13 0x00007ffff6215602 in do_dlopen at dl-libc.c:89
636*6777b538SAndroid Build Coastguard Worker // #14 0x00007ffff7de9176 in _dl_catch_error at dl-error.c:178
637*6777b538SAndroid Build Coastguard Worker // #15 0x00007ffff62156c4 in dlerror_run at dl-libc.c:48
638*6777b538SAndroid Build Coastguard Worker // #16 __GI___libc_dlopen_mode at dl-libc.c:165
639*6777b538SAndroid Build Coastguard Worker // #17 0x00007ffff61ef8f5 in init
640*6777b538SAndroid Build Coastguard Worker // at ../sysdeps/x86_64/../ia64/backtrace.c:53
641*6777b538SAndroid Build Coastguard Worker // #18 0x00007ffff6aad400 in pthread_once
642*6777b538SAndroid Build Coastguard Worker // at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:104
643*6777b538SAndroid Build Coastguard Worker // #19 0x00007ffff61efa14 in __GI___backtrace
644*6777b538SAndroid Build Coastguard Worker // at ../sysdeps/x86_64/../ia64/backtrace.c:104
645*6777b538SAndroid Build Coastguard Worker // #20 0x0000000000752a54 in base::debug::StackTrace::StackTrace
646*6777b538SAndroid Build Coastguard Worker // at base/debug/stack_trace_posix.cc:175
647*6777b538SAndroid Build Coastguard Worker // #21 0x00000000007a4ae5 in
648*6777b538SAndroid Build Coastguard Worker // base::(anonymous namespace)::StackDumpSignalHandler
649*6777b538SAndroid Build Coastguard Worker // at base/process_util_posix.cc:172
650*6777b538SAndroid Build Coastguard Worker // #22 <signal handler called>
651*6777b538SAndroid Build Coastguard Worker StackTrace stack_trace;
652*6777b538SAndroid Build Coastguard Worker }
653*6777b538SAndroid Build Coastguard Worker
654*6777b538SAndroid Build Coastguard Worker #if defined(USE_SYMBOLIZE)
655*6777b538SAndroid Build Coastguard Worker
656*6777b538SAndroid Build Coastguard Worker // class SandboxSymbolizeHelper.
657*6777b538SAndroid Build Coastguard Worker //
658*6777b538SAndroid Build Coastguard Worker // The purpose of this class is to prepare and install a "file open" callback
659*6777b538SAndroid Build Coastguard Worker // needed by the stack trace symbolization code
660*6777b538SAndroid Build Coastguard Worker // (base/third_party/symbolize/symbolize.h) so that it can function properly
661*6777b538SAndroid Build Coastguard Worker // in a sandboxed process. The caveat is that this class must be instantiated
662*6777b538SAndroid Build Coastguard Worker // before the sandboxing is enabled so that it can get the chance to open all
663*6777b538SAndroid Build Coastguard Worker // the object files that are loaded in the virtual address space of the current
664*6777b538SAndroid Build Coastguard Worker // process.
665*6777b538SAndroid Build Coastguard Worker class SandboxSymbolizeHelper {
666*6777b538SAndroid Build Coastguard Worker public:
667*6777b538SAndroid Build Coastguard Worker // Returns the singleton instance.
GetInstance()668*6777b538SAndroid Build Coastguard Worker static SandboxSymbolizeHelper* GetInstance() {
669*6777b538SAndroid Build Coastguard Worker return Singleton<SandboxSymbolizeHelper,
670*6777b538SAndroid Build Coastguard Worker LeakySingletonTraits<SandboxSymbolizeHelper>>::get();
671*6777b538SAndroid Build Coastguard Worker }
672*6777b538SAndroid Build Coastguard Worker
673*6777b538SAndroid Build Coastguard Worker SandboxSymbolizeHelper(const SandboxSymbolizeHelper&) = delete;
674*6777b538SAndroid Build Coastguard Worker SandboxSymbolizeHelper& operator=(const SandboxSymbolizeHelper&) = delete;
675*6777b538SAndroid Build Coastguard Worker
676*6777b538SAndroid Build Coastguard Worker private:
677*6777b538SAndroid Build Coastguard Worker friend struct DefaultSingletonTraits<SandboxSymbolizeHelper>;
678*6777b538SAndroid Build Coastguard Worker
SandboxSymbolizeHelper()679*6777b538SAndroid Build Coastguard Worker SandboxSymbolizeHelper()
680*6777b538SAndroid Build Coastguard Worker : is_initialized_(false) {
681*6777b538SAndroid Build Coastguard Worker Init();
682*6777b538SAndroid Build Coastguard Worker }
683*6777b538SAndroid Build Coastguard Worker
~SandboxSymbolizeHelper()684*6777b538SAndroid Build Coastguard Worker ~SandboxSymbolizeHelper() {
685*6777b538SAndroid Build Coastguard Worker UnregisterCallback();
686*6777b538SAndroid Build Coastguard Worker CloseObjectFiles();
687*6777b538SAndroid Build Coastguard Worker }
688*6777b538SAndroid Build Coastguard Worker
689*6777b538SAndroid Build Coastguard Worker // Returns a O_RDONLY file descriptor for |file_path| if it was opened
690*6777b538SAndroid Build Coastguard Worker // successfully during the initialization. The file is repositioned at
691*6777b538SAndroid Build Coastguard Worker // offset 0.
692*6777b538SAndroid Build Coastguard Worker // IMPORTANT: This function must be async-signal-safe because it can be
693*6777b538SAndroid Build Coastguard Worker // called from a signal handler (symbolizing stack frames for a crash).
GetFileDescriptor(const char * file_path)694*6777b538SAndroid Build Coastguard Worker int GetFileDescriptor(const char* file_path) {
695*6777b538SAndroid Build Coastguard Worker int fd = -1;
696*6777b538SAndroid Build Coastguard Worker
697*6777b538SAndroid Build Coastguard Worker #if !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
698*6777b538SAndroid Build Coastguard Worker if (file_path) {
699*6777b538SAndroid Build Coastguard Worker // The assumption here is that iterating over std::map<std::string,
700*6777b538SAndroid Build Coastguard Worker // base::ScopedFD> does not allocate dynamic memory, hence it is
701*6777b538SAndroid Build Coastguard Worker // async-signal-safe.
702*6777b538SAndroid Build Coastguard Worker for (const auto& filepath_fd : modules_) {
703*6777b538SAndroid Build Coastguard Worker if (strcmp(filepath_fd.first.c_str(), file_path) == 0) {
704*6777b538SAndroid Build Coastguard Worker // POSIX.1-2004 requires an implementation to guarantee that dup()
705*6777b538SAndroid Build Coastguard Worker // is async-signal-safe.
706*6777b538SAndroid Build Coastguard Worker fd = HANDLE_EINTR(dup(filepath_fd.second.get()));
707*6777b538SAndroid Build Coastguard Worker break;
708*6777b538SAndroid Build Coastguard Worker }
709*6777b538SAndroid Build Coastguard Worker }
710*6777b538SAndroid Build Coastguard Worker // POSIX.1-2004 requires an implementation to guarantee that lseek()
711*6777b538SAndroid Build Coastguard Worker // is async-signal-safe.
712*6777b538SAndroid Build Coastguard Worker if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) {
713*6777b538SAndroid Build Coastguard Worker // Failed to seek.
714*6777b538SAndroid Build Coastguard Worker fd = -1;
715*6777b538SAndroid Build Coastguard Worker }
716*6777b538SAndroid Build Coastguard Worker }
717*6777b538SAndroid Build Coastguard Worker #endif // !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
718*6777b538SAndroid Build Coastguard Worker
719*6777b538SAndroid Build Coastguard Worker return fd;
720*6777b538SAndroid Build Coastguard Worker }
721*6777b538SAndroid Build Coastguard Worker
722*6777b538SAndroid Build Coastguard Worker // Searches for the object file (from /proc/self/maps) that contains
723*6777b538SAndroid Build Coastguard Worker // the specified pc. If found, sets |start_address| to the start address
724*6777b538SAndroid Build Coastguard Worker // of where this object file is mapped in memory, sets the module base
725*6777b538SAndroid Build Coastguard Worker // address into |base_address|, copies the object file name into
726*6777b538SAndroid Build Coastguard Worker // |out_file_name|, and attempts to open the object file. If the object
727*6777b538SAndroid Build Coastguard Worker // file is opened successfully, returns the file descriptor. Otherwise,
728*6777b538SAndroid Build Coastguard Worker // returns -1. |out_file_name_size| is the size of the file name buffer
729*6777b538SAndroid Build Coastguard Worker // (including the null terminator).
730*6777b538SAndroid Build Coastguard Worker // IMPORTANT: This function must be async-signal-safe because it can be
731*6777b538SAndroid Build Coastguard Worker // called from a signal handler (symbolizing stack frames for a crash).
OpenObjectFileContainingPc(uint64_t pc,uint64_t & start_address,uint64_t & base_address,char * file_path,size_t file_path_size)732*6777b538SAndroid Build Coastguard Worker static int OpenObjectFileContainingPc(uint64_t pc,
733*6777b538SAndroid Build Coastguard Worker uint64_t& start_address,
734*6777b538SAndroid Build Coastguard Worker uint64_t& base_address,
735*6777b538SAndroid Build Coastguard Worker char* file_path,
736*6777b538SAndroid Build Coastguard Worker size_t file_path_size) {
737*6777b538SAndroid Build Coastguard Worker // This method can only be called after the singleton is instantiated.
738*6777b538SAndroid Build Coastguard Worker // This is ensured by the following facts:
739*6777b538SAndroid Build Coastguard Worker // * This is the only static method in this class, it is private, and
740*6777b538SAndroid Build Coastguard Worker // the class has no friends (except for the DefaultSingletonTraits).
741*6777b538SAndroid Build Coastguard Worker // The compiler guarantees that it can only be called after the
742*6777b538SAndroid Build Coastguard Worker // singleton is instantiated.
743*6777b538SAndroid Build Coastguard Worker // * This method is used as a callback for the stack tracing code and
744*6777b538SAndroid Build Coastguard Worker // the callback registration is done in the constructor, so logically
745*6777b538SAndroid Build Coastguard Worker // it cannot be called before the singleton is created.
746*6777b538SAndroid Build Coastguard Worker SandboxSymbolizeHelper* instance = GetInstance();
747*6777b538SAndroid Build Coastguard Worker
748*6777b538SAndroid Build Coastguard Worker // Cannot use STL iterators here, since debug iterators use locks.
749*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(modernize-loop-convert)
750*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < instance->regions_.size(); ++i) {
751*6777b538SAndroid Build Coastguard Worker const MappedMemoryRegion& region = instance->regions_[i];
752*6777b538SAndroid Build Coastguard Worker if (region.start <= pc && pc < region.end) {
753*6777b538SAndroid Build Coastguard Worker start_address = region.start;
754*6777b538SAndroid Build Coastguard Worker base_address = region.base;
755*6777b538SAndroid Build Coastguard Worker if (file_path && file_path_size > 0) {
756*6777b538SAndroid Build Coastguard Worker strncpy(file_path, region.path.c_str(), file_path_size);
757*6777b538SAndroid Build Coastguard Worker // Ensure null termination.
758*6777b538SAndroid Build Coastguard Worker file_path[file_path_size - 1] = '\0';
759*6777b538SAndroid Build Coastguard Worker }
760*6777b538SAndroid Build Coastguard Worker return instance->GetFileDescriptor(region.path.c_str());
761*6777b538SAndroid Build Coastguard Worker }
762*6777b538SAndroid Build Coastguard Worker }
763*6777b538SAndroid Build Coastguard Worker return -1;
764*6777b538SAndroid Build Coastguard Worker }
765*6777b538SAndroid Build Coastguard Worker
766*6777b538SAndroid Build Coastguard Worker // This class is copied from
767*6777b538SAndroid Build Coastguard Worker // third_party/crashpad/crashpad/util/linux/scoped_pr_set_dumpable.h.
768*6777b538SAndroid Build Coastguard Worker // It aims at ensuring the process is dumpable before opening /proc/self/mem.
769*6777b538SAndroid Build Coastguard Worker // If the process is already dumpable, this class doesn't do anything.
770*6777b538SAndroid Build Coastguard Worker class ScopedPrSetDumpable {
771*6777b538SAndroid Build Coastguard Worker public:
772*6777b538SAndroid Build Coastguard Worker // Uses `PR_SET_DUMPABLE` to make the current process dumpable.
773*6777b538SAndroid Build Coastguard Worker //
774*6777b538SAndroid Build Coastguard Worker // Restores the dumpable flag to its original value on destruction. If the
775*6777b538SAndroid Build Coastguard Worker // original value couldn't be determined, the destructor attempts to
776*6777b538SAndroid Build Coastguard Worker // restore the flag to 0 (non-dumpable).
ScopedPrSetDumpable()777*6777b538SAndroid Build Coastguard Worker explicit ScopedPrSetDumpable() {
778*6777b538SAndroid Build Coastguard Worker int result = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
779*6777b538SAndroid Build Coastguard Worker was_dumpable_ = result > 0;
780*6777b538SAndroid Build Coastguard Worker
781*6777b538SAndroid Build Coastguard Worker if (!was_dumpable_) {
782*6777b538SAndroid Build Coastguard Worker std::ignore = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
783*6777b538SAndroid Build Coastguard Worker }
784*6777b538SAndroid Build Coastguard Worker }
785*6777b538SAndroid Build Coastguard Worker
786*6777b538SAndroid Build Coastguard Worker ScopedPrSetDumpable(const ScopedPrSetDumpable&) = delete;
787*6777b538SAndroid Build Coastguard Worker ScopedPrSetDumpable& operator=(const ScopedPrSetDumpable&) = delete;
788*6777b538SAndroid Build Coastguard Worker
~ScopedPrSetDumpable()789*6777b538SAndroid Build Coastguard Worker ~ScopedPrSetDumpable() {
790*6777b538SAndroid Build Coastguard Worker if (!was_dumpable_) {
791*6777b538SAndroid Build Coastguard Worker std::ignore = prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
792*6777b538SAndroid Build Coastguard Worker }
793*6777b538SAndroid Build Coastguard Worker }
794*6777b538SAndroid Build Coastguard Worker
795*6777b538SAndroid Build Coastguard Worker private:
796*6777b538SAndroid Build Coastguard Worker bool was_dumpable_;
797*6777b538SAndroid Build Coastguard Worker };
798*6777b538SAndroid Build Coastguard Worker
799*6777b538SAndroid Build Coastguard Worker // Set the base address for each memory region by reading ELF headers in
800*6777b538SAndroid Build Coastguard Worker // process memory.
SetBaseAddressesForMemoryRegions()801*6777b538SAndroid Build Coastguard Worker void SetBaseAddressesForMemoryRegions() {
802*6777b538SAndroid Build Coastguard Worker base::ScopedFD mem_fd;
803*6777b538SAndroid Build Coastguard Worker {
804*6777b538SAndroid Build Coastguard Worker ScopedPrSetDumpable s;
805*6777b538SAndroid Build Coastguard Worker mem_fd = base::ScopedFD(
806*6777b538SAndroid Build Coastguard Worker HANDLE_EINTR(open("/proc/self/mem", O_RDONLY | O_CLOEXEC)));
807*6777b538SAndroid Build Coastguard Worker if (!mem_fd.is_valid()) {
808*6777b538SAndroid Build Coastguard Worker return;
809*6777b538SAndroid Build Coastguard Worker }
810*6777b538SAndroid Build Coastguard Worker }
811*6777b538SAndroid Build Coastguard Worker
812*6777b538SAndroid Build Coastguard Worker auto safe_memcpy = [&mem_fd](void* dst, uintptr_t src, size_t size) {
813*6777b538SAndroid Build Coastguard Worker return HANDLE_EINTR(pread(mem_fd.get(), dst, size,
814*6777b538SAndroid Build Coastguard Worker static_cast<off_t>(src))) == ssize_t(size);
815*6777b538SAndroid Build Coastguard Worker };
816*6777b538SAndroid Build Coastguard Worker
817*6777b538SAndroid Build Coastguard Worker uintptr_t cur_base = 0;
818*6777b538SAndroid Build Coastguard Worker for (auto& r : regions_) {
819*6777b538SAndroid Build Coastguard Worker ElfW(Ehdr) ehdr;
820*6777b538SAndroid Build Coastguard Worker static_assert(SELFMAG <= sizeof(ElfW(Ehdr)), "SELFMAG too large");
821*6777b538SAndroid Build Coastguard Worker if ((r.permissions & MappedMemoryRegion::READ) &&
822*6777b538SAndroid Build Coastguard Worker safe_memcpy(&ehdr, r.start, sizeof(ElfW(Ehdr))) &&
823*6777b538SAndroid Build Coastguard Worker memcmp(ehdr.e_ident, ELFMAG, SELFMAG) == 0) {
824*6777b538SAndroid Build Coastguard Worker switch (ehdr.e_type) {
825*6777b538SAndroid Build Coastguard Worker case ET_EXEC:
826*6777b538SAndroid Build Coastguard Worker cur_base = 0;
827*6777b538SAndroid Build Coastguard Worker break;
828*6777b538SAndroid Build Coastguard Worker case ET_DYN:
829*6777b538SAndroid Build Coastguard Worker // Find the segment containing file offset 0. This will correspond
830*6777b538SAndroid Build Coastguard Worker // to the ELF header that we just read. Normally this will have
831*6777b538SAndroid Build Coastguard Worker // virtual address 0, but this is not guaranteed. We must subtract
832*6777b538SAndroid Build Coastguard Worker // the virtual address from the address where the ELF header was
833*6777b538SAndroid Build Coastguard Worker // mapped to get the base address.
834*6777b538SAndroid Build Coastguard Worker //
835*6777b538SAndroid Build Coastguard Worker // If we fail to find a segment for file offset 0, use the address
836*6777b538SAndroid Build Coastguard Worker // of the ELF header as the base address.
837*6777b538SAndroid Build Coastguard Worker cur_base = r.start;
838*6777b538SAndroid Build Coastguard Worker for (unsigned i = 0; i != ehdr.e_phnum; ++i) {
839*6777b538SAndroid Build Coastguard Worker ElfW(Phdr) phdr;
840*6777b538SAndroid Build Coastguard Worker if (safe_memcpy(&phdr, r.start + ehdr.e_phoff + i * sizeof(phdr),
841*6777b538SAndroid Build Coastguard Worker sizeof(phdr)) &&
842*6777b538SAndroid Build Coastguard Worker phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
843*6777b538SAndroid Build Coastguard Worker cur_base = r.start - phdr.p_vaddr;
844*6777b538SAndroid Build Coastguard Worker break;
845*6777b538SAndroid Build Coastguard Worker }
846*6777b538SAndroid Build Coastguard Worker }
847*6777b538SAndroid Build Coastguard Worker break;
848*6777b538SAndroid Build Coastguard Worker default:
849*6777b538SAndroid Build Coastguard Worker // ET_REL or ET_CORE. These aren't directly executable, so they
850*6777b538SAndroid Build Coastguard Worker // don't affect the base address.
851*6777b538SAndroid Build Coastguard Worker break;
852*6777b538SAndroid Build Coastguard Worker }
853*6777b538SAndroid Build Coastguard Worker }
854*6777b538SAndroid Build Coastguard Worker
855*6777b538SAndroid Build Coastguard Worker r.base = cur_base;
856*6777b538SAndroid Build Coastguard Worker }
857*6777b538SAndroid Build Coastguard Worker }
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker // Parses /proc/self/maps in order to compile a list of all object file names
860*6777b538SAndroid Build Coastguard Worker // for the modules that are loaded in the current process.
861*6777b538SAndroid Build Coastguard Worker // Returns true on success.
CacheMemoryRegions()862*6777b538SAndroid Build Coastguard Worker bool CacheMemoryRegions() {
863*6777b538SAndroid Build Coastguard Worker // Reads /proc/self/maps.
864*6777b538SAndroid Build Coastguard Worker std::string contents;
865*6777b538SAndroid Build Coastguard Worker if (!ReadProcMaps(&contents)) {
866*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to read /proc/self/maps";
867*6777b538SAndroid Build Coastguard Worker return false;
868*6777b538SAndroid Build Coastguard Worker }
869*6777b538SAndroid Build Coastguard Worker
870*6777b538SAndroid Build Coastguard Worker // Parses /proc/self/maps.
871*6777b538SAndroid Build Coastguard Worker if (!ParseProcMaps(contents, ®ions_)) {
872*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse the contents of /proc/self/maps";
873*6777b538SAndroid Build Coastguard Worker return false;
874*6777b538SAndroid Build Coastguard Worker }
875*6777b538SAndroid Build Coastguard Worker
876*6777b538SAndroid Build Coastguard Worker SetBaseAddressesForMemoryRegions();
877*6777b538SAndroid Build Coastguard Worker
878*6777b538SAndroid Build Coastguard Worker is_initialized_ = true;
879*6777b538SAndroid Build Coastguard Worker return true;
880*6777b538SAndroid Build Coastguard Worker }
881*6777b538SAndroid Build Coastguard Worker
882*6777b538SAndroid Build Coastguard Worker // Opens all object files and caches their file descriptors.
OpenSymbolFiles()883*6777b538SAndroid Build Coastguard Worker void OpenSymbolFiles() {
884*6777b538SAndroid Build Coastguard Worker // Pre-opening and caching the file descriptors of all loaded modules is
885*6777b538SAndroid Build Coastguard Worker // not safe for production builds. Hence it is only done in non-official
886*6777b538SAndroid Build Coastguard Worker // builds. For more details, take a look at: http://crbug.com/341966.
887*6777b538SAndroid Build Coastguard Worker #if !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
888*6777b538SAndroid Build Coastguard Worker // Open the object files for all read-only executable regions and cache
889*6777b538SAndroid Build Coastguard Worker // their file descriptors.
890*6777b538SAndroid Build Coastguard Worker std::vector<MappedMemoryRegion>::const_iterator it;
891*6777b538SAndroid Build Coastguard Worker for (it = regions_.begin(); it != regions_.end(); ++it) {
892*6777b538SAndroid Build Coastguard Worker const MappedMemoryRegion& region = *it;
893*6777b538SAndroid Build Coastguard Worker // Only interesed in read-only executable regions.
894*6777b538SAndroid Build Coastguard Worker if ((region.permissions & MappedMemoryRegion::READ) ==
895*6777b538SAndroid Build Coastguard Worker MappedMemoryRegion::READ &&
896*6777b538SAndroid Build Coastguard Worker (region.permissions & MappedMemoryRegion::WRITE) == 0 &&
897*6777b538SAndroid Build Coastguard Worker (region.permissions & MappedMemoryRegion::EXECUTE) ==
898*6777b538SAndroid Build Coastguard Worker MappedMemoryRegion::EXECUTE) {
899*6777b538SAndroid Build Coastguard Worker if (region.path.empty()) {
900*6777b538SAndroid Build Coastguard Worker // Skip regions with empty file names.
901*6777b538SAndroid Build Coastguard Worker continue;
902*6777b538SAndroid Build Coastguard Worker }
903*6777b538SAndroid Build Coastguard Worker if (region.path[0] == '[') {
904*6777b538SAndroid Build Coastguard Worker // Skip pseudo-paths, like [stack], [vdso], [heap], etc ...
905*6777b538SAndroid Build Coastguard Worker continue;
906*6777b538SAndroid Build Coastguard Worker }
907*6777b538SAndroid Build Coastguard Worker if (base::EndsWith(region.path, " (deleted)",
908*6777b538SAndroid Build Coastguard Worker base::CompareCase::SENSITIVE)) {
909*6777b538SAndroid Build Coastguard Worker // Skip deleted files.
910*6777b538SAndroid Build Coastguard Worker continue;
911*6777b538SAndroid Build Coastguard Worker }
912*6777b538SAndroid Build Coastguard Worker // Avoid duplicates.
913*6777b538SAndroid Build Coastguard Worker if (modules_.find(region.path) == modules_.end()) {
914*6777b538SAndroid Build Coastguard Worker int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC);
915*6777b538SAndroid Build Coastguard Worker if (fd >= 0) {
916*6777b538SAndroid Build Coastguard Worker modules_.emplace(region.path, base::ScopedFD(fd));
917*6777b538SAndroid Build Coastguard Worker } else {
918*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to open file: " << region.path
919*6777b538SAndroid Build Coastguard Worker << "\n Error: " << strerror(errno);
920*6777b538SAndroid Build Coastguard Worker }
921*6777b538SAndroid Build Coastguard Worker }
922*6777b538SAndroid Build Coastguard Worker }
923*6777b538SAndroid Build Coastguard Worker }
924*6777b538SAndroid Build Coastguard Worker #endif // !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
925*6777b538SAndroid Build Coastguard Worker }
926*6777b538SAndroid Build Coastguard Worker
927*6777b538SAndroid Build Coastguard Worker // Initializes and installs the symbolization callback.
Init()928*6777b538SAndroid Build Coastguard Worker void Init() {
929*6777b538SAndroid Build Coastguard Worker if (CacheMemoryRegions()) {
930*6777b538SAndroid Build Coastguard Worker OpenSymbolFiles();
931*6777b538SAndroid Build Coastguard Worker google::InstallSymbolizeOpenObjectFileCallback(
932*6777b538SAndroid Build Coastguard Worker &OpenObjectFileContainingPc);
933*6777b538SAndroid Build Coastguard Worker }
934*6777b538SAndroid Build Coastguard Worker }
935*6777b538SAndroid Build Coastguard Worker
936*6777b538SAndroid Build Coastguard Worker // Unregister symbolization callback.
UnregisterCallback()937*6777b538SAndroid Build Coastguard Worker void UnregisterCallback() {
938*6777b538SAndroid Build Coastguard Worker if (is_initialized_) {
939*6777b538SAndroid Build Coastguard Worker google::InstallSymbolizeOpenObjectFileCallback(nullptr);
940*6777b538SAndroid Build Coastguard Worker is_initialized_ = false;
941*6777b538SAndroid Build Coastguard Worker }
942*6777b538SAndroid Build Coastguard Worker }
943*6777b538SAndroid Build Coastguard Worker
944*6777b538SAndroid Build Coastguard Worker // Closes all file descriptors owned by this instance.
CloseObjectFiles()945*6777b538SAndroid Build Coastguard Worker void CloseObjectFiles() {
946*6777b538SAndroid Build Coastguard Worker #if !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
947*6777b538SAndroid Build Coastguard Worker modules_.clear();
948*6777b538SAndroid Build Coastguard Worker #endif // !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
949*6777b538SAndroid Build Coastguard Worker }
950*6777b538SAndroid Build Coastguard Worker
951*6777b538SAndroid Build Coastguard Worker // Set to true upon successful initialization.
952*6777b538SAndroid Build Coastguard Worker bool is_initialized_;
953*6777b538SAndroid Build Coastguard Worker
954*6777b538SAndroid Build Coastguard Worker #if !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
955*6777b538SAndroid Build Coastguard Worker // Mapping from file name to file descriptor. Includes file descriptors
956*6777b538SAndroid Build Coastguard Worker // for all successfully opened object files and the file descriptor for
957*6777b538SAndroid Build Coastguard Worker // /proc/self/maps. This code is not safe for production builds.
958*6777b538SAndroid Build Coastguard Worker std::map<std::string, base::ScopedFD> modules_;
959*6777b538SAndroid Build Coastguard Worker #endif // !defined(OFFICIAL_BUILD) || !defined(NO_UNWIND_TABLES)
960*6777b538SAndroid Build Coastguard Worker
961*6777b538SAndroid Build Coastguard Worker // Cache for the process memory regions. Produced by parsing the contents
962*6777b538SAndroid Build Coastguard Worker // of /proc/self/maps cache.
963*6777b538SAndroid Build Coastguard Worker std::vector<MappedMemoryRegion> regions_;
964*6777b538SAndroid Build Coastguard Worker };
965*6777b538SAndroid Build Coastguard Worker #endif // USE_SYMBOLIZE
966*6777b538SAndroid Build Coastguard Worker
967*6777b538SAndroid Build Coastguard Worker } // namespace
968*6777b538SAndroid Build Coastguard Worker
EnableInProcessStackDumping()969*6777b538SAndroid Build Coastguard Worker bool EnableInProcessStackDumping() {
970*6777b538SAndroid Build Coastguard Worker #if defined(USE_SYMBOLIZE)
971*6777b538SAndroid Build Coastguard Worker SandboxSymbolizeHelper::GetInstance();
972*6777b538SAndroid Build Coastguard Worker #endif // USE_SYMBOLIZE
973*6777b538SAndroid Build Coastguard Worker
974*6777b538SAndroid Build Coastguard Worker // When running in an application, our code typically expects SIGPIPE
975*6777b538SAndroid Build Coastguard Worker // to be ignored. Therefore, when testing that same code, it should run
976*6777b538SAndroid Build Coastguard Worker // with SIGPIPE ignored as well.
977*6777b538SAndroid Build Coastguard Worker struct sigaction sigpipe_action;
978*6777b538SAndroid Build Coastguard Worker memset(&sigpipe_action, 0, sizeof(sigpipe_action));
979*6777b538SAndroid Build Coastguard Worker sigpipe_action.sa_handler = SIG_IGN;
980*6777b538SAndroid Build Coastguard Worker sigemptyset(&sigpipe_action.sa_mask);
981*6777b538SAndroid Build Coastguard Worker bool success = (sigaction(SIGPIPE, &sigpipe_action, nullptr) == 0);
982*6777b538SAndroid Build Coastguard Worker
983*6777b538SAndroid Build Coastguard Worker // Avoid hangs during backtrace initialization, see above.
984*6777b538SAndroid Build Coastguard Worker WarmUpBacktrace();
985*6777b538SAndroid Build Coastguard Worker
986*6777b538SAndroid Build Coastguard Worker struct sigaction action;
987*6777b538SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
988*6777b538SAndroid Build Coastguard Worker action.sa_flags = static_cast<int>(SA_RESETHAND | SA_SIGINFO);
989*6777b538SAndroid Build Coastguard Worker action.sa_sigaction = &StackDumpSignalHandler;
990*6777b538SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
991*6777b538SAndroid Build Coastguard Worker
992*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGILL, &action, nullptr) == 0);
993*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGABRT, &action, nullptr) == 0);
994*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGFPE, &action, nullptr) == 0);
995*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGBUS, &action, nullptr) == 0);
996*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGSEGV, &action, nullptr) == 0);
997*6777b538SAndroid Build Coastguard Worker // On Linux, SIGSYS is reserved by the kernel for seccomp-bpf sandboxing.
998*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
999*6777b538SAndroid Build Coastguard Worker success &= (sigaction(SIGSYS, &action, nullptr) == 0);
1000*6777b538SAndroid Build Coastguard Worker #endif // !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
1001*6777b538SAndroid Build Coastguard Worker
1002*6777b538SAndroid Build Coastguard Worker return success;
1003*6777b538SAndroid Build Coastguard Worker }
1004*6777b538SAndroid Build Coastguard Worker
1005*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
SetStackDumpFirstChanceCallback(bool (* handler)(int,siginfo_t *,void *))1006*6777b538SAndroid Build Coastguard Worker bool SetStackDumpFirstChanceCallback(bool (*handler)(int, siginfo_t*, void*)) {
1007*6777b538SAndroid Build Coastguard Worker DCHECK(try_handle_signal == nullptr || handler == nullptr);
1008*6777b538SAndroid Build Coastguard Worker try_handle_signal = handler;
1009*6777b538SAndroid Build Coastguard Worker
1010*6777b538SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
1011*6777b538SAndroid Build Coastguard Worker defined(THREAD_SANITIZER) || defined(LEAK_SANITIZER) || \
1012*6777b538SAndroid Build Coastguard Worker defined(UNDEFINED_SANITIZER)
1013*6777b538SAndroid Build Coastguard Worker struct sigaction installed_handler;
1014*6777b538SAndroid Build Coastguard Worker CHECK_EQ(sigaction(SIGSEGV, NULL, &installed_handler), 0);
1015*6777b538SAndroid Build Coastguard Worker // If the installed handler does not point to StackDumpSignalHandler, then
1016*6777b538SAndroid Build Coastguard Worker // allow_user_segv_handler is 0.
1017*6777b538SAndroid Build Coastguard Worker if (installed_handler.sa_sigaction != StackDumpSignalHandler) {
1018*6777b538SAndroid Build Coastguard Worker LOG(WARNING)
1019*6777b538SAndroid Build Coastguard Worker << "WARNING: sanitizers are preventing signal handler installation. "
1020*6777b538SAndroid Build Coastguard Worker << "WebAssembly trap handlers are disabled.\n";
1021*6777b538SAndroid Build Coastguard Worker return false;
1022*6777b538SAndroid Build Coastguard Worker }
1023*6777b538SAndroid Build Coastguard Worker #endif
1024*6777b538SAndroid Build Coastguard Worker return true;
1025*6777b538SAndroid Build Coastguard Worker }
1026*6777b538SAndroid Build Coastguard Worker #endif
1027*6777b538SAndroid Build Coastguard Worker
CollectStackTrace(const void ** trace,size_t count)1028*6777b538SAndroid Build Coastguard Worker size_t CollectStackTrace(const void** trace, size_t count) {
1029*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
1030*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
1031*6777b538SAndroid Build Coastguard Worker
1032*6777b538SAndroid Build Coastguard Worker #if defined(NO_UNWIND_TABLES) && BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
1033*6777b538SAndroid Build Coastguard Worker // If we do not have unwind tables, then try tracing using frame pointers.
1034*6777b538SAndroid Build Coastguard Worker return base::debug::TraceStackFramePointers(trace, count, 0);
1035*6777b538SAndroid Build Coastguard Worker #elif defined(HAVE_BACKTRACE)
1036*6777b538SAndroid Build Coastguard Worker // Though the backtrace API man page does not list any possible negative
1037*6777b538SAndroid Build Coastguard Worker // return values, we take no chance.
1038*6777b538SAndroid Build Coastguard Worker return base::saturated_cast<size_t>(
1039*6777b538SAndroid Build Coastguard Worker backtrace(const_cast<void**>(trace), base::saturated_cast<int>(count)));
1040*6777b538SAndroid Build Coastguard Worker #else
1041*6777b538SAndroid Build Coastguard Worker return 0;
1042*6777b538SAndroid Build Coastguard Worker #endif
1043*6777b538SAndroid Build Coastguard Worker }
1044*6777b538SAndroid Build Coastguard Worker
1045*6777b538SAndroid Build Coastguard Worker // static
PrintMessageWithPrefix(cstring_view prefix_string,cstring_view message)1046*6777b538SAndroid Build Coastguard Worker void StackTrace::PrintMessageWithPrefix(cstring_view prefix_string,
1047*6777b538SAndroid Build Coastguard Worker cstring_view message) {
1048*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
1049*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
1050*6777b538SAndroid Build Coastguard Worker if (!prefix_string.empty()) {
1051*6777b538SAndroid Build Coastguard Worker PrintToStderr(prefix_string.c_str());
1052*6777b538SAndroid Build Coastguard Worker }
1053*6777b538SAndroid Build Coastguard Worker PrintToStderr(message.c_str());
1054*6777b538SAndroid Build Coastguard Worker }
1055*6777b538SAndroid Build Coastguard Worker
PrintWithPrefixImpl(cstring_view prefix_string) const1056*6777b538SAndroid Build Coastguard Worker void StackTrace::PrintWithPrefixImpl(cstring_view prefix_string) const {
1057*6777b538SAndroid Build Coastguard Worker // NOTE: This code MUST be async-signal safe (it's used by in-process
1058*6777b538SAndroid Build Coastguard Worker // stack dumping signal handler). NO malloc or stdio is allowed here.
1059*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_BACKTRACE)
1060*6777b538SAndroid Build Coastguard Worker PrintBacktraceOutputHandler handler;
1061*6777b538SAndroid Build Coastguard Worker ProcessBacktrace(trace_, count_, prefix_string, &handler);
1062*6777b538SAndroid Build Coastguard Worker #endif
1063*6777b538SAndroid Build Coastguard Worker }
1064*6777b538SAndroid Build Coastguard Worker
1065*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_BACKTRACE)
OutputToStreamWithPrefixImpl(std::ostream * os,cstring_view prefix_string) const1066*6777b538SAndroid Build Coastguard Worker void StackTrace::OutputToStreamWithPrefixImpl(
1067*6777b538SAndroid Build Coastguard Worker std::ostream* os,
1068*6777b538SAndroid Build Coastguard Worker cstring_view prefix_string) const {
1069*6777b538SAndroid Build Coastguard Worker StreamBacktraceOutputHandler handler(os);
1070*6777b538SAndroid Build Coastguard Worker ProcessBacktrace(trace_, count_, prefix_string, &handler);
1071*6777b538SAndroid Build Coastguard Worker }
1072*6777b538SAndroid Build Coastguard Worker #endif
1073*6777b538SAndroid Build Coastguard Worker
1074*6777b538SAndroid Build Coastguard Worker namespace internal {
1075*6777b538SAndroid Build Coastguard Worker
1076*6777b538SAndroid Build Coastguard Worker // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
itoa_r(intptr_t i,char * buf,size_t sz,int base,size_t padding)1077*6777b538SAndroid Build Coastguard Worker char* itoa_r(intptr_t i, char* buf, size_t sz, int base, size_t padding) {
1078*6777b538SAndroid Build Coastguard Worker // Make sure we can write at least one NUL byte.
1079*6777b538SAndroid Build Coastguard Worker size_t n = 1;
1080*6777b538SAndroid Build Coastguard Worker if (n > sz)
1081*6777b538SAndroid Build Coastguard Worker return nullptr;
1082*6777b538SAndroid Build Coastguard Worker
1083*6777b538SAndroid Build Coastguard Worker if (base < 2 || base > 16) {
1084*6777b538SAndroid Build Coastguard Worker buf[0] = '\000';
1085*6777b538SAndroid Build Coastguard Worker return nullptr;
1086*6777b538SAndroid Build Coastguard Worker }
1087*6777b538SAndroid Build Coastguard Worker
1088*6777b538SAndroid Build Coastguard Worker char* start = buf;
1089*6777b538SAndroid Build Coastguard Worker
1090*6777b538SAndroid Build Coastguard Worker uintptr_t j = static_cast<uintptr_t>(i);
1091*6777b538SAndroid Build Coastguard Worker
1092*6777b538SAndroid Build Coastguard Worker // Handle negative numbers (only for base 10).
1093*6777b538SAndroid Build Coastguard Worker if (i < 0 && base == 10) {
1094*6777b538SAndroid Build Coastguard Worker // This does "j = -i" while avoiding integer overflow.
1095*6777b538SAndroid Build Coastguard Worker j = static_cast<uintptr_t>(-(i + 1)) + 1;
1096*6777b538SAndroid Build Coastguard Worker
1097*6777b538SAndroid Build Coastguard Worker // Make sure we can write the '-' character.
1098*6777b538SAndroid Build Coastguard Worker if (++n > sz) {
1099*6777b538SAndroid Build Coastguard Worker buf[0] = '\000';
1100*6777b538SAndroid Build Coastguard Worker return nullptr;
1101*6777b538SAndroid Build Coastguard Worker }
1102*6777b538SAndroid Build Coastguard Worker *start++ = '-';
1103*6777b538SAndroid Build Coastguard Worker }
1104*6777b538SAndroid Build Coastguard Worker
1105*6777b538SAndroid Build Coastguard Worker // Loop until we have converted the entire number. Output at least one
1106*6777b538SAndroid Build Coastguard Worker // character (i.e. '0').
1107*6777b538SAndroid Build Coastguard Worker char* ptr = start;
1108*6777b538SAndroid Build Coastguard Worker do {
1109*6777b538SAndroid Build Coastguard Worker // Make sure there is still enough space left in our output buffer.
1110*6777b538SAndroid Build Coastguard Worker if (++n > sz) {
1111*6777b538SAndroid Build Coastguard Worker buf[0] = '\000';
1112*6777b538SAndroid Build Coastguard Worker return nullptr;
1113*6777b538SAndroid Build Coastguard Worker }
1114*6777b538SAndroid Build Coastguard Worker
1115*6777b538SAndroid Build Coastguard Worker // Output the next digit.
1116*6777b538SAndroid Build Coastguard Worker *ptr++ = "0123456789abcdef"[j % static_cast<uintptr_t>(base)];
1117*6777b538SAndroid Build Coastguard Worker j /= static_cast<uintptr_t>(base);
1118*6777b538SAndroid Build Coastguard Worker
1119*6777b538SAndroid Build Coastguard Worker if (padding > 0)
1120*6777b538SAndroid Build Coastguard Worker padding--;
1121*6777b538SAndroid Build Coastguard Worker } while (j > 0 || padding > 0);
1122*6777b538SAndroid Build Coastguard Worker
1123*6777b538SAndroid Build Coastguard Worker // Terminate the output with a NUL character.
1124*6777b538SAndroid Build Coastguard Worker *ptr = '\000';
1125*6777b538SAndroid Build Coastguard Worker
1126*6777b538SAndroid Build Coastguard Worker // Conversion to ASCII actually resulted in the digits being in reverse
1127*6777b538SAndroid Build Coastguard Worker // order. We can't easily generate them in forward order, as we can't tell
1128*6777b538SAndroid Build Coastguard Worker // the number of characters needed until we are done converting.
1129*6777b538SAndroid Build Coastguard Worker // So, now, we reverse the string (except for the possible "-" sign).
1130*6777b538SAndroid Build Coastguard Worker while (--ptr > start) {
1131*6777b538SAndroid Build Coastguard Worker char ch = *ptr;
1132*6777b538SAndroid Build Coastguard Worker *ptr = *start;
1133*6777b538SAndroid Build Coastguard Worker *start++ = ch;
1134*6777b538SAndroid Build Coastguard Worker }
1135*6777b538SAndroid Build Coastguard Worker return buf;
1136*6777b538SAndroid Build Coastguard Worker }
1137*6777b538SAndroid Build Coastguard Worker
1138*6777b538SAndroid Build Coastguard Worker } // namespace internal
1139*6777b538SAndroid Build Coastguard Worker
1140*6777b538SAndroid Build Coastguard Worker } // namespace debug
1141*6777b538SAndroid Build Coastguard Worker } // namespace base
1142