-1

プログラムカウンター(命令ポインター)の内容を変更したい。C でシステム シグナル ハンドラをオーバーライドすることで、システム スタック フレームでポインタを取得できると考えました。そこから、関数の戻りアドレスを取得して変更できます。

ただし、スタック内のポインターを取得しましたが、リターンアドレスがスタックフレームのどこに格納されているか正確にはわかりません。

void signal_handler(int signal){

   char* ptr = (char*) & signal;
   // As, signal is stored on the paramter list of the stack, 
   // I get the address in the current stack frame. From , here
   // I want to change the return address(that is stored in the 
   // current stack frame).
}
4

2 に答える 2

4

セグメンテーション違反の後、プログラムは不確定な状態になります。正しい値を持つもの (レジスターなど) に依存することはできなくなります。

フォルトの後に次の命令に戻ることができたとしても、シグナル ハンドラが問題のある命令を [コンテキスト内で] 逆アセンブルし、レジスタ値を変更して補償しない限り、プログラムは信頼できず、おそらく segfault または segfault を続行することになります。 [さらに悪い] はるかに悲惨な結果 (たとえばunlink間違ったファイルなど) で操作します。

しかし、「トランポリン」という信号のため、これを行うことはできません。詳細については、sigreturnman ページを参照してください。シグナル ハンドラに渡されるスタック フレームは、必ずしも通常のものとは限りません。

プログラムを既知の「安全な」状態に復元する必要があります。それを行う唯一の方法は、[上記のコメントで述べたように]シグナル ハンドラーを使用して復旧ポイントを設定し、内部でsigsetjmp実行することです。補足:これらの使用は、 で例外を使用するのと似ていますが、手動でより多くの作業を行う必要があります。siglongjmpC++

私は多くの segfault キャッチ シグナル ハンドラをリカバリで実行しましたが、それらはすべてsigsetjmp/siglongjmp.

これはまた疑問を投げかけます: そもそもセグメンテーション違反を起こさないようにプログラムをデバッグしないのはなぜですか? これを妨げる特別なニーズは何ですか?

于 2016-01-29T00:00:51.053 に答える