+
+static void lttng_ust_notrace __attribute__((constructor))
+__tracepoints__init(void);
+static void
+__tracepoints__init(void)
+{
+ if (__tracepoint_registered++) {
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ return;
+ __tracepoint__init_urcu_sym();
+ return;
+ }
+
+ if (!tracepoint_dlopen_ptr)
+ tracepoint_dlopen_ptr = &tracepoint_dlopen;
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ tracepoint_dlopen_ptr->liblttngust_handle =
+ dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ return;
+ __tracepoint__init_urcu_sym();
+}
+
+static void lttng_ust_notrace __attribute__((destructor))
+__tracepoints__destroy(void);
+static void
+__tracepoints__destroy(void)
+{
+ int ret;
+
+ if (--__tracepoint_registered)
+ 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->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;
+ }
+
+ 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
+
+/*
+ * These weak symbols, the constructor, and destructor take care of
+ * registering only _one_ instance of the tracepoints per shared-ojbect
+ * (or for the whole main program).
+ */
+extern struct lttng_ust_tracepoint * const __start___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+
+/*
+ * When TRACEPOINT_PROBE_DYNAMIC_LINKAGE is defined, we do not emit a
+ * unresolved symbol that requires the provider to be linked in. When
+ * TRACEPOINT_PROBE_DYNAMIC_LINKAGE is not defined, we emit an
+ * unresolved symbol that depends on having the provider linked in,
+ * otherwise the linker complains. This deals with use of static
+ * libraries, ensuring that the linker does not remove the provider
+ * object from the executable.
+ */
+#ifdef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#define _TRACEPOINT_UNDEFINED_REF(provider) NULL
+#else /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
+#define _TRACEPOINT_UNDEFINED_REF(provider) &__tracepoint_provider_##provider
+#endif /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
+
+/*
+ * Note: to allow PIC code, we need to allow the linker to update the pointers
+ * in the __tracepoints_ptrs section.
+ * Therefore, this section is _not_ const (read-only).
+ */
+#define _TP_EXTRACT_STRING(...) #__VA_ARGS__
+
+#define _DEFINE_TRACEPOINT(_provider, _name, _args) \
+ extern int __tracepoint_provider_##_provider; \
+ static const char __tp_strtab_##_provider##___##_name[] \
+ __attribute__((section("__tracepoints_strings"))) = \
+ #_provider ":" #_name; \
+ struct lttng_ust_tracepoint __tracepoint_##_provider##___##_name \
+ __attribute__((section("__tracepoints"))) = \
+ { \
+ __tp_strtab_##_provider##___##_name, \
+ 0, \
+ NULL, \
+ _TRACEPOINT_UNDEFINED_REF(_provider), \
+ _TP_EXTRACT_STRING(_args), \
+ { }, \
+ }; \
+ static struct lttng_ust_tracepoint * \
+ __tracepoint_ptr_##_provider##___##_name \
+ __attribute__((used, section("__tracepoints_ptrs"))) = \
+ &__tracepoint_##_provider##___##_name;
+
+static void lttng_ust_notrace __attribute__((constructor))
+__tracepoints__ptrs_init(void);
+static void
+__tracepoints__ptrs_init(void)
+{
+ if (__tracepoint_ptrs_registered++)
+ return;
+ if (!tracepoint_dlopen_ptr)
+ tracepoint_dlopen_ptr = &tracepoint_dlopen;
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ tracepoint_dlopen_ptr->liblttngust_handle =
+ 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,
+ "tracepoint_register_lib"));
+ tracepoint_dlopen_ptr->tracepoint_unregister_lib =
+ 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,