シグナル ハンドラーで backtrace() の適切な解決策を見つけるために既に何度もグーグルを実行し、ほとんどすべてを試しましたが、シグナル ハンドラーでバックトレースを正常に取得できませんでした。これは SIGUSR1 ハンドラーではありません。
- uclibc config で UCLIBC_HAS_BACKTRACE=y を有効にしてコンパイルする
- libubacktrace.so が作成されていることを確認
- 次のオプションでアプリケーションバイナリをコンパイルしました -g -rdynamic -fexception または -funwind-tables
- バイナリ自体が「削除」されているようです
ただし、シグナル ハンドラから完全なバックトレースを取得できませんでした。シグナルハンドラで呼び出した関数アドレスのみが出力されました。
target-gdb バイナリを使用し、gdb --pid コマンドを使用してプロセスをアタッチすると、完全なバックトレースを適切に取得できました。
また、pstack を試してみましたが (pstack-1.2 - arm-patch を試しましたが、ひどい... 何も出力されませんでした) あまり役に立ちませんでした。
何かアドバイス?
1) Makefile のコンパイラ オプション
CFLAGS += -g -fexceptions -funwind-tables -Werror $(WARN) ...
2) コード
コードは非常にシンプルです。
#define CALLSTACK_SIZE 10
static void print_stack(void) {
int i, nptrs;
void *buf[CALLSTACK_SIZE + 1];
char **strings;
nptrs = backtrace(buf, CALLSTACK_SIZE);
printf("%s: backtrace() returned %d addresses\n", __func__, nptrs);
strings = backtrace_symbols(buf, nptrs);
if(strings == NULL) {
printf("%s: no backtrace captured\n", __func__);
return;
}
for(i = 0; i < nptrs; i++) {
printf("%s\n", strings[i]);
}
free(strings);
}
...
static void sigHandler(int signum)
{
printf("%s: signal %d\n", __FUNCTION__, signum);
switch(signum ) {
case SIGUSR2:
// told to quit
print_stack();
break;
default:
break;
}
}