Recently the documentation for GCC 4.8 was updated which now introduces a new optimization switch, -Og
. This
[..] addresses the need for fast compilation and a superior debugging experience while providing a reasonable level of runtime performance. Overall experience for development should be better than the default optimization level -O0.
Does this switch imply -g
or do I have to add it to my CXXFLAGS
manually?
A look in the GCC 4.9.2 source code (gcc/opts.c) showed that -Og
is the the same as -O1
, but with some flags disabled that could result in a worse debugging experience:
/* in function default_options_optimization: */
case OPT_Og:
/* -Og selects optimization level 1. */
opts->x_optimize_size = 0;
opts->x_optimize = 1;
opts->x_optimize_fast = 0;
opts->x_optimize_debug = 1;
break;
A few steps later, function maybe_default_option
gets called with a set of options and the x_optimize_debug
flag. Options marked with OPT_LEVELS_1_PLUS_NOT_DEBUG
, OPT_LEVELS_1_PLUS_SPEED_ONLY
and OPT_LEVELS_2_PLUS_SPEED_ONLY
will not be enabled when -Og
is used.
So this is where the statement "should be better than -O0" comes from. -Og
is between -O0
and -O1
. This does not affect the inclusion of debugging information that would be enabled through the -g
options. You would probably also be interested in the different -g
options:
-ggdb
overrides -g
. That is, if you set -ggdb
after -g
, the -g
option effectively gets ignored.-g
is equal to -g2
and omitting -g
is the same as -g0
.-g3
produces a larger debugging section than -g2
and so does -ggdb3
against -ggdb2
.-O0
< -O1
< -Og
< -O2
< -O3
).strip --strip-debug
resulted in the same object size independent of the -g
levels. This matched the expectation that only the -O
level has an effect on the actual code where -g
determines the debug sections.strip --keep-debug
results in objects where the size is dominated by the -g
level, followed by -O
levels. (so -g0 -O3
is smaller than -g3 -O0
).Note: here I did not consider the time to compile. It will likely increase with more aggressive optimization levels. I would expect that the debug levels would only have a minor impact on the time (compared to optimization) since it just means that extra details needs to be tracked during passes.
Here is the command I used to test the actual behavior (also compare -ggdbX
instead of -gX
):
for g in -g0 -g2 -g3;do
for O in -O0 -O1 -O2 -O3 -Og; do
flags="$g $O";
gcc -fPIC -rdynamic -c -Wall -Wextra -Ilib ltunify.c -o obj/gL_"${flags// /_}_.o" $flags || break;
done;
done
Short answer: No, you must still add -g
manually.
Long answer:
I have struggled to find a hard answer straight from the source, so I decided to test it out myself using the methods described here: How to check if program was compiled with debug symbols?
I built an executable with the -O3
flag and without -g
. Using objdump --syms <file> | grep debug
yielded nothing, as expected.
I then built an executable with -g
and without any optimization flags. The same objdump
command yielded six results such as this:
0000000000000000 l d .debug_info 0000000000000000 .debug_info
I finally built an executable with the -Og
flag and without -g
. The objdump
command yielded nothing. That implies that debug symbols are not present in this case.
While I can't find any explicit documentation from GCC itself, the Gentoo Wiki (as mentioned before by Marco Scannadinari) confirms my assertion that -Og
does not imply -g
.
Manual of gcc --version gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
on fedora 29 workstation x86_64.
Different version but I think it is helpful.
Options for Debugging Your Program
... If you are not using some other optimization option, consider using -Og with -g. With no -O option at all, some compiler passes that collect information useful for debugging do not run at all, so that -Og may result in a better debugging experience. ...
Options That Control Optimization
... -Og Optimize debugging experience. -Og enables optimizations that do not interfere with debugging. It should be the optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization while maintaining fast compilation and a good debugging experience. ...
So, we can see -Og
is one of the optimization options. If you are not using some other optimization option, consider using -Og with -g.
Sample:
#include <stdio.h>
int main(int argc, char *argv[]) {
int n;
for (n=0; n<10; n++) {
printf("Print Number: %d\n", n);
}
return 0;
}
compile:
[user@localhost myctest]$ gcc sample.c -o sample
[user@localhost myctest]$ gcc sample.c -o sample.Og -Og
[user@localhost myctest]$ gcc sample.c -o sample.g -g
[user@localhost myctest]$ gcc sample.c -o sample.Og.g -Og -g
Then you can see the size of the compiled files:
[user@localhost myctest]$ ls -l --human-readable sample*
-rwxrwxr-x. 1 user user 18K Aug 10 19:43 sample
-rw-rw-r--. 1 user user 162 Aug 10 19:43 sample.c
-rwxrwxr-x. 1 user user 21K Aug 10 19:43 sample.g
-rwxrwxr-x. 1 user user 18K Aug 10 19:43 sample.Og
-rwxrwxr-x. 1 user user 21K Aug 10 19:44 sample.Og.g
Then you can use readelf
(GNU readelf version 2.31.1-13.fc29) to re-check the debug info in those files.
[user@localhost myctest]$ readelf --debug-dump=aranges sample
[user@localhost myctest]$ readelf --debug-dump=aranges sample.g
Contents of the .debug_aranges section:
Length: 44
Version: 2
Offset into .debug_info: 0x0
Pointer Size: 8
Segment Size: 0
Address Length
0000000000401126 000000000000003d
0000000000000000 0000000000000000
[user@localhost myctest]$ readelf --debug-dump=aranges sample.Og
[user@localhost myctest]$ readelf --debug-dump=aranges sample.Og.g
Contents of the .debug_aranges section:
Length: 44
Version: 2
Offset into .debug_info: 0x0
Pointer Size: 8
Segment Size: 0
Address Length
0000000000401126 0000000000000028
0000000000000000 0000000000000000
You can see there is no debug information in the file compiled only by -Og
option. You also can check more information with options of readelf --debug-dump=
. For example readelf --debug-dump=aranges,info sample.g
. And readelf --headers sample.g | grep debug
See man readelf
:
--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]
You can use gdb to check:
[user@localhost myctest]$ gdb sample.Og
GNU gdb (GDB) Fedora 8.2-3.fc29
Copyright (C) 2018 Free Software Foundation, Inc.
...
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from sample.Og...(no debugging symbols found)...done.
(gdb)
Then you get (no debugging symbols found)
for the file, sample.Og.
4.8.x
For 4.8.x documentation, -Og
is not mentioned in the section Debugging-Options, only introduced in section Optimize-Options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With