CMS 3D CMS Logo

Namespaces | Defines | Functions | Variables

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/FWCore/Services/src/SimpleProfiler.cc File Reference

#include <pthread.h>
#include <unistd.h>
#include <dlfcn.h>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <ucontext.h>
#include <execinfo.h>
#include "SimpleProfiler.h"
#include "ProfParse.h"
#include <fstream>

Go to the source code of this file.

Namespaces

namespace  INSTR

Defines

#define _POSIX_C_SOURCE   199309
#define DODEBUG   if(0) std::cerr
#define getBP(X)   asm ( "movl %%ebp,%0" : "=m" (X) )
#define getSP(X)   asm ( "movl %%esp,%0" : "=m" (X) )
#define MUST_BE_ZERO(fun)   if((fun)!=0) { perror("function failed"); abort(); }

Functions

void sigFunc (int sig, siginfo_t *info, void *context)
int stacktrace (void *addresses[], int nmax)

Variables

data refman pasoursint
CMSSW_4_1_8_patch12 src FWCore
Services src SimpleProfiler cc
data refman pasoursint
CMSSW_4_1_8_patch12 src FWCore
Services src SimpleProfiler cc
typedef unsigned char 
INSTR::byte
const int REG_EBP = 6
const int REG_EIP = 14
const int REG_ESP = 7
const byte INSTR::RET = 0xc3

Define Documentation

#define _POSIX_C_SOURCE   199309

Definition at line 3 of file SimpleProfiler.cc.

#define DODEBUG   if(0) std::cerr

Definition at line 75 of file SimpleProfiler.cc.

#define getBP (   X)    asm ( "movl %%ebp,%0" : "=m" (X) )

Definition at line 69 of file SimpleProfiler.cc.

Referenced by stacktrace().

#define getSP (   X)    asm ( "movl %%esp,%0" : "=m" (X) )

Definition at line 70 of file SimpleProfiler.cc.

Referenced by stacktrace().

#define MUST_BE_ZERO (   fun)    if((fun)!=0) { perror("function failed"); abort(); }

Definition at line 68 of file SimpleProfiler.cc.


Function Documentation

void sigFunc ( int  sig,
siginfo_t *  info,
void *  context 
)

Definition at line 350 of file SimpleProfiler.cc.

References SimpleProfiler::commitFrame(), SimpleProfiler::instance(), stacktrace(), SimpleProfiler::tempStack(), and SimpleProfiler::tempStackSize().

  {
    SimpleProfiler* prof = SimpleProfiler::instance();
    void** arr = prof->tempStack();
    int nmax =   prof->tempStackSize();
    int stackdepth = stacktrace(arr, nmax);

    assert(stackdepth <= nmax);

    // We don't want the first three entries, because they always
    // contain information about the how the signal handler was
    // called, the signal handler, and the stacktrace function.
    prof->commitFrame(arr+3, arr + stackdepth);
  }
int stacktrace ( void *  addresses[],
int  nmax 
)

Definition at line 224 of file SimpleProfiler.cc.

References evf::utils::eip, evf::utils::esp, getBP, getSP, if(), info, REG_EBP, and REG_EIP.

Referenced by sigFunc().

