さて、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)
_
新しいシミュレータ(iOS 8、64ビット)xcode 6は例外フレームで使用しています:objc_exception_throw
po $rax
32ビットで:
po $eax
raxとは?
Raxは古いeaxを置き換える64ビットのレジスタです
すべてのレジスタを見つけるには?
register read
この記事を書いている時点では、この投稿はGoogleで最もヒットしているものです:lldb print exception。したがって、私はこの答えを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] '
ただし、アプリケーションを終了するとNiceスタックトレースが失われるため、おそらく続行せずに検査する方法を探しています。
そのためには、Fnordの答えが最善のように思えますが、LLDBで動作させることができませんでした。