Core dump进行分析进程dump

1. core dump说明

core dump是该进程实际使用的物理内存的“快照”,所以对于分析Linux 应用程序非常有帮助。我们在实际使用中也是使用core dump文件获取应用 程序崩溃时的现场信息,如程序运行时CPU寄存器值,堆栈指针,栈数据,函数 调用栈等信息。

2. core dump工作机制

首先core dump是基于Linux信号实现的,Linux中信号是一种异步事件 处理机制,每种信号都应有默认的异常处理操作,默认操作包括忽略该信号(Ignore), 暂停进程(Stop),终止进程(Terminate),终止并产生core dump(Core)等。 参考常见一些信号: Signal value Aciton comment SIGHUP 1 Term SIGINT 2 Term Interrupt from keyboard SIGQUIT 3 Core Quit from keyboard SIGSEGV 11 Core Invalid memory reference

3. core dump产生条件

1)内存访问越界(数组越界,字符串读写越界)
2)多线程程序种使用了线程不安全的函数,如不可重入函数
3)多线程读写的数据未加锁保护(临界区资源需要互斥访问)
4)非法指针
5)堆栈溢出
用户程序发生某些错误或者异常时,在Linux内核会捕获到异常,并

给用户进程发送signal异常信号,进程在返回用户空间之前处理信号, 调用Linux内核coredump,生成elf格式的core文件,保存到指定路径(没有 设置,则保存到工作目录)。 引申:coredump 内核层面

4. core dump获取

要想获取到core dump,需要使能core dump机制,linux内核层需要支持, 对于ARM平台,需要保证支持上该机制(裁剪时注意)

1) core dump开启

#ulimit -c 
#  0----关闭状态, unlimited----开启状态

使用命令“ulimit -c unlimited” 开启,core dump机制

2) core dump文件路径

命名相关规则保存在 /proc/sys/kernel/core_pattern , 默认情况下是保存在应用程序当前目录下(如果工作中切换了目录,则保存在对应工作目录)

3) core dump文件命令规范

%% 单个%字符 
    %p 所dump进程的进程ID
    %u 所dump进程的实际用户ID
    %g 所dump的进程的实际组ID
    %s 导致本次core dump的信号
    %t core dump的时间

更改coredump文件命令以及路径: echo "/data/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

5. core dump分析

可以使用file查看一个core文件。 core文件本质上是elf格式的,可以使用readelf查看。(#readelf -h core)

5.1 分析程序时崩溃点,堆栈情况

使用命令

#gdb demo core

&&&&参考程序:

void cause_crash() 
{
    char *ptr = NULL;
    *ptr = 'A';  // 尝试在空指针上进行写操作,导致段错误
}

int main(int argc, char *argv[])
{

    printf("demo for f1c200s chip!\r\n");
    cause_crash();
    printf("coredump finish!\r\n");
    return 0;
}

&&&&参考输出core分析内容:

GNU gdb (GDB) 10.2
Copyright (C) 2021 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 "--host=x86_64-pc-linux-gnu --target=arm-xiaodong-linux-uclibcgnueabi".
Type "show configuration" for configuration details.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from coredump-demo...
warning: Can't open file /root/coredump-demo during file-backed mapping note processing
warning: Can't open file /lib/libuClibc-1.0.39.so during file-backed mapping note processing
warning: Can't open file /lib/ld-uClibc-1.0.39.so during file-backed mapping note processing
warning: exec file is newer than core file.
[New LWP 155]

warning: Could not load shared library symbols for 2 libraries, e.g. /lib//libc.so.0.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Core was generated by `./coredump-demo'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000103f0 in cause_crash () at ./main.c:12
12      *ptr = 'A';  // 尝试在空指针上进行写操作,导致段错误
(gdb)

&&&&&进一步分析 从上面可以看到,是由于signal SIGSEGV,该信号产生了终止dump。

1)、通过bt -n (backtrace)命令显示函数调用栈信息,n表示追溯深度。

(gdb) bt
#0  0x000103f0 in cause_crash () at ./main.c:12
#1  0x00010424 in main (argc=1, argv=0xbe997e54) at ./main.c:19
(gdb)

2)、通过disassemble命令打印出错时的汇编代码片段,其中箭头

指向出错的指令,也就是PC寄存器指向的地址,PC寄存器存放的是下一条 执行指令,因为程序执行时,PC寄存器指向的指令是待执行指令。 CPU在执行过程中,确实是执行过这一条指令,但是CPU发现这条指令异常, 这时就是进入异常处理流程,gdb通过回溯调用堆栈就可以找到这一条指令前的 状态。

(gdb) disassemble
Dump of assembler code for function cause_crash:
   0x000103d4 <+0>: push    {r11}       ; (str r11, [sp, #-4]!)
   0x000103d8 <+4>: add r11, sp, #0
   0x000103dc <+8>: sub sp, sp, #12
   0x000103e0 <+12>:    mov r3, #0
   0x000103e4 <+16>:    str r3, [r11, #-8]
   0x000103e8 <+20>:    ldr r3, [r11, #-8]
   0x000103ec <+24>:    mov r2, #65 ; 0x41
=> 0x000103f0 <+28>:    strb    r2, [r3]
   0x000103f4 <+32>:    nop         ; (mov r0, r0)
   0x000103f8 <+36>:    add sp, r11, #0
   0x000103fc <+40>:    pop {r11}       ; (ldr r11, [sp], #4)
   0x00010400 <+44>:    bx  lr
End of assembler dump.
(gdb)

3)、其它一些命令

info 查看一些具体变量,地址信息。

6、ARM平台上分析

ARM平台上分析流程和PC上一样,如上测试用例来自arm平台上测试。 Linux内核层面,允许执行coredump 参考配置:

CONFIG_COREDUMP=y #保证内核支持core dump

参考源码:

linux-5.4.99/fs/coredump.c
void do_coredump(const kernel_siginfo_t *siginfo);

调试分析coredump时,需要生成arm版本的gdb,可以在buildroot构建时统一构建: 参考buildroot时构建:

#
# Host GDB Options
#
# BR2_PACKAGE_HOST_GDB is not set
BR2_PACKAGE_HOST_GDB=y

参考运行效果:

#arm-linux-gdb coredump-demo core
GNU gdb (GDB) 10.2
Copyright (C) 2021 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 "--host=x86_64-pc-linux-gnu --target=arm-xiaodong-linux-uclibcgnueabi".

7、使用注意事项

对于部分进程,发生dump后,会自动重启,要注意dump文件覆盖问题。