From 54dc0ae9c62623d0348b7b55d79c7bebe477e487 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Mar 15 2023 23:06:21 +0000 Subject: Update to 0.9.8 and refresh clang PGO patches --- diff --git a/.gitignore b/.gitignore index 6d2c2d4..7c98a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /kpatch-dnf-v0.4.tar.gz /v0.9.7.tar.gz +/v0.9.8.tar.gz diff --git a/0100-kpatch-build-for-clang-use-.strtab-if-no-.shstrtab.patch b/0100-kpatch-build-for-clang-use-.strtab-if-no-.shstrtab.patch deleted file mode 100644 index dc9a279..0000000 --- a/0100-kpatch-build-for-clang-use-.strtab-if-no-.shstrtab.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 5f6c5965f117cb9b2b21749da49b22b23305d114 Mon Sep 17 00:00:00 2001 -From: Pete Swain -Date: Tue, 27 Sep 2022 15:56:06 -0400 -Subject: [PATCH 100/108] kpatch-build: for clang, use .strtab if no .shstrtab - -While gcc puts strings in .strtab and .shstrtab sections, -llvm toolchain just uses .strtab. - -Adapt kpatch to handle both styles. - -Signed-off-by: Pete Swain -Signed-off-by: Joe Lawrence [small changes] ---- - kpatch-build/kpatch-elf.c | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - -diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c -index 58dbe1a..c7d12ec 100644 ---- a/kpatch-build/kpatch-elf.c -+++ b/kpatch-build/kpatch-elf.c -@@ -607,7 +607,7 @@ void kpatch_create_shstrtab(struct kpatch_elf *kelf) - - shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); - if (!shstrtab) -- ERROR("find_section_by_name"); -+ return; - - /* determine size of string table */ - size = 1; /* for initial NULL terminator */ -@@ -648,7 +648,7 @@ void kpatch_create_shstrtab(struct kpatch_elf *kelf) - - void kpatch_create_strtab(struct kpatch_elf *kelf) - { -- struct section *strtab; -+ struct section *strtab, *shstrtab; - struct symbol *sym; - size_t size = 0, offset = 0, len; - char *buf; -@@ -657,6 +657,8 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) - if (!strtab) - ERROR("find_section_by_name"); - -+ shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); -+ - /* determine size of string table */ - list_for_each_entry(sym, &kelf->symbols, list) { - if (sym->type == STT_SECTION) -@@ -664,6 +666,15 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) - size += strlen(sym->name) + 1; /* include NULL terminator */ - } - -+ /* and when covering for missing .shstrtab ... */ -+ if (!shstrtab) { -+ /* factor out into common (sh)strtab feeder */ -+ struct section *sec; -+ -+ list_for_each_entry(sec, &kelf->sections, list) -+ size += strlen(sec->name) + 1; /* include NULL terminator */ -+ } -+ - /* allocate data buffer */ - buf = malloc(size); - if (!buf) -@@ -682,8 +693,20 @@ void kpatch_create_strtab(struct kpatch_elf *kelf) - offset += len; - } - -+ if (!shstrtab) { -+ struct section *sec; -+ -+ /* populate string table and link with section header */ -+ list_for_each_entry(sec, &kelf->sections, list) { -+ len = strlen(sec->name) + 1; -+ sec->sh.sh_name = (unsigned int)offset; -+ memcpy(buf + offset, sec->name, len); -+ offset += len; -+ } -+ } -+ - if (offset != size) -- ERROR("shstrtab size mismatch"); -+ ERROR("strtab size mismatch"); - - strtab->data->d_buf = buf; - strtab->data->d_size = size; -@@ -928,7 +951,9 @@ void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile, - - shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); - if (!shstrtab) -- ERROR("missing .shstrtab section"); -+ shstrtab = find_section_by_name(&kelf->sections, ".strtab"); -+ if (!shstrtab) -+ ERROR("missing .shstrtab, .strtab sections"); - - ehout.e_shstrndx = (unsigned short)shstrtab->index; - --- -2.37.3 - diff --git a/0100-support-ubsan-for-kpatch.patch b/0100-support-ubsan-for-kpatch.patch new file mode 100644 index 0000000..2a240cb --- /dev/null +++ b/0100-support-ubsan-for-kpatch.patch @@ -0,0 +1,132 @@ +From 85344cf524cccc7b8e10bf04ed38a0f586bffd10 Mon Sep 17 00:00:00 2001 +From: Sumanth Korikkar +Date: Tue, 21 Feb 2023 15:28:21 +0100 +Subject: [PATCH] support ubsan for kpatch + +ubsan generates .data..Lubsan_data* sections as follows: + +1. int main(int argc, char **argv) { + int arr[100]; + arr[101] = 1; + printf("arr[101] = %d", arr[101]); + return 0; +} + +2. 1a: 50 10 b0 ac st %r1,172(%r11) + int arr[100]; + arr[101] = 1; +1e: a7 39 00 65 lghi %r3,101 +22: c0 20 00 00 00 00 larl %r2,22 + 24: R_390_PC32DBL .data..Lubsan_data1+0x2 +28: c0 e5 00 00 00 00 brasl %r14,28 + 2a: R_390_PLT32DBL __ubsan_handle_out_of_bounds+0x2 + +3. 0000000000000000 <.data..Lubsan_data1>: +0: R_390_64 .rodata <=== source_location.location->file_name +8: 00 00 00 04 .long 0x00000004 <=== source_location.location->line +c: 00 00 00 05 .long 0x00000005 <=== source_location.location->column + +10: R_390_64 .data..Lubsan_type0 <== source_location->array_type +18: R_390_64 .data..Lubsan_type1 <=== source_location->index_type + +4. Avoid correlating the *.data.Lubsan* sections. This means + included function points to new *.data.Lubsan* sections. + +Signed-off-by: Sumanth Korikkar +--- + kpatch-build/create-diff-object.c | 13 +++++++++++++ + kpatch-build/kpatch-elf.c | 12 ++++++++++++ + kpatch-build/kpatch-elf.h | 1 + + kpatch-build/lookup.c | 3 ++- + 4 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index 707b0a9..454783a 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -1036,6 +1036,9 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig, + sec_patched->twin) + continue; + ++ if (is_ubsan_sec(sec_orig->name)) ++ continue; ++ + if (is_special_static(is_rela_section(sec_orig) ? + sec_orig->base->secsym : + sec_orig->secsym)) +@@ -1072,6 +1075,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig, + sym_orig->type != sym_patched->type || sym_patched->twin) + continue; + ++ if (is_ubsan_sec(sym_orig->name)) ++ continue; ++ + if (is_special_static(sym_orig)) + continue; + +@@ -1547,6 +1553,13 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf) + if (rela->sym->type != STT_SECTION || !rela->sym->sec) + continue; + ++ /* ++ * UBSAN data will be taken wholesale, no need to ++ * replace section symbols. ++ */ ++ if (is_ubsan_sec(rela->sym->name)) ++ continue; ++ + /* + * These sections don't have symbols associated with + * them: +diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c +index c7d12ec..405e0d3 100644 +--- a/kpatch-build/kpatch-elf.c ++++ b/kpatch-build/kpatch-elf.c +@@ -587,6 +587,18 @@ bool is_local_sym(struct symbol *sym) + return sym->bind == STB_LOCAL; + } + ++bool is_ubsan_sec(const char *name) { ++ if (!strncmp(name, ".data.rel.local..Lubsan_data", 28) || ++ !strncmp(name, ".data..Lubsan_type", 18) || ++ !strncmp(name, ".Lubsan_data", 12) || ++ !strncmp(name, ".data..Lubsan_data", 18) || ++ !strncmp(name, ".rela.data..Lubsan_data", 23) || ++ !strncmp(name, ".rela.data.rel.local..Lubsan_data", 33)) ++ return true; ++ else ++ return false; ++} ++ + void print_strtab(char *buf, size_t size) + { + size_t i; +diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h +index cd2900c..187b1d1 100644 +--- a/kpatch-build/kpatch-elf.h ++++ b/kpatch-build/kpatch-elf.h +@@ -170,6 +170,7 @@ bool is_null_sym(struct symbol *sym); + bool is_file_sym(struct symbol *sym); + bool is_local_func_sym(struct symbol *sym); + bool is_local_sym(struct symbol *sym); ++bool is_ubsan_sec(const char *name); + + void print_strtab(char *buf, size_t size); + void kpatch_create_shstrtab(struct kpatch_elf *kelf); +diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c +index f2596b1..2ccc181 100644 +--- a/kpatch-build/lookup.c ++++ b/kpatch-build/lookup.c +@@ -84,7 +84,8 @@ static bool maybe_discarded_sym(const char *name) + !strncmp(name, "__func_stack_frame_non_standard_", 32) || + strstr(name, "__addressable_") || + strstr(name, "__UNIQUE_ID_") || +- !strncmp(name, ".L.str", 6)) ++ !strncmp(name, ".L.str", 6) || ++ is_ubsan_sec(name)) + return true; + + return false; +-- +2.37.3 + diff --git a/0101-create-diff-object-handle-__initcall_stub-with-CONFI.patch b/0101-create-diff-object-handle-__initcall_stub-with-CONFI.patch new file mode 100644 index 0000000..a90e6ed --- /dev/null +++ b/0101-create-diff-object-handle-__initcall_stub-with-CONFI.patch @@ -0,0 +1,66 @@ +From 3672db9de548ed4ed5e87089a1263f6b5ddc4a11 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Mon, 13 Feb 2023 15:14:32 -0800 +Subject: [PATCH 101/107] create-diff-object: handle __initcall_stub with + CONFIG_LTO_CLANG + +The kernel use a special __initcall_stub() with CONFIG_LTO_CLANG to avoid +name collisions. Handle it in kpatch_mangled_strcmp() by ignoring all +digits for symbols start with __initstub__kmod_syscall__. + +Signed-off-by: Song Liu +--- + kpatch-build/create-diff-object.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index 2d7b072..fec57b8 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -430,6 +430,23 @@ static int __kpatch_unique_id_strcmp(char *s1, char *s2) + return 1; + } + ++static int __kpatch_skip_digits_strcmp(char *s1, char *s2) ++{ ++ while (*s1 == *s2) { ++ if (!*s1) ++ return 0; ++ s1++; ++ s2++; ++ ++ while (isdigit(*s1)) ++ s1++; ++ while (isdigit(*s2)) ++ s2++; ++ } ++ ++ return 1; ++} ++ + /* + * This is like strcmp, but for gcc-mangled symbols. It skips the comparison + * of any substring which consists of '.' followed by any number of digits. +@@ -446,6 +463,19 @@ static int kpatch_mangled_strcmp(char *s1, char *s2) + if (!strncmp(s1, "__UNIQUE_ID_", 12)) + return __kpatch_unique_id_strcmp(s1, s2); + ++ /* ++ * Hack for __initcall_stub() with CONFIG_LTO_CLANG. ++ * The following should match: ++ * ++ * __initstub__kmod_syscall__728_5326_bpf_syscall_sysctl_init7 ++ * __initstub__kmod_syscall__728_5324_bpf_syscall_sysctl_init7 ++ * ++ * Please refer to __initcall_stub() in include/linux/init.h for ++ * more details. ++ */ ++ if (!strncmp(s1, "__initstub__kmod_syscall__", 26)) ++ return __kpatch_skip_digits_strcmp(s1, s2); ++ + while (*s1 == *s2) { + if (!*s1) + return 0; +-- +2.37.3 + diff --git a/0101-create-diff-object-ignore-clang-s-.llvm_addrsig-sect.patch b/0101-create-diff-object-ignore-clang-s-.llvm_addrsig-sect.patch deleted file mode 100644 index 02a0ea9..0000000 --- a/0101-create-diff-object-ignore-clang-s-.llvm_addrsig-sect.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 37040572440efb95db9a3193d3b51d7597e1badd Mon Sep 17 00:00:00 2001 -From: Pete Swain -Date: Tue, 27 Sep 2022 15:56:06 -0400 -Subject: [PATCH 101/108] create-diff-object: ignore clang's .llvm_addrsig - sections - -Signed-off-by: Pete Swain -Signed-off-by: Joe Lawrence [subject line] ---- - kpatch-build/create-diff-object.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c -index 918d21c..fa7e07f 100644 ---- a/kpatch-build/create-diff-object.c -+++ b/kpatch-build/create-diff-object.c -@@ -2717,7 +2717,8 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) - /* Ignore any discarded sections */ - list_for_each_entry(sec, &kelf->sections, list) { - if (!strncmp(sec->name, ".discard", 8) || -- !strncmp(sec->name, ".rela.discard", 13)) -+ !strncmp(sec->name, ".rela.discard", 13) || -+ !strncmp(sec->name, ".llvm_addrsig", 13)) - sec->ignore = 1; - } - --- -2.37.3 - diff --git a/0102-create-diff-object-ignore-.llvm.-sections.patch b/0102-create-diff-object-ignore-.llvm.-sections.patch deleted file mode 100644 index 5deef12..0000000 --- a/0102-create-diff-object-ignore-.llvm.-sections.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 85781b7ea79fb4122efbb51f0bf573ed5fab03e1 Mon Sep 17 00:00:00 2001 -From: Pete Swain -Date: Tue, 27 Sep 2022 15:56:06 -0400 -Subject: [PATCH 102/108] create-diff-object: ignore .llvm.* sections - -Clang FDO adds a new, ignorable ELF section, .llvm.call-graph-profile - -Generalize to ignore all .llvm.* - -Signed-off-by: Pete Swain -Signed-off-by: Joe Lawrence [subject line] ---- - kpatch-build/create-diff-object.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c -index fa7e07f..cdcc13b 100644 ---- a/kpatch-build/create-diff-object.c -+++ b/kpatch-build/create-diff-object.c -@@ -2718,7 +2718,8 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) - list_for_each_entry(sec, &kelf->sections, list) { - if (!strncmp(sec->name, ".discard", 8) || - !strncmp(sec->name, ".rela.discard", 13) || -- !strncmp(sec->name, ".llvm_addrsig", 13)) -+ !strncmp(sec->name, ".llvm_addrsig", 13) || -+ !strncmp(sec->name, ".llvm.", 6)) - sec->ignore = 1; - } - --- -2.37.3 - diff --git a/0102-kpatch-build-support-CONFIG_LTO_CLANG_THIN.patch b/0102-kpatch-build-support-CONFIG_LTO_CLANG_THIN.patch new file mode 100644 index 0000000..9107b49 --- /dev/null +++ b/0102-kpatch-build-support-CONFIG_LTO_CLANG_THIN.patch @@ -0,0 +1,187 @@ +From 3db1cfb91b9b2b7cf6c5564995c446567baa371a Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Fri, 3 Feb 2023 10:28:16 -0800 +Subject: [PATCH 102/107] kpatch-build: support CONFIG_LTO_CLANG_THIN + +Support CONFIG_LTO_CLANG_THIN with ld.lld --lto-obj-path option. + +With CONFIG_LTO_CLANG_THIN, .o files are LLVM IR binary, so CDO doesn't +work on .o file. To solve this issue, we CDO the thinlto files generated +by the --lto-obj-path option. Clang LTO generates the thinlto files +after cross file inline, so they are good candidates for CDO. See [1] for +more discussions about this. + +To achieve this, we need: + + 1. kpatch-build to update kernel Makefile(s) so it generates thinlto + files; + 2. kpatch-build and kpatch-cc to save the thinlto file properly; + 3. kpatch-build to feed these thinlto files to CDO; + 4. The user need to supply vmlinux.o, from which we generate the symtab + file. We need this because GLOBAL symbols may be marked as LOCAL in + LTO vmlinux; + +[1] https://github.com/dynup/kpatch/issues/1320 + +Signed-off-by: Song Liu +--- + kpatch-build/kpatch-build | 59 +++++++++++++++++++++++++++++++++------ + kpatch-build/kpatch-cc | 18 ++++++++++++ + 2 files changed, 68 insertions(+), 9 deletions(-) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index 45e8b14..f712578 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -173,11 +173,11 @@ cleanup() { + # restore original vmlinux if it was overwritten by sourcedir build + [[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$KERNEL_SRCDIR/" + +- # restore original link-vmlinux.sh if we updated it for the build ++ # restore any files that were modified for the build + [[ -e "$TEMPDIR/link-vmlinux.sh" ]] && mv -f "$TEMPDIR/link-vmlinux.sh" "$KERNEL_SRCDIR/scripts" +- +- # restore original Makefile.modfinal if we updated it for the build + [[ -e "$TEMPDIR/Makefile.modfinal" ]] && mv -f "$TEMPDIR/Makefile.modfinal" "$KERNEL_SRCDIR/scripts" ++ [[ -e "$TEMPDIR/Makefile.build" ]] && mv -f "$TEMPDIR/Makefile.build" "$KERNEL_SRCDIR/scripts" ++ [[ -e "$TEMPDIR/Makefile" ]] && mv -f "$TEMPDIR/Makefile" "$KERNEL_SRCDIR" + + [[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR" + rm -rf "$RPMTOPDIR" +@@ -1054,6 +1054,23 @@ if [[ -n "$CONFIG_DEBUG_INFO_BTF" ]]; then + fi + fi + ++if [[ -n "$CONFIG_LTO_CLANG" ]]; then ++ [[ -n "$CONFIG_LTO_CLANG_THIN" ]] || die "Non-thin LTO is not supported. Please enable CONFIG_LTO_CLANG_THIN" ++ ++ # This is a heuristic: use -x to check vmlinux vs. vmlinux.o ++ [[ -x "$VMLINUX" ]] && die "For kernel with CONFIG_LTO_CLANG, please supply vmlinux.o instead of vmlinux via -v|--vmlinux option." ++ ++ # update Makefile so that ld.lld generate vmlinux.o.thinlto.o* files for vmlinux.o ++ cp -f "$KERNEL_SRCDIR/Makefile" "$TEMPDIR/Makefile" || die ++ sed -i "s/--thinlto-cache-dir=\$(extmod_prefix).thinlto-cache/--lto-obj-path=vmlinux.o.thinlto.o/g" "$KERNEL_SRCDIR"/Makefile ++ ++ # update scripts/Makefile.build so that ld.lld generate XX.o.thinlto.o* files for modules ++ cp -f "$KERNEL_SRCDIR/scripts/Makefile.build" "$TEMPDIR/Makefile.build" || die ++ sed -i "s/\$(ld_flags)/\$(ld_flags) --lto-obj-path=\$@.thinlto.o/g" "$KERNEL_SRCDIR"/scripts/Makefile.build ++ ++ export KPATCH_CC_LTO=1 ++fi ++ + if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then + echo "WARNING: Clang support is experimental" + fi +@@ -1174,9 +1191,14 @@ if [[ -n "$CONFIG_MODVERSIONS" ]]; then + trace_on + fi + ++if [[ -n "$CONFIG_LTO_CLANG" ]]; then ++ DIFF_OBJS="$TEMPDIR/thinlto_objs" ++else ++ DIFF_OBJS="$TEMPDIR/changed_objs" ++fi + # Read as words, no quotes. + # shellcheck disable=SC2013 +-for i in $(cat "$TEMPDIR/changed_objs") ++for i in $(cat "$DIFF_OBJS") + do + mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die + cp -f "$BUILDDIR/$i" "$TEMPDIR/patched/$i" || die +@@ -1205,7 +1227,8 @@ if [[ -z "$MODNAME" ]] ; then + + MODNAME="$(module_name_string "$MODNAME")" + fi +-FILES="$(cat "$TEMPDIR/changed_objs")" ++FILES="$(cat "$DIFF_OBJS")" ++ + cd "$TEMPDIR" || die + mkdir output + declare -a objnames +@@ -1229,7 +1252,11 @@ for i in $FILES; do + + mkdir -p "output/$(dirname "$i")" + cd "$BUILDDIR" || die +- find_kobj "$i" ++ if [[ -n "$CONFIG_LTO_CLANG" ]] ; then ++ KOBJFILE=${i/.o.thinlto.o*/} ++ else ++ find_kobj "$i" ++ fi + cd "$TEMPDIR" || die + if [[ -e "orig/$i" ]]; then + if [[ -n $OOT_MODULE ]]; then +@@ -1246,16 +1273,30 @@ for i in $FILES; do + else + KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}") + KOBJFILE_NAME="${KOBJFILE_NAME//-/_}" +- KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE" ++ if [[ -n "$CONFIG_LTO_CLANG" ]] ; then ++ KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE.ko" ++ else ++ KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE" ++ fi + SYMTAB="${KOBJFILE_PATH}.symtab" + SYMVERS_FILE="$BUILDDIR/Module.symvers" + fi + +- "$READELF" -s --wide "$KOBJFILE_PATH" > "$SYMTAB" ++ # With CONFIG_LTO_CLANG, multiple .thinlto files share a ++ # symtab file. Only generate the symtab file once. ++ [[ -e "$SYMTAB" ]] || "$READELF" --symbols --wide "$KOBJFILE_PATH" > "$SYMTAB" + if [[ "$ARCH" = "ppc64le" ]]; then + sed -ri 's/\s+\[: 8\]//' "$SYMTAB" + fi + ++ if [[ -n "$CONFIG_LTO_CLANG" ]] ; then ++ # skip .thinlto file that didn't change at all ++ diff "orig/$i" "patched/$i" 2> /dev/null && continue ++ # skip .thinlto file without any functions ++ num_func=$("$READELF" --symbols "orig/$i" | grep -c FUNC) ++ [[ $num_func -eq 0 ]] && continue ++ fi ++ + # create-diff-object orig.o patched.o parent-name parent-symtab + # Module.symvers patch-mod-name output.o + "$TOOLSDIR"/create-diff-object $CDO_FLAGS "orig/$i" "patched/$i" "$KOBJFILE_NAME" \ +@@ -1308,7 +1349,7 @@ fi + cd "$TEMPDIR/output" || die + # $KPATCH_LDFLAGS and result of find used as list, no quotes. + # shellcheck disable=SC2086,SC2046 +-"$LD" -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die ++"$LD" -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o*") 2>&1 | logger || die + + if [[ "$USE_KLP" -eq 1 ]]; then + cp -f "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die +diff --git a/kpatch-build/kpatch-cc b/kpatch-build/kpatch-cc +index 2a3d264..7e9e1be 100755 +--- a/kpatch-build/kpatch-cc ++++ b/kpatch-build/kpatch-cc +@@ -79,6 +79,24 @@ elif [[ "$TOOLCHAINCMD" =~ ^(.*-)?ld || "$TOOLCHAINCMD" =~ ^(.*-)?ld.lld ]] ; th + args+=(--warn-unresolved-symbols) + break + ;; ++ */.tmp_*.o) ++ # .tmp_*.o is used for single file modules. ++ # See "cmd_ld_single_m" in scripts/Makefile.build. ++ if [[ $KPATCH_CC_LTO -eq 1 ]] ; then ++ mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")" ++ cp "${obj/.tmp_/}".thinlto.o* "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")" ++ echo "${obj/.tmp_/}".thinlto.o* >> "$KPATCH_GCC_TEMPDIR/thinlto_objs" ++ fi ++ break ++ ;; ++ *.o) ++ if [[ $KPATCH_CC_LTO -eq 1 ]] ; then ++ mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")" ++ cp "$obj".thinlto* "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")" ++ echo "$obj".thinlto.o* >> "$KPATCH_GCC_TEMPDIR/thinlto_objs" ++ fi ++ break ++ ;; + *) + break + ;; +-- +2.37.3 + diff --git a/0103-create-diff-object-compare-section-name-with-kpatch_.patch b/0103-create-diff-object-compare-section-name-with-kpatch_.patch new file mode 100644 index 0000000..eee4a01 --- /dev/null +++ b/0103-create-diff-object-compare-section-name-with-kpatch_.patch @@ -0,0 +1,52 @@ +From 47d1b39ba7686e2368c1ad24af274dfd9f54ecf9 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Wed, 13 Oct 2021 00:10:20 -0700 +Subject: [PATCH 103/107] create-diff-object: compare section name with + kpatch_section_function_name + +Profile-Guided Optimization (PGO) uses profiling data to help the compiler +to evaluate the properties of a function, and thus adds different prefixes +to the section/function. For example, with -ffunction-sections, the +compiler will prefix some sectiones with .text.unlikely. However, if a +function changes from the version in the profiling data, the compiler may +ignore the profiling data. This often happens to the patched function +when kpatch-build builds the patch. As a result, the original function +and the patch function may have different prefix, i.e., one of them has +.text, the other has .text.unlikely. + +To correlate these functions properly, use kpatch_section_function_name() +in kpatch_correlate_sections() to find matching sections. + +Signed-off-by: Song Liu +--- + kpatch-build/create-diff-object.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index fec57b8..e88cb3b 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -1053,6 +1053,8 @@ static void kpatch_correlate_section(struct section *sec_orig, + kpatch_correlate_symbol(sec_orig->sym, sec_patched->sym); + } + ++static char *kpatch_section_function_name(struct section *sec); ++ + static void kpatch_correlate_sections(struct list_head *seclist_orig, + struct list_head *seclist_patched) + { +@@ -1062,8 +1064,9 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig, + if (sec_orig->twin) + continue; + list_for_each_entry(sec_patched, seclist_patched, list) { +- if (kpatch_mangled_strcmp(sec_orig->name, sec_patched->name) || +- sec_patched->twin) ++ if (sec_patched->twin || ++ kpatch_mangled_strcmp(kpatch_section_function_name(sec_orig), ++ kpatch_section_function_name(sec_patched))) + continue; + + if (is_ubsan_sec(sec_orig->name)) +-- +2.37.3 + diff --git a/0103-gcc-plugin-update-headers-for-gcc-12.patch b/0103-gcc-plugin-update-headers-for-gcc-12.patch deleted file mode 100644 index ac3745c..0000000 --- a/0103-gcc-plugin-update-headers-for-gcc-12.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 13182e50b027c70bd63f53ca43598557d6b41e2e Mon Sep 17 00:00:00 2001 -From: Joe Lawrence -Date: Tue, 27 Sep 2022 16:41:48 -0400 -Subject: [PATCH 103/108] gcc-plugin: update headers for gcc-12 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix build error seen on gcc (GCC) 12.1.1 20220507 (Red Hat 12.1.1-1): - - g++ -MMD -MP -I../kmod/patch -Iinsn -Wall -Wsign-compare -Wno-sign-conversion -g -Werror -shared -I/usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include -Igcc-plugins -fPIC -fno-rtti -O2 -Wall gcc-plugins/ppc64le-plugin.c -o gcc-plugins/ppc64le-plugin.so - In file included from /usr/include/features.h:490, - from /usr/include/bits/libc-header-start.h:33, - from /usr/include/stdio.h:27, - from /usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include/system.h:46, - from /usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include/gcc-plugin.h:28, - from gcc-plugins/gcc-common.h:6, - from gcc-plugins/ppc64le-plugin.c:1: - /usr/include/bits/error-ldbl.h:23:1: error: type of ‘error’ is unknown - 23 | __LDBL_REDIR_DECL (error) - | ^~~~~~~~~~~~~~~~~ - /usr/include/bits/error-ldbl.h:23:1: error: ‘int error’ redeclared as different kind of entity - 23 | __LDBL_REDIR_DECL (error) - | ^~~~~~~~~~~~~~~~~ - In file included from gcc-plugins/ppc64le-plugin.c:2: - /usr/include/error.h:31:13: note: previous declaration ‘void error(int, int, const char*, ...)’ - 31 | extern void error (int __status, int __errnum, const char *__format, ...) - | ^~~~~ - make[1]: *** [Makefile:39: gcc-plugins/ppc64le-plugin.so] Error 1 - -Signed-off-by: Joe Lawrence ---- - kpatch-build/gcc-plugins/ppc64le-plugin.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kpatch-build/gcc-plugins/ppc64le-plugin.c b/kpatch-build/gcc-plugins/ppc64le-plugin.c -index e3ec20f..ba4a01e 100644 ---- a/kpatch-build/gcc-plugins/ppc64le-plugin.c -+++ b/kpatch-build/gcc-plugins/ppc64le-plugin.c -@@ -1,5 +1,5 @@ --#include "gcc-common.h" - #include -+#include "gcc-common.h" - - #define PLUGIN_NAME "ppc64le-plugin" - --- -2.37.3 - diff --git a/0104-kpatch-build-add-support-for-clang-pgo.patch b/0104-kpatch-build-add-support-for-clang-pgo.patch new file mode 100644 index 0000000..416b464 --- /dev/null +++ b/0104-kpatch-build-add-support-for-clang-pgo.patch @@ -0,0 +1,73 @@ +From 19c4942a1415d0f99c910949ba55c95ddcc5a976 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Wed, 13 Oct 2021 01:03:55 -0700 +Subject: [PATCH 104/107] kpatch-build: add support for clang pgo + +For clang with Profile-Guided Optimization (PGO), profile data is needed +to compile the livepatch properly. Add option -p|--profile-data, which +specifies the profile data file. This option is only valid with +CONFIG_CC_IS_CLANG and CONFIG_PGO_CLANG. + +Signed-off-by: Song Liu +--- + kpatch-build/kpatch-build | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index f712578..fc9f92b 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -677,9 +677,10 @@ usage() { + echo " --skip-cleanup Skip post-build cleanup" >&2 + echo " --skip-compiler-check Skip compiler version matching check" >&2 + echo " (not recommended)" >&2 ++ echo " -p, --profile-data specify profile data for PGO (clang only)" >&2 + } + +-options="$(getopt -o ha:r:s:c:v:j:t:n:o:dR -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed" ++options="$(getopt -o ha:r:s:c:v:j:t:n:o:dRp: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace,profile-data" -- "$@")" || die "getopt failed" + + eval set -- "$options" + +@@ -761,6 +762,10 @@ while [[ $# -gt 0 ]]; do + echo "WARNING: Skipping compiler version matching check (not recommended)" + SKIPCOMPILERCHECK=1 + ;; ++ -p|--profile-data) ++ PROFILE_DATA="$(readlink -f "$2")" ++ shift ++ ;; + *) + [[ "$1" = "--" ]] && shift && continue + [[ ! -f "$1" ]] && die "patch file '$1' not found" +@@ -1073,6 +1078,16 @@ fi + + if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then + echo "WARNING: Clang support is experimental" ++ if [[ -z "$PROFILE_DATA" ]] && [[ -n "$CONFIG_PGO_CLANG" ]]; then ++ die "Please specify profile-data for CONFIG_PGO_CLANG" ++ fi ++ if [[ -n "$PROFILE_DATA" ]] && [[ -z "$CONFIG_PGO_CLANG" ]]; then ++ echo "WARNING profile-data specified w/o CONFIG_PGO_CLANG, ignore it" ++ fi ++else ++ if [[ -n "$PROFILE_DATA" ]]; then ++ die "Only supports profile-data with Clang" ++ fi + fi + + if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then +@@ -1124,6 +1139,10 @@ declare -a MAKEVARS + if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then + MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${CLANG}") + MAKEVARS+=("HOSTCC=clang") ++ if [[ -n "$CONFIG_PGO_CLANG" ]]; then ++ MAKEVARS+=("CFLAGS_PGO_CLANG=-fprofile-use=$PROFILE_DATA") ++ MAKEVARS+=("LLVM=1") ++ fi + else + MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${GCC}") + fi +-- +2.37.3 + diff --git a/0104-kpatch-cc-Add-more-file-ignores.patch b/0104-kpatch-cc-Add-more-file-ignores.patch deleted file mode 100644 index cf69849..0000000 --- a/0104-kpatch-cc-Add-more-file-ignores.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 1ead10d2b214ec5545ee2cdb25d5b0cdb3b4f735 Mon Sep 17 00:00:00 2001 -From: Josh Poimboeuf -Date: Wed, 17 Aug 2022 12:10:39 -0700 -Subject: [PATCH 104/108] kpatch-cc: Add more file ignores - -These files aren't in the kernel proper, and can be ignored. - -Signed-off-by: Josh Poimboeuf ---- - kpatch-build/kpatch-cc | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/kpatch-build/kpatch-cc b/kpatch-build/kpatch-cc -index 6f0063e..d2bccdd 100755 ---- a/kpatch-build/kpatch-cc -+++ b/kpatch-build/kpatch-cc -@@ -31,22 +31,22 @@ if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; th - vmlinux.o|\ - .tmp_kallsyms1.o|\ - .tmp_kallsyms2.o|\ -- init/version.o|\ -- arch/x86/boot/version.o|\ -- arch/x86/boot/compressed/eboot.o|\ -- arch/x86/boot/header.o|\ -- arch/x86/boot/compressed/efi_stub_64.o|\ -- arch/x86/boot/compressed/piggy.o|\ -- kernel/system_certificates.o|\ -- arch/x86/vdso/*|\ -+ arch/x86/boot/*|\ - arch/x86/entry/vdso/*|\ -- drivers/firmware/efi/libstub/*|\ -+ arch/x86/purgatory/*|\ -+ arch/x86/realmode/*|\ -+ arch/x86/tools/*|\ -+ arch/x86/vdso/*|\ - arch/powerpc/kernel/prom_init.o|\ - arch/powerpc/kernel/vdso64/*|\ - arch/s390/boot/*|\ - arch/s390/purgatory/*|\ - arch/s390/kernel/vdso64/*|\ -+ drivers/firmware/efi/libstub/*|\ -+ init/version.o|\ -+ kernel/system_certificates.o|\ - lib/*|\ -+ tools/*|\ - .*.o|\ - */.lib_exports.o) - break --- -2.37.3 - diff --git a/0105-create-diff-object-ignore-section-.rel.llvm.call-gra.patch b/0105-create-diff-object-ignore-section-.rel.llvm.call-gra.patch new file mode 100644 index 0000000..914e182 --- /dev/null +++ b/0105-create-diff-object-ignore-section-.rel.llvm.call-gra.patch @@ -0,0 +1,29 @@ +From 88bf611ea0a16930a764509a59700cc2418641f0 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Wed, 1 Mar 2023 15:25:19 -0800 +Subject: [PATCH 105/107] create-diff-object: ignore section + .rel.llvm.call-graph-profile + +This section is used by llvm to store profile data. Ignore it in the +livepatch. + +Signed-off-by: Song Liu +--- + kpatch-build/create-diff-object.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index e88cb3b..4e3341e 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -2869,6 +2869,7 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) + if (!strncmp(sec->name, ".discard", 8) || + !strncmp(sec->name, ".rela.discard", 13) || + !strncmp(sec->name, ".llvm_addrsig", 13) || ++ !strncmp(sec->name, ".rel.llvm.call-graph-profile", 28) || + !strncmp(sec->name, ".llvm.", 6)) + sec->ignore = 1; + } +-- +2.37.3 + diff --git a/0105-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch b/0105-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch deleted file mode 100644 index fef1169..0000000 --- a/0105-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 7861240f482aa41bfad41fbb57ac1990cd6b6960 Mon Sep 17 00:00:00 2001 -From: Josh Poimboeuf -Date: Wed, 17 Aug 2022 12:17:19 -0700 -Subject: [PATCH 105/108] kpatch-build: Add find_kobj() short-circuit for OOT - modules - -When patching an OOT module, the parent object is always the OOT module. -Hard-code that to prevent the need for any further special casing in -find_kobj() (e.g., commit 9143e88f16a1 ("kpatch-build: fix -find_parent_obj")). - -Signed-off-by: Josh Poimboeuf ---- - kpatch-build/kpatch-build | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - -diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build -index 296fa48..5435a19 100755 ---- a/kpatch-build/kpatch-build -+++ b/kpatch-build/kpatch-build -@@ -479,6 +479,12 @@ find_parent_obj() { - - find_kobj() { - arg="$1" -+ -+ if [[ -n $OOT_MODULE ]]; then -+ KOBJFILE="$OOT_MODULE" -+ return -+ fi -+ - KOBJFILE="$arg" - DEEP_FIND=0 - ERROR_IF_DIFF= -@@ -1093,17 +1099,17 @@ for i in $FILES; do - find_kobj "$i" - cd "$TEMPDIR" || die - if [[ -e "orig/$i" ]]; then -- if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then -- KOBJFILE_NAME=vmlinux -- KOBJFILE_PATH="$VMLINUX" -- SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" -- SYMVERS_FILE="$BUILDDIR/Module.symvers" -- elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then -+ if [[ -n $OOT_MODULE ]]; then - KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")" - KOBJFILE_NAME="${KOBJFILE_NAME//-/_}" - KOBJFILE_PATH="$OOT_MODULE" - SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab" - SYMVERS_FILE="$TEMPDIR/Module.symvers" -+ elif [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then -+ KOBJFILE_NAME=vmlinux -+ KOBJFILE_PATH="$VMLINUX" -+ SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" -+ SYMVERS_FILE="$BUILDDIR/Module.symvers" - else - KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}") - KOBJFILE_NAME="${KOBJFILE_NAME//-/_}" --- -2.37.3 - diff --git a/0106-kpatch-build-Run-objtool-on-thinlto-files.patch b/0106-kpatch-build-Run-objtool-on-thinlto-files.patch new file mode 100644 index 0000000..5df0f7d --- /dev/null +++ b/0106-kpatch-build-Run-objtool-on-thinlto-files.patch @@ -0,0 +1,44 @@ +From 764a57b1756dffba9bf7c990f752dbd739ea149f Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Mon, 6 Mar 2023 22:43:43 -0800 +Subject: [PATCH 106/107] kpatch-build: Run objtool on thinlto files + +In this way, CDO should generate patches with required sections, such as +the .orc sections. + +Signed-off-by: Song Liu +--- + kpatch-build/kpatch-build | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index fc9f92b..938e88f 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -1212,6 +1212,9 @@ fi + + if [[ -n "$CONFIG_LTO_CLANG" ]]; then + DIFF_OBJS="$TEMPDIR/thinlto_objs" ++ ++ # Get the objtool command line, so we can run it on the thinlto files ++ OBJTOOL_CMD=$(grep -o -e "/tools/objtool/objtool .*" "$BUILDDIR"/.vmlinux.o.cmd | sed 's/vmlinux.o//') + else + DIFF_OBJS="$TEMPDIR/changed_objs" + fi +@@ -1314,6 +1317,13 @@ for i in $FILES; do + # skip .thinlto file without any functions + num_func=$("$READELF" --symbols "orig/$i" | grep -c FUNC) + [[ $num_func -eq 0 ]] && continue ++ if [[ $i = vmlinux.o.* ]] ; then ++ eval "$BUILDDIR/$OBJTOOL_CMD orig/$i" ++ eval "$BUILDDIR/$OBJTOOL_CMD patched/$i" ++ else ++ eval "$BUILDDIR/$OBJTOOL_CMD --module orig/$i" ++ eval "$BUILDDIR/$OBJTOOL_CMD --module patched/$i" ++ fi + fi + + # create-diff-object orig.o patched.o parent-name parent-symtab +-- +2.37.3 + diff --git a/0106-kpatch-build-support-Linux-5.19-.cmd-file-format.patch b/0106-kpatch-build-support-Linux-5.19-.cmd-file-format.patch deleted file mode 100644 index 94f1a7c..0000000 --- a/0106-kpatch-build-support-Linux-5.19-.cmd-file-format.patch +++ /dev/null @@ -1,299 +0,0 @@ -From 1d7e8a74bb6c282ebe6c9193e4bd0218ec689e46 Mon Sep 17 00:00:00 2001 -From: Josh Poimboeuf -Date: Wed, 17 Aug 2022 12:21:04 -0700 -Subject: [PATCH 106/108] kpatch-build: support Linux 5.19 .cmd file format - -Rewrite kobj_find() to deal with Linux 5.19, where the .cmd files use -object file paths relative to the .cmd file rather than relative to the -root of the kernel tree. - -While at it, add several performance enhancements to prevent all -currently known deep finds. - -This is all quite fiddly. But it works. - -Fixes #1277. - -Signed-off-by: Josh Poimboeuf ---- - kpatch-build/kpatch-build | 243 +++++++++++++++++++++++++++++--------- - 1 file changed, 188 insertions(+), 55 deletions(-) - -diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build -index 5435a19..bec8010 100755 ---- a/kpatch-build/kpatch-build -+++ b/kpatch-build/kpatch-build -@@ -434,82 +434,215 @@ find_special_section_data() { - return - } - --filter_parent_obj() --{ -- local dir="${1}" -- local file="${2}" -+# path of file, relative to dir -+# adapted from https://stackoverflow.com/a/24848739 -+relpath() { -+ local file="$1" -+ local dir="$2" -+ -+ local filedir -+ local common -+ local result -+ -+ filedir="$(dirname "$(readlink -f "$file")")" -+ common="$(readlink -f "$dir")" -+ -+ if [[ "$filedir" = "$common" ]]; then -+ basename "$file" -+ return -+ fi -+ -+ while [[ "${filedir#$common/}" = "$filedir" ]]; do -+ common="$(dirname "$common")" -+ result="../$result" -+ done - -- grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" -+ result="${result}${filedir#$common/}" -+ echo "${result}/$(basename "$file")" - } - --find_parent_obj() { -- dir="$(dirname "$1")" -- absdir="$(readlink -f "$dir")" -- pwddir="$(readlink -f .)" -- pdir="${absdir#$pwddir/}" -- file="$(basename "$1")" -- grepname="${1%.o}" -- grepname="$grepname\\.o" -- if [[ "$DEEP_FIND" -eq 1 ]]; then -- num=0 -- if [[ -n "$last_deep_find" ]]; then -- parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)" -- num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)" -+cmd_file_to_o_file() { -+ local parent="$1" -+ -+ # convert cmd file name to corresponding .o -+ parent_dir="$(dirname "$parent")" -+ parent_dir="${parent_dir#./}" -+ parent="$(basename "$parent")" -+ parent="${parent#.}" -+ parent="${parent%.cmd}" -+ parent="$parent_dir/$parent" -+ -+ [[ -f $parent ]] || die "can't find $parent associated with $1" -+ -+ echo "$parent" -+} -+ -+get_parent_from_parents() { -+ local parents=("$@") -+ -+ [[ ${#parents[@]} -eq 0 ]] && PARENT="" && return -+ [[ ${#parents[@]} -eq 1 ]] && PARENT="${parents[0]}" && return -+ -+ # multiple parents: -+ local parent -+ local mod_name="${parents[0]%.*}" -+ local mod_file -+ for parent in "${parents[@]}"; do -+ # for modules, there can be multiple matches. Some -+ # combination of foo.o, foo.mod, and foo.ko, depending -+ # on kernel version and whether the module is single or -+ # multi-object. Make sure a .mod and/or .ko exists, and no -+ # more than one .mod/.ko exists. -+ -+ [[ $parent = *.o ]] && continue -+ -+ if [[ ${parent%.*} != "$mod_name" ]]; then -+ mod_file="" -+ break - fi -- if [[ "$num" -eq 0 ]]; then -- parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)" -- num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)" -- [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" -+ -+ if [[ $parent = *.mod || $parent = *.ko ]]; then -+ mod_file=$parent -+ continue - fi -+ -+ mod_file="" -+ break -+ done -+ -+ if [[ -n $mod_file ]]; then -+ PARENT="$mod_file" -+ return -+ fi -+ -+ ERROR_IF_DIFF="multiple parent matches for $file: ${parents[*]}" -+ PARENT="${parents[0]}" -+} -+ -+__find_parent_obj_in_dir() { -+ local file="$1" -+ local dir="$2" -+ -+ declare -a parents -+ -+ while IFS='' read -r parent; do -+ parent="$(cmd_file_to_o_file "$parent")" -+ [[ $parent -ef $file ]] && continue -+ parents+=("$parent") -+ done < <(grep -El "[ ]${file/./\\.}([ \)]|$)" "$dir"/.*.cmd) -+ -+ get_parent_from_parents "${parents[@]}" -+} -+ -+find_parent_obj_in_dir() { -+ local file="$1" -+ local dir="$2" -+ -+ # make sure the dir has .cmd files -+ if ! compgen -G "$dir"/.*.cmd > /dev/null; then -+ PARENT="" -+ return -+ fi -+ -+ # 5.19+: ../acp/acp_hw.o -+ __find_parent_obj_in_dir "$(relpath "$file" "$dir")" "$dir" -+ [[ -n $PARENT ]] && return -+ -+ # pre-5.19 (and 5.19+ single-object modules): -+ if [[ $file == $dir* ]]; then -+ # arch/x86/kernel/smp.o -+ __find_parent_obj_in_dir "$file" "$dir" - else -- parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)" -- num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)" -+ # drivers/gpu/drm/amd/amdgpu/../acp/acp_hw.o -+ __find_parent_obj_in_dir "$dir"/"$(relpath "$file" "$dir")" "$dir" - fi -+} - -- [[ "$num" -eq 0 ]] && PARENT="" && return -- [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" -+find_parent_obj() { -+ local file="$1" -+ -+ # common case: look in same directory -+ find_parent_obj_in_dir "$file" "$(dirname "$file")" -+ [[ -n $PARENT ]] && return - -- dir="$(dirname "$parent")" -- PARENT="$(basename "$parent")" -- PARENT="${PARENT#.}" -- PARENT="${PARENT%.cmd}" -- [[ $dir != "." ]] && PARENT="$dir/$PARENT" -- [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" -+ # if we previously had a successful deep find, try that dir first -+ if [[ -n "$LAST_DEEP_FIND_DIR" ]]; then -+ find_parent_obj_in_dir "$file" "$LAST_DEEP_FIND_DIR" -+ [[ -n "$PARENT" ]] && return -+ fi -+ -+ # prevent known deep finds -+ if [[ $file = drivers/gpu/drm/amd/* ]]; then -+ find_parent_obj_in_dir "$file" "drivers/gpu/drm/amd/amdgpu" -+ [[ -n "$PARENT" ]] && return -+ fi -+ if [[ $file = virt/kvm/* ]]; then -+ find_parent_obj_in_dir "$file" "arch/x86/kvm" -+ [[ -n "$PARENT" ]] && return -+ fi -+ if [[ $file = drivers/oprofile/* ]]; then -+ find_parent_obj_in_dir "$file" "arch/x86/oprofile" -+ [[ -n "$PARENT" ]] && return -+ fi -+ -+ # check higher-level dirs -+ local dir -+ dir="$(dirname "$file")" -+ while [[ ! $dir -ef . ]]; do -+ dir="$(dirname "$dir")" -+ find_parent_obj_in_dir "$file" "$dir" -+ [[ -n $PARENT ]] && return -+ done -+ -+ # slow path: search the entire tree ("deep find") -+ echo 'doing "deep find" for parent object' -+ declare -a parents -+ while IFS= read -r -d '' dir; do -+ find_parent_obj_in_dir "$file" "$dir" -+ if [[ -n $PARENT ]]; then -+ parents+=("$PARENT") -+ LAST_DEEP_FIND_DIR="$dir" -+ fi -+ done < <(find . -type d -print0) -+ -+ get_parent_from_parents "${parents[@]}" - } - -+# find vmlinux or .ko associated with a .o file - find_kobj() { -- arg="$1" -+ local file="$1" - - if [[ -n $OOT_MODULE ]]; then - KOBJFILE="$OOT_MODULE" - return - fi - -- KOBJFILE="$arg" -- DEEP_FIND=0 -+ KOBJFILE="$file" - ERROR_IF_DIFF= - while true; do -+ case "$KOBJFILE" in -+ *.mod) -+ KOBJFILE=${PARENT/.mod/.ko} -+ [[ -e $KOBJFILE ]] || die "can't find .ko for $PARENT" -+ return -+ ;; -+ *.ko) -+ return -+ ;; -+ */built-in.o|\ -+ */built-in.a|\ -+ arch/x86/kernel/ebda.o|\ -+ arch/x86/kernel/head*.o|\ -+ arch/x86/kernel/platform-quirks.o|\ -+ arch/x86/lib/lib.a|\ -+ lib/lib.a) -+ KOBJFILE=vmlinux -+ return -+ ;; -+ esac -+ - find_parent_obj "$KOBJFILE" -- [[ -n "$PARENT" ]] && DEEP_FIND=0 -- if [[ -z "$PARENT" ]]; then -- [[ "$KOBJFILE" = *.ko ]] && return -- case "$KOBJFILE" in -- */built-in.o|\ -- */built-in.a|\ -- arch/x86/lib/lib.a|\ -- arch/x86/kernel/head*.o|\ -- arch/x86/kernel/ebda.o|\ -- arch/x86/kernel/platform-quirks.o|\ -- lib/lib.a) -- KOBJFILE=vmlinux -- return -- esac -- if [[ "$DEEP_FIND" -eq 0 ]]; then -- DEEP_FIND=1 -- continue; -- fi -- die "invalid ancestor $KOBJFILE for $arg" -- fi -+ [[ -z "$PARENT" ]] && die "invalid ancestor $KOBJFILE for $file" - KOBJFILE="$PARENT" - done - } --- -2.37.3 - diff --git a/0107-create-diff-object-compare-section-name-with-kpatch_.patch b/0107-create-diff-object-compare-section-name-with-kpatch_.patch deleted file mode 100644 index 5d016ac..0000000 --- a/0107-create-diff-object-compare-section-name-with-kpatch_.patch +++ /dev/null @@ -1,52 +0,0 @@ -From ce97c8ef720bd288fbc53aad51969571a1c2c1e6 Mon Sep 17 00:00:00 2001 -From: Song Liu -Date: Wed, 13 Oct 2021 00:10:20 -0700 -Subject: [PATCH 107/108] create-diff-object: compare section name with - kpatch_section_function_name - -Profile-Guided Optimization (PGO) uses profiling data to help the compiler -to evaluate the properties of a function, and thus adds different prefixes -to the section/function. For example, with -ffunction-sections, the -compiler will prefix some sectiones with .text.unlikely. However, if a -function changes from the version in the profiling data, the compiler may -ignore the profiling data. This often happens to the patched function -when kpatch-build builds the patch. As a result, the original function -and the patch function may have different prefix, i.e., one of them has -.text, the other has .text.unlikely. - -To correlate these functions properly, use kpatch_section_function_name() -in kpatch_correlate_sections() to find matching sections. - -Signed-off-by: Song Liu ---- - kpatch-build/create-diff-object.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c -index 1967bd8..6f08c4d 100644 ---- a/kpatch-build/create-diff-object.c -+++ b/kpatch-build/create-diff-object.c -@@ -986,6 +986,8 @@ static void kpatch_correlate_section(struct section *sec_orig, - kpatch_correlate_symbol(sec_orig->sym, sec_patched->sym); - } - -+static char *kpatch_section_function_name(struct section *sec); -+ - static void kpatch_correlate_sections(struct list_head *seclist_orig, - struct list_head *seclist_patched) - { -@@ -995,8 +997,9 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig, - if (sec_orig->twin) - continue; - list_for_each_entry(sec_patched, seclist_patched, list) { -- if (kpatch_mangled_strcmp(sec_orig->name, sec_patched->name) || -- sec_patched->twin) -+ if (sec_patched->twin || -+ kpatch_mangled_strcmp(kpatch_section_function_name(sec_orig), -+ kpatch_section_function_name(sec_patched))) - continue; - - if (is_special_static(is_rela_section(sec_orig) ? --- -2.37.3 - diff --git a/0107-kpatch-build-skip-more-symbols-in-locals_match.patch b/0107-kpatch-build-skip-more-symbols-in-locals_match.patch new file mode 100644 index 0000000..1e32e52 --- /dev/null +++ b/0107-kpatch-build-skip-more-symbols-in-locals_match.patch @@ -0,0 +1,38 @@ +From b479edd20f6083c65cda9c9277cc54cc56ce0939 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Wed, 15 Mar 2023 11:21:31 -0700 +Subject: [PATCH 107/107] kpatch-build: skip more symbols in locals_match + +Skip table_sym with maybe_discarded_sym() == true. This is probably only +needed for LTO build. + +Signed-off-by: Song Liu +--- + kpatch-build/lookup.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c +index 2ccc181..c8844f8 100644 +--- a/kpatch-build/lookup.c ++++ b/kpatch-build/lookup.c +@@ -107,6 +107,8 @@ static bool locals_match(struct lookup_table *table, int idx, + if (table_sym->type != STT_FUNC && table_sym->type != STT_OBJECT) + continue; + ++ if (maybe_discarded_sym(table_sym->name)) ++ continue; + found = 0; + sym = file_sym; + list_for_each_entry_continue(sym, sym_list, list) { +@@ -115,6 +117,8 @@ static bool locals_match(struct lookup_table *table, int idx, + if (sym->bind != STB_LOCAL) + continue; + ++ if (maybe_discarded_sym(sym->name)) ++ continue; + if (sym->type == table_sym->type && + !strcmp(sym->name, table_sym->name)) { + found = 1; +-- +2.37.3 + diff --git a/0108-kpatch-build-add-support-for-clang-pgo.patch b/0108-kpatch-build-add-support-for-clang-pgo.patch deleted file mode 100644 index b88c922..0000000 --- a/0108-kpatch-build-add-support-for-clang-pgo.patch +++ /dev/null @@ -1,73 +0,0 @@ -From db5d32876a6c89454aab9e8e9412435fc5b3facd Mon Sep 17 00:00:00 2001 -From: Song Liu -Date: Wed, 13 Oct 2021 01:03:55 -0700 -Subject: [PATCH 108/108] kpatch-build: add support for clang pgo - -For clang with Profile-Guided Optimization (PGO), profile data is needed -to compile the livepatch properly. Add option -p|--profile-data, which -specifies the profile data file. This option is only valid with -CONFIG_CC_IS_CLANG and CONFIG_PGO_CLANG. - -Signed-off-by: Song Liu ---- - kpatch-build/kpatch-build | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build -index bec8010..13bccab 100755 ---- a/kpatch-build/kpatch-build -+++ b/kpatch-build/kpatch-build -@@ -677,9 +677,10 @@ usage() { - echo " --skip-cleanup Skip post-build cleanup" >&2 - echo " --skip-compiler-check Skip compiler version matching check" >&2 - echo " (not recommended)" >&2 -+ echo " -p, --profile-data specify profile data for PGO (clang only)" >&2 - } - --options="$(getopt -o ha:r:s:c:v:j:t:n:o:dR -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed" -+options="$(getopt -o ha:r:s:c:v:j:t:n:o:dRp: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace,profile-data" -- "$@")" || die "getopt failed" - - eval set -- "$options" - -@@ -761,6 +762,10 @@ while [[ $# -gt 0 ]]; do - echo "WARNING: Skipping compiler version matching check (not recommended)" - SKIPCOMPILERCHECK=1 - ;; -+ -p|--profile-data) -+ PROFILE_DATA="$(readlink -f "$2")" -+ shift -+ ;; - *) - [[ "$1" = "--" ]] && shift && continue - [[ ! -f "$1" ]] && die "patch file '$1' not found" -@@ -1056,6 +1061,16 @@ fi - - if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then - echo "WARNING: Clang support is experimental" -+ if [[ -z "$PROFILE_DATA" ]] && [[ -n "$CONFIG_PGO_CLANG" ]]; then -+ die "Please specify profile-data for CONFIG_PGO_CLANG" -+ fi -+ if [[ -n "$PROFILE_DATA" ]] && [[ -z "$CONFIG_PGO_CLANG" ]]; then -+ echo "WARNING profile-data specified w/o CONFIG_PGO_CLANG, ignore it" -+ fi -+else -+ if [[ -n "$PROFILE_DATA" ]]; then -+ die "Only supports profile-data with Clang" -+ fi - fi - - if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then -@@ -1107,6 +1122,10 @@ declare -a MAKEVARS - if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then - MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${CLANG}") - MAKEVARS+=("HOSTCC=clang") -+ if [[ -n "$CONFIG_PGO_CLANG" ]]; then -+ MAKEVARS+=("CFLAGS_PGO_CLANG=-fprofile-use=$PROFILE_DATA") -+ MAKEVARS+=("LLVM=1") -+ fi - else - MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${GCC}") - fi --- -2.37.3 - diff --git a/kpatch.spec b/kpatch.spec index 4f17474..9129ff0 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,8 +1,8 @@ %define kpatch_dnf_ver 0.4 Name: kpatch -Version: 0.9.7 -Release: 2.1%{?dist} +Version: 0.9.8 +Release: 1.1%{?dist} Summary: Dynamic kernel patch manager Group: System Environment/Kernel @@ -17,15 +17,14 @@ Patch1: 0002-kpatch-clarify-unload-unsupport.patch Patch2: 0003-do-not-rm-selinux-rpm-owned-directory.patch # Upstream backports -Patch100: 0100-kpatch-build-for-clang-use-.strtab-if-no-.shstrtab.patch -Patch101: 0101-create-diff-object-ignore-clang-s-.llvm_addrsig-sect.patch -Patch102: 0102-create-diff-object-ignore-.llvm.-sections.patch -Patch103: 0103-gcc-plugin-update-headers-for-gcc-12.patch -Patch104: 0104-kpatch-cc-Add-more-file-ignores.patch -Patch105: 0105-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch -Patch106: 0106-kpatch-build-support-Linux-5.19-.cmd-file-format.patch -Patch107: 0107-create-diff-object-compare-section-name-with-kpatch_.patch -Patch108: 0108-kpatch-build-add-support-for-clang-pgo.patch +Patch100: 0100-support-ubsan-for-kpatch.patch +Patch101: 0101-create-diff-object-handle-__initcall_stub-with-CONFI.patch +Patch102: 0102-kpatch-build-support-CONFIG_LTO_CLANG_THIN.patch +Patch103: 0103-create-diff-object-compare-section-name-with-kpatch_.patch +Patch104: 0104-kpatch-build-add-support-for-clang-pgo.patch +Patch105: 0105-create-diff-object-ignore-section-.rel.llvm.call-gra.patch +Patch106: 0106-kpatch-build-Run-objtool-on-thinlto-files.patch +Patch107: 0107-kpatch-build-skip-more-symbols-in-locals_match.patch # kpatch-dnf backports (inactive -- for future reference) #Patch200: 0200-foo-bar-etcetera.patch @@ -83,7 +82,6 @@ kpatch-patch packages updates. %patch105 -p1 %patch106 -p1 %patch107 -p1 -%patch108 -p1 %setup -D -T -a 1 @@ -126,6 +124,10 @@ echo "To enable automatic kpatch-patch subscription, run:" echo -e "\t$ dnf kpatch auto" %changelog +* Wed Mar 15 2023 Davide Cavalca - 0.9.8-1.1 +- Update to 0.9.8 +- Refresh clang PGO patches + * Wed Dec 07 2022 Davide Cavalca - 0.9.7-2.1 - Merge upstream changes into Hyperscale diff --git a/sources b/sources index 102aa6f..75d6a90 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ SHA512 (kpatch-dnf-v0.4.tar.gz) = d76b2ec5595e06fd560ae928f43ad275b4ce07574a1fc829d184d56c5f09a88ce0cb1d1b05e58eb53e6d934a879886b7f0149f782950d7856fbb99c61ce436c3 -SHA512 (v0.9.7.tar.gz) = c876d9b1e5f6e6ab858fa6f302e78152beb3e50cedd93f3c61ab6f747e32199b0601ad4a36d426d43d0e9a37d9bf1d6bbfddccc86df4b31d5e3e6edead6cded3 +SHA512 (v0.9.8.tar.gz) = ab3a771dfcde92a9eee768afcf7fddb6f1ad5ba9e8c7f44d579d258ce9b6ee1722869b1b70c4597ae951b0faf71413efa26a5b135f50308c996b284a9dcee5b7