Merge pull request #1237 from joe-lawrence/CONFIG_PRINTK_INDEX

kpatch-build: refactor kernel config and special section parsing
This commit is contained in:
Joe Lawrence 2021-12-17 14:50:48 -05:00 committed by GitHub
commit 774ede4e88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 80 additions and 106 deletions

View File

@ -331,111 +331,94 @@ clang_version_check() {
return
}
find_special_section_data_ppc64le() {
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1"
[[ "$CONFIG_PRINTK_INDEX" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_i=1"
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data '
BEGIN { f = b = e = j = 0 }
# Set state if name matches
f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next}
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
# Reset state unless this abbrev describes the struct size
f == 1 && !/DW_AT_byte_size/ { f = 0; next }
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
i == 1 && !/DW_AT_byte_size/ { i = 0; next }
# Now that we know the size, stop parsing for it
f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2}
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
i == 1 {printf("export PRINTK_INDEX_STRUCT_SIZE=%d\n", $4); i = 2}
# Bail out once we have everything
f == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && (i == 2 || skip_i) {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
[[ -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry size"
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
[[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
[[ -z "$PRINTK_INDEX_STRUCT_SIZE" && "$CONFIG_PRINTK_INDEX" -ne 0 ]] && die "can't find special struct pi_entry size"
return
}
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
local -A check
# Common features across all arches
check[b]=true # bug_entry
check[e]=true # exception_table_entry
# Arch-specific features, without kernel CONFIG_ toggle
if [[ "$ARCH" = "x86_64" ]]; then
check[a]=true # alt_instr
kernel_version_gte 5.10.0 && check[s]=true # static_call_site
elif [[ "$ARCH" = "ppc64le" ]]; then
check[f]=true # fixup_entry
fi
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
[[ "$CONFIG_PRINTK_INDEX" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_i=1"
! kernel_version_gte 5.10.0 && AWK_OPTIONS="$AWK_OPTIONS -vskip_s=1"
# Kernel CONFIG_ features
[[ -n "$CONFIG_PRINTK_INDEX" ]] && check[i]=true # pi_entry
[[ -n "$CONFIG_JUMP_LABEL" ]] && check[j]=true # jump_entry
[[ -n "$CONFIG_UNWINDER_ORC" ]] && check[o]=true # orc_entry
[[ -n "$CONFIG_PARAVIRT" ]] && check[p]=true # paravirt_patch_site
local c AWK_OPTIONS
for c in "${!check[@]}"; do
AWK_OPTIONS+=" -vcheck_${c}=1"
done
local SPECIAL_VARS
# If $AWK_OPTIONS are blank gawk would treat "" as a blank script
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
BEGIN { a = b = p = e = o = j = s = i = 0 }
BEGIN { a = b = e = f = i = j = o = p = s = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
s == 0 && /DW_AT_name.* static_call_site[[:space:]]*$/ {s = 1; next}
i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
check_a && a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
check_b && b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
check_e && e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
check_f && f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next}
check_i && i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
check_j && j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
check_o && o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
check_p && p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
check_s && s == 0 && /DW_AT_name.* static_call_site[[:space:]]*$/ {s = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
s == 1 && !/DW_AT_byte_size/ { s = 0; next }
f == 1 && !/DW_AT_byte_size/ { f = 0; next }
i == 1 && !/DW_AT_byte_size/ { i = 0; next }
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
s == 1 && !/DW_AT_byte_size/ { s = 0; next }
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
s == 1 {printf("export STATIC_CALL_STRUCT_SIZE=%d\n", $4); s = 2}
f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2}
i == 1 {printf("export PRINTK_INDEX_STRUCT_SIZE=%d\n", $4); i = 2}
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
s == 1 {printf("export STATIC_CALL_STRUCT_SIZE=%d\n", $4); s = 2}
# Bail out once we have everything
a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) && (s == 2 || skip_s) && (i == 2 || skip_i) {exit}')"
(!check_a || a == 2) &&
(!check_b || b == 2) &&
(!check_e || e == 2) &&
(!check_f || f == 2) &&
(!check_i || i == 2) &&
(!check_j || j == 2) &&
(!check_o || o == 2) &&
(!check_p || p == 2) &&
(!check_s || s == 2) {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
[[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
[[ -z "$PARA_STRUCT_SIZE" && "$CONFIG_PARAVIRT" -ne 0 ]] && die "can't find special struct paravirt_patch_site size"
[[ -z "$ORC_STRUCT_SIZE" && "$CONFIG_UNWINDER_ORC" -ne 0 ]] && die "can't find special struct orc_entry size"
[[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
[[ -z "$PRINTK_INDEX_STRUCT_SIZE" && "$CONFIG_PRINTK_INDEX" -ne 0 ]] && die "can't find special struct pi_entry size"
[[ -z "$STATIC_CALL_STRUCT_SIZE" ]] && kernel_version_gte 5.10.0 && die "can't find special struct static_call_site size"
[[ ${check[a]} && -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
[[ ${check[b]} && -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
[[ ${check[e]} && -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
[[ ${check[f]} && -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry size"
[[ ${check[i]} && -z "$PRINTK_INDEX_STRUCT_SIZE" ]] && die "can't find special struct pi_entry size"
[[ ${check[j]} && -z "$JUMP_STRUCT_SIZE" ]] && die "can't find special struct jump_entry size"
[[ ${check[o]} && -z "$ORC_STRUCT_SIZE" ]] && die "can't find special struct orc_entry size"
[[ ${check[p]} && -z "$PARA_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
[[ ${check[s]} && -z "$STATIC_CALL_STRUCT_SIZE" ]] && die "can't find special struct static_call_site size"
save_env
return
@ -841,21 +824,20 @@ if [[ -z "$OOT_MODULE" && ! "$CONFIGFILE" -ef "$KERNEL_SRCDIR"/.config ]] ; then
fi
# kernel option checking
grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
# Don't check external file.
# shellcheck disable=SC1090
source "$CONFIGFILE"
[[ -z "$CONFIG_DEBUG_INFO" ]] && die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
# Build variables - Set some defaults, then adjust features
# according to .config and kernel version
KPATCH_LDFLAGS=""
USE_KLP=0
USE_KLP_ARCH=0
CONFIG_PARAVIRT=0
CONFIG_UNWINDER_ORC=0
CONFIG_JUMP_LABEL=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 [[ -n "$CONFIG_LIVEPATCH" ]] && (kernel_is_rhel || kernel_version_gte 4.9.0); then
USE_KLP=1
@ -881,24 +863,16 @@ else
KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE"
fi
# optional kernel configs:
grep -q "CONFIG_PARAVIRT=y" "$CONFIGFILE" && CONFIG_PARAVIRT=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_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
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
grep -q "CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported"
grep -q "CONFIG_GCC_PLUGIN_RANDSTRUCT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
[[ -n "$CONFIG_DEBUG_INFO_SPLIT" ]] && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
[[ -n "$CONFIG_GCC_PLUGIN_LATENT_ENTROPY" ]] && die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported"
[[ -n "$CONFIG_GCC_PLUGIN_RANDSTRUCT" ]] && die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
# CONFIG_DEBUG_INFO_BTF invokes pahole, for which some versions don't
# support extended ELF sections. Disable the BTF typeinfo generation in
# link-vmlinux.sh and Makefile.modfinal since kpatch doesn't care about
# that anyway.
if grep -q "CONFIG_DEBUG_INFO_BTF=y" "$CONFIGFILE" ; then
if [[ -n "$CONFIG_DEBUG_INFO_BTF" ]]; then
cp -f "$KERNEL_SRCDIR/scripts/link-vmlinux.sh" "$TEMPDIR/link-vmlinux.sh" || die
sed -i 's/CONFIG_DEBUG_INFO_BTF/DISABLED_FOR_KPATCH_BUILD/g' "$KERNEL_SRCDIR"/scripts/link-vmlinux.sh || die
@ -908,7 +882,7 @@ if grep -q "CONFIG_DEBUG_INFO_BTF=y" "$CONFIGFILE" ; then
fi
fi
if [[ "$CONFIG_CC_IS_CLANG" -eq 1 ]]; then
if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then
echo "WARNING: Clang support is experimental"
fi
@ -918,10 +892,10 @@ if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then
else
target="$VMLINUX"
fi
if [[ "$CONFIG_CC_IS_CLANG" -eq 0 ]]; then
gcc_version_check "$target" || die
else
if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then
clang_version_check "$target" || die
else
gcc_version_check "$target" || die
fi
fi
@ -954,14 +928,14 @@ unset KPATCH_GCC_TEMPDIR
KPATCH_CC_PREFIX="$TOOLSDIR/kpatch-cc "
declare -a MAKEVARS
if [ "$CONFIG_CC_IS_CLANG" -eq 1 ]; then
if [[ -n "$CONFIG_CC_IS_CLANG" ]]; 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
if [[ -n "$CONFIG_LD_IS_LLD" ]]; then
MAKEVARS+=("LD=${KPATCH_CC_PREFIX}ld.lld")
MAKEVARS+=("HOSTLD=ld.lld")
else
@ -999,7 +973,7 @@ fi
grep -q vmlinux "$KERNEL_SRCDIR/Module.symvers" || die "truncated $KERNEL_SRCDIR/Module.symvers file"
if [[ "$CONFIG_MODVERSIONS" -eq 1 ]]; then
if [[ -n "$CONFIG_MODVERSIONS" ]]; then
while read -ra sym_line; do
if [[ ${#sym_line[@]} -lt 4 ]]; then
die "Malformed ${TEMPDIR}/Module.symvers file"
@ -1195,7 +1169,7 @@ if [[ "$USE_KLP" -eq 1 ]]; then
[[ "$rc" -ne 0 ]] && die "create-klp-module: exited with return code: $rc"
fi
if [[ "$CONFIG_MODVERSIONS" -eq 1 ]]; then
if [[ -n "$CONFIG_MODVERSIONS" ]]; then
# Check that final module does not reference symbols with different version
# than the target kernel
KP_MOD_VALID=true