mirror of
https://github.com/dynup/kpatch
synced 2024-12-28 00:02:02 +00:00
kpatch-build: build the kernel in ~/.kpatch/src again
Once upon a time, kpatch-build did the kernel build in three passes. The extra pass was done without '-ffunction-sections -fdata-sections', so it could produce the original vmlinux file. At that time, there was no ~/.kpatch/obj directory. The kernel was built directly in ~/.kpatch/src. Because the same directory was used for both the original kernel build and the '-ffunction-sections -fdata-sections' build, the entire tree had to be rebuilt twice for every kpatch-build incantation, making it very slow. That situation was improved with the following commit:5352d8b01a
("build objects in separate directory to fix caching") That built the regular and special binaries in ~/.kpatch/obj and ~/.kpatch/obj2, respectively. Since then we've simplified things so that it only does two build passes: original and patched, both with '-ffunction-sections -fdata-sections', and ~/.kpatch/obj2 was removed. However, ~/.kpatch/obj still remained. That's because we never had a reason to change it, until now. Recent commitaa2907df29
("support dup file+symbol") triggers a new warning: create-diff-object: ERROR: dynamic_debug.o: find_local_syms: 124: find_local_syms for dynamic_debug.c: found_none This was actually a preexisting issue which that commit helped uncover. The root issue is that dynamic_debug.c has some creative uses of the `__FILE__` macro. When building the kernel objects outside the source tree, the macro results in a absolute path like: /home/jpoimboe/.kpatch/src/lib/dynamic_debug.c But when building inside the source tree it's a relative path: lib/dynamic_debug.c The Fedora kernel is built in-tree, and I would imagine most other distros are also built that way. So the way kpatch builds can result in a slightly different 'original' object than the distro version, thanks to the __FILE__ macro. In this case, the order of the symbol table changed slightly between vmlinux and the 'orig' object. Presumably, the difference in string lengths was enough to convince the compiler to shuffle things around a bit. So considering that bug, and the possibility of other mismatches, go back to building the kernel in the source tree.
This commit is contained in:
parent
4779b9c0d8
commit
2e99d6b7a4
@ -40,7 +40,6 @@ ARCHVERSION="$(uname -r)"
|
||||
CPUS="$(getconf _NPROCESSORS_ONLN)"
|
||||
CACHEDIR="${CACHEDIR:-$HOME/.kpatch}"
|
||||
SRCDIR="$CACHEDIR/src"
|
||||
OBJDIR="$CACHEDIR/obj"
|
||||
RPMTOPDIR="$CACHEDIR/buildroot"
|
||||
VERSIONFILE="$CACHEDIR/version"
|
||||
TEMPDIR="$CACHEDIR/tmp"
|
||||
@ -79,12 +78,11 @@ cleanup() {
|
||||
# we've reverted our patch above.
|
||||
[[ -d $SRCDIR/.git ]] && (cd $SRCDIR && git update-index -q --refresh)
|
||||
fi
|
||||
if [[ -n $USERSRCDIR ]]; then
|
||||
# restore original .config and vmlinux since they were removed
|
||||
# with mrproper
|
||||
[[ -e $TEMPDIR/vmlinux ]] && cp -f $TEMPDIR/vmlinux $USERSRCDIR
|
||||
[[ -e $TEMPDIR/.config ]] && cp -f $TEMPDIR/.config $USERSRCDIR
|
||||
fi
|
||||
|
||||
# restore original .config and vmlinux if they were removed with mrproper
|
||||
[[ -e $TEMPDIR/.config ]] && mv -f $TEMPDIR/.config $SRCDIR/
|
||||
[[ -e $TEMPDIR/vmlinux ]] && mv -f $TEMPDIR/vmlinux $SRCDIR/
|
||||
|
||||
[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
|
||||
rm -rf "$RPMTOPDIR"
|
||||
unset KCFLAGS
|
||||
@ -93,8 +91,7 @@ cleanup() {
|
||||
|
||||
clean_cache() {
|
||||
[[ -z $USERSRCDIR ]] && rm -rf "$SRCDIR"
|
||||
rm -rf "$OBJDIR" "$VERSIONFILE"
|
||||
mkdir -p "$OBJDIR"
|
||||
rm -rf "$VERSIONFILE"
|
||||
}
|
||||
|
||||
check_pipe_status() {
|
||||
@ -319,24 +316,18 @@ mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
|
||||
rm -rf "$TEMPDIR"/*
|
||||
rm -f "$LOGFILE"
|
||||
|
||||
[[ $SKIPCLEANUP -eq 0 ]] && trap cleanup EXIT INT TERM HUP
|
||||
|
||||
if [[ -n $USERSRCDIR ]]; then
|
||||
# save .config and vmlinux since they'll get removed with mrproper so
|
||||
# we can restore them later and be able to run kpatch-build multiple
|
||||
# times on the same sourcedir
|
||||
[[ -z $CONFIGFILE ]] && CONFIGFILE="$USERSRCDIR"/.config
|
||||
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
|
||||
[[ "$CONFIGFILE" = "$USERSRCDIR"/.config ]] && cp -f "$CONFIGFILE" $TEMPDIR
|
||||
SRCDIR="$USERSRCDIR"
|
||||
|
||||
[[ -z $VMLINUX ]] && VMLINUX="$USERSRCDIR"/vmlinux
|
||||
[[ -z $VMLINUX ]] && VMLINUX="$SRCDIR"/vmlinux
|
||||
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
|
||||
[[ "$VMLINUX" = "$USERSRCDIR"/vmlinux ]] && cp -f "$VMLINUX" $TEMPDIR/vmlinux && VMLINUX=$TEMPDIR/vmlinux
|
||||
|
||||
# Extract the target kernel version from vmlinux in this case.
|
||||
ARCHVERSION=$(strings "$VMLINUX" | grep -e "^Linux version" | awk '{ print($3); }')
|
||||
fi
|
||||
|
||||
[[ $SKIPCLEANUP -eq 0 ]] && trap cleanup EXIT INT TERM HUP
|
||||
|
||||
KVER=${ARCHVERSION%%-*}
|
||||
if [[ $ARCHVERSION =~ - ]]; then
|
||||
KREL=${ARCHVERSION##*-}
|
||||
@ -384,13 +375,13 @@ fi
|
||||
|
||||
if [[ -n "$USERSRCDIR" ]]; then
|
||||
echo "Using source directory at $USERSRCDIR"
|
||||
SRCDIR="$USERSRCDIR"
|
||||
|
||||
clean_cache
|
||||
|
||||
cp -f "$CONFIGFILE" "$OBJDIR/.config"
|
||||
# save vmlinux before it gets removed with mrproper
|
||||
[[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" $TEMPDIR/vmlinux && VMLINUX=$TEMPDIR/vmlinux
|
||||
|
||||
elif [[ -e "$SRCDIR" ]] && [[ -e "$VERSIONFILE" ]] && [[ $(cat "$VERSIONFILE") = $ARCHVERSION ]]; then
|
||||
elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ $(cat "$VERSIONFILE") = $ARCHVERSION ]]; then
|
||||
echo "Using cache at $SRCDIR"
|
||||
|
||||
else
|
||||
@ -422,7 +413,6 @@ else
|
||||
rm -rf "$RPMTOPDIR"
|
||||
rm -rf "$SRCDIR/.git"
|
||||
|
||||
cp "$SRCDIR/.config" "$OBJDIR" || die
|
||||
if [[ "$ARCHVERSION" == *-* ]]; then
|
||||
echo "-${ARCHVERSION##*-}" > "$SRCDIR/localversion" || die
|
||||
fi
|
||||
@ -468,7 +458,7 @@ else
|
||||
tar $taroptions usr/src/linux-source-$KVER.tar.${extension} >> "$LOGFILE" || die "tar: Failed to extract kernel source package"
|
||||
clean_cache
|
||||
mv linux-source-$KVER "$SRCDIR" || die
|
||||
cp "/boot/config-${ARCHVERSION}" "$OBJDIR/.config" || die
|
||||
cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die
|
||||
if [[ "$ARCHVERSION" == *-* ]]; then
|
||||
echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
|
||||
fi
|
||||
@ -482,6 +472,11 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# save .config before it gets removed with mrproper
|
||||
[[ -z $CONFIGFILE ]] && CONFIGFILE="$SRCDIR"/.config
|
||||
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
|
||||
[[ "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" $TEMPDIR && CONFIGFILE="$TEMPDIR"/.config
|
||||
|
||||
# Build variables - Set some defaults, then adjust features
|
||||
# according to .config and kernel version
|
||||
KBUILD_EXTRA_SYMBOLS=""
|
||||
@ -489,8 +484,8 @@ KPATCH_LDFLAGS=""
|
||||
KPATCH_MODULE=true
|
||||
|
||||
# kernel option checking: CONFIG_DEBUG_KERNEL and CONFIG_LIVEPATCH
|
||||
grep -q "CONFIG_DEBUG_KERNEL=y" "$OBJDIR/.config" || die "kernel doesn't have 'CONFIG_DEBUG_KERNEL' enabled"
|
||||
if grep "CONFIG_LIVEPATCH=y" "$OBJDIR/.config" > /dev/null; then
|
||||
grep -q "CONFIG_DEBUG_KERNEL=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_KERNEL' enabled"
|
||||
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then
|
||||
# The kernel supports livepatch.
|
||||
if version_gte ${ARCHVERSION//-*/} 4.7.0; then
|
||||
# Use new .klp.rela. sections
|
||||
@ -506,14 +501,14 @@ else
|
||||
fi
|
||||
|
||||
# optional kernel configs: CONFIG_PARAVIRT
|
||||
if grep "CONFIG_PARAVIRT=y" "$OBJDIR/.config" > /dev/null; then
|
||||
if grep -q "CONFIG_PARAVIRT=y" "$CONFIGFILE"; then
|
||||
CONFIG_PARAVIRT=1
|
||||
else
|
||||
CONFIG_PARAVIRT=0
|
||||
fi
|
||||
|
||||
# unsupported kernel option checking: CONFIG_DEBUG_INFO_SPLIT
|
||||
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$OBJDIR/.config" && 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"
|
||||
|
||||
echo "Testing patch file"
|
||||
cd "$SRCDIR" || die
|
||||
@ -565,8 +560,9 @@ done
|
||||
echo "Building original kernel"
|
||||
./scripts/setlocalversion --save-scmversion || die
|
||||
make mrproper >> "$LOGFILE" 2>&1 || die
|
||||
cp -f "$CONFIGFILE" "$SRCDIR/.config"
|
||||
unset KPATCH_GCC_TEMPDIR
|
||||
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
|
||||
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1 || die
|
||||
|
||||
echo "Building patched kernel"
|
||||
patch -N -p1 < "$APPLIEDPATCHFILE" >> "$LOGFILE" 2>&1 || die
|
||||
@ -575,7 +571,7 @@ KPATCH_GCC_TEMPDIR=$TEMPDIR
|
||||
export KPATCH_GCC_TEMPDIR
|
||||
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
|
||||
KBUILD_MODPOST_WARN=1 \
|
||||
make "-j$CPUS" $TARGETS "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
|
||||
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
|
||||
@ -587,7 +583,7 @@ fi
|
||||
for i in $(cat "$TEMPDIR/changed_objs")
|
||||
do
|
||||
mkdir -p "$TEMPDIR/patched/$(dirname $i)" || die
|
||||
cp -f "$OBJDIR/$i" "$TEMPDIR/patched/$i" || die
|
||||
cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
|
||||
done
|
||||
|
||||
echo "Extracting new and modified ELF sections"
|
||||
@ -607,7 +603,7 @@ for i in $FILES; do
|
||||
[[ $i = usr/initramfs_data.o ]] && continue
|
||||
|
||||
mkdir -p "output/$(dirname $i)"
|
||||
cd "$OBJDIR"
|
||||
cd "$SRCDIR"
|
||||
find_kobj $i
|
||||
if [[ $KOBJFILE = vmlinux ]]; then
|
||||
KOBJFILE=$VMLINUX
|
||||
@ -618,7 +614,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" "$OBJDIR/Module.symvers" "kpatch_${PATCHNAME//-/_}" 2>&1 |tee -a "$LOGFILE"
|
||||
"output/$i" "$SRCDIR/Module.symvers" "kpatch_${PATCHNAME//-/_}" 2>&1 |tee -a "$LOGFILE"
|
||||
check_pipe_status create-diff-object
|
||||
# create-diff-object returns 3 if no functional change is found
|
||||
[[ $rc -eq 0 ]] || [[ $rc -eq 3 ]] || ERROR=$(expr $ERROR "+" 1)
|
||||
@ -654,7 +650,6 @@ if $KPATCH_MODULE; then
|
||||
fi
|
||||
|
||||
echo "Building patch module: kpatch-$PATCHNAME.ko"
|
||||
cp "$OBJDIR/.config" "$SRCDIR"
|
||||
cd "$SRCDIR"
|
||||
make prepare >> "$LOGFILE" 2>&1 || die
|
||||
|
||||
@ -685,7 +680,7 @@ cd "$TEMPDIR/patch"
|
||||
KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$PATCHNAME" \
|
||||
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
|
||||
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
|
||||
make "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
|
||||
make >> "$LOGFILE" 2>&1 || die
|
||||
|
||||
if ! $KPATCH_MODULE; then
|
||||
if [[ -z "$KPATCH_LDFLAGS" ]]; then
|
||||
|
Loading…
Reference in New Issue
Block a user