X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ust%2Flttng-probes.c;h=e8e08ff176ce6d5e2b4bccf556bf2053fcb51762;hb=4c155a06d838e1ab5d385abd1d73ae56e71b7d5e;hp=1e73064907865e8e2e7cfbc396fd0fa1fe96c647;hpb=a9fd951a21f28704ffdfd4217766f725a217208b;p=lttng-ust.git diff --git a/src/lib/lttng-ust/lttng-probes.c b/src/lib/lttng-ust/lttng-probes.c index 1e730649..e8e08ff1 100644 --- a/src/lib/lttng-ust/lttng-probes.c +++ b/src/lib/lttng-ust/lttng-probes.c @@ -39,17 +39,98 @@ static CDS_LIST_HEAD(lazy_probe_init); */ 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.", @@ -61,6 +142,20 @@ bool check_event_provider(const struct lttng_ust_probe_desc *probe_desc) 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; } @@ -131,34 +226,6 @@ struct cds_list_head *lttng_get_probe_list_head(void) 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) { @@ -326,7 +393,7 @@ int lttng_probes_get_field_list(struct lttng_ust_field_list *list) 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; @@ -348,9 +415,9 @@ int lttng_probes_get_field_list(struct lttng_ust_field_list *list) 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. */