第20章 実行中のアプリケーションのデバッグ

本章では、開発者が直接アクセスできるマシンで、必要に応じて何度でも起動でき、アプリケーションをデバッグする方法を紹介します。

20.1. デバッグ情報を使用したデバッグの有効化

アプリケーションやライブラリーをデバッグするには、デバッグ情報が必要です。以下のセクションでは、この情報を取得する方法を説明します。

20.1.1. デバッグの情報

実行可能なコードをデバッグする場合に、ツールやプログラマーは 2 種類の情報を使用して、バイナリーコードを理解することができます。

  • ソースコードテキスト
  • ソースコードテキストがバイナリーコードにどのように関連しているのかの説明

上記がデバッグ情報と呼ばれるものです。

Red Hat Enterprise Linux は、実行可能なバイナリー、共有ライブラリー、または debuginfo ファイルに ELF 形式を使用します。この ELF ファイルでは、DWARF 形式を使用してデバッグ情報を保持します。

DWARF シンボルは、readelf -w file コマンドを使用して読み込みます。

注意

STABS は UNIX で使用される場合もあります。STABS は、機能が少ない旧式の形式です。Red Hat は、STABS の使用は推奨していません。GCC および GDB は、STABS の実稼働および使用はベストエフォートでのみサポートされます。Valgrind および elfutils などの他のツールでは、STABS のサポートはありません。

関連資料

20.1.2. GCC を使用した C および C++ アプリケーションのデバッグの有効化

デバッグの情報が大きい場合には、デフォルトでは実行可能ファイルは含まれません。GCC を使用した C および C++ アプリケーションのデバッグを有効化するには、コンパイラーに対して、ファイルを作成するように、明示的に指示する必要があります。

GCC を使用したデバッグ情報の作成の有効化

コードのコンパイルおよびリンク時には GCC でデバッグ情報の作成を有効化するには、-g オプションを使用します。

$ gcc ... -g ...
  • コンパイラーとリンカーで最適化を行うと、実行可能なコードを、元のソースコードと関連付けることが難しくなります。変数の最適化、ループのアンロール、周りの操作へのマージなどが行われる可能性があります。デバッグの体験を向上するには、-Og オプションを指定して、最適化を設定することを考慮してください。ただし、最適化レベルを変更すると、実行可能なコードが変更され、バグを取り除くための実際の動作が変更される可能性があります。
  • -fcompare-debug GCC オプションでは、GCC でコンパイルしたコードを、デバッグ情報を使用して (または、デバッグ情報を使用せずに) テストします。このテストでは、出力されたバイナリーファイル 2 つが同一であれば合格します。このテストを行うことで、実行可能なコードはデバッグオプションによる影響は受けないようにするだけでなく、デバッグコードにバグが含まれないようにします。-fcompare-debug オプションを使用するとコンピレーションの時間が大幅に伸びます。このオプションに関する詳細情報は、GCC の man ページを参照してください。
関連資料

20.1.3. Debuginfo パッケージ

Debuginfo パッケージには、プログラムとライブラリーのデバッグ情報と、デバッグソースコードが含まれます。

前提条件
Debuginfo パッケージ

Red Hat Enterprise Linux リポジトリーのパッケージにインストールされているアプリケーションやライブラリーの場合は、別のチャンネルで提供されている別の debuginfo パッケージにとしてデバッグ情報とデバッグソースコードを取得することができます。debuginfo パッケージには .debug ファイルが含まれており、その中には、バイナリーパッケージのコンパイルに使用する DWARF debuginfo とソースファイルがあります。Debuginfo パッケージのコンテンツは、/usr/lib/debug ディレクトリーにインストールされます。

debuginfo パッケージでは、名前、バージョン、リリース、アーキテクチャーが同じバイナリーパッケージでのみ有効なデバッグ情報が提供されます。

  • バイナリーパッケージ: packagename-version-release.architecture.rpm
  • Debuginfo パッケージ: packagename-debuginfo-version-release.architecture.rpm

20.1.4. GDB を使用したアプリケーションまたはライブラリー向けの debuginfo パッケージ取得

GNU デバッガー (GDB) は、自動的に足りないデバッグ情報を認識して、パッケージ名を解決します。

