用GDB nexti解释段错误的原因

时间:2015-08-28 18:40:34

标签: c++ assembly segmentation-fault gdb

所以,我正在调试一个通过SIGSEGV神秘崩溃的程序。该程序是单线程的。

之前我调试了很多段错误 - 大多数都归结为堆栈或堆损坏。使用valgrind调试堆损坏问题通常很容易。堆栈损坏比较棘手,但是当GDB显示堆栈被破坏时,通常至少可以告诉堆栈损坏是问题。

但是,在这里我遇到了一个我从未见过的非常奇怪的问题。使用GDB按指令进行指令,我发现segfault在callq指令后立即发生。除了callq地址不是从寄存器或内存动态加载的 - 它只是一个静态函数地址:

(gdb) ni
0x00007ffff659c423      223         setPolicyDocumentLoader(docLoader);
1: x/i $pc
=> 0x7ffff659c423 <WebCore::FrameLoader::init()+351>:   mov    %rdx,%rsi
(gdb)
0x00007ffff659c426      223         setPolicyDocumentLoader(docLoader);
1: x/i $pc
=> 0x7ffff659c426 <WebCore::FrameLoader::init()+354>:   mov    %rax,%rdi
(gdb)
0x00007ffff659c429      223         setPolicyDocumentLoader(docLoader);
1: x/i $pc
=> 0x7ffff659c429 <WebCore::FrameLoader::init()+357>:
    callq  0x7ffff53a2d50 <_ZN7WebCore11FrameLoader23setPolicyDocumentLoaderEPNS_14DocumentLoaderE@plt>
(gdb) ni

Program received signal SIGSEGV, Segmentation fault.
0x0000000000683670 in ?? ()
1: x/i $pc
=> 0x683670:    add    %al,(%rax)
(gdb) 

因此,只要它callq执行到地址0x7ffff53a2d50,就会突然发生段错误。

我意识到,一般来说,Stackoverflow对于大多数段错误或类似问题都不太可能有用,因为其原因往往对某些特定环境非常具体,并且通常只是通过程序员错误归结为内存损坏。

但我仍然认为值得提出这个问题,因为这对我来说根本没有任何意义。当程序对合法的静态确定的函数地址执行callq指令时,OS如何可能以提供SIGSEGV?

2 个答案:

答案 0 :(得分:3)

nexti将执行下一条指令,但如果指令是call,则执行直到函数返回。来自GDB manual

  

nexti,nexti arg,ni

     
    

执行一条机器指令,但如果是函数调用,则继续执行直到该函数返回。参数是重复计数,如下一步。

  

当您调用callq调试器进入该函数但在执行该函数期间在某处崩溃。如果您想进入功能调用,那么当您点击stepi

时,我建议callq 0x7ffff53a2d50

答案 1 :(得分:0)

  

一旦它执行callq到地址0x7ffff53a2d50,它就会突然发生段错误。

这通常是由堆栈溢出引起的。

查找深度递归(使用where命令)。另请查看$rsp输出中的堆栈区域(包含当前info proc map值)。