【问题标题】:Printing a variable's content using lldb使用 lldb 打印变量的内容
【发布时间】:2014-08-06 12:53:36
【问题描述】:

好的,所以这听起来像是一个愚蠢的问题,但我被困住了:我在 lldb 调试会话期间无法读取变量的值(gdb 工作正常)。

我找到了其他人的帖子,他们遇到了与我相同的错误消息,但不同的是,我什至不知道如何打印出最简单形式的变量的值。

为了更好地表达我的问题,我将在这里考虑一个非常简单的示例。我们有一个包含以下代码的文件“main.c”:

#include <stdlib.h>
#include <stdio.h>

int main(void) {
  int a = 1;
  int b = 2;
  int c = 0;
  c = a + b;
  c = c*b;
  printf("c = %d\n", c);
  return 0;
}

我使用它编译它:

user@machine ~ $ gcc -g main.c

一个名为的二进制文件 “a.out” 生成

然后我 ivoque lldb :

user@machine ~ $ lldb-3.4 ./a.out

我想在第 9 行停下来读取 c 的值。因此,我首先添加一个断点:

(lldb) breakpoint set -f main.c -l 9

然后我运行代码:

(lldb) run

到目前为止,一切都按预期进行。现在是棘手的部分:我想读取变量 c 的值。因此,我写:

(lldb) print c

然后 lldb 返回我:

error: use of undeclared identifier 'c'
error: 1 errors parsing expression

当然:

(lldb) expression c

返回完全相同的错误信息。

有什么我错过的吗?任何帮助将不胜感激。

我的设置:

  • lldb:“lldb 版本 3.4(修订版)”(包 v.:“3.4~svn183914-1ubuntu1”)
  • gcc : "gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1" (package v. : "4.8.1-2ubuntu3")
  • (我的仓库是linux mint 16默认提供的)

@Sean Perry 的回答提供了更多信息:

1:附加选项 -O0 似乎不会改变调试器的行为。

2:我也尝试使用以下虚拟代码代替我之前的代码

#include <stdlib.h>
#include <stdio.h>

int main(void) {
  long a = 1;
  long b = 2;
  long c = 0;
  c = a + b;
  c += (long) &c;
  printf("c = %ld\n", c);
  return 0;
}

我不确定@Sean Perry 所说的“使用指针”是什么意思,但我认为它必须阻止代码优化,因为每次运行二进制文件时变量 c 的地址(或多或少)都会随机更改。

3:最后,我注意到了一些有趣的事情:

  • 使用 gcc [-g -O0] 编译,然后使用 gdb 进行调试:可行
  • 使用 gcc [-g -O0] 编译然后使用 lldb 调试:不起作用
  • 使用 clang [-g -O0] 编译然后使用 gdb 调试:工作
  • 使用 clang [-g -O0] 编译然后使用 lldb 调试:工作

edit1:回复@SeanPerry edit2 : 区分软件版本和软件包版本

