Fix: support compile units including 'sys/sdt.h' without defining SDT_USE_VARIADIC
[lttng-ust.git] / include / lttng / tracepoint.h
index 03bc913fd877292857215165d2926bc003cc11dd..1cf02188f37f78eafb1f61a32b56e99f748b697e 100644 (file)
 #include <lttng/ust-compiler.h>
 
 #ifdef LTTNG_UST_HAVE_SDT_INTEGRATION
-#define SDT_USE_VARIADIC
+/*
+ * Instead of using SDT_USE_VARIADIC from 'sys/sdt.h', use our own namespaced
+ * macros since the instrumented application might already have included
+ * 'sys/sdt.h' without variadic support.
+ */
 #include <sys/sdt.h>
-#define LTTNG_STAP_PROBEV STAP_PROBEV
+
+#define _LTTNG_SDT_NARG(...) \
+       __LTTNG_SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0)
+
+#define __LTTNG_SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N
+
+#define _LTTNG_SDT_PROBE_N(provider, name, N, ...) \
+       _SDT_PROBE(provider, name, N, (__VA_ARGS__))
+
+#define LTTNG_STAP_PROBEV(provider, name, ...) \
+       _LTTNG_SDT_PROBE_N(provider, name, _LTTNG_SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)
+
 #else
 #define LTTNG_STAP_PROBEV(...)
 #endif
@@ -226,23 +241,6 @@ struct lttng_ust_tracepoint_dlopen {
 extern struct lttng_ust_tracepoint_dlopen tracepoint_dlopen;
 extern struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr;
 
-/* Disable tracepoint destructors. */
-int __tracepoints__disable_destructors __attribute__((weak));
-
-/*
- * Programs that have threads that survive after they exit, and
- * therefore call library destructors, should disable the tracepoint
- * destructors by calling tracepoint_disable_destructors(). This will
- * leak the tracepoint instrumentation library shared object, leaving
- * its teardown to the operating system process teardown.
- */
-static inline void tracepoint_disable_destructors(void)
-{
-       __tracepoints__disable_destructors = 1;
-}
-
-#if defined(TRACEPOINT_DEFINE) || defined(TRACEPOINT_CREATE_PROBES)
-
 /*
  * These weak symbols, the constructor, and destructor take care of
  * registering only _one_ instance of the tracepoints per shared-ojbect
@@ -267,6 +265,37 @@ struct lttng_ust_tracepoint_dlopen tracepoint_dlopen
 struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr
        __attribute__((weak, visibility("hidden")));
 
+/*
+ * Tracepoint dynamic linkage handling (callbacks). Hidden visibility: shared
+ * across objects in a module/main executable. The callbacks are used to
+ * control and check if the destructors should be executed.
+ */
+struct lttng_ust_tracepoint_destructors_syms {
+       int *old_tracepoint_disable_destructors;
+       void (*tracepoint_disable_destructors)(void);
+       int (*tracepoint_get_destructors_state)(void);
+};
+
+extern struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms;
+extern struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr;
+
+struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms
+       __attribute__((weak, visibility("hidden")));
+struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr
+       __attribute__((weak, visibility("hidden")));
+
+static inline void tracepoint_disable_destructors(void)
+{
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       if (tracepoint_dlopen_ptr->liblttngust_handle
+                       && tracepoint_destructors_syms_ptr->tracepoint_disable_destructors)
+               tracepoint_destructors_syms_ptr->tracepoint_disable_destructors();
+       *tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors = 1;
+}
+
 #ifndef _LGPL_SOURCE
 static inline void lttng_ust_notrace
 __tracepoint__init_urcu_sym(void);
@@ -337,19 +366,44 @@ __tracepoints__destroy(void)
                return;
        if (!tracepoint_dlopen_ptr)
                tracepoint_dlopen_ptr = &tracepoint_dlopen;
-       if (!__tracepoints__disable_destructors
-                       && tracepoint_dlopen_ptr->liblttngust_handle
-                       && !__tracepoint_ptrs_registered) {
-               ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
-               if (ret) {
-                       fprintf(stderr, "Error (%d) in dlclose\n", ret);
-                       abort();
-               }
-               memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr));
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
+               return;
+       if (__tracepoint_ptrs_registered)
+               return;
+       /*
+        * Lookup if destructors must be executed using the new method.
+        */
+       if (tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state
+               && !tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()) {
+               /*
+                * The tracepoint_get_destructors_state symbol was found with
+                * dlsym but its returned value is 0 meaning that destructors
+                * must not be executed.
+                */
+               return;
+       }
+       /*
+        * Lookup if destructors must be executed using the old method.
+        */
+       if (tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors
+               && *tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors) {
+               /*
+                * The old_tracepoint_disable_destructors symbol was found with
+                * dlsym but its value is 1 meaning that destructors must not
+                * be executed.
+                */
+               return;
        }