前提条件
手順
  1. デバッグするアプリケーションまたはライブラリーにアタッチされている GDB を起動します。GDB は自動的に、足りないデバッグ情報を認識して、実行するコマンドを提案します。

    $ gdb -q /bin/ls
    Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done.
    (no debugging symbols found)...done.
    Missing separate debuginfos, use: debuginfo-install coreutils-8.22-21.el7.x86_64
    (gdb)
  2. これ以上何もせずに、GDB を終了します。q を入力して、Enter を押します。

    (gdb) q
  3. GDB が提案するコマンドを実行して、必要な debuginfo パッケージをインストールします。

    # debuginfo-install coreutils-8.22-21.el7.x86_64

    アプリケーションまたはライブラリーの debuginfo パッケージをインストールすると、依存関係の debuginfo パッケージもすべてインストールされます。

  4. GDB が debuginfo パッケージを提案できない場合には、「手動でのアプリケーションまたはライブラリー向けの debuginfo パッケージ取得」の手順に従ってください。
関連資料

20.1.5. 手動でのアプリケーションまたはライブラリー向けの debuginfo パッケージ取得

実行可能ファイルの場所を特定して、そのファイルをインストールするパッケージを検索し、インストール用の debuginfo パッケージを手動で判断できます。

注記

GDB を使用してインストールするパッケージを決定すること を推奨します。GDB によりインストールするパッケージが提案されない場合にのみ、この手動の手順を使用してください。

前提条件
手順
  1. アプリケーションまたはライブラリーの実行可能ファイルを検索します。

    1. which コマンドを使用して、アプリケーションファイルを検索します。

      $ which nautilus
      /usr/bin/nautilus
    2. locate コマンドを使用して、ライブラリーファイルを検索します。

      $ locate libz | grep so
      /usr/lib64/libz.so
      /usr/lib64/libz.so.1
      /usr/lib64/libz.so.1.2.7

      デバッグの理由がエラーメッセージに含まれていた場合には、ライブラリーのファイル名に同じ追加の数字が含まれる結果を選択します。分からない場合は、ライブラリーのファイル名に追加の数字が含まれていない結果を使用して、残りの手順を実行してください。

      注記

      locate コマンドは mlocate パッケージで提供されます。このパッケージをインストールして使用を有効にするには以下を実行します。

      # yum install mlocate
      # updatedb
  2. ファイルパスを使用して、対象のファイルを提供するパッケージを検索します。

    # yum provides /usr/lib64/libz.so.1.2.7
    Loaded plugins: product-id, search-disabled-repos, subscription-manager
    zlib-1.2.7-17.el7.x86_64 : The compression and decompression library
    Repo        : @anaconda/7.4
    Matched from:
    Filename    : /usr/lib64/libz.so.1.2.7

    この出力では、name-version.distribution.platform の形式でパッケージ一覧が表示されます。yum の出力で表示されるバージョンは実際にインストールされているバージョンでない場合があるので、この手順では、パッケージの 名前 のみが重要です。

    重要

    この手順では結果が返されないので、どのパッケージがバイナリーファイル用のパッケージであるか、この手順が失敗したかの判断ができません。

  3. rpm の低レベルのパッケージ管理ツールを使用して、どのパッケージバージョンがシステムにインストールされているのかを確認します。パッケージ名を引数として使用します。

    $ rpm -q zlib
    zlib-1.2.7-17.el7.x86_64

    この出力では、name-versiondistribution.platform の形式でインストールされたパッケージの詳細が表示されます。

  4. debuginfo-install ユーティリティーを使用して debuginfo パッケージをインストールします。このコマンドでは、前の手順で判断したパッケージ名などの情報を使用します。

    # debuginfo-install zlib-1.2.7-17.el7.x86_64

    アプリケーションまたはライブラリーの debuginfo パッケージをインストールすると、依存関係の debuginfo パッケージもすべてインストールされます。

関連資料

20.2. GDB を使用したアプリケーションの内部状況の検証

アプリケーションが正しく機能しない理由を特定するには、実行を管理して、デバッガーの内部状況を検証します。このセクションでは、このタスクにおける GNU デバッガー (GDB) の使用方法を説明します。

