有时写c/c++程序,运行后出现core, 如果有core文件则可以gdb方便的定位问题,
可是,当core文件找不到(或被删除)时如何定位?
刚做了个测试,在没有core文件的情况下对程序bug进行定位
cat core.cpp
1 #include <iostream>
2
3 int main(int argc, char** argv){
4
5 int *p = NULL;
6 for(int i=0; i<15; i++){
7 p[i] = i;
8 }
9
10 return 0;
11 }
g++ -g core.cpp -o core
./core
Segmentation fault
/var/log]# vim messages
Nov 24 04:02:08 i237 syslogd 1.4.1: restart.
Nov 25 13:55:01 i237 kernel: testreg[19978]: segfault at 000000000000000a rip 00000036ed078d50 rsp 00007fffa7125888 error 4
Nov 25 13:58:20 i237 kernel: testreg[20711]: segfault at 00000000000003e8 rip 00000036ed078d70 rsp 00007fff8e28ac98 error 4
Nov 25 16:19:10 i237 kernel: core[17962]: segfault at 0000000000000000 rip 0000000000400677 rsp 00007fff0c53dc30 error 6
最后一个core[17962]即是刚才生成core的进程
可以到这个core.cpp生成core的目录下
执行:
addr2line 0000000000400677 -e /path/./core
输出:
....../core.cpp:7
这样我们可以初步定位到位core.cpp第7行的问题,回到程序中看是非法地址的赋值
我们看下man addr2line
NAME
addr2line - convert addresses into file names and line numbers.
这个命令本身就是把地址转成名称和行号的,只是我们对于这个地址需要在message日志中看rip地址才能得到
另外,error 后的数字转换到二进制依次对应描述如下:
bit2: 值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
所以从这个error 6也可以知道原因是 用户程序操作访问越界
最后百科里借用一个寄存器:
专用寄存器
专用寄存器包括: RIP、RSP和RFLAGS以及段寄存器CS、DS、ES、SS、FS和GS。
RIP(指令指针)RIP寻址代码段存储区内的下一条指令。当微处理器工作在实模式下时,这个寄存器是IP(16位);当80386及更高型号的微处理器工作于保护模式下时,则是EIP(32位)。注意,8086、8088和80286不包含EIP寄存器,而且只有80286及更高型号的微处理器可以工作于保护模式。指令指针指向程序的下一条指令,用于微处理器在程序中顺序地寻址代码段内的下一条指令。指令指针也可由转移指令或调用指令修改。在64位模式中,RIP包含40位地址总线,可用于寻址1TB平展模式地址空间。
RSP(堆栈指针)RSP寻址一个称为堆栈的存储区。通过这个指针存取堆栈存储器数据,具体操作将在本书后面讲解访问堆栈存储器数据的指令时再进行说明。这个寄存器作为16位寄存器被引用时,为SP;如果作为32位寄存器,则是ESP。