系统相关
首页 > 系统相关> > Linux backtrace()系列函数

Linux backtrace()系列函数

作者:互联网

目录

backtrace()系列函数

backtrace()系列函数有3个:backtrace,backtrace_symbols,backtrace_symbols_fd。主要用于应用程序反调试(self-debugging)。

参见man 3 BACKTRACE,3个函数原型:

#include <execinfo.h>

int backtrace(void **buffer, int size);

char **backtrace_symbols(void *const *buffer, int size);

void backtrace_symbols_fd(void *const *buffer, int size, int fd);

backtrace()

backtrace() 返回调用程序的回溯(跟踪)信息,存储在由buffer指向的数组中。对于特定程序,backtrace就是一系列当前激活的函数调用(active function call)。

backtrace_symbols()

backtrace() 返回一组地址,backtrace_symbols()象征性地翻译这些地址为一个描述地址的字符串数组。

backtrace_symbols_fd()

backtrace_symbols_fd()的参数buffer、size同backtrace_symbos(),不同之处在于,backtrace_symbols_fd()并不会返回一个字符串数组给调用者,而是将字符串写入fd对应文件。backtrace_symbols_fd()也不会调用malloc分配二维数组空间,因此可应用于malloc可能会失败的情形。

版本说明

backtrace,backtrace_symbols,backtrace_symbols_fd在glibc 2.1以后就提供了。

3个函数是GNU 扩展(GNU extensions),因此只能用于GNU gcc/g++系列编译器。

应用示例

用backtrace和backtrace_symbols,打印函数的调用栈信息。

注意:

代码如下:

// backtrace.c
#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>

using namespace std;

void myfunc3()
{
    int j, nptrs;
#define SIZE 128
    void *buffer[100];
    char **strings;

    nptrs = backtrace(buffer, SIZE);
    printf("backtrace() return %d address\n", nptrs);

    strings = backtrace_symbols(buffer, nptrs);
    if (strings == NULL) {
        perror("backtrace_symbols");
        exit(EXIT_FAILURE);
    }

    for (j = 0; j < nptrs; j++)
        printf("%s\n", strings[j]);

    free(strings);
}

static void myfunc2()
{
    myfunc3();
}

void myfunc(int ncalls)
{
    if (ncalls > 1)
        myfunc(ncalls - 1);
    else
        myfunc2();
}

int main(int argc, char* argv[])
{
    if (argc != 2) {
        fprintf(stderr, "%s num-calls\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    myfunc(atoi(argv[1]));

/*
    printf("main address: %p\n", main);
    printf("myfunc address: %p\n", myfunc);
    printf("myfunc2 address: %p\n", myfunc2);
    printf("myfunc3 address: %p\n", myfunc3);
*/
    exit(EXIT_SUCCESS);
    return 0;
}

这里我们用g++编译器编译(当然也可以用gcc编译器)。

$ g++ -rdynamic -std=c++11 backtrace.c -o backtrace

运行结果:

$ ./backtrace 2
backtrace() return 7 address
./backtrace(_Z7myfunc3v+0x1f) [0x400a8c]
./backtrace() [0x400b45]
./backtrace(_Z6myfunci+0x25) [0x400b6c]
./backtrace(_Z6myfunci+0x1e) [0x400b65]
./backtrace(main+0x59) [0x400bc7]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f7170ed1f45]
./backtrace() [0x4009a9]

可以看到一共返回了7个地址,从上到下,可以推测出调用栈对应函数依次为:myfunc3、无名函数、myfunc2、myfunc1、main、__libc_start_main、无名函数。
而从$ ./backtrace 2,我们可以知道调用函数顺序为:main、myfunc、myfunc、myfunc2、myfunc3。与推测的函数栈调用顺序基本一致。

参考

在Linux中如何利用backtrace信息解决程序崩溃的问题 | CSDN

标签:函数,buffer,backtrace,void,symbols,int,fd,Linux
来源: https://www.cnblogs.com/fortunely/p/15894786.html