blob: de383b80821438abd9baf7eb78ca18dc8858e131 [file] [log] [blame]
[email protected]380d8322012-02-28 21:35:441// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[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
5#include "base/debug/debugger.h"
6
7#include <errno.h>
8#include <fcntl.h>
aviebe805c2015-12-24 08:20:289#include <stddef.h>
[email protected]58580352010-10-26 04:07:5010#include <stdio.h>
11#include <stdlib.h>
[email protected]0c6f3b0c2011-04-15 06:15:0412#include <sys/param.h>
[email protected]58580352010-10-26 04:07:5013#include <sys/stat.h>
[email protected]58580352010-10-26 04:07:5014#include <sys/types.h>
15#include <unistd.h>
16
dcheng093de9b2016-04-04 21:25:5117#include <memory>
[email protected]58580352010-10-26 04:07:5018#include <vector>
19
Hans Wennborgc3cffa62020-04-27 10:09:1220#include "base/check_op.h"
Sebastien Marchandbd02bc29e2020-03-11 15:53:3621#include "base/clang_profiling_buildflags.h"
Hans Wennborgc3cffa62020-04-27 10:09:1222#include "base/notreached.h"
Avi Drissmane3b70bf2019-01-04 19:50:2223#include "base/stl_util.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
33#if defined(OS_MACOSX)
34#include <AvailabilityMacros.h>
35#endif
36
[email protected]e37e88a02011-11-15 00:06:1637#if defined(OS_MACOSX) || defined(OS_BSD)
[email protected]94f8c952011-06-25 04:54:4138#include <sys/sysctl.h>
39#endif
40
[email protected]af824362011-12-04 14:19:4141#if defined(OS_FREEBSD)
42#include <sys/user.h>
43#endif
44
Brett Wilsonb1de6ba2020-02-05 19:07:4545#if defined(OS_FUCHSIA)
46#include <zircon/process.h>
47#include <zircon/syscalls.h>
48#endif
49
[email protected]a5c0fd982011-09-01 20:19:5350#include <ostream>
[email protected]58580352010-10-26 04:07:5051
hashimoto56a15912015-08-26 20:53:3452#include "base/debug/alias.h"
Tom Anderson5a1ce542019-03-08 20:19:2753#include "base/debug/debugging_buildflags.h"
54#include "base/environment.h"
55#include "base/files/file_util.h"
[email protected]58580352010-10-26 04:07:5056#include "base/logging.h"
[email protected]2025d002012-11-14 20:54:3557#include "base/posix/eintr_wrapper.h"
Tom Anderson5a1ce542019-03-08 20:19:2758#include "base/process/process.h"
59#include "base/strings/string_number_conversions.h"
[email protected]eb62f7262013-03-30 14:29:0060#include "base/strings/string_piece.h"
[email protected]58580352010-10-26 04:07:5061
Sebastien Marchandbd02bc29e2020-03-11 15:53:3662#if BUILDFLAG(CLANG_PROFILING)
63#include "base/test/clang_profiling.h"
Yannic Bonenberger6801e6c2019-06-07 10:42:5364#endif
65
[email protected]58580352010-10-26 04:07:5066#if defined(USE_SYMBOLIZE)
67#include "base/third_party/symbolize/symbolize.h"
68#endif
69
70namespace base {
71namespace debug {
72
[email protected]e37e88a02011-11-15 00:06:1673#if defined(OS_MACOSX) || defined(OS_BSD)
[email protected]58580352010-10-26 04:07:5074
75// Based on Apple's recommended method as described in
76// http://developer.apple.com/qa/qa2004/qa1361.html
77bool BeingDebugged() {
[email protected]1e218b72012-11-14 19:32:2378 // NOTE: This code MUST be async-signal safe (it's used by in-process
79 // stack dumping signal handler). NO malloc or stdio is allowed here.
80 //
81 // While some code used below may be async-signal unsafe, note how
82 // the result is cached (see |is_set| and |being_debugged| static variables
83 // right below). If this code is properly warmed-up early
84 // in the start-up process, it should be safe to use later.
85
[email protected]58580352010-10-26 04:07:5086 // If the process is sandboxed then we can't use the sysctl, so cache the
87 // value.
88 static bool is_set = false;
89 static bool being_debugged = false;
90
[email protected]1e218b72012-11-14 19:32:2391 if (is_set)
[email protected]58580352010-10-26 04:07:5092 return being_debugged;
[email protected]58580352010-10-26 04:07:5093
94 // Initialize mib, which tells sysctl what info we want. In this case,
95 // we're looking for information about a specific process ID.
96 int mib[] = {
97 CTL_KERN,
98 KERN_PROC,
99 KERN_PROC_PID,
100 getpid()
[email protected]88b49f72011-10-18 17:41:07101#if defined(OS_OPENBSD)
102 , sizeof(struct kinfo_proc),
103 0
104#endif
[email protected]58580352010-10-26 04:07:50105 };
106
107 // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
108 // binary interfaces may change.
109 struct kinfo_proc info;
110 size_t info_size = sizeof(info);
111
[email protected]88b49f72011-10-18 17:41:07112#if defined(OS_OPENBSD)
Avi Drissmane3b70bf2019-01-04 19:50:22113 if (sysctl(mib, base::size(mib), NULL, &info_size, NULL, 0) < 0)
[email protected]88b49f72011-10-18 17:41:07114 return -1;
115
116 mib[5] = (info_size / sizeof(struct kinfo_proc));
117#endif
118
Avi Drissmane3b70bf2019-01-04 19:50:22119 int sysctl_result = sysctl(mib, base::size(mib), &info, &info_size, NULL, 0);
[email protected]58580352010-10-26 04:07:50120 DCHECK_EQ(sysctl_result, 0);
121 if (sysctl_result != 0) {
122 is_set = true;
123 being_debugged = false;
124 return being_debugged;
125 }
126
127 // This process is being debugged if the P_TRACED flag is set.
128 is_set = true;
[email protected]af824362011-12-04 14:19:41129#if defined(OS_FREEBSD)
130 being_debugged = (info.ki_flag & P_TRACED) != 0;
131#elif defined(OS_BSD)
[email protected]88b49f72011-10-18 17:41:07132 being_debugged = (info.p_flag & P_TRACED) != 0;
133#else
[email protected]58580352010-10-26 04:07:50134 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
[email protected]88b49f72011-10-18 17:41:07135#endif
[email protected]58580352010-10-26 04:07:50136 return being_debugged;
137}
138
Erik Chen5c80c7a2019-08-29 22:48:15139void VerifyDebugger() {
140#if BUILDFLAG(ENABLE_LLDBINIT_WARNING)
141 if (Environment::Create()->HasVar("CHROMIUM_LLDBINIT_SOURCED"))
142 return;
143 if (!BeingDebugged())
144 return;
145 DCHECK(false)
146 << "Detected lldb without sourcing //tools/lldb/lldbinit.py. lldb may "
147 "not be able to find debug symbols. Please see debug instructions for "
148 "using //tools/lldb/lldbinit.py:\n"
149 "https://chromium.googlesource.com/chromium/src/+/master/docs/"
150 "lldbinit.md\n"
151 "To continue anyway, type 'continue' in lldb. To always skip this "
152 "check, define an environment variable CHROMIUM_LLDBINIT_SOURCED=1";
153#endif
154}
Tom Anderson5a1ce542019-03-08 20:19:27155
rayb0088ee52017-04-26 22:35:08156#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX)
[email protected]58580352010-10-26 04:07:50157
158// We can look in /proc/self/status for TracerPid. We are likely used in crash
159// handling, so we are careful not to use the heap or have side effects.
160// Another option that is common is to try to ptrace yourself, but then we
161// can't detach without forking(), and that's not so great.
162// static
Tom Anderson5a1ce542019-03-08 20:19:27163Process GetDebuggerProcess() {
[email protected]1e218b72012-11-14 19:32:23164 // NOTE: This code MUST be async-signal safe (it's used by in-process
165 // stack dumping signal handler). NO malloc or stdio is allowed here.
166
[email protected]58580352010-10-26 04:07:50167 int status_fd = open("/proc/self/status", O_RDONLY);
168 if (status_fd == -1)
Tom Anderson5a1ce542019-03-08 20:19:27169 return Process();
[email protected]58580352010-10-26 04:07:50170
171 // We assume our line will be in the first 1024 characters and that we can
172 // read this much all at once. In practice this will generally be true.
173 // This simplifies and speeds up things considerably.
174 char buf[1024];
175
176 ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
[email protected]d89eec82013-12-03 14:10:59177 if (IGNORE_EINTR(close(status_fd)) < 0)
Tom Anderson5a1ce542019-03-08 20:19:27178 return Process();
[email protected]58580352010-10-26 04:07:50179
180 if (num_read <= 0)
Tom Anderson5a1ce542019-03-08 20:19:27181 return Process();
[email protected]58580352010-10-26 04:07:50182
183 StringPiece status(buf, num_read);
184 StringPiece tracer("TracerPid:\t");
185
186 StringPiece::size_type pid_index = status.find(tracer);
187 if (pid_index == StringPiece::npos)
Tom Anderson5a1ce542019-03-08 20:19:27188 return Process();
[email protected]58580352010-10-26 04:07:50189 pid_index += tracer.size();
Tom Anderson5a1ce542019-03-08 20:19:27190 StringPiece::size_type pid_end_index = status.find('\n', pid_index);
191 if (pid_end_index == StringPiece::npos)
192 return Process();
193
194 StringPiece pid_str(buf + pid_index, pid_end_index - pid_index);
195 int pid = 0;
196 if (!StringToInt(pid_str, &pid))
197 return Process();
198
199 return Process(pid);
200}
201
202bool BeingDebugged() {
203 return GetDebuggerProcess().IsValid();
204}
205
206void VerifyDebugger() {
207#if BUILDFLAG(ENABLE_GDBINIT_WARNING)
208 // Quick check before potentially slower GetDebuggerProcess().
209 if (Environment::Create()->HasVar("CHROMIUM_GDBINIT_SOURCED"))
210 return;
211
212 Process proc = GetDebuggerProcess();
213 if (!proc.IsValid())
214 return;
215
216 FilePath cmdline_file =
217 FilePath("/proc").Append(NumberToString(proc.Handle())).Append("cmdline");
218 std::string cmdline;
219 if (!ReadFileToString(cmdline_file, &cmdline))
220 return;
221
222 // /proc/*/cmdline separates arguments with null bytes, but we only care about
223 // the executable name, so interpret |cmdline| as a null-terminated C string
224 // to extract the exe portion.
225 StringPiece exe(cmdline.c_str());
226
227 DCHECK(ToLowerASCII(exe).find("gdb") == std::string::npos)
228 << "Detected gdb without sourcing //tools/gdb/gdbinit. gdb may not be "
229 "able to find debug symbols, and pretty-printing of STL types may not "
230 "work. Please see debug instructions for using //tools/gdb/gdbinit:\n"
231 "https://chromium.googlesource.com/chromium/src/+/master/docs/"
Tom Andersonf06ac382019-04-10 03:49:38232 "gdbinit.md\n"
233 "To continue anyway, type 'continue' in gdb. To always skip this "
234 "check, define an environment variable CHROMIUM_GDBINIT_SOURCED=1";
Tom Anderson5a1ce542019-03-08 20:19:27235#endif
[email protected]58580352010-10-26 04:07:50236}
237
Scott Grahama60f59b2017-06-05 19:00:30238#elif defined(OS_FUCHSIA)
239
240bool BeingDebugged() {
Brett Wilsonb1de6ba2020-02-05 19:07:45241 zx_info_process_t info = {};
242 // Ignore failures. The 0-initialization above will result in "false" for
243 // error cases.
244 zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS, &info, sizeof(info),
245 nullptr, nullptr);
246 return info.debugger_attached;
Scott Grahama60f59b2017-06-05 19:00:30247}
248
Tom Anderson5a1ce542019-03-08 20:19:27249void VerifyDebugger() {}
250
[email protected]94f8c952011-06-25 04:54:41251#else
[email protected]58580352010-10-26 04:07:50252
[email protected]d0282962011-01-01 16:08:52253bool BeingDebugged() {
[email protected]58580352010-10-26 04:07:50254 NOTIMPLEMENTED();
255 return false;
256}
257
Tom Anderson5a1ce542019-03-08 20:19:27258void VerifyDebugger() {}
259
[email protected]af824362011-12-04 14:19:41260#endif
[email protected]58580352010-10-26 04:07:50261
262// We want to break into the debugger in Debug mode, and cause a crash dump in
263// Release mode. Breakpad behaves as follows:
264//
265// +-------+-----------------+-----------------+
266// | OS | Dump on SIGTRAP | Dump on SIGABRT |
267// +-------+-----------------+-----------------+
268// | Linux | N | Y |
269// | Mac | Y | N |
270// +-------+-----------------+-----------------+
271//
272// Thus we do the following:
[email protected]c706ecf82013-10-28 16:39:22273// Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send
274// SIGABRT
[email protected]58580352010-10-26 04:07:50275// Mac: Always send SIGTRAP.
276
[email protected]70d36252014-02-06 02:51:01277#if defined(ARCH_CPU_ARMEL)
[email protected]e35e1162013-10-29 19:45:32278#define DEBUG_BREAK_ASM() asm("bkpt 0")
[email protected]70d36252014-02-06 02:51:01279#elif defined(ARCH_CPU_ARM64)
280#define DEBUG_BREAK_ASM() asm("brk 0")
[email protected]e35e1162013-10-29 19:45:32281#elif defined(ARCH_CPU_MIPS_FAMILY)
282#define DEBUG_BREAK_ASM() asm("break 2")
283#elif defined(ARCH_CPU_X86_FAMILY)
284#define DEBUG_BREAK_ASM() asm("int3")
285#endif
286
[email protected]3132e35c2011-07-07 20:46:50287#if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]58580352010-10-26 04:07:50288#define DEBUG_BREAK() abort()
[email protected]651d9c02010-12-01 07:36:54289#elif defined(OS_NACL)
290// The NaCl verifier doesn't let use use int3. For now, we call abort(). We
291// should ask for advice from some NaCl experts about the optimum thing here.
292// http://code.google.com/p/nativeclient/issues/detail?id=645
293#define DEBUG_BREAK() abort()
[email protected]c706ecf82013-10-28 16:39:22294#elif !defined(OS_MACOSX)
[email protected]3132e35c2011-07-07 20:46:50295// Though Android has a "helpful" process called debuggerd to catch native
[email protected]480a2a32013-04-23 07:37:03296// signals on the general assumption that they are fatal errors. If no debugger
297// is attached, we call abort since Breakpad needs SIGABRT to create a dump.
298// When debugger is attached, for ARM platform the bkpt instruction appears
299// to cause SIGBUS which is trapped by debuggerd, and we've had great
300// difficulty continuing in a debugger once we stop from SIG triggered by native
301// code, use GDB to set |go| to 1 to resume execution; for X86 platform, use
302// "int3" to setup breakpiont and raise SIGTRAP.
[email protected]c706ecf82013-10-28 16:39:22303//
304// On other POSIX architectures, except Mac OS X, we use the same logic to
305// ensure that breakpad creates a dump on crashes while it is still possible to
306// use a debugger.
[email protected]901a5e382013-04-08 23:26:25307namespace {
308void DebugBreak() {
309 if (!BeingDebugged()) {
310 abort();
311 } else {
[email protected]e35e1162013-10-29 19:45:32312#if defined(DEBUG_BREAK_ASM)
313 DEBUG_BREAK_ASM();
[email protected]480a2a32013-04-23 07:37:03314#else
[email protected]901a5e382013-04-08 23:26:25315 volatile int go = 0;
Tom Anderson5a1ce542019-03-08 20:19:27316 while (!go)
317 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
[email protected]480a2a32013-04-23 07:37:03318#endif
[email protected]901a5e382013-04-08 23:26:25319 }
320}
321} // namespace
322#define DEBUG_BREAK() DebugBreak()
[email protected]e35e1162013-10-29 19:45:32323#elif defined(DEBUG_BREAK_ASM)
324#define DEBUG_BREAK() DEBUG_BREAK_ASM()
325#else
326#error "Don't know how to debug break on this architecture/OS"
[email protected]58580352010-10-26 04:07:50327#endif
328
329void BreakDebugger() {
Sebastien Marchandbd02bc29e2020-03-11 15:53:36330#if BUILDFLAG(CLANG_PROFILING)
331 WriteClangProfilingProfile();
Wezd2031d302018-08-16 23:34:25332#endif
333
[email protected]1e218b72012-11-14 19:32:23334 // NOTE: This code MUST be async-signal safe (it's used by in-process
335 // stack dumping signal handler). NO malloc or stdio is allowed here.
336
hashimoto56a15912015-08-26 20:53:34337 // Linker's ICF feature may merge this function with other functions with the
338 // same definition (e.g. any function whose sole job is to call abort()) and
339 // it may confuse the crash report processing system. http://crbug.com/508489
340 static int static_variable_to_make_this_function_unique = 0;
Tom Anderson5a1ce542019-03-08 20:19:27341 Alias(&static_variable_to_make_this_function_unique);
hashimoto56a15912015-08-26 20:53:34342
[email protected]58580352010-10-26 04:07:50343 DEBUG_BREAK();
[email protected]b3e58442012-06-29 06:39:27344#if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD)
345 // For Android development we always build release (debug builds are
346 // unmanageably large), so the unofficial build is used for debugging. It is
347 // helpful to be able to insert BreakDebugger() statements in the source,
348 // attach the debugger, inspect the state of the program and then resume it by
349 // setting the 'go' variable above.
350#elif defined(NDEBUG)
351 // Terminate the program after signaling the debug break.
Nico Weberd9d917c02020-03-20 11:10:20352 // When DEBUG_BREAK() expands to abort(), this is unreachable code. Rather
353 // than carefully tracking in which cases DEBUG_BREAK()s is noreturn, just
354 // disable the unreachable code warning here.
355#pragma GCC diagnostic push
356#pragma GCC diagnostic ignored "-Wunreachable-code"
[email protected]f355c562011-01-21 05:02:17357 _exit(1);
Nico Weberd9d917c02020-03-20 11:10:20358#pragma GCC diagnostic pop
[email protected]f355c562011-01-21 05:02:17359#endif
[email protected]58580352010-10-26 04:07:50360}
361
362} // namespace debug
363} // namespace base