#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
+#include <dlfcn.h>
#include <urcu/arch.h>
#include <lttng/urcu/urcu-ust.h>
* The tracepoint mutex protects the library tracepoints, the hash table, and
* the library list.
* All calls to the tracepoint API must be protected by the tracepoint mutex,
- * excepts calls to tracepoint_register_lib and
- * tracepoint_unregister_lib, which take the tracepoint mutex themselves.
+ * excepts calls to lttng_ust_tracepoint_module_register and
+ * lttng_ust_tracepoint_module_unregister, which take the tracepoint mutex themselves.
*/
/*
}
}
+/*
+ * Use a symbol of the previous ABI to detect if liblttng-ust-tracepoint.so.0
+ * is loaded in the current process.
+ */
+#define LTTNG_UST_TRACEPOINT_SONAME_0_SYM "tracepoint_unregister_lib"
+
+static
+void lttng_ust_tracepoint_check_soname_0(void)
+{
+ if (!dlsym(RTLD_DEFAULT, LTTNG_UST_TRACEPOINT_SONAME_0_SYM))
+ return;
+
+ CRIT("Incompatible library ABIs detected within the same process. "
+ "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+ "The detection was triggered by lookup of ABI 0 symbol \"%s\" in the Global Symbol Table\n",
+ LTTNG_UST_TRACEPOINT_SONAME_0_SYM);
+}
+
+/*
+ * Expose a canary symbol of the previous ABI to ensure we catch uses of a
+ * liblttng-ust-tracepoint.so.0 dlopen'd after .so.1 has been loaded. Use a
+ * different symbol than the detection code to ensure we don't detect ourself.
+ */
+int tracepoint_register_lib(void *arg0 __attribute__((unused)), int arg1 __attribute__((unused)));
+int tracepoint_register_lib(void *arg0 __attribute__((unused)), int arg1 __attribute__((unused)))
+{
+ CRIT("Incompatible library ABIs detected within the same process. "
+ "The process is likely linked against different major soname of LTTng-UST which is unsupported. "
+ "The detection was triggered by canary symbol \"%s\"\n", __func__);
+
+ return -1;
+}
+
/**
- * lttng_ust_tracepoint_probe_register - Connect a probe to a tracepoint
+ * lttng_ust_tracepoint_provider_register - Connect a probe to a tracepoint
* @name: tracepoint provider name
* @name: tracepoint event name
* @probe: probe handler
* The probe address must at least be aligned on the architecture pointer size.
* Called with the tracepoint mutex held.
*/
-int lttng_ust_tracepoint_probe_register(const char *provider_name, const char *event_name,
+int lttng_ust_tracepoint_provider_register(const char *provider_name, const char *event_name,
void (*probe)(void), void *data, const char *signature)
{
void *old;
int ret = 0;
+ /*
+ * Check if we find a symbol of the previous ABI in the current process
+ * as different ABIs of liblttng-ust can't co-exist in a process. If we
+ * do so, emit a critical log message which will also abort if the
+ * LTTNG_UST_ABORT_ON_CRITICAL environment variable is set.
+ */
+ lttng_ust_tracepoint_check_soname_0();
+
DBG("Registering probe to tracepoint \"%s:%s\"", provider_name, event_name);
pthread_mutex_lock(&tracepoint_mutex);
* @probe: probe function pointer
* @probe: probe data pointer
*/
-int lttng_ust_tracepoint_probe_unregister(const char *provider_name, const char *event_name,
+int lttng_ust_tracepoint_provider_unregister(const char *provider_name, const char *event_name,
void (*probe)(void), void *data)
{
void *old;
* against recent liblttng-ust headers require a recent liblttng-ust
* runtime for those tracepoints to be taken into account.
*/
-int tracepoint_register_lib(struct lttng_ust_tracepoint * const *tracepoints_start,
+int lttng_ust_tracepoint_module_register(struct lttng_ust_tracepoint * const *tracepoints_start,
int tracepoints_count);
-int tracepoint_register_lib(struct lttng_ust_tracepoint * const *tracepoints_start,
+int lttng_ust_tracepoint_module_register(struct lttng_ust_tracepoint * const *tracepoints_start,
int tracepoints_count)
{
struct tracepoint_lib *pl, *iter;
return 0;
}
-int tracepoint_unregister_lib(struct lttng_ust_tracepoint * const *tracepoints_start);
-int tracepoint_unregister_lib(struct lttng_ust_tracepoint * const *tracepoints_start)
+int lttng_ust_tracepoint_module_unregister(struct lttng_ust_tracepoint * const *tracepoints_start);
+int lttng_ust_tracepoint_module_unregister(struct lttng_ust_tracepoint * const *tracepoints_start)
{
struct tracepoint_lib *lib;
/*
* Create the wrapper symbols.
*/
-#undef tp_rcu_read_lock
-#undef tp_rcu_read_unlock
-#undef tp_rcu_dereference
+#undef lttng_ust_tp_rcu_read_lock
+#undef lttng_ust_tp_rcu_read_unlock
+#undef lttng_ust_tp_rcu_dereference
-void tp_rcu_read_lock(void);
-void tp_rcu_read_lock(void)
+void lttng_ust_tp_rcu_read_lock(void);
+void lttng_ust_tp_rcu_read_lock(void)
{
lttng_ust_urcu_read_lock();
}
-void tp_rcu_read_unlock(void);
-void tp_rcu_read_unlock(void)
+void lttng_ust_tp_rcu_read_unlock(void);
+void lttng_ust_tp_rcu_read_unlock(void)
{
lttng_ust_urcu_read_unlock();
}
-void *tp_rcu_dereference_sym(void *p);
-void *tp_rcu_dereference_sym(void *p)
+void *lttng_ust_tp_rcu_dereference_sym(void *p);
+void *lttng_ust_tp_rcu_dereference_sym(void *p)
{
return lttng_ust_rcu_dereference(p);
}
/*
* Programs that have threads that survive after they exit, and therefore call
* library destructors, should disable the tracepoint destructors by calling
- * tp_disable_destructors(). This will leak the tracepoint
+ * lttng_ust_tp_disable_destructors(). This will leak the tracepoint
* instrumentation library shared object, leaving its teardown to the operating
* system process teardown.
*
* To access and/or modify this value, users need to use a combination of
* dlopen(3) and dlsym(3) to get an handle on the
- * tp_disable_destructors and tp_get_destructors_state symbols below.
+ * lttng_ust_tp_disable_destructors and lttng_ust_tp_get_destructors_state symbols below.
*/
-void tp_disable_destructors(void);
-void tp_disable_destructors(void)
+void lttng_ust_tp_disable_destructors(void);
+void lttng_ust_tp_disable_destructors(void)
{
uatomic_set(&tracepoint_destructors_state, 0);
}
* Returns 1 if the destructors are enabled and should be executed.
* Returns 0 if the destructors are disabled.
*/
-int tp_get_destructors_state(void);
-int tp_get_destructors_state(void)
+int lttng_ust_tp_get_destructors_state(void);
+int lttng_ust_tp_get_destructors_state(void)
{
return uatomic_read(&tracepoint_destructors_state);
}