《linux 调试系列(一)coredump环境配置》
《linux 调试系列(二)coredump段错误查找使用详解》
一、 背景
这一节,通过一个样例,详细介绍怎么使用coredump来定位程序段错误。
构造两个常用错误,缓冲区溢出和非法指针引用。
二、非法指针样例程序
- 测试程序
#include <stdio.h>
#include <string.h>
/**
* [buf_overflow 缓冲区溢出]
* @author hayson <haixing9@qq.com>
* @date 2023-03-24 08:28
*/
void buf_overflow(){
char data[8] = {0x0};
strcpy(data, "hello world! hello world! hello world!hello world!hello world!hello world!");
}
/**
* [illegal_pointer 非法指针引用]
* @author hayson <haixing9@qq.com>
* @date 2023-03-24 08:28
* @param [description]
*/
void illegal_pointer(){
char *data = NULL;
strcpy(data, "hello world! hello world! hello world!hello world!hello world!hello world!");
}
int main(int argc, char** argv){
int input = 0;
if(argc == 2)
input = atoi(argv[1]);
if(input)
buf_overflow();
else
illegal_pointer();
return 0;
}
- 编译
编译记得带上-g调试信息
gcc -o test test.c -g
三、调试程序
非法指针测试
- 运行程序,生成coredump文件
$ ./test_core
Segmentation fault (core dumped)
$ ls
core.test_core.7568 Makefile src test_core
我们能看到生成了core.test_core.756文件。
2. gdb 运行调试定位
首先gdb运行程序载入程序函数符号表
gdb ./test_core
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 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 "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test_core...
然后继续在gdb环境内输入core-file
命令载入刚刚的coredump文件。
(gdb) core-file core.test_core.7568
[New LWP 7568]
Core was generated by `./test_core'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000aaaadb3908d4 in illegal_pointer () at src/test_illegal.c:22
22 strcpy(data, "hello world! hello world! hello world!hello world!hello world!hello world!");
(gdb) quit
以上信息,我们可以看到进程收到了一个SIGSEGV信号,段错误退出了,在22行,SIGSEGV信号的默认处理动作是终止进程,并进行coredump,这就是我们程序退出的全部原因
缓冲区溢出测试
- 运行程序,生成coredump文件
$ ./test_core 1
*** stack smashing detected ***: terminated
Aborted (core dumped)
$ ls
core.test_core.7568 core.test_core.7623 Makefile src test_core
core.test_core.7623即core文件
2. gdb 运行调试定位
$ gdb test_core
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 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 "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test_core...
(gdb) core-file core.test_core.7623
[New LWP 7623]
Core was generated by `./test_core 1'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb)
我们能看到程序收到了SIGABRT信号aborted,但并没有真正指向错误处。
继续查询栈内容
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x0000ffffbe9daaac in __GI_abort () at abort.c:79
#2 0x0000ffffbea27f40 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0xffffbeae7ff0 "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x0000ffffbea9a4c8 in __GI___fortify_fail (msg=msg@entry=0xffffbeae7fd8 "stack smashing detected") at fortify_fail.c:26
#4 0x0000ffffbea9a49c in __stack_chk_fail () at stack_chk_fail.c:24
#5 0x0000aaaade5508b0 in buf_overflow () at src/test_illegal.c:12
#6 0x0000aaaade550950 in main (argc=1819438967, argv=0x656821646c726f77) at src/test_illegal.c:31
(gdb)
到这里,我们就能看出,错误是一个__stack_chk_fail,字面堆栈检测错误,继续往下看
0x0000aaaade5508b0 in buf_overflow () at src/test_illegal.c:12
这里就明确指出来了出错位置,这是一个典型的缓冲区使用不当造成的栈溢出。
信号类型说明
处理动作一项中的字母含义如下
A 缺省的动作是终止进程。
B 缺省的动作是忽略此信号,将该信号丢弃,不做处理。
C 缺省的动作是终止进程并进行内核映像转储(core dump),内核映像转储是指将进程数据在内存的映像和进程在内核结构中的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员 提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。
D 缺省的动作是停止进程,进入停止状况以后还能重新进行下去。
E 信号不能被捕获。
F 信号不能被忽略。
工程
最后,附上源码工程github地址:
git clone https://github.com/hayson/coredump_sample.git
参考
Linux实用gdb结合coredump定位崩溃进程
【Linux】GDB用法详解(5小时快速教程)
Linux程序coredump地址显示问号的调试方法 - 基于map文件