4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
14 #include <common/bytecode/bytecode.h>
15 #include <common/error.h>
16 #include <common/macros.h>
17 #include <common/mi-lttng.h>
18 #include <lttng/event-expr-internal.h>
19 #include <lttng/event-expr.h>
22 enum lttng_event_expr_type
lttng_event_expr_get_type(
23 const struct lttng_event_expr
*expr
)
25 enum lttng_event_expr_type type
;
28 type
= LTTNG_EVENT_EXPR_TYPE_INVALID
;
39 struct lttng_event_expr
*create_empty_expr(enum lttng_event_expr_type type
,
42 struct lttng_event_expr
*expr
;
56 struct lttng_event_expr_field
*create_field_event_expr(
57 enum lttng_event_expr_type type
,
60 struct lttng_event_expr_field
*expr
=
62 create_empty_expr(type
, sizeof(*expr
)),
63 struct lttng_event_expr_field
, parent
);
70 expr
->name
= strdup(name
);
79 lttng_event_expr_destroy(&expr
->parent
);
87 struct lttng_event_expr
*lttng_event_expr_event_payload_field_create(
88 const char *field_name
)
90 struct lttng_event_expr
*expr
= NULL
;
96 expr
= &create_field_event_expr(
97 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
,
104 struct lttng_event_expr
*lttng_event_expr_channel_context_field_create(
105 const char *field_name
)
107 struct lttng_event_expr
*expr
= NULL
;
113 expr
= &create_field_event_expr(
114 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
,
121 struct lttng_event_expr
*lttng_event_expr_app_specific_context_field_create(
122 const char *provider_name
, const char *type_name
)
124 struct lttng_event_expr_app_specific_context_field
*expr
= NULL
;
125 struct lttng_event_expr
*ret_parent_expr
;
127 if (!type_name
|| !provider_name
) {
131 expr
= container_of(create_empty_expr(
132 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
,
134 struct lttng_event_expr_app_specific_context_field
,
140 expr
->provider_name
= strdup(provider_name
);
141 if (!expr
->provider_name
) {
145 expr
->type_name
= strdup(type_name
);
146 if (!expr
->type_name
) {
150 ret_parent_expr
= &expr
->parent
;
155 lttng_event_expr_destroy(&expr
->parent
);
157 ret_parent_expr
= NULL
;
160 return ret_parent_expr
;
163 struct lttng_event_expr
*lttng_event_expr_array_field_element_create(
164 struct lttng_event_expr
*array_field_expr
,
167 struct lttng_event_expr_array_field_element
*expr
= NULL
;
168 struct lttng_event_expr
*ret_parent_expr
;
170 /* The parent array field expression must be an l-value */
171 if (!array_field_expr
||
172 !lttng_event_expr_is_lvalue(array_field_expr
)) {
176 expr
= container_of(create_empty_expr(
177 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
,
179 struct lttng_event_expr_array_field_element
,
185 expr
->array_field_expr
= array_field_expr
;
187 ret_parent_expr
= &expr
->parent
;
192 lttng_event_expr_destroy(&expr
->parent
);
194 ret_parent_expr
= NULL
;
197 return ret_parent_expr
;
200 const char *lttng_event_expr_event_payload_field_get_name(
201 const struct lttng_event_expr
*expr
)
203 const char *ret
= NULL
;
205 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
) {
209 ret
= container_of(expr
,
210 const struct lttng_event_expr_field
, parent
)->name
;
216 const char *lttng_event_expr_channel_context_field_get_name(
217 const struct lttng_event_expr
*expr
)
219 const char *ret
= NULL
;
221 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
) {
225 ret
= container_of(expr
,
226 const struct lttng_event_expr_field
, parent
)->name
;
232 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
233 const struct lttng_event_expr
*expr
)
235 const char *ret
= NULL
;
237 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
241 ret
= container_of(expr
,
242 const struct lttng_event_expr_app_specific_context_field
,
243 parent
)->provider_name
;
249 const char *lttng_event_expr_app_specific_context_field_get_type_name(
250 const struct lttng_event_expr
*expr
)
252 const char *ret
= NULL
;
254 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
258 ret
= container_of(expr
,
259 const struct lttng_event_expr_app_specific_context_field
,
266 const struct lttng_event_expr
*
267 lttng_event_expr_array_field_element_get_parent_expr(
268 const struct lttng_event_expr
*expr
)
270 const struct lttng_event_expr
*ret
= NULL
;
272 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
) {
276 ret
= container_of(expr
,
277 const struct lttng_event_expr_array_field_element
,
278 parent
)->array_field_expr
;
284 enum lttng_event_expr_status
lttng_event_expr_array_field_element_get_index(
285 const struct lttng_event_expr
*expr
, unsigned int *index
)
287 enum lttng_event_expr_status ret
= LTTNG_EVENT_EXPR_STATUS_OK
;
289 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
||
291 ret
= LTTNG_EVENT_EXPR_STATUS_INVALID
;
295 *index
= container_of(expr
,
296 const struct lttng_event_expr_array_field_element
,
303 bool lttng_event_expr_is_equal(const struct lttng_event_expr
*expr_a
,
304 const struct lttng_event_expr
*expr_b
)
306 bool is_equal
= true;
308 if (!expr_a
&& !expr_b
) {
309 /* Both `NULL`: equal */
313 if (!expr_a
|| !expr_b
) {
314 /* Only one `NULL`: not equal */
318 if (expr_a
->type
!= expr_b
->type
) {
319 /* Different types: not equal */
323 switch (expr_a
->type
) {
324 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
325 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
327 const struct lttng_event_expr_field
*field_expr_a
=
329 const struct lttng_event_expr_field
,
331 const struct lttng_event_expr_field
*field_expr_b
=
333 const struct lttng_event_expr_field
,
336 if (strcmp(field_expr_a
->name
, field_expr_b
->name
) != 0) {
342 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
344 const struct lttng_event_expr_app_specific_context_field
*field_expr_a
=
346 const struct lttng_event_expr_app_specific_context_field
,
348 const struct lttng_event_expr_app_specific_context_field
*field_expr_b
=
350 const struct lttng_event_expr_app_specific_context_field
,
353 if (strcmp(field_expr_a
->provider_name
,
354 field_expr_b
->provider_name
) != 0) {
358 if (strcmp(field_expr_a
->type_name
,
359 field_expr_b
->type_name
) != 0) {
365 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
367 const struct lttng_event_expr_array_field_element
*elem_expr_a
=
369 const struct lttng_event_expr_array_field_element
,
371 const struct lttng_event_expr_array_field_element
*elem_expr_b
=
373 const struct lttng_event_expr_array_field_element
,
376 if (!lttng_event_expr_is_equal(elem_expr_a
->array_field_expr
,
377 elem_expr_b
->array_field_expr
)) {
381 if (elem_expr_a
->index
!= elem_expr_b
->index
) {
400 void lttng_event_expr_destroy(struct lttng_event_expr
*expr
)
406 switch (expr
->type
) {
407 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
408 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
410 struct lttng_event_expr_field
*field_expr
=
412 struct lttng_event_expr_field
, parent
);
414 free(field_expr
->name
);
417 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
419 struct lttng_event_expr_app_specific_context_field
*field_expr
=
421 struct lttng_event_expr_app_specific_context_field
,
424 free(field_expr
->provider_name
);
425 free(field_expr
->type_name
);
428 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
430 struct lttng_event_expr_array_field_element
*elem_expr
=
432 struct lttng_event_expr_array_field_element
,
435 lttng_event_expr_destroy(elem_expr
->array_field_expr
);
448 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr
*expr
,
449 struct lttng_bytecode_alloc
**bytecode
,
450 struct lttng_bytecode_alloc
**bytecode_reloc
)
453 enum lttng_event_expr_status event_expr_status
;
455 switch (lttng_event_expr_get_type(expr
)) {
456 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
460 status
= bytecode_push_get_payload_root(bytecode
);
462 ERR("Failed to get payload root from bytecode");
466 name
= lttng_event_expr_event_payload_field_get_name(expr
);
468 ERR("Failed to get payload field name from event expression");
473 status
= bytecode_push_get_symbol(
474 bytecode
, bytecode_reloc
, name
);
476 ERR("Failed to push 'get symbol %s' in bytecode", name
);
482 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
486 status
= bytecode_push_get_context_root(bytecode
);
488 ERR("Failed to get context root from bytecode");
492 name
= lttng_event_expr_channel_context_field_get_name(expr
);
494 ERR("Failed to get channel context field name from event expression");
499 status
= bytecode_push_get_symbol(
500 bytecode
, bytecode_reloc
, name
);
502 ERR("Failed to push 'get symbol %s' in bytecode", name
);
508 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
512 const char *provider_name
, *type_name
;
514 status
= bytecode_push_get_app_context_root(bytecode
);
516 ERR("Failed to get application context root from bytecode");
520 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
522 if (!provider_name
) {
523 ERR("Failed to get application context provider name from event expression");
528 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
531 ERR("Failed to get application context type name from event expression");
537 * Reconstitute the app context field name from its two parts.
539 ret
= asprintf(&name
, "%s:%s", provider_name
, type_name
);
541 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
542 provider_name
, type_name
);
547 status
= bytecode_push_get_symbol(
548 bytecode
, bytecode_reloc
, name
);
551 ERR("Failed to push 'get symbol %s:%s' in bytecode",
552 provider_name
, type_name
);
558 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
561 const struct lttng_event_expr
*parent
;
563 parent
= lttng_event_expr_array_field_element_get_parent_expr(
566 ERR("Failed to get parent expression from array event expression");
571 status
= event_expr_to_bytecode_recursive(
572 parent
, bytecode
, bytecode_reloc
);
578 lttng_event_expr_array_field_element_get_index(
580 if (event_expr_status
!= LTTNG_EVENT_EXPR_STATUS_OK
) {
581 ERR("Failed to get array field element index from event expression");
586 status
= bytecode_push_get_index_u64(bytecode
, index
);
588 ERR("Failed to push 'get index %u' in bytecode", index
);
604 int lttng_event_expr_to_bytecode(const struct lttng_event_expr
*expr
,
605 struct lttng_bytecode
**bytecode_out
)
608 struct return_op ret_insn
;
609 struct lttng_bytecode_alloc
*bytecode
= NULL
;
610 struct lttng_bytecode_alloc
*bytecode_reloc
= NULL
;
612 status
= bytecode_init(&bytecode
);
614 ERR("Failed to initialize bytecode");
618 status
= bytecode_init(&bytecode_reloc
);
620 ERR("Failed to initialize relocation bytecode");
624 status
= event_expr_to_bytecode_recursive(
625 expr
, &bytecode
, &bytecode_reloc
);
627 /* Errors already logged. */
631 ret_insn
.op
= BYTECODE_OP_RETURN
;
632 bytecode_push(&bytecode
, &ret_insn
, 1, sizeof(ret_insn
));
634 /* Append symbol table to bytecode. */
635 bytecode
->b
.reloc_table_offset
= bytecode_get_len(&bytecode
->b
);
636 status
= bytecode_push(&bytecode
, bytecode_reloc
->b
.data
, 1,
637 bytecode_get_len(&bytecode_reloc
->b
));
639 ERR("Failed to push symbol table to bytecode");
643 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
644 *bytecode_out
= lttng_bytecode_copy(&bytecode
->b
);
645 if (!*bytecode_out
) {
655 if (bytecode_reloc
) {
656 free(bytecode_reloc
);
663 enum lttng_error_code
lttng_event_expr_event_payload_field_mi_serialize(
664 const struct lttng_event_expr
*expression
,
665 struct mi_writer
*writer
)
668 enum lttng_error_code ret_code
;
669 const char *name
= NULL
;
673 assert(expression
->type
== LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
);
675 name
= lttng_event_expr_event_payload_field_get_name(expression
);
678 /* Open event expr payload field element. */
679 ret
= mi_lttng_writer_open_element(
680 writer
, mi_lttng_element_event_expr_payload_field
);
686 ret
= mi_lttng_writer_write_element_string(
687 writer
, config_element_name
, name
);
692 /* Close event expr payload field element. */
693 ret
= mi_lttng_writer_close_element(writer
);
702 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
708 enum lttng_error_code
lttng_event_expr_channel_context_field_mi_serialize(
709 const struct lttng_event_expr
*expression
,
710 struct mi_writer
*writer
)
713 enum lttng_error_code ret_code
;
714 const char *name
= NULL
;
718 assert(expression
->type
== LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
);
720 name
= lttng_event_expr_channel_context_field_get_name(expression
);
723 /* Open event expr channel context field element. */
724 ret
= mi_lttng_writer_open_element(writer
,
725 mi_lttng_element_event_expr_channel_context_field
);
731 ret
= mi_lttng_writer_write_element_string(
732 writer
, config_element_name
, name
);
737 /* Close event expr channel context field element. */
738 ret
= mi_lttng_writer_close_element(writer
);
747 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
753 enum lttng_error_code
lttng_event_expr_app_specific_context_field_mi_serialize(
754 const struct lttng_event_expr
*expression
,
755 struct mi_writer
*writer
)
758 enum lttng_error_code ret_code
;
759 const char *provider_name
= NULL
;
760 const char *type_name
= NULL
;
764 assert(expression
->type
==
765 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
);
767 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
769 assert(provider_name
);
771 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
773 assert(provider_name
);
775 /* Open event expr app specific context field element. */
776 ret
= mi_lttng_writer_open_element(writer
,
777 mi_lttng_element_event_expr_app_specific_context_field
);
783 ret
= mi_lttng_writer_write_element_string(writer
,
784 mi_lttng_element_event_expr_provider_name
,
791 ret
= mi_lttng_writer_write_element_string(writer
,
792 mi_lttng_element_event_expr_type_name
, type_name
);
797 /* Close event expr app specific context field element. */
798 ret
= mi_lttng_writer_close_element(writer
);
807 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
813 enum lttng_error_code
lttng_event_expr_array_field_element_mi_serialize(
814 const struct lttng_event_expr
*expression
,
815 struct mi_writer
*writer
)
818 enum lttng_error_code ret_code
;
819 enum lttng_event_expr_status status
;
820 const struct lttng_event_expr
*parent_expr
= NULL
;
825 assert(expression
->type
== LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
);
827 status
= lttng_event_expr_array_field_element_get_index(
829 assert(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
831 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
833 assert(parent_expr
!= NULL
);
835 /* Open event expr array field element. */
836 ret
= mi_lttng_writer_open_element(writer
,
837 mi_lttng_element_event_expr_array_field_element
);
843 ret
= mi_lttng_writer_write_element_unsigned_int(
844 writer
, mi_lttng_element_event_expr_index
, index
);
849 /* Parent expression. */
850 ret_code
= lttng_event_expr_mi_serialize(parent_expr
, writer
);
851 if (ret_code
!= LTTNG_OK
) {
855 /* Close event expr array field element. */
856 ret
= mi_lttng_writer_close_element(writer
);
865 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
871 enum lttng_error_code
lttng_event_expr_mi_serialize(
872 const struct lttng_event_expr
*expression
,
873 struct mi_writer
*writer
)
876 enum lttng_error_code ret_code
;
881 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr
);
886 switch (expression
->type
) {
887 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
888 ret_code
= lttng_event_expr_event_payload_field_mi_serialize(
891 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
892 ret_code
= lttng_event_expr_channel_context_field_mi_serialize(
895 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
896 ret_code
= lttng_event_expr_app_specific_context_field_mi_serialize(
899 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
900 ret_code
= lttng_event_expr_array_field_element_mi_serialize(
907 if (ret_code
!= LTTNG_OK
) {
911 ret
= mi_lttng_writer_close_element(writer
);
920 ret_code
= LTTNG_ERR_MI_IO_FAIL
;