-}
 
-#endif
+       ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
+       if (ret) {
+               fprintf(stderr, "Error (%d) in dlclose\n", ret);
+               abort();
+       }
+       memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr));
+}
 
 #ifdef TRACEPOINT_DEFINE
 
@@ -402,7 +456,8 @@ extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[]
                };                                                              \
        static struct lttng_ust_tracepoint *                                    \
                __tracepoint_ptr_##_provider##___##_name                        \
-               __attribute__((used, section("__tracepoints_ptrs"))) =          \
+               __attribute__((section("__tracepoints_ptrs"), used))            \
+               __lttng_ust_variable_attribute_no_sanitize_address =            \
                        &__tracepoint_##_provider##___##_name;
 
 static void lttng_ust_notrace __attribute__((constructor))
@@ -419,6 +474,8 @@ __tracepoints__ptrs_init(void)
                        dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
        if (!tracepoint_dlopen_ptr->liblttngust_handle)
                return;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
        tracepoint_dlopen_ptr->tracepoint_register_lib =
                URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *, int),
                                dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
@@ -427,6 +484,18 @@ __tracepoints__ptrs_init(void)
                URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *),
                                dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
                                        "tracepoint_unregister_lib"));
+       tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors =
+               URCU_FORCE_CAST(int *,
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "__tracepoints__disable_destructors"));
+       tracepoint_destructors_syms_ptr->tracepoint_disable_destructors =
+               URCU_FORCE_CAST(void (*)(void),
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_disable_destructors"));
+       tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state =
+               URCU_FORCE_CAST(int (*)(void),
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_get_destructors_state"));
        __tracepoint__init_urcu_sym();
        if (tracepoint_dlopen_ptr->tracepoint_register_lib) {
                tracepoint_dlopen_ptr->tracepoint_register_lib(__start___tracepoints_ptrs,
@@ -446,10 +515,13 @@ __tracepoints__ptrs_destroy(void)
                return;
        if (!tracepoint_dlopen_ptr)
                tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
        if (tracepoint_dlopen_ptr->tracepoint_unregister_lib)
                tracepoint_dlopen_ptr->tracepoint_unregister_lib(__start___tracepoints_ptrs);
-       if (!__tracepoints__disable_destructors
-                       && tracepoint_dlopen_ptr->liblttngust_handle
+       if (tracepoint_dlopen_ptr->liblttngust_handle
+                       && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state
+                       && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()
                        && !__tracepoint_ptrs_registered) {
                ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
                if (ret) {
@@ -524,7 +596,7 @@ __tracepoints__ptrs_destroy(void)
  * How to use the TRACEPOINT_EVENT macro:
  *
  * An example:
- * 
+ *
  * TRACEPOINT_EVENT(someproject_component, event_name,
  *
  *     * TP_ARGS takes from 0 to 10 "type, field_name" pairs *
@@ -535,23 +607,23 @@ __tracepoints__ptrs_destroy(void)
  *     * TP_FIELDS describes the event payload layout in the trace *
  *
  *     TP_FIELDS(
- *         * Integer, printed in base 10 * 
+ *         * Integer, printed in base 10 *
  *         ctf_integer(int, field_a, arg0)
  *
- *         * Integer, printed with 0x base 16 * 
+ *         * Integer, printed with 0x base 16 *
  *         ctf_integer_hex(unsigned long, field_d, arg1)
  *
  *         * Enumeration *
  *         ctf_enum(someproject_component, enum_name, int, field_e, arg0)
  *
- *         * Array Sequence, printed as UTF8-encoded array of bytes * 
+ *         * Array Sequence, printed as UTF8-encoded array of bytes *
  *         ctf_array_text(char, field_b, string, FIXED_LEN)
  *         ctf_sequence_text(char, field_c, string, size_t, strlen)
  *
- *         * String, printed as UTF8-encoded string * 
+ *         * String, printed as UTF8-encoded string *
  *         ctf_string(field_e, string)
  *
- *         * Array sequence of signed integer values * 
+ *         * Array sequence of signed integer values *
  *         ctf_array(long, field_f, arg4, FIXED_LEN4)
  *         ctf_sequence(long, field_g, arg4, size_t, arg4_len)
  *     )
This page took 0.025668 seconds and 4 git commands to generate.