アンワインド プロシージャ

更新 : 2007 年 11 月

アンワインド コード配列を降順に並べ替えます。例外が発生すると、オペレーティング システムによって完全なコンテキストがコンテキスト レコード内に格納されます。次に、例外ディスパッチ ロジックが呼び出されます。例外ディスパッチ ロジックは、例外ハンドラを検索するために繰り返し次のステップを実行します。

  1. コンテキスト レコードに格納された現在の RIP を使用して、現在の関数 (チェーン UNWIND_INFO エントリの場合は、関数の一部) を記述する RUNTIME_FUNCTION テーブル エントリを検索します。

  2. 関数テーブル エントリが見つからない場合、関数テーブル エントリはリーフ関数内にあるため、RSP はリターン ポインタを直接アドレス指定します。[RSP] のリターン ポインタは、更新されたコンテキスト内に格納され、シミュレートされた RSP は 8 ずつインクリメントされ、ステップ 1 が繰り返されます。

  3. 関数テーブル エントリが見つかった場合、RIP は、a) エピローグ、b) プロローグ、c) 例外ハンドラによって処理されるコード、の 3 つの領域内のいずれかに配置されます。

    • ケース a) RIP がエピローグ内に配置されると、コントロールは関数を無視します。この関数のこの例外に関連付けられた例外ハンドラが存在しない可能性があるので、呼び出し元関数のコンテキストを計算するためにエピローグの効果を継続させる必要があります。RIP がエピローグ内にあるかどうかを判断するには、RIP からのコード ストリームを調べます。該当するコード ストリームが正規のエピローグの末尾部分に一致する場合、RIP はエピローグ内にあり、エピローグのその他の部分がシミュレートされ、命令が処理されるたびにコンテキスト レコードが更新されます。この後、ステップ 1 が繰り返されます。

    • ケース b) RIP がプロローグ内に配置された場合、コントロールに関数が入力されていません。この関数のこの例外に関連付けられた例外ハンドラが存在しない可能性があるので、呼び出し元関数のコンテキストを計算するためにプロローグの効果を元に戻す必要があります。関数の開始から RIP までの距離がアンワインド情報でエンコードされたプロローグのサイズ以下である場合、RIP はプロローグ内に配置されています。関数の開始からの RIP のオフセット以下のオフセットを持つ最初のエントリのアンワインド コード配列を前方向にスキャンし、アンワインド コード配列内の残りの項目すべての効果を元に戻すことで、プロローグの効果がアンワインドされます。次に、ステップ 1 が繰り返されます。

    • ケース c) RIP がプロローグまたはエピローグ内に配置されず、関数に例外ハンドラが存在する (UNW_FLAG_EHANDLER が設定されている) 場合、言語固有のハンドラが呼び出されます。ハンドラはそのデータをスキャンし、適宜フィルタ関数を呼び出します。言語固有のハンドラは、例外が処理済みであること、または検索を続行することを返します。また、言語固有のハンドラは、アンワインドを直接実行することもできます。

  4. 言語固有のハンドラが処理済みステータスを返すと、元のコンテキスト レコードを使用して実行が継続されます。

  5. 言語固有のハンドラが存在しないか、言語固有のハンドラが "継続検索"ステータスを返す場合、コンテキスト レコードを呼び出し元の状態にアンワインドする必要があります。これを実行するには、アンワインドコード配列のすべての要素を処理し、各要素の効果を元に戻します。次に、ステップ 1 が繰り返されます。

チェーン アンワインド情報が含まれる場合も、これらの基本ステップが実行されます。唯一の違いは、プロローグの効果をアンワインドするためにアンワインド コード配列を検索しているときに、配列の終わりに到達すると、アンワインド コード配列が親アンワインド情報にリンクされ、そこで発見されたアンワインド コード配列全体を検索することです。UNW_CHAINED_INFO フラグがないアンワインド情報に到達し、そのアンワインド コード配列の検索が終了するまで、このリンクは継続されます。

アンワインド データの最小セットは、8 バイトです。この 8 バイトが、128 バイト以下のスタックのみを割り当てた関数を表す場合もあれば、1 つの不揮発性レジスタを保存している可能性のある関数を表す場合もあります。また、これはアンワインド コードを持たない長さ 0 のプロローグのチェーン アンワインド情報のサイズでもあります。

参照

参照

例外処理 (x64)