[libvirt] [PATCH v2] Rewrite the way mockable functions are handled.

Daniel P. Berrange posted 1 patch 6 years, 8 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20170804171342.16180-1-berrange@redhat.com
build-aux/mock-noinline.pl      | 22 +++--------
src/check-symfile.pl            |  2 +-
src/internal.h                  | 36 +++++++++++++-----
src/qemu/qemu_capabilities.c    |  7 ++--
src/qemu/qemu_capspriv.h        |  2 +-
src/rpc/virnetsocket.c          | 43 ++++++++++++----------
src/rpc/virnetsocket.h          |  6 +--
src/util/vircommand.c           |  4 +-
src/util/vircommand.h           |  2 +-
src/util/vircrypto.c            |  3 +-
src/util/vircrypto.h            |  2 +-
src/util/virfile.c              |  3 +-
src/util/virfile.h              |  2 +-
src/util/virhashcode.c          |  3 +-
src/util/virhashcode.h          |  3 +-
src/util/virhostcpu.c           | 12 ++++--
src/util/virhostcpu.h           |  4 +-
src/util/virmacaddr.c           |  5 ++-
src/util/virmacaddr.h           |  2 +-
src/util/virnetdev.c            | 25 ++++++++-----
src/util/virnetdev.h            |  9 ++---
src/util/virnetdevip.c          | 19 +++++-----
src/util/virnetdevip.h          |  2 +-
src/util/virnetdevopenvswitch.c |  7 ++--
src/util/virnetdevopenvswitch.h |  2 +-
src/util/virnetdevtap.c         | 40 +++++++++++---------
src/util/virnetdevtap.h         |  6 +--
src/util/virnuma.c              | 81 ++++++++++++++++++++++++-----------------
src/util/virnuma.h              | 16 ++++----
src/util/virrandom.c            | 14 ++++---
src/util/virrandom.h            |  6 +--
src/util/virscsi.c              | 11 +++---
src/util/virscsi.h              |  2 +-
src/util/virscsivhost.c         |  3 +-
src/util/virscsivhost.h         |  2 +-
src/util/virtpm.c               |  3 +-
src/util/virtpm.h               |  2 +-
src/util/virutil.c              | 24 ++++++++----
src/util/virutil.h              | 10 ++---
src/util/viruuid.c              |  4 +-
src/util/viruuid.h              |  2 +-
41 files changed, 257 insertions(+), 196 deletions(-)
[libvirt] [PATCH v2] Rewrite the way mockable functions are handled.
Posted by Daniel P. Berrange 6 years, 8 months ago
Currently any mockable functions are marked with attributes
noinline, noclone and weak. This prevents the compiler from
optimizing away the impl of these functions.

It has an unfortunate side effect with the libtool convenience
libraries, if executables directly link to them. For example
virlockd, virlogd both link to libvirt_util.la  When this is
done, the linker does not consider weak symbols as being
undefined, so it never copies them into the final executable.

