Chapter 4. Debugging
Useful, well-written software generally goes through several different phases of application development, allowing ample opportunity for mistakes to be made. Some phases come with their own set of mechanisms to detect errors. For example, during compilation an elementary semantic analysis is often performed to make sure objects, such as variables and functions, are adequately described.
The error-checking mechanisms performed during each application development phase aims to catch simple and obvious mistakes in code. The debugging phase helps to bring more subtle errors to light that fell through the cracks during routine code inspection.
4.1. ELF Executable Binaries
Red Hat Enterprise Linux uses ELF for executable binaries, shared libraries, or debuginfo files. Within these debuginfo ELF files, the DWARF format is used. Version 3 of DWARF is used in ELF files (that is,
gcc -g
is equivalent to gcc -gdwarf-3
). DWARF debuginfo includes:
- names of all the compiled functions and variables, including their target addresses in binaries
- source files used for compilation, including their source line numbers
- local variables location
Important
STABS is occasionally used with UNIX. STABS is an older, less capable format. Its use is discouraged by Red Hat. GCC and GDB support STABS production and consumption on a best effort basis only.
Within these ELF files, the GCC debuginfo level is also used. The default is level 2, where macro information is not present; level 3 has C/C++ macro definitions included, but the debuginfo can be very large with this setting. The command for the default
gcc -g
is the same as gcc -g2
. To change the macro information to level three, use gcc -g3
.
There are multiple levels of debuginfo available. Use the command
readelf -WS file
to see which sections are used in a file.
Binary State
|
Command
|
Notes
|
---|---|---|
Stripped
| strip file
or
gcc -s -o file
|
Only the symbols required for runtime linkage with shared libraries are present.
ELF section in use:
.dynsym
|
ELF symbols
| gcc -o file
|
Only the names of functions and variables are present, no binding to the source files and no types.
ELF section in use:
.symtab
|
DWARF debuginfo with macros
| gcc -g -o file
|
The source file names and line numbers are known, including types.
ELF section in use:
.debug_*
|
DWARF debuginfo with macros
| gcc -g3 -o file
|
Similar to
gcc -g but the macros are known to GDB.
ELF section in use:
.debug_macro
|
Note
GDB never interprets the source files, it only displays them as text. Use
gcc -g
and its variants to store the information into DWARF.
Compiling a program or library with
gcc -rdynamic
is discouraged. For specific symbols, use gcc -Wl, --dynamic-list=...
instead. If gcc -rdynamic
is used, the strip
command or -s
gcc option have no effect. This is because all ELF symbols are kept in the binary for possible runtime linkage with shared libraries.
ELF symbols can be read by the
readelf -s file
command.
DWARF symbols are read by the
readelf -w file
command.
The command
readelf -wi file
is a good verification of debuginfo, compiled within your program. The commands strip file
or gcc -s
are commonly accidentally executed on the output during various compilation stages of the program.
The
readelf -w file
command can also be used to show a special section called .eh_frame
with a format and purpose is similar to the DWARF section .debug_frame
. The .eh_frame
section is used for runtime C++ exception resolution and is present even if -g
gcc option was not used. It is kept in the primary RPM and is never present in the debuginfo RPMs.
Debuginfo RPMs contain the sections
.symtab
and .debug_*
. Neither .eh_frame
, .eh_frame_hdr
, nor .dynsym
are moved or present in debuginfo RPMs as those sections are needed during program runtime.