现在的位置: 首页 > 综合 > 正文

linux系统crash问题练习五:空指针访问

2014年05月24日 ⁄ 综合 ⁄ 共 2997字 ⁄ 字号 评论关闭

测试代码如下:
case1:
#include <string.h>

static void _null_pointer_test(void)
{
    char *ps_str = 0;
   
    *ps_str = 'o';
   
    return;
}

int main(int argc, char *argv[])
{
    _null_pointer_test();
   
    while(1)
    {
        sleep(1);
    }
   
    exit(0);
}

对于case1,可以很容易的从callstack中查到问题点,
sh-# ./gdb -c ./core_test_main_sig11_pid2653 ./test_main
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from ./test_main...done.
[New Thread 2653]
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.3...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.3
Core was generated by `./test_main'.
Program terminated with signal 11, Segmentation fault.
#0  0x0000837c in _null_pointer_test ()
(gdb) bt
#0  0x0000837c in _null_pointer_test ()
#1  0x000083a4 in main ()
(gdb)
#0  0x0000837c in _null_pointer_test ()
#1  0x000083a4 in main ()
(gdb)

case2:
#include <string.h>

static void _null_pointer_test(void)
{
    char *ps_str = 0;
   
    strcpy(ps_str, "_null_pointer_test");
   
    return;
}

int main(int argc, char *argv[])
{
    _null_pointer_test();
   
    while(1)
    {
        sleep(1);
    }
   
    exit(0);
}

运行测试程序,
sh-# ./test_main &
1966
sh-#

对于case2,又如何确认问题点呢?
从使用gdb查看callstack的结果来看,并不能很快定位到具体的问题。
sh-# ./gdb -c ./core_test_main_sig11_pid1966 ./test_main
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from ./test_main...done.

warning: exec file is newer than core file.
[New Thread 1966]
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.3...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.3
Core was generated by `./test_main'.
Program terminated with signal 11, Segmentation fault.
#0  0x4017d9d8 in memcpy () from /lib/libc.so.6
(gdb) bt
#0  0x4017d9d8 in memcpy () from /lib/libc.so.6
#1  0x00000000 in ?? ()
(gdb)

#0  0x4017d9d8 in memcpy () from /lib/libc.so.6
#1  0x00000000 in ?? ()
(gdb)

2014/04/09补充:
先接case2的分析,对于这种字符串copy可能已经破坏了函数的调用栈,
所以不能很显然的从core dump的callstack中看出问题点。
这时可能就需要通过地址0x4017d9d8来查了,通过objdump/nm/readelf来查看这个地址所在的symbol。
此处不详述,未来有机会再起一篇讨论。

case3:
以上case1/2讨论的都是向空指针写入数据造成的系统crash的case;
其实读空指针也会引起系统crash;
二者读写空指针引起的系统crash,kernel都会发出SIGSEGV(段访问错误)出来。
因为linux在进程crash时会发送特定的signal出来,所以我们就可以利用core dump来协助debug了。

int main(int argc, char *argv[])
{
    int* p_value = null;
   
    /* read from null address */
    printf("\n*p_value=%d\n", *p_value);
   
    while(1)
    {
        sleep(1);
    }
   
    exit(0);
}

抱歉!评论已关闭.