20.2.1. GNU デバッガー (GDB)

デバッガーは、コード実行の制御や、コードの状態の検証を有効にするツールです。この機能は、プログラム内で何が発生しているのか、またその発生理由についての調査に使用します。

Red Hat Enterprise Linux には、コマンドラインユーザーインターフェースで機能を使用できる GNU デバッガー (GDB) が含まれます。

GDB へのグラフィカルフロントエンドについては、Eclipse 統合開発環境をインストールします。「Using Eclipse」を参照してください。

GDB 機能

単一の GDB セッションで、以下をデバッグできます。

  • マルチスレッドやフォーク用のプログラムをデバッグ
  • 一度に複数のプログラムをデバッグ
  • TCP/IP ネットワーク接続経由で接続された gdbserver ユーティリティーを使用するコンテナー内または、リモートマシンのプログラムをデバッグ
デバッグの要件

実行可能なコードをデバッグするには、GDB では、適切なデバッグ情報が必要です。

  • 自分で開発したプログラムの場合は、コードの構築時にデバッグ情報を作成できます。
  • パッケージからインストールしたシステムプログラムの場合は、適切な debuginfo パッケージをインストールする必要があります。

20.2.2. プロセスへの GDB のアタッチ

プロセスを検証するには、GDB はプロセスに アタッチ する必要があります。

前提条件
GDB でのプログラムの起動

プログラムがプロセスとして実行されていない場合は、GDB でプログラムを起動します。

$ gdb program

program は、ファイル名またはプログラムへのパスに置き換えます。

GDB は、プログラムの実行を開始するように設定します。ブレークポイントと gdb 環境を設定してから、run コマンドでプロセスの実行を開始するようにしてください。

すでに実行中のプロセスへの GDB のアタッチ

プロセスとしてすでに実行中のプログラムに GDB をアタッチするには、以下を実行します。

  1. ps コマンドで、プロセス id (pid) を検索します。

    $ ps -C program -o pid h
     pid

    program は、ファイル名またはプログラムへのパスに置き換えます。

  2. このプロセスに GDB をアタッチします。

    $ gdb -p pid

    pid は、ps の出力にある実際のプロセス id の数字に置き換えます。

すでに実行中のプロセスに実行中の GDB をアタッチする手順

すでに実行中のプロセスに実行中の GDB をアタッチします。

  1. shell GDB コマンドを使用して、ps コマンドを実行し、プログラムのプロセス id (pid) を特定します。

    (gdb) shell ps -C program -o pid h
     pid

    program は、ファイル名またはプログラムへのパスに置き換えます。

  2. attach コマンドを使用して、GDB をプログラムにアタッチします。

    (gdb) attach pid

    pid は、ps の出力にある実際のプロセス id の数字に置き換えます。

注記

場合によっては GDB は適切な実行可能ファイルを検索できない可能性があります。file コマンドを使用して、パスを指定してください。

(gdb) file path/to/program
関連資料

20.2.3. GDB でのプログラムコードの活用

GDB デバッガーがプログラムにアタッチされたら、複数のコマンドを使用して、プログラムの実行を制御できます。

前提条件
コードを活用するための GDB コマンド
r (run)
プログラムの実行を開始します。引数を指定して run を実行すると、プログラムが通常通り開始されたかのように、その引数が実行可能ファイルに渡されます。ユーザーは通常、ブレークポイントを設定してから、このコマンドを実行します。
start
プログラムの実行を開始し、プログラムの主な機能の開始時点で停止します。引数を指定して start を実行すると、これらの引数は、プログラムが通常に起動したかのように、実行可能ファイルに渡されます。
c (continue)

現在の状態からプログラムの実行を継続します。プログラムの実行は、以下のいずれかが真になるまで継続されます。

  • ブレークポイントに到達した場合
  • 指定の条件を満たした場合
  • プログラムからシグナルを受け取った場合
  • エラーが発生した場合
  • プログラムが終了された場合
n (next)

現在のソースファイルでコードが次の行に移動するまで、現在の状態からプログラムの実行を続けます。プログラムの実行は、以下の内容が真になるまで継続されます。

  • ブレークポイントに到達した場合
  • 指定の条件を満たした場合
  • プログラムからシグナルを受け取った場合
  • エラーが発生した場合
  • プログラムが終了された場合
