Linux下关于coredump的定位方法说明

 更新时间:2023年09月04日 08:52:53   作者:凌肖战  
这篇文章主要介绍了Linux下关于coredump的定位方法说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一. Linux 下 cordump 机制

Linux 系统下存在一种 coredump 机制。

当程序运行过程中异常终止或崩溃,Linux 操作系统会将程序当时的堆栈等内存状态信息记录下来,会在指定文件下生成一个 coredump 相关的 Log 文件。

软件开发人员可以通过对 coredump文件进行分析,即可定位到导致程序运行崩溃的 bug

当程序访问的内存超过了系统给定的内存空间,就会产生 Segmentation fault(core dumped),所以:

一般产生段错误的原因有如下:

  • 1. 访问了不存在的内存地址。
  • 2. 访问了系统保护的内存地址。
  • 3. 数组或堆空间访问越界,等等一系列内存非法访问操作。

二. coredump 文件定位方法

根据上一篇配置 coredump 机制的方法,成功配置好之后。

就可以运行代码,当程序运行中崩溃时即可产生相应的 coredump 文件。

操作如下:

  • 1. 首先,开启 coredump 功能。设置成功后,可以通过 ulimit -c 命令验证。
  • 2. 其次,关闭 ubuntu 系统下 apport.service 服务程序。
  • 3. 其次,编译代码。编译时必须加 -g 编译选项(带调试信息的编译选项)。
  • 4. 最后,运行程序。当程序运行时出现 核心转储等提示错误时,即可生成 coredump 文件。

这里为了方便起见,不更改 coredump 文件的生成路径,即生成的 coredump 文件会与可执行程序在同一目录下,文件默认叫 core 的文件。

下面以一段测试代码说明一下,Linux 环境下 使用 gdb 调试器对 coredump 文件进行分析调试。

代码如下:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
int fun()
{
    printf("---fun()\n");
    char buffer[3] = {0}; 
    memcpy(buffer, "Hello", 6);  
    printf("---buffer: %s\n", buffer);  
    return 0;
}
int main()
{
    printf("---main()---\n");   
    int pid = 0;
    pid = getpid();
    printf("pid %d\n", pid);
    fun(); 
    printf("---End main\n");
    return 0;
}

1. 编译运行

操作如下:

编译代码。输入 gcc -g main.c -o main.out 命令

运行程序。输入 ./main.out 命令。

如下所示:

wangtian@wangtian-virtual-machine:~/Code_Learns/C_Learns/debug/debug2$ ./main.out 
---main()---
pid 3814
---fun()
---buffer: Hello
*** stack smashing detected ***: terminated
已放弃 (核心已转储)

当程序出现段错误时崩溃时,可查看程序当前目录下是否生成 coredump 相关文件。

如下所示:

wangtian@wangtian-virtual-machine:~/Code_Learns/C_Learns/debug/debug2$ ls -l
总用量 180
-rw------- 1 wangtian wangtian 393216 12月 13 16:55 core
drwxrwxr-x 2 wangtian wangtian   4096 11月 25 22:24 debug
-rw-rw-r-- 1 wangtian wangtian     90 10月 28 13:32 debug.c
-rw-rw-r-- 1 wangtian wangtian     81 10月 20 18:12 debug.h
-rw-rw-r-- 1 wangtian wangtian   5688 12月 13 16:55 debug.o
-rw-rw-r-- 1 wangtian wangtian    356 12月 13 16:55 main.c
-rw-rw-r-- 1 wangtian wangtian   7144 12月 13 16:55 main.o
-rwxrwxr-x 1 wangtian wangtian  21144 12月 13 16:55 main.out

2. gdb 调试 coredump 文件

查看 coredump 文件。

输入 objdump -t core 命令:

wangtian@wangtian-virtual-machine:~/Code_Learns/C_Learns/debug/debug2$  objdump -t core
core:     文件格式 elf64-x86-64
SYMBOL TABLE:
无符号

可以看到,coredump 文件是不带符号表的。

所以调试时,需要同时加上 可执行程序文件。

输入命令 gdb main.out core 进行调试,如下所示:

