Featured image: Debuginfo

For a long time at Red Hat, all executables in RPMs were built with debuginfo enabled. While this practice makes it easier for people in support to investigate issues reported using tools such as GDB and crash, there are other important non-debugging uses for the resulting debuginfo.

Debuginfo was named for its initial use. Over time, other applications (such as application binary interface [ABI] compliance checking, data struct layout analysis, and performance monitoring) that use the same information needed for debugging have been developed. It is best to think of the debuginfo as mapping information between the executable that compilers generate and the source code that developers write. It helps humans get crucial information to better understand the executable code actually running their systems, and provides a means of double-checking the compiler's and the developers' work.

Application binary interface (ABI) checking

Currently, on Linux, very few applications are monolithic stand-alone binaries. Most binaries make extensive use of shared libraries to leverage the work of other projects and reduce the size of executables. However, for this practice to work, the application binary interfaces (ABIs) provided by the libraries need to be stable. It would be horrible if a Linux distribution updated a shared library used by an application and suddenly the application stopped working as a result. Tools such as libabigail compare different versions of a shared library to detect any changes in the ABI.

These ABI checking tools use the debuginfo to determine which functions are available, the functions' return types, the arguments being passed into the functions, and the data layout of those various types. The debuginfo is a machine-readable mechanism to verify that the ABI has not changed. Without the debuginfo, these checks would not be feasible.

For distributions such as Red Hat Enterprise Linux and Fedora, these ABI checks are essential. ABI checks are done comparing the newer candidate build of packages to previous builds to ensure ABI compatibility. This ensures that other software that relies on those packages will continue to function.

Data structure layout analysis

The compiler might insert padding in data structures to ensure that the data structures do not violate the alignment constraints of the target computer architecture. This padding wastes memory. When developers create data structures, they might not be aware of the alignment constraints. Also, there might be different alignment constraints used for certain compiler options and other target processors.

Tools such as pahole in the dwarves package reads the debuginfo describing the data structures and determines where padding has been added. Even on machines with gigabytes of RAM, there can be a great desire to more efficiently organize the data structures to avoid wasting space.

Performance monitoring

One might want to provide feedback on a program's operation in production. This information can provide a baseline of how the program normally operates. It can also provide insights into which areas of the program consume too much time and could be made more efficient. Periodic sampling of the program counter by perf is a common way of estimating the time spent in various areas of program. However, just having raw samples of program addresses and bytes from the program stack is not useful for developers. Developers want stack backtraces so they can produce flame graphs and be able to determine which areas of the source code they need to revise to improve performance of future versions of the software.

Keep the debuginfo information handy

These non-debugging uses of the debuginfo can help improve code quality by catching unexpected changes in ABI, unexpected wasted space in data structures, and unexpected inefficient sections of code. The debuginfo does take up space, but there are methods to strip that information from binaries and place it elsewhere so the default binaries are not any larger than binaries compiled without the debuginfo. Thus, it is best to default to compiling code with debuginfo enabled.

Last updated: January 6, 2021