gcc LTO 似乎去除了调试符号

gcc LTO appears to strip debugging symbols

我有一个项目,运行 在 ARM Cortex-M4 处理器上,我试图在其中包含 gcc link-时间优化 (LTO) 功能。

目前我的编译和 linking 标志是:

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

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

然后我尝试将 -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

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

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

编辑: 忘记包含我的 gcc 信息。我使用的是 GNU ARM Embedded Toolchain,测试是在 5.4-2016q2 和 5.4-2016q3 版本上进行的。

因为gcc不支持combine -flto with -g.

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

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

当您使用 -flto 时,-g 将被忽略。

可以尝试使用 attribute((used)) 或者可以尝试以不改变其值的方式使用调试符号。

现在情况应该有所好转。 GCC 8 终于得到了早期调试信息的改进: 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.

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