ホームページ  >  記事  >  システムチュートリアル  >  Linux デバッガ スタックの拡張!

Linux デバッガ スタックの拡張!

王林
王林転載
2024-01-06 22:25:43961ブラウズ
###導入### 知っておくべき最も重要な情報は、現在のプログラムの状態がどのようにしてそこに到達したかということである場合があります。 backtrace コマンドがあり、プログラムの現在の関数呼び出しチェーンを取得できます。この記事では、x86_64 でスタックの巻き戻しを実装してこのようなトレースバックを生成する方法を説明します。 シリーズインデックス
これらのリンクは、他の投稿が公開されると公開されます。

環境の準備
  1. ブレークポイント
  2. レジスタとメモリ
  3. エルフとドワーフ
  4. ソースコードとシグナル
  5. ソースコードレベルのステップバイステップ実行
  6. ソースレベルのブレークポイント
  7. スタックの拡張
  8. 変数の読み取り
  9. ###次のステップ###
  10. 次のプログラムを例として使用します:
  11. リーリー
  12. デバッガが //stopped here' 行で停止した場合、そこに到達する方法は 2 つあります: main->b->a または main->c->a`。 LLDB でブレークポイントを設定し、実行を継続してトレースバックを要求すると、次の結果が得られます。 リーリー
これは、現在関数 a にいて、a は関数 b からジャンプし、b はメインからジャンプする、ということを意味します。最後の 2 つのフレームは、コンパイラーが main 関数をブートストラップする方法です。

問題は、それを x86_64 にどのように実装するかです。最も堅牢なアプローチは、ELF ファイルの .eh_frame 部分を解析し、そこからスタックを巻き戻す方法を見つけることですが、それは面倒です。 libunwind などを使用して実行することもできますが、それは退屈です。代わりに、コンパイラが何らかの方法でスタックを設定していると想定し、それを手動で走査します。これを行うには、まずスタックのレイアウトを理解する必要があります。

リーリー

ご覧のとおり、最後のスタック フレームのフレーム ポインタは現在のスタック フレームの先頭に格納され、ポインタのリンク リストが作成されます。スタックはこのリンクされたリストに基づいてアンワインドされます。 DWARF メッセージ内の戻りアドレスを検索することで、リスト内の次のフレームの関数を見つけることができます。一部のコンパイラは、EBP のフレーム ベース アドレスの追跡を無視します。これは、これが ESP からのオフセットとして表現され、追加のレジスタが解放されるためです。最適化が有効になっている場合でも、-fno-omit-frame-pointer を GCC または Clang に渡すと、依存する規則に強制的に従うことになります。

print_backtrace 関数ですべての作業を行います:

リーリー

最初に決定することは、フレーム情報を出力するためにどの形式を使用するかです。このメソッドを展開するにはラムダを使用しました:

リーリー

印刷される最初のフレームは、現在実行中のフレームです。 DWARF で現在のプログラム カウンターを検索することで、このフレームに関する情報を取得できます:

リーリー

次に、フレーム ポインターと現在の関数の戻りアドレスを取得する必要があります。フレーム ポインタは rbp レジスタに格納され、リターン アドレスはフレーム ポインタからスタックされた 8 バイトです。

リーリー

これで、スタックを拡張するために必要な情報がすべて揃いました。デバッガーが main に到達するまで巻き戻しを続けますが、フレーム ポインターが 0x0 のときに停止することも選択できます。これは、main 関数を呼び出す前に呼び出す関数です。各フレームからフレーム ポインターと戻りアドレスを取得し、情報を出力します。

リーリー ###それでおしまい!関数全体は次のとおりです:

リーリー

コマンドを追加

もちろん、このコマンドをユーザーに公開する必要があります。

リーリー ###テスト###

この機能をテストする 1 つの方法は、相互に呼び出しを行う多数の小さな関数を含むテスト プログラムを作成することです。いくつかのブレークポイントを設定し、コードの近くにジャンプして、トレースバックが正確であることを確認します。

私たちは、他のプログラムを生成して接続することしかできないプログラムから長い道のりを歩んできました。このシリーズの最後から 2 番目の記事では、変数の読み取りと書き込みをサポートすることでデバッガーの実装を完了します。それまでは、この投稿のコードをここで見つけることができます。

以上がLinux デバッガ スタックの拡張!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlinuxprobe.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。