当前位置: 首页 > news >正文

使用crash解析vmcore(fulldump)文件,基于qemu,arm64,linux6.6

背景

       文章主要讲述了使用qemu运行linux6.6的内核,并通过telnet的方式生成vmcore(fulldump)文件以及最后使用crash工具对抓取的vmcore(fulldump)进行分析,相当于搭建一套fulldump的生成解析的环境,文章使用的所有工具以及代码均为github的开放源代码。

搭建这个环境的过程并不顺利,这篇文件也包含了自己在搭建过程中踩过的一些坑;

此文章也是为后续对块设备框架做一个整体剖析的利器;

环境搭建所需要的工具以及版本:qemu8.2,crash8.0.6,linux6.6.0,gdb10.2 

host主机:ubuntu20.04 server版本 gcc9.4 g++9.4

以下是最终界面:

一、生成抓取vmcore以及解析步骤,工具环境需求说明

备注:如果你使用4.19的版本以及5.15的内核版本,同样的方式抓取vmcore文件,使用crash是可以直接解析的不会报错,以下配置仅针对于6.0+的内核版本,亲测6.6,6.9可以用。

1,编译linux并生成zImage和vmlinux

这里要注意几个点,kernel这几个配置需要与下面一致,这几个都是需要修改的地方,

CONFIG_RANDOMIZE_BASE=n //这个必须手动设置为n,6.6内核默认设置为y
CONFIG_DEBUG_INFO_REDUCED=n //必须设置为n,高版本内核默认为y

CONFIG_ARM64_VA_BITS=39  // VA=39 PA=48 这个不设置的话会解析vmcore报错,应该是因为kimage_voffset计算的有问题
CONFIG_ARM64_PA_BITS=48  // 6.6内核默认是VA=48,6.9以上内核默认VA=52

底版本内核 CONFIG_RANDOMIZE_BASE默认是关闭的,但是6.0+的内核默认开启了,应该是考虑到内核的安全性,另外打开这个选项之后,也会使得使用gdb单步调试内核的时候设置的断点不会触发,因为函数的运行地址,与vmlinux中的地址会相差一个random offset,因此简单起见,建议关闭此选项

CONFIG_DEBUG_INFO_REDUCED=y 6.0+版本内核默认打开了这个选项,应该是考虑到内核性能,这样会导致vmlinux中缺少调试信息,crash会因为无法识别到调试信息,而加载失败,这个crash加载时会有明确的报错。

CONFIG_ARM64_VA_BITS=396.0+版本的内核默认将vabit设置为48,6.9版本内核默认设置为52,在这两种状态下,即便正确计算了vabits_actual和kimage_voffset的值,crash加载vmcore的时候也会报错,只能加载为minidump,因此需要吧VA_BIT设置为39位。

其他的配置保持默认(COREDUMP相关的配置默认都是打开的,不再赘述)编译即可;编译会生成vmlinux以及zImage文件

2,使用qemu运行linux,并触发panic

使用以下qemu命令,运行虚拟开发板:

qemu-system-aarch64 -cpu cortex-a72 \
                    -machine virt,virtualization=true,gic-version=3 \ #虚拟设备
                    -m 1024M \ #内存1G
                    -smp 2 \  #双核
                    -kernel kernel/out6/arch/arm64/boot/Image \ #linux6.6编译生成的镜像
                    -append "root=/dev/ram rdinit=/linuxrc loglevel=7 log-buf-len=1M console=ttyAMA0 nokaslr" \  # 最好带上nokaslr
                    -initrd ./rootfs.img \ 
                    -monitor telnet:127.0.0.1:5555,server,nowait \ #这个参数必须加,因为我们选择的是通过talnet的方式生成vmcore
                    -nographic

 -kernel kernel/out6/arch/arm64/boot/Image

 Image是我们编译linux6.6生成的文件,添加路径即可

-monitor telnet:127.0.0.1:5555,server,nowait

这个参数是需要带的,当使用echo c触发panic后,需要使用telnet 连接monitor获取vmcore

运行以上命令之后:

使用以下命令触发panic:

echo c >/proc/sysrq-trigger

 触发之后如下:

3,telnet 生成panic时的vmcore文件

备注:vmcore的生成方式有很多种,可以使用onitor netdump的方式,也可以通过proc/vmcore的方式生成,也可以将其写入到指定的磁盘中,这里我们选择使用monitor netdump的方式

此时使用telnet 127.0.0.1 5555连接monitor

然后运行  dump-guest-memory ./dump/vmcorev60606 生成vmcorev60606

vmcorev60606 的大小一般与板子内存大小是一致的,我们内存是1G,因此文件大小匹配

此时我们已经编译生成了vmlinux以及panic时的vmcore文件,可以使用crash进行加载了

4,使用crash工具加载vmcore文件

48位虚拟地址,和52位虚拟地址对应的kimage_voffset=0xffff80003fe00000,可以通过gdb调试获取这个值,但是即便加上这个值,加载48位编译的内核vmcore也会报IRQ的错误,而无法加载

