4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
13 #include <common/bytecode/bytecode.h>
14 #include <common/error.h>
15 #include <common/macros.h>
16 #include <common/mi-lttng.h>
17 #include <lttng/event-expr-internal.h>
18 #include <lttng/event-expr.h>
21 enum lttng_event_expr_type
lttng_event_expr_get_type(
22 const struct lttng_event_expr
*expr
)
24 enum lttng_event_expr_type type
;
27 type
= LTTNG_EVENT_EXPR_TYPE_INVALID
;
38 struct lttng_event_expr
*create_empty_expr(enum lttng_event_expr_type type
,
41 struct lttng_event_expr
*expr
;
43 expr
= (lttng_event_expr
*) zmalloc(size
);
55 struct lttng_event_expr_field
*create_field_event_expr(
56 enum lttng_event_expr_type type
,
59 struct lttng_event_expr_field
*expr
=
61 create_empty_expr(type
, sizeof(*expr
)),
62 struct lttng_event_expr_field
, parent
);
69 expr
->name
= strdup(name
);
78 lttng_event_expr_destroy(&expr
->parent
);
86 struct lttng_event_expr
*lttng_event_expr_event_payload_field_create(
87 const char *field_name
)
89 struct lttng_event_expr
*expr
= NULL
;
95 expr
= &create_field_event_expr(
96 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
,
103 struct lttng_event_expr
*lttng_event_expr_channel_context_field_create(
104 const char *field_name
)
106 struct lttng_event_expr
*expr
= NULL
;
112 expr
= &create_field_event_expr(
113 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
,
120 struct lttng_event_expr
*lttng_event_expr_app_specific_context_field_create(
121 const char *provider_name
, const char *type_name
)
123 struct lttng_event_expr_app_specific_context_field
*expr
= NULL
;
124 struct lttng_event_expr
*ret_parent_expr
;
126 if (!type_name
|| !provider_name
) {
130 expr
= container_of(create_empty_expr(
131 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
,
133 struct lttng_event_expr_app_specific_context_field
,
139 expr
->provider_name
= strdup(provider_name
);
140 if (!expr
->provider_name
) {
144 expr
->type_name
= strdup(type_name
);
145 if (!expr
->type_name
) {
149 ret_parent_expr
= &expr
->parent
;
154 lttng_event_expr_destroy(&expr
->parent
);
156 ret_parent_expr
= NULL
;
159 return ret_parent_expr
;
162 struct lttng_event_expr
*lttng_event_expr_array_field_element_create(
163 struct lttng_event_expr
*array_field_expr
,
166 struct lttng_event_expr_array_field_element
*expr
= NULL
;
167 struct lttng_event_expr
*ret_parent_expr
;
169 /* The parent array field expression must be an l-value */
170 if (!array_field_expr
||
171 !lttng_event_expr_is_lvalue(array_field_expr
)) {
175 expr
= container_of(create_empty_expr(
176 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
,
178 struct lttng_event_expr_array_field_element
,
184 expr
->array_field_expr
= array_field_expr
;
186 ret_parent_expr
= &expr
->parent
;
190 ret_parent_expr
= NULL
;
193 return ret_parent_expr
;
196 const char *lttng_event_expr_event_payload_field_get_name(
197 const struct lttng_event_expr
*expr
)
199 const char *ret
= NULL
;
201 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
) {
205 ret
= container_of(expr
,
206 const struct lttng_event_expr_field
, parent
)->name
;
212 const char *lttng_event_expr_channel_context_field_get_name(
213 const struct lttng_event_expr
*expr
)
215 const char *ret
= NULL
;
217 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
) {
221 ret
= container_of(expr
,
222 const struct lttng_event_expr_field
, parent
)->name
;
228 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
229 const struct lttng_event_expr
*expr
)
231 const char *ret
= NULL
;
233 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
237 ret
= container_of(expr
,
238 const struct lttng_event_expr_app_specific_context_field
,
239 parent
)->provider_name
;
245 const char *lttng_event_expr_app_specific_context_field_get_type_name(
246 const struct lttng_event_expr
*expr
)
248 const char *ret
= NULL
;
250 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
254 ret
= container_of(expr
,
255 const struct lttng_event_expr_app_specific_context_field
,
262 const struct lttng_event_expr
*
263 lttng_event_expr_array_field_element_get_parent_expr(
264 const struct lttng_event_expr
*expr
)
266 const struct lttng_event_expr
*ret
= NULL
;
268 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
) {
272 ret
= container_of(expr
,
273 const struct lttng_event_expr_array_field_element
,
274 parent
)->array_field_expr
;
280 enum lttng_event_expr_status
lttng_event_expr_array_field_element_get_index(
281 const struct lttng_event_expr
*expr
, unsigned int *index
)
283 enum lttng_event_expr_status ret
= LTTNG_EVENT_EXPR_STATUS_OK
;
285 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
||
287 ret
= LTTNG_EVENT_EXPR_STATUS_INVALID
;
291 *index
= container_of(expr
,
292 const struct lttng_event_expr_array_field_element
,
299 bool lttng_event_expr_is_equal(const struct lttng_event_expr
*expr_a
,
300 const struct lttng_event_expr
*expr_b
)
302 bool is_equal
= true;
304 if (!expr_a
&& !expr_b
) {
305 /* Both `NULL`: equal */
309 if (!expr_a
|| !expr_b
) {
310 /* Only one `NULL`: not equal */
314 if (expr_a
->type
!= expr_b
->type
) {
315 /* Different types: not equal */
319 switch (expr_a
->type
) {
320 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
321 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
323 const struct lttng_event_expr_field
*field_expr_a
=
325 const struct lttng_event_expr_field
,
327 const struct lttng_event_expr_field
*field_expr_b
=
329 const struct lttng_event_expr_field
,
332 if (strcmp(field_expr_a
->name
, field_expr_b
->name
) != 0) {
338 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
340 const struct lttng_event_expr_app_specific_context_field
*field_expr_a
=
342 const struct lttng_event_expr_app_specific_context_field
,
344 const struct lttng_event_expr_app_specific_context_field
*field_expr_b
=
346 const struct lttng_event_expr_app_specific_context_field
,
349 if (strcmp(field_expr_a
->provider_name
,
350 field_expr_b
->provider_name
) != 0) {
354 if (strcmp(field_expr_a
->type_name
,
355 field_expr_b
->type_name
) != 0) {
361 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
363 const struct lttng_event_expr_array_field_element
*elem_expr_a
=
365 const struct lttng_event_expr_array_field_element
,
367 const struct lttng_event_expr_array_field_element
*elem_expr_b
=
369 const struct lttng_event_expr_array_field_element
,
372 if (!lttng_event_expr_is_equal(elem_expr_a
->array_field_expr
,
373 elem_expr_b
->array_field_expr
)) {
377 if (elem_expr_a
->index
!= elem_expr_b
->index
) {
396 void lttng_event_expr_destroy(struct lttng_event_expr
*expr
)
402 switch (expr
->type
) {
403 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
404 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
406 struct lttng_event_expr_field
*field_expr
=
408 struct lttng_event_expr_field
, parent
);
410 free(field_expr
->name
);
413 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
415 struct lttng_event_expr_app_specific_context_field
*field_expr
=
417 struct lttng_event_expr_app_specific_context_field
,
420 free(field_expr
->provider_name
);
421 free(field_expr
->type_name
);
424 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
426 struct lttng_event_expr_array_field_element
*elem_expr
=
428 struct lttng_event_expr_array_field_element
,
431 lttng_event_expr_destroy(elem_expr
->array_field_expr
);
444 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr
*expr
,
445 struct lttng_bytecode_alloc
**bytecode
,
446 struct lttng_bytecode_alloc
**bytecode_reloc
)
449 enum lttng_event_expr_status event_expr_status
;
451 switch (lttng_event_expr_get_type(expr
)) {
452 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
456 status
= bytecode_push_get_payload_root(bytecode
);
458 ERR("Failed to get payload root from bytecode");
462 name
= lttng_event_expr_event_payload_field_get_name(expr
);
464 ERR("Failed to get payload field name from event expression");
469 status
= bytecode_push_get_symbol(
470 bytecode
, bytecode_reloc
, name
);
472 ERR("Failed to push 'get symbol %s' in bytecode", name
);
478 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
482 status
= bytecode_push_get_context_root(bytecode
);
484 ERR("Failed to get context root from bytecode");
488 name
= lttng_event_expr_channel_context_field_get_name(expr
);
490 ERR("Failed to get channel context field name from event expression");
495 status
= bytecode_push_get_symbol(
496 bytecode
, bytecode_reloc
, name
);
498 ERR("Failed to push 'get symbol %s' in bytecode", name
);
504 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
508 const char *provider_name
, *type_name
;
510 status
= bytecode_push_get_app_context_root(bytecode
);
512 ERR("Failed to get application context root from bytecode");
516 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
518 if (!provider_name
) {
519 ERR("Failed to get application context provider name from event expression");
524 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
527 ERR("Failed to get application context type name from event expression");
533 * Reconstitute the app context field name from its two parts.
535 ret
= asprintf(&name
, "%s:%s", provider_name
, type_name
);
537 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
538 provider_name
, type_name
);
543 status
= bytecode_push_get_symbol(
544 bytecode
, bytecode_reloc
, name
);
547 ERR("Failed to push 'get symbol %s:%s' in bytecode",
548 provider_name
, type_name
);
554 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
557 const struct lttng_event_expr
*parent
;
559 parent
= lttng_event_expr_array_field_element_get_parent_expr(
562 ERR("Failed to get parent expression from array event expression");
567 status
= event_expr_to_bytecode_recursive(
568 parent
, bytecode
, bytecode_reloc
);
574 lttng_event_expr_array_field_element_get_index(
576 if (event_expr_status
!= LTTNG_EVENT_EXPR_STATUS_OK
) {
577 ERR("Failed to get array field element index from event expression");
582 status
= bytecode_push_get_index_u64(bytecode
, index
);
584 ERR("Failed to push 'get index %u' in bytecode", index
);
599 int lttng_event_expr_to_bytecode(const struct lttng_event_expr
*expr
,
600 struct lttng_bytecode
**bytecode_out
)
603 struct return_op ret_insn
;
604 struct lttng_bytecode_alloc
*bytecode
= NULL
;
605 struct lttng_bytecode_alloc
*bytecode_reloc
= NULL
;
607 status
= bytecode_init(&bytecode
);
609 ERR("Failed to initialize bytecode");
613 status
= bytecode_init(&bytecode_reloc
);
615 ERR("Failed to initialize relocation bytecode");
619 status
= event_expr_to_bytecode_recursive(
620 expr
, &bytecode
, &bytecode_reloc
);
622 /* Errors already logged. */
626 ret_insn
.op
= BYTECODE_OP_RETURN
;
627 bytecode_push(&bytecode
, &ret_insn
, 1, sizeof(ret_insn
));
629 /* Append symbol table to bytecode. */
630 bytecode
->b
.reloc_table_offset
= bytecode_get_len(&bytecode
->b
);
631 status
= bytecode_push(&bytecode
, bytecode_reloc
->b
.data
, 1,
632 bytecode_get_len(&bytecode_reloc
->b
));
634 ERR("Failed to push symbol table to bytecode");
638 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
639 *bytecode_out
= lttng_bytecode_copy(&bytecode
->b
);
640 if (!*bytecode_out
) {
650 if (bytecode_reloc
) {
651 free(bytecode_reloc
);
658 enum lttng_error_code
lttng_event_expr_event_payload_field_mi_serialize(
659 const struct lttng_event_expr
*expression
,
660 struct mi_writer
*writer
)
663 enum lttng_error_code ret_code
;
664 const char *name
= NULL
;
666 LTTNG_ASSERT(expression
);
667 LTTNG_ASSERT(writer
);
668 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
);
670 name
= lttng_event_expr_event_payload_field_get_name(expression
);
673 /* Open event expr payload field element. */
674 ret
= mi_lttng_writer_open_element(
675 writer
, mi_lttng_element_event_expr_payload_field
);
681 ret
= mi_lttng_writer_write_element_string(
682 writer
, config_element_name
, name
);
687 /* Close event expr payload field element. */
688 ret
= mi_lttng_writer_close_element(writer
);
697 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
703 enum lttng_error_code
lttng_event_expr_channel_context_field_mi_serialize(
704 const struct lttng_event_expr
*expression
,
705 struct mi_writer
*writer
)
708 enum lttng_error_code ret_code
;
709 const char *name
= NULL
;
711 LTTNG_ASSERT(expression
);
712 LTTNG_ASSERT(writer
);
713 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
);
715 name
= lttng_event_expr_channel_context_field_get_name(expression
);
718 /* Open event expr channel context field element. */
719 ret
= mi_lttng_writer_open_element(writer
,
720 mi_lttng_element_event_expr_channel_context_field
);
726 ret
= mi_lttng_writer_write_element_string(
727 writer
, config_element_name
, name
);
732 /* Close event expr channel context field element. */
733 ret
= mi_lttng_writer_close_element(writer
);
742 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
748 enum lttng_error_code
lttng_event_expr_app_specific_context_field_mi_serialize(
749 const struct lttng_event_expr
*expression
,
750 struct mi_writer
*writer
)
753 enum lttng_error_code ret_code
;
754 const char *provider_name
= NULL
;
755 const char *type_name
= NULL
;
757 LTTNG_ASSERT(expression
);
758 LTTNG_ASSERT(writer
);
759 LTTNG_ASSERT(expression
->type
==
760 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
);
762 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
764 LTTNG_ASSERT(provider_name
);
766 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
768 LTTNG_ASSERT(provider_name
);
770 /* Open event expr app specific context field element. */
771 ret
= mi_lttng_writer_open_element(writer
,
772 mi_lttng_element_event_expr_app_specific_context_field
);
778 ret
= mi_lttng_writer_write_element_string(writer
,
779 mi_lttng_element_event_expr_provider_name
,
786 ret
= mi_lttng_writer_write_element_string(writer
,
787 mi_lttng_element_event_expr_type_name
, type_name
);
792 /* Close event expr app specific context field element. */
793 ret
= mi_lttng_writer_close_element(writer
);
802 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
808 enum lttng_error_code
lttng_event_expr_array_field_element_mi_serialize(
809 const struct lttng_event_expr
*expression
,
810 struct mi_writer
*writer
)
813 enum lttng_error_code ret_code
;
814 enum lttng_event_expr_status status
;
815 const struct lttng_event_expr
*parent_expr
= NULL
;
818 LTTNG_ASSERT(expression
);
819 LTTNG_ASSERT(writer
);
820 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
);
822 status
= lttng_event_expr_array_field_element_get_index(
824 LTTNG_ASSERT(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
826 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
828 LTTNG_ASSERT(parent_expr
!= NULL
);
830 /* Open event expr array field element. */
831 ret
= mi_lttng_writer_open_element(writer
,
832 mi_lttng_element_event_expr_array_field_element
);
838 ret
= mi_lttng_writer_write_element_unsigned_int(
839 writer
, mi_lttng_element_event_expr_index
, index
);
844 /* Parent expression. */
845 ret_code
= lttng_event_expr_mi_serialize(parent_expr
, writer
);
846 if (ret_code
!= LTTNG_OK
) {
850 /* Close event expr array field element. */
851 ret
= mi_lttng_writer_close_element(writer
);
860 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
865 enum lttng_error_code
lttng_event_expr_mi_serialize(
866 const struct lttng_event_expr
*expression
,
867 struct mi_writer
*writer
)
870 enum lttng_error_code ret_code
;
872 LTTNG_ASSERT(expression
);
873 LTTNG_ASSERT(writer
);
875 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr
);
880 switch (expression
->type
) {
881 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
882 ret_code
= lttng_event_expr_event_payload_field_mi_serialize(
885 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
886 ret_code
= lttng_event_expr_channel_context_field_mi_serialize(
889 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
890 ret_code
= lttng_event_expr_app_specific_context_field_mi_serialize(
893 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
894 ret_code
= lttng_event_expr_array_field_element_mi_serialize(
901 if (ret_code
!= LTTNG_OK
) {
905 ret
= mi_lttng_writer_close_element(writer
);
914 ret_code
= LTTNG_ERR_MI_IO_FAIL
;