linux 段错误调试方法
1.如果崩溃在程序中,例如 SMH kernel: process_name[32183]: segfault at 24 ip 0000000000412b13 sp 00007fffaab744e0 error 6 in process_name[400000+6e000]
1> 可以通过 addr2line -e process_name 0x412b13 -f 具体定位到源码中的那行那个函数。
2> 可以通过反汇编 objdump -dgS process_name > output 然后在output文件中搜索412b13,同样也可以定位到具体的函数。
2. 如果程序崩溃在共享库中,例如 process_name[10678]: segfault at 1 ip 00007f6ddc43c650 sp 00000000461b41a8 error 4 in libc-2.4.so[7f6ddc3ca000+127000]
指令的实际地址是:00007f6ddc43c650 - 7f6ddc3ca000 = 0x72650
1> 可以通过 addr2line -e libc-2.4.so 0x412b13 -f 具体定位到libc-2.4.so中的那个函数。2> 可以通过反汇编 objdump -dgS libc-2.4.so > output 然后在output文件中搜索72650,同样也可以定位到具体的函数。
3.对上述两个示例做一些必要的说明:
1> error code(比如上述的 error 4 & error 6)做一些说明: 具体可以在/usr/src/linux***/arch/i386/mm/fault.c中可以通过搜索"segfault at"找到
/*
* Page fault
error code bits
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
* bit 3 == 1 means use of reserved bit detected
* bit 4 == 1 means fault was an instruction fetch
*/
- #define PF_PROT (1<<0)
- #define PF_WRITE (1<<1)
- #define PF_USER (1<<2)
- #define PF_RSVD (1<<3)
- #define PF_INSTR (1<<4)
- 2>. 当装载程序时候,如果共享库是通过动态链接(还有一种是动态加载, dynamic linker & dynamic loader)的方式,那么会为该共享库分配地址空间(每次执行程序时候地址都是不一样的)。所以崩溃时的指令地址是需要减去共享库的基地址的,才是指令的偏移地址。以上面的例子就是 00007f6ddc43c650 - 7f6ddc3ca000 = 0x72650
- 3>. 程序崩溃时候,仅通过常规方法是没有办法知道源程序中哪行代码调用了库函数中的接口导致了程序的崩溃,因为无法获取到寄存器的相关信息,换句话说,就是没办法知道下一条指令的地址。为此,我们还是可以放开coredump的开关,通过gdb process_name coredump来分析(糟糕的情形,栈帧被破坏了,我们能做的是分析汇编指令想法恢复被破坏的栈帧);或者在我们的源程序中通过捕捉SIGSEGV信号,将栈帧的信息打印到日志文件中来分析,采用gcc提供的backtrace和backtrace_symbol,如若想要打印出来的栈帧信息中包含函数名,那么我们需要在编译的时候采用rdynamic选项(通知链接器将符号添加到动态符号表中)。
4>.参考资料 http://www.2cto.com/kf/201311/256739.html
http://blog.chinaunix.net/uid-20357359-id-1963702.html
http://www.xxlinux.com/linux/article/accidence/technique/20070125/7209.html
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。