15
votes

I have project, running on an ARM Cortex-M4 processor, where I'm trying to include the gcc link-time optimization (LTO) feature.

Currently my compilation and linking flags are:

CFLAGS = -ggdb -ffunction-sections -Og
LDFLAGS = -Wl,-gc-sections

Everything works fine with these flags and I'm able to correctly debug the project.

Then I tried adding -flto to CFLAGS. Although the program works fine, I'm no longer able to debug the project, with gdb complaining of missing debugging symbols. Running objdump -g on the ELF file (with LTO enabled) gives the following output:

xxx.elf:     file format elf32-littlearm

Contents of the .debug_frame section:

00000000 0000000c ffffffff CIE
  Version:               1
  Augmentation:          ""
  Code alignment factor: 2
  Data alignment factor: -4
  Return address column: 14

  DW_CFA_def_cfa: r13 ofs 0

00000010 00000018 00000000 FDE cie=00000000 pc=08002a3c..08002a88
  DW_CFA_advance_loc: 2 to 08002a3e
  DW_CFA_def_cfa_offset: 16
  DW_CFA_offset: r4 at cfa-16
  DW_CFA_offset: r5 at cfa-12
  DW_CFA_offset: r6 at cfa-8
  DW_CFA_offset: r14 at cfa-4
  DW_CFA_nop

0000002c 0000000c ffffffff CIE
  Version:               1
  Augmentation:          ""
  Code alignment factor: 2
  Data alignment factor: -4
  Return address column: 14

  DW_CFA_def_cfa: r13 ofs 0

0000003c 0000000c 0000002c FDE cie=0000002c pc=08002a88..08002a98

Note the missing .debug_info section. Going back to the project settings and only removing -flto from CFLAGS solves the problem. objdump -g on the ELF file without LTO now shows a .debug_info section, filled with the proper references to the functions in my project, and debugging works fine again.

How to get LTO and debug symbols to play well together?

Edit: forgot to include my gcc information. I'm using the GNU ARM Embedded Toolchain, and the test was performed on versions 5.4-2016q2 and 5.4-2016q3.

3
There is some information that may be of interest to you here: gcc.gnu.org/wiki/early-debugPyves
Did you ever figure this out?Trygve Laugstøl
Not yet. I haven't tested on a newer version of gcc though.swineone
@TrygveLaugstøl Update: I've just tested this on the latest version of the GNU ARM Embedded Toolchain (6-2017-q1-update) and, at least according to objdump, the debug symbols are back. Unfortunately, since it's the weekend, I don't have access to my hardware to test it. I will report back when I do.swineone
@swineone nice, thanks for letting me know!Trygve Laugstøl

3 Answers

7
votes

It's because gcc does not support combine -flto with -g.

You can find the details GCC Online Docs - Optimize Options

"Combining -flto with -g is currently experimental and expected to produce unexpected results."

When you use -flto, the -g will be ignored.

5
votes

The situation should have improved by now. GCC 8 finally got the early debug info improvements: http://hubicka.blogspot.com/2018/06/gcc-8-link-time-and-interprocedural.html

While it was possible to build with LTO and -g and debug the resulting binary, the debug information was kind of messed up C, instead of debug info corresponding to the language program was originally written in. This is finally solved. [...] The main idea is to produce DWARF early during compilation, store it into object files and during link-time just copy necessary fragments to final object files without need for compiler to parse it and update it.

But note that -gsplit-dwarf won't work with LTO.

0
votes

One can try using attribute((used)) or alternatively one can try using the debugging symbols in a way that does not change their values.