/* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code * distributions retain the above copyright notice and this paragraph * in its entirety, and (2) distributions including binary code include * the above copyright notice and this paragraph in its entirety in * the documentation or other materials provided with the distribution. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include extern int profile_func_level; int profile_func_level = -1; /* * Generate instrumentation calls for entry and exit to functions. * Just after function entry and just before function exit, the * following profiling functions are called with the address of the * current function and its call site (currently not use). * * The attribute 'no_instrument_function' causes this instrumentation is * not done. * * These profiling functions print the function names with indentation * and call level. * * To instument a static function, remove temporarily the static specifier. */ void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function)); void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function)); /* * The get_function_name() get the function name by calling dladdr() */ static const char *get_function_name(void *func) __attribute__((no_instrument_function)); static const char * get_function_name(void *func) { Dl_info info; const char *function_name; if(dladdr(func, &info)) function_name = info.dli_sname; else function_name = NULL; return function_name; } void __cyg_profile_func_enter(void *this_fn, void *call_site __attribute__((unused))) { int i; const char *function_name; if((function_name = get_function_name(this_fn)) != NULL) { profile_func_level += 1; for (i = 0 ; i < profile_func_level ; i++) putchar(' '); printf("[>> %s (%d)]\n", function_name, profile_func_level); } fflush(stdout); } void __cyg_profile_func_exit(void *this_fn, void *call_site __attribute__((unused))) { int i; const char *function_name; if((function_name = get_function_name(this_fn)) != NULL) { for (i = 0 ; i < profile_func_level ; i++) putchar(' '); printf ("[<< %s (%d)]\n", function_name, profile_func_level); profile_func_level -= 1; } fflush(stdout); }