[email protected] | 380d832 | 2012-02-28 21:35:44 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 2 | // 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> |
avi | ebe805c | 2015-12-24 08:20:28 | [diff] [blame] | 9 | #include <stddef.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 10 | #include <stdio.h> |
| 11 | #include <stdlib.h> |
[email protected] | 0c6f3b0c | 2011-04-15 06:15:04 | [diff] [blame] | 12 | #include <sys/param.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 13 | #include <sys/stat.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 14 | #include <sys/types.h> |
| 15 | #include <unistd.h> |
| 16 | |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 17 | #include <memory> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 18 | #include <vector> |
| 19 | |
Hans Wennborg | c3cffa6 | 2020-04-27 10:09:12 | [diff] [blame^] | 20 | #include "base/check_op.h" |
Sebastien Marchand | bd02bc29e | 2020-03-11 15:53:36 | [diff] [blame] | 21 | #include "base/clang_profiling_buildflags.h" |
Hans Wennborg | c3cffa6 | 2020-04-27 10:09:12 | [diff] [blame^] | 22 | #include "base/notreached.h" |
Avi Drissman | e3b70bf | 2019-01-04 19:50:22 | [diff] [blame] | 23 | #include "base/stl_util.h" |
Hans Wennborg | b3e433a | 2020-04-21 11:21:40 | [diff] [blame] | 24 | #include "base/strings/string_util.h" |
bjaideep | fbf0381 | 2016-10-14 23:02:12 | [diff] [blame] | 25 | #include "base/threading/platform_thread.h" |
| 26 | #include "base/time/time.h" |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 27 | #include "build/build_config.h" |
| 28 | |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 29 | #if defined(__GLIBCXX__) |
| 30 | #include <cxxabi.h> |
| 31 | #endif |
| 32 | |
| 33 | #if defined(OS_MACOSX) |
| 34 | #include <AvailabilityMacros.h> |
| 35 | #endif |
| 36 | |
[email protected] | e37e88a0 | 2011-11-15 00:06:16 | [diff] [blame] | 37 | #if defined(OS_MACOSX) || defined(OS_BSD) |
[email protected] | 94f8c95 | 2011-06-25 04:54:41 | [diff] [blame] | 38 | #include <sys/sysctl.h> |
| 39 | #endif |
| 40 | |
[email protected] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 41 | #if defined(OS_FREEBSD) |
| 42 | #include <sys/user.h> |
| 43 | #endif |
| 44 | |
Brett Wilson | b1de6ba | 2020-02-05 19:07:45 | [diff] [blame] | 45 | #if defined(OS_FUCHSIA) |
| 46 | #include <zircon/process.h> |
| 47 | #include <zircon/syscalls.h> |
| 48 | #endif |
| 49 | |
[email protected] | a5c0fd98 | 2011-09-01 20:19:53 | [diff] [blame] | 50 | #include <ostream> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 51 | |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 52 | #include "base/debug/alias.h" |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 53 | #include "base/debug/debugging_buildflags.h" |
| 54 | #include "base/environment.h" |
| 55 | #include "base/files/file_util.h" |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 56 | #include "base/logging.h" |
[email protected] | 2025d00 | 2012-11-14 20:54:35 | [diff] [blame] | 57 | #include "base/posix/eintr_wrapper.h" |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 58 | #include "base/process/process.h" |
| 59 | #include "base/strings/string_number_conversions.h" |
[email protected] | eb62f726 | 2013-03-30 14:29:00 | [diff] [blame] | 60 | #include "base/strings/string_piece.h" |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 61 | |
Sebastien Marchand | bd02bc29e | 2020-03-11 15:53:36 | [diff] [blame] | 62 | #if BUILDFLAG(CLANG_PROFILING) |
| 63 | #include "base/test/clang_profiling.h" |
Yannic Bonenberger | 6801e6c | 2019-06-07 10:42:53 | [diff] [blame] | 64 | #endif |
| 65 | |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 66 | #if defined(USE_SYMBOLIZE) |
| 67 | #include "base/third_party/symbolize/symbolize.h" |
| 68 | #endif |
| 69 | |
| 70 | namespace base { |
| 71 | namespace debug { |
| 72 | |
[email protected] | e37e88a0 | 2011-11-15 00:06:16 | [diff] [blame] | 73 | #if defined(OS_MACOSX) || defined(OS_BSD) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 74 | |
| 75 | // Based on Apple's recommended method as described in |
| 76 | // http://developer.apple.com/qa/qa2004/qa1361.html |
| 77 | bool BeingDebugged() { |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 78 | // 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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 86 | // 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] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 91 | if (is_set) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 92 | return being_debugged; |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 93 | |
| 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] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 101 | #if defined(OS_OPENBSD) |
| 102 | , sizeof(struct kinfo_proc), |
| 103 | 0 |
| 104 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 105 | }; |
| 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] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 112 | #if defined(OS_OPENBSD) |
Avi Drissman | e3b70bf | 2019-01-04 19:50:22 | [diff] [blame] | 113 | if (sysctl(mib, base::size(mib), NULL, &info_size, NULL, 0) < 0) |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 114 | return -1; |
| 115 | |
| 116 | mib[5] = (info_size / sizeof(struct kinfo_proc)); |
| 117 | #endif |
| 118 | |
Avi Drissman | e3b70bf | 2019-01-04 19:50:22 | [diff] [blame] | 119 | int sysctl_result = sysctl(mib, base::size(mib), &info, &info_size, NULL, 0); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 120 | 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] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 129 | #if defined(OS_FREEBSD) |
| 130 | being_debugged = (info.ki_flag & P_TRACED) != 0; |
| 131 | #elif defined(OS_BSD) |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 132 | being_debugged = (info.p_flag & P_TRACED) != 0; |
| 133 | #else |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 134 | being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 135 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 136 | return being_debugged; |
| 137 | } |
| 138 | |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 139 | void 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 155 | |
rayb | 0088ee5 | 2017-04-26 22:35:08 | [diff] [blame] | 156 | #elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 157 | |
| 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 163 | Process GetDebuggerProcess() { |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 164 | // 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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 167 | int status_fd = open("/proc/self/status", O_RDONLY); |
| 168 | if (status_fd == -1) |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 169 | return Process(); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 170 | |
| 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] | d89eec8 | 2013-12-03 14:10:59 | [diff] [blame] | 177 | if (IGNORE_EINTR(close(status_fd)) < 0) |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 178 | return Process(); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 179 | |
| 180 | if (num_read <= 0) |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 181 | return Process(); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 182 | |
| 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 188 | return Process(); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 189 | pid_index += tracer.size(); |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 190 | 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 | |
| 202 | bool BeingDebugged() { |
| 203 | return GetDebuggerProcess().IsValid(); |
| 204 | } |
| 205 | |
| 206 | void 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 Anderson | f06ac38 | 2019-04-10 03:49:38 | [diff] [blame] | 232 | "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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 235 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 236 | } |
| 237 | |
Scott Graham | a60f59b | 2017-06-05 19:00:30 | [diff] [blame] | 238 | #elif defined(OS_FUCHSIA) |
| 239 | |
| 240 | bool BeingDebugged() { |
Brett Wilson | b1de6ba | 2020-02-05 19:07:45 | [diff] [blame] | 241 | 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 Graham | a60f59b | 2017-06-05 19:00:30 | [diff] [blame] | 247 | } |
| 248 | |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 249 | void VerifyDebugger() {} |
| 250 | |
[email protected] | 94f8c95 | 2011-06-25 04:54:41 | [diff] [blame] | 251 | #else |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 252 | |
[email protected] | d028296 | 2011-01-01 16:08:52 | [diff] [blame] | 253 | bool BeingDebugged() { |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 254 | NOTIMPLEMENTED(); |
| 255 | return false; |
| 256 | } |
| 257 | |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 258 | void VerifyDebugger() {} |
| 259 | |
[email protected] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 260 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 261 | |
| 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] | c706ecf8 | 2013-10-28 16:39:22 | [diff] [blame] | 273 | // Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send |
| 274 | // SIGABRT |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 275 | // Mac: Always send SIGTRAP. |
| 276 | |
[email protected] | 70d3625 | 2014-02-06 02:51:01 | [diff] [blame] | 277 | #if defined(ARCH_CPU_ARMEL) |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 278 | #define DEBUG_BREAK_ASM() asm("bkpt 0") |
[email protected] | 70d3625 | 2014-02-06 02:51:01 | [diff] [blame] | 279 | #elif defined(ARCH_CPU_ARM64) |
| 280 | #define DEBUG_BREAK_ASM() asm("brk 0") |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 281 | #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] | 3132e35c | 2011-07-07 20:46:50 | [diff] [blame] | 287 | #if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 288 | #define DEBUG_BREAK() abort() |
[email protected] | 651d9c0 | 2010-12-01 07:36:54 | [diff] [blame] | 289 | #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] | c706ecf8 | 2013-10-28 16:39:22 | [diff] [blame] | 294 | #elif !defined(OS_MACOSX) |
[email protected] | 3132e35c | 2011-07-07 20:46:50 | [diff] [blame] | 295 | // Though Android has a "helpful" process called debuggerd to catch native |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 296 | // 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] | c706ecf8 | 2013-10-28 16:39:22 | [diff] [blame] | 303 | // |
| 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] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 307 | namespace { |
| 308 | void DebugBreak() { |
| 309 | if (!BeingDebugged()) { |
| 310 | abort(); |
| 311 | } else { |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 312 | #if defined(DEBUG_BREAK_ASM) |
| 313 | DEBUG_BREAK_ASM(); |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 314 | #else |
[email protected] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 315 | volatile int go = 0; |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 316 | while (!go) |
| 317 | PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 318 | #endif |
[email protected] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 319 | } |
| 320 | } |
| 321 | } // namespace |
| 322 | #define DEBUG_BREAK() DebugBreak() |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 323 | #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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 327 | #endif |
| 328 | |
| 329 | void BreakDebugger() { |
Sebastien Marchand | bd02bc29e | 2020-03-11 15:53:36 | [diff] [blame] | 330 | #if BUILDFLAG(CLANG_PROFILING) |
| 331 | WriteClangProfilingProfile(); |
Wez | d2031d30 | 2018-08-16 23:34:25 | [diff] [blame] | 332 | #endif |
| 333 | |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 334 | // 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 | |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 337 | // 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 341 | Alias(&static_variable_to_make_this_function_unique); |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 342 | |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 343 | DEBUG_BREAK(); |
[email protected] | b3e5844 | 2012-06-29 06:39:27 | [diff] [blame] | 344 | #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 Weber | d9d917c0 | 2020-03-20 11:10:20 | [diff] [blame] | 352 | // 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] | f355c56 | 2011-01-21 05:02:17 | [diff] [blame] | 357 | _exit(1); |
Nico Weber | d9d917c0 | 2020-03-20 11:10:20 | [diff] [blame] | 358 | #pragma GCC diagnostic pop |
[email protected] | f355c56 | 2011-01-21 05:02:17 | [diff] [blame] | 359 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | } // namespace debug |
| 363 | } // namespace base |