#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_patch9 src FWCore Services src SimpleProfiler cc data refman pasoursint CMSSW_4_1_8_patch9 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 _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.
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. // (https://www.trilithium.com/johan/2005/08/linux-gate/) // (https://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 }
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.