libcareplus应用于Qemu-6.1.0
Posted rtoax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libcareplus应用于Qemu-6.1.0相关的知识,希望对你有一定的参考价值。
1. 环境与步骤
1.1. 软件版本
- Qemu:6.1.0
- libvirt:7.0.0
- virt-manager:2.2.1
略过Qemu、libcirt、rit-manager以及虚拟机的安装,直接进行热补丁测试。
1.2. 测试步骤
- 使用virt-manager启动qemu-KVM虚拟机;
- 查看宿主机中的qemu进程,使用工具查看虚拟机Guest OS状态;
- 使用libcareplus制作补丁文件;
- 使用libcareplus生成补丁;
- 使用libcareplus加载热补丁;
- 使用libcareplus查看热补丁信息;
- 使用libcareplus删除补丁;
下面,按照上述步骤,进行分节详述。
2. 启动虚拟机
直接使用virt-manager启动或者使用virsh启动即可。
3. 查看宿主机中Guest OS进程
$ ps -ef | grep qemu-system
root 16961 1 0 Sep24 ? 00:18:59 /usr/bin/qemu-system-x86_64 -name guest=centos8, [省略参数...]
这是一个后台
运行的进程,它的父进程是1
号进程,在CentOS中为systemd
进程,它的PID为16961
。
4. 创建补丁
可以参考视频教程《QEMU 用户态热补丁》中的实例,创建patch补丁文件。
首先,进入qemu目录,创建补丁文件0004.softmmu-qdev-monitor.patch
:
--- softmmu/qdev-monitor.c 2021-09-26 08:56:52.094677975 +0800
+++ patches/softmmu-qdev-monitor.c 2021-09-30 10:36:34.564842699 +0800
@@ -777,6 +777,7 @@ static void qbus_print(Monitor *mon, Bus
void hmp_info_qtree(Monitor *mon, const QDict *qdict)
{
+ qemu_printf("### hmp_info_qtree patched.\\n");
if (sysbus_get_default())
qbus_print(mon, sysbus_get_default(), 0);
}
其中softmmu/qdev-monitor.c
是qemu-6.1.0
源码路径,patches/softmmu-qdev-monitor.c
为补丁源代码。这个补丁很简单,在函数起始处添加了一条打印,补丁文件可以使用diff -up src.c src-modify.c
指令生成。
5. 编译源码生成二进制补丁
在测试阶段,此时没有虚拟机在运行,当准备好qemu的可执行文件后,再启动虚拟机。
使用libcareplus提供的脚本,对源码进行编译:
/home/rongtao/libcareplus/src/libcare-patch-make -j 10 --clean 0004.softmmu-qdev-monitor.patch
其中:
-j 10
指定了参与编译的CPU核心数(该参数是我添加的,目前在gitee上提交了补丁,但是目前位置还没有被接受)--clean
表明此次编译是否需要删除上次编译的结果,即在编译前期是否执行make clean
;0004.softmmu-qdev-monitor.patch
为补丁的文本文件;
在编译过程中,会将gcc重定向到libcare-cc中,不过不用担心,这已经在脚本libcare-patch-make
中帮你做了。还会生成补丁对应的汇编文件,并利用此汇编文件生成ELF文件,并通过一层封装生成二进制补丁文件。
在我们的是过程中,我们将补丁重命名为mypatch1.kpatch
。
6. 启动虚拟机
使用virt-manager或者virsh启动虚拟机
# virsh list
Id Name State
-------------------------
5 centos8 running
此时,qemu进程已经正常运行:
# ps -ef | grep qemu
root 53108 1 2 11:13 ? 00:00:23 /usr/bin/qemu-system-x86_64 [...]
需要注意的是,我的测试环境只有一个虚拟机运行,如果存在多个虚拟机,同时会存在qemu进程。
7. 加载热补丁
为了验证热补丁的加载是否成功,这里先进行反汇编查看打补丁位置的汇编代码:
# gdb -q -p $(pidof qemu-system-x86_64)
Attaching to process 53108
[New LWP 53114]
[New LWP 53119]
[New LWP 53120]
[New LWP 53122]
[New LWP 53123]
[...]
因为现在gdb attach了qemu进程,所以你会从virt-manager中看到,虚拟机停止运行了:
这时候,在gdb的命令行下,反汇编我们打补丁的函数hmp_info_qtree
:
(gdb) disassemble hmp_info_qtree
Dump of assembler code for function hmp_info_qtree:
0x000055d20a164ea0 <+0>: push %rbx
0x000055d20a164ea1 <+1>: mov %rdi,%rbx
0x000055d20a164ea4 <+4>: callq 0x55d20a1aa1b0 <sysbus_get_default>
0x000055d20a164ea9 <+9>: test %rax,%rax
0x000055d20a164eac <+12>: je 0x55d20a164ec8 <hmp_info_qtree+40>
0x000055d20a164eae <+14>: callq 0x55d20a1aa1b0 <sysbus_get_default>
0x000055d20a164eb3 <+19>: mov %rbx,%rdi
0x000055d20a164eb6 <+22>: xor %edx,%edx
0x000055d20a164eb8 <+24>: pop %rbx
0x000055d20a164eb9 <+25>: mov %rax,%rsi
0x000055d20a164ebc <+28>: jmpq 0x55d20a163be0 <qbus_print>
0x000055d20a164ec1 <+33>: nopl 0x0(%rax)
0x000055d20a164ec8 <+40>: pop %rbx
0x000055d20a164ec9 <+41>: retq
End of assembler dump.
然后,我们退出gdb,这将会使qemu进程(KVM虚拟机)继续运行。
下面进行热补丁的加载:
# /home/rongtao/libcareplus/src/libcare-ctl patch -p $(pidof qemu-system-x86_64) mypatch1.kpatch
1 patch hunk(s) have been successfully applied to PID '53108'
再次进行gdb反汇编:
(gdb) disassemble hmp_info_qtree
Dump of assembler code for function hmp_info_qtree:
0x000055d20a164ea0 <+0>: jmpq 0x55d20ac475f0
0x000055d20a164ea5 <+5>: (bad)
0x000055d20a164ea6 <+6>: push %rbx
0x000055d20a164ea7 <+7>: add $0x0,%al
0x000055d20a164ea9 <+9>: test %rax,%rax
0x000055d20a164eac <+12>: je 0x55d20a164ec8 <hmp_info_qtree+40>
0x000055d20a164eae <+14>: callq 0x55d20a1aa1b0 <sysbus_get_default>
0x000055d20a164eb3 <+19>: mov %rbx,%rdi
0x000055d20a164eb6 <+22>: xor %edx,%edx
0x000055d20a164eb8 <+24>: pop %rbx
0x000055d20a164eb9 <+25>: mov %rax,%rsi
0x000055d20a164ebc <+28>: jmpq 0x55d20a163be0 <qbus_print>
0x000055d20a164ec1 <+33>: nopl 0x0(%rax)
0x000055d20a164ec8 <+40>: pop %rbx
0x000055d20a164ec9 <+41>: retq
End of assembler dump.
很显然,函数开头的汇编指令push %rbx
被替换为jmpq 0x55d20ac475f0
,热补丁成功。
8. 删除热补丁
直接执行删除的命令即可
# /home/rongtao/libcareplus/src/libcare-ctl unpatch -p $(pidof qemu-system-x86_64)
1 patch hunk(s) were successfully cancelled from PID '53108'
如果使用gdb再次进行反汇编,会发现函数起始的指令又被替换回push %rbx
指令。
以上是关于libcareplus应用于Qemu-6.1.0的主要内容,如果未能解决你的问题,请参考以下文章