qemu 抓取linux kernel vmcore

news2024/10/5 19:17:39

一、背景

在qemu调试linux kernel时 有时我们会遇到dump 情况,这时可以通过gdb 方式连接分析dump, 但实际中我们用得更多的是离线dump 分析,分析的文件通常是vmcore(linux kernel panic 生成的coredump文件)或者ramdump(类似高通平台提供的抓取手机的整个内存空间);这里我将介绍如何利用qemu 抓取vmcore, 以及后续利用crash 工具离线分析异常的方法。

二、qemu monitor建立连接

1、qemu 抓取vmcore 需要建立连接,server端连接建立

qemu-system-aarch64 \
    -monitor telnet:127.0.0.1:5554,server,nowait \
    -machine virt,virtualization=true,gic-version=3 \
    -nographic \
    -m size=2048M \
    -cpu cortex-a72 \
    -smp 2 \ 
    -kernel Image \
    -drive format=raw,file=rootfs.img \
    -append "root=/dev/vda rw "

对比前面的qemu 启动linux kernel, 这里需要增加指令:

-monitor telnet:127.0.0.1:5554,server,nowait

monitor通过telnet端口5554 建立server连接;

2、qemu monitor telnet client连接

geek@geek-virtual-machine:~/workspace/linux/qemu$ telnet 127.0.0.1 5554

qemu monitor中也有一些指令用来查看qemu运行的linux kernel 状态,这里不详细展开,有兴趣的可以自行搜索(比如热插拔增加一个device, 执行info roms查看 qemu运行的信息,抓取寄存器等)

对于抓取vmcore,我们唯一需要关心的是指令dump-guest-memory

dump-guest-memory [-p] [-d] [-z|-l|-s|-w] filename [begin length] -- dump guest memory into file 'filename'.
			-p: do paging to get guest's memory mapping.
			-d: return immediately (do not wait for completion).
			-z: dump in kdump-compressed format, with zlib compression.
			-l: dump in kdump-compressed format, with lzo compression.
			-s: dump in kdump-compressed format, with snappy compression.
			-w: dump in Windows crashdump format (can be used instead of ELF-dump converting),
			    for Windows x64 guests with vmcoreinfo driver only.
			begin: the starting physical address.
			length: the memory size, in bytes.

通常使用 dump-guest-memory filename 或 dump-guest-memory -z filename 指令会抓取qemu中linux kernel的vmcore,一个是不压缩,一个是zlib压缩格式, 后续就可以利用这个vmcore来进行kernel panic 离线分析;

三、qemu vmcore抓取

1、如何生成vmcore

先用最简单的命令行触发一个panic: echo c > /proc/sysrq-trigger

~ # echo c > /proc/sysrq-trigger 
[  142.419430] sysrq: Trigger a crash
[  142.419886] Kernel panic - not syncing: sysrq triggered crash
[  142.420293] CPU: 0 PID: 143 Comm: sh Tainted: G                 N 6.6.1-g3cba94c761ec-dirty #15
[  142.420642] Hardware name: linux,dummy-virt (DT)
[  142.420985] Call trace:
[  142.421120]  dump_backtrace+0x90/0xe8
[  142.421412]  show_stack+0x18/0x24
[  142.421673]  dump_stack_lvl+0x48/0x60
[  142.422098]  dump_stack+0x1c/0x28
[  142.422434]  panic+0x39c/0x3f0
[  142.422744]  sysrq_reset_seq_param_set+0x0/0x10c
[  142.423099]  __handle_sysrq+0x154/0x294
[  142.423427]  write_sysrq_trigger+0x80/0xcc
[  142.423731]  proc_reg_write+0x108/0x16c
[  142.423990]  vfs_write+0x158/0x45c
[  142.424218]  ksys_write+0xd0/0x180
[  142.424425]  __arm64_sys_write+0x44/0x58
[  142.424651]  invoke_syscall+0x60/0x184
[  142.424887]  el0_svc_common.constprop.0+0x78/0x13c
[  142.425132]  do_el0_svc+0x30/0x40
[  142.425351]  el0_svc+0x38/0x70
[  142.425559]  el0t_64_sync_handler+0x120/0x12c
[  142.425816]  el0t_64_sync+0x190/0x194
[  142.426441] SMP: stopping secondary CPUs
[  142.427057] Kernel Offset: disabled
[  142.427264] CPU features: 0x1,00000200,3c020000,1000421b
[  142.427700] Memory Limit: none
[  142.428385] ---[ end Kernel panic - not syncing: sysrq triggered crash ]---