s (step)
step コマンドは、現在のソースファイルのコード行ごとに実行を停止させます。ただし、実行が 関数呼び出し が含まれるソースの行で停止中の場合には、GDB は (関数呼び出しを実行するのではなく)、関数呼び出しに入る前に実行を停止します。
until location
location で指定したコードの場所に到達するまで、実行が継続されます。
fini (finish)

プログラムの実行を再開し、実行が関数から戻り値として返された時点で停止します。プログラムの実行は、以下のいずれかが真になるまで継続されます。

  • ブレークポイントに到達した場合
  • 指定の条件を満たした場合
  • プログラムからシグナルを受け取った場合
  • エラーが発生した場合
  • プログラムが終了された場合
q (quit)
実行を中断して、GDB を終了します。
関連資料

20.2.4. GDB でのプログラム内部値の表示

プログラムの内部変数の値を表示することは、プログラムが何を実行しているかを理解する場合に重要です。GDB には、内部変数の検証に使用可能なコマンドが複数含まれています。このセクションでは、これらのコマンドの中で最も有用なものを説明します。

前提条件
  • GDB デバッガーを理解していること
プログラムの内部の状態を表示するための GDB コマンド
p (print)

指定した引数の値を表示します。引数には通常、単純な値 1 つや構造など、あらゆる複雑性の変数名を指定できます。引数には、プログラム変数やライブラリー関数での用途、テストするプログラムに定義する関数など、現在の言語で有効な表現も指定できます。

pretty-printer Python または Guile スクリプトを使用して GDB を拡張し、print コマンドを使用して、(クラス、構造など) データ構造をカスタマイズ表示することができます。

bt (backtrace)

現在の実行ポイントに到達するために使用する関数呼び出しチェーンや、実行が中断されるまで使用する関数チェーンを表示します。これは、原因を特定しにくい、深刻なバグ (セグメント障害など) を調査する場合に便利です。

backtrace コマンドに full オプションを追加すると、ローカルの変数も表示されます。

frame filter Python スクリプトを使用して GDB を拡張し、btinfo frame コマンドでデータをカスタマイズして表示することができます。frame は、単一の関数呼び出しに関連付けられたデータを参照します。

info

info コマンドは、様々な項目に関する情報を表示するための汎用コマンドです。このコマンドでは、説明を確認する項目をオプションとして指定できます。

  • info args コマンドは、現在選択されているフレームの関数呼び出しオプションを表示します。
  • info locals コマンドは、現在選択されているフレームにローカルの変数を表示します。

指定可能なオプションを一覧表示するには、GDB セッションで help info のコマンドを実行します。

(gdb) help info
l (list)
プログラムが停止したソースコードの行を表示します。このコマンドは、プログラムの実行が停止された場合のみ利用できます。list は、内部の状態を厳密に表示するコマンドではありませんが、プログラム実行の次のステップでどのような変更が内部状態に加えられるのかを理解することができます。
関連資料

20.2.5. 定義したコードの場所で実行を停止するための GDB ブレークポイントの使用

多くの場合、特定のコードの行に到達するまでプログラムを実行させると有益です。

前提条件
  • GDB を理解していること
GDB でのブレークポイントの使用

ブレークポイントは、プログラムの実行を停止するように GDB に指示を出すためのマーカーです。ブレークポイントは一般的に、ソースコードの行と関連付けられており、ブレークポイントを配置するには、ソースファイルと行数を指定する必要があります。

  • ブレークポイントを配置する方法:

    • ソースコードの ファイル 名と、そのファイルの を指定します。

      (gdb) br file:line
    • file がない場合には、現在実行中のポイントのソースファイル名を使用します。

      (gdb) br line
    • または、関数名を使用して、起動時にブレークポイントを配置します。

      (gdb) br function_name
  • タスクを特定の回数反復すると、プログラムにエラーが発生する可能性があります。実行を停止するには、追加の 条件 を指定します。

    (gdb) br file:line if condition

    condition は、C または C++ 言語の条件に置き換えます。fileline は、上記と同様に、ファイル名および行数に置き換えます。

  • 全ブレークポイントおよびウォッチポイントの状態を 検証 するには以下を実行します。

    (gdb) info br
  • info br の出力で表示された 数字 を使用して、ブレークポイントを 削除するには 以下を実行します。

    (gdb) delete number
  • 指定の場所のブレークポイントを 削除 するには以下を実行します。

    (gdb) clear file:line
