mirror of
https://github.com/dynup/kpatch
synced 2025-01-03 11:12:01 +00:00
kpatch-build: clang support
Add support for clang-built kernels. This is completely automatic, we check if the kernel was built with clang by looking for CONFIG_CC_IS_CLANG in config. This has almost no effect on non-clang built kernels with one exception: we now do compliler checks _after_ we download kernel sources which is a waste of resources in case when compilers don't match. Signed-off-by: Artem Savkov <asavkov@redhat.com>
This commit is contained in:
parent
2af31916ce
commit
41de9e763a
2
Makefile
2
Makefile
@ -62,7 +62,7 @@ vagrant-integration-quick:
|
|||||||
$(MAKE) -C $(INTEGRATION_DIR) vagrant-quick
|
$(MAKE) -C $(INTEGRATION_DIR) vagrant-quick
|
||||||
|
|
||||||
check:
|
check:
|
||||||
shellcheck kpatch/kpatch kpatch-build/kpatch-build kpatch-build/kpatch-gcc
|
shellcheck kpatch/kpatch kpatch-build/kpatch-build kpatch-build/kpatch-cc
|
||||||
shellcheck test/difftree.sh test/integration/kpatch-test \
|
shellcheck test/difftree.sh test/integration/kpatch-test \
|
||||||
test/integration/lib.sh test/integration/rebase-patches \
|
test/integration/lib.sh test/integration/rebase-patches \
|
||||||
test/integration/test-vagrant \
|
test/integration/test-vagrant \
|
||||||
|
@ -40,7 +40,7 @@ $(PLUGIN): gcc-plugins/ppc64le-plugin.c
|
|||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(INSTALL) -d $(LIBEXECDIR)
|
$(INSTALL) -d $(LIBEXECDIR)
|
||||||
$(INSTALL) $(TARGETS) kpatch-gcc $(LIBEXECDIR)
|
$(INSTALL) $(TARGETS) kpatch-cc $(LIBEXECDIR)
|
||||||
$(INSTALL) -d $(BINDIR)
|
$(INSTALL) -d $(BINDIR)
|
||||||
$(INSTALL) kpatch-build $(BINDIR)
|
$(INSTALL) kpatch-build $(BINDIR)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ LOGFILE="$CACHEDIR/build.log"
|
|||||||
RELEASE_FILE=/etc/os-release
|
RELEASE_FILE=/etc/os-release
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
SKIPCLEANUP=0
|
SKIPCLEANUP=0
|
||||||
SKIPGCCCHECK=0
|
SKIPCOMPILERCHECK=0
|
||||||
ARCH_KCFLAGS=""
|
ARCH_KCFLAGS=""
|
||||||
DEBUG_KCFLAGS=""
|
DEBUG_KCFLAGS=""
|
||||||
declare -a PATCH_LIST
|
declare -a PATCH_LIST
|
||||||
@ -219,10 +219,11 @@ find_core_symvers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gcc_version_from_file() {
|
gcc_version_from_file() {
|
||||||
readelf -p .comment "$1" | grep -o 'GCC:.*' | head -n 1
|
readelf -p .comment "$1" | grep -m 1 -o 'GCC:.*'
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_version_check() {
|
gcc_version_check() {
|
||||||
|
local target="$1"
|
||||||
local c="$TEMPDIR/test.c" o="$TEMPDIR/test.o"
|
local c="$TEMPDIR/test.c" o="$TEMPDIR/test.o"
|
||||||
local out gccver kgccver
|
local out gccver kgccver
|
||||||
|
|
||||||
@ -231,11 +232,7 @@ gcc_version_check() {
|
|||||||
echo 'void main(void) {}' > "$c"
|
echo 'void main(void) {}' > "$c"
|
||||||
out="$(gcc -c -pg -ffunction-sections -o "$o" "$c" 2>&1)"
|
out="$(gcc -c -pg -ffunction-sections -o "$o" "$c" 2>&1)"
|
||||||
gccver="$(gcc_version_from_file "$o")"
|
gccver="$(gcc_version_from_file "$o")"
|
||||||
if [[ -n "$OOT_MODULE" ]]; then
|
kgccver="$(gcc_version_from_file "$target")"
|
||||||
kgccver="$(gcc_version_from_file "$OOT_MODULE")"
|
|
||||||
else
|
|
||||||
kgccver="$(gcc_version_from_file "$VMLINUX")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$out" ]]; then
|
if [[ -n "$out" ]]; then
|
||||||
warn "gcc >= 4.8 required for -pg -ffunction-settings"
|
warn "gcc >= 4.8 required for -pg -ffunction-settings"
|
||||||
@ -254,7 +251,31 @@ gcc_version_check() {
|
|||||||
warn "gcc/kernel version mismatch"
|
warn "gcc/kernel version mismatch"
|
||||||
echo "gcc version: $gccver"
|
echo "gcc version: $gccver"
|
||||||
echo "kernel version: $kgccver"
|
echo "kernel version: $kgccver"
|
||||||
echo "Install the matching gcc version (recommended) or use --skip-gcc-check"
|
echo "Install the matching gcc version (recommended) or use --skip-compiler-check"
|
||||||
|
echo "to skip the version matching enforcement (not recommended)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clang_version_from_file() {
|
||||||
|
readelf -p .comment "$1" | grep -m 1 -Eo 'clang version [0-9.]+'
|
||||||
|
}
|
||||||
|
|
||||||
|
clang_version_check() {
|
||||||
|
local target="$1"
|
||||||
|
local clangver kclangver
|
||||||
|
|
||||||
|
clangver=$(clang --version | grep -m 1 -Eo 'clang version [0-9.]+')
|
||||||
|
kclangver="$(clang_version_from_file "$target")"
|
||||||
|
|
||||||
|
# ensure clang version matches that used to build the kernel
|
||||||
|
if [[ "$clangver" != "$kclangver" ]]; then
|
||||||
|
warn "clang/kernel version mismatch"
|
||||||
|
echo "clang version: $clangver"
|
||||||
|
echo "kernel version: $kclangver"
|
||||||
|
echo "Install the matching clang version (recommended) or use --skip-compiler-check"
|
||||||
echo "to skip the version matching enforcement (not recommended)"
|
echo "to skip the version matching enforcement (not recommended)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -456,11 +477,11 @@ usage() {
|
|||||||
echo " -e, --oot-module Enable patching out-of-tree module," >&2
|
echo " -e, --oot-module Enable patching out-of-tree module," >&2
|
||||||
echo " specify current version of module" >&2
|
echo " specify current version of module" >&2
|
||||||
echo " --skip-cleanup Skip post-build cleanup" >&2
|
echo " --skip-cleanup Skip post-build cleanup" >&2
|
||||||
echo " --skip-gcc-check Skip gcc version matching check" >&2
|
echo " --skip-compiler-check Skip compiler version matching check" >&2
|
||||||
echo " (not recommended)" >&2
|
echo " (not recommended)" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
|
options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup" -- "$@")" || die "getopt failed"
|
||||||
|
|
||||||
eval set -- "$options"
|
eval set -- "$options"
|
||||||
|
|
||||||
@ -528,8 +549,11 @@ while [[ $# -gt 0 ]]; do
|
|||||||
SKIPCLEANUP=1
|
SKIPCLEANUP=1
|
||||||
;;
|
;;
|
||||||
--skip-gcc-check)
|
--skip-gcc-check)
|
||||||
echo "WARNING: Skipping gcc version matching check (not recommended)"
|
echo "DEPRECATED: --skip-gcc-check is deprecated, use --skip-compiler-check instead"
|
||||||
SKIPGCCCHECK=1
|
;&
|
||||||
|
--skip-compiler-check)
|
||||||
|
echo "WARNING: Skipping compiler version matching check (not recommended)"
|
||||||
|
SKIPCOMPILERCHECK=1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
[[ "$1" = "--" ]] && shift && continue
|
[[ "$1" = "--" ]] && shift && continue
|
||||||
@ -631,10 +655,6 @@ fi
|
|||||||
|
|
||||||
find_dirs || die "can't find supporting tools"
|
find_dirs || die "can't find supporting tools"
|
||||||
|
|
||||||
if [[ "$SKIPGCCCHECK" -eq 0 ]]; then
|
|
||||||
gcc_version_check || die
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$USERSRCDIR" ]]; then
|
if [[ -n "$USERSRCDIR" ]]; then
|
||||||
echo "Using source directory at $USERSRCDIR"
|
echo "Using source directory at $USERSRCDIR"
|
||||||
|
|
||||||
@ -751,6 +771,8 @@ CONFIG_PARAVIRT=0
|
|||||||
CONFIG_UNWINDER_ORC=0
|
CONFIG_UNWINDER_ORC=0
|
||||||
CONFIG_JUMP_LABEL=0
|
CONFIG_JUMP_LABEL=0
|
||||||
CONFIG_MODVERSIONS=0
|
CONFIG_MODVERSIONS=0
|
||||||
|
CONFIG_CC_IS_CLANG=0
|
||||||
|
CONFIG_LD_IS_LLD=0
|
||||||
|
|
||||||
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE" && (kernel_is_rhel || kernel_version_gte 4.9.0); then
|
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE" && (kernel_is_rhel || kernel_version_gte 4.9.0); then
|
||||||
|
|
||||||
@ -777,6 +799,8 @@ grep -q "CONFIG_PARAVIRT=y" "$CONFIGFILE" && CONFIG_PARAVIRT=1
|
|||||||
grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE" && CONFIG_UNWINDER_ORC=1
|
grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE" && CONFIG_UNWINDER_ORC=1
|
||||||
grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE" && CONFIG_JUMP_LABEL=1
|
grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE" && CONFIG_JUMP_LABEL=1
|
||||||
grep -q "CONFIG_MODVERSIONS=y" "$CONFIGFILE" && CONFIG_MODVERSIONS=1
|
grep -q "CONFIG_MODVERSIONS=y" "$CONFIGFILE" && CONFIG_MODVERSIONS=1
|
||||||
|
grep -q "CONFIG_CC_IS_CLANG=y" "$CONFIGFILE" && CONFIG_CC_IS_CLANG=1
|
||||||
|
grep -q "CONFIG_LD_IS_LLD=y" "$CONFIGFILE" && CONFIG_LD_IS_LLD=1
|
||||||
|
|
||||||
# unsupported kernel option checking
|
# unsupported kernel option checking
|
||||||
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
|
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
|
||||||
@ -791,6 +815,23 @@ if grep -q "CONFIG_DEBUG_INFO_BTF=y" "$CONFIGFILE" ; then
|
|||||||
sed -i 's/CONFIG_DEBUG_INFO_BTF/DISABLED_FOR_KPATCH_BUILD/g' "$SRCDIR"/scripts/link-vmlinux.sh || die
|
sed -i 's/CONFIG_DEBUG_INFO_BTF/DISABLED_FOR_KPATCH_BUILD/g' "$SRCDIR"/scripts/link-vmlinux.sh || die
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$CONFIG_CC_IS_CLANG" -eq 1 ]]; then
|
||||||
|
echo "WARNING: Clang support is experimental"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then
|
||||||
|
if [[ -n "$OOT_MODULE" ]]; then
|
||||||
|
target="$OOT_MODULE"
|
||||||
|
else
|
||||||
|
target="$VMLINUX"
|
||||||
|
fi
|
||||||
|
if [[ "$CONFIG_CC_IS_CLANG" -eq 0 ]]; then
|
||||||
|
gcc_version_check "$target" || die
|
||||||
|
else
|
||||||
|
clang_version_check "$target" || die
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Testing patch file(s)"
|
echo "Testing patch file(s)"
|
||||||
cd "$SRCDIR" || die
|
cd "$SRCDIR" || die
|
||||||
verify_patch_files
|
verify_patch_files
|
||||||
@ -816,9 +857,27 @@ fi
|
|||||||
echo "Building original source"
|
echo "Building original source"
|
||||||
[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die
|
[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die
|
||||||
unset KPATCH_GCC_TEMPDIR
|
unset KPATCH_GCC_TEMPDIR
|
||||||
|
|
||||||
|
KPATCH_CC_PREFIX="$TOOLSDIR/kpatch-cc "
|
||||||
|
declare -a MAKEVARS
|
||||||
|
if [ "$CONFIG_CC_IS_CLANG" -eq 1 ]; then
|
||||||
|
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}clang")
|
||||||
|
MAKEVARS+=("HOSTCC=clang")
|
||||||
|
else
|
||||||
|
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}gcc")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CONFIG_LD_IS_LLD" -eq 1 ]; then
|
||||||
|
MAKEVARS+=("LD=${KPATCH_CC_PREFIX}ld.lld")
|
||||||
|
MAKEVARS+=("HOSTLD=ld.lld")
|
||||||
|
else
|
||||||
|
MAKEVARS+=("LD=${KPATCH_CC_PREFIX}ld")
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# $TARGETS used as list, no quotes.
|
# $TARGETS used as list, no quotes.
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
|
make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
|
||||||
|
|
||||||
# Save original module symvers
|
# Save original module symvers
|
||||||
cp -f "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers" || die
|
cp -f "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers" || die
|
||||||
@ -832,9 +891,7 @@ KPATCH_GCC_SRCDIR="$SRCDIR"
|
|||||||
export KPATCH_GCC_SRCDIR
|
export KPATCH_GCC_SRCDIR
|
||||||
# $TARGETS used as list, no quotes.
|
# $TARGETS used as list, no quotes.
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
|
KBUILD_MODPOST_WARN=1 make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
|
||||||
KBUILD_MODPOST_WARN=1 \
|
|
||||||
make "-j$CPUS" $TARGETS 2>&1 | logger || die
|
|
||||||
|
|
||||||
# source.c:(.section+0xFF): undefined reference to `symbol'
|
# source.c:(.section+0xFF): undefined reference to `symbol'
|
||||||
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
|
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
|
||||||
@ -1026,10 +1083,16 @@ if [[ -z "$OOT_MODULE" ]]; then
|
|||||||
else
|
else
|
||||||
KPATCH_BUILD="/lib/modules/$ARCHVERSION/build"
|
KPATCH_BUILD="/lib/modules/$ARCHVERSION/build"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# We no longer need kpatch-cc
|
||||||
|
for ((idx=0; idx<${#MAKEVARS[@]}; idx++)); do
|
||||||
|
MAKEVARS[$idx]=${MAKEVARS[$idx]/${KPATCH_CC_PREFIX}/}
|
||||||
|
done
|
||||||
|
|
||||||
KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
|
KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
|
||||||
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
|
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
|
||||||
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
|
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
|
||||||
make 2>&1 | logger || die
|
make "${MAKEVARS[@]}" 2>&1 | logger || die
|
||||||
|
|
||||||
if [[ "$USE_KLP" -eq 1 ]]; then
|
if [[ "$USE_KLP" -eq 1 ]]; then
|
||||||
if [[ "$USE_KLP_ARCH" -eq 0 ]]; then
|
if [[ "$USE_KLP_ARCH" -eq 0 ]]; then
|
||||||
|
@ -13,7 +13,7 @@ fi
|
|||||||
|
|
||||||
declare -a args=("$@")
|
declare -a args=("$@")
|
||||||
|
|
||||||
if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
|
if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; then
|
||||||
while [ "$#" -gt 0 ]; do
|
while [ "$#" -gt 0 ]; do
|
||||||
if [ "$1" = "-o" ]; then
|
if [ "$1" = "-o" ]; then
|
||||||
obj="$2"
|
obj="$2"
|
||||||
@ -61,7 +61,7 @@ if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
|
|||||||
fi
|
fi
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
|
elif [[ "$TOOLCHAINCMD" =~ ^(.*-)?ld || "$TOOLCHAINCMD" =~ ^(.*-)?ld.lld ]] ; then
|
||||||
while [ "$#" -gt 0 ]; do
|
while [ "$#" -gt 0 ]; do
|
||||||
if [ "$1" = "-o" ]; then
|
if [ "$1" = "-o" ]; then
|
||||||
obj="$2"
|
obj="$2"
|
@ -54,12 +54,12 @@ effect.
|
|||||||
--skip-cleanup
|
--skip-cleanup
|
||||||
Skip post-build cleanup
|
Skip post-build cleanup
|
||||||
|
|
||||||
--skip-gcc-check
|
--skip-compiler-check
|
||||||
Skips check that ensures that the system gcc version and
|
Skips check that ensures that the system compiler version and
|
||||||
the gcc version that built the kernel match. Skipping this
|
the compiler version that built the kernel match. Skipping this
|
||||||
check is not recommended, but is useful if the exact gcc
|
check is not recommended, but is useful if the exact compiler
|
||||||
version is not available or is not easily installed. Use
|
version is not available or is not easily installed. Use
|
||||||
only when confident that the two versions of gcc output
|
only when confident that the two versions of compiler output
|
||||||
identical objects for a given target. Otherwise, use of
|
identical objects for a given target. Otherwise, use of
|
||||||
this option might result in unexpected changed objects
|
this option might result in unexpected changed objects
|
||||||
being detected.
|
being detected.
|
||||||
|
Loading…
Reference in New Issue
Block a user