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

2017-08-09 Thread Daniel P. Berrange
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 

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


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

2017-08-04 Thread Daniel P. Berrange
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 
---

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 () {
-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 () {
-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