関連資料

20.2.6. データへのアクセスや変更が合った場合に実行を停止するための GDB ウォッチポイントの使用

多くの場合、特定のデータが変更されるまで、または特定のデータにアクセスがあるまで、プログラムを実行させるようにすると有益です。このセクションでは、一般的なコマンドについて説明します。

前提条件
  • GDB の理解
GDB でのウォッチポイントの章

ウォッチポイントは、プログラム実行を停止するように GDB に指示を出すマーカーです。ウォッチポイントは、データと関連付けられており、ウォッチポイントを配置するには、変数を記述する表現、複数の変数、またはメモリーアドレスを指定する必要があります。

  • データを 変更 (書き込み) するために、ウォッチポイントを 配置 します。

    (gdb) watch expression

    expression は、ウォッチの対象を記述する表現に置き換えます。変数の場合は、expression は変数名と同じです。

  • データに アクセス (読み取り) するために、ウォッチポイントを 配置 します。

    (gdb) rwatch expression
  • あらゆる データにアクセス (読み取りおよび書き込み) するために、ウォッチポイントを 配置 します。

    (gdb) awatch expression
  • 全ウォッチポイントおよびブレークポイントの状態を 検証 するには以下を実行します。

    (gdb) info br
  • ウォッチポイントを 削除 するには以下を実行します。

    (gdb) delete num

    num オプションは、info br コマンドで報告された数字に置き換えます。

関連資料

20.2.7. GDB でのフォーク用またはスレッド化されたプログラムのデバッグ

プログラムによっては、コードを並行実行するためにフォークまたはスレッドを使用するものがあります。複数同時に実行パスをデバッグするには、特別な留意点があります。

前提条件
  • GDB デバッガーを理解していること
  • フォークおよびスレッドプロセスのコンセプトを理解していること
GDB でのフォークされたプログラムのデバッグ

フォークとは、プログラム () により、独立したコピー () を作成する状況のことを指します。以下の設定およびコマンドを使用して、フォークを行う場合に GDB にどのような動作をさせるかを決定します。

  • follow-fork-mode 設定で、フォークの後に GDB が親、子どちらに従うのかを制御します。

    set follow-fork-mode parent
    フォークの後に、親のプロセスをデバッグします。これはデフォルトです。
    set follow-fork-mode child
    フォークの後に子のプロセスをデバッグします。
    show follow-fork-mode
    follow-fork-mode の現在の設定を表示します。
  • set detach-on-fork 設定では、GDB が (フォローしていない) 他のプロセスを制御するか、そのまま実行させるかを制御します。

    set detach-on-fork on
    フォローしていないプロセス (follow-fork-mode の値による) は切り離され、別個で実行されます。これはデフォルトです。
    set detach-on-fork off
    GDB は両プロセスを制御します。フォローしているプロセス (follow-fork-mode の値による) は通常通りにデバッグされ、他は一時停止されます。
    show detach-on-fork
    detach-on-fork の現在の設定を表示します。
GDB でのスレッド化されたプログラムのデバッグ

GDB には、個別のスレッドをデバッグし、そのスレッドを個別に操作および検査する機能があります。GDB を使用して、検証したスレッドのみを停止させるには、set non-stop on および set target-async on のコマンドを使用します。これらのコマンドは、.gdbinit ファイルに追加することができます。この機能をオンにすると、GDB でスレッドのデバッグを行う準備が整います。

GDB は current thread のコンセプトを使用します。デフォルトでは、コマンドは現在のスレッドのみに適用されます。

