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