【Linux】coredump 分析

简介

core的最原始含义是磁芯,是一种存储设备,dump的意思是倒出,那么core dump的含义就是:当进程发生异常时,会把当时的内存信息倾倒出来,形成core文件。

Segmentation fault (core dumped)

示例

示例程序

#include <stdio.h>
void swap(int *px, int *py)
{
        int tmp = *px;
        *px = *py;
        *py = tmp;
}
int main()
{
        int a = 1;
        int b = 2;
        int c = a + b;
        printf("%d, %d, %d\n", a, b, c);
        swap(&a,& b);
        printf("%d, %d, %d\n", a, b, c);
        int *p = NULL;
        *p = 0;
        return 0;
}

方法一

dmesg + addr2line

ubuntu@VM-0-15-ubuntu:~$ g++ -g test.cpp
ubuntu@VM-0-15-ubuntu:~$ 
ubuntu@VM-0-15-ubuntu:~$ ./a.out
Segmentation fault (core dumped)
ubuntu@VM-0-15-ubuntu:~$ 
ubuntu@VM-0-15-ubuntu:~$ dmesg
a.out[3709]: segfault at 0 ip 080483c9 sp bff75a60 error 6 in a.out[8048000+1000]
ubuntu@VM-0-15-ubuntu:~$ addr2line -e a.out 080483c9
/home/ubuntu/test.cpp:21

方法二

strace + addr2line

strace, 用来查看系统调用

