首页
社区
课程
招聘
[原创]QEMU在kvm加速下软件断点的实现分析
发表于: 2019-3-20 15:05 6599

[原创]QEMU在kvm加速下软件断点的实现分析

2019-3-20 15:05
6599

问题源于我想在KVM的加持下来加速用QEMU调试Linux的虚拟机。刚开始我还没遇到这个问题,突然有一天我需要在start_kernel()这个函数下断点。发现断不下来。但是系统启动后,对任意函数下断点又没有问题。问题就变成了在KVM的加持下对start_kernel()下断点无效。

QEMU在使用KVM方案后,kvm_set_user_memory_region()函数通过KVM API设置虚拟机的内存和主机的内存映射关系。本次调试的虚拟机内存设置为4G,cpu核数为1。


图1

如图1所示看到一段虚拟机的内存0xfffc0000是和主机内存0x7fffe4400000做的映射。0xfffc0000位置用于放置bios代码。

下面是我找到一些后面要用的虚拟机和主机映射的地址范围。


图2

图2中的其中比较有意思的是$37这组数据。上面说过虚拟机只有4G物理内存,为什么会有4G-5G这一段物理内存那?这个问题是PCI BUS总线地址原因。PCI BUS总线地址占到物理内存的3G-4G位置上,我们的那段3G-4G内存地址就映射到了4G-5G的内存地址。在Linux的dmesg中看e820的布局也能看到这个现象。e820中没有3G-4G的物理地址,代替它的是4G-5G的物理地址。


图3

图2的内存布局是为了方便我们下一步验证的工作。QEMU加载Linux内核代码在load_linux()中实现的。部分代码如下:


图4

图4中的代码告诉QEMU把一个linux的内核加载到物理内存的位置。调试的内核是Linux-4.13-2版本,物理内存位置在897行。real_addr的部分是放置Linux内核header.S(arch/x86/boot)的代码。一个压缩的内核例如bzImage由两部分组成setup和kernel.其中kernel是压缩了,setup部分用于启动和解压。图4 real_addr用于放setup实模式的代码。prot_addr用于放置setup保护模式的代码。


图5


图6

图5是代码,图6是生成后内核。header.S很多功能例如定义了setup的大小等重要信息。header.S中有很多关键的信息用于确定后面压缩的内核在那。

知道了QEMU把Linux加载到哪,下面就是QEMU什么时候加载Linux内核了。通过图2找到虚拟机0x10200物理地址在主机内存的位置,下一个watch断点我们找到如图7所示


图7


图8

图8已经看到QEMU中运行的bootloader代码把bzImage加载到指定的内存中。下面介绍一种不是完美方法来查看虚拟机中当前CPU运行的状态。首先对kvm_getput_regs()中有对虚拟机中CPU寄存器的获取


图9

图9 为下断点获取((CPUX86State *) 0x5555566756e0)它保存,


图10

此函数是在KVM中的虚拟机执行前执行。所以获取当前CPU的CPUX86State比较好。

继续回到上面看图8中此时虚拟机中断时候的寄存器和内存状态。



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 6
活跃值: (3290)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习了
2019-3-20 19:18
0
雪    币: 52
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
赞一个,有深度。
2019-6-22 22:50
0
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
你把qemu看完了吗
2019-6-30 23:40
0
游客
登录 | 注册 方可回帖
返回
//