7

longjmp 関数がどのように機能するかを理解する必要があります。私はそれが何をするかを知っていますが、それがどのように行うかを知る必要があります.

gdb のコードを disas しようとしましたが、いくつかの手順を理解できません。コードは次のとおりです。

0xb7ead420 <siglongjmp+0>:      push   %ebp
0xb7ead421 <siglongjmp+1>:      mov    %esp,%ebp
0xb7ead423 <siglongjmp+3>:      sub    $0x18,%esp
0xb7ead426 <siglongjmp+6>:      mov    %ebx,-0xc(%ebp)
0xb7ead429 <siglongjmp+9>:      call   0xb7e9828f <_Unwind_Find_FDE@plt+119>
0xb7ead42e <siglongjmp+14>:     add    $0x12bbc6,%ebx
0xb7ead434 <siglongjmp+20>:     mov    %esi,-0x8(%ebp)
0xb7ead437 <siglongjmp+23>:     mov    0xc(%ebp),%esi
0xb7ead43a <siglongjmp+26>:     mov    %edi,-0x4(%ebp)
0xb7ead43d <siglongjmp+29>:     mov    0x8(%ebp),%edi
0xb7ead440 <siglongjmp+32>:     mov    %esi,0x4(%esp)
0xb7ead444 <siglongjmp+36>:     mov    %edi,(%esp)
0xb7ead447 <siglongjmp+39>:     call   0xb7ead4d0
0xb7ead44c <siglongjmp+44>:     mov    0x18(%edi),%eax
0xb7ead44f <siglongjmp+47>:     test   %eax,%eax
0xb7ead451 <siglongjmp+49>:     jne    0xb7ead470 <siglongjmp+80>
0xb7ead453 <siglongjmp+51>:     test   %esi,%esi
0xb7ead455 <siglongjmp+53>:     mov    $0x1,%eax
0xb7ead45a <siglongjmp+58>:     cmove  %eax,%esi
0xb7ead45d <siglongjmp+61>:     mov    %esi,0x4(%esp)
0xb7ead461 <siglongjmp+65>:     mov    %edi,(%esp)
0xb7ead464 <siglongjmp+68>:     call   0xb7ead490
0xb7ead469 <siglongjmp+73>:     lea    0x0(%esi,%eiz,1),%esi
0xb7ead470 <siglongjmp+80>:     lea    0x1c(%edi),%eax
0xb7ead473 <siglongjmp+83>:     movl   $0x0,0x8(%esp)
0xb7ead47b <siglongjmp+91>:     mov    %eax,0x4(%esp)
0xb7ead47f <siglongjmp+95>:     movl   $0x2,(%esp)
0xb7ead486 <siglongjmp+102>:    call   0xb7ead890 <sigprocmask>
0xb7ead48b <siglongjmp+107>:    jmp    0xb7ead453 <siglongjmp+51>

誰かがコードを簡単に説明してくれたり、システム内のソース コードの場所を教えてくれませんか?

4

6 に答える 6

6

これは、標準のi386 ABIでのi386コードでlongjmpあり、C ++、例外、クリーンアップ関数、シグナルマスクなどとの相互作用のためのクレイジーな拡張機能はありません。

    mov 4(%esp),%edx
    mov 8(%esp),%eax
    test %eax,%eax
    jnz 1f
    inc %eax
1:
    mov (%edx),%ebx
    mov 4(%edx),%esi
    mov 8(%edx),%edi
    mov 12(%edx),%ebp
    mov 16(%edx),%ecx
    mov %ecx,%esp
    mov 20(%edx),%ecx
    jmp *%ecx
于 2011-05-26T21:56:25.577 に答える
4

ほとんどの場合、レジスタとスタックは対応する時点の状態に復元されますsetjmp()setjmpの明らかな戻り値とは異なる値を返すだけでなく、いくつかの追加のクリーンアップ (シグナル処理の修正と保留中のスタック ハンドラーのアンワインド) が必要ですが、状態を復元することが操作の本質です。

これが機能するためには、スタックが setjmp が呼び出されたポイントより下にあることはできません。Longjmp は、setjmp が呼び出されたときと同じフレームにスタック ポインターを設定するだけで、コール スタック (または関数呼び出しの入れ子シーケンス) 内の同じレベルまで呼び出されたものをすべて忘れてしまう野蛮な方法です。

正常に機能するために、中間関数のすべての終了ハンドラーをlongjmp()呼び出して、変数を削除できるようにし、関数が戻るときに通常行われるその他のクリーンアップをすべて行います。スタックをより深いポイントにリセットすると、すべてのauto変数が解放されますが、それらのいずれかが である場合はFILE *、ファイルを閉じて、i/o バッファーも解放する必要があります。

于 2011-05-26T21:17:53.347 に答える
3

プロシージャアクティベーションレコードコールスタック、およびSetjmp.hの構造を確認する必要があると思いますjmp_buf

エキスパートCプログラミングからの引用:ディープCの秘密:

Setjmpは、プログラムカウンターと現在のポインターのコピーをスタックの最上位に保存します。これにより、必要に応じていくつかの初期値が保存されます。次に、longjmpはこれらの値を復元して、制御を効果的に転送し、保存を行ったときの状態にリセットします。保存されたものに到達するまでスタックからアクティベーションレコードを展開するため、これは「スタックの巻き戻し」と呼ばれます。

こちらも153ページをご覧ください。

スタックフレームはマシンと実行可能ファイルに大きく依存しますが、考え方は同じです。

于 2011-05-27T08:17:29.047 に答える
0

setjmp() にバッファ パラメータを渡します。次に、現在のレジスタ情報などをこのバッファに格納します。longjmp() への呼び出しは、バッファからこれらの値を復元します。さらに、ウォーリクが言ったこと。

于 2011-05-26T21:30:57.880 に答える