然后在qemu monitor 端执行: dump-guest-memory ramdump1

或者:dump-guest-memory -z vmcore1

用 -z参数和不带参数抓取的vmcore只是一个压缩,一个不压缩,大小不同而已,对我们分析无影响

后面我们就用这个抓取到的ramdump1/vmcore1 文件进行分析,分析前我们还需要准备对应的kernel版本的vmlinux, 以及crash 工具(这个工具是redhat开发的分析kdump的免费开源工具);

2、crash工具交叉编译

1.下载crash tool
https://github.com/crash-utility/crash.git
2.编译crash, 我们分析的vmcore是arm64平台
make target=ARM64
3.根目录会生成crash工具,加到环境变量中使用即可
4. crash 还有一些externsion在目录extensions  ---本次分析vmcore暂时不涉及,可以忽略
   make extensions
   编译生成后的so,在crash中通过extend XXX.so方式加载
   a. trace.so 用来提取ramdump中的trace log, 分析一些疑难杂症是有用,
      本质就是根据trace buffer结构体提取里面的trace log
   https://github.com/fujitsu/crash-trace
   b.gcore.so 可以在kernel panic后的ramdump中提取指定进程的coredump,对应用端逻辑调用栈进行分析
   https://github.com/fujitsu/crash-gcore

crash 的指令学习可以参考下面两篇文章:

CRASH安装和调试_crash gcore-CSDN博客

四、crash加载vmcore

1、crash加载指令:

crash vmcore路径 vmlinux路径 -m vabits_actual=XX 指定虚拟地址长度(位长的设置后面会介绍)

crash  ../qemu/vmcore1 vmlinux -m vabits_actual=48

虚拟地址长度可以在.config中查看(64位平台通常的配置是48或者39):
//CONFIG_ARM64_VA_BITS_48=y CONFIG_ARM64_VA_BITS=48

2、加载遇到问题

看来这个问题已经在crash bug上有人报过了,但是问题还是没有解决(反馈者对比发现4.X 版本的内核是正常的---我自己用4.19也是正常的, 现在我用的linux6.6.1也是有问题,这个问题应该在crash arm64上存在了很久,但是没人去解决)。

[Crash-utility] [Question] crash-arm64 cannot determine VA_BITS_ACTUAL for qemu dump-guest-memory

花了些时间分析后, 发现是自动计算kimage_voffset时遇到了问题,导致后面无法进行; 由于这个在一个编译的版本上是固定值,于是我简单通过 gdb 连接,然后在内核查看变量kimage_voffset的值,最后通过crash的参数设定传入,

(gdb) p /x kimage_voffset
$3 = 0xffff80003fe00000

上面可以看到我这个版本的kimage_voffset值是0xffff80003fe00000,不清楚怎么单步调试kernel的参考我前面的文章: 无人知晓:qemu单步调试arm64 linux kernel

3、crash增加参数 kimage_voffset=XXX

重新加载vmcore, 通过gdb获取kimage_voffset的值,在crash 加载vmcore/ramdump时,arm64平台有如下几个参数可以设置:

    ARM64: //这些都是特定平台相关参数,通过 -m option=value 指定
      phys_offset=<physical-address>  //指定物理地址的起始
      kimage_voffset=<kimage_voffset-value>   //指定kimage_voofset的值
      max_physmem_bits=<value>                  
      vabits_actual=<value>     //指定虚拟地址长度,手机通常使用39位,虚拟地址空间已经到512G,足够使用,
                                //39位相对48位,正好少一级页表,性能上有提升,同时当前的虚拟地址空间足够手机使用了

   --kaslr offset //kaslr指定kaslr偏移的参数,qemu调试我们通常会关闭,否则对齐vmlinux需要花些功夫
                  //在高通平台中ocimem.bin特定offset存放,
                  //linux ramdump parse解析的结果也有这个offset
