This Time Self-Hosted
dark mode light mode Search

Debug code and debug information

There are many different but common misconceptions about debugging that are spread among those users who, having never learnt a programming language, cannot understand properly the difference between debug code and debug information. Some of these misconception causes misunderstanding with Gentoo’s way of handling the two things as separate and distinct feature of a software.

First of all, let’s start with what the -g, -ggdb and -g3 options are supposed to do. These three flags are used to add debug information, in form of either stabs or DWARF data, depending on the architecture, to the compiled files, may they be object files, shared objects or final executables. This data is used by debuggers like gdb to provide a meaningful backtrace, and is added to some special sections of the file. The difference between a file that is built with these options and a file that is built without those can be removed by using the strip command, since they don’t go touching the actual executable code or data entries. The only software that is susceptible to break with -g3 is the dynamic loader, and even that I’m not sure why.

The various level of debugging information are used to provide various level of backtracing, starting from giving the name of the functions called, and arriving to have the line numbers, the source lines, and macro expansion (which is especially useful when debugging stuff like scanelf, that is composed of a huge amount of macro-based meta-functions. Even when the full debug information is enabled in files, it’s not hindering performance, if not during the first scan and read of the ELF files, since the loader does not load the debug information by default, they are not in sections that are allocated in memory at runtime at all. (This is something you can easily understand once you know the difference between allocated and non-allocated ELF segments).

Debug code, instead, means adding special instruction in the executable code for debugging purposes; the most simple example is the assert() macro used to make sure that unexpected code paths are not taken; although this is often misused as a way to enact limitations in functions, the original idea behind assertions was to make the program die in a way easy to debug when a condition supposed to be always true was instead false. These checks wouldn’t be needed during standard usage, or should be handled gracefully if they indeed happen, so the assertions would just need to be taken out of the built code at that point, which is exactly what -DNDEBUG does. (On an autotools-related note, the AC_HEADER_ASSERT autoconf macro not only checks for the correct header, but also provides an easy to use --disable-assert option for the configure script to disable assertions altogether). Unfortunately nowadays assertions are often used to check the behaviour of code at runtime, even though an error would then cause the abort of the software, which makes it more difficult to just disable them altogether for final users.

But debug code can be much more complex, and might slow down operation a lot; it might be logging data extensively, it might fill the terminal with pointless information, it might check every and each step during processing. This type of code must certainly not be enabled for users’ runtime or their work would be greatly hindered.

Now that the distinctions are made, you can see why splitdebug/strip FEATURES are distinct from the debug USE flag. If you want to just get a backtrace for a crash you got during execution, you need debug information, you don’t need debug code; if possible, debug code might actually stop the software from crashing; as could reducing the optimisation flags. For users, it’s more than likely than the debug USE flag wouldn’t be useful at all; for developers who know what to do, this fine-grained control is most likely the best option they have.

So please next time you think about mixing the debug USE flag and the splitdebug/strip FEATURES in the same idea, try to think of what exactly you want to achieve. And no, disabling -O2 is not always a good idea to have a meaningful backtrace, especially since as I said, -O0 might make stuff not build, so you shouldn’t be ready to just enable that unconditionally to get a backtrace for a bug report.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.