上一篇介绍了“GDK7+NanoCode调试学习系列6–Intel System Studio(ISS)搭建环境调试GDK7”,本篇继续学习,将尝试使用NanoCode来分析Linux虚机KVM模块的相关调用。

本调试目标机Linux内核版本为5.3.0-62-generic。

准备工作:

  1. 关于kvm.ko符号和内核源码的下载,请参考以前的文章(https://blog.csdn.net/henly1217/article/details/107662054);

  2. kvm.ko处于/usr/lib/debug/lib/modules/5.3.0-62-generic/kernel/arch/x86/kvm目录,和其他drivers不太一样。

  3. 复制带符号的kvm.ko到主机,放入以前的符号目录。

  4. 使用kvm驱动模块的功能,需要安装应用层工具qemu,应用层通过/dev/kvm文件符号和驱动通信。

  5. 可参考https://help.ubuntu.com/community/KVM/Installation安装virt-manager(虚拟系统管理器),安装完之后,可以“新建虚拟机”来创建一个新的虚拟机。如下图,正在运行的一个虚拟机。可以通过下面指令查看kvm的debugfs:

sudo su - // 进入root

mount -t debugfs debugfs /opt/debugfs // mount debugfs 到/opt/debufs下

cd /opt/debugfs

ls kvm

可以看到kvm的debugfs, 其中2448-12目录正是当前运行的这个虚拟机的debugfs.

开始调试:

  1. 参考系列3中断并设置符号和内核源码路径。

  1. 已经成功加载了内核符号了,通过(.srcpath+ 内核源码路径)来设置一下源码路径,通过(x kvm!*)来加载一下kvm的符号。

  1. 环境已经准备就绪了。

  2. 我们尝试使用NanoCode提供的Views->JTAG events的VMLaunch和VMExit来设置一下,看看是否能够中断?

先设置VMLaunch,然后g起来

有点遗憾,启动VMLuanch是自动断下来了,可以获取不到执行信息,启动VMExist没有断下来

  1. 我们暂时跳过JTAG events,继续研究一下源代码。

  2. 在virt/kvm/kvm_main.c里面有kvm_vcpu_init和kvm_vcpu_uninit函数,我们先对他们下个断点。

bp kvm!kvm_vcpu_init

bp kvm!kvm_vcpu_uninit

然后重新g起来;

然后启动另一个虚拟机,果然,kvm_vcpu_init断点命中,这是虚拟机启动的初始化函数,我们稍微调试一下,

kv //看下调用堆栈

dv //查看临时变量,但是没有显示出来??

p // 先单步一次

dv //在查看临时变量,出来了,当前的vcpu=0xffff8a8f`66f50000

然后重新g起来,我们关闭刚刚启动的虚拟机,看看kvm_vcpu_uninit是否断下?没有问题,也断下了,而且参数vcpu=0xffff8a8f`66f50000。

  1. 简单分析启动和关闭之后,我们在研究一下应用层和驱动是通过哪里交互的,应用层和驱动通过/dev/kvm来交互,通过kvm_dev_ioctl来实现,如下图,然后根据ioctl来分发不同的请求,包括创建新的虚拟机kvm_dev_ioctl_create_vm,kvm_arch_dev_ioctl会根据不同的架构,调用到不同架构的实现里面去。

我们尝试对kvm_dev_ioctl下断点(bp kvm!kvm_dev_ioctl),很快命中断点,ioctl=0xae03,刚好是KVM_CHECK_EXTENSION

  1. 至此,我们简单地配合源码和调试器,分析了kvm的几个函数。

总结:

  1. 在调试器下简单分析kvm的创建,启动/关闭,和通信的加个函数

  2. 待续。。。
    ————————————————

                         版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/henly1217/article/details/108491230

作者:沈根成  创建时间:2024-03-20 14:44
最后编辑:沈根成  更新时间:2024-04-26 11:30