summaryrefslogtreecommitdiffstats
path: root/base/debug/debugger_posix.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-26 04:07:50 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-26 04:07:50 +0000
commit58580359a452cb7c3b9580edc0843c3ab3d158df (patch)
tree964dbcc1505f4b9c2bbb5e7a64720861d604c8f3 /base/debug/debugger_posix.cc
parent23872906817de5d402b0c2da6d5f7ee6026378e6 (diff)
downloadchromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.zip
chromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.tar.gz
chromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.tar.bz2
Move debug-related stuff from base to the base/debug directory and use the
base::debug namespace. This splits apart debug_util into base/debugger and base/stack_trace There are still two functions in debug_util that I'm not sure what to do with. Since this uses the base::debug namespace, I removed the functions in debugger.h from the static class and just made them free functions in the namespace. TEST=it compiles BUG=none Review URL: http://codereview.chromium.org/3945002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63859 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug/debugger_posix.cc')
-rw-r--r--base/debug/debugger_posix.cc165
1 files changed, 165 insertions, 0 deletions
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc
new file mode 100644
index 0000000..a5ab066
--- /dev/null
+++ b/base/debug/debugger_posix.cc
@@ -0,0 +1,165 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/debugger.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#if defined(__GLIBCXX__)
+#include <cxxabi.h>
+#endif
+
+#if defined(OS_MACOSX)
+#include <AvailabilityMacros.h>
+#endif
+
+#include <iostream>
+
+#include "base/basictypes.h"
+#include "base/compat_execinfo.h"
+#include "base/eintr_wrapper.h"
+#include "base/logging.h"
+#include "base/safe_strerror_posix.h"
+#include "base/scoped_ptr.h"
+#include "base/string_piece.h"
+#include "base/stringprintf.h"
+
+#if defined(USE_SYMBOLIZE)
+#include "base/third_party/symbolize/symbolize.h"
+#endif
+
+namespace base {
+namespace debug {
+
+bool SpawnDebuggerOnProcess(unsigned /* process_id */) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+#if defined(OS_MACOSX)
+
+// Based on Apple's recommended method as described in
+// http://developer.apple.com/qa/qa2004/qa1361.html
+bool BeingDebugged() {
+ // If the process is sandboxed then we can't use the sysctl, so cache the
+ // value.
+ static bool is_set = false;
+ static bool being_debugged = false;
+
+ if (is_set) {
+ return being_debugged;
+ }
+
+ // Initialize mib, which tells sysctl what info we want. In this case,
+ // we're looking for information about a specific process ID.
+ int mib[] = {
+ CTL_KERN,
+ KERN_PROC,
+ KERN_PROC_PID,
+ getpid()
+ };
+
+ // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
+ // binary interfaces may change.
+ struct kinfo_proc info;
+ size_t info_size = sizeof(info);
+
+ int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
+ DCHECK_EQ(sysctl_result, 0);
+ if (sysctl_result != 0) {
+ is_set = true;
+ being_debugged = false;
+ return being_debugged;
+ }
+
+ // This process is being debugged if the P_TRACED flag is set.
+ is_set = true;
+ being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
+ return being_debugged;
+}
+
+#elif defined(OS_LINUX)
+
+// We can look in /proc/self/status for TracerPid. We are likely used in crash
+// handling, so we are careful not to use the heap or have side effects.
+// Another option that is common is to try to ptrace yourself, but then we
+// can't detach without forking(), and that's not so great.
+// static
+bool BeingDebugged() {
+ int status_fd = open("/proc/self/status", O_RDONLY);
+ if (status_fd == -1)
+ return false;
+
+ // We assume our line will be in the first 1024 characters and that we can
+ // read this much all at once. In practice this will generally be true.
+ // This simplifies and speeds up things considerably.
+ char buf[1024];
+
+ ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
+ if (HANDLE_EINTR(close(status_fd)) < 0)
+ return false;
+
+ if (num_read <= 0)
+ return false;
+
+ StringPiece status(buf, num_read);
+ StringPiece tracer("TracerPid:\t");
+
+ StringPiece::size_type pid_index = status.find(tracer);
+ if (pid_index == StringPiece::npos)
+ return false;
+
+ // Our pid is 0 without a debugger, assume this for any pid starting with 0.
+ pid_index += tracer.size();
+ return pid_index < status.size() && status[pid_index] != '0';
+}
+
+#elif defined(OS_FREEBSD)
+
+bool DebugUtil::BeingDebugged() {
+ // TODO(benl): can we determine this under FreeBSD?
+ NOTIMPLEMENTED();
+ return false;
+}
+
+#endif // defined(OS_FREEBSD)
+
+// We want to break into the debugger in Debug mode, and cause a crash dump in
+// Release mode. Breakpad behaves as follows:
+//
+// +-------+-----------------+-----------------+
+// | OS | Dump on SIGTRAP | Dump on SIGABRT |
+// +-------+-----------------+-----------------+
+// | Linux | N | Y |
+// | Mac | Y | N |
+// +-------+-----------------+-----------------+
+//
+// Thus we do the following:
+// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT.
+// Mac: Always send SIGTRAP.
+
+#if defined(NDEBUG) && !defined(OS_MACOSX)
+#define DEBUG_BREAK() abort()
+#elif defined(ARCH_CPU_ARM_FAMILY)
+#define DEBUG_BREAK() asm("bkpt 0")
+#else
+#define DEBUG_BREAK() asm("int3")
+#endif
+
+void BreakDebugger() {
+ DEBUG_BREAK();
+}
+
+} // namespace debug
+} // namespace base