CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Namespaces | Macros | Typedefs | Functions | Variables
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

 INSTR
 

Macros

#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(); }
 

Typedefs

typedef unsigned char INSTR::byte
 

Functions

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

Variables

const int REG_EBP = 6
 
const int REG_EIP = 14
 
const int REG_ESP = 7
 
const byte INSTR::RET = 0xc3
 

Macro Definition 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().

351  {
353  void** arr = prof->tempStack();
354  int nmax = prof->tempStackSize();
355  int stackdepth = stacktrace(arr, nmax);
356 
357  assert(stackdepth <= nmax);
358 
359  // We don't want the first three entries, because they always
360  // contain information about the how the signal handler was
361  // called, the signal handler, and the stacktrace function.
362  prof->commitFrame(arr+3, arr + stackdepth);
363  }
void commitFrame(void **first, void **last)
static SimpleProfiler * instance()
void ** tempStack()
int stacktrace(void *addresses[], int nmax)
size_type tempStackSize()
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().

225 {
226  ++samples_total;
227 #if __linux && __i386
228 # if ! __x86_64__
229 # define PROBABLY_VSYSCALL_PAGE 0xffff0000
230 # else
231 # define PROBABLY_VSYSCALL_PAGE 0xffffffff00000000
232 # endif
233  struct frame
234  {
235  // Normal frame.
236  frame *ebp;
237  void *eip;
238  // Signal frame stuff, put in here by kernel.
239  int signo;
240  siginfo_t *info;
241  ucontext_t *ctx;
242  };
243  // register frame *ebp __asm__ ("ebp");
244  // register frame *esp __asm__ ("esp");
245  // use macros to avoid compiler warning.
246 #define getBP(X) asm ( "movl %%ebp,%0" : "=m" (X) )
247 #define getSP(X) asm ( "movl %%esp,%0" : "=m" (X) )
248  register frame* ebp = 0;
249  getBP(ebp);
250  register frame* esp = 0;
251  getSP(esp);
252 
253  frame *fp = ebp;
254  int depth = 0;
255 
256  // Add fake entry to be compatible with other methods
257  if (depth < nmax) addresses[depth++] = reinterpret_cast<void *>(reinterpret_cast<unsigned long>(&stacktrace));
258 
259  // Top-most frame ends with null pointer; check the rest is reasonable
260  while (depth < nmax && fp >= esp)
261  {
262  // Add this stack frame. The return address is the
263  // instruction immediately after the "call". The call
264  // instruction itself is 4 or 6 bytes; we guess 4.
265  addresses[depth++] = (char *) fp->eip - 4;
266 
267  // Recognise signal frames. We use two different methods
268  // depending on the linux kernel version.
269  //
270  // For the "old" kernels / systems we check the instructions
271  // at the caller's return address. We take it to be a signal
272  // frame if we find the signal return code sequence there
273  // and the thread register context structure pointer:
274  //
275  // mov $__NR_rt_sigreturn, %eax
276  // int 0x80
277  //
278  // For the "new" kernels / systems the operating system maps
279  // a "vsyscall" page at a high address, and it may contain
280  // either the above code, or use of the sysenter/sysexit
281  // instructions. We cannot poke at that page so we take the
282  // the high address as an indication this is a signal frame.
283  // (http://www.trilithium.com/johan/2005/08/linux-gate/)
284  // (http://manugarg.googlepages.com/systemcallinlinux2_6.html)
285  //
286  // If we don't recognise the signal frame correctly here, we
287  // lose one stack frame: signal delivery is not a call so
288  // when the signal handler is entered, ebp still points to
289  // what it was just before the signal.
290  unsigned char *insn = (unsigned char *) fp->eip;
291  if (insn
292  && insn[0] == 0xb8 && insn[1] == __NR_rt_sigreturn
293  && insn[5] == 0xcd && insn[6] == 0x80
294  && fp->ctx)
295  {
296  void *retip = (void *) fp->ctx->uc_mcontext.gregs [REG_EIP];
297  if (depth < nmax) addresses[depth++] = retip;
298 
299  fp = (frame *) fp->ctx->uc_mcontext.gregs [REG_EBP];
300  if (fp && (unsigned long) retip > PROBABLY_VSYSCALL_PAGE)
301  {
302  // __kernel_vsyscall stack on system call exit is
303  // [0] %ebp, [1] %edx, [2] %ecx, [3] return address.
304  if (depth < nmax) addresses[depth++] = ((void **) fp)[3];
305  fp = fp->ebp;
306 
307  // It seems the frame _above_ __kernel_syscall (the
308  // syscall implementation in libc, such as __mmap())
309  // is essentially frame-pointer-less, so we should
310  // find also the call above, but I don't know how
311  // to determine how many arguments the system call
312  // pushed on stack to call __kernel_syscall short
313  // of interpreting the DWARF unwind information :-(
314  // So we may lose one level of call stack here.
315  ++samples_missing_framepointer;
316  }
317  }
318 
319  // Otherwise it's a normal frame, process through frame pointer.
320  else
321  fp = fp->ebp;
322  }
323 
324  return depth;
325 #elif __linux
326  return backtrace (addresses, nmax);
327 #elif HAVE_UNWIND_BACKTRACE
328  if (nmax >= 1)
329  {
330  IgHookTraceArgs args = { addresses, 0, nmax };
331  _Unwind_Backtrace (&GCCBackTrace, &args);
332 
333  if (args.count > 1 && args.array [args.count-1] == 0)
334  args.count--;
335 
336  return args.count;
337  }
338  return 0;
339 #else
340  return 0;
341 #endif
342 }
#define getBP(X)
#define getSP(X)
const int REG_EIP
const int REG_EBP
dictionary args
int stacktrace(void *addresses[], int nmax)
perl if(1 lt scalar(@::datatypes))
Definition: edlooper.cc:31

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.