Chapter 7. Enabling Debugging with Debugging Information

To debug applications and libraries, debugging information is required. The following sections describe how to obtain this information.

7.1. Debugging information

While debugging any executable code, two types of information allow the tools, and by extension the programmer, to comprehend the binary code:

  • the source code text
  • a description of how the source code text relates to the binary code

Such information is called debugging information.

Red Hat Enterprise Linux uses the ELF format for executable binaries, shared libraries, or debuginfo files. Within these ELF files, the DWARF format is used to hold the debug information.

To display DWARF information stored within an ELF file, run the readelf -w file command.

Caution

STABS is an older, less capable format, occasionally used with UNIX. Its use is discouraged by Red Hat. GCC and GDB provide STABS production and consumption on a best effort basis only. Some other tools such as Valgrind and elfutils do not work with STABS.

Additional resources

7.2. Enabling debugging of C and C++ applications with GCC

Because debugging information is large, it is not included in executable files by default. To enable debugging of your C and C++ applications with it, you must explicitly instruct the compiler to create it.

To enable creation of debugging information with GCC when compiling and linking code, use the -g option:

$ gcc ... -g ...
  • Optimizations performed by the compiler and linker can result in executable code which is hard to relate to the original source code: Variables may be optimized out, loops unrolled, operations merged into the surrounding ones etc. This affects debugging negatively. For improved debuging experience, consider setting the optimization with the -Og option. However, changing the optimization level changes the executable code and may change the actual behaviour so as to remove some bugs.
  • To include also macro definitions in the debug information, use the -g3 option instead of -g.
  • The -fcompare-debug GCC option tests code compiled by GCC with debug information and without debug information. The test passes if the resulting two binary files are identical. This test ensures that executable code is not affected by any debugging options, which further ensures that there are no hidden bugs in the debug code. Note that using the -fcompare-debug option significantly increases compilation time. See the GCC manual page for details about this option.

Additional resources

7.3. Debuginfo and debugsource packages

The debuginfo and debugsource packages contain debugging information and debug source code for programs and libraries. For applications and libraries installed in packages from the Red Hat Enterprise Linux repositories, you can obtain separate debuginfo and debugsource packages from an additional channel.

Debugging information package types

There are two types of packages available for debugging:

Debuginfo packages
The debuginfo packages provide debugging information needed to provide human-readable names for binary code features. These packages contain .debug files, which contain DWARF debugging information. These files are installed to the /usr/lib/debug directory.
Debugsource packages
The debugsource packages contain the source files used for compiling the binary code. With both respective debuginfo and debugsource package installed, debuggers such as GDB or LLDB can relate the execution of binary code to the source code. The source code files are installed to the /usr/src/debug directory.

Differences from RHEL 7

In Red Hat Enterprise Linux 7, the debuginfo packages contained both kinds of information. Red Hat Enterprise Linux 8 splits the source code data needed for debugging from the debuginfo packages into separate debugsource packages.

Package names

A debuginfo or debugsource package provides debugging information valid only for a binary package with the same name, version, release and architecture:

  • Binary package: packagename-version-release.architecture.rpm
  • Debuginfo package: packagename-debuginfo-version-release.architecture.rpm
  • Debugsource package: packagename-debugsource-version-release.architecture.rpm

7.4. Getting debuginfo packages for an application or library using GDB

Debugging information is required to debug code. For code that is installed from a package, the GNU Debugger (GDB) automatically recognizes missing debug information, resolves the package name and provides concrete advice on how to get the package.

Prerequisites

Procedure

  1. Start GDB attached to the application or library you want to debug. GDB automatically recognizes missing debugging information and suggests a command to run.

    $ 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. Exit GDB: type q and confirm with Enter.

    (gdb) q
  3. Run the command suggested by GDB to install the required debuginfo packages:

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

    The dnf package management tool provides a summary of the changes, asks for confirmation and once you confirm, downloads and installs all the necessary files.

  4. In case GDB is not able to suggest the debuginfo package, follow the procedure described in Section 7.5, “Getting debuginfo packages for an application or library manually”.

7.5. Getting debuginfo packages for an application or library manually

You can determine manually which debuginfo packages you need to install by locating the executable file and then finding the package that installs it.

Note

Red Hat recommends that you use GDB to determine the packages for installation. Use this manual procedure only if GDB is not able to suggest the package to install.

Prerequisites

Procedure

  1. Find the executable file of the application or library.

    1. Use the which command to find the application file.

      $ which less
      /usr/bin/less
    2. Use the locate command to find the library file.

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

      If the original reasons for debugging include error messages, pick the result where the library has the same additional numbers in its file name as those mentioned in the error messages. If in doubt, try following the rest of the procedure with the result where the library file name includes no additional numbers.

      Note

      The locate command is provided by the mlocate package. To install it and enable its use:

      # yum install mlocate
      # updatedb
  2. Search for a name and version of the package that provided the file:

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

    The output provides details for the installed package in the name:epoch-version.release.architecture format.

    Important

    If this step does not produce any results, it is not possible to determine which package provided the binary file. There are several possible cases:

    • The file is installed from a package which is not known to package management tools in their current configuration.
    • The file is installed from a locally downloaded and manually installed package. Determining a suitable debuginfo package automatically is impossible in that case.
    • Your package management tools are misconfigured.
    • The file is not installed from any package. In such case, no respective debuginfo package exists, either.

    Because further steps depend on this one, you must resolve this situation or abort this procedure. Describing the exact troubleshooting steps is beyond the scope of this procedure.

  3. Install the debuginfo packages using the debuginfo-install utility. In the command, use the package name and other details you determined during the previous step:

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

Additional resources