gdb调试core dump快速入门

10 篇文章 0 订阅

What is a core dump file?

在linux系统下,使用 man 5 core 命令查看 core dump file 的描述,如下:

The default action of certain signals is to cause a process to terminate and produce a core dump file, a file containing an image of the process’s memory at the time of termination. This image can be used in a debugger (e.g., gdb(1)) to inspect the state of the program at the time that it terminated. A list of the signals which cause a process to dump core can be found in signal(7).

简单点说,当一个进程非正常被终止时,操作系统会为该进程生成一个 core dump file,该文件保存了进程终止时的上下文状态,例如寄存器状态,堆栈指针等。

打开 core dump 文件的生成

linux系统默认情况下,core dump 文件的生成是关闭的,可以使用 ulimit -c 命令查看,若该值为 0,则说明默认不会生成 core dump file。可以 ulimit --help 查看详情。

ulimit --help
# ulimit --help
ulimit: ulimit [-SHabcdefiklmnpqrstuvxPT] [limit]
    Modify shell resource limits.
    
    Provides control over the resources available to the shell and processes
    it creates, on systems that allow such control.
    
    Options:
      -S        use the `soft' resource limit
      -H        use the `hard' resource limit
      -a        all current limits are reported
      -b        the socket buffer size
      -c        the maximum size of core files created
      -d        the maximum size of a process's data segment
      -e        the maximum scheduling priority (`nice')
      -f        the maximum size of files written by the shell and its children
      -i        the maximum number of pending signals
      -k        the maximum number of kqueues allocated for this process
      -l        the maximum size a process may lock into memory
      -m        the maximum resident set size
      -n        the maximum number of open file descriptors
      -p        the pipe buffer size
      -q        the maximum number of bytes in POSIX message queues
      -r        the maximum real-time scheduling priority
      -s        the maximum stack size
      -t        the maximum amount of cpu time in seconds
      -u        the maximum number of user processes
      -v        the size of virtual memory
      -x        the maximum number of file locks
      -P        the maximum number of pseudoterminals
      -R        the maximum time a real-time process can run before blocking
      -T        the maximum number of threads
    
    Not all options are available on all platforms.
    
    If LIMIT is given, it is the new value of the specified resource; the
    special LIMIT values `soft', `hard', and `unlimited' stand for the
    current soft limit, the current hard limit, and no limit, respectively.
    Otherwise, the current value of the specified resource is printed.  If
    no option is given, then -f is assumed.
    
    Values are in 1024-byte increments, except for -t, which is in seconds,
    -p, which is in increments of 512 bytes, and -u, which is an unscaled
    number of processes.
    
    Exit Status:
    Returns success unless an invalid option is supplied or an error occurs.

使用 ulimit -c unlimited 命令打开 core dump file 的生成。默认情况下,core dump file 会生成在进程的工作目录中,生成的 core dump file 文件名为 core 或 core.pid。

需要注意,ulimit -c unlimited 命令只会在当前 shell 会话中生效,通常有两种方式,一种是设置永久生效,一种是在shell脚本中设置,然后在shell脚本中执行程序。

  1. 设置永久生效

    1. vim /etc/profile,打开文件
    2. 在文件中添加 ulimit -c unlimited
    3. 使用 source /etc/profile 使修改立即生效
  2. shell 中设置

    # run.sh
    ulimit -c unlimited
    
    ./executable_program
    

    ./run.sh

若在当前目录的下没有发现生成的 core dump file,可能是 core_pattern 文件中的值被修改。例如在我的Ubuntu-22.04系统中,通过 cat /proc/sys/kernel/core_pattern 发现其内容为 |/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E,说明产生的 core 文件被写到其他目录下了。sudo sh -c ‘echo “core” > /proc/sys/kernel/core_pattern’。 通过 sudo sh -c 'echo "core_%e_%p" > /proc/sys/kernel/core_pattern' 将内容修改为 core_%e_%p,进程崩溃时,core 文件会产生到当前目录下,文件名为 core_processName_pid%e 表示进程名,%p 表示进程ID。

关于 core dump file 配置的相关信息,可以使用 man 5 core 命令进行查看。

使用 gdb 调试 core dump file 的示例

示例代码: 一个显而易见的bug,在进行字符串拷贝前,没有分配内存。

// example.cpp
#include <iostream>
#include <cstring>

void func1(char*);
void func2(char*);
void func3(char*);
void func4(char*);

void func1(char* p)
{
    func2(p);
}

void func2(char* p)
{
    func3(p);
}

void func3(char* p)
{
    func4(p);
}

void func4(char* p)
{
    char* str;
    strcpy(str, p);
    printf("%s\n", str);    
}

int main()
{
    char str[64] = "this is a string";
    func1(str);
}
  • 编译该程序,g++ example.cpp -o example

  • 运行该程序,./example,如预期一样,Segmentation fault,在工作目录下发现生成了一个 core dump file,名为 core_example_2226878

    Segmentation fault (core dumped)
    
  • 使用 gdb 命令进行调试,命令形式为 gdb [程序文件] [对应的core文件]

    GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1
    Copyright (C) 2022 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:
    <https://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 example...
    --Type <RET> for more, q to quit, c to continue without paging--
    (No debugging symbols found in example)
    [New LWP 2226878]
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    Core was generated by `./example'.
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0  __strcpy_evex () at ../sysdeps/x86_64/multiarch/strcpy-evex.S:631
    
  • 查看调用栈。在 gdb 中使用 bt 命令查看程序崩溃时的函数调用栈,由此可以很清晰的看到函数的调用关系为 main->func1->func2->func3->func4,且程序是在执行到 func4 时崩溃的,从而可以进一步的进行分析。

    (gdb) bt
    #0  __strcpy_evex () at ../sysdeps/x86_64/multiarch/strcpy-evex.S:631
    #1  0x0000562f8287f249 in func4(char*) ()
    #2  0x0000562f8287f223 in func3(char*) ()
    #3  0x0000562f8287f204 in func2(char*) ()
    #4  0x0000562f8287f1e5 in func1(char*) ()
    #5  0x0000562f8287f2cb in main ()
    (gdb) 
    

小结

希望这篇博客能够帮助你快速地了解什么是 core dump file,以及快速地进行 core dump file 的调试。本篇文章的定位是一篇快速上手的博文,最后给出一些参考学习的文章供进一步学习。

  • https://doc.embedfire.com/linux/imx6/base/zh/latest/linux_debug/backtrace.html
  • https://kernel.org/doc/man-pages/
  • https://linuxtools-rst.readthedocs.io/zh-cn/latest/advance/02_program_debug.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值