wangtian@wangtian-virtual-machine:~/Code_Learns/C_Learns/debug/debug2$ gdb main.out core
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from main.out...
[New LWP 4272]
Core was generated by `./main.out'.
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: 没有那个文件或目录.

可以看到,程序收到 signal SIGABRT 后崩溃了。

输入 bt (backtrace 缩写) 命令,可以查看下程序崩溃时的堆栈信息,

如下所示:

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ff8d6f5c859 in __GI_abort () at abort.c:79
#2  0x00007ff8d6fc729e in __libc_message (action=action@entry=do_abort, 
    fmt=fmt@entry=0x7ff8d70f108f "*** %s ***: terminated\n")
    at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ff8d7069aea in __GI___fortify_fail (
    msg=msg@entry=0x7ff8d70f1077 "stack smashing detected") at fortify_fail.c:26
#4  0x00007ff8d7069ab6 in __stack_chk_fail () at stack_chk_fail.c:24
#5  0x000056183642c243 in fun () at main.c:12
#6  0x000056183642c28c in main () at main.c:20

以上的堆栈信息,显示 __stack_chk_fail () 错误。可以看到调用 fun() 函数过程中发生了栈问题。

__stack_chk_fail () 打印信息说明发生了缓冲区溢出,即数组越界问题。

从这段栈信息中并不能直观的定位到出现问题的地方,因为出现问题的地方是之前的数组越界,但是这里的栈信息已经执行到主函数 main中, 特别是在大项目中更是无法准确的定位出错的地方。

越界写坏内存,什么时候会 crash 取决于我们写坏的内存什么时候被用到,有时候会离犯罪现场特别远。所以,导致定位这样情况的崩溃问题比较麻烦。

在发生__stack_chk_fail () 错误的附近函数 fun() 中第11 行打断点,如下所示:

(gdb) b main.c:11
Breakpoint 1 at 0x56183642c22a: file main.c, line 11.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000056183642c22a in fun at main.c:11
(gdb) r
Starting program: /home/wangtian/Code_Learns/C_Learns/debug/debug2/main.out 
---main()---
pid 3868
---fun()
---buffer: Hello
Breakpoint 1, fun () at main.c:11
11	    return 0;
(gdb) n
12	}
(gdb) 
*** stack smashing detected ***: terminated
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.
(gdb) 

初步可以定位到,是在函数 fun() 内部发生了数组越界问题。目前还不能定位到具体某一行。

canary 栈溢出保护机制的具体原理:

  • gcc 编译器默认开启了 canary 栈保护机制。
  • canray 栈保护机制是专门针对栈溢出攻击涉及的一中保护机制。
  • 由于栈溢出攻击的主要目标是通过溢出覆盖函数栈高位的返回地址,因此,其思路是在函数开始执行前,即返回地址前写入一个字长的随机数据(canary),在函数返回前校验该值是否被改变,如果改变则认为是栈溢出,程序直接终止,以此来防止信息泄露。

总结

以上一系列的操作,说明通过 gdb 对 数据越界问题的调试定位,这种方法不是太好用。

原因:越界写坏内存,什么时候会 crash 取决于我们写坏的内存什么时候被用到,有时候会离犯罪现场特别远。所以,导致定位这样情况的崩溃问题比较麻烦。后续文章再针对数组越界问题定位方法进行新的总结。

好了,以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • RHEL 7中防火墙的配置和使用方法

    RHEL 7中防火墙的配置和使用方法

    下面小编就为大家带来一篇RHEL 7中防火墙的配置和使用方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 解决CentOS 7升级Python到3.6.6后yum出错问题总结

    解决CentOS 7升级Python到3.6.6后yum出错问题总结

    这篇文章主要介绍了CentOS 7升级Python到3.6.6后yum出错问题解决总结,本文给大家介绍的非常详细具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • linux网络知识详解:iptables 规则介绍

    linux网络知识详解:iptables 规则介绍

    这篇文章主要介绍了linux网络知识详解:iptables 规则介绍,需要的朋友可以参考下
    2024-02-02
  • Linux VPS/服务器 网站及数据库自动本地备份并FTP上传备份脚本

    Linux VPS/服务器 网站及数据库自动本地备份并FTP上传备份脚本

    Linux VPS/服务器 网站及数据库自动本地备份并FTP上传备份脚本的操作时怎样进行的?如今备份已经成为一种非常重要的操作技术,掌握好数据库备份,对大家以后的工作会很有帮助
    2012-05-05
  • linux开机启动nodemanager步骤

    linux开机启动nodemanager步骤

    这篇文章主要介绍了linux开机启动nodemanager的步骤,大家参考使用吧
    2014-01-01
  • centos查找已安装的jdk路径的方法

    centos查找已安装的jdk路径的方法

    本篇文章主要介绍了centos查找已安装的jdk路径的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 缓存服务器的建立原理分析

    缓存服务器的建立原理分析

    通常情况下我们运行程序的过程中会产生一些中间数据,这些中间数据需要在将来的某个时间读取。这就要求我们要把它存在一个提供高速存取的地方,最好的选择就是内存中。
    2008-10-10
  • Apache之AllowOverride参数使用说明

    Apache之AllowOverride参数使用说明

    通常利用Apache的rewrite模块对 URL 进行重写的时候, rewrite规则会写在 .htaccess 文件里。但要使 apache 能够正常的读取.htaccess 文件的内容,就必须对.htaccess 所在目录进行配置。
    2011-01-01
  • Ubuntu linux 安装 PHP5.3.0的命令

    Ubuntu linux 安装 PHP5.3.0的命令

    5.3.0 的正式版已经发布有段时间了,看到脚本之家上面有个windows下的安装php5.3的教程,所以想起写一个关于linux的PHP5.3的安装教程。
    2009-09-09
  • Linux中搭建coturn服务器的过程

    Linux中搭建coturn服务器的过程

    这篇文章主要介绍了Linux中搭建coturn服务器,首先下载coturn源码,进入到coturn路径下执行相应命令,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-11-11

最新评论