2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
12 #include <lttng/condition/condition-internal.h>
13 #include <lttng/condition/event-rule-internal.h>
14 #include <lttng/condition/event-rule.h>
15 #include <lttng/event-expr-internal.h>
16 #include <lttng/event-expr.h>
17 #include <lttng/event-rule/event-rule-internal.h>
20 #include <vendor/msgpack/msgpack.h>
22 #define IS_EVENT_RULE_CONDITION(condition) \
23 (lttng_condition_get_type(condition) == \
24 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT)
26 static bool is_event_rule_evaluation(const struct lttng_evaluation
*evaluation
)
28 enum lttng_condition_type type
= lttng_evaluation_get_type(evaluation
);
30 return type
== LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
33 static bool lttng_condition_event_rule_validate(
34 const struct lttng_condition
*condition
);
35 static int lttng_condition_event_rule_serialize(
36 const struct lttng_condition
*condition
,
37 struct lttng_payload
*payload
);
38 static bool lttng_condition_event_rule_is_equal(
39 const struct lttng_condition
*_a
,
40 const struct lttng_condition
*_b
);
41 static void lttng_condition_event_rule_destroy(
42 struct lttng_condition
*condition
);
44 static bool lttng_condition_event_rule_validate(
45 const struct lttng_condition
*condition
)
48 struct lttng_condition_event_rule
*event_rule
;
54 event_rule
= container_of(
55 condition
, struct lttng_condition_event_rule
, parent
);
56 if (!event_rule
->rule
) {
57 ERR("Invalid event rule condition: a rule must be set.");
61 valid
= lttng_event_rule_validate(event_rule
->rule
);
67 * Serializes the C string `str` into `buf`.
69 * Encoding is the length of `str` plus one (for the null character),
70 * and then the string, including its null terminator.
73 int serialize_cstr(const char *str
, struct lttng_dynamic_buffer
*buf
)
76 const uint32_t len
= strlen(str
) + 1;
78 /* Serialize the length, including the null terminator. */
79 DBG("Serializing C string's length (including null terminator): "
81 ret
= lttng_dynamic_buffer_append(buf
, &len
, sizeof(len
));
86 /* Serialize the string. */
87 DBG("Serializing C string: '%s'", str
);
88 ret
= lttng_dynamic_buffer_append(buf
, str
, len
);
98 * Serializes the event expression `expr` into `buf`.
101 int serialize_event_expr(const struct lttng_event_expr
*expr
,
102 struct lttng_payload
*payload
)
104 const uint8_t type
= expr
->type
;
107 /* Serialize the expression's type. */
108 DBG("Serializing event expression's type: %d", expr
->type
);
109 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &type
, sizeof(type
));
114 /* Serialize the expression */
115 switch (expr
->type
) {
116 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
117 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
119 const struct lttng_event_expr_field
*field_expr
=
121 const struct lttng_event_expr_field
,
124 /* Serialize the field name. */
125 DBG("Serializing field event expression's field name: '%s'",
127 ret
= serialize_cstr(field_expr
->name
, &payload
->buffer
);
134 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
136 const struct lttng_event_expr_app_specific_context_field
*field_expr
=
138 const struct lttng_event_expr_app_specific_context_field
,
141 /* Serialize the provider name. */
142 DBG("Serializing app-specific context field event expression's "
143 "provider name: '%s'",
144 field_expr
->provider_name
);
145 ret
= serialize_cstr(field_expr
->provider_name
, &payload
->buffer
);
150 /* Serialize the type name. */
151 DBG("Serializing app-specific context field event expression's "
153 field_expr
->provider_name
);
154 ret
= serialize_cstr(field_expr
->type_name
, &payload
->buffer
);
161 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
163 const struct lttng_event_expr_array_field_element
*elem_expr
=
165 const struct lttng_event_expr_array_field_element
,
167 const uint32_t index
= elem_expr
->index
;
169 /* Serialize the index. */
170 DBG("Serializing array field element event expression's "
171 "index: %u", elem_expr
->index
);
172 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &index
, sizeof(index
));
177 /* Serialize the parent array field expression. */
178 DBG("Serializing array field element event expression's "
179 "parent array field event expression.");
180 ret
= serialize_event_expr(elem_expr
->array_field_expr
, payload
);
195 static int lttng_condition_event_rule_serialize(
196 const struct lttng_condition
*condition
,
197 struct lttng_payload
*payload
)
200 struct lttng_condition_event_rule
*event_rule
;
201 enum lttng_condition_status status
;
202 /* Used for iteration and communication (size matters). */
203 uint32_t i
, capture_descr_count
;
205 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
210 DBG("Serializing event rule condition");
211 event_rule
= container_of(
212 condition
, struct lttng_condition_event_rule
, parent
);
214 DBG("Serializing event rule condition's event rule");
215 ret
= lttng_event_rule_serialize(event_rule
->rule
, payload
);
220 status
= lttng_condition_event_rule_get_capture_descriptor_count(
221 condition
, &capture_descr_count
);
222 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
227 DBG("Serializing event rule condition's capture descriptor count: %" PRIu32
,
228 capture_descr_count
);
229 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &capture_descr_count
,
230 sizeof(capture_descr_count
));
235 for (i
= 0; i
< capture_descr_count
; i
++) {
236 const struct lttng_event_expr
*expr
=
237 lttng_condition_event_rule_get_capture_descriptor_at_index(
240 DBG("Serializing event rule condition's capture descriptor %" PRIu32
,
242 ret
= serialize_event_expr(expr
, payload
);
253 bool capture_descriptors_are_equal(
254 const struct lttng_condition
*condition_a
,
255 const struct lttng_condition
*condition_b
)
257 bool is_equal
= true;
258 unsigned int capture_descr_count_a
;
259 unsigned int capture_descr_count_b
;
261 enum lttng_condition_status status
;
263 status
= lttng_condition_event_rule_get_capture_descriptor_count(
264 condition_a
, &capture_descr_count_a
);
265 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
269 status
= lttng_condition_event_rule_get_capture_descriptor_count(
270 condition_b
, &capture_descr_count_b
);
271 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
275 if (capture_descr_count_a
!= capture_descr_count_b
) {
279 for (i
= 0; i
< capture_descr_count_a
; i
++) {
280 const struct lttng_event_expr
*expr_a
=
281 lttng_condition_event_rule_get_capture_descriptor_at_index(
284 const struct lttng_event_expr
*expr_b
=
285 lttng_condition_event_rule_get_capture_descriptor_at_index(
289 if (!lttng_event_expr_is_equal(expr_a
, expr_b
)) {
303 static bool lttng_condition_event_rule_is_equal(
304 const struct lttng_condition
*_a
,
305 const struct lttng_condition
*_b
)
307 bool is_equal
= false;
308 struct lttng_condition_event_rule
*a
, *b
;
310 a
= container_of(_a
, struct lttng_condition_event_rule
, parent
);
311 b
= container_of(_b
, struct lttng_condition_event_rule
, parent
);
313 /* Both event rules must be set or both must be unset. */
314 if ((a
->rule
&& !b
->rule
) || (!a
->rule
&& b
->rule
)) {
315 WARN("Comparing event_rule conditions with uninitialized rule");
319 is_equal
= lttng_event_rule_is_equal(a
->rule
, b
->rule
);
324 is_equal
= capture_descriptors_are_equal(_a
, _b
);
330 static void lttng_condition_event_rule_destroy(
331 struct lttng_condition
*condition
)
333 struct lttng_condition_event_rule
*event_rule
;
335 event_rule
= container_of(
336 condition
, struct lttng_condition_event_rule
, parent
);
338 lttng_event_rule_put(event_rule
->rule
);
339 lttng_dynamic_pointer_array_reset(&event_rule
->capture_descriptors
);
344 void destroy_capture_descriptor(void *ptr
)
346 struct lttng_capture_descriptor
*desc
=
347 (struct lttng_capture_descriptor
*) ptr
;
349 lttng_event_expr_destroy(desc
->event_expression
);
350 free(desc
->bytecode
);
354 struct lttng_condition
*lttng_condition_event_rule_create(
355 struct lttng_event_rule
*rule
)
357 struct lttng_condition
*parent
= NULL
;
358 struct lttng_condition_event_rule
*condition
= NULL
;
364 condition
= zmalloc(sizeof(struct lttng_condition_event_rule
));
369 lttng_condition_init(&condition
->parent
,
370 LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
);
371 condition
->parent
.validate
= lttng_condition_event_rule_validate
,
372 condition
->parent
.serialize
= lttng_condition_event_rule_serialize
,
373 condition
->parent
.equal
= lttng_condition_event_rule_is_equal
,
374 condition
->parent
.destroy
= lttng_condition_event_rule_destroy
,
376 lttng_event_rule_get(rule
);
377 condition
->rule
= rule
;
380 lttng_dynamic_pointer_array_init(&condition
->capture_descriptors
,
381 destroy_capture_descriptor
);
383 parent
= &condition
->parent
;
389 uint64_t uint_from_buffer(const struct lttng_buffer_view
*view
, size_t size
,
393 const struct lttng_buffer_view uint_view
=
394 lttng_buffer_view_from_view(view
, *offset
, size
);
396 if (!lttng_buffer_view_is_valid(&uint_view
)) {
403 ret
= (uint64_t) *uint_view
.data
;
405 case sizeof(uint32_t):
409 memcpy(&u32
, uint_view
.data
, sizeof(u32
));
410 ret
= (uint64_t) u32
;
414 memcpy(&ret
, uint_view
.data
, sizeof(ret
));
427 const char *str_from_buffer(const struct lttng_buffer_view
*view
,
433 len
= uint_from_buffer(view
, sizeof(uint32_t), offset
);
434 if (len
== UINT64_C(-1)) {
438 ret
= &view
->data
[*offset
];
440 if (!lttng_buffer_view_contains_string(view
, ret
, len
)) {
455 struct lttng_event_expr
*event_expr_from_payload(
456 struct lttng_payload_view
*view
, size_t *offset
)
458 struct lttng_event_expr
*expr
= NULL
;
462 type
= uint_from_buffer(&view
->buffer
, sizeof(uint8_t), offset
);
463 if (type
== UINT64_C(-1)) {
468 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
469 str
= str_from_buffer(&view
->buffer
, offset
);
474 expr
= lttng_event_expr_event_payload_field_create(str
);
476 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
477 str
= str_from_buffer(&view
->buffer
, offset
);
482 expr
= lttng_event_expr_channel_context_field_create(str
);
484 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
486 const char *provider_name
;
487 const char *type_name
;
489 provider_name
= str_from_buffer(&view
->buffer
, offset
);
490 if (!provider_name
) {
494 type_name
= str_from_buffer(&view
->buffer
, offset
);
499 expr
= lttng_event_expr_app_specific_context_field_create(
500 provider_name
, type_name
);
503 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
505 struct lttng_event_expr
*array_field_expr
;
506 const uint64_t index
= uint_from_buffer(
507 &view
->buffer
, sizeof(uint32_t), offset
);
509 if (index
== UINT64_C(-1)) {
513 /* Array field expression is the encoded after this. */
514 array_field_expr
= event_expr_from_payload(view
, offset
);
515 if (!array_field_expr
) {
519 /* Move ownership of `array_field_expr` to new expression. */
520 expr
= lttng_event_expr_array_field_element_create(
521 array_field_expr
, (unsigned int) index
);
523 /* `array_field_expr` not moved: destroy it. */
524 lttng_event_expr_destroy(array_field_expr
);
536 lttng_event_expr_destroy(expr
);
544 ssize_t
lttng_condition_event_rule_create_from_payload(
545 struct lttng_payload_view
*view
,
546 struct lttng_condition
**_condition
)
548 ssize_t consumed_length
;
550 ssize_t event_rule_length
;
551 uint32_t i
, capture_descr_count
;
552 struct lttng_condition
*condition
= NULL
;
553 struct lttng_event_rule
*event_rule
= NULL
;
555 if (!view
|| !_condition
) {
559 /* Struct lttng_event_rule. */
561 struct lttng_payload_view event_rule_view
=
562 lttng_payload_view_from_view(view
, offset
, -1);
564 event_rule_length
= lttng_event_rule_create_from_payload(
565 &event_rule_view
, &event_rule
);
568 if (event_rule_length
< 0 || !event_rule
) {
572 /* Create condition (no capture descriptors yet) at this point. */
573 condition
= lttng_condition_event_rule_create(event_rule
);
579 /* Capture descriptor count. */
580 assert(event_rule_length
>= 0);
581 offset
+= (size_t) event_rule_length
;
582 capture_descr_count
= uint_from_buffer(&view
->buffer
, sizeof(uint32_t), &offset
);
583 if (capture_descr_count
== UINT32_C(-1)) {
587 /* Capture descriptors. */
588 for (i
= 0; i
< capture_descr_count
; i
++) {
589 struct lttng_event_expr
*expr
= event_expr_from_payload(
591 enum lttng_condition_status status
;
597 /* Move ownership of `expr` to `condition`. */
598 status
= lttng_condition_event_rule_append_capture_descriptor(
600 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
601 /* `expr` not moved: destroy it. */
602 lttng_event_expr_destroy(expr
);
607 consumed_length
= (ssize_t
) offset
;
608 *_condition
= condition
;
613 consumed_length
= -1;
616 lttng_event_rule_put(event_rule
);
617 lttng_condition_put(condition
);
618 return consumed_length
;
622 enum lttng_condition_status
lttng_condition_event_rule_borrow_rule_mutable(
623 const struct lttng_condition
*condition
,
624 struct lttng_event_rule
**rule
)
626 struct lttng_condition_event_rule
*event_rule
;
627 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
629 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !rule
) {
630 status
= LTTNG_CONDITION_STATUS_INVALID
;
634 event_rule
= container_of(
635 condition
, struct lttng_condition_event_rule
, parent
);
636 if (!event_rule
->rule
) {
637 status
= LTTNG_CONDITION_STATUS_UNSET
;
641 *rule
= event_rule
->rule
;
646 enum lttng_condition_status
lttng_condition_event_rule_get_rule(
647 const struct lttng_condition
*condition
,
648 const struct lttng_event_rule
**rule
)
650 struct lttng_event_rule
*mutable_rule
= NULL
;
651 const enum lttng_condition_status status
=
652 lttng_condition_event_rule_borrow_rule_mutable(
653 condition
, &mutable_rule
);
655 *rule
= mutable_rule
;
659 enum lttng_condition_status
660 lttng_condition_event_rule_append_capture_descriptor(
661 struct lttng_condition
*condition
,
662 struct lttng_event_expr
*expr
)
665 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
666 struct lttng_condition_event_rule
*event_rule_cond
=
667 container_of(condition
,
668 struct lttng_condition_event_rule
, parent
);
669 struct lttng_capture_descriptor
*descriptor
= NULL
;
671 /* Only accept l-values. */
672 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !expr
||
673 !lttng_event_expr_is_lvalue(expr
)) {
674 status
= LTTNG_CONDITION_STATUS_INVALID
;
678 descriptor
= malloc(sizeof(*descriptor
));
679 if (descriptor
== NULL
) {
680 status
= LTTNG_CONDITION_STATUS_ERROR
;
684 descriptor
->event_expression
= expr
;
685 descriptor
->bytecode
= NULL
;
687 ret
= lttng_dynamic_pointer_array_add_pointer(
688 &event_rule_cond
->capture_descriptors
, descriptor
);
690 status
= LTTNG_CONDITION_STATUS_ERROR
;
694 /* Ownership is transfered to the internal capture_descriptors array */
701 enum lttng_condition_status
702 lttng_condition_event_rule_get_capture_descriptor_count(
703 const struct lttng_condition
*condition
, unsigned int *count
)
705 enum lttng_condition_status status
= LTTNG_CONDITION_STATUS_OK
;
706 const struct lttng_condition_event_rule
*event_rule_cond
=
707 container_of(condition
,
708 const struct lttng_condition_event_rule
,
711 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
) || !count
) {
712 status
= LTTNG_CONDITION_STATUS_INVALID
;
716 *count
= lttng_dynamic_pointer_array_get_count(
717 &event_rule_cond
->capture_descriptors
);
723 const struct lttng_event_expr
*
724 lttng_condition_event_rule_get_capture_descriptor_at_index(
725 const struct lttng_condition
*condition
, unsigned int index
)
727 const struct lttng_condition_event_rule
*event_rule_cond
=
728 container_of(condition
,
729 const struct lttng_condition_event_rule
,
731 const struct lttng_event_expr
*expr
= NULL
;
732 struct lttng_capture_descriptor
*desc
= NULL
;
734 enum lttng_condition_status status
;
736 if (!condition
|| !IS_EVENT_RULE_CONDITION(condition
)) {
740 status
= lttng_condition_event_rule_get_capture_descriptor_count(condition
, &count
);
741 if (status
!= LTTNG_CONDITION_STATUS_OK
) {
745 if (index
>= count
) {
749 desc
= lttng_dynamic_pointer_array_get_pointer(
750 &event_rule_cond
->capture_descriptors
, index
);
751 expr
= desc
->event_expression
;
758 ssize_t
lttng_evaluation_event_rule_create_from_payload(
759 struct lttng_payload_view
*view
,
760 struct lttng_evaluation
**_evaluation
)
762 ssize_t ret
, offset
= 0;
763 const char *trigger_name
;
764 struct lttng_evaluation
*evaluation
= NULL
;
765 const struct lttng_evaluation_event_rule_comm
*header
;
766 const struct lttng_payload_view header_view
=
767 lttng_payload_view_from_view(
768 view
, 0, sizeof(*header
));
775 if (!lttng_payload_view_is_valid(&header_view
)) {
776 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain header");
781 header
= (typeof(header
)) header_view
.buffer
.data
;
783 /* Map the originating trigger's name. */
784 offset
+= sizeof(*header
);
786 struct lttng_payload_view current_view
=
787 lttng_payload_view_from_view(view
, offset
,
788 header
->trigger_name_length
);
790 if (!lttng_payload_view_is_valid(¤t_view
)) {
791 ERR("Failed to initialize from malformed event rule evaluation: buffer too short to contain trigger name");
796 trigger_name
= current_view
.buffer
.data
;
797 if (!lttng_buffer_view_contains_string(¤t_view
.buffer
,
798 trigger_name
, header
->trigger_name_length
)) {
799 ERR("Failed to initialize from malformed event rule evaluation: invalid trigger name");
805 offset
+= header
->trigger_name_length
;
807 evaluation
= lttng_evaluation_event_rule_create(trigger_name
);
813 *_evaluation
= evaluation
;
818 lttng_evaluation_destroy(evaluation
);
822 static int lttng_evaluation_event_rule_serialize(
823 const struct lttng_evaluation
*evaluation
,
824 struct lttng_payload
*payload
)
827 struct lttng_evaluation_event_rule
*hit
;
828 struct lttng_evaluation_event_rule_comm comm
;
831 evaluation
, struct lttng_evaluation_event_rule
, parent
);
834 comm
.trigger_name_length
= strlen(hit
->name
) + 1;
836 ret
= lttng_dynamic_buffer_append(
837 &payload
->buffer
, &comm
, sizeof(comm
));
842 ret
= lttng_dynamic_buffer_append(
843 &payload
->buffer
, hit
->name
, comm
.trigger_name_length
);
848 static void lttng_evaluation_event_rule_destroy(
849 struct lttng_evaluation
*evaluation
)
851 struct lttng_evaluation_event_rule
*hit
;
854 evaluation
, struct lttng_evaluation_event_rule
, parent
);
860 struct lttng_evaluation
*lttng_evaluation_event_rule_create(
861 const char *trigger_name
)
863 struct lttng_evaluation_event_rule
*hit
;
864 struct lttng_evaluation
*evaluation
= NULL
;
866 hit
= zmalloc(sizeof(struct lttng_evaluation_event_rule
));
871 hit
->name
= strdup(trigger_name
);
876 hit
->parent
.type
= LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
;
877 hit
->parent
.serialize
= lttng_evaluation_event_rule_serialize
;
878 hit
->parent
.destroy
= lttng_evaluation_event_rule_destroy
;
880 evaluation
= &hit
->parent
;
885 lttng_evaluation_event_rule_destroy(&hit
->parent
);
891 enum lttng_evaluation_status
lttng_evaluation_event_rule_get_trigger_name(
892 const struct lttng_evaluation
*evaluation
, const char **name
)
894 struct lttng_evaluation_event_rule
*hit
;
895 enum lttng_evaluation_status status
= LTTNG_EVALUATION_STATUS_OK
;
897 if (!evaluation
|| !is_event_rule_evaluation(evaluation
) || !name
) {
898 status
= LTTNG_EVALUATION_STATUS_INVALID
;
903 evaluation
, struct lttng_evaluation_event_rule
, parent
);