#include <dlfcn.h>
#include <stdio.h>
#include <typeinfo>
#include <cxxabi.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
 
// From binutils/include/demangle.h
#define DMGL_PARAMS      (1 << 0)  /* Include function args */
#define DMGL_ANSI        (1 << 1)  /* Include const, volatile, etc */
#define DMGL_VERBOSE     (1 << 3)  /* Include implementation details.  */
#define DMGL_TYPES       (1 << 4)  /* Also try to demangle type encodings. */

extern "C" { 
    void __cyg_profile_func_enter(void* func_address, void* call_site);
    void __cyg_profile_func_exit(void* func_address, void* call_site);
    char *cplus_demangle(const char *mangled, int options);
}

double getTime(){
  struct rusage t;
  struct timeval tv;

  getrusage(RUSAGE_SELF, &t);
  tv = t.ru_utime;
  return tv.tv_sec + (double)tv.tv_usec*1e-6;
}

double time_stack[1000];
int stack_num = 0;

void time_push(){
  time_stack[stack_num] = getTime();
  stack_num++;
}

double time_pop(){
  stack_num--;
  return getTime() - time_stack[stack_num];
}

// dladdrを用いて関数アドレスから関数シンボルへ変換
const char* addr2name(void* address) {  

    int status;
    Dl_info dli;
    int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
    const char * func_name = 0;
    if (0 != dladdr(address, &dli)) {
      func_name = abi::__cxa_demangle(dli.dli_sname, 0, 0, &status);
      if( func_name == 0 ){
        func_name = cplus_demangle(dli.dli_sname, options);
      }
    }
    return func_name;
} 

int count = 1;

void __cyg_profile_func_enter(void* func_address, void* call_site) {
  count++;
  for( int i = 0; i < count; i++){ printf(" "); }
  const char* func_name = addr2name(func_address);
  printf("=> %p %s enter\n", func_address, func_name);
  time_push();
}

void __cyg_profile_func_exit(void* func_address, void* call_site) {
  for( int i = 0; i < count; i++){ printf(" "); }
  const char* func_name = addr2name(func_address);
  double time = time_pop();
  printf("<= %p %s exit time:%11.9f\n", func_address, func_name, time);
  count--;
}
最終更新:2011年04月09日 11:50