#include <urcu/hlist.h>
#include <lttng/ust-events.h>
#include <lttng/tracepoint.h>
-#include "tracepoint-internal.h"
+#include "common/tracepoint.h"
#include <assert.h>
#include "common/macros.h"
#include <ctype.h>
#include "lttng-tracer-core.h"
#include "common/jhash.h"
-#include "error.h"
#include "lib/lttng-ust/events.h"
/*
*/
static int lazy_nesting;
+static
+int check_provider_version(const struct lttng_ust_probe_desc *desc)
+{
+ /*
+ * Check tracepoint provider version compatibility.
+ */
+ if (desc->major <= LTTNG_UST_PROVIDER_MAJOR &&
+ desc->major >= LTTNG_UST_PROVIDER_MAJOR_OLDEST_COMPATIBLE) {
+ DBG("Provider \"%s\" accepted, version %u.%u is compatible "
+ "with LTTng UST provider version %u.%u.",
+ desc->provider_name, desc->major, desc->minor,
+ LTTNG_UST_PROVIDER_MAJOR,
+ LTTNG_UST_PROVIDER_MINOR);
+ if (desc->major < LTTNG_UST_PROVIDER_MAJOR) {
+ DBG("However, some LTTng UST features might not be "
+ "available for this provider unless it is "
+ "recompiled against a more recent LTTng UST.");
+ }
+ return 1; /* accept */
+ } else {
+ ERR("Provider \"%s\" rejected, version %u.%u is incompatible "
+ "with LTTng UST provider version %u.%u. Please upgrade "
+ "LTTng UST.",
+ desc->provider_name, desc->major, desc->minor,
+ LTTNG_UST_PROVIDER_MAJOR,
+ LTTNG_UST_PROVIDER_MINOR);
+ return 0; /* reject */
+ }
+}
+
+static
+bool check_type_provider(const struct lttng_ust_type_common *type);
+
+static
+bool check_type_provider(const struct lttng_ust_type_common *type)
+{
+ switch (type->type) {
+ case lttng_ust_type_integer:
+ return true;
+ case lttng_ust_type_string:
+ return true;
+ case lttng_ust_type_float:
+ return true;
+ case lttng_ust_type_dynamic:
+ return true;
+ case lttng_ust_type_enum:
+ {
+ const struct lttng_ust_type_enum *enum_type = caa_container_of(type, const struct lttng_ust_type_enum, parent);
+
+ return check_provider_version(enum_type->desc->probe_desc);
+ }
+ case lttng_ust_type_array:
+ {
+ const struct lttng_ust_type_array *array_type = caa_container_of(type, const struct lttng_ust_type_array, parent);
+
+ return check_type_provider(array_type->elem_type);
+ }
+ case lttng_ust_type_sequence:
+ {
+ const struct lttng_ust_type_sequence *sequence_type = caa_container_of(type, const struct lttng_ust_type_sequence, parent);
+
+ return check_type_provider(sequence_type->elem_type);
+ }
+ case lttng_ust_type_struct:
+ {
+ const struct lttng_ust_type_struct *struct_type = caa_container_of(type, const struct lttng_ust_type_struct, parent);
+ size_t i;
+
+ for (i = 0; i < struct_type->nr_fields; i++) {
+ if (!check_type_provider(struct_type->fields[i]->type))
+ return false;
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
/*
* Validate that each event within the probe provider refers to the
- * right probe, and that the resulting name is not too long.
+ * right probe, that the resulting name is not too long, and that the
+ * event class belongs to a provider with compatible version.
*/
static
bool check_event_provider(const struct lttng_ust_probe_desc *probe_desc)
{
- int i;
+ int i, j;
for (i = 0; i < probe_desc->nr_events; i++) {
const struct lttng_ust_event_desc *event_desc = probe_desc->event_desc[i];
+ const struct lttng_ust_tracepoint_class *tp_class = event_desc->tp_class;
if (event_desc->probe_desc != probe_desc) {
ERR("Error registering probe provider '%s'. Event '%s:%s' refers to the wrong provider descriptor.",
probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name);
return false; /* provider mismatch */
}
+ if (!check_provider_version(tp_class->probe_desc)) {
+ ERR("Error registering probe provider '%s'. Event '%s:%s' refers to an event class in a provider with incompatible version.",
+ probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name);
+ return false;
+ }
+ for (j = 0; j < tp_class->nr_fields; j++) {
+ const struct lttng_ust_event_field *field = tp_class->fields[j];
+
+ if (!check_type_provider(field->type)) {
+ ERR("Error registering probe provider '%s'. Event '%s:%s' contains a field which refers to an provider with incompatible version.",
+ probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name);
+ return false;
+ }
+ }
}
return true;
}
/*
* The provider ensures there are no duplicate event names.
- * Duplicated TRACEPOINT_EVENT event names would generate a
+ * Duplicated LTTNG_UST_TRACEPOINT_EVENT event names would generate a
* compile-time error due to duplicated symbol names.
*/
return &_probe_list;
}
-static
-int check_provider_version(const struct lttng_ust_probe_desc *desc)
-{
- /*
- * Check tracepoint provider version compatibility.
- */
- if (desc->major <= LTTNG_UST_PROVIDER_MAJOR) {
- DBG("Provider \"%s\" accepted, version %u.%u is compatible "
- "with LTTng UST provider version %u.%u.",
- desc->provider_name, desc->major, desc->minor,
- LTTNG_UST_PROVIDER_MAJOR,
- LTTNG_UST_PROVIDER_MINOR);
- if (desc->major < LTTNG_UST_PROVIDER_MAJOR) {
- DBG("However, some LTTng UST features might not be "
- "available for this provider unless it is "
- "recompiled against a more recent LTTng UST.");
- }
- return 1; /* accept */
- } else {
- ERR("Provider \"%s\" rejected, version %u.%u is incompatible "
- "with LTTng UST provider version %u.%u. Please upgrade "
- "LTTng UST.",
- desc->provider_name, desc->major, desc->minor,
- LTTNG_UST_PROVIDER_MAJOR,
- LTTNG_UST_PROVIDER_MINOR);
- return 0; /* reject */
- }
-}
struct lttng_ust_registered_probe *lttng_ust_probe_register(const struct lttng_ust_probe_desc *desc)
{
struct lttng_ust_registered_probe *reg_probe = NULL;
- lttng_ust_fixup_tls();
+ lttng_ust_common_init_thread(0);
/*
* If version mismatch, don't register, but don't trigger assert
void lttng_ust_probe_unregister(struct lttng_ust_registered_probe *reg_probe)
{
- lttng_ust_fixup_tls();
+ lttng_ust_common_init_thread(0);
if (!reg_probe)
return;
cds_list_add(&list_entry->head, &list->head);
lttng_ust_format_event_name(event_desc, list_entry->tp.name);
if (!event_desc->loglevel) {
- list_entry->tp.loglevel = TRACE_DEFAULT;
+ list_entry->tp.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT;
} else {
list_entry->tp.loglevel = *(*event_desc->loglevel);
}
probe_desc->event_desc[i];
int j;
- if (event_desc->nr_fields == 0) {
+ if (event_desc->tp_class->nr_fields == 0) {
/* Events without fields. */
struct tp_field_list_entry *list_entry;
list_entry->field.field_name[0] = '\0';
list_entry->field.type = LTTNG_UST_ABI_FIELD_OTHER;
if (!event_desc->loglevel) {
- list_entry->field.loglevel = TRACE_DEFAULT;
+ list_entry->field.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT;
} else {
list_entry->field.loglevel = *(*event_desc->loglevel);
}
list_entry->field.nowrite = 1;
}
- for (j = 0; j < event_desc->nr_fields; j++) {
+ for (j = 0; j < event_desc->tp_class->nr_fields; j++) {
const struct lttng_ust_event_field *event_field =
- event_desc->fields[j];
+ event_desc->tp_class->fields[j];
struct tp_field_list_entry *list_entry;
/* Skip event if name is too long. */
list_entry->field.type = LTTNG_UST_ABI_FIELD_OTHER;
}
if (!event_desc->loglevel) {
- list_entry->field.loglevel = TRACE_DEFAULT;
+ list_entry->field.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT;
} else {
list_entry->field.loglevel = *(*event_desc->loglevel);
}