内核vmcore文件分析方法

linux内核在运行过程中,总会由于硬件异常,驱动异常或者用户态程序等等原因导致coredump,从而转储vmcore文件。而coredump发生后,我们如何去分析coredump愿原因,成为了维护内核工作的重点,那么我们怎么去分析coredump呢,接下来就让我们一起来看看。

一、开启coredump转储

现在linux系统中,默认都开启了内核coredump转储功能。我们可以通过ulimit -c命令进行确认。

如果ulimit -c显示为0,证明被关闭(限制core文件的大小为0,意为不转储),我们可以设置为

ulimit -c unlimited

二、coredump文件的常用分析工具和方法

首先,我们要知道分析内核需要什么,其实我们需要3个东西:

1)crash工具

2)coredump转储的文件,即vmcore文件

3)发生奔溃的内核映像文件(vmlinux文件,虽然boot目录下也有vmliunz-xxx文件,但是boot下的这个文件被压缩过,不包含我们调试需要的信息,所以无法用它来进行调试工作),这里包含了调试内核所需要的调试信息(和我们调试程序时添加-g参数编出来的文件相似)

1、安装分析coredump所需的包

首先,我们系统一般不会预装crash工具和内核debug包,所以我们分析内核的vmcore文件,需要安装以下包:

  • crash
  • kernel-debuginfo
  • kernel-debuginfo-common

可以联网yum源的环境,直接yum install crash kernel-debuginfo kernel-debuginfo-common即可;yum源不可用的环境,可以通过在网上找到对应的rpm包,直接使用wget下载后,rpm -ivh *rpm安装。

注意:这里的kernel-debuginfo包的版本必须与当前发生coredump的内核完全版本一致,如果不一致会因为符号不一致,导致后续crash命令无法正常解析vmcore文件。

安装完成后,在系统的/lib/debug/lib/modules/xxx(内核版本)/下有问们需要的vmlinux文件。

2、crash命令的用法说明

①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个参数的,仍存储在栈上。

②dis命令

使用bt命令我们会看到[exception RIP: sysrq_handle_crash+22]信息,那这条指令在做什么呢。就需要使用dis命令(dis -l (function+offset) 10 反汇编出指令所在代码开始,10行代码)

③sym命令

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

如上面bt打印的RIP: ffffffffc07c5024,使用sym转换查看系统符号信息
sym addr 通过虚拟地址,显示symbol和源码位置

然后我们可以对照着代码,来辅助我们进行问题分析。

④ps命令

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

⑤log命令

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

⑥p命令

p命令可以用来打印出表达式或者变量的值

⑦kmem命令

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

⑧task

task 查看当前进程或指定进程task_struct和thread_info的信息(系统进程导致的奔溃,我们往往需要查看进程的信息)

⑨其他命令

可以通过help直接查看,如下:

三、举例分析

1、场景的coredump场景

造成程序coredump的原因有很多,比较常见的有:

1)硬件异常

硬件异常其实也很常见,他可能是一个由ipmitool监控到的一个硬件异常,然后给内核发送诸如Serror的异常中断;也可能是内存ECC异常(比如不可纠正的内存异常,ECC异常发生原理可以参考内存ECC问题的分析和实践-优快云博客);亦可能是pci总线异常(硬件引脚接触不良,无法上电下电之类)7等等。

这类异常我们没法通过软件或者内核层面去解决,只能去排查硬件问题。而我们使用crash分析vmcore文件主要是为了解决软件的异常。必须如下面的5个场景场景。

2)内存访问越界

a) 由于使用错误的下标,导致数组访问越界。
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符。
c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

3)多线程程序使用了线程不安全的函数

应该使用下面这些可重入的函数,它们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n)ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c)getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c)fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c)getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3)getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n)nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3)getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c)getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c)getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

4)多线程读写的数据未加锁保护

对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成coredump

5)非法指针

a) 使用空指针
b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump。

6)堆栈溢出

不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。

2、实际coredump场景模拟和分析

1)先写一个ha-check脚本,脚本里执行以下命令模拟一个空指针导致的内核panic。

echo 1 >/proc/sys/kernel/sysrq

echo c >/proc/sys/kernel/sysrq

2)crash分析vmcore

其实crash一开始就会给我们列出coredump的原因,我们模拟的这次coredump导致内核奔溃的原因是PANIC: "BUG: unable to handle kernel NULL pointer dereference at           (null)"对应的进程是PID: 13165,进程指令名称是COMMAND: "ha-check"。

包括bt显示的调用栈也清晰的写明了奔溃的来源,如下:

从上我们还可以看出明显由一个sysrq_trigger的写入动作。(正好我们的ha-check也是执行了一个echo c >/proc/sys/kernel/sysrq模拟内核奔溃的示例)。而上面奔溃的地方是[exception RIP: sysrq_handle_crash+22]这里,对应下方代码:

我们都指导,指针初始化时赋值位为NULL时,编译虽然没问题,但是会运行错误,指针所指向地址必须为合法有效的内存地址。所以模拟的奔溃错误是”unable to handle kernel NULL pointer dereference at           (null)”。

四、参考资料

1.coredump详解_coredump文件分析_贺二公子的博客-优快云博客

2.crash分析linux内核崩溃转储文件vmcore_linux crash分析-优快云博客

### 如何分析 Linux 内核 Dump 文件 #### 工具介绍 为了分析 Linux 内核 dump 文件,通常使用的工具有 `crash` 和其他辅助工具。这些工具能够帮助开发者深入理解内核崩溃的原因以及内存状态。 - **Crash 工具** 是一种强大的交互式故障诊断程序,用于分析 Linux 内核 core dump 文件。它可以解析 vmlinux 符号表并提供丰富的命令来查看内核数据结构、调用栈和其他重要信息[^1]。 #### 使用 Crash 打开 Core Dump 文件 要使用 `crash` 分析核心转储文件,需指定两个主要参数:vmlinux 文件vmcore 文件。以下是具体方法: ```bash crash /path/to/vmlinux /path/to/vmcore ``` 其中: - `/path/to/vmlinux` 表示编译时生成的带有调试符号的内核映像文件。 - `/path/to/vmcore` 则是实际的核心转储文件路径。 此命令启动了一个交互式的 shell,在这里可以通过各种内置命令进一步探索系统状态。 #### 常见 Crash 命令及其用途 下面列举了一些常用的 crash 命令及它们的作用: - **bt (Backtrace)** 显示当前线程或所有线程的回溯信息,有助于追踪错误发生前后的函数调用链路。 - **ps (Process Status)** 展示整个系统的进程列表,类似于 top 或 ps 的功能但更详尽。 - **log (System Log Buffer Contents)** 输出 dmesg 缓冲区的内容,这对于发现最近发生的异常事件非常有用。 - **vm (Virtual Memory Information)** 提供虚拟地址空间布局详情,适合研究内存分配情况。 以上只是部分基础指令;实际上还有更多高级选项可以根据需求选用。 #### 配置环境准备 确保安装好必要的软件包之后才能顺利执行上述流程。对于基于 RPM 的发行版来说可能需要如下几个组件: - kernel-debuginfo - crash utility itself 可通过 yum/apt-get 安装相应版本的 debug info packages 来获取完整的 symbol table 支持。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随心所欲的小强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值