【问题讨论】:

  • 我已经尝试复制粘贴您的确切代码并使用Ubuntu 4.8.2-19ubuntu1Ubuntu/Linaro 4.7.3-12ubuntu1 编译它,并尝试使用lldb-3.4 (stable branch) 对其进行调试,它可以正常工作(即@987654334 @导致(int) $0 = 3)
  • @Scis:尴尬……你是在 32 位还是 64 位机器上? (只是想知道我正在使用的 64-b 版本的 gcc 是否存在故障)。我的 gcc 版本是 Ubuntu/Linaro 4.8.1-10ubuntu9,我的 lldb 版本是“lldb version 3.4 (revision)”。我对这是一个稳定版本还是不稳定版本有点困惑......一方面,我的仓库中的 lldb 包被标记为“svn”,另一方面我安装它并输入“aptitude install lldb-3.4” ,这正是您建议我阅读的页面 [链接] (llvm.org/apt) 上给出的说明。你知道我怎么能找到这个吗?
  • 我使用的是 64 位 ubuntu 14.04 LTS。至于安装,似乎我们俩都以相同的方式安装了它(顺便说一下,您是否也按照建议安装了clang-3.4?尝试再次运行apt-get install clang-3.4 lldb-3.4,也许有一些版本不匹配——这当然只是一种猜测,但又一次这是一种奇怪的行为)
  • 我好像安装了clang-3.2.* 版本的clang。我还安装了libllvm-3.3libllvm-3.3:i386 以及libllvm-3.4(lib 的3.3 版本是其他软件的依赖项,包括x.org 似乎)。但是,仅安装 clang-3.4lldb-3.4 似乎没有任何区别。再一次,clang+lldb 组合工作正常,这是 gcc+lldb 组合失败。当我第一次发布我的问题时,我认为我无法正确使用 lldb,但越是这样,我就越觉得这个问题来自我特定的 gcc 版本中的一个小故障。 ...
  • @Scis 实际上,问题来自我的特定版本的 gcc (4.8.1)。使用 gcc 4.7.3 可以正常工作。我认为这一定是在我的 r 之间纠正的小故障。 4.8.1 和 r。 4.8.2 你有……这么少……(^.^')谢谢你的帮助!

标签: c debugging lldb


【解决方案1】:

这段代码非常简单,我敢打赌 llvm 已经完全删除了变量。尝试在禁用优化 (-O0) 的情况下进行编译,看看是否有帮助。除此之外,使用指针或做一些更复杂的事情,这样编译器就不会删除你的数学并用预先计算的值替换它。

【讨论】:

  • 一种简单的测试方法可能是在二进制文件上使用objdump 并查看它生成的代码。不过,如果它适用于gdb..
  • 感谢您的回复!根据您的回答,我尝试了一些事情,但不幸的是我不是很成功......我用今天的尝试结果完成了我最初的问题。
  • @cnicutar 我使用 objdump 反汇编了二进制文件,似乎二进制文件中正在进行加法和乘法运算:000000000040052d
    : [...] 400551: 48 8b 55 e8 mov -0x18(%rbp),%rdx 400555: 48 01 d0 添加 %rdx,%rax 400558: 48 89 45 f8 mov %rax,-0x8(%rbp) [...] 40055c: 48 8b 45 f8 mov - 0x8(%rbp),%rax 400560: 48 0f af 45 f0 imul -0x10(%rbp),%rax 400565: 48 89 45 f8 mov %rax,-0x8(%rbp) [...] 这不是“ hard" 证明,但我想这意味着某处必须有 ac 变量。
【解决方案2】:

似乎这是使用gcc 4.8.1lldb-3.4 时的特定问题

使用gcc-4.8.2gcc-4.7.3 可以正常工作。

【讨论】:

  • 该死的,你发布答案的速度比我还快! (^.-)
【解决方案3】:

调查您所看到的行为的最佳方法是查看调试信息。在 Mac OS X 系统上,如果您没有创建 dSYM,您将在 .dSYM 包或 .o 文件上运行 dwarfdump。调试信息包含从编译器到调试器的关于在何处查找变量的指令。

在实时进程中,使用 lldb,您可以使用 image lookup -v -a $pc(或简称为 im loo -va $pc)让 lldb 向您显示所有局部变量的存储位置(以 DWARF 位置表达式语言表示)。

如果有一个程序 gdb 不能打印变量而 lldb 在同一个 pc 地址 不能,这听起来可能是一个 lldb 错误。调试信息是关于变量存储在哪里以及它们“存活”多长时间的最终事实(就调试器而言)。在优化的代码中,它们可能只存在于您函数的非常短的部分。

从 hack 的角度来看,真正的来源是阅读汇编代码。通常,在优化下,编译器不会尽可能地跟踪变量的位置——它可能某个变量在给定的 pc 地址不可用,但如果你阅读程序集足够接近,您可能会发现仍然保存在堆栈中的最后一个值的副本等。

【讨论】:

  • 感谢您的信息!我显然对这一切都很陌生,因此我从未真正深入研究过二进制代码,所以你所说的对我来说很有趣。我抬头看看$pc 是什么(我有点发现),但后来我想知道:是否还有其他“特殊”变量可能与lldb-debugging 相关?
  • 其他问题:虽然 DWARF 格式是标准的调试格式,但 *.dSYM 文件的生成是一种普遍的做法,还是主要与 Mac 相关?为什么您似乎更喜欢将调试信息与编译代码本身分开?奇怪的是,我找不到gccclang 或生成那些*.dSYM 文件的选项,但我可能忽略了它...
猜你喜欢
  • 2016-07-06
  • 2013-11-13
  • 2016-07-10
  • 2021-10-02
  • 1970-01-01
  • 2018-08-09
  • 2015-10-03
  • 2018-08-15
  • 2019-06-15
相关资源
最近更新 更多