blob: 4139f73c61839c4c5f170cacd380acdc2ca47b29 [file] [log] [blame]
[email protected]380d8322012-02-28 21:35:441// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]58580352010-10-26 04:07:502// 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"
[email protected]651d9c02010-12-01 07:36:546#include "build/build_config.h"
[email protected]58580352010-10-26 04:07:507
8#include <errno.h>
9#include <fcntl.h>
10#include <stdio.h>
11#include <stdlib.h>
[email protected]0c6f3b0c2011-04-15 06:15:0412#include <sys/param.h>
[email protected]58580352010-10-26 04:07:5013#include <sys/stat.h>
[email protected]58580352010-10-26 04:07:5014#include <sys/types.h>
15#include <unistd.h>
16
17#include <string>
18#include <vector>
19
[email protected]380d8322012-02-28 21:35:4420#if !defined(OS_ANDROID) && !defined(OS_NACL)
[email protected]4d0f93c2011-09-29 04:43:5421#include <execinfo.h>
22#endif
23
[email protected]58580352010-10-26 04:07:5024#if defined(__GLIBCXX__)
25#include <cxxabi.h>
26#endif
27
28#if defined(OS_MACOSX)
29#include <AvailabilityMacros.h>
30#endif
31
[email protected]e37e88a02011-11-15 00:06:1632#if defined(OS_MACOSX) || defined(OS_BSD)
[email protected]94f8c952011-06-25 04:54:4133#include <sys/sysctl.h>
34#endif
35
[email protected]af824362011-12-04 14:19:4136#if defined(OS_FREEBSD)
37#include <sys/user.h>
38#endif
39
[email protected]a5c0fd982011-09-01 20:19:5340#include <ostream>
[email protected]58580352010-10-26 04:07:5041
42#include "base/basictypes.h"
[email protected]58580352010-10-26 04:07:5043#include "base/eintr_wrapper.h"
44#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1545#include "base/memory/scoped_ptr.h"
[email protected]58580352010-10-26 04:07:5046#include "base/safe_strerror_posix.h"
[email protected]58580352010-10-26 04:07:5047#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
[email protected]3132e35c2011-07-07 20:46:5054#if defined(OS_ANDROID)
[email protected]3132e35c2011-07-07 20:46:5055#include "base/threading/platform_thread.h"
56#endif
57
[email protected]58580352010-10-26 04:07:5058namespace base {
59namespace debug {
60
[email protected]66bf4eed2012-06-06 00:47:4061bool SpawnDebuggerOnProcess(unsigned process_id) {
[email protected]fccfcf22012-06-09 01:09:0562#if OS_ANDROID || OS_NACL
[email protected]58580352010-10-26 04:07:5063 NOTIMPLEMENTED();
64 return false;
[email protected]66bf4eed2012-06-06 00:47:4065#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
[email protected]58580352010-10-26 04:07:5075}
76
[email protected]e37e88a02011-11-15 00:06:1677#if defined(OS_MACOSX) || defined(OS_BSD)
[email protected]58580352010-10-26 04:07:5078
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()
[email protected]88b49f72011-10-18 17:41:0798#if defined(OS_OPENBSD)
99 , sizeof(struct kinfo_proc),
100 0
101#endif
[email protected]58580352010-10-26 04:07:50102 };
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
[email protected]88b49f72011-10-18 17:41:07109#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
[email protected]58580352010-10-26 04:07:50116 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;
[email protected]af824362011-12-04 14:19:41126#if defined(OS_FREEBSD)
127 being_debugged = (info.ki_flag & P_TRACED) != 0;
128#elif defined(OS_BSD)
[email protected]88b49f72011-10-18 17:41:07129 being_debugged = (info.p_flag & P_TRACED) != 0;
130#else
[email protected]58580352010-10-26 04:07:50131 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
[email protected]88b49f72011-10-18 17:41:07132#endif
[email protected]58580352010-10-26 04:07:50133 return being_debugged;
134}
135
[email protected]3132e35c2011-07-07 20:46:50136#elif defined(OS_LINUX) || defined(OS_ANDROID)
[email protected]58580352010-10-26 04:07:50137
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
[email protected]94f8c952011-06-25 04:54:41172#else
[email protected]58580352010-10-26 04:07:50173
[email protected]d0282962011-01-01 16:08:52174bool BeingDebugged() {
[email protected]58580352010-10-26 04:07:50175 NOTIMPLEMENTED();
176 return false;
177}
178
[email protected]af824362011-12-04 14:19:41179#endif
[email protected]58580352010-10-26 04:07:50180
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
[email protected]3132e35c2011-07-07 20:46:50195#if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]58580352010-10-26 04:07:50196#define DEBUG_BREAK() abort()
[email protected]651d9c02010-12-01 07:36:54197#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()
[email protected]58580352010-10-26 04:07:50202#elif defined(ARCH_CPU_ARM_FAMILY)
[email protected]3132e35c2011-07-07 20:46:50203#if defined(OS_ANDROID)
204// Though Android has a "helpful" process called debuggerd to catch native
[email protected]b3e58442012-06-29 06:39:27205// 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.
[email protected]3132e35c2011-07-07 20:46:50209//
210// Use GDB to set |go| to 1 to resume execution.
211#define DEBUG_BREAK() do { \
[email protected]b3e58442012-06-29 06:39:27212 if (!BeingDebugged()) { \
213 abort(); \
214 } else { \
215 volatile int go = 0; \
216 while (!go) { \
217 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); \
218 } \
[email protected]a1b75b942011-12-31 22:53:51219 } \
[email protected]3132e35c2011-07-07 20:46:50220} while (0)
221#else
222// ARM && !ANDROID
[email protected]58580352010-10-26 04:07:50223#define DEBUG_BREAK() asm("bkpt 0")
[email protected]3132e35c2011-07-07 20:46:50224#endif
[email protected]58580352010-10-26 04:07:50225#else
226#define DEBUG_BREAK() asm("int3")
227#endif
228
229void BreakDebugger() {
230 DEBUG_BREAK();
[email protected]b3e58442012-06-29 06:39:27231#if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD)
232 // For Android development we always build release (debug builds are
233 // unmanageably large), so the unofficial build is used for debugging. It is
234 // helpful to be able to insert BreakDebugger() statements in the source,
235 // attach the debugger, inspect the state of the program and then resume it by
236 // setting the 'go' variable above.
237#elif defined(NDEBUG)
238 // Terminate the program after signaling the debug break.
[email protected]f355c562011-01-21 05:02:17239 _exit(1);
240#endif
[email protected]58580352010-10-26 04:07:50241}
242
243} // namespace debug
244} // namespace base