4

私はここで少し凝ったことをしようとしていますが、ドキュメントはそれが可能であるはずだと示唆しています。LLDBはまだ新しすぎるかもしれませんが、デバッガーのクラッシュやデッドロックが頻繁に発生しており、それが発生しない場合でも、期待どおりに機能していないようです。

コードの特定のチャンク内にメッセージコールグラフを抽出するために、すべてのセレクター呼び出しの周りにデバッグラッパーをまとめようとしています。(本当に知りたいのであれば、その理由を説明できますが、デバッガーの問題にはあまり関係ありません。)

追跡を開始したい行のXcodeブレークポイントから始めます(ボーナスポイントの場合、これはセカンダリスレッドで発生しますが、質問する前に、他のスレッドではこのオブジェクトへのアクセスを行っていません。そのプロパティサブグラフのすべて):

[myObject startProcessing];

ブレークポイントがトリガーされ、以下を抽出するために「bt」を実行します。

* thread #5: tid = 0x2203, 0x000277d2 .........

次に、やや邪悪なことをします。実際のオブジェクトセレクターを呼び出す命令のすぐ近くにあるobjc_msgSendにブレークポイントを設定します。objc_msgSendは次のようになります:

libobjc.A.dylib`objc_msgSend:
...(instructions)...
0x37babfa4:  bx     r12
...(more instructions)...

(実際には2つのbx呼び出しがありますが、物事を単純に保ちましょう。)私は実行します:

breakpoint set -a 0x37babfa4 -t 0x2203

(この1つのスレッドを追跡するのに十分な問題があり、無関係なものが干渉する必要がないため、TIDが含まれています。)

ここでスクリプトが登場します。上記の設定は、私が望むとおりに機能します。ブレークポイントがトリガーされるまで実行を再開すると、次のように実行できます。

frame select 0
thread step-inst -m this-thread 5
frame info
continue

その結果、デバッガーは次のようになります。

  • objc_msgSendフレームに移動します
  • 1つの命令でステップし、それをポイントしていたオブジェクトセレクターフレームに進めます
  • 関連する詳細を表示します(オブジェクトタイプ、呼び出されるセレクター)
  • 実行を再開します

その時点で、これらの4つのコマンドを何度も貼り付け、自分が嫌いになるまで出力をコピーし続けることができます。

一方、私が実行した場合:

breakpoint command add -s command

まったく同じコマンドを貼り付けると、すべてが壊れます。オブジェクトセレクターフレームには進みません。フレームの詳細は表示されないか、少なくとも正しいものは表示されません。さまざまな調整(以下を参照)に応じて、「objc_msgSend」が現在の関数として表示される場合と表示されない場合があります。実行を再開しません。

この場合、その例を機能させることができれば、私は大体幸せになるでしょう。しかし、さらに多くのボーナスポイントについては、Pythonでこれを試しました。これにより、はるかに高度なロギングが可能になるため、次のようになります。

breakpoint command add -s python
> thread = frame.GetThread()
> thread.StepInstruction(1)
> newFrame = thread.GetFrameAtIndex(0)
> print " " * thread.GetNumFrames() + newFrame.GetFunctionName()
> process = thread.GetProcess()
> process.Continue()
> DONE

再びダメ。繰り返しますが、細部に応じて、これは何か(通常はobjc_msgSend)を印刷する場合としない場合がありますが、正しいものを印刷することはありません。命令を前に進めることはありません。その後、実行を再開することはありません。

繰り返しになりますが、Pythonバージョンは、手動で実行すると正常に機能します。ブレークポイントが発生するまで待ってから「script」を実行し、まったく同じ行を入力すると、期待どおりに機能します。一部のパーツは単独でも機能します。たとえば、プロセスを取得してprocess.Continue()を呼び出し、それらを自動的にトリガーする部分を除くすべてを削除すると、「機能」します(つまり、lldbプロンプトが一時停止および再開すると、すばやく点滅します。実行。通常、これは応答しなくなり、すぐにクラッシュするため、後悔しています。)

だから:何かアイデアはありますか?テクノロジーはまだ準備ができていませんか、それともすべてを修正するパズルの巧妙な部分が欠けていますか?それとも、私は完全に諦めて、私が理解できないオブジェクトの内部のいくつかの部分があるという事実だけで生きるべきですか?...

4

1 に答える 1

3

ブレークポイントコマンドは、少なくとも今日は、実行を再開してから再び制御を取り戻すことはできません。ブレークポイント1がプロセスを実行していて、ブレークポイント2がヒットした場合に何が起こるかについては、未解決の質問がたくさんあります。コードベースがネストされたブレークポイントを実際に正しく処理できるかどうか(そのように設計されているかどうか)の質問全体に加えて、ブレークポイント2が実行を停止する必要があると判断した場合はどういう意味ですか?ブレークポイント1の状態は破棄されますか?

下位プロセスをステップ実行しているときにブレークポイントが別のブレークポイントにヒットすることを心配するのは少し難解なようですが、すべての詳細が理解されていない限り、ユーザーは簡単に足を撃ちます。したがって、今日の場合、ブレークポイントコマンドは、ブレークポイントに到達したときに停止するか、実行を継続できますが、少し実行してさらに処理を行う機能はありません。これは特定のタスクにとって非常に便利な機能になることはわかっていますが、実行する前に検討する必要のある落とし穴がたくさんあります。

場合によっては、逆の方法で処理することもできます...関数parser()によって呼び出されたときにのみ関数を停止したい場合は、いくつかのpythonコマンドを使用してlexer()ブレークポイントを設定するのは簡単です。lexer()スタックフレームをスタックし、呼び出し元の関数が何であるかを確認します。そうでない場合はlexer()、続行します。しかし、これはあなたがやろうとしていることに当てはまるとは思いません。

于 2012-10-17T02:31:54.223 に答える