WindowsのSEHについて、これはarticleです。 ここにソースコードmyseh.cppWindowsのSEH、コールスタックトレースバックがなくなった
私はmyseh.cppをデバッグしました。私はprintf("Hello from an exception handler\n");
の行に24とDWORD handler = (DWORD)_except_handler;
をそれぞれ36行で2つのブレークポイントを設定しました。
私はそれを実行し、それはラインで壊れた:36。私はスタックトレースを以下のように見ました。行くよう
、AccessViolationExceptionは、その後、それはラインで破ったためmov [eax], 1
で発生しました:24。私はスタックトレースを以下のように見ました。
同じスレッドが、main
のフレームは消えていました! _except_handle
の代わりに。そしてESPは0018f6c8
から0018ef34
に飛んでいた;それは0018f6c8
と0018ef34
例外の処理後の大きなギャップである。
_except_handle
は、カーネルモードではなくユーザーモードで実行する必要があります。 _except_handle
が返された後、スレッドはring0に変わり、その後WindowsカーネルはCONTEXT EAX
を&scratch
&に変更し、ring3に戻しました。したがって、スレッドは継続的に実行されました。
私は例外を扱うウィンドウのメカニズムについての好奇心:main
を呼び出すフレームは消えていた WHY?
ESPは(私は大きなピッチを意味する)?0018ef34
に0018f6c8
から飛び降りWHY、それらのESPアドレスが同じスレッドのスタックに属していますか?カーネルはring3のESPでいくつかのトリックを果たしましたか?その場合、ハンドラコールバックのフレームとして0018ef34
のアドレスを選択した理由は何ですか?どうもありがとう!
はい同じスレッドのスタックです。カーネルは 'CONTEXT'と' EXCEPTION_RECORD'をユーザスレッドスタックにコピーします。オフコースの騒ぎEspの例外 - これは既にEspの深刻な減少。 'KiUserExceptionDispatcher'コールバックがこのコピーされた' CONTEXT'レコードと 'EXCEPTION_RECORD'レコードへのポインタとともにカーネルから呼び出されます。最後にあなたの '_except_handler'が呼び出されました。 'ContextRecord-> Esp'を探すなら、' main() 'の' Esp'と全く同じであることに気付くことができます。実際のハンドラの実装では '\ VC \ crt \ src \ i386 \ chandler4.c'と' \ VC \ crt \ src \ amd64 \ chandler.c'を参照してください。 – RbMm
ええ、私は、例外が発生したときにCONTEXTをハードウェアのスナップショット。だから、 'ContextRecord-> Esp == Esp(main) 'である。実際には、スタックトレースを失うデバッガのデフォルト設定に責任を負うべきである。 Btw、私は '* ContextRecord'の修正可能性を知っています、それはカーネルがring3に戻る前に望むようにハードウェアのコンテキストを回復する平均です。 WHYは 'const *'ではなく '*'型の第2引数 'ExceptionRecord'ですか? – TanakaYasen
ExceptionRecordは実際にはconstではありません。 ExceptionFlagsは例外処理中に変更されます。私たちはスタックで2回歩いています! 'ExceptionFlags'に' EXCEPTION_UNWIND'フラグをセットし、 '__try/__ finally'ハンドラのスタックを再び歩く' RtlUnwindEx'と呼ばれる 'EXECEPTION_EXECUTE_HANDLER'と' _except_handlerX'を返すまで、 '__try/__ except'ブロックを探します。 'winnt.h'と' wdm.h'に 'IS_DISPATCHING(Flag)'と 'IS_UNWINDING(Flag)'マクロがあるか調べてください - 'chandler.c'も調べてくださいif(IS_DISPATCHING(ExceptionRecord-> ExceptionFlags))switch – RbMm