All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joe Lawrence <joe.lawrence@redhat.com>
To: live-patching@vger.kernel.org
Cc: Josh Poimboeuf <jpoimboe@kernel.org>, Song Liu <song@kernel.org>,
	Miroslav Benes <mbenes@suse.cz>, Petr Mladek <pmladek@suse.com>,
	Yafang Shao <laoar.shao@gmail.com>
Subject: [RFC PATCH v2 6/7] livepatch/klp-build: add pre-built object support for advanced OOT workflows
Date: Wed, 26 Aug 2026 15:49:59 -0400	[thread overview]
Message-ID: <20260826195000.455905-7-joe.lawrence@redhat.com> (raw)
In-Reply-To: <20260826195000.455905-1-joe.lawrence@redhat.com>

Most real-world out-of-tree drivers use complicated, non-standard build
systems (DKMS, cmake, autoconf, proprietary toolchains) that cannot be
driven by klp-build's internal build stages.  Rather than attempting to
accommodate every third-party build system, let the user handle the
build process and supply the object pairs directly.

Enhance klp-build with --orig-dir and --patched-dir options that accept
directories of pre-built .o files.  The user is responsible for building
original and patched objects externally.  The only hard requirement is
that both builds use -ffunction-sections and -fdata-sections so that
objtool can identify changed functions at the object level.

From there, klp-build performs its binary comparison, symbol extraction,
and livepatch module assembly pipeline used for in-tree patches, only
with the build steps factored out.  External symbol ownership is
determined from the target kernel's Module.symvers (--symvers,
defaulting to $PWD/Module.symvers).

The new options are mutually exclusive with --oot-dir (which drives the
build itself) and --short-circuit (which is specific to the standard
build pipeline).

The workflow is as follows:

  # 1. Build OOT objects with -ffunction-sections and -fdata-sections
  mkdir -p /tmp/orig && cp $OOT/my_module.o /tmp/orig/

  # 2. (Optional) leverage the kernel's fix-patch-lines script to "undo"
  #    the effects of line number shift by the patch
  $KDIR/scripts/livepatch/fix-patch-lines $OOT/fix-overflow.patch \
      | recountdiff > /tmp/fixed.patch

  # 3. Apply patch, rebuild
  mkdir -p /tmp/patched && cp $OOT/my_module.o /tmp/patched/

  # 4. Generate the livepatch
  cd $KDIR
  ./scripts/livepatch/klp-build \
      --orig-dir /tmp/orig \
      --patched-dir /tmp/patched \
      --symvers $KDIR/Module.symvers \
      -o livepatch-my_module.ko

NOTE: klp-build does not verify that user-supplied objects were built
against the correct kernel headers or with compatible compiler options.
The resulting livepatch module is only as correct as the inputs
provided.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 110 +++++++++++++++++++++++++++++++++---
 1 file changed, 102 insertions(+), 8 deletions(-)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index b60f5a5da31e..e118f133e923 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -22,6 +22,9 @@ shopt -s lastpipe
 unset DEBUG_CLONE DIFF_CHECKSUM SKIP_CLEANUP VERBOSE XTRACE
 
 OOT_DIR=""
+USER_ORIG_DIR=""
+USER_PATCHED_DIR=""
+SYMVERS_PATH=""
 REPLACE=1
 SHORT_CIRCUIT=0
 JOBS="$(getconf _NPROCESSORS_ONLN)"
@@ -127,6 +130,7 @@ trap trap_err ERR
 __usage() {
 	cat <<EOF
 Usage: $SCRIPT [OPTIONS] PATCH_FILE(s)
+       $SCRIPT --orig-dir=<DIR> --patched-dir=<DIR> [OPTIONS]
 Generate a livepatch module.
 
 Options:
@@ -139,6 +143,9 @@ Options:
 Advanced Options:
    -d, --debug			Show symbol/reloc cloning decisions
        --oot-dir=<DIR>		Out-of-tree module source directory
+       --orig-dir=<DIR>		Directory of pre-built original .o files
+       --patched-dir=<DIR>	Directory of pre-built patched .o files
+       --symvers=<FILE>		Path to Module.symvers [default: \$PWD/Module.symvers]
    -S, --short-circuit=STEP	Start at build step (requires prior --keep-tmp)
 				   1|orig		Build original kernel (default)
 				   2|patched		Build patched kernel
@@ -162,7 +169,7 @@ process_args() {
 	local patch
 
 	short="hfj:o:vdS:T"
-	long="help,show-first-changed,jobs:,oot-dir:,output:,no-replace,verbose,debug,short-circuit:,keep-tmp"
+	long="help,show-first-changed,jobs:,oot-dir:,orig-dir:,patched-dir:,symvers:,output:,no-replace,verbose,debug,short-circuit:,keep-tmp"
 
 	args=$(getopt --options "$short" --longoptions "$long" -- "$@") || {
 		echo; usage; exit
@@ -208,6 +215,18 @@ process_args() {
 				OOT_DIR="$2"
 				shift 2
 				;;
+			--orig-dir)
+				USER_ORIG_DIR="$2"
+				shift 2
+				;;
+			--patched-dir)
+				USER_PATCHED_DIR="$2"
+				shift 2
+				;;
+			--symvers)
+				SYMVERS_PATH="$2"
+				shift 2
+				;;
 			-S | --short-circuit)
 				[[ ! -d "$TMP_DIR" ]] && die "--short-circuit requires preserved klp-tmp dir"
 				keep_tmp=1
