我正在尝试调试我正在编写的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
会覆盖它,对吧?
我尝试了什么
我使用相同的构建设置通过一个简单的“hello world”程序重新创建了这个问题。
经过一番搜索后,我尝试运行dsymutil main.o
warning: no debug symbols in executable (-arch x86_64)
,所以也许我的构建命令没有生成调试符号?
我也尝试在构建命令中添加-gsplit-dwarf
但没有效果。
以下是我的'hello world'版本的链接命令:
clang ++ main.o -L / usr / local / lib -g -o hello
我在可执行文件和目标文件上运行dwarfdump
(I read about it here)。它看起来像我的未经训练的眼睛,如目标文件中存在的调试符号 ,但不存在于可执行文件本身中(除非dwarfdump
仅适用于目标文件,这是可能的)。所以也许链接阶段是问题。或者DWARF可能存在问题。
我现在通过在终端中逐个发布构建命令,让它在'hello world'程序中工作。因此我猜测这可能是我的构建系统(Tup)的一个问题,可能使用不同的工作目录运行命令,因此路径会被破坏或者其他东西。
答案 0 :(得分:19)
将-g命令行选项添加到clang时,DWARF调试信息将放在.o
文件中。当您将目标文件(.o
,ranlib归档,又名静态库,即.a
文件)链接到可执行文件/ dylib / framework / bundle,&#34;调试说明&#34;在可执行文件中放入(1).o
etc文件的位置和调试信息,以及(2)可执行二进制文件中函数/变量的最终地址。优化标志(-O0
,-O2
等)对调试信息生成没有影响 - 尽管使用优化编译的调试代码比调试-O0
生成的代码要困难得多。
如果您在该可执行二进制文件上运行调试器 - 无需任何其他修改 - 调试器将从.o
等文件 中读取调试信息,只要它们是&#d;在构建可执行文件时,仍然在同一文件路径上的文件系统 。这使得迭代开发变得快速 - 没有工具需要读取,更新和输出(大)调试信息。你可以看到这些&#34;调试笔记&#34;在可执行文件中,通过运行nm -pa exename
并查找OSO
个条目(以及其他条目)。这些是stabs nlist条目,并且在您的可执行文件上运行strip(1)
将删除它们。
如果要将所有调试信息(在.o
文件中)收集到独立包中,则在可执行文件上运行dsymutil
。这使用调试注释(假设:(1).o
文件仍在其原始位置,(2)可执行文件尚未被剥离)以创建&#34; dSYM
包&# 34 ;.如果二进制文件是 exename ,则dSYM包是 exename.dSYM 。当调试器在 exename 上运行时,它将在dSYM包的二进制文件旁边显示。如果在那里找不到,它将进行Spotlight搜索以查看dSYM是否位于计算机上的聚光灯索引位置。
您可以在dwarfdump
文件或dSYM软件包上运行.o
- 它们都包含调试信息。 dwarfdump
无法在输出可执行文件中找到任何调试信息。
所以,正常的工作流程:用-g编译。链接可执行映像。如果是迭代开发,请运行调试器。如果运送/存档二进制文件,请创建dSYM,删除可执行文件。
答案 1 :(得分:3)
我通过使用(lldb) target symbols add a.out.dSYM
命令添加调试符号的路径解决了这个问题,该路径存在于a.out.dSYM目录中。