web-dev-qa-db-ja.com

Xcode / LLDB:スローされたばかりの例外に関する情報を取得する方法は?

さて、objc_exception_throwのブレークポイントがトリガーされたと想像してください。デバッガプロンプトに座っているので、例外オブジェクトに関する詳細情報を取得したいです。どこにありますか?

81
Karoy Lorentey

例外オブジェクトは、_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)
_
157
Karoy Lorentey

新しいシミュレータ(iOS 8、64ビット)xcode 6は例外フレームで使用しています:objc_exception_throw

po $rax

32ビットで:

po $eax

raxとは?

Raxは古いeaxを置き換える64ビットのレジスタです

すべてのレジスタを見つけるには?

register read

ソースウィキペディア

10
João Nunes

この記事を書いている時点では、この投稿は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月に公開され、より現代的なものになりました。

5
Jeff

Catchステートメントがある場合は、そこにブレークポイントを配置すると、その時点で例外オブジェクトを検査できます。

Catchステートメントがない場合は、続行します。

端末に次のようなメッセージが表示されます。

キャッチされない例外 'NSInvalidArgumentException'によるアプリの終了、理由: '*-[__ NSPlaceholderDictionary initWithObjects:forKeys:count:]:オブジェクトからnilオブジェクトを挿入しようとしました[0] '

ただし、アプリケーションを終了するとNiceスタックトレースが失われるため、おそらく続行せずに検査する方法を探しています。

そのためには、Fnordの答えが最善のように思えますが、LLDBで動作させることができませんでした。

0
funroll