@@ -236,7 +255,18 @@ process_args() {
 		esac
 	done
 
-	if [[ $# -eq 0 ]] && (( SHORT_CIRCUIT <= 2 )); then
+	if [[ -n "$USER_ORIG_DIR" || -n "$USER_PATCHED_DIR" ]]; then
+		[[ -n "$USER_ORIG_DIR" && -n "$USER_PATCHED_DIR" ]] ||
+			die "--orig-dir and --patched-dir must both be specified"
+		[[ -v NAME ]] ||
+			die "--orig-dir/--patched-dir requires -o <output.ko>"
+		[[ -n "$OOT_DIR" ]] &&
+			die "--orig-dir/--patched-dir and --oot-dir are mutually exclusive"
+		(( SHORT_CIRCUIT > 0 )) &&
+			die "--short-circuit is not used with --orig-dir/--patched-dir"
+		[[ $# -gt 0 ]] &&
+			die "patch files are not used with --orig-dir/--patched-dir"
+	elif [[ $# -eq 0 ]] && (( SHORT_CIRCUIT <= 2 )); then
 		usage
 		exit 1
 	fi
@@ -456,7 +486,19 @@ validate_patches() {
 do_init() {
 	[[ ! "$PWD" -ef "$SCRIPT_DIR/../.." ]] && die "please run from the kernel root directory"
 
-	if [[ -n "$OOT_DIR" ]]; then
+	if [[ -n "$USER_ORIG_DIR" ]]; then
+		[[ -d "$USER_ORIG_DIR" ]] || die "directory not found: $USER_ORIG_DIR"
+		[[ -d "$USER_PATCHED_DIR" ]] || die "directory not found: $USER_PATCHED_DIR"
+		USER_ORIG_DIR="$(realpath "$USER_ORIG_DIR")"
+		USER_PATCHED_DIR="$(realpath "$USER_PATCHED_DIR")"
+		if [[ -n "$SYMVERS_PATH" ]]; then
+			SYMVERS_PATH="$(realpath "$SYMVERS_PATH")"
+			[[ -f "$SYMVERS_PATH" ]] || die "Module.symvers not found: $SYMVERS_PATH"
+		else
+			[[ -f "$PWD/Module.symvers" ]] ||
+				die "no Module.symvers in $PWD; use --symvers to specify"
+		fi
+	elif [[ -n "$OOT_DIR" ]]; then
 		[[ -d "$OOT_DIR" ]] || die "module directory not found: $OOT_DIR"
 		OOT_DIR="$(realpath "$OOT_DIR")"
 		[[ -f "$OOT_DIR/Kbuild" || -f "$OOT_DIR/Makefile" ]] ||
@@ -482,14 +524,19 @@ do_init() {
 	(( SHORT_CIRCUIT <= 1 )) && rm -rf "$TMP_DIR"
 	mkdir -p "$TMP_DIR"
 
+	validate_config
+	set_module_name
+	set_kernelversion
+
+	# Pre-built OOT init complete
+	if [[ -n "$USER_ORIG_DIR" ]]; then
+		return 0
+	fi
+
 	APPLIED_PATCHES=()
 
 	[[ -x "$FIX_PATCH_LINES" ]] || die "can't find fix-patch-lines"
 	command -v recountdiff &>/dev/null || die "recountdiff not found (install patchutils)"
-
-	validate_config
-	set_module_name
-	set_kernelversion
 }
 
 # Refresh the patch hunk headers, specifically the line numbers and counts.
@@ -757,7 +804,11 @@ diff_objects() {
 		cmd+=("klp")
 		cmd+=("diff")
 		(( ${#opts[@]} > 0 )) && cmd+=("${opts[@]}")
-		[[ -n "$OOT_DIR" ]] && cmd+=("--symvers" "$PWD/Module.symvers")
+		if [[ -n "$SYMVERS_PATH" ]]; then
+			cmd+=("--symvers" "$SYMVERS_PATH")
+		elif [[ -n "$OOT_DIR" || -n "$USER_ORIG_DIR" ]]; then
+			cmd+=("--symvers" "$PWD/Module.symvers")
+		fi
 		cmd+=("$orig_file")
 		cmd+=("$patched_file")
 		cmd+=("$out_file")
@@ -931,11 +982,54 @@ build_patch_module() {
 }
 
 
+setup_oot() {
+	local files=()
+	local rel
+
+	mkdir -p "$ORIG_DIR" "$PATCHED_DIR"
+
+	find "$USER_ORIG_DIR" -type f -name "*.o" -printf '%P\n' | mapfile -t files
+	[[ ${#files[@]} -gt 0 ]] || die "no .o files found in $USER_ORIG_DIR"
+	for rel in "${files[@]}"; do
+		[[ -f "$USER_PATCHED_DIR/$rel" ]] ||
+			die "$rel found in orig dir but missing from patched dir"
+		mkdir -p "$ORIG_DIR/$(dirname "$rel")"
+		mkdir -p "$PATCHED_DIR/$(dirname "$rel")"
+		cp -f "$USER_ORIG_DIR/$rel" "$ORIG_DIR/$rel"
+		cp -f "$USER_PATCHED_DIR/$rel" "$PATCHED_DIR/$rel"
+	done
+
+	touch "$ORIG_DIR/.complete"
+	touch "$PATCHED_DIR/.complete"
+}
+
+
 ################################################################################
 
 process_args "$@"
 do_init
 
+# User provided OOT original and patched object files can jump straight
+# to checksum + diff + build steps
+if [[ -n "$USER_ORIG_DIR" ]]; then
+	status "Setting up OOT objects"
+	setup_oot
+
+	status "Generating original checksums"
+	generate_checksums "$ORIG_DIR" "$ORIG_CSUM_DIR" "$PATCHED_DIR"
+	status "Generating patched checksums"
+	generate_checksums "$PATCHED_DIR" "$PATCHED_CSUM_DIR"
+
+	status "Diffing objects"
+	diff_objects
+
+	status "Building patch module: $OUTFILE"
+	build_patch_module
+
+	status "SUCCESS"
+	exit 0
+fi
+
 BUILD_TARGET="kernel"
 [[ -n "$OOT_DIR" ]] && BUILD_TARGET="module ${OOT_DIR##*/}"
 
-- 
2.55.0


  parent reply	other threads:[~2026-08-26 19:50 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 19:49 [RFC PATCH v2 0/7] klp-build: OOT module support Joe Lawrence
2026-08-26 19:49 ` [RFC PATCH v2 1/7] objtool/klp: simplify read_exports file handling Joe Lawrence
2026-08-26 23:31   ` Song Liu
2026-09-10 14:35   ` Miroslav Benes
2026-08-26 19:49 ` [RFC PATCH v2 2/7] objtool/klp: add --symvers option to klp diff Joe Lawrence
2026-08-26 23:31   ` Song Liu
2026-09-10 14:35   ` Miroslav Benes
2026-08-26 19:49 ` [RFC PATCH v2 3/7] objtool/klp: allow special section entry size overrides Joe Lawrence
2026-08-27 19:17   ` Josh Poimboeuf
2026-08-26 19:49 ` [RFC PATCH v2 4/7] objtool: add target architecture to usage Joe Lawrence
2026-08-26 19:57   ` sashiko-bot
2026-08-27 19:23   ` Josh Poimboeuf
2026-08-26 19:49 ` [RFC PATCH v2 5/7] livepatch/klp-build: add basic out-of-tree module support Joe Lawrence
2026-08-26 20:00   ` sashiko-bot
2026-08-27 21:21   ` Josh Poimboeuf
2026-08-26 19:49 ` Joe Lawrence [this message]
2026-08-26 20:01   ` [RFC PATCH v2 6/7] livepatch/klp-build: add pre-built object support for advanced OOT workflows sashiko-bot
2026-08-27 21:45   ` Josh Poimboeuf
2026-08-26 19:50 ` [RFC PATCH v2 7/7] livepatch/klp-build: add validation for user-supplied OOT objects Joe Lawrence

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260826195000.455905-7-joe.lawrence@redhat.com \
    --to=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=laoar.shao@gmail.com \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.