文章目录
- 57 KVM工具使用指南-制作 LibcarePlus 热补丁
- 57.1 概述
- 57.2 手动制作
- 57.3 通过脚本制作
57 KVM工具使用指南-制作 LibcarePlus 热补丁
57.1 概述
LibcarePlus 支持如下方式制作热补丁:
- 手动制作
- 通过脚本制作
手动制作热补丁的过程繁琐,对于代码量较大的工程,例如QEMU,手动制作热补丁极其困难。建议使用 LibcarePlus 自带脚本一键式地生成热补丁文件。
57.2 手动制作
本节以原文件 foo.c 和补丁文件 bar.c 为例,给出手动制作热补丁的指导。
-
准备 C 语言编写的原文件和补丁文件。例如原文件 foo.c 和补丁文件 bar.c 。
点击展开 foo.c -
编译得到原文件和补丁文件的汇编文件 foo.s 和 bar.s,参考命令如下:
# gcc -S foo.c # gcc -S bar.c # ls bar.c bar.s foo.c foo.s
-
使用 kpatch_gensrc 对比 foo.s 和 bar.s 差异,生成包含原文件的汇编内容和差异内容的 foobar.s,参考命令如下:
# sed -i 's/bar.c/foo.c/' bar.s # kpatch_gensrc --os=rhel6 -i foo.s -i bar.s -o foobar.s --force-global
由于 kpatch_gensrc 默认对同一 C 语言原文件进行对比,所以对比前需要使用 sed 命令将补丁汇编文件 bar.s 中的 bar.c 改为原文件名称 foo.c。随后调用 kpatch_gensrc,指定输入文件为 foo.s 与 bar.s,输出文件为 foobar.s。
-
编译原文件的汇编文件 foo.s 和生成的汇编文件 foobar.s,得到可执行文件 foo 和 foobar,参考命令如下:
# gcc -o foo foo.s # gcc -o foobar foobar.s -Wl,-q
链接选项 -Wl, -q 将保留foobar中的重定位节。
-
利用 kpatch_strip 去除可执行程序 foo 和 foobar 的相同内容,保留制作热补丁所需要的内容。
# kpatch_strip --strip foobar foobar.stripped # kpatch_strip --rel-fixup foo foobar.stripped # strip --strip-unneeded foobar.stripped # kpatch_strip --undo-link foo foobar.stripped
上述命令中的各参数含义为:
- –strip 用于去除 foobar 中对于补丁制作无用的 section;
- –rel-fixup 用于修复补丁内所访问的变量以及函数的地址;
- strip –strip-unneeded 用于去除对于热补丁重定位操作无用的符号信息;
- –undo-link 用于将补丁内符号的地址从绝对地址更改为相对地址。
-
制作热补丁文件。
通过以上操作,已经得到了热补丁制作所需的主要内容。接下来需要使用 kpatch_make 将原可执行文件的 Build ID 以及 kpatch_strip 的输出文件 foobar.stripped 作为参数传递给 kpatch_make,最终生成热补丁文件,参考命令如下:
# str=$(readelf -n foo | grep 'Build ID') # substr=${str##* } # kpatch_make -b $substr -i 0001 foobar.stripped -o foo.kpatch # ls bar.c bar.s foo foobar foobar.s foobar.stripped foo.c foo.kpatch foo.s
至此,就得到了patch ID为0001的热补丁文件 foo.kpatch。
57.3 通过脚本制作
本节介绍如何利用 LibcarePlus 自带的 libcare-patch-make 脚本制作热补丁文件,仍以原文件 foo.c 和补丁文件 bar.c 为例。
-
利用 diff 命令生成 foo.c 和 bar.c 的对比文件,命令如下所示:
# diff -up foo.c bar.c > foo.patch
foo.patch 文件内容如下所示:
点击展开 foo.patch -
编写编译 foo.c 的 Makefile 文件,具体如下所示:
点击展开 Makefile -
编写好 Makefile 之后,直接调用 libcare-patch-make 即可。若 libcare-patch-make 询问选择哪个文件进行打补丁操作,输入原文件名即可,具体如下所示:
# libcare-patch-make --clean -i 0001 foo.patch rm -f foo BUILDING ORIGINAL CODE /usr/local/bin/libcare-cc -o foo foo.c INSTALLING ORIGINAL OBJECTS INTO /libcareplus/test/lpmake mkdir $DESTDIR || : cp foo $DESTDIR applying foo.patch... can't find file to patch at input line 3 Perhaps you used the wrong -p or --strip option? The text leading up to this was: -------------------------- |--- foo.c 2020-12-10 09:43:04.445375845 +0800 |+++ bar.c 2020-12-10 09:48:36.778379648 +0800 -------------------------- File to patch: foo.c patching file foo.c BUILDING PATCHED CODE /usr/local/bin/libcare-cc -o foo foo.c INSTALLING PATCHED OBJECTS INTO /libcareplus/test/.lpmaketmp/patched mkdir $DESTDIR || : cp foo $DESTDIR MAKING PATCHES Fixing up relocation printf@@GLIBC_2.2.5+fffffffffffffffc Fixing up relocation print_hello+0 patch for /libcareplus/test/lpmake/foo is in /libcareplus/test/patchroot/700297b7bc56a11e1d5a6fb564c2a5bc5b282082.kpatch
执行成功之后,输出显示:热补丁文件位于当前目录的 patchroot 目录下,可执行文件则在 lpmake 目录下。脚本生成的热补丁文件默认是采用 Build ID 作为热补丁文件的文件名。
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!