blob: 17ff94cccd7f2b1cbc307166bb82c69c6903fbad [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]58580352010-10-26 04:07:502// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakj51d26a42024-04-25 14:23:565
[email protected]58580352010-10-26 04:07:506#include "base/debug/debugger.h"
7
8#include <errno.h>
9#include <fcntl.h>
aviebe805c2015-12-24 08:20:2810#include <stddef.h>
[email protected]58580352010-10-26 04:07:5011#include <stdio.h>
12#include <stdlib.h>
[email protected]0c6f3b0c2011-04-15 06:15:0413#include <sys/param.h>
[email protected]58580352010-10-26 04:07:5014#include <sys/stat.h>
[email protected]58580352010-10-26 04:07:5015#include <sys/types.h>
16#include <unistd.h>
17
Kalvin Leec524a502025-04-15 19:46:2718#include <array>
dcheng093de9b2016-04-04 21:25:5119#include <memory>
Helmut Januschkae1fe1aa2024-03-13 02:21:2820#include <string_view>
[email protected]58580352010-10-26 04:07:5021
Hans Wennborgc3cffa62020-04-27 10:09:1222#include "base/check_op.h"
Peter Boström6e2fd082024-01-23 01:17:5523#include "base/notimplemented.h"
Hans Wennborgb3e433a2020-04-21 11:21:4024#include "base/strings/string_util.h"
bjaideepfbf03812016-10-14 23:02:1225#include "base/threading/platform_thread.h"
26#include "base/time/time.h"
dcheng093de9b2016-04-04 21:25:5127#include "build/build_config.h"
28
[email protected]58580352010-10-26 04:07:5029#if defined(__GLIBCXX__)
30#include <cxxabi.h>
31#endif
32
Xiaohan Wang131aa4d2022-01-15 19:39:4133#if BUILDFLAG(IS_APPLE)
[email protected]58580352010-10-26 04:07:5034#include <AvailabilityMacros.h>
35#endif
36
Xiaohan Wang131aa4d2022-01-15 19:39:4137#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD)
[email protected]94f8c952011-06-25 04:54:4138#include <sys/sysctl.h>
39#endif
40
Xiaohan Wang131aa4d2022-01-15 19:39:4141#if BUILDFLAG(IS_FREEBSD)
[email protected]af824362011-12-04 14:19:4142#include <sys/user.h>
43#endif
44
[email protected]a5c0fd982011-09-01 20:19:5345#include <ostream>
[email protected]58580352010-10-26 04:07:5046
Hans Wennborg7b533712020-06-22 20:52:2747#include "base/check.h"
hashimoto56a15912015-08-26 20:53:3448#include "base/debug/alias.h"
Tom Anderson5a1ce542019-03-08 20:19:2749#include "base/debug/debugging_buildflags.h"
50#include "base/environment.h"
51#include "base/files/file_util.h"
[email protected]2025d002012-11-14 20:54:3552#include "base/posix/eintr_wrapper.h"
Tom Anderson5a1ce542019-03-08 20:19:2753#include "base/process/process.h"
54#include "base/strings/string_number_conversions.h"
[email protected]58580352010-10-26 04:07:5055
56#if defined(USE_SYMBOLIZE)
Daniel Cheng780e01be2024-03-05 01:47:2757#include "base/third_party/symbolize/symbolize.h" // nogncheck
[email protected]58580352010-10-26 04:07:5058#endif
59
Peter Kasting811504a72025-01-09 03:18:5060namespace base::debug {
[email protected]58580352010-10-26 04:07:5061
Xiaohan Wang131aa4d2022-01-15 19:39:4162#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD)
[email protected]58580352010-10-26 04:07:5063
64// Based on Apple's recommended method as described in
65// http://developer.apple.com/qa/qa2004/qa1361.html
66bool BeingDebugged() {
[email protected]1e218b72012-11-14 19:32:2367 // NOTE: This code MUST be async-signal safe (it's used by in-process
68 // stack dumping signal handler). NO malloc or stdio is allowed here.
69 //
70 // While some code used below may be async-signal unsafe, note how
71 // the result is cached (see |is_set| and |being_debugged| static variables
72 // right below). If this code is properly warmed-up early
73 // in the start-up process, it should be safe to use later.
74
[email protected]58580352010-10-26 04:07:5075 // If the process is sandboxed then we can't use the sysctl, so cache the
76 // value.
77 static bool is_set = false;
78 static bool being_debugged = false;
79
Peter Kasting134ef9af2024-12-28 02:30:0980 if (is_set) {
[email protected]58580352010-10-26 04:07:5081 return being_debugged;
Peter Kasting134ef9af2024-12-28 02:30:0982 }
[email protected]58580352010-10-26 04:07:5083
84 // Initialize mib, which tells sysctl what info we want. In this case,
85 // we're looking for information about a specific process ID.
Peter Kasting134ef9af2024-12-28 02:30:0986 int mib[] = {CTL_KERN,
87 KERN_PROC,
88 KERN_PROC_PID,
89 getpid()
Xiaohan Wang131aa4d2022-01-15 19:39:4190#if BUILDFLAG(IS_OPENBSD)
Peter Kasting134ef9af2024-12-28 02:30:0991 ,
92 sizeof(struct kinfo_proc),
93 0
[email protected]88b49f72011-10-18 17:41:0794#endif
[email protected]58580352010-10-26 04:07:5095 };
96
97 // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
98 // binary interfaces may change.
99 struct kinfo_proc info;
100 size_t info_size = sizeof(info);
101
Xiaohan Wang131aa4d2022-01-15 19:39:41102#if BUILDFLAG(IS_OPENBSD)
Peter Kasting134ef9af2024-12-28 02:30:09103 if (sysctl(mib, std::size(mib), NULL, &info_size, NULL, 0) < 0) {
[email protected]88b49f72011-10-18 17:41:07104 return -1;
Peter Kasting134ef9af2024-12-28 02:30:09105 }
[email protected]88b49f72011-10-18 17:41:07106
107 mib[5] = (info_size / sizeof(struct kinfo_proc));
108#endif
109
Daniel Chengf45f47602022-02-28 22:38:32110 int sysctl_result = sysctl(mib, std::size(mib), &info, &info_size, NULL, 0);
[email protected]58580352010-10-26 04:07:50111 DCHECK_EQ(sysctl_result, 0);
112 if (sysctl_result != 0) {
113 is_set = true;
114 being_debugged = false;
115 return being_debugged;
116 }
117
118 // This process is being debugged if the P_TRACED flag is set.
119 is_set = true;
Xiaohan Wang131aa4d2022-01-15 19:39:41120#if BUILDFLAG(IS_FREEBSD)
[email protected]af824362011-12-04 14:19:41121 being_debugged = (info.ki_flag & P_TRACED) != 0;
Xiaohan Wang131aa4d2022-01-15 19:39:41122#elif BUILDFLAG(IS_BSD)
[email protected]88b49f72011-10-18 17:41:07123 being_debugged = (info.p_flag & P_TRACED) != 0;
124#else
[email protected]58580352010-10-26 04:07:50125 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
[email protected]88b49f72011-10-18 17:41:07126#endif
[email protected]58580352010-10-26 04:07:50127 return being_debugged;
128}
129
Erik Chen5c80c7a2019-08-29 22:48:15130void VerifyDebugger() {
131#if BUILDFLAG(ENABLE_LLDBINIT_WARNING)
Peter Kasting134ef9af2024-12-28 02:30:09132 if (Environment::Create()->HasVar("CHROMIUM_LLDBINIT_SOURCED")) {
Erik Chen5c80c7a2019-08-29 22:48:15133 return;
Peter Kasting134ef9af2024-12-28 02:30:09134 }
135 if (!BeingDebugged()) {
Erik Chen5c80c7a2019-08-29 22:48:15136 return;
Peter Kasting134ef9af2024-12-28 02:30:09137 }
Erik Chen5c80c7a2019-08-29 22:48:15138 DCHECK(false)
139 << "Detected lldb without sourcing //tools/lldb/lldbinit.py. lldb may "
140 "not be able to find debug symbols. Please see debug instructions for "
141 "using //tools/lldb/lldbinit.py:\n"
John Palmerd29fc4362021-05-20 03:29:22142 "https://chromium.googlesource.com/chromium/src/+/main/docs/"
Erik Chen5c80c7a2019-08-29 22:48:15143 "lldbinit.md\n"
144 "To continue anyway, type 'continue' in lldb. To always skip this "
145 "check, define an environment variable CHROMIUM_LLDBINIT_SOURCED=1";
146#endif
147}
Tom Anderson5a1ce542019-03-08 20:19:27148
Xiaohan Wang131aa4d2022-01-15 19:39:41149#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
150 BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX)
[email protected]58580352010-10-26 04:07:50151
152// We can look in /proc/self/status for TracerPid. We are likely used in crash
153// handling, so we are careful not to use the heap or have side effects.
154// Another option that is common is to try to ptrace yourself, but then we
155// can't detach without forking(), and that's not so great.
156// static
Tom Anderson5a1ce542019-03-08 20:19:27157Process GetDebuggerProcess() {
[email protected]1e218b72012-11-14 19:32:23158 // NOTE: This code MUST be async-signal safe (it's used by in-process
159 // stack dumping signal handler). NO malloc or stdio is allowed here.
160
[email protected]58580352010-10-26 04:07:50161 int status_fd = open("/proc/self/status", O_RDONLY);
Peter Kasting134ef9af2024-12-28 02:30:09162 if (status_fd == -1) {
Tom Anderson5a1ce542019-03-08 20:19:27163 return Process();
Peter Kasting134ef9af2024-12-28 02:30:09164 }
[email protected]58580352010-10-26 04:07:50165
166 // We assume our line will be in the first 1024 characters and that we can
167 // read this much all at once. In practice this will generally be true.
168 // This simplifies and speeds up things considerably.
Kalvin Leec524a502025-04-15 19:46:27169 std::array<char, 1024> buf;
[email protected]58580352010-10-26 04:07:50170
Kalvin Leec524a502025-04-15 19:46:27171 ssize_t num_read = HANDLE_EINTR(read(
172 status_fd, buf.data(), (buf.size() * sizeof(decltype(buf)::value_type))));
Peter Kasting134ef9af2024-12-28 02:30:09173 if (IGNORE_EINTR(close(status_fd)) < 0) {
Tom Anderson5a1ce542019-03-08 20:19:27174 return Process();
Peter Kasting134ef9af2024-12-28 02:30:09175 }
[email protected]58580352010-10-26 04:07:50176
Peter Kasting134ef9af2024-12-28 02:30:09177 if (num_read <= 0) {
Tom Anderson5a1ce542019-03-08 20:19:27178 return Process();
Peter Kasting134ef9af2024-12-28 02:30:09179 }
[email protected]58580352010-10-26 04:07:50180
Kalvin Leec524a502025-04-15 19:46:27181 std::string_view status(buf.data(), static_cast<size_t>(num_read));
Helmut Januschkae1fe1aa2024-03-13 02:21:28182 std::string_view tracer("TracerPid:\t");
[email protected]58580352010-10-26 04:07:50183
Helmut Januschka8800b6642024-07-16 04:05:51184 std::string_view::size_type pid_index = status.find(tracer);
185 if (pid_index == std::string_view::npos) {
Tom Anderson5a1ce542019-03-08 20:19:27186 return Process();
Helmut Januschka8800b6642024-07-16 04:05:51187 }
[email protected]58580352010-10-26 04:07:50188 pid_index += tracer.size();
Helmut Januschka8800b6642024-07-16 04:05:51189 std::string_view::size_type pid_end_index = status.find('\n', pid_index);
190 if (pid_end_index == std::string_view::npos) {
Tom Anderson5a1ce542019-03-08 20:19:27191 return Process();
Helmut Januschka8800b6642024-07-16 04:05:51192 }
Tom Anderson5a1ce542019-03-08 20:19:27193
Kalvin Leec524a502025-04-15 19:46:27194 std::string_view pid_str(base::span<char>(buf).subspan(pid_index).data(),
195 pid_end_index - pid_index);
Tom Anderson5a1ce542019-03-08 20:19:27196 int pid = 0;
Peter Kasting134ef9af2024-12-28 02:30:09197 if (!StringToInt(pid_str, &pid)) {
Tom Anderson5a1ce542019-03-08 20:19:27198 return Process();
Peter Kasting134ef9af2024-12-28 02:30:09199 }
Tom Anderson5a1ce542019-03-08 20:19:27200
201 return Process(pid);
202}
203
204bool BeingDebugged() {
205 return GetDebuggerProcess().IsValid();
206}
207
208void VerifyDebugger() {
209#if BUILDFLAG(ENABLE_GDBINIT_WARNING)
210 // Quick check before potentially slower GetDebuggerProcess().
Peter Kasting134ef9af2024-12-28 02:30:09211 if (Environment::Create()->HasVar("CHROMIUM_GDBINIT_SOURCED")) {
Tom Anderson5a1ce542019-03-08 20:19:27212 return;
Peter Kasting134ef9af2024-12-28 02:30:09213 }
Tom Anderson5a1ce542019-03-08 20:19:27214
215 Process proc = GetDebuggerProcess();
Peter Kasting134ef9af2024-12-28 02:30:09216 if (!proc.IsValid()) {
Tom Anderson5a1ce542019-03-08 20:19:27217 return;
Peter Kasting134ef9af2024-12-28 02:30:09218 }
Tom Anderson5a1ce542019-03-08 20:19:27219
220 FilePath cmdline_file =
221 FilePath("/proc").Append(NumberToString(proc.Handle())).Append("cmdline");
222 std::string cmdline;
Peter Kasting134ef9af2024-12-28 02:30:09223 if (!ReadFileToString(cmdline_file, &cmdline)) {
Tom Anderson5a1ce542019-03-08 20:19:27224 return;
Peter Kasting134ef9af2024-12-28 02:30:09225 }
Tom Anderson5a1ce542019-03-08 20:19:27226
227 // /proc/*/cmdline separates arguments with null bytes, but we only care about
228 // the executable name, so interpret |cmdline| as a null-terminated C string
229 // to extract the exe portion.
Helmut Januschkae1fe1aa2024-03-13 02:21:28230 std::string_view exe(cmdline.c_str());
Tom Anderson5a1ce542019-03-08 20:19:27231
232 DCHECK(ToLowerASCII(exe).find("gdb") == std::string::npos)
233 << "Detected gdb without sourcing //tools/gdb/gdbinit. gdb may not be "
234 "able to find debug symbols, and pretty-printing of STL types may not "
235 "work. Please see debug instructions for using //tools/gdb/gdbinit:\n"
John Palmerd29fc4362021-05-20 03:29:22236 "https://chromium.googlesource.com/chromium/src/+/main/docs/"
Tom Andersonf06ac382019-04-10 03:49:38237 "gdbinit.md\n"
238 "To continue anyway, type 'continue' in gdb. To always skip this "
239 "check, define an environment variable CHROMIUM_GDBINIT_SOURCED=1";
Tom Anderson5a1ce542019-03-08 20:19:27240#endif
[email protected]58580352010-10-26 04:07:50241}
242
[email protected]94f8c952011-06-25 04:54:41243#else
[email protected]58580352010-10-26 04:07:50244
[email protected]d0282962011-01-01 16:08:52245bool BeingDebugged() {
[email protected]58580352010-10-26 04:07:50246 NOTIMPLEMENTED();
247 return false;
248}
249
Tom Anderson5a1ce542019-03-08 20:19:27250void VerifyDebugger() {}
251
[email protected]af824362011-12-04 14:19:41252#endif
[email protected]58580352010-10-26 04:07:50253
254// We want to break into the debugger in Debug mode, and cause a crash dump in
255// Release mode. Breakpad behaves as follows:
256//
257// +-------+-----------------+-----------------+
258// | OS | Dump on SIGTRAP | Dump on SIGABRT |
259// +-------+-----------------+-----------------+
260// | Linux | N | Y |
261// | Mac | Y | N |
262// +-------+-----------------+-----------------+
263//
264// Thus we do the following:
[email protected]c706ecf82013-10-28 16:39:22265// Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send
266// SIGABRT
[email protected]58580352010-10-26 04:07:50267// Mac: Always send SIGTRAP.
268
[email protected]70d36252014-02-06 02:51:01269#if defined(ARCH_CPU_ARMEL)
[email protected]e35e1162013-10-29 19:45:32270#define DEBUG_BREAK_ASM() asm("bkpt 0")
[email protected]70d36252014-02-06 02:51:01271#elif defined(ARCH_CPU_ARM64)
272#define DEBUG_BREAK_ASM() asm("brk 0")
[email protected]e35e1162013-10-29 19:45:32273#elif defined(ARCH_CPU_MIPS_FAMILY)
274#define DEBUG_BREAK_ASM() asm("break 2")
275#elif defined(ARCH_CPU_X86_FAMILY)
276#define DEBUG_BREAK_ASM() asm("int3")
277#endif
278
Xiaohan Wang131aa4d2022-01-15 19:39:41279#if defined(NDEBUG) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
[email protected]58580352010-10-26 04:07:50280#define DEBUG_BREAK() abort()
Xiaohan Wang131aa4d2022-01-15 19:39:41281#elif !BUILDFLAG(IS_APPLE)
[email protected]3132e35c2011-07-07 20:46:50282// Though Android has a "helpful" process called debuggerd to catch native
[email protected]480a2a32013-04-23 07:37:03283// signals on the general assumption that they are fatal errors. If no debugger
284// is attached, we call abort since Breakpad needs SIGABRT to create a dump.
285// When debugger is attached, for ARM platform the bkpt instruction appears
286// to cause SIGBUS which is trapped by debuggerd, and we've had great
287// difficulty continuing in a debugger once we stop from SIG triggered by native
288// code, use GDB to set |go| to 1 to resume execution; for X86 platform, use
289// "int3" to setup breakpiont and raise SIGTRAP.
[email protected]c706ecf82013-10-28 16:39:22290//
291// On other POSIX architectures, except Mac OS X, we use the same logic to
292// ensure that breakpad creates a dump on crashes while it is still possible to
293// use a debugger.
[email protected]901a5e382013-04-08 23:26:25294namespace {
295void DebugBreak() {
296 if (!BeingDebugged()) {
297 abort();
298 } else {
[email protected]e35e1162013-10-29 19:45:32299#if defined(DEBUG_BREAK_ASM)
300 DEBUG_BREAK_ASM();
[email protected]480a2a32013-04-23 07:37:03301#else
[email protected]901a5e382013-04-08 23:26:25302 volatile int go = 0;
Peter Kasting134ef9af2024-12-28 02:30:09303 while (!go) {
Peter Kasting53fd6ee2021-10-05 20:40:48304 PlatformThread::Sleep(Milliseconds(100));
Peter Kasting134ef9af2024-12-28 02:30:09305 }
[email protected]480a2a32013-04-23 07:37:03306#endif
[email protected]901a5e382013-04-08 23:26:25307 }
308}
309} // namespace
310#define DEBUG_BREAK() DebugBreak()
[email protected]e35e1162013-10-29 19:45:32311#elif defined(DEBUG_BREAK_ASM)
312#define DEBUG_BREAK() DEBUG_BREAK_ASM()
313#else
314#error "Don't know how to debug break on this architecture/OS"
[email protected]58580352010-10-26 04:07:50315#endif
316
Benoit Lize33a16522021-09-13 20:15:14317void BreakDebuggerAsyncSafe() {
[email protected]1e218b72012-11-14 19:32:23318 // NOTE: This code MUST be async-signal safe (it's used by in-process
319 // stack dumping signal handler). NO malloc or stdio is allowed here.
320
hashimoto56a15912015-08-26 20:53:34321 // Linker's ICF feature may merge this function with other functions with the
322 // same definition (e.g. any function whose sole job is to call abort()) and
323 // it may confuse the crash report processing system. http://crbug.com/508489
324 static int static_variable_to_make_this_function_unique = 0;
Tom Anderson5a1ce542019-03-08 20:19:27325 Alias(&static_variable_to_make_this_function_unique);
hashimoto56a15912015-08-26 20:53:34326
[email protected]58580352010-10-26 04:07:50327 DEBUG_BREAK();
Xiaohan Wang131aa4d2022-01-15 19:39:41328#if BUILDFLAG(IS_ANDROID) && !defined(OFFICIAL_BUILD)
[email protected]b3e58442012-06-29 06:39:27329 // For Android development we always build release (debug builds are
330 // unmanageably large), so the unofficial build is used for debugging. It is
331 // helpful to be able to insert BreakDebugger() statements in the source,
332 // attach the debugger, inspect the state of the program and then resume it by
333 // setting the 'go' variable above.
334#elif defined(NDEBUG)
335 // Terminate the program after signaling the debug break.
Nico Weberd9d917c02020-03-20 11:10:20336 // When DEBUG_BREAK() expands to abort(), this is unreachable code. Rather
337 // than carefully tracking in which cases DEBUG_BREAK()s is noreturn, just
338 // disable the unreachable code warning here.
339#pragma GCC diagnostic push
340#pragma GCC diagnostic ignored "-Wunreachable-code"
[email protected]f355c562011-01-21 05:02:17341 _exit(1);
Nico Weberd9d917c02020-03-20 11:10:20342#pragma GCC diagnostic pop
[email protected]f355c562011-01-21 05:02:17343#endif
[email protected]58580352010-10-26 04:07:50344}
345
Peter Kasting811504a72025-01-09 03:18:50346} // namespace base::debug