[libvirt] [PATCH] build: work around older systemtap header

Eric Blake eblake at redhat.com
Fri Jul 1 21:43:35 UTC 2011


Systemtap 1.2 <sys/sdt.h> tried to expand STAP_PROBE3 into an
initialization:
  volatile __typeof__(arg) foo = arg;
but that fails if arg was declared as 'char arg[100]'.
Rather than make all callers to PROBE deal with the stupidity
of <sys/sdt.h>, we instead make PROBE cast away the problem.
Some of this preprocessor abuse copies ideas in src/libvirt.c.

* daemon/libvirtd.h (PROBE): Add casts to all arguments, using...
(VIR_ADD_CASTS, VIR_ADD_CAST, VIR_ADD_CAST2, VIR_ADD_CAST3)
(VIR_ADD_CAST_EXPAND, VIR_ADD_CAST_PASTE, VIR_COUNT_ARGS)
(VIR_ARG5, PROBE_EXPAND): New macros.
Reported by Wen Congyang.
---

This took me entirely too long to come up with.  It works for me
with systemtap 1.4; if I can get feedback from systemtap 1.2 and
1.3 users, then I'll gladly apply it, and we can forget about
having to do stupid casts or other workarounds at every PROBE
client.

 daemon/libvirtd.h |   32 +++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index 6c604fc..2f0987e 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -46,11 +46,41 @@
 #   define LIBVIRTD_PROBES_H
 #   include "probes.h"
 #  endif /* LIBVIRTD_PROBES_H */
+
+/* Systemtap 1.2 headers have a bug where they cannot handle a
+ * variable declared with array type.  Work around this by casting all
+ * arguments.  This is some gross use of the preprocessor because
+ * PROBE is a var-arg macro, but it is better than the alternative of
+ * making all callers to PROBE have to be aware of the issues.  And
+ * hopefully, if we ever add a call to PROBE with other than 2 or 3
+ * end arguments, you can figure out the pattern to extend this hack.
+ */
+#  define VIR_COUNT_ARGS(...) VIR_ARG5(__VA_ARGS__, 4, 3, 2, 1)
+#  define VIR_ARG5(_1, _2, _3, _4, _5, ...) _5
+#  define VIR_ADD_CAST_EXPAND(a, b, ...) VIR_ADD_CAST_PASTE(a, b, __VA_ARGS__)
+#  define VIR_ADD_CAST_PASTE(a, b, ...) a##b(__VA_ARGS__)
+
+/* The double cast is necessary to silence gcc warnings; any pointer
+ * can safely go to intptr_t and back to void *, which collapses
+ * arrays into pointers; while any integer can be widened to intptr_t
+ * then cast to void *.  */
+#  define VIR_ADD_CAST(a) ((void *)(intptr_t)(a))
+#  define VIR_ADD_CAST2(a, b)                           \
+    VIR_ADD_CAST(a), VIR_ADD_CAST(b)
+#  define VIR_ADD_CAST3(a, b, c)                        \
+    VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c)
+
+#  define VIR_ADD_CASTS(...)                                            \
+    VIR_ADD_CAST_EXPAND(VIR_ADD_CAST, VIR_COUNT_ARGS(__VA_ARGS__),      \
+                        __VA_ARGS__)
+
+#  define PROBE_EXPAND(NAME, ARGS) NAME(ARGS)
 #  define PROBE(NAME, FMT, ...)                              \
     VIR_DEBUG_INT("trace." __FILE__ , __func__, __LINE__,    \
                   #NAME ": " FMT, __VA_ARGS__);              \
     if (LIBVIRTD_ ## NAME ## _ENABLED()) {                   \
-        LIBVIRTD_ ## NAME(__VA_ARGS__);                      \
+        PROBE_EXPAND(LIBVIRTD_ ## NAME,                      \
+                     VIR_ADD_CASTS(__VA_ARGS__));            \
     }
 # else
 #  define PROBE(NAME, FMT, ...)                              \
-- 
1.7.4.4




More information about the libvir-list mailing list