info threads
現在のスレッドを指す idgid の数字を使用してスレッドの一覧を表示します。
thread id
id を指定して現在のスレッドとして、スレッドを設定します。
thread apply ids command
command コマンドを ids で表示されたスレッドすべてに適用します。ids オプションは、スペースで区切られたスレッド ID です。特別な値 all でこのコマンドを全スレッドに適用します。
break location thread id if condition
スレッド番号 id に対してのみ、特定の condition の特定 location で、ブレークポイントを設定します。
watch expression thread id
スレッド番号 id に対してのみ、expression で定義したウォッチポイントを設定します。
command&
コマンド command を実行して、すぐに gdb プロンプト (gdb) に戻りますが、バックグラウンドでコードの実行が続行されます。
interrupt
バックグラウンドでの実行が停止されます。
関連資料

20.3. アプリケーションの対話の記録

アプリケーションの実行可能コードは、オペレーティングシステムや共有ライブラリーのコードと対話します。これらの対話に関するアクティビティーログを記録すると、実際のアプリケーションコードをデバッグせずに、アプリケーションの動作を詳細にわたり知ることができます。また、アプリケーションの対話を分析すると、バグが発生した状況をピンポイントで特定しやすくなります。

20.3.1. アプリケーションの対話の記録に役立つツール

Red Hat Enterprise Linux には、アプリケーションの対話を分析するための複数のツールが含まれます。

strace