In this new approach, we stop annotating the headers entirely.
Instead we create a weak function alias in the source.

   int fooImpl(void) {
      ..the real code..
   }

   int foo(void) __attribute__((noinline, noclone, weak, alias("fooImpl"))

If any functions in the same file call "foo", this prevents the
optimizer from inlining any part of fooImpl. When linking to the
libtool convenience static library, we also get all the symbols
present. Finally the test suite can just directly define a
'foo' function in its source, removing the need to use LD_PRELOAD
(though removal of LD_PRELOADS is left for a future patch).

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---

Changed in v2:

 - Use macro magic to define the alias

 build-aux/mock-noinline.pl      | 22 +++--------
 src/check-symfile.pl            |  2 +-
 src/internal.h                  | 36 +++++++++++++-----
 src/qemu/qemu_capabilities.c    |  7 ++--
 src/qemu/qemu_capspriv.h        |  2 +-
 src/rpc/virnetsocket.c          | 43 ++++++++++++----------
 src/rpc/virnetsocket.h          |  6 +--
 src/util/vircommand.c           |  4 +-
 src/util/vircommand.h           |  2 +-
 src/util/vircrypto.c            |  3 +-
 src/util/vircrypto.h            |  2 +-
 src/util/virfile.c              |  3 +-
 src/util/virfile.h              |  2 +-
 src/util/virhashcode.c          |  3 +-
 src/util/virhashcode.h          |  3 +-
 src/util/virhostcpu.c           | 12 ++++--
 src/util/virhostcpu.h           |  4 +-
 src/util/virmacaddr.c           |  5 ++-
 src/util/virmacaddr.h           |  2 +-
 src/util/virnetdev.c            | 25 ++++++++-----
 src/util/virnetdev.h            |  9 ++---
 src/util/virnetdevip.c          | 19 +++++-----
 src/util/virnetdevip.h          |  2 +-
 src/util/virnetdevopenvswitch.c |  7 ++--
 src/util/virnetdevopenvswitch.h |  2 +-
 src/util/virnetdevtap.c         | 40 +++++++++++---------
 src/util/virnetdevtap.h         |  6 +--
 src/util/virnuma.c              | 81 ++++++++++++++++++++++++-----------------
 src/util/virnuma.h              | 16 ++++----
 src/util/virrandom.c            | 14 ++++---
 src/util/virrandom.h            |  6 +--
 src/util/virscsi.c              | 11 +++---
 src/util/virscsi.h              |  2 +-
 src/util/virscsivhost.c         |  3 +-
 src/util/virscsivhost.h         |  2 +-
 src/util/virtpm.c               |  3 +-
 src/util/virtpm.h               |  2 +-
 src/util/virutil.c              | 24 ++++++++----
 src/util/virutil.h              | 10 ++---
 src/util/viruuid.c              |  4 +-
 src/util/viruuid.h              |  2 +-
 41 files changed, 257 insertions(+), 196 deletions(-)

diff --git a/build-aux/mock-noinline.pl b/build-aux/mock-noinline.pl
index eafe20d2e..cac46b767 100644
--- a/build-aux/mock-noinline.pl
+++ b/build-aux/mock-noinline.pl
@@ -8,12 +8,12 @@ my %mocked;
 $noninlined{"virEventAddTimeout"} = 1;
 
 foreach my $arg (@ARGV) {
-    if ($arg =~ /\.h$/) {
-        #print "Scan header $arg\n";
-        &scan_annotations($arg);
-    } elsif ($arg =~ /mock\.c$/) {
+    if ($arg =~ /mock\.c$/) {
         #print "Scan mock $arg\n";
         &scan_overrides($arg);
+    } elsif ($arg =~ /\.c$/) {
+        #print "Scan header $arg\n";
+        &scan_annotations($arg);
     }
 }
 
@@ -35,18 +35,8 @@ sub scan_annotations {
 
     my $func;
     while (<FH>) {
-        if (/^\s*(\w+)\(/ || /^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(/) {
-            my $name = $1;
-            if ($name !~ /ATTRIBUTE/) {
-                $func = $name;
-            }
-        } elsif (/^\s*$/) {
-            $func = undef;
-        }
-        if (/ATTRIBUTE_NOINLINE/) {
-            if (defined $func) {
-                $noninlined{$func} = 1;
-            }
+        if (/VIR_MOCKABLE\((\w+)\)/) {
+            $noninlined{$1} = 1;
         }
     }
 
diff --git a/src/check-symfile.pl b/src/check-symfile.pl
index d59a213eb..3b062d0a4 100755
--- a/src/check-symfile.pl
+++ b/src/check-symfile.pl
@@ -52,7 +52,7 @@ foreach my $elflib (@elflibs) {
     open NM, "-|", "nm", $elflib or die "cannot run 'nm $elflib': $!";
 
     while (<NM>) {
-        next unless /^\S+\s(?:[TBD])\s(\S+)\s*$/;
+        next unless /^\S+\s(?:[TBDW])\s(\S+)\s*$/;
 
         $gotsyms{$1} = 1;
     }
diff --git a/src/internal.h b/src/internal.h
index c29f20f02..6838f7798 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -113,16 +113,6 @@
 # endif
 
 /**
- * ATTRIBUTE_NOINLINE:
- *
- * Force compiler not to inline a method. Should be used if
- * the method need to be overridable by test mocks.
- */
-# ifndef ATTRIBUTE_NOINLINE
-#  define ATTRIBUTE_NOINLINE __attribute__((__noinline__))
-# endif
-
-/**
  * ATTRIBUTE_FMT_PRINTF
  *
  * Macro used to check printf like functions, if compiling
@@ -232,6 +222,32 @@
 #  define VIR_WARNINGS_NO_WLOGICALOP_STRCHR
 # endif
 
+# if WIN32
+#  if __GNUC_PREREQ(4, 5)
+#   define VIR_MOCKABLE(name)                                           \
+      typeof(name) name  ## Impl;                                       \
+      typeof(name) name                                                 \
+      __attribute__((noinline, noclone, __alias__(#name "Impl")))
+#  else
+#   define VIR_MOCKABLE(name)                                           \
+      typeof(name) name ## Impl;                                        \
+      typeof(name) name                                                 \
+      __attribute__((noinline, __alias__(#name "Impl")))
+#  endif
+# else
+#  if __GNUC_PREREQ(4, 5)
+#   define VIR_MOCKABLE(name)                                           \
+      typeof(name) name ##Impl;                                         \
+      typeof(name) name                                                 \
+      __attribute__((noinline, noclone, weak, __alias__(#name "Impl")))
+#  else
+#   define VIR_MOCKABLE(name)                                           \
+      typeof(name) name ##Impl;                                         \
+      typeof(name) name                                                 \
+      __attribute__((noinline, weak, __alias__(#name "Impl")))
+#  endif
+# endif
+
 
 /*
  * Use this when passing possibly-NULL strings to printf-a-likes.
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e61d2f7b0..f07af3c01 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1157,10 +1157,11 @@ virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
 }
 
 
+VIR_MOCKABLE(virQEMUCapsProbeHostCPUForEmulator);
 virCPUDefPtr
-virQEMUCapsProbeHostCPUForEmulator(virArch hostArch,
-                                   virQEMUCapsPtr qemuCaps,
-                                   virDomainVirtType type)
+virQEMUCapsProbeHostCPUForEmulatorImpl(virArch hostArch,
+                                       virQEMUCapsPtr qemuCaps,
+                                       virDomainVirtType type)
 {
     size_t nmodels;
     char **models;
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index d05256bd3..41763e3d4 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -81,7 +81,7 @@ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
 virCPUDefPtr
 virQEMUCapsProbeHostCPUForEmulator(virArch hostArch,
                                    virQEMUCapsPtr qemuCaps,
-                                   virDomainVirtType type) ATTRIBUTE_NOINLINE;
+                                   virDomainVirtType type);
 
 void
 virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index d228c8a8c..ee963bb60 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -1425,11 +1425,12 @@ int virNetSocketGetPort(virNetSocketPtr sock)
 
 
 #if defined(SO_PEERCRED)
-int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
-                                uid_t *uid,
-                                gid_t *gid,
-                                pid_t *pid,
-                                unsigned long long *timestamp)
+VIR_MOCKABLE(virNetSocketGetUNIXIdentity);
+int virNetSocketGetUNIXIdentityImpl(virNetSocketPtr sock,
+                                    uid_t *uid,
+                                    gid_t *gid,
+                                    pid_t *pid,
+                                    unsigned long long *timestamp)
 {
 # if defined(HAVE_STRUCT_SOCKPEERCRED)
     struct sockpeercred cr;
@@ -1482,11 +1483,12 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
 #  define VIR_SOL_PEERCRED 0
 # endif
 
-int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
-                                uid_t *uid,
-                                gid_t *gid,
-                                pid_t *pid,
-                                unsigned long long *timestamp)
+VIR_MOCKABLE(virNetSocketGetUNIXIdentity);
+int virNetSocketGetUNIXIdentityImpl(virNetSocketPtr sock,
+                                    uid_t *uid,
+                                    gid_t *gid,
+                                    pid_t *pid,
+                                    unsigned long long *timestamp)
 {
     struct xucred cr;
     socklen_t cr_len = sizeof(cr);
@@ -1550,11 +1552,12 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
     return ret;
 }
 #else
-int virNetSocketGetUNIXIdentity(virNetSocketPtr sock ATTRIBUTE_UNUSED,
-                                uid_t *uid ATTRIBUTE_UNUSED,
-                                gid_t *gid ATTRIBUTE_UNUSED,
-                                pid_t *pid ATTRIBUTE_UNUSED,
-                                unsigned long long *timestamp ATTRIBUTE_UNUSED)
+VIR_MOCKABLE(virNetSocketGetUNIXIdentity);
+int virNetSocketGetUNIXIdentityImpl(virNetSocketPtr sock ATTRIBUTE_UNUSED,
+                                    uid_t *uid ATTRIBUTE_UNUSED,
+                                    gid_t *gid ATTRIBUTE_UNUSED,
+                                    pid_t *pid ATTRIBUTE_UNUSED,
+                                    unsigned long long *timestamp ATTRIBUTE_UNUSED)
 {
     /* XXX Many more OS support UNIX socket credentials we could port to. See dbus ....*/
     virReportSystemError(ENOSYS, "%s",
@@ -1564,8 +1567,9 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock ATTRIBUTE_UNUSED,
 #endif
 
 #ifdef WITH_SELINUX
-int virNetSocketGetSELinuxContext(virNetSocketPtr sock,
-                                  char **context)
+VIR_MOCKABLE(virNetSocketGetSELinuxContext);
+int virNetSocketGetSELinuxContextImpl(virNetSocketPtr sock,
+                                      char **context)
 {
     security_context_t seccon = NULL;
     int ret = -1;
@@ -1593,8 +1597,9 @@ int virNetSocketGetSELinuxContext(virNetSocketPtr sock,
     return ret;
 }
 #else
-int virNetSocketGetSELinuxContext(virNetSocketPtr sock ATTRIBUTE_UNUSED,
-                                  char **context)
+VIR_MOCKABLE(virNetSocketGetSELinuxContext);
+int virNetSocketGetSELinuxContextImpl(virNetSocketPtr sock ATTRIBUTE_UNUSED,
+                                      char **context)
 {
     *context = NULL;
     return 0;
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index de795af91..1e75ee62b 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -136,11 +136,9 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
                                 uid_t *uid,
                                 gid_t *gid,
                                 pid_t *pid,
-                                unsigned long long *timestamp)
-    ATTRIBUTE_NOINLINE;
+                                unsigned long long *timestamp);
 int virNetSocketGetSELinuxContext(virNetSocketPtr sock,
-                                  char **context)
-    ATTRIBUTE_NOINLINE;
+                                  char **context);
 
 int virNetSocketSetBlocking(virNetSocketPtr sock,
                             bool blocking);
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 60c1121da..5ecd7fdaa 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -985,8 +985,9 @@ virCommandNewVAList(const char *binary, va_list list)
  * be closed in the parent no later than Run/RunAsync/Free. The parent
  * should cease using the @fd when this call completes
  */
+VIR_MOCKABLE(virCommandPassFD);
 void
-virCommandPassFD(virCommandPtr cmd, int fd, unsigned int flags)
+virCommandPassFDImpl(virCommandPtr cmd, int fd, unsigned int flags)
 {
     int ret = 0;
 
@@ -1012,6 +1013,7 @@ virCommandPassFD(virCommandPtr cmd, int fd, unsigned int flags)
     }
 }
 
+
 /**
  * virCommandPassListenFDs:
  * @cmd: the command to modify
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index e7c2e513b..99dcdeb54 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -58,7 +58,7 @@ enum {
 
 void virCommandPassFD(virCommandPtr cmd,
                       int fd,
-                      unsigned int flags) ATTRIBUTE_NOINLINE;
+                      unsigned int flags);
 
 void virCommandPassListenFDs(virCommandPtr cmd);
 
diff --git a/src/util/vircrypto.c b/src/util/vircrypto.c
index 48b04fc8c..de9f637dd 100644
--- a/src/util/vircrypto.c
+++ b/src/util/vircrypto.c
@@ -300,8 +300,9 @@ virCryptoEncryptData(virCryptoCipher algorithm,
  *
  * Returns pointer memory containing byte stream on success, NULL on failure
  */
+VIR_MOCKABLE(virCryptoGenerateRandom);
 uint8_t *
-virCryptoGenerateRandom(size_t nbytes)
+virCryptoGenerateRandomImpl(size_t nbytes)
 {
     uint8_t *buf;
     int ret;
diff --git a/src/util/vircrypto.h b/src/util/vircrypto.h
index 068602f5d..52ba3b3ad 100644
--- a/src/util/vircrypto.h
+++ b/src/util/vircrypto.h
@@ -55,6 +55,6 @@ int virCryptoEncryptData(virCryptoCipher algorithm,
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6)
     ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(9) ATTRIBUTE_RETURN_CHECK;
 
-uint8_t *virCryptoGenerateRandom(size_t nbytes) ATTRIBUTE_NOINLINE;
+uint8_t *virCryptoGenerateRandom(size_t nbytes);
 
 #endif /* __VIR_CRYPTO_H__ */
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 2f28e83f4..5bdd336dc 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -1824,8 +1824,9 @@ virFileIsDir(const char *path)
  * Returns true if the file exists, false if it doesn't, setting errno
  * appropriately.
  */
+VIR_MOCKABLE(virFileExists);
 bool
-virFileExists(const char *path)
+virFileExistsImpl(const char *path)
 {
     return access(path, F_OK) == 0;
 }
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 57ceb8072..40034f08f 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -188,7 +188,7 @@ void virFileActivateDirOverride(const char *argv0)
 
 off_t virFileLength(const char *path, int fd) ATTRIBUTE_NONNULL(1);
 bool virFileIsDir (const char *file) ATTRIBUTE_NONNULL(1);
-bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NOINLINE;
+bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1);
 bool virFileIsExecutable(const char *file) ATTRIBUTE_NONNULL(1);
 
 enum {
diff --git a/src/util/virhashcode.c b/src/util/virhashcode.c
index 310ec891c..3adca6740 100644
--- a/src/util/virhashcode.c
+++ b/src/util/virhashcode.c
@@ -56,7 +56,8 @@ static inline uint32_t fmix(uint32_t h)
 }
 
 
-uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed)
+VIR_MOCKABLE(virHashCodeGen);
+uint32_t virHashCodeGenImpl(const void *key, size_t len, uint32_t seed)
 {
     const uint8_t *blocks;
     const uint8_t *tail;
diff --git a/src/util/virhashcode.h b/src/util/virhashcode.h
index f8171df26..7732f816c 100644
--- a/src/util/virhashcode.h
+++ b/src/util/virhashcode.h
@@ -30,7 +30,6 @@
 
 # include "internal.h"
 
-uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed)
-    ATTRIBUTE_NOINLINE;
+uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed);
 
 #endif /* __VIR_HASH_CODE_H__ */
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index c485a9721..31a513e93 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -1112,8 +1112,9 @@ virHostCPUGetMap(unsigned char **cpumap,
  *
  * Returns the number of threads per subcore if subcores are in use, zero
  * if subcores are not in use, and a negative value on error */
+VIR_MOCKABLE(virHostCPUGetThreadsPerSubcore);
 int
-virHostCPUGetThreadsPerSubcore(virArch arch)
+virHostCPUGetThreadsPerSubcoreImpl(virArch arch)
 {
     int threads_per_subcore = 0;
     int kvmfd;
@@ -1158,8 +1159,9 @@ virHostCPUGetThreadsPerSubcore(virArch arch)
 
 /* Fallback for nodeGetThreadsPerSubcore() used when KVM headers
  * are not available on the system */
+VIR_MOCKABLE(virHostCPUGetThreadsPerSubcore);
 int
-virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
+virHostCPUGetThreadsPerSubcoreImpl(virArch arch ATTRIBUTE_UNUSED)
 {
     return 0;
 }
@@ -1167,8 +1169,9 @@ virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
 #endif /* HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT) */
 
 #if HAVE_LINUX_KVM_H
+VIR_MOCKABLE(virHostCPUGetKVMMaxVCPUs);
 int
-virHostCPUGetKVMMaxVCPUs(void)
+virHostCPUGetKVMMaxVCPUsImpl(void)
 {
     int fd;
     int ret;
@@ -1198,8 +1201,9 @@ virHostCPUGetKVMMaxVCPUs(void)
     return ret;
 }
 #else
+VIR_MOCKABLE(virHostCPUGetKVMMaxVCPUs);
 int
-virHostCPUGetKVMMaxVCPUs(void)
+virHostCPUGetKVMMaxVCPUsImpl(void)
 {
     virReportSystemError(ENOSYS, "%s",
                          _("KVM is not supported on this platform"));
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
index 67033de84..e9c22eecc 100644
--- a/src/util/virhostcpu.h
+++ b/src/util/virhostcpu.h
@@ -38,7 +38,7 @@ bool virHostCPUHasBitmap(void);
 virBitmapPtr virHostCPUGetPresentBitmap(void);
 virBitmapPtr virHostCPUGetOnlineBitmap(void);
 int virHostCPUGetCount(void);
-int virHostCPUGetThreadsPerSubcore(virArch arch) ATTRIBUTE_NOINLINE;
+int virHostCPUGetThreadsPerSubcore(virArch arch);
 
 int virHostCPUGetMap(unsigned char **cpumap,
                      unsigned int *online,
@@ -51,7 +51,7 @@ int virHostCPUGetInfo(virArch hostarch,
                       unsigned int *cores,
                       unsigned int *threads);
 
-int virHostCPUGetKVMMaxVCPUs(void) ATTRIBUTE_NOINLINE;
+int virHostCPUGetKVMMaxVCPUs(void);
 
 int virHostCPUStatsAssign(virNodeCPUStatsPtr param,
                           const char *name,
diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c
index 7afe032b9..c198b4a86 100644
--- a/src/util/virmacaddr.c
+++ b/src/util/virmacaddr.c
@@ -223,8 +223,9 @@ virMacAddrParseHex(const char *str, virMacAddrPtr addr)
     return 0;
 }
 
-void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
-                        virMacAddrPtr addr)
+VIR_MOCKABLE(virMacAddrGenerate);
+void virMacAddrGenerateImpl(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
+                            virMacAddrPtr addr)
 {
     addr->addr[0] = prefix[0];
     addr->addr[1] = prefix[1];
diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h
index f4f5e2ce1..ae26867d4 100644
--- a/src/util/virmacaddr.h
+++ b/src/util/virmacaddr.h
@@ -48,7 +48,7 @@ void virMacAddrGetRaw(const virMacAddr *src, unsigned char dst[VIR_MAC_BUFLEN]);
 const char *virMacAddrFormat(const virMacAddr *addr,
                              char *str);
 void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
-                        virMacAddrPtr addr) ATTRIBUTE_NOINLINE;
+                        virMacAddrPtr addr);
 int virMacAddrParse(const char* str,
                     virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK;
 int virMacAddrParseHex(const char* str,
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 90b7bee34..374291d76 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -346,9 +346,10 @@ virNetDevSetMACInternal(const char *ifname,
 #endif
 
 
+VIR_MOCKABLE(virNetDevSetMAC);
 int
-virNetDevSetMAC(const char *ifname,
-                const virMacAddr *macaddr)
+virNetDevSetMACImpl(const char *ifname,
+                    const virMacAddr *macaddr)
 {
     return virNetDevSetMACInternal(ifname, macaddr, false);
 }
@@ -686,9 +687,10 @@ virNetDevSetIFFlag(const char *ifname,
  *
  * Returns 0 in case of success or -1 on error.
  */
+VIR_MOCKABLE(virNetDevSetOnline);
 int
-virNetDevSetOnline(const char *ifname,
-                   bool online)
+virNetDevSetOnlineImpl(const char *ifname,
+                       bool online)
 {
 
     return virNetDevSetIFFlag(ifname, VIR_IFF_UP, online);
@@ -1122,9 +1124,10 @@ int virNetDevValidateConfig(const char *ifname ATTRIBUTE_UNUSED,
 
 #ifdef __linux__
 
+VIR_MOCKABLE(virNetDevSysfsFile);
 int
-virNetDevSysfsFile(char **pf_sysfs_device_link, const char *ifname,
-                   const char *file)
+virNetDevSysfsFileImpl(char **pf_sysfs_device_link, const char *ifname,
+                       const char *file)
 {
 
     if (virAsprintf(pf_sysfs_device_link, SYSFS_NET_DIR "%s/%s", ifname, file) < 0)
@@ -1491,10 +1494,11 @@ virNetDevGetVirtualFunctionInfo(const char *vfname ATTRIBUTE_UNUSED,
     return -1;
 }
 
+VIR_MOCKABLE(virNetDevSysfsFile);
 int
-virNetDevSysfsFile(char **pf_sysfs_device_link ATTRIBUTE_UNUSED,
-                   const char *ifname ATTRIBUTE_UNUSED,
-                   const char *file ATTRIBUTE_UNUSED)
+virNetDevSysfsFileImpl(char **pf_sysfs_device_link ATTRIBUTE_UNUSED,
+                       const char *ifname ATTRIBUTE_UNUSED,
+                       const char *file ATTRIBUTE_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
                          _("Unable to get sysfs info on this platform"));
@@ -3268,8 +3272,9 @@ int virNetDevSetCoalesce(const char *ifname,
  * This function executes script for new tap device created by libvirt.
  * Returns 0 in case of success or -1 on failure
  */
+VIR_MOCKABLE(virNetDevRunEthernetScript);
 int
-virNetDevRunEthernetScript(const char *ifname, const char *script)
+virNetDevRunEthernetScriptImpl(const char *ifname, const char *script)
 {
     virCommandPtr cmd;
     int ret;
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 51fcae544..c2c09af63 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -156,7 +156,7 @@ int virNetDevExists(const char *brname)
 
 int virNetDevSetOnline(const char *ifname,
                        bool online)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
 int virNetDevGetOnline(const char *ifname,
                       bool *online)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
@@ -164,7 +164,7 @@ int virNetDevGetOnline(const char *ifname,
 
 int virNetDevSetMAC(const char *ifname,
                     const virMacAddr *macaddr)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 int virNetDevGetMAC(const char *ifname,
                     virMacAddrPtr macaddr)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
@@ -303,8 +303,7 @@ int virNetDevSysfsFile(char **pf_sysfs_device_link,
                        const char *ifname,
                        const char *file)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_RETURN_CHECK;
 
-int virNetDevRunEthernetScript(const char *ifname, const char *script)
-    ATTRIBUTE_NOINLINE;
+int virNetDevRunEthernetScript(const char *ifname, const char *script);
 #endif /* __VIR_NETDEV_H__ */
diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index bf98ed8a5..b0c225001 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -163,11 +163,12 @@ virNetDevCreateNetlinkAddressMessage(int messageType,
  *
  * Returns 0 in case of success or -1 in case of error.
  */
+VIR_MOCKABLE(virNetDevIPAddrAdd);
 int
-virNetDevIPAddrAdd(const char *ifname,
-                   virSocketAddr *addr,
-                   virSocketAddr *peer,
-                   unsigned int prefix)
+virNetDevIPAddrAddImpl(const char *ifname,
+                       virSocketAddr *addr,
+                       virSocketAddr *peer,
+                       unsigned int prefix)
 {
     virSocketAddr *broadcast = NULL;
     int ret = -1;
@@ -680,12 +681,12 @@ virNetDevIPCheckIPv6Forwarding(void)
 
 #else /* defined(__linux__) && defined(HAVE_LIBNL) */
 
-
+VIR_MOCKABLE(virNetDevIPAddrAdd);
 int
-virNetDevIPAddrAdd(const char *ifname,
-                   virSocketAddr *addr,
-                   virSocketAddr *peer,
-                   unsigned int prefix)
+virNetDevIPAddrAddImpl(const char *ifname,
+                       virSocketAddr *addr,
+                       virSocketAddr *peer,
+                       unsigned int prefix)
 {
     virCommandPtr cmd = NULL;
     char *addrstr = NULL, *bcaststr = NULL, *peerstr = NULL;
diff --git a/src/util/virnetdevip.h b/src/util/virnetdevip.h
index 6b509ea44..cc466ca25 100644
--- a/src/util/virnetdevip.h
+++ b/src/util/virnetdevip.h
@@ -67,7 +67,7 @@ int virNetDevIPAddrAdd(const char *ifname,
                        virSocketAddr *addr,
                        virSocketAddr *peer,
                        unsigned int prefix)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 int virNetDevIPRouteAdd(const char *ifname,
                         virSocketAddrPtr addr,
                         unsigned int prefix,
diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
index 06ce9d8ee..bf1d71bbf 100644
--- a/src/util/virnetdevopenvswitch.c
+++ b/src/util/virnetdevopenvswitch.c
@@ -405,7 +405,7 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
 }
 
 /**
- * virNetDevOpenvswitchVhostuserGetIfname:
+ * virNetDevOpenvswitchGetVhostuserIfname:
  * @path: the path of the unix socket
  * @ifname: the retrieved name of the interface
  *
@@ -415,9 +415,10 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
  *          0 if it is not, but no other error occurred,
  *         -1 otherwise.
  */
+VIR_MOCKABLE(virNetDevOpenvswitchGetVhostuserIfname);
 int
-virNetDevOpenvswitchGetVhostuserIfname(const char *path,
-                                       char **ifname)
+virNetDevOpenvswitchGetVhostuserIfnameImpl(const char *path,
+                                           char **ifname)
 {
     virCommandPtr cmd = NULL;
     char *tmpIfname = NULL;
diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h
index 6f6e620c2..7965dee5b 100644
--- a/src/util/virnetdevopenvswitch.h
+++ b/src/util/virnetdevopenvswitch.h
@@ -59,7 +59,7 @@ int virNetDevOpenvswitchInterfaceStats(const char *ifname,
 
 int virNetDevOpenvswitchGetVhostuserIfname(const char *path,
                                            char **ifname)
-    ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 
 int virNetDevOpenvswitchUpdateVlan(const char *ifname,
                                    virNetDevVlanPtr virtVlan)
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index 175dc2bfa..9971f6675 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -98,8 +98,9 @@ virNetDevTapGetName(int tapfd ATTRIBUTE_UNUSED, char **ifname ATTRIBUTE_UNUSED)
  * Returns the proper interface name or NULL if no corresponding interface
  * found.
  */
+VIR_MOCKABLE(virNetDevTapGetRealDeviceName);
 char*
-virNetDevTapGetRealDeviceName(char *ifname ATTRIBUTE_UNUSED)
+virNetDevTapGetRealDeviceNameImpl(char *ifname ATTRIBUTE_UNUSED)
 {
 #ifdef TAPGIFNAME
     char *ret = NULL;
@@ -238,11 +239,12 @@ virNetDevProbeVnetHdr(int tapfd)
  *
  * Returns 0 in case of success or -1 on failure.
  */
-int virNetDevTapCreate(char **ifname,
-                       const char *tunpath,
-                       int *tapfd,
-                       size_t tapfdSize,
-                       unsigned int flags)
+VIR_MOCKABLE(virNetDevTapCreate);
+int virNetDevTapCreateImpl(char **ifname,
+                           const char *tunpath,
+                           int *tapfd,
+                           size_t tapfdSize,
+                           unsigned int flags)
 {
     size_t i;
     struct ifreq ifr;
@@ -373,11 +375,12 @@ int virNetDevTapDelete(const char *ifname,
     return ret;
 }
 #elif defined(SIOCIFCREATE2) && defined(SIOCIFDESTROY) && defined(IF_MAXUNIT)
-int virNetDevTapCreate(char **ifname,
-                       const char *tunpath ATTRIBUTE_UNUSED,
-                       int *tapfd,
-                       size_t tapfdSize,
-                       unsigned int flags ATTRIBUTE_UNUSED)
+VIR_MOCKABLE(virNetDevTapCreate);
+int virNetDevTapCreateImpl(char **ifname,
+                           const char *tunpath ATTRIBUTE_UNUSED,
+                           int *tapfd,
+                           size_t tapfdSize,
+                           unsigned int flags ATTRIBUTE_UNUSED)
 {
     int s;
     struct ifreq ifr;
@@ -484,11 +487,12 @@ int virNetDevTapDelete(const char *ifname,
 }
 
 #else
-int virNetDevTapCreate(char **ifname ATTRIBUTE_UNUSED,
-                       const char *tunpath ATTRIBUTE_UNUSED,
-                       int *tapfd ATTRIBUTE_UNUSED,
-                       size_t tapfdSize ATTRIBUTE_UNUSED,
-                       unsigned int flags ATTRIBUTE_UNUSED)
+VIR_MOCKABLE(virNetDevTapCreate);
+int virNetDevTapCreateImpl(char **ifname ATTRIBUTE_UNUSED,
+                           const char *tunpath ATTRIBUTE_UNUSED,
+                           int *tapfd ATTRIBUTE_UNUSED,
+                           size_t tapfdSize ATTRIBUTE_UNUSED,
+                           unsigned int flags ATTRIBUTE_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
                          _("Unable to create TAP devices on this platform"));
@@ -608,7 +612,9 @@ virNetDevTapAttachBridge(const char *tapname,
  *
  * Returns 0 in case of success or -1 on failure
  */
-int virNetDevTapCreateInBridgePort(const char *brname,
+VIR_MOCKABLE(virNetDevTapCreateInBridgePort);
+int
+virNetDevTapCreateInBridgePortImpl(const char *brname,
                                    char **ifname,
                                    const virMacAddr *macaddr,
                                    const unsigned char *vmuuid,
diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
index 0b17feb8d..bd5ec14d4 100644
--- a/src/util/virnetdevtap.h
+++ b/src/util/virnetdevtap.h
@@ -39,7 +39,7 @@ int virNetDevTapCreate(char **ifname,
                        int *tapfd,
                        size_t tapfdSize,
                        unsigned int flags)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
 
 int virNetDevTapDelete(const char *ifname,
                        const char *tunpath)
@@ -49,7 +49,7 @@ int virNetDevTapGetName(int tapfd, char **ifname)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 
 char* virNetDevTapGetRealDeviceName(char *ifname)
-      ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+      ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
 
 typedef enum {
    VIR_NETDEV_TAP_CREATE_NONE = 0,
@@ -89,7 +89,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
                                    unsigned int *actualMTU,
                                    unsigned int flags)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
-    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_RETURN_CHECK;
 
 int virNetDevTapInterfaceStats(const char *ifname,
                                virDomainInterfaceStatsPtr stats)
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index bebe301f8..77a954d2f 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -160,8 +160,9 @@ virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode,
     return ret;
 }
 
+VIR_MOCKABLE(virNumaIsAvailable);
 bool
-virNumaIsAvailable(void)
+virNumaIsAvailableImpl(void)
 {
     return numa_available() != -1;
 }
@@ -174,8 +175,9 @@ virNumaIsAvailable(void)
  *
  * Returns the highest NUMA node id on success, -1 on error.
  */
+VIR_MOCKABLE(virNumaGetMaxNode);
 int
-virNumaGetMaxNode(void)
+virNumaGetMaxNodeImpl(void)
 {
     int ret;
 
@@ -207,10 +209,11 @@ virNumaGetMaxNode(void)
  *
  * Returns 0 on success, -1 on error. Does not report errors.
  */
+VIR_MOCKABLE(virNumaGetNodeMemory);
 int
-virNumaGetNodeMemory(int node,
-                     unsigned long long *memsize,
-                     unsigned long long *memfree)
+virNumaGetNodeMemoryImpl(int node,
+                         unsigned long long *memsize,
+                         unsigned long long *memfree)
 {
     long long node_size;
     long long node_free;
@@ -248,9 +251,10 @@ virNumaGetNodeMemory(int node,
 # define n_bits(var) (8 * sizeof(var))
 # define MASK_CPU_ISSET(mask, cpu) \
   (((mask)[((cpu) / n_bits(*(mask)))] >> ((cpu) % n_bits(*(mask)))) & 1)
+VIR_MOCKABLE(virNumaGetNodeCPUs);
 int
-virNumaGetNodeCPUs(int node,
-                   virBitmapPtr *cpus)
+virNumaGetNodeCPUsImpl(int node,
+                       virBitmapPtr *cpus)
 {
     unsigned long *mask = NULL;
     unsigned long *allonesmask = NULL;
@@ -321,15 +325,17 @@ virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode ATTRIBUTE_UNUSED,
     return 0;
 }
 
+VIR_MOCKABLE(virNumaIsAvailable);
 bool
-virNumaIsAvailable(void)
+virNumaIsAvailableImpl(void)
 {
     return false;
 }
 
 
+VIR_MOCKABLE(virNumaGetMaxNode);
 int
-virNumaGetMaxNode(void)
+virNumaGetMaxNodeImpl(void)
 {
     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("NUMA isn't available on this host"));
@@ -337,10 +343,11 @@ virNumaGetMaxNode(void)
 }
 
 
+VIR_MOCKABLE(virNumaGetNodeMemory);
 int
-virNumaGetNodeMemory(int node ATTRIBUTE_UNUSED,
-                     unsigned long long *memsize,
-                     unsigned long long *memfree)
+virNumaGetNodeMemoryImpl(int node ATTRIBUTE_UNUSED,
+                         unsigned long long *memsize,
+                         unsigned long long *memfree)
 {
     if (memsize)
         *memsize = 0;
@@ -353,9 +360,10 @@ virNumaGetNodeMemory(int node ATTRIBUTE_UNUSED,
 }
 
 
+VIR_MOCKABLE(virNumaGetNodeCPUs);
 int
-virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED,
-                   virBitmapPtr *cpus)
+virNumaGetNodeCPUsImpl(int node ATTRIBUTE_UNUSED,
+                       virBitmapPtr *cpus)
 {
     *cpus = NULL;
 
@@ -390,8 +398,9 @@ virNumaGetMaxCPUs(void)
  * Returns: true if @node is available,
  *          false if @node doesn't exist
  */
+VIR_MOCKABLE(virNumaNodeIsAvailable);
 bool
-virNumaNodeIsAvailable(int node)
+virNumaNodeIsAvailableImpl(int node)
 {
     return numa_bitmask_isbitset(numa_nodes_ptr, node);
 }
@@ -416,10 +425,11 @@ virNumaNodeIsAvailable(int node)
  *
  * Returns 0 on success, -1 otherwise.
  */
+VIR_MOCKABLE(virNumaGetDistances);
 int
-virNumaGetDistances(int node,
-                    int **distances,
-                    int *ndistances)
+virNumaGetDistancesImpl(int node,
+                        int **distances,
+                        int *ndistances)
 {
     int ret = -1;
     int max_node;
@@ -454,8 +464,9 @@ virNumaGetDistances(int node,
 
 #else /* !(WITH_NUMACTL && HAVE_NUMA_BITMASK_ISBITSET) */
 
+VIR_MOCKABLE(virNumaNodeIsAvailable);
 bool
-virNumaNodeIsAvailable(int node)
+virNumaNodeIsAvailableImpl(int node)
 {
     int max_node = virNumaGetMaxNode();
 
@@ -467,10 +478,11 @@ virNumaNodeIsAvailable(int node)
 }
 
 
+VIR_MOCKABLE(virNumaGetDistances);
 int
-virNumaGetDistances(int node ATTRIBUTE_UNUSED,
-                    int **distances,
-                    int *ndistances)
+virNumaGetDistancesImpl(int node ATTRIBUTE_UNUSED,
+                        int **distances,
+                        int *ndistances)
 {
     *distances = NULL;
     *ndistances = 0;
@@ -706,12 +718,13 @@ virNumaGetPageInfo(int node,
  *
  * Returns 0 on success, -1 otherwise.
  */
+VIR_MOCKABLE(virNumaGetPages);
 int
-virNumaGetPages(int node,
-                unsigned int **pages_size,
-                unsigned int **pages_avail,
-                unsigned int **pages_free,
-                size_t *npages)
+virNumaGetPagesImpl(int node,
+                    unsigned int **pages_size,
+                    unsigned int **pages_avail,
+                    unsigned int **pages_free,
+                    size_t *npages)
 {
     int ret = -1;
     char *path = NULL;
@@ -943,12 +956,13 @@ virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
 }
 
 
+VIR_MOCKABLE(virNumaGetPages);
 int
-virNumaGetPages(int node ATTRIBUTE_UNUSED,
-                unsigned int **pages_size ATTRIBUTE_UNUSED,
-                unsigned int **pages_avail ATTRIBUTE_UNUSED,
-                unsigned int **pages_free ATTRIBUTE_UNUSED,
-                size_t *npages ATTRIBUTE_UNUSED)
+virNumaGetPagesImpl(int node ATTRIBUTE_UNUSED,
+                    unsigned int **pages_size ATTRIBUTE_UNUSED,
+                    unsigned int **pages_avail ATTRIBUTE_UNUSED,
+                    unsigned int **pages_free ATTRIBUTE_UNUSED,
+                    size_t *npages ATTRIBUTE_UNUSED)
 {
     virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                    _("page info is not supported on this platform"));
@@ -968,8 +982,9 @@ virNumaSetPagePoolSize(int node ATTRIBUTE_UNUSED,
 }
 #endif /* #ifdef __linux__ */
 
+VIR_MOCKABLE(virNumaNodesetIsAvailable);
 bool
-virNumaNodesetIsAvailable(virBitmapPtr nodeset)
+virNumaNodesetIsAvailableImpl(virBitmapPtr nodeset)
 {
     ssize_t bit = -1;
 
diff --git a/src/util/virnuma.h b/src/util/virnuma.h
index e4e1fd0b9..f3eef324a 100644
--- a/src/util/virnuma.h
+++ b/src/util/virnuma.h
@@ -34,20 +34,20 @@ int virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode,
                              virBitmapPtr nodeset);
 
 virBitmapPtr virNumaGetHostMemoryNodeset(void);
-bool virNumaNodesetIsAvailable(virBitmapPtr nodeset) ATTRIBUTE_NOINLINE;
-bool virNumaIsAvailable(void) ATTRIBUTE_NOINLINE;
-int virNumaGetMaxNode(void) ATTRIBUTE_NOINLINE;
-bool virNumaNodeIsAvailable(int node) ATTRIBUTE_NOINLINE;
+bool virNumaNodesetIsAvailable(virBitmapPtr nodeset);
+bool virNumaIsAvailable(void);
+int virNumaGetMaxNode(void);
+bool virNumaNodeIsAvailable(int node);
 int virNumaGetDistances(int node,
                         int **distances,
-                        int *ndistances) ATTRIBUTE_NOINLINE;
+                        int *ndistances);
 int virNumaGetNodeMemory(int node,
                          unsigned long long *memsize,
-                         unsigned long long *memfree) ATTRIBUTE_NOINLINE;
+                         unsigned long long *memfree);
 
 unsigned int virNumaGetMaxCPUs(void);
 
-int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus) ATTRIBUTE_NOINLINE;
+int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus);
 
 int virNumaGetPageInfo(int node,
                        unsigned int page_size,
@@ -59,7 +59,7 @@ int virNumaGetPages(int node,
                     unsigned int **pages_avail,
                     unsigned int **pages_free,
                     size_t *npages)
-    ATTRIBUTE_NONNULL(5) ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(5);
 int virNumaSetPagePoolSize(int node,
                            unsigned int page_size,
                            unsigned long long page_count,
diff --git a/src/util/virrandom.c b/src/util/virrandom.c
index 41daa404b..2accf9532 100644
--- a/src/util/virrandom.c
+++ b/src/util/virrandom.c
@@ -99,7 +99,8 @@ VIR_ONCE_GLOBAL_INIT(virRandom)
  *
  * Return: a random number with @nbits entropy
  */
-uint64_t virRandomBits(int nbits)
+VIR_MOCKABLE(virRandomBits);
+uint64_t virRandomBitsImpl(int nbits)
 {
     uint64_t ret = 0;
     int32_t bits;
@@ -170,9 +171,10 @@ uint32_t virRandomInt(uint32_t max)
  *
  * Returns 0 on success or an errno on failure
  */
+VIR_MOCKABLE(virRandomBytes);
 int
-virRandomBytes(unsigned char *buf,
-               size_t buflen)
+virRandomBytesImpl(unsigned char *buf,
+                   size_t buflen)
 {
     int fd;
 
@@ -204,10 +206,10 @@ virRandomBytes(unsigned char *buf,
 #define MICROSOFT_OUI "0050f2"
 #define XEN_OUI "00163e"
 
-
+VIR_MOCKABLE(virRandomGenerateWWN);
 int
-virRandomGenerateWWN(char **wwn,
-                     const char *virt_type)
+virRandomGenerateWWNImpl(char **wwn,
+                         const char *virt_type)
 {
     const char *oui = NULL;
 
diff --git a/src/util/virrandom.h b/src/util/virrandom.h
index 7a984ee7b..f457d2de6 100644
--- a/src/util/virrandom.h
+++ b/src/util/virrandom.h
@@ -24,11 +24,11 @@
 
 # include "internal.h"
 
-uint64_t virRandomBits(int nbits) ATTRIBUTE_NOINLINE;
+uint64_t virRandomBits(int nbits);
 double virRandom(void);
 uint32_t virRandomInt(uint32_t max);
 int virRandomBytes(unsigned char *buf, size_t buflen)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE;
-int virRandomGenerateWWN(char **wwn, const char *virt_type) ATTRIBUTE_NOINLINE;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virRandomGenerateWWN(char **wwn, const char *virt_type);
 
 #endif /* __VIR_RANDOM_H__ */
diff --git a/src/util/virscsi.c b/src/util/virscsi.c
index 22f2677a3..8433a244d 100644
--- a/src/util/virscsi.c
+++ b/src/util/virscsi.c
@@ -109,12 +109,13 @@ virSCSIDeviceGetAdapterId(const char *adapter,
     return -1;
 }
 
+VIR_MOCKABLE(virSCSIDeviceGetSgName);
 char *
-virSCSIDeviceGetSgName(const char *sysfs_prefix,
-                       const char *adapter,
-                       unsigned int bus,
-                       unsigned int target,
-                       unsigned long long unit)
+virSCSIDeviceGetSgNameImpl(const char *sysfs_prefix,
+                           const char *adapter,
+                           unsigned int bus,
+                           unsigned int target,
+                           unsigned long long unit)
 {
     DIR *dir = NULL;
     struct dirent *entry;
diff --git a/src/util/virscsi.h b/src/util/virscsi.h
index 9f8b3ecf1..7d88d4e70 100644
--- a/src/util/virscsi.h
+++ b/src/util/virscsi.h
@@ -37,7 +37,7 @@ char *virSCSIDeviceGetSgName(const char *sysfs_prefix,
                              const char *adapter,
                              unsigned int bus,
                              unsigned int target,
-                             unsigned long long unit) ATTRIBUTE_NOINLINE;
+                             unsigned long long unit);
 char *virSCSIDeviceGetDevName(const char *sysfs_prefix,
                               const char *adapter,
                               unsigned int bus,
diff --git a/src/util/virscsivhost.c b/src/util/virscsivhost.c
index dc7df757a..bd581dc1f 100644
--- a/src/util/virscsivhost.c
+++ b/src/util/virscsivhost.c
@@ -83,8 +83,9 @@ virSCSIVHostOnceInit(void)
 VIR_ONCE_GLOBAL_INIT(virSCSIVHost)
 
 
+VIR_MOCKABLE(virSCSIVHostOpenVhostSCSI);
 int
-virSCSIVHostOpenVhostSCSI(int *vhostfd)
+virSCSIVHostOpenVhostSCSIImpl(int *vhostfd)
 {
     if (!virFileExists(VHOST_SCSI_DEVICE))
         goto error;
diff --git a/src/util/virscsivhost.h b/src/util/virscsivhost.h
index 21887ddbd..6018b835e 100644
--- a/src/util/virscsivhost.h
+++ b/src/util/virscsivhost.h
@@ -61,6 +61,6 @@ void virSCSIVHostDeviceGetUsedBy(virSCSIVHostDevicePtr dev,
                                  const char **drv_name,
                                  const char **dom_name);
 void virSCSIVHostDeviceFree(virSCSIVHostDevicePtr dev);
-int virSCSIVHostOpenVhostSCSI(int *vhostfd) ATTRIBUTE_NOINLINE;
+int virSCSIVHostOpenVhostSCSI(int *vhostfd);
 
 #endif /* __VIR_SCSIHOST_H__ */
diff --git a/src/util/virtpm.c b/src/util/virtpm.c
index 6d9b0657a..b4b3581ed 100644
--- a/src/util/virtpm.c
+++ b/src/util/virtpm.c
@@ -38,8 +38,9 @@
  *
  * Create the cancel path given the path to the TPM device
  */
+VIR_MOCKABLE(virTPMCreateCancelPath);
 char *
-virTPMCreateCancelPath(const char *devpath)
+virTPMCreateCancelPathImpl(const char *devpath)
 {
     char *path = NULL;
     const char *dev;
diff --git a/src/util/virtpm.h b/src/util/virtpm.h
index b21fc0532..fe71307a1 100644
--- a/src/util/virtpm.h
+++ b/src/util/virtpm.h
@@ -22,6 +22,6 @@
 #ifndef __VIR_TPM_H__
 # define __VIR_TPM_H__
 
-char *virTPMCreateCancelPath(const char *devpath) ATTRIBUTE_NOINLINE;
+char *virTPMCreateCancelPath(const char *devpath);
 
 #endif /* __VIR_TPM_H__ */
diff --git a/src/util/virutil.c b/src/util/virutil.c
index e08f9fa4a..76c6a5340 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -884,14 +884,16 @@ char *virGetUserRuntimeDirectory(void)
     }
 }
 
-char *virGetUserName(uid_t uid)
+VIR_MOCKABLE(virGetUserName);
+char *virGetUserNameImpl(uid_t uid)
 {
     char *ret;
     virGetUserEnt(uid, &ret, NULL, NULL, NULL, false);
     return ret;
 }
 
-char *virGetGroupName(gid_t gid)
+VIR_MOCKABLE(virGetGroupName);
+char *virGetGroupNameImpl(gid_t gid)
 {
     return virGetGroupEnt(gid);
 }
@@ -1340,8 +1342,9 @@ virGetUserRuntimeDirectory(void)
 }
 # endif /* ! HAVE_GETPWUID_R && ! WIN32 */
 
+VIR_MOCKABLE(virGetUserName);
 char *
-virGetUserName(uid_t uid ATTRIBUTE_UNUSED)
+virGetUserNameImpl(uid_t uid ATTRIBUTE_UNUSED)
 {
     virReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("virGetUserName is not available"));
@@ -1379,8 +1382,9 @@ virSetUIDGID(uid_t uid ATTRIBUTE_UNUSED,
     return -1;
 }
 
+VIR_MOCKABLE(virGetGroupName);
 char *
-virGetGroupName(gid_t gid ATTRIBUTE_UNUSED)
+virGetGroupNameImpl(gid_t gid ATTRIBUTE_UNUSED)
 {
     virReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("virGetGroupName is not available"));
@@ -1908,19 +1912,22 @@ virGetListenFDs(void)
 #endif /* WIN32 */
 
 #ifndef WIN32
-long virGetSystemPageSize(void)
+VIR_MOCKABLE(virGetSystemPageSize);
+long virGetSystemPageSizeImpl(void)
 {
     return sysconf(_SC_PAGESIZE);
 }
 #else /* WIN32 */
-long virGetSystemPageSize(void)
+VIR_MOCKABLE(virGetSystemPageSize);
+long virGetSystemPageSizeImpl(void)
 {
     errno = ENOSYS;
     return -1;
 }
 #endif /* WIN32 */
 
-long virGetSystemPageSizeKB(void)
+VIR_MOCKABLE(virGetSystemPageSizeKB);
+long virGetSystemPageSizeKBImpl(void)
 {
     long val = virGetSystemPageSize();
     if (val < 0)
@@ -1963,8 +1970,9 @@ virMemoryLimitIsSet(unsigned long long value)
  *
  * Returns the maximum possible memory value in bytes.
  */
+VIR_MOCKABLE(virMemoryMaxValue);
 unsigned long long
-virMemoryMaxValue(bool capped)
+virMemoryMaxValueImpl(bool capped)
 {
     /* On 32-bit machines, our bound is 0xffffffff * KiB. On 64-bit
      * machines, our bound is off_t (2^63).  */
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 49382557f..3bbe29eed 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -139,8 +139,8 @@ char *virGetUserConfigDirectory(void);
 char *virGetUserCacheDirectory(void);
 char *virGetUserRuntimeDirectory(void);
 char *virGetUserShell(uid_t uid);
-char *virGetUserName(uid_t uid) ATTRIBUTE_NOINLINE;
-char *virGetGroupName(gid_t gid) ATTRIBUTE_NOINLINE;
+char *virGetUserName(uid_t uid);
+char *virGetGroupName(gid_t gid);
 int virGetGroupList(uid_t uid, gid_t group, gid_t **groups)
     ATTRIBUTE_NONNULL(3);
 int virGetUserID(const char *name,
@@ -201,12 +201,12 @@ verify((int)VIR_TRISTATE_BOOL_ABSENT == (int)VIR_TRISTATE_SWITCH_ABSENT);
 
 unsigned int virGetListenFDs(void);
 
-long virGetSystemPageSize(void) ATTRIBUTE_NOINLINE;
-long virGetSystemPageSizeKB(void) ATTRIBUTE_NOINLINE;
+long virGetSystemPageSize(void);
+long virGetSystemPageSizeKB(void);
 
 unsigned long long virMemoryLimitTruncate(unsigned long long value);
 bool virMemoryLimitIsSet(unsigned long long value);
-unsigned long long virMemoryMaxValue(bool ulong) ATTRIBUTE_NOINLINE;
+unsigned long long virMemoryMaxValue(bool ulong);
 
 /**
  * VIR_ASSIGN_IS_OVERFLOW:
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index 3cbaae0b8..f99c58b73 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -68,8 +68,9 @@ virUUIDGeneratePseudoRandomBytes(unsigned char *buf,
  *
  * Returns 0 in case of success and -1 in case of failure
  */
+VIR_MOCKABLE(virUUIDGenerate);
 int
-virUUIDGenerate(unsigned char *uuid)
+virUUIDGenerateImpl(unsigned char *uuid)
 {
     int err;
 
@@ -106,6 +107,7 @@ virUUIDGenerate(unsigned char *uuid)
     return err;
 }
 
+
 /**
  * virUUIDParse:
  * @uuidstr: zero terminated string representation of the UUID
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index 1d67e9ee5..5790a1736 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -49,7 +49,7 @@ int virGetHostUUID(unsigned char *host_uuid) ATTRIBUTE_NONNULL(1);
 
 int virUUIDIsValid(unsigned char *uuid);
 
-int virUUIDGenerate(unsigned char *uuid) ATTRIBUTE_NOINLINE;
+int virUUIDGenerate(unsigned char *uuid);
 
 int virUUIDParse(const char *uuidstr,
                  unsigned char *uuid)
-- 
2.13.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] Rewrite the way mockable functions are handled.
Posted by Daniel P. Berrange 6 years, 8 months ago
On Fri, Aug 04, 2017 at 06:13:42PM +0100, Daniel P. Berrange wrote:
> Currently any mockable functions are marked with attributes
> noinline, noclone and weak. This prevents the compiler from
> optimizing away the impl of these functions.
> 
> It has an unfortunate side effect with the libtool convenience
> libraries, if executables directly link to them. For example
> virlockd, virlogd both link to libvirt_util.la  When this is
> done, the linker does not consider weak symbols as being
> undefined, so it never copies them into the final executable.
> 
> In this new approach, we stop annotating the headers entirely.
> Instead we create a weak function alias in the source.
> 
>    int fooImpl(void) {
>       ..the real code..
>    }
> 
>    int foo(void) __attribute__((noinline, noclone, weak, alias("fooImpl"))
> 
> If any functions in the same file call "foo", this prevents the
> optimizer from inlining any part of fooImpl. When linking to the
> libtool convenience static library, we also get all the symbols
> present. Finally the test suite can just directly define a
> 'foo' function in its source, removing the need to use LD_PRELOAD
> (though removal of LD_PRELOADS is left for a future patch).
> 
> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>

Self-NACK.

This breaks on OS-X because the linker doesn't support 'alias' or
'weak'.  For that matter it doesn't support LD_PRELOAD either, so
we need to avoid wrapping the functions on this platform.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list