crash最终启动命令: 
crash  ../qemu/vmcore1 vmlinux -m vabits_actual=48 -m kimage_voffset=0xffff80003fe00000

如上,加载vmcore成功。

五、crash中如何调试一个vmcore

echo c > /proc/sysrq-trigger 方式触发的dump, 入口在drivers/tty/sysrq.c中

实际我们在调试中,遇到panic都需要恢复调用栈及问题发生时的寄存器来进行分析;

1、如何恢复调用栈

crash> bt
PID: 143      TASK: ffff00000bc09f00  CPU: 0    COMMAND: "sh"
bt: WARNING: cannot determine starting stack frame for task ffff00000bc09f00

执行bt为什么无法恢复调用栈?panic时sp指针等信息并没有填入导致的,正如我们在使用T32调试通常也需要也个cmm放置 x0~x29, sp/lr 等信息才能正常恢复异常现场

2、如何获取panic时的寄存器信息?

通常内核发生异常时会打印当前CPU的寄存器信息,利用这个打印信息就可以,在遇到wdt或者tz卡死类问题时,肯定是无法打印出来,这时平台通常是触发fiq到trustzone, 然后在TZ中抓取EL1 的cpu寄存信息,我们这里是因为调用的panic, 这个默认也是不打印寄存器信息的。如果是触发data abort或者instuction abort等异常还是能正常打印,如:

上面是我用4.19内核echo c 触发的,4.19的实现就是通过空指针访问制造的异常(个人觉得用空指针制造的panic更方便分析)

3、获取panic时的调用栈

执行bt时,提供了 pid和触发panic的进程name信息:

PID: 143 TASK: ffff00000bc09f00 CPU: 0 COMMAND: "sh"

crash> task -x -R thread.cpu_context 143
PID: 143 TASK: ffff00000bc09f00 CPU: 0 COMMAND: "sh"
thread.cpu_context = {
x19 = 0xffff80008475af40,
x20 = 0x0,
x21 = 0xffff00000bc09f00,
x22 = 0xffff7fffb13f4000,
x23 = 0xffff800082e0e748,
x24 = 0xffff00000bd1d500,
x25 = 0xffff800085fd7850,
x26 = 0xffff80008475b338,
x27 = 0xffff800082e0e750,
x28 = 0xffff000034202748,
fp = 0xffff800085fd7740,
sp = 0xffff800085fd7740, //利用sp恢复
pc = 0xffff8000817d4390
},
利用bt恢复时,需要lr指针,sp + 8就是lr, sp中存放的是上一级的sp;不清楚可以看后面参考的链接:https://student.cs.uwaterloo.ca/~cs452/docs/rpi4b/aapcs64.pdf

crash> bt -S 0xffff800085fd7748
PID: 143      TASK: ffff00000bc09f00  CPU: 0    COMMAND: "sh"
bt: WARNING: cannot determine starting stack frame for task ffff00000bc09f00
 #0 [ffff800085fd7750] idle_cpu at ffff80008010a9a0
 #1 [ffff800085fd7780] irq_exit_rcu at ffff8000800c4a68
 #2 [ffff800085fd7790] arm64_preempt_schedule_irq at ffff8000817d424c
 #3 [ffff800085fd77b0] el1_interrupt at ffff8000817caf10
 #4 [ffff800085fd77d0] el1h_64_irq_handler at ffff8000817cb2c0
 #5 [ffff800085fd7910] el1h_64_irq at ffff800080011ae4
 #6 [ffff800082b361e0] (null) at f420
     PC: 000000000044fd4c   LR: 00000000004b7734   SP: 0000ffffd8894070
    X29: 0000ffffd8894070  X28: 0000000000000000  X27: 0000000000000000
    X26: 0000000001e57970  X25: 0000000000000002  X24: 0000000000000020
    X23: 0000000001e5c6a0  X22: 0000000000602000  X21: 0000000000000002
    X20: 0000000001e5c6a0  X19: 0000000000000001  X18: 0000000000000000
    X17: 0000000000403140  X16: 0000000000600020  X15: 000000000360ed96
    X14: 0000000000000001  X13: 0000ffffd88941b0  X12: 00000000ffffffc8
    X11: 00000000ffffff80  X10: 0000000000000000   X9: 0000000000000020
     X8: 0000000000000040   X7: 7f7f7f7f7f7f7f7f   X6: 0000000000000063
     X5: fffffffffffffffe   X4: 0000000000000001   X3: 0000000000601ca5
     X2: 0000000000000002   X1: 0000000001e5c6a0   X0: 0000000000000001
    ORIG_X0: 0000000000000001  SYSCALLNO: 40  PSTATE: 80000000

