]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
livepatch/klp-build: Introduce fix-patch-lines script to avoid __LINE__ diff noise
authorJosh Poimboeuf <jpoimboe@kernel.org>
Wed, 17 Sep 2025 16:04:06 +0000 (09:04 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 14 Oct 2025 21:50:19 +0000 (14:50 -0700)
The __LINE__ macro creates challenges for binary diffing.  When a .patch
file adds or removes lines, it shifts the line numbers for all code
below it.

This can cause the code generation of functions using __LINE__ to change
due to the line number constant being embedded in a MOV instruction,
despite there being no semantic difference.

Avoid such false positives by adding a fix-patch-lines script which can
be used to insert a #line directive in each patch hunk affecting the
line numbering.  This script will be used by klp-build, which will be
introduced in a subsequent patch.

Acked-by: Petr Mladek <pmladek@suse.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
MAINTAINERS
scripts/livepatch/fix-patch-lines [new file with mode: 0755]

index 755e2528f8391cdda516366107bedeb54db5e22b..fc573e9a523ccb9e61ceb639ce755c1266ff36c2 100644 (file)
@@ -14443,6 +14443,7 @@ F:      include/linux/livepatch*.h
 F:     kernel/livepatch/
 F:     kernel/module/livepatch.c
 F:     samples/livepatch/
+F:     scripts/livepatch/
 F:     tools/testing/selftests/livepatch/
 
 LLC (802.2)
diff --git a/scripts/livepatch/fix-patch-lines b/scripts/livepatch/fix-patch-lines
new file mode 100755 (executable)
index 0000000..73c5e3d
--- /dev/null
@@ -0,0 +1,79 @@
+#!/usr/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Use #line directives to preserve original __LINE__ numbers across patches to
+# avoid unwanted compilation changes.
+
+BEGIN {
+       in_hunk = 0
+       skip    = 0
+}
+
+/^--- / {
+       skip = $2 !~ /\.(c|h)$/
+       print
+       next
+}
+
+/^@@/ {
+       if (skip) {
+               print
+               next
+       }
+
+       in_hunk = 1
+
+       # for @@ -1,3 +1,4 @@:
+       #   1: line number in old file
+       #   3: how many lines the hunk covers in old file
+       #   1: line number in new file
+       #   4: how many lines the hunk covers in new file
+
+       match($0, /^@@ -([0-9]+)(,([0-9]+))? \+([0-9]+)(,([0-9]+))? @@/, m)
+
+       # Set 'cur' to the old file's line number at the start of the hunk.  It
+       # gets incremented for every context line and every line removal, so
+       # that it always represents the old file's current line number.
+       cur = m[1]
+
+       # last = last line number of current hunk
+       last = cur + (m[3] ? m[3] : 1) - 1
+
+       need_line_directive = 0
+
+       print
+       next
+}
+
+{
+       if (skip || !in_hunk || $0 ~ /^\\ No newline at end of file/) {
+               print
+               next
+       }
+
+       # change line
+       if ($0 ~ /^[+-]/) {
+               # inject #line after this group of changes
+               need_line_directive = 1
+
+               if ($0 ~ /^-/)
+                       cur++
+
+               print
+               next
+       }
+
+       # If this is the first context line after a group of changes, inject
+       # the #line directive to force the compiler to correct the line
+       # numbering to match the original file.
+       if (need_line_directive) {
+               print "+#line " cur
+               need_line_directive = 0
+       }
+
+       if (cur == last)
+               in_hunk = 0
+
+       cur++
+       print
+}