Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
[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 | |
danakj | 51d26a4 | 2024-04-25 14:23:56 | [diff] [blame] | 5 | |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 6 | #include "base/debug/debugger.h" |
| 7 | |
| 8 | #include <errno.h> |
| 9 | #include <fcntl.h> |
avi | ebe805c | 2015-12-24 08:20:28 | [diff] [blame] | 10 | #include <stddef.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
[email protected] | 0c6f3b0c | 2011-04-15 06:15:04 | [diff] [blame] | 13 | #include <sys/param.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 14 | #include <sys/stat.h> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 15 | #include <sys/types.h> |
| 16 | #include <unistd.h> |
| 17 | |
Kalvin Lee | c524a50 | 2025-04-15 19:46:27 | [diff] [blame] | 18 | #include <array> |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 19 | #include <memory> |
Helmut Januschka | e1fe1aa | 2024-03-13 02:21:28 | [diff] [blame] | 20 | #include <string_view> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 21 | |
Hans Wennborg | c3cffa6 | 2020-04-27 10:09:12 | [diff] [blame] | 22 | #include "base/check_op.h" |
Peter Boström | 6e2fd08 | 2024-01-23 01:17:55 | [diff] [blame] | 23 | #include "base/notimplemented.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 | |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 33 | #if BUILDFLAG(IS_APPLE) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 34 | #include <AvailabilityMacros.h> |
| 35 | #endif |
| 36 | |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 37 | #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD) |
[email protected] | 94f8c95 | 2011-06-25 04:54:41 | [diff] [blame] | 38 | #include <sys/sysctl.h> |
| 39 | #endif |
| 40 | |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 41 | #if BUILDFLAG(IS_FREEBSD) |
[email protected] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 42 | #include <sys/user.h> |
| 43 | #endif |
| 44 | |
[email protected] | a5c0fd98 | 2011-09-01 20:19:53 | [diff] [blame] | 45 | #include <ostream> |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 46 | |
Hans Wennborg | 7b53371 | 2020-06-22 20:52:27 | [diff] [blame] | 47 | #include "base/check.h" |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 48 | #include "base/debug/alias.h" |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 49 | #include "base/debug/debugging_buildflags.h" |
| 50 | #include "base/environment.h" |
| 51 | #include "base/files/file_util.h" |
[email protected] | 2025d00 | 2012-11-14 20:54:35 | [diff] [blame] | 52 | #include "base/posix/eintr_wrapper.h" |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 53 | #include "base/process/process.h" |
| 54 | #include "base/strings/string_number_conversions.h" |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 55 | |
| 56 | #if defined(USE_SYMBOLIZE) |
Daniel Cheng | 780e01be | 2024-03-05 01:47:27 | [diff] [blame] | 57 | #include "base/third_party/symbolize/symbolize.h" // nogncheck |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 58 | #endif |
| 59 | |
Peter Kasting | 811504a7 | 2025-01-09 03:18:50 | [diff] [blame] | 60 | namespace base::debug { |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 61 | |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 62 | #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 63 | |
| 64 | // Based on Apple's recommended method as described in |
| 65 | // http://developer.apple.com/qa/qa2004/qa1361.html |
| 66 | bool BeingDebugged() { |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 67 | // 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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 75 | // 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 Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 80 | if (is_set) { |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 81 | return being_debugged; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 82 | } |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 83 | |
| 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 Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 86 | int mib[] = {CTL_KERN, |
| 87 | KERN_PROC, |
| 88 | KERN_PROC_PID, |
| 89 | getpid() |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 90 | #if BUILDFLAG(IS_OPENBSD) |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 91 | , |
| 92 | sizeof(struct kinfo_proc), |
| 93 | 0 |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 94 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 95 | }; |
| 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 Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 102 | #if BUILDFLAG(IS_OPENBSD) |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 103 | if (sysctl(mib, std::size(mib), NULL, &info_size, NULL, 0) < 0) { |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 104 | return -1; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 105 | } |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 106 | |
| 107 | mib[5] = (info_size / sizeof(struct kinfo_proc)); |
| 108 | #endif |
| 109 | |
Daniel Cheng | f45f4760 | 2022-02-28 22:38:32 | [diff] [blame] | 110 | int sysctl_result = sysctl(mib, std::size(mib), &info, &info_size, NULL, 0); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 111 | 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 Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 120 | #if BUILDFLAG(IS_FREEBSD) |
[email protected] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 121 | being_debugged = (info.ki_flag & P_TRACED) != 0; |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 122 | #elif BUILDFLAG(IS_BSD) |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 123 | being_debugged = (info.p_flag & P_TRACED) != 0; |
| 124 | #else |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 125 | being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; |
[email protected] | 88b49f7 | 2011-10-18 17:41:07 | [diff] [blame] | 126 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 127 | return being_debugged; |
| 128 | } |
| 129 | |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 130 | void VerifyDebugger() { |
| 131 | #if BUILDFLAG(ENABLE_LLDBINIT_WARNING) |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 132 | if (Environment::Create()->HasVar("CHROMIUM_LLDBINIT_SOURCED")) { |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 133 | return; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 134 | } |
| 135 | if (!BeingDebugged()) { |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 136 | return; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 137 | } |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 138 | 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 Palmer | d29fc436 | 2021-05-20 03:29:22 | [diff] [blame] | 142 | "https://chromium.googlesource.com/chromium/src/+/main/docs/" |
Erik Chen | 5c80c7a | 2019-08-29 22:48:15 | [diff] [blame] | 143 | "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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 148 | |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 149 | #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ |
| 150 | BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 151 | |
| 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 157 | Process GetDebuggerProcess() { |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 158 | // 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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 161 | int status_fd = open("/proc/self/status", O_RDONLY); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 162 | if (status_fd == -1) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 163 | return Process(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 164 | } |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 165 | |
| 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 Lee | c524a50 | 2025-04-15 19:46:27 | [diff] [blame] | 169 | std::array<char, 1024> buf; |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 170 | |
Kalvin Lee | c524a50 | 2025-04-15 19:46:27 | [diff] [blame] | 171 | ssize_t num_read = HANDLE_EINTR(read( |
| 172 | status_fd, buf.data(), (buf.size() * sizeof(decltype(buf)::value_type)))); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 173 | if (IGNORE_EINTR(close(status_fd)) < 0) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 174 | return Process(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 175 | } |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 176 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 177 | if (num_read <= 0) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 178 | return Process(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 179 | } |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 180 | |
Kalvin Lee | c524a50 | 2025-04-15 19:46:27 | [diff] [blame] | 181 | std::string_view status(buf.data(), static_cast<size_t>(num_read)); |
Helmut Januschka | e1fe1aa | 2024-03-13 02:21:28 | [diff] [blame] | 182 | std::string_view tracer("TracerPid:\t"); |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 183 | |
Helmut Januschka | 8800b664 | 2024-07-16 04:05:51 | [diff] [blame] | 184 | std::string_view::size_type pid_index = status.find(tracer); |
| 185 | if (pid_index == std::string_view::npos) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 186 | return Process(); |
Helmut Januschka | 8800b664 | 2024-07-16 04:05:51 | [diff] [blame] | 187 | } |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 188 | pid_index += tracer.size(); |
Helmut Januschka | 8800b664 | 2024-07-16 04:05:51 | [diff] [blame] | 189 | std::string_view::size_type pid_end_index = status.find('\n', pid_index); |
| 190 | if (pid_end_index == std::string_view::npos) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 191 | return Process(); |
Helmut Januschka | 8800b664 | 2024-07-16 04:05:51 | [diff] [blame] | 192 | } |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 193 | |
Kalvin Lee | c524a50 | 2025-04-15 19:46:27 | [diff] [blame] | 194 | std::string_view pid_str(base::span<char>(buf).subspan(pid_index).data(), |
| 195 | pid_end_index - pid_index); |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 196 | int pid = 0; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 197 | if (!StringToInt(pid_str, &pid)) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 198 | return Process(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 199 | } |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 200 | |
| 201 | return Process(pid); |
| 202 | } |
| 203 | |
| 204 | bool BeingDebugged() { |
| 205 | return GetDebuggerProcess().IsValid(); |
| 206 | } |
| 207 | |
| 208 | void VerifyDebugger() { |
| 209 | #if BUILDFLAG(ENABLE_GDBINIT_WARNING) |
| 210 | // Quick check before potentially slower GetDebuggerProcess(). |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 211 | if (Environment::Create()->HasVar("CHROMIUM_GDBINIT_SOURCED")) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 212 | return; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 213 | } |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 214 | |
| 215 | Process proc = GetDebuggerProcess(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 216 | if (!proc.IsValid()) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 217 | return; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 218 | } |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 219 | |
| 220 | FilePath cmdline_file = |
| 221 | FilePath("/proc").Append(NumberToString(proc.Handle())).Append("cmdline"); |
| 222 | std::string cmdline; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 223 | if (!ReadFileToString(cmdline_file, &cmdline)) { |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 224 | return; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 225 | } |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 226 | |
| 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 Januschka | e1fe1aa | 2024-03-13 02:21:28 | [diff] [blame] | 230 | std::string_view exe(cmdline.c_str()); |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 231 | |
| 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 Palmer | d29fc436 | 2021-05-20 03:29:22 | [diff] [blame] | 236 | "https://chromium.googlesource.com/chromium/src/+/main/docs/" |
Tom Anderson | f06ac38 | 2019-04-10 03:49:38 | [diff] [blame] | 237 | "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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 240 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 241 | } |
| 242 | |
[email protected] | 94f8c95 | 2011-06-25 04:54:41 | [diff] [blame] | 243 | #else |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 244 | |
[email protected] | d028296 | 2011-01-01 16:08:52 | [diff] [blame] | 245 | bool BeingDebugged() { |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 246 | NOTIMPLEMENTED(); |
| 247 | return false; |
| 248 | } |
| 249 | |
Tom Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 250 | void VerifyDebugger() {} |
| 251 | |
[email protected] | af82436 | 2011-12-04 14:19:41 | [diff] [blame] | 252 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 253 | |
| 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] | c706ecf8 | 2013-10-28 16:39:22 | [diff] [blame] | 265 | // Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send |
| 266 | // SIGABRT |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 267 | // Mac: Always send SIGTRAP. |
| 268 | |
[email protected] | 70d3625 | 2014-02-06 02:51:01 | [diff] [blame] | 269 | #if defined(ARCH_CPU_ARMEL) |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 270 | #define DEBUG_BREAK_ASM() asm("bkpt 0") |
[email protected] | 70d3625 | 2014-02-06 02:51:01 | [diff] [blame] | 271 | #elif defined(ARCH_CPU_ARM64) |
| 272 | #define DEBUG_BREAK_ASM() asm("brk 0") |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 273 | #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 Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 279 | #if defined(NDEBUG) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID) |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 280 | #define DEBUG_BREAK() abort() |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 281 | #elif !BUILDFLAG(IS_APPLE) |
[email protected] | 3132e35c | 2011-07-07 20:46:50 | [diff] [blame] | 282 | // Though Android has a "helpful" process called debuggerd to catch native |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 283 | // 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] | c706ecf8 | 2013-10-28 16:39:22 | [diff] [blame] | 290 | // |
| 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] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 294 | namespace { |
| 295 | void DebugBreak() { |
| 296 | if (!BeingDebugged()) { |
| 297 | abort(); |
| 298 | } else { |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 299 | #if defined(DEBUG_BREAK_ASM) |
| 300 | DEBUG_BREAK_ASM(); |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 301 | #else |
[email protected] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 302 | volatile int go = 0; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 303 | while (!go) { |
Peter Kasting | 53fd6ee | 2021-10-05 20:40:48 | [diff] [blame] | 304 | PlatformThread::Sleep(Milliseconds(100)); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 305 | } |
[email protected] | 480a2a3 | 2013-04-23 07:37:03 | [diff] [blame] | 306 | #endif |
[email protected] | 901a5e38 | 2013-04-08 23:26:25 | [diff] [blame] | 307 | } |
| 308 | } |
| 309 | } // namespace |
| 310 | #define DEBUG_BREAK() DebugBreak() |
[email protected] | e35e116 | 2013-10-29 19:45:32 | [diff] [blame] | 311 | #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] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 315 | #endif |
| 316 | |
Benoit Lize | 33a1652 | 2021-09-13 20:15:14 | [diff] [blame] | 317 | void BreakDebuggerAsyncSafe() { |
[email protected] | 1e218b7 | 2012-11-14 19:32:23 | [diff] [blame] | 318 | // 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 | |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 321 | // 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 Anderson | 5a1ce54 | 2019-03-08 20:19:27 | [diff] [blame] | 325 | Alias(&static_variable_to_make_this_function_unique); |
hashimoto | 56a1591 | 2015-08-26 20:53:34 | [diff] [blame] | 326 | |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 327 | DEBUG_BREAK(); |
Xiaohan Wang | 131aa4d | 2022-01-15 19:39:41 | [diff] [blame] | 328 | #if BUILDFLAG(IS_ANDROID) && !defined(OFFICIAL_BUILD) |
[email protected] | b3e5844 | 2012-06-29 06:39:27 | [diff] [blame] | 329 | // 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 Weber | d9d917c0 | 2020-03-20 11:10:20 | [diff] [blame] | 336 | // 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] | f355c56 | 2011-01-21 05:02:17 | [diff] [blame] | 341 | _exit(1); |
Nico Weber | d9d917c0 | 2020-03-20 11:10:20 | [diff] [blame] | 342 | #pragma GCC diagnostic pop |
[email protected] | f355c56 | 2011-01-21 05:02:17 | [diff] [blame] | 343 | #endif |
[email protected] | 5858035 | 2010-10-26 04:07:50 | [diff] [blame] | 344 | } |
| 345 | |
Peter Kasting | 811504a7 | 2025-01-09 03:18:50 | [diff] [blame] | 346 | } // namespace base::debug |