恢复到第五级,遇到一些问题,直接查看堆栈内容,在0xffff800085fd7910处出现了栈回溯问题,这是因为中断的原因,跳过这一级继续向下就可以恢复完整异常发生的调用栈,如下标红线的就是sp回溯,sp + 8就是每一级对应的lr函数,可以通过sym XXXXX查看

从0xffff800085fd7920 开始恢复调用栈,此时就是真实触发异常的调用栈

crash> bt -S 0xffff800085fd7928
PID: 143      TASK: ffff00000bc09f00  CPU: 0    COMMAND: "sh"
bt: WARNING: cannot determine starting stack frame for task ffff00000bc09f00
 #0 [ffff800085fd7930] __delay at ffff800081789ecc
 #1 [ffff800085fd7960] __const_udelay at ffff800081789fb0
 #2 [ffff800085fd7a20] panic at ffff8000800ba5ec
 #3 [ffff800085fd7ab0] sysrq_handle_crash at ffff800080bc78c8
 #4 [ffff800085fd7ac0] __handle_sysrq at ffff800080bc8414
 #5 [ffff800085fd7b40] write_sysrq_trigger at ffff800080bc8eb8
 #6 [ffff800085fd7b70] proc_reg_write at ffff8000804b83e8
 #7 [ffff800085fd7ca0] vfs_write at ffff8000803f5b84
 #8 [ffff800085fd7d60] ksys_write at ffff8000803f6130
 #9 [ffff800085fd7da0] __arm64_sys_write at ffff8000803f6224
#10 [ffff800085fd7dd0] invoke_syscall at ffff80008002ee48
#11 [ffff800085fd7e20] el0_svc_common.constprop.0 at ffff80008002efe4
#12 [ffff800085fd7e60] do_el0_svc at ffff80008002f0d8
#13 [ffff800085fd7e80] el0_svc at ffff8000817cb060
#14 [ffff800085fd7ea0] el0t_64_sync_handler at ffff8000817cb45c
#15 [ffff800085fd7fe0] el0t_64_sync at ffff800080011d48
     PC: 000000000044fd4c   LR: 00000000004b7734   SP: 0000ffffd8894070
    X29: 0000ffffd8894070  X28: 0000000000000000  X27: 0000000000000000
    X26: 0000000001e57970  X25: 0000000000000002  X24: 0000000000000020
    X23: 0000000001e5c6a0  X22: 0000000000602000  X21: 0000000000000002
    X20: 0000000001e5c6a0  X19: 0000000000000001  X18: 0000000000000000
    X17: 0000000000403140  X16: 0000000000600020  X15: 000000000360ed96
    X14: 0000000000000001  X13: 0000ffffd88941b0  X12: 00000000ffffffc8
    X11: 00000000ffffff80  X10: 0000000000000000   X9: 0000000000000020
     X8: 0000000000000040   X7: 7f7f7f7f7f7f7f7f   X6: 0000000000000063
     X5: fffffffffffffffe   X4: 0000000000000001   X3: 0000000000601ca5
     X2: 0000000000000002   X1: 0000000001e5c6a0   X0: 0000000000000001
    ORIG_X0: 0000000000000001  SYSCALLNO: 40  PSTATE: 80000000

crash的使用技巧可以参考文末部分(写得都很详细)

六、总结

1、利用qemu monitor 提取vmcore

2、利用crash 工具加载分析vmcore

参考:

CRASH安装和调试_crash gcore-CSDN博客

crash实战:手把手教你使用crash分析内核dump-CSDN博客

https://student.cs.uwaterloo.ca/~cs452/docs/rpi4b/aapcs64.pdf