{
  ++samples_total;
#if __linux && __i386
# if ! __x86_64__
#  define PROBABLY_VSYSCALL_PAGE 0xffff0000
# else
#  define PROBABLY_VSYSCALL_PAGE 0xffffffff00000000
# endif
  struct frame
  {
    // Normal frame.
    frame               *ebp;
    void                *eip;
    // Signal frame stuff, put in here by kernel.
    int         signo;
    siginfo_t   *info;
    ucontext_t  *ctx;
  };
  // register frame      *ebp __asm__ ("ebp");
  // register frame      *esp __asm__ ("esp");
  // use macros to avoid compiler warning.
#define getBP(X)  asm ( "movl %%ebp,%0" : "=m" (X) )
#define getSP(X)  asm ( "movl %%esp,%0" : "=m" (X) )
  register frame* ebp = 0;
  getBP(ebp);
  register frame* esp = 0;
  getSP(esp);

  frame               *fp = ebp;
  int                   depth = 0;

  // Add fake entry to be compatible with other methods
  if (depth < nmax) addresses[depth++] = reinterpret_cast<void *>(reinterpret_cast<unsigned long>(&stacktrace));

  // Top-most frame ends with null pointer; check the rest is reasonable
  while (depth < nmax && fp >= esp)
    {
      // Add this stack frame.  The return address is the
      // instruction immediately after the "call".  The call
      // instruction itself is 4 or 6 bytes; we guess 4.
      addresses[depth++] = (char *) fp->eip - 4;

      // Recognise signal frames.  We use two different methods
      // depending on the linux kernel version.
      //
      // For the "old" kernels / systems we check the instructions
      // at the caller's return address.  We take it to be a signal
      // frame if we find the signal return code sequence there
      // and the thread register context structure pointer:
      //
      //    mov $__NR_rt_sigreturn, %eax
      //    int 0x80
      //
      // For the "new" kernels / systems the operating system maps
      // a "vsyscall" page at a high address, and it may contain
      // either the above code, or use of the sysenter/sysexit
      // instructions.  We cannot poke at that page so we take the
      // the high address as an indication this is a signal frame.
      // (http://www.trilithium.com/johan/2005/08/linux-gate/)
      // (http://manugarg.googlepages.com/systemcallinlinux2_6.html)
      //
      // If we don't recognise the signal frame correctly here, we
      // lose one stack frame: signal delivery is not a call so
      // when the signal handler is entered, ebp still points to
      // what it was just before the signal.
      unsigned char *insn = (unsigned char *) fp->eip;
      if (insn
          && insn[0] == 0xb8 && insn[1] == __NR_rt_sigreturn
          && insn[5] == 0xcd && insn[6] == 0x80
          && fp->ctx)
        {   
          void *retip = (void *) fp->ctx->uc_mcontext.gregs [REG_EIP];
          if (depth < nmax) addresses[depth++] = retip;

          fp = (frame *) fp->ctx->uc_mcontext.gregs [REG_EBP];
          if (fp && (unsigned long) retip > PROBABLY_VSYSCALL_PAGE)
            {
              // __kernel_vsyscall stack on system call exit is
              // [0] %ebp, [1] %edx, [2] %ecx, [3] return address.
              if (depth < nmax) addresses[depth++] = ((void **) fp)[3];
              fp = fp->ebp;

              // It seems the frame _above_ __kernel_syscall (the
              // syscall implementation in libc, such as __mmap())
              // is essentially frame-pointer-less, so we should
              // find also the call above, but I don't know how
              // to determine how many arguments the system call
              // pushed on stack to call __kernel_syscall short
              // of interpreting the DWARF unwind information :-(
              // So we may lose one level of call stack here.
              ++samples_missing_framepointer;
            }
        }

      // Otherwise it's a normal frame, process through frame pointer.
      else
        fp = fp->ebp;
    }

  return depth;
#elif __linux
  return backtrace (addresses, nmax);
#elif HAVE_UNWIND_BACKTRACE
  if (nmax >= 1)
    {
      IgHookTraceArgs args = { addresses, 0, nmax };
      _Unwind_Backtrace (&GCCBackTrace, &args);

      if (args.count > 1 && args.array [args.count-1] == 0)
        args.count--;

      return args.count;
    }
  return 0;
#else
  return 0;
#endif
}

Variable Documentation

const int REG_EBP = 6

Definition at line 82 of file SimpleProfiler.cc.

Referenced by stacktrace().

const int REG_EIP = 14

Definition at line 81 of file SimpleProfiler.cc.

Referenced by stacktrace().

const int REG_ESP = 7

Definition at line 83 of file SimpleProfiler.cc.