OK、ブレークポイントobjc_exception_throw
がトリガーされたところを想像してみてください。デバッガープロンプトに座っていますが、例外オブジェクトに関する詳細情報を取得したいと思います。どこにありますか?
OK、ブレークポイントobjc_exception_throw
がトリガーされたところを想像してみてください。デバッガープロンプトに座っていますが、例外オブジェクトに関する詳細情報を取得したいと思います。どこにありますか?
回答:
例外オブジェクトは、最初の引数としてに渡されますobjc_exception_throw
。LLDBは、正しい呼び出し規約で引数を参照するための$arg1
..$argn
変数を提供し、例外の詳細を簡単に出力できるようにします。
(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
objc_exception_throw
これらのコマンドを実行する前に、必ずコールスタックでフレームを選択してください。これがステージで実行されることを確認するには、WWDC15セッションビデオの「高度なデバッグとアドレスサニタイザー」を参照してください。
古い情報
GDBを使用している場合、最初の引数を参照する構文は、実行しているアーキテクチャの呼び出し規約によって異なります。実際のiOSデバイスでデバッグしている場合、オブジェクトへのポインターはレジスターにありr0
ます。印刷またはメッセージを送信するには、次の簡単な構文を使用します。
(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]
iPhoneシミュレーターでは、すべての関数の引数がスタックに渡されるため、構文はかなりひどいものになります。それに到達するために私が構築できる最短の式は*(id *)($ebp + 8)
です。苦痛を軽減するために、便利な変数を使用することをお勧めします。
(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]
$exception
コマンドリストをobjc_exception_throw
ブレークポイントに追加することにより、ブレークポイントがトリガーされるたびに自動的に設定することもできます。
(テストしたすべてのケースで、ブレークポイントがヒットしたときに例外オブジェクトがeax
とedx
レジスタにも存在していたことに注意してください。ただし、常にそうなるかどうかはわかりません。)
以下のコメントから追加:
でlldb、用スタックフレームを選択objc_exception_throw
して、次のコマンドを入力します。
(lldb) po *(id *)($esp + 4)
objc_exception_throw
にLLDB:po *(id *)($esp + 4)
。
objc_exception_throw
)。
po $eax
シミュレーターでは、$r0
デバイス上にあるときのペンダントとして機能します。
新しいシミュレーター(iOS 8、64ビット)の場合、例外フレームで使用するxcode 6 im: objc_exception_throw
po $rax
32ビット:
po $eax
ラックスとは何ですか?
Raxは、古いeaxを置き換える64ビットレジスタです。
すべてのレジスタを見つける方法は?
register read
この記事の執筆時点で、この投稿は、lldb printexceptionに対するGoogleのトップヒットです。したがって、lldbとx86_64を説明するためにこの回答を追加しています。
を使用po $eax
して例外を見つけようとして失敗しましたerror: Couldn't materialize struct: Couldn't read eax (materialize)
。以前の回答からのリンクされたドキュメントに記載されている他の試みも失敗しました。
重要なのは、最初objc_exception_throw
にメインスレッドのフレームをクリックする必要があったことです。lldbはそのフレームで開始されません。
私の検索と次のすべての例で、このブログエントリは私にとってうまくいく方法で物事を説明した最初のものでした。それはより現代的で、2012年8月に投稿されました。
catchステートメントがある場合は、そこにブレークポイントを設定すると、その時点で例外オブジェクトを検査できます。
catchステートメントがない場合は、続行してください。
ターミナルに次のようなメッセージが表示されます。
キャッチされなかった例外 'NSInvalidArgumentException'が原因でアプリを終了しています、理由: ' * -[__ NSPlaceholderDictionary initWithObjects:forKeys:count:]:オブジェクトからnilオブジェクトを挿入しようとしています[0]'
ただし、アプリケーションが終了するとスタックトレースが失われるため、続行せずに検査する方法を探している可能性があります。
そのため、Fnordの答えが最善のように思えますが、LLDBで機能させることができませんでした。