【问题标题】:gcc LTO appears to strip debugging symbolsgcc LTO 似乎去除了调试符号
【发布时间】:2017-04-06 05:13:25
【问题描述】:

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

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

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

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

然后我尝试将-flto 添加到 CFLAGS。尽管程序运行良好,但我不再能够调试项目,gdb 抱怨缺少调试符号。在 ELF 文件(启用 LTO)上运行 objdump -g 会得到以下输出:

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 即可解决问题。没有 LTO 的 ELF 文件上的 objdump -g 现在显示 .debug_info 部分,其中填充了对我项目中函数的正确引用,并且调试再次正常工作。

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

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

【问题讨论】:

  • 这里有一些您可能感兴趣的信息:gcc.gnu.org/wiki/early-debug
  • 你有没有想过这个问题?
  • 还没有。不过,我还没有在更新版本的 gcc 上进行测试。
  • @TrygveLaugstøl 更新:我刚刚在最新版本的 GNU ARM Embedded Toolchain (6-2017-q1-update) 上对此进行了测试,至少根据 objdump,调试符号又回来了.不幸的是,由于是周末,我无法访问我的硬件来测试它。我会在我这样做的时候报告。
  • @swineone 很好,谢谢你告诉我!

标签: debugging gcc optimization lto


【解决方案1】:

这是因为 gcc 不支持将 -flto-g 结合起来。

你可以找到详情GCC Online Docs - Optimize Options

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

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

【讨论】:

  • 当前 7.3.0 显示“链接时间优化不适用于生成调试信息。将 -flto 与 -g 结合目前处于试验阶段,预计会产生意想不到的结果。”
【解决方案2】:

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

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

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

【讨论】:

  • 我决定接受这个答案,尽管没有用较新版本的 gcc 实际尝试过。如果有人尝试但仍然有问题,请在下面发表评论。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2019-01-27
    • 2019-02-18
    相关资源
    最近更新 更多