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.
To remove debugging symbols from a binary (which must be an a. out or ELF binary), run strip --strip-debug filename. Wildcards can be used to treat multiple files (use something like strip --strip-debug $LFS/tools/bin/*).
A debug symbol is a special kind of symbol that attaches additional information to the symbol table of an object file, such as a shared library or an executable.
To check if there's debug info inside the kernel object, you can add the following at the end of the objdump command: | grep debug . If this string is found, you know the kernel object contains debug information. If not, then it's a "clean" kernel object.
Load time will be increased when the debug symbols are present over when not present. The on-disk footprint will be larger. If you compiled with zero optimization then you really lose nothing. If you set optimization, then the optimized code will be less optimized because of the debug symbols.
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.
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.
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