2012-02-09 13 views
6

Linux上で動作する64ビットマルチスレッドC++アプリケーションのシグナルハンドラからスタックトレースを出力する必要があります。いくつかのコード例が見つかりましたが、どれもコンパイルされません。私のブロッキングポイントは、ucontext_t構造体からの呼び出し元(シグナルが生成されたポイント)アドレスを取得しています。私が見つけることができるすべての情報は、ucontext.gregs [REG_EIP]またはucontext.eipとしてEIPレジスタを指しています。どちらもx86固有のものだと思われます。 IntelとAMD CPUの両方に64ビット準拠のコードが必要です。誰でも助けることができますか?シグナルハンドラからスタックトレースを出力する

+0

できない場合は、私には驚かないでしょう。あなたは32ビットでやってみましたか?また、どのディストロ? –

+0

64ビットでは、レジスタはRIPです。それがどこかにあることは間違いありません。 –

+0

Red Hat 4.1.2-50です。私たちは最大60GB以上の大きなメモリ領域を扱うので、32ビットアプリケーションにすることはできません。 – GMichael

答えて

1

スタックトレースを取得する通常の方法は、に使用される最適化オプション に依存している(そして コンパイラがコードを生成する方法に応じて、それにいくつかのマジックナンバーを追加し、ローカル 変数のアドレスを取ることですコードをコンパイルしてください)、そこから戻って作業してください。すべて非常にシステム に依存していますが、あなたが何をしているのか分かっていれば実行可能です。

これが信号ハンドラで動作するかどうかは別の問題です。私は あなたが記述するプラットフォームについては知っていませんが、多くのシステムは シグナルハンドラのための別のスタックをインストールし、ユーザーがアクセス可能なメモリには 割り込みスタックに戻りません。

+0

中断されたスタックに戻るリンクがないことを意味しますか? –

+0

@wood_brianユーザーがアクセス可能なメモリではありません。 (OSは明らかに何らかの形で情報を保持しています。) –

+0

中断された静的を書きました。私はスタックの中断を意味すると思った。 –

4

glibc機能があります。バックトレースです。マニュアルページには、その呼び出しの例がリストされています。

#define SIZE 100 
void myfunc3(void) { 
     int j, nptrs; 

     void *buffer[100]; 
     char **strings; 

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

     /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 
      would produce similar output to the following: */ 

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

詳細はmanページを参照してください。

posixは動作することが保証されているいくつかのリエントラント関数しかリストしていないので、シグナルハンドラから実際に動作することが保証されているかどうかは分かりません。覚えておいてください:シグナルハンドラは、残りのプロセスがmalloc呼び出しの途中で正しく呼び出されることがあります。

私の推測は、これは通常動作しますが、時々失敗する可能性があります。デバッグにはこれで十分です。

関連する問題