https://linux.web.cern.ch/centos7/docs/rhel/Red_Hat_Enterprise_Linux-7-Kernel_Crash_Dump_Guide-en-US.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1418620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

合并有序链表---链表OJ---归并思想

https://leetcode.cn/problems/merge-two-sorted-lists/?envTypestudy-plan-v2&envIdtop-100-liked 将两个有序的链表合并为一个新的有序链表&#xff0c;那不就是和归并排序中最后合并的思想一样吗&#xff1f;只不过那里合并的是数组&#xff0c;这里合并的是链表。 首先…

构建知识图谱:从技术到实战的完整指南

目录 一、概述二、知识图谱的基础理论定义与分类核心组成历史与发展 三、知识获取与预处理数据源选择数据清洗实体识别 四、知识表示方法知识表示模型RDFOWL属性图模型 本体构建关系提取与表示 五、知识图谱构建技术图数据库选择Neo4jArangoDB 构建流程数据预处理实体关系识别图…

C++类和对象引入以及类的介绍使用

文章目录 一、面向过程和面向对象的初步认识二、类的引入2.2 类的引入 三、类的访问限定符及封装3.3 访问限定符3.4 【面试题】C中struct和class的区别3.5 类的两种定义方式 四、封装【面试题】面向对象的三大特性 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储…

[嵌入式系统-5]:龙芯1B 开发学习套件 -2- LoongIDE 集成开发环境集成开发环境的安装步骤

目录 一、LoongIDE&#xff08;龙芯开发工具集成环境&#xff09;概述 1.1 概述 二、软件开发环境的安装过程 2.0 注意事项 2.1 步骤1&#xff1a;MingW运行环境 2.2 步骤2&#xff1a;安装LoongIDE 2.3 步骤3&#xff1a;安装MIPS工具链 2.4 配置工具链 2.5 重启电脑…

做什么副业比较靠谱,这五个正规项目,记得收藏

人这一生不易&#xff0c;每个阶段都会有压力和烦恼&#xff0c;尤其是成年人&#xff0c;上有老下有小的&#xff0c;生活的重担都在一个人身上&#xff0c;压得人喘不过气。生活的方方面面都需要钱&#xff0c;仅靠工资已经很难维持一家人的开支了。所以很多人打算利用业余时…

基于YOLOv7算法和FLIR数据集的高精度实时红外行人目标检测系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法和FLIR数据集的高精度实时红外行人目标检测系统可用于日常生活中检测与定位自行车、汽车、狗和行人目标&#xff0c;此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别&#xff0c;同时本系统还支持检测结果可视化与导出。本…

Alexa Fluo350 NHS 酯,AF350活性酯,可用于标记胺修饰的寡核苷酸

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;AF350 Succinimidyl Ester&#xff0c;AF350 NHS Ester&#xff0c;Alexa Fluo350 NHS 酯&#xff0c;AF350活性酯 一、基本信息 产品简介&#xff1a;AF 350 is a blue fluorescent dye. AF 350 dye is used for s…

NPDP证书:让你的职业生涯飞升!

&#x1f31f;没错&#xff01;NPDP证书正在成为产品经理们的“新宠”&#xff01;越来越多的同行们纷纷选择考取NPDP证书&#xff0c;为什么这么火爆&#xff1f;一起来探究下吧&#xff01; &#x1f680;NPDP认证&#xff1a;产品经理的国际通行证 &#x1f4cd;NPDP&#x…

雪深传感器的工作原理

TH-XL2雪深传感器的工作原理主要是利用超声波的发射和反射来测量雪的厚度。传感器发射超声波&#xff0c;超声波遇到雪表面后会反射回来&#xff0c;传感器再接收反射回来的超声波&#xff0c;通过计算超声波的传播时间和速度&#xff0c;就可以得出雪的厚度。 另外&#xff0c…

给信息安全专业想做网络安全方面的人一些忠告

别一直打CTF 打CTF是为了打基础&#xff0c;大概知道一些基础就出来吧&#xff0c;千万不要一直打下去出不来了。简历上实习经历&#xff0c;项目经历以及漏洞成果才能构成一个不错的背景&#xff0c;只有ctf比赛会很尴尬。要知道有些人是py打比赛&#xff0c;面试官知道情况&…

