NAME

backtrace, backtrace_symbols, backtrace_symbols_fd - 응용 셀프 디버깅 지원

SYNOPSIS

#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);

DESCRIPTION

backtrace()buffer가 가리키는 배열로 호출 프로그램의 백트레이스를 반환한다. 백트레이스란 프로그램에서 현재 활성인 함수 호출들의 열이다. buffer가 가리키는 배열의 각 항목은 void * 타입이며 대응하는 스택 프레임의 반환 주소다. size 인자는 buffer에 저장할 수 있는 주소의 최대 개수를 나타낸다. 백트레이스가 size보다 큰 경우에는 가장 최근 size 개 함수 호출에 대응하는 주소들만 반환된다. 백트레이스 전체를 얻으려면 buffersize를 충분히 크게 해야 한다.

backtrace()가 반환한 주소 집합을 backtrace_symbols()에게 buffer로 주면 주소를 심볼로 나타낸 문자열들의 배열로 변환해 준다. size 인자는 buffer의 주소 개수를 나타낸다. 각 주소의 심볼 표현은 함수 이름 (알아낼 수 있는 경우), 16진수로 된 함수 내 오프셋, (16진수로 된) 실제 반환 주소로 이뤄져 있다. 문자열 포인터들의 배열의 주소를 backtrace_symbols()가 함수 결과로 반환한다. 그 배열은 backtrace_symbols()에서 malloc(3) 한 것이므로 호출자가 해제해야 한다. (그 포인터 배열이 가리키는 문자열들은 해제할 필요가 없으며 해서도 안 된다.)

backtrace_symbols_fd()backtrace_symbols()와 같은 buffersize 인자를 받되 문자열 배열을 호출자에게 반환하는 대신 파일 디스크립터 fd에 그 문자열들을 한 행에 하나씩 출력한다. backtrace_symbols_fd()malloc(3)을 호출하지 않으므로 malloc(3)이 실패할 수도 있는 경우에 이용할 수 있다. 하지만 NOTES를 보라.

RETURN VALUE

backtrace()buffer로 반환하는 주소들의 수를 반환하며 그 값은 size보다 크지 않다. 반환 값이 size보다 작은 경우에는 백트레이스 전체가 저장된 것이다. size와 같은 경우에는 일부가 잘렸을 수도 있으며, 그 경우 오래된 스택 프레임들의 주소가 반환되지 않는다.

성공 시 backtrace_symbols()는 호출 내에서 malloc(3) 한 배열의 포인터를 반환한다. 오류 시 NULL을 반환한다.

ATTRIBUTES

이 절에서 사용하는 용어들에 대한 설명은 attributes(7)를 보라.

인터페이스 속성
backtrace(), backtrace_symbols(),
backtrace_symbols_fd()
스레드 안전성 MT-Safe

CONFORMING TO

이 함수들은 GNU 확장이다.

NOTES

이 함수들에서는 함수의 반환 주소가 스택에 저장되는 방식에 대해 몇 가지 가정을 한다. 다음에 유의하라.

특별한 링커 옵션을 쓰지 않으면 심볼 이름을 얻지 못할 수도 있다. GNU 링커를 사용하는 시스템에서는 -rdynamic 링커 옵션을 써야 한다. 참고로 "static" 함수의 이름은 노출되지 않으므로 백트레이스에 나오지 않는다.

EXAMPLES

아래 프로그램은 backtrace()backtrace_symbols()의 사용 방식을 보여 준다. 다음 셸 세션은 프로그램 실행 시 볼 수 있는 결과이다.

$ cc -rdynamic prog.c -o prog
$ ./prog 3
backtrace() returned 8 addresses
./prog(myfunc3+0x5c) [0x80487f0]
./prog [0x8048871]
./prog(myfunc+0x21) [0x8048894]
./prog(myfunc+0x1a) [0x804888d]
./prog(myfunc+0x1a) [0x804888d]
./prog(main+0x65) [0x80488fb]
/lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c]
./prog [0x8048711]

프로그램 소스

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

#define BT_BUF_SIZE 100

void
myfunc3(void)
{
    int nptrs;
    void *buffer[BT_BUF_SIZE];
    char **strings;

    nptrs = backtrace(buffer, BT_BUF_SIZE);
    printf("backtrace() returned %d addresses\n", nptrs);

    /* backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 호출 시
       다음 코드와 비슷한 출력이 나옴: */

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

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

    free(strings);
}

static void   /* "static"이므로 심볼 내보이지 않음... */
myfunc2(void)
{
    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]));
    exit(EXIT_SUCCESS);
}

SEE ALSO

addr2line(1), gcc(1), gdb(1), ld(1), dlopen(3), malloc(3)


2021-03-22