第3章 アプリケーションのデバッグ

デバッグアプリケーションのトピックは非常に広範囲です。ここでは、開発者向けに複数の状況でデバッグを行うための最も一般的な手法を説明します。

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

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

3.1.1. デバッグの情報

実行なコードをデバッグしている場合は、2 種類の情報により、ツール、さらにはプログラマーがバイナリーコードを理解できます。

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

このような情報はデバッグ情報と呼ばれます。

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

ELF ファイルに保存されている DWARF 情報を表示するには、readelf -w file コマンドを実行します。

重要

STABS は、UNIX でしばしば使用される、以前の、機能の少ない形式です。Red Hat は、この使用を推奨していません。GCC と GDB は、最適な作業でのみ、STABS の実稼働および使用を提供します。Valgrind や elfutils などの他のツールの一部は STABS では動作しません。

3.1.2. GCC で C および C++ のアプリケーションのデバッグの有効化

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

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

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

関連情報

3.1.3. debuginfo パッケージおよび debugsource パッケージ

debuginfo パッケージおよび debugsource パッケージには、プログラムおよびライブラリーのデバッグ情報と、デバッグソースコードが含まれます。Red Hat Enterprise Linux リポジトリーのパッケージにインストールされているアプリケーションやライブラリーの場合は、追加のチャンネルから個別の debuginfo パッケージおよび debugsource パッケージを取得できます。

デバッグの情報パッケージタイプ

デバッグに使用できるパッケージには、以下の 2 つのタイプがあります。

debuginfo パッケージ
debuginfo パッケージは、バイナリーコード機能用に人間が判読可能な名前を提供するために必要なデバッグ情報を提供します。このパッケージには、DWARF デバッグ情報が含まれる .debug ファイルが含まれています。このファイルは、/usr/lib/debug ディレクトリーにインストールされます。
debugsource パッケージ
debugsource パッケージには、バイナリーコードのコンパイルに使用されるソースファイルが含まれています。適切な debuginfo パッケージおよび debugsource パッケージの両方がインストールされている状態で、GDB、LLDB などのデバッガーは、バイナリーコードの実行をソースコードに関連付けることができます。ソースコードファイルは、/usr/src/debug ディレクトリーにインストールされています。

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

デバッグ情報は、コードをデバッグするために必要です。パッケージからインストールされるコードの場合、GNU デバッガー (GDB) は足りないデバッグ情報を自動的に認識し、パッケージ名を解決し、パッケージの取得方法に関する具体的なアドバイスを提供します。

前提条件

手順

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

    $ gdb -q /bin/ls
    Reading symbols from /bin/ls...Reading symbols from .gnu_debugdata for /usr/bin/ls...(no debugging symbols found)...done.
    (no debugging symbols found)...done.
    Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.30-6.el8.x86_64
    (gdb)
  2. GDB を終了します。q と入力して、Enter で確認します。

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

    # dnf debuginfo-install coreutils-8.30-6.el8.x86_64

    dnf パッケージ管理ツールは、変更の概要を提供し、確認を求め、確認後に必要なファイルをすべてダウンロードしてインストールします。

  4. GDB が debuginfo パッケージを提案できない場合は、手動でのアプリケーションまたはライブラリーの debuginfo パッケージの取得 で説明されている手順に従います。

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

実行ファイルの場所を特定し、インストールするパッケージを見つけることで、インストールする debuginfo パッケージを手動で判断できます。

注記

Red Hat は、GDB を使用して、インストールするパッケージを判断することを推奨します。この手動の手順は、GDB がインストールするパッケージを提案できない場合にのみ使用してください。

前提条件

  • アプリケーションまたはライブラリーをシステムにインストールしている。
  • アプリケーションまたはライブラリーが、パッケージからインストールされている。
  • debuginfo-install ツールが、システムで利用できるようにする必要がある。
  • debuginfo パッケージを提供するチャネルをシステム上で設定し、有効にする。

手順

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

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

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

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

      デバッグの元の理由にエラーメッセージが含まれる場合は、ライブラリーのファイル名にエラーメッセージに記載されている番号と同じ追加番号が含まれるものを選択します。疑わしい場合は、ライブラリーファイルの名前に追加の番号が含まれていないものを使用して、残りの手順を試してください。

      注記

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

      # dnf install mlocate
      # updatedb
  2. ファイルを提供するパッケージの名前およびバージョンを検索します。

    $ rpm -qf /usr/lib64/libz.so.1.2.7
    zlib-1.2.11-10.el8.x86_64

    この出力では、インストールされているパッケージの詳細が、name:epoch-version.release.architecture 形式で提供されます。

    重要

    この手順では結果が生成されないので、どのパッケージがこのバイナリーファイルを提供しているかは判断できません。次のような状況が考えられます。

    • このファイルは、現在 の設定でパッケージ管理ツールに認識されないパッケージからインストールされます。
    • このファイルは、ローカルにダウンロードして手動でインストールしたパッケージからインストールされます。この場合、適切な debuginfo パッケージを自動的に判断することはできません。
    • パッケージ管理ツールの設定が正しく設定されていません。
    • このファイルは、どのパッケージからもインストールされません。そのような場合は、それぞれの debuginfo パッケージも存在しません。

    これ以降の手順はこの手順によって異なるため、この状況を解決するか、この手順を中止する必要があります。正確なトラブルシューティング手順の説明は、この手順の範囲外です。

  3. debuginfo-install ユーティリティーを使用して debuginfo パッケージをインストールします。そのコマンドで、前の手順で確認したパッケージ名およびその他の詳細情報を使用します。

    # debuginfo-install zlib-1.2.11-10.el8.x86_64