diff --git a/0001-tests-fix-mocking-of-stat-lstat-functions.patch b/0001-tests-fix-mocking-of-stat-lstat-functions.patch
new file mode 100644
index 0000000..3dcf1af
--- /dev/null
+++ b/0001-tests-fix-mocking-of-stat-lstat-functions.patch
@@ -0,0 +1,1309 @@
+From ff376c6283c97217fa65766e3b24d27929e3ff6e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Mon, 1 Apr 2019 17:47:25 +0100
+Subject: [PATCH] tests: fix mocking of stat() / lstat() functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Quite a few of the tests have a need to mock the stat() / lstat()
+functions and they are taking somewhat different & inconsistent
+approaches none of which are actually fully correct. This is shown
+by fact that 'make check' fails on 32-bit hosts. Investigation
+revealed that the code was calling into the native C library impl,
+not getting intercepted by our mocks.
+
+The POSIX stat() function might resolve to any number of different
+symbols in the C library.
+
+The may be an additional stat64() function exposed by the headers
+too.
+
+On 64-bit hosts the stat & stat64 functions are identical, always
+refering to the 64-bit ABI.
+
+On 32-bit hosts they refer to the 32-bit & 64-bit ABIs respectively.
+
+Libvirt uses _FILE_OFFSET_BITS=64 on 32-bit hosts, which causes the
+C library to transparently rewrite stat() calls to be stat64() calls.
+Libvirt will never see the 32-bit ABI from the traditional stat()
+call. We cannot assume this rewriting is done using a macro. It might
+be, but on GLibC it is done with a magic __asm__ statement to apply
+the rewrite at link time instead of at preprocessing.
+
+In GLibC there may be two additional functions exposed by the headers,
+__xstat() and __xstat64(). When these exist, stat() and stat64() are
+transparently rewritten to call __xstat() and __xstat64() respectively.
+The former symbols will not actally exist in the library at all, only
+the header. The leading "__" indicates the symbols are a private impl
+detail of the C library that applications should not care about.
+Unfortunately, because we are trying to mock replace the C library,
+we need to know about this internal impl detail.
+
+With all this in mind the list of functions we have to mock will depend
+on several factors
+
+ - If _FILE_OFFSET_BITS is set, then we are on a 32-bit host, and we
+   only need to mock stat64 and __xstat64. The other stat / __xstat
+   functions exist, but we'll never call them so they can be ignored
+   for mocking.
+
+ - If _FILE_OFFSET_BITS is not set, then we are on a 64-bit host and
+   we should mock stat, stat64, __xstat & __xstat64. Either may be
+   called by app code.
+
+ - If __xstat & __xstat64 exist, then stat & stat64 will not exist
+   as symbols in the library, so the latter should not be mocked.
+
+The same all applies to lstat()
+
+These rules are complex enough that we don't want to duplicate them
+across every mock file, so this centralizes all the logic in a helper
+file virmockstathelper.c that should be #included when needed. The
+code merely need to provide a filename rewriting callback called
+virMockStatRedirect(). Optionally VIR_MOCK_STAT_HOOK can be defined
+as a macro if further processing is needed inline.
+
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+---
+ build-aux/mock-noinline.pl |   3 +
+ cfg.mk                     |   4 +-
+ tests/Makefile.am          |   1 +
+ tests/qemusecuritymock.c   | 131 ++++-----------
+ tests/vircgroupmock.c      | 146 +++--------------
+ tests/virfilewrapper.c     |  85 ++--------
+ tests/virmock.h            |  11 --
+ tests/virmockstathelpers.c | 326 +++++++++++++++++++++++++++++++++++++
+ tests/virpcimock.c         |  93 +----------
+ tests/virtestmock.c        | 140 +---------------
+ 10 files changed, 413 insertions(+), 527 deletions(-)
+ create mode 100644 tests/virmockstathelpers.c
+
+diff --git a/build-aux/mock-noinline.pl b/build-aux/mock-noinline.pl
+index c6b40001c5..958e133885 100644
+--- a/build-aux/mock-noinline.pl
++++ b/build-aux/mock-noinline.pl
+@@ -6,6 +6,9 @@ my %mocked;
+ # Functions in public header don't get the noinline annotation
+ # so whitelist them here
+ $noninlined{"virEventAddTimeout"} = 1;
++# This one confuses the script as its defined in the mock file
++# but is actually just a local helper
++$noninlined{"virMockStatRedirect"} = 1;
+ 
+ foreach my $arg (@ARGV) {
+     if ($arg =~ /\.h$/) {
+diff --git a/cfg.mk b/cfg.mk
+index 8594f64482..5ffae32f2a 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -1272,10 +1272,10 @@ exclude_file_name_regexp--sc_prohibit_xmlURI = ^src/util/viruri\.c$$
+ exclude_file_name_regexp--sc_prohibit_return_as_function = \.py$$
+ 
+ exclude_file_name_regexp--sc_require_config_h = \
+-	^(examples/|tools/virsh-edit\.c$$)
++	^(examples/|tools/virsh-edit\.c$$|tests/virmockstathelpers.c)
+ 
+ exclude_file_name_regexp--sc_require_config_h_first = \
+-	^(examples/|tools/virsh-edit\.c$$)
++	^(examples/|tools/virsh-edit\.c$$|tests/virmockstathelpers.c)
+ 
+ exclude_file_name_regexp--sc_trailing_blank = \
+   /sysinfodata/.*\.data|/virhostcpudata/.*\.cpuinfo|^gnulib/local/.*/.*diff$$
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index d3cdbff8bb..436aac285f 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -146,6 +146,7 @@ EXTRA_DIST = \
+ 	virjsondata \
+ 	virmacmaptestdata \
+ 	virmock.h \
++	virmockstathelpers.h \
+ 	virnetdaemondata \
+ 	virnetdevtestdata \
+ 	virnwfilterbindingxml2xmldata \
+diff --git a/tests/qemusecuritymock.c b/tests/qemusecuritymock.c
+index d1b17d8aa4..3fdc165fb1 100644
+--- a/tests/qemusecuritymock.c
++++ b/tests/qemusecuritymock.c
+@@ -50,10 +50,6 @@
+ 
+ 
+ static int (*real_chown)(const char *path, uid_t uid, gid_t gid);
+-static int (*real_lstat)(const char *path, struct stat *sb);
+-static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
+-static int (*real_stat)(const char *path, struct stat *sb);
+-static int (*real___xstat)(int ver, const char *path, struct stat *sb);
+ static int (*real_open)(const char *path, int flags, ...);
+ static int (*real_close)(int fd);
+ 
+@@ -106,8 +102,6 @@ init_syms(void)
+         return;
+ 
+     VIR_MOCK_REAL_INIT(chown);
+-    VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat);
+-    VIR_MOCK_REAL_INIT_ALT(stat, __xstat);
+     VIR_MOCK_REAL_INIT(open);
+     VIR_MOCK_REAL_INIT(close);
+ 
+@@ -211,36 +205,35 @@ int virFileRemoveXAttr(const char *path,
+ }
+ 
+ 
+-static int
+-mock_stat(const char *path,
+-          struct stat *sb)
+-{
+-    uint32_t *val;
+-
+-    virMutexLock(&m);
+-    init_hash();
+-
+-    memset(sb, 0, sizeof(*sb));
+-
+-    sb->st_mode = S_IFREG | 0666;
+-    sb->st_size = 123456;
+-    sb->st_ino = 1;
+-
+-    if (!(val = virHashLookup(chown_paths, path))) {
+-        /* New path. Set the defaults */
+-        sb->st_uid = DEFAULT_UID;
+-        sb->st_gid = DEFAULT_GID;
+-    } else {
+-        /* Known path. Set values passed to chown() earlier */
+-        sb->st_uid = *val % 16;
+-        sb->st_gid = *val >> 16;
+-    }
+-
+-    virMutexUnlock(&m);
+-
+-    return 0;
+-}
+-
++#define VIR_MOCK_STAT_HOOK \
++    do { \
++        if (getenv(ENVVAR)) { \
++            uint32_t *val; \
++\
++            virMutexLock(&m); \
++            init_hash(); \
++\
++            memset(sb, 0, sizeof(*sb)); \
++\
++            sb->st_mode = S_IFREG | 0666; \
++            sb->st_size = 123456; \
++            sb->st_ino = 1; \
++\
++            if (!(val = virHashLookup(chown_paths, path))) { \
++                /* New path. Set the defaults */ \
++                sb->st_uid = DEFAULT_UID; \
++                sb->st_gid = DEFAULT_GID; \
++            } else { \
++                /* Known path. Set values passed to chown() earlier */ \
++                sb->st_uid = *val % 16; \
++                sb->st_gid = *val >> 16; \
++            } \
++\
++            virMutexUnlock(&m); \
++\
++            return 0; \
++        } \
++    } while (0)
+ 
+ static int
+ mock_chown(const char *path,
+@@ -276,68 +269,12 @@ mock_chown(const char *path,
+ }
+ 
+ 
+-#ifdef HAVE___LXSTAT
+-int
+-__lxstat(int ver, const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (getenv(ENVVAR))
+-        ret = mock_stat(path, sb);
+-    else
+-        ret = real___lxstat(ver, path, sb);
+-
+-    return ret;
+-}
+-#endif /* HAVE___LXSTAT */
+-
+-int
+-lstat(const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (getenv(ENVVAR))
+-        ret = mock_stat(path, sb);
+-    else
+-        ret = real_lstat(path, sb);
+-
+-    return ret;
+-}
+-
+-#ifdef HAVE___XSTAT
+-int
+-__xstat(int ver, const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (getenv(ENVVAR))
+-        ret = mock_stat(path, sb);
+-    else
+-        ret = real___xstat(ver, path, sb);
+-
+-    return ret;
+-}
+-#endif /* HAVE___XSTAT */
++#include "virmockstathelpers.c"
+ 
+-int
+-stat(const char *path, struct stat *sb)
++static int
++virMockStatRedirect(const char *path ATTRIBUTE_UNUSED, char **newpath ATTRIBUTE_UNUSED)
+ {
+-    int ret;
+-
+-    init_syms();
+-
+-    if (getenv(ENVVAR))
+-        ret = mock_stat(path, sb);
+-    else
+-        ret = real_stat(path, sb);
+-
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -386,6 +323,8 @@ close(int fd)
+ {
+     int ret;
+ 
++    init_syms();
++
+     if (fd == 42 && getenv(ENVVAR))
+         ret = 0;
+     else
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index 9c67a44b0d..11a24035aa 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -38,10 +38,6 @@
+ static int (*real_open)(const char *path, int flags, ...);
+ static FILE *(*real_fopen)(const char *path, const char *mode);
+ static int (*real_access)(const char *path, int mode);
+-static int (*real_stat)(const char *path, struct stat *sb);
+-static int (*real___xstat)(int ver, const char *path, struct stat *sb);
+-static int (*real_lstat)(const char *path, struct stat *sb);
+-static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
+ static int (*real_mkdir)(const char *path, mode_t mode);
+ 
+ /* Don't make static, since it causes problems with clang
+@@ -317,8 +313,6 @@ static void init_syms(void)
+ 
+     VIR_MOCK_REAL_INIT(fopen);
+     VIR_MOCK_REAL_INIT(access);
+-    VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat);
+-    VIR_MOCK_REAL_INIT_ALT(stat, __xstat);
+     VIR_MOCK_REAL_INIT(mkdir);
+     VIR_MOCK_REAL_INIT(open);
+ }
+@@ -508,139 +502,41 @@ int access(const char *path, int mode)
+     return ret;
+ }
+ 
+-int __lxstat(int ver, const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+-        init_sysfs();
+-        char *newpath;
+-        if (asprintf(&newpath, "%s%s",
+-                     fakesysfscgroupdir,
+-                     path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+-            errno = ENOMEM;
+-            return -1;
+-        }
+-        ret = real___lxstat(ver, newpath, sb);
+-        free(newpath);
+-    } else if (STRPREFIX(path, fakedevicedir0)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(8, 0);
+-        return 0;
+-    } else if (STRPREFIX(path, fakedevicedir1)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(9, 0);
+-        return 0;
+-    } else {
+-        ret = real___lxstat(ver, path, sb);
+-    }
+-    return ret;
+-}
+-
+-int lstat(const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+-        init_sysfs();
+-        char *newpath;
+-        if (asprintf(&newpath, "%s%s",
+-                     fakesysfscgroupdir,
+-                     path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+-            errno = ENOMEM;
+-            return -1;
+-        }
+-        ret = real_lstat(newpath, sb);
+-        free(newpath);
+-    } else if (STRPREFIX(path, fakedevicedir0)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(8, 0);
+-        return 0;
+-    } else if (STRPREFIX(path, fakedevicedir1)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(9, 0);
+-        return 0;
+-    } else {
+-        ret = real_lstat(path, sb);
+-    }
+-    return ret;
+-}
+-
+-int __xstat(int ver, const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
++# define VIR_MOCK_STAT_HOOK \
++    do { \
++        if (STRPREFIX(path, fakedevicedir0)) { \
++            sb->st_mode = S_IFBLK; \
++            sb->st_rdev = makedev(8, 0); \
++            return 0; \
++        } else if (STRPREFIX(path, fakedevicedir1)) { \
++            sb->st_mode = S_IFBLK; \
++            sb->st_rdev = makedev(9, 0); \
++            return 0; \
++        } \
++    } while (0)
+ 
+-    if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+-        init_sysfs();
+-        char *newpath;
+-        if (asprintf(&newpath, "%s%s",
+-                     fakesysfscgroupdir,
+-                     path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+-            errno = ENOMEM;
+-            return -1;
+-        }
+-        ret = real___xstat(ver, newpath, sb);
+-        free(newpath);
+-    } else if (STRPREFIX(path, fakedevicedir0)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(8, 0);
+-        return 0;
+-    } else if (STRPREFIX(path, fakedevicedir1)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(9, 0);
+-        return 0;
+-    } else {
+-        ret = real___xstat(ver, path, sb);
+-    }
+-    return ret;
+-}
++# include "virmockstathelpers.c"
+ 
+-int stat(const char *path, struct stat *sb)
++static int
++virMockStatRedirect(const char *path, char **newpath)
+ {
+-    char *newpath = NULL;
+-    int ret;
+-
+-    init_syms();
+-
+     if (STREQ(path, SYSFS_CPU_PRESENT)) {
+         init_sysfs();
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(newpath, "%s/%s",
+                      fakesysfscgroupdir,
+-                     SYSFS_CPU_PRESENT_MOCKED) < 0) {
+-            errno = ENOMEM;
++                     SYSFS_CPU_PRESENT_MOCKED) < 0)
+             return -1;
+-        }
+     } else if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+-        if (asprintf(&newpath, "%s%s",
++        if (asprintf(newpath, "%s%s",
+                      fakesysfscgroupdir,
+-                     path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+-            errno = ENOMEM;
+-            return -1;
+-        }
+-    } else if (STRPREFIX(path, fakedevicedir0)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(8, 0);
+-        return 0;
+-    } else if (STRPREFIX(path, fakedevicedir1)) {
+-        sb->st_mode = S_IFBLK;
+-        sb->st_rdev = makedev(9, 0);
+-        return 0;
+-    } else {
+-        if (!(newpath = strdup(path)))
++                     path + strlen(SYSFS_CGROUP_PREFIX)) < 0)
+             return -1;
+     }
+-    ret = real_stat(newpath, sb);
+-    free(newpath);
+-    return ret;
++    return 0;
+ }
+ 
++
+ int mkdir(const char *path, mode_t mode)
+ {
+     int ret;
+diff --git a/tests/virfilewrapper.c b/tests/virfilewrapper.c
+index 88441331ce..067cb30657 100644
+--- a/tests/virfilewrapper.c
++++ b/tests/virfilewrapper.c
+@@ -39,15 +39,9 @@ static size_t nprefixes;
+ static const char **prefixes;
+ 
+ /* TODO: callbacks */
+-
+-
+ static int (*real_open)(const char *path, int flags, ...);
+ static FILE *(*real_fopen)(const char *path, const char *mode);
+ static int (*real_access)(const char *path, int mode);
+-static int (*real_stat)(const char *path, struct stat *sb);
+-static int (*real___xstat)(int ver, const char *path, struct stat *sb);
+-static int (*real_lstat)(const char *path, struct stat *sb);
+-static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
+ static int (*real_mkdir)(const char *path, mode_t mode);
+ static DIR *(*real_opendir)(const char *path);
+ 
+@@ -58,8 +52,6 @@ static void init_syms(void)
+ 
+     VIR_MOCK_REAL_INIT(fopen);
+     VIR_MOCK_REAL_INIT(access);
+-    VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat);
+-    VIR_MOCK_REAL_INIT_ALT(stat, __xstat);
+     VIR_MOCK_REAL_INIT(mkdir);
+     VIR_MOCK_REAL_INIT(open);
+     VIR_MOCK_REAL_INIT(opendir);
+@@ -115,10 +107,11 @@ virFileWrapperClearPrefixes(void)
+     VIR_FREE(overrides);
+ }
+ 
+-static char *
+-virFileWrapperOverridePrefix(const char *path)
++# include "virmockstathelpers.c"
++
++int
++virMockStatRedirect(const char *path, char **newpath)
+ {
+-    char *ret = NULL;
+     size_t i = 0;
+ 
+     for (i = 0; i < noverrides; i++) {
+@@ -127,16 +120,13 @@ virFileWrapperOverridePrefix(const char *path)
+         if (!tmp)
+             continue;
+ 
+-        if (virAsprintfQuiet(&ret, "%s%s", overrides[i], tmp) < 0)
+-            return NULL;
++        if (virAsprintfQuiet(newpath, "%s%s", overrides[i], tmp) < 0)
++            return -1;
+ 
+         break;
+     }
+ 
+-    if (!ret)
+-        ignore_value(VIR_STRDUP_QUIET(ret, path));
+-
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -144,8 +134,7 @@ virFileWrapperOverridePrefix(const char *path)
+     do { \
+         init_syms(); \
+  \
+-        newpath = virFileWrapperOverridePrefix(path); \
+-        if (!newpath) \
++        if (virMockStatRedirect(path, &newpath) < 0) \
+             abort(); \
+     } while (0)
+ 
+@@ -156,7 +145,7 @@ FILE *fopen(const char *path, const char *mode)
+ 
+     PATH_OVERRIDE(newpath, path);
+ 
+-    return real_fopen(newpath, mode);
++    return real_fopen(newpath ? newpath : path, mode);
+ }
+ 
+ int access(const char *path, int mode)
+@@ -165,56 +154,7 @@ int access(const char *path, int mode)
+ 
+     PATH_OVERRIDE(newpath, path);
+ 
+-    return real_access(newpath, mode);
+-}
+-
+-# ifdef HAVE___LXSTAT
+-int __lxstat(int ver, const char *path, struct stat *sb)
+-{
+-    VIR_AUTOFREE(char *) newpath = NULL;
+-
+-    PATH_OVERRIDE(newpath, path);
+-
+-    return real___lxstat(ver, newpath, sb);
+-}
+-# endif /* HAVE___LXSTAT */
+-
+-int lstat(const char *path, struct stat *sb)
+-{
+-    VIR_AUTOFREE(char *) newpath = NULL;
+-
+-    PATH_OVERRIDE(newpath, path);
+-
+-    return real_lstat(newpath, sb);
+-}
+-
+-# ifdef HAVE___XSTAT
+-int __xstat(int ver, const char *path, struct stat *sb)
+-{
+-    VIR_AUTOFREE(char *) newpath = NULL;
+-
+-    PATH_OVERRIDE(newpath, path);
+-
+-    return real___xstat(ver, newpath, sb);
+-}
+-# endif /* HAVE___XSTAT */
+-
+-int stat(const char *path, struct stat *sb)
+-{
+-    VIR_AUTOFREE(char *) newpath = NULL;
+-
+-    PATH_OVERRIDE(newpath, path);
+-
+-    return real_stat(newpath, sb);
+-}
+-
+-int mkdir(const char *path, mode_t mode)
+-{
+-    VIR_AUTOFREE(char *) newpath = NULL;
+-
+-    PATH_OVERRIDE(newpath, path);
+-
+-    return real_mkdir(newpath, mode);
++    return real_access(newpath ? newpath : path, mode);
+ }
+ 
+ int open(const char *path, int flags, ...)
+@@ -234,7 +174,7 @@ int open(const char *path, int flags, ...)
+         va_end(ap);
+     }
+ 
+-    return real_open(newpath, flags, mode);
++    return real_open(newpath ? newpath : path, flags, mode);
+ }
+ 
+ DIR *opendir(const char *path)
+@@ -243,6 +183,7 @@ DIR *opendir(const char *path)
+ 
+     PATH_OVERRIDE(newpath, path);
+ 
+-    return real_opendir(newpath);
++    return real_opendir(newpath ? newpath : path);
+ }
++
+ #endif
+diff --git a/tests/virmock.h b/tests/virmock.h
+index 9c7ecf60ce..46631433c7 100644
+--- a/tests/virmock.h
++++ b/tests/virmock.h
+@@ -290,15 +290,4 @@
+         } \
+     } while (0)
+ 
+-# define VIR_MOCK_REAL_INIT_ALT(name1, name2) \
+-    do { \
+-        real_ ## name1 = dlsym(RTLD_NEXT, #name1); \
+-        real_ ## name2 = dlsym(RTLD_NEXT, #name2); \
+-        if (!real_##name1 && !real_##name2) { \
+-            fprintf(stderr, "Cannot find real '%s' or '%s' symbol\n", \
+-                    #name1, #name2); \
+-            abort(); \
+-        } \
+-    } while (0)
+-
+ #endif /* LIBVIRT_VIRMOCK_H */
+diff --git a/tests/virmockstathelpers.c b/tests/virmockstathelpers.c
+new file mode 100644
+index 0000000000..0bbea4b437
+--- /dev/null
++++ b/tests/virmockstathelpers.c
+@@ -0,0 +1,326 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Helpers for dealing with the many variants of stat(). This
++ * C file should be included from any file that wants to mock
++ * stat() correctly.
++ */
++
++#include "virmock.h"
++#include "viralloc.h"
++
++#include <sys/stat.h>
++#include <unistd.h>
++
++/*
++ * The POSIX stat() function might resolve to any number of different
++ * symbols in the C library.
++ *
++ * The may be an additional stat64() function exposed by the headers
++ * too.
++ *
++ * On 64-bit hosts the stat & stat64 functions are identical, always
++ * refering to the 64-bit ABI.
++ *
++ * On 32-bit hosts they refer to the 32-bit & 64-bit ABIs respectively.
++ *
++ * Libvirt uses _FILE_OFFSET_BITS=64 on 32-bit hosts, which causes the
++ * C library to transparently rewrite stat() calls to be stat64() calls.
++ * Libvirt will never see the 32-bit ABI from the traditional stat()
++ * call. We cannot assume this rewriting is done using a macro. It might
++ * be, but on GLibC it is done with a magic __asm__ statement to apply
++ * the rewrite at link time instead of at preprocessing.
++ *
++ * In GLibC there may be two additional functions exposed by the headers,
++ * __xstat() and __xstat64(). When these exist, stat() and stat64() are
++ * transparently rewritten to call __xstat() and __xstat64() respectively.
++ * The former symbols will not actally exist in the library at all, only
++ * the header. The leading "__" indicates the symbols are a private impl
++ * detail of the C library that applications should not care about.
++ * Unfortunately, because we are trying to mock replace the C library,
++ * we need to know about this internal impl detail.
++ *
++ * With all this in mind the list of functions we have to mock will depend
++ * on several factors
++ *
++ *  - If _FILE_OFFSET_BITS is set, then we are on a 32-bit host, and we
++ *    only need to mock stat64 and __xstat64. The other stat / __xstat
++ *    functions exist, but we'll never call them so they can be ignored
++ *    for mocking.
++ *
++ *  - If _FILE_OFFSET_BITS is not set, then we are on a 64-bit host and
++ *    we should mock stat, stat64, __xstat & __xstat64. Either may be
++ *    called by app code.
++ *
++ *  - If __xstat & __xstat64 exist, then stat & stat64 will not exist
++ *    as symbols in the library, so the latter should not be mocked.
++ *
++ * The same all applies to lstat()
++ */
++
++
++
++#if defined(HAVE_STAT) && !defined(HAVE___XSTAT) && !defined(_FILE_OFFSET_BITS)
++# define MOCK_STAT
++#endif
++#if defined(HAVE_STAT64) && !defined(HAVE___XSTAT64)
++# define MOCK_STAT64
++#endif
++#if defined(HAVE___XSTAT) && !defined(_FILE_OFFSET_BITS)
++# define MOCK___XSTAT
++#endif
++#if defined(HAVE___XSTAT64)
++# define MOCK___XSTAT64
++#endif
++#if defined(HAVE_LSTAT) && !defined(HAVE___LXSTAT) && !defined(_FILE_OFFSET_BITS)
++# define MOCK_LSTAT
++#endif
++#if defined(HAVE_LSTAT64) && !defined(HAVE___LXSTAT64)
++# define MOCK_LSTAT64
++#endif
++#if defined(HAVE___LXSTAT) && !defined(_FILE_OFFSET_BITS)
++# define MOCK___LXSTAT
++#endif
++#if defined(HAVE___LXSTAT64)
++# define MOCK___LXSTAT64
++#endif
++
++#ifdef MOCK_STAT
++static int (*real_stat)(const char *path, struct stat *sb);
++#endif
++#ifdef MOCK_STAT64
++static int (*real_stat64)(const char *path, struct stat64 *sb);
++#endif
++#ifdef MOCK___XSTAT
++static int (*real___xstat)(int ver, const char *path, struct stat *sb);
++#endif
++#ifdef MOCK___XSTAT64
++static int (*real___xstat64)(int ver, const char *path, struct stat64 *sb);
++#endif
++#ifdef MOCK_LSTAT
++static int (*real_lstat)(const char *path, struct stat *sb);
++#endif
++#ifdef MOCK_LSTAT64
++static int (*real_lstat64)(const char *path, struct stat64 *sb);
++#endif
++#ifdef MOCK___LXSTAT
++static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
++#endif
++#ifdef MOCK___LXSTAT64
++static int (*real___lxstat64)(int ver, const char *path, struct stat64 *sb);
++#endif
++
++static bool init;
++static bool debug;
++
++#define fdebug(msg, ...) do { if (debug) fprintf(stderr, msg, __VA_ARGS__); } while (0)
++
++static void virMockStatInit(void)
++{
++    if (init)
++        return;
++
++    init = true;
++    debug = getenv("VIR_MOCK_STAT_DEBUG");
++
++#ifdef MOCK_STAT
++    VIR_MOCK_REAL_INIT(stat);
++    fdebug("real stat %p\n", real_stat);
++#endif
++#ifdef MOCK_STAT64
++    VIR_MOCK_REAL_INIT(stat64);
++    fdebug("real stat64 %p\n", real_stat64);
++#endif
++#ifdef MOCK___XSTAT
++    VIR_MOCK_REAL_INIT(__xstat);
++    fdebug("real __xstat %p\n", real___xstat);
++#endif
++#ifdef MOCK___XSTAT64
++    VIR_MOCK_REAL_INIT(__xstat64);
++    fdebug("real __xstat64 %p\n", real___xstat64);
++#endif
++#ifdef MOCK_LSTAT
++    VIR_MOCK_REAL_INIT(lstat);
++    fdebug("real lstat %p\n", real_lstat);
++#endif
++#ifdef MOCK_LSTAT64
++    VIR_MOCK_REAL_INIT(lstat64);
++    fdebug("real lstat64 %p\n", real_lstat64);
++#endif
++#ifdef MOCK___LXSTAT
++    VIR_MOCK_REAL_INIT(__lxstat);
++    fdebug("real __lxstat %p\n", real___lxstat);
++#endif
++#ifdef MOCK___LXSTAT64
++    VIR_MOCK_REAL_INIT(__lxstat64);
++    fdebug("real __lxstat64 %p\n", real___lxstat64);
++#endif
++}
++
++/*
++ * @stat: the path being queried
++ * @newpath: fill with redirected path, or leave NULL to use orig path
++ *
++ * Return 0 on success, -1 on allocation error
++ */
++static int virMockStatRedirect(const char *path, char **newpath);
++
++#ifndef VIR_MOCK_STAT_HOOK
++# define VIR_MOCK_STAT_HOOK do { } while (0)
++#endif
++
++#ifdef MOCK_STAT
++int stat(const char *path, struct stat *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("stat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real_stat(newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK_STAT64
++int stat64(const char *path, struct stat64 *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("stat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real_stat64(newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK___XSTAT
++int
++__xstat(int ver, const char *path, struct stat *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("__xstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real___xstat(ver, newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK___XSTAT64
++int
++__xstat64(int ver, const char *path, struct stat64 *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("__xstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real___xstat64(ver, newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK_LSTAT
++int
++lstat(const char *path, struct stat *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("lstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real_lstat(newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK_LSTAT64
++int
++lstat64(const char *path, struct stat64 *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("lstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real_lstat64(newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK___LXSTAT
++int
++__lxstat(int ver, const char *path, struct stat *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("__lxstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real___lxstat(ver, newpath ? newpath : path, sb);
++}
++#endif
++
++#ifdef MOCK___LXSTAT64
++int
++__lxstat64(int ver, const char *path, struct stat64 *sb)
++{
++    VIR_AUTOFREE(char *) newpath = NULL;
++
++    virMockStatInit();
++
++    if (virMockStatRedirect(path, &newpath) < 0)
++        abort();
++    fdebug("__lxstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
++
++    VIR_MOCK_STAT_HOOK;
++
++    return real___lxstat64(ver, newpath ? newpath : path, sb);
++}
++#endif
+diff --git a/tests/virpcimock.c b/tests/virpcimock.c
+index ce8176cbec..7f9cdaa9b8 100644
+--- a/tests/virpcimock.c
++++ b/tests/virpcimock.c
+@@ -31,10 +31,6 @@
+ # include "dirname.h"
+ 
+ static int (*real_access)(const char *path, int mode);
+-static int (*real_lstat)(const char *path, struct stat *sb);
+-static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
+-static int (*real_stat)(const char *path, struct stat *sb);
+-static int (*real___xstat)(int ver, const char *path, struct stat *sb);
+ static int (*real_open)(const char *path, int flags, ...);
+ static int (*real_close)(int fd);
+ static DIR * (*real_opendir)(const char *name);
+@@ -365,15 +361,9 @@ pci_device_new_from_stub(const struct pciDevice *data)
+     if (virFileMakePath(devpath) < 0)
+         ABORT("Unable to create: %s", devpath);
+ 
+-    if (real_stat && real_stat(configSrc, &sb) == 0)
++    if (stat(configSrc, &sb) == 0)
+         configSrcExists = true;
+ 
+-# ifdef HAVE___XSTAT
+-    if (!configSrcExists &&
+-        real___xstat && real___xstat(_STAT_VER, configSrc, &sb) == 0)
+-        configSrcExists = true;
+-# endif
+-
+     /* If there is a config file for the device within virpcitestdata dir,
+      * symlink it. Otherwise create a dummy config file. */
+     if (configSrcExists) {
+@@ -813,8 +803,6 @@ init_syms(void)
+         return;
+ 
+     VIR_MOCK_REAL_INIT(access);
+-    VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat);
+-    VIR_MOCK_REAL_INIT_ALT(stat, __xstat);
+     VIR_MOCK_REAL_INIT(open);
+     VIR_MOCK_REAL_INIT(close);
+     VIR_MOCK_REAL_INIT(opendir);
+@@ -896,85 +884,17 @@ access(const char *path, int mode)
+     return ret;
+ }
+ 
+-# ifdef HAVE___LXSTAT
+-int
+-__lxstat(int ver, const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (STRPREFIX(path, SYSFS_PCI_PREFIX)) {
+-        char *newpath;
+-        if (getrealpath(&newpath, path) < 0)
+-            return -1;
+-        ret = real___lxstat(ver, newpath, sb);
+-        VIR_FREE(newpath);
+-    } else {
+-        ret = real___lxstat(ver, path, sb);
+-    }
+-    return ret;
+-}
+-# endif /* HAVE___LXSTAT */
+-
+-int
+-lstat(const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (STRPREFIX(path, SYSFS_PCI_PREFIX)) {
+-        char *newpath;
+-        if (getrealpath(&newpath, path) < 0)
+-            return -1;
+-        ret = real_lstat(newpath, sb);
+-        VIR_FREE(newpath);
+-    } else {
+-        ret = real_lstat(path, sb);
+-    }
+-    return ret;
+-}
+ 
+-# ifdef HAVE___XSTAT
+-int
+-__xstat(int ver, const char *path, struct stat *sb)
++static int
++virMockStatRedirect(const char *path, char **newpath)
+ {
+-    int ret;
+-
+-    init_syms();
+-
+     if (STRPREFIX(path, SYSFS_PCI_PREFIX)) {
+-        char *newpath;
+-        if (getrealpath(&newpath, path) < 0)
++        if (getrealpath(newpath, path) < 0)
+             return -1;
+-        ret = real___xstat(ver, newpath, sb);
+-        VIR_FREE(newpath);
+-    } else {
+-        ret = real___xstat(ver, path, sb);
+     }
+-    return ret;
++    return 0;
+ }
+-# endif /* HAVE___XSTAT */
+ 
+-int
+-stat(const char *path, struct stat *sb)
+-{
+-    int ret;
+-
+-    init_syms();
+-
+-    if (STRPREFIX(path, SYSFS_PCI_PREFIX)) {
+-        char *newpath;
+-        if (getrealpath(&newpath, path) < 0)
+-            return -1;
+-        ret = real_stat(newpath, sb);
+-        VIR_FREE(newpath);
+-    } else {
+-        ret = real_stat(path, sb);
+-    }
+-    return ret;
+-}
+ 
+ int
+ open(const char *path, int flags, ...)
+@@ -1058,6 +978,9 @@ virFileCanonicalizePath(const char *path)
+ 
+     return ret;
+ }
++
++# include "virmockstathelpers.c"
++
+ #else
+ /* Nothing to override on this platform */
+ #endif
+diff --git a/tests/virtestmock.c b/tests/virtestmock.c
+index 3049c90789..bc62312444 100644
+--- a/tests/virtestmock.c
++++ b/tests/virtestmock.c
+@@ -36,33 +36,9 @@
+ #include "viralloc.h"
+ #include "virfile.h"
+ 
+-/* stat can be a macro as follows:
+- *
+- *   #define stat stat64
+- *
+- * This wouldn't fly with our mock. Make sure that the macro (and
+- * all its friends) are undefined. We don't want anybody mangling
+- * our code. */
+-#undef stat
+-#undef stat64
+-#undef __xstat
+-#undef __xstat64
+-#undef lstat
+-#undef lstat64
+-#undef __lxstat
+-#undef __lxstat64
+-
+ static int (*real_open)(const char *path, int flags, ...);
+ static FILE *(*real_fopen)(const char *path, const char *mode);
+ static int (*real_access)(const char *path, int mode);
+-static int (*real_stat)(const char *path, struct stat *sb);
+-static int (*real_stat64)(const char *path, void *sb);
+-static int (*real___xstat)(int ver, const char *path, struct stat *sb);
+-static int (*real___xstat64)(int ver, const char *path, void *sb);
+-static int (*real_lstat)(const char *path, struct stat *sb);
+-static int (*real_lstat64)(const char *path, void *sb);
+-static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
+-static int (*real___lxstat64)(int ver, const char *path, void *sb);
+ static int (*real_connect)(int fd, const struct sockaddr *addr, socklen_t addrlen);
+ 
+ static const char *progname;
+@@ -78,10 +54,6 @@ static void init_syms(void)
+     VIR_MOCK_REAL_INIT(open);
+     VIR_MOCK_REAL_INIT(fopen);
+     VIR_MOCK_REAL_INIT(access);
+-    VIR_MOCK_REAL_INIT_ALT(stat, __xstat);
+-    VIR_MOCK_REAL_INIT_ALT(stat64, __xstat64);
+-    VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat);
+-    VIR_MOCK_REAL_INIT_ALT(lstat64, __lxstat64);
+     VIR_MOCK_REAL_INIT(connect);
+ }
+ 
+@@ -217,119 +189,15 @@ int access(const char *path, int mode)
+     return real_access(path, mode);
+ }
+ 
+-/* Okay, the following ifdef rain forest may look messy at a
+- * first glance. But here's the thing: during run time linking of
+- * a binary, stat() may not be actually needing symbol stat. It
+- * might as well not had been stat() in the first place (see the
+- * reasoning at the beginning of this file). However, if we would
+- * expose stat symbol here, we will poison the well and trick
+- * dynamic linker into thinking we are some old binary that still
+- * uses the symbol. So whenever code from upper layers calls
+- * stat(), the control would get here, but real_stat can actually
+- * be a NULL pointer because newer glibc have __xstat instead.
+- * Worse, it can have __xstat64 instead __xstat.
+- *
+- * Anyway, these ifdefs are there to implement the following
+- * preference function:
+- *
+- * stat < stat64 < __xstat < __xstat64
+- *
+- * It's the same story with lstat.
+- * Also, I feel sorry for you that you had to read this.
+- */
+-#if defined(HAVE_STAT) && !defined(HAVE___XSTAT)
+-int stat(const char *path, struct stat *sb)
+-{
+-    init_syms();
+ 
+-    checkPath(path, "stat");
++#define VIR_MOCK_STAT_HOOK CHECK_PATH(path)
+ 
+-    return real_stat(path, sb);
+-}
+-#endif
++#include "virmockstathelpers.c"
+ 
+-#if defined(HAVE_STAT64) && !defined(HAVE___XSTAT64)
+-int stat64(const char *path, struct stat64 *sb)
++static int virMockStatRedirect(const char *path ATTRIBUTE_UNUSED, char **newpath ATTRIBUTE_UNUSED)
+ {
+-    init_syms();
+-
+-    checkPath(path, "stat");
+-
+-    return real_stat64(path, sb);
++    return 0;
+ }
+-#endif
+-
+-#if defined(HAVE___XSTAT) && !defined(HAVE___XSTAT64)
+-int
+-__xstat(int ver, const char *path, struct stat *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "stat");
+-
+-    return real___xstat(ver, path, sb);
+-}
+-#endif
+-
+-#if defined(HAVE___XSTAT64)
+-int
+-__xstat64(int ver, const char *path, struct stat64 *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "stat");
+-
+-    return real___xstat64(ver, path, sb);
+-}
+-#endif
+-
+-#if defined(HAVE_LSTAT) && !defined(HAVE___LXSTAT)
+-int
+-lstat(const char *path, struct stat *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "lstat");
+-
+-    return real_lstat(path, sb);
+-}
+-#endif
+-
+-#if defined(HAVE_LSTAT64) && !defined(HAVE___LXSTAT64)
+-int
+-lstat64(const char *path, struct stat64 *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "lstat");
+-
+-    return real_lstat64(path, sb);
+-}
+-#endif
+-
+-#if defined(HAVE___LXSTAT) && !defined(HAVE___LXSTAT64)
+-int
+-__lxstat(int ver, const char *path, struct stat *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "lstat");
+-
+-    return real___lxstat(ver, path, sb);
+-}
+-#endif
+-
+-#if defined(HAVE___LXSTAT64)
+-int
+-__lxstat64(int ver, const char *path, struct stat64 *sb)
+-{
+-    init_syms();
+-
+-    checkPath(path, "lstat");
+-
+-    return real___lxstat64(ver, path, sb);
+-}
+-#endif
+ 
+ 
+ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+-- 
+2.20.1
+
diff --git a/libvirt.spec b/libvirt.spec
index 2b62c77..0d8b03a 100644
--- a/libvirt.spec
+++ b/libvirt.spec
@@ -224,6 +224,7 @@ URL: https://libvirt.org/
     %define mainturl stable_updates/
 %endif
 Source: https://libvirt.org/sources/%{?mainturl}libvirt-%{version}.tar.xz
+Patch1: 0001-tests-fix-mocking-of-stat-lstat-functions.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}