blob: 4dee92db8dcfab1596b7a881342b39dd1014a221 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 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]4d0f93c2011-09-29 04:43:5420#if !defined(OS_ANDROID)
21#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
61bool SpawnDebuggerOnProcess(unsigned /* process_id */) {
62 NOTIMPLEMENTED();
63 return false;
64}
65
[email protected]e37e88a02011-11-15 00:06:1666#if defined(OS_MACOSX) || defined(OS_BSD)
[email protected]58580352010-10-26 04:07:5067
68// Based on Apple's recommended method as described in
69// http://developer.apple.com/qa/qa2004/qa1361.html
70bool BeingDebugged() {
71 // If the process is sandboxed then we can't use the sysctl, so cache the
72 // value.
73 static bool is_set = false;
74 static bool being_debugged = false;
75
76 if (is_set) {
77 return being_debugged;
78 }
79
80 // Initialize mib, which tells sysctl what info we want. In this case,
81 // we're looking for information about a specific process ID.
82 int mib[] = {
83 CTL_KERN,
84 KERN_PROC,
85 KERN_PROC_PID,
86 getpid()
[email protected]88b49f72011-10-18 17:41:0787#if defined(OS_OPENBSD)
88 , sizeof(struct kinfo_proc),
89 0
90#endif
[email protected]58580352010-10-26 04:07:5091 };
92
93 // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
94 // binary interfaces may change.
95 struct kinfo_proc info;
96 size_t info_size = sizeof(info);
97
[email protected]88b49f72011-10-18 17:41:0798#if defined(OS_OPENBSD)
99 if (sysctl(mib, arraysize(mib), NULL, &info_size, NULL, 0) < 0)
100 return -1;
101
102 mib[5] = (info_size / sizeof(struct kinfo_proc));
103#endif
104
[email protected]58580352010-10-26 04:07:50105 int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
106 DCHECK_EQ(sysctl_result, 0);
107 if (sysctl_result != 0) {
108 is_set = true;
109 being_debugged = false;
110 return being_debugged;
111 }
112
113 // This process is being debugged if the P_TRACED flag is set.
114 is_set = true;
[email protected]af824362011-12-04 14:19:41115#if defined(OS_FREEBSD)
116 being_debugged = (info.ki_flag & P_TRACED) != 0;
117#elif defined(OS_BSD)
[email protected]88b49f72011-10-18 17:41:07118 being_debugged = (info.p_flag & P_TRACED) != 0;
119#else
[email protected]58580352010-10-26 04:07:50120 being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
[email protected]88b49f72011-10-18 17:41:07121#endif
[email protected]58580352010-10-26 04:07:50122 return being_debugged;
123}
124
[email protected]3132e35c2011-07-07 20:46:50125#elif defined(OS_LINUX) || defined(OS_ANDROID)
[email protected]58580352010-10-26 04:07:50126
127// We can look in /proc/self/status for TracerPid. We are likely used in crash
128// handling, so we are careful not to use the heap or have side effects.
129// Another option that is common is to try to ptrace yourself, but then we
130// can't detach without forking(), and that's not so great.
131// static
132bool BeingDebugged() {
133 int status_fd = open("/proc/self/status", O_RDONLY);
134 if (status_fd == -1)
135 return false;
136
137 // We assume our line will be in the first 1024 characters and that we can
138 // read this much all at once. In practice this will generally be true.
139 // This simplifies and speeds up things considerably.
140 char buf[1024];
141
142 ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
143 if (HANDLE_EINTR(close(status_fd)) < 0)
144 return false;
145
146 if (num_read <= 0)
147 return false;
148
149 StringPiece status(buf, num_read);
150 StringPiece tracer("TracerPid:\t");
151
152 StringPiece::size_type pid_index = status.find(tracer);
153 if (pid_index == StringPiece::npos)
154 return false;
155
156 // Our pid is 0 without a debugger, assume this for any pid starting with 0.
157 pid_index += tracer.size();
158 return pid_index < status.size() && status[pid_index] != '0';
159}
160
[email protected]94f8c952011-06-25 04:54:41161#else
[email protected]58580352010-10-26 04:07:50162
[email protected]d0282962011-01-01 16:08:52163bool BeingDebugged() {
[email protected]58580352010-10-26 04:07:50164 NOTIMPLEMENTED();
165 return false;
166}
167
[email protected]af824362011-12-04 14:19:41168#endif
[email protected]58580352010-10-26 04:07:50169
170// We want to break into the debugger in Debug mode, and cause a crash dump in
171// Release mode. Breakpad behaves as follows:
172//
173// +-------+-----------------+-----------------+
174// | OS | Dump on SIGTRAP | Dump on SIGABRT |
175// +-------+-----------------+-----------------+
176// | Linux | N | Y |
177// | Mac | Y | N |
178// +-------+-----------------+-----------------+
179//
180// Thus we do the following:
181// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT.
182// Mac: Always send SIGTRAP.
183
[email protected]3132e35c2011-07-07 20:46:50184#if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]58580352010-10-26 04:07:50185#define DEBUG_BREAK() abort()
[email protected]651d9c02010-12-01 07:36:54186#elif defined(OS_NACL)
187// The NaCl verifier doesn't let use use int3. For now, we call abort(). We
188// should ask for advice from some NaCl experts about the optimum thing here.
189// http://code.google.com/p/nativeclient/issues/detail?id=645
190#define DEBUG_BREAK() abort()
[email protected]58580352010-10-26 04:07:50191#elif defined(ARCH_CPU_ARM_FAMILY)
[email protected]3132e35c2011-07-07 20:46:50192#if defined(OS_ANDROID)
193// Though Android has a "helpful" process called debuggerd to catch native
194// signals on the general assumption that they are fatal errors, we've had great
195// difficulty continuing in a debugger once we stop from SIGINT triggered by
196// native code.
197//
198// Use GDB to set |go| to 1 to resume execution.
199#define DEBUG_BREAK() do { \
200 volatile int go = 0; \
201 while (!go) { base::PlatformThread::Sleep(100); } \
202} while (0)
203#else
204// ARM && !ANDROID
[email protected]58580352010-10-26 04:07:50205#define DEBUG_BREAK() asm("bkpt 0")
[email protected]3132e35c2011-07-07 20:46:50206#endif
[email protected]58580352010-10-26 04:07:50207#else
208#define DEBUG_BREAK() asm("int3")
209#endif
210
211void BreakDebugger() {
212 DEBUG_BREAK();
[email protected]f355c562011-01-21 05:02:17213#if defined(NDEBUG)
214 _exit(1);
215#endif
[email protected]58580352010-10-26 04:07:50216}
217
218} // namespace debug
219} // namespace base