Blame kpatch-build/kpatch-build

Packit Service ac8aad
#!/bin/bash
Packit Service ac8aad
#
Packit Service ac8aad
# kpatch build script
Packit Service ac8aad
#
Packit Service ac8aad
# Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
Packit Service ac8aad
# Copyright (C) 2013,2014 Josh Poimboeuf <jpoimboe@redhat.com>
Packit Service ac8aad
#
Packit Service ac8aad
# This program is free software; you can redistribute it and/or
Packit Service ac8aad
# modify it under the terms of the GNU General Public License
Packit Service ac8aad
# as published by the Free Software Foundation; either version 2
Packit Service ac8aad
# of the License, or (at your option) any later version.
Packit Service ac8aad
#
Packit Service ac8aad
# This program is distributed in the hope that it will be useful,
Packit Service ac8aad
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service ac8aad
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service ac8aad
# GNU General Public License for more details.
Packit Service ac8aad
#
Packit Service ac8aad
# You should have received a copy of the GNU General Public License
Packit Service ac8aad
# along with this program; if not, write to the Free Software
Packit Service ac8aad
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA,
Packit Service ac8aad
# 02110-1301, USA.
Packit Service ac8aad
Packit Service ac8aad
# This script takes a patch based on the version of the kernel
Packit Service ac8aad
# currently running and creates a kernel module that will
Packit Service ac8aad
# replace modified functions in the kernel such that the
Packit Service ac8aad
# patched code takes effect.
Packit Service ac8aad
Packit Service ac8aad
# This script:
Packit Service ac8aad
# - Either uses a specified kernel source directory or downloads the kernel
Packit Service ac8aad
#   source package for the currently running kernel
Packit Service ac8aad
# - Unpacks and prepares the source package for building if necessary
Packit Service da4517
# - Builds the base kernel or module
Packit Service da4517
# - Builds the patched kernel/module and monitors changed objects
Packit Service ac8aad
# - Builds the patched objects with gcc flags -f[function|data]-sections
Packit Service ac8aad
# - Runs kpatch tools to create and link the patch kernel module
Packit Service ac8aad
Packit Service ac8aad
set -o pipefail
Packit Service ac8aad
Packit Service ac8aad
BASE="$PWD"
Packit Service ac8aad
SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
Packit Service ac8aad
ARCH="$(uname -m)"
Packit Service ac8aad
CPUS="$(getconf _NPROCESSORS_ONLN)"
Packit Service ac8aad
CACHEDIR="${CACHEDIR:-$HOME/.kpatch}"
Packit Service ac8aad
SRCDIR="$CACHEDIR/src"
Packit Service ac8aad
RPMTOPDIR="$CACHEDIR/buildroot"
Packit Service ac8aad
VERSIONFILE="$CACHEDIR/version"
Packit Service ac8aad
TEMPDIR="$CACHEDIR/tmp"
Packit Service ac8aad
LOGFILE="$CACHEDIR/build.log"
Packit Service da4517
RELEASE_FILE=/etc/os-release
Packit Service ac8aad
DEBUG=0
Packit Service ac8aad
SKIPCLEANUP=0
Packit Service ac8aad
SKIPGCCCHECK=0
Packit Service ac8aad
ARCH_KCFLAGS=""
Packit Service da4517
DEBUG_KCFLAGS=""
Packit Service ac8aad
declare -a PATCH_LIST
Packit Service ac8aad
APPLIED_PATCHES=0
Packit Service da4517
OOT_MODULE=
Packit Service ac8aad
Packit Service ac8aad
warn() {
Packit Service ac8aad
	echo "ERROR: $1" >&2
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
die() {
Packit Service ac8aad
	if [[ -z "$1" ]]; then
Packit Service ac8aad
		msg="kpatch build failed"
Packit Service ac8aad
	else
Packit Service ac8aad
		msg="$1"
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	if [[ -e "$LOGFILE" ]]; then
Packit Service ac8aad
		warn "$msg. Check $LOGFILE for more details."
Packit Service ac8aad
	else
Packit Service ac8aad
		warn "$msg."
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	exit 1
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
logger() {
Packit Service ac8aad
	local to_stdout=${1:-0}
Packit Service ac8aad
Packit Service ac8aad
	if [[ $DEBUG -ge 2 ]] || [[ "$to_stdout" -eq 1 ]]; then
Packit Service ac8aad
		# Log to both stdout and the logfile
Packit Service ac8aad
		tee -a "$LOGFILE"
Packit Service ac8aad
	else
Packit Service ac8aad
		# Log only to the logfile
Packit Service ac8aad
		cat >> "$LOGFILE"
Packit Service ac8aad
	fi
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service da4517
verify_patch_files() {
Packit Service da4517
	local path
Packit Service da4517
	local dir
Packit Service da4517
	local ret=0
Packit Service da4517
Packit Service da4517
	for patch in "${PATCH_LIST[@]}"; do
Packit Service da4517
		for path in $(lsdiff "$patch" 2>/dev/null); do
Packit Service da4517
Packit Service da4517
			dir=$(dirname "$path")
Packit Service da4517
			ext="${path##*.}"
Packit Service da4517
Packit Service da4517
			if [[ "$dir" =~ ^lib$ ]] || [[ "$dir" =~ ^lib/ ]] ; then
Packit Service da4517
				warn "$patch: unsupported patch to lib/: $path"
Packit Service da4517
				ret=1
Packit Service da4517
			fi
Packit Service da4517
Packit Service da4517
			if [[ "$ext" == "S" ]] ; then
Packit Service da4517
				warn "$patch: unsupported patch to assembly: $path"
Packit Service da4517
				ret=1
Packit Service da4517
			fi
Packit Service da4517
Packit Service da4517
		done
Packit Service da4517
	done
Packit Service da4517
Packit Service da4517
	[[ $ret == 1 ]] && die "Unsupported changes detected"
Packit Service da4517
}
Packit Service da4517
Packit Service ac8aad
apply_patches() {
Packit Service ac8aad
	local patch
Packit Service ac8aad
Packit Service ac8aad
	for patch in "${PATCH_LIST[@]}"; do
Packit Service ac8aad
		patch -N -p1 --dry-run < "$patch" 2>&1 | logger || die "$patch file failed to apply"
Packit Service ac8aad
		patch -N -p1 < "$patch" 2>&1 | logger || die "$patch file failed to apply"
Packit Service ac8aad
		(( APPLIED_PATCHES++ ))
Packit Service ac8aad
	done
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
remove_patches() {
Packit Service ac8aad
	local patch
Packit Service ac8aad
	local idx
Packit Service ac8aad
Packit Service ac8aad
	for (( ; APPLIED_PATCHES>0; APPLIED_PATCHES-- )); do
Packit Service ac8aad
		idx=$(( APPLIED_PATCHES - 1))
Packit Service ac8aad
		patch="${PATCH_LIST[$idx]}"
Packit Service ac8aad
		patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null
Packit Service ac8aad
	done
Packit Service ac8aad
Packit Service ac8aad
	# If $SRCDIR was a git repo, make sure git actually sees that
Packit Service ac8aad
	# we've reverted our patch(es).
Packit Service ac8aad
	[[ -d "$SRCDIR/.git" ]] && (cd "$SRCDIR" && git update-index -q --refresh)
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
cleanup() {
Packit Service ac8aad
	rm -f "$SRCDIR/.scmversion"
Packit Service ac8aad
Packit Service ac8aad
	remove_patches
Packit Service ac8aad
Packit Service ac8aad
	# restore original vmlinux if it was overwritten by sourcedir build
Packit Service ac8aad
	[[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/"
Packit Service ac8aad
Packit Service ac8aad
	[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
Packit Service ac8aad
	rm -rf "$RPMTOPDIR"
Packit Service ac8aad
	unset KCFLAGS
Packit Service ac8aad
	unset KCPPFLAGS
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
clean_cache() {
Packit Service da4517
	rm -rf "${CACHEDIR:?}"/*
Packit Service ac8aad
	mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
check_pipe_status() {
Packit Service ac8aad
	rc="${PIPESTATUS[0]}"
Packit Service ac8aad
	if [[ "$rc" = 139 ]]; then
Packit Service ac8aad
		# There doesn't seem to be a consistent/portable way of
Packit Service ac8aad
		# accessing the last executed command in bash, so just
Packit Service ac8aad
		# pass in the script name for now..
Packit Service ac8aad
		warn "$1 SIGSEGV"
Packit Service ac8aad
		if ls core* &> /dev/null; then
Packit Service ac8aad
			cp core* /tmp
Packit Service ac8aad
			die "core file at /tmp/$(ls core*)"
Packit Service ac8aad
		fi
Packit Service da4517
		die "There was a SIGSEGV, but no core dump was found in the current directory.  Depending on your distro you might find it in /var/lib/systemd/coredump or /var/crash."
Packit Service ac8aad
	fi
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service da4517
kernel_version_gte() {
Packit Service da4517
	[  "${ARCHVERSION//-*/}" = "$(echo -e "${ARCHVERSION//-*}\\n$1" | sort -rV | head -n1)" ]
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service da4517
kernel_is_rhel() {
Packit Service da4517
	[[ "$ARCHVERSION" =~ \.el[78]\. ]]
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
find_dirs() {
Packit Service ac8aad
	if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
Packit Service ac8aad
		# git repo
Packit Service ac8aad
		TOOLSDIR="$SCRIPTDIR"
Packit Service ac8aad
		DATADIR="$(readlink -f "$SCRIPTDIR/../kmod")"
Packit Service ac8aad
		PLUGINDIR="$(readlink -f "$SCRIPTDIR/gcc-plugins")"
Packit Service ac8aad
	elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
Packit Service ac8aad
		# installation path
Packit Service ac8aad
		TOOLSDIR="$(readlink -f "$SCRIPTDIR/../libexec/kpatch")"
Packit Service ac8aad
		DATADIR="$(readlink -f "$SCRIPTDIR/../share/kpatch")"
Packit Service ac8aad
		PLUGINDIR="$TOOLSDIR"
Packit Service ac8aad
	else
Packit Service ac8aad
		return 1
Packit Service ac8aad
	fi
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
find_core_symvers() {
Packit Service ac8aad
	SYMVERSFILE=""
Packit Service ac8aad
	if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
Packit Service ac8aad
		# git repo
Packit Service ac8aad
		SYMVERSFILE="$DATADIR/core/Module.symvers"
Packit Service ac8aad
	elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
Packit Service ac8aad
		# installation path
Packit Service ac8aad
		if [[ -e "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers" ]]; then
Packit Service ac8aad
			SYMVERSFILE="$(readlink -f "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers")"
Packit Service ac8aad
		elif [[ -e /lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers ]]; then
Packit Service ac8aad
			SYMVERSFILE="$(readlink -f "/lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers")"
Packit Service ac8aad
		fi
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	[[ -e "$SYMVERSFILE" ]]
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
gcc_version_from_file() {
Packit Service da4517
	readelf -p .comment "$1" | grep -o 'GCC:.*' | head -n 1
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
gcc_version_check() {
Packit Service ac8aad
	local c="$TEMPDIR/test.c" o="$TEMPDIR/test.o"
Packit Service ac8aad
	local out gccver kgccver
Packit Service ac8aad
Packit Service ac8aad
	# gcc --version varies between distributions therefore extract version
Packit Service ac8aad
	# by compiling a test file and compare it to vmlinux's version.
Packit Service ac8aad
	echo 'void main(void) {}' > "$c"
Packit Service ac8aad
	out="$(gcc -c -pg -ffunction-sections -o "$o" "$c" 2>&1)"
Packit Service ac8aad
	gccver="$(gcc_version_from_file "$o")"
Packit Service da4517
	if [[ -n "$OOT_MODULE" ]]; then
Packit Service da4517
		kgccver="$(gcc_version_from_file "$OOT_MODULE")"
Packit Service da4517
	else
Packit Service da4517
		kgccver="$(gcc_version_from_file "$VMLINUX")"
Packit Service da4517
	fi
Packit Service ac8aad
Packit Service ac8aad
	if [[ -n "$out" ]]; then
Packit Service ac8aad
		warn "gcc >= 4.8 required for -pg -ffunction-settings"
Packit Service ac8aad
		echo "gcc output: $out"
Packit Service ac8aad
		return 1
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service da4517
	out="$(gcc -c -gz=none -o "$o" "$c" 2>&1)"
Packit Service da4517
	if [[ -z "$out" ]]; then
Packit Service da4517
		DEBUG_KCFLAGS="-gz=none"
Packit Service da4517
	fi
Packit Service da4517
	rm -f "$c" "$o"
Packit Service da4517
Packit Service ac8aad
	# ensure gcc version matches that used to build the kernel
Packit Service ac8aad
	if [[ "$gccver" != "$kgccver" ]]; then
Packit Service ac8aad
		warn "gcc/kernel version mismatch"
Packit Service ac8aad
		echo "gcc version:    $gccver"
Packit Service ac8aad
		echo "kernel version: $kgccver"
Packit Service ac8aad
		echo "Install the matching gcc version (recommended) or use --skip-gcc-check"
Packit Service ac8aad
		echo "to skip the version matching enforcement (not recommended)"
Packit Service ac8aad
		return 1
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	return
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
find_special_section_data_ppc64le() {
Packit Service da4517
Packit Service da4517
	[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1"
Packit Service da4517
Packit Service ac8aad
	SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
Packit Service ac8aad
		gawk --non-decimal-data '
Packit Service da4517
		BEGIN { f = b = e = j = 0 }
Packit Service ac8aad
Packit Service ac8aad
		# Set state if name matches
Packit Service ac8aad
		f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next}
Packit Service ac8aad
		b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
Packit Service ac8aad
		e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
Packit Service da4517
		j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
Packit Service ac8aad
Packit Service ac8aad
		# Reset state unless this abbrev describes the struct size
Packit Service ac8aad
		f == 1 && !/DW_AT_byte_size/ { f = 0; next }
Packit Service ac8aad
		b == 1 && !/DW_AT_byte_size/ { b = 0; next }
Packit Service ac8aad
		e == 1 && !/DW_AT_byte_size/ { e = 0; next }
Packit Service da4517
		j == 1 && !/DW_AT_byte_size/ { j = 0; next }
Packit Service ac8aad
Packit Service ac8aad
		# Now that we know the size, stop parsing for it
Packit Service da4517
		f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2}
Packit Service ac8aad
		b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
Packit Service ac8aad
		e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
Packit Service da4517
		j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
Packit Service ac8aad
Packit Service ac8aad
		# Bail out once we have everything
Packit Service da4517
		f == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {exit}')"
Packit Service ac8aad
Packit Service ac8aad
	[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
Packit Service ac8aad
Packit Service ac8aad
	[[ -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry size"
Packit Service ac8aad
	[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
Packit Service ac8aad
	[[ -z "$EX_STRUCT_SIZE" ]]  && die "can't find special struct exception_table_entry size"
Packit Service da4517
	[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]]  && die "can't find special struct jump_entry size"
Packit Service ac8aad
Packit Service ac8aad
	return
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
find_special_section_data() {
Packit Service ac8aad
	if [[ "$ARCH" = "ppc64le" ]]; then
Packit Service ac8aad
		find_special_section_data_ppc64le
Packit Service ac8aad
		return
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
Packit Service ac8aad
	[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
Packit Service da4517
	[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
Packit Service ac8aad
Packit Service ac8aad
	# If $AWK_OPTIONS are blank gawk would treat "" as a blank script
Packit Service ac8aad
	# shellcheck disable=SC2086
Packit Service ac8aad
	SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
Packit Service ac8aad
		gawk --non-decimal-data $AWK_OPTIONS '
Packit Service da4517
		BEGIN { a = b = p = e = o = j = 0 }
Packit Service ac8aad
Packit Service ac8aad
		# Set state if name matches
Packit Service ac8aad
		a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
Packit Service ac8aad
		b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
Packit Service ac8aad
		p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
Packit Service ac8aad
		e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
Packit Service ac8aad
		o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
Packit Service da4517
		j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
Packit Service ac8aad
Packit Service ac8aad
		# Reset state unless this abbrev describes the struct size
Packit Service ac8aad
		a == 1 && !/DW_AT_byte_size/ { a = 0; next }
Packit Service ac8aad
		b == 1 && !/DW_AT_byte_size/ { b = 0; next }
Packit Service ac8aad
		p == 1 && !/DW_AT_byte_size/ { p = 0; next }
Packit Service ac8aad
		e == 1 && !/DW_AT_byte_size/ { e = 0; next }
Packit Service ac8aad
		o == 1 && !/DW_AT_byte_size/ { o = 0; next }
Packit Service da4517
		j == 1 && !/DW_AT_byte_size/ { j = 0; next }
Packit Service ac8aad
Packit Service ac8aad
		# Now that we know the size, stop parsing for it
Packit Service ac8aad
		a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
Packit Service ac8aad
		b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
Packit Service ac8aad
		p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
Packit Service ac8aad
		e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
Packit Service ac8aad
		o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
Packit Service da4517
		j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
Packit Service ac8aad
Packit Service ac8aad
		# Bail out once we have everything
Packit Service da4517
		a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) {exit}')"
Packit Service ac8aad
Packit Service ac8aad
	[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
Packit Service ac8aad
Packit Service ac8aad
	[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
Packit Service ac8aad
	[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
Packit Service ac8aad
	[[ -z "$EX_STRUCT_SIZE" ]]  && die "can't find special struct paravirt_patch_site size"
Packit Service ac8aad
	[[ -z "$PARA_STRUCT_SIZE" && "$CONFIG_PARAVIRT" -ne 0 ]] && die "can't find special struct paravirt_patch_site size"
Packit Service ac8aad
	[[ -z "$ORC_STRUCT_SIZE" && "$CONFIG_UNWINDER_ORC" -ne 0 ]] && die "can't find special struct orc_entry size"
Packit Service da4517
	[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
Packit Service ac8aad
Packit Service ac8aad
	return
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service da4517
filter_parent_obj()
Packit Service da4517
{
Packit Service da4517
  local dir="${1}"
Packit Service da4517
  local file="${2}"
Packit Service da4517
Packit Service da4517
  grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd"
Packit Service da4517
}
Packit Service da4517
Packit Service ac8aad
find_parent_obj() {
Packit Service ac8aad
	dir="$(dirname "$1")"
Packit Service ac8aad
	absdir="$(readlink -f "$dir")"
Packit Service ac8aad
	pwddir="$(readlink -f .)"
Packit Service ac8aad
	pdir="${absdir#$pwddir/}"
Packit Service ac8aad
	file="$(basename "$1")"
Packit Service ac8aad
	grepname="${1%.o}"
Packit Service ac8aad
	grepname="$grepname\\.o"
Packit Service ac8aad
	if [[ "$DEEP_FIND" -eq 1 ]]; then
Packit Service ac8aad
		num=0
Packit Service ac8aad
		if [[ -n "$last_deep_find" ]]; then
Packit Service da4517
			parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)"
Packit Service da4517
			num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)"
Packit Service ac8aad
		fi
Packit Service ac8aad
		if [[ "$num" -eq 0 ]]; then
Packit Service da4517
			parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)"
Packit Service da4517
			num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)"
Packit Service ac8aad
			[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
Packit Service ac8aad
		fi
Packit Service ac8aad
	else
Packit Service da4517
		parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)"
Packit Service da4517
		num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)"
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	[[ "$num" -eq 0 ]] && PARENT="" && return
Packit Service ac8aad
	[[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1"
Packit Service ac8aad
Packit Service ac8aad
	dir="$(dirname "$parent")"
Packit Service ac8aad
	PARENT="$(basename "$parent")"
Packit Service ac8aad
	PARENT="${PARENT#.}"
Packit Service ac8aad
	PARENT="${PARENT%.cmd}"
Packit Service da4517
	[[ $dir != "." ]] && PARENT="$dir/$PARENT"
Packit Service ac8aad
	[[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
find_kobj() {
Packit Service ac8aad
	arg="$1"
Packit Service ac8aad
	KOBJFILE="$arg"
Packit Service ac8aad
	DEEP_FIND=0
Packit Service ac8aad
	ERROR_IF_DIFF=
Packit Service ac8aad
	while true; do
Packit Service ac8aad
		find_parent_obj "$KOBJFILE"
Packit Service ac8aad
		[[ -n "$PARENT" ]] && DEEP_FIND=0
Packit Service ac8aad
		if [[ -z "$PARENT" ]]; then
Packit Service ac8aad
			[[ "$KOBJFILE" = *.ko ]] && return
Packit Service ac8aad
			case "$KOBJFILE" in
Packit Service ac8aad
				*/built-in.o|\
Packit Service ac8aad
				*/built-in.a|\
Packit Service ac8aad
				arch/x86/lib/lib.a|\
Packit Service ac8aad
				arch/x86/kernel/head*.o|\
Packit Service ac8aad
				arch/x86/kernel/ebda.o|\
Packit Service ac8aad
				arch/x86/kernel/platform-quirks.o|\
Packit Service ac8aad
				lib/lib.a)
Packit Service ac8aad
					KOBJFILE=vmlinux
Packit Service ac8aad
					return
Packit Service ac8aad
			esac
Packit Service ac8aad
			if [[ "$DEEP_FIND" -eq 0 ]]; then
Packit Service ac8aad
				DEEP_FIND=1
Packit Service ac8aad
				continue;
Packit Service ac8aad
			fi
Packit Service ac8aad
			die "invalid ancestor $KOBJFILE for $arg"
Packit Service ac8aad
		fi
Packit Service ac8aad
		KOBJFILE="$PARENT"
Packit Service ac8aad
	done
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
# Only allow alphanumerics and '_' and '-' in the module name.  Everything else
Packit Service ac8aad
# is replaced with '-'.  Also truncate to 48 chars so the full name fits in the
Packit Service ac8aad
# kernel's 56-byte module name array.
Packit Service ac8aad
module_name_string() {
Packit Service ac8aad
	echo "${1//[^a-zA-Z0-9_-]/-}" | cut -c 1-48
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service ac8aad
usage() {
Packit Service ac8aad
	echo "usage: $(basename "$0") [options] <patch1 ... patchN>" >&2
Packit Service ac8aad
	echo "		patchN             Input patchfile(s)" >&2
Packit Service ac8aad
	echo "		-h, --help         Show this help message" >&2
Packit Service ac8aad
	echo "		-a, --archversion  Specify the kernel arch version" >&2
Packit Service ac8aad
	echo "		-r, --sourcerpm    Specify kernel source RPM" >&2
Packit Service ac8aad
	echo "		-s, --sourcedir    Specify kernel source directory" >&2
Packit Service ac8aad
	echo "		-c, --config       Specify kernel config file" >&2
Packit Service ac8aad
	echo "		-v, --vmlinux      Specify original vmlinux" >&2
Packit Service ac8aad
	echo "		-j, --jobs         Specify the number of make jobs" >&2
Packit Service ac8aad
	echo "		-t, --target       Specify custom kernel build targets" >&2
Packit Service ac8aad
	echo "		-n, --name         Specify the name of the kpatch module" >&2
Packit Service ac8aad
	echo "		-o, --output       Specify output folder" >&2
Packit Service ac8aad
	echo "		-d, --debug        Enable 'xtrace' and keep scratch files" >&2
Packit Service ac8aad
	echo "		                   in <CACHEDIR>/tmp" >&2
Packit Service ac8aad
	echo "		                   (can be specified multiple times)" >&2
Packit Service da4517
	echo "		-e, --oot-module   Enable patching out-of-tree module," >&2
Packit Service da4517
	echo "		                   specify current version of module" >&2
Packit Service ac8aad
	echo "		--skip-cleanup     Skip post-build cleanup" >&2
Packit Service ac8aad
	echo "		--skip-gcc-check   Skip gcc version matching check" >&2
Packit Service ac8aad
	echo "		                   (not recommended)" >&2
Packit Service ac8aad
}
Packit Service ac8aad
Packit Service da4517
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"
Packit Service ac8aad
Packit Service ac8aad
eval set -- "$options"
Packit Service ac8aad
Packit Service ac8aad
while [[ $# -gt 0 ]]; do
Packit Service ac8aad
	case "$1" in
Packit Service ac8aad
	-h|--help)
Packit Service ac8aad
		usage
Packit Service ac8aad
		exit 0
Packit Service ac8aad
		;;
Packit Service ac8aad
	-a|--archversion)
Packit Service ac8aad
		ARCHVERSION="$2"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-r|--sourcerpm)
Packit Service ac8aad
		[[ ! -f "$2" ]] && die "source rpm '$2' not found"
Packit Service ac8aad
		SRCRPM="$(readlink -f "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-s|--sourcedir)
Packit Service ac8aad
		[[ ! -d "$2" ]] && die "source dir '$2' not found"
Packit Service ac8aad
		USERSRCDIR="$(readlink -f "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-c|--config)
Packit Service ac8aad
		[[ ! -f "$2" ]] && die "config file '$2' not found"
Packit Service ac8aad
		CONFIGFILE="$(readlink -f "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-v|--vmlinux)
Packit Service ac8aad
		[[ ! -f "$2" ]] && die "vmlinux file '$2' not found"
Packit Service ac8aad
		VMLINUX="$(readlink -f "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-j|--jobs)
Packit Service ac8aad
		[[ ! "$2" -gt 0 ]] && die "Invalid number of make jobs '$2'"
Packit Service ac8aad
		CPUS="$2"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-t|--target)
Packit Service ac8aad
		TARGETS="$TARGETS $2"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-n|--name)
Packit Service ac8aad
		MODNAME="$(module_name_string "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-o|--output)
Packit Service ac8aad
		[[ ! -d "$2" ]] && die "output dir '$2' not found"
Packit Service ac8aad
		BASE="$(readlink -f "$2")"
Packit Service ac8aad
		shift
Packit Service ac8aad
		;;
Packit Service ac8aad
	-d|--debug)
Packit Service ac8aad
		DEBUG=$((DEBUG + 1))
Packit Service ac8aad
		if [[ $DEBUG -eq 1 ]]; then
Packit Service ac8aad
			echo "DEBUG mode enabled"
Packit Service ac8aad
		fi
Packit Service ac8aad
		;;
Packit Service da4517
	-e|--oot-module)
Packit Service da4517
		[[ ! -f "$2" ]] && die "out-of-tree module '$2' not found"
Packit Service da4517
		OOT_MODULE="$(readlink -f "$2")"
Packit Service da4517
		shift
Packit Service da4517
		;;
Packit Service ac8aad
	--skip-cleanup)
Packit Service ac8aad
		echo "Skipping cleanup"
Packit Service ac8aad
		SKIPCLEANUP=1
Packit Service ac8aad
		;;
Packit Service ac8aad
	--skip-gcc-check)
Packit Service ac8aad
		echo "WARNING: Skipping gcc version matching check (not recommended)"
Packit Service ac8aad
		SKIPGCCCHECK=1
Packit Service ac8aad
		;;
Packit Service ac8aad
	*)
Packit Service ac8aad
		[[ "$1" = "--" ]] && shift && continue
Packit Service ac8aad
		[[ ! -f "$1" ]] && die "patch file '$1' not found"
Packit Service ac8aad
		PATCH_LIST+=("$(readlink -f "$1")")
Packit Service ac8aad
		;;
Packit Service ac8aad
	esac
Packit Service ac8aad
	shift
Packit Service ac8aad
done
Packit Service ac8aad
Packit Service ac8aad
if [[ ${#PATCH_LIST[@]} -eq 0 ]]; then
Packit Service ac8aad
	warn "no patch file(s) specified"
Packit Service ac8aad
	usage
Packit Service ac8aad
	exit 1
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
if [[ $DEBUG -eq 1 ]] || [[ $DEBUG -ge 3 ]]; then
Packit Service ac8aad
	set -o xtrace
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
if [[ -n "$ARCHVERSION" ]] && [[ -n "$VMLINUX" ]]; then
Packit Service da4517
	die "--archversion is incompatible with --vmlinux"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
if [[ -n "$SRCRPM" ]]; then
Packit Service ac8aad
	if  [[ -n "$ARCHVERSION" ]]; then
Packit Service ac8aad
		warn "--archversion is incompatible with --sourcerpm"
Packit Service ac8aad
		exit 1
Packit Service ac8aad
	fi
Packit Service ac8aad
	rpmname="$(basename "$SRCRPM")"
Packit Service ac8aad
	ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)"
Packit Service ac8aad
	ARCHVERSION="${ARCHVERSION#kernel-}"
Packit Service ac8aad
	ARCHVERSION="${ARCHVERSION#alt-}"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service da4517
if [[ -n "$OOT_MODULE" ]] &&  [[ -z "$USERSRCDIR" ]]; then
Packit Service da4517
	warn "--oot-module requires --sourcedir"
Packit Service da4517
	exit 1
Packit Service da4517
fi
Packit Service da4517
Packit Service ac8aad
# ensure cachedir and tempdir are setup properly and cleaned
Packit Service ac8aad
mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
Packit Service ac8aad
rm -rf "${TEMPDIR:?}"/*
Packit Service ac8aad
rm -f "$LOGFILE"
Packit Service ac8aad
Packit Service ac8aad
if [[ -n "$USERSRCDIR" ]]; then
Packit Service ac8aad
	if [[ -n "$ARCHVERSION" ]]; then
Packit Service ac8aad
		warn "--archversion is incompatible with --sourcedir"
Packit Service ac8aad
		exit 1
Packit Service ac8aad
	fi
Packit Service ac8aad
	SRCDIR="$USERSRCDIR"
Packit Service ac8aad
Packit Service da4517
	if [[ -z "$OOT_MODULE" ]]; then
Packit Service da4517
		[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
Packit Service da4517
		[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
Packit Service ac8aad
Packit Service da4517
		# Extract the target kernel version from vmlinux in this case.
Packit Service da4517
		ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')"
Packit Service da4517
	else
Packit Service da4517
		ARCHVERSION="$(modinfo -F vermagic "$OOT_MODULE" | awk '{print $1}')"
Packit Service da4517
	fi
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
[[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)"
Packit Service ac8aad
Packit Service ac8aad
[[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP
Packit Service ac8aad
Packit Service ac8aad
KVER="${ARCHVERSION%%-*}"
Packit Service ac8aad
if [[ "$ARCHVERSION" =~ - ]]; then
Packit Service ac8aad
	KREL="${ARCHVERSION##*-}"
Packit Service ac8aad
	KREL="${KREL%.*}"
Packit Service ac8aad
fi
Packit Service ac8aad
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
Packit Service ac8aad
Packit Service ac8aad
[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
Packit Service ac8aad
Packit Service ac8aad
# Don't check external file.
Packit Service da4517
# shellcheck disable=SC1090
Packit Service da4517
[[ -f "$RELEASE_FILE" ]] && source "$RELEASE_FILE"
Packit Service ac8aad
DISTRO="$ID"
Packit Service ac8aad
if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
Packit Service ac8aad
	[[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux"
Packit Service ac8aad
	[[ -e "$VMLINUX" ]] || die "kernel-debuginfo-$ARCHVERSION not installed"
Packit Service ac8aad
Packit Service ac8aad
	export PATH="/usr/lib64/ccache:$PATH"
Packit Service ac8aad
Packit Service ac8aad
elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
Packit Service ac8aad
	[[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/boot/vmlinux-$ARCHVERSION"
Packit Service ac8aad
Packit Service ac8aad
	if [[ "$DISTRO" = ubuntu ]]; then
Packit Service ac8aad
		[[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbgsym not installed"
Packit Service ac8aad
Packit Service ac8aad
	elif [[ "$DISTRO" = debian ]]; then
Packit Service ac8aad
		[[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbg not installed"
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	export PATH="/usr/lib/ccache:$PATH"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
find_dirs || die "can't find supporting tools"
Packit Service ac8aad
Packit Service ac8aad
if [[ "$SKIPGCCCHECK" -eq 0 ]]; then
Packit Service ac8aad
	gcc_version_check || die
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
if [[ -n "$USERSRCDIR" ]]; then
Packit Service ac8aad
	echo "Using source directory at $USERSRCDIR"
Packit Service ac8aad
Packit Service ac8aad
	# save original vmlinux before it gets overwritten by sourcedir build
Packit Service da4517
	if [[ -z "$OOT_MODULE" ]] && [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]]; then
Packit Service da4517
		cp -f "$VMLINUX" "$TEMPDIR/vmlinux"
Packit Service da4517
		VMLINUX="$TEMPDIR/vmlinux"
Packit Service da4517
	fi
Packit Service da4517
Packit Service da4517
	# For external modules, use the running kernel's config
Packit Service da4517
	if [[ -n "$OOT_MODULE" ]] && [[ -z "$CONFIGFILE" ]]; then
Packit Service da4517
		CONFIGFILE="/boot/config-${ARCHVERSION}"
Packit Service da4517
	fi
Packit Service ac8aad
Packit Service ac8aad
elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then
Packit Service ac8aad
	echo "Using cache at $SRCDIR"
Packit Service ac8aad
Packit Service ac8aad
else
Packit Service ac8aad
	if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
Packit Service ac8aad
Packit Service ac8aad
		echo "Fedora/Red Hat distribution detected"
Packit Service ac8aad
Packit Service ac8aad
		clean_cache
Packit Service ac8aad
Packit Service ac8aad
		echo "Downloading kernel source for $ARCHVERSION"
Packit Service ac8aad
		if [[ -z "$SRCRPM" ]]; then
Packit Service ac8aad
			if [[ "$DISTRO" = fedora ]]; then
Packit Service ac8aad
				wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die
Packit Service ac8aad
			else
Packit Service da4517
				command -v yumdownloader &>/dev/null || die "yumdownloader (yum-utils or dnf-utils) not installed"
Packit Service ac8aad
				yumdownloader --source --destdir "$TEMPDIR" "kernel$ALT-$KVER-$KREL" 2>&1 | logger || die
Packit Service ac8aad
			fi
Packit Service ac8aad
			SRCRPM="$TEMPDIR/kernel$ALT-$KVER-$KREL.src.rpm"
Packit Service ac8aad
		fi
Packit Service ac8aad
Packit Service ac8aad
		echo "Unpacking kernel source"
Packit Service ac8aad
Packit Service ac8aad
		rpm -D "_topdir $RPMTOPDIR" -ivh "$SRCRPM" 2>&1 | logger || die
Packit Service da4517
		rpmbuild -D "_topdir $RPMTOPDIR" -bp --nodeps "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel$ALT.spec 2>&1 | logger ||
Packit Service ac8aad
			die "rpmbuild -bp failed.  you may need to run 'yum-builddep kernel' first."
Packit Service ac8aad
Packit Service da4517
		mv "$RPMTOPDIR"/BUILD/kernel-*/linux-* "$SRCDIR" 2>&1 | logger || die
Packit Service ac8aad
		rm -rf "$RPMTOPDIR"
Packit Service ac8aad
		rm -rf "$SRCDIR/.git"
Packit Service ac8aad
Packit Service ac8aad
		if [[ "$ARCHVERSION" == *-* ]]; then
Packit Service ac8aad
			echo "-${ARCHVERSION##*-}" > "$SRCDIR/localversion" || die
Packit Service ac8aad
		fi
Packit Service ac8aad
Packit Service ac8aad
		echo "$ARCHVERSION" > "$VERSIONFILE" || die
Packit Service ac8aad
Packit Service ac8aad
		[[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR/configs/kernel$ALT-$KVER-$ARCH.config"
Packit Service ac8aad
Packit Service ac8aad
		(cd "$SRCDIR" && make mrproper 2>&1 | logger) || die
Packit Service ac8aad
Packit Service ac8aad
	elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
Packit Service ac8aad
Packit Service ac8aad
		echo "Debian/Ubuntu distribution detected"
Packit Service ac8aad
Packit Service ac8aad
		if [[ "$DISTRO" = ubuntu ]]; then
Packit Service ac8aad
Packit Service ac8aad
			# url may be changed for a different mirror
Packit Service ac8aad
			url="http://archive.ubuntu.com/ubuntu/pool/main/l"
Packit Service ac8aad
			sublevel="SUBLEVEL = 0"
Packit Service ac8aad
Packit Service ac8aad
		elif [[ "$DISTRO" = debian ]]; then
Packit Service ac8aad
Packit Service ac8aad
			# url may be changed for a different mirror
Packit Service ac8aad
			url="http://ftp.debian.org/debian/pool/main/l"
Packit Service ac8aad
			sublevel="SUBLEVEL ="
Packit Service ac8aad
		fi
Packit Service ac8aad
Packit Service da4517
		pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)"
Packit Service ac8aad
		pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")"
Packit Service ac8aad
		dscname="${pkgname}_${pkgver}.dsc"
Packit Service ac8aad
Packit Service ac8aad
		clean_cache
Packit Service ac8aad
Packit Service ac8aad
		cd "$TEMPDIR" || die
Packit Service ac8aad
		echo "Downloading and unpacking the kernel source for $ARCHVERSION"
Packit Service ac8aad
		# Download source deb pkg
Packit Service ac8aad
		(dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}"
Packit Service ac8aad
		mv "${pkgname}-$KVER" "$SRCDIR" || die
Packit Service ac8aad
		[[ -z "$CONFIGFILE" ]] && CONFIGFILE="/boot/config-${ARCHVERSION}"
Packit Service ac8aad
		if [[ "$ARCHVERSION" == *-* ]]; then
Packit Service ac8aad
			echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
Packit Service ac8aad
		fi
Packit Service ac8aad
		# for some reason the Ubuntu kernel versions don't follow the
Packit Service ac8aad
		# upstream SUBLEVEL; they are always at SUBLEVEL 0
Packit Service ac8aad
		sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die
Packit Service ac8aad
		echo "$ARCHVERSION" > "$VERSIONFILE" || die
Packit Service ac8aad
Packit Service ac8aad
	else
Packit Service ac8aad
		die "Unsupported distribution"
Packit Service ac8aad
	fi
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
[[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config
Packit Service ac8aad
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
Packit Service ac8aad
[[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$SRCDIR/.config"
Packit Service ac8aad
Packit Service da4517
# kernel option checking
Packit Service da4517
grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
Packit Service da4517
Packit Service ac8aad
# Build variables - Set some defaults, then adjust features
Packit Service ac8aad
# according to .config and kernel version
Packit Service ac8aad
KBUILD_EXTRA_SYMBOLS=""
Packit Service ac8aad
KPATCH_LDFLAGS=""
Packit Service da4517
USE_KLP=0
Packit Service da4517
USE_KLP_ARCH=0
Packit Service da4517
CONFIG_PARAVIRT=0
Packit Service da4517
CONFIG_UNWINDER_ORC=0
Packit Service da4517
CONFIG_JUMP_LABEL=0
Packit Service da4517
CONFIG_MODVERSIONS=0
Packit Service ac8aad
Packit Service da4517
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE" && (kernel_is_rhel || kernel_version_gte 4.9.0); then
Packit Service da4517
Packit Service da4517
	USE_KLP=1
Packit Service da4517
Packit Service da4517
	if kernel_is_rhel || ! kernel_version_gte 5.8.0; then
Packit Service da4517
		USE_KLP_ARCH=1
Packit Service da4517
		KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions"
Packit Service da4517
		CDO_FLAGS="--klp-arch"
Packit Service ac8aad
	fi
Packit Service ac8aad
else
Packit Service ac8aad
	# No support for livepatch in the kernel. Kpatch core module is needed.
Packit Service da4517
Packit Service da4517
	# There may be ordering bugs, with jump labels and other special
Packit Service da4517
	# sections.  Use with caution!
Packit Service da4517
	echo "WARNING: Use of kpatch core module (kpatch.ko) is deprecated!  There may be bugs!" >&2
Packit Service da4517
Packit Service ac8aad
	find_core_symvers || die "unable to find Module.symvers for kpatch core module"
Packit Service ac8aad
	KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
# optional kernel configs:
Packit Service da4517
grep -q "CONFIG_PARAVIRT=y"     "$CONFIGFILE" && CONFIG_PARAVIRT=1
Packit Service da4517
grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE" && CONFIG_UNWINDER_ORC=1
Packit Service da4517
grep -q "CONFIG_JUMP_LABEL=y"   "$CONFIGFILE" && CONFIG_JUMP_LABEL=1
Packit Service da4517
grep -q "CONFIG_MODVERSIONS=y"  "$CONFIGFILE" && CONFIG_MODVERSIONS=1
Packit Service ac8aad
Packit Service da4517
# unsupported kernel option checking
Packit Service ac8aad
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
Packit Service da4517
grep -q "CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported"
Packit Service da4517
grep -q "CONFIG_GCC_PLUGIN_RANDSTRUCT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
Packit Service ac8aad
Packit Service ac8aad
echo "Testing patch file(s)"
Packit Service ac8aad
cd "$SRCDIR" || die
Packit Service da4517
verify_patch_files
Packit Service ac8aad
apply_patches
Packit Service ac8aad
remove_patches
Packit Service ac8aad
Packit Service ac8aad
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
Packit Service ac8aad
Packit Service ac8aad
if [[ "$ARCH" = "ppc64le" ]]; then
Packit Service ac8aad
	ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service da4517
export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \
Packit Service da4517
		$ARCH_KCFLAGS $DEBUG_KCFLAGS"
Packit Service ac8aad
Packit Service ac8aad
echo "Reading special section data"
Packit Service ac8aad
find_special_section_data
Packit Service ac8aad
Packit Service ac8aad
if [[ $DEBUG -ge 4 ]]; then
Packit Service ac8aad
	export KPATCH_GCC_DEBUG=1
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service da4517
echo "Building original source"
Packit Service da4517
[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die
Packit Service ac8aad
unset KPATCH_GCC_TEMPDIR
Packit Service ac8aad
# $TARGETS used as list, no quotes.
Packit Service ac8aad
# shellcheck disable=SC2086
Packit Service ac8aad
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
Packit Service ac8aad
Packit Service da4517
# Save original module symvers
Packit Service da4517
cp "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers"
Packit Service da4517
Packit Service da4517
echo "Building patched source"
Packit Service ac8aad
apply_patches
Packit Service ac8aad
mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
Packit Service ac8aad
KPATCH_GCC_TEMPDIR="$TEMPDIR"
Packit Service ac8aad
export KPATCH_GCC_TEMPDIR
Packit Service da4517
KPATCH_GCC_SRCDIR="$SRCDIR"
Packit Service da4517
export KPATCH_GCC_SRCDIR
Packit Service ac8aad
# $TARGETS used as list, no quotes.
Packit Service ac8aad
# shellcheck disable=SC2086
Packit Service ac8aad
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
Packit Service ac8aad
	KBUILD_MODPOST_WARN=1 \
Packit Service ac8aad
	make "-j$CPUS" $TARGETS 2>&1 | logger || die
Packit Service ac8aad
Packit Service ac8aad
# source.c:(.section+0xFF): undefined reference to `symbol'
Packit Service ac8aad
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
Packit Service ac8aad
	>"${TEMPDIR}"/undefined_references
Packit Service ac8aad
Packit Service ac8aad
# WARNING: "symbol" [path/to/module.ko] undefined!
Packit Service ac8aad
grep "undefined!" "$LOGFILE" | cut -d\" -f2 >>"${TEMPDIR}"/undefined_references
Packit Service ac8aad
Packit Service ac8aad
if [[ ! -e "$TEMPDIR/changed_objs" ]]; then
Packit Service ac8aad
	die "no changed objects found"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service da4517
[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
Packit Service da4517
Packit Service da4517
if [[ "$CONFIG_MODVERSIONS" -eq 1 ]]; then
Packit Service da4517
    while read -ra sym_line; do
Packit Service da4517
        if [[ ${#sym_line[@]} -lt 4 ]]; then
Packit Service da4517
            die "Malformed ${TEMPDIR}/Module.symvers file"
Packit Service da4517
        fi
Packit Service da4517
Packit Service da4517
        sym=${sym_line[1]}
Packit Service da4517
Packit Service da4517
        read -ra patched_sym_line <<< "$(grep "\s$sym\s" "$SRCDIR/Module.symvers")"
Packit Service da4517
        if [[ ${#patched_sym_line[@]} -lt 4 ]]; then
Packit Service da4517
            die "Malformed symbol entry for ${sym} in ${SRCDIR}/Module.symvers file"
Packit Service da4517
        fi
Packit Service da4517
Packit Service da4517
        # Assume that both original and patched symvers have the same format.
Packit Service da4517
        # In both cases, the symbol should have the same CRC, belong to the same
Packit Service da4517
        # Module/Namespace and have the same export type.
Packit Service da4517
        if [[ ${#sym_line[@]} -ne ${#patched_sym_line[@]} || \
Packit Service da4517
                  "${sym_line[*]}" != "${patched_sym_line[*]}" ]]; then
Packit Service da4517
            warn "Version disagreement for symbol ${sym}"
Packit Service da4517
        fi
Packit Service da4517
    done < "${TEMPDIR}/Module.symvers"
Packit Service da4517
fi
Packit Service ac8aad
Packit Service ac8aad
# Read as words, no quotes.
Packit Service ac8aad
# shellcheck disable=SC2013
Packit Service ac8aad
for i in $(cat "$TEMPDIR/changed_objs")
Packit Service ac8aad
do
Packit Service ac8aad
	mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
Packit Service ac8aad
	cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
Packit Service ac8aad
done
Packit Service ac8aad
Packit Service ac8aad
echo "Extracting new and modified ELF sections"
Packit Service ac8aad
# If no kpatch module name was provided on the command line:
Packit Service ac8aad
#   - For single input .patch, use the patch filename
Packit Service ac8aad
#   - For multiple input .patches, use "patch"
Packit Service ac8aad
#   - Prefix with "kpatch" or "livepatch" accordingly
Packit Service ac8aad
if [[ -z "$MODNAME" ]] ; then
Packit Service ac8aad
	if [[ "${#PATCH_LIST[@]}" -eq 1 ]]; then
Packit Service ac8aad
		MODNAME="$(basename "${PATCH_LIST[0]}")"
Packit Service ac8aad
		if [[ "$MODNAME" =~ \.patch$ ]] || [[ "$MODNAME" =~ \.diff$ ]]; then
Packit Service ac8aad
			MODNAME="${MODNAME%.*}"
Packit Service ac8aad
		fi
Packit Service ac8aad
	else
Packit Service ac8aad
		MODNAME="patch"
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service da4517
	if [[ "$USE_KLP" -eq 1 ]]; then
Packit Service ac8aad
		MODNAME="livepatch-$MODNAME"
Packit Service da4517
	else
Packit Service da4517
		MODNAME="kpatch-$MODNAME"
Packit Service ac8aad
	fi
Packit Service ac8aad
Packit Service ac8aad
	MODNAME="$(module_name_string "$MODNAME")"
Packit Service ac8aad
fi
Packit Service ac8aad
FILES="$(cat "$TEMPDIR/changed_objs")"
Packit Service ac8aad
cd "$TEMPDIR" || die
Packit Service ac8aad
mkdir output
Packit Service ac8aad
declare -a objnames
Packit Service ac8aad
CHANGED=0
Packit Service ac8aad
ERROR=0
Packit Service da4517
Packit Service da4517
# Prepare OOT module symvers file
Packit Service da4517
if [[ -n "$OOT_MODULE" ]]; then
Packit Service da4517
    BUILDDIR="/lib/modules/$ARCHVERSION/build/"
Packit Service da4517
    cp "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers"
Packit Service da4517
    awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$TEMPDIR/Module.symvers"
Packit Service da4517
fi
Packit Service da4517
Packit Service ac8aad
for i in $FILES; do
Packit Service ac8aad
	# In RHEL 7 based kernels, copy_user_64.o misuses the .fixup section,
Packit Service ac8aad
	# which confuses create-diff-object.  It's fine to skip it, it's an
Packit Service ac8aad
	# assembly file anyway.
Packit Service ac8aad
	[[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = ol ]] && \
Packit Service ac8aad
		[[ "$i" = arch/x86/lib/copy_user_64.o ]] && continue
Packit Service ac8aad
Packit Service ac8aad
	[[ "$i" = usr/initramfs_data.o ]] && continue
Packit Service ac8aad
Packit Service ac8aad
	mkdir -p "output/$(dirname "$i")"
Packit Service ac8aad
	cd "$SRCDIR" || die
Packit Service ac8aad
	find_kobj "$i"
Packit Service ac8aad
	cd "$TEMPDIR" || die
Packit Service ac8aad
	if [[ -e "orig/$i" ]]; then
Packit Service da4517
		if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then
Packit Service ac8aad
			KOBJFILE_NAME=vmlinux
Packit Service ac8aad
			KOBJFILE_PATH="$VMLINUX"
Packit Service ac8aad
			SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
Packit Service da4517
			SYMVERS_FILE="$SRCDIR/Module.symvers"
Packit Service da4517
		elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then
Packit Service da4517
			KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")"
Packit Service da4517
			KOBJFILE_PATH="$OOT_MODULE"
Packit Service da4517
			SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab"
Packit Service da4517
			SYMVERS_FILE="$TEMPDIR/Module.symvers"
Packit Service ac8aad
		else
Packit Service ac8aad
			KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}")
Packit Service da4517
			KOBJFILE_NAME="${KOBJFILE_NAME//-/_}"
Packit Service ac8aad
			KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
Packit Service ac8aad
			SYMTAB="${KOBJFILE_PATH}.symtab"
Packit Service da4517
			SYMVERS_FILE="$SRCDIR/Module.symvers"
Packit Service ac8aad
		fi
Packit Service ac8aad
Packit Service da4517
		readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
Packit Service da4517
		if [[ "$ARCH" = "ppc64le" ]]; then
Packit Service da4517
			sed -ri 's/\s+\[<localentry>: 8\]//' "$SYMTAB"
Packit Service da4517
		fi
Packit Service ac8aad
Packit Service ac8aad
		# create-diff-object orig.o patched.o parent-name parent-symtab
Packit Service ac8aad
		#		     Module.symvers patch-mod-name output.o
Packit Service da4517
		"$TOOLSDIR"/create-diff-object $CDO_FLAGS "orig/$i" "patched/$i" "$KOBJFILE_NAME" \
Packit Service da4517
			"$SYMTAB" "$SYMVERS_FILE" "${MODNAME//-/_}" \
Packit Service ac8aad
			"output/$i" 2>&1 | logger 1
Packit Service ac8aad
		check_pipe_status create-diff-object
Packit Service ac8aad
		# create-diff-object returns 3 if no functional change is found
Packit Service ac8aad
		[[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$((ERROR + 1))"
Packit Service ac8aad
		if [[ "$rc" -eq 0 ]]; then
Packit Service ac8aad
			[[ -n "$ERROR_IF_DIFF" ]] && die "$ERROR_IF_DIFF"
Packit Service ac8aad
			CHANGED=1
Packit Service ac8aad
			objnames[${#objnames[@]}]="$KOBJFILE"
Packit Service ac8aad
		fi
Packit Service ac8aad
	else
Packit Service ac8aad
		cp -f "patched/$i" "output/$i"
Packit Service ac8aad
		objnames[${#objnames[@]}]="$KOBJFILE"
Packit Service ac8aad
	fi
Packit Service ac8aad
done
Packit Service ac8aad
Packit Service ac8aad
if [[ "$ERROR" -ne 0 ]]; then
Packit Service ac8aad
	die "$ERROR error(s) encountered"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
if [[ "$CHANGED" -eq 0 ]]; then
Packit Service ac8aad
	die "no functional changes found"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
echo -n "Patched objects:"
Packit Service ac8aad
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
Packit Service ac8aad
do
Packit Service ac8aad
	echo -n " $i"
Packit Service ac8aad
done
Packit Service ac8aad
echo
Packit Service ac8aad
Packit Service ac8aad
export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS"
Packit Service da4517
if [[ "$USE_KLP" -eq 0 ]]; then
Packit Service ac8aad
	export KCPPFLAGS="-D__KPATCH_MODULE__"
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
echo "Building patch module: $MODNAME.ko"
Packit Service ac8aad
Packit Service ac8aad
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
Packit Service ac8aad
	# UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it
Packit Service ac8aad
	UBUNTU_ABI="${ARCHVERSION#*-}"
Packit Service ac8aad
	UBUNTU_ABI="${UBUNTU_ABI%-*}"
Packit Service ac8aad
	echo "#define UTS_UBUNTU_RELEASE_ABI $UBUNTU_ABI" >> "$SRCDIR"/include/generated/utsrelease.h
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
cd "$TEMPDIR/output" || die
Packit Service ac8aad
# $KPATCH_LDFLAGS and result of find used as list, no quotes.
Packit Service ac8aad
# shellcheck disable=SC2086,SC2046
Packit Service ac8aad
ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
Packit Service ac8aad
Packit Service da4517
if [[ "$USE_KLP" -eq 1 ]]; then
Packit Service da4517
	cp "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die
Packit Service da4517
	# Avoid MODPOST warning (pre-v5.8) and error (v5.8+) with an empty .cmd file
Packit Service da4517
	touch "$TEMPDIR"/patch/.output.o.cmd || die
Packit Service da4517
else
Packit Service ac8aad
	# Add .kpatch.checksum for kpatch script
Packit Service ac8aad
	md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
Packit Service ac8aad
	objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly  ../patch/tmp_output.o || die
Packit Service ac8aad
	rm -f checksum.tmp
Packit Service ac8aad
	"$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1
Packit Service ac8aad
	check_pipe_status create-kpatch-module
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
cd "$TEMPDIR/patch" || die
Packit Service da4517
if [[ -z "$OOT_MODULE" ]]; then
Packit Service da4517
	KPATCH_BUILD="$SRCDIR"
Packit Service da4517
else
Packit Service da4517
	KPATCH_BUILD="/lib/modules/$ARCHVERSION/build"
Packit Service da4517
fi
Packit Service da4517
KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
Packit Service ac8aad
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
Packit Service ac8aad
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
Packit Service ac8aad
	make 2>&1 | logger || die
Packit Service ac8aad
Packit Service da4517
if [[ "$USE_KLP" -eq 1 ]]; then
Packit Service da4517
	if [[ "$USE_KLP_ARCH" -eq 0 ]]; then
Packit Service ac8aad
		extra_flags="--no-klp-arch-sections"
Packit Service ac8aad
	fi
Packit Service ac8aad
	cp "$TEMPDIR/patch/$MODNAME.ko" "$TEMPDIR/patch/tmp.ko" || die
Packit Service ac8aad
	"$TOOLSDIR"/create-klp-module $extra_flags "$TEMPDIR/patch/tmp.ko" "$TEMPDIR/patch/$MODNAME.ko" 2>&1 | logger 1
Packit Service ac8aad
	check_pipe_status create-klp-module
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service da4517
if [[ "$CONFIG_MODVERSIONS" -eq 1 ]]; then
Packit Service da4517
    # Check that final module does not reference symbols with different version
Packit Service da4517
    # than the target kernel
Packit Service da4517
    KP_MOD_VALID=true
Packit Service da4517
    # shellcheck disable=SC2086
Packit Service da4517
    while read -ra mod_symbol; do
Packit Service da4517
        if [[ ${#mod_symbol[@]} -lt 2 ]]; then
Packit Service da4517
            continue
Packit Service da4517
        fi
Packit Service da4517
Packit Service da4517
        # Check if the symbol exists in the old Module.symvers, and if it does
Packit Service da4517
        # check that the CRCs are unchanged.
Packit Service da4517
        if ! awk -v sym="${mod_symbol[1]}" -v crc="${mod_symbol[0]}" \
Packit Service da4517
             '$2==sym && $1!=crc { exit 1 }' "$TEMPDIR/Module.symvers"; then
Packit Service da4517
            warn "Patch module references ${mod_symbol[1]} with invalid version"
Packit Service da4517
            KP_MOD_VALID=false
Packit Service da4517
        fi
Packit Service da4517
    done <<< "$(modprobe --dump-modversions $TEMPDIR/patch/$MODNAME.ko)"
Packit Service da4517
    if ! $KP_MOD_VALID; then
Packit Service da4517
        die "Patch module referencing altered exported kernel symbols cannot be loaded"
Packit Service da4517
    fi
Packit Service da4517
fi
Packit Service da4517
Packit Service ac8aad
readelf --wide --symbols "$TEMPDIR/patch/$MODNAME.ko" 2>/dev/null | \
Packit Service da4517
	sed -r 's/\s+\[<localentry>: 8\]//' | \
Packit Service ac8aad
	awk '($4=="FUNC" || $4=="OBJECT") && ($5=="GLOBAL" || $5=="WEAK") && $7!="UND" {print $NF}' \
Packit Service ac8aad
	>"${TEMPDIR}"/new_symbols
Packit Service ac8aad
Packit Service da4517
if [[ "$USE_KLP" -eq 0 ]]; then
Packit Service ac8aad
	cat >>"${TEMPDIR}"/new_symbols <<-EOF
Packit Service ac8aad
		kpatch_shadow_free
Packit Service ac8aad
		kpatch_shadow_alloc
Packit Service ac8aad
		kpatch_register
Packit Service ac8aad
		kpatch_shadow_get
Packit Service ac8aad
		kpatch_unregister
Packit Service ac8aad
		kpatch_root_kobj
Packit Service ac8aad
	EOF
Packit Service ac8aad
fi
Packit Service ac8aad
Packit Service ac8aad
# Compare undefined_references and new_symbols files and print only the first
Packit Service ac8aad
# column containing lines unique to first file.
Packit Service ac8aad
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
Packit Service ac8aad
	<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
Packit Service da4517
[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
Packit Service ac8aad
Packit Service ac8aad
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
Packit Service ac8aad
Packit Service da4517
[[ "$DEBUG" -eq 0 && "$SKIPCLEANUP" -eq 0 ]] && rm -f "$LOGFILE"
Packit Service ac8aad
Packit Service ac8aad
echo "SUCCESS"