2017年11月6日追記.demangle 処理を追加したコードを公開しています.詳細は http://d.hatena.ne.jp/pyopyopyo/edit?date=20171106 で.
http://0xcc.net/blog/archives/000067.html にて知ったのだが,glibc はバックトレースを表示するための関数を提供しているとのこと.
関数名は backtrace(), backtrace_symbols_fd()で,execinfo.h というヘッダファイルで定義されている.使い方は以下の通り.
int foo(int a) { void *trace[128]; int n = backtrace(trace, sizeof(trace) / sizeof(trace[0])); backtrace_symbols_fd(trace, n, 1); } int main(int argc, char *argv[]) { foo(123); return 0; }
backtrace_symbols_fd()の最後の引数はバックトレースの出力先のfile descriptor で,上記サンプルは stdout に出すために 即値で 1 を指定してある.
気をつけないといけないのはコンパイル方法で,(少なくともglibc-2.5な環境では)コンパイルする際に "-rdynamic" を付けるか付けないかで出力される情報が異なった.具体的には "-rdynamic" をつけた場合は,シンボル名まで表示された.
$ gcc -rdynamic bt.c $ ./a.out ./a.out(foo+0x1f)[0x8048573] ./a.out(main+0x1d)[0x80485b2] /lib/libc.so.6(__libc_start_main+0xdc)[0xb7e27f2c] ./a.out[0x80484d1]
一方,"-rdynamic" をつけなかった場合は,シンボル名は表示されない.
$ gcc bt.c $ ./a.out ./a.out[0x80483d3] ./a.out[0x8048412] /lib/libc.so.6(__libc_start_main+0xdc)[0xb7e1ef2c] ./a.out[0x8048331]
このようにfooとかmainのようなシンボルが表示されない.
バックトレースを見るはめになる状況を想定すると,execinfo.h 一派を使う時は -rdynamic オプションは必須だと思われる.