#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