本文只涉及两大棘手的工具,不涉及内核环境(kexec config、cma for crashkernel)
kexec-tools编译&安装
GitHub - horms/kexec-tools: Kexec Tools: Userspace portion of Kexec
编译
此处选择2.0.22版本,
LDFLAGS=-static ./configure ARCH=arm64 --host=aarch64-linux-gnu CC=/home/hiwa/code/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc LD=/home/hiwa/code/aarch64-linux-gnu/bin/aarch64-linux-gnu-ld STRIP=/home/hiwa/code/aarch64-linux-gnu/bin/aarch64-linux-gnu-strip --prefix=/home/hiwa/code/kexec-tools-2.0.22/output
需要指定CC LD STRIP的交叉链的位置
make & make install
检查一下
hiwa@hiwa:~/code/kexec-tools-2.0.22/output/sbin$ file kexec
kexec: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=5524eddd5547f7e3c753a763ac61d21da44d5cfd, with debug_info, not stripped
启动kexec
./mnt/kexec-tools/sbin/kexec -p /mnt/vmlinux --append="root=/dev/vda rw rootfstype=ext4 console=ttyAMA0 init=/linuxrc loglevel=8"
-p 后面跟发生崩溃后用于启动的内核,该内核会转存vmcore 在 /proc目录下
--append 后面跟系统的cmdline
可以将该指令添加在 /etc/init.d/rcS 启动文件中
kexec程序会检查 /proc/kcore,如果该文件不存在,在内核中config一下。
使用 sysrq触发一次崩溃。测试内核 5.4
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
可以看到标志性 log
Starting crashdump kernel...
默认产生的vmcore和内存一样大。瘦身办法,使用 makedumpfile
makedumpfile -c -d 31 /proc/vmcore 目标位置。makedumpfile也需交叉编译。
crash编译&安装
GitHub - crash-utility/crash: Linux kernel crash utility
编译
这里选择 7.3.0 进入crash目录
编译64位ARM的crash:make target=ARM64
无需交叉编译。编译成功后在当前目录下生成对应的crash文件。
使用
编完以后使用./crash vmlinux vmcore (在编译crash源码的机器上执行./crash)
问题1 crash: cannot determine VA_BITS_ACTUAL 该问题表示需要指定虚拟地址位宽
./crash --help
ARM64:
phys_offset=<physical-address>
kimage_voffset=<kimage_voffset-value>
max_physmem_bits=<value>
vabits_actual=<value>
./crash vmlinux vmcore -m vabits_actual=48 48为当前发生崩溃的机器的虚拟地址位宽,需按实际指定。
问题2 crash: cannot resolve "p2m_top" 没有p2m_top该变量。追了一下crash源码,发现该变量是x86的,直接注释掉。kernel.c 的 kernel_init 函数中,对下面这个if分支,用 #ifndef ARM64 包起来。
if (symbol_exists("p2m_mid_missing")) { } else if (!symbol_exists("xen_p2m_addr")) { }
重新编译,就可以使用了。
编完后给crash瘦身一下 strip -s crash ,从一百多兆瘦身到 十几兆
网传开启了内核随机地址(KASLR),使用 crash 解析 ARM64 可能需要设置kimage_voffset,经测试,不加这个参数,也可以启动crash。
编译拓展命令
在目录下执行make extensions(根据之前的target来编译),可以在extensions目录下看到
ls extensions/*.so
extensions/dminfo.so extensions/snap.so
extensions/echo.so extensions/trace.so
使用拓展命令:
crash> extend xxx.so
拓展命令trace的使用还需要trace-cmd支持,源码
进入源码直接make,在tracecmd目录下生成trace-cmd,将其放在crash的extensions目录下,和trace.so一起。
启用crash里的trace前执行 export TRACE_CMD=/xxx/trace-cmd
然后就可以使用trace了。
7.3.0版本中extension里没有trace.c了,移到了独立仓库 https://github.com/fujitsu/crash-trace
commit b440dc57c6f3370249ab417b455ab7d5faef2eb2
Author: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Mon Apr 19 09:35:47 2021 +0900
extensions: remove trace.c
The trace.c extension module moved to the separate repository [1],
remove the file from the crash repository.
[1] https://github.com/fujitsu/crash-trace
公众号:linux码头