strace ツールは主に、アプリケーションが使用するシステム呼び出し (カーネルの関数) のログ記録を有効化します。

  • strace は、パラメーターを解釈し、下層のカーネルコードのナレッジを結果として提供するので、strace 出力は詳細にわたり、呼び出しに関する詳しい情報を提供します。数字は、適切な定数名に変換され、ビット単位で統合されたフラグはフラグ一覧に拡張され、文字配列に対するポインターは実際の文字列を提供するために逆参照されます。最新のカーネル機能のサポートに欠ける場合があります。
  • トレースされた呼び出しをフィルタリングして、取得するデータ量を減らすことができます。
  • [command]`strace を使用するために、ログフィルターの設定以外に、特別な設定は必要ありません。
  • strace でアプリケーションコードを追跡すると、アプリケーションの実行速度が大幅に遅くなるため、多くの場合、strace は、実稼働デプロイメントに適していません。代わりに、ltrace または SystemTap の使用を検討してください。
  • Red Hat Developer Toolset で利用可能な strace のバージョンでは、システム呼び出しで異なる結果を出すことができるので、この機能は、デバッグに役立ちます。
ltrace

ltrace ツールは、アプリケーションの共有オブジェクト (動的ライブラリー) へのユーザー空間呼び出しをロギングできるようにします。

  • ltrace は、ライブラリーへの呼び出しをトレースできるようにします。
  • トレースされた呼び出しをフィルタリングして、取得するデータ量を減らすことができます。
  • ltrace を使用するために、ログフィルターの設定以外に、特別な設定は必要ありません。
  • ltrace は、軽量、高速で、strace の代わりとして使用できます。strace でカーネルの関数をトレースする代わりに、ltraceglibc など、ライブラリー内の適切なインターフェースをトレースできます。
  • ltracestrace などの既知の呼び出しを処理しないので、ライブラリーの関数に渡す値の情報は提供されません。ltrace の出力には、未処理の数字やポインターだけが含まれます。ltrace 出力を解釈するには、出力に含まれるライブラリーの実際のインターフェースの宣言を確認する必要があります。
SystemTap

SystemTap は、Linux システム上で実行中のプロセスおよびカーネルアクティビティをプローブするための有用なインストルメンテーションプラットフォームです。SystemTap は、独自のスクリプト言語を使用してカスタムのイベントハンドラーをプログラミングします。

  • straceltrace の使用と比較して、ロギングをスクリプト化すると、初期の設定フェーズでの作業量が増加しますが、スクリプト機能があると、SystemTap は、ログの生成以外の利便性が増します。
  • SystemTap は、カーネルモジュールを作成、挿入することで機能します。SystemTap は効率的で、システムやアプリケーションの実行速度を大幅に下げることはありません。
  • SystemTap には使用例が複数含まれています。
GDB

GNU デバッガーは主に、ロギングではなく、デバッグを行いますが、GNU デバッガーの機能の中で、アプリケーションの対話が主なアクティビティーとなるシナリオでも、有用なものがあります。

  • GDB では、対話イベントを取得して、後に続く実行パスを即時にデバッグするように、都合よく組み合わせることができます。
  • GDB は、他のツールで問題の状況を最初に特定してから、頻度の低いイベントや単一のイベントを分析するのが一番適しています。イベントの発生頻度が高い場合には、GDB の使用が非効率であったり、使用ができなくなったりします。
関連資料

20.3.2. strace でのアプリケーションのシステム呼び出し監視

strace ツールでは、アプリケーションを実行するシステム (カーネル) 呼び出しの監視を有効化します。

前提条件
ステップ
  1. 監視するシステム呼び出しを特定します。
  2. 監視するプログラムが実行されていない場合は、strace を起動して、プログラム を指定します。

    $ strace -fvttTyy -s 256 -e trace=call program

    call は、表示されるシステム呼び出しに置き換えます。-e trace=call オプションは複数回使用できます。何も指定しない場合は、strace は全システム呼び出しの種類を表示します。詳しい情報は strace(1) の man ページを参照してください。

    プログラムがすでに実行中の場合には、プロセス id (pid) を検索して、その id に strace をアタッチします。

    $ ps -C program
    (...)
    $ strace -fvttTyy -s 256 -e trace=call -ppid

    フォークしたプロセスまたはスレッドをトレースしない場合には、-f オプションは指定しないでください。

  3. strace は、アプリケーションで作成したシステム呼び出しとその詳細を表示します。

    多くの場合、アプリケーションとそのライブラリーは大量の呼び出しを作成し、これらのシステム呼び出しにフィルターが設定されていない場合には、strace の出力が直後に表示されます。

  4. strace は、プログラムが終了すると、終了します。

    トレースしたプログラムが終了する前にモニタリングを中断するには、ctrl+C を押してください。

    • strace でプログラムを起動した場合には、プログラムは strace とともに中断されます。
    • 実行中のプログラムに strace をアタッチした場合には、プログラムは strace とともに中断されます。
  5. アプリケーションが実行したシステム呼び出しの一覧を分析します。

    • リソースのアクセスや可用性の問題は、エラーを返した呼び出しとしてログに表示されます。
    • システム呼び出しや呼び出しシーケンスのパターンに渡す値により、アプリケーションの動作の原因が分かります。
    • アプリケーションがクラッシュした場合に、重要な情報はおそらく、ログの最後に表示されます。
    • 出力には、不必要な情報が多く含まれていますが、より正確なフィルターを構築して、繰り返し手順を実行してください。
注記

出力を確認することも、ファイルに保存することもどちらも有用です。これには、tee コマンドを使用します。

$ strace ... |& tee your_log_file.log
関連資料

20.3.3. ltrace でのアプリケーションのライブラリー関数呼び出しの監視

ltrace ツールは、ライブラリー (共有オブジェクト) で利用可能な関数に対するアプリケーションの呼び出しを監視できます。

前提条件
ステップ
  1. 可能であれば、対象のライブラリーおよび関数を特定します。
  2. 監視するプログラムが実行されていない場合には、ltrace を起動して、プログラム を指定します。

    $ ltrace -f -l library -e function program

    -e および -l のオプションを使用して、出力をフィルタリングします。

    • function として表示する関数名を提示します。-e function オプションは複数回使用できます。何も指定しない場合は、ltrace は全関数への呼び出しを表示します。
    • 関数を指定するのではなく、-l library オプションでライブラリー全体を指定することができます。このオプションは、-e function オプションと同様に動作します。

    詳細情報は、ltrace(1)_ man ページを参照してください。

    プログラムがすでに実行中の場合は、プロセス id (pid) を検索して、その id を指定して ltrace を実行します。

    $ ps -C program
    (...)
    $ ltrace ... -ppid

    フォークしたプロセスまたはスレッドをトレースしない場合には、-f オプションは指定しないでください。

  3. ltrace はアプリケーションのライブラリー呼び出しを表示します。

    多くの場合、アプリケーションは大量の呼び出しを作成し、フィルターが設定されていない場合には、ltrace の出力がすぐに表示されます。

  4. ltrace は、プログラムが終了すると、終了します。

    トレースしたプログラムが終了する前にモニタリングを中断するには、ctrl+C を押してください。

    • ltrace でプログラムを起動した場合には、プログラムは ltrace とともに中断されます。
    • ltrace をすでに実行中のプログラムにアタッチした場合には、プログラムは ltrace とともに中断されます。
  5. アプリケーションが実行したライブラリー呼び出しの一覧を分析します。

    • アプリケーションがクラッシュした場合に、重要な情報はおそらく、ログの最後に表示されます。
    • 出力には、不必要な情報が多く含まれていますが、より正確なフィルターを構築して、繰り返し手順を実行してください。
注記

出力を確認することも、ファイルに保存することもどちらも有用です。これには、tee コマンドを使用します。

$ ltrace ... |& tee your_log_file.log
関連資料
  • strace(1) man ページ
  • 『Red Hat Developer Toolset User Guide 』 - 「ltrace」

20.3.4. SystemTap でのアプリケーションのシステム呼び出し監視

SystemTap ツールでは、カーネルイベントにカスタムイベントハンドラーを登録できるようになります。strace と比較すると、使いにくいですが、効率性が高く、より複雑な処理ロジックを使用できます。

前提条件
ステップ
  1. 以下の内容を含む my_script.stp ファイルを作成します。

    probe begin
    {
      printf("waiting for syscalls of process %d \n", target())
    }
    
    probe syscall.*
    {
      if (pid() == target())
        printf("%s(%s)\n", name, argstr)
    }
    
    probe process.end
    {
      if (pid() == target())
        exit()
    }
  2. 監視するプロセスのプロセス ID (pid) を検索します。

    $ ps -aux
  3. スクリプトで SystemTap を実行します。

    # stap my_script.stp -x pid

    pid には、プロセス id を指定します。

    スクリプトはカーネルモジュールにコンパイルされてから読み込まれるため、コマンドを入力してから出力が表示されるまで若干の遅延があります。

  4. プロセスでシステム呼び出しが実行されると、呼び出し名とパラメーターがターミナルに出力されます。
  5. プロセスが中断された場合や、Ctrl+C が押された場合に、スクリプトは終了します。
関連資料

20.3.5. GDB を使用したアプリケーションシステム呼び出しの遮断

GDB は、プログラムの実行中に発生するさまざまな状況において実行を指定できます。プログラムがシステム呼び出しを実行時に実行を停止するには、GDB catchpoint を使用します。

前提条件

GDB でのシステム呼び出しでプログラム実行の停止

  1. キャッチポイントを設定します。

    (gdb) catch syscall syscall-name

    catch syscall コマンドは、プログラムによりシステム呼び出しが行われた時に実行を停止する特別なブレークポイントを設定します。

    syscall-name オプショは、呼び出し名を指定します。様々なシステム呼び出しに対して複数のキャッチポイントを指定することができます。syscall-name オプションに何も指定しない場合には、システム呼び出しがあると、GDB が停止してしまいます。

  2. プログラムにより、実行が開始されていない場合には、開始してください。

    (gdb) r

    プログラムの実行が一時停止されているだけの場合は、再開してください。

    (gdb) c
  3. GDB は、指定のシステム呼び出しがプログラムにより実行された後に実行を一時停止します。
関連資料

20.3.6. アプリケーションによるシグナルの処理を遮断するための GDB の使用

GDB は、プログラムの実行中に発生するさまざまな状況において実行を指定できます。プログラムがオペレーティングシステムからシグナルを受信した時に実行を停止するには、GDB catchpoint を使用します。

前提条件
GDB でのシグナル受信時のプログラム実行停止
  1. キャッチポイントを設定します。

    (gdb) catch signal signal-type

    catch signal コマンドは、プログラムでシグナルを受信した場合に、実行を一時停止する特別なブレークポイントを設定します。signal-type オプションは、シグナルのタイプを指定します。すべてのシグナルを取得するには、特別な値 'all' を使用します。

  2. プログラムにより、実行が開始されていない場合には、開始してください。

    (gdb) r

    プログラムの実行が一時停止されているだけの場合は、再開してください。

    (gdb) c
  3. GDB は、プログラムが指定のシグナルを受信すると実行を停止します。
関連資料