Linux 内核调试方法接前一篇文章:中移(苏州)软件技术有限公司面试问题与解答(8)—— coredump与vmcore(1)
本文参考以下文章:
vmcore分析和实战
内核vmcore文件分析方法
crash工具分析Kdump下vmcore文件常用命令总结(三)(实例易懂)
vmcore
特此致谢!
本文对于中移(苏州)软件技术有限公司面试问题中的“(13)实际工作中有没有使用core dump进行调试以及问题定位?core dump的具体机制是什么?”进行解答与解析。
上一回讲了coredump,本回讲一下与coredump密切相关的vmcore。
1. 什么是vmcore
vmcore是一个操作系统在内存崩溃时保存的核心转储文件。它包含了操作系统、内核和进程的状态信息,可以对故障进行分析和调试。vmcore就像一本黑匣子,为我们提供了查看故障现场的途径,让我们能够快速定位和解决问题。
Linux内核在运行过程中,总会由于硬件异常、驱动异常或者用户态程序等等原因导致coredump,从而转储vmcore文件。而coredump发生后,我们如何去分析coredump产生的原因,成为了维护内核工作的重点。
从vmcore的定义和上一回core文件的说明就能看出,vmcore文件其实就是上一回说的那个core文件(当然,具体名字可以设定)。我说面试这帮人老是一会说ccoredump、一会又说vmcore呢。
2. 开启coredump转储
现代Linux系统中,默认都开启了内核coredump转储功能。我们可以通过ulimit -c命令进行确认。如果ulimit -c显示为0,证明被关闭(限制core文件的大小为0,意为不转储),我们可以设置为unlimited。
ulimit -c unlimited
其实这一部分上一回已经详细讲解过了,在此不再赘述。
3. coredump的常用分析工具
(1)所需要的东西
首先得知道分析内核需要什么,其实我们需要以下3样东西:
1)crash工具;
2)coredump转储的文件,即vmcore文件(看到这俩的关系了吧);
3)发生崩溃的内核映像文件,即vmlinux文件(虽然boot目录下也有vmliunz-xxx文件,但是boot下的这个文件被压缩过,不包含我们调试需要的信息,所以无法用它来进行调试工作),这里包含了调试内核所需要的调试信息(和我们调试程序时添加-g参数编出来的文件相似)
(2)安装分析coredump所需的包
系统中一般不会预装crash工具和内核debug包,因此要分析内核的vmcore文件,需要先安装以下包:
- crash
通过apt下载安装crash工具。实际命令及结果如下:
$ sudo apt install crash
[sudo] password for ph:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Suggested packages:
kexec-tools makedumpfile
The following NEW packages will be installed:
crash
0 upgraded, 1 newly installed, 0 to remove and 26 not upgraded.
Need to get 4,165 kB of archives.
After this operation, 12.4 MB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/main amd64 crash amd64 8.0.0-1ubuntu1 [4,165 kB]
Fetched 4,165 kB in 0s (8,941 kB/s)
Selecting previously unselected package crash.
(Reading database ... 266385 files and directories currently installed.)
Preparing to unpack .../crash_8.0.0-1ubuntu1_amd64.deb ...
Unpacking crash (8.0.0-1ubuntu1) ...
Setting up crash (8.0.0-1ubuntu1) ...
Processing triggers for man-db (2.10.2-1) ...
- kernel-debuginfo
通过apt下载安装kernel-debuginfo。实际命令及结果如下:
ph@ph-virtual-machine:~$ sudo apt install kernel-debuginfo
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package kernel-debuginfo
出错了,为什么会报错?
因为kernel-debuginfo就是分析之前需要安装系带有debug-info的内核。kernel-debuginfo是redhat 的叫法,Ubuntu下叫作debug symbols,简称dbgsym。与kernel-debuginfo一样,Ubuntu默认安装时也不会安装dbgsym,但更坏的消息是,Ubuntu默认仓库上也没有dbgsym包。dbgsym包存在于独立的仓库上,官方仓库地址为:http://ddebs.ubuntu.com/,页面如下:
版本应该和系统运行的内核版本完全一致。
安装完成后,会在/usr/lib/debug/boot/目录下生成带有调试信息的vmlinux;也有一说在系/lib/debug/lib/modules/xxx(内核版本)/下生成带有调试信息的vmlinux文件。
注:这一步笔者没有亲自尝试。
3. crash命令的用法说明
注:以下各步骤均非笔者实际操作,只是为了了解相关知识。
(0)进入crash环境
[root@localhost /]# crash /lib/debug/lib/modules/3.10.0.el7.x86_64/vmlinux /var/crash/127.0.0.1-2022-05-06-17\:25\:34/vmcore
GNU gdb (GDB) 7.6
Copyright (C) 2013 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-unknown-linux-gnu"...
KERNEL: /boot/vmlinux
DUMPFILE: /var/crash/127.0.0.1-2022-05-06-17:25:41/vmcore [PARTIAL DUMP]
CPUS: 8
DATE: Fri May 06 17:25:34 2022
UPTIME: 00:34:45
LOAD AVERAGE: 3.37, 3.71, 3.38
TASKS: 1316
NODENAME: fe0fdb76-b761-11e9-b107-0014101e89e7
RELEASE: 3.10.0+
VERSION: #1 SMP Thu Dec 24 16:27:16 CST 2020
MACHINE: x86_64 (3408 Mhz)
MEMORY: 31.9 GB
PANIC: "SysRq : Trigger a crash"
PID: 1942
COMMAND: "bash"
TASK: ffff88068c957300 [THREAD_INFO: ffff88062b8f4000]
CPU: 2
STATE: TASK_RUNNING (SYSRQ)
针对于上边各项的说明如下:
KERNEL:指明crash时运行的kernel
DUMPFILE:转储的内存core文件名称
CPUS:机器上cpu个数
DATE:crash发生的时间.
TASKS:crash时内存中运行任务的数量
NODENAME:crash的主机名
RELEASE:and VERSION:kernel的版本号
MACHINE:机器的cpu架构
MEMORY:机器的内存大小
PANIC:系统panic类型。如:Oops、soft lockup、hard lockup、oom、hung task等
PID:触发panic的进程ID
COMMAND:触发panic的进程名称,此处为swapper
TASK:问题进程地址
CPU:crash时进程运行的当前cpu号
STATE:crash时进程的运行状态
(1)bt命令
backtrace,打印内核栈信息。
bt pid打印指定进程栈信息。
上边最重要的信息是:[exception RIP: sysrq_handle_crash+22],指出发生异常的指令信息为:
RIP: ffffffffa54627a6。
由此可知,发生crash的函数是在sysrq_handle_crash中,偏移22字节处的指令。
这里,对应x86-64汇编,应用层下来的系统调用对应的6个参数存放的寄存器依次对应:rdi、rsi、rdx、rcx、r8、r9。对于多于6个参数的,仍存储在栈上。
crash命令的更多介绍请看下回。