24

我正在尝试调试我正在编写的 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. 经过一番搜索,我尝试运行dsymutil main.owhich said warning: no debug symbols in executable (-arch x86_64),所以调试符号可能不是由我的构建命令生成的?

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

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

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

  5. 我在可执行文件和目标文件上运行dwarfdump我在这里读到了)。在我未经训练的眼睛看来,调试符号出现在目标文件中,但不在可执行文件本身中(除非dwarfdump仅适用于目标文件,这是可能的)。所以也许链接阶段是问题所在。或者也许 DWARF 有问题。

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

4

2 回答 2

28

当您将 -g 命令行选项添加到 clang 时,DWARF 调试信息将放入.o文件中。当您将目标文件(.o,ranlib 档案又名静态库又名.a文件)链接到可执行文件/dylib/framework/bundle 时,“调试说明”会放在可执行文件中,以说明(1).o带有调试信息的 etc 文件的位置, 和 (2) 可执行二进制文件中函数/变量的最终地址。优化标志(-O0-O2)对调试信息的生成没有影响——尽管使用优化编译的调试代码比调试在-O0.

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

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

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

因此,正常的工作流程:使用 -g 编译。链接可执行映像。如果是迭代开发,运行调试器。如果发送/归档二进制文件,请创建 dSYM,剥离可执行文件。

于 2016-05-02T00:35:00.723 回答
7

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

于 2016-05-19T16:47:56.370 回答