16

アプリケーションでマッハ例外をキャプチャするために、独自のマッハ ポートを登録することができました。32 ビットをターゲットにすると、うまく機能します。ただし、64 ビットをターゲットにすると、例外ハンドラーcatch_exception_raise()が呼び出されますが、ハンドラーに渡される例外コードの配列は 32 ビット幅です。これは 32 ビット ビルドでは予想されますが、64 ビットでは予想されません。

私がキャッチした場合EXC_BAD_ACCESS、最初のコードはエラー番号で、2 番目のコードは障害のアドレスです。2 番目のコードは 32 ビット幅であるため、64 ビットの障害アドレスの上位 32 ビットは切り捨てられます。

<mach/exception_types.h>I can pass in task_set_exception_ports()calledのフラグを見つけましたMACH_EXCEPTION_CODES。Darwin ソースを見ると、ハンドラーに渡されるコードのサイズを制御しているように見えます。に渡された動作で ored されることを意図しているようtask_set_exception_ports()です。

ただし、これを実行して例外をトリガーすると、マッハ ポートが通知され、呼び出しexc_server()てもハンドラーが呼び出されず、応答メッセージがカーネルに送り返されると、デフォルトの例外動作が発生します。

10.6 SDK をターゲットにしています。

Appleがこのことをよりよく文書化してくれることを本当に願っています。アイデアはありますか?

4

1 に答える 1

17

さて、私はそれを理解しました。

マッハ例外を処理するには、関心のある例外のマッハポートを登録する必要があります。次に、メッセージが別のスレッドのポートに到着するのを待ちます。メッセージが到着したら、exc_server()System.libraryによって実装が提供されている呼び出しを行います。exec_server()到着したメッセージを受け取り、提供する必要のある3つのハンドラーの1つを呼び出します。catch_exception_raise()、、catch_exception_raise_state()またはcatch_exception_raise_state_identity()に渡した引数によって異なりますtask_set_exception_ports()。これは、32ビットアプリで行われる方法です。

64ビットアプリの場合、32ビット方式は引き続き機能しますが、ハンドラーで渡されるデータは32ビットに切り捨てられる場合があります。64ビットデータをハンドラーに渡すには、少し余分な作業が必要ですが、これは非常に単純ではなく、私が知る限り、十分に文書化されていません。GDBのソースを調べて、ソリューションに出くわしました。

exc_server()メッセージがポートに到着したときに呼び出す代わりに、代わりに呼び出す必要がありますmach_exc_server()catch_mach_exception_raise()ハンドラーには、、、、catch_mach_exception_raise_state()およびも異なる名前を付ける必要がありcatch_mach_exception_raise_state_identity()ます。ハンドラーのパラメーターは、対応する32ビットのパラメーターと同じです。問題は、mach_exc_server()その方法が提供されていないことexc_server()です。の実装を取得するmach_exc_server()には、MIG(Mach Interface Generator)ユーティリティを使用する必要があります。MIGは、インターフェイス定義ファイルを受け取り、指定したハンドラーにマッハメッセージをディスパッチするサーバー関数を含む一連のソースファイルを生成します。10.5および10.6SDKには、例外メッセージ用のMIG定義ファイル<mach_exc.defs>が含まれており、mach_exc_server()働き。次に、生成されたソースファイルをプロジェクトに含めれば、準備は完了です。

良い点は、10.6+(およびおそらく10.5)をターゲットにしている場合、32ビットと64ビットの両方に同じ例外処理を使用できることです。MACH_EXCEPTION_CODES例外ポートを設定するときの例外動作とORするだけです。例外コードは64ビット値として送信されますが、32ビットビルドでは32ビットに切り捨てることができます。

ファイルを取得mach_exc.defsしてソースディレクトリにコピーし、ターミナルを開いてコマンドを使用しましたmig -v mach_exc.defsmach_exc.hこれにより、、、mach_excServer.cおよびが生成されmach_excUser.cました。次に、これらのファイルをプロジェクトに含め、サーバー関数の正しい宣言をソースファイルに追加し、ハンドラーを実装しました。その後、アプリを作成して、準備が整いました。

まあ、これは最良の説明ではありませんが、うまくいけば、それは他の誰かを助けるでしょう。

于 2010-05-15T06:11:28.753 に答える