mirror of https://github.com/dynup/kpatch
Merge pull request #1289 from jpoimboe/find_kobj
kpatch-build: support Linux 5.19 .cmd file format
This commit is contained in:
commit
f1fbf97345
|
@ -434,76 +434,215 @@ find_special_section_data() {
|
|||
return
|
||||
}
|
||||
|
||||
filter_parent_obj()
|
||||
{
|
||||
local dir="${1}"
|
||||
local file="${2}"
|
||||
# path of file, relative to dir
|
||||
# adapted from https://stackoverflow.com/a/24848739
|
||||
relpath() {
|
||||
local file="$1"
|
||||
local dir="$2"
|
||||
|
||||
grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd"
|
||||
local filedir
|
||||
local common
|
||||
local result
|
||||
|
||||
filedir="$(dirname "$(readlink -f "$file")")"
|
||||
common="$(readlink -f "$dir")"
|
||||
|
||||
if [[ "$filedir" = "$common" ]]; then
|
||||
basename "$file"
|
||||
return
|
||||
fi
|
||||
|
||||
while [[ "${filedir#$common/}" = "$filedir" ]]; do
|
||||
common="$(dirname "$common")"
|
||||
result="../$result"
|
||||
done
|
||||
|
||||
result="${result}${filedir#$common/}"
|
||||
echo "${result}/$(basename "$file")"
|
||||
}
|
||||
|
||||
cmd_file_to_o_file() {
|
||||
local parent="$1"
|
||||
|
||||
# convert cmd file name to corresponding .o
|
||||
parent_dir="$(dirname "$parent")"
|
||||
parent_dir="${parent_dir#./}"
|
||||
parent="$(basename "$parent")"
|
||||
parent="${parent#.}"
|
||||
parent="${parent%.cmd}"
|
||||
parent="$parent_dir/$parent"
|
||||
|
||||
[[ -f $parent ]] || die "can't find $parent associated with $1"
|
||||
|
||||
echo "$parent"
|
||||
}
|
||||
|
||||
get_parent_from_parents() {
|
||||
local parents=("$@")
|
||||
|
||||
[[ ${#parents[@]} -eq 0 ]] && PARENT="" && return
|
||||
[[ ${#parents[@]} -eq 1 ]] && PARENT="${parents[0]}" && return
|
||||
|
||||
# multiple parents:
|
||||
local parent
|
||||
local mod_name="${parents[0]%.*}"
|
||||
local mod_file
|
||||
for parent in "${parents[@]}"; do
|
||||
# for modules, there can be multiple matches. Some
|
||||
# combination of foo.o, foo.mod, and foo.ko, depending
|
||||
# on kernel version and whether the module is single or
|
||||
# multi-object. Make sure a .mod and/or .ko exists, and no
|
||||
# more than one .mod/.ko exists.
|
||||
|
||||
[[ $parent = *.o ]] && continue
|
||||
|
||||
if [[ ${parent%.*} != "$mod_name" ]]; then
|
||||
mod_file=""
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ $parent = *.mod || $parent = *.ko ]]; then
|
||||
mod_file=$parent
|
||||
continue
|
||||
fi
|
||||
|
||||
mod_file=""
|
||||
break
|
||||
done
|
||||
|
||||
if [[ -n $mod_file ]]; then
|
||||
PARENT="$mod_file"
|
||||
return
|
||||
fi
|
||||
|
||||
ERROR_IF_DIFF="multiple parent matches for $file: ${parents[*]}"
|
||||
PARENT="${parents[0]}"
|
||||
}
|
||||
|
||||
__find_parent_obj_in_dir() {
|
||||
local file="$1"
|
||||
local dir="$2"
|
||||
|
||||
declare -a parents
|
||||
|
||||
while IFS='' read -r parent; do
|
||||
parent="$(cmd_file_to_o_file "$parent")"
|
||||
[[ $parent -ef $file ]] && continue
|
||||
parents+=("$parent")
|
||||
done < <(grep -El "[ ]${file/./\\.}([ \)]|$)" "$dir"/.*.cmd)
|
||||
|
||||
get_parent_from_parents "${parents[@]}"
|
||||
}
|
||||
|
||||
find_parent_obj_in_dir() {
|
||||
local file="$1"
|
||||
local dir="$2"
|
||||
|
||||
# make sure the dir has .cmd files
|
||||
if ! compgen -G "$dir"/.*.cmd > /dev/null; then
|
||||
PARENT=""
|
||||
return
|
||||
fi
|
||||
|
||||
# 5.19+: ../acp/acp_hw.o
|
||||
__find_parent_obj_in_dir "$(relpath "$file" "$dir")" "$dir"
|
||||
[[ -n $PARENT ]] && return
|
||||
|
||||
# pre-5.19 (and 5.19+ single-object modules):
|
||||
if [[ $file == $dir* ]]; then
|
||||
# arch/x86/kernel/smp.o
|
||||
__find_parent_obj_in_dir "$file" "$dir"
|
||||
else
|
||||
# drivers/gpu/drm/amd/amdgpu/../acp/acp_hw.o
|
||||
__find_parent_obj_in_dir "$dir"/"$(relpath "$file" "$dir")" "$dir"
|
||||
fi
|
||||
}
|
||||
|
||||
find_parent_obj() {
|
||||
dir="$(dirname "$1")"
|
||||
absdir="$(readlink -f "$dir")"
|
||||
pwddir="$(readlink -f .)"
|
||||
pdir="${absdir#$pwddir/}"
|
||||
file="$(basename "$1")"
|
||||
grepname="${1%.o}"
|
||||
grepname="$grepname\\.o"
|
||||
if [[ "$DEEP_FIND" -eq 1 ]]; then
|
||||
num=0
|
||||
if [[ -n "$last_deep_find" ]]; then
|
||||
parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)"
|
||||
num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)"
|
||||
fi
|
||||
if [[ "$num" -eq 0 ]]; then
|
||||
parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)"
|
||||
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)"
|
||||
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
|
||||
fi
|
||||
else
|
||||
parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)"
|
||||
num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)"
|
||||
local file="$1"
|
||||
|
||||
# common case: look in same directory
|
||||
find_parent_obj_in_dir "$file" "$(dirname "$file")"
|
||||
[[ -n $PARENT ]] && return
|
||||
|
||||
# if we previously had a successful deep find, try that dir first
|
||||
if [[ -n "$LAST_DEEP_FIND_DIR" ]]; then
|
||||
find_parent_obj_in_dir "$file" "$LAST_DEEP_FIND_DIR"
|
||||
[[ -n "$PARENT" ]] && return
|
||||
fi
|
||||
|
||||
[[ "$num" -eq 0 ]] && PARENT="" && return
|
||||
[[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1"
|
||||
# prevent known deep finds
|
||||
if [[ $file = drivers/gpu/drm/amd/* ]]; then
|
||||
find_parent_obj_in_dir "$file" "drivers/gpu/drm/amd/amdgpu"
|
||||
[[ -n "$PARENT" ]] && return
|
||||
fi
|
||||
if [[ $file = virt/kvm/* ]]; then
|
||||
find_parent_obj_in_dir "$file" "arch/x86/kvm"
|
||||
[[ -n "$PARENT" ]] && return
|
||||
fi
|
||||
if [[ $file = drivers/oprofile/* ]]; then
|
||||
find_parent_obj_in_dir "$file" "arch/x86/oprofile"
|
||||
[[ -n "$PARENT" ]] && return
|
||||
fi
|
||||
|
||||
dir="$(dirname "$parent")"
|
||||
PARENT="$(basename "$parent")"
|
||||
PARENT="${PARENT#.}"
|
||||
PARENT="${PARENT%.cmd}"
|
||||
[[ $dir != "." ]] && PARENT="$dir/$PARENT"
|
||||
[[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
|
||||
# check higher-level dirs
|
||||
local dir
|
||||
dir="$(dirname "$file")"
|
||||
while [[ ! $dir -ef . ]]; do
|
||||
dir="$(dirname "$dir")"
|
||||
find_parent_obj_in_dir "$file" "$dir"
|
||||
[[ -n $PARENT ]] && return
|
||||
done
|
||||
|
||||
# slow path: search the entire tree ("deep find")
|
||||
echo 'doing "deep find" for parent object'
|
||||
declare -a parents
|
||||
while IFS= read -r -d '' dir; do
|
||||
find_parent_obj_in_dir "$file" "$dir"
|
||||
if [[ -n $PARENT ]]; then
|
||||
parents+=("$PARENT")
|
||||
LAST_DEEP_FIND_DIR="$dir"
|
||||
fi
|
||||
done < <(find . -type d -print0)
|
||||
|
||||
get_parent_from_parents "${parents[@]}"
|
||||
}
|
||||
|
||||
# find vmlinux or .ko associated with a .o file
|
||||
find_kobj() {
|
||||
arg="$1"
|
||||
KOBJFILE="$arg"
|
||||
DEEP_FIND=0
|
||||
local file="$1"
|
||||
|
||||
if [[ -n $OOT_MODULE ]]; then
|
||||
KOBJFILE="$OOT_MODULE"
|
||||
return
|
||||
fi
|
||||
|
||||
KOBJFILE="$file"
|
||||
ERROR_IF_DIFF=
|
||||
while true; do
|
||||
case "$KOBJFILE" in
|
||||
*.mod)
|
||||
KOBJFILE=${PARENT/.mod/.ko}
|
||||
[[ -e $KOBJFILE ]] || die "can't find .ko for $PARENT"
|
||||
return
|
||||
;;
|
||||
*.ko)
|
||||
return
|
||||
;;
|
||||
*/built-in.o|\
|
||||
*/built-in.a|\
|
||||
arch/x86/kernel/ebda.o|\
|
||||
arch/x86/kernel/head*.o|\
|
||||
arch/x86/kernel/platform-quirks.o|\
|
||||
arch/x86/lib/lib.a|\
|
||||
lib/lib.a)
|
||||
KOBJFILE=vmlinux
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
find_parent_obj "$KOBJFILE"
|
||||
[[ -n "$PARENT" ]] && DEEP_FIND=0
|
||||
if [[ -z "$PARENT" ]]; then
|
||||
[[ "$KOBJFILE" = *.ko ]] && return
|
||||
case "$KOBJFILE" in
|
||||
*/built-in.o|\
|
||||
*/built-in.a|\
|
||||
arch/x86/lib/lib.a|\
|
||||
arch/x86/kernel/head*.o|\
|
||||
arch/x86/kernel/ebda.o|\
|
||||
arch/x86/kernel/platform-quirks.o|\
|
||||
lib/lib.a)
|
||||
KOBJFILE=vmlinux
|
||||
return
|
||||
esac
|
||||
if [[ "$DEEP_FIND" -eq 0 ]]; then
|
||||
DEEP_FIND=1
|
||||
continue;
|
||||
fi
|
||||
die "invalid ancestor $KOBJFILE for $arg"
|
||||
fi
|
||||
[[ -z "$PARENT" ]] && die "invalid ancestor $KOBJFILE for $file"
|
||||
KOBJFILE="$PARENT"
|
||||
done
|
||||
}
|
||||
|
@ -1093,17 +1232,17 @@ for i in $FILES; do
|
|||
find_kobj "$i"
|
||||
cd "$TEMPDIR" || die
|
||||
if [[ -e "orig/$i" ]]; then
|
||||
if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then
|
||||
KOBJFILE_NAME=vmlinux
|
||||
KOBJFILE_PATH="$VMLINUX"
|
||||
SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
|
||||
SYMVERS_FILE="$BUILDDIR/Module.symvers"
|
||||
elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then
|
||||
if [[ -n $OOT_MODULE ]]; then
|
||||
KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")"
|
||||
KOBJFILE_NAME="${KOBJFILE_NAME//-/_}"
|
||||
KOBJFILE_PATH="$OOT_MODULE"
|
||||
SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab"
|
||||
SYMVERS_FILE="$TEMPDIR/Module.symvers"
|
||||
elif [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then
|
||||
KOBJFILE_NAME=vmlinux
|
||||
KOBJFILE_PATH="$VMLINUX"
|
||||
SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
|
||||
SYMVERS_FILE="$BUILDDIR/Module.symvers"
|
||||
else
|
||||
KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}")
|
||||
KOBJFILE_NAME="${KOBJFILE_NAME//-/_}"
|
||||
|
|
|
@ -31,22 +31,22 @@ if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; th
|
|||
vmlinux.o|\
|
||||
.tmp_kallsyms1.o|\
|
||||
.tmp_kallsyms2.o|\
|
||||
init/version.o|\
|
||||
arch/x86/boot/version.o|\
|
||||
arch/x86/boot/compressed/eboot.o|\
|
||||
arch/x86/boot/header.o|\
|
||||
arch/x86/boot/compressed/efi_stub_64.o|\
|
||||
arch/x86/boot/compressed/piggy.o|\
|
||||
kernel/system_certificates.o|\
|
||||
arch/x86/vdso/*|\
|
||||
arch/x86/boot/*|\
|
||||
arch/x86/entry/vdso/*|\
|
||||
drivers/firmware/efi/libstub/*|\
|
||||
arch/x86/purgatory/*|\
|
||||
arch/x86/realmode/*|\
|
||||
arch/x86/tools/*|\
|
||||
arch/x86/vdso/*|\
|
||||
arch/powerpc/kernel/prom_init.o|\
|
||||
arch/powerpc/kernel/vdso64/*|\
|
||||
arch/s390/boot/*|\
|
||||
arch/s390/purgatory/*|\
|
||||
arch/s390/kernel/vdso64/*|\
|
||||
drivers/firmware/efi/libstub/*|\
|
||||
init/version.o|\
|
||||
kernel/system_certificates.o|\
|
||||
lib/*|\
|
||||
tools/*|\
|
||||
.*.o|\
|
||||
*/.lib_exports.o)
|
||||
break
|
||||
|
|
Loading…
Reference in New Issue