| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 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 #include "build/build_config.h" | |
| 7 | |
| 8 #include <errno.h> | |
| 9 #include <fcntl.h> | |
| 10 #include <stdio.h> | |
| 11 #include <stdlib.h> | |
| 12 #include <sys/param.h> | |
| 13 #include <sys/stat.h> | |
| 14 #include <sys/types.h> | |
| 15 #include <unistd.h> | |
| 16 | |
| 17 #include <vector> | |
| 18 | |
| 19 #if defined(__GLIBCXX__) | |
| 20 #include <cxxabi.h> | |
| 21 #endif | |
| 22 | |
| 23 #if defined(OS_MACOSX) | |
| 24 #include <AvailabilityMacros.h> | |
| 25 #endif | |
| 26 | |
| 27 #if defined(OS_MACOSX) || defined(OS_BSD) | |
| 28 #include <sys/sysctl.h> | |
| 29 #endif | |
| 30 | |
| 31 #if defined(OS_FREEBSD) | |
| 32 #include <sys/user.h> | |
| 33 #endif | |
| 34 | |
| 35 #include <ostream> | |
| 36 | |
| 37 #include "base/basictypes.h" | |
| 38 #include "base/logging.h" | |
| 39 #include "base/memory/scoped_ptr.h" | |
| 40 #include "base/posix/eintr_wrapper.h" | |
| 41 #include "base/strings/string_piece.h" | |
| 42 | |
| 43 #if defined(USE_SYMBOLIZE) | |
| 44 #include "base/third_party/symbolize/symbolize.h" | |
| 45 #endif | |
| 46 | |
| 47 #if defined(OS_ANDROID) | |
| 48 #include "base/threading/platform_thread.h" | |
| 49 #endif | |
| 50 | |
| 51 namespace base { | |
| 52 namespace debug { | |
| 53 | |
| 54 #if defined(OS_MACOSX) || defined(OS_BSD) | |
| 55 | |
| 56 // Based on Apple's recommended method as described in | |
| 57 // http://developer.apple.com/qa/qa2004/qa1361.html | |
| 58 bool BeingDebugged() { | |
| 59 // NOTE: This code MUST be async-signal safe (it's used by in-process | |
| 60 // stack dumping signal handler). NO malloc or stdio is allowed here. | |
| 61 // | |
| 62 // While some code used below may be async-signal unsafe, note how | |
| 63 // the result is cached (see |is_set| and |being_debugged| static variables | |
| 64 // right below). If this code is properly warmed-up early | |
| 65 // in the start-up process, it should be safe to use later. | |
| 66 | |
| 67 // If the process is sandboxed then we can't use the sysctl, so cache the | |
| 68 // value. | |
| 69 static bool is_set = false; | |
| 70 static bool being_debugged = false; | |
| 71 | |
| 72 if (is_set) | |
| 73 return being_debugged; | |
| 74 | |
| 75 // Initialize mib, which tells sysctl what info we want. In this case, | |
| 76 // we're looking for information about a specific process ID. | |
| 77 int mib[] = { | |
| 78 CTL_KERN, | |
| 79 KERN_PROC, | |
| 80 KERN_PROC_PID, | |
| 81 getpid() | |
| 82 #if defined(OS_OPENBSD) | |
| 83 , sizeof(struct kinfo_proc), | |
| 84 0 | |
| 85 #endif | |
| 86 }; | |
| 87 | |
| 88 // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and | |
| 89 // binary interfaces may change. | |
| 90 struct kinfo_proc info; | |
| 91 size_t info_size = sizeof(info); | |
| 92 | |
| 93 #if defined(OS_OPENBSD) | |
| 94 if (sysctl(mib, arraysize(mib), NULL, &info_size, NULL, 0) < 0) | |
| 95 return -1; | |
| 96 | |
| 97 mib[5] = (info_size / sizeof(struct kinfo_proc)); | |
| 98 #endif | |
| 99 | |
| 100 int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); | |
| 101 DCHECK_EQ(sysctl_result, 0); | |
| 102 if (sysctl_result != 0) { | |
| 103 is_set = true; | |
| 104 being_debugged = false; | |
| 105 return being_debugged; | |
| 106 } | |
| 107 | |
| 108 // This process is being debugged if the P_TRACED flag is set. | |
| 109 is_set = true; | |
| 110 #if defined(OS_FREEBSD) | |
| 111 being_debugged = (info.ki_flag & P_TRACED) != 0; | |
| 112 #elif defined(OS_BSD) | |
| 113 being_debugged = (info.p_flag & P_TRACED) != 0; | |
| 114 #else | |
| 115 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; | |
| 116 #endif | |
| 117 return being_debugged; | |
| 118 } | |
| 119 | |
| 120 #elif defined(OS_LINUX) || defined(OS_ANDROID) | |
| 121 | |
| 122 // We can look in /proc/self/status for TracerPid. We are likely used in crash | |
| 123 // handling, so we are careful not to use the heap or have side effects. | |
| 124 // Another option that is common is to try to ptrace yourself, but then we | |
| 125 // can't detach without forking(), and that's not so great. | |
| 126 // static | |
| 127 bool BeingDebugged() { | |
| 128 // NOTE: This code MUST be async-signal safe (it's used by in-process | |
| 129 // stack dumping signal handler). NO malloc or stdio is allowed here. | |
| 130 | |
| 131 int status_fd = open("/proc/self/status", O_RDONLY); | |
| 132 if (status_fd == -1) | |
| 133 return false; | |
| 134 | |
| 135 // We assume our line will be in the first 1024 characters and that we can | |
| 136 // read this much all at once. In practice this will generally be true. | |
| 137 // This simplifies and speeds up things considerably. | |
| 138 char buf[1024]; | |
| 139 | |
| 140 ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); | |
| 141 if (IGNORE_EINTR(close(status_fd)) < 0) | |
| 142 return false; | |
| 143 | |
| 144 if (num_read <= 0) | |
| 145 return false; | |
| 146 | |
| 147 StringPiece status(buf, num_read); | |
| 148 StringPiece tracer("TracerPid:\t"); | |
| 149 | |
| 150 StringPiece::size_type pid_index = status.find(tracer); | |
| 151 if (pid_index == StringPiece::npos) | |
| 152 return false; | |
| 153 | |
| 154 // Our pid is 0 without a debugger, assume this for any pid starting with 0. | |
| 155 pid_index += tracer.size(); | |
| 156 return pid_index < status.size() && status[pid_index] != '0'; | |
| 157 } | |
| 158 | |
| 159 #else | |
| 160 | |
| 161 bool BeingDebugged() { | |
| 162 NOTIMPLEMENTED(); | |
| 163 return false; | |
| 164 } | |
| 165 | |
| 166 #endif | |
| 167 | |
| 168 // We want to break into the debugger in Debug mode, and cause a crash dump in | |
| 169 // Release mode. Breakpad behaves as follows: | |
| 170 // | |
| 171 // +-------+-----------------+-----------------+ | |
| 172 // | OS | Dump on SIGTRAP | Dump on SIGABRT | | |
| 173 // +-------+-----------------+-----------------+ | |
| 174 // | Linux | N | Y | | |
| 175 // | Mac | Y | N | | |
| 176 // +-------+-----------------+-----------------+ | |
| 177 // | |
| 178 // Thus we do the following: | |
| 179 // Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send | |
| 180 // SIGABRT | |
| 181 // Mac: Always send SIGTRAP. | |
| 182 | |
| 183 #if defined(ARCH_CPU_ARMEL) | |
| 184 #define DEBUG_BREAK_ASM() asm("bkpt 0") | |
| 185 #elif defined(ARCH_CPU_ARM64) | |
| 186 #define DEBUG_BREAK_ASM() asm("brk 0") | |
| 187 #elif defined(ARCH_CPU_MIPS_FAMILY) | |
| 188 #define DEBUG_BREAK_ASM() asm("break 2") | |
| 189 #elif defined(ARCH_CPU_X86_FAMILY) | |
| 190 #define DEBUG_BREAK_ASM() asm("int3") | |
| 191 #endif | |
| 192 | |
| 193 #if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | |
| 194 #define DEBUG_BREAK() abort() | |
| 195 #elif defined(OS_NACL) | |
| 196 // The NaCl verifier doesn't let use use int3. For now, we call abort(). We | |
| 197 // should ask for advice from some NaCl experts about the optimum thing here. | |
| 198 // http://code.google.com/p/nativeclient/issues/detail?id=645 | |
| 199 #define DEBUG_BREAK() abort() | |
| 200 #elif !defined(OS_MACOSX) | |
| 201 // Though Android has a "helpful" process called debuggerd to catch native | |
| 202 // signals on the general assumption that they are fatal errors. If no debugger | |
| 203 // is attached, we call abort since Breakpad needs SIGABRT to create a dump. | |
| 204 // When debugger is attached, for ARM platform the bkpt instruction appears | |
| 205 // to cause SIGBUS which is trapped by debuggerd, and we've had great | |
| 206 // difficulty continuing in a debugger once we stop from SIG triggered by native | |
| 207 // code, use GDB to set |go| to 1 to resume execution; for X86 platform, use | |
| 208 // "int3" to setup breakpiont and raise SIGTRAP. | |
| 209 // | |
| 210 // On other POSIX architectures, except Mac OS X, we use the same logic to | |
| 211 // ensure that breakpad creates a dump on crashes while it is still possible to | |
| 212 // use a debugger. | |
| 213 namespace { | |
| 214 void DebugBreak() { | |
| 215 if (!BeingDebugged()) { | |
| 216 abort(); | |
| 217 } else { | |
| 218 #if defined(DEBUG_BREAK_ASM) | |
| 219 DEBUG_BREAK_ASM(); | |
| 220 #else | |
| 221 volatile int go = 0; | |
| 222 while (!go) { | |
| 223 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | |
| 224 } | |
| 225 #endif | |
| 226 } | |
| 227 } | |
| 228 } // namespace | |
| 229 #define DEBUG_BREAK() DebugBreak() | |
| 230 #elif defined(DEBUG_BREAK_ASM) | |
| 231 #define DEBUG_BREAK() DEBUG_BREAK_ASM() | |
| 232 #else | |
| 233 #error "Don't know how to debug break on this architecture/OS" | |
| 234 #endif | |
| 235 | |
| 236 void BreakDebugger() { | |
| 237 // NOTE: This code MUST be async-signal safe (it's used by in-process | |
| 238 // stack dumping signal handler). NO malloc or stdio is allowed here. | |
| 239 | |
| 240 DEBUG_BREAK(); | |
| 241 #if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD) | |
| 242 // For Android development we always build release (debug builds are | |
| 243 // unmanageably large), so the unofficial build is used for debugging. It is | |
| 244 // helpful to be able to insert BreakDebugger() statements in the source, | |
| 245 // attach the debugger, inspect the state of the program and then resume it by | |
| 246 // setting the 'go' variable above. | |
| 247 #elif defined(NDEBUG) | |
| 248 // Terminate the program after signaling the debug break. | |
| 249 _exit(1); | |
| 250 #endif | |
| 251 } | |
| 252 | |
| 253 } // namespace debug | |
| 254 } // namespace base | |
| OLD | NEW |