LLDB 不显示源代码

LLDB not showing source code

我正在尝试调试我正在编写的 C++ 程序,但是当我在 LLDB 中 运行 它并停止程序时,它只显示汇编程序,而不是原始源代码。 例如崩溃后我正在尝试调试:

Process 86122 stopped
* thread #13: tid = 0x142181, 0x0000000100006ec1 debug_build`game::update() + 10961, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x0000000100006ec1 debug_build`game::update() + 10961
debug_build`game::update:
->  0x100006ec1 <+10961>: movq   (%rdx), %rdx
    0x100006ec4 <+10964>: movq   %rax, -0xb28(%rbp)
    0x100006ecb <+10971>: movq   -0x1130(%rbp), %rax
    0x100006ed2 <+10978>: movq   0x8(%rax), %rsi

我正在使用 -O0 -g 进行编译。当通过 Xcode(我在 OSX)或从命令行 运行 调试器时,我看到了同样的事情。

我还需要做什么才能让源代码显示在 LLDB 中?

补充说明

这是典型构建命令的示例:

clang++ -std=c++1y -stdlib=libc++ -fexceptions -I/usr/local/include -c -O2 -Wall -ferror-limit=5 -g -O0 -ftrapv lib/format.cpp -o format.o

较早的 -O2 在那里,因为这是我使用的默认值,但我相信较晚的 -O0 会覆盖它,对吧?

我试过的

  1. 我使用相同的构建设置通过一个简单的“hello world”程序重现了这个问题。

  2. 经过一些搜索,我尝试了 运行ning dsymutil main.owarning: no debug symbols in executable (-arch x86_64),所以也许我的构建命令没有生成调试符号?

  3. 我也尝试在构建命令中添加 -gsplit-dwarf 但没有效果。

  4. 这是我的“hello world”版本中的 link 命令:

    clang++ main.o -L/usr/local/lib -g -o 你好

  5. I 运行 dwarfdump (I read about it here) 在可执行文件和目标文件上。在我未经训练的人看来,调试符号 存在于目标文件中,但不存在于可执行文件本身中(除非 dwarfdump 仅适用于目标文件,这是可能的) .所以也许 linking 阶段是问题所在。或者 DWARF 有问题。

  6. 我现在已经在“hello world”程序中运行了,通过在终端中一个一个地发出构建命令。因此,我猜测这可能是我的构建系统 (Tup) 的问题,可能 运行 将命令与不同的工作目录结合使用,因此路径会被破坏或发生其他问题。

当您将 -g 命令行选项添加到 clang 时,DWARF 调试信息将放入 .o 文件中。当你 link 你的目标文件(.o,ranlib 归档又名静态库又名 .a 文件)到 executable/dylib/framework/bundle 时,"debug notes" 被放在可执行文件中说(1) 包含调试信息的 .o etc 文件的位置,以及 (2) 可执行二进制文件中 functions/variables 的最终地址。优化标志(-O0-O2 等)对调试信息生成没有影响 - 尽管调试优化编译的代码比调试在 -O0 构建的代码困难得多。

如果您 运行 该可执行二进制文件上的调试器 -- 没有任何其他修改 -- 调试器将从 .o etc 文件中读取调试信息 只要它们在您构建可执行文件时仍在文件系统中的相同文件路径中。这使得迭代开发变得快速——没有工具需要读取、更新和输出(大)调试信息。您可以通过 运行ning nm -pa exename 并查找 OSO 条目(以及其他条目)在可执行文件中看到这些 "debug notes"。这些是 stabs nlist 条目,运行ning strip(1) 在您的可执行文件上将删除它们。

如果您想将所有调试信息(在 .o 文件中)收集到一个独立的包中,那么您 运行 dsymutil 在可执行文件上。这使用调试说明(假设:(1) .o 文件仍在其原始位置,并且 (2) 可执行文件未被剥离)创建“dSYM 包”。如果二进制文件是 exename,则 dSYM 包是 exename.dSYM。当调试器在 exename 上 运行 时,它将在该二进制文件旁边查找 dSYM 包。如果在那里找不到,它将进行 Spotlight 搜索以查看 dSYM 是否位于您计算机上的 Spotlight 索引位置。

您可以 运行 dwarfdump .o 文件或 dSYM 包——它们都包含调试信息。 dwarfdump 在您的输出可执行文件中找不到任何调试信息。

所以,正常的工作流程:用-g编译。 Link 可执行映像。如果迭代开发,运行调试器。如果 shipping/archiving 二进制文件,创建 dSYM,剥离可执行文件。

我通过使用 (lldb) target symbols add a.out.dSYM 命令添加存在于 a.out.dSYM 目录中的调试符号的路径来解决它。