所以,我正在调试一个通过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?
答案 0 :(得分:3)
nexti
将执行下一条指令,但如果指令是call
,则执行直到函数返回。来自GDB manual:
nexti,nexti arg,ni
执行一条机器指令,但如果是函数调用,则继续执行直到该函数返回。参数是重复计数,如下一步。
当您调用callq
调试器进入该函数但在执行该函数期间在某处崩溃。如果您想进入功能调用,那么当您点击stepi
callq 0x7ffff53a2d50
答案 1 :(得分:0)
一旦它执行callq到地址0x7ffff53a2d50,它就会突然发生段错误。
这通常是由堆栈溢出引起的。
查找深度递归(使用where
命令)。另请查看$rsp
输出中的堆栈区域(包含当前info proc map
值)。