根据两个主键查询变更日志 抽屉时间线降序

时间戳例子&#xff1a; <div class"block"><el-timeline><el-timeline-item timestamp"2018/4/12" placement"top"><el-card><h4>更新 Github 模板</h4><p>王小虎 提交于 2018/4/12 20:46</p>…

SimpleDateFormat 格式化 Date 时间戳

前言 Date 是 Java 中经常用来表示时间的类型&#xff0c;但将 Date 类型的数据发送给前端时&#xff0c;通常会呈现出乱码的状态&#xff0c;用户不宜理解&#xff0c;所以要通过 SimpleDateFormat 把 Date 类型的数据格式化为用户容易理解的格式 如下是 Date 的格式&#xff…

GIS应用水平考试一级—2009 年度第二次

全国信息化工程师——GIS应用水平考试 2009 年度第二次全国统一考试一级 试卷说明: 1、本试卷共9页,6个大题,满分150 分,150 分钟完卷。 2、考试方式为闭卷考试。 3、将第一、二、三題的答案用铅笔涂写到(NCIE-GIS)答题卡上。 4、将第四、五、六题的答案填写到主观题答题卡上…

ARP 地址解析协议

目录 ARP&#xff08;Address Resolution Protocol&#xff09; 地址解析协议 ARP 的作用 ARP 高速缓存 (ARP cache) ARP 工作过程 ARP 查找 IP 地址对应的 MAC地址 ARP 高速缓存的作用 不在同一局域网的两个主机运行ARP协议 使用 ARP 的四种典型情况 为什么要使用两种…

vcomp140.dll缺失的多种处理方法,教你4种方法修复vcomp140.dll

"vcomp140.dll缺失"是一个在电脑使用过程中较为普遍遇到的错误情况&#xff0c;这个问题可能会阻止许多程序的正常启动。vcomp140.dll是一个属于 Visual C Redistributable for Visual Studio 2015 的文件&#xff0c;对于运行那些基于 Visual Studio 2015 创建的应用…

从公有云对象存储迁移到回私有化 MinIO需要了解的所有信息

我们上一篇文章《如何从 AWS S3 遣返到 MinIO》的反响非常出色 - 我们已经接到了数十个企业的电话&#xff0c;要求我们提供遣返建议。我们已将这些回复汇总到这篇新文章中&#xff0c;其中我们更深入地研究了与遣返相关的成本和节省&#xff0c;以便您更轻松地进行自己的分析。…

Tomcat多实例配置与tomcat反向代理集群

目录 Tomcat多实例配置 1.首先配置Tomcat单实例 2.tomcat多实例配置 1.1复制单实例tomcat 1.2修改端口&#xff0c;以启动多实例。多实例之间端口不能一致 1.3对比文件不同之处 3.启动tomcat 4.检查端口查看是否启动: 5.测试浏览器访问 二、tomcat反向代理集群 1、负载…

Thymeleaf基础教程

系列文章目录 文章目录 系列文章目录一、Thymeleaf 语法规则二、Thymeleaf 语法分为以下 2 类标准表达式语法th 属性2.1 基础语法2.1.1 变量表达式 ${}2.1.2 选择变量表达式 *{}2.1.3 链接表达式 {} 2.1.4 消息表达式 三、常用的 th 标签四、迭代循环 一、Thymeleaf 语法规则 …

【MySQL】MVCC多版本并发控制

目录 一、数据库的并发场景二、多版本并发控制隐藏字段undo日志模拟MVCCRead View整体流程RC&#xff08;不可重复读&#xff09;和RR&#xff08;可重复读&#xff09;的本质区别 一、数据库的并发场景 数据库并发的场景无非如下三种&#xff1a; 读-读并发&#xff1a;不存…

web前端项目-实现录音功能【附源码】

录音功能 运行效果&#xff1a;本项目可实现录音软件的录音、存储、播放等功能 HTML源码&#xff1a; &#xff08;1&#xff09;index.html&#xff1a; <!DOCTYPE html> <html><head><meta http-equiv"Content-Type" content"text/h…