【发布时间】:2015-09-15 09:29:08
【问题描述】:
我正在调试一个分段错误。这是在 ff_printf 调用时出错的代码 sn-p。
for (p = &v[QUEUE], i = 0; i < p->used; i++) {
queue_t *q = p->data[i];
ff_printf(F_DB, " %02u %s\n",
p->cp, q->tq->queue_name);
}
段错误在 ff_printf 行。当我通过 gdb 调试时,我可以解析 p->cp 和 q->tq->queue_name。 F_DB 也被解析,因为它是一个枚举。因此,它并没有因为无效的尊重而出现段错误。
反汇编代码后,我得到了上面代码 sn-p 的以下汇编代码,用于 ff_printf 行。
0x0000000000449b88 <+360>: mov -0x14(%r13),%rax
0x0000000000449b8c <+364>: movzwl %r10w,%edx
0x0000000000449b90 <+368>: movzwl (%rbx),%r9d
0x0000000000449b94 <+372>: mov $0x56a4d9,%r8d
0x0000000000449b9a <+378>: mov $0x5,%ecx
0x0000000000449b9f <+383>: mov $0x5bb,%esi
0x0000000000449ba4 <+388>: mov $0x56a27b,%edi
0x0000000000449ba9 <+393>: mov (%rax,%rdx,8),%rax
0x0000000000449bad <+397>: mov $0x56aec0,%edx
=> 0x0000000000449bb2 <+402>: mov 0x88(%rax),%rax
0x0000000000449bb9 <+409>: mov %r10d,-0x48(%rbp)
0x0000000000449bbd <+413>: mov %rax,(%rsp)
0x0000000000449bc1 <+417>: xor %eax,%eax
0x0000000000449bc3 <+419>: callq 0x4423c0 <ff_printf>
现在,我确实调试了寄存器并使用代码 sn-p 进行了验证。我能够通过程序集调试(即通过寄存器)获得 F_DB、p->cp、q->tq->queue_name。我观察到 %rax 的值为 0x0。我观察到段错误发生在调用 ff_printf 库之前。
我有两个问题:
1:我如何映射这个
" => 0x0000000000449bb2 <+402>: mov 0x88(%rax),%rax"
到代码sn-p?
我观察到 %rax 是通过
0x0000000000449b88 <+360>: mov -0x14(%r13),%rax
我认为是 mov ($r13 - 0x14 的地址) 到 %rax。
和
0x0000000000449ba9 <+393>: mov (%rax,%rdx,8),%rax
我认为它是 mov(地址 $rax+ 地址 $rdx+ 8)到 %rax。我对吗 ?
2:我不确定是否有任何堆栈损坏。这个段错误非常罕见,我无法重现它。如何从这里进一步回溯?
【问题讨论】:
-
在 gdb 中,运行
disassemble /m以查看与反汇编指令混合的 C 源代码。 (这只有在程序使用-g选项编译时才有效。)你能打印p->data[i]的值吗?如果它是零,这将解释 seg 错误。 -
我通过 gdb 运行 disas /m。事实上,上述汇编是针对 C 源代码中的 ff_printf 行的。我能够打印 p->cp、q->tq->queue_name 的值。因此,p->data[i] 没有问题。我确实从寄存器中检查了这些值,因为这些值是从 gdb 中优化出来的。我很困惑它正在从 gdb 打印 q->tq->queue_name 的值。但在寄存器 %rax 中,该值为 null,这说明了段错误。但我不明白为什么它为 null 以及它使用 mov 指令执行什么操作。我猜这是一个竞争条件。
-
是的,可执行文件的调试信息可能包含部分不正确的关于 q 位置的信息,而 q 实际上保存在 %rax 中。这就是为什么我很好奇
p->data[i]的价值是什么。当我看到一个mov (reg,reg,8)指令时,它通常对应一个C数组访问。
标签: c debugging assembly linux-kernel gdb