Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC 4.8: Does -Og imply -g?

Tags:

gcc

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?

like image 903
cschwan Avatar asked Oct 19 '12 08:10

cschwan


3 Answers

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:

  • Option -ggdb overrides -g. That is, if you set -ggdb after -g, the -g option effectively gets ignored.
  • Option -g is equal to -g2 and omitting -g is the same as -g0.
  • Option -g3 produces a larger debugging section than -g2 and so does -ggdb3 against -ggdb2.
  • Higher optimization levels both result in an increase of the code and debugging sections. (-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
like image 56
Lekensteyn Avatar answered Oct 13 '22 01:10

Lekensteyn


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.

like image 21
pattivacek Avatar answered Oct 13 '22 01:10

pattivacek


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.

like image 1
Nick Dong Avatar answered Oct 13 '22 01:10

Nick Dong