diff -pruN 0.6.0-0.2/contrib/kpatch.service 0.8.0-0ubuntu7/contrib/kpatch.service
--- 0.6.0-0.2/contrib/kpatch.service	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/contrib/kpatch.service	2019-08-28 17:34:00.000000000 +0000
@@ -6,7 +6,6 @@ ConditionKernelCommandLine=!kpatch.enabl
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=PREFIX/sbin/kpatch load --all
-ExecStop=PREFIX/sbin/kpatch unload --all
 
 [Install]
 WantedBy=multi-user.target
diff -pruN 0.6.0-0.2/contrib/kpatch.spec 0.8.0-0ubuntu7/contrib/kpatch.spec
--- 0.6.0-0.2/contrib/kpatch.spec	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/contrib/kpatch.spec	2019-08-28 17:34:00.000000000 +0000
@@ -1,7 +1,7 @@
 Name: kpatch
 Summary: Dynamic kernel patching
-Version: 0.6.0
-License: GPLv2 
+Version: 0.8.0
+License: GPLv2
 Group: System Environment/Kernel
 URL: http://github.com/dynup/kpatch
 Release: 1%{?dist}
@@ -14,7 +14,7 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{na
 # needed for the kernel specific module
 %define KVER %(uname -r)
 
-%description 
+%description
 kpatch is a Linux dynamic kernel patching tool which allows you to patch a
 running kernel without rebooting or restarting any processes.  It enables
 sysadmins to apply critical security patches to the kernel immediately, without
@@ -60,10 +60,10 @@ sacrificing security or stability.
 
 
 %prep
-%setup -q 
+%setup -q
 
 %build
-make %{_smp_mflags} 
+make %{_smp_mflags}
 
 %install
 rm -rf %{buildroot}
@@ -93,6 +93,101 @@ rm -rf %{buildroot}
 %{_mandir}/man1/kpatch-build.1*
 
 %changelog
+* Wed Aug 21 2019 Artem Savkov <asavkov@redhat.com> - 0.8.0
+- kpatch.ko atomic replace fixes
+- Fixes for potential problems found by covscan
+- Remove manual signaling logic from kpatch utility
+- Don't strip callback symbols
+- Allow dynamic debug static keys
+
+* Wed Jul 24 2019 Josh Poimboeuf <jpoimboe@redhat.com> - 0.7.1
+- Fix several powerpc-specific bugs, including two which can result in kernel
+  panics
+- Use rpmbuild --nodeps for installing srpm on Fedora/RHEL
+- Fix inconsistent unit test failures for FAIL tests
+
+* Thu Jul 18 2019 Artem Savkov <asavkov@redhat.com> - 0.7.0
+- Multiple memory leak fixes in kpatch-build
+- livepatch-patch-hook compatability fixes for kernels 5.1+
+- Making kpatch-build compatible with custom gcc names
+- Added rhel-rebased integration tests
+- kpatch.service will no longer unload modules on stop
+- kpatch load will no longer fail if a module is already loaded and enabled
+- kpatch-build will now check for *_fixup section changes on ppc64le and will
+  fail on such changes
+- Add support for R_X86_64_PLT32
+- don't allow jump labels
+- ppc64le-specific kpatch-build fixes
+
+* Fri Apr 12 2019 Joe Lawrence <joe.lawrence@redhat.com> - 0.6.3
+- Lots of integration test work
+- Better support for building out-of-tree modules
+- Updated manpage options, drop deprecated distro specific mentions
+- README.md updates for shadow variables, out-of-tree modules
+- Fix core module compilation with CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+- kpatch-build detects and abort on unsupported options
+  GCC_PLUGIN_LATENT_ENTROPY, GCC_PLUGIN_RANDSTRUCT
+- Fix patch linking with 4.20+
+- Other minor shellcheck and kpatch-build fixups
+
+* Tue Oct 2 2018 Joe Lawrence <joe.lawrence@redhat.com> - 0.6.2
+- ppc64le: relax .text section addralign value check
+- gcc8: unit-tests
+- gcc8: support parent/child symbol relations
+- gcc8: handle functions changing subsection
+- gcc8: consider ".text.hot" sections bundleable
+- kpatch-build: bugfix for less aggressive clean build-cache
+- ubuntu: remove "-signed" substring from the kernel source package name
+- ubuntu: explicitly note elfutils dependency
+- upstream 4.18: unit-tests
+- upstream 4.18: KCFLAGS -mcount-record support support
+- RHEL-8: don't care who provides yumdownloader
+- RHEL-8: account for quirky SRPM / release name conventions
+
+* Tue May 29 2018 Joe Lawrence <joe.lawrence@redhat.com> - 0.6.1
+- Increase the transition timeout, helpful for large CPU count systems
+- Miscellaneous unit testing, ppc64, etc. fixes
+
+* Mon Apr 22 2018 Josh Poimboeuf <jpoimboe@redhat.com> - 0.6.0
+- Support and converted to livepatch-style hooks.
+- Lots of misc bugfixes and cleanups
+- Manpage, README.md fixups
+- More PPC64 work
+- "Undefined reference" build failure rework
+- Livepatch disable retries
+- New unit testing framework
+
+* Thu Dec 21 2017 Josh Poimboeuf <jpoimboe@redhat.com> - 0.5.0
+- Basic ppc64le support
+- kpatch: load automatically signals stalled processes after a timeout
+- kpatch: list shows stalled processes
+- kpatch: signal signals stalled processes
+- kpatch-build: multiple source patches can be combined into a single binary patch module
+- kpatch-build: -n|--name option for giving a custom name to the patch module
+- kpatch-build: additional -d options for more verbose debug modes
+- The module prefix is now either livepatch- or kpatch- depending on the underlying patching technology
+
+* Mon Mar 13 2017 Josh Poimboeuf <jpoimboe@redhat.com> - 0.4.0
+- The tools underlying kpatch-build have been made more modular, in preparation for making create-diff-object more generally useful to other use cases (kernel livepatch, Xen live patching, user space patching).
+- Support for all new upstream kernels up to 4.10.
+- KASLR support.
+- Many other bug fixes and improvements.
+
+* Thu Oct 11 2016 Jessica Yu - 0.3.4
+- bump version to 0.3.4
+
+* Fri Aug 19 2016 Josh Poimboeuf <jpoimboe@redhat.com> - 0.3.3
+- bump version to 0.3.3
+
+* Thu Feb 18 2016 Josh Poimboeuf <jpoimboe@redhat.com> - 0.3.2
+- bump version to 0.3.2
+
+* Thu Nov 19 2015 Josh Poimboeuf <jpoimboe@redhat.com> - 0.3.1
+- Get kernel version from vmlinux if the kernel source tree is used
+
+* Wed Nov 18 2015 Josh Poimboeuf <jpoimboe@redhat.com> - 0.3.0
+- kpatch-build: fix gcc_version_check: both "GNU" and "GCC" are possible
+
 * Wed Dec 3 2014 Josh Poimboeuf <jpoimboe@redhat.com> - 0.2.2-1
 - rebased to current version
 
diff -pruN 0.6.0-0.2/debian/changelog 0.8.0-0ubuntu7/debian/changelog
--- 0.6.0-0.2/debian/changelog	2019-01-07 19:39:23.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/changelog	2020-12-17 12:00:04.000000000 +0000
@@ -1,3 +1,99 @@
+kpatch (0.8.0-0ubuntu7) hirsute; urgency=medium
+
+  * Revert the last change, and build explicitly with GCC 9.
+    kpatch 0.8 is not ready for GCC 10. There is 0.9.2 ...
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 17 Dec 2020 13:00:04 +0100
+
+kpatch (0.8.0-0ubuntu5) hirsute; urgency=medium
+
+  * Build using gcc-10-plugin-dev.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 17 Dec 2020 12:50:48 +0100
+
+kpatch (0.8.0-0ubuntu4) hirsute; urgency=medium
+
+  * Merge packaging fixes from 0.6.0-0.2 0.6.0-0.1 and 0.3.2-3.1
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Fri, 11 Dec 2020 16:03:59 +0100
+
+kpatch (0.8.0-0ubuntu3) hirsute; urgency=medium
+
+  * Drop dh-systemd runtime dependency with debhelper >=10
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Fri, 11 Dec 2020 13:08:00 +0100
+
+kpatch (0.8.0-0ubuntu2) focal; urgency=medium
+
+  * No-change rebuild for libgcc-s1 package name change.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 22 Mar 2020 16:45:05 +0100
+
+kpatch (0.8.0-0ubuntu1) focal; urgency=low
+
+  [ Benjamin M Romer ]
+  * Upstream bump to 0.8.0
+  * These remaining patches have been refreshed to apply to the updated
+     upstream:
+     - kpatch-build-adjust-dirs.patch
+     - use-debian-rules-for-ubuntu-builds.patch
+     - ubuntu-kernel-variants.patch
+  * Packaging changes to produce only kpatch and kpatch-build
+     - kpatch-dkms will be deprecated in the upstream soon
+     - kmod-fix-symbol-lookup-on-linux-4.19.patch no longer needed
+  * Enhance ubuntu-kernel-variants.patch to support additional kernel flavors
+  * Added missing devscripts dependency, required by kpatch-build 
+  * Added elfutils dependency for ppc64el support
+  * Added gcc plugin devpackage dependency for ppc64el support
+  * Extra patch for xenial shellcheck version
+
+  [ Matthias Klose ]
+  * Depend on python2-dev instead of python-dev.
+
+ -- Benjamin M Romer <benjamin.romer@canonical.com>  Tue, 21 Jan 2020 16:12:05 +0100
+
+kpatch (0.5.0-0ubuntu2) disco; urgency=medium
+
+  * Import v0.6 pataches from unstable for v4.19/v5 compat.
+  * Add more shellcheck fixes.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Mon, 18 Feb 2019 09:39:39 +0100
+
+kpatch (0.5.0-0ubuntu1) bionic; urgency=low
+
+   * Upstream bump to 0.5.0 (LP: #1763065).
+   * Drop patches that are present in the upstream release:
+     - kpatch-build-works-without-kpatch-kmod.patch
+     - kmod-core-fix-stacktrace_ops-address-function-protot.patch
+     - create-diff-object-fix-WARN-_ONCE-detection-on-newer.patch
+     - use-livepatch-4.5-kernel-features.patch
+   * output-kernel-build-in-debug.patch was dropped to reduce build output.
+   * These remaining patches have been updated to apply to the refreshed
+     upstream:
+     - kpatch-build-adjust-dirs.patch
+     - use-debian-rules-for-ubuntu-builds.patch
+     - ubuntu-kernel-variants.patch
+   * The shellcheck linter is called during packaging, to verify the quality of
+     the scripts used in the package.
+   * List the Ubuntu Kernel Team as the package maintainer in the control file
+   * kmod/core: fix stacktrace_ops 'address' function prototype for 4.6 (LP: #1665613, #1659581)
+
+ -- Benjamin M Romer <benjamin.romer@canonical.com>  Wed, 11 Apr 2018 21:41:51 -0400
+
+kpatch (0.3.2-3ubuntu1) yakkety; urgency=low
+
+  * Merge from Debian unstable.  Remaining changes:
+    - Add additional depends for building Ubuntu kernel
+    - Ubuntu Specific Patches:
+      - output-kernel-build-in-debug.patch
+      - ubuntu-kernel-variants.patch
+      - use-debian-rules-for-ubuntu-builds.patch
+      - use-livepatch-4.5-kernel-features.patch
+      - use-ubuntu-utsrelease-for-kpatch-build.patch
+    - make dpks updates dir in post-dkms.sh script
+
+ -- Chris J Arges <chris.j.arges@canonical.com>  Tue, 16 Aug 2016 08:41:04 -0500
+
 kpatch (0.6.0-0.2) unstable; urgency=medium
 
   * Non-maintainer upload
@@ -43,6 +139,52 @@ kpatch (0.3.2-2) unstable; urgency=mediu
 
  -- Chris J Arges <chris.j.arges@canonical.com>  Mon, 27 Jun 2016 14:01:29 -0500
 
+kpatch (0.3.2-1ubuntu6) yakkety; urgency=medium
+
+  * Allow kpatch-build to build for Ubuntu flavors. (LP: #1586515)
+
+ -- Benjamin M Romer <benjamin.romer@canonical.com>  Tue, 24 May 2016 11:09:54 -0400
+
+kpatch (0.3.2-1ubuntu5) yakkety; urgency=medium
+
+  * Use debian/rules to build the kernel (LP: #1578661)
+  * During kernel builds, generate output when not in debug mode to
+    prevent builders timing out due to the build appearing hung (LP: #1570012)
+
+ -- Benjamin M Romer <benjamin.romer@canonical.com>  Wed, 04 May 2016 12:49:33 -0400
+
+kpatch (0.3.2-1ubuntu4) xenial; urgency=medium
+
+  [ Chris J Arges ]
+  * Use Build-Depends from the Ubuntu linux source package.
+
+  [ Benjamin M Romer ]
+  * When running in debug mode, write the linux build output to stdout as well
+    as the log file. (LP: #1566924)
+
+ -- Chris J Arges <chris.j.arges@canonical.com>  Thu, 07 Apr 2016 09:20:33 +0100
+
+kpatch (0.3.2-1ubuntu3) xenial; urgency=medium
+
+  * Generate UTS_UBUNTU_RELEASE_ABI for utsrelease.h instead of previous
+    attempt. (LP: #1566460)
+
+ -- Chris J Arges <chris.j.arges@canonical.com>  Tue, 05 Apr 2016 18:01:53 +0100
+
+kpatch (0.3.2-1ubuntu2) xenial; urgency=medium
+
+  * Use utsrelease.h as generated in linux-headers-`uname -r` instead of
+    regenerating it. (LP: #1560216)
+
+ -- Chris J Arges <chris.j.arges@canonical.com>  Mon, 21 Mar 2016 15:46:31 -0500
+
+kpatch (0.3.2-1ubuntu1) xenial; urgency=medium
+
+  * Ensure we use sympos structures for patched Ubuntu v4.4 kernel.
+    (LP: #1548430)
+
+ -- Chris J Arges <chris.j.arges@canonical.com>  Mon, 22 Feb 2016 13:09:36 -0500
+
 kpatch (0.3.2-1) unstable; urgency=medium
 
   * New upstream release.
@@ -67,3 +209,4 @@ kpatch (0.3.1-1) unstable; urgency=mediu
   * Initial release (Closes: #810268)
 
  -- Chris J Arges <chris.j.arges@canonical.com>  Thu, 07 Jan 2016 10:03:07 -0600
+
diff -pruN 0.6.0-0.2/debian/control 0.8.0-0ubuntu7/debian/control
--- 0.6.0-0.2/debian/control	2018-06-15 22:23:46.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/control	2020-12-17 11:57:40.000000000 +0000
@@ -1,16 +1,19 @@
 Source: kpatch
 Section: kernel
 Priority: optional
-Maintainer: Chris J Arges <chris.j.arges@canonical.com>
-Build-Depends: debhelper (>= 9), libelf-dev, dkms, shellcheck
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+XSBC-Original-Maintainer: Chris J Arges <chris.j.arges@canonical.com>
+Build-Depends: debhelper (>= 9), libelf-dev, shellcheck, g++-9, gcc-9-plugin-dev
 Standards-Version: 3.9.8
 Homepage: http://github.com/dynup/kpatch
 Vcs-Git: https://salsa.debian.org/debian/kpatch.git
 Vcs-Browser: https://salsa.debian.org/debian/kpatch
 
 Package: kpatch
-Architecture: linux-amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, binutils
+Architecture: any
+Replaces: kpatch-dkms
+Depends: ${shlibs:Depends}, ${misc:Depends},
+ linux-headers-amd64 | linux-headers-generic
 Description: Runtime tools for Kpatch
  kpatch is a Linux dynamic kernel patching tool which allows you to patch a
  running kernel without rebooting or restarting any processes.  It enables
@@ -19,20 +22,15 @@ Description: Runtime tools for Kpatch
  for scheduled reboot windows.  It gives more control over up-time without
  sacrificing security or stability.
 
-Package: kpatch-dkms
-Architecture: linux-amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, dkms,
- linux-headers-amd64 | linux-headers-generic
-Description: DKMS module for Kpatch
- This package contains the Kpatch module built with DKMS. It installs the source
- and makefiles into the appropriate locations in order to handle various kernel
- versions.
-
 Package: kpatch-build
-Architecture: linux-amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, dpkg-dev, linux-source, kernel-wedge, gawk, bc
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, dpkg-dev, debhelper (>= 10),
+ cpio, kernel-wedge, kmod, makedumpfile, libelf-dev, devscripts,
+ libnewt-dev, libiberty-dev, rsync, libdw-dev, libpci-dev, pkg-config, flex,
+ bison, libunwind8-dev, openssl, libssl-dev, libaudit-dev, bc, python2-dev, gawk,
+ libudev-dev, autoconf, automake, libtool, uuid-dev, xmlto, docbook-utils,
+ ghostscript, transfig, bzip2, sharutils, asciidoc, elfutils
 Suggests: ccache
 Description: Build Tools for Kpatch and Livepatch
  kpatch-build is a tool that can build both kpatch and livepatch modules from
  a given patch.
-
diff -pruN 0.6.0-0.2/debian/kpatch-dkms.dkms 0.8.0-0ubuntu7/debian/kpatch-dkms.dkms
--- 0.6.0-0.2/debian/kpatch-dkms.dkms	2019-01-07 19:24:43.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/kpatch-dkms.dkms	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-MAKE="make -C kmod/ KPATCH_BUILD=/lib/modules/${kernelver}/build"
-BUILT_MODULE_NAME="kpatch"
-BUILT_MODULE_LOCATION="kmod/core"
-DEST_MODULE_LOCATION="/updates/dkms"
-CLEAN="make -C kmod/ KPATCH_BUILD=/lib/modules/${kernelver}/build clean"
-PACKAGE_NAME="kpatch"
-PACKAGE_VERSION=#MODULE_VERSION#
-REMAKE_INITRD="no"
-STRIP="no"
-AUTOINSTALL="yes"
-POST_BUILD="post-dkms.sh #MODULE_VERSION# ${kernelver}"
diff -pruN 0.6.0-0.2/debian/patches/create-diff-object-fix-WARN-_ONCE-detection-on-newer.patch 0.8.0-0ubuntu7/debian/patches/create-diff-object-fix-WARN-_ONCE-detection-on-newer.patch
--- 0.6.0-0.2/debian/patches/create-diff-object-fix-WARN-_ONCE-detection-on-newer.patch	2018-06-15 22:23:46.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/create-diff-object-fix-WARN-_ONCE-detection-on-newer.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,64 +0,0 @@
-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;
diff -pruN 0.6.0-0.2/debian/patches/Fix-build-err-by-Werror-maybe-uninitialized.patch 0.8.0-0ubuntu7/debian/patches/Fix-build-err-by-Werror-maybe-uninitialized.patch
--- 0.6.0-0.2/debian/patches/Fix-build-err-by-Werror-maybe-uninitialized.patch	2018-06-15 22:23:46.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/Fix-build-err-by-Werror-maybe-uninitialized.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-From a25c18eb82c6cd1186b262e4920e6d30d7273a36 Mon Sep 17 00:00:00 2001
-From: Nobuhiro Iwamatsu <iwamatsu@debian.org>
-Date: Sun, 17 Jun 2018 06:59:47 +0900
-Subject: [PATCH] Fix build err by '-Werror=maybe-uninitialized'
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
------
-create-diff-object.c: In function $B!F(Bkpatch_compare_sections$B!G(B:
-create-diff-object.c:316:20: error: $B!F(Btoc_data1$B!G(B may be used uninitialized in this function [-Werror=maybe-uninitialized]
-   return toc_data1 == toc_data2;
-          ~~~~~~~~~~^~~~~~~~~~~~
-create-diff-object.c:256:16: note: $B!F(Btoc_data1$B!G(B was declared here
-  unsigned long toc_data1, toc_data2;
-                ^~~~~~~~~
-cc1: all warnings being treated as errors
------
-
-Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@debian.org>
----
- kpatch-build/create-diff-object.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
-index 026ee1d..391171f 100644
---- a/kpatch-build/create-diff-object.c
-+++ b/kpatch-build/create-diff-object.c
-@@ -253,7 +253,7 @@ static int kpatch_mangled_strcmp(char *s1, char *s2)
- static int rela_equal(struct rela *rela1, struct rela *rela2)
- {
- 	struct rela *rela_toc1, *rela_toc2;
--	unsigned long toc_data1, toc_data2;
-+	unsigned long toc_data1 = 0, toc_data2 = 0;
- 
- 	if (rela1->type != rela2->type ||
- 	    rela1->offset != rela2->offset)
--- 
-2.17.1
-
diff -pruN 0.6.0-0.2/debian/patches/gcc-9.diff 0.8.0-0ubuntu7/debian/patches/gcc-9.diff
--- 0.6.0-0.2/debian/patches/gcc-9.diff	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/gcc-9.diff	2020-12-17 12:00:04.000000000 +0000
@@ -0,0 +1,29 @@
+--- a/kpatch-build/Makefile
++++ b/kpatch-build/Makefile
+@@ -16,7 +16,7 @@ else ifeq ($(ARCH),ppc64le)
+ SOURCES += gcc-plugins/ppc64le-plugin.c
+ PLUGIN   = gcc-plugins/ppc64le-plugin.so
+ TARGETS += $(PLUGIN)
+-GCC_PLUGINS_DIR := $(shell gcc -print-file-name=plugin)
++GCC_PLUGINS_DIR := $(shell gcc-9 -print-file-name=plugin)
+ PLUGIN_CFLAGS    = -shared $(CFLAGS) -I$(GCC_PLUGINS_DIR)/include \
+ 		   -Igcc-plugins -fPIC -fno-rtti -O2 -Wall
+ endif
+@@ -31,7 +31,7 @@ create-klp-module: create-klp-module.o k
+ create-kpatch-module: create-kpatch-module.o kpatch-elf.o
+ 
+ $(PLUGIN): gcc-plugins/ppc64le-plugin.c
+-	g++ $(PLUGIN_CFLAGS) $< -o $@
++	g++-9 $(PLUGIN_CFLAGS) $< -o $@
+ 
+ install: all
+ 	$(INSTALL) -d $(LIBEXECDIR)
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -1,5 +1,5 @@
+ SHELL = /bin/sh
+-CC    = gcc
++CC    = gcc-9
+ 
+ INSTALL = /usr/bin/install
+ 
diff -pruN 0.6.0-0.2/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch 0.8.0-0ubuntu7/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch
--- 0.6.0-0.2/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch	2019-01-07 19:38:41.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,41 +0,0 @@
-From: Ben Hutchings <ben@decadent.org.uk>
-Date: Mon, 07 Jan 2019 19:19:42 +0000
-Subject: kmod: Fix symbol lookup on Linux 4.19
-
-Since Linux 4.19, symbols may contain either an absolute address or a
-self-relative offset, depending on
-CONFIG_HAVE_ARCH_PREL32_RELOCATIONS.  The function to resolve the
-address is unfortunately not inline or exported, so copy it here.
-
-Since the configuration symbol didn't exist before, we don't need to
-add an explicit kernel version check.
-
----
---- a/kmod/core/core.c
-+++ b/kmod/core/core.c
-@@ -636,6 +636,16 @@ static int kpatch_find_object_symbol(con
- 	return -EINVAL;
- }
- 
-+/* Copied from kernel/module.c */
-+static unsigned long kernel_symbol_value(const struct kernel_symbol *sym)
-+{
-+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
-+	return (unsigned long)offset_to_ptr(&sym->value_offset);
-+#else
-+	return sym->value;
-+#endif
-+}
-+
- /*
-  * External symbols are located outside the parent object (where the parent
-  * object is either vmlinux or the kmod being patched).
-@@ -651,7 +661,7 @@ static int kpatch_find_external_symbol(c
- 	sym = find_symbol(name, NULL, NULL, true, true);
- 	preempt_enable();
- 	if (sym) {
--		*addr = sym->value;
-+		*addr = kernel_symbol_value(sym);
- 		return 0;
- 	}
- 
diff -pruN 0.6.0-0.2/debian/patches/kpatch-build-works-without-kpatch-kmod.patch 0.8.0-0ubuntu7/debian/patches/kpatch-build-works-without-kpatch-kmod.patch
--- 0.6.0-0.2/debian/patches/kpatch-build-works-without-kpatch-kmod.patch	2018-06-15 22:23:46.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/kpatch-build-works-without-kpatch-kmod.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-Description: only warn if kpatch module isn't available
- kpatch-build checks if the kpatch module is installed properly. In cases where we build
- livepatch modules this is not necessary. Turn these errors into warnings and let the user
- proceed.
-Author: Chris J Arges <chris.j.arges@canonical.com>
-Last-Update: 2016-01-20
-
---- a/kpatch-build/kpatch-build
-+++ b/kpatch-build/kpatch-build
-@@ -109,7 +109,6 @@
- 			SYMVERSFILE="$(readlink -f /lib/modules/$ARCHVERSION/updates/dkms/kpatch.Module.symvers)"
- 		else
- 			warn "unable to find Module.symvers for kpatch core module"
--			return 1
- 		fi
- 		return
- 	fi
-@@ -340,7 +339,7 @@
- 
- find_dirs || die "can't find supporting tools"
- 
--[[ -e "$SYMVERSFILE" ]] || die "can't find core module Module.symvers"
-+[[ -e "$SYMVERSFILE" ]] || warn "can't find core module Module.symvers"
- 
- 
- if [[ $SKIPGCCCHECK -eq 0 ]]; then
diff -pruN 0.6.0-0.2/debian/patches/remove-dkms.patch 0.8.0-0ubuntu7/debian/patches/remove-dkms.patch
--- 0.6.0-0.2/debian/patches/remove-dkms.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/remove-dkms.patch	2019-08-28 17:37:11.000000000 +0000
@@ -0,0 +1,13 @@
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -17,10 +17,5 @@
+ SYSTEMDDIR = $(DESTDIR)$(PREFIX)/lib/systemd/system
+ UPSTARTDIR = $(DESTDIR)/etc/init
+ 
+-# The core module is only supported on x86_64
+-ifeq ($(ARCH),x86_64)
+-BUILDMOD  ?= yes
+-endif
+-
+ .PHONY: all install clean
+ .DEFAULT: all
diff -pruN 0.6.0-0.2/debian/patches/series 0.8.0-0ubuntu7/debian/patches/series
--- 0.6.0-0.2/debian/patches/series	2019-01-07 19:38:32.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/series	2020-12-17 11:58:46.000000000 +0000
@@ -1,4 +1,7 @@
+remove-dkms.patch
+use-debian-rules-for-ubuntu-builds.patch
+ubuntu-kernel-variants.patch
+xenial-shellcheck-fixes.patch
 kpatch-build-adjust-dirs.patch
-Fix-build-err-by-Werror-maybe-uninitialized.patch
-kmod-fix-symbol-lookup-on-linux-4.19.patch
 kpatch-build-fix-clean-target.patch
+gcc-9.diff
diff -pruN 0.6.0-0.2/debian/patches/ubuntu-kernel-variants.patch 0.8.0-0ubuntu7/debian/patches/ubuntu-kernel-variants.patch
--- 0.6.0-0.2/debian/patches/ubuntu-kernel-variants.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/ubuntu-kernel-variants.patch	2019-08-28 17:37:11.000000000 +0000
@@ -0,0 +1,139 @@
+Description: support ubuntu kernel flavors
+ Add support for kernel flavors (generic, lowlatency, aws, etc...) the flavor
+ may contain dashes and/or tildes, so handle these cases.
+
+Author: Benjamin M Romer <benjamin.romer@canonical.com>
+Last-Update: 2018-10-22
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/kpatch-build/kpatch-build
++++ b/kpatch-build/kpatch-build
+@@ -423,7 +423,7 @@
+ 	echo "		                   (not recommended)" >&2
+ }
+ 
+-options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
++options="$(getopt -o ha:r:s:c:v:j:t:n:o:def: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup,flavor:" -- "$@")" || die "getopt failed"
+ 
+ eval set -- "$options"
+ 
+@@ -494,6 +494,10 @@
+ 		echo "WARNING: Skipping gcc version matching check (not recommended)"
+ 		SKIPGCCCHECK=1
+ 		;;
++	-f|--flavor)
++		FLAVOR="$2"
++		shift
++		;;
+ 	*)
+ 		[[ "$1" = "--" ]] && shift && continue
+ 		[[ ! -f "$1" ]] && die "patch file '$1' not found"
+@@ -551,11 +555,23 @@
+ 
+ 		# Extract the target kernel version from vmlinux in this case.
+ 		ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')"
++		FLAV=${ARCHVERSION#*-*-}
++		if [[ -n "$FLAVOR" ]]; then
++			if [[ "$FLAVOR" != "$FLAV" ]]; then
++				die "specified flavor $FLAVOR does not match vmlinux ($FLAV)"
++			fi
++		else
++			FLAVOR=$FLAV
++		fi
+ 	else
+ 		ARCHVERSION="$(modinfo -F vermagic "$OOT_MODULE" | awk '{print $1}')"
+ 	fi
+ fi
+ 
++if [[ -z "$FLAVOR" ]]; then
++	FLAVOR=$(uname -r | cut -d - -f 3)
++fi
++
+ [[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)"
+ 
+ [[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP
+@@ -775,7 +791,7 @@
+ 	fakeroot debian/rules clean 2>&1 | logger || die
+ 	# shellcheck disable=SC1117
+ 	MAKEFLAGS="--no-print-directory" fakeroot \
+-		debian/rules -j "$CPUS"	build-generic build_image=vmlinux \
++		debian/rules -j "$CPUS"	"build-$FLAVOR" build_image=vmlinux \
+ 		builddir="$TEMPDIR" enable_zfs=false \
+ 		CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ "  2>&1 | logger \
+ 		|| die
+@@ -794,10 +810,10 @@
+ KPATCH_GCC_SRCDIR="$SRCDIR"
+ export KPATCH_GCC_SRCDIR
+ if [[ $DISTRO = ubuntu ]]; then
+-	rm -f debian/stamps/stamp-build-generic
++	rm -f "debian/stamps/stamp-build-$FLAVOR"
+ 	# shellcheck disable=SC1117
+ 	  MAKEFLAGS="--no-print-directory" fakeroot \
+-	  debian/rules -j "$CPUS" build-generic build_image=vmlinux \
++	  debian/rules -j "$CPUS" "build-$FLAVOR" build_image=vmlinux \
+ 	  CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " enable_zfs=false \
+ 	  LDFLAGS_vmlinux="--warn-unresolved-symbols" \
+ 	  KBUILD_MODPOST_WARN=1 builddir="$TEMPDIR" 2>&1 | logger || die
+@@ -821,7 +837,7 @@
+ fi
+ 
+ if [[ $DISTRO = ubuntu ]]; then
+-	[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-generic/Module.symvers" || die "truncated $TEMPDIR/build-generic/Module.symvers file"
++	[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-$FLAVOR/Module.symvers" || die "truncated $TEMPDIR/build-$FLAVOR/Module.symvers file"
+ else
+ 	[[ -n "$OOT_MODULE" ]] ||grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
+ fi
+@@ -832,7 +848,7 @@
+ do
+ 	mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
+ 	if [[ $DISTRO = ubuntu ]]; then
+-		cp -f "$TEMPDIR/build-generic/$i" "$TEMPDIR/patched/$i" || die
++		cp -f "$TEMPDIR/build-$FLAVOR/$i" "$TEMPDIR/patched/$i" || die
+ 	else
+ 		cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ 	fi
+@@ -878,7 +894,7 @@
+ 
+ 	mkdir -p "output/$(dirname "$i")"
+ 	if [[ "$DISTRO" = ubuntu ]]; then
+-		cd "$TEMPDIR/build-generic" || die
++		cd "$TEMPDIR/build-$FLAVOR" || die
+ 	else
+ 		cd "$SRCDIR" || die
+ 	fi
+@@ -890,7 +906,7 @@
+ 			KOBJFILE_PATH="$VMLINUX"
+ 			SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
+ 			if [[ "$DISTRO" = ubuntu ]]; then
+-				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++				SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers"
+ 			else
+ 				SYMVERS_FILE="$SRCDIR/Module.symvers"
+ 			fi
+@@ -899,7 +915,7 @@
+ 			KOBJFILE_PATH="$OOT_MODULE"
+ 			SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab"
+ 			if [[ "$DISTRO" = ubuntu ]]; then
+-				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++				SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers"
+ 			else
+ 				SYMVERS_FILE="$SRCDIR/Module.symvers"
+ 			fi
+@@ -912,7 +928,7 @@
+ 			KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
+ 			SYMTAB="${KOBJFILE_PATH}.symtab"
+ 			if [[ "$DISTRO" = ubuntu ]]; then
+-				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++				SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers"
+ 			else
+ 				SYMVERS_FILE="$SRCDIR/Module.symvers"
+ 			fi
+@@ -983,7 +999,7 @@
+ cd "$TEMPDIR/patch" || die
+ if [[ -z "$OOT_MODULE" ]]; then
+ 	if [[ "$DISTRO" == ubuntu ]]; then
+-		KPATCH_BUILD="$TEMPDIR/build-generic"
++		KPATCH_BUILD="$TEMPDIR/build-$FLAVOR"
+ 	else
+ 		KPATCH_BUILD="$SRCDIR"
+ 	fi
diff -pruN 0.6.0-0.2/debian/patches/use-debian-rules-for-ubuntu-builds.patch 0.8.0-0ubuntu7/debian/patches/use-debian-rules-for-ubuntu-builds.patch
--- 0.6.0-0.2/debian/patches/use-debian-rules-for-ubuntu-builds.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/use-debian-rules-for-ubuntu-builds.patch	2019-08-28 17:37:11.000000000 +0000
@@ -0,0 +1,209 @@
+Description: Use Ubuntu-style build for Livepatch Generation
+ This patch changes the livepatch mechanism for Ubuntu. Instead of using
+ the kernel makefile directly, the build is performed using debian/rules,
+ so it matches how the Ubuntu kernel is actually made.
+
+Author: Benjamin M Romer <benjamin.romer@canonical.com>
+Last-Update: 2019-08-29
+
+--- a/kpatch-build/kpatch-build
++++ b/kpatch-build/kpatch-build
+@@ -117,8 +117,9 @@
+ 
+ 	remove_patches
+ 
+-	# restore original vmlinux if it was overwritten by sourcedir build
++	# restore original vmlinux and debian if it was overwritten by sourcedir build
+ 	[[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/"
++	[[ -e "$TEMPDIR/debian.bak" ]] && cp -rf "$TEMPDIR/debian.bak" "$SRCDIR/debian"
+ 
+ 	[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
+ 	rm -rf "$RPMTOPDIR"
+@@ -611,6 +612,9 @@
+ 		CONFIGFILE="/boot/config-${ARCHVERSION}"
+ 	fi
+ 
++	# save debian before it gets removed with mrproper
++	[[ -e "$SRCDIR/debian" ]] && cp -rf "$SRCDIR/debian" "$TEMPDIR/debian.bak"
++
+ elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then
+ 	echo "Using cache at $SRCDIR"
+ 
+@@ -681,9 +685,7 @@
+ 		(dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}"
+ 		mv "${pkgname}-$KVER" "$SRCDIR" || die
+ 		[[ -z "$CONFIGFILE" ]] && CONFIGFILE="/boot/config-${ARCHVERSION}"
+-		if [[ "$ARCHVERSION" == *-* ]]; then
+-			echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
+-		fi
++
+ 		# for some reason the Ubuntu kernel versions don't follow the
+ 		# upstream SUBLEVEL; they are always at SUBLEVEL 0
+ 		sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die
+@@ -766,10 +768,23 @@
+ 
+ echo "Building original source"
+ [[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die
+-unset KPATCH_GCC_TEMPDIR
+-# $TARGETS used as list, no quotes.
+-# shellcheck disable=SC2086
+-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
++if [[ $DISTRO = ubuntu ]]; then
++	mv "$SRCDIR/debian" "$SRCDIR/debian.master" "$TEMPDIR"
++	make mrproper 2>&1 | logger || die
++	mv "$TEMPDIR/debian" "$TEMPDIR/debian.master" "$SRCDIR"
++	fakeroot debian/rules clean 2>&1 | logger || die
++	# shellcheck disable=SC1117
++	MAKEFLAGS="--no-print-directory" fakeroot \
++		debian/rules -j "$CPUS"	build-generic build_image=vmlinux \
++		builddir="$TEMPDIR" enable_zfs=false \
++		CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ "  2>&1 | logger \
++		|| die
++else
++	unset KPATCH_GCC_TEMPDIR
++	# $TARGETS used as list, no quotes.
++	# shellcheck disable=SC2086
++	CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
++fi
+ 
+ echo "Building patched source"
+ apply_patches
+@@ -778,11 +793,21 @@
+ export KPATCH_GCC_TEMPDIR
+ KPATCH_GCC_SRCDIR="$SRCDIR"
+ export KPATCH_GCC_SRCDIR
+-# $TARGETS used as list, no quotes.
+-# shellcheck disable=SC2086
+-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+-	KBUILD_MODPOST_WARN=1 \
+-	make "-j$CPUS" $TARGETS 2>&1 | logger || die
++if [[ $DISTRO = ubuntu ]]; then
++	rm -f debian/stamps/stamp-build-generic
++	# shellcheck disable=SC1117
++	  MAKEFLAGS="--no-print-directory" fakeroot \
++	  debian/rules -j "$CPUS" build-generic build_image=vmlinux \
++	  CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " enable_zfs=false \
++	  LDFLAGS_vmlinux="--warn-unresolved-symbols" \
++	  KBUILD_MODPOST_WARN=1 builddir="$TEMPDIR" 2>&1 | logger || die
++else
++	# $TARGETS used as list, no quotes.
++	# shellcheck disable=SC2086
++	CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
++		KBUILD_MODPOST_WARN=1 \
++		make "-j$CPUS" $TARGETS 2>&1 | logger || die
++fi
+ 
+ # source.c:(.section+0xFF): undefined reference to `symbol'
+ grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
+@@ -795,14 +820,22 @@
+ 	die "no changed objects found"
+ fi
+ 
+-[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
++if [[ $DISTRO = ubuntu ]]; then
++	[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-generic/Module.symvers" || die "truncated $TEMPDIR/build-generic/Module.symvers file"
++else
++	[[ -n "$OOT_MODULE" ]] ||grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
++fi
+ 
+ # Read as words, no quotes.
+ # shellcheck disable=SC2013
+ for i in $(cat "$TEMPDIR/changed_objs")
+ do
+ 	mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
+-	cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
++	if [[ $DISTRO = ubuntu ]]; then
++		cp -f "$TEMPDIR/build-generic/$i" "$TEMPDIR/patched/$i" || die
++	else
++		cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
++	fi
+ done
+ 
+ echo "Extracting new and modified ELF sections"
+@@ -844,7 +877,11 @@
+ 	[[ "$i" = usr/initramfs_data.o ]] && continue
+ 
+ 	mkdir -p "output/$(dirname "$i")"
+-	cd "$SRCDIR" || die
++	if [[ "$DISTRO" = ubuntu ]]; then
++		cd "$TEMPDIR/build-generic" || die
++	else
++		cd "$SRCDIR" || die
++	fi
+ 	find_kobj "$i"
+ 	cd "$TEMPDIR" || die
+ 	if [[ -e "orig/$i" ]]; then
+@@ -852,12 +889,20 @@
+ 			KOBJFILE_NAME=vmlinux
+ 			KOBJFILE_PATH="$VMLINUX"
+ 			SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
+-			SYMVERS_FILE="$SRCDIR/Module.symvers"
++			if [[ "$DISTRO" = ubuntu ]]; then
++				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++			else
++				SYMVERS_FILE="$SRCDIR/Module.symvers"
++			fi
+ 		elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then
+ 			KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")"
+ 			KOBJFILE_PATH="$OOT_MODULE"
+ 			SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab"
+-			SYMVERS_FILE="$TEMPDIR/Module.symvers"
++			if [[ "$DISTRO" = ubuntu ]]; then
++				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++			else
++				SYMVERS_FILE="$SRCDIR/Module.symvers"
++			fi
+ 			BUILDDIR="/lib/modules/$ARCHVERSION/build/"
+ 			cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+ 			awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
+@@ -866,7 +911,11 @@
+ 			KOBJFILE_NAME="${KOBJFILE_NAME/-/_}"
+ 			KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
+ 			SYMTAB="${KOBJFILE_PATH}.symtab"
+-			SYMVERS_FILE="$SRCDIR/Module.symvers"
++			if [[ "$DISTRO" = ubuntu ]]; then
++				SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers"
++			else
++				SYMVERS_FILE="$SRCDIR/Module.symvers"
++			fi
+ 		fi
+ 
+ 		readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
+@@ -915,13 +964,6 @@
+ 
+ echo "Building patch module: $MODNAME.ko"
+ 
+-if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
+-	# UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it
+-	UBUNTU_ABI="${ARCHVERSION#*-}"
+-	UBUNTU_ABI="${UBUNTU_ABI%-*}"
+-	echo "#define UTS_UBUNTU_RELEASE_ABI $UBUNTU_ABI" >> "$SRCDIR"/include/generated/utsrelease.h
+-fi
+-
+ cd "$TEMPDIR/output" || die
+ # $KPATCH_LDFLAGS and result of find used as list, no quotes.
+ # shellcheck disable=SC2086,SC2046
+@@ -940,7 +982,11 @@
+ 
+ cd "$TEMPDIR/patch" || die
+ if [[ -z "$OOT_MODULE" ]]; then
+-	KPATCH_BUILD="$SRCDIR"
++	if [[ "$DISTRO" == ubuntu ]]; then
++		KPATCH_BUILD="$TEMPDIR/build-generic"
++	else
++		KPATCH_BUILD="$SRCDIR"
++	fi
+ else
+ 	KPATCH_BUILD="/lib/modules/$ARCHVERSION/build"
+ fi
+--- a/kpatch-build/kpatch-gcc
++++ b/kpatch-build/kpatch-gcc
+@@ -16,7 +16,7 @@
+ if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
+ 	while [ "$#" -gt 0 ]; do
+ 		if [ "$1" = "-o" ]; then
+-			obj="$2"
++			obj="${2##"$EXTDIR"}"
+ 
+ 			# skip copying the temporary .o files created by
+ 			# recordmcount.pl
diff -pruN 0.6.0-0.2/debian/patches/xenial-shellcheck-fixes.patch 0.8.0-0ubuntu7/debian/patches/xenial-shellcheck-fixes.patch
--- 0.6.0-0.2/debian/patches/xenial-shellcheck-fixes.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/patches/xenial-shellcheck-fixes.patch	2019-08-28 17:37:11.000000000 +0000
@@ -0,0 +1,40 @@
+--- a/kpatch-build/kpatch-build
++++ b/kpatch-build/kpatch-build
+@@ -689,7 +689,9 @@
+ 			sublevel="SUBLEVEL ="
+ 		fi
+ 
++		# shellcheck disable=SC2016
+ 		pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)"
++		# shellcheck disable=SC2016
+ 		pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")"
+ 		dscname="${pkgname}_${pkgver}.dsc"
+ 
+--- a/kpatch-build/kpatch-gcc
++++ b/kpatch-build/kpatch-gcc
+@@ -13,6 +13,7 @@
+ 
+ declare -a args=("$@")
+ 
++# shellcheck disable=SC2076
+ if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
+ 	while [ "$#" -gt 0 ]; do
+ 		if [ "$1" = "-o" ]; then
+--- a/kpatch/kpatch
++++ b/kpatch/kpatch
+@@ -310,6 +310,7 @@
+ 			out="$(LC_ALL=C insmod "$module" 2>&1)"
+ 			[[ -z "$out" ]] && break
+ 			echo "$out" 1>&2
++			# shellcheck disable=SC2076
+ 			[[ ! "$out" =~ "Device or resource busy" ]] &&
+ 				die "failed to load module $module"
+ 
+@@ -348,6 +349,7 @@
+ 			out="$(export LC_ALL=C; sh -c "echo 0 > $enabled" 2>&1)"
+ 			[[ -z "$out" ]] && break
+ 			echo "$out" 1>&2
++			# shellcheck disable=SC2076
+ 			if [[ ! "$out" =~ "Device or resource busy" ]]; then
+ 				die "failed to disable module $modname"
+ 			fi
diff -pruN 0.6.0-0.2/debian/post-dkms.sh 0.8.0-0ubuntu7/debian/post-dkms.sh
--- 0.6.0-0.2/debian/post-dkms.sh	2018-06-15 22:23:46.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/post-dkms.sh	1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-#!/bin/bash
-module_version=$1
-kernelver=$2
-mkdir -p /lib/modules/$kernelver/updates/dkms
-cp /var/lib/dkms/kpatch/$module_version/build/kmod/core/Module.symvers /lib/modules/$kernelver/updates/dkms/kpatch.Module.symvers
diff -pruN 0.6.0-0.2/debian/rules 0.8.0-0ubuntu7/debian/rules
--- 0.6.0-0.2/debian/rules	2019-01-07 19:34:02.000000000 +0000
+++ 0.8.0-0ubuntu7/debian/rules	2020-12-11 12:16:25.000000000 +0000
@@ -15,10 +15,3 @@ override_dh_auto_install:
 override_dh_auto_test:
 	-dh_auto_test
 
-override_dh_install:
-	mkdir -p debian/tmp/usr/src/kpatch-$(VERSION)
-	dh_install -pkpatch-dkms -X.o -X.ko -Xkmod/patch kmod/ usr/src/kpatch-$(VERSION)
-	dh_install -pkpatch-dkms Makefile.inc usr/src/kpatch-$(VERSION)
-	dh_install -pkpatch-dkms debian/post-dkms.sh usr/src/kpatch-$(VERSION)
-	dh_dkms -V $(VERSION)
-	dh_install
diff -pruN 0.6.0-0.2/.git/config 0.8.0-0ubuntu7/.git/config
--- 0.6.0-0.2/.git/config	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/config	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	url = https://github.com/dynup/kpatch.git
+	fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -pruN 0.6.0-0.2/.git/description 0.8.0-0ubuntu7/.git/description
--- 0.6.0-0.2/.git/description	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/description	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -pruN 0.6.0-0.2/.git/HEAD 0.8.0-0ubuntu7/.git/HEAD
--- 0.6.0-0.2/.git/HEAD	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/HEAD	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+ref: refs/heads/master
diff -pruN 0.6.0-0.2/.git/hooks/applypatch-msg.sample 0.8.0-0ubuntu7/.git/hooks/applypatch-msg.sample
--- 0.6.0-0.2/.git/hooks/applypatch-msg.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/applypatch-msg.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
+test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
+:
diff -pruN 0.6.0-0.2/.git/hooks/commit-msg.sample 0.8.0-0ubuntu7/.git/hooks/commit-msg.sample
--- 0.6.0-0.2/.git/hooks/commit-msg.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/commit-msg.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -pruN 0.6.0-0.2/.git/hooks/fsmonitor-watchman.sample 0.8.0-0ubuntu7/.git/hooks/fsmonitor-watchman.sample
--- 0.6.0-0.2/.git/hooks/fsmonitor-watchman.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/fsmonitor-watchman.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,114 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use IPC::Open2;
+
+# An example hook script to integrate Watchman
+# (https://facebook.github.io/watchman/) with git to speed up detecting
+# new and modified files.
+#
+# The hook is passed a version (currently 1) and a time in nanoseconds
+# formatted as a string and outputs to stdout all files that have been
+# modified since the given time. Paths must be relative to the root of
+# the working tree and separated by a single NUL.
+#
+# To enable this hook, rename this file to "query-watchman" and set
+# 'git config core.fsmonitor .git/hooks/query-watchman'
+#
+my ($version, $time) = @ARGV;
+
+# Check the hook interface version
+
+if ($version == 1) {
+	# convert nanoseconds to seconds
+	$time = int $time / 1000000000;
+} else {
+	die "Unsupported query-fsmonitor hook version '$version'.\n" .
+	    "Falling back to scanning...\n";
+}
+
+my $git_work_tree;
+if ($^O =~ 'msys' || $^O =~ 'cygwin') {
+	$git_work_tree = Win32::GetCwd();
+	$git_work_tree =~ tr/\\/\//;
+} else {
+	require Cwd;
+	$git_work_tree = Cwd::cwd();
+}
+
+my $retry = 1;
+
+launch_watchman();
+
+sub launch_watchman {
+
+	my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
+	    or die "open2() failed: $!\n" .
+	    "Falling back to scanning...\n";
+
+	# In the query expression below we're asking for names of files that
+	# changed since $time but were not transient (ie created after
+	# $time but no longer exist).
+	#
+	# To accomplish this, we're using the "since" generator to use the
+	# recency index to select candidate nodes and "fields" to limit the
+	# output to file names only. Then we're using the "expression" term to
+	# further constrain the results.
+	#
+	# The category of transient files that we want to ignore will have a
+	# creation clock (cclock) newer than $time_t value and will also not
+	# currently exist.
+
+	my $query = <<"	END";
+		["query", "$git_work_tree", {
+			"since": $time,
+			"fields": ["name"],
+			"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
+		}]
+	END
+
+	print CHLD_IN $query;
+	close CHLD_IN;
+	my $response = do {local $/; <CHLD_OUT>};
+
+	die "Watchman: command returned no output.\n" .
+	    "Falling back to scanning...\n" if $response eq "";
+	die "Watchman: command returned invalid output: $response\n" .
+	    "Falling back to scanning...\n" unless $response =~ /^\{/;
+
+	my $json_pkg;
+	eval {
+		require JSON::XS;
+		$json_pkg = "JSON::XS";
+		1;
+	} or do {
+		require JSON::PP;
+		$json_pkg = "JSON::PP";
+	};
+
+	my $o = $json_pkg->new->utf8->decode($response);
+
+	if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
+		print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
+		$retry--;
+		qx/watchman watch "$git_work_tree"/;
+		die "Failed to make watchman watch '$git_work_tree'.\n" .
+		    "Falling back to scanning...\n" if $? != 0;
+
+		# Watchman will always return all files on the first query so
+		# return the fast "everything is dirty" flag to git and do the
+		# Watchman query just to get it over with now so we won't pay
+		# the cost in git to look up each individual file.
+		print "/\0";
+		eval { launch_watchman() };
+		exit 0;
+	}
+
+	die "Watchman: $o->{error}.\n" .
+	    "Falling back to scanning...\n" if $o->{error};
+
+	binmode STDOUT, ":utf8";
+	local $, = "\0";
+	print @{$o->{files}};
+}
diff -pruN 0.6.0-0.2/.git/hooks/post-update.sample 0.8.0-0ubuntu7/.git/hooks/post-update.sample
--- 0.6.0-0.2/.git/hooks/post-update.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/post-update.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -pruN 0.6.0-0.2/.git/hooks/pre-applypatch.sample 0.8.0-0ubuntu7/.git/hooks/pre-applypatch.sample
--- 0.6.0-0.2/.git/hooks/pre-applypatch.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/pre-applypatch.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+precommit="$(git rev-parse --git-path hooks/pre-commit)"
+test -x "$precommit" && exec "$precommit" ${1+"$@"}
+:
diff -pruN 0.6.0-0.2/.git/hooks/pre-commit.sample 0.8.0-0ubuntu7/.git/hooks/pre-commit.sample
--- 0.6.0-0.2/.git/hooks/pre-commit.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/pre-commit.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=$(git hash-object -t tree /dev/null)
+fi
+
+# If you want to allow non-ASCII filenames set this variable to true.
+allownonascii=$(git config --bool hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ASCII filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	cat <<\EOF
+Error: Attempt to add a non-ASCII file name.
+
+This can cause problems if you want to work with people on other platforms.
+
+To be portable it is advisable to rename the file.
+
+If you know what you are doing you can disable this check using:
+
+  git config hooks.allownonascii true
+EOF
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -pruN 0.6.0-0.2/.git/hooks/prepare-commit-msg.sample 0.8.0-0ubuntu7/.git/hooks/prepare-commit-msg.sample
--- 0.6.0-0.2/.git/hooks/prepare-commit-msg.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/prepare-commit-msg.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples. The first one removes the
+# "# Please enter the commit message..." help message.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+COMMIT_MSG_FILE=$1
+COMMIT_SOURCE=$2
+SHA1=$3
+
+/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
+
+# case "$COMMIT_SOURCE,$SHA1" in
+#  ,|template,)
+#    /usr/bin/perl -i.bak -pe '
+#       print "\n" . `git diff --cached --name-status -r`
+# 	 if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
+#  *) ;;
+# esac
+
+# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
+# if test -z "$COMMIT_SOURCE"
+# then
+#   /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
+# fi
diff -pruN 0.6.0-0.2/.git/hooks/pre-push.sample 0.8.0-0ubuntu7/.git/hooks/pre-push.sample
--- 0.6.0-0.2/.git/hooks/pre-push.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/pre-push.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# An example hook script to verify what is about to be pushed.  Called by "git
+# push" after it has checked the remote status, but before anything has been
+# pushed.  If this script exits with a non-zero status nothing will be pushed.
+#
+# This hook is called with the following parameters:
+#
+# $1 -- Name of the remote to which the push is being done
+# $2 -- URL to which the push is being done
+#
+# If pushing without using a named remote those arguments will be equal.
+#
+# Information about the commits which are being pushed is supplied as lines to
+# the standard input in the form:
+#
+#   <local ref> <local sha1> <remote ref> <remote sha1>
+#
+# This sample shows how to prevent push of commits where the log message starts
+# with "WIP" (work in progress).
+
+remote="$1"
+url="$2"
+
+z40=0000000000000000000000000000000000000000
+
+while read local_ref local_sha remote_ref remote_sha
+do
+	if [ "$local_sha" = $z40 ]
+	then
+		# Handle delete
+		:
+	else
+		if [ "$remote_sha" = $z40 ]
+		then
+			# New branch, examine all commits
+			range="$local_sha"
+		else
+			# Update to existing branch, examine new commits
+			range="$remote_sha..$local_sha"
+		fi
+
+		# Check for WIP commit
+		commit=`git rev-list -n 1 --grep '^WIP' "$range"`
+		if [ -n "$commit" ]
+		then
+			echo >&2 "Found WIP commit in $local_ref, not pushing"
+			exit 1
+		fi
+	fi
+done
+
+exit 0
diff -pruN 0.6.0-0.2/.git/hooks/pre-rebase.sample 0.8.0-0ubuntu7/.git/hooks/pre-rebase.sample
--- 0.6.0-0.2/.git/hooks/pre-rebase.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/pre-rebase.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up to date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -pruN 0.6.0-0.2/.git/hooks/pre-receive.sample 0.8.0-0ubuntu7/.git/hooks/pre-receive.sample
--- 0.6.0-0.2/.git/hooks/pre-receive.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/pre-receive.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to make use of push options.
+# The example simply echoes all push options that start with 'echoback='
+# and rejects all pushes when the "reject" push option is used.
+#
+# To enable this hook, rename this file to "pre-receive".
+
+if test -n "$GIT_PUSH_OPTION_COUNT"
+then
+	i=0
+	while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
+	do
+		eval "value=\$GIT_PUSH_OPTION_$i"
+		case "$value" in
+		echoback=*)
+			echo "echo from the pre-receive-hook: ${value#*=}" >&2
+			;;
+		reject)
+			exit 1
+		esac
+		i=$((i + 1))
+	done
+fi
diff -pruN 0.6.0-0.2/.git/hooks/update.sample 0.8.0-0ubuntu7/.git/hooks/update.sample
--- 0.6.0-0.2/.git/hooks/update.sample	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/hooks/update.sample	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to block unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
Binary files 0.6.0-0.2/.git/index and 0.8.0-0ubuntu7/.git/index differ
diff -pruN 0.6.0-0.2/.git/info/exclude 0.8.0-0ubuntu7/.git/info/exclude
--- 0.6.0-0.2/.git/info/exclude	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/info/exclude	2019-08-28 17:33:59.000000000 +0000
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff -pruN 0.6.0-0.2/.git/logs/HEAD 0.8.0-0ubuntu7/.git/logs/HEAD
--- 0.6.0-0.2/.git/logs/HEAD	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/logs/HEAD	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer <benjamin.romer@canonical.com> 1567013640 -0400	clone: from https://github.com/dynup/kpatch.git
diff -pruN 0.6.0-0.2/.git/logs/refs/heads/master 0.8.0-0ubuntu7/.git/logs/refs/heads/master
--- 0.6.0-0.2/.git/logs/refs/heads/master	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/logs/refs/heads/master	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer <benjamin.romer@canonical.com> 1567013640 -0400	clone: from https://github.com/dynup/kpatch.git
diff -pruN 0.6.0-0.2/.git/logs/refs/remotes/origin/HEAD 0.8.0-0ubuntu7/.git/logs/refs/remotes/origin/HEAD
--- 0.6.0-0.2/.git/logs/refs/remotes/origin/HEAD	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/logs/refs/remotes/origin/HEAD	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer <benjamin.romer@canonical.com> 1567013640 -0400	clone: from https://github.com/dynup/kpatch.git
Binary files 0.6.0-0.2/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.idx and 0.8.0-0ubuntu7/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.idx differ
Binary files 0.6.0-0.2/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.pack and 0.8.0-0ubuntu7/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.pack differ
diff -pruN 0.6.0-0.2/.git/packed-refs 0.8.0-0ubuntu7/.git/packed-refs
--- 0.6.0-0.2/.git/packed-refs	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/packed-refs	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,31 @@
+# pack-refs with: peeled fully-peeled sorted 
+30a7dd677bcc25bd70070f7f9d16a88c190b8b0b refs/remotes/origin/master
+258ac3f39a14d52d73868d24770b5b6f5786eca2 refs/tags/0.5.0
+135b438af0b9c9d903b01b3386c74add1401dda1 refs/tags/v0.1.0
+0f3f8ae3369cec5be61c73bf559a8df0c82f9df4 refs/tags/v0.1.1
+6ed046f1c2a770099ae984e305fc2260480749f0 refs/tags/v0.1.10
+2601b154d3351b3411043fcff4ccd71fbb039e1d refs/tags/v0.1.2
+a705c223fc6efa87a8d7521c791e9515ad6d981c refs/tags/v0.1.3
+3ca8106987bad32dcc60ff9c54d687b92033c0c1 refs/tags/v0.1.4
+f4bba70412801a475eed21087e2dd8cae6b94996 refs/tags/v0.1.5
+92fb49e6f2ec98684b35df6f50976e25fa8eced8 refs/tags/v0.1.6
+44ad2ba733063438616ecbf4222da5caebd62a6e refs/tags/v0.1.7
+576ee094420918c6d431d9d97b135046f138e919 refs/tags/v0.1.8
+ce8bb40fc06cc2cd6c4d02199ee3a895bfadb551 refs/tags/v0.1.9
+688a03d8b629287a5ffb501bfa28dd9a3781e10f refs/tags/v0.2.0
+0fd7f7f0be4287e95af4d2c69e57865fea63dcb1 refs/tags/v0.2.1
+f817265c5adbc11b71f853b804cfacd6ab85db7c refs/tags/v0.2.2
+f4b5eded0c14ef4f2d6b6d801f1519659e84e217 refs/tags/v0.3.0
+b60d3acddb7b96b3b6dd7a4c519189a05b0a4d18 refs/tags/v0.3.1
+706b63ad99cc00c539970961b1950da303cb1f3b refs/tags/v0.3.2
+fa557bd11da59a9a4aea20f3a74125ead2477792 refs/tags/v0.3.3
+4e1a5962dabf08b6aefe2584c28d26fc594e8fb6 refs/tags/v0.3.4
+810f9243826219cca9276d364512bb88411aa863 refs/tags/v0.4.0
+258ac3f39a14d52d73868d24770b5b6f5786eca2 refs/tags/v0.5.0
+d5eb921af14b707079ce70809ad64eddfdb1f00f refs/tags/v0.6.0
+7f550f01bd308cf058ae782327d29c8916cc5602 refs/tags/v0.6.1
+7305d6c29a45594c44036601e42909b5e5132bdc refs/tags/v0.6.2
+f4ed9ff76997114ed838a3b964508d721f19f293 refs/tags/v0.6.3
+535e91767900c12ccd49eb5c9fe1732a0c1d85bb refs/tags/v0.7.0
+d7c5810e2a6acacfa5fec1e38d2f75af8e8c818c refs/tags/v0.7.1
+2a29bc7dea9a7da12705c7b50315eee1acdd9156 refs/tags/v0.8.0
diff -pruN 0.6.0-0.2/.git/refs/heads/master 0.8.0-0ubuntu7/.git/refs/heads/master
--- 0.6.0-0.2/.git/refs/heads/master	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/refs/heads/master	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+30a7dd677bcc25bd70070f7f9d16a88c190b8b0b
diff -pruN 0.6.0-0.2/.git/refs/remotes/origin/HEAD 0.8.0-0ubuntu7/.git/refs/remotes/origin/HEAD
--- 0.6.0-0.2/.git/refs/remotes/origin/HEAD	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.git/refs/remotes/origin/HEAD	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
diff -pruN 0.6.0-0.2/.gitattributes 0.8.0-0ubuntu7/.gitattributes
--- 0.6.0-0.2/.gitattributes	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/.gitattributes	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-*.ORIG.o filter=lfs diff=lfs merge=lfs -text
-*.PATCHED.o filter=lfs diff=lfs merge=lfs -text
-*.PATCHED.FAIL.o filter=lfs diff=lfs merge=lfs -text
diff -pruN 0.6.0-0.2/.gitignore 0.8.0-0ubuntu7/.gitignore
--- 0.6.0-0.2/.gitignore	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/.gitignore	2019-08-28 17:34:00.000000000 +0000
@@ -7,10 +7,6 @@
 *.swp
 *.d
 *.so
-*.test.out
-!*.ORIG.o
-!*.PATCHED.o
-!*.PATCHED.FAIL.o
 .tmp_versions
 Module.symvers
 kmod/core/.cache.mk
diff -pruN 0.6.0-0.2/.gitmodules 0.8.0-0ubuntu7/.gitmodules
--- 0.6.0-0.2/.gitmodules	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/.gitmodules	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+[submodule "test/unit/objs"]
+	path = test/unit/objs
+	url = https://github.com/dynup/kpatch-unit-test-objs.git
diff -pruN 0.6.0-0.2/kmod/core/core.c 0.8.0-0ubuntu7/kmod/core/core.c
--- 0.6.0-0.2/kmod/core/core.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kmod/core/core.c	2019-08-28 17:34:00.000000000 +0000
@@ -83,6 +83,11 @@ struct kpatch_kallsyms_args {
 	unsigned long pos;
 };
 
+struct kpatch_apply_patch_args {
+	struct kpatch_module *kpmod;
+	bool replace;
+};
+
 /* this is a double loop, use goto instead of break */
 #define do_for_each_linked_func(kpmod, func) {				\
 	struct kpatch_object *_object;					\
@@ -207,7 +212,8 @@ static inline int kpatch_compare_address
 }
 
 static int kpatch_backtrace_address_verify(struct kpatch_module *kpmod,
-					   unsigned long address)
+					   unsigned long address,
+					   bool replace)
 {
 	struct kpatch_func *func;
 	int i;
@@ -242,8 +248,11 @@ static int kpatch_backtrace_address_veri
 	} while_for_each_linked_func();
 
 	/* in the replace case, need to check the func hash as well */
-	hash_for_each_rcu(kpatch_func_hash, i, func, node) {
-		if (func->op == KPATCH_OP_UNPATCH && !func->force) {
+	if (replace) {
+		hash_for_each_rcu(kpatch_func_hash, i, func, node) {
+			if (func->op != KPATCH_OP_UNPATCH || func->force)
+				continue;
+
 			ret = kpatch_compare_addresses(address,
 						       func->new_addr,
 						       func->new_size,
@@ -262,7 +271,8 @@ static int kpatch_backtrace_address_veri
  *
  * This function is called from stop_machine() context.
  */
-static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod)
+static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod,
+					   bool replace)
 {
 	struct task_struct *g, *t;
 	int i;
@@ -284,7 +294,8 @@ static int kpatch_verify_activeness_safe
 			if (trace.entries[i] == ULONG_MAX)
 				break;
 			ret = kpatch_backtrace_address_verify(kpmod,
-							      trace.entries[i]);
+							      trace.entries[i],
+							      replace);
 			if (ret)
 				goto out;
 		}
@@ -350,12 +361,17 @@ static inline void post_unpatch_callback
 /* Called from stop_machine */
 static int kpatch_apply_patch(void *data)
 {
-	struct kpatch_module *kpmod = data;
+	struct kpatch_apply_patch_args *args = data;
+	struct kpatch_module *kpmod;
 	struct kpatch_func *func;
+	struct hlist_node *tmp;
 	struct kpatch_object *object;
 	int ret;
+	int i;
 
-	ret = kpatch_verify_activeness_safety(kpmod);
+	kpmod = args->kpmod;
+
+	ret = kpatch_verify_activeness_safety(kpmod, args->replace);
 	if (ret) {
 		kpatch_state_finish(KPATCH_STATE_FAILURE);
 		return ret;
@@ -396,6 +412,19 @@ static int kpatch_apply_patch(void *data
 		goto err;
 	}
 
+	/*
+	 * The new patch has been applied successfully. Remove the functions
+	 * provided by the replaced patches (if any) from hash, to make sure
+	 * they will not be executed anymore.
+	 */
+	if (args->replace) {
+		hash_for_each_safe(kpatch_func_hash, i, tmp, func, node) {
+			if (func->op != KPATCH_OP_UNPATCH)
+				continue;
+			hash_del_rcu(&func->node);
+		}
+	}
+
 	/* run any user-defined post-patch callbacks */
 	list_for_each_entry(object, &kpmod->objects, list)
 		post_patch_callback(object);
@@ -417,7 +446,7 @@ static int kpatch_remove_patch(void *dat
 	struct kpatch_object *object;
 	int ret;
 
-	ret = kpatch_verify_activeness_safety(kpmod);
+	ret = kpatch_verify_activeness_safety(kpmod, false);
 	if (ret) {
 		kpatch_state_finish(KPATCH_STATE_FAILURE);
 		return ret;
@@ -651,7 +680,11 @@ static int kpatch_find_external_symbol(c
 	sym = find_symbol(name, NULL, NULL, true, true);
 	preempt_enable();
 	if (sym) {
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+		*addr = (unsigned long)offset_to_ptr(&sym->value_offset);
+#else
 		*addr = sym->value;
+#endif
 		return 0;
 	}
 
@@ -696,6 +729,7 @@ static int kpatch_write_relocations(stru
 		case R_X86_64_NONE:
 			continue;
 		case R_X86_64_PC32:
+		case R_X86_64_PLT32:
 			loc = dynrela->dest;
 			val = (u32)(dynrela->src + dynrela->addend -
 				    dynrela->dest);
@@ -970,12 +1004,41 @@ out:
 	return 0;
 }
 
+/*
+ * Remove the obsolete functions from the ftrace filter.
+ * Return 1 if one or more of such functions have 'force' flag set,
+ * 0 otherwise.
+ */
+static int kpatch_ftrace_remove_unpatched_funcs(void)
+{
+	struct kpatch_module *kpmod;
+	struct kpatch_func *func;
+	int force = 0;
+
+	list_for_each_entry(kpmod, &kpmod_list, list) {
+		do_for_each_linked_func(kpmod, func) {
+			if (func->op != KPATCH_OP_UNPATCH)
+				continue;
+			if (func->force)
+				force = 1;
+			WARN_ON(kpatch_ftrace_remove_func(func->old_addr));
+		} while_for_each_linked_func();
+	}
+
+	return force;
+}
+
 int kpatch_register(struct kpatch_module *kpmod, bool replace)
 {
-	int ret, i, force = 0;
+	int ret, i;
 	struct kpatch_object *object, *object_err = NULL;
 	struct kpatch_func *func;
 
+	struct kpatch_apply_patch_args args = {
+		.kpmod = kpmod,
+		.replace = replace,
+	};
+
 	if (!kpmod->mod || list_empty(&kpmod->objects))
 		return -EINVAL;
 
@@ -1027,24 +1090,18 @@ int kpatch_register(struct kpatch_module
 	 * Idle the CPUs, verify activeness safety, and atomically make the new
 	 * functions visible to the ftrace handler.
 	 */
-	ret = stop_machine(kpatch_apply_patch, kpmod, NULL);
+	ret = stop_machine(kpatch_apply_patch, &args, NULL);
 
 	/*
-	 * For the replace case, remove any obsolete funcs from the hash and
-	 * the ftrace filter, and disable the owning patch module so that it
-	 * can be removed.
+	 * For the replace case, remove any obsolete funcs from the ftrace
+	 * filter, and disable the owning patch module so that it can be
+	 * removed.
 	 */
 	if (!ret && replace) {
 		struct kpatch_module *kpmod2, *safe;
+		int force;
 
-		hash_for_each_rcu(kpatch_func_hash, i, func, node) {
-			if (func->op != KPATCH_OP_UNPATCH)
-				continue;
-			if (func->force)
-				force = 1;
-			hash_del_rcu(&func->node);
-			WARN_ON(kpatch_ftrace_remove_func(func->old_addr));
-		}
+		force = kpatch_ftrace_remove_unpatched_funcs();
 
 		list_for_each_entry_safe(kpmod2, safe, &kpmod_list, list) {
 			if (kpmod == kpmod2)
diff -pruN 0.6.0-0.2/kmod/patch/livepatch-patch-hook.c 0.8.0-0ubuntu7/kmod/patch/livepatch-patch-hook.c
--- 0.6.0-0.2/kmod/patch/livepatch-patch-hook.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kmod/patch/livepatch-patch-hook.c	2019-08-28 17:34:00.000000000 +0000
@@ -47,10 +47,13 @@
 #define HAVE_SYMPOS
 #endif
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) &&			\
-     LINUX_VERSION_CODE <= KERNEL_VERSION(4, 15, 0)) ||			\
-    defined(RHEL_RELEASE_CODE)
-#define HAVE_IMMEDIATE
+#ifdef RHEL_RELEASE_CODE
+# if RHEL_RELEASE_CODE <= RHEL_RELEASE_VERSION(7, 5)
+#  define HAVE_IMMEDIATE
+# endif
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) &&		\
+       LINUX_VERSION_CODE <= KERNEL_VERSION(4, 15, 0))
+# define HAVE_IMMEDIATE
 #endif
 
 #ifdef RHEL_RELEASE_CODE
@@ -61,6 +64,16 @@
 # define HAVE_CALLBACKS
 #endif
 
+#ifdef RHEL_RELEASE_CODE
+# if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 8) && 		\
+	 RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 0)) || 		\
+      RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8, 2)
+#  define HAVE_SIMPLE_ENABLE
+# endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
+# define HAVE_SIMPLE_ENABLE
+#endif
+
 /*
  * There are quite a few similar structures at play in this file:
  * - livepatch.h structs prefixed with klp_*
@@ -372,7 +385,7 @@ static int __init patch_init(void)
 		goto out;
 	lpatch->mod = THIS_MODULE;
 	lpatch->objs = lobjects;
-#if defined(__powerpc__) && defined(HAVE_IMMEDIATE)
+#if defined(__powerpc64__) && defined(HAVE_IMMEDIATE)
 	lpatch->immediate = true;
 #endif
 
@@ -434,15 +447,19 @@ static int __init patch_init(void)
 	 */
 	patch_free_scaffold();
 
+#ifndef HAVE_SIMPLE_ENABLE
 	ret = klp_register_patch(lpatch);
 	if (ret) {
 		patch_free_livepatch(lpatch);
 		return ret;
 	}
+#endif
 
 	ret = klp_enable_patch(lpatch);
 	if (ret) {
+#ifndef HAVE_SIMPLE_ENABLE
 		WARN_ON(klp_unregister_patch(lpatch));
+#endif
 		patch_free_livepatch(lpatch);
 		return ret;
 	}
@@ -456,7 +473,10 @@ out:
 
 static void __exit patch_exit(void)
 {
+#ifndef HAVE_SIMPLE_ENABLE
 	WARN_ON(klp_unregister_patch(lpatch));
+#endif
+	patch_free_livepatch(lpatch);
 }
 
 module_init(patch_init);
diff -pruN 0.6.0-0.2/kmod/patch/Makefile 0.8.0-0ubuntu7/kmod/patch/Makefile
--- 0.6.0-0.2/kmod/patch/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kmod/patch/Makefile	2019-08-28 17:34:00.000000000 +0000
@@ -11,13 +11,15 @@ KBUILD_CFLAGS_MODULE += -mcmodel=large
 endif
 
 obj-m += $(KPATCH_NAME).o
+ldflags-y += -T $(src)/kpatch.lds
+extra-y := kpatch.lds
 
-$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
+$(KPATCH_NAME)-objs += patch-hook.o output.o
 
 all: $(KPATCH_NAME).ko
 
 $(KPATCH_NAME).ko:
-	$(KPATCH_MAKE) $(KPATCH_NAME).ko
+	$(KPATCH_MAKE)
 
 patch-hook.o: patch-hook.c kpatch-patch-hook.c livepatch-patch-hook.c
 	$(KPATCH_MAKE) patch-hook.o
diff -pruN 0.6.0-0.2/kpatch/kpatch 0.8.0-0ubuntu7/kpatch/kpatch
--- 0.6.0-0.2/kpatch/kpatch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch/kpatch	2019-08-28 17:34:00.000000000 +0000
@@ -25,8 +25,8 @@
 
 INSTALLDIR=/var/lib/kpatch
 SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
-VERSION="0.6.0"
-POST_ENABLE_WAIT=5	# seconds
+VERSION="0.8.0"
+POST_ENABLE_WAIT=15	# seconds
 POST_SIGNAL_WAIT=60	# seconds
 
 # How many times to try loading the patch if activeness safety check fails.
@@ -126,7 +126,7 @@ find_core_module() {
 }
 
 core_loaded () {
-	grep -q -e "T klp_register_patch" -e "T kpatch_register" /proc/kallsyms
+	grep -q -e "T klp_enable_patch" -e "T kpatch_register" /proc/kallsyms
 }
 
 get_module_name () {
@@ -157,7 +157,7 @@ verify_module_checksum () {
 	checksum="$(readelf -p .kpatch.checksum "$1" 2>&1 | grep '\[.*\]' | awk '{print $3}')"
 
 	# Fail checksum match only if both exist and diverge
-	if [[ ! -z "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
+	if [[ -n "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
 		sysfs_checksum="$(cat "$SYSFS/${modname}/checksum")"
 		[[ "$checksum" == "$sysfs_checksum" ]] || return 1
 	fi
@@ -230,21 +230,8 @@ signal_stalled_processes() {
 	[[ -z "$module" ]] && return
 
 	if [[ -e "/sys/kernel/livepatch/$module/signal" ]] ; then
+		echo "signaling stalled process(es):"
 		echo 1 > "/sys/kernel/livepatch/$module/signal"
-	else
-		for proc_task in /proc/[0-9]*/task/[0-9]*; do
-			tid=${proc_task#*/task/}
-			if is_stalled "$module" "$tid" ; then
-				if [[ "$tid" -eq "$$" ]] ; then
-					echo "skipping pid $tid $(cat "$proc_task"/comm 2>/dev/null)"
-				else
-					echo "signaling pid $tid $(cat "$proc_task"/comm 2>/dev/null)"
-					kill -SIGSTOP "$tid"
-					sleep .1
-					kill -SIGCONT "$tid"
-				fi
-			fi
-		done
 	fi
 }
 
@@ -263,7 +250,7 @@ wait_for_patch_transition() {
 		sleep 1s
 	done
 
-	echo "patch transition has stalled, signaling stalled process(es):"
+	echo "patch transition has stalled!"
 	signal_stalled_processes
 
 	echo "waiting (up to $POST_SIGNAL_WAIT seconds) for patch transition to complete..."
@@ -314,30 +301,30 @@ load_module () {
 				die "error: cannot re-enable patch module $modname, cannot verify checksum match"
 			fi
 		else
-			die "error: module named $modname already loaded and enabled"
+			echo "module named $modname already loaded and enabled"
 		fi
-	fi
+	else
+		echo "loading patch module: $module"
+		local i=0
+		while true; do
+			out="$(LC_ALL=C insmod "$module" 2>&1)"
+			[[ -z "$out" ]] && break
+			echo "$out" 1>&2
+			[[ ! "$out" =~ "Device or resource busy" ]] &&
+				die "failed to load module $module"
 
-	echo "loading patch module: $module"
-	local i=0
-	while true; do
-		out="$(LC_ALL=C insmod "$module" 2>&1)"
-		[[ -z "$out" ]] && break
-		echo "$out" 1>&2
-		[[ ! "$out" =~ "Device or resource busy" ]] &&
-			die "failed to load module $module"
-
-		# "Device or resource busy" means the activeness safety check
-		# failed.  Retry in a few seconds.
-		i=$((i+1))
-		if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then
-			die "failed to load module $module"
-			break
-		else
-			warn "retrying..."
-			sleep $RETRY_INTERVAL
-		fi
-	done
+			# "Device or resource busy" means the activeness safety check
+			# failed.  Retry in a few seconds.
+			i=$((i+1))
+			if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then
+				die "failed to load module $module"
+				break
+			else
+				warn "retrying..."
+				sleep $RETRY_INTERVAL
+			fi
+		done
+	fi
 
 	if ! wait_for_patch_transition "$modname" ; then
 		echo "module $modname did not complete its transition, unloading..."
@@ -469,7 +456,7 @@ case "$1" in
 	echo "installing $PATCH ($KVER)"
 	mkdir -p "$INSTALLDIR/$KVER" || die "failed to create install directory"
 	cp -f "$PATCH" "$INSTALLDIR/$KVER" || die "failed to install module $PATCH"
-	systemctl enable kpatch.service
+	command -v systemctl > /dev/null 2>&1 && systemctl enable kpatch.service
 	;;
 
 "uninstall")
@@ -533,7 +520,7 @@ case "$1" in
 	echo "Installed patch modules:"
 	for kdir in "$INSTALLDIR"/*; do
 		[[ -e "$kdir" ]] || continue
-		for module in "$kdir"/*; do
+		for module in "$kdir"/*.ko; do
 			[[ -e "$module" ]] || continue
 			mod_name "$module"
 			echo "$MODNAME ($(basename "$kdir"))"
diff -pruN 0.6.0-0.2/kpatch-build/create-diff-object.c 0.8.0-0ubuntu7/kpatch-build/create-diff-object.c
--- 0.6.0-0.2/kpatch-build/create-diff-object.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/create-diff-object.c	2019-08-28 17:34:00.000000000 +0000
@@ -52,14 +52,15 @@
 #include "kpatch-patch.h"
 #include "kpatch-elf.h"
 #include "kpatch-intermediate.h"
+#include "kpatch.h"
 
 #define DIFF_FATAL(format, ...) \
 ({ \
 	fprintf(stderr, "ERROR: %s: " format "\n", childobj, ##__VA_ARGS__); \
-	error(2, 0, "unreconcilable difference"); \
+	error(EXIT_STATUS_DIFF_FATAL, 0, "unreconcilable difference"); \
 })
 
-#ifdef __powerpc__
+#ifdef __powerpc64__
 #define ABSOLUTE_RELA_TYPE R_PPC64_ADDR64
 #else
 #define ABSOLUTE_RELA_TYPE R_X86_64_64
@@ -67,6 +68,12 @@
 
 char *childobj;
 
+enum subsection {
+	SUBSECTION_NORMAL,
+	SUBSECTION_HOT,
+	SUBSECTION_UNLIKELY
+};
+
 enum loglevel loglevel = NORMAL;
 
 /*******************
@@ -75,6 +82,7 @@ enum loglevel loglevel = NORMAL;
 struct special_section {
 	char *name;
 	int (*group_size)(struct kpatch_elf *kelf, int offset);
+	int unsupported;
 };
 
 /*************
@@ -90,7 +98,14 @@ static int is_bundleable(struct symbol *
 
 	if (sym->type == STT_FUNC &&
 	    !strncmp(sym->sec->name, ".text.unlikely.",15) &&
-	    !strcmp(sym->sec->name + 15, sym->name))
+	    (!strcmp(sym->sec->name + 15, sym->name) ||
+			 (strstr(sym->name, ".cold.") &&
+			  !strncmp(sym->sec->name + 15, sym->name, strlen(sym->sec->name) - 15))))
+		return 1;
+
+	if (sym->type == STT_FUNC &&
+	    !strncmp(sym->sec->name, ".text.hot.",10) &&
+	    !strcmp(sym->sec->name + 10, sym->name))
 		return 1;
 
 	if (sym->type == STT_OBJECT &&
@@ -99,6 +114,16 @@ static int is_bundleable(struct symbol *
 		return 1;
 
 	if (sym->type == STT_OBJECT &&
+	    !strncmp(sym->sec->name, ".data.rel.", 10) &&
+	    !strcmp(sym->sec->name + 10, sym->name))
+		return 1;
+
+	if (sym->type == STT_OBJECT &&
+	    !strncmp(sym->sec->name, ".data.rel.ro.", 13) &&
+	    !strcmp(sym->sec->name + 13, sym->name))
+		return 1;
+
+	if (sym->type == STT_OBJECT &&
 	   !strncmp(sym->sec->name, ".rodata.",8) &&
 	   !strcmp(sym->sec->name + 8, sym->name))
 		return 1;
@@ -111,7 +136,7 @@ static int is_bundleable(struct symbol *
 	return 0;
 }
 
-#ifdef __powerpc__
+#ifdef __powerpc64__
 /* Symbol st_others value for powerpc */
 #define STO_PPC64_LOCAL_BIT     5
 #define STO_PPC64_LOCAL_MASK    (7 << STO_PPC64_LOCAL_BIT)
@@ -181,6 +206,47 @@ static void kpatch_bundle_symbols(struct
 }
 
 /*
+ * During optimization gcc may move unlikely execution branches into *.cold
+ * subfunctions. kpatch_detect_child_functions detects such subfunctions and
+ * crossreferences them with their parent functions through parent/child
+ * pointers.
+ */
+static void kpatch_detect_child_functions(struct kpatch_elf *kelf)
+{
+	struct symbol *sym;
+
+	list_for_each_entry(sym, &kelf->symbols, list) {
+		char *coldstr;
+
+		coldstr = strstr(sym->name, ".cold.");
+		if (coldstr != NULL) {
+			char *pname;
+
+			pname = strndup(sym->name, coldstr - sym->name);
+			if (!pname)
+				ERROR("strndup");
+
+			sym->parent = find_symbol_by_name(&kelf->symbols, pname);
+			free(pname);
+
+			if (!sym->parent)
+				ERROR("failed to find parent function for %s", sym->name);
+
+			sym->parent->child = sym;
+		}
+	}
+}
+
+static bool is_dynamic_debug_symbol(struct symbol *sym)
+{
+	if (sym->type == STT_OBJECT && !strcmp(sym->sec->name, "__verbose"))
+		return true;
+	if (sym->type == STT_SECTION && !strcmp(sym->name, "__verbose"))
+		return true;
+	return false;
+}
+
+/*
  * This function detects whether the given symbol is a "special" static local
  * variable (for lack of a better term).
  *
@@ -192,8 +258,8 @@ static int is_special_static(struct symb
 	static char *prefixes[] = {
 		"__key.",
 		"__warned.",
-		"descriptor.",
 		"__func__.",
+		"__FUNCTION__.",
 		"_rs.",
 		"CSWTCH.",
 		NULL,
@@ -203,12 +269,12 @@ static int is_special_static(struct symb
 	if (!sym)
 		return 0;
 
-	if (sym->type == STT_SECTION) {
-		/* __verbose section contains the descriptor variables */
-		if (!strcmp(sym->name, "__verbose"))
-			return 1;
+	/* pr_debug() uses static local variables in the __verbose section */
+	if (is_dynamic_debug_symbol(sym))
+		return 1;
 
-		/* otherwise make sure section is bundled */
+	if (sym->type == STT_SECTION) {
+		/* make sure section is bundled */
 		if (!sym->sec->sym)
 			return 0;
 
@@ -253,7 +319,7 @@ static int kpatch_mangled_strcmp(char *s
 static int rela_equal(struct rela *rela1, struct rela *rela2)
 {
 	struct rela *rela_toc1, *rela_toc2;
-	unsigned long toc_data1, toc_data2;
+	unsigned long toc_data1 = 0, toc_data2 = 0; /* = 0 to prevent gcc warning */
 
 	if (rela1->type != rela2->type ||
 	    rela1->offset != rela2->offset)
@@ -315,6 +381,9 @@ static int rela_equal(struct rela *rela1
 	if (!rela_toc1 && !rela_toc2)
 		return toc_data1 == toc_data2;
 
+	if (!rela_toc1 || !rela_toc2)
+		return 0;
+
 	if (rela_toc1->string)
 		return rela_toc2->string && !strcmp(rela_toc1->string, rela_toc2->string);
 
@@ -372,8 +441,9 @@ static void kpatch_compare_correlated_se
 	/* Compare section headers (must match or fatal) */
 	if (sec1->sh.sh_type != sec2->sh.sh_type ||
 	    sec1->sh.sh_flags != sec2->sh.sh_flags ||
-	    sec1->sh.sh_addralign != sec2->sh.sh_addralign ||
-	    sec1->sh.sh_entsize != sec2->sh.sh_entsize)
+	    sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
+	    (sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
+	     !is_text_section(sec1)))
 		DIFF_FATAL("%s section header details differ", sec1->name);
 
 	/* Short circuit for mcount sections, we rebuild regardless */
@@ -428,7 +498,7 @@ out:
  * 1) immediate move of the line number to %esi
  * 2) (optional) string section rela
  * 3) (optional) __warned.xxxxx static local rela
- * 4) warn_slowpath_* or __might_sleep or ___might_sleep rela
+ * 4) warn_slowpath_* or __might_sleep or some other similar rela
  */
 static int kpatch_line_macro_change_only(struct section *sec)
 {
@@ -466,15 +536,16 @@ static int kpatch_line_macro_change_only
 			    length))
 			continue;
 
-		/* verify it's a mov immediate to %esi */
+		/* verify it's a mov immediate to %edx or %esi */
 		insn_get_opcode(&insn1);
 		insn_get_opcode(&insn2);
-		if (insn1.opcode.value != 0xbe || insn2.opcode.value != 0xbe)
+		if (!(insn1.opcode.value == 0xba && insn2.opcode.value == 0xba) &&
+		    !(insn1.opcode.value == 0xbe && insn2.opcode.value == 0xbe))
 			return 0;
 
 		/*
 		 * Verify zero or more string relas followed by a
-		 * warn_slowpath_* or __might_sleep or ___might_sleep rela.
+		 * warn_slowpath_* or another similar rela.
 		 */
 		found = 0;
 		list_for_each_entry(rela, &sec->rela->relas, list) {
@@ -485,8 +556,78 @@ static int kpatch_line_macro_change_only
 			if (!strncmp(rela->sym->name, "__warned.", 9))
 				continue;
 			if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
+			   (!strcmp(rela->sym->name, "__warn_printk")) ||
 			   (!strcmp(rela->sym->name, "__might_sleep")) ||
-			   (!strcmp(rela->sym->name, "___might_sleep"))) {
+			   (!strcmp(rela->sym->name, "___might_sleep")) ||
+			   (!strcmp(rela->sym->name, "__might_fault")) ||
+			   (!strcmp(rela->sym->name, "printk")) ||
+			   (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) {
+				found = 1;
+				break;
+			}
+			return 0;
+		}
+		if (!found)
+			return 0;
+
+		lineonly = 1;
+	}
+
+	if (!lineonly)
+		ERROR("no instruction changes detected for changed section %s",
+		      sec->name);
+
+	return 1;
+}
+#elif __powerpc64__
+#define PPC_INSTR_LEN 4
+#define PPC_RA_OFFSET 16
+
+static int kpatch_line_macro_change_only(struct section *sec)
+{
+	unsigned long start1, start2, size, offset;
+	unsigned int instr1, instr2;
+	struct rela *rela;
+	int lineonly = 0, found;
+
+	if (sec->status != CHANGED ||
+	    is_rela_section(sec) ||
+	    !is_text_section(sec) ||
+	    sec->sh.sh_size != sec->twin->sh.sh_size ||
+	    !sec->rela ||
+	    sec->rela->status != SAME)
+		return 0;
+
+	start1 = (unsigned long)sec->twin->data->d_buf;
+	start2 = (unsigned long)sec->data->d_buf;
+	size = sec->sh.sh_size;
+	for (offset = 0; offset < size; offset += PPC_INSTR_LEN) {
+		if (!memcmp((void *)start1 + offset, (void *)start2 + offset,
+			    PPC_INSTR_LEN))
+			continue;
+
+		instr1 = *(unsigned int *)(start1 + offset) >> PPC_RA_OFFSET;
+		instr2 = *(unsigned int *)(start2 + offset) >> PPC_RA_OFFSET;
+
+		/* verify it's a load immediate to r5 */
+		if (!(instr1 == 0x38a0 && instr2 == 0x38a0))
+			return 0;
+
+		found = 0;
+		list_for_each_entry(rela, &sec->rela->relas, list) {
+			if (rela->offset < offset + PPC_INSTR_LEN)
+				continue;
+			if (toc_rela(rela) && toc_rela(rela)->string)
+				continue;
+			if (!strncmp(rela->sym->name, "__warned.", 9))
+				continue;
+			if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
+			   (!strcmp(rela->sym->name, "__warn_printk")) ||
+			   (!strcmp(rela->sym->name, "__might_sleep")) ||
+			   (!strcmp(rela->sym->name, "___might_sleep")) ||
+			   (!strcmp(rela->sym->name, "__might_fault")) ||
+			   (!strcmp(rela->sym->name, "printk")) ||
+			   (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) {
 				found = 1;
 				break;
 			}
@@ -538,12 +679,34 @@ static void kpatch_compare_sections(stru
 			if (sec->base->sym && sec->base->sym->status != CHANGED)
 				sec->base->sym->status = sec->status;
 		} else {
-			if (sec->sym && sec->sym->status != CHANGED)
-				sec->sym->status = sec->status;
+			struct symbol *sym = sec->sym;
+
+			if (sym && sym->status != CHANGED)
+				sym->status = sec->status;
+
+			if (sym && sym->child && sym->status == SAME &&
+			    sym->child->sec->status == CHANGED)
+				sym->status = CHANGED;
 		}
 	}
 }
 
+static enum subsection kpatch_subsection_type(struct section *sec)
+{
+	if (!strncmp(sec->name, ".text.unlikely.", 15))
+		return SUBSECTION_UNLIKELY;
+
+	if (!strncmp(sec->name, ".text.hot.", 10))
+		return SUBSECTION_HOT;
+
+	return SUBSECTION_NORMAL;
+}
+
+static int kpatch_subsection_changed(struct section *sec1, struct section *sec2)
+{
+	return kpatch_subsection_type(sec1) != kpatch_subsection_type(sec2);
+}
+
 static void kpatch_compare_correlated_symbol(struct symbol *sym)
 {
 	struct symbol *sym1 = sym, *sym2 = sym->twin;
@@ -556,10 +719,12 @@ static void kpatch_compare_correlated_sy
 	/*
 	 * If two symbols are correlated but their sections are not, then the
 	 * symbol has changed sections.  This is only allowed if the symbol is
-	 * moving out of an ignored section.
+	 * moving out of an ignored section, or moving between normal/hot/unlikely
+	 * subsections.
 	 */
 	if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
-		if (sym2->sec->twin && sym2->sec->twin->ignore)
+		if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
+		    kpatch_subsection_changed(sym1->sec, sym2->sec))
 			sym->status = CHANGED;
 		else
 			DIFF_FATAL("symbol changed sections: %s", sym1->name);
@@ -752,6 +917,7 @@ static void kpatch_rename_mangled_functi
 
 		if (!strstr(sym->name, ".isra.") &&
 		    !strstr(sym->name, ".constprop.") &&
+		    !strstr(sym->name, ".cold.") &&
 		    !strstr(sym->name, ".part."))
 			continue;
 
@@ -962,8 +1128,8 @@ static void kpatch_correlate_static_loca
 			if (bundled != patched_bundled)
 				ERROR("bundle mismatch for symbol %s", sym->name);
 			if (!bundled && sym->sec->twin != patched_sym->sec)
-				ERROR("sections %s and %s aren't correlated",
-				      sym->sec->name, patched_sym->sec->name);
+				ERROR("sections %s and %s aren't correlated for symbol %s",
+				      sym->sec->name, patched_sym->sec->name, sym->name);
 
 			log_debug("renaming and correlating static local %s to %s\n",
 				  patched_sym->name, sym->name);
@@ -1080,6 +1246,10 @@ static void rela_insn(struct section *se
 
 	start = (unsigned long)sec->base->data->d_buf;
 	end = start + sec->base->sh.sh_size;
+
+	if (end <= start)
+		ERROR("bad section size");
+
 	rela_addr = start + rela->offset;
 	for (insn_addr = start; insn_addr < end; insn_addr += insn->length) {
 		insn_init(insn, (void *)insn_addr, 1);
@@ -1094,6 +1264,28 @@ static void rela_insn(struct section *se
 }
 #endif
 
+static bool is_callback_section(struct section *sec) {
+
+	static char *callback_sections[] = {
+		".kpatch.callbacks.pre_patch",
+		".kpatch.callbacks.post_patch",
+		".kpatch.callbacks.pre_unpatch",
+		".kpatch.callbacks.post_unpatch",
+		".rela.kpatch.callbacks.pre_patch",
+		".rela.kpatch.callbacks.post_patch",
+		".rela.kpatch.callbacks.pre_unpatch",
+		".rela.kpatch.callbacks.post_unpatch",
+		NULL,
+	};
+	char **callback_sec;
+
+	for (callback_sec = callback_sections; *callback_sec; callback_sec++)
+		if (!strcmp(sec->name, *callback_sec))
+			return true;
+
+	return false;
+}
+
 /*
  * Mangle the relas a little.  The compiler will sometimes use section symbols
  * to reference local objects and functions rather than the object or function
@@ -1127,13 +1319,25 @@ static void kpatch_replace_sections_syms
 			if (rela->sym->sec && rela->sym->sec->sym) {
 				rela->sym = rela->sym->sec->sym;
 
+				/*
+				 * On ppc64le with GCC6+, even with
+				 * -ffunction-sections, the function symbol
+				 *  starts 8 bytes past the beginning of the
+				 *  section, because the .TOC pointer is at the
+				 *  beginning, right before the code.  So even
+				 *  though the symbol is bundled, we can't
+				 *  assume it's at offset 0 in the section.
+				 */
+				rela->addend -= rela->sym->sym.st_value;
+
 				continue;
 			}
 
-#ifdef __powerpc__
+#ifdef __powerpc64__
 			add_off = 0;
 #else
-			if (rela->type == R_X86_64_PC32) {
+			if (rela->type == R_X86_64_PC32 ||
+			    rela->type == R_X86_64_PLT32) {
 				struct insn insn;
 				rela_insn(sec, rela, &insn);
 				add_off = (long)insn.next_byte -
@@ -1154,6 +1358,7 @@ static void kpatch_replace_sections_syms
 				int start, end;
 
 				if (sym->type == STT_SECTION ||
+				    !sym->sec ||
 				    sym->sec != rela->sym->sec)
 					continue;
 
@@ -1221,7 +1426,7 @@ static void kpatch_check_func_profiling_
 	int errs = 0;
 
 	list_for_each_entry(sym, &kelf->symbols, list) {
-		if (sym->type != STT_FUNC || sym->status != CHANGED)
+		if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent)
 			continue;
 		if (!sym->twin->has_func_profiling) {
 			log_normal("function %s has no fentry/mcount call, unable to patch\n",
@@ -1375,57 +1580,28 @@ static int kpatch_include_callback_eleme
 	struct rela *rela;
 	int found = 0;
 
-	static char *callback_sections[] = {
-		".kpatch.callbacks.pre_patch",
-		".kpatch.callbacks.post_patch",
-		".kpatch.callbacks.pre_unpatch",
-		".kpatch.callbacks.post_unpatch",
-		".rela.kpatch.callbacks.pre_patch",
-		".rela.kpatch.callbacks.post_patch",
-		".rela.kpatch.callbacks.pre_unpatch",
-		".rela.kpatch.callbacks.post_unpatch",
-		NULL,
-	};
-	char **callback_section;
-
 	/* include load/unload sections */
 	list_for_each_entry(sec, &kelf->sections, list) {
+		if (!is_callback_section(sec))
+			continue;
 
-		for (callback_section = callback_sections; *callback_section; callback_section++) {
-
-			if (strcmp(*callback_section, sec->name))
-				continue;
-
-			sec->include = 1;
-			found = 1;
-			if (is_rela_section(sec)) {
-				/* include callback dependencies */
-				rela = list_entry(sec->relas.next,
-			                         struct rela, list);
-				sym = rela->sym;
-				log_normal("found callback: %s\n",sym->name);
-				kpatch_include_symbol(sym);
-				/* strip the callback symbol */
-				sym->include = 0;
-				sym->sec->sym = NULL;
-				/* use section symbol instead */
-				rela->sym = sym->sec->secsym;
-			} else {
-				sec->secsym->include = 1;
-			}
+		sec->include = 1;
+		found = 1;
+		if (is_rela_section(sec)) {
+			/* include callback dependencies */
+			rela = list_entry(sec->relas.next, struct rela, list);
+			sym = rela->sym;
+			log_normal("found callback: %s\n",sym->name);
+			kpatch_include_symbol(sym);
+		} else {
+			sec->secsym->include = 1;
 		}
 	}
 
 	/* Strip temporary global structures used by the callback macros. */
 	list_for_each_entry(sym, &kelf->symbols, list) {
-		if (!sym->sec)
-			continue;
-		for (callback_section = callback_sections; *callback_section; callback_section++) {
-			if (!strcmp(*callback_section, sym->sec->name)) {
-				sym->include = 0;
-				break;
-			}
-		}
+		if (sym->sec && is_callback_section(sym->sec))
+			sym->include = 0;
 	}
 
 	return found;
@@ -1501,7 +1677,7 @@ static void kpatch_print_changes(struct
 	struct symbol *sym;
 
 	list_for_each_entry(sym, &kelf->symbols, list) {
-		if (!sym->include || !sym->sec || sym->type != STT_FUNC)
+		if (!sym->include || !sym->sec || sym->type != STT_FUNC || sym->parent)
 			continue;
 		if (sym->status == NEW)
 			log_normal("new function: %s\n", sym->name);
@@ -1617,6 +1793,21 @@ static int ex_table_group_size(struct kp
 	return size;
 }
 
+static int jump_table_group_size(struct kpatch_elf *kelf, int offset)
+{
+	static int size = 0;
+	char *str;
+
+	if (!size) {
+		str = getenv("JUMP_STRUCT_SIZE");
+		if (!str)
+			ERROR("JUMP_STRUCT_SIZE not set");
+		size = atoi(str);
+	}
+
+	return size;
+}
+
 #ifdef __x86_64__
 static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
 {
@@ -1653,7 +1844,7 @@ static int smp_locks_group_size(struct k
 	return 4;
 }
 #endif
-#ifdef __powerpc__
+#ifdef __powerpc64__
 static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset)
 {
 	static int size = 0;
@@ -1671,7 +1862,12 @@ static int fixup_entry_group_size(struct
 
 static int fixup_lwsync_group_size(struct kpatch_elf *kelf, int offset)
 {
-	return 4;
+	return 8;
+}
+
+static int fixup_barrier_nospec_group_size(struct kpatch_elf *kelf, int offset)
+{
+	return 8;
 }
 #endif
 
@@ -1717,6 +1913,8 @@ static int fixup_group_size(struct kpatc
 		/* last group */
 		struct section *fixupsec;
 		fixupsec = find_section_by_name(&kelf->sections, ".fixup");
+		if (!fixupsec)
+			ERROR("missing .fixup section");
 		return fixupsec->sh.sh_size - offset;
 	}
 
@@ -1728,16 +1926,6 @@ static struct special_section special_se
 		.name		= "__bug_table",
 		.group_size	= bug_table_group_size,
 	},
-#ifdef __x86_64__
-	{
-		.name		= ".smp_locks",
-		.group_size	= smp_locks_group_size,
-	},
-	{
-		.name		= ".parainstructions",
-		.group_size	= parainstructions_group_size,
-	},
-#endif
 	{
 		.name		= ".fixup",
 		.group_size	= fixup_group_size,
@@ -1746,28 +1934,49 @@ static struct special_section special_se
 		.name		= "__ex_table", /* must come after .fixup */
 		.group_size	= ex_table_group_size,
 	},
+	{
+		.name		= "__jump_table",
+		.group_size	= jump_table_group_size,
+	},
 #ifdef __x86_64__
 	{
+		.name		= ".smp_locks",
+		.group_size	= smp_locks_group_size,
+	},
+	{
+		.name		= ".parainstructions",
+		.group_size	= parainstructions_group_size,
+	},
+	{
 		.name		= ".altinstructions",
 		.group_size	= altinstructions_group_size,
 	},
 #endif
-#ifdef __powerpc__
+#ifdef __powerpc64__
 	{
 		.name		= "__ftr_fixup",
 		.group_size	= fixup_entry_group_size,
+		.unsupported	= 1,
 	},
 	{
 		.name		= "__mmu_ftr_fixup",
 		.group_size	= fixup_entry_group_size,
+		.unsupported	= 1,
 	},
 	{
 		.name		= "__fw_ftr_fixup",
 		.group_size	= fixup_entry_group_size,
+		.unsupported	= 1,
 	},
 	{
 		.name		= "__lwsync_fixup",
 		.group_size	= fixup_lwsync_group_size,
+		.unsupported	= 1,
+	},
+	{
+		.name		= "__barrier_nospec_fixup",
+		.group_size	= fixup_barrier_nospec_group_size,
+		.unsupported	= 1,
 	},
 #endif
 	{},
@@ -1826,6 +2035,7 @@ static void kpatch_regenerate_special_se
 	struct rela *rela, *safe;
 	char *src, *dest;
 	unsigned int group_size, src_offset, dest_offset, include;
+	int jump_table = !strcmp(special->name, "__jump_table");
 
 	LIST_HEAD(newrelas);
 
@@ -1843,7 +2053,6 @@ static void kpatch_regenerate_special_se
 		}
 	}
 
-	group_size = 0;
 	src_offset = 0;
 	dest_offset = 0;
 	for ( ; src_offset < sec->base->sh.sh_size; src_offset += group_size) {
@@ -1866,6 +2075,52 @@ static void kpatch_regenerate_special_se
 		if (!include)
 			continue;
 
+		if (special->unsupported)
+			DIFF_FATAL("unsupported reference to special section %s", sec->base->name);
+
+		/*
+		 * Jump labels (aka static keys or static branches) aren't
+		 * actually supported for the time being.  Warn on all
+		 * non-tracepoint jump labels when they occur in a replacement
+		 * function.  An inert tracepoint is harmless enough, but a
+		 * broken static key can cause unexpected behavior.
+		 *
+		 * Here we hard-code knowledge about the contents of the
+		 * jump_label struct.  It has three fields: code, target, and
+		 * key.
+		 */
+		if (jump_table) {
+			struct rela *code, *key;
+			int i = 0;
+
+			list_for_each_entry(rela, &sec->relas, list) {
+				if (rela->offset >= src_offset &&
+				    rela->offset < src_offset + group_size) {
+					if (i == 0)
+						code = rela;
+					else if (i == 2)
+						key = rela;
+					i++;
+				}
+			}
+
+			if (i != 3)
+				ERROR("BUG: __jump_table has an unexpected format");
+
+			/* inert tracepoints are harmless */
+			if (!strncmp(key->sym->name, "__tracepoint_", 13))
+				continue;
+
+			/* inert dynamic debug printks are harmless */
+			if (is_dynamic_debug_symbol(key->sym))
+				continue;
+
+			ERROR("Found a jump label at %s()+0x%x, using key %s.  Jump labels aren't currently supported.  Use static_key_enabled() instead.",
+			      code->sym->name, code->addend, key->sym->name);
+
+			continue;
+		}
+
 		/*
 		 * Copy all relas in the group.  It's possible that the relas
 		 * aren't sorted (e.g. .rela.fixup), so go through the entire
@@ -1924,6 +2179,97 @@ static void kpatch_regenerate_special_se
 	sec->base->data->d_size = dest_offset;
 }
 
+#define ORC_IP_PTR_SIZE 4
+
+/*
+ * This function is similar to kpatch_regenerate_special_section(), but
+ * customized for the ORC-related sections.  ORC is more special than the other
+ * special sections because each ORC entry is split into .orc_unwind (struct
+ * orc_entry) and .orc_unwind_ip.
+ */
+static void kpatch_regenerate_orc_sections(struct kpatch_elf *kelf)
+{
+	struct rela *rela, *safe;
+	char *src, *dest, *str;
+	unsigned int src_idx = 0, dest_idx = 0, orc_entry_size;
+	struct section *orc_sec, *ip_sec;
+
+
+	str = getenv("ORC_STRUCT_SIZE");
+	if (!str)
+		return;
+	orc_entry_size = atoi(str);
+
+	if (!orc_entry_size)
+		ERROR("bad ORC_STRUCT_SIZE");
+
+	LIST_HEAD(newrelas);
+
+	orc_sec = find_section_by_name(&kelf->sections, ".orc_unwind");
+	ip_sec  = find_section_by_name(&kelf->sections, ".orc_unwind_ip");
+
+	if (!orc_sec || !ip_sec)
+		return;
+
+	if (orc_sec->sh.sh_size % orc_entry_size != 0)
+		ERROR("bad .orc_unwind size");
+
+	if (ip_sec->sh.sh_size !=
+	    (orc_sec->sh.sh_size / orc_entry_size) * ORC_IP_PTR_SIZE)
+		ERROR(".orc_unwind/.orc_unwind_ip size mismatch");
+
+	src = orc_sec->data->d_buf;
+	dest = malloc(orc_sec->sh.sh_size);
+	if (!dest)
+		ERROR("malloc");
+
+	list_for_each_entry_safe(rela, safe, &ip_sec->rela->relas, list) {
+
+		if (rela->sym->type != STT_FUNC || !rela->sym->sec->include)
+			goto next;
+
+		/* copy orc entry */
+		memcpy(dest + (dest_idx * orc_entry_size),
+		       src + (src_idx * orc_entry_size),
+		       orc_entry_size);
+
+		/* move ip rela */
+		list_del(&rela->list);
+		list_add_tail(&rela->list, &newrelas);
+		rela->offset = dest_idx * ORC_IP_PTR_SIZE;
+		rela->sym->include = 1;
+
+		dest_idx++;
+next:
+		src_idx++;
+	}
+
+	if (!dest_idx) {
+		/* no changed or global functions referenced */
+		orc_sec->status = ip_sec->status = ip_sec->rela->status = SAME;
+		orc_sec->include = ip_sec->include = ip_sec->rela->include = 0;
+		free(dest);
+		return;
+	}
+
+	/* overwrite with new relas list */
+	list_replace(&newrelas, &ip_sec->rela->relas);
+
+	/* include the sections */
+	orc_sec->include = ip_sec->include = ip_sec->rela->include = 1;
+
+	/*
+	 * Update data buf/size.
+	 *
+	 * The ip section can keep its old (zeroed data), though its size has
+	 * possibly decreased.  The ip rela section's data buf and size will be
+	 * regenerated in kpatch_rebuild_rela_section_data().
+	 */
+	orc_sec->data->d_buf = dest;
+	orc_sec->data->d_size = dest_idx * orc_entry_size;
+	ip_sec->data->d_size = dest_idx * ORC_IP_PTR_SIZE;
+}
+
 static void kpatch_check_relocations(struct kpatch_elf *kelf)
 {
 	struct rela *rela;
@@ -2004,6 +2350,7 @@ static void kpatch_mark_ignored_sections
 		 * from the section data comparison, but this is a simpler way.
 		 */
 		strsec->include = 1;
+		strsec->secsym->include = 1;
 		name = strsec->data->d_buf + rela->addend;
 		ignoresec = find_section_by_name(&kelf->sections, name);
 		if (!ignoresec)
@@ -2066,6 +2413,10 @@ static void kpatch_mark_ignored_function
 			log_normal("NOTICE: no change detected in function %s, unnecessary KPATCH_IGNORE_FUNCTION()?\n", rela->sym->name);
 		rela->sym->status = SAME;
 		rela->sym->sec->status = SAME;
+
+		if (rela->sym->child)
+			rela->sym->child->status = SAME;
+
 		if (rela->sym->sec->secsym)
 			rela->sym->sec->secsym->status = SAME;
 		if (rela->sym->sec->rela)
@@ -2082,15 +2433,13 @@ static void kpatch_mark_ignored_function
 static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *objname)
 {
 	struct special_section *special;
-	struct kpatch_arch *entries;
 	struct symbol *strsym;
 	struct section *sec, *karch_sec;
 	struct rela *rela;
 	int nr, index = 0;
 
 	nr = sizeof(special_sections) / sizeof(special_sections[0]);
-	karch_sec = create_section_pair(kelf, ".kpatch.arch", sizeof(*entries), nr);
-	entries = karch_sec->data->d_buf;
+	karch_sec = create_section_pair(kelf, ".kpatch.arch", sizeof(struct kpatch_arch), nr);
 
 	/* lookup strings symbol */
 	strsym = find_symbol_by_name(&kelf->symbols, ".kpatch.strings");
@@ -2111,7 +2460,7 @@ static void kpatch_create_kpatch_arch_se
 		rela->sym = sec->secsym;
 		rela->type = ABSOLUTE_RELA_TYPE;
 		rela->addend = 0;
-		rela->offset = index * sizeof(*entries) + \
+		rela->offset = index * sizeof(struct kpatch_arch) + \
 			       offsetof(struct kpatch_arch, sec);
 
 		/* entries[index].objname */
@@ -2119,7 +2468,7 @@ static void kpatch_create_kpatch_arch_se
 		rela->sym = strsym;
 		rela->type = ABSOLUTE_RELA_TYPE;
 		rela->addend = offset_of_string(&kelf->strings, objname);
-		rela->offset = index * sizeof(*entries) + \
+		rela->offset = index * sizeof(struct kpatch_arch) + \
 			       offsetof(struct kpatch_arch, objname);
 
 		index++;
@@ -2179,7 +2528,7 @@ static void kpatch_process_special_secti
 			sec->rela->include = 1;
 			/* include all symbols referenced by relas */
 			list_for_each_entry(rela, &sec->rela->relas, list)
-				rela->sym->include = 1;
+				kpatch_include_symbol(rela->sym);
 		}
 	}
 
@@ -2204,6 +2553,8 @@ static void kpatch_process_special_secti
 			sec->rela->include = 0;
 		}
 	}
+
+	kpatch_regenerate_orc_sections(kelf);
 }
 
 static struct sym_compare_type *kpatch_elf_locals(struct kpatch_elf *kelf)
@@ -2235,7 +2586,7 @@ static struct sym_compare_type *kpatch_e
 			continue;
 
 		sym_array[i].type = sym->type;
-		sym_array[i++].name = sym->name;
+		sym_array[i++].name = strdup(sym->name);
 	}
 	sym_array[i].type = 0;
 	sym_array[i].name = NULL;
@@ -2257,7 +2608,7 @@ static void kpatch_create_patches_sectio
 	/* count patched functions */
 	nr = 0;
 	list_for_each_entry(sym, &kelf->symbols, list)
-		if (sym->type == STT_FUNC && sym->status == CHANGED)
+		if (sym->type == STT_FUNC && sym->status == CHANGED && !sym->parent)
 			nr++;
 
 	/* create text/rela section pair */
@@ -2276,7 +2627,7 @@ static void kpatch_create_patches_sectio
 	/* populate sections */
 	index = 0;
 	list_for_each_entry(sym, &kelf->symbols, list) {
-		if (sym->type == STT_FUNC && sym->status == CHANGED) {
+		if (sym->type == STT_FUNC && sym->status == CHANGED && !sym->parent) {
 			if (sym->bind == STB_LOCAL) {
 				if (lookup_local_symbol(table, sym->name,
 				                        &result))
@@ -2387,6 +2738,7 @@ static int function_ptr_rela(const struc
 	const struct rela *rela_toc = toc_rela(rela);
 
 	return (rela_toc && rela_toc->sym->type == STT_FUNC &&
+		!rela_toc->sym->parent &&
 		/* skip switch table on PowerPC */
 		rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
 		(rela->type == R_X86_64_32S ||
@@ -2396,8 +2748,17 @@ static int function_ptr_rela(const struc
 
 static int may_need_dynrela(const struct rela *rela)
 {
+	/*
+	 * References to .TOC. are treated specially by the module loader and
+	 * should never be converted to dynrelas.
+	 */
+	if (rela->type == R_PPC64_REL16_HA || rela->type == R_PPC64_REL16_LO ||
+	    rela->type == R_PPC64_REL64)
+		return 0;
+
 	if (!rela->sym->sec)
 		return 1;
+
 	/*
 	 * Nested functions used as callbacks are a special case.
 	 * They are not supposed to be visible outside of the
@@ -2491,7 +2852,8 @@ static void kpatch_create_intermediate_s
 		if (!is_rela_section(sec))
 			continue;
 		if (!strcmp(sec->name, ".rela.kpatch.funcs") ||
-		    !strcmp(sec->name, ".rela.kpatch.dynrelas"))
+		    !strcmp(sec->name, ".rela.kpatch.relocations") ||
+		    !strcmp(sec->name, ".rela.kpatch.symbols"))
 			continue;
 		list_for_each_entry_safe(rela, safe, &sec->relas, list) {
 			if (!rela->need_dynrela)
@@ -2553,7 +2915,7 @@ static void kpatch_create_intermediate_s
 				 * a global symbol.  Use a normal rela for
 				 * exported symbols and a dynrela otherwise.
 				 */
-#ifdef __powerpc__
+#ifdef __powerpc64__
 				/*
 				 * An exported symbol might be local to an
 				 * object file and any access to the function
@@ -2752,7 +3114,7 @@ static void kpatch_create_callbacks_objn
 	}
 }
 
-#ifdef __powerpc__
+#ifdef __powerpc64__
 void kpatch_create_mcount_sections(struct kpatch_elf *kelf) { }
 #else
 /*
@@ -2768,7 +3130,7 @@ static void kpatch_create_mcount_section
 	struct section *sec, *relasec;
 	struct symbol *sym;
 	struct rela *rela;
-	void **funcs, *newdata;
+	void *newdata;
 	unsigned char *insn;
 
 	nr = 0;
@@ -2778,9 +3140,8 @@ static void kpatch_create_mcount_section
 			nr++;
 
 	/* create text/rela section pair */
-	sec = create_section_pair(kelf, "__mcount_loc", sizeof(*funcs), nr);
+	sec = create_section_pair(kelf, "__mcount_loc", sizeof(void*), nr);
 	relasec = sec->rela;
-	funcs = sec->data->d_buf;
 
 	/* populate sections */
 	index = 0;
@@ -2799,28 +3160,39 @@ static void kpatch_create_mcount_section
 		rela->sym = sym;
 		rela->type = R_X86_64_64;
 		rela->addend = 0;
-		rela->offset = index * sizeof(*funcs);
+		rela->offset = index * sizeof(void*);
 
 		/*
 		 * Modify the first instruction of the function to "callq
 		 * __fentry__" so that ftrace will be happy.
 		 */
 		newdata = malloc(sym->sec->data->d_size);
+		if (!newdata)
+			ERROR("malloc");
+
 		memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
 		sym->sec->data->d_buf = newdata;
 		insn = newdata;
-		if (insn[0] != 0xf)
-			ERROR("%s: unexpected instruction at the start of the function",
-			      sym->name);
-		insn[0] = 0xe8;
-		insn[1] = 0;
-		insn[2] = 0;
-		insn[3] = 0;
-		insn[4] = 0;
 
 		rela = list_first_entry(&sym->sec->rela->relas, struct rela,
 					list);
-		rela->type = R_X86_64_PC32;
+
+		/*
+		 * R_X86_64_NONE is only generated by older versions of kernel/gcc
+		 * which use the mcount script.
+		 */
+		if (rela->type == R_X86_64_NONE) {
+			if (insn[0] != 0xf)
+				ERROR("%s: unexpected instruction at the start of the function",
+				      sym->name);
+			insn[0] = 0xe8;
+			insn[1] = 0;
+			insn[2] = 0;
+			insn[3] = 0;
+			insn[4] = 0;
+
+			rela->type = R_X86_64_PC32;
+		}
 
 		index++;
 	}
@@ -2912,12 +3284,66 @@ static void kpatch_build_strings_section
 	}
 }
 
+/*
+ * Don't allow sibling calls from patched functions on ppc64le.  Before doing a
+ * sibling call, the patched function restores the stack to its caller's stack.
+ * The kernel-generated stub then writes the patch module's r2 (toc) value to
+ * the caller's stack, corrupting it, eventually causing a panic after it
+ * returns to the caller and the caller tries to use the livepatch module's toc
+ * value.
+ *
+ * In theory we could instead a) generate a custom stub, or b) modify the
+ * kernel livepatch_handler code to save/restore the stack r2 value, but this
+ * is easier for now.
+ */
+static void kpatch_no_sibling_calls_ppc64le(struct kpatch_elf *kelf)
+{
+#ifdef __powerpc64__
+	struct symbol *sym;
+	unsigned int insn;
+	unsigned long offset;
+
+	list_for_each_entry(sym, &kelf->symbols, list) {
+		if (sym->type != STT_FUNC || sym->status != CHANGED)
+			continue;
+
+		for (offset = 0; offset < sym->sec->data->d_size; offset += 4) {
+
+			insn = *(unsigned int *)(sym->sec->data->d_buf + offset);
+
+			/*
+			 * The instruction 0x48000000 can be assumed to be a
+			 * sibling call:
+			 *
+			 * Bits 0-5 (opcode) == 0x9: unconditional branch
+			 * Bit 30 (absolute) == 0: relative address
+			 * Bit 31 (link) == 0: doesn't set LR (not a call)
+			 *
+			 * Bits 6-29 (branch address) == zero, which means
+			 * it's either a branch to self (infinite loop), or
+			 * there's a REL24 relocation for the address which
+			 * will be written by the linker or the kernel.
+			 */
+			if (insn != 0x48000000)
+				continue;
+
+			/* Make sure it's not a branch-to-self: */
+			if (!find_rela_by_offset(sym->sec->rela, offset))
+				continue;
+
+			ERROR("Found an unsupported sibling call at %s()+0x%lx.  Add __attribute__((optimize(\"-fno-optimize-sibling-calls\"))) to %s() definition.",
+			      sym->name, sym->sym.st_value + offset, sym->name);
+		}
+	}
+#endif
+}
+
 struct arguments {
-	char *args[6];
+	char *args[7];
 	int debug;
 };
 
-static char args_doc[] = "original.o patched.o kernel-object output.o Module.symvers patch-module-name";
+static char args_doc[] = "original.o patched.o parent-name parent-symtab Module.symvers patch-module-name output.o";
 
 static struct argp_option options[] = {
 	{"debug", 'd', NULL, 0, "Show debug output" },
@@ -2936,13 +3362,13 @@ static error_t parse_opt (int key, char
 			arguments->debug = 1;
 			break;
 		case ARGP_KEY_ARG:
-			if (state->arg_num >= 6)
+			if (state->arg_num >= 7)
 				/* Too many arguments. */
 				argp_usage (state);
 			arguments->args[state->arg_num] = arg;
 			break;
 		case ARGP_KEY_END:
-			if (state->arg_num < 6)
+			if (state->arg_num < 7)
 				/* Not enough arguments. */
 				argp_usage (state);
 			break;
@@ -2962,9 +3388,9 @@ int main(int argc, char *argv[])
 	struct lookup_table *lookup;
 	struct section *sec, *symtab;
 	struct symbol *sym;
-	char *hint = NULL, *objname, *pos;
-	char *mod_symvers_path, *pmod_name;
-	struct sym_compare_type *base_locals;
+	char *hint = NULL, *orig_obj, *patched_obj, *parent_name;
+	char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
+	struct sym_compare_type *base_locals, *sym_comp;
 
 	arguments.debug = 0;
 	argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -2973,34 +3399,41 @@ int main(int argc, char *argv[])
 
 	elf_version(EV_CURRENT);
 
-	childobj = basename(arguments.args[0]);
+	orig_obj      = arguments.args[0];
+	patched_obj   = arguments.args[1];
+	parent_name   = arguments.args[2];
+	parent_symtab = arguments.args[3];
+	mod_symvers   = arguments.args[4];
+	patch_name    = arguments.args[5];
+	output_obj    = arguments.args[6];
 
-	mod_symvers_path = arguments.args[4];
-	pmod_name = arguments.args[5];
+	childobj = basename(orig_obj);
 
-	kelf_base = kpatch_elf_open(arguments.args[0]);
-	kelf_patched = kpatch_elf_open(arguments.args[1]);
+	kelf_base = kpatch_elf_open(orig_obj);
+	kelf_patched = kpatch_elf_open(patched_obj);
 
 	kpatch_bundle_symbols(kelf_base);
 	kpatch_bundle_symbols(kelf_patched);
 
+	kpatch_detect_child_functions(kelf_base);
+	kpatch_detect_child_functions(kelf_patched);
+
 	kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf);
 	kpatch_check_program_headers(kelf_base->elf);
 	kpatch_check_program_headers(kelf_patched->elf);
 
 	list_for_each_entry(sym, &kelf_base->symbols, list) {
 		if (sym->type == STT_FILE) {
-			hint = sym->name;
+			hint = strdup(sym->name);
 			break;
 		}
 	}
-	if (!hint)
-		ERROR("FILE symbol not found in base. Stripped?\n");
+	if (!hint) {
+		log_normal("WARNING: FILE symbol not found in base. Stripped object file or assembly source?\n");
+		return EXIT_STATUS_NO_CHANGE;
+	}
 
-	/* create symbol lookup table */
 	base_locals = kpatch_elf_locals(kelf_base);
-	lookup = lookup_open(arguments.args[2], mod_symvers_path, hint, base_locals);
-	free(base_locals);
 
 	kpatch_mark_grouped_sections(kelf_patched);
 	kpatch_replace_sections_syms(kelf_base);
@@ -3031,10 +3464,11 @@ int main(int argc, char *argv[])
 	kpatch_include_force_elements(kelf_patched);
 	new_globals_exist = kpatch_include_new_globals(kelf_patched);
 
+	kpatch_process_special_sections(kelf_patched);
+
 	kpatch_print_changes(kelf_patched);
 	kpatch_dump_kelf(kelf_patched);
 
-	kpatch_process_special_sections(kelf_patched);
 	kpatch_verify_patchability(kelf_patched);
 
 	if (!num_changed && !new_globals_exist) {
@@ -3042,7 +3476,8 @@ int main(int argc, char *argv[])
 			log_debug("no changed functions were found, but callbacks exist\n");
 		else {
 			log_debug("no changed functions were found\n");
-			return 3; /* 1 is ERROR, 2 is DIFF_FATAL */
+			free(hint);
+			return EXIT_STATUS_NO_CHANGE;
 		}
 	}
 
@@ -3057,27 +3492,22 @@ int main(int argc, char *argv[])
 	 */
 	kpatch_elf_teardown(kelf_patched);
 
-	/* extract module name (destructive to arguments.modulefile) */
-	objname = basename(arguments.args[2]);
-	if (!strncmp(objname, "vmlinux-", 8))
-		objname = "vmlinux";
-	else {
-		pos = strchr(objname,'.');
-		if (pos) {
-			/* kernel module */
-			*pos = '\0';
-			pos = objname;
-			while ((pos = strchr(pos, '-')))
-				*pos++ = '_';
-		}
+	/* create symbol lookup table */
+	lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals);
+	for (sym_comp = base_locals; sym_comp && sym_comp->name; sym_comp++) {
+		free(sym_comp->name);
 	}
+	free(base_locals);
+	free(hint);
+
+	kpatch_no_sibling_calls_ppc64le(kelf_out);
 
 	/* create strings, patches, and dynrelas sections */
 	kpatch_create_strings_elements(kelf_out);
-	kpatch_create_patches_sections(kelf_out, lookup, objname);
-	kpatch_create_intermediate_sections(kelf_out, lookup, objname, pmod_name);
-	kpatch_create_kpatch_arch_section(kelf_out, objname);
-	kpatch_create_callbacks_objname_rela(kelf_out, objname);
+	kpatch_create_patches_sections(kelf_out, lookup, parent_name);
+	kpatch_create_intermediate_sections(kelf_out, lookup, parent_name, patch_name);
+	kpatch_create_kpatch_arch_section(kelf_out, parent_name);
+	kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
 	kpatch_build_strings_section_data(kelf_out);
 
 	kpatch_create_mcount_sections(kelf_out);
@@ -3098,6 +3528,9 @@ int main(int argc, char *argv[])
 	 * buffers from the relas lists.
 	 */
 	symtab = find_section_by_name(&kelf_out->sections, ".symtab");
+	if (!symtab)
+		ERROR("missing .symtab section");
+
 	list_for_each_entry(sec, &kelf_out->sections, list) {
 		if (!is_rela_section(sec))
 			continue;
@@ -3111,11 +3544,12 @@ int main(int argc, char *argv[])
 	kpatch_create_strtab(kelf_out);
 	kpatch_create_symtab(kelf_out);
 	kpatch_dump_kelf(kelf_out);
-	kpatch_write_output_elf(kelf_out, kelf_patched->elf, arguments.args[3]);
+	kpatch_write_output_elf(kelf_out, kelf_patched->elf, output_obj);
 
+	lookup_close(lookup);
 	kpatch_elf_free(kelf_patched);
 	kpatch_elf_teardown(kelf_out);
 	kpatch_elf_free(kelf_out);
 
-	return 0;
+	return EXIT_STATUS_SUCCESS;
 }
diff -pruN 0.6.0-0.2/kpatch-build/create-klp-module.c 0.8.0-0ubuntu7/kpatch-build/create-klp-module.c
--- 0.6.0-0.2/kpatch-build/create-klp-module.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/create-klp-module.c	2019-08-28 17:34:00.000000000 +0000
@@ -57,9 +57,7 @@ static struct symbol *find_or_add_ksym_t
 	if (!rela)
 		ERROR("name of ksym not found?");
 
-	name = strdup(strings + rela->addend);
-	if (!name)
-		ERROR("strdup");
+	name = strings + rela->addend;
 
 	/* Get objname of ksym */
 	rela = find_rela_by_offset(ksymsec->rela,
@@ -67,9 +65,7 @@ static struct symbol *find_or_add_ksym_t
 	if (!rela)
 		ERROR("objname of ksym not found?");
 
-	objname = strdup(strings + rela->addend);
-	if (!objname)
-		ERROR("strdup");
+	objname = strings + rela->addend;
 
 	snprintf(pos, 32, "%lu", ksym->pos);
 	/* .klp.sym.objname.name,pos */
@@ -81,7 +77,7 @@ static struct symbol *find_or_add_ksym_t
 			return sym;
 	}
 
-	ALLOC_LINK(sym, &kelf->symbols);
+	ALLOC_LINK(sym, NULL);
 	sym->name = strdup(buf);
 	if (!sym->name)
 		ERROR("strdup");
@@ -93,6 +89,25 @@ static struct symbol *find_or_add_ksym_t
 	 */
 	sym->sym.st_shndx = SHN_LIVEPATCH;
 	sym->sym.st_info = GELF_ST_INFO(sym->bind, sym->type);
+	/*
+	 * Figure out where to put the new symbol:
+	 *   a) locals need to be grouped together, before globals
+	 *   b) globals can be tacked into the end of the list
+	 */
+	if (is_local_sym(sym)) {
+		struct list_head *head;
+		struct symbol *s;
+
+		head = &kelf->symbols;
+		list_for_each_entry(s, &kelf->symbols, list) {
+			if (!is_local_sym(s))
+				break;
+			head = &s->list;
+		}
+		list_add_tail(&sym->list, head);
+	} else {
+		list_add_tail(&sym->list, &kelf->symbols);
+	}
 
 	return sym;
 }
@@ -183,9 +198,7 @@ static void create_klp_relasecs_and_syms
 		if (!rela)
 			ERROR("find_rela_by_offset");
 
-		objname = strdup(strings + rela->addend);
-		if (!objname)
-			ERROR("strdup");
+		objname = strings + rela->addend;
 
 		/* Get the .kpatch.symbol entry for the rela src */
 		rela = find_rela_by_offset(krelasec->rela,
@@ -231,7 +244,6 @@ static void create_klp_relasecs_and_syms
 static void create_klp_arch_sections(struct kpatch_elf *kelf, char *strings)
 {
 	struct section *karch, *sec, *base = NULL;
-	struct kpatch_arch *entries;
 	struct rela *rela, *rela2;
 	char *secname, *objname = NULL;
 	char buf[256];
@@ -241,11 +253,10 @@ static void create_klp_arch_sections(str
 	if (!karch)
 		return;
 
-	entries = karch->data->d_buf;
-	nr = karch->data->d_size / sizeof(*entries);
+	nr = karch->data->d_size / sizeof(struct kpatch_arch);
 
 	for (index = 0; index < nr; index++) {
-		offset = index * sizeof(*entries);
+		offset = index * sizeof(struct kpatch_arch);
 
 		/* Get the base section (.parainstructions or .altinstructions) */
 		rela = find_rela_by_offset(karch->rela,
@@ -263,9 +274,7 @@ static void create_klp_arch_sections(str
 		if (!rela)
 			ERROR("find_rela_by_offset");
 
-		objname = strdup(strings + rela->addend);
-		if (!objname)
-			ERROR("strdup");
+		objname = strings + rela->addend;
 
 		/* Example: .klp.arch.vmlinux..parainstructions */
 		snprintf(buf, 256, "%s%s.%s", KLP_ARCH_PREFIX, objname, base->name);
@@ -292,6 +301,27 @@ static void create_klp_arch_sections(str
 		 * single .klp.arch.vmlinux..parainstructions section
 		 */
 		old_size = sec->data->d_size;
+
+		/*
+		 * Due to a quirk in how .parainstructions gets linked, the
+		 * section size doesn't encompass the last 4 bytes of the last
+		 * entry.  Align the old size properly before merging.
+		 */
+		if (!strcmp(base->name, ".parainstructions")) {
+			char *str;
+			static int align_mask = 0;
+
+			if (!align_mask) {
+				str = getenv("PARA_STRUCT_SIZE");
+				if (!str)
+					ERROR("PARA_STRUCT_SIZE not set");
+
+				align_mask = atoi(str) - 1;
+			}
+
+			old_size = (old_size + align_mask) & ~align_mask;
+		}
+
 		new_size = old_size + base->data->d_size;
 		sec->data->d_buf = realloc(sec->data->d_buf, new_size);
 		sec->data->d_size = new_size;
@@ -456,6 +486,9 @@ int main(int argc, char *argv[])
 
 	/* Rebuild rela sections, new klp rela sections will be rebuilt too. */
 	symtab = find_section_by_name(&kelf->sections, ".symtab");
+	if (!symtab)
+		ERROR("missing .symtab section");
+
 	list_for_each_entry(sec, &kelf->sections, list) {
 		if (!is_rela_section(sec))
 			continue;
diff -pruN 0.6.0-0.2/kpatch-build/create-kpatch-module.c 0.8.0-0ubuntu7/kpatch-build/create-kpatch-module.c
--- 0.6.0-0.2/kpatch-build/create-kpatch-module.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/create-kpatch-module.c	2019-08-28 17:34:00.000000000 +0000
@@ -231,6 +231,9 @@ int main(int argc, char *argv[])
 	kpatch_reindex_elements(kelf);
 
 	symtab = find_section_by_name(&kelf->sections, ".symtab");
+	if (!symtab)
+		ERROR("missing .symtab section");
+
 	list_for_each_entry(sec, &kelf->sections, list) {
 		if (!is_rela_section(sec))
 			continue;
diff -pruN 0.6.0-0.2/kpatch-build/gcc-plugins/gcc-common.h 0.8.0-0ubuntu7/kpatch-build/gcc-plugins/gcc-common.h
--- 0.6.0-0.2/kpatch-build/gcc-plugins/gcc-common.h	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/gcc-plugins/gcc-common.h	2019-08-28 17:34:00.000000000 +0000
@@ -96,6 +96,10 @@
 #include "predict.h"
 #include "ipa-utils.h"
 
+#if BUILDING_GCC_VERSION >= 8000
+#include "stringpool.h"
+#endif
+
 #if BUILDING_GCC_VERSION >= 4009
 #include "attribs.h"
 #include "varasm.h"
diff -pruN 0.6.0-0.2/kpatch-build/kpatch-build 0.8.0-0ubuntu7/kpatch-build/kpatch-build
--- 0.6.0-0.2/kpatch-build/kpatch-build	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/kpatch-build	2019-08-28 17:34:00.000000000 +0000
@@ -29,8 +29,8 @@
 # - Either uses a specified kernel source directory or downloads the kernel
 #   source package for the currently running kernel
 # - Unpacks and prepares the source package for building if necessary
-# - Builds the base kernel (vmlinux)
-# - Builds the patched kernel and monitors changed objects
+# - Builds the base kernel or module
+# - Builds the patched kernel/module and monitors changed objects
 # - Builds the patched objects with gcc flags -f[function|data]-sections
 # - Runs kpatch tools to create and link the patch kernel module
 
@@ -50,8 +50,10 @@ DEBUG=0
 SKIPCLEANUP=0
 SKIPGCCCHECK=0
 ARCH_KCFLAGS=""
+DEBUG_KCFLAGS=""
 declare -a PATCH_LIST
 APPLIED_PATCHES=0
+OOT_MODULE=
 
 warn() {
 	echo "ERROR: $1" >&2
@@ -115,8 +117,7 @@ cleanup() {
 
 	remove_patches
 
-	# restore original .config and vmlinux if they were removed with mrproper
-	[[ -e "$TEMPDIR/.config" ]] && mv -f "$TEMPDIR/.config" "$SRCDIR/"
+	# restore original vmlinux if it was overwritten by sourcedir build
 	[[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/"
 
 	[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
@@ -126,7 +127,7 @@ cleanup() {
 }
 
 clean_cache() {
-	rm -rf "$CACHEDIR"
+	rm -rf "${CACHEDIR:?}"/*
 	mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
 }
 
@@ -141,13 +142,13 @@ check_pipe_status() {
 			cp core* /tmp
 			die "core file at /tmp/$(ls core*)"
 		fi
-		die "no core file found, run 'ulimit -c unlimited' and try to recreate"
+		die "There was a SIGSEGV, but no core dump was found in the current directory.  Depending on your distro you might find it in /var/lib/systemd/coredump or /var/crash."
 	fi
 }
 
 # $1 >= $2
 version_gte() {
-	[  "$1" = "$(echo -e "$1\n$2" | sort -rV | head -n1)" ]
+	[  "$1" = "$(echo -e "$1\\n$2" | sort -rV | head -n1)" ]
 }
 
 is_rhel() {
@@ -188,7 +189,7 @@ find_core_symvers() {
 }
 
 gcc_version_from_file() {
-	readelf -p .comment "$1" | grep -o 'GCC:.*'
+	readelf -p .comment "$1" | grep -o 'GCC:.*' | head -n 1
 }
 
 gcc_version_check() {
@@ -200,8 +201,11 @@ gcc_version_check() {
 	echo 'void main(void) {}' > "$c"
 	out="$(gcc -c -pg -ffunction-sections -o "$o" "$c" 2>&1)"
 	gccver="$(gcc_version_from_file "$o")"
-	kgccver="$(gcc_version_from_file "$VMLINUX")"
-	rm -f "$c" "$o"
+	if [[ -n "$OOT_MODULE" ]]; then
+		kgccver="$(gcc_version_from_file "$OOT_MODULE")"
+	else
+		kgccver="$(gcc_version_from_file "$VMLINUX")"
+	fi
 
 	if [[ -n "$out" ]]; then
 		warn "gcc >= 4.8 required for -pg -ffunction-settings"
@@ -209,6 +213,12 @@ gcc_version_check() {
 		return 1
 	fi
 
+	out="$(gcc -c -gz=none -o "$o" "$c" 2>&1)"
+	if [[ -z "$out" ]]; then
+		DEBUG_KCFLAGS="-gz=none"
+	fi
+	rm -f "$c" "$o"
+
 	# ensure gcc version matches that used to build the kernel
 	if [[ "$gccver" != "$kgccver" ]]; then
 		warn "gcc/kernel version mismatch"
@@ -223,33 +233,40 @@ gcc_version_check() {
 }
 
 find_special_section_data_ppc64le() {
+
+	[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1"
+
 	SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
 		gawk --non-decimal-data '
-		BEGIN { f = b = e = 0 }
+		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}
 
 		# 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 }
 
 		# Now that we know the size, stop parsing for it
-		f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); a = 2}
+		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}
 
 		# Bail out once we have everything
-		f == 2 && b == 2 && e == 2 {exit}')"
+		f == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {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"
 
 	return
 }
@@ -261,30 +278,41 @@ find_special_section_data() {
 	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"
+
+	# 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 = 0 }
+		BEGIN { a = b = p = e = o = j = 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}
 
 		# 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 }
 
 		# 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}
 
 		# Bail out once we have everything
-		a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 {exit}')"
+		a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) {exit}')"
 
 	[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
 
@@ -292,6 +320,8 @@ find_special_section_data() {
 	[[ -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"
 
 	return
 }
@@ -303,7 +333,7 @@ find_parent_obj() {
 	pdir="${absdir#$pwddir/}"
 	file="$(basename "$1")"
 	grepname="${1%.o}"
-	grepname="$grepname\.o"
+	grepname="$grepname\\.o"
 	if [[ "$DEEP_FIND" -eq 1 ]]; then
 		num=0
 		if [[ -n "$last_deep_find" ]]; then
@@ -311,8 +341,8 @@ find_parent_obj() {
 			num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -Fvc "$pdir/.${file}.cmd")"
 		fi
 		if [[ "$num" -eq 0 ]]; then
-			parent="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
-			num="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+			parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
+			num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
 			[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
 		fi
 	else
@@ -385,12 +415,14 @@ usage() {
 	echo "		-d, --debug        Enable 'xtrace' and keep scratch files" >&2
 	echo "		                   in <CACHEDIR>/tmp" >&2
 	echo "		                   (can be specified multiple times)" >&2
+	echo "		-e, --oot-module   Enable patching out-of-tree module," >&2
+	echo "		                   specify current version of module" >&2
 	echo "		--skip-cleanup     Skip post-build cleanup" >&2
 	echo "		--skip-gcc-check   Skip gcc version matching check" >&2
 	echo "		                   (not recommended)" >&2
 }
 
-options="$(getopt -o ha:r:s:c:v:j:t:n:o:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
+options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
 
 eval set -- "$options"
 
@@ -448,6 +480,11 @@ while [[ $# -gt 0 ]]; do
 			echo "DEBUG mode enabled"
 		fi
 		;;
+	-e|--oot-module)
+		[[ ! -f "$2" ]] && die "out-of-tree module '$2' not found"
+		OOT_MODULE="$(readlink -f "$2")"
+		shift
+		;;
 	--skip-cleanup)
 		echo "Skipping cleanup"
 		SKIPCLEANUP=1
@@ -476,8 +513,7 @@ if [[ $DEBUG -eq 1 ]] || [[ $DEBUG -ge 3
 fi
 
 if [[ -n "$ARCHVERSION" ]] && [[ -n "$VMLINUX" ]]; then
-	warn "--archversion is incompatible with --vmlinux"
-	exit 1
+	die "--archversion is incompatible with --vmlinux"
 fi
 
 if [[ -n "$SRCRPM" ]]; then
@@ -488,6 +524,12 @@ if [[ -n "$SRCRPM" ]]; then
 	rpmname="$(basename "$SRCRPM")"
 	ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)"
 	ARCHVERSION="${ARCHVERSION#kernel-}"
+	ARCHVERSION="${ARCHVERSION#alt-}"
+fi
+
+if [[ -n "$OOT_MODULE" ]] &&  [[ -z "$USERSRCDIR" ]]; then
+	warn "--oot-module requires --sourcedir"
+	exit 1
 fi
 
 # ensure cachedir and tempdir are setup properly and cleaned
@@ -502,11 +544,15 @@ if [[ -n "$USERSRCDIR" ]]; then
 	fi
 	SRCDIR="$USERSRCDIR"
 
-	[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
-	[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
+	if [[ -z "$OOT_MODULE" ]]; then
+		[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
+		[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
 
-	# Extract the target kernel version from vmlinux in this case.
-	ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')"
+		# Extract the target kernel version from vmlinux in this case.
+		ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')"
+	else
+		ARCHVERSION="$(modinfo -F vermagic "$OOT_MODULE" | awk '{print $1}')"
+	fi
 fi
 
 [[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)"
@@ -518,6 +564,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
 	KREL="${ARCHVERSION##*-}"
 	KREL="${KREL%.*}"
 fi
+[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
 
 [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
 
@@ -553,8 +600,16 @@ fi
 if [[ -n "$USERSRCDIR" ]]; then
 	echo "Using source directory at $USERSRCDIR"
 
-	# save vmlinux before it gets removed with mrproper
-	[[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" "$TEMPDIR/vmlinux" && VMLINUX="$TEMPDIR/vmlinux"
+	# save original vmlinux before it gets overwritten by sourcedir build
+	if [[ -z "$OOT_MODULE" ]] && [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]]; then
+		cp -f "$VMLINUX" "$TEMPDIR/vmlinux"
+		VMLINUX="$TEMPDIR/vmlinux"
+	fi
+
+	# For external modules, use the running kernel's config
+	if [[ -n "$OOT_MODULE" ]] && [[ -z "$CONFIGFILE" ]]; then
+		CONFIGFILE="/boot/config-${ARCHVERSION}"
+	fi
 
 elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then
 	echo "Using cache at $SRCDIR"
@@ -571,19 +626,19 @@ else
 			if [[ "$DISTRO" = fedora ]]; then
 				wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die
 			else
-				rpm -q --quiet yum-utils || die "yum-utils not installed"
-				yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" 2>&1 | logger || die
+				command -v yumdownloader &>/dev/null || die "yumdownloader (yum-utils or dnf-utils) not installed"
+				yumdownloader --source --destdir "$TEMPDIR" "kernel$ALT-$KVER-$KREL" 2>&1 | logger || die
 			fi
-			SRCRPM="$TEMPDIR/kernel-$KVER-$KREL.src.rpm"
+			SRCRPM="$TEMPDIR/kernel$ALT-$KVER-$KREL.src.rpm"
 		fi
 
 		echo "Unpacking kernel source"
 
 		rpm -D "_topdir $RPMTOPDIR" -ivh "$SRCRPM" 2>&1 | logger || die
-		rpmbuild -D "_topdir $RPMTOPDIR" -bp "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel.spec 2>&1 | logger ||
+		rpmbuild -D "_topdir $RPMTOPDIR" -bp --nodeps "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel$ALT.spec 2>&1 | logger ||
 			die "rpmbuild -bp failed.  you may need to run 'yum-builddep kernel' first."
 
-		mv "$RPMTOPDIR"/BUILD/kernel-*/linux-"${ARCHVERSION%.*}"*"${ARCHVERSION##*.}" "$SRCDIR" 2>&1 | logger || die
+		mv "$RPMTOPDIR"/BUILD/kernel-*/linux-* "$SRCDIR" 2>&1 | logger || die
 		rm -rf "$RPMTOPDIR"
 		rm -rf "$SRCDIR/.git"
 
@@ -593,6 +648,10 @@ else
 
 		echo "$ARCHVERSION" > "$VERSIONFILE" || die
 
+		[[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR/configs/kernel$ALT-$KVER-$ARCH.config"
+
+		(cd "$SRCDIR" && make mrproper 2>&1 | logger) || die
+
 	elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
 
 		echo "Debian/Ubuntu distribution detected"
@@ -610,7 +669,7 @@ else
 			sublevel="SUBLEVEL ="
 		fi
 
-		pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION")"
+		pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)"
 		pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")"
 		dscname="${pkgname}_${pkgver}.dsc"
 
@@ -621,7 +680,7 @@ else
 		# Download source deb pkg
 		(dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}"
 		mv "${pkgname}-$KVER" "$SRCDIR" || die
-		cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die
+		[[ -z "$CONFIGFILE" ]] && CONFIGFILE="/boot/config-${ARCHVERSION}"
 		if [[ "$ARCHVERSION" == *-* ]]; then
 			echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
 		fi
@@ -635,10 +694,9 @@ else
 	fi
 fi
 
-# save .config before it gets removed with mrproper
 [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config
 [[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
-[[ "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$TEMPDIR" && CONFIGFILE="$TEMPDIR"/.config
+[[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$SRCDIR/.config"
 
 # Build variables - Set some defaults, then adjust features
 # according to .config and kernel version
@@ -663,15 +721,27 @@ else
 	KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE"
 fi
 
-# optional kernel configs: CONFIG_PARAVIRT
+# optional kernel configs:
 if grep -q "CONFIG_PARAVIRT=y" "$CONFIGFILE"; then
 	CONFIG_PARAVIRT=1
 else
 	CONFIG_PARAVIRT=0
 fi
+if grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE"; then
+	CONFIG_UNWINDER_ORC=1
+else
+	CONFIG_UNWINDER_ORC=0
+fi
+if grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE"; then
+	CONFIG_JUMP_LABEL=1
+else
+	CONFIG_JUMP_LABEL=0
+fi
 
-# unsupported kernel option checking: CONFIG_DEBUG_INFO_SPLIT
+# 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"
 
 echo "Testing patch file(s)"
 cd "$SRCDIR" || die
@@ -684,7 +754,8 @@ if [[ "$ARCH" = "ppc64le" ]]; then
 	ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
 fi
 
-export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS"
+export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \
+		$ARCH_KCFLAGS $DEBUG_KCFLAGS"
 
 echo "Reading special section data"
 find_special_section_data
@@ -693,20 +764,20 @@ if [[ $DEBUG -ge 4 ]]; then
 	export KPATCH_GCC_DEBUG=1
 fi
 
-echo "Building original kernel"
-./scripts/setlocalversion --save-scmversion || die
-make mrproper 2>&1 | logger || die
-cp -f "$CONFIGFILE" "$SRCDIR/.config"
+echo "Building original source"
+[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die
 unset KPATCH_GCC_TEMPDIR
 # $TARGETS used as list, no quotes.
 # shellcheck disable=SC2086
 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
 
-echo "Building patched kernel"
+echo "Building patched source"
 apply_patches
 mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
 KPATCH_GCC_TEMPDIR="$TEMPDIR"
 export KPATCH_GCC_TEMPDIR
+KPATCH_GCC_SRCDIR="$SRCDIR"
+export KPATCH_GCC_SRCDIR
 # $TARGETS used as list, no quotes.
 # shellcheck disable=SC2086
 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
@@ -714,7 +785,7 @@ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
 	make "-j$CPUS" $TARGETS 2>&1 | logger || die
 
 # source.c:(.section+0xFF): undefined reference to `symbol'
-grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\1/" \
+grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
 	>"${TEMPDIR}"/undefined_references
 
 # WARNING: "symbol" [path/to/module.ko] undefined!
@@ -724,6 +795,8 @@ if [[ ! -e "$TEMPDIR/changed_objs" ]]; t
 	die "no changed objects found"
 fi
 
+[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
+
 # Read as words, no quotes.
 # shellcheck disable=SC2013
 for i in $(cat "$TEMPDIR/changed_objs")
@@ -773,16 +846,39 @@ for i in $FILES; do
 	mkdir -p "output/$(dirname "$i")"
 	cd "$SRCDIR" || die
 	find_kobj "$i"
-	if [[ "$KOBJFILE" = vmlinux ]]; then
-		KOBJFILE="$VMLINUX"
-	else
-		KOBJFILE="$TEMPDIR/module/$KOBJFILE"
-	fi
 	cd "$TEMPDIR" || die
 	if [[ -e "orig/$i" ]]; then
-		# create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name
-		"$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \
-			"output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1
+		if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then
+			KOBJFILE_NAME=vmlinux
+			KOBJFILE_PATH="$VMLINUX"
+			SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab"
+			SYMVERS_FILE="$SRCDIR/Module.symvers"
+		elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then
+			KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")"
+			KOBJFILE_PATH="$OOT_MODULE"
+			SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab"
+			SYMVERS_FILE="$TEMPDIR/Module.symvers"
+			BUILDDIR="/lib/modules/$ARCHVERSION/build/"
+			cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+			awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
+		else
+			KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}")
+			KOBJFILE_NAME="${KOBJFILE_NAME/-/_}"
+			KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
+			SYMTAB="${KOBJFILE_PATH}.symtab"
+			SYMVERS_FILE="$SRCDIR/Module.symvers"
+		fi
+
+		readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
+		if [[ "$ARCH" = "ppc64le" ]]; then
+			sed -ri 's/\s+\[<localentry>: 8\]//' "$SYMTAB"
+		fi
+
+		# create-diff-object orig.o patched.o parent-name parent-symtab
+		#		     Module.symvers patch-mod-name output.o
+		"$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE_NAME" \
+			"$SYMTAB" "$SYMVERS_FILE" "${MODNAME//-/_}" \
+			"output/$i" 2>&1 | logger 1
 		check_pipe_status create-diff-object
 		# create-diff-object returns 3 if no functional change is found
 		[[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$((ERROR + 1))"
@@ -808,7 +904,7 @@ fi
 echo -n "Patched objects:"
 for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
 do
-	echo -n " $(basename "$i")"
+	echo -n " $i"
 done
 echo
 
@@ -843,8 +939,12 @@ else
 fi
 
 cd "$TEMPDIR/patch" || die
-
-KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \
+if [[ -z "$OOT_MODULE" ]]; then
+	KPATCH_BUILD="$SRCDIR"
+else
+	KPATCH_BUILD="/lib/modules/$ARCHVERSION/build"
+fi
+KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
 KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
 KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
 	make 2>&1 | logger || die
@@ -859,6 +959,7 @@ if ! "$KPATCH_MODULE"; then
 fi
 
 readelf --wide --symbols "$TEMPDIR/patch/$MODNAME.ko" 2>/dev/null | \
+	sed -r 's/\s+\[<localentry>: 8\]//' | \
 	awk '($4=="FUNC" || $4=="OBJECT") && ($5=="GLOBAL" || $5=="WEAK") && $7!="UND" {print $NF}' \
 	>"${TEMPDIR}"/new_symbols
 
@@ -877,7 +978,7 @@ fi
 # column containing lines unique to first file.
 UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
 	<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
 
 cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
 
diff -pruN 0.6.0-0.2/kpatch-build/kpatch-elf.c 0.8.0-0ubuntu7/kpatch-build/kpatch-elf.c
--- 0.6.0-0.2/kpatch-build/kpatch-elf.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/kpatch-elf.c	2019-08-28 17:34:00.000000000 +0000
@@ -322,7 +322,7 @@ static void kpatch_find_func_profiling_c
 	list_for_each_entry(sym, &kelf->symbols, list) {
 		if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela)
 			continue;
-#ifdef __powerpc__
+#ifdef __powerpc64__
 		list_for_each_entry(rela, &sym->sec->rela->relas, list) {
 			if (!strcmp(rela->sym->name, "_mcount")) {
 				sym->has_func_profiling = 1;
@@ -332,7 +332,9 @@ static void kpatch_find_func_profiling_c
 #else
 		rela = list_first_entry(&sym->sec->rela->relas, struct rela,
 					list);
-		if (rela->type != R_X86_64_NONE ||
+		if ((rela->type != R_X86_64_NONE &&
+		     rela->type != R_X86_64_PC32 &&
+		     rela->type != R_X86_64_PLT32) ||
 		    strcmp(rela->sym->name, "__fentry__"))
 			continue;
 
@@ -565,6 +567,7 @@ void kpatch_create_strtab(struct kpatch_
 void kpatch_create_symtab(struct kpatch_elf *kelf)
 {
 	struct section *symtab;
+	struct section *strtab;
 	struct symbol *sym;
 	char *buf;
 	size_t size;
@@ -598,7 +601,11 @@ void kpatch_create_symtab(struct kpatch_
 	symtab->data->d_size = size;
 
 	/* update symtab section header */
-	symtab->sh.sh_link = find_section_by_name(&kelf->sections, ".strtab")->index;
+	strtab = find_section_by_name(&kelf->sections, ".strtab");
+	if (!strtab)
+		ERROR("missing .strtab section");
+
+	symtab->sh.sh_link = strtab->index;
 	symtab->sh.sh_info = nr_local;
 }
 
@@ -647,6 +654,7 @@ struct section *create_section_pair(stru
 	relasec->data = malloc(sizeof(*relasec->data));
 	if (!relasec->data)
 		ERROR("malloc");
+	relasec->data->d_type = ELF_T_RELA;
 
 	/* set section header */
 	relasec->sh.sh_type = SHT_RELA;
@@ -750,6 +758,7 @@ void kpatch_write_output_elf(struct kpat
 {
 	int fd;
 	struct section *sec;
+	struct section *shstrtab;
 	Elf *elfout;
 	GElf_Ehdr eh, ehout;
 	Elf_Scn *scn;
@@ -765,7 +774,7 @@ void kpatch_write_output_elf(struct kpat
 	if (!elfout)
 		ERROR("elf_begin");
 
-	if (!gelf_newehdr(elfout, gelf_getclass(kelf->elf)))
+	if (!gelf_newehdr(elfout, gelf_getclass(elf)))
 		ERROR("gelf_newehdr");
 
 	if (!gelf_getehdr(elfout, &ehout))
@@ -779,7 +788,12 @@ void kpatch_write_output_elf(struct kpat
 	ehout.e_machine = eh.e_machine;
 	ehout.e_type = eh.e_type;
 	ehout.e_version = EV_CURRENT;
-	ehout.e_shstrndx = find_section_by_name(&kelf->sections, ".shstrtab")->index;
+
+	shstrtab = find_section_by_name(&kelf->sections, ".shstrtab");
+	if (!shstrtab)
+		ERROR("missing .shstrtab section");
+
+	ehout.e_shstrndx = shstrtab->index;
 
 	/* add changed sections */
 	list_for_each_entry(sec, &kelf->sections, list) {
@@ -814,6 +828,9 @@ void kpatch_write_output_elf(struct kpat
 		printf("%s\n",elf_errmsg(-1));
 		ERROR("elf_update");
 	}
+
+	elf_end(elfout);
+	close(fd);
 }
 
 /*
diff -pruN 0.6.0-0.2/kpatch-build/kpatch-elf.h 0.8.0-0ubuntu7/kpatch-build/kpatch-elf.h
--- 0.6.0-0.2/kpatch-build/kpatch-elf.h	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/kpatch-elf.h	2019-08-28 17:34:00.000000000 +0000
@@ -70,6 +70,8 @@ struct section {
 struct symbol {
 	struct list_head list;
 	struct symbol *twin;
+	struct symbol *parent;
+	struct symbol *child;
 	struct section *sec;
 	GElf_Sym sym;
 	char *name;
@@ -128,7 +130,8 @@ struct rela *find_rela_by_offset(struct
 		ERROR("malloc"); \
 	memset((_new), 0, sizeof(*(_new))); \
 	INIT_LIST_HEAD(&(_new)->list); \
-	list_add_tail(&(_new)->list, (_list)); \
+	if (_list) \
+		list_add_tail(&(_new)->list, (_list)); \
 }
 
 int offset_of_string(struct list_head *list, char *name);
diff -pruN 0.6.0-0.2/kpatch-build/kpatch-gcc 0.8.0-0ubuntu7/kpatch-build/kpatch-gcc
--- 0.6.0-0.2/kpatch-build/kpatch-gcc	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/kpatch-gcc	2019-08-28 17:34:00.000000000 +0000
@@ -13,7 +13,7 @@ fi
 
 declare -a args=("$@")
 
-if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
 	while [ "$#" -gt 0 ]; do
 		if [ "$1" = "-o" ]; then
 			obj="$2"
@@ -23,7 +23,8 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
 			[[ "$obj" = */.tmp_mc_*.o ]] && break;
 
 			[[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
-			case "$obj" in
+			relobj=${obj//$KPATCH_GCC_SRCDIR\//}
+			case "$relobj" in
 				*.mod.o|\
 				*built-in.o|\
 				*built-in.a|\
@@ -41,14 +42,15 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
 				arch/x86/entry/vdso/*|\
 				drivers/firmware/efi/libstub/*|\
 				arch/powerpc/kernel/prom_init.o|\
+				lib/*|\
 				.*.o|\
 				*/.lib_exports.o)
 					break
 					;;
 				*.o)
-					mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$obj")"
-					[[ -e "$obj" ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$obj"
-					echo "$obj" >> "$KPATCH_GCC_TEMPDIR/changed_objs"
+					mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")"
+					[[ -e "$obj" ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$relobj"
+					echo "$relobj" >> "$KPATCH_GCC_TEMPDIR/changed_objs"
 					break
 					;;
 				*)
@@ -62,10 +64,11 @@ elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
 	while [ "$#" -gt 0 ]; do
 		if [ "$1" = "-o" ]; then
 			obj="$2"
+			relobj=${obj//$KPATCH_GCC_SRCDIR\//}
 			case "$obj" in
 				*.ko)
-					mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$obj")"
-					cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$obj"
+					mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$relobj")"
+					cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$relobj"
 					break
 					;;
 				.tmp_vmlinux*|vmlinux)
diff -pruN 0.6.0-0.2/kpatch-build/kpatch.h 0.8.0-0ubuntu7/kpatch-build/kpatch.h
--- 0.6.0-0.2/kpatch-build/kpatch.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/kpatch.h	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+#ifndef _KPATCH_H_
+#define _KPATCH_H_
+
+enum exit_status {
+	EXIT_STATUS_SUCCESS		= 0,
+	EXIT_STATUS_ERROR		= 1,
+	EXIT_STATUS_DIFF_FATAL		= 2,
+	EXIT_STATUS_NO_CHANGE		= 3,
+};
+
+#endif /* _KPATCH_H_ */
diff -pruN 0.6.0-0.2/kpatch-build/log.h 0.8.0-0ubuntu7/kpatch-build/log.h
--- 0.6.0-0.2/kpatch-build/log.h	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/log.h	2019-08-28 17:34:00.000000000 +0000
@@ -2,13 +2,14 @@
 #define _LOG_H_
 
 #include <error.h>
+#include "kpatch.h"
 
 /* Files that include log.h must define loglevel and childobj */
 extern enum loglevel loglevel;
 extern char *childobj;
 
 #define ERROR(format, ...) \
-	error(1, 0, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+	error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__)
 
 #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__)
 #define log_normal(format, ...) log(NORMAL, "%s: " format, childobj, ##__VA_ARGS__)
diff -pruN 0.6.0-0.2/kpatch-build/lookup.c 0.8.0-0ubuntu7/kpatch-build/lookup.c
--- 0.6.0-0.2/kpatch-build/lookup.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/lookup.c	2019-08-28 17:34:00.000000000 +0000
@@ -43,7 +43,7 @@ struct object_symbol {
 	unsigned long value;
 	unsigned long size;
 	char *name;
-	int type, bind, skip;
+	int type, bind;
 };
 
 struct export_symbol {
@@ -80,7 +80,8 @@ static int maybe_discarded_sym(const cha
 	 */
 	if (!strncmp(name, "__exitcall_", 11) ||
 	    !strncmp(name, "__brk_reservation_fn_", 21) ||
-	    !strncmp(name, "__func_stack_frame_non_standard_", 32))
+	    !strncmp(name, "__func_stack_frame_non_standard_", 32) ||
+	    !strncmp(name, "__addressable_", 14))
 		return 1;
 
 	return 0;
@@ -171,105 +172,112 @@ static void find_local_syms(struct looku
 	}
 
 	if (!table->local_syms)
-		ERROR("find_local_syms for %s: found_none", hint);
+		ERROR("find_local_syms for %s: couldn't find in vmlinux symbol table", hint);
 }
 
-static void obj_read(struct lookup_table *table, char *path)
+/* Strip the path and replace '-' with '_' */
+static char *make_modname(char *modname)
 {
-	Elf *elf;
-	int fd, i, len;
-	Elf_Scn *scn;
-	GElf_Shdr sh;
-	GElf_Sym sym;
-	Elf_Data *data;
-	char *name;
-	struct object_symbol *mysym;
-	size_t shstrndx;
+	char *cur, *name;
 
-	if ((fd = open(path, O_RDONLY, 0)) < 0)
-		ERROR("open");
+	if (!modname)
+		return NULL;
 
-	elf_version(EV_CURRENT);
+	name = strdup(basename(modname));
+	if (!name)
+		ERROR("strdup");
 
-	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
-	if (!elf) {
-		printf("%s\n", elf_errmsg(-1));
-		ERROR("elf_begin");
+	cur = name; /* use cur as tmp */
+	while (*cur != '\0') {
+		if (*cur == '-')
+			*cur = '_';
+		cur++;
 	}
 
-	if (elf_getshdrstrndx(elf, &shstrndx))
-		ERROR("elf_getshdrstrndx");
+	return name;
+}
 
-	scn = NULL;
-	while ((scn = elf_nextscn(elf, scn))) {
-		if (!gelf_getshdr(scn, &sh))
-			ERROR("gelf_getshdr");
-
-		name = elf_strptr(elf, shstrndx, sh.sh_name);
-		if (!name)
-			ERROR("elf_strptr scn");
+static void symtab_read(struct lookup_table *table, char *path)
+{
+	FILE *file;
+	long unsigned int value;
+	unsigned int i = 0;
+	int matched;
+	char line[256], name[256], size[16], type[16], bind[16], ndx[16];
 
-		if (!strcmp(name, ".symtab"))
-			break;
-	}
+	if ((file = fopen(path, "r")) == NULL)
+		ERROR("fopen");
 
-	if (!scn)
-		ERROR(".symtab section not found");
+	while (fgets(line, 256, file)) {
+		matched = sscanf(line, "%*s %lx %s %s %s %*s %s %s\n",
+				 &value, size, type, bind, ndx, name);
+
+		if (matched == 5) {
+			name[0] = '\0';
+			matched++;
+		}
 
-	data = elf_getdata(scn, NULL);
-	if (!data)
-		ERROR("elf_getdata");
+		if (matched != 6 ||
+		    !strcmp(ndx, "UND") ||
+		    !strcmp(type, "SECTION"))
+			continue;
 
-	len = sh.sh_size / sh.sh_entsize;
+		table->obj_nr++;
+	}
 
-	table->obj_syms = malloc(len * sizeof(*table->obj_syms));
+	table->obj_syms = malloc(table->obj_nr * sizeof(*table->obj_syms));
 	if (!table->obj_syms)
 		ERROR("malloc table.obj_syms");
-	memset(table->obj_syms, 0, len * sizeof(*table->obj_syms));
-	table->obj_nr = len;
+	memset(table->obj_syms, 0, table->obj_nr * sizeof(*table->obj_syms));
 
-	for_each_obj_symbol(i, mysym, table) {
-		if (!gelf_getsym(data, i, &sym))
-			ERROR("gelf_getsym");
+	rewind(file);
 
-		if (sym.st_shndx == SHN_UNDEF) {
-			mysym->skip = 1;
-			continue;
+	while (fgets(line, 256, file)) {
+		matched = sscanf(line, "%*s %lx %s %s %s %*s %s %s\n",
+				 &value, size, type, bind, ndx, name);
+
+		if (matched == 5) {
+			name[0] = '\0';
+			matched++;
 		}
 
-		name = elf_strptr(elf, sh.sh_link, sym.st_name);
-		if(!name)
-			ERROR("elf_strptr sym");
-
-		mysym->value = sym.st_value;
-		mysym->size = sym.st_size;
-		mysym->type = GELF_ST_TYPE(sym.st_info);
-		mysym->bind = GELF_ST_BIND(sym.st_info);
-		mysym->name = strdup(name);
-		if (!mysym->name)
-			ERROR("strdup");
-	}
+		if (matched != 6 ||
+		    !strcmp(ndx, "UND") ||
+		    !strcmp(type, "SECTION"))
+			continue;
 
-	close(fd);
-	elf_end(elf);
-}
+		table->obj_syms[i].value = value;
+		table->obj_syms[i].size = strtoul(size, NULL, 0);
 
-/* Strip the path and replace '-' with '_' */
-static char *make_modname(char *modname)
-{
-	char *cur;
+		if (!strcmp(bind, "LOCAL")) {
+			table->obj_syms[i].bind = STB_LOCAL;
+		} else if (!strcmp(bind, "GLOBAL")) {
+			table->obj_syms[i].bind = STB_GLOBAL;
+		} else if (!strcmp(bind, "WEAK")) {
+			table->obj_syms[i].bind = STB_WEAK;
+		} else {
+			ERROR("unknown symbol bind %s", bind);
+		}
 
-	if (!modname)
-		return NULL;
+		if (!strcmp(type, "NOTYPE")) {
+			table->obj_syms[i].type = STT_NOTYPE;
+		} else if (!strcmp(type, "OBJECT")) {
+			table->obj_syms[i].type = STT_OBJECT;
+		} else if (!strcmp(type, "FUNC")) {
+			table->obj_syms[i].type = STT_FUNC;
+		} else if (!strcmp(type, "FILE")) {
+			table->obj_syms[i].type = STT_FILE;
+		} else {
+			ERROR("unknown symbol type %s", type);
+		}
 
-	cur = modname;
-	while (*cur != '\0') {
-		if (*cur == '-')
-			*cur = '_';
-		cur++;
+		table->obj_syms[i].name = strdup(name);
+		if (!table->obj_syms[i].name)
+			ERROR("strdup");
+		i++;
 	}
 
-	return basename(modname);
+	fclose(file);
 }
 
 static void symvers_read(struct lookup_table *table, char *path)
@@ -279,7 +287,7 @@ static void symvers_read(struct lookup_t
 	char name[256], mod[256], export[256];
 	char *objname, *symname;
 
-	if ((file = fopen(path, "r")) < 0)
+	if ((file = fopen(path, "r")) == NULL)
 		ERROR("fopen");
 
 	while (fscanf(file, "%x %s %s %s\n",
@@ -300,11 +308,7 @@ static void symvers_read(struct lookup_t
 		if (!symname)
 			perror("strdup");
 
-		objname = strdup(mod);
-		if (!objname)
-			perror("strdup");
-		/* Modifies objname in-place */
-		objname = make_modname(objname);
+		objname = make_modname(mod);
 
 		table->exp_syms[i].name = symname;
 		table->exp_syms[i].objname = objname;
@@ -314,7 +318,7 @@ static void symvers_read(struct lookup_t
 	fclose(file);
 }
 
-struct lookup_table *lookup_open(char *obj_path, char *symvers_path,
+struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
 				 char *hint, struct sym_compare_type *locals)
 {
 	struct lookup_table *table;
@@ -324,7 +328,7 @@ struct lookup_table *lookup_open(char *o
 		ERROR("malloc table");
 	memset(table, 0, sizeof(*table));
 
-	obj_read(table, obj_path);
+	symtab_read(table, symtab_path);
 	symvers_read(table, symvers_path);
 	find_local_syms(table, hint, locals);
 
@@ -333,7 +337,18 @@ struct lookup_table *lookup_open(char *o
 
 void lookup_close(struct lookup_table *table)
 {
+	int i;
+	struct object_symbol *obj_sym;
+	struct export_symbol *exp_sym;
+
+	for_each_obj_symbol(i, obj_sym, table)
+		free(obj_sym->name);
 	free(table->obj_syms);
+
+	for_each_exp_symbol(i, exp_sym, table) {
+		free(exp_sym->name);
+		free(exp_sym->objname);
+	}
 	free(table->exp_syms);
 	free(table);
 }
@@ -350,9 +365,6 @@ int lookup_local_symbol(struct lookup_ta
 
 	memset(result, 0, sizeof(*result));
 	for_each_obj_symbol(i, sym, table) {
-		if (sym->skip)
-			continue;
-
 		if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
 			pos++;
 
@@ -390,7 +402,7 @@ int lookup_global_symbol(struct lookup_t
 
 	memset(result, 0, sizeof(*result));
 	for_each_obj_symbol(i, sym, table) {
-		if (!sym->skip && (sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+		if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
 		    !strcmp(sym->name, name)) {
 			result->value = sym->value;
 			result->size = sym->size;
diff -pruN 0.6.0-0.2/kpatch-build/lookup.h 0.8.0-0ubuntu7/kpatch-build/lookup.h
--- 0.6.0-0.2/kpatch-build/lookup.h	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/kpatch-build/lookup.h	2019-08-28 17:34:00.000000000 +0000
@@ -14,7 +14,7 @@ struct sym_compare_type {
 	int type;
 };
 
-struct lookup_table *lookup_open(char *obj_path, char *symvers_path,
+struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
 				 char *hint, struct sym_compare_type *locals);
 void lookup_close(struct lookup_table *table);
 int lookup_local_symbol(struct lookup_table *table, char *name,
diff -pruN 0.6.0-0.2/Makefile 0.8.0-0ubuntu7/Makefile
--- 0.6.0-0.2/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/Makefile	2019-08-28 17:34:00.000000000 +0000
@@ -7,10 +7,14 @@ UNINSTALL_DIRS = $(SUBDIRS:%=uninstall-%
 CLEAN_DIRS   = $(SUBDIRS:%=clean-%)
 
 UNITTEST_DIR = test/unit
+INTEGRATION_DIR = test/integration
 CLEAN_DIRS  += clean-$(UNITTEST_DIR)
 
 .PHONY: all install uninstall clean check unit
 .PHONY: $(SUBDIRS) $(BUILD_DIRS) $(INSTALL_DIRS) $(CLEAN_DIRS)
+.PHONY: integration integration-slow integration-quick
+.PHONY: vagrant-integration-slow vagrant-integration-quick vagrant-integration
+.PHONY: vagrant-install
 
 
 all: $(BUILD_DIRS)
@@ -32,5 +36,30 @@ $(CLEAN_DIRS):
 unit: $(UNITTEST_DIR)/Makefile build-kpatch-build
 	$(MAKE) -C $(UNITTEST_DIR)
 
+integration: integration-quick
+
+integration-slow: $(INTEGRATION_DIR)/Makefile build-kpatch-build build-kpatch build-kmod
+	$(MAKE) -C $(INTEGRATION_DIR) slow
+
+integration-quick: $(INTEGRATION_DIR)/Makefile build-kpatch-build build-kpatch build-kmod
+	$(MAKE) -C $(INTEGRATION_DIR) quick
+
+vagrant-install: $(INTEGRATION_DIR)/lib.sh
+ifneq ($(shell id -u), 0)
+	@echo "WARNING: This target is intended for use on freshly-installed machines/vms only." && \
+	echo "Do not proceed unless you read $(INTEGRATION_DIR)/lib.sh and realise what this target does." && \
+	echo "Press ctrl-c to abort, return to proceed." && \
+	read
+endif
+	source $(INTEGRATION_DIR)/lib.sh && kpatch_check_install_vagrant
+
+vagrant-integration: vagrant-integration-quick
+
+vagrant-integration-slow:
+	$(MAKE) -C $(INTEGRATION_DIR) vagrant-slow
+
+vagrant-integration-quick:
+	$(MAKE) -C $(INTEGRATION_DIR) vagrant-quick
+
 check:
 	shellcheck kpatch/kpatch kpatch-build/kpatch-build kpatch-build/kpatch-gcc
diff -pruN 0.6.0-0.2/man/kpatch.1 0.8.0-0ubuntu7/man/kpatch.1
--- 0.6.0-0.2/man/kpatch.1	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/man/kpatch.1	2019-08-28 17:34:00.000000000 +0000
@@ -35,6 +35,9 @@ info <module>
 list
        list installed patch modules
 
+signal
+       signal/poke any process stalling the current patch transition
+
 version
        display the kpatch version
 
diff -pruN 0.6.0-0.2/man/kpatch-build.1 0.8.0-0ubuntu7/man/kpatch-build.1
--- 0.6.0-0.2/man/kpatch-build.1	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/man/kpatch-build.1	2019-08-28 17:34:00.000000000 +0000
@@ -11,9 +11,6 @@ currently running and creates a kernel m
 modified functions in the kernel such that the patched code takes 
 effect.
 
-This script currently only works on Fedora and will need to be adapted 
-to work on other distros.  
-
 .SH OPTIONS
 
 -h|--help
@@ -50,6 +47,10 @@ to work on other distros.
    Keep scratch files in /tmp
    (can be specified multiple times)
 
+-e|--oot-module
+   Enable patching out-of-tree module,
+   specify current version of module
+
 --skip-cleanup
    Skip post-build cleanup
 
diff -pruN 0.6.0-0.2/README.md 0.8.0-0ubuntu7/README.md
--- 0.6.0-0.2/README.md	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/README.md	2019-08-28 17:34:00.000000000 +0000
@@ -44,6 +44,9 @@ sudo dnf install pesign yum-utils openss
 sudo dnf builddep kernel-${UNAME%.*}
 sudo dnf debuginfo-install kernel-${UNAME%.*}
 
+# required on ppc64le
+sudo dnf install gcc-plugin-devel
+
 # optional, but highly recommended
 sudo dnf install ccache
 ccache --max-size=5G
@@ -75,6 +78,9 @@ sudo yum install pesign yum-utils zlib-d
 sudo yum-builddep kernel-${UNAME%.*}
 sudo debuginfo-install kernel-${UNAME%.*}
 
+# required on ppc64le
+sudo yum install gcc-plugin-devel
+
 # optional, but highly recommended
 sudo yum install https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/c/ccache-3.3.4-1.el7.x86_64.rpm
 ccache --max-size=5G
@@ -152,7 +158,7 @@ ccache --max-size=5G
 sudo yum install patchutils
 ```
 
-#### Ubuntu 14.04
+#### Ubuntu
 
 *NOTE: You'll need about 15GB of free disk space for the kpatch-build cache in
 `~/.kpatch` and for ccache.*
@@ -166,9 +172,13 @@ apt-get install make gcc libelf-dev
 Install the dependencies for the "kpatch-build" command:
 
 ```bash
-apt-get install dpkg-dev devscripts
+apt-get install dpkg-dev devscripts elfutils
 apt-get build-dep linux
 
+# required on ppc64le
+# e.g., on Ubuntu 18.04 for gcc-7.3
+apt-get install gcc-7-plugin-dev
+
 # optional, but highly recommended
 apt-get install ccache
 ccache --max-size=5G
@@ -232,6 +242,10 @@ Install the dependencies for the "kpatch
     apt-get install dpkg-dev
     apt-get build-dep linux
 
+    # required on ppc64le
+    # e.g., on stretch for gcc-6.3
+    apt-get install gcc-6-plugin-dev
+
     # optional, but highly recommended
     apt-get install ccache
     ccache --max-size=5G
@@ -459,11 +473,10 @@ Limitations
   supported.  kpatch-build will return an error if the patch attempts
   to do so.
 
-- Patches which modify statically allocated data are not supported.
-  kpatch-build will detect that and return an error.  (In the future
-  we will add a facility to support it.  It will probably require the
-  user to write code which runs at patch module loading time which manually
-  updates the data.)
+- Patches which modify statically allocated data are not directly supported.
+  kpatch-build will detect that and return an error.  This limitation can be
+  overcome by using callbacks or shadow variables, as described in the
+  [Patch Author Guide](doc/patch-author-guide.md).
 
 - Patches which change the way a function interacts with dynamically
   allocated data might be safe, or might not.  It isn't possible for
@@ -634,9 +647,27 @@ sys_nanosleep(), etc?**
 
 **Q. Can you patch out-of-tree modules?**
 
-- Yes, though it's currently a bit of a manual process.  See this
-  [message](https://www.redhat.com/archives/kpatch/2015-June/msg00004.html) on
-  the kpatch mailing list for more information.
+Yes! There's a few requirements, and the feature is still in its infancy.
+
+1. You need to use the `--oot-module` flag to specify the version of the
+module that's currently running on the machine.
+2. `--sourcedir` has to be passed with a directory containing the same
+version of code as the running module, all set up and ready to build with a
+`make` command. For example, some modules need `autogen.sh` and
+`./configure` to have been run with the appropriate flags to match the
+currently-running module.
+3. If the `Module.symvers` file for the out-of-tree module doesn't appear
+in the root of the provided source directory, a symlink needs to be created
+in that directory that points to its actual location.
+4. Usually you'll need to pass the `--target` flag as well, to specify the
+proper `make` target names.
+5. This has only been tested for a single out-of-tree module per patch, and
+not for out-of-tree modules with dependencies on other out-of-tree modules
+built separately.
+
+***Sample invocation***
+
+`kpatch-build --sourcedir ~/test/ --target default --oot-module /lib/modules/$(uname -r)/extra/test.ko test.patch`
 
 
 Get involved
diff -pruN 0.6.0-0.2/test/difftree.sh 0.8.0-0ubuntu7/test/difftree.sh
--- 0.6.0-0.2/test/difftree.sh	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/difftree.sh	2019-08-28 17:34:00.000000000 +0000
@@ -46,7 +46,7 @@ do
 		;;
 	esac
 	# skip objects that are the linked product of more than one object file
-	[[ $(eu-readelf -s $i | grep FILE | wc -l) -ne 1 ]] && continue
+	[[ $(readelf -s $i | awk '$4=="FILE" {n++} END {print n}') -ne 1 ]] && continue
 	$SCRIPTDIR/../kpatch-build/create-diff-object $i $i /usr/lib/debug/lib/modules/$(uname -r)/vmlinux "$TEMPDIR/output.o" > "$TEMPDIR/log.txt" 2>&1
 	RETCODE=$?
 	# expect RETCODE to be 3 indicating no change
diff -pruN 0.6.0-0.2/test/integration/centos-7/fixup-section.patch 0.8.0-0ubuntu7/test/integration/centos-7/fixup-section.patch
--- 0.6.0-0.2/test/integration/centos-7/fixup-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,12 +1,12 @@
-diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c
---- src.orig/fs/readdir.c	2017-09-22 15:27:21.658056010 -0400
-+++ src/fs/readdir.c	2017-09-22 15:27:26.378075555 -0400
-@@ -166,6 +166,8 @@ static int filldir(void * __buf, const c
+diff --git a/fs/readdir.c b/fs/readdir.c
+index febd02dfbe2d..064db7bd70d0 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
  			goto efault;
  	}
  	dirent = buf->current_dir;
-+	if (dirent->d_ino == 12345678)
-+		printk("kpatch-test: testing .fixup section changes\n");
++	asm("nop");
  	if (__put_user(d_ino, &dirent->d_ino))
  		goto efault;
  	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/centos-7/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/centos-7/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/centos-7/gcc-static-local-var-4.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
 	exit 1
 else
 	exit 0
diff -pruN 0.6.0-0.2/test/integration/centos-7/macro-printk.patch 0.8.0-0ubuntu7/test/integration/centos-7/macro-printk.patch
--- 0.6.0-0.2/test/integration/centos-7/macro-printk.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,7 +1,8 @@
-diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c
---- src.orig/net/ipv4/fib_frontend.c	2017-09-22 16:52:10.646110299 -0400
-+++ src/net/ipv4/fib_frontend.c	2017-09-22 16:55:14.395870305 -0400
-@@ -633,6 +633,7 @@ errout:
+Index: src/net/ipv4/fib_frontend.c
+===================================================================
+--- src.orig/net/ipv4/fib_frontend.c
++++ src/net/ipv4/fib_frontend.c
+@@ -685,6 +685,7 @@ errout:
  	return err;
  }
  
@@ -9,7 +10,7 @@ diff -Nupr src.orig/net/ipv4/fib_fronten
  static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
  	struct net *net = sock_net(skb->sk);
-@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b
+@@ -703,6 +704,7 @@ static int inet_rtm_newroute(struct sk_b
  	}
  
  	err = fib_table_insert(net, tb, &cfg);
@@ -17,10 +18,11 @@ diff -Nupr src.orig/net/ipv4/fib_fronten
  errout:
  	return err;
  }
-diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c
---- src.orig/net/ipv4/fib_semantics.c	2017-09-22 16:52:10.645110295 -0400
-+++ src/net/ipv4/fib_semantics.c	2017-09-22 16:54:05.175584004 -0400
-@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi,
+Index: src/net/ipv4/fib_semantics.c
+===================================================================
+--- src.orig/net/ipv4/fib_semantics.c
++++ src/net/ipv4/fib_semantics.c
+@@ -969,6 +969,7 @@ fib_convert_metrics(struct fib_info *fi,
  	return 0;
  }
  
@@ -28,7 +30,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  struct fib_info *fib_create_info(struct fib_config *cfg)
  {
  	int err;
-@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct
+@@ -993,6 +994,7 @@ struct fib_info *fib_create_info(struct
  #endif
  
  	err = -ENOBUFS;
@@ -36,7 +38,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  	if (fib_info_cnt >= fib_info_hash_size) {
  		unsigned int new_size = fib_info_hash_size << 1;
  		struct hlist_head *new_info_hash;
-@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct
+@@ -1013,6 +1015,7 @@ struct fib_info *fib_create_info(struct
  		if (!fib_info_hash_size)
  			goto failure;
  	}
@@ -44,15 +46,15 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
  	if (fi == NULL)
-@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct
- 	} else
- 		fi->fib_metrics = (u32 *) dst_default_metrics;
+@@ -1028,6 +1031,7 @@ struct fib_info *fib_create_info(struct
+ 		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
+ 	}
  	fib_info_cnt++;
 +	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
- 
  	fi->fib_net = net;
  	fi->fib_protocol = cfg->fc_protocol;
-@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct
+ 	fi->fib_scope = cfg->fc_scope;
+@@ -1043,8 +1047,10 @@ struct fib_info *fib_create_info(struct
  		if (!nexthop_nh->nh_pcpu_rth_output)
  			goto failure;
  	} endfor_nexthops(fi)
@@ -63,7 +65,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  	if (err)
  		goto failure;
  
-@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct
+@@ -1095,6 +1101,7 @@ struct fib_info *fib_create_info(struct
  		nh->nh_weight = 1;
  #endif
  	}
@@ -71,7 +73,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (fib_props[cfg->fc_type].error) {
  		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
-@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct
+@@ -1112,6 +1119,7 @@ struct fib_info *fib_create_info(struct
  			goto err_inval;
  		}
  	}
@@ -79,7 +81,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (cfg->fc_scope > RT_SCOPE_HOST)
  		goto err_inval;
-@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct
+@@ -1134,6 +1142,7 @@ struct fib_info *fib_create_info(struct
  				goto failure;
  		} endfor_nexthops(fi)
  	}
@@ -87,7 +89,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (fi->fib_prefsrc) {
  		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
-@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct
+@@ -1146,6 +1155,7 @@ struct fib_info *fib_create_info(struct
  		fib_info_update_nh_saddr(net, nexthop_nh);
  		fib_add_weight(fi, nexthop_nh);
  	} endfor_nexthops(fi)
@@ -95,7 +97,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fib_rebalance(fi);
  
-@@ -1110,6 +1120,7 @@ link_it:
+@@ -1157,6 +1167,7 @@ link_it:
  		ofi->fib_treeref++;
  		return ofi;
  	}
@@ -103,7 +105,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fi->fib_treeref++;
  	atomic_inc(&fi->fib_clntref);
-@@ -1133,6 +1144,7 @@ link_it:
+@@ -1180,6 +1191,7 @@ link_it:
  		hlist_add_head(&nexthop_nh->nh_hash, head);
  	} endfor_nexthops(fi)
  	spin_unlock_bh(&fib_info_lock);
@@ -111,7 +113,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  	return fi;
  
  err_inval:
-@@ -1143,6 +1155,7 @@ failure:
+@@ -1190,6 +1202,7 @@ failure:
  		fi->fib_dead = 1;
  		free_fib_info(fi);
  	}
@@ -119,10 +121,11 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	return ERR_PTR(err);
  }
-diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c
---- src.orig/net/ipv4/fib_trie.c	2017-09-22 16:52:10.645110295 -0400
-+++ src/net/ipv4/fib_trie.c	2017-09-22 16:55:39.940975963 -0400
-@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie
+Index: src/net/ipv4/fib_trie.c
+===================================================================
+--- src.orig/net/ipv4/fib_trie.c
++++ src/net/ipv4/fib_trie.c
+@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie
  }
  
  /* Caller must hold RTNL. */
@@ -130,7 +133,7 @@ diff -Nupr src.orig/net/ipv4/fib_trie.c
  int fib_table_insert(struct net *net, struct fib_table *tb,
  		     struct fib_config *cfg)
  {
-@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st
+@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st
  	if ((plen < KEYLENGTH) && (key << plen))
  		return -EINVAL;
  
@@ -144,4 +147,4 @@ diff -Nupr src.orig/net/ipv4/fib_trie.c
 +	KPATCH_PRINTK("[fib_table_insert]: cross\n");
  
  	l = fib_find_node(t, &tp, key);
- 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL;
+ 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
diff -pruN 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test
--- 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled
--- 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch
--- 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
---- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
-+++ src/fs/proc/cmdline.c	2017-09-22 15:27:37.842123028 -0400
-@@ -5,7 +5,7 @@
- 
- static int cmdline_proc_show(struct seq_file *m, void *v)
- {
--	seq_printf(m, "%s\n", saved_command_line);
-+	seq_printf(m, "%s kpatch=1\n", saved_command_line);
- 	return 0;
- }
- 
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
-+++ src/fs/proc/meminfo.c	2017-09-22 15:27:37.843123032 -0400
-@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
- 		"Committed_AS:   %8lu kB\n"
- 		"VmallocTotal:   %8lu kB\n"
- 		"VmallocUsed:    %8lu kB\n"
--		"VmallocChunk:   %8lu kB\n"
-+		"VMALLOCCHUNK:   %8lu kB\n"
- #ifdef CONFIG_MEMORY_FAILURE
- 		"HardwareCorrupted: %5lu kB\n"
- #endif
-diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h
---- src.orig/include/linux/kernel.h	2017-09-22 15:27:20.379050713 -0400
-+++ src/include/linux/kernel.h	2017-09-22 15:27:37.843123032 -0400
-@@ -2,6 +2,7 @@
- #define _LINUX_KERNEL_H
- 
- 
-+
- #include <stdarg.h>
- #include <linux/linkage.h>
- #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled
--- 0.6.0-0.2/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,37 @@
+Disabled due to CSWTITCH issue from https://github.com/dynup/kpatch/issues/876
+---
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:37.842123028 -0400
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:37.843123032 -0400
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
+diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h
+--- src.orig/include/linux/kernel.h	2017-09-22 15:27:20.379050713 -0400
++++ src/include/linux/kernel.h	2017-09-22 15:27:37.843123032 -0400
+@@ -2,6 +2,7 @@
+ #define _LINUX_KERNEL_H
+ 
+ 
++
+ #include <stdarg.h>
+ #include <linux/linkage.h>
+ #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/centos-7/module-shadow.patch 0.8.0-0ubuntu7/test/integration/centos-7/module-shadow.patch
--- 0.6.0-0.2/test/integration/centos-7/module-shadow.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/module-shadow.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,22 +1,23 @@
-diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
---- src.orig/arch/x86/kvm/vmx.c	2017-09-22 15:27:20.853052676 -0400
-+++ src/arch/x86/kvm/vmx.c	2017-09-22 15:27:44.742151601 -0400
-@@ -10581,10 +10581,20 @@ static void vmx_leave_nested(struct kvm_
+Index: src/arch/x86/kvm/vmx.c
+===================================================================
+--- src.orig/arch/x86/kvm/vmx.c
++++ src/arch/x86/kvm/vmx.c
+@@ -11406,10 +11406,20 @@ static void vmx_leave_nested(struct kvm_
   * It should only be called before L2 actually succeeded to run, and when
   * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
   */
-+#include "kpatch.h"
++#include <linux/livepatch.h>
  static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
  			struct vmcs12 *vmcs12,
  			u32 reason, unsigned long qualification)
  {
 +	int *kpatch;
 +
-+	kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch),
-+				     GFP_KERNEL);
++	kpatch = klp_shadow_alloc(vcpu, 0, sizeof(*kpatch),
++				     GFP_KERNEL, NULL, NULL);
 +	if (kpatch) {
-+		kpatch_shadow_get(vcpu, "kpatch");
-+		kpatch_shadow_free(vcpu, "kpatch");
++		klp_shadow_get(vcpu, 0);
++		klp_shadow_free(vcpu, 0, NULL);
 +	}
 +
  	load_vmcs12_host_state(vcpu, vmcs12);
diff -pruN 0.6.0-0.2/test/integration/centos-7/multiple.test 0.8.0-0ubuntu7/test/integration/centos-7/multiple.test
--- 0.6.0-0.2/test/integration/centos-7/multiple.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -4,6 +4,10 @@ SCRIPTDIR="$(readlink -f $(dirname $(typ
 ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)"
 KPATCH="sudo $ROOTDIR/kpatch/kpatch"
 
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
 set -o errexit
 
 die() {
@@ -12,12 +16,27 @@ die() {
 }
 
 ko_to_test() {
-	tmp=${1%.ko}-LOADED.test
-	echo ${tmp#kpatch-}
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
 }
 
 # make sure any modules added here are disjoint
-declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko)
+declare -a modules
+declare -a blacklist=(data-new-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
 
 for mod in "${modules[@]}"; do
 	testprog=$(ko_to_test $mod)
@@ -33,7 +52,8 @@ for mod in "${modules[@]}"; do
 	$SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules"
 done
 
-for mod in "${modules[@]}"; do
+for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do
+	mod=${modules[idx]}
 	$KPATCH unload $mod
 done
 
diff -pruN 0.6.0-0.2/test/integration/centos-7/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/centos-7/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/centos-7/shadow-newpid.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/centos-7/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,11 +1,12 @@
-diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c
---- src.orig/fs/proc/array.c	2017-09-22 16:52:10.597110096 -0400
-+++ src/fs/proc/array.c	2017-09-22 16:59:40.799972178 -0400
-@@ -359,13 +359,20 @@ static inline void task_seccomp(struct s
- #endif
+Index: src/fs/proc/array.c
+===================================================================
+--- src.orig/fs/proc/array.c
++++ src/fs/proc/array.c
+@@ -394,13 +394,20 @@ static inline void task_seccomp(struct s
+ 	seq_putc(m, '\n');
  }
  
-+#include "kpatch.h"
++#include <linux/livepatch.h>
  static inline void task_context_switch_counts(struct seq_file *m,
  						struct task_struct *p)
  {
@@ -16,52 +17,54 @@ diff -Nupr src.orig/fs/proc/array.c src/
  			p->nvcsw,
  			p->nivcsw);
 +
-+	newpid = kpatch_shadow_get(p, "newpid");
++	newpid = klp_shadow_get(p, 0);
 +	if (newpid)
 +		seq_printf(m, "newpid:\t%d\n", *newpid);
  }
  
  static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
-diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c
---- src.orig/kernel/exit.c	2017-09-22 16:52:10.506109720 -0400
-+++ src/kernel/exit.c	2017-09-22 16:59:40.799972178 -0400
-@@ -715,6 +715,7 @@ static void check_stack_usage(void)
+Index: src/kernel/exit.c
+===================================================================
+--- src.orig/kernel/exit.c
++++ src/kernel/exit.c
+@@ -791,6 +791,7 @@ static void check_stack_usage(void)
  static inline void check_stack_usage(void) {}
  #endif
  
-+#include "kpatch.h"
++#include <linux/livepatch.h>
  void do_exit(long code)
  {
  	struct task_struct *tsk = current;
-@@ -812,6 +813,8 @@ void do_exit(long code)
+@@ -888,6 +889,8 @@ void do_exit(long code)
  	check_stack_usage();
  	exit_thread();
  
-+	kpatch_shadow_free(tsk, "newpid");
++	klp_shadow_free(tsk, 0, NULL);
 +
  	/*
  	 * Flush inherited counters to the parent - before the parent
  	 * gets woken up by child-exit notifications.
-diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
---- src.orig/kernel/fork.c	2017-09-22 16:52:10.504109711 -0400
-+++ src/kernel/fork.c	2017-09-22 17:00:44.938237460 -0400
-@@ -1700,6 +1700,7 @@ struct task_struct *fork_idle(int cpu)
+Index: src/kernel/fork.c
+===================================================================
+--- src.orig/kernel/fork.c
++++ src/kernel/fork.c
+@@ -1757,6 +1757,7 @@ struct task_struct *fork_idle(int cpu)
   * It copies the process, and if successful kick-starts
   * it and waits for it to finish using the VM if required.
   */
-+#include "kpatch.h"
++#include <linux/livepatch.h>
  long do_fork(unsigned long clone_flags,
  	      unsigned long stack_start,
  	      unsigned long stack_size,
-@@ -1737,6 +1738,13 @@ long do_fork(unsigned long clone_flags,
+@@ -1794,6 +1795,13 @@ long do_fork(unsigned long clone_flags,
  	if (!IS_ERR(p)) {
  		struct completion vfork;
  		struct pid *pid;
 +		int *newpid;
 +		static int ctr = 0;
 +
-+		newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
-+					     GFP_KERNEL);
++		newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid),
++					     GFP_KERNEL, NULL, NULL);
 +		if (newpid)
 +			*newpid = ctr++;
  
diff -pruN 0.6.0-0.2/test/integration/fedora-27/bug-table-section.patch 0.8.0-0ubuntu7/test/integration/fedora-27/bug-table-section.patch
--- 0.6.0-0.2/test/integration/fedora-27/bug-table-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/bug-table-section.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
---- src.orig/fs/proc/proc_sysctl.c	2017-11-17 15:58:41.115211972 -0500
-+++ src/fs/proc/proc_sysctl.c	2017-11-17 15:58:51.725211972 -0500
-@@ -332,6 +332,8 @@ static void start_unregistering(struct c
- 
- static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
- {
-+	if (jiffies == 0)
-+		printk("kpatch-test: testing __bug_table section changes\n");
- 	BUG_ON(!head);
- 	spin_lock(&sysctl_lock);
- 	if (!use_table(head))
diff -pruN 0.6.0-0.2/test/integration/fedora-27/cmdline-string-LOADED.test 0.8.0-0ubuntu7/test/integration/fedora-27/cmdline-string-LOADED.test
--- 0.6.0-0.2/test/integration/fedora-27/cmdline-string-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/cmdline-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/fedora-27/cmdline-string.patch 0.8.0-0ubuntu7/test/integration/fedora-27/cmdline-string.patch
--- 0.6.0-0.2/test/integration/fedora-27/cmdline-string.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/cmdline-string.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
---- src.orig/fs/proc/cmdline.c	2017-11-17 15:58:41.126211972 -0500
-+++ src/fs/proc/cmdline.c	2017-11-17 15:58:54.891211972 -0500
-@@ -5,7 +5,7 @@
- 
- static int cmdline_proc_show(struct seq_file *m, void *v)
- {
--	seq_printf(m, "%s\n", saved_command_line);
-+	seq_printf(m, "%s kpatch=1\n", saved_command_line);
- 	return 0;
- }
- 
diff -pruN 0.6.0-0.2/test/integration/fedora-27/convert-global-local.patch 0.8.0-0ubuntu7/test/integration/fedora-27/convert-global-local.patch
--- 0.6.0-0.2/test/integration/fedora-27/convert-global-local.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/convert-global-local.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-This is a test for #658: a kernel panic seen when patching an exported
-function (e.g., kmalloc) which is used by patch_init().
----
-diff -Nupr src.orig/mm/slub.c src/mm/slub.c
---- src.orig/mm/slub.c	2017-11-17 15:58:51.157211972 -0500
-+++ src/mm/slub.c	2017-11-17 15:58:56.808211972 -0500
-@@ -3731,6 +3731,9 @@ void *__kmalloc(size_t size, gfp_t flags
- 	struct kmem_cache *s;
- 	void *ret;
- 
-+	if (!jiffies)
-+		printk("kpatch kmalloc\n");
-+
- 	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
- 		return kmalloc_large(size, flags);
- 
diff -pruN 0.6.0-0.2/test/integration/fedora-27/data-read-mostly.patch 0.8.0-0ubuntu7/test/integration/fedora-27/data-read-mostly.patch
--- 0.6.0-0.2/test/integration/fedora-27/data-read-mostly.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/data-read-mostly.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c
---- src.orig/net/core/dev.c	2017-11-17 15:58:50.569211972 -0500
-+++ src/net/core/dev.c	2017-11-17 15:59:00.286211972 -0500
-@@ -4260,6 +4260,7 @@ skip_classify:
- 		case RX_HANDLER_PASS:
- 			break;
- 		default:
-+			printk("BUG!\n");
- 			BUG();
- 		}
- 	}
diff -pruN 0.6.0-0.2/test/integration/fedora-27/fixup-section.patch 0.8.0-0ubuntu7/test/integration/fedora-27/fixup-section.patch
--- 0.6.0-0.2/test/integration/fedora-27/fixup-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/fixup-section.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c
---- src.orig/fs/readdir.c	2017-11-17 15:58:39.457211972 -0500
-+++ src/fs/readdir.c	2017-11-17 15:59:02.078211972 -0500
-@@ -189,6 +189,8 @@ static int filldir(struct dir_context *c
- 			goto efault;
- 	}
- 	dirent = buf->current_dir;
-+	if (dirent->d_ino == 12345678)
-+		printk("kpatch-test: testing .fixup section changes\n");
- 	if (__put_user(d_ino, &dirent->d_ino))
- 		goto efault;
- 	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-constprop.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-constprop.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-constprop.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-constprop.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-ensure timekeeping_forward_now.constprop.8 and
-timekeeping_forward_now.constprop.9 are correlated.
-
-diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c
---- src.orig/kernel/time/timekeeping.c	2017-11-17 15:58:51.500211972 -0500
-+++ src/kernel/time/timekeeping.c	2017-11-17 15:59:03.810211972 -0500
-@@ -1206,6 +1206,9 @@ void do_gettimeofday(struct timeval *tv)
- {
- 	struct timespec64 now;
- 
-+	if (!tv)
-+		return;
-+
- 	getnstimeofday64(&now);
- 	tv->tv_sec = now.tv_sec;
- 	tv->tv_usec = now.tv_nsec/1000;
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-isra.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-isra.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-isra.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-isra.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
---- src.orig/fs/proc/proc_sysctl.c	2017-11-17 15:58:41.115211972 -0500
-+++ src/fs/proc/proc_sysctl.c	2017-11-17 15:59:05.548211972 -0500
-@@ -47,6 +47,7 @@ void proc_sys_poll_notify(struct ctl_tab
- 	if (!poll)
- 		return;
- 
-+	printk("kpatch-test: testing gcc .isra function name mangling\n");
- 	atomic_inc(&poll->event);
- 	wake_up_interruptible(&poll->wait);
- }
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-mangled-3.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-ensure that __cmpxchg_double_slab.isra.45 and
-__cmpxchg_double_slab.isra.45.part.46 aren't correlated.
-
-diff -Nupr src.orig/mm/slub.c src/mm/slub.c
---- src.orig/mm/slub.c	2017-11-17 15:58:51.157211972 -0500
-+++ src/mm/slub.c	2017-11-17 15:59:07.361211972 -0500
-@@ -5824,6 +5824,9 @@ void get_slabinfo(struct kmem_cache *s,
- 	int node;
- 	struct kmem_cache_node *n;
- 
-+	if (!jiffies)
-+		printk("slabinfo\n");
-+
- 	for_each_kmem_cache_node(s, node, n) {
- 		nr_slabs += node_nr_slabs(n);
- 		nr_objs += node_nr_objs(n);
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-2.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-2.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-2.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-2.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,13 +0,0 @@
-diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c
---- src.orig/mm/mmap.c	2017-11-17 15:58:51.131211972 -0500
-+++ src/mm/mmap.c	2017-11-17 15:59:09.094211972 -0500
-@@ -1609,6 +1610,9 @@ unsigned long mmap_region(struct file *f
- 	struct rb_node **rb_link, *rb_parent;
- 	unsigned long charged = 0;
- 
-+	if (!jiffies)
-+		printk("kpatch mmap foo\n");
-+
- 	/* Check against address space limit. */
- 	if (!may_expand_vm(mm, vm_flags, len >> PAGE_SHIFT)) {
- 		unsigned long nr_pages;
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-3.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-3.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-3.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-3.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,19 +0,0 @@
-diff -Nupr src.orig/kernel/reboot.c src/kernel/reboot.c
---- src.orig/kernel/reboot.c	2017-11-17 15:58:51.558211972 -0500
-+++ src/kernel/reboot.c	2017-11-17 15:59:10.774211972 -0500
-@@ -366,8 +366,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
- 	return ret;
- }
- 
-+void kpatch_bar(void)
-+{
-+	if (!jiffies)
-+		printk("kpatch_foo\n");
-+}
-+
- static void deferred_cad(struct work_struct *dummy)
- {
-+	kpatch_bar();
- 	kernel_restart(NULL);
- }
- 
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-4.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-4.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-4.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-4.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,21 +0,0 @@
-diff -Nupr src.orig/fs/aio.c src/fs/aio.c
---- src.orig/fs/aio.c	2017-11-17 15:58:38.111211972 -0500
-+++ src/fs/aio.c	2017-11-17 15:59:12.467211972 -0500
-@@ -271,10 +271,17 @@ static int __init aio_setup(void)
- }
- __initcall(aio_setup);
- 
-+void kpatch_aio_foo(void)
-+{
-+	if (!jiffies)
-+		printk("kpatch aio foo\n");
-+}
-+
- static void put_aio_ring_file(struct kioctx *ctx)
- {
- 	struct file *aio_ring_file = ctx->aio_ring_file;
- 	struct address_space *i_mapping;
-+	kpatch_aio_foo();
- 
- 	if (aio_ring_file) {
- 		truncate_setsize(file_inode(aio_ring_file), 0);
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-4.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then
-	exit 1
-else
-	exit 0
-fi
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-5.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-5.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var-5.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var-5.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,45 +0,0 @@
-diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c
---- src.orig/kernel/audit.c	2017-11-17 15:58:51.516211972 -0500
-+++ src/kernel/audit.c	2017-11-17 15:59:14.324211972 -0500
-@@ -282,6 +282,12 @@ void audit_panic(const char *message)
- 	}
- }
- 
-+void kpatch_audit_foo(void)
-+{
-+	if (!jiffies)
-+		printk("kpatch audit foo\n");
-+}
-+
- static inline int audit_rate_check(void)
- {
- 	static unsigned long	last_check = 0;
-@@ -292,6 +298,7 @@ static inline int audit_rate_check(void)
- 	unsigned long		elapsed;
- 	int			retval	   = 0;
- 
-+	kpatch_audit_foo();
- 	if (!audit_rate_limit) return 1;
- 
- 	spin_lock_irqsave(&lock, flags);
-@@ -311,6 +318,11 @@ static inline int audit_rate_check(void)
- 	return retval;
- }
- 
-+noinline void kpatch_audit_check(void)
-+{
-+	audit_rate_check();
-+}
-+
- /**
-  * audit_log_lost - conditionally log lost audit message event
-  * @message: the message stating reason for lost audit message
-@@ -357,6 +369,8 @@ static int audit_log_config_change(char
- 	struct audit_buffer *ab;
- 	int rc = 0;
- 
-+	kpatch_audit_check();
-+
- 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- 	if (unlikely(!ab))
- 		return rc;
diff -pruN 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var.patch 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var.patch
--- 0.6.0-0.2/test/integration/fedora-27/gcc-static-local-var.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/gcc-static-local-var.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c
---- src.orig/arch/x86/kernel/ldt.c	2017-11-17 15:58:09.662211972 -0500
-+++ src/arch/x86/kernel/ldt.c	2017-11-17 15:59:16.084211972 -0500
-@@ -100,6 +100,12 @@ static void free_ldt_struct(struct ldt_s
- 	kfree(ldt);
- }
- 
-+void hi_there(void)
-+{
-+	if (!jiffies)
-+		printk("hi there\n");
-+}
-+
- /*
-  * we do not have to muck with descriptors here, that is
-  * done in switch_mm() as needed.
-@@ -110,6 +116,8 @@ int init_new_context_ldt(struct task_str
- 	struct mm_struct *old_mm;
- 	int retval = 0;
- 
-+	hi_there();
-+
- 	mutex_init(&mm->context.lock);
- 	old_mm = current->mm;
- 	if (!old_mm) {
diff -pruN 0.6.0-0.2/test/integration/fedora-27/macro-printk.patch 0.8.0-0ubuntu7/test/integration/fedora-27/macro-printk.patch
--- 0.6.0-0.2/test/integration/fedora-27/macro-printk.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/macro-printk.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,147 +0,0 @@
-diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c
---- src.orig/net/ipv4/fib_frontend.c	2017-11-17 16:16:54.789211972 -0500
-+++ src/net/ipv4/fib_frontend.c	2017-11-17 16:19:58.429211972 -0500
-@@ -740,6 +740,7 @@ errout:
- 	return err;
- }
- 
-+#include "kpatch-macros.h"
- static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
- 			     struct netlink_ext_ack *extack)
- {
-@@ -759,6 +760,7 @@ static int inet_rtm_newroute(struct sk_b
- 	}
- 
- 	err = fib_table_insert(net, tb, &cfg, extack);
-+	KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err);
- errout:
- 	return err;
- }
-diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c
---- src.orig/net/ipv4/fib_semantics.c	2017-11-17 16:16:54.789211972 -0500
-+++ src/net/ipv4/fib_semantics.c	2017-11-17 16:21:11.653211972 -0500
-@@ -1026,6 +1026,7 @@ fib_convert_metrics(struct fib_info *fi,
- 	return 0;
- }
- 
-+#include "kpatch-macros.h"
- struct fib_info *fib_create_info(struct fib_config *cfg,
- 				 struct netlink_ext_ack *extack)
- {
-@@ -1059,6 +1060,7 @@ struct fib_info *fib_create_info(struct
- #endif
- 
- 	err = -ENOBUFS;
-+	KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err);
- 	if (fib_info_cnt >= fib_info_hash_size) {
- 		unsigned int new_size = fib_info_hash_size << 1;
- 		struct hlist_head *new_info_hash;
-@@ -1079,6 +1081,7 @@ struct fib_info *fib_create_info(struct
- 		if (!fib_info_hash_size)
- 			goto failure;
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err);
- 
- 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
- 	if (!fi)
-@@ -1093,6 +1096,8 @@ struct fib_info *fib_create_info(struct
- 	} else {
- 		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
-+
- 	fib_info_cnt++;
- 	fi->fib_net = net;
- 	fi->fib_protocol = cfg->fc_protocol;
-@@ -1110,6 +1115,7 @@ struct fib_info *fib_create_info(struct
- 		if (!nexthop_nh->nh_pcpu_rth_output)
- 			goto failure;
- 	} endfor_nexthops(fi)
-+	KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err);
- 
- 	err = fib_convert_metrics(fi, cfg);
- 	if (err)
-@@ -1174,6 +1180,9 @@ struct fib_info *fib_create_info(struct
- #endif
- 	}
- 
-+	KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err);
-+	KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err);
-+
- 	if (fib_props[cfg->fc_type].error) {
- 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) {
- 			NL_SET_ERR_MSG(extack,
-@@ -1194,6 +1203,7 @@ struct fib_info *fib_create_info(struct
- 			goto err_inval;
- 		}
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err);
- 
- 	if (cfg->fc_scope > RT_SCOPE_HOST) {
- 		NL_SET_ERR_MSG(extack, "Invalid scope");
-@@ -1232,6 +1242,7 @@ struct fib_info *fib_create_info(struct
- 		if (linkdown == fi->fib_nhs)
- 			fi->fib_flags |= RTNH_F_LINKDOWN;
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err);
- 
- 	if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc)) {
- 		NL_SET_ERR_MSG(extack, "Invalid prefsrc address");
-@@ -1242,6 +1253,7 @@ struct fib_info *fib_create_info(struct
- 		fib_info_update_nh_saddr(net, nexthop_nh);
- 		fib_add_weight(fi, nexthop_nh);
- 	} endfor_nexthops(fi)
-+	KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err);
- 
- 	fib_rebalance(fi);
- 
-@@ -1253,6 +1265,7 @@ link_it:
- 		ofi->fib_treeref++;
- 		return ofi;
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err);
- 
- 	fi->fib_treeref++;
- 	refcount_set(&fi->fib_clntref, 1);
-@@ -1276,6 +1289,7 @@ link_it:
- 		hlist_add_head(&nexthop_nh->nh_hash, head);
- 	} endfor_nexthops(fi)
- 	spin_unlock_bh(&fib_info_lock);
-+	KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err);
- 	return fi;
- 
- err_inval:
-@@ -1286,6 +1300,7 @@ failure:
- 		fi->fib_dead = 1;
- 		free_fib_info(fi);
- 	}
-+	KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err);
- 
- 	return ERR_PTR(err);
- }
-diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c
---- src.orig/net/ipv4/fib_trie.c	2017-11-17 16:16:54.789211972 -0500
-+++ src/net/ipv4/fib_trie.c	2017-11-17 16:22:11.702211972 -0500
-@@ -1116,6 +1116,7 @@ static bool fib_valid_key_len(u32 key, u
- }
- 
- /* Caller must hold RTNL. */
-+#include "kpatch-macros.h"
- int fib_table_insert(struct net *net, struct fib_table *tb,
- 		     struct fib_config *cfg, struct netlink_ext_ack *extack)
- {
-@@ -1138,11 +1139,14 @@ int fib_table_insert(struct net *net, st
- 
- 	pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
- 
-+	KPATCH_PRINTK("[fib_table_insert]: start\n");
- 	fi = fib_create_info(cfg, extack);
- 	if (IS_ERR(fi)) {
- 		err = PTR_ERR(fi);
-+		KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err);
- 		goto err;
- 	}
-+	KPATCH_PRINTK("[fib_table_insert]: cross\n");
- 
- 	l = fib_find_node(t, &tp, key);
- 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
---- src.orig/fs/proc/cmdline.c	2017-11-17 15:58:41.126211972 -0500
-+++ src/fs/proc/cmdline.c	2017-11-17 15:59:19.323211972 -0500
-@@ -5,7 +5,7 @@
- 
- static int cmdline_proc_show(struct seq_file *m, void *v)
- {
--	seq_printf(m, "%s\n", saved_command_line);
-+	seq_printf(m, "%s kpatch=1\n", saved_command_line);
- 	return 0;
- }
- 
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2017-11-17 15:58:41.113211972 -0500
-+++ src/fs/proc/meminfo.c	2017-11-17 15:59:19.323211972 -0500
-@@ -132,7 +132,7 @@ static int meminfo_proc_show(struct seq_
- 	seq_printf(m, "VmallocTotal:   %8lu kB\n",
- 		   (unsigned long)VMALLOC_TOTAL >> 10);
- 	show_val_kb(m, "VmallocUsed:    ", 0ul);
--	show_val_kb(m, "VmallocChunk:   ", 0ul);
-+	show_val_kb(m, "VMALLOCCHUNK:   ", 0ul);
- 
- #ifdef CONFIG_MEMORY_FAILURE
- 	seq_printf(m, "HardwareCorrupted: %5lu kB\n",
-diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h
---- src.orig/include/linux/kernel.h	2017-11-17 15:58:48.205211972 -0500
-+++ src/include/linux/kernel.h	2017-11-17 15:59:19.376211972 -0500
-@@ -2,6 +2,7 @@
- #define _LINUX_KERNEL_H
- 
- 
-+
- #include <stdarg.h>
- #include <linux/linkage.h>
- #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,40 @@
+Disabled due to https://github.com/dynup/kpatch/issues/767
+---
+Index: src/fs/proc/cmdline.c
+===================================================================
+--- src.orig/fs/proc/cmdline.c
++++ src/fs/proc/cmdline.c
+@@ -7,7 +7,7 @@
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+ 	seq_puts(m, saved_command_line);
+-	seq_putc(m, '\n');
++	seq_puts(m, " kpatch=1\n");
+ 	return 0;
+ }
+ 
+Index: src/fs/proc/meminfo.c
+===================================================================
+--- src.orig/fs/proc/meminfo.c
++++ src/fs/proc/meminfo.c
+@@ -120,7 +120,7 @@ static int meminfo_proc_show(struct seq_
+ 	seq_printf(m, "VmallocTotal:   %8lu kB\n",
+ 		   (unsigned long)VMALLOC_TOTAL >> 10);
+ 	show_val_kb(m, "VmallocUsed:    ", 0ul);
+-	show_val_kb(m, "VmallocChunk:   ", 0ul);
++	show_val_kb(m, "VMALLOCCHUNK:   ", 0ul);
+ 
+ #ifdef CONFIG_MEMORY_FAILURE
+ 	seq_printf(m, "HardwareCorrupted: %5lu kB\n",
+Index: src/include/linux/kernel.h
+===================================================================
+--- src.orig/include/linux/kernel.h
++++ src/include/linux/kernel.h
+@@ -3,6 +3,7 @@
+ #define _LINUX_KERNEL_H
+ 
+ 
++
+ #include <stdarg.h>
+ #include <linux/linkage.h>
+ #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-init2-FAIL.patch 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-init2-FAIL.patch
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-init2-FAIL.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-init2-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,20 +0,0 @@
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2017-11-17 15:58:41.113211972 -0500
-+++ src/fs/proc/meminfo.c	2017-11-17 15:59:21.276211972 -0500
-@@ -51,6 +51,8 @@ static int meminfo_proc_show(struct seq_
- 	unsigned long pages[NR_LRU_LISTS];
- 	int lru;
- 
-+	printk("a\n");
-+
- 	si_meminfo(&i);
- 	si_swapinfo(&i);
- 	committed = percpu_counter_read_positive(&vm_committed_as);
-@@ -175,6 +177,7 @@ static const struct file_operations memi
- 
- static int __init proc_meminfo_init(void)
- {
-+	printk("a\n");
- 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
- 	return 0;
- }
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-init-FAIL.patch 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-init-FAIL.patch
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-init-FAIL.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-init-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2017-11-17 15:58:41.113211972 -0500
-+++ src/fs/proc/meminfo.c	2017-11-17 15:59:23.081211972 -0500
-@@ -175,6 +175,7 @@ static const struct file_operations memi
- 
- static int __init proc_meminfo_init(void)
- {
-+	printk("a\n");
- 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
- 	return 0;
- }
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-string-LOADED.test 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-string-LOADED.test
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-string-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep VMALLOCCHUNK /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/fedora-27/meminfo-string.patch 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-string.patch
--- 0.6.0-0.2/test/integration/fedora-27/meminfo-string.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/meminfo-string.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2017-11-17 15:59:24.724211972 -0500
-+++ src/fs/proc/meminfo.c	2017-11-17 15:59:24.721211972 -0500
-@@ -132,7 +132,7 @@ static int meminfo_proc_show(struct seq_
- 	seq_printf(m, "VmallocTotal:   %8lu kB\n",
- 		   (unsigned long)VMALLOC_TOTAL >> 10);
- 	show_val_kb(m, "VmallocUsed:    ", 0ul);
--	show_val_kb(m, "VmallocChunk:   ", 0ul);
-+	show_val_kb(m, "VMALLOCCHUNK:   ", 0ul);
- 
- #ifdef CONFIG_MEMORY_FAILURE
- 	seq_printf(m, "HardwareCorrupted: %5lu kB\n",
diff -pruN 0.6.0-0.2/test/integration/fedora-27/module-kvm-fixup.patch 0.8.0-0ubuntu7/test/integration/fedora-27/module-kvm-fixup.patch
--- 0.6.0-0.2/test/integration/fedora-27/module-kvm-fixup.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/module-kvm-fixup.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
---- src.orig/arch/x86/kvm/vmx.c	2017-11-17 15:58:19.369211972 -0500
-+++ src/arch/x86/kvm/vmx.c	2017-11-17 15:59:27.980211972 -0500
-@@ -11275,6 +11275,8 @@ static int vmx_check_intercept(struct kv
- 			       struct x86_instruction_info *info,
- 			       enum x86_intercept_stage stage)
- {
-+	if (!jiffies)
-+		printk("kpatch vmx_check_intercept\n");
- 	return X86EMUL_CONTINUE;
- }
- 
diff -pruN 0.6.0-0.2/test/integration/fedora-27/multiple.test 0.8.0-0ubuntu7/test/integration/fedora-27/multiple.test
--- 0.6.0-0.2/test/integration/fedora-27/multiple.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -4,6 +4,10 @@ SCRIPTDIR="$(readlink -f $(dirname $(typ
 ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)"
 KPATCH="sudo $ROOTDIR/kpatch/kpatch"
 
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
 set -o errexit
 
 die() {
@@ -12,12 +16,27 @@ die() {
 }
 
 ko_to_test() {
-	tmp=${1%.ko}-LOADED.test
-	echo ${tmp#kpatch-}
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
 }
 
 # make sure any modules added here are disjoint
-declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko)
+declare -a modules
+declare -a blacklist=(meminfo-cmdline-rebuild-SLOW-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
 
 for mod in "${modules[@]}"; do
 	testprog=$(ko_to_test $mod)
diff -pruN 0.6.0-0.2/test/integration/fedora-27/parainstructions-section.patch 0.8.0-0ubuntu7/test/integration/fedora-27/parainstructions-section.patch
--- 0.6.0-0.2/test/integration/fedora-27/parainstructions-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/parainstructions-section.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c
---- src.orig/fs/proc/generic.c	2017-11-17 16:08:17.202211972 -0500
-+++ src/fs/proc/generic.c	2017-11-17 16:08:46.585211972 -0500
-@@ -191,6 +191,7 @@ int proc_alloc_inum(unsigned int *inum)
- {
- 	int i;
- 
-+	printk("kpatch-test: testing change to .parainstructions section\n");
- 	i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
- 			   GFP_KERNEL);
- 	if (i < 0)
diff -pruN 0.6.0-0.2/test/integration/fedora-27/replace-section-references.patch 0.8.0-0ubuntu7/test/integration/fedora-27/replace-section-references.patch
--- 0.6.0-0.2/test/integration/fedora-27/replace-section-references.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/replace-section-references.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
---- src.orig/arch/x86/kvm/x86.c	2017-11-17 15:58:19.002211972 -0500
-+++ src/arch/x86/kvm/x86.c	2017-11-17 15:59:34.499211972 -0500
-@@ -252,6 +252,8 @@ static void shared_msr_update(unsigned s
- 
- void kvm_define_shared_msr(unsigned slot, u32 msr)
- {
-+	if (!jiffies)
-+		printk("kpatch kvm define shared msr\n");
- 	BUG_ON(slot >= KVM_NR_SHARED_MSRS);
- 	shared_msrs_global.msrs[slot] = msr;
- 	if (slot >= shared_msrs_global.nr)
diff -pruN 0.6.0-0.2/test/integration/fedora-27/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/fedora-27/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/fedora-27/shadow-newpid.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,7 +1,8 @@
-diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c
---- src.orig/fs/proc/array.c	2017-11-17 15:58:41.136211972 -0500
-+++ src/fs/proc/array.c	2017-11-17 15:59:36.184211972 -0500
-@@ -354,12 +354,19 @@ static inline void task_seccomp(struct s
+Index: src/fs/proc/array.c
+===================================================================
+--- src.orig/fs/proc/array.c
++++ src/fs/proc/array.c
+@@ -363,12 +363,19 @@ static inline void task_seccomp(struct s
  	seq_putc(m, '\n');
  }
  
@@ -21,9 +22,10 @@ diff -Nupr src.orig/fs/proc/array.c src/
  }
  
  static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
-diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c
---- src.orig/kernel/exit.c	2017-11-17 15:58:51.659211972 -0500
-+++ src/kernel/exit.c	2017-11-17 15:59:36.184211972 -0500
+Index: src/kernel/exit.c
+===================================================================
+--- src.orig/kernel/exit.c
++++ src/kernel/exit.c
 @@ -760,6 +760,7 @@ static void check_stack_usage(void)
  static inline void check_stack_usage(void) {}
  #endif
@@ -41,10 +43,11 @@ diff -Nupr src.orig/kernel/exit.c src/ke
  	/*
  	 * Flush inherited counters to the parent - before the parent
  	 * gets woken up by child-exit notifications.
-diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
---- src.orig/kernel/fork.c	2017-11-17 15:58:51.541211972 -0500
-+++ src/kernel/fork.c	2017-11-17 15:59:36.184211972 -0500
-@@ -2003,6 +2003,7 @@ struct task_struct *fork_idle(int cpu)
+Index: src/kernel/fork.c
+===================================================================
+--- src.orig/kernel/fork.c
++++ src/kernel/fork.c
+@@ -2062,6 +2062,7 @@ struct task_struct *fork_idle(int cpu)
   * It copies the process, and if successful kick-starts
   * it and waits for it to finish using the VM if required.
   */
@@ -52,17 +55,24 @@ diff -Nupr src.orig/kernel/fork.c src/ke
  long _do_fork(unsigned long clone_flags,
  	      unsigned long stack_start,
  	      unsigned long stack_size,
-@@ -2042,6 +2043,13 @@ long _do_fork(unsigned long clone_flags,
- 	if (!IS_ERR(p)) {
- 		struct completion vfork;
- 		struct pid *pid;
-+		int *newpid;
-+		static int ctr = 0;
-+
-+		newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
-+					     GFP_KERNEL);
-+		if (newpid)
-+			*newpid = ctr++;
+@@ -2074,6 +2075,8 @@ long _do_fork(unsigned long clone_flags,
+ 	struct task_struct *p;
+ 	int trace = 0;
+ 	long nr;
++	int *newpid;
++	static int ctr = 0;
  
- 		trace_sched_process_fork(current, p);
+ 	/*
+ 	 * Determine whether and which event to report to ptracer.  When
+@@ -2100,6 +2103,11 @@ long _do_fork(unsigned long clone_flags,
+ 	if (IS_ERR(p))
+ 		return PTR_ERR(p);
  
++	newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
++				     GFP_KERNEL);
++	if (newpid)
++		*newpid = ctr++;
++
+ 	/*
+ 	 * Do this prior waking up the new thread - the thread pointer
+ 	 * might get invalid after that point, if the thread exits quickly.
diff -pruN 0.6.0-0.2/test/integration/fedora-27/smp-locks-section.patch 0.8.0-0ubuntu7/test/integration/fedora-27/smp-locks-section.patch
--- 0.6.0-0.2/test/integration/fedora-27/smp-locks-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/smp-locks-section.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c
---- src.orig/drivers/tty/tty_buffer.c	2017-11-17 15:58:00.518211972 -0500
-+++ src/drivers/tty/tty_buffer.c	2017-11-17 15:59:37.806211972 -0500
-@@ -255,6 +255,8 @@ static int __tty_buffer_request_room(str
- 	struct tty_buffer *b, *n;
- 	int left, change;
- 
-+	if (!size)
-+		printk("kpatch-test: testing .smp_locks section changes\n");
- 	b = buf->tail;
- 	if (b->flags & TTYB_NORMAL)
- 		left = 2 * b->size - b->used;
diff -pruN 0.6.0-0.2/test/integration/fedora-27/special-static-2.patch 0.8.0-0ubuntu7/test/integration/fedora-27/special-static-2.patch
--- 0.6.0-0.2/test/integration/fedora-27/special-static-2.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/special-static-2.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,24 +0,0 @@
-diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
---- src.orig/arch/x86/kvm/x86.c	2017-11-17 15:58:19.002211972 -0500
-+++ src/arch/x86/kvm/x86.c	2017-11-17 15:59:39.427211972 -0500
-@@ -2126,12 +2126,20 @@ static void record_steal_time(struct kvm
- 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
- }
- 
-+void kpatch_kvm_x86_foo(void)
-+{
-+	if (!jiffies)
-+		printk("kpatch kvm x86 foo\n");
-+}
-+
- int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
- {
- 	bool pr = false;
- 	u32 msr = msr_info->index;
- 	u64 data = msr_info->data;
- 
-+	kpatch_kvm_x86_foo();
-+
- 	switch (msr) {
- 	case MSR_AMD64_NB_CFG:
- 	case MSR_IA32_UCODE_REV:
diff -pruN 0.6.0-0.2/test/integration/fedora-27/special-static.patch 0.8.0-0ubuntu7/test/integration/fedora-27/special-static.patch
--- 0.6.0-0.2/test/integration/fedora-27/special-static.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/special-static.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,22 +0,0 @@
-diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
---- src.orig/kernel/fork.c	2017-11-17 15:58:51.541211972 -0500
-+++ src/kernel/fork.c	2017-11-17 15:59:41.041211972 -0500
-@@ -1374,10 +1374,18 @@ static void posix_cpu_timers_init_group(
- static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
- #endif
- 
-+void kpatch_foo(void)
-+{
-+	if (!jiffies)
-+		printk("kpatch copy signal\n");
-+}
-+
- static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
- {
- 	struct signal_struct *sig;
- 
-+	kpatch_foo();
-+
- 	if (clone_flags & CLONE_THREAD)
- 		return 0;
- 
diff -pruN 0.6.0-0.2/test/integration/fedora-27/tracepoints-section.patch 0.8.0-0ubuntu7/test/integration/fedora-27/tracepoints-section.patch
--- 0.6.0-0.2/test/integration/fedora-27/tracepoints-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/tracepoints-section.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,15 +0,0 @@
-ensure __jump_table is parsed and we can tell that it effectively didn't change
-
-diff -Nupr src.orig/kernel/time/timer.c src/kernel/time/timer.c
---- src.orig/kernel/time/timer.c	2017-11-17 15:58:51.501211972 -0500
-+++ src/kernel/time/timer.c	2017-11-17 15:59:42.654211972 -0500
-@@ -1643,6 +1643,9 @@ static __latent_entropy void run_timer_s
- 	 */
- 	base->must_forward_clk = false;
- 
-+	if (!base)
-+		printk("kpatch-test: testing __tracepoints section changes\n");
-+
- 	__run_timers(base);
- 	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active)
- 		__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
diff -pruN 0.6.0-0.2/test/integration/fedora-27/warn-detect-FAIL.patch 0.8.0-0ubuntu7/test/integration/fedora-27/warn-detect-FAIL.patch
--- 0.6.0-0.2/test/integration/fedora-27/warn-detect-FAIL.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/fedora-27/warn-detect-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,8 +1,9 @@
-diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
---- src.orig/arch/x86/kvm/x86.c	2017-11-17 15:58:19.002211972 -0500
-+++ src/arch/x86/kvm/x86.c	2017-11-17 15:59:44.327211972 -0500
+diff --git a/net/core/dev.c b/net/core/dev.c
+index ef0cc6ea5f8d..9a840ec54270 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
 @@ -1,3 +1,4 @@
 +
  /*
-  * Kernel-based Virtual Machine driver for Linux
+  *      NET3    Protocol independent device support routines.
   *
diff -pruN 0.6.0-0.2/test/integration/kpatch-test 0.8.0-0ubuntu7/test/integration/kpatch-test
--- 0.6.0-0.2/test/integration/kpatch-test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/kpatch-test	2019-08-28 17:34:00.000000000 +0000
@@ -28,8 +28,6 @@
 #
 # - foo.patch: patch that should build successfully
 #
-# - foo-SLOW.patch: patch that should be skipped in the quick test
-#
 # - bar-FAIL.patch: patch that should fail to build
 #
 # - foo-LOADED.test: executable which tests whether the foo.patch module is
@@ -51,7 +49,7 @@ unset CCACHE_HASHDIR
 KPATCHBUILD="$ROOTDIR"/kpatch-build/kpatch-build
 ERROR=0
 LOG=test.log
-rm -f $LOG
+rm -f *.log
 
 PATCHDIR="${PATCHDIR:-$PWD}"
 declare -a PATCH_LIST
@@ -63,7 +61,7 @@ usage() {
 	echo "		-h, --help	Show this help message" >&2
 	echo "		-c, --cached	Don't rebuild patch modules" >&2
 	echo "		-d, --directory	Patch directory" >&2
-	echo "		-q, --quick	Just combine all patches into one module for testing" >&2
+	echo "		-q, --quick	Test combined patch and -FAIL patches only" >&2
 }
 
 options=$(getopt -o hcd:q -l "help,cached,directory,quick" -- "$@") || exit 1
@@ -106,7 +104,6 @@ else
 		prefix=${file%%.patch}
 		[[ -e "$prefix-FAIL.test" ]]   && TEST_LIST+=("$prefix-FAIL.test")
 		[[ -e "$prefix-LOADED.test" ]] && TEST_LIST+=("$prefix-LOADED.test")
-		[[ -e "$prefix-SLOW.test" ]]   && TEST_LIST+=("$prefix-SLOW.test")
 	done
 fi
 
@@ -133,7 +130,8 @@ unload_all() {
 build_module() {
 	file=$1
 	prefix=$(basename ${file%%.patch})
-	module=kpatch-$prefix.ko
+	modname="test-$prefix"
+	module="${modname}.ko"
 
 	if [[ $prefix =~ -FAIL ]]; then
 		shouldfail=1
@@ -150,8 +148,11 @@ build_module() {
 
 	log "build: $prefix"
 
-	if ! $KPATCHBUILD $file >> $LOG 2>&1; then
-		[[ $shouldfail -eq 0 ]] && error "$prefix: build failed"
+	if ! $KPATCHBUILD -n $modname $file >> $LOG 2>&1; then
+		if [[ $shouldfail -eq 0 ]]; then
+			error "$prefix: build failed"
+			cp $HOME/.kpatch/build.log $prefix.log
+		fi
 	else
 		[[ $shouldfail -eq 1 ]] && error "$prefix: build succeeded when it should have failed"
 	fi
@@ -160,7 +161,8 @@ build_module() {
 run_load_test() {
 	file=$1
 	prefix=$(basename ${file%%.patch})
-	module=kpatch-$prefix.ko
+	modname="test-$prefix"
+	module="${modname}.ko"
 	testprog="$(dirname $1)/$prefix-LOADED.test"
 
 	[[ $prefix =~ -FAIL ]] && return
@@ -204,7 +206,7 @@ run_load_test() {
 
 run_custom_test() {
 	testprog=$1
-	prefix=$(basename ${file%%.test})
+	prefix=$(basename ${testprog%%.test})
 
 	[[ $testprog = *-LOADED.test ]] && return
 
@@ -217,7 +219,7 @@ run_custom_test() {
 
 build_combined_module() {
 
-	if [[ $SKIPBUILD -eq 1 ]] && [[ -e kpatch-COMBINED.ko ]]; then
+	if [[ $SKIPBUILD -eq 1 ]] && [[ -e test-COMBINED.ko ]]; then
 		log "skipping build: combined"
 		return
 	fi
@@ -225,7 +227,6 @@ build_combined_module() {
 	declare -a COMBINED_LIST
 	for file in "${PATCH_LIST[@]}"; do
 		[[ $file =~ -FAIL ]] && log "combine: skipping $file" && continue
-		[[ $file =~ -SLOW ]] && log "combine: skipping $file" && continue
 		COMBINED_LIST+=($file)
 	done
 	if [[ ${#COMBINED_LIST[@]} -le 1 ]]; then
@@ -235,14 +236,15 @@ build_combined_module() {
 
 	log "build: combined module"
 
-	if ! $KPATCHBUILD -n kpatch-COMBINED "${COMBINED_LIST[@]}" >> $LOG 2>&1; then
+	if ! $KPATCHBUILD -n test-COMBINED "${COMBINED_LIST[@]}" >> $LOG 2>&1; then
 		error "combined build failed"
+		cp $HOME/.kpatch/build.log combined.log
 	fi
 }
 
 run_combined_test() {
-	if [[ ! -e kpatch-COMBINED.ko ]]; then
-		log "can't find kpatch-COMBINED.ko, skipping"
+	if [[ ! -e test-COMBINED.ko ]]; then
+		log "can't find test-COMBINED.ko, skipping"
 		return
 	fi
 
@@ -258,7 +260,7 @@ run_combined_test() {
 		fi
 	done
 
-	if ! $KPATCH load kpatch-COMBINED.ko >> $LOG 2>&1; then
+	if ! $KPATCH load test-COMBINED.ko >> $LOG 2>&1; then
 		error "combined: kpatch load failed"
 		return
 	fi
@@ -270,7 +272,7 @@ run_combined_test() {
 		fi
 	done
 
-	if ! $KPATCH unload kpatch-COMBINED.ko >> $LOG 2>&1; then
+	if ! $KPATCH unload test-COMBINED.ko >> $LOG 2>&1; then
 		error "combined: kpatch unload failed"
 		return
 	fi
@@ -288,11 +290,11 @@ run_combined_test() {
 echo "clearing printk buffer"
 sudo dmesg -C
 
-if [[ $QUICK != 1 ]]; then
-	for file in "${PATCH_LIST[@]}"; do
+for file in "${PATCH_LIST[@]}"; do
+	if [[ $QUICK != 1 || $file =~ -FAIL ]]; then
 		build_module $file
-	done
-fi
+	fi
+done
 
 build_combined_module
 
@@ -308,15 +310,20 @@ run_combined_test
 
 if [[ $QUICK != 1 ]]; then
 	for testprog in "${TEST_LIST[@]}"; do
-		unload_all
-		run_custom_test $testprog
+		if [[ ! $testprog =~ -FAIL ]]; then
+			unload_all
+			run_custom_test $testprog
+		fi
 	done
 fi
 
 
 unload_all
 
-dmesg |grep -q "Call Trace" && error "kernel error detected in printk buffer"
+if dmesg | grep -q "Call Trace"; then
+	dmesg > dmesg.log
+	error "kernel error detected in printk buffer"
+fi
 
 if [[ $ERROR -gt 0 ]]; then
 	log "$ERROR errors encountered"
diff -pruN 0.6.0-0.2/test/integration/lib.sh 0.8.0-0ubuntu7/test/integration/lib.sh
--- 0.6.0-0.2/test/integration/lib.sh	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/lib.sh	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,300 @@
+#!/bin/bash
+
+kpatch_set_ccache_max_size()
+{
+	local ccache_max_size=${1:-10G}
+
+	ccache --max-size="${ccache_max_size}"
+}
+
+kpatch_fedora_dependencies()
+{
+	local kernel_version
+	kernel_version=$(uname -r)
+
+	sudo dnf install -y gcc "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel
+	sudo dnf install -y pesign yum-utils openssl wget numactl-devel
+	sudo dnf builddep -y "kernel-${kernel_version%.*}"
+	sudo dnf debuginfo-install -y "kernel-${kernel_version%.*}"
+
+	sudo dnf install -y ccache
+}
+
+kpatch_ubuntu_dependencies()
+{
+	sudo sed -i 's/# deb-src/deb-src/' /etc/apt/sources.list
+	sudo apt-get update
+
+	sudo apt-get install -y make gcc libelf-dev elfutils
+	sudo apt-get install -y dpkg-dev devscripts
+	sudo apt-get build-dep -y linux
+
+	sudo apt-get install -y ccache
+
+	# Add ddebs repository
+	if ! grep -q 'ddebs.ubuntu.com' /etc/apt/sources.list.d/ddebs.list; then
+		local codename
+		codename=$(lsb_release -sc)
+		sudo tee /etc/apt/sources.list.d/ddebs.list <<-EOF
+			deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse
+			deb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiverse
+			deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse
+			deb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverse
+		EOF
+
+		# add APT key
+		wget -Nq http://ddebs.ubuntu.com/dbgsym-release-key.asc -O- | sudo apt-key add -
+		sudo apt-get update
+	fi
+	sudo apt-get install -y "linux-image-$(uname -r)-dbgsym"
+}
+
+kpatch_rhel_dependencies()
+{
+	local kernel_version
+	local arch
+	kernel_version=$(uname -r)
+	arch=$(uname -m)
+
+	sudo yum install -y git gcc gcc-c++ "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel
+	sudo yum install -y yum-utils zlib-devel binutils-devel newt-devel \
+		python-devel perl-ExtUtils-Embed audit-libs-devel numactl-devel \
+		pciutils-devel bison ncurses-devel rpm-build java-devel
+	sudo yum-builddep -y "kernel-${kernel_version%.*}"
+	sudo debuginfo-install -y "kernel-${kernel_version%.*}"
+
+	[ "${arch}" == "x86_64" ] && sudo yum install -y pesign
+	[ "${arch}" == "ppc64le" ] && sudo yum install -y gcc-plugin-devel
+
+	sudo yum install -y "https://dl.fedoraproject.org/pub/epel/7/${arch}/Packages/c/ccache-3.3.4-1.el7.${arch}.rpm"
+}
+
+kpatch_centos_dependencies()
+{
+	local kernel_version
+	local arch
+	kernel_version=$(uname -r)
+	arch=$(uname -m)
+
+	sudo yum install -y gcc gcc-c++ "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel
+	sudo yum install -y yum-utils zlib-devel binutils-devel newt-devel \
+		python-devel perl-ExtUtils-Embed audit-libs-devel numactl-devel \
+		pciutils-devel bison ncurses-devel rpm-build java-devel pesign
+	sudo yum-config-manager --enable debug
+	sudo yum-builddep -y "kernel-${kernel_version%.*}"
+	sudo debuginfo-install -y "kernel-${kernel_version%.*}"
+
+	sudo yum install -y "https://dl.fedoraproject.org/pub/epel/7/${arch}/Packages/c/ccache-3.3.4-1.el7.${arch}.rpm"
+}
+
+kpatch_dependencies()
+{
+	# shellcheck disable=SC1091
+	source /etc/os-release
+
+	eval "kpatch_${ID}_dependencies" || { echo "Unsupported distro: ${ID}"; exit 1; }
+}
+
+kpatch_separate_partition_cache()
+{
+	local partition=${1}
+	local mountpoint=${2}
+	local reformat=${3}
+	local owner=${USER}
+
+	if [[ "${reformat}" == "y" ]]; then
+		sudo mkfs.xfs -f "${partition}"
+	fi
+
+	sudo mkdir -p "${mountpoint}"
+	sudo mount "${partition}" "${mountpoint}"
+	sudo chown "${owner}":"${owner}" "${mountpoint}"
+
+	rm -rf "${mountpoint}/.ccache"
+	rm -rf "${mountpoint}/.kpatch"
+	mkdir "${mountpoint}/.ccache"
+	mkdir "${mountpoint}/.kpatch"
+
+	rm -rf "${HOME}/.ccache"
+	rm -rf "${HOME}/.kpatch"
+
+	ln -sv "${mountpoint}/.ccache" "${HOME}/.ccache"
+	ln -sv "${mountpoint}/.kpatch" "${HOME}/.kpatch"
+}
+
+kpatch_separate_disk_cache()
+{
+	local device=${1}
+	local mountpoint=${2}
+	local partition="${device}1"
+
+	echo -e "o\\nn\\np\\n1\\n\\n\\nw\\n" | sudo fdisk "${device}"
+	kpatch_separate_partition_cache "${partition}" "${mountpoint}" y
+}
+
+kpatch_install_vagrant_centos()
+{
+	local image_path=${1}
+
+	sudo yum group install -y "Development Tools"
+	sudo yum -y install qemu-kvm libvirt virt-install bridge-utils libvirt-devel libxslt-devel libxml2-devel libvirt-devel libguestfs-tools-c libvirt-client
+
+	echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf
+	sudo sysctl -p /etc/sysctl.d/99-ipforward.conf
+
+	sudo systemctl enable libvirtd
+	sudo systemctl start libvirtd || exit 1
+
+	if [[ -n "${image_path}" ]]; then
+		mkdir -p "${image_path}/libvirt/images"
+		virsh pool-define-as --target "${image_path}/libvirt/images" default dir || exit 1
+		virsh pool-start default || exit 1
+	fi
+
+	sudo yum install -y https://releases.hashicorp.com/vagrant/2.1.2/vagrant_2.1.2_x86_64.rpm || exit 1
+
+	vagrant plugin install vagrant-libvirt
+}
+
+kpatch_install_vagrant_rhel()
+{
+	local image_path=${1}
+
+	kpatch_install_vagrant_centos "${image_path}"
+
+	sudo systemctl enable nfs
+	sudo systemctl start nfs || exit 1
+
+}
+
+kpatch_install_vagrant_fedora()
+{
+	local image_path=${1}
+
+	echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf
+	sudo sysctl -p /etc/sysctl.d/99-ipforward.conf
+
+	sudo dnf install -y libvirt virt-install libvirt-client nfs-utils vagrant vagrant-libvirt
+
+	echo "[nfsd]" | sudo tee -a /etc/nfs.conf
+	echo "udp=y" | sudo tee -a /etc/nfs.conf
+	echo "vers3=y" | sudo tee -a /etc/nfs.conf
+	sudo systemctl restart nfs
+
+	sudo systemctl enable libvirtd
+	sudo systemctl start libvirtd || exit 1
+
+	if [[ -n "${image_path}" ]]; then
+		mkdir -p "${image_path}/libvirt/images"
+		virsh pool-define-as --target "${image_path}/libvirt/images" default dir || exit 1
+		virsh pool-start default || exit 1
+	fi
+}
+
+kpatch_install_vagrant()
+{
+	local image_path=${1}
+
+	# shellcheck disable=SC1091
+	source /etc/os-release
+
+	eval "kpatch_install_vagrant_${ID} ${image_path}" || { echo "Unsupported distro: ${ID}"; exit 1; }
+}
+
+kpatch_check_install_vagrant()
+{
+	local image_path=${1}
+	[ "$(which vagrant)" == "" ] && kpatch_install_vagrant "${image_path}"
+	return 0
+}
+
+kpatch_write_vagrantfile_template()
+{
+	local target_distro=${1}
+
+	local box_prefix="kpatch"
+
+	cat >Vagrantfile <<EOF
+Vagrant.configure("2") do |config|
+	config.vm.provider :libvirt do |libvirt|
+		libvirt.storage :file, :size => '40G'
+		libvirt.cpus = $(getconf _NPROCESSORS_ONLN)
+		libvirt.memory = $(awk '/MemTotal/ {printf("%d\n", ($2*0.8)/1024)}' /proc/meminfo)
+		libvirt.graphics_type = "none"
+		libvirt.disk_bus = 'virtio'
+		libvirt.disk_device = 'vda'
+	end
+	config.vm.box = "${box_prefix}/${target_distro}"
+	config.vm.synced_folder ".", "/vagrant", type: "nfs"
+EOF
+}
+
+kpatch_write_vagrantfile_centos_provision()
+{
+	cat >>Vagrantfile <<EOF
+	config.vm.provision "shell", inline: "yum install -y git"
+EOF
+}
+
+kpatch_write_vagrantfile()
+{
+	local target_distro=${1}
+
+	kpatch_write_vagrantfile_template "${target_distro}"
+
+	if echo "${target_distro}" | grep -qE "^centos"; then
+		kpatch_write_vagrantfile_centos_provision
+	fi
+
+	echo 'end' >>Vagrantfile
+}
+
+kpatch_integration_tests_vagrant_distro()
+{
+	local target_distro=${1}
+	local test_script=${2}
+	local slowtest=${3}
+
+	local testdir
+	local workdir
+	local logdir
+
+	testdir="$(pwd)"
+	workdir="${target_distro}.vagrant"
+	rm -rf "${workdir}"
+	mkdir -p "${workdir}"
+	cd "${workdir}" || exit 1
+
+	kpatch_write_vagrantfile "${target_distro}"
+
+	vagrant up || { vagrant destroy -f; exit 1; }
+
+	local test_cmd="bash /vagrant/runtest.sh"
+	if [ "${slowtest}" == "1" ]; then
+		test_cmd="${test_cmd} --slow"
+	fi
+
+	cp "${test_script}" ./runtest.sh
+	vagrant ssh -c "${test_cmd}"
+	local rc=$?
+
+	if [ $rc -eq 0 ]; then
+		echo "${target_distro} PASS"
+	else
+		echo "${target_distro} FAIL"
+	fi
+
+	logdir="${testdir}/${target_distro}_log"
+	rm -rf "${logdir}"
+	mkdir -p "${logdir}"
+	cp logs/* "${logdir}"
+
+	vagrant destroy -f
+
+	cd "${testdir}" || exit 1
+	if [ $rc -eq 0 ]; then
+		rm -rf "${workdir}"
+	fi
+
+	return "${rc}"
+}
diff -pruN 0.6.0-0.2/test/integration/Makefile 0.8.0-0ubuntu7/test/integration/Makefile
--- 0.6.0-0.2/test/integration/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/Makefile	2019-08-28 17:34:00.000000000 +0000
@@ -18,6 +18,14 @@ quick: clean
 cached:
 	./kpatch-test -d $(PATCH_DIR) --cached $(PATCHES)
 
+vagrant: vagrant_quick
+
+vagrant-quick:
+	./test-vagrant
+
+vagrant-slow:
+	./test-vagrant --slow
+
 clean:
 	rm -f *.ko *.log COMBINED.patch
 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/bug-table-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/bug-table-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/bug-table-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/bug-table-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
+--- src.orig/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.769056469 -0400
+@@ -266,6 +266,8 @@ void sysctl_head_put(struct ctl_table_he
+ 
+ static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
+ {
++	if (jiffies == 0)
++		printk("kpatch-test: testing __bug_table section changes\n");
+ 	BUG_ON(!head);
+ 	spin_lock(&sysctl_lock);
+ 	if (!use_table(head))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/cmdline-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/cmdline-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.4/cmdline-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/cmdline-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/cmdline-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/cmdline-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/cmdline-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/cmdline-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:22.955061380 -0400
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/data-new-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-new-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.4/data-new-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-new-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep "kpatch: 5" /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/data-new.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-new.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/data-new.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-new.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,28 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:24.102066130 -0400
+@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m
+ {
+ }
+ 
++static int foo = 5;
++
+ static int meminfo_proc_show(struct seq_file *m, void *v)
+ {
+ 	struct sysinfo i;
+@@ -106,6 +108,7 @@ static int meminfo_proc_show(struct seq_
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ 		"AnonHugePages:  %8lu kB\n"
+ #endif
++		"kpatch: %d"
+ 		,
+ 		K(i.totalram),
+ 		K(i.freeram),
+@@ -167,6 +170,7 @@ static int meminfo_proc_show(struct seq_
+ 		,K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) *
+ 		   HPAGE_PMD_NR)
+ #endif
++		,foo
+ 		);
+ 
+ 	hugetlb_report_meminfo(m);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/data-read-mostly.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-read-mostly.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/data-read-mostly.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/data-read-mostly.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c
+--- src.orig/net/core/dev.c	2017-09-22 15:27:21.759056428 -0400
++++ src/net/core/dev.c	2017-09-22 15:27:25.244070859 -0400
+@@ -4012,6 +4012,7 @@ ncls:
+ 		case RX_HANDLER_PASS:
+ 			break;
+ 		default:
++			printk("BUG!\n");
+ 			BUG();
+ 		}
+ 	}
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/fixup-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/fixup-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/fixup-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff --git a/fs/readdir.c b/fs/readdir.c
+index fee38e04fae4..bce1e5ce74e5 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -166,6 +166,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+ 			goto efault;
+ 	}
+ 	dirent = buf->current_dir;
++	asm("nop");
+ 	if (__put_user(d_ino, &dirent->d_ino))
+ 		goto efault;
+ 	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-constprop.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-constprop.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-constprop.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-constprop.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c
+--- src.orig/kernel/time/timekeeping.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/time/timekeeping.c	2017-09-22 15:27:27.522080292 -0400
+@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv)
+ {
+ 	struct timespec64 now;
+ 
++	if (!tv)
++		return;
++
+ 	getnstimeofday64(&now);
+ 	tv->tv_sec = now.tv_sec;
+ 	tv->tv_usec = now.tv_nsec/1000;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-isra.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-isra.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-isra.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-isra.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
+--- src.orig/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/proc_sysctl.c	2017-09-22 15:27:28.670085046 -0400
+@@ -24,6 +24,7 @@ void proc_sys_poll_notify(struct ctl_tab
+ 	if (!poll)
+ 		return;
+ 
++	printk("kpatch-test: testing gcc .isra function name mangling\n");
+ 	atomic_inc(&poll->event);
+ 	wake_up_interruptible(&poll->wait);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-mangled-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/mm/slub.c src/mm/slub.c
+--- src.orig/mm/slub.c	2017-09-22 15:27:21.618055844 -0400
++++ src/mm/slub.c	2017-09-22 15:27:29.830089850 -0400
+@@ -5528,6 +5528,9 @@ void get_slabinfo(struct kmem_cache *s,
+ 	unsigned long nr_free = 0;
+ 	int node;
+ 
++	if (!jiffies)
++		printk("slabinfo\n");
++
+ 	for_each_online_node(node) {
+ 		struct kmem_cache_node *n = get_node(s, node);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c
+--- src.orig/mm/mmap.c	2017-09-22 15:27:21.618055844 -0400
++++ src/mm/mmap.c	2017-09-22 15:27:31.024094794 -0400
+@@ -1687,6 +1688,9 @@ unsigned long mmap_region(struct file *f
+ 	struct rb_node **rb_link, *rb_parent;
+ 	unsigned long charged = 0;
+ 
++	if (!jiffies)
++		printk("kpatch mmap foo\n");
++
+ 	/* Check against address space limit. */
+ 	if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
+ 		unsigned long nr_pages;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,19 @@
+diff -Nupr src.orig/kernel/sys.c src/kernel/sys.c
+--- src.orig/kernel/sys.c	2017-09-22 15:27:21.601055773 -0400
++++ src/kernel/sys.c	2017-09-22 15:27:32.170099540 -0400
+@@ -554,8 +554,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
+ 	return ret;
+ }
+ 
++void kpatch_bar(void)
++{
++	if (!jiffies)
++		printk("kpatch_foo\n");
++}
++
+ static void deferred_cad(struct work_struct *dummy)
+ {
++	kpatch_bar();
+ 	kernel_restart(NULL);
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-4.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-4.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-4.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-4.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+diff -Nupr src.orig/fs/aio.c src/fs/aio.c
+--- src.orig/fs/aio.c	2017-09-22 15:27:21.702056192 -0400
++++ src/fs/aio.c	2017-09-22 15:27:33.299104215 -0400
+@@ -219,9 +219,16 @@ static int __init aio_setup(void)
+ }
+ __initcall(aio_setup);
+ 
++void kpatch_aio_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch aio foo\n");
++}
++
+ static void put_aio_ring_file(struct kioctx *ctx)
+ {
+ 	struct file *aio_ring_file = ctx->aio_ring_file;
++	kpatch_aio_foo();
+ 	if (aio_ring_file) {
+ 		truncate_setsize(aio_ring_file->f_inode, 0);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+	exit 1
+else
+	exit 0
+fi
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-5.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-5.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-5.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-5.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,45 @@
+diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c
+--- src.orig/kernel/audit.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/audit.c	2017-09-22 15:27:34.429108894 -0400
+@@ -205,6 +205,12 @@ void audit_panic(const char *message)
+ 	}
+ }
+ 
++void kpatch_audit_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch audit foo\n");
++}
++
+ static inline int audit_rate_check(void)
+ {
+ 	static unsigned long	last_check = 0;
+@@ -215,6 +221,7 @@ static inline int audit_rate_check(void)
+ 	unsigned long		elapsed;
+ 	int			retval	   = 0;
+ 
++	kpatch_audit_foo();
+ 	if (!audit_rate_limit) return 1;
+ 
+ 	spin_lock_irqsave(&lock, flags);
+@@ -234,6 +241,11 @@ static inline int audit_rate_check(void)
+ 	return retval;
+ }
+ 
++noinline void kpatch_audit_check(void)
++{
++	audit_rate_check();
++}
++
+ /**
+  * audit_log_lost - conditionally log lost audit message event
+  * @message: the message stating reason for lost audit message
+@@ -282,6 +294,8 @@ static int audit_log_config_change(char
+ 	struct audit_buffer *ab;
+ 	int rc = 0;
+ 
++	kpatch_audit_check();
++
+ 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ 	if (unlikely(!ab))
+ 		return rc;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-6.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-6.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var-6.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var-6.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index a9d587a..23336ed 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb,
+	return 0;
+ }
+
++#include "kpatch-macros.h"
++
+ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+			struct flowi *fl, bool strict)
+ {
+@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+	struct dst_entry *result;
+	int err;
+
++	if (!jiffies)
++		printk("kpatch nf_ip6_route foo\n");
++
+	result = ip6_route_output(net, sk, &fl->u.ip6);
+	err = result->error;
+	if (err)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/gcc-static-local-var.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/gcc-static-local-var.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,25 @@
+diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c
+--- src.orig/arch/x86/kernel/ldt.c	2017-09-22 15:27:20.847052651 -0400
++++ src/arch/x86/kernel/ldt.c	2017-09-22 15:27:35.573113632 -0400
+@@ -98,6 +98,12 @@ static inline int copy_ldt(mm_context_t
+ 	return 0;
+ }
+ 
++void hi_there(void)
++{
++	if (!jiffies)
++		printk("hi there\n");
++}
++
+ /*
+  * we do not have to muck with descriptors here, that is
+  * done in switch_mm() as needed.
+@@ -107,6 +113,8 @@ int init_new_context(struct task_struct
+ 	struct mm_struct *old_mm;
+ 	int retval = 0;
+ 
++	hi_there();
++
+ 	mutex_init(&mm->context.lock);
+ 	mm->context.size = 0;
+ 	old_mm = current->mm;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/macro-callbacks.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/macro-callbacks.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/macro-callbacks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/macro-callbacks.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,160 @@
+kpatch/livepatch callback test patch:
+
+  vmlinux
+  pcspkr (mod)
+  joydev (mod)
+
+Note: update joydev's pre-patch callback to return -ENODEV to test failure path
+
+--- src.old/fs/aio.c	2018-02-26 11:07:51.522610407 -0500
++++ src/fs/aio.c	2018-03-05 11:17:21.560015449 -0500
+@@ -42,6 +42,50 @@
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
++
+ #define AIO_RING_MAGIC			0xa10a10a1
+ #define AIO_RING_COMPAT_FEATURES	1
+ #define AIO_RING_INCOMPAT_FEATURES	0
+--- src.old/drivers/input/joydev.c	2018-02-26 11:07:49.470610407 -0500
++++ src/drivers/input/joydev.c	2018-03-05 11:18:13.998015449 -0500
+@@ -954,3 +954,47 @@ static void __exit joydev_exit(void)
+ 
+ module_init(joydev_init);
+ module_exit(joydev_exit);
++
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0; /* return -ENODEV; */
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+--- src.old/drivers/input/misc/pcspkr.c	2018-02-26 11:07:49.477610407 -0500
++++ src/drivers/input/misc/pcspkr.c	2018-03-05 11:18:23.411015449 -0500
+@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla
+ };
+ module_platform_driver(pcspkr_platform_driver);
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/macro-printk.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/macro-printk.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/macro-printk.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,147 @@
+diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c
+--- src.orig/net/ipv4/fib_frontend.c	2017-09-22 16:52:10.646110299 -0400
++++ src/net/ipv4/fib_frontend.c	2017-09-22 16:55:14.395870305 -0400
+@@ -633,6 +633,7 @@ errout:
+ 	return err;
+ }
+ 
++#include "kpatch-macros.h"
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	struct net *net = sock_net(skb->sk);
+@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b
+ 	}
+ 
+ 	err = fib_table_insert(net, tb, &cfg);
++	KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err);
+ errout:
+ 	return err;
+ }
+diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c
+--- src.orig/net/ipv4/fib_semantics.c	2017-09-22 16:52:10.645110295 -0400
++++ src/net/ipv4/fib_semantics.c	2017-09-22 16:54:05.175584004 -0400
+@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi,
+ 	return 0;
+ }
+ 
++#include "kpatch-macros.h"
+ struct fib_info *fib_create_info(struct fib_config *cfg)
+ {
+ 	int err;
+@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct
+ #endif
+ 
+ 	err = -ENOBUFS;
++	KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err);
+ 	if (fib_info_cnt >= fib_info_hash_size) {
+ 		unsigned int new_size = fib_info_hash_size << 1;
+ 		struct hlist_head *new_info_hash;
+@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct
+ 		if (!fib_info_hash_size)
+ 			goto failure;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err);
+ 
+ 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ 	if (fi == NULL)
+@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct
+ 	} else
+ 		fi->fib_metrics = (u32 *) dst_default_metrics;
+ 	fib_info_cnt++;
++	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
+ 
+ 	fi->fib_net = net;
+ 	fi->fib_protocol = cfg->fc_protocol;
+@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct
+ 		if (!nexthop_nh->nh_pcpu_rth_output)
+ 			goto failure;
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err);
+ 
+ 	err = fib_convert_metrics(fi, cfg);
++	KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err);
+ 	if (err)
+ 		goto failure;
+ 
+@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct
+ 		nh->nh_weight = 1;
+ #endif
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err);
+ 
+ 	if (fib_props[cfg->fc_type].error) {
+ 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
+@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct
+ 			goto err_inval;
+ 		}
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err);
+ 
+ 	if (cfg->fc_scope > RT_SCOPE_HOST)
+ 		goto err_inval;
+@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct
+ 				goto failure;
+ 		} endfor_nexthops(fi)
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err);
+ 
+ 	if (fi->fib_prefsrc) {
+ 		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct
+ 		fib_info_update_nh_saddr(net, nexthop_nh);
+ 		fib_add_weight(fi, nexthop_nh);
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err);
+ 
+ 	fib_rebalance(fi);
+ 
+@@ -1110,6 +1120,7 @@ link_it:
+ 		ofi->fib_treeref++;
+ 		return ofi;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err);
+ 
+ 	fi->fib_treeref++;
+ 	atomic_inc(&fi->fib_clntref);
+@@ -1133,6 +1144,7 @@ link_it:
+ 		hlist_add_head(&nexthop_nh->nh_hash, head);
+ 	} endfor_nexthops(fi)
+ 	spin_unlock_bh(&fib_info_lock);
++	KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err);
+ 	return fi;
+ 
+ err_inval:
+@@ -1143,6 +1155,7 @@ failure:
+ 		fi->fib_dead = 1;
+ 		free_fib_info(fi);
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err);
+ 
+ 	return ERR_PTR(err);
+ }
+diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c
+--- src.orig/net/ipv4/fib_trie.c	2017-09-22 16:52:10.645110295 -0400
++++ src/net/ipv4/fib_trie.c	2017-09-22 16:55:39.940975963 -0400
+@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie
+ }
+ 
+ /* Caller must hold RTNL. */
++#include "kpatch-macros.h"
+ int fib_table_insert(struct net *net, struct fib_table *tb,
+ 		     struct fib_config *cfg)
+ {
+@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st
+ 	if ((plen < KEYLENGTH) && (key << plen))
+ 		return -EINVAL;
+ 
++	KPATCH_PRINTK("[fib_table_insert]: start\n");
+ 	fi = fib_create_info(cfg);
+ 	if (IS_ERR(fi)) {
+ 		err = PTR_ERR(fi);
++		KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err);
+ 		goto err;
+ 	}
++	KPATCH_PRINTK("[fib_table_insert]: cross\n");
+ 
+ 	l = fib_find_node(t, &tp, key);
+ 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/meminfo-init2-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-init2-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/meminfo-init2-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-init2-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,19 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:38.972127707 -0400
+@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_
+ 	unsigned long pages[NR_LRU_LISTS];
+ 	int lru;
+ 
++	printk("a\n");
+ /*
+  * display in kilobytes.
+  */
+@@ -191,6 +192,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/meminfo-init-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-init-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/meminfo-init-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-init-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:40.130132502 -0400
+@@ -191,6 +191,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/meminfo-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.4/meminfo-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/meminfo-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/meminfo-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/meminfo-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:41.274137239 -0400
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/module-call-external.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-call-external.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/module-call-external.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-call-external.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,33 @@
+diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c
+--- src.orig/fs/nfsd/export.c	2017-09-22 15:27:21.705056204 -0400
++++ src/fs/nfsd/export.c	2017-09-22 15:27:42.411141948 -0400
+@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m
+ 	}
+ }
+ 
++extern char *kpatch_string(void);
++
+ static int e_show(struct seq_file *m, void *p)
+ {
+ 	struct cache_head *cp = p;
+@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo
+ 	if (p == SEQ_START_TOKEN) {
+ 		seq_puts(m, "# Version 1.1\n");
+ 		seq_puts(m, "# Path Client(Flags) # IPs\n");
++		seq_puts(m, kpatch_string());
+ 		return 0;
+ 	}
+ 
+diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
+--- src.orig/net/netlink/af_netlink.c	2017-09-22 15:27:21.754056407 -0400
++++ src/net/netlink/af_netlink.c	2017-09-22 15:27:42.412141952 -0400
+@@ -3260,4 +3260,9 @@ panic:
+ 	panic("netlink_init: Cannot allocate nl_table\n");
+ }
+ 
++char *kpatch_string(void)
++{
++	return "# kpatch\n";
++}
++
+ core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/module-kvm-fixup.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-kvm-fixup.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/module-kvm-fixup.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-kvm-fixup.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
+--- src.orig/arch/x86/kvm/vmx.c	2017-09-22 15:27:20.853052676 -0400
++++ src/arch/x86/kvm/vmx.c	2017-09-22 15:27:43.583146801 -0400
+@@ -10597,6 +10597,8 @@ static int vmx_check_intercept(struct kv
+ 			       struct x86_instruction_info *info,
+ 			       enum x86_intercept_stage stage)
+ {
++	if (!jiffies)
++		printk("kpatch vmx_check_intercept\n");
+ 	return X86EMUL_CONTINUE;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/module-shadow.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-shadow.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/module-shadow.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/module-shadow.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,24 @@
+diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
+--- src.orig/arch/x86/kvm/vmx.c	2017-09-22 15:27:20.853052676 -0400
++++ src/arch/x86/kvm/vmx.c	2017-09-22 15:27:44.742151601 -0400
+@@ -10581,10 +10581,20 @@ static void vmx_leave_nested(struct kvm_
+  * It should only be called before L2 actually succeeded to run, and when
+  * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
+  */
++#include "kpatch.h"
+ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ 			struct vmcs12 *vmcs12,
+ 			u32 reason, unsigned long qualification)
+ {
++	int *kpatch;
++
++	kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch),
++				     GFP_KERNEL);
++	if (kpatch) {
++		kpatch_shadow_get(vcpu, "kpatch");
++		kpatch_shadow_free(vcpu, "kpatch");
++	}
++
+ 	load_vmcs12_host_state(vcpu, vmcs12);
+ 	vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
+ 	vmcs12->exit_qualification = qualification;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/multiple.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/multiple.test
--- 0.6.0-0.2/test/integration/rhel-7.4/multiple.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
+ROOTDIR="$(readlink -f $SCRIPTDIR/../..)"
+KPATCH="sudo $ROOTDIR/kpatch/kpatch"
+
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
+set -o errexit
+
+die() {
+	echo "ERROR: $@" >&2
+	exit 1
+}
+
+ko_to_test() {
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
+}
+
+# make sure any modules added here are disjoint
+declare -a modules
+declare -a blacklist=(meminfo-string-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules"
+done
+
+for mod in "${modules[@]}"; do
+	$KPATCH load $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules"
+done
+
+for mod in "${modules[@]}"; do
+	$KPATCH unload $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules"
+done
+
+exit 0
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/new-function.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/new-function.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/new-function.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/new-function.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,25 @@
+diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c
+--- src.orig/drivers/tty/n_tty.c	2017-09-22 15:27:21.084053633 -0400
++++ src/drivers/tty/n_tty.c	2017-09-22 15:27:45.888156346 -0400
+@@ -2016,7 +2016,7 @@ do_it_again:
+  *		  lock themselves)
+  */
+ 
+-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file,
+ 			   const unsigned char *buf, size_t nr)
+ {
+ 	const unsigned char *b = buf;
+@@ -2098,6 +2098,12 @@ break_out:
+ 	return (b - buf) ? b - buf : retval;
+ }
+ 
++static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
++			   const unsigned char *buf, size_t nr)
++{
++	return kpatch_n_tty_write(tty, file, buf, nr);
++}
++
+ /**
+  *	n_tty_poll		-	poll method for N_TTY
+  *	@tty: terminal device
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/new-globals.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/new-globals.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/new-globals.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/new-globals.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,34 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:47.028161067 -0400
+@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void
+ 	return 0;
+ }
+ module_init(proc_cmdline_init);
++
++#include <linux/printk.h>
++void kpatch_print_message(void)
++{
++	if (!jiffies)
++		printk("hello there!\n");
++}
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:47.029161071 -0400
+@@ -16,6 +16,8 @@
+ #include <asm/pgtable.h>
+ #include "internal.h"
+ 
++void kpatch_print_message(void);
++
+ void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
+ {
+ }
+@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_
+ 	/*
+ 	 * Tagged format, for easy grepping and expansion.
+ 	 */
++	kpatch_print_message();
+ 	seq_printf(m,
+ 		"MemTotal:       %8lu kB\n"
+ 		"MemFree:        %8lu kB\n"
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/parainstructions-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/parainstructions-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/parainstructions-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/parainstructions-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c
+--- src.orig/fs/proc/generic.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/generic.c	2017-09-22 15:27:48.190165879 -0400
+@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum)
+ 	unsigned int i;
+ 	int error;
+ 
++	printk("kpatch-test: testing change to .parainstructions section\n");
+ retry:
+ 	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+ 		return -ENOMEM;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/replace-section-references.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/replace-section-references.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/replace-section-references.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/replace-section-references.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:49.362170732 -0400
+@@ -248,6 +248,8 @@ static void shared_msr_update(unsigned s
+ 
+ void kvm_define_shared_msr(unsigned slot, u32 msr)
+ {
++	if (!jiffies)
++		printk("kpatch kvm define shared msr\n");
+ 	BUG_ON(slot >= KVM_NR_SHARED_MSRS);
+ 	shared_msrs_global.msrs[slot] = msr;
+ 	if (slot >= shared_msrs_global.nr)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/shadow-newpid-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.4/shadow-newpid-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.4/shadow-newpid-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/shadow-newpid-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep -q newpid: /proc/$$/status
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/shadow-newpid.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,69 @@
+diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c
+--- src.orig/fs/proc/array.c	2017-09-22 16:52:10.597110096 -0400
++++ src/fs/proc/array.c	2017-09-22 16:59:40.799972178 -0400
+@@ -359,13 +359,20 @@ static inline void task_seccomp(struct s
+ #endif
+ }
+ 
++#include "kpatch.h"
+ static inline void task_context_switch_counts(struct seq_file *m,
+ 						struct task_struct *p)
+ {
++	int *newpid;
++
+ 	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
+ 			"nonvoluntary_ctxt_switches:\t%lu\n",
+ 			p->nvcsw,
+ 			p->nivcsw);
++
++	newpid = kpatch_shadow_get(p, "newpid");
++	if (newpid)
++		seq_printf(m, "newpid:\t%d\n", *newpid);
+ }
+ 
+ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
+diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c
+--- src.orig/kernel/exit.c	2017-09-22 16:52:10.506109720 -0400
++++ src/kernel/exit.c	2017-09-22 16:59:40.799972178 -0400
+@@ -715,6 +715,7 @@ static void check_stack_usage(void)
+ static inline void check_stack_usage(void) {}
+ #endif
+ 
++#include "kpatch.h"
+ void do_exit(long code)
+ {
+ 	struct task_struct *tsk = current;
+@@ -812,6 +813,8 @@ void do_exit(long code)
+ 	check_stack_usage();
+ 	exit_thread();
+ 
++	kpatch_shadow_free(tsk, "newpid");
++
+ 	/*
+ 	 * Flush inherited counters to the parent - before the parent
+ 	 * gets woken up by child-exit notifications.
+diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
+--- src.orig/kernel/fork.c	2017-09-22 16:52:10.504109711 -0400
++++ src/kernel/fork.c	2017-09-22 17:00:44.938237460 -0400
+@@ -1700,6 +1700,7 @@ struct task_struct *fork_idle(int cpu)
+  * It copies the process, and if successful kick-starts
+  * it and waits for it to finish using the VM if required.
+  */
++#include "kpatch.h"
+ long do_fork(unsigned long clone_flags,
+ 	      unsigned long stack_start,
+ 	      unsigned long stack_size,
+@@ -1737,6 +1738,13 @@ long do_fork(unsigned long clone_flags,
+ 	if (!IS_ERR(p)) {
+ 		struct completion vfork;
+ 		struct pid *pid;
++		int *newpid;
++		static int ctr = 0;
++
++		newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
++					     GFP_KERNEL);
++		if (newpid)
++			*newpid = ctr++;
+ 
+ 		trace_sched_process_fork(current, p);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/smp-locks-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/smp-locks-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/smp-locks-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/smp-locks-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c
+--- src.orig/drivers/tty/tty_buffer.c	2017-09-22 15:27:21.077053604 -0400
++++ src/drivers/tty/tty_buffer.c	2017-09-22 15:27:50.542175618 -0400
+@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p
+ 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ 	   remove this conditional if its worth it. This would be invisible
+ 	   to the callers */
++
++	if (!size)
++		printk("kpatch-test: testing .smp_locks section changes\n");
++
+ 	b = buf->tail;
+ 	if (b != NULL)
+ 		left = b->size - b->used;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/special-static-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/special-static-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/special-static-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/special-static-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,24 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:51.744180596 -0400
+@@ -2093,12 +2093,20 @@ static void record_steal_time(struct kvm
+ 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+ }
+ 
++void kpatch_kvm_x86_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch kvm x86 foo\n");
++}
++
+ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ {
+ 	bool pr = false;
+ 	u32 msr = msr_info->index;
+ 	u64 data = msr_info->data;
+ 
++	kpatch_kvm_x86_foo();
++
+ 	switch (msr) {
+ 	case MSR_AMD64_NB_CFG:
+ 	case MSR_IA32_UCODE_REV:
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/special-static.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/special-static.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/special-static.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/special-static.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,22 @@
+diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
+--- src.orig/kernel/fork.c	2017-09-22 15:27:21.600055769 -0400
++++ src/kernel/fork.c	2017-09-22 15:27:53.052186012 -0400
+@@ -1129,10 +1129,18 @@ static void posix_cpu_timers_init_group(
+ 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+ }
+ 
++void kpatch_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch copy signal\n");
++}
++
+ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ 	struct signal_struct *sig;
+ 
++	kpatch_foo();
++
+ 	if (clone_flags & CLONE_THREAD)
+ 		return 0;
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/tracepoints-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/tracepoints-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/tracepoints-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/tracepoints-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/timer.c src/kernel/timer.c
+--- src.orig/kernel/timer.c	2017-09-22 15:27:21.600055769 -0400
++++ src/kernel/timer.c	2017-09-22 15:27:54.288191131 -0400
+@@ -1390,6 +1390,9 @@ static void run_timer_softirq(struct sof
+ {
+ 	struct tvec_base *base = __this_cpu_read(tvec_bases);
+ 
++	if (!base)
++		printk("kpatch-test: testing __tracepoints section changes\n");
++
+ 	if (time_after_eq(jiffies, base->timer_jiffies))
+ 		__run_timers(base);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.4/warn-detect-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.4/warn-detect-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.4/warn-detect-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.4/warn-detect-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,8 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:55.489196104 -0400
+@@ -1,3 +1,4 @@
++
+ /*
+  * Kernel-based Virtual Machine driver for Linux
+  *
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/bug-table-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/bug-table-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/bug-table-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/bug-table-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
+--- src.orig/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.769056469 -0400
+@@ -266,6 +266,8 @@ void sysctl_head_put(struct ctl_table_he
+ 
+ static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
+ {
++	if (jiffies == 0)
++		printk("kpatch-test: testing __bug_table section changes\n");
+ 	BUG_ON(!head);
+ 	spin_lock(&sysctl_lock);
+ 	if (!use_table(head))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/cmdline-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/cmdline-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.5/cmdline-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/cmdline-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/cmdline-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/cmdline-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/cmdline-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/cmdline-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:22.955061380 -0400
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/data-new-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-new-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.5/data-new-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-new-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep "kpatch: 5" /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/data-new.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-new.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/data-new.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-new.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,28 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:24.102066130 -0400
+@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m
+ {
+ }
+ 
++static int foo = 5;
++
+ static int meminfo_proc_show(struct seq_file *m, void *v)
+ {
+ 	struct sysinfo i;
+@@ -106,6 +108,7 @@ static int meminfo_proc_show(struct seq_
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ 		"AnonHugePages:  %8lu kB\n"
+ #endif
++		"kpatch: %d"
+ 		,
+ 		K(i.totalram),
+ 		K(i.freeram),
+@@ -167,6 +170,7 @@ static int meminfo_proc_show(struct seq_
+ 		,K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) *
+ 		   HPAGE_PMD_NR)
+ #endif
++		,foo
+ 		);
+ 
+ 	hugetlb_report_meminfo(m);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/data-read-mostly.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-read-mostly.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/data-read-mostly.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/data-read-mostly.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c
+--- src.orig/net/core/dev.c	2017-09-22 15:27:21.759056428 -0400
++++ src/net/core/dev.c	2017-09-22 15:27:25.244070859 -0400
+@@ -4012,6 +4012,7 @@ ncls:
+ 		case RX_HANDLER_PASS:
+ 			break;
+ 		default:
++			printk("BUG!\n");
+ 			BUG();
+ 		}
+ 	}
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/fixup-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/fixup-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/fixup-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff --git a/fs/readdir.c b/fs/readdir.c
+index febd02dfbe2d..064db7bd70d0 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+ 			goto efault;
+ 	}
+ 	dirent = buf->current_dir;
++	asm("nop");
+ 	if (__put_user(d_ino, &dirent->d_ino))
+ 		goto efault;
+ 	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-constprop.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-constprop.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-constprop.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-constprop.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c
+--- src.orig/kernel/time/timekeeping.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/time/timekeeping.c	2017-09-22 15:27:27.522080292 -0400
+@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv)
+ {
+ 	struct timespec64 now;
+ 
++	if (!tv)
++		return;
++
+ 	getnstimeofday64(&now);
+ 	tv->tv_sec = now.tv_sec;
+ 	tv->tv_usec = now.tv_nsec/1000;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-isra.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-isra.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-isra.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-isra.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c
+--- src.orig/fs/proc/proc_sysctl.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/proc_sysctl.c	2017-09-22 15:27:28.670085046 -0400
+@@ -24,6 +24,7 @@ void proc_sys_poll_notify(struct ctl_tab
+ 	if (!poll)
+ 		return;
+ 
++	printk("kpatch-test: testing gcc .isra function name mangling\n");
+ 	atomic_inc(&poll->event);
+ 	wake_up_interruptible(&poll->wait);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-mangled-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/mm/slub.c src/mm/slub.c
+--- src.orig/mm/slub.c	2017-09-22 15:27:21.618055844 -0400
++++ src/mm/slub.c	2017-09-22 15:27:29.830089850 -0400
+@@ -5528,6 +5528,9 @@ void get_slabinfo(struct kmem_cache *s,
+ 	unsigned long nr_free = 0;
+ 	int node;
+ 
++	if (!jiffies)
++		printk("slabinfo\n");
++
+ 	for_each_online_node(node) {
+ 		struct kmem_cache_node *n = get_node(s, node);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c
+--- src.orig/mm/mmap.c	2017-09-22 15:27:21.618055844 -0400
++++ src/mm/mmap.c	2017-09-22 15:27:31.024094794 -0400
+@@ -1687,6 +1688,9 @@ unsigned long mmap_region(struct file *f
+ 	struct rb_node **rb_link, *rb_parent;
+ 	unsigned long charged = 0;
+ 
++	if (!jiffies)
++		printk("kpatch mmap foo\n");
++
+ 	/* Check against address space limit. */
+ 	if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
+ 		unsigned long nr_pages;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,19 @@
+diff -Nupr src.orig/kernel/sys.c src/kernel/sys.c
+--- src.orig/kernel/sys.c	2017-09-22 15:27:21.601055773 -0400
++++ src/kernel/sys.c	2017-09-22 15:27:32.170099540 -0400
+@@ -554,8 +554,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
+ 	return ret;
+ }
+ 
++void kpatch_bar(void)
++{
++	if (!jiffies)
++		printk("kpatch_foo\n");
++}
++
+ static void deferred_cad(struct work_struct *dummy)
+ {
++	kpatch_bar();
+ 	kernel_restart(NULL);
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-4.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-4.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-4.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-4.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+diff -Nupr src.orig/fs/aio.c src/fs/aio.c
+--- src.orig/fs/aio.c	2017-09-22 15:27:21.702056192 -0400
++++ src/fs/aio.c	2017-09-22 15:27:33.299104215 -0400
+@@ -219,9 +219,16 @@ static int __init aio_setup(void)
+ }
+ __initcall(aio_setup);
+ 
++void kpatch_aio_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch aio foo\n");
++}
++
+ static void put_aio_ring_file(struct kioctx *ctx)
+ {
+ 	struct file *aio_ring_file = ctx->aio_ring_file;
++	kpatch_aio_foo();
+ 	if (aio_ring_file) {
+ 		truncate_setsize(aio_ring_file->f_inode, 0);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+	exit 1
+else
+	exit 0
+fi
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-5.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-5.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-5.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-5.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,45 @@
+diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c
+--- src.orig/kernel/audit.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/audit.c	2017-09-22 15:27:34.429108894 -0400
+@@ -205,6 +205,12 @@ void audit_panic(const char *message)
+ 	}
+ }
+ 
++void kpatch_audit_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch audit foo\n");
++}
++
+ static inline int audit_rate_check(void)
+ {
+ 	static unsigned long	last_check = 0;
+@@ -215,6 +221,7 @@ static inline int audit_rate_check(void)
+ 	unsigned long		elapsed;
+ 	int			retval	   = 0;
+ 
++	kpatch_audit_foo();
+ 	if (!audit_rate_limit) return 1;
+ 
+ 	spin_lock_irqsave(&lock, flags);
+@@ -234,6 +241,11 @@ static inline int audit_rate_check(void)
+ 	return retval;
+ }
+ 
++noinline void kpatch_audit_check(void)
++{
++	audit_rate_check();
++}
++
+ /**
+  * audit_log_lost - conditionally log lost audit message event
+  * @message: the message stating reason for lost audit message
+@@ -282,6 +294,8 @@ static int audit_log_config_change(char
+ 	struct audit_buffer *ab;
+ 	int rc = 0;
+ 
++	kpatch_audit_check();
++
+ 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ 	if (unlikely(!ab))
+ 		return rc;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-6.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-6.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var-6.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var-6.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index a9d587a..23336ed 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb,
+	return 0;
+ }
+
++#include "kpatch-macros.h"
++
+ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+			struct flowi *fl, bool strict)
+ {
+@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+	struct dst_entry *result;
+	int err;
+
++	if (!jiffies)
++		printk("kpatch nf_ip6_route foo\n");
++
+	result = ip6_route_output(net, sk, &fl->u.ip6);
+	err = result->error;
+	if (err)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/gcc-static-local-var.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/gcc-static-local-var.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,25 @@
+diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c
+--- src.orig/arch/x86/kernel/ldt.c	2017-09-22 15:27:20.847052651 -0400
++++ src/arch/x86/kernel/ldt.c	2017-09-22 15:27:35.573113632 -0400
+@@ -98,6 +98,12 @@ static inline int copy_ldt(mm_context_t
+ 	return 0;
+ }
+ 
++void hi_there(void)
++{
++	if (!jiffies)
++		printk("hi there\n");
++}
++
+ /*
+  * we do not have to muck with descriptors here, that is
+  * done in switch_mm() as needed.
+@@ -107,6 +113,8 @@ int init_new_context(struct task_struct
+ 	struct mm_struct *old_mm;
+ 	int retval = 0;
+ 
++	hi_there();
++
+ 	mutex_init(&mm->context.lock);
+ 	mm->context.size = 0;
+ 	old_mm = current->mm;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/macro-callbacks.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/macro-callbacks.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/macro-callbacks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/macro-callbacks.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,160 @@
+kpatch/livepatch callback test patch:
+
+  vmlinux
+  pcspkr (mod)
+  joydev (mod)
+
+Note: update joydev's pre-patch callback to return -ENODEV to test failure path
+
+--- src.old/fs/aio.c	2018-02-26 11:07:51.522610407 -0500
++++ src/fs/aio.c	2018-03-05 11:17:21.560015449 -0500
+@@ -42,6 +42,50 @@
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
++
+ #define AIO_RING_MAGIC			0xa10a10a1
+ #define AIO_RING_COMPAT_FEATURES	1
+ #define AIO_RING_INCOMPAT_FEATURES	0
+--- src.old/drivers/input/joydev.c	2018-02-26 11:07:49.470610407 -0500
++++ src/drivers/input/joydev.c	2018-03-05 11:18:13.998015449 -0500
+@@ -954,3 +954,47 @@ static void __exit joydev_exit(void)
+ 
+ module_init(joydev_init);
+ module_exit(joydev_exit);
++
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0; /* return -ENODEV; */
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+--- src.old/drivers/input/misc/pcspkr.c	2018-02-26 11:07:49.477610407 -0500
++++ src/drivers/input/misc/pcspkr.c	2018-03-05 11:18:23.411015449 -0500
+@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla
+ };
+ module_platform_driver(pcspkr_platform_driver);
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/macro-printk.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/macro-printk.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/macro-printk.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,147 @@
+diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c
+--- src.orig/net/ipv4/fib_frontend.c	2017-09-22 16:52:10.646110299 -0400
++++ src/net/ipv4/fib_frontend.c	2017-09-22 16:55:14.395870305 -0400
+@@ -633,6 +633,7 @@ errout:
+ 	return err;
+ }
+ 
++#include "kpatch-macros.h"
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	struct net *net = sock_net(skb->sk);
+@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b
+ 	}
+ 
+ 	err = fib_table_insert(net, tb, &cfg);
++	KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err);
+ errout:
+ 	return err;
+ }
+diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c
+--- src.orig/net/ipv4/fib_semantics.c	2017-09-22 16:52:10.645110295 -0400
++++ src/net/ipv4/fib_semantics.c	2017-09-22 16:54:05.175584004 -0400
+@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi,
+ 	return 0;
+ }
+ 
++#include "kpatch-macros.h"
+ struct fib_info *fib_create_info(struct fib_config *cfg)
+ {
+ 	int err;
+@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct
+ #endif
+ 
+ 	err = -ENOBUFS;
++	KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err);
+ 	if (fib_info_cnt >= fib_info_hash_size) {
+ 		unsigned int new_size = fib_info_hash_size << 1;
+ 		struct hlist_head *new_info_hash;
+@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct
+ 		if (!fib_info_hash_size)
+ 			goto failure;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err);
+ 
+ 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ 	if (fi == NULL)
+@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct
+ 	} else
+ 		fi->fib_metrics = (u32 *) dst_default_metrics;
+ 	fib_info_cnt++;
++	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
+ 
+ 	fi->fib_net = net;
+ 	fi->fib_protocol = cfg->fc_protocol;
+@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct
+ 		if (!nexthop_nh->nh_pcpu_rth_output)
+ 			goto failure;
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err);
+ 
+ 	err = fib_convert_metrics(fi, cfg);
++	KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err);
+ 	if (err)
+ 		goto failure;
+ 
+@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct
+ 		nh->nh_weight = 1;
+ #endif
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err);
+ 
+ 	if (fib_props[cfg->fc_type].error) {
+ 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
+@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct
+ 			goto err_inval;
+ 		}
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err);
+ 
+ 	if (cfg->fc_scope > RT_SCOPE_HOST)
+ 		goto err_inval;
+@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct
+ 				goto failure;
+ 		} endfor_nexthops(fi)
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err);
+ 
+ 	if (fi->fib_prefsrc) {
+ 		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct
+ 		fib_info_update_nh_saddr(net, nexthop_nh);
+ 		fib_add_weight(fi, nexthop_nh);
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err);
+ 
+ 	fib_rebalance(fi);
+ 
+@@ -1110,6 +1120,7 @@ link_it:
+ 		ofi->fib_treeref++;
+ 		return ofi;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err);
+ 
+ 	fi->fib_treeref++;
+ 	atomic_inc(&fi->fib_clntref);
+@@ -1133,6 +1144,7 @@ link_it:
+ 		hlist_add_head(&nexthop_nh->nh_hash, head);
+ 	} endfor_nexthops(fi)
+ 	spin_unlock_bh(&fib_info_lock);
++	KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err);
+ 	return fi;
+ 
+ err_inval:
+@@ -1143,6 +1155,7 @@ failure:
+ 		fi->fib_dead = 1;
+ 		free_fib_info(fi);
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err);
+ 
+ 	return ERR_PTR(err);
+ }
+diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c
+--- src.orig/net/ipv4/fib_trie.c	2017-09-22 16:52:10.645110295 -0400
++++ src/net/ipv4/fib_trie.c	2017-09-22 16:55:39.940975963 -0400
+@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie
+ }
+ 
+ /* Caller must hold RTNL. */
++#include "kpatch-macros.h"
+ int fib_table_insert(struct net *net, struct fib_table *tb,
+ 		     struct fib_config *cfg)
+ {
+@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st
+ 	if ((plen < KEYLENGTH) && (key << plen))
+ 		return -EINVAL;
+ 
++	KPATCH_PRINTK("[fib_table_insert]: start\n");
+ 	fi = fib_create_info(cfg);
+ 	if (IS_ERR(fi)) {
+ 		err = PTR_ERR(fi);
++		KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err);
+ 		goto err;
+ 	}
++	KPATCH_PRINTK("[fib_table_insert]: cross\n");
+ 
+ 	l = fib_find_node(t, &tp, key);
+ 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/meminfo-init2-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-init2-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/meminfo-init2-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-init2-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,19 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:38.972127707 -0400
+@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_
+ 	unsigned long pages[NR_LRU_LISTS];
+ 	int lru;
+ 
++	printk("a\n");
+ /*
+  * display in kilobytes.
+  */
+@@ -191,6 +192,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/meminfo-init-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-init-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/meminfo-init-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-init-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:40.130132502 -0400
+@@ -191,6 +191,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/meminfo-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.5/meminfo-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/meminfo-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/meminfo-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/meminfo-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:41.274137239 -0400
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/module-call-external.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-call-external.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/module-call-external.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-call-external.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,33 @@
+diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c
+--- src.orig/fs/nfsd/export.c	2017-09-22 15:27:21.705056204 -0400
++++ src/fs/nfsd/export.c	2017-09-22 15:27:42.411141948 -0400
+@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m
+ 	}
+ }
+ 
++extern char *kpatch_string(void);
++
+ static int e_show(struct seq_file *m, void *p)
+ {
+ 	struct cache_head *cp = p;
+@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo
+ 	if (p == SEQ_START_TOKEN) {
+ 		seq_puts(m, "# Version 1.1\n");
+ 		seq_puts(m, "# Path Client(Flags) # IPs\n");
++		seq_puts(m, kpatch_string());
+ 		return 0;
+ 	}
+ 
+diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
+--- src.orig/net/netlink/af_netlink.c	2017-09-22 15:27:21.754056407 -0400
++++ src/net/netlink/af_netlink.c	2017-09-22 15:27:42.412141952 -0400
+@@ -3260,4 +3260,9 @@ panic:
+ 	panic("netlink_init: Cannot allocate nl_table\n");
+ }
+ 
++char *kpatch_string(void)
++{
++	return "# kpatch\n";
++}
++
+ core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/module-kvm-fixup.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-kvm-fixup.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/module-kvm-fixup.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-kvm-fixup.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
+--- src.orig/arch/x86/kvm/vmx.c	2017-09-22 15:27:20.853052676 -0400
++++ src/arch/x86/kvm/vmx.c	2017-09-22 15:27:43.583146801 -0400
+@@ -10597,6 +10597,8 @@ static int vmx_check_intercept(struct kv
+ 			       struct x86_instruction_info *info,
+ 			       enum x86_intercept_stage stage)
+ {
++	if (!jiffies)
++		printk("kpatch vmx_check_intercept\n");
+ 	return X86EMUL_CONTINUE;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/module-shadow.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-shadow.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/module-shadow.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/module-shadow.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,25 @@
+Index: src/arch/x86/kvm/vmx.c
+===================================================================
+--- src.orig/arch/x86/kvm/vmx.c
++++ src/arch/x86/kvm/vmx.c
+@@ -11168,10 +11168,20 @@ static void vmx_leave_nested(struct kvm_
+  * It should only be called before L2 actually succeeded to run, and when
+  * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
+  */
++#include <linux/livepatch.h>
+ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ 			struct vmcs12 *vmcs12,
+ 			u32 reason, unsigned long qualification)
+ {
++	int *kpatch;
++
++	kpatch = klp_shadow_alloc(vcpu, 0, NULL, sizeof(*kpatch),
++				     GFP_KERNEL);
++	if (kpatch) {
++		klp_shadow_get(vcpu, 0);
++		klp_shadow_free(vcpu, 0);
++	}
++
+ 	load_vmcs12_host_state(vcpu, vmcs12);
+ 	vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
+ 	vmcs12->exit_qualification = qualification;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/multiple.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/multiple.test
--- 0.6.0-0.2/test/integration/rhel-7.5/multiple.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
+ROOTDIR="$(readlink -f $SCRIPTDIR/../..)"
+KPATCH="sudo $ROOTDIR/kpatch/kpatch"
+
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
+set -o errexit
+
+die() {
+	echo "ERROR: $@" >&2
+	exit 1
+}
+
+ko_to_test() {
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
+}
+
+# make sure any modules added here are disjoint
+declare -a modules
+declare -a blacklist=(meminfo-string-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules"
+done
+
+for mod in "${modules[@]}"; do
+	$KPATCH load $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules"
+done
+
+for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do
+	mod=${modules[idx]}
+	$KPATCH unload $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules"
+done
+
+exit 0
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/new-function.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/new-function.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/new-function.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/new-function.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,25 @@
+diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c
+--- src.orig/drivers/tty/n_tty.c	2017-09-22 15:27:21.084053633 -0400
++++ src/drivers/tty/n_tty.c	2017-09-22 15:27:45.888156346 -0400
+@@ -2016,7 +2016,7 @@ do_it_again:
+  *		  lock themselves)
+  */
+ 
+-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file,
+ 			   const unsigned char *buf, size_t nr)
+ {
+ 	const unsigned char *b = buf;
+@@ -2098,6 +2098,12 @@ break_out:
+ 	return (b - buf) ? b - buf : retval;
+ }
+ 
++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file,
++			   const unsigned char *buf, size_t nr)
++{
++	return kpatch_n_tty_write(tty, file, buf, nr);
++}
++
+ /**
+  *	n_tty_poll		-	poll method for N_TTY
+  *	@tty: terminal device
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/new-globals.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/new-globals.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/new-globals.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/new-globals.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,34 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:47.028161067 -0400
+@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void
+ 	return 0;
+ }
+ module_init(proc_cmdline_init);
++
++#include <linux/printk.h>
++void kpatch_print_message(void)
++{
++	if (!jiffies)
++		printk("hello there!\n");
++}
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:47.029161071 -0400
+@@ -16,6 +16,8 @@
+ #include <asm/pgtable.h>
+ #include "internal.h"
+ 
++void kpatch_print_message(void);
++
+ void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
+ {
+ }
+@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_
+ 	/*
+ 	 * Tagged format, for easy grepping and expansion.
+ 	 */
++	kpatch_print_message();
+ 	seq_printf(m,
+ 		"MemTotal:       %8lu kB\n"
+ 		"MemFree:        %8lu kB\n"
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/parainstructions-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/parainstructions-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/parainstructions-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/parainstructions-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c
+--- src.orig/fs/proc/generic.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/generic.c	2017-09-22 15:27:48.190165879 -0400
+@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum)
+ 	unsigned int i;
+ 	int error;
+ 
++	printk("kpatch-test: testing change to .parainstructions section\n");
+ retry:
+ 	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+ 		return -ENOMEM;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/replace-section-references.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/replace-section-references.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/replace-section-references.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/replace-section-references.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:49.362170732 -0400
+@@ -248,6 +248,8 @@ static void shared_msr_update(unsigned s
+ 
+ void kvm_define_shared_msr(unsigned slot, u32 msr)
+ {
++	if (!jiffies)
++		printk("kpatch kvm define shared msr\n");
+ 	BUG_ON(slot >= KVM_NR_SHARED_MSRS);
+ 	shared_msrs_global.msrs[slot] = msr;
+ 	if (slot >= shared_msrs_global.nr)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/shadow-newpid-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.5/shadow-newpid-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.5/shadow-newpid-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/shadow-newpid-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep -q newpid: /proc/$$/status
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/shadow-newpid.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,72 @@
+Index: src/fs/proc/array.c
+===================================================================
+--- src.orig/fs/proc/array.c
++++ src/fs/proc/array.c
+@@ -394,13 +394,20 @@ static inline void task_seccomp(struct s
+ 	seq_putc(m, '\n');
+ }
+ 
++#include <linux/livepatch.h>
+ static inline void task_context_switch_counts(struct seq_file *m,
+ 						struct task_struct *p)
+ {
++	int *newpid;
++
+ 	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
+ 			"nonvoluntary_ctxt_switches:\t%lu\n",
+ 			p->nvcsw,
+ 			p->nivcsw);
++
++	newpid = klp_shadow_get(p, 0);
++	if (newpid)
++		seq_printf(m, "newpid:\t%d\n", *newpid);
+ }
+ 
+ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
+Index: src/kernel/exit.c
+===================================================================
+--- src.orig/kernel/exit.c
++++ src/kernel/exit.c
+@@ -715,6 +715,7 @@ static void check_stack_usage(void)
+ static inline void check_stack_usage(void) {}
+ #endif
+ 
++#include <linux/livepatch.h>
+ void do_exit(long code)
+ {
+ 	struct task_struct *tsk = current;
+@@ -812,6 +813,8 @@ void do_exit(long code)
+ 	check_stack_usage();
+ 	exit_thread();
+ 
++	klp_shadow_free(tsk, 0);
++
+ 	/*
+ 	 * Flush inherited counters to the parent - before the parent
+ 	 * gets woken up by child-exit notifications.
+Index: src/kernel/fork.c
+===================================================================
+--- src.orig/kernel/fork.c
++++ src/kernel/fork.c
+@@ -1751,6 +1751,7 @@ struct task_struct *fork_idle(int cpu)
+  * It copies the process, and if successful kick-starts
+  * it and waits for it to finish using the VM if required.
+  */
++#include <linux/livepatch.h>
+ long do_fork(unsigned long clone_flags,
+ 	      unsigned long stack_start,
+ 	      unsigned long stack_size,
+@@ -1788,6 +1789,13 @@ long do_fork(unsigned long clone_flags,
+ 	if (!IS_ERR(p)) {
+ 		struct completion vfork;
+ 		struct pid *pid;
++		int *newpid;
++		static int ctr = 0;
++
++		newpid = klp_shadow_get_or_alloc(p, 0, NULL, sizeof(*newpid),
++					     GFP_KERNEL);
++		if (newpid)
++			*newpid = ctr++;
+ 
+ 		trace_sched_process_fork(current, p);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/smp-locks-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/smp-locks-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/smp-locks-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/smp-locks-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c
+--- src.orig/drivers/tty/tty_buffer.c	2017-09-22 15:27:21.077053604 -0400
++++ src/drivers/tty/tty_buffer.c	2017-09-22 15:27:50.542175618 -0400
+@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p
+ 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ 	   remove this conditional if its worth it. This would be invisible
+ 	   to the callers */
++
++	if (!size)
++		printk("kpatch-test: testing .smp_locks section changes\n");
++
+ 	b = buf->tail;
+ 	if (b != NULL)
+ 		left = b->size - b->used;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/special-static-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/special-static-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/special-static-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/special-static-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,24 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:51.744180596 -0400
+@@ -2093,12 +2093,20 @@ static void record_steal_time(struct kvm
+ 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+ }
+ 
++void kpatch_kvm_x86_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch kvm x86 foo\n");
++}
++
+ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ {
+ 	bool pr = false;
+ 	u32 msr = msr_info->index;
+ 	u64 data = msr_info->data;
+ 
++	kpatch_kvm_x86_foo();
++
+ 	switch (msr) {
+ 	case MSR_AMD64_NB_CFG:
+ 	case MSR_IA32_UCODE_REV:
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/special-static.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/special-static.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/special-static.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/special-static.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,22 @@
+diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
+--- src.orig/kernel/fork.c	2017-09-22 15:27:21.600055769 -0400
++++ src/kernel/fork.c	2017-09-22 15:27:53.052186012 -0400
+@@ -1129,10 +1129,18 @@ static void posix_cpu_timers_init_group(
+ 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+ }
+ 
++void kpatch_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch copy signal\n");
++}
++
+ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ 	struct signal_struct *sig;
+ 
++	kpatch_foo();
++
+ 	if (clone_flags & CLONE_THREAD)
+ 		return 0;
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/tracepoints-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/tracepoints-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/tracepoints-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/tracepoints-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/timer.c src/kernel/timer.c
+--- src.orig/kernel/timer.c	2017-09-22 15:27:21.600055769 -0400
++++ src/kernel/timer.c	2017-09-22 15:27:54.288191131 -0400
+@@ -1390,6 +1390,9 @@ static void run_timer_softirq(struct sof
+ {
+ 	struct tvec_base *base = __this_cpu_read(tvec_bases);
+ 
++	if (!base)
++		printk("kpatch-test: testing __tracepoints section changes\n");
++
+ 	if (time_after_eq(jiffies, base->timer_jiffies))
+ 		__run_timers(base);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.5/warn-detect-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.5/warn-detect-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.5/warn-detect-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.5/warn-detect-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,8 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:55.489196104 -0400
+@@ -1,3 +1,4 @@
++
+ /*
+  * Kernel-based Virtual Machine driver for Linux
+  *
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/bug-table-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/bug-table-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/bug-table-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/bug-table-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+Index: kernel-rhel7/fs/proc/proc_sysctl.c
+===================================================================
+--- kernel-rhel7.orig/fs/proc/proc_sysctl.c
++++ kernel-rhel7/fs/proc/proc_sysctl.c
+@@ -301,6 +301,8 @@ void sysctl_head_put(struct ctl_table_he
+ 
+ static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
+ {
++	if (jiffies == 0)
++		printk("kpatch-test: testing __bug_table section changes\n");
+ 	BUG_ON(!head);
+ 	spin_lock(&sysctl_lock);
+ 	if (!use_table(head))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/cmdline-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/cmdline-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.6/cmdline-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/cmdline-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/cmdline-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/cmdline-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/cmdline-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/cmdline-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:22.955061380 -0400
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/data-new-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-new-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.6/data-new-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-new-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep "kpatch: 5" /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/data-new.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-new.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/data-new.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-new.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,29 @@
+Index: kernel-rhel7/fs/proc/meminfo.c
+===================================================================
+--- kernel-rhel7.orig/fs/proc/meminfo.c
++++ kernel-rhel7/fs/proc/meminfo.c
+@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m
+ {
+ }
+ 
++static int foo = 5;
++
+ static int meminfo_proc_show(struct seq_file *m, void *v)
+ {
+ 	struct sysinfo i;
+@@ -110,6 +112,7 @@ static int meminfo_proc_show(struct seq_
+ 		"CmaTotal:       %8lu kB\n"
+ 		"CmaFree:        %8lu kB\n"
+ #endif
++		"kpatch: %d"
+ 		,
+ 		K(i.totalram),
+ 		K(i.freeram),
+@@ -175,6 +178,7 @@ static int meminfo_proc_show(struct seq_
+ 		, K(totalcma_pages)
+ 		, K(global_page_state(NR_FREE_CMA_PAGES))
+ #endif
++		,foo
+ 		);
+ 
+ 	hugetlb_report_meminfo(m);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/data-read-mostly.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-read-mostly.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/data-read-mostly.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/data-read-mostly.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel-rhel7/net/core/dev.c
+===================================================================
+--- kernel-rhel7.orig/net/core/dev.c
++++ kernel-rhel7/net/core/dev.c
+@@ -4199,6 +4199,7 @@ skip_classify:
+ 		case RX_HANDLER_PASS:
+ 			break;
+ 		default:
++			printk("BUG!\n");
+ 			BUG();
+ 		}
+ 	}
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/fixup-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/fixup-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/fixup-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff --git a/fs/readdir.c b/fs/readdir.c
+index febd02dfbe2d..064db7bd70d0 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+ 			goto efault;
+ 	}
+ 	dirent = buf->current_dir;
++	asm("nop");
+ 	if (__put_user(d_ino, &dirent->d_ino))
+ 		goto efault;
+ 	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-constprop.patch.disabled 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-constprop.patch.disabled
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-constprop.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-constprop.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c
+--- src.orig/kernel/time/timekeeping.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/time/timekeeping.c	2017-09-22 15:27:27.522080292 -0400
+@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv)
+ {
+ 	struct timespec64 now;
+ 
++	if (!tv)
++		return;
++
+ 	getnstimeofday64(&now);
+ 	tv->tv_sec = now.tv_sec;
+ 	tv->tv_usec = now.tv_nsec/1000;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-isra.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-isra.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-isra.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-isra.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel-rhel7/fs/proc/proc_sysctl.c
+===================================================================
+--- kernel-rhel7.orig/fs/proc/proc_sysctl.c
++++ kernel-rhel7/fs/proc/proc_sysctl.c
+@@ -46,6 +46,7 @@ void proc_sys_poll_notify(struct ctl_tab
+ 	if (!poll)
+ 		return;
+ 
++	printk("kpatch-test: testing gcc .isra function name mangling\n");
+ 	atomic_inc(&poll->event);
+ 	wake_up_interruptible(&poll->wait);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-mangled-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel-rhel7/mm/slub.c
+===================================================================
+--- kernel-rhel7.orig/mm/slub.c
++++ kernel-rhel7/mm/slub.c
+@@ -5611,6 +5611,9 @@ void get_slabinfo(struct kmem_cache *s,
+ 	unsigned long nr_free = 0;
+ 	int node;
+ 
++	if (!jiffies)
++		printk("slabinfo\n");
++
+ 	for_each_online_node(node) {
+ 		struct kmem_cache_node *n = get_node(s, node);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel-rhel7/mm/mmap.c
+===================================================================
+--- kernel-rhel7.orig/mm/mmap.c
++++ kernel-rhel7/mm/mmap.c
+@@ -1715,6 +1715,9 @@ unsigned long mmap_region(struct file *f
+ 	struct rb_node **rb_link, *rb_parent;
+ 	unsigned long charged = 0;
+ 
++	if (!jiffies)
++		printk("kpatch mmap foo\n");
++
+ 	/* Check against address space limit. */
+ 	if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
+ 		unsigned long nr_pages;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+Index: kernel-rhel7/kernel/sys.c
+===================================================================
+--- kernel-rhel7.orig/kernel/sys.c
++++ kernel-rhel7/kernel/sys.c
+@@ -559,8 +559,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
+ 	return ret;
+ }
+ 
++void kpatch_bar(void)
++{
++	if (!jiffies)
++		printk("kpatch_foo\n");
++}
++
+ static void deferred_cad(struct work_struct *dummy)
+ {
++	kpatch_bar();
+ 	kernel_restart(NULL);
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-4.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-4.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-4.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-4.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,21 @@
+Index: kernel-rhel7/fs/aio.c
+===================================================================
+--- kernel-rhel7.orig/fs/aio.c
++++ kernel-rhel7/fs/aio.c
+@@ -223,9 +223,16 @@ static int __init aio_setup(void)
+ }
+ __initcall(aio_setup);
+ 
++void kpatch_aio_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch aio foo\n");
++}
++
+ static void put_aio_ring_file(struct kioctx *ctx)
+ {
+ 	struct file *aio_ring_file = ctx->aio_ring_file;
++	kpatch_aio_foo();
+ 	if (aio_ring_file) {
+ 		truncate_setsize(aio_ring_file->f_inode, 0);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+	exit 1
+else
+	exit 0
+fi
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-5.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-5.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-5.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-5.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,45 @@
+diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c
+--- src.orig/kernel/audit.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/audit.c	2017-09-22 15:27:34.429108894 -0400
+@@ -205,6 +205,12 @@ void audit_panic(const char *message)
+ 	}
+ }
+ 
++void kpatch_audit_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch audit foo\n");
++}
++
+ static inline int audit_rate_check(void)
+ {
+ 	static unsigned long	last_check = 0;
+@@ -215,6 +221,7 @@ static inline int audit_rate_check(void)
+ 	unsigned long		elapsed;
+ 	int			retval	   = 0;
+ 
++	kpatch_audit_foo();
+ 	if (!audit_rate_limit) return 1;
+ 
+ 	spin_lock_irqsave(&lock, flags);
+@@ -234,6 +241,11 @@ static inline int audit_rate_check(void)
+ 	return retval;
+ }
+ 
++noinline void kpatch_audit_check(void)
++{
++	audit_rate_check();
++}
++
+ /**
+  * audit_log_lost - conditionally log lost audit message event
+  * @message: the message stating reason for lost audit message
+@@ -282,6 +294,8 @@ static int audit_log_config_change(char
+ 	struct audit_buffer *ab;
+ 	int rc = 0;
+ 
++	kpatch_audit_check();
++
+ 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ 	if (unlikely(!ab))
+ 		return rc;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-6.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-6.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/gcc-static-local-var-6.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/gcc-static-local-var-6.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index a9d587a..23336ed 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb,
+	return 0;
+ }
+
++#include "kpatch-macros.h"
++
+ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+			struct flowi *fl, bool strict)
+ {
+@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+	struct dst_entry *result;
+	int err;
+
++	if (!jiffies)
++		printk("kpatch nf_ip6_route foo\n");
++
+	result = ip6_route_output(net, sk, &fl->u.ip6);
+	err = result->error;
+	if (err)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/macro-callbacks.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/macro-callbacks.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/macro-callbacks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/macro-callbacks.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,160 @@
+kpatch/livepatch callback test patch:
+
+  vmlinux
+  pcspkr (mod)
+  joydev (mod)
+
+Note: update joydev's pre-patch callback to return -ENODEV to test failure path
+
+--- src.old/fs/aio.c	2018-02-26 11:07:51.522610407 -0500
++++ src/fs/aio.c	2018-03-05 11:17:21.560015449 -0500
+@@ -42,6 +42,50 @@
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
++
+ #define AIO_RING_MAGIC			0xa10a10a1
+ #define AIO_RING_COMPAT_FEATURES	1
+ #define AIO_RING_INCOMPAT_FEATURES	0
+--- src.old/drivers/input/joydev.c	2018-02-26 11:07:49.470610407 -0500
++++ src/drivers/input/joydev.c	2018-03-05 11:18:13.998015449 -0500
+@@ -954,3 +954,47 @@ static void __exit joydev_exit(void)
+ 
+ module_init(joydev_init);
+ module_exit(joydev_exit);
++
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0; /* return -ENODEV; */
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+--- src.old/drivers/input/misc/pcspkr.c	2018-02-26 11:07:49.477610407 -0500
++++ src/drivers/input/misc/pcspkr.c	2018-03-05 11:18:23.411015449 -0500
+@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla
+ };
+ module_platform_driver(pcspkr_platform_driver);
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/macro-printk.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/macro-printk.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/macro-printk.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,151 @@
+Index: kernel-rhel7/net/ipv4/fib_frontend.c
+===================================================================
+--- kernel-rhel7.orig/net/ipv4/fib_frontend.c
++++ kernel-rhel7/net/ipv4/fib_frontend.c
+@@ -685,6 +685,7 @@ errout:
+ 	return err;
+ }
+ 
++#include "kpatch-macros.h"
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	struct net *net = sock_net(skb->sk);
+@@ -703,6 +704,7 @@ static int inet_rtm_newroute(struct sk_b
+ 	}
+ 
+ 	err = fib_table_insert(net, tb, &cfg);
++	KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err);
+ errout:
+ 	return err;
+ }
+Index: kernel-rhel7/net/ipv4/fib_semantics.c
+===================================================================
+--- kernel-rhel7.orig/net/ipv4/fib_semantics.c
++++ kernel-rhel7/net/ipv4/fib_semantics.c
+@@ -969,6 +969,7 @@ fib_convert_metrics(struct fib_info *fi,
+ 	return 0;
+ }
+ 
++#include "kpatch-macros.h"
+ struct fib_info *fib_create_info(struct fib_config *cfg)
+ {
+ 	int err;
+@@ -993,6 +994,7 @@ struct fib_info *fib_create_info(struct
+ #endif
+ 
+ 	err = -ENOBUFS;
++	KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err);
+ 	if (fib_info_cnt >= fib_info_hash_size) {
+ 		unsigned int new_size = fib_info_hash_size << 1;
+ 		struct hlist_head *new_info_hash;
+@@ -1013,6 +1015,7 @@ struct fib_info *fib_create_info(struct
+ 		if (!fib_info_hash_size)
+ 			goto failure;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err);
+ 
+ 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ 	if (fi == NULL)
+@@ -1028,6 +1031,8 @@ struct fib_info *fib_create_info(struct
+ 		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
+ 	}
+ 	fib_info_cnt++;
++	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
++
+ 	fi->fib_net = net;
+ 	fi->fib_protocol = cfg->fc_protocol;
+ 	fi->fib_scope = cfg->fc_scope;
+@@ -1043,8 +1048,10 @@ struct fib_info *fib_create_info(struct
+ 		if (!nexthop_nh->nh_pcpu_rth_output)
+ 			goto failure;
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err);
+ 
+ 	err = fib_convert_metrics(fi, cfg);
++	KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err);
+ 	if (err)
+ 		goto failure;
+ 
+@@ -1095,6 +1102,7 @@ struct fib_info *fib_create_info(struct
+ 		nh->nh_weight = 1;
+ #endif
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err);
+ 
+ 	if (fib_props[cfg->fc_type].error) {
+ 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
+@@ -1112,6 +1120,7 @@ struct fib_info *fib_create_info(struct
+ 			goto err_inval;
+ 		}
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err);
+ 
+ 	if (cfg->fc_scope > RT_SCOPE_HOST)
+ 		goto err_inval;
+@@ -1134,6 +1143,7 @@ struct fib_info *fib_create_info(struct
+ 				goto failure;
+ 		} endfor_nexthops(fi)
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err);
+ 
+ 	if (fi->fib_prefsrc) {
+ 		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+@@ -1146,6 +1156,7 @@ struct fib_info *fib_create_info(struct
+ 		fib_info_update_nh_saddr(net, nexthop_nh);
+ 		fib_add_weight(fi, nexthop_nh);
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err);
+ 
+ 	fib_rebalance(fi);
+ 
+@@ -1157,6 +1168,7 @@ link_it:
+ 		ofi->fib_treeref++;
+ 		return ofi;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err);
+ 
+ 	fi->fib_treeref++;
+ 	atomic_inc(&fi->fib_clntref);
+@@ -1180,6 +1192,7 @@ link_it:
+ 		hlist_add_head(&nexthop_nh->nh_hash, head);
+ 	} endfor_nexthops(fi)
+ 	spin_unlock_bh(&fib_info_lock);
++	KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err);
+ 	return fi;
+ 
+ err_inval:
+@@ -1190,6 +1203,7 @@ failure:
+ 		fi->fib_dead = 1;
+ 		free_fib_info(fi);
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err);
+ 
+ 	return ERR_PTR(err);
+ }
+Index: kernel-rhel7/net/ipv4/fib_trie.c
+===================================================================
+--- kernel-rhel7.orig/net/ipv4/fib_trie.c
++++ kernel-rhel7/net/ipv4/fib_trie.c
+@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie
+ }
+ 
+ /* Caller must hold RTNL. */
++#include "kpatch-macros.h"
+ int fib_table_insert(struct net *net, struct fib_table *tb,
+ 		     struct fib_config *cfg)
+ {
+@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st
+ 	if ((plen < KEYLENGTH) && (key << plen))
+ 		return -EINVAL;
+ 
++	KPATCH_PRINTK("[fib_table_insert]: start\n");
+ 	fi = fib_create_info(cfg);
+ 	if (IS_ERR(fi)) {
+ 		err = PTR_ERR(fi);
++		KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err);
+ 		goto err;
+ 	}
++	KPATCH_PRINTK("[fib_table_insert]: cross\n");
+ 
+ 	l = fib_find_node(t, &tp, key);
+ 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/meminfo-init2-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-init2-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/meminfo-init2-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-init2-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+Index: kernel-rhel7/fs/proc/meminfo.c
+===================================================================
+--- kernel-rhel7.orig/fs/proc/meminfo.c
++++ kernel-rhel7/fs/proc/meminfo.c
+@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_
+ 	unsigned long pages[NR_LRU_LISTS];
+ 	int lru;
+ 
++	printk("a\n");
+ /*
+  * display in kilobytes.
+  */
+@@ -199,6 +200,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/meminfo-init-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-init-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/meminfo-init-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-init-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel-rhel7/fs/proc/meminfo.c
+===================================================================
+--- kernel-rhel7.orig/fs/proc/meminfo.c
++++ kernel-rhel7/fs/proc/meminfo.c
+@@ -199,6 +199,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/meminfo-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.6/meminfo-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/meminfo-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/meminfo-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/meminfo-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:41.274137239 -0400
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/module-call-external.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/module-call-external.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/module-call-external.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/module-call-external.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,35 @@
+Index: kernel-rhel7/fs/nfsd/export.c
+===================================================================
+--- kernel-rhel7.orig/fs/nfsd/export.c
++++ kernel-rhel7/fs/nfsd/export.c
+@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m
+ 	}
+ }
+ 
++extern char *kpatch_string(void);
++
+ static int e_show(struct seq_file *m, void *p)
+ {
+ 	struct cache_head *cp = p;
+@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo
+ 	if (p == SEQ_START_TOKEN) {
+ 		seq_puts(m, "# Version 1.1\n");
+ 		seq_puts(m, "# Path Client(Flags) # IPs\n");
++		seq_puts(m, kpatch_string());
+ 		return 0;
+ 	}
+ 
+Index: kernel-rhel7/net/netlink/af_netlink.c
+===================================================================
+--- kernel-rhel7.orig/net/netlink/af_netlink.c
++++ kernel-rhel7/net/netlink/af_netlink.c
+@@ -2568,4 +2568,9 @@ panic:
+ 	panic("netlink_init: Cannot allocate nl_table\n");
+ }
+ 
++char *kpatch_string(void)
++{
++	return "# kpatch\n";
++}
++
+ core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/multiple.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/multiple.test
--- 0.6.0-0.2/test/integration/rhel-7.6/multiple.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
+ROOTDIR="$(readlink -f $SCRIPTDIR/../..)"
+KPATCH="sudo $ROOTDIR/kpatch/kpatch"
+
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
+set -o errexit
+
+die() {
+	echo "ERROR: $@" >&2
+	exit 1
+}
+
+ko_to_test() {
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
+}
+
+# make sure any modules added here are disjoint
+declare -a modules
+declare -a blacklist=(meminfo-string-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules"
+done
+
+for mod in "${modules[@]}"; do
+	$KPATCH load $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules"
+done
+
+for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do
+	mod=${modules[idx]}
+	$KPATCH unload $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules"
+done
+
+exit 0
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/new-function.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/new-function.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/new-function.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/new-function.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,26 @@
+Index: kernel-rhel7/drivers/tty/n_tty.c
+===================================================================
+--- kernel-rhel7.orig/drivers/tty/n_tty.c
++++ kernel-rhel7/drivers/tty/n_tty.c
+@@ -2128,7 +2128,7 @@ do_it_again:
+  *		  lock themselves)
+  */
+ 
+-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file,
+ 			   const unsigned char *buf, size_t nr)
+ {
+ 	const unsigned char *b = buf;
+@@ -2210,6 +2210,12 @@ break_out:
+ 	return (b - buf) ? b - buf : retval;
+ }
+ 
++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file,
++			   const unsigned char *buf, size_t nr)
++{
++	return kpatch_n_tty_write(tty, file, buf, nr);
++}
++
+ /**
+  *	n_tty_poll		-	poll method for N_TTY
+  *	@tty: terminal device
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/new-globals.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/new-globals.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/new-globals.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/new-globals.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,34 @@
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/cmdline.c	2017-09-22 15:27:47.028161067 -0400
+@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void
+ 	return 0;
+ }
+ module_init(proc_cmdline_init);
++
++#include <linux/printk.h>
++void kpatch_print_message(void)
++{
++	if (!jiffies)
++		printk("hello there!\n");
++}
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2017-09-22 15:27:21.699056179 -0400
++++ src/fs/proc/meminfo.c	2017-09-22 15:27:47.029161071 -0400
+@@ -16,6 +16,8 @@
+ #include <asm/pgtable.h>
+ #include "internal.h"
+ 
++void kpatch_print_message(void);
++
+ void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
+ {
+ }
+@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_
+ 	/*
+ 	 * Tagged format, for easy grepping and expansion.
+ 	 */
++	kpatch_print_message();
+ 	seq_printf(m,
+ 		"MemTotal:       %8lu kB\n"
+ 		"MemFree:        %8lu kB\n"
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/parainstructions-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/parainstructions-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/parainstructions-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/parainstructions-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,11 @@
+diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c
+--- src.orig/fs/proc/generic.c	2017-09-22 15:27:21.698056175 -0400
++++ src/fs/proc/generic.c	2017-09-22 15:27:48.190165879 -0400
+@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum)
+ 	unsigned int i;
+ 	int error;
+ 
++	printk("kpatch-test: testing change to .parainstructions section\n");
+ retry:
+ 	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+ 		return -ENOMEM;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/shadow-newpid-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.6/shadow-newpid-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.6/shadow-newpid-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/shadow-newpid-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep -q newpid: /proc/$$/status
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/shadow-newpid.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,72 @@
+diff --git a/fs/proc/array.c b/fs/proc/array.c
+index 39684c79e8e2..138b60d1314d 100644
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -394,13 +394,20 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
+ 	seq_putc(m, '\n');
+ }
+ 
++#include <linux/livepatch.h>
+ static inline void task_context_switch_counts(struct seq_file *m,
+ 						struct task_struct *p)
+ {
++	int *newpid;
++
+ 	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
+ 			"nonvoluntary_ctxt_switches:\t%lu\n",
+ 			p->nvcsw,
+ 			p->nivcsw);
++
++	newpid = klp_shadow_get(p, 0);
++	if (newpid)
++		seq_printf(m, "newpid:\t%d\n", *newpid);
+ }
+ 
+ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 148a7842928d..e1dbab71b37d 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -791,6 +791,7 @@ static void check_stack_usage(void)
+ static inline void check_stack_usage(void) {}
+ #endif
+ 
++#include <linux/livepatch.h>
+ void do_exit(long code)
+ {
+ 	struct task_struct *tsk = current;
+@@ -888,6 +889,8 @@ void do_exit(long code)
+ 	check_stack_usage();
+ 	exit_thread();
+ 
++	klp_shadow_free(tsk, 0, NULL);
++
+ 	/*
+ 	 * Flush inherited counters to the parent - before the parent
+ 	 * gets woken up by child-exit notifications.
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 9bff3b28c357..529a2c943d7c 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -1757,6 +1757,7 @@ struct task_struct *fork_idle(int cpu)
+  * It copies the process, and if successful kick-starts
+  * it and waits for it to finish using the VM if required.
+  */
++#include <linux/livepatch.h>
+ long do_fork(unsigned long clone_flags,
+ 	      unsigned long stack_start,
+ 	      unsigned long stack_size,
+@@ -1794,6 +1795,13 @@ long do_fork(unsigned long clone_flags,
+ 	if (!IS_ERR(p)) {
+ 		struct completion vfork;
+ 		struct pid *pid;
++		int *newpid;
++		static int ctr = 0;
++
++		newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), GFP_KERNEL,
++						NULL, NULL);
++		if (newpid)
++			*newpid = ctr++;
+ 
+ 		trace_sched_process_fork(current, p);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/smp-locks-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/smp-locks-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/smp-locks-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/smp-locks-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c
+--- src.orig/drivers/tty/tty_buffer.c	2017-09-22 15:27:21.077053604 -0400
++++ src/drivers/tty/tty_buffer.c	2017-09-22 15:27:50.542175618 -0400
+@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p
+ 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ 	   remove this conditional if its worth it. This would be invisible
+ 	   to the callers */
++
++	if (!size)
++		printk("kpatch-test: testing .smp_locks section changes\n");
++
+ 	b = buf->tail;
+ 	if (b != NULL)
+ 		left = b->size - b->used;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/special-static.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/special-static.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/special-static.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/special-static.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+Index: kernel-rhel7/kernel/fork.c
+===================================================================
+--- kernel-rhel7.orig/kernel/fork.c
++++ kernel-rhel7/kernel/fork.c
+@@ -1146,10 +1146,18 @@ static void posix_cpu_timers_init_group(
+ 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+ }
+ 
++void kpatch_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch copy signal\n");
++}
++
+ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ 	struct signal_struct *sig;
+ 
++	kpatch_foo();
++
+ 	if (clone_flags & CLONE_THREAD)
+ 		return 0;
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/tracepoints-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/tracepoints-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/tracepoints-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/tracepoints-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel-rhel7/kernel/timer.c
+===================================================================
+--- kernel-rhel7.orig/kernel/timer.c
++++ kernel-rhel7/kernel/timer.c
+@@ -1454,6 +1454,9 @@ static void run_timer_softirq(struct sof
+ {
+ 	struct tvec_base *base = __this_cpu_read(tvec_bases);
+ 
++	if (!base)
++		printk("kpatch-test: testing __tracepoints section changes\n");
++
+ 	if (time_after_eq(jiffies, base->timer_jiffies))
+ 		__run_timers(base);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.6/warn-detect-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.6/warn-detect-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.6/warn-detect-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.6/warn-detect-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,8 @@
+diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c
+--- src.orig/arch/x86/kvm/x86.c	2017-09-22 15:27:20.852052672 -0400
++++ src/arch/x86/kvm/x86.c	2017-09-22 15:27:55.489196104 -0400
+@@ -1,3 +1,4 @@
++
+ /*
+  * Kernel-based Virtual Machine driver for Linux
+  *
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/bug-table-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/bug-table-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/bug-table-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/bug-table-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+Index: kernel/fs/proc/proc_sysctl.c
+===================================================================
+--- kernel.orig/fs/proc/proc_sysctl.c
++++ kernel/fs/proc/proc_sysctl.c
+@@ -301,6 +301,8 @@ void sysctl_head_put(struct ctl_table_he
+ 
+ static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
+ {
++	if (jiffies == 0)
++		printk("kpatch-test: testing __bug_table section changes\n");
+ 	BUG_ON(!head);
+ 	spin_lock(&sysctl_lock);
+ 	if (!use_table(head))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/cmdline-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/cmdline-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.7/cmdline-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/cmdline-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/cmdline-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/cmdline-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/cmdline-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/cmdline-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+Index: kernel/fs/proc/cmdline.c
+===================================================================
+--- kernel.orig/fs/proc/cmdline.c
++++ kernel/fs/proc/cmdline.c
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/data-new-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-new-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.7/data-new-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-new-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep "kpatch: 5" /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/data-new.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-new.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/data-new.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-new.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,29 @@
+Index: kernel/fs/proc/meminfo.c
+===================================================================
+--- kernel.orig/fs/proc/meminfo.c
++++ kernel/fs/proc/meminfo.c
+@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m
+ {
+ }
+ 
++static int foo = 5;
++
+ static int meminfo_proc_show(struct seq_file *m, void *v)
+ {
+ 	struct sysinfo i;
+@@ -110,6 +112,7 @@ static int meminfo_proc_show(struct seq_
+ 		"CmaTotal:       %8lu kB\n"
+ 		"CmaFree:        %8lu kB\n"
+ #endif
++		"kpatch: %d"
+ 		,
+ 		K(i.totalram),
+ 		K(i.freeram),
+@@ -175,6 +178,7 @@ static int meminfo_proc_show(struct seq_
+ 		, K(totalcma_pages)
+ 		, K(global_page_state(NR_FREE_CMA_PAGES))
+ #endif
++		,foo
+ 		);
+ 
+ 	hugetlb_report_meminfo(m);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/data-read-mostly.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-read-mostly.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/data-read-mostly.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/data-read-mostly.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel/net/core/dev.c
+===================================================================
+--- kernel.orig/net/core/dev.c
++++ kernel/net/core/dev.c
+@@ -4327,6 +4327,7 @@ skip_classify:
+ 		case RX_HANDLER_PASS:
+ 			break;
+ 		default:
++			printk("BUG!\n");
+ 			BUG();
+ 		}
+ 	}
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/fixup-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/fixup-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/fixup-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel/fs/readdir.c
+===================================================================
+--- kernel.orig/fs/readdir.c
++++ kernel/fs/readdir.c
+@@ -176,6 +176,7 @@ static int filldir(void * __buf, const c
+ 			goto efault;
+ 	}
+ 	dirent = buf->current_dir;
++	asm("nop");
+ 	if (__put_user(d_ino, &dirent->d_ino))
+ 		goto efault;
+ 	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-constprop.patch.disabled 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-constprop.patch.disabled
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-constprop.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-constprop.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c
+--- src.orig/kernel/time/timekeeping.c	2017-09-22 15:27:21.602055778 -0400
++++ src/kernel/time/timekeeping.c	2017-09-22 15:27:27.522080292 -0400
+@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv)
+ {
+ 	struct timespec64 now;
+ 
++	if (!tv)
++		return;
++
+ 	getnstimeofday64(&now);
+ 	tv->tv_sec = now.tv_sec;
+ 	tv->tv_usec = now.tv_nsec/1000;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-isra.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-isra.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-isra.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-isra.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel/fs/proc/proc_sysctl.c
+===================================================================
+--- kernel.orig/fs/proc/proc_sysctl.c
++++ kernel/fs/proc/proc_sysctl.c
+@@ -46,6 +46,7 @@ void proc_sys_poll_notify(struct ctl_tab
+ 	if (!poll)
+ 		return;
+ 
++	printk("kpatch-test: testing gcc .isra function name mangling\n");
+ 	atomic_inc(&poll->event);
+ 	wake_up_interruptible(&poll->wait);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-mangled-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel/mm/slub.c
+===================================================================
+--- kernel.orig/mm/slub.c
++++ kernel/mm/slub.c
+@@ -5675,6 +5675,9 @@ void get_slabinfo(struct kmem_cache *s,
+ 	unsigned long nr_free = 0;
+ 	int node;
+ 
++	if (!jiffies)
++		printk("slabinfo\n");
++
+ 	for_each_online_node(node) {
+ 		struct kmem_cache_node *n = get_node(s, node);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-2.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-2.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-2.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel/mm/mmap.c
+===================================================================
+--- kernel.orig/mm/mmap.c
++++ kernel/mm/mmap.c
+@@ -1716,6 +1716,9 @@ unsigned long mmap_region(struct file *f
+ 	struct rb_node **rb_link, *rb_parent;
+ 	unsigned long charged = 0;
+ 
++	if (!jiffies)
++		printk("kpatch mmap foo\n");
++
+ 	/* Check against address space limit. */
+ 	if (!may_expand_vm(mm, len >> PAGE_SHIFT)) {
+ 		unsigned long nr_pages;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-3.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-3.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-3.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+Index: kernel/kernel/sys.c
+===================================================================
+--- kernel.orig/kernel/sys.c
++++ kernel/kernel/sys.c
+@@ -559,8 +559,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
+ 	return ret;
+ }
+ 
++void kpatch_bar(void)
++{
++	if (!jiffies)
++		printk("kpatch_foo\n");
++}
++
+ static void deferred_cad(struct work_struct *dummy)
+ {
++	kpatch_bar();
+ 	kernel_restart(NULL);
+ }
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-4.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-4.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-4.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-4.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,21 @@
+Index: kernel/fs/aio.c
+===================================================================
+--- kernel.orig/fs/aio.c
++++ kernel/fs/aio.c
+@@ -223,9 +223,16 @@ static int __init aio_setup(void)
+ }
+ __initcall(aio_setup);
+ 
++void kpatch_aio_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch aio foo\n");
++}
++
+ static void put_aio_ring_file(struct kioctx *ctx)
+ {
+ 	struct file *aio_ring_file = ctx->aio_ring_file;
++	kpatch_aio_foo();
+ 	if (aio_ring_file) {
+ 		truncate_setsize(aio_ring_file->f_inode, 0);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+	exit 1
+else
+	exit 0
+fi
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-5.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-5.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-5.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-5.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,46 @@
+Index: kernel/kernel/audit.c
+===================================================================
+--- kernel.orig/kernel/audit.c
++++ kernel/kernel/audit.c
+@@ -205,6 +205,12 @@ void audit_panic(const char *message)
+ 	}
+ }
+ 
++void kpatch_audit_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch audit foo\n");
++}
++
+ static inline int audit_rate_check(void)
+ {
+ 	static unsigned long	last_check = 0;
+@@ -215,6 +221,7 @@ static inline int audit_rate_check(void)
+ 	unsigned long		elapsed;
+ 	int			retval	   = 0;
+ 
++	kpatch_audit_foo();
+ 	if (!audit_rate_limit) return 1;
+ 
+ 	spin_lock_irqsave(&lock, flags);
+@@ -234,6 +241,11 @@ static inline int audit_rate_check(void)
+ 	return retval;
+ }
+ 
++noinline void kpatch_audit_check(void)
++{
++	audit_rate_check();
++}
++
+ /**
+  * audit_log_lost - conditionally log lost audit message event
+  * @message: the message stating reason for lost audit message
+@@ -282,6 +294,8 @@ static int audit_log_config_change(char
+ 	struct audit_buffer *ab;
+ 	int rc = 0;
+ 
++	kpatch_audit_check();
++
+ 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+ 	if (unlikely(!ab))
+ 		return rc;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-6.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-6.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/gcc-static-local-var-6.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/gcc-static-local-var-6.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+Index: kernel/net/ipv6/netfilter.c
+===================================================================
+--- kernel.orig/net/ipv6/netfilter.c
++++ kernel/net/ipv6/netfilter.c
+@@ -112,6 +112,8 @@ static int nf_ip6_reroute(struct sk_buff
+ 	return 0;
+ }
+ 
++#include "kpatch-macros.h"
++
+ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+ 			struct flowi *fl, bool strict)
+ {
+@@ -125,6 +127,9 @@ static int nf_ip6_route(struct net *net,
+ 	struct dst_entry *result;
+ 	int err;
+ 
++	if (!jiffies)
++		printk("kpatch nf_ip6_route foo\n");
++
+ 	result = ip6_route_output(net, sk, &fl->u.ip6);
+ 	err = result->error;
+ 	if (err)
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/macro-callbacks.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/macro-callbacks.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/macro-callbacks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/macro-callbacks.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,166 @@
+kpatch/livepatch callback test patch:
+
+  vmlinux
+  pcspkr (mod)
+  joydev (mod)
+
+Note: update joydev's pre-patch callback to return -ENODEV to test failure path
+
+Index: kernel/fs/aio.c
+===================================================================
+--- kernel.orig/fs/aio.c
++++ kernel/fs/aio.c
+@@ -42,6 +42,50 @@
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
++
+ #define AIO_RING_MAGIC			0xa10a10a1
+ #define AIO_RING_COMPAT_FEATURES	1
+ #define AIO_RING_INCOMPAT_FEATURES	0
+Index: kernel/drivers/input/joydev.c
+===================================================================
+--- kernel.orig/drivers/input/joydev.c
++++ kernel/drivers/input/joydev.c
+@@ -954,3 +954,47 @@ static void __exit joydev_exit(void)
+ 
+ module_init(joydev_init);
+ module_exit(joydev_exit);
++
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0; /* return -ENODEV; */
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+Index: kernel/drivers/input/misc/pcspkr.c
+===================================================================
+--- kernel.orig/drivers/input/misc/pcspkr.c
++++ kernel/drivers/input/misc/pcspkr.c
+@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla
+ };
+ module_platform_driver(pcspkr_platform_driver);
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/macro-printk.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/macro-printk.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/macro-printk.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,151 @@
+Index: kernel/net/ipv4/fib_frontend.c
+===================================================================
+--- kernel.orig/net/ipv4/fib_frontend.c
++++ kernel/net/ipv4/fib_frontend.c
+@@ -686,6 +686,7 @@ errout:
+ 	return err;
+ }
+ 
++#include "kpatch-macros.h"
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	struct net *net = sock_net(skb->sk);
+@@ -704,6 +705,7 @@ static int inet_rtm_newroute(struct sk_b
+ 	}
+ 
+ 	err = fib_table_insert(net, tb, &cfg);
++	KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err);
+ errout:
+ 	return err;
+ }
+Index: kernel/net/ipv4/fib_semantics.c
+===================================================================
+--- kernel.orig/net/ipv4/fib_semantics.c
++++ kernel/net/ipv4/fib_semantics.c
+@@ -985,6 +985,7 @@ fib_convert_metrics(struct fib_info *fi,
+ 	return 0;
+ }
+ 
++#include "kpatch-macros.h"
+ struct fib_info *fib_create_info(struct fib_config *cfg)
+ {
+ 	int err;
+@@ -1009,6 +1010,7 @@ struct fib_info *fib_create_info(struct
+ #endif
+ 
+ 	err = -ENOBUFS;
++	KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err);
+ 	if (fib_info_cnt >= fib_info_hash_size) {
+ 		unsigned int new_size = fib_info_hash_size << 1;
+ 		struct hlist_head *new_info_hash;
+@@ -1029,6 +1031,7 @@ struct fib_info *fib_create_info(struct
+ 		if (!fib_info_hash_size)
+ 			goto failure;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err);
+ 
+ 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ 	if (fi == NULL)
+@@ -1044,6 +1047,8 @@ struct fib_info *fib_create_info(struct
+ 		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
+ 	}
+ 	fib_info_cnt++;
++	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
++
+ 	fi->fib_net = net;
+ 	fi->fib_protocol = cfg->fc_protocol;
+ 	fi->fib_scope = cfg->fc_scope;
+@@ -1059,8 +1064,10 @@ struct fib_info *fib_create_info(struct
+ 		if (!nexthop_nh->nh_pcpu_rth_output)
+ 			goto failure;
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err);
+ 
+ 	err = fib_convert_metrics(fi, cfg);
++	KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err);
+ 	if (err)
+ 		goto failure;
+ 
+@@ -1111,6 +1118,7 @@ struct fib_info *fib_create_info(struct
+ 		nh->nh_weight = 1;
+ #endif
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err);
+ 
+ 	if (fib_props[cfg->fc_type].error) {
+ 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
+@@ -1128,6 +1136,7 @@ struct fib_info *fib_create_info(struct
+ 			goto err_inval;
+ 		}
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err);
+ 
+ 	if (cfg->fc_scope > RT_SCOPE_HOST)
+ 		goto err_inval;
+@@ -1150,6 +1159,7 @@ struct fib_info *fib_create_info(struct
+ 				goto failure;
+ 		} endfor_nexthops(fi)
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err);
+ 
+ 	if (fi->fib_prefsrc) {
+ 		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+@@ -1162,6 +1172,7 @@ struct fib_info *fib_create_info(struct
+ 		fib_info_update_nh_saddr(net, nexthop_nh);
+ 		fib_add_weight(fi, nexthop_nh);
+ 	} endfor_nexthops(fi)
++	KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err);
+ 
+ 	fib_rebalance(fi);
+ 
+@@ -1173,6 +1184,7 @@ link_it:
+ 		ofi->fib_treeref++;
+ 		return ofi;
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err);
+ 
+ 	fi->fib_treeref++;
+ 	atomic_inc(&fi->fib_clntref);
+@@ -1196,6 +1208,7 @@ link_it:
+ 		hlist_add_head(&nexthop_nh->nh_hash, head);
+ 	} endfor_nexthops(fi)
+ 	spin_unlock_bh(&fib_info_lock);
++	KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err);
+ 	return fi;
+ 
+ err_inval:
+@@ -1206,6 +1219,7 @@ failure:
+ 		fi->fib_dead = 1;
+ 		free_fib_info(fi);
+ 	}
++	KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err);
+ 
+ 	return ERR_PTR(err);
+ }
+Index: kernel/net/ipv4/fib_trie.c
+===================================================================
+--- kernel.orig/net/ipv4/fib_trie.c
++++ kernel/net/ipv4/fib_trie.c
+@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie
+ }
+ 
+ /* Caller must hold RTNL. */
++#include "kpatch-macros.h"
+ int fib_table_insert(struct net *net, struct fib_table *tb,
+ 		     struct fib_config *cfg)
+ {
+@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st
+ 	if ((plen < KEYLENGTH) && (key << plen))
+ 		return -EINVAL;
+ 
++	KPATCH_PRINTK("[fib_table_insert]: start\n");
+ 	fi = fib_create_info(cfg);
+ 	if (IS_ERR(fi)) {
+ 		err = PTR_ERR(fi);
++		KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err);
+ 		goto err;
+ 	}
++	KPATCH_PRINTK("[fib_table_insert]: cross\n");
+ 
+ 	l = fib_find_node(t, &tp, key);
+ 	fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/meminfo-init2-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-init2-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/meminfo-init2-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-init2-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,20 @@
+Index: kernel/fs/proc/meminfo.c
+===================================================================
+--- kernel.orig/fs/proc/meminfo.c
++++ kernel/fs/proc/meminfo.c
+@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_
+ 	unsigned long pages[NR_LRU_LISTS];
+ 	int lru;
+ 
++	printk("a\n");
+ /*
+  * display in kilobytes.
+  */
+@@ -199,6 +200,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/meminfo-init-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-init-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/meminfo-init-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-init-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel/fs/proc/meminfo.c
+===================================================================
+--- kernel.orig/fs/proc/meminfo.c
++++ kernel/fs/proc/meminfo.c
+@@ -199,6 +199,7 @@ static const struct file_operations memi
+ 
+ static int __init proc_meminfo_init(void)
+ {
++	printk("a\n");
+ 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
+ 	return 0;
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/meminfo-string-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-string-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.7/meminfo-string-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-string-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/meminfo-string.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-string.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/meminfo-string.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/meminfo-string.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,13 @@
+Index: kernel/fs/proc/meminfo.c
+===================================================================
+--- kernel.orig/fs/proc/meminfo.c
++++ kernel/fs/proc/meminfo.c
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/module-call-external.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/module-call-external.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/module-call-external.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/module-call-external.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,35 @@
+Index: kernel/fs/nfsd/export.c
+===================================================================
+--- kernel.orig/fs/nfsd/export.c
++++ kernel/fs/nfsd/export.c
+@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m
+ 	}
+ }
+ 
++extern char *kpatch_string(void);
++
+ static int e_show(struct seq_file *m, void *p)
+ {
+ 	struct cache_head *cp = p;
+@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo
+ 	if (p == SEQ_START_TOKEN) {
+ 		seq_puts(m, "# Version 1.1\n");
+ 		seq_puts(m, "# Path Client(Flags) # IPs\n");
++		seq_puts(m, kpatch_string());
+ 		return 0;
+ 	}
+ 
+Index: kernel/net/netlink/af_netlink.c
+===================================================================
+--- kernel.orig/net/netlink/af_netlink.c
++++ kernel/net/netlink/af_netlink.c
+@@ -2568,4 +2568,9 @@ panic:
+ 	panic("netlink_init: Cannot allocate nl_table\n");
+ }
+ 
++char *kpatch_string(void)
++{
++	return "# kpatch\n";
++}
++
+ core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/multiple.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/multiple.test
--- 0.6.0-0.2/test/integration/rhel-7.7/multiple.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
+ROOTDIR="$(readlink -f $SCRIPTDIR/../..)"
+KPATCH="sudo $ROOTDIR/kpatch/kpatch"
+
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
+set -o errexit
+
+die() {
+	echo "ERROR: $@" >&2
+	exit 1
+}
+
+ko_to_test() {
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
+}
+
+# make sure any modules added here are disjoint
+declare -a modules
+declare -a blacklist=(meminfo-string-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules"
+done
+
+for mod in "${modules[@]}"; do
+	$KPATCH load $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules"
+done
+
+for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do
+	mod=${modules[idx]}
+	$KPATCH unload $mod
+done
+
+for mod in "${modules[@]}"; do
+	testprog=$(ko_to_test $mod)
+	$SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules"
+done
+
+exit 0
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/new-function.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/new-function.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/new-function.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/new-function.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,26 @@
+Index: kernel/drivers/tty/n_tty.c
+===================================================================
+--- kernel.orig/drivers/tty/n_tty.c
++++ kernel/drivers/tty/n_tty.c
+@@ -2175,7 +2175,7 @@ do_it_again:
+  *		  lock themselves)
+  */
+ 
+-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file,
+ 			   const unsigned char *buf, size_t nr)
+ {
+ 	const unsigned char *b = buf;
+@@ -2264,6 +2264,12 @@ break_out:
+ 	return (b - buf) ? b - buf : retval;
+ }
+ 
++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file,
++			   const unsigned char *buf, size_t nr)
++{
++	return kpatch_n_tty_write(tty, file, buf, nr);
++}
++
+ /**
+  *	n_tty_poll		-	poll method for N_TTY
+  *	@tty: terminal device
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/new-globals.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/new-globals.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/new-globals.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/new-globals.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,36 @@
+Index: kernel/fs/proc/cmdline.c
+===================================================================
+--- kernel.orig/fs/proc/cmdline.c
++++ kernel/fs/proc/cmdline.c
+@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void
+ 	return 0;
+ }
+ module_init(proc_cmdline_init);
++
++#include <linux/printk.h>
++void kpatch_print_message(void)
++{
++	if (!jiffies)
++		printk("hello there!\n");
++}
+Index: kernel/fs/proc/meminfo.c
+===================================================================
+--- kernel.orig/fs/proc/meminfo.c
++++ kernel/fs/proc/meminfo.c
+@@ -16,6 +16,8 @@
+ #include <asm/pgtable.h>
+ #include "internal.h"
+ 
++void kpatch_print_message(void);
++
+ void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
+ {
+ }
+@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_
+ 	/*
+ 	 * Tagged format, for easy grepping and expansion.
+ 	 */
++	kpatch_print_message();
+ 	seq_printf(m,
+ 		"MemTotal:       %8lu kB\n"
+ 		"MemFree:        %8lu kB\n"
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/parainstructions-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/parainstructions-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/parainstructions-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/parainstructions-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+Index: kernel/fs/proc/generic.c
+===================================================================
+--- kernel.orig/fs/proc/generic.c
++++ kernel/fs/proc/generic.c
+@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum)
+ 	unsigned int i;
+ 	int error;
+ 
++	printk("kpatch-test: testing change to .parainstructions section\n");
+ retry:
+ 	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+ 		return -ENOMEM;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/shadow-newpid-LOADED.test 0.8.0-0ubuntu7/test/integration/rhel-7.7/shadow-newpid-LOADED.test
--- 0.6.0-0.2/test/integration/rhel-7.7/shadow-newpid-LOADED.test	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/shadow-newpid-LOADED.test	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep -q newpid: /proc/$$/status
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/shadow-newpid.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/shadow-newpid.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,72 @@
+Index: kernel/fs/proc/array.c
+===================================================================
+--- kernel.orig/fs/proc/array.c
++++ kernel/fs/proc/array.c
+@@ -395,13 +395,20 @@ static inline void task_seccomp(struct s
+ 	seq_putc(m, '\n');
+ }
+ 
++#include <linux/livepatch.h>
+ static inline void task_context_switch_counts(struct seq_file *m,
+ 						struct task_struct *p)
+ {
++	int *newpid;
++
+ 	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
+ 			"nonvoluntary_ctxt_switches:\t%lu\n",
+ 			p->nvcsw,
+ 			p->nivcsw);
++
++	newpid = klp_shadow_get(p, 0);
++	if (newpid)
++		seq_printf(m, "newpid:\t%d\n", *newpid);
+ }
+ 
+ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
+Index: kernel/kernel/exit.c
+===================================================================
+--- kernel.orig/kernel/exit.c
++++ kernel/kernel/exit.c
+@@ -791,6 +791,7 @@ static void check_stack_usage(void)
+ static inline void check_stack_usage(void) {}
+ #endif
+ 
++#include <linux/livepatch.h>
+ void do_exit(long code)
+ {
+ 	struct task_struct *tsk = current;
+@@ -888,6 +889,8 @@ void do_exit(long code)
+ 	check_stack_usage();
+ 	exit_thread();
+ 
++	klp_shadow_free(tsk, 0, NULL);
++
+ 	/*
+ 	 * Flush inherited counters to the parent - before the parent
+ 	 * gets woken up by child-exit notifications.
+Index: kernel/kernel/fork.c
+===================================================================
+--- kernel.orig/kernel/fork.c
++++ kernel/kernel/fork.c
+@@ -1760,6 +1760,7 @@ struct task_struct *fork_idle(int cpu)
+  * It copies the process, and if successful kick-starts
+  * it and waits for it to finish using the VM if required.
+  */
++#include <linux/livepatch.h>
+ long do_fork(unsigned long clone_flags,
+ 	      unsigned long stack_start,
+ 	      unsigned long stack_size,
+@@ -1797,6 +1798,13 @@ long do_fork(unsigned long clone_flags,
+ 	if (!IS_ERR(p)) {
+ 		struct completion vfork;
+ 		struct pid *pid;
++		int *newpid;
++		static int ctr = 0;
++
++		newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), GFP_KERNEL,
++						NULL, NULL);
++		if (newpid)
++			*newpid = ctr++;
+ 
+ 		trace_sched_process_fork(current, p);
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/smp-locks-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/smp-locks-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/smp-locks-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/smp-locks-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,15 @@
+Index: kernel/drivers/tty/tty_buffer.c
+===================================================================
+--- kernel.orig/drivers/tty/tty_buffer.c
++++ kernel/drivers/tty/tty_buffer.c
+@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p
+ 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ 	   remove this conditional if its worth it. This would be invisible
+ 	   to the callers */
++
++	if (!size)
++		printk("kpatch-test: testing .smp_locks section changes\n");
++
+ 	b = buf->tail;
+ 	if (b != NULL)
+ 		left = b->size - b->used;
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/special-static.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/special-static.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/special-static.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/special-static.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,23 @@
+Index: kernel/kernel/fork.c
+===================================================================
+--- kernel.orig/kernel/fork.c
++++ kernel/kernel/fork.c
+@@ -1146,10 +1146,18 @@ static void posix_cpu_timers_init_group(
+ 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+ }
+ 
++void kpatch_foo(void)
++{
++	if (!jiffies)
++		printk("kpatch copy signal\n");
++}
++
+ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ 	struct signal_struct *sig;
+ 
++	kpatch_foo();
++
+ 	if (clone_flags & CLONE_THREAD)
+ 		return 0;
+ 
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/tracepoints-section.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/tracepoints-section.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/tracepoints-section.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/tracepoints-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,14 @@
+Index: kernel/kernel/timer.c
+===================================================================
+--- kernel.orig/kernel/timer.c
++++ kernel/kernel/timer.c
+@@ -1454,6 +1454,9 @@ static void run_timer_softirq(struct sof
+ {
+ 	struct tvec_base *base = __this_cpu_read(tvec_bases);
+ 
++	if (!base)
++		printk("kpatch-test: testing __tracepoints section changes\n");
++
+ 	if (time_after_eq(jiffies, base->timer_jiffies))
+ 		__run_timers(base);
+ }
diff -pruN 0.6.0-0.2/test/integration/rhel-7.7/warn-detect-FAIL.patch 0.8.0-0ubuntu7/test/integration/rhel-7.7/warn-detect-FAIL.patch
--- 0.6.0-0.2/test/integration/rhel-7.7/warn-detect-FAIL.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/rhel-7.7/warn-detect-FAIL.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,9 @@
+Index: kernel/arch/x86/kvm/x86.c
+===================================================================
+--- kernel.orig/arch/x86/kvm/x86.c
++++ kernel/arch/x86/kvm/x86.c
+@@ -1,3 +1,4 @@
++
+ /*
+  * Kernel-based Virtual Machine driver for Linux
+  *
diff -pruN 0.6.0-0.2/test/integration/test-vagrant 0.8.0-0ubuntu7/test/integration/test-vagrant
--- 0.6.0-0.2/test/integration/test-vagrant	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/test-vagrant	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+SCRIPTDIR=$(readlink -f "$(dirname "$(type -p "${0}")")")
+ROOTDIR=$(readlink -f "${SCRIPTDIR}/../..")
+SLOWTEST=0
+
+# shellcheck disable=SC1090
+source "${ROOTDIR}/test/integration/lib.sh"
+
+usage()
+{
+	echo "usage: $(basename "${0}") [options]" >&2
+	echo "-h, --help This message" >&2
+	echo "-s, --slow Run all of the tests" >&2
+}
+
+options="$(getopt -o hs -l "help,slow" -- "$@")" || "getopt failed"
+
+eval set -- "${options}"
+
+while [[ $# -gt 0 ]]; do
+	case "$1" in
+		-s|--slow)
+			SLOWTEST=1
+			;;
+		-h|--help)
+			usage
+			exit 0
+		;;
+	esac
+	shift
+done
+
+declare -a distros=("fedora27" "centos7")
+
+ret=0
+for distro in "${distros[@]}"; do
+	kpatch_integration_tests_vagrant_distro "${distro}" "${ROOTDIR}/test/integration/vm-integration-run" "${SLOWTEST}"
+	rc=$?
+	ret=$((ret + rc))
+done
+exit ${ret}
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/fixup-section.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/fixup-section.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/fixup-section.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/fixup-section.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,12 +1,12 @@
-diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c
---- src.orig/fs/readdir.c	2016-12-15 19:55:39.196000000 +0000
-+++ src/fs/readdir.c	2016-12-15 19:56:25.868000000 +0000
-@@ -173,6 +173,8 @@ static int filldir(struct dir_context *c
+diff --git a/fs/readdir.c b/fs/readdir.c
+index ced679179cac..7fb338324582 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -173,6 +173,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
  			goto efault;
  	}
  	dirent = buf->current_dir;
-+	if (dirent->d_ino == 12345678)
-+		printk("kpatch-test: testing .fixup section changes\n");
++	asm("nop");
  	if (__put_user(d_ino, &dirent->d_ino))
  		goto efault;
  	if (__put_user(reclen, &dirent->d_reclen))
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-mangled-3.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-mangled-3.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-mangled-3.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-mangled-3.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-ensure that __cmpxchg_double_slab.isra.45 and
-__cmpxchg_double_slab.isra.45.part.46 aren't correlated.
-
-diff -Nupr src.orig/mm/slub.c src/mm/slub.c
---- src.orig/mm/slub.c	2016-12-15 19:55:38.988000000 +0000
-+++ src/mm/slub.c	2016-12-15 19:56:39.068000000 +0000
-@@ -5531,6 +5531,9 @@ void get_slabinfo(struct kmem_cache *s,
- 	int node;
- 	struct kmem_cache_node *n;
- 
-+	if (!jiffies)
-+		printk("slabinfo\n");
-+
- 	for_each_kmem_cache_node(s, node, n) {
- 		nr_slabs += node_nr_slabs(n);
- 		nr_objs += node_nr_objs(n);
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled
--- 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,19 @@
+ensure that __cmpxchg_double_slab.isra.45 and
+__cmpxchg_double_slab.isra.45.part.46 aren't correlated.
+
+Disabled: __flush_cpu_slab() is present in vmlinux.symtab but is optimized
+out during kpatch builds
+
+diff -Nupr src.orig/mm/slub.c src/mm/slub.c
+--- src.orig/mm/slub.c	2016-12-15 19:55:38.988000000 +0000
++++ src/mm/slub.c	2016-12-15 19:56:39.068000000 +0000
+@@ -5531,6 +5531,9 @@ void get_slabinfo(struct kmem_cache *s,
+ 	int node;
+ 	struct kmem_cache_node *n;
+ 
++	if (!jiffies)
++		printk("slabinfo\n");
++
+ 	for_each_kmem_cache_node(s, node, n) {
+ 		nr_slabs += node_nr_slabs(n);
+ 		nr_objs += node_nr_objs(n);
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/integration/ubuntu-16.04/gcc-static-local-var-4.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/gcc-static-local-var-4.test	2019-08-28 17:34:00.000000000 +0000
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then
+if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then
 	exit 1
 else
 	exit 0
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/macro-callbacks.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-callbacks.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/macro-callbacks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-callbacks.patch	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,163 @@
+kpatch/livepatch callback test patch:
+
+  vmlinux
+  pcspkr (mod)
+  joydev (mod)
+
+Note: update joydev's pre-patch callback to return -ENODEV to test failure path
+
+diff -Nupr src.old/drivers/input/joydev.c src/drivers/input/joydev.c
+--- src.old/drivers/input/joydev.c	2017-09-03 16:56:17.000000000 -0400
++++ src/drivers/input/joydev.c	2018-03-22 16:32:40.963082354 -0400
+@@ -1010,3 +1010,47 @@ static void __exit joydev_exit(void)
+ 
+ module_init(joydev_init);
+ module_exit(joydev_exit);
++
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0; /* return -ENODEV; */
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+diff -Nupr src.old/drivers/input/misc/pcspkr.c src/drivers/input/misc/pcspkr.c
+--- src.old/drivers/input/misc/pcspkr.c	2018-03-22 16:29:27.716082354 -0400
++++ src/drivers/input/misc/pcspkr.c	2018-03-22 16:32:40.963082354 -0400
+@@ -132,3 +132,46 @@ static struct platform_driver pcspkr_pla
+ };
+ module_platform_driver(pcspkr_platform_driver);
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
+diff -Nupr src.old/fs/aio.c src/fs/aio.c
+--- src.old/fs/aio.c	2017-09-03 16:56:17.000000000 -0400
++++ src/fs/aio.c	2018-03-22 16:32:40.962082354 -0400
+@@ -46,6 +46,50 @@
+ 
+ #include "internal.h"
+ 
++#include <linux/module.h>
++#include "kpatch-macros.h"
++
++static const char *const module_state[] = {
++	[MODULE_STATE_LIVE]	= "[MODULE_STATE_LIVE] Normal state",
++	[MODULE_STATE_COMING]	= "[MODULE_STATE_COMING] Full formed, running module_init",
++	[MODULE_STATE_GOING]	= "[MODULE_STATE_GOING] Going away",
++	[MODULE_STATE_UNFORMED]	= "[MODULE_STATE_UNFORMED] Still setting it up",
++};
++
++static void callback_info(const char *callback, patch_object *obj)
++{
++	if (obj->mod)
++		pr_info("%s: %s -> %s\n", callback, obj->mod->name,
++			module_state[obj->mod->state]);
++	else
++		pr_info("%s: vmlinux\n", callback);
++}
++
++static int pre_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++	return 0;
++}
++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback);
++
++static void post_patch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_PATCH_CALLBACK(post_patch_callback);
++
++static void pre_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback);
++
++static void post_unpatch_callback(patch_object *obj)
++{
++	callback_info(__func__, obj);
++}
++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback);
++
+ #define AIO_RING_MAGIC			0xa10a10a1
+ #define AIO_RING_COMPAT_FEATURES	1
+ #define AIO_RING_INCOMPAT_FEATURES	0
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/macro-hooks-LOADED.test 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-hooks-LOADED.test
--- 0.6.0-0.2/test/integration/ubuntu-16.04/macro-hooks-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-hooks-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-[[ $(cat /proc/sys/fs/aio-max-nr) = 262144 ]]
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/macro-hooks.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-hooks.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/macro-hooks.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-hooks.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,24 +0,0 @@
-diff -Nupr src.orig/fs/aio.c src/fs/aio.c
---- src.orig/fs/aio.c	2016-12-15 19:55:38.992000000 +0000
-+++ src/fs/aio.c	2016-12-15 19:57:05.396000000 +0000
-@@ -1716,6 +1716,20 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t
- 	return ret;
- }
- 
-+static int aio_max_nr_orig;
-+void kpatch_load_aio_max_nr(void)
-+{
-+	aio_max_nr_orig = aio_max_nr;
-+	aio_max_nr = 0x40000;
-+}
-+void kpatch_unload_aio_max_nr(void)
-+{
-+	aio_max_nr = aio_max_nr_orig;
-+}
-+#include "kpatch-macros.h"
-+KPATCH_LOAD_HOOK(kpatch_load_aio_max_nr);
-+KPATCH_UNLOAD_HOOK(kpatch_unload_aio_max_nr);
-+
- /* io_getevents:
-  *	Attempts to read at least min_nr events and up to nr events from
-  *	the completion queue for the aio_context specified by ctx_id. If
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/macro-printk.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-printk.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/macro-printk.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/macro-printk.patch	2019-08-28 17:34:00.000000000 +0000
@@ -1,6 +1,7 @@
-diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c
---- src.orig/net/ipv4/fib_frontend.c	2016-12-15 19:55:39.724000000 +0000
-+++ src/net/ipv4/fib_frontend.c	2016-12-15 19:57:09.672000000 +0000
+Index: src/net/ipv4/fib_frontend.c
+===================================================================
+--- src.orig/net/ipv4/fib_frontend.c
++++ src/net/ipv4/fib_frontend.c
 @@ -728,6 +728,7 @@ errout:
  	return err;
  }
@@ -17,10 +18,11 @@ diff -Nupr src.orig/net/ipv4/fib_fronten
  errout:
  	return err;
  }
-diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c
---- src.orig/net/ipv4/fib_semantics.c	2016-12-15 19:55:39.720000000 +0000
-+++ src/net/ipv4/fib_semantics.c	2016-12-15 19:57:09.672000000 +0000
-@@ -991,6 +991,7 @@ fib_convert_metrics(struct fib_info *fi,
+Index: src/net/ipv4/fib_semantics.c
+===================================================================
+--- src.orig/net/ipv4/fib_semantics.c
++++ src/net/ipv4/fib_semantics.c
+@@ -998,6 +998,7 @@ fib_convert_metrics(struct fib_info *fi,
  	return 0;
  }
  
@@ -28,7 +30,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  struct fib_info *fib_create_info(struct fib_config *cfg)
  {
  	int err;
-@@ -1018,6 +1019,7 @@ struct fib_info *fib_create_info(struct
+@@ -1025,6 +1026,7 @@ struct fib_info *fib_create_info(struct
  #endif
  
  	err = -ENOBUFS;
@@ -36,7 +38,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  	if (fib_info_cnt >= fib_info_hash_size) {
  		unsigned int new_size = fib_info_hash_size << 1;
  		struct hlist_head *new_info_hash;
-@@ -1038,6 +1040,7 @@ struct fib_info *fib_create_info(struct
+@@ -1045,6 +1047,7 @@ struct fib_info *fib_create_info(struct
  		if (!fib_info_hash_size)
  			goto failure;
  	}
@@ -44,15 +46,15 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
  	if (!fi)
-@@ -1049,6 +1052,7 @@ struct fib_info *fib_create_info(struct
- 			goto failure;
- 	} else
- 		fi->fib_metrics = (u32 *) dst_default_metrics;
+@@ -1059,6 +1062,7 @@ struct fib_info *fib_create_info(struct
+ 	} else {
+ 		fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
+ 	}
 +	KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err);
- 
+ 	fib_info_cnt++;
  	fi->fib_net = net;
  	fi->fib_protocol = cfg->fc_protocol;
-@@ -1065,6 +1069,7 @@ struct fib_info *fib_create_info(struct
+@@ -1075,6 +1079,7 @@ struct fib_info *fib_create_info(struct
  		if (!nexthop_nh->nh_pcpu_rth_output)
  			goto failure;
  	} endfor_nexthops(fi)
@@ -60,7 +62,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	err = fib_convert_metrics(fi, cfg);
  	if (err)
-@@ -1117,6 +1122,8 @@ struct fib_info *fib_create_info(struct
+@@ -1127,6 +1132,8 @@ struct fib_info *fib_create_info(struct
  		nh->nh_weight = 1;
  #endif
  	}
@@ -69,7 +71,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (fib_props[cfg->fc_type].error) {
  		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
-@@ -1134,6 +1141,7 @@ struct fib_info *fib_create_info(struct
+@@ -1144,6 +1151,7 @@ struct fib_info *fib_create_info(struct
  			goto err_inval;
  		}
  	}
@@ -77,7 +79,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (cfg->fc_scope > RT_SCOPE_HOST)
  		goto err_inval;
-@@ -1162,6 +1170,7 @@ struct fib_info *fib_create_info(struct
+@@ -1172,6 +1180,7 @@ struct fib_info *fib_create_info(struct
  		if (linkdown == fi->fib_nhs)
  			fi->fib_flags |= RTNH_F_LINKDOWN;
  	}
@@ -85,7 +87,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc))
  		goto err_inval;
-@@ -1170,6 +1179,7 @@ struct fib_info *fib_create_info(struct
+@@ -1180,6 +1189,7 @@ struct fib_info *fib_create_info(struct
  		fib_info_update_nh_saddr(net, nexthop_nh);
  		fib_add_weight(fi, nexthop_nh);
  	} endfor_nexthops(fi)
@@ -93,7 +95,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fib_rebalance(fi);
  
-@@ -1181,6 +1191,7 @@ link_it:
+@@ -1191,6 +1201,7 @@ link_it:
  		ofi->fib_treeref++;
  		return ofi;
  	}
@@ -101,7 +103,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	fi->fib_treeref++;
  	atomic_inc(&fi->fib_clntref);
-@@ -1204,6 +1215,7 @@ link_it:
+@@ -1214,6 +1225,7 @@ link_it:
  		hlist_add_head(&nexthop_nh->nh_hash, head);
  	} endfor_nexthops(fi)
  	spin_unlock_bh(&fib_info_lock);
@@ -109,7 +111,7 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  	return fi;
  
  err_inval:
-@@ -1214,6 +1226,7 @@ failure:
+@@ -1224,6 +1236,7 @@ failure:
  		fi->fib_dead = 1;
  		free_fib_info(fi);
  	}
@@ -117,9 +119,10 @@ diff -Nupr src.orig/net/ipv4/fib_semanti
  
  	return ERR_PTR(err);
  }
-diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c
---- src.orig/net/ipv4/fib_trie.c	2016-12-15 19:55:39.720000000 +0000
-+++ src/net/ipv4/fib_trie.c	2016-12-15 19:57:09.676000000 +0000
+Index: src/net/ipv4/fib_trie.c
+===================================================================
+--- src.orig/net/ipv4/fib_trie.c
++++ src/net/ipv4/fib_trie.c
 @@ -1078,6 +1078,7 @@ static int fib_insert_alias(struct trie
  }
  
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test
--- 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled
--- 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
---- src.orig/fs/proc/cmdline.c	2016-12-15 19:55:39.084000000 +0000
-+++ src/fs/proc/cmdline.c	2016-12-15 19:57:13.988000000 +0000
-@@ -5,7 +5,7 @@
- 
- static int cmdline_proc_show(struct seq_file *m, void *v)
- {
--	seq_printf(m, "%s\n", saved_command_line);
-+	seq_printf(m, "%s kpatch=1\n", saved_command_line);
- 	return 0;
- }
- 
-diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
---- src.orig/fs/proc/meminfo.c	2016-12-15 19:55:39.084000000 +0000
-+++ src/fs/proc/meminfo.c	2016-12-15 19:57:13.988000000 +0000
-@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
- 		"Committed_AS:   %8lu kB\n"
- 		"VmallocTotal:   %8lu kB\n"
- 		"VmallocUsed:    %8lu kB\n"
--		"VmallocChunk:   %8lu kB\n"
-+		"VMALLOCCHUNK:   %8lu kB\n"
- #ifdef CONFIG_MEMORY_FAILURE
- 		"HardwareCorrupted: %5lu kB\n"
- #endif
-diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h
---- src.orig/include/linux/kernel.h	2016-12-15 19:55:56.996000000 +0000
-+++ src/include/linux/kernel.h	2016-12-15 19:57:13.992000000 +0000
-@@ -2,6 +2,7 @@
- #define _LINUX_KERNEL_H
- 
- 
-+
- #include <stdarg.h>
- #include <linux/linkage.h>
- #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled
--- 0.6.0-0.2/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,42 @@
+Disabled:
+kpatch-build currently fails with "invalid ancestor" error. This happens
+with at least drivers/gpu/drm/i2c/adv7511.o and drivers/hwmon/htu21.o
+files. The problem is their .ko counterparts are never built for some
+reason, This looks like a kernel bug since in both cases there are files
+with same name but in different paths that have .ko module built.
+---
+diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c
+--- src.orig/fs/proc/cmdline.c	2016-12-15 19:55:39.084000000 +0000
++++ src/fs/proc/cmdline.c	2016-12-15 19:57:13.988000000 +0000
+@@ -5,7 +5,7 @@
+ 
+ static int cmdline_proc_show(struct seq_file *m, void *v)
+ {
+-	seq_printf(m, "%s\n", saved_command_line);
++	seq_printf(m, "%s kpatch=1\n", saved_command_line);
+ 	return 0;
+ }
+ 
+diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c
+--- src.orig/fs/proc/meminfo.c	2016-12-15 19:55:39.084000000 +0000
++++ src/fs/proc/meminfo.c	2016-12-15 19:57:13.988000000 +0000
+@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
+ 		"Committed_AS:   %8lu kB\n"
+ 		"VmallocTotal:   %8lu kB\n"
+ 		"VmallocUsed:    %8lu kB\n"
+-		"VmallocChunk:   %8lu kB\n"
++		"VMALLOCCHUNK:   %8lu kB\n"
+ #ifdef CONFIG_MEMORY_FAILURE
+ 		"HardwareCorrupted: %5lu kB\n"
+ #endif
+diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h
+--- src.orig/include/linux/kernel.h	2016-12-15 19:55:56.996000000 +0000
++++ src/include/linux/kernel.h	2016-12-15 19:57:13.992000000 +0000
+@@ -2,6 +2,7 @@
+ #define _LINUX_KERNEL_H
+ 
+ 
++
+ #include <stdarg.h>
+ #include <linux/linkage.h>
+ #include <linux/stddef.h>
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/module-call-external.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-call-external.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/module-call-external.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-call-external.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,33 +0,0 @@
-diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c
---- src.orig/fs/nfsd/export.c	2016-12-15 19:55:39.012000000 +0000
-+++ src/fs/nfsd/export.c	2016-12-15 19:57:31.068000000 +0000
-@@ -1183,6 +1183,8 @@ static void exp_flags(struct seq_file *m
- 	}
- }
- 
-+extern char *kpatch_string(void);
-+
- static int e_show(struct seq_file *m, void *p)
- {
- 	struct cache_head *cp = p;
-@@ -1192,6 +1194,7 @@ static int e_show(struct seq_file *m, vo
- 	if (p == SEQ_START_TOKEN) {
- 		seq_puts(m, "# Version 1.1\n");
- 		seq_puts(m, "# Path Client(Flags) # IPs\n");
-+		seq_puts(m, kpatch_string());
- 		return 0;
- 	}
- 
-diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
---- src.orig/net/netlink/af_netlink.c	2016-12-15 19:55:39.772000000 +0000
-+++ src/net/netlink/af_netlink.c	2016-12-15 19:57:31.072000000 +0000
-@@ -3353,4 +3353,9 @@ panic:
- 	panic("netlink_init: Cannot allocate nl_table\n");
- }
- 
-+char *kpatch_string(void)
-+{
-+	return "# kpatch\n";
-+}
-+
- core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/module-call-external.patch.disable 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-call-external.patch.disable
--- 0.6.0-0.2/test/integration/ubuntu-16.04/module-call-external.patch.disable	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-call-external.patch.disable	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,38 @@
+Disabled:
+Original build includes "kzalloc" in af_netlink.c's symbol list, this
+does not happen during kpatch build so create-diff-object fails with
+find_local_syms.
+---
+diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c
+--- src.orig/fs/nfsd/export.c	2016-12-15 19:55:39.012000000 +0000
++++ src/fs/nfsd/export.c	2016-12-15 19:57:31.068000000 +0000
+@@ -1183,6 +1183,8 @@ static void exp_flags(struct seq_file *m
+ 	}
+ }
+ 
++extern char *kpatch_string(void);
++
+ static int e_show(struct seq_file *m, void *p)
+ {
+ 	struct cache_head *cp = p;
+@@ -1192,6 +1194,7 @@ static int e_show(struct seq_file *m, vo
+ 	if (p == SEQ_START_TOKEN) {
+ 		seq_puts(m, "# Version 1.1\n");
+ 		seq_puts(m, "# Path Client(Flags) # IPs\n");
++		seq_puts(m, kpatch_string());
+ 		return 0;
+ 	}
+ 
+diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c
+--- src.orig/net/netlink/af_netlink.c	2016-12-15 19:55:39.772000000 +0000
++++ src/net/netlink/af_netlink.c	2016-12-15 19:57:31.072000000 +0000
+@@ -3353,4 +3353,9 @@ panic:
+ 	panic("netlink_init: Cannot allocate nl_table\n");
+ }
+ 
++char *kpatch_string(void)
++{
++	return "# kpatch\n";
++}
++
+ core_initcall(netlink_proto_init);
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/module-shadow.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-shadow.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/module-shadow.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/module-shadow.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,24 +0,0 @@
-diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c
---- src.orig/arch/x86/kvm/vmx.c	2016-12-15 19:55:57.436000000 +0000
-+++ src/arch/x86/kvm/vmx.c	2016-12-15 19:57:39.592000000 +0000
-@@ -10558,10 +10558,20 @@ static void vmx_leave_nested(struct kvm_
-  * It should only be called before L2 actually succeeded to run, and when
-  * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
-  */
-+#include "kpatch.h"
- static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
- 			struct vmcs12 *vmcs12,
- 			u32 reason, unsigned long qualification)
- {
-+	int *kpatch;
-+
-+	kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch),
-+				     GFP_KERNEL);
-+	if (kpatch) {
-+		kpatch_shadow_get(vcpu, "kpatch");
-+		kpatch_shadow_free(vcpu, "kpatch");
-+	}
-+
- 	load_vmcs12_host_state(vcpu, vmcs12);
- 	vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
- 	vmcs12->exit_qualification = qualification;
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/multiple.test 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/multiple.test
--- 0.6.0-0.2/test/integration/ubuntu-16.04/multiple.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/multiple.test	2019-08-28 17:34:00.000000000 +0000
@@ -4,6 +4,10 @@ SCRIPTDIR="$(readlink -f $(dirname $(typ
 ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)"
 KPATCH="sudo $ROOTDIR/kpatch/kpatch"
 
+MODULE_PREFIX="test-"
+MODULE_POSTFIX=".ko"
+TEST_POSTFIX="-LOADED.test"
+
 set -o errexit
 
 die() {
@@ -12,12 +16,27 @@ die() {
 }
 
 ko_to_test() {
-	tmp=${1%.ko}-LOADED.test
-	echo ${tmp#kpatch-}
+	tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX}
+	echo ${tmp#${MODULE_PREFIX}}
 }
 
 # make sure any modules added here are disjoint
-declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko)
+declare -a modules
+declare -a blacklist=(data-new-LOADED.test meminfo-cmdline-rebuild-SLOW-LOADED.test)
+
+for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do
+	name=$(basename ${file})
+	skip=0
+	for bname in "${blacklist[@]}"; do
+		if [ "${bname}" == "${name}" ]; then
+			skip=1
+			break
+		fi
+	done
+	if [ ${skip} -eq 0 ]; then
+		modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX})
+	fi
+done
 
 for mod in "${modules[@]}"; do
 	testprog=$(ko_to_test $mod)
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test
--- 0.6.0-0.2/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-grep -q newpid: /proc/$$/status
diff -pruN 0.6.0-0.2/test/integration/ubuntu-16.04/shadow-newpid.patch 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/shadow-newpid.patch
--- 0.6.0-0.2/test/integration/ubuntu-16.04/shadow-newpid.patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/ubuntu-16.04/shadow-newpid.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,69 +0,0 @@
-diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c
---- src.orig/fs/proc/array.c	2016-12-15 19:55:39.080000000 +0000
-+++ src/fs/proc/array.c	2016-12-15 19:58:00.840000000 +0000
-@@ -334,13 +334,20 @@ static inline void task_seccomp(struct s
- #endif
- }
- 
-+#include "kpatch.h"
- static inline void task_context_switch_counts(struct seq_file *m,
- 						struct task_struct *p)
- {
-+	int *newpid;
-+
- 	seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
- 			"nonvoluntary_ctxt_switches:\t%lu\n",
- 			p->nvcsw,
- 			p->nivcsw);
-+
-+	newpid = kpatch_shadow_get(p, "newpid");
-+	if (newpid)
-+		seq_printf(m, "newpid:\t%d\n", *newpid);
- }
- 
- static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
-diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c
---- src.orig/kernel/exit.c	2016-12-15 19:56:00.184000000 +0000
-+++ src/kernel/exit.c	2016-12-15 19:58:00.840000000 +0000
-@@ -650,6 +650,7 @@ static void check_stack_usage(void)
- static inline void check_stack_usage(void) {}
- #endif
- 
-+#include "kpatch.h"
- void do_exit(long code)
- {
- 	struct task_struct *tsk = current;
-@@ -758,6 +759,8 @@ void do_exit(long code)
- 
- 	cgroup_exit(tsk);
- 
-+	kpatch_shadow_free(tsk, "newpid");
-+
- 	/*
- 	 * FIXME: do that only when needed, using sched_exit tracepoint
- 	 */
-diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c
---- src.orig/kernel/fork.c	2016-12-15 19:56:00.184000000 +0000
-+++ src/kernel/fork.c	2016-12-15 19:58:00.840000000 +0000
-@@ -1726,6 +1726,7 @@ struct task_struct *fork_idle(int cpu)
-  * It copies the process, and if successful kick-starts
-  * it and waits for it to finish using the VM if required.
-  */
-+#include "kpatch.h"
- long _do_fork(unsigned long clone_flags,
- 	      unsigned long stack_start,
- 	      unsigned long stack_size,
-@@ -1764,6 +1765,13 @@ long _do_fork(unsigned long clone_flags,
- 	if (!IS_ERR(p)) {
- 		struct completion vfork;
- 		struct pid *pid;
-+		int *newpid;
-+		static int ctr = 0;
-+
-+		newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
-+					     GFP_KERNEL);
-+		if (newpid)
-+			*newpid = ctr++;
- 
- 		trace_sched_process_fork(current, p);
- 
diff -pruN 0.6.0-0.2/test/integration/vm-integration-run 0.8.0-0ubuntu7/test/integration/vm-integration-run
--- 0.6.0-0.2/test/integration/vm-integration-run	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/integration/vm-integration-run	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+KPATCH_SLOW=0
+KPATCH_GIT=${KPATCH_GIT:-https://github.com/dynup/kpatch.git}
+KPATCH_REV=${KPATCH_REV:-HEAD}
+LOGDIR="/vagrant/logs"
+
+usage()
+{
+  echo "usage: $(basename "${0}") [options]" >&2
+  echo "-h, --help      This message" >&2
+  echo "-s, --slow      Run all of the tests" >&2
+  echo "-g, --git       Git url to clone from" >&2
+  echo "-r, --revision  Revision to use (HEAD by default)" >&2
+}
+
+options="$(getopt -o "shg:r:" -l "slow,help,git:,revision:" -- "$@")" || "getopt failed"
+
+eval set -- "${options}"
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    -s|--slow)
+      KPATCH_SLOW=1
+      shift
+      ;;
+    -g|--git)
+      KPATCH_GIT="${2}"
+      shift 2
+      ;;
+    -r|--revision)
+      KPATCH_REV="${2}"
+      shift 2
+      ;;
+    -h|--help)
+      usage
+      exit 0
+      ;;
+    --)
+      shift
+      break
+      ;;
+  esac
+done
+
+git clone "${KPATCH_GIT}" || exit 1
+
+cd kpatch || exit 1
+
+git reset --hard "${KPATCH_REV}" || exit 1
+
+# shellcheck disable=SC1091
+source test/integration/lib.sh
+
+kpatch_dependencies
+kpatch_separate_disk_cache /dev/vdb /mnt/build
+kpatch_set_ccache_max_size 10G
+
+# Check if we have predownloaded sources and move them to ~/.kpatch dir which
+# is a symlink to a dir on a separate (bigger) volume, suitable for building.
+if [[ -d "${HOME}/src" && -f "${HOME}/src/version" ]]; then
+  cp "${HOME}/src/version" "${HOME}/.kpatch/"
+  mv "${HOME}/src" "${HOME}/.kpatch/"
+fi
+
+if [ ${KPATCH_SLOW} -eq 1 ]; then
+  make integration-slow 2>&1
+else
+  make integration-quick 2>&1
+fi
+
+rc=${PIPESTATUS[0]}
+rm -rf "${LOGDIR}"
+mkdir -p "${LOGDIR}"
+cp ./test/integration/*.log "${LOGDIR}"
+
+exit "${rc}"
diff -pruN 0.6.0-0.2/test/test-functions.sh 0.8.0-0ubuntu7/test/test-functions.sh
--- 0.6.0-0.2/test/test-functions.sh	1970-01-01 00:00:00.000000000 +0000
+++ 0.8.0-0ubuntu7/test/test-functions.sh	2019-08-28 17:34:00.000000000 +0000
@@ -0,0 +1,12 @@
+FILE=$1
+
+assert_num_funcs() {
+	local num_funcs=$(nm $FILE | grep -i " t " | wc -l)
+
+	if [[ $num_funcs != $1 ]]; then
+		echo "$FILE: assertion failed: file has $num_funcs funcs, expected $1" 1>&2
+		exit 1
+	fi
+
+	return 0
+}
diff -pruN 0.6.0-0.2/test/testmod/doit-client.sh 0.8.0-0ubuntu7/test/testmod/doit-client.sh
--- 0.6.0-0.2/test/testmod/doit-client.sh	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/doit-client.sh	1970-01-01 00:00:00.000000000 +0000
@@ -1,27 +0,0 @@
-#!/bin/bash
-
-#set -x
-
-rmmod testmod 2> /dev/null
-rmmod kpatch 2> /dev/null
-insmod testmod.ko || exit 1
-insmod kpatch.ko || exit 1
-if [[ "$(cat /sys/kernel/testmod/value)" != "2" ]]
-then
-	exit 1
-fi
-insmod kpatch-patch.ko
-dmesg | tail
-if [[ "$(cat /sys/kernel/testmod/value)" != "3" ]]
-then
-	exit 1
-fi
-echo 0 > /sys/kernel/kpatch/kpatch_patch/enabled
-rmmod kpatch-patch
-if [[ "$(cat /sys/kernel/testmod/value)" != "2" ]]
-then
-	exit 1
-fi
-rmmod kpatch
-rmmod testmod
-echo "SUCCESS"
diff -pruN 0.6.0-0.2/test/testmod/doit.sh 0.8.0-0ubuntu7/test/testmod/doit.sh
--- 0.6.0-0.2/test/testmod/doit.sh	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/doit.sh	1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-#!/bin/bash
-
-#set -x
-
-# If testing on a remote machine, set it here
-# Probably want to use preshared keys.
-
-unset REMOTE
-#REMOTE="192.168.100.150"
-
-cd ../../ || exit 1
-make clean || exit 1
-make || exit 1
-cd test/testmod || exit 1
-make || exit 1
-../../kpatch-build/create-diff-object testmod_drv.o.orig testmod_drv.o.patched testmod.ko output.o || exit 1
-cd ../../kmod/patch || exit 1
-make clean || exit 1
-cp ../../test/testmod/output.o . || exit 1
-md5sum output.o | awk '{printf "%s\0", $1}' > checksum.tmp || exit 1
-objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly output.o || exit 1
-rm -f checksum.tmp
-KBUILD_EXTRA_SYMBOLS="$(readlink -e ../../kmod/core/Module.symvers)" make || exit 1
-cd ../../test/testmod
-
-if [[ -z "$REMOTE" ]]
-then
-	cp ../../kmod/core/kpatch.ko .
-	cp ../../kmod/patch/kpatch-patch.ko .
-	sudo ./doit-client.sh
-else
-	scp ../../kmod/core/kpatch.ko root@$REMOTE:~/. || exit 1
-	scp ../../kmod/patch/kpatch-patch.ko root@$REMOTE:~/. || exit 1
-	scp testmod.ko root@$REMOTE:~/. || exit 1
-	scp doit-client.sh root@$REMOTE:~/. || exit 1
-	ssh root@$REMOTE ./doit-client.sh
-fi
diff -pruN 0.6.0-0.2/test/testmod/Makefile 0.8.0-0ubuntu7/test/testmod/Makefile
--- 0.6.0-0.2/test/testmod/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/Makefile	1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-BUILD ?= /lib/modules/$(shell uname -r)/build
-
-testmod.ko: testmod_drv.c
-	patch < patch
-	KCFLAGS="-ffunction-sections -fdata-sections" $(MAKE) -C $(BUILD) M=$(PWD) testmod.ko
-	strip --keep-file-symbols -d testmod_drv.o
-	cp testmod_drv.o testmod_drv.o.patched
-	patch -R < patch
-	KCFLAGS="-ffunction-sections -fdata-sections" $(MAKE) -C $(BUILD) M=$(PWD) testmod.ko
-	strip --keep-file-symbols -d testmod_drv.o
-	cp testmod_drv.o testmod_drv.o.orig
-	$(MAKE) -C $(BUILD) M=$(PWD) clean
-	$(MAKE) -C $(BUILD) M=$(PWD) testmod.ko
-
-all: testmod.ko
-
-clean:
-	$(MAKE) -C $(BUILD) M=$(PWD) clean
-	rm *.orig *.patched
-
-# kbuild rules
-obj-m := testmod.o
-testmod-y := testmod_drv.o
diff -pruN 0.6.0-0.2/test/testmod/patch 0.8.0-0ubuntu7/test/testmod/patch
--- 0.6.0-0.2/test/testmod/patch	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
---- testmod_drv.c.orig	2014-06-02 16:49:49.428509600 -0500
-+++ testmod_drv.c	2014-06-02 16:49:56.973656791 -0500
-@@ -11,7 +11,7 @@
- static ssize_t value_show(struct kobject *kobj,
-                           struct kobj_attribute *attr, char *buf)
- {
--	return sprintf(buf, "%d\n", value);
-+	return sprintf(buf, "%d\n", value+1);
- }
- 
- static struct kobj_attribute testmod_value_attr = __ATTR_RO(value);
diff -pruN 0.6.0-0.2/test/testmod/README 0.8.0-0ubuntu7/test/testmod/README
--- 0.6.0-0.2/test/testmod/README	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/README	1970-01-01 00:00:00.000000000 +0000
@@ -1,4 +0,0 @@
-To test, run ./doit.sh from the current directory.
-
-To test on a remote system, set remote system using REMOTE in doit.sh.
-Then run ./doit.sh.
diff -pruN 0.6.0-0.2/test/testmod/testmod_drv.c 0.8.0-0ubuntu7/test/testmod/testmod_drv.c
--- 0.6.0-0.2/test/testmod/testmod_drv.c	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/testmod/testmod_drv.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,44 +0,0 @@
-#define pr_fmt(fmt) "testmod: " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-
-static struct kobject *testmod_kobj;
-int value = 2;
-
-static ssize_t value_show(struct kobject *kobj,
-                          struct kobj_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", value);
-}
-
-static struct kobj_attribute testmod_value_attr = __ATTR_RO(value);
-
-static int testmod_init(void)
-{
-	int ret;
-
-	testmod_kobj = kobject_create_and_add("testmod", kernel_kobj);
-	if (!testmod_kobj)
-		return -ENOMEM;
-
-	ret = sysfs_create_file(testmod_kobj, &testmod_value_attr.attr);
-	if (ret) {
-		kobject_put(testmod_kobj);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void testmod_exit(void)
-{
-	sysfs_remove_file(testmod_kobj, &testmod_value_attr.attr);
-	kobject_put(testmod_kobj);
-}
-
-module_init(testmod_init);
-module_exit(testmod_exit);
-MODULE_LICENSE("GPL");
diff -pruN 0.6.0-0.2/test/unit/Makefile 0.8.0-0ubuntu7/test/unit/Makefile
--- 0.6.0-0.2/test/unit/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/Makefile	2019-08-28 17:34:00.000000000 +0000
@@ -1,7 +1,13 @@
-ARCH=$(shell uname -m)
+ARCH    = $(shell uname -m)
+OBJDIR ?= objs/$(ARCH)
 
-all: Makefile.include $(ARCH)/Makefile
-	$(MAKE) -C $(ARCH)
+.PHONY: all clean
 
-clean: Makefile.include $(ARCH)/Makefile
-	$(MAKE) -C $(ARCH) clean
+all: Makefile.include
+	@cd $(shell git rev-parse --show-toplevel) && \
+		git diff-index --quiet HEAD test/unit/objs || \
+		echo -e "\nWARNING: unit tests are out of date - run \"git submodule update\"\n"
+	$(MAKE) -C $(OBJDIR)
+
+clean: Makefile.include
+	if [ -d $(OBJDIR) ]; then $(MAKE) -C $(OBJDIR) clean; fi
diff -pruN 0.6.0-0.2/test/unit/Makefile.include 0.8.0-0ubuntu7/test/unit/Makefile.include
--- 0.6.0-0.2/test/unit/Makefile.include	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/Makefile.include	2019-08-28 17:34:00.000000000 +0000
@@ -4,26 +4,27 @@ EXT_FAIL        ?= PATCHED.FAIL.o
 EXT_TEST        ?= test
 EXT_OUTPUT      ?= OUTPUT.o
 EXT_TEST_OUTPUT ?= test.out
+EXT_SYMTAB      ?= symtab
+EXT_SYMVERS     ?= symvers
+EXT_ENV         ?= env
 TNAME            = $(@:.$(EXT_OUTPUT)=)
 
 ifndef VERBOSE
 MUTE_PASS := >/dev/null
 MUTE_FAIL := >/dev/null 2>&1
+.SILENT: $(TARGETS) $(TEST_TARGETS)
 endif
 
-SRC_PATH ?= $(realpath ../../../)
-CDO      ?= $(SRC_PATH)/kpatch-build/create-diff-object
+SRC_PATH        ?= $(realpath ../../../../)
+CDO             ?= $(SRC_PATH)/kpatch-build/create-diff-object
+TEST_LIBRARY    ?= $(SRC_PATH)/test/test-functions.sh
 
-TENV = PARA_STRUCT_SIZE=16 EX_STRUCT_SIZE=12 BUG_STRUCT_SIZE=12 ALT_STRUCT_SIZE=13
+TEST_ENV = KPATCH_TEST_LIBRARY=$(TEST_LIBRARY)
 
 TARGETS      = $(patsubst %.$(EXT_ORIG),%.$(EXT_OUTPUT),$(wildcard *.$(EXT_ORIG)))
 TEST_TARGETS = $(patsubst %.$(EXT_TEST),%.$(EXT_TEST_OUTPUT),$(wildcard *.$(EXT_TEST)))
 
-define check_lfs =
-	$(if $(shell head -1 $(1) | grep git-lfs.github.com),
-		$(error $(1) is not fetched. Unittests require https://git-lfs.github.com/),
-	)
-endef
+SYMVERS_FILE = $(if $(wildcard $(TNAME).$(EXT_SYMVERS)),$(TNAME).$(EXT_SYMVERS),/dev/null)
 
 define check_stripped =
 	$(if $(shell readelf --debug-dump $(1)),
@@ -32,31 +33,41 @@ define check_stripped =
 endef
 
 define check_all =
-	$(call check_lfs,$(1))
-	$(call check_stripped,$(1))
+	$(if $(findstring NOSTRIP,$(1)), , $(call check_stripped,$(1)))
 endef
 
+.DELETE_ON_ERROR: %.$(EXT_OUTPUT)
+
 all: $(TARGETS) $(TEST_TARGETS)
 
 clean:
-	rm -f $(TARGETS) $(TEST_TARGETS)
+	rm -f *.$(EXT_TEST_OUTPUT) *.$(EXT_OUTPUT)
 
-%.$(EXT_TEST_OUTPUT): %.$(EXT_OUTPUT) %.$(EXT_TEST)
-	bash $(@:.$(EXT_TEST_OUTPUT)=.$(EXT_TEST)) $<
+%.$(EXT_SYMTAB):
+	readelf -s --wide $(patsubst %.$(EXT_SYMTAB),%.$(EXT_ORIG),$(@)) | \
+		sed -r 's/\s+\[<localentry>: 8\]//' >$@
+
+%.$(EXT_TEST_OUTPUT): %.$(EXT_OUTPUT) %.$(EXT_TEST) $(TEST_LIBRARY)
+	@echo "TEST $(@:.$(EXT_TEST_OUTPUT)=)"
+	$(TEST_ENV) bash $(@:.$(EXT_TEST_OUTPUT)=.$(EXT_TEST)) $<
 # Don't rely on script creating this
 	@touch $@
 
-%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_PATCHED) $(CDO)
+%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_PATCHED) %.$(EXT_SYMTAB) $(CDO)
+	@echo "BUILD $(TNAME)"
 	$(call check_all,$(TNAME).$(EXT_ORIG))
 	$(call check_all,$(TNAME).$(EXT_PATCHED))
-	$(TENV) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_PATCHED) \
-		$(TNAME).$(EXT_ORIG) $@ /dev/null test_$(TNAME) $(MUTE_PASS)
+	$(CDO_ENV) $(shell cat $(TNAME).$(EXT_ENV) 2>/dev/null) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_PATCHED) \
+		vmlinux $(TNAME).$(EXT_SYMTAB) $(SYMVERS_FILE) \
+		test_$(TNAME) $@ $(MUTE_PASS)
 
-%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_FAIL) $(CDO)
+%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_FAIL) %.$(EXT_SYMTAB) $(CDO)
+	@echo "BUILD $(TNAME)-FAIL"
 	$(call check_all,$(TNAME).$(EXT_ORIG))
 	$(call check_all,$(TNAME).$(EXT_FAIL))
-	! $(TENV) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_FAIL) \
-		$(TNAME).$(EXT_ORIG) $@ /dev/null test_$(TNAME) $(MUTE_FAIL)
+	! $(CDO_ENV) $(shell cat $(TNAME).$(EXT_ENV) 2>/dev/null) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_FAIL) \
+		vmlinux $(TNAME).$(EXT_SYMTAB) $(SYMVERS_FILE) \
+		test_$(TNAME) $@ $(MUTE_FAIL)
 # Expecting to fail, thus create output file manually so we won't rerun the
 # test without clean
 	@touch $@
diff -pruN 0.6.0-0.2/test/unit/x86_64/bug-table-section.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/bug-table-section.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/bug-table-section.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/bug-table-section.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c90532c33be3e1059d1c4e11e8a0a45b910397628bb7ad23d257d1f5793743fb
-size 44992
diff -pruN 0.6.0-0.2/test/unit/x86_64/bug-table-section.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/bug-table-section.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/bug-table-section.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/bug-table-section.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:4a5d756499e91c19b712ca0534c3469bb0576941ae649f51d21505643719b8f2
-size 45272
diff -pruN 0.6.0-0.2/test/unit/x86_64/convert-global-local.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/convert-global-local.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/convert-global-local.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/convert-global-local.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3c49c9fdd4df5bac01c1abe0947c404393a4e9d6654f2c883e0413f9d54b3962
-size 157736
diff -pruN 0.6.0-0.2/test/unit/x86_64/convert-global-local.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/convert-global-local.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/convert-global-local.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/convert-global-local.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:22f6c80ae9217515a773d9298297c7beca7715aef356e57e698bbe46bd383b79
-size 157984
diff -pruN 0.6.0-0.2/test/unit/x86_64/data-new.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/data-new.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/data-new.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/data-new.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c82d4048941bbe8fb85dae796eec63ad838925150cd740aec18fa506132b52f5
-size 9528
diff -pruN 0.6.0-0.2/test/unit/x86_64/data-new.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/data-new.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/data-new.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/data-new.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6ae5708808a8ef41d1d6dda664871b3a4351291c6cba7de6257db96a467ea5dc
-size 9608
diff -pruN 0.6.0-0.2/test/unit/x86_64/data-read-mostly.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/data-read-mostly.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/data-read-mostly.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/data-read-mostly.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:74577f1c6457f5dd2d46997377ef57a22f75644cf6f1239699b4d566c9a391c0
-size 315504
diff -pruN 0.6.0-0.2/test/unit/x86_64/data-read-mostly.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/data-read-mostly.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/data-read-mostly.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/data-read-mostly.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e7c643e5e190617a08d8625d8cecc979d48b00de171bdc048bdecdd7cbe14aeb
-size 315616
diff -pruN 0.6.0-0.2/test/unit/x86_64/fixup-section.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/fixup-section.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/fixup-section.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/fixup-section.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3564e932091cad1ebea8e3124ff2e695a6cdeb2e77385cb28b2864f02da0a409
-size 25760
diff -pruN 0.6.0-0.2/test/unit/x86_64/fixup-section.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/fixup-section.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/fixup-section.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/fixup-section.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:792c261bef5723fa88f5c2a546fdf8d54737c8ecb979ed09d1ba7f3ce299a389
-size 26048
diff -pruN 0.6.0-0.2/test/unit/x86_64/function-ptr-new.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/function-ptr-new.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/function-ptr-new.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/function-ptr-new.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:550e34f0e1ad732f6fb2adee2b8ef40c23959770f3885a99b03387df1ca8b479
-size 9696
diff -pruN 0.6.0-0.2/test/unit/x86_64/function-ptr-new.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/function-ptr-new.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/function-ptr-new.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/function-ptr-new.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8f71d13f5f4f31dc025ef9a270d7afbb3eb591d09b56a604e578ae23d05d43ff
-size 10344
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-constprop.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-constprop.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-constprop.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-constprop.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:cf616b62df11ad10b14707061ba24a4711107680612eb13deab2668d55d36a7f
-size 71704
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-constprop.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-constprop.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-constprop.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-constprop.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d60e3a1f928b7a526f8f1a150bdd29487cd85e9d0b47516fd73b641c57af9fee
-size 71704
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-isra.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-isra.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-isra.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-isra.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:4a5d756499e91c19b712ca0534c3469bb0576941ae649f51d21505643719b8f2
-size 45272
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-isra.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-isra.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-isra.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-isra.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:607339c8d247162e67a8770892ec5e0a77d9a743fa6c2a623ed92b24044a3235
-size 45512
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-mangled-3.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-mangled-3.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-mangled-3.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-mangled-3.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3c49c9fdd4df5bac01c1abe0947c404393a4e9d6654f2c883e0413f9d54b3962
-size 157736
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-mangled-3.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-mangled-3.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-mangled-3.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-mangled-3.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3de719e0324331e64ab1230b0c3a844701162519844a3a689da186deb6f19f8f
-size 157984
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-2.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-2.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-2.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-2.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5705ea1d1917fa1829f7a70979bfae3fcf17635e3b1c76f3358dda57673f28e1
-size 68728
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-2.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-2.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-2.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-2.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:21027abe867833593505f69a381d06519647c6e52551a1b67522a6600561d31b
-size 69008
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-3.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-3.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-3.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-3.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0529108c62c58a736a1cdc88f9d5b32d5230705b9d5e44baf56ee1bc563516ad
-size 28600
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-3.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-3.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-3.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-3.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:735b1f6eb57d75ad0fd188a7ed0bcf4ca8afb96d9ed19e4421825f65ac04271e
-size 29232
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d165518f5f75ea16f4edb63fabca532aa98571bbc9e151cfdafb2575f352acb1
-size 69560
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9a07e8acf553af1c7b001fd37e3acb3d21a6eff87fe0b75f5a5d425a72802253
-size 70256
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.test 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.test
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-4.test	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-4.test	1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-if $(nm ${1} | grep -q free_ioctx); then
-	exit 1
-else
-	exit 0
-fi
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-5.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-5.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-5.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-5.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f3d2d05a244e8c0006968e71f2fffc71eee0286e4b7dbbe5880a8e51eedb3625
-size 75720
diff -pruN 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-5.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-5.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/gcc-static-local-var-5.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/gcc-static-local-var-5.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1545d26ae126d67e7b8545db1e9060ed7fcd27e5868e7d7e82a3e23bee76fca0
-size 77224
diff -pruN 0.6.0-0.2/test/unit/x86_64/macro-hooks.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/macro-hooks.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/macro-hooks.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/macro-hooks.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d165518f5f75ea16f4edb63fabca532aa98571bbc9e151cfdafb2575f352acb1
-size 69560
diff -pruN 0.6.0-0.2/test/unit/x86_64/macro-hooks.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/macro-hooks.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/macro-hooks.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/macro-hooks.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:a41f8dcd6ed3eddfed5a9d1be3776936fff13d9fc276d39e66d6daede1be8868
-size 70984
diff -pruN 0.6.0-0.2/test/unit/x86_64/Makefile 0.8.0-0ubuntu7/test/unit/x86_64/Makefile
--- 0.6.0-0.2/test/unit/x86_64/Makefile	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/Makefile	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-include ../Makefile.include
diff -pruN 0.6.0-0.2/test/unit/x86_64/meminfo-init2.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init2.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/meminfo-init2.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init2.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c82d4048941bbe8fb85dae796eec63ad838925150cd740aec18fa506132b52f5
-size 9528
diff -pruN 0.6.0-0.2/test/unit/x86_64/meminfo-init2.PATCHED.FAIL.o 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init2.PATCHED.FAIL.o
--- 0.6.0-0.2/test/unit/x86_64/meminfo-init2.PATCHED.FAIL.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init2.PATCHED.FAIL.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5feaf8bfa5d9195bc4566e644324c0992ca318b2191b5090b645ce0cae690ca1
-size 9688
diff -pruN 0.6.0-0.2/test/unit/x86_64/meminfo-init.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/meminfo-init.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c82d4048941bbe8fb85dae796eec63ad838925150cd740aec18fa506132b52f5
-size 9528
diff -pruN 0.6.0-0.2/test/unit/x86_64/meminfo-init.PATCHED.FAIL.o 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init.PATCHED.FAIL.o
--- 0.6.0-0.2/test/unit/x86_64/meminfo-init.PATCHED.FAIL.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/meminfo-init.PATCHED.FAIL.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:78203d10a0e5140ab608ff932932e3ec6cb807e609a59c50b6d908b45821a694
-size 9608
diff -pruN 0.6.0-0.2/test/unit/x86_64/module-kvm-fixup.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/module-kvm-fixup.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/module-kvm-fixup.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/module-kvm-fixup.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9e928bc0240f0d844d5bc5b83faa7e39359db85bdeb050d07031fc87646c458d
-size 380192
diff -pruN 0.6.0-0.2/test/unit/x86_64/module-kvm-fixup.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/module-kvm-fixup.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/module-kvm-fixup.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/module-kvm-fixup.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:192874c24acee410915a76883571accffff03636fc7232313caa901d9b8b13f2
-size 380512
diff -pruN 0.6.0-0.2/test/unit/x86_64/new-fuction.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/new-fuction.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/new-fuction.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/new-fuction.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:7269c12c89ea0f716fdc7859912540708917c49ca877a9c4c68484ba99aa8878
-size 35912
diff -pruN 0.6.0-0.2/test/unit/x86_64/new-fuction.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/new-fuction.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/new-fuction.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/new-fuction.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e25c16a5039a5300f3816f40b93f7e0dc8976dfc0a637f77937ec60f83fb82fb
-size 36176
diff -pruN 0.6.0-0.2/test/unit/x86_64/parainstructions-section.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/parainstructions-section.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/parainstructions-section.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/parainstructions-section.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:772b7f5b3c6f0459d4f6410255daa2840b2889375ae62138fd196317a015c430
-size 26280
diff -pruN 0.6.0-0.2/test/unit/x86_64/parainstructions-section.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/parainstructions-section.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/parainstructions-section.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/parainstructions-section.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:dec5ecd177b53d044742bd0e99b3fc09f649ff0f290b5928601c58e5aea37ffd
-size 26440
diff -pruN 0.6.0-0.2/test/unit/x86_64/replace-section-references.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/replace-section-references.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/replace-section-references.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/replace-section-references.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:383827483e470394fb5d41fce5d9a71de2b281974b034a3415062902df198dec
-size 547392
diff -pruN 0.6.0-0.2/test/unit/x86_64/replace-section-references.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/replace-section-references.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/replace-section-references.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/replace-section-references.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f54a179c6a4abb64557016221a283c71fcdda2c524b9688dfc2730b35d22e251
-size 547680
diff -pruN 0.6.0-0.2/test/unit/x86_64/smp-locks-section.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/smp-locks-section.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/smp-locks-section.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/smp-locks-section.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8718b5b17db29fbf52f82eb40cfcd36c4f79e119e368f61321ab6578399c3cf1
-size 16784
diff -pruN 0.6.0-0.2/test/unit/x86_64/smp-locks-section.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/smp-locks-section.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/smp-locks-section.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/smp-locks-section.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:fb7a7b77873bb58768fd9c23fc56f1d1890530fac83290349db6bbaa8eb05c1e
-size 17088
diff -pruN 0.6.0-0.2/test/unit/x86_64/special-static-2.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/special-static-2.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/special-static-2.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/special-static-2.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:2331c16208f12843c84eb277fb63c7564e1b930f45632e4e423064413606a861
-size 525184
diff -pruN 0.6.0-0.2/test/unit/x86_64/special-static-2.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/special-static-2.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/special-static-2.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/special-static-2.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6db5ec7322ebc78086c8334235453c9fc99119447f02fcbdc2883936a88bc5a5
-size 525888
diff -pruN 0.6.0-0.2/test/unit/x86_64/special-static.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/special-static.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/special-static.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/special-static.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b901d86e5d599e6a88c12431df55a465d7afa2939af779b8dc720bbafa56522a
-size 89288
diff -pruN 0.6.0-0.2/test/unit/x86_64/special-static.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/special-static.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/special-static.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/special-static.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d2cd61e78c41a68816a93a0de97a2d30043c5279f0e5c80ad2692321ff0d6f4b
-size 89760
diff -pruN 0.6.0-0.2/test/unit/x86_64/tracepoints-section.ORIG.o 0.8.0-0ubuntu7/test/unit/x86_64/tracepoints-section.ORIG.o
--- 0.6.0-0.2/test/unit/x86_64/tracepoints-section.ORIG.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/tracepoints-section.ORIG.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0f00c311e4b79b03805ccd367e3ea889cef25c3f5db887b9c871ce1f200aa59e
-size 95048
diff -pruN 0.6.0-0.2/test/unit/x86_64/tracepoints-section.PATCHED.o 0.8.0-0ubuntu7/test/unit/x86_64/tracepoints-section.PATCHED.o
--- 0.6.0-0.2/test/unit/x86_64/tracepoints-section.PATCHED.o	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/test/unit/x86_64/tracepoints-section.PATCHED.o	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:198143f177fa687b07cc3f35f6af262a3901514416a4f69d4bbc701164f427d3
-size 95280
diff -pruN 0.6.0-0.2/.travis.yml 0.8.0-0ubuntu7/.travis.yml
--- 0.6.0-0.2/.travis.yml	2018-04-22 20:04:27.000000000 +0000
+++ 0.8.0-0ubuntu7/.travis.yml	2019-08-28 17:34:00.000000000 +0000
@@ -1,7 +1,7 @@
 language: c
 before_install:
   - sudo apt-get -qq update
-  - sudo apt-get install -y libelf-dev linux-headers-$(uname -r) shellcheck
+  - sudo apt-get install -y libelf-dev linux-headers-$(uname -r) shellcheck elfutils
 
 script:
   - make
