From 6b03bc8ec08106fd9070885c9fbd1fcb2bb7cb39 Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
Date: Wed, 13 Jul 2016 16:44:14 -0500
Subject: [PATCH] create-diff-object: fix WARN*_ONCE detection on newer kernels

This fixes the detection of WARN_ON_ONCE, WARN_ONCE, and WARN_TAINT_ONCE
on Linux 4.6 and newer.

The signature for those macros changed with upstream Linux commit
dfbf2897d004 ("bug: set warn variable before calling WARN()").

Fixes #602.
---
 kpatch-build/create-diff-object.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -690,22 +690,21 @@
  * Warning: Hackery lies herein.  It's hopefully justified by the fact that
  * this issue is very common.
  *
- * base object:
- *
- * be 5e 04 00 00          mov    $0x45e,%esi
- * 48 c7 c7 ff 5a a1 81    mov    $0xffffffff81a15aff,%rdi
- * e8 26 13 08 00          callq  ffffffff8108d0d0 <warn_slowpath_fmt>
- *
- * patched object:
- *
- * be 5e 04 00 00          mov    $0x45f,%esi
- * 48 c7 c7 ff 5a a1 81    mov    $0xffffffff81a15aff,%rdi
- * e8 26 13 08 00          callq  ffffffff8108d0d0 <warn_slowpath_fmt>
- *
- * The above is the most common case.  The pattern which applies to all cases
- * is an immediate move of the line number to %esi followed by zero or more
- * relas to a string section followed by a rela to warn_slowpath_*.
+ * Example:
  *
+ *  938:   be 70 00 00 00          mov    $0x70,%esi
+ *  93d:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi
+ *                         940: R_X86_64_32S       .rodata.tcp_conn_request.str1.8+0x88
+ *  944:   c6 05 00 00 00 00 01    movb   $0x1,0x0(%rip)        # 94b <tcp_conn_request+0x94b>
+ *                         946: R_X86_64_PC32      .data.unlikely-0x1
+ *  94b:   e8 00 00 00 00          callq  950 <tcp_conn_request+0x950>
+ *                         94c: R_X86_64_PC32      warn_slowpath_null-0x4
+ *
+ * The pattern which applies to all cases:
+ * 1) immediate move of the line number to %esi
+ * 2) (optional) string section rela
+ * 3) (optional) __warned.xxxxx static local rela
+ * 4) warn_slowpath_* rela
  */
 static int kpatch_warn_only_change(struct section *sec)
 {
@@ -759,6 +758,8 @@
 				continue;
 			if (rela->string)
 				continue;
+			if (!strncmp(rela->sym->name, "__warned.", 9))
+				continue;
 			if (!strncmp(rela->sym->name, "warn_slowpath_", 14)) {
 				found = 1;
 				break;
