GNU 的入口和出口配置函数的使用以及函数调用栈追踪

1、gcc参数-finstrument-functions,__cyg_profile_func_enter 函数和__cyg_profile_func_exit 函数的使用:

//#define _GNU_SOURCE  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

//#define __USE_GNU
#include <dlfcn.h>

__attribute__((no_instrument_function))
void
__cyg_profile_func_enter (void *this_fn, void *call_site)
{
        printf("%s,%p,called by %p\n",__func__,this_fn,call_site);
}

__attribute__((no_instrument_function))
void
__cyg_profile_func_exit (void *this_fn, void *call_site){
        printf("%s,%p,called by %p\n",__func__,this_fn,call_site);
}

void hello1()
{
        printf("hello1\n");
}
int main()
{
        printf("main\n");
        hello1();
        return 1;
}


$ gcc  -finstrument-functions -o main main.c 

$./main

__cyg_profile_func_enter,0x400642,called by 0x7fbe4618576d
main
__cyg_profile_func_enter,0x400616,called by 0x40066d
hello1
__cyg_profile_func_exit,0x400616,called by 0x40066d
__cyg_profile_func_exit,0x400642,called by 0x7fbe4618576d
以上只是打印出了函数的调用和退出的函数地址,如果要打印出具体函数名称,可以参考

http://www.ibm.com/developerworks/cn/linux/l-graphvis/

或者参考directfb源代码中的函数调用栈打印的用法;

2、另外还可以用atexit()函数注册函数正常退出时的执行函数:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

static void my_exit(void);

int main(void)
{
    if (atexit(my_exit) != 0)
        printf("can't register my_exit");

    printf("main is done\n");
    return 0;
}

static void my_exit(void)
{
    printf("Stuff print in my_exit\n");
}





你可能感兴趣的:(GNU 的入口和出口配置函数的使用以及函数调用栈追踪)