From c27f1093cd47c48e2f403c4ffb29bf066ce0bea5 Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Fri, 2 Nov 2018 17:24:24 +0000 Subject: [PATCH 1002/1015] kpatch-build: support third party module make hotpatch support out of tree module to make hotpatch. Signed-off-by: Zhipeng Xie --- kpatch-build/kpatch-build | 76 ++++++++++++++++++++++++++++++++++++--------- kpatch-build/kpatch-gcc | 5 +++ 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index a76913f..ccef86d 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -102,7 +102,11 @@ remove_patches() { for (( ; APPLIED_PATCHES>0; APPLIED_PATCHES-- )); do idx=$(( APPLIED_PATCHES - 1)) patch="${PATCH_LIST[$idx]}" - patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null + if [ -n "$USERMODDIR" ];then + patch -p1 -R -d "$USERMODDIR" < "$patch" &> /dev/null + else + patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null + fi done # If $SRCDIR was a git repo, make sure git actually sees that @@ -318,8 +322,8 @@ find_parent_obj() { num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -Fvc "$pdir/.${file}.cmd")" fi if [[ "$num" -eq 0 ]]; then - parent="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)" - num="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")" + parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)" + num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")" [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" fi else @@ -335,6 +339,9 @@ find_parent_obj() { PARENT="${PARENT#.}" PARENT="${PARENT%.cmd}" PARENT="$dir/$PARENT" + if [ -n "$USERMODDIR" ];then + PARENT="$(readlink -f "$PARENT")" + fi [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" } @@ -397,7 +404,7 @@ usage() { echo " (not recommended)" >&2 } -options="$(getopt -o ha:r:s:c:v:j:t:n:o:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed" +options="$(getopt -o ha:r:s:c:v:j:t:n:o:dm:b: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup,moduledir,builddir" -- "$@")" || die "getopt failed" eval set -- "$options" @@ -463,6 +470,16 @@ while [[ $# -gt 0 ]]; do echo "WARNING: Skipping gcc version matching check (not recommended)" SKIPGCCCHECK=1 ;; + -m|--moduledir) + USERMODDIR=$(readlink -f "$2") + shift + [[ ! -d "$USERMODDIR" ]] && die "module dir $USERMODDIR not found" + ;; + -b|--builddir) + BUILDDIR=$(readlink -f "$2") + shift + [[ ! -d "$BUILDDIR" ]] && die "kernel develop dir $BUILDDIR not found" + ;; *) [[ "$1" = "--" ]] && shift && continue [[ ! -f "$1" ]] && die "patch file '$1' not found" @@ -528,7 +545,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then fi [[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt" -[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules" +[[ -z "$USERMODDIR" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules" # Don't check external file. # shellcheck disable=SC1091 @@ -691,7 +708,11 @@ fi grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported" echo "Testing patch file(s)" -cd "$SRCDIR" || die +if [ -z "$USERMODDIR" ];then + cd "$SRCDIR" || die +else + cd $USERMODDIR || die +fi apply_patches remove_patches @@ -709,15 +730,23 @@ find_special_section_data if [[ $DEBUG -ge 4 ]]; then export KPATCH_GCC_DEBUG=1 fi - -echo "Building original kernel" -./scripts/setlocalversion --save-scmversion || die +if [ -z "$USERMODDIR" ];then + echo "Building original kernel" + ./scripts/setlocalversion --save-scmversion || die +else + echo "Building original module" +fi unset KPATCH_GCC_TEMPDIR # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die -echo "Building patched kernel" +sleep 1 +if [ -z "$USERMODDIR" ];then + echo "Building patched kernel" +else + echo "Building patched module" +fi apply_patches mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched" KPATCH_GCC_TEMPDIR="$TEMPDIR" @@ -739,14 +768,22 @@ if [[ ! -e "$TEMPDIR/changed_objs" ]]; then die "no changed objects found" fi -grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file" +SYMVERS="$SRCDIR/Module.symvers" +if [ ! -f "$SYMVERS" -a -n "$BUILDDIR" ];then + SYMVERS="$BUILDDIR/Module.symvers" +fi +grep -q vmlinux "$SYMVERS" || die "truncated $SYMVERS file" # Read as words, no quotes. # shellcheck disable=SC2013 for i in $(cat "$TEMPDIR/changed_objs") do mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die - cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die + if [ -z "$USERMODDIR" ];then + cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die + else + cp -f "$i" "$TEMPDIR/patched/$i" || die + fi done echo "Extracting new and modified ELF sections" @@ -788,7 +825,11 @@ for i in $FILES; do [[ "$i" = usr/initramfs_data.o ]] && continue mkdir -p "output/$(dirname "$i")" - cd "$SRCDIR" || die + if [ -z "$USERMODDIR" ];then + cd "$SRCDIR" || die + else + cd $USERMODDIR || die + fi find_kobj "$i" cd "$TEMPDIR" || die if [[ -e "orig/$i" ]]; then @@ -808,7 +849,7 @@ for i in $FILES; do # create-diff-object orig.o patched.o parent-name parent-symtab # Module.symvers patch-mod-name output.o "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE_NAME" \ - "$SYMTAB" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" \ + "$SYMTAB" "$SYMVERS" "${MODNAME//-/_}" \ "output/$i" 2>&1 | logger 1 check_pipe_status create-diff-object # create-diff-object returns 3 if no functional change is found @@ -871,7 +912,12 @@ fi cd "$TEMPDIR/patch" || die -KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \ +if [ -z "$BUILDDIR" ];then + KPATCH_BUILDIR="$SRCDIR" +else + KPATCH_BUILDIR="$BUILDDIR" +fi +KPATCH_BUILD="$KPATCH_BUILDIR" KPATCH_NAME="$MODNAME" \ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ make 2>&1 | logger || die diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc index 2d56da1..21f7e2e 100755 --- a/kpatch-build/kpatch-gcc +++ b/kpatch-build/kpatch-gcc @@ -23,6 +23,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then [[ "$obj" = */.tmp_mc_*.o ]] && break; [[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}" + + if [[ $obj =~ \/\.[0-9]+\.o ]]; then + break; + fi + case "$obj" in *.mod.o|\ *built-in.o|\ -- 1.7.5.4