1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/debug_util_posix.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,187 @@ 1.4 +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "build/build_config.h" 1.9 +#include "base/debug_util.h" 1.10 + 1.11 +#define MOZ_HAVE_EXECINFO_H (defined(OS_LINUX) && !defined(ANDROID)) 1.12 + 1.13 +#include <errno.h> 1.14 +#include <fcntl.h> 1.15 +#include <stdio.h> 1.16 +#include <limits.h> 1.17 +#include <sys/stat.h> 1.18 +#include <sys/param.h> 1.19 +#include <sys/types.h> 1.20 +#include <unistd.h> 1.21 +#if MOZ_HAVE_EXECINFO_H 1.22 +#include <execinfo.h> 1.23 +#endif 1.24 + 1.25 +#if defined(OS_MACOSX) || defined(OS_BSD) 1.26 +#if defined(OS_OPENBSD) 1.27 +#include <sys/proc.h> 1.28 +#endif 1.29 +#include <sys/sysctl.h> 1.30 +#endif 1.31 + 1.32 +#if defined(OS_DRAGONFLY) || defined(OS_FREEBSD) 1.33 +#include <sys/user.h> 1.34 +#endif 1.35 + 1.36 +#include "base/basictypes.h" 1.37 +#include "base/eintr_wrapper.h" 1.38 +#include "base/logging.h" 1.39 +#include "base/scoped_ptr.h" 1.40 +#include "base/string_piece.h" 1.41 + 1.42 +#if defined(OS_NETBSD) 1.43 +#undef KERN_PROC 1.44 +#define KERN_PROC KERN_PROC2 1.45 +#define KINFO_PROC struct kinfo_proc2 1.46 +#else 1.47 +#define KINFO_PROC struct kinfo_proc 1.48 +#endif 1.49 + 1.50 +#if defined(OS_MACOSX) 1.51 +#define KP_FLAGS kp_proc.p_flag 1.52 +#elif defined(OS_DRAGONFLY) 1.53 +#define KP_FLAGS kp_flags 1.54 +#elif defined(OS_FREEBSD) 1.55 +#define KP_FLAGS ki_flag 1.56 +#elif defined(OS_OPENBSD) && !defined(_P_TRACED) 1.57 +#define KP_FLAGS p_psflags 1.58 +#define P_TRACED PS_TRACED 1.59 +#else 1.60 +#define KP_FLAGS p_flag 1.61 +#endif 1.62 + 1.63 +// static 1.64 +bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) { 1.65 + NOTIMPLEMENTED(); 1.66 + return false; 1.67 +} 1.68 + 1.69 +#if defined(OS_MACOSX) || defined(OS_BSD) 1.70 + 1.71 +// Based on Apple's recommended method as described in 1.72 +// http://developer.apple.com/qa/qa2004/qa1361.html 1.73 +// static 1.74 +bool DebugUtil::BeingDebugged() { 1.75 + // If the process is sandboxed then we can't use the sysctl, so cache the 1.76 + // value. 1.77 + static bool is_set = false; 1.78 + static bool being_debugged = false; 1.79 + 1.80 + if (is_set) { 1.81 + return being_debugged; 1.82 + } 1.83 + 1.84 + // Initialize mib, which tells sysctl what info we want. In this case, 1.85 + // we're looking for information about a specific process ID. 1.86 + int mib[] = { 1.87 + CTL_KERN, 1.88 + KERN_PROC, 1.89 + KERN_PROC_PID, 1.90 + getpid(), 1.91 +#if defined(OS_NETBSD) || defined(OS_OPENBSD) 1.92 + sizeof(KINFO_PROC), 1.93 + 1, 1.94 +#endif 1.95 + }; 1.96 + 1.97 + // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and 1.98 + // binary interfaces may change. 1.99 + KINFO_PROC info; 1.100 + size_t info_size = sizeof(info); 1.101 + 1.102 + int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); 1.103 + DCHECK(sysctl_result == 0); 1.104 + if (sysctl_result != 0) { 1.105 + is_set = true; 1.106 + being_debugged = false; 1.107 + return being_debugged; 1.108 + } 1.109 + 1.110 + // This process is being debugged if the P_TRACED flag is set. 1.111 + is_set = true; 1.112 + being_debugged = (info.KP_FLAGS & P_TRACED) != 0; 1.113 + return being_debugged; 1.114 +} 1.115 + 1.116 +#elif defined(OS_LINUX) 1.117 + 1.118 +// We can look in /proc/self/status for TracerPid. We are likely used in crash 1.119 +// handling, so we are careful not to use the heap or have side effects. 1.120 +// Another option that is common is to try to ptrace yourself, but then we 1.121 +// can't detach without forking(), and that's not so great. 1.122 +// static 1.123 +bool DebugUtil::BeingDebugged() { 1.124 + int status_fd = open("/proc/self/status", O_RDONLY); 1.125 + if (status_fd == -1) 1.126 + return false; 1.127 + 1.128 + // We assume our line will be in the first 1024 characters and that we can 1.129 + // read this much all at once. In practice this will generally be true. 1.130 + // This simplifies and speeds up things considerably. 1.131 + char buf[1024]; 1.132 + 1.133 + ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); 1.134 + HANDLE_EINTR(close(status_fd)); 1.135 + 1.136 + if (num_read <= 0) 1.137 + return false; 1.138 + 1.139 + StringPiece status(buf, num_read); 1.140 + StringPiece tracer("TracerPid:\t"); 1.141 + 1.142 + StringPiece::size_type pid_index = status.find(tracer); 1.143 + if (pid_index == StringPiece::npos) 1.144 + return false; 1.145 + 1.146 + // Our pid is 0 without a debugger, assume this for any pid starting with 0. 1.147 + pid_index += tracer.size(); 1.148 + return pid_index < status.size() && status[pid_index] != '0'; 1.149 +} 1.150 + 1.151 +#endif // OS_LINUX 1.152 + 1.153 +// static 1.154 +void DebugUtil::BreakDebugger() { 1.155 +#if defined(ARCH_CPU_X86_FAMILY) 1.156 + asm ("int3"); 1.157 +#endif 1.158 +} 1.159 + 1.160 +StackTrace::StackTrace() { 1.161 + const int kMaxCallers = 256; 1.162 + 1.163 + void* callers[kMaxCallers]; 1.164 +#if MOZ_HAVE_EXECINFO_H 1.165 + int count = backtrace(callers, kMaxCallers); 1.166 +#else 1.167 + int count = 0; 1.168 +#endif 1.169 + 1.170 + // Though the backtrace API man page does not list any possible negative 1.171 + // return values, we still still exclude them because they would break the 1.172 + // memcpy code below. 1.173 + if (count > 0) { 1.174 + trace_.resize(count); 1.175 + memcpy(&trace_[0], callers, sizeof(callers[0]) * count); 1.176 + } else { 1.177 + trace_.resize(0); 1.178 + } 1.179 +} 1.180 + 1.181 +void StackTrace::PrintBacktrace() { 1.182 + fflush(stderr); 1.183 +#if MOZ_HAVE_EXECINFO_H 1.184 + backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO); 1.185 +#endif 1.186 +} 1.187 + 1.188 +void StackTrace::OutputToStream(std::ostream* os) { 1.189 + return; 1.190 +}