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 #include "build/build_config.h" | 6 #include "build/build_config.h" |
7 | 7 |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
(...skipping 61 matching lines...) Loading... |
72 return false; | 72 return false; |
73 return true; | 73 return true; |
74 #endif | 74 #endif |
75 } | 75 } |
76 | 76 |
77 #if defined(OS_MACOSX) || defined(OS_BSD) | 77 #if defined(OS_MACOSX) || defined(OS_BSD) |
78 | 78 |
79 // Based on Apple's recommended method as described in | 79 // Based on Apple's recommended method as described in |
80 // http://developer.apple.com/qa/qa2004/qa1361.html | 80 // http://developer.apple.com/qa/qa2004/qa1361.html |
81 bool BeingDebugged() { | 81 bool BeingDebugged() { |
| 82 // NOTE: This code MUST be async-signal safe (it's used by in-process |
| 83 // stack dumping signal handler). NO malloc or stdio is allowed here. |
| 84 // |
| 85 // While some code used below may be async-signal unsafe, note how |
| 86 // the result is cached (see |is_set| and |being_debugged| static variables |
| 87 // right below). If this code is properly warmed-up early |
| 88 // in the start-up process, it should be safe to use later. |
| 89 |
82 // If the process is sandboxed then we can't use the sysctl, so cache the | 90 // If the process is sandboxed then we can't use the sysctl, so cache the |
83 // value. | 91 // value. |
84 static bool is_set = false; | 92 static bool is_set = false; |
85 static bool being_debugged = false; | 93 static bool being_debugged = false; |
86 | 94 |
87 if (is_set) { | 95 if (is_set) |
88 return being_debugged; | 96 return being_debugged; |
89 } | |
90 | 97 |
91 // Initialize mib, which tells sysctl what info we want. In this case, | 98 // Initialize mib, which tells sysctl what info we want. In this case, |
92 // we're looking for information about a specific process ID. | 99 // we're looking for information about a specific process ID. |
93 int mib[] = { | 100 int mib[] = { |
94 CTL_KERN, | 101 CTL_KERN, |
95 KERN_PROC, | 102 KERN_PROC, |
96 KERN_PROC_PID, | 103 KERN_PROC_PID, |
97 getpid() | 104 getpid() |
98 #if defined(OS_OPENBSD) | 105 #if defined(OS_OPENBSD) |
99 , sizeof(struct kinfo_proc), | 106 , sizeof(struct kinfo_proc), |
(...skipping 34 matching lines...) Loading... |
134 } | 141 } |
135 | 142 |
136 #elif defined(OS_LINUX) || defined(OS_ANDROID) | 143 #elif defined(OS_LINUX) || defined(OS_ANDROID) |
137 | 144 |
138 // We can look in /proc/self/status for TracerPid. We are likely used in crash | 145 // 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. | 146 // 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 | 147 // 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. | 148 // can't detach without forking(), and that's not so great. |
142 // static | 149 // static |
143 bool BeingDebugged() { | 150 bool BeingDebugged() { |
| 151 // NOTE: This code MUST be async-signal safe (it's used by in-process |
| 152 // stack dumping signal handler). NO malloc or stdio is allowed here. |
| 153 |
144 int status_fd = open("/proc/self/status", O_RDONLY); | 154 int status_fd = open("/proc/self/status", O_RDONLY); |
145 if (status_fd == -1) | 155 if (status_fd == -1) |
146 return false; | 156 return false; |
147 | 157 |
148 // We assume our line will be in the first 1024 characters and that we can | 158 // 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. | 159 // read this much all at once. In practice this will generally be true. |
150 // This simplifies and speeds up things considerably. | 160 // This simplifies and speeds up things considerably. |
151 char buf[1024]; | 161 char buf[1024]; |
152 | 162 |
153 ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); | 163 ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); |
(...skipping 68 matching lines...) Loading... |
222 // ARM && !ANDROID | 232 // ARM && !ANDROID |
223 #define DEBUG_BREAK() asm("bkpt 0") | 233 #define DEBUG_BREAK() asm("bkpt 0") |
224 #endif | 234 #endif |
225 #elif defined(ARCH_CPU_MIPS_FAMILY) | 235 #elif defined(ARCH_CPU_MIPS_FAMILY) |
226 #define DEBUG_BREAK() asm("break 2") | 236 #define DEBUG_BREAK() asm("break 2") |
227 #else | 237 #else |
228 #define DEBUG_BREAK() asm("int3") | 238 #define DEBUG_BREAK() asm("int3") |
229 #endif | 239 #endif |
230 | 240 |
231 void BreakDebugger() { | 241 void BreakDebugger() { |
| 242 // NOTE: This code MUST be async-signal safe (it's used by in-process |
| 243 // stack dumping signal handler). NO malloc or stdio is allowed here. |
| 244 |
232 DEBUG_BREAK(); | 245 DEBUG_BREAK(); |
233 #if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD) | 246 #if defined(OS_ANDROID) && !defined(OFFICIAL_BUILD) |
234 // For Android development we always build release (debug builds are | 247 // For Android development we always build release (debug builds are |
235 // unmanageably large), so the unofficial build is used for debugging. It is | 248 // unmanageably large), so the unofficial build is used for debugging. It is |
236 // helpful to be able to insert BreakDebugger() statements in the source, | 249 // 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 | 250 // attach the debugger, inspect the state of the program and then resume it by |
238 // setting the 'go' variable above. | 251 // setting the 'go' variable above. |
239 #elif defined(NDEBUG) | 252 #elif defined(NDEBUG) |
240 // Terminate the program after signaling the debug break. | 253 // Terminate the program after signaling the debug break. |
241 _exit(1); | 254 _exit(1); |
242 #endif | 255 #endif |
243 } | 256 } |
244 | 257 |
245 } // namespace debug | 258 } // namespace debug |
246 } // namespace base | 259 } // namespace base |
OLD | NEW |