From c33adf0ff23cc88479e36e6a81aadfd63a75b6ba Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Wed, 8 Nov 2017 16:30:31 +0100 Subject: [PATCH 1/8] kpatch-build: Remove unnecessary 'make prepare' This was introduced in commit 5352d8b01aa1 ('build objects in separate directory to fix caching') but is no longer necessary. Fixes: 2e99d6b7a448 ('kpatch-build: build the kernel in ~/.kpatch/src again') Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 2 -- 1 file changed, 2 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 90ddb726e..3dec1c77e 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -763,8 +763,6 @@ if "$KPATCH_MODULE"; then fi echo "Building patch module: $MODNAME.ko" -cd "$SRCDIR" || die -make prepare >> "$LOGFILE" 2>&1 || die if [[ ! -z "$UBUNTU_KERNEL" ]]; then # UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it From 15cdcc8b5fe245c5610aea9d53bf68bcc7133028 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Wed, 8 Nov 2017 16:39:13 +0100 Subject: [PATCH 2/8] kpatch-build: Add -n, --name to the usage Fixes: 8dc25d79d1b0 ('kpatch-build: let user specify kpatch module name') Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 1 + 1 file changed, 1 insertion(+) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 3dec1c77e..8c3ac70c3 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -361,6 +361,7 @@ usage() { echo " -v, --vmlinux Specify original vmlinux" >&2 echo " -j, --jobs Specify the number of make jobs" >&2 echo " -t, --target Specify custom kernel build targets" >&2 + echo " -n, --name Specify the name of the kpatch module" >&2 echo " -o, --output Specify output folder" >&2 echo " -d, --debug Keep scratch files in /tmp" >&2 echo " --skip-cleanup Skip post-build cleanup" >&2 From 862327db3ee3586c802cfe44e4a22b6e784211de Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Wed, 8 Nov 2017 17:42:38 +0100 Subject: [PATCH 3/8] kpatch-build: Fix indentation Replace stray spaces with tabs, except in the usage output where tabs don't make much sense. Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 103 +++++++++++++++++++------------------- kpatch-build/kpatch-gcc | 2 +- 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 8c3ac70c3..e65ffe749 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -174,6 +174,7 @@ find_core_symvers() { gcc_version_from_file() { readelf -p .comment "$1" | grep -o 'GCC:.*' } + gcc_version_check() { local c="$TEMPDIR/test.c" o="$TEMPDIR/test.o" local out gccver kgccver @@ -207,26 +208,26 @@ gcc_version_check() { find_special_section_data_ppc64le() { SPECIAL_VARS="$(readelf -wi "$VMLINUX" | - gawk --non-decimal-data ' - BEGIN { f = b = e = 0 } + gawk --non-decimal-data ' + BEGIN { f = b = e = 0 } - # Set state if name matches - f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next} - b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} - e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} + # Set state if name matches + f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next} + b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} + e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} - # Reset state unless this abbrev describes the struct size - f == 1 && !/DW_AT_byte_size/ { f = 0; next } - b == 1 && !/DW_AT_byte_size/ { b = 0; next } - e == 1 && !/DW_AT_byte_size/ { e = 0; next } + # Reset state unless this abbrev describes the struct size + f == 1 && !/DW_AT_byte_size/ { f = 0; next } + b == 1 && !/DW_AT_byte_size/ { b = 0; next } + e == 1 && !/DW_AT_byte_size/ { e = 0; next } - # Now that we know the size, stop parsing for it - f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); a = 2} - b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} - e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} + # Now that we know the size, stop parsing for it + f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); a = 2} + b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} + e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} - # Bail out once we have everything - f == 2 && b == 2 && e == 2 {exit}')" + # Bail out once we have everything + f == 2 && b == 2 && e == 2 {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" @@ -245,29 +246,29 @@ find_special_section_data() { [[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1" SPECIAL_VARS="$(readelf -wi "$VMLINUX" | - gawk --non-decimal-data $AWK_OPTIONS ' - BEGIN { a = b = p = e = 0 } - - # Set state if name matches - a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next} - b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} - p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next} - e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} - - # Reset state unless this abbrev describes the struct size - a == 1 && !/DW_AT_byte_size/ { a = 0; next } - b == 1 && !/DW_AT_byte_size/ { b = 0; next } - p == 1 && !/DW_AT_byte_size/ { p = 0; next } - e == 1 && !/DW_AT_byte_size/ { e = 0; next } - - # Now that we know the size, stop parsing for it - a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2} - b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} - p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2} - e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} - - # Bail out once we have everything - a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 {exit}')" + gawk --non-decimal-data $AWK_OPTIONS ' + BEGIN { a = b = p = e = 0 } + + # Set state if name matches + a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next} + b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} + p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next} + e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} + + # Reset state unless this abbrev describes the struct size + a == 1 && !/DW_AT_byte_size/ { a = 0; next } + b == 1 && !/DW_AT_byte_size/ { b = 0; next } + p == 1 && !/DW_AT_byte_size/ { p = 0; next } + e == 1 && !/DW_AT_byte_size/ { e = 0; next } + + # Now that we know the size, stop parsing for it + a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2} + b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} + p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2} + e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} + + # Bail out once we have everything + a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" @@ -353,17 +354,17 @@ module_name_string() { usage() { echo "usage: $(basename "$0") [options] " >&2 - echo " patchN Input patchfile(s)" >&2 - echo " -h, --help Show this help message" >&2 - echo " -r, --sourcerpm Specify kernel source RPM" >&2 - echo " -s, --sourcedir Specify kernel source directory" >&2 - echo " -c, --config Specify kernel config file" >&2 - echo " -v, --vmlinux Specify original vmlinux" >&2 - echo " -j, --jobs Specify the number of make jobs" >&2 - echo " -t, --target Specify custom kernel build targets" >&2 - echo " -n, --name Specify the name of the kpatch module" >&2 - echo " -o, --output Specify output folder" >&2 - echo " -d, --debug Keep scratch files in /tmp" >&2 + echo " patchN Input patchfile(s)" >&2 + echo " -h, --help Show this help message" >&2 + echo " -r, --sourcerpm Specify kernel source RPM" >&2 + echo " -s, --sourcedir Specify kernel source directory" >&2 + echo " -c, --config Specify kernel config file" >&2 + echo " -v, --vmlinux Specify original vmlinux" >&2 + echo " -j, --jobs Specify the number of make jobs" >&2 + echo " -t, --target Specify custom kernel build targets" >&2 + echo " -n, --name Specify the name of the kpatch module" >&2 + echo " -o, --output Specify output folder" >&2 + echo " -d, --debug Keep scratch files in /tmp" >&2 echo " --skip-cleanup Skip post-build cleanup" >&2 echo " --skip-gcc-check Skip gcc version matching check" >&2 echo " (not recommended)" >&2 @@ -489,7 +490,7 @@ elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then if [[ "$DISTRO" = ubuntu ]]; then [[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbgsym not installed" - elif [[ "$DISTRO" = debian ]]; then + elif [[ "$DISTRO" = debian ]]; then [[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbg not installed" fi diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc index 195be0b0a..72dc51d9b 100755 --- a/kpatch-build/kpatch-gcc +++ b/kpatch-build/kpatch-gcc @@ -6,7 +6,7 @@ TOOLCHAINCMD="$1" shift if [[ -z "$KPATCH_GCC_TEMPDIR" ]]; then - exec "$TOOLCHAINCMD" "$@" + exec "$TOOLCHAINCMD" "$@" fi declare -a args=("$@") From 1950c193ecc371f502e3fc125a9e1cfc67613919 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Wed, 8 Nov 2017 17:24:19 +0100 Subject: [PATCH 4/8] kpatch-build: Add -a, --archversion commandline option This can be used for building a kpatch module for a non-running kernel. Note that the correct kernel and debug packages still need to be installed. Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index e65ffe749..36919d658 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -37,7 +37,6 @@ BASE="$PWD" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")" ARCH="$(uname -m)" -ARCHVERSION="$(uname -r)" CPUS="$(getconf _NPROCESSORS_ONLN)" CACHEDIR="${CACHEDIR:-$HOME/.kpatch}" SRCDIR="$CACHEDIR/src" @@ -356,6 +355,7 @@ usage() { echo "usage: $(basename "$0") [options] " >&2 echo " patchN Input patchfile(s)" >&2 echo " -h, --help Show this help message" >&2 + echo " -a, --archversion Specify the kernel arch version" >&2 echo " -r, --sourcerpm Specify kernel source RPM" >&2 echo " -s, --sourcedir Specify kernel source directory" >&2 echo " -c, --config Specify kernel config file" >&2 @@ -370,7 +370,7 @@ usage() { echo " (not recommended)" >&2 } -options="$(getopt -o hr:s:c:v:j:t:n:o:d -l "help,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:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed" eval set -- "$options" @@ -380,13 +380,14 @@ while [[ $# -gt 0 ]]; do usage exit 0 ;; + -a|--archversion) + ARCHVERSION="$2" + shift + ;; -r|--sourcerpm) [[ ! -f "$2" ]] && die "source rpm '$2' not found" SRCRPM="$(readlink -f "$2")" shift - rpmname="$(basename "$SRCRPM")" - ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)" - ARCHVERSION="${ARCHVERSION#kernel-}" ;; -s|--sourcedir) [[ ! -d "$2" ]] && die "source dir '$2' not found" @@ -449,12 +450,31 @@ if [[ ${#PATCH_LIST[@]} -eq 0 ]]; then exit 1 fi +if [[ -n "$ARCHVERSION" ]] && [[ -n "$VMLINUX" ]]; then + warn "--archversion is incompatible with --vmlinux" + exit 1 +fi + +if [[ -n "$SRCRPM" ]]; then + if [[ -n "$ARCHVERSION" ]]; then + warn "--archversion is incompatible with --sourcerpm" + exit 1 + fi + rpmname="$(basename "$SRCRPM")" + ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)" + ARCHVERSION="${ARCHVERSION#kernel-}" +fi + # ensure cachedir and tempdir are setup properly and cleaned mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR" rm -rf "${TEMPDIR:?}"/* rm -f "$LOGFILE" if [[ -n "$USERSRCDIR" ]]; then + if [[ -n "$ARCHVERSION" ]]; then + warn "--archversion is incompatible with --sourcedir" + exit 1 + fi SRCDIR="$USERSRCDIR" [[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux @@ -464,6 +484,8 @@ if [[ -n "$USERSRCDIR" ]]; then ARCHVERSION="$(strings "$VMLINUX" | grep -e "^Linux version" | awk '{ print($3); }')" fi +[[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)" + [[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP KVER="${ARCHVERSION%%-*}" From 7770c18f93ccfce424ffc377c23d79e4eebe19df Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Thu, 9 Nov 2017 12:51:58 +0100 Subject: [PATCH 5/8] kpatch-build: Fix the logfile checks for 'undefined' The current checks never fail, because the first grep in the pipeline doesn't write anything to stdout. Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 36919d658..297c4ae07 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -686,8 +686,8 @@ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ KBUILD_MODPOST_WARN=1 \ make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1 || die [[ "${PIPESTATUS[0]}" -eq 0 ]] || die -grep -q "undefined reference" "$LOGFILE" | grep -qv kpatch_shadow && die -grep -q "undefined!" "$LOGFILE" |grep -qv kpatch_shadow && die +grep "undefined reference" "$LOGFILE" | grep -qv kpatch_shadow && die +grep "undefined!" "$LOGFILE" | grep -qv kpatch_shadow && die if [[ ! -e "$TEMPDIR/changed_objs" ]]; then die "no changed objects found" From b5f77d06084aed886ee4e9eaad8729f67e95b933 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Thu, 9 Nov 2017 14:02:55 +0100 Subject: [PATCH 6/8] kpatch-build: Stop reading vmlinux after the first match When searching for 'Linux version ...' in vmlinux, stop after the first match so that we don't keep reading a potentially huge file. Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 297c4ae07..dec75edcb 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -481,7 +481,7 @@ if [[ -n "$USERSRCDIR" ]]; then [[ ! -e "$VMLINUX" ]] && die "can't find vmlinux" # Extract the target kernel version from vmlinux in this case. - ARCHVERSION="$(strings "$VMLINUX" | grep -e "^Linux version" | awk '{ print($3); }')" + ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')" fi [[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)" From b2c00b121583d99b3c0586bc0f09baddf4e3d919 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Tue, 7 Nov 2017 16:23:17 +0100 Subject: [PATCH 7/8] kpatch-build: Add a flexible logger function Add a logger funcition that can be used to log to both stdout and the logfile or only to the logfile. This is needed for subsequent patches where we introduce an alternate debug mode. Since we're piping to a logger now, we need to set 'pipefail' otherwise the return status of such a pipeline is always 0 (the exit status of the logger) and we won't catch any errors. From the bash manpage: The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 50 +++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index dec75edcb..0fdea6eda 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -34,6 +34,8 @@ # - Builds the patched objects with gcc flags -f[function|data]-sections # - Runs kpatch tools to create and link the patch kernel module +set -o pipefail + BASE="$PWD" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")" ARCH="$(uname -m)" @@ -71,12 +73,24 @@ die() { exit 1 } +logger() { + local to_stdout=${1:-0} + + if [[ "$to_stdout" -eq 1 ]]; then + # Log to both stdout and the logfile + tee -a "$LOGFILE" + else + # Log only to the logfile + cat >> "$LOGFILE" + fi +} + apply_patches() { local patch for patch in "${PATCH_LIST[@]}"; do - patch -N -p1 --dry-run < "$patch" >> "$LOGFILE" 2>&1 || die "$patch file failed to apply" - patch -N -p1 < "$patch" >> "$LOGFILE" 2>&1 || die "$patch file failed to apply" + patch -N -p1 --dry-run < "$patch" 2>&1 | logger || die "$patch file failed to apply" + patch -N -p1 < "$patch" 2>&1 | logger || die "$patch file failed to apply" (( APPLIED_PATCHES++ )) done } @@ -364,7 +378,8 @@ usage() { echo " -t, --target Specify custom kernel build targets" >&2 echo " -n, --name Specify the name of the kpatch module" >&2 echo " -o, --output Specify output folder" >&2 - echo " -d, --debug Keep scratch files in /tmp" >&2 + echo " -d, --debug Enable 'xtrace' and keep scratch files" >&2 + echo " in /tmp" >&2 echo " --skip-cleanup Skip post-build cleanup" >&2 echo " --skip-gcc-check Skip gcc version matching check" >&2 echo " (not recommended)" >&2 @@ -545,21 +560,21 @@ else echo "Downloading kernel source for $ARCHVERSION" if [[ -z "$SRCRPM" ]]; then if [[ "$DISTRO" = fedora ]]; then - wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" >> "$LOGFILE" 2>&1 || die + wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die else rpm -q --quiet yum-utils || die "yum-utils not installed" - yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" >> "$LOGFILE" 2>&1 || die + yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" 2>&1 | logger || die fi SRCRPM="$TEMPDIR/kernel-$KVER-$KREL.src.rpm" fi echo "Unpacking kernel source" - rpm -D "_topdir $RPMTOPDIR" -ivh "$SRCRPM" >> "$LOGFILE" 2>&1 || die - rpmbuild -D "_topdir $RPMTOPDIR" -bp "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel.spec >> "$LOGFILE" 2>&1 || + rpm -D "_topdir $RPMTOPDIR" -ivh "$SRCRPM" 2>&1 | logger || die + rpmbuild -D "_topdir $RPMTOPDIR" -bp "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel.spec 2>&1 | logger || die "rpmbuild -bp failed. you may need to run 'yum-builddep kernel' first." - mv "$RPMTOPDIR"/BUILD/kernel-*/linux-"${ARCHVERSION%.*}"*"${ARCHVERSION##*.}" "$SRCDIR" >> "$LOGFILE" 2>&1 || die + mv "$RPMTOPDIR"/BUILD/kernel-*/linux-"${ARCHVERSION%.*}"*"${ARCHVERSION##*.}" "$SRCDIR" 2>&1 | logger || die rm -rf "$RPMTOPDIR" rm -rf "$SRCDIR/.git" @@ -596,7 +611,7 @@ else cd "$TEMPDIR" || die echo "Downloading and unpacking the kernel source for $ARCHVERSION" # Download source deb pkg - (dget -u "$url/${pkgname}/${dscname}" 2>&1) >> "$LOGFILE" || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}" + (dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}" mv "${pkgname}-$KVER" "$SRCDIR" || die cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die if [[ "$ARCHVERSION" == *-* ]]; then @@ -668,12 +683,12 @@ find_special_section_data echo "Building original kernel" ./scripts/setlocalversion --save-scmversion || die -make mrproper >> "$LOGFILE" 2>&1 || die +make mrproper 2>&1 | logger || die cp -f "$CONFIGFILE" "$SRCDIR/.config" unset KPATCH_GCC_TEMPDIR # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 -CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1 || die +CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die echo "Building patched kernel" apply_patches @@ -684,8 +699,7 @@ export KPATCH_GCC_TEMPDIR # shellcheck disable=SC2086 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ KBUILD_MODPOST_WARN=1 \ - make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1 || die -[[ "${PIPESTATUS[0]}" -eq 0 ]] || die + make "-j$CPUS" $TARGETS 2>&1 | logger || die grep "undefined reference" "$LOGFILE" | grep -qv kpatch_shadow && die grep "undefined!" "$LOGFILE" | grep -qv kpatch_shadow && die @@ -751,7 +765,7 @@ for i in $FILES; do if [[ -e "orig/$i" ]]; then # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ - "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | tee -a "$LOGFILE" + "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 check_pipe_status create-diff-object # create-diff-object returns 3 if no functional change is found [[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$((ERROR + 1))" @@ -798,14 +812,14 @@ 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") >> "$LOGFILE" 2>&1 || die +ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die if "$KPATCH_MODULE"; then # Add .kpatch.checksum for kpatch script md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die rm -f checksum.tmp - "$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | tee -a "$LOGFILE" + "$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1 check_pipe_status create-kpatch-module else cp "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die @@ -816,14 +830,14 @@ cd "$TEMPDIR/patch" || die KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ - make >> "$LOGFILE" 2>&1 || die + make 2>&1 | logger || die if ! "$KPATCH_MODULE"; then if [[ -z "$KPATCH_LDFLAGS" ]]; then extra_flags="--no-klp-arch-sections" fi cp "$TEMPDIR/patch/$MODNAME.ko" "$TEMPDIR/patch/tmp.ko" || die - "$TOOLSDIR"/create-klp-module $extra_flags "$TEMPDIR/patch/tmp.ko" "$TEMPDIR/patch/$MODNAME.ko" 2>&1 | tee -a "$LOGFILE" + "$TOOLSDIR"/create-klp-module $extra_flags "$TEMPDIR/patch/tmp.ko" "$TEMPDIR/patch/$MODNAME.ko" 2>&1 | logger 1 check_pipe_status create-klp-module fi From 757bc71d2b76b2ed74a01a71ab55df9d78445647 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Thu, 16 Nov 2017 13:38:22 +0100 Subject: [PATCH 8/8] kpatch-build: Add additional debug modes By specifying -d, --debug multiple times, the following additional debug modes can be enabled: -d -d: Writes everything that is written to the logfile also to stdout. -d -d -d: Same as '-d -d' plus sets 'xtrace' in kpatch-build. -d -d -d -d: Same as '-d -d -d' plus sets 'xtrace' in kpatch-gcc. Signed-off-by: Juerg Haefliger --- kpatch-build/kpatch-build | 18 ++++++++++++++---- kpatch-build/kpatch-gcc | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 0fdea6eda..166ecbd60 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -76,7 +76,7 @@ die() { logger() { local to_stdout=${1:-0} - if [[ "$to_stdout" -eq 1 ]]; then + if [[ $DEBUG -ge 2 ]] || [[ "$to_stdout" -eq 1 ]]; then # Log to both stdout and the logfile tee -a "$LOGFILE" else @@ -380,6 +380,7 @@ usage() { echo " -o, --output Specify output folder" >&2 echo " -d, --debug Enable 'xtrace' and keep scratch files" >&2 echo " in /tmp" >&2 + echo " (can be specified multiple times)" >&2 echo " --skip-cleanup Skip post-build cleanup" >&2 echo " --skip-gcc-check Skip gcc version matching check" >&2 echo " (not recommended)" >&2 @@ -438,9 +439,10 @@ while [[ $# -gt 0 ]]; do shift ;; -d|--debug) - echo "DEBUG mode enabled" - DEBUG=1 - set -o xtrace + DEBUG=$((DEBUG + 1)) + if [[ $DEBUG -eq 1 ]]; then + echo "DEBUG mode enabled" + fi ;; --skip-cleanup) echo "Skipping cleanup" @@ -465,6 +467,10 @@ if [[ ${#PATCH_LIST[@]} -eq 0 ]]; then exit 1 fi +if [[ $DEBUG -eq 1 ]] || [[ $DEBUG -ge 3 ]]; then + set -o xtrace +fi + if [[ -n "$ARCHVERSION" ]] && [[ -n "$VMLINUX" ]]; then warn "--archversion is incompatible with --vmlinux" exit 1 @@ -681,6 +687,10 @@ export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLA echo "Reading special section data" find_special_section_data +if [[ $DEBUG -ge 4 ]]; then + export KPATCH_GCC_DEBUG=1 +fi + echo "Building original kernel" ./scripts/setlocalversion --save-scmversion || die make mrproper 2>&1 | logger || die diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc index 72dc51d9b..6ba133cd2 100755 --- a/kpatch-build/kpatch-gcc +++ b/kpatch-build/kpatch-gcc @@ -1,6 +1,8 @@ #!/bin/bash -set -x +if [[ ${KPATCH_GCC_DEBUG:-0} -ne 0 ]]; then + set -o xtrace +fi TOOLCHAINCMD="$1" shift