美文网首页
使用crash分析linux内核崩溃转储文件vmcore

使用crash分析linux内核崩溃转储文件vmcore

作者: 大胖005 | 来源:发表于2020-04-21 20:52 被阅读0次

    我们在Kdump-内核崩溃转储服务中,介绍了kdump服务可以在系统崩溃时,生成崩溃转储文件vmcore,便于我们分析内核崩溃原因,那么,下面我们就来看下如何使用crash工具可以帮助我们分析系统崩溃原因。

    crash工具,跟gdb很类似,它可以交互的分析运行中的内核,也可以分析由kdump、netdump、diskdump、xendump产生的core dump文件。

    本文实验环境:

    [root@yglocal ~]# cat /etc/redhat-release 
    CentOS Linux release 7.6.1810 (Core) 
    [root@yglocal ~]# uname -r
    3.10.0-957.el7.x86_64
    

    一、调试环境准备

    使用crash工具分析vmcore,需要:

    • crash工具
    • 崩溃转储文件(vmcore)
    • 发生崩溃的内核映像文件(vmlinux),包含调试内核所需调试信息
    一般系统在安装后在/boot目录下,也有个内核映像文件,vmlinuxz开头的文件,但是它是压缩过后的,无法完成调试工作,如下图: vmlinuxz

    所以我们需要下载带有完整调试信息的内核映像文件(编译时带-g选项),内核调试信息包kernel-debuginfo有两个:

    • kernel-debuginfo
    • kernel-debuginfo-common

    对于centos系统,可以在http://debuginfo.centos.org/上下载到各发行版本所需的调试包。
    对于centos7.x,安装对应内核版本的内核调试包,执行如下即可:

    # wget http://debuginfo.centos.org/7/x86_64/kernel-debuginfo-common-x86_64-`uname -r`.rpm
    # wget http://debuginfo.centos.org/7/x86_64/kernel-debuginfo-`uname -r`.rpm
    

    注意:如果系统为centos6.x,则将debuginfo.centos.org/后面的7改成6即可。

    下载完后,安装内核调试包:

    rpm -ivh *.rpm
    

    安装完成后,可以在/lib/debug/lib/modules/3.10.0-957.el7.x86_64/目录下看到vmlinux内核映像文件:

    [root@yglocal ~]# ll -th /lib/debug/lib/modules/3.10.0-957.el7.x86_64/
    total 419M
    drwxr-xr-x.  2 root root  119 Mar 26 13:13 vdso
    drwxr-xr-x. 12 root root  128 Mar 26 13:13 kernel
    -rwxr-xr-x.  2 root root 419M Nov  9  2018 vmlinux
    

    再来安装crash工具,先查看下是否已安装

    [root@yglocal ~]# rpm -q crash
    crash-7.2.3-8.el7.x86_64
    

    若没有安装过,则执行以下命令安装:

    yum install crash
    

    二、使用crash分析vmcore

    分析vmcore文件,执行命令:

    crash /lib/debug/lib/modules/3.10.0-957.el7.x86_64/vmlinux /var/crash/127.0.0.1-2020-04-04-14\:10\:45/vmcore
    
    启动crash

    其中下面这些信息,就是导致系统崩溃的直接原因及进程相关信息:

     PANIC: "BUG: unable to handle kernel NULL pointer dereference at 000000000000000c"
        PID: 27005
    COMMAND: "pickup"
       TASK: ffff997b388ae180  [THREAD_INFO: ffff997b37f64000]
        CPU: 1
      STATE: TASK_RUNNING (PANIC)
    

    1、bt命令

    backtrace打印内核栈回溯信息,bt pid 打印指定进程栈信息。 bt命令

    最重要的信息:[exception RIP: my_openat+36],指出发生异常的指令信息

    RIP: ffffffffc07c5024,可以得知,发生crash的函数是my_openat中,偏移36字节处的指令。

    这里,对应x86-64汇编,应用层下来的系统调用对应的6个参数存放的寄存器依次对应:rdi、rsi、rdx、rcx、r8、r9。对于多于6个参数的,仍存储在栈上。

    2、log命令

    打印vmcore所在的系统内核日志信息。


    log命令

    可以分析出当时,内核启动的各项配置,内核最后崩溃时异常日志信息。

    3、dis命令

    dis -l (function+offset) 10 反汇编出指令所在代码开始,10行代码


    dis反汇编

    幸运的话,反汇编出来会直接对应源码,我们这里只能看出执行mov 0x70(%rdi),%r13时系统崩溃。

    4、mod命令

    mod 查看当时内核加载的所有内核模块信息


    mod命令

    重装加载进改内核模块:

    crash> mod -s my_test_lkm /mnt/hgfs/test_ko/lkm-test05/my_test_lkm.ko
         MODULE       NAME                            SIZE  OBJECT FILE
    ffffffffc07c7000  my_test_lkm                    12740  /mnt/hgfs/test_ko/lkm-test05/my_test_lkm.ko
    

    5、sym命令

    sym 转换指定符号为其虚拟地址,显示系统中符号信息

    如上面bt打印的RIP: ffffffffc07c5024,使用sym转换查看系统符号信息

    crash> sym ffffffffc07c5024
    ffffffffc07c5024 (t) my_openat+36 [my_test_lkm] /mnt/hgfs/test_ko/lkm-test05/my_lkm.c: 25
    

    这时就可以看出对应到my_test_lkm模块的源码,/mnt/hgfs/test_ko/lkm-test05/my_lkm.c文件里第25行,查看代码可以发现:


    sym命令

    原因:这种hook写法在centos8.x上的最新系统调用约定,是内核版本4.17及之后采用的调用约定。而我当前环境是centos7.6,内核版本为3.10。0,其调用约定并不是这样的,所以这样取参数是有问题的。

    6、ps命令

    ps 打印内核崩溃时,正常的进程信息


    ps查看当前进程信息

    带 > 标识代表是活跃的进程,ps pid打印某指定进程的状态信息:

    crash> ps 27005
       PID    PPID  CPU       TASK        ST  %MEM     VSZ    RSS  COMM
    > 27005   7783   1  ffff997b388ae180  RU   0.2   91732   4124  pickup
    

    7、files命令

    files pid 打印指定进程所打开的文件信息


    files命令

    8、vm命令

    vm pid 打印某指定进程当时虚拟内存基本信息


    vm命令

    9、task命令

    task 查看当前进程或指定进程task_struct和thread_info的信息


    task命令

    10、kmem命令

    kmen 查看当时系统内存使用信息

    kmem [-f|-F|-c|-C|-i|-v|-V|-n|-z|-o|-h] [-p | -m member[,member]]
    
           [[-s|-S] [slab] [-I slab[,slab]]] [-g [flags]] [[-P] address]]
    

    我们是要kmem -i查看:


    kmem -i

    11、其它命令

    可以通过help查看到如下:


    help命令

    如:可以使用rd memory读取内存内容;
    struct命令显示结构体定义及指定地址的结构体内容;
    irq查看中断信息;
    vtop查看地址页表信息等等。

    三、写在最后

    如果我们确定是某个内核模块导致的问题,可以反汇编出该模块的源代码:

    objdump -S -D my_test_lkm.ko > lkm.S
    

    然后vim查看lkm.S文件,查看对应的源码,我们上面调试的bt信息中[exception RIP: my_openat+36],也即是my_openat中偏移量为0x24的地方,如下图:

    lkm.S
    如果崩溃处对应有c代码的话,这样排查起来就简单多了。

    可以关注我的微信公众号大胖聊编程,一起交流学习。

    参考资料:
    [1]: Red_Hat_Enterprise_Linux-7-Kernel_Administration_Guide-en-US 7.5. ANALYZING A CORE DUMP

    相关文章

      网友评论

          本文标题:使用crash分析linux内核崩溃转储文件vmcore

          本文链接:https://www.haomeiwen.com/subject/pafmihtx.html