1 : // Copyright (c) 2006-2009 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 "build/build_config.h"
6 : #include "base/debug_util.h"
7 :
8 : #define MOZ_HAVE_EXECINFO_H (!defined(ANDROID) && !defined(__OpenBSD__))
9 :
10 : #include <errno.h>
11 : #include <fcntl.h>
12 : #include <stdio.h>
13 : #include <limits.h>
14 : #include <sys/stat.h>
15 : #include <sys/param.h>
16 : #include <sys/types.h>
17 : #include <unistd.h>
18 : #if MOZ_HAVE_EXECINFO_H
19 : #include <execinfo.h>
20 : #include <sys/sysctl.h>
21 : #endif
22 :
23 : #include "base/basictypes.h"
24 : #include "base/eintr_wrapper.h"
25 : #include "base/logging.h"
26 : #include "base/scoped_ptr.h"
27 : #include "base/string_piece.h"
28 :
29 : // static
30 0 : bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
31 0 : NOTIMPLEMENTED();
32 0 : return false;
33 : }
34 :
35 : #if defined(OS_MACOSX)
36 :
37 : // Based on Apple's recommended method as described in
38 : // http://developer.apple.com/qa/qa2004/qa1361.html
39 : // static
40 : bool DebugUtil::BeingDebugged() {
41 : // If the process is sandboxed then we can't use the sysctl, so cache the
42 : // value.
43 : static bool is_set = false;
44 : static bool being_debugged = false;
45 :
46 : if (is_set) {
47 : return being_debugged;
48 : }
49 :
50 : // Initialize mib, which tells sysctl what info we want. In this case,
51 : // we're looking for information about a specific process ID.
52 : int mib[] = {
53 : CTL_KERN,
54 : KERN_PROC,
55 : KERN_PROC_PID,
56 : getpid()
57 : };
58 :
59 : // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
60 : // binary interfaces may change.
61 : struct kinfo_proc info;
62 : size_t info_size = sizeof(info);
63 :
64 : int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
65 : DCHECK(sysctl_result == 0);
66 : if (sysctl_result != 0) {
67 : is_set = true;
68 : being_debugged = false;
69 : return being_debugged;
70 : }
71 :
72 : // This process is being debugged if the P_TRACED flag is set.
73 : is_set = true;
74 : being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
75 : return being_debugged;
76 : }
77 :
78 : #elif defined(OS_LINUX)
79 :
80 : // We can look in /proc/self/status for TracerPid. We are likely used in crash
81 : // handling, so we are careful not to use the heap or have side effects.
82 : // Another option that is common is to try to ptrace yourself, but then we
83 : // can't detach without forking(), and that's not so great.
84 : // static
85 0 : bool DebugUtil::BeingDebugged() {
86 0 : int status_fd = open("/proc/self/status", O_RDONLY);
87 0 : if (status_fd == -1)
88 0 : return false;
89 :
90 : // We assume our line will be in the first 1024 characters and that we can
91 : // read this much all at once. In practice this will generally be true.
92 : // This simplifies and speeds up things considerably.
93 : char buf[1024];
94 :
95 0 : ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
96 0 : HANDLE_EINTR(close(status_fd));
97 :
98 0 : if (num_read <= 0)
99 0 : return false;
100 :
101 0 : StringPiece status(buf, num_read);
102 0 : StringPiece tracer("TracerPid:\t");
103 :
104 0 : StringPiece::size_type pid_index = status.find(tracer);
105 0 : if (pid_index == StringPiece::npos)
106 0 : return false;
107 :
108 : // Our pid is 0 without a debugger, assume this for any pid starting with 0.
109 0 : pid_index += tracer.size();
110 0 : return pid_index < status.size() && status[pid_index] != '0';
111 : }
112 :
113 : #endif // OS_LINUX
114 :
115 : // static
116 0 : void DebugUtil::BreakDebugger() {
117 : #if defined(ARCH_CPU_X86_FAMILY)
118 0 : asm ("int3");
119 : #endif
120 0 : }
121 :
122 0 : StackTrace::StackTrace() {
123 0 : const int kMaxCallers = 256;
124 :
125 : void* callers[kMaxCallers];
126 : #if MOZ_HAVE_EXECINFO_H
127 0 : int count = backtrace(callers, kMaxCallers);
128 : #else
129 : int count = 0;
130 : #endif
131 :
132 : // Though the backtrace API man page does not list any possible negative
133 : // return values, we still still exclude them because they would break the
134 : // memcpy code below.
135 0 : if (count > 0) {
136 0 : trace_.resize(count);
137 0 : memcpy(&trace_[0], callers, sizeof(callers[0]) * count);
138 : } else {
139 0 : trace_.resize(0);
140 : }
141 0 : }
142 :
143 0 : void StackTrace::PrintBacktrace() {
144 0 : fflush(stderr);
145 : #if MOZ_HAVE_EXECINFO_H
146 0 : backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO);
147 : #endif
148 0 : }
149 :
150 0 : void StackTrace::OutputToStream(std::ostream* os) {
151 : return;
152 4392 : }
|