crash_arm64 ./kernel/out6/vmlinux ./dump/vmcorev60606 -m vabits_actual=39

 直接使用上面命令加载vmcore文件即可 

大功告成。

附录1:QEMU源码编译,运行

github 或者码云直接下载

GitHub - qemu/qemu at stable-8.2

编译步骤:

cd qemu-stable-8.2
mkdir build
cd build
../configure --enable-kvm --enable-slirp --enable-debug --enable-virtfs --target-list=aarch64-softmmu,x86_64-softmmu
make -j16

编译过程中没有报什么错,如果有相关库依赖的,直接安装就行,编译完成

生成上面两个文件就是ok了,

创建一个链接文件,就可以直接使用; 

附录2:crash的源码编译

备注:这个最好有vpn,因为编译crash的时候会下载gdb的源码包,没有vpn会很慢,或者会超时失败;

github直接下载 内核源码

https://github.com/crash-utility/crash

1,下载源码,使用下面命令直接编译

tar -xf crash-8.0.6.tar.gz
cd crash-8.0.6
make target=ARM64 CFLAGS+=-fpie CXXFLAGS+=-fpie CFLAGS_FOR_TARGET+=-fpie CXXFLAGS_FOR_TARGET+=-fpie -j16

crash如果使用自带README的编译方法会在链接GDB的时候报以下错误:

/usr/bin/ld: …/sim/aarch64/libsim.a(callback.o): relocation R_X86_64_32S against symbol cb_init_syscall_map' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: …/sim/aarch64/libsim.a(sim-command.o): relocation R_X86_64_32 against .rodata.str1.1 can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: …/sim/aarch64/libsim.a(sim-core.o): relocation R_X86_64_32 against .text’ can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: …/sim/aarch64/libsim.a(sim-endian.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making PIE object; recompile with -fPIE

执行make指令后,不出意外会生成一大堆链接阶段relocation一些符号失败的问题,
这个问题还怀疑过是链接器ld的版本太低了,但是LD是系统自带的,我host是20.01不算老,所以排除了这个问题。
根据报错信息,查明这是由于这些符号库文件在编译的时候没有使用 位置无关执行代码(-fpie)的参数,导致链接重定位失败,lib文件是需要编译为位置无关代码的,因此针对以上几行的报错信息,需要在编译:
…/sim/aarch64/libsim.a(callback.o) ----------------------callback.c
…/sim/aarch64/libsim.a(sim-command.o)------------------sim-command.c
…/sim/aarch64/libsim.a(sim-core.o): ---------------------sim-core.c
…/sim/aarch64/libsim.a(sim-endian.o) ------------------------sim-endian.c


文件的时候这些文件为目标文件的时候加上-fpie参数即可,在ld的时候也加上 -fpie的参数 也就是需要在makefile里面对应CCFLAG += fpie CXXFLAG +=fpie 即可 如果部分文件是clang编译的,也需要同步添加,最后在make的时候传入这个修改参数,编译ok!!!

总结

这篇文章仅仅是相当远搭建了一个fulldump的环境,也持续耗费了几周的时间,但是相信利用full dump的环境,我们在后续针对某些问题细节的分析与理解会更深刻!!!

                                                                                                                                2025/03/20 1:18

相关文章:

  • 社区医疗管理系统基于Spring Boot SSM
  • Trae如何使用插件Mybatis Log MybatisX转换SQL语句?
  • 分裂层次聚类算法:从原理到实战的全方位解析
  • Java-模块一
  • Controller/RestController的区别
  • 支持多个和可选参数
  • 【WPF】c#读取CAD的dxf文件,并基于Canvas将读取到的数据重新描绘到界面
  • Unity URP 实现场景和UI添加后处理
  • Java 反射详细教程
  • 数据可视化(matplotlib)-------辅助图标的设置
  • 早餐 3.20
  • 笔记:代码随想录算法训练营day57:99.岛屿数量 深搜、岛屿数量 广搜、100.岛屿的最大面积
  • ssh连接解析时间过长如何解决
  • 模块、包和库
  • 【day16】搭建测试环境数据库
  • uni-app基础问题(一)
  • SysOM 可观测体系建设(一):万字长文解读低开销、高精度性能剖析工具livetrace
  • Linux线程操作(创建,终止,等待,分离)
  • 基于STM32电子钟闹钟数码管显示设计(Proteus仿真+程序+设计报告+原理图PCB+讲解视频)
  • 二分查找的应用
  • 江苏疾控:下设部门无“病毒研究所”,常荣山非本单位工作人员
  • 见微知沪|科学既要勇攀高峰,又要放低身段
  • 民间打拐志愿者上官正义遭人身安全威胁,杭州公安:已立案
  • 浙江省委金融办原副主任潘广恩被“双开”
  • 秦洪看盘|风格有所转变,热钱回流高弹性品种
  • 昔日千亿房企祥生集团约2.03亿元债权被拍卖,起拍价8000万元