【问题标题】:Segmentation fault - Debugging assembly gdb分段错误 - 调试程序集 gdb
【发布时间】: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-&gt;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-&gt;data[i] 的价值是什么。当我看到一个mov (reg,reg,8)指令时,它通常对应一个C数组访问。

标签: c debugging assembly linux-kernel gdb


【解决方案1】:

p = &v[队列]

如果 QUEUE 是 v 的大小,则错误,因为它的索引范围从零到 QUEUE-1。

所以用

p = &v[QUEUE-1]

或者,如果您想从 v 的开头开始,请使用

p = v

【讨论】:

  • 格式不好见谅,我在用手机
猜你喜欢
  • 2018-03-26
  • 2013-12-28
  • 2010-10-16
  • 2020-01-29
  • 2017-07-04
  • 2013-09-22
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
相关资源
最近更新 更多