🦛
glibcのbacktrace_symbols_fd関数を使う
はじめに
glibcのbacktrace_symbols_fd関数を使用してみます。
サンプル
Backtracesに
以下のようなサンプルが記載されています。
ここではbacktraceとbacktrace_symbolsが使用されています。
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
char **strings;
int size, i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
if (strings != NULL)
{
printf ("Obtained %d stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
}
free (strings);
}
/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}
int
main (void)
{
dummy_function ();
return 0;
}
backtrace_symbols_fdという関数もあるので、こちらを使用した例を書いてみました。
backtrace_symbols_fdを使用した例
以下のようなコードを書いてみました。
上記のbacktrace_symbols
を使用した例とほぼ同じです。
main関数内でbacktraceした結果を書き込むファイルをopenして、
fileno
関数でファイルディスクリプタを取得しています。
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
FILE* fd;
int filedescriptor;
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
char **strings;
int size, i;
size = backtrace (array, 10);
backtrace_symbols_fd (array, size, filedescriptor);
}
/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}
int
main (void)
{
// パスは環境に合わせて修正してください
fd = fopen("/home/yutaka/temp/glibcs/log.log","w");
filedescriptor = fileno(fd);
dummy_function ();
return 0;
}
コンパイルして、実行します。
トレース結果に関数名を出力するため、-rdynamicオプションを付けます。
$ gcc -o sample sample.c -rdynamic
$ ./sample
出力されたlog.log
ファイルを見ると、backtraceの結果が出力されました。
$ cat log.log
./sample(print_trace+0x19)[0x40115f]
./sample(dummy_function+0x9)[0x401185]
./sample(main+0x34)[0x4011bc]
/gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31/lib/libc.so.6(__libc_start_main+0xed)[0x7f890247ea6d]
./sample(_start+0x2a)[0x40109a]
Discussion