ipc/chromium/src/base/debug_util_posix.cc

changeset 0
6474c204b198
     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 +}

mercurial