| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/debugger.h" | 5 #include "base/debug/debugger.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <signal.h> |
| 9 #include <stddef.h> | 10 #include <stddef.h> |
| 10 #include <stdio.h> | 11 #include <stdio.h> |
| 11 #include <stdlib.h> | 12 #include <stdlib.h> |
| 12 #include <sys/param.h> | 13 #include <sys/param.h> |
| 13 #include <sys/stat.h> | 14 #include <sys/stat.h> |
| 14 #include <sys/types.h> | 15 #include <sys/types.h> |
| 15 #include <unistd.h> | 16 #include <unistd.h> |
| 16 | 17 |
| 17 #include <memory> | 18 #include <memory> |
| 18 #include <vector> | 19 #include <vector> |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 #endif | 53 #endif |
| 53 | 54 |
| 54 namespace base { | 55 namespace base { |
| 55 namespace debug { | 56 namespace debug { |
| 56 | 57 |
| 57 #if defined(OS_MACOSX) || defined(OS_BSD) | 58 #if defined(OS_MACOSX) || defined(OS_BSD) |
| 58 | 59 |
| 59 // Based on Apple's recommended method as described in | 60 // Based on Apple's recommended method as described in |
| 60 // http://developer.apple.com/qa/qa2004/qa1361.html | 61 // http://developer.apple.com/qa/qa2004/qa1361.html |
| 61 bool BeingDebugged() { | 62 bool BeingDebugged() { |
| 63 LOG(ERROR) << "In BeingDebugged()"; |
| 62 // NOTE: This code MUST be async-signal safe (it's used by in-process | 64 // NOTE: This code MUST be async-signal safe (it's used by in-process |
| 63 // stack dumping signal handler). NO malloc or stdio is allowed here. | 65 // stack dumping signal handler). NO malloc or stdio is allowed here. |
| 64 // | 66 // |
| 65 // While some code used below may be async-signal unsafe, note how | 67 // While some code used below may be async-signal unsafe, note how |
| 66 // the result is cached (see |is_set| and |being_debugged| static variables | 68 // the result is cached (see |is_set| and |being_debugged| static variables |
| 67 // right below). If this code is properly warmed-up early | 69 // right below). If this code is properly warmed-up early |
| 68 // in the start-up process, it should be safe to use later. | 70 // in the start-up process, it should be safe to use later. |
| 69 | 71 |
| 70 // If the process is sandboxed then we can't use the sysctl, so cache the | 72 // If the process is sandboxed then we can't use the sysctl, so cache the |
| 71 // value. | 73 // value. |
| 72 static bool is_set = false; | 74 static bool is_set = false; |
| 73 static bool being_debugged = false; | 75 static bool being_debugged = false; |
| 74 | 76 |
| 75 if (is_set) | 77 if (is_set) { |
| 78 LOG(ERROR) << "is_set=true, being_debugged=" << being_debugged; |
| 76 return being_debugged; | 79 return being_debugged; |
| 80 } |
| 77 | 81 |
| 78 // Initialize mib, which tells sysctl what info we want. In this case, | 82 // Initialize mib, which tells sysctl what info we want. In this case, |
| 79 // we're looking for information about a specific process ID. | 83 // we're looking for information about a specific process ID. |
| 80 int mib[] = { | 84 int mib[] = { |
| 81 CTL_KERN, | 85 CTL_KERN, |
| 82 KERN_PROC, | 86 KERN_PROC, |
| 83 KERN_PROC_PID, | 87 KERN_PROC_PID, |
| 84 getpid() | 88 getpid() |
| 85 #if defined(OS_OPENBSD) | 89 #if defined(OS_OPENBSD) |
| 86 , sizeof(struct kinfo_proc), | 90 , sizeof(struct kinfo_proc), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 98 return -1; | 102 return -1; |
| 99 | 103 |
| 100 mib[5] = (info_size / sizeof(struct kinfo_proc)); | 104 mib[5] = (info_size / sizeof(struct kinfo_proc)); |
| 101 #endif | 105 #endif |
| 102 | 106 |
| 103 int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); | 107 int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); |
| 104 DCHECK_EQ(sysctl_result, 0); | 108 DCHECK_EQ(sysctl_result, 0); |
| 105 if (sysctl_result != 0) { | 109 if (sysctl_result != 0) { |
| 106 is_set = true; | 110 is_set = true; |
| 107 being_debugged = false; | 111 being_debugged = false; |
| 112 LOG(ERROR) << "sysctl_result=" << sysctl_result << " being_debugged=" << bei
ng_debugged; |
| 108 return being_debugged; | 113 return being_debugged; |
| 109 } | 114 } |
| 110 | 115 |
| 111 // This process is being debugged if the P_TRACED flag is set. | 116 // This process is being debugged if the P_TRACED flag is set. |
| 112 is_set = true; | 117 is_set = true; |
| 113 #if defined(OS_FREEBSD) | 118 #if defined(OS_FREEBSD) |
| 114 being_debugged = (info.ki_flag & P_TRACED) != 0; | 119 being_debugged = (info.ki_flag & P_TRACED) != 0; |
| 115 #elif defined(OS_BSD) | 120 #elif defined(OS_BSD) |
| 116 being_debugged = (info.p_flag & P_TRACED) != 0; | 121 being_debugged = (info.p_flag & P_TRACED) != 0; |
| 117 #else | 122 #else |
| 118 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; | 123 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; |
| 119 #endif | 124 #endif |
| 125 LOG(ERROR) << "being_debugged=" << being_debugged; |
| 120 return being_debugged; | 126 return being_debugged; |
| 121 } | 127 } |
| 122 | 128 |
| 123 #elif defined(OS_LINUX) || defined(OS_ANDROID) | 129 #elif defined(OS_LINUX) || defined(OS_ANDROID) |
| 124 | 130 |
| 125 // We can look in /proc/self/status for TracerPid. We are likely used in crash | 131 // We can look in /proc/self/status for TracerPid. We are likely used in crash |
| 126 // handling, so we are careful not to use the heap or have side effects. | 132 // handling, so we are careful not to use the heap or have side effects. |
| 127 // Another option that is common is to try to ptrace yourself, but then we | 133 // Another option that is common is to try to ptrace yourself, but then we |
| 128 // can't detach without forking(), and that's not so great. | 134 // can't detach without forking(), and that's not so great. |
| 129 // static | 135 // static |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 // | Linux | N | Y | | 183 // | Linux | N | Y | |
| 178 // | Mac | Y | N | | 184 // | Mac | Y | N | |
| 179 // +-------+-----------------+-----------------+ | 185 // +-------+-----------------+-----------------+ |
| 180 // | 186 // |
| 181 // Thus we do the following: | 187 // Thus we do the following: |
| 182 // Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send | 188 // Linux: Debug mode if a debugger is attached, send SIGTRAP; otherwise send |
| 183 // SIGABRT | 189 // SIGABRT |
| 184 // Mac: Always send SIGTRAP. | 190 // Mac: Always send SIGTRAP. |
| 185 | 191 |
| 186 #if defined(ARCH_CPU_ARMEL) | 192 #if defined(ARCH_CPU_ARMEL) |
| 187 #define DEBUG_BREAK_ASM() asm("bkpt 0") | 193 #define DEBUG_BREAK_ASM() do { LOG(ERROR) << "DEBUG_BREAK_ASM brpt 0"; asm("bkpt
0"); } while (0) |
| 188 #elif defined(ARCH_CPU_ARM64) | 194 #elif defined(ARCH_CPU_ARM64) |
| 189 #define DEBUG_BREAK_ASM() asm("brk 0") | 195 #define DEBUG_BREAK_ASM() do { LOG(ERROR) << "DEBUG_BREAK_ASM brk 0"; asm("brk 0
"); } while (0) |
| 190 #elif defined(ARCH_CPU_MIPS_FAMILY) | 196 #elif defined(ARCH_CPU_MIPS_FAMILY) |
| 191 #define DEBUG_BREAK_ASM() asm("break 2") | 197 #define DEBUG_BREAK_ASM() do { LOG(ERROR) << "DEBUG_BREAK_ASM break 2"; asm("bre
ak 2"); } while (0) |
| 192 #elif defined(ARCH_CPU_X86_FAMILY) | 198 #elif defined(ARCH_CPU_X86_FAMILY) |
| 193 #define DEBUG_BREAK_ASM() asm("int3") | 199 #define DEBUG_BREAK_ASM() do { LOG(ERROR) << "DEBUG_BREAK_ASM abort"; abort(); a
sm("int3"); } while (0) |
| 194 #endif | 200 #endif |
| 195 | 201 |
| 196 #if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 202 #if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| 197 #define DEBUG_BREAK() abort() | 203 #define DEBUG_BREAK() do { LOG(ERROR) << "DEBUG_BREAK abort()"; abort(); } while
(0) |
| 198 #elif defined(OS_NACL) | 204 #elif defined(OS_NACL) |
| 199 // The NaCl verifier doesn't let use use int3. For now, we call abort(). We | 205 // The NaCl verifier doesn't let use use int3. For now, we call abort(). We |
| 200 // should ask for advice from some NaCl experts about the optimum thing here. | 206 // should ask for advice from some NaCl experts about the optimum thing here. |
| 201 // http://code.google.com/p/nativeclient/issues/detail?id=645 | 207 // http://code.google.com/p/nativeclient/issues/detail?id=645 |
| 202 #define DEBUG_BREAK() abort() | 208 #define DEBUG_BREAK() do { LOG(ERROR) << "DEBUG_BREAK abort()"; abort(); } while
(0) |
| 203 #elif !defined(OS_MACOSX) | 209 #elif !defined(OS_MACOSX) |
| 204 // Though Android has a "helpful" process called debuggerd to catch native | 210 // Though Android has a "helpful" process called debuggerd to catch native |
| 205 // signals on the general assumption that they are fatal errors. If no debugger | 211 // signals on the general assumption that they are fatal errors. If no debugger |
| 206 // is attached, we call abort since Breakpad needs SIGABRT to create a dump. | 212 // is attached, we call abort since Breakpad needs SIGABRT to create a dump. |
| 207 // When debugger is attached, for ARM platform the bkpt instruction appears | 213 // When debugger is attached, for ARM platform the bkpt instruction appears |
| 208 // to cause SIGBUS which is trapped by debuggerd, and we've had great | 214 // to cause SIGBUS which is trapped by debuggerd, and we've had great |
| 209 // difficulty continuing in a debugger once we stop from SIG triggered by native | 215 // difficulty continuing in a debugger once we stop from SIG triggered by native |
| 210 // code, use GDB to set |go| to 1 to resume execution; for X86 platform, use | 216 // code, use GDB to set |go| to 1 to resume execution; for X86 platform, use |
| 211 // "int3" to setup breakpiont and raise SIGTRAP. | 217 // "int3" to setup breakpiont and raise SIGTRAP. |
| 212 // | 218 // |
| 213 // On other POSIX architectures, except Mac OS X, we use the same logic to | 219 // On other POSIX architectures, except Mac OS X, we use the same logic to |
| 214 // ensure that breakpad creates a dump on crashes while it is still possible to | 220 // ensure that breakpad creates a dump on crashes while it is still possible to |
| 215 // use a debugger. | 221 // use a debugger. |
| 216 namespace { | 222 namespace { |
| 217 void DebugBreak() { | 223 void DebugBreak() { |
| 224 LOG(ERROR) << "DebugBreak function"; |
| 218 if (!BeingDebugged()) { | 225 if (!BeingDebugged()) { |
| 226 LOG(ERROR) << "Not being debugged. abort()"; |
| 219 abort(); | 227 abort(); |
| 220 } else { | 228 } else { |
| 221 #if defined(DEBUG_BREAK_ASM) | 229 #if defined(DEBUG_BREAK_ASM) |
| 222 DEBUG_BREAK_ASM(); | 230 DEBUG_BREAK_ASM(); |
| 223 #else | 231 #else |
| 224 volatile int go = 0; | 232 volatile int go = 0; |
| 225 while (!go) { | 233 while (!go) { |
| 234 LOG(ERROR) << "In loop waiting for debugger"; |
| 226 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 235 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
| 227 } | 236 } |
| 228 #endif | 237 #endif |
| 229 } | 238 } |
| 230 } | 239 } |
| 231 } // namespace | 240 } // namespace |
| 232 #define DEBUG_BREAK() DebugBreak() | 241 #define DEBUG_BREAK() DebugBreak() |
| 233 #elif defined(DEBUG_BREAK_ASM) | 242 #elif defined(DEBUG_BREAK_ASM) |
| 234 #define DEBUG_BREAK() DEBUG_BREAK_ASM() | 243 #define DEBUG_BREAK() DEBUG_BREAK_ASM() |
| 235 #else | 244 #else |
| 236 #error "Don't know how to debug break on this architecture/OS" | 245 #error "Don't know how to debug break on this architecture/OS" |
| 237 #endif | 246 #endif |
| 238 | 247 |
| 248 typedef void (*handlert)(int); |
| 249 handlert oldhandlers[32]; |
| 250 void newhandler(int sig) { |
| 251 LOG(ERROR) << "handler: " << sig; |
| 252 oldhandlers[sig](sig); |
| 253 } |
| 254 |
| 239 void BreakDebugger() { | 255 void BreakDebugger() { |
| 240 // NOTE: This code MUST be async-signal safe (it's used by in-process | 256 // NOTE: This code MUST be async-signal safe (it's used by in-process |
| 241 // stack dumping signal handler). NO malloc or stdio is allowed here. | 257 // stack dumping signal handler). NO malloc or stdio is allowed here. |
| 242 | 258 |
| 243 // Linker's ICF feature may merge this function with other functions with the | 259 // Linker's ICF feature may merge this function with other functions with the |
| 244 // same definition (e.g. any function whose sole job is to call abort()) and | 260 // same definition (e.g. any function whose sole job is to call abort()) and |
| 245 // it may confuse the crash report processing system. http://crbug.com/508489 | 261 // it may confuse the crash report processing system. http://crbug.com/508489 |
| 246 static int static_variable_to_make_this_function_unique = 0; | 262 static int static_variable_to_make_this_function_unique = 0; |
| 247 base::debug::Alias(&static_variable_to_make_this_function_unique); | 263 base::debug::Alias(&static_variable_to_make_this_function_unique); |
| 248 | 264 |
| 265 LOG(ERROR) << "DEBUG_BREAK"; |
| 266 |
| 267 //for (int i = 1; i < 32; ++i) |
| 268 // oldhandlers[i] = signal(i, newhandler); |
| 269 |
| 249 DEBUG_BREAK(); | 270 DEBUG_BREAK(); |
| 271 |
| 272 LOG(ERROR) << "After DEBUG_BREAK"; |
| 273 |
| 250 #if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD) | 274 #if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD) |
| 251 // For Android development we always build release (debug builds are | 275 // For Android development we always build release (debug builds are |
| 252 // unmanageably large), so the unofficial build is used for debugging. It is | 276 // unmanageably large), so the unofficial build is used for debugging. It is |
| 253 // helpful to be able to insert BreakDebugger() statements in the source, | 277 // helpful to be able to insert BreakDebugger() statements in the source, |
| 254 // attach the debugger, inspect the state of the program and then resume it by | 278 // attach the debugger, inspect the state of the program and then resume it by |
| 255 // setting the 'go' variable above. | 279 // setting the 'go' variable above. |
| 256 #elif defined(NDEBUG) | 280 #elif defined(NDEBUG) |
| 257 // Terminate the program after signaling the debug break. | 281 // Terminate the program after signaling the debug break. |
| 258 _exit(1); | 282 _exit(1); |
| 259 #endif | 283 #endif |
| 260 } | 284 } |
| 261 | 285 |
| 262 } // namespace debug | 286 } // namespace debug |
| 263 } // namespace base | 287 } // namespace base |
| OLD | NEW |