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