使用kdump内核调试工具遇到的问题及解决
修改linux内核代码或者内核模块的时候,搞不好就会造成linux死机崩溃,crash死机后/var/log/kern.log里面不会有任何异常信息记录。这时候kdump就会派上用场了,网上kdump的中英文介绍资料很多,但是很多都是基于系统自带的linux进行说明的,这里记录一下在新编译的内核上使用kdump遇到的问题
1、首先使用ubuntu的config文件编译的内核可以使用kdump
2、在上面的config文件后打开内核编译的DEBUG_INFO选项,编译安装内核后,结果kdmup不起作用,crash后电脑直接卡死没反应,有下面几个现象
通过service --status-all查看,kdump服务成功启动
通过kdump-config show 查看,kdump not ready。
重新启动kdump服务。提示启动成功,但是查看/var/log/syslog,看到有提示"Could not find a free area of memory of xxxxx",kdump预留内存不足,通过/proc/iomem查看已经预留了crash memory,但是预留的crash memory与syslog中提示的内存非常接近
重新启动笔记本,在grub命令行编辑启动命令,设置crash memory为256M,之前grub配置文件中为128M,重启后,发现kdump服务ok,通过kdump-config show查看kdump 也是ready状态。
通过echo c > /proc/sysrq-trigger触发内核崩溃,看到kdump有响应,但是并不会重启笔记本,也不会记录crash信息
3、既然没有配置DEBUG_INFO时候编译的内核可以kdump,配置DEBUG_INFO后编译的内核反而不能kdump,那么在安装尝试把DEBUG信息去掉
objcopy --strip-debug ./vmlinux.o (建议先备份vmlinux.o)
make modules_installs INSTALL_MOD_STRIP=1 install
上面两条命令一个是把内核中的debug信息去掉,另外一个命令则是在安装内核模块的时候,同样把内核模块的debug info去掉,INSTALL_MOD_STRIP这个参数实际上就是从内核makefile中找到的,INSTALL_MOD_STRIP在makefile中就是控制strip-debug是否使能的。
4、经过上面把内核以及内核模块的调试信息去掉后,确认kdump可以正常使用了
root@Inspiron:/home/lybxin# crash doc/ubuntu-compile/vmlinux /var/crash/201610291718/dump.201610291718
crash 7.1.4
Copyright(C)2002-2015 RedHat,Inc.
Copyright(C)2004,2005,2006,2010 IBM Corporation
Copyright(C)1999-2006 Hewlett-PackardCo
Copyright(C)2005,2006,2011,2012 FujitsuLimited
Copyright(C)2006,2007 VA LinuxSystemsJapan K.K.
Copyright(C)2005,2011 NEC Corporation
Copyright(C)1999,2002,2007 SiliconGraphics,Inc.
Copyright(C)1999,2000,2001,2002 MissionCriticalLinux,Inc.
This program is free software, covered by the GNU GeneralPublicLicense,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter"help copying" to see the conditions.
This program has absolutely no warranty. Enter"help warranty"for details.
GNU gdb (GDB)7.6
Copyright(C)2013FreeSoftwareFoundation,Inc.
LicenseGPLv3+: 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: doc/ubuntu-compile/vmlinux
DUMPFILE:/var/crash/201610291718/dump.201610291718 [PARTIAL DUMP]
CPUS:4
DATE:SatOct2917:17:442016
UPTIME:00:03:39
LOAD AVERAGE:0.69,1.06,0.50
TASKS:582
NODENAME:Inspiron
RELEASE:4.4.13+
VERSION:#35 SMP Fri Oct 28 23:13:30 CST 2016
MACHINE: x86_64 (2526Mhz)
MEMORY:3.9 GB
PANIC:"sysrq: SysRq : Trigger a crash"
PID:2656
COMMAND:"bash"
TASK: ffff880081543e80 [THREAD_INFO: ffff880124db8000]
CPU:0
STATE: TASK_RUNNING (SYSRQ)
crash> bt
PID:2656 TASK: ffff880081543e80 CPU:0 COMMAND:"bash"
#0 [ffff880124dbbaf0] machine_kexec at ffffffff8105ae6b
#1 [ffff880124dbbb50] crash_kexec at ffffffff8110cb12
#2 [ffff880124dbbc20] oops_end at ffffffff81030c29
#3 [ffff880124dbbc48] no_context at ffffffff81069c35
#4 [ffff880124dbbca8] __bad_area_nosemaphore at ffffffff81069f00
#5 [ffff880124dbbcf0] bad_area at ffffffff8106a0d3
#6 [ffff880124dbbd18] __do_page_fault at ffffffff8106a5eb
#7 [ffff880124dbbd70] do_page_fault at ffffffff8106a6b2
#8 [ffff880124dbbd90] page_fault at ffffffff81832178
[exception RIP: sysrq_handle_crash+22]
RIP: ffffffff814f42b6 RSP: ffff880124dbbe48 RFLAGS:00010282
RAX:000000000000000f RBX:0000000000000063 RCX:0000000000000000
RDX:0000000000000000 RSI: ffff880137c0dc78 RDI:0000000000000063
RBP: ffff880124dbbe48 R8:0000000000000002 R9:00000000000003ed
R10:0000000000000001 R11:00000000000003ed R12:0000000000000004
R13:0000000000000000 R14: ffffffff81ebada0 R15:0000000000000000
ORIG_RAX: ffffffffffffffff CS:0010 SS:0018
#9 [ffff880124dbbe50] __handle_sysrq at ffffffff814f4a8a
#10 [ffff880124dbbe80] write_sysrq_trigger at ffffffff814f4f0f
#11 [ffff880124dbbe98] proc_reg_write at ffffffff81279782
#12 [ffff880124dbbeb8] __vfs_write at ffffffff8120b438
#13 [ffff880124dbbec8] vfs_write at ffffffff8120bdc9
#14 [ffff880124dbbf08] sys_write at ffffffff8120ca85
#15 [ffff880124dbbf50] entry_SYSCALL_64_fastpath at ffffffff8182fff2
RIP:00007fe506368a10 RSP:00007ffd28c06838 RFLAGS:00000246
RAX: ffffffffffffffda RBX:00000000006f4378 RCX:00007fe506368a10
RDX:0000000000000002 RSI:00000000011bc408 RDI:0000000000000001
RBP:00007ffd28c06770 R8:00007fe506637780 R9:00007fe506c6b700
R10:0000000000000001 R11:0000000000000246 R12:00007fe506c6d5d0
R13:0000000000000000 R14:00007fe506c8f168 R15:00007ffd28c06798
ORIG_RAX:0000000000000001 CS:0033 SS:002b
后记:
实际上编译debug info后遇到两个问题,第一个是预留的crash内存不足的问题,另外一个是预留足够内存后虽然kdump服务正常了,但是内核崩溃的时候仍然不能启动kdump服务
对于第一个预留内存不足的问题,后来查看kdump-tools和kexec-tools的源码,原来kdump-config show执行的时候,就是读取的/sys/kernel/kexec_crash_loaded这个文件的值,如果kexec_crash_loaded为0就表示kdump没有处于ready状态。接着查看内核源码,/sys/kernel/kexec_crash_loaded文件对应内核变量kexec_crash_image,而这个变量只会在两个系统调用中进行修改,一个是kexec_load另外一个是kexec_file_load,而我并没有修改kexec相关的代码,因此内核这块出问题的概率比较小。
通过跟踪kdump服务的启动脚本执行过程,原来启动kdump服务最终执行的命令是/bin/systemctl --no-pager start kdump-tools.service ,而systemctl则会通过/run/systemd/private这个socket与init进程通信,init最终又会执行kexec-tools中的kexec程序,在kexec执行的时候则会查找预留的carsh memory,当预留的内存不足的时候就会输出"Could not find a free area of memory of xxxxx"错误信息,当预留的内存充足的时候,则会执行kexec_load系统调用进行加载。
对于第二个,kdump服务启动后还不能正常使用kdump的问题,打开debug info和debug info对比,发现预留的crash memory位置不同,估计多半和内核的内存机制与kexec机制有关系,这块不太懂了,没有深入研究了。好在单独剥离debug info后可以正常使用kdump。
grub启动文件中crashkernel参数的解析,可以参考内核代码parse_crashkernel
命令备记:
objcopy --only-keep-debug ./vmlinux.o vmlinux.debug
objcopy --strip-debug ./vmlinux.o
INSTALL_MOD_STRIP=1
strace -f -F -ff -o kdump /bin/systemctl --no-pager start kdump-tools.service
linux/boot/vmlinuz-4.4.13 root=UUID=1ba5f5c5-70c3-4936-b757-821899fe6264 ro quiet splash crashkernel=384M-:128M $vt_handoff