gcc LTO似乎剥离了调试符号

swi*_*one 12 debugging optimization gcc lto

我有一个项目,在ARM Cortex-M4处理器上运行,我正在尝试包含gcc链接时优化(LTO)功能.

目前我的编译和链接标志是:

CFLAGS = -ggdb -ffunction-sections -Og
LDFLAGS = -Wl,-gc-sections
Run Code Online (Sandbox Code Playgroud)

使用这些标志一切正常,我能够正确调试项目.

然后我尝试添加-flto到CFLAGS.虽然程序工作正常,但我无法再调试项目,gdb抱怨缺少调试符号.objdump -g在ELF文件上运行(启用LTO)会提供以下输出:

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
Run Code Online (Sandbox Code Playgroud)

请注意缺少的.debug_info部分.回到项目设置,只有-flto从CFLAGS中删除才能解决问题.objdump -g在没有LTO的ELF文件上现在显示一个.debug_info部分,其中填充了对项目中函数的正确引用,并且调试再次正常工作.

如何让LTO和调试符号一起发挥好?

编辑:忘记包含我的gcc信息.我正在使用GNU ARM嵌入式工具链,测试是在版本5.4-2016q2和5.4-2016q3上执行的.

alp*_*pha 7

这是因为gcc不支持合并-flto-g.

您可以在GCC Online Docs - Optimize Options中找到详细信息

"结合-flto-g目前处于试验阶段,预计将产生意想不到的效果."

使用时-flto,-g将被忽略.


Tra*_*s3r 5

现在情况应该有所改善。GCC 8 终于得到了早期调试信息的改进:http : //hubicka.blogspot.com/2018/06/gcc-8-link-time-and-interprocedural.html

虽然可以使用 LTO 和 -g 构建并调试生成的二进制文件,但调试信息有点混乱,而不是最初编写的语言程序对应的调试信息。这终于解决了。[...] 主要思想是在编译早期生成 DWARF,将其存储到目标文件中,并在链接时将必要的片段复制到最终目标文件,而无需编译器对其进行解析和更新。

但请注意,-gsplit-dwarf这不适用于 LTO。