ubuntu@VM-0-15-ubuntu:~$ g++ -g test.cpp
ubuntu@VM-0-15-ubuntu:~$
ubuntu@VM-0-15-ubuntu:~$ strace -i ./a.out 
[00ff4424] execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
[0086e2fd] brk(0)                       = 0x818e000
[0086f6d3] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb771c000
[0086f5d1] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[0086f494] open("/etc/ld.so.cache", O_RDONLY) = 3
[0086f45e] fstat64(3, {st_mode=S_IFREG|0644, st_size=49072, ...}) = 0
[0086f6d3] mmap2(NULL, 49072, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7710000
[0086f4cd] close(3)                     = 0
[0086f494] open("/lib/libc.so.6", O_RDONLY) = 3
[0086f514] read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 N\211\0004\0\0\0"..., 512) = 512
[0086f45e] fstat64(3, {st_mode=S_IFREG|0755, st_size=1855584, ...}) = 0
[0086f6d3] mmap2(0x87e000, 1620360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x87e000
[0086f754] mprotect(0xa03000, 4096, PROT_NONE) = 0
[0086f6d3] mmap2(0xa04000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x185) = 0xa04000
[0086f6d3] mmap2(0xa07000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xa07000
[0086f4cd] close(3)                     = 0
[0086f6d3] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb770f000
[0085a552] set_thread_area({entry_number:-1 -> 6, base_addr:0xb770f6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
[0086f754] mprotect(0xa04000, 8192, PROT_READ) = 0
[0086f754] mprotect(0x876000, 4096, PROT_READ) = 0
[0086f711] munmap(0xb7710000, 49072)    = 0
[00ba1424] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
[00ba1424] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb771b000
[00ba1424] write(1, "1, 2, 3\n", 81, 2, 3
)     = 8
[00ba1424] write(1, "2, 1, 3\n", 82, 1, 3
)     = 8
[08048479] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
[????????] +++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
ubuntu@VM-0-15-ubuntu:~$ 
ubuntu@VM-0-15-ubuntu:~$ addr2line -e a.out 08048479
/home/ubuntu/test.cpp:21

方法三

gdb

root@DESKTOP-2SUVHU6:/mnt/e/study/gdb# ./demo 
1, 2, 3
2, 1, 3
Segmentation fault
root@DESKTOP-2SUVHU6:/mnt/e/study/gdb# gdb demo 
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 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 "x86_64-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 demo...done.
(gdb) r
Starting program: /mnt/e/study/gdb/demo 
1, 2, 3
2, 1, 3

Program received signal SIGSEGV, Segmentation fault.
0x000055555540075e in main () at coredump_test.c:17
17              *p = 0;
(gdb) quit

方法四

Linux 下生成 core dump

  1. 查看并开启 coredump 配置
// 输入目录查看状态, 0 说明是禁止生成 core 文件。
[root@ ~]# ulimit -c
0
# 1024 core 文件大小不超过 1024K
# unlimited: 字面意思,没有限制 core 文件大小。
[root@ ~]# ulimit -c unlimited
# 不是 root 用户可能会失败,如 Ubuntu 启用了 root,但不能用 sudo 去执行,而要 su root 切换过去才能成功执行
[非root用户@ ~]$ ulimit -c unlimited
bash: ulimit: core file size: 无法修改 limit 值: 不允许的操作
  1. 设置 core 文件的存储目录和命名格式

    设置 core 的存储目录和命名格式,主要是修改配置文件 /proc/sys/kernel/core_pattern:

# 1. 默认在当前程序执行目录下生成,core-程序名-程序pid-时间 [core-test-3451-1516257740]
[root@ ~]# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
# 2. 添加路径,可以把所有的 core 集中到一个文件夹里 [把所有的core文件放到 /root/core-file 目录下]
[root@ ~]# echo "/root/core-file/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
  1. 用法
    1)使用下面的示例程序,将内存释放两次
// FILE:test.c
#include<stdlib.h>

void repeatFree(char *p)
{
    if(NULL != p)
    {
        free(p);
    }
}

int main()
{
    char* pstr =(char*) malloc(10);

    repeatFree(pstr); // 第一次释放

    repeatFree(pstr); // 第二次释放

    return 0;
}

2)编译
gcc -g test.c -o test 携带调试信息

# 编译
[root@ ~]# gcc -g test.c -o test
# 运行
[root@ ~]# ./test 
*** Error in `./test': double free or corruption (top): 0x0000000001078010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f753c2e47e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f753c2ed37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f753c2f153c]
./test[0x400585]
./test[0x4005b6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f753c28d830]
./test[0x400499]
# 可以看到,当前目录下生成了一个 core 文件(如果你配置在当前目录生成 core 文件的话)
[root@ ~]# ls
core-test-19317-1516269504  test  test.c

3)gdb 调试,找出出错的位置

[root@ ~]# gdb test core-test-19317-1516269504
[New LWP 19317]
.......一些基本信息.......
Core was generated by `./test'.
Program terminated with signal SIGABRT, Aborted.
.......一些错误信息.......
(gdb) where
#0  0x00007f753c2a2428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007f753c2a402a in __GI_abort () at abort.c:89
#2  0x00007f753c2e47ea in __libc_message (do_abort=do_abort@entry=2, 
    fmt=fmt@entry=0x7f753c3fde98 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007f753c2ed37a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, 
    str=0x7f753c3fdf88 "double free or corruption (top)", action=3) at malloc.c:5006
#4  _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3867
#5  0x00007f753c2f153c in __GI___libc_free (mem=<optimized out>) at malloc.c:2968
#6  0x0000000000400585 in repeatFree (p=0x1078010 "") at test.c:8
#7  0x00000000004005b6 in main () at test.c:18
(gdb) 

在 gdb 内,输入 where 可以看出, 我们写的程序出错的两行:

#6  0x0000000000400585 in repeatFree (p=0x1078010 "") at test.c:8
#7  0x00000000004005b6 in main () at test.c:18
了解,可以为您提供一些关于Linux core dump文件分析的信息。首先,core dump文件是在程序崩溃或异常终止时生成的,它包含了程序崩溃时的内存映像和其他相关信息。分析core dump文件可以帮助我们定位程序崩溃的原因。 在Linux中,您可以使用以下工具来分析core dump文件: 1. GDB (GNU调试器): GDB是一个功能强大的调试器,可以用于分析core dump文件。您可以使用以下命令来加载core dump文件并进行分析: ``` gdb <可执行文件> <core dump文件> ``` 这将启动GDB并加载core dump文件。您可以使用GDB的各种命令来查看内存状态、寄存器值等,以帮助定位问题。 2. Crash: Crash是一个用于分析core dump文件的命令行工具,它提供了一些有用的命令和脚本来帮助您分析崩溃。您可以使用以下命令来使用crash工具: ``` crash <vmlinux> <core dump文件> ``` 其中,`vmlinux` 是内核符号文件,您可以在`/usr/lib/debug/boot`目录下找到。 3. SystemTap: SystemTap是一个功能强大的系统跟踪工具,可以用于分析各种系统问题,包括core dump文件。您可以编写SystemTap脚本来分析core dump文件中的各种信息。例如,您可以编写一个脚本来检查程序崩溃时的堆栈跟踪信息。 这些工具都有很多功能和选项,可以根据您的具体需求进行深入的分析。请注意,对于大型和复杂的core dump文件,分析可能需要一些时间和经验。 希望这些信息对您有所帮助!如果您有其他问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值