4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
13 #include <common/bytecode/bytecode.hpp>
14 #include <common/error.hpp>
15 #include <common/macros.hpp>
16 #include <common/mi-lttng.hpp>
17 #include <lttng/event-expr-internal.hpp>
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
= zmalloc
<lttng_event_expr
>(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
= lttng::utils::container_of(
60 create_empty_expr(type
, sizeof(*expr
)), <tng_event_expr_field::parent
);
67 expr
->name
= strdup(name
);
76 lttng_event_expr_destroy(&expr
->parent
);
84 struct lttng_event_expr
*lttng_event_expr_event_payload_field_create(
85 const char *field_name
)
87 struct lttng_event_expr
*expr
= NULL
;
93 expr
= &create_field_event_expr(
94 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
,
101 struct lttng_event_expr
*lttng_event_expr_channel_context_field_create(
102 const char *field_name
)
104 struct lttng_event_expr
*expr
= NULL
;
110 expr
= &create_field_event_expr(
111 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
,
118 struct lttng_event_expr
*lttng_event_expr_app_specific_context_field_create(
119 const char *provider_name
, const char *type_name
)
121 struct lttng_event_expr_app_specific_context_field
*expr
= NULL
;
122 struct lttng_event_expr
*ret_parent_expr
;
124 if (!type_name
|| !provider_name
) {
128 expr
= lttng::utils::container_of(create_empty_expr(
129 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
,
131 <tng_event_expr_app_specific_context_field::parent
);
136 expr
->provider_name
= strdup(provider_name
);
137 if (!expr
->provider_name
) {
141 expr
->type_name
= strdup(type_name
);
142 if (!expr
->type_name
) {
146 ret_parent_expr
= &expr
->parent
;
151 lttng_event_expr_destroy(&expr
->parent
);
153 ret_parent_expr
= NULL
;
156 return ret_parent_expr
;
159 struct lttng_event_expr
*lttng_event_expr_array_field_element_create(
160 struct lttng_event_expr
*array_field_expr
,
163 struct lttng_event_expr_array_field_element
*expr
= NULL
;
164 struct lttng_event_expr
*ret_parent_expr
;
166 /* The parent array field expression must be an l-value */
167 if (!array_field_expr
||
168 !lttng_event_expr_is_lvalue(array_field_expr
)) {
172 expr
= lttng::utils::container_of(create_empty_expr(
173 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
,
175 <tng_event_expr_array_field_element::parent
);
180 expr
->array_field_expr
= array_field_expr
;
182 ret_parent_expr
= &expr
->parent
;
186 ret_parent_expr
= NULL
;
189 return ret_parent_expr
;
192 const char *lttng_event_expr_event_payload_field_get_name(
193 const struct lttng_event_expr
*expr
)
195 const char *ret
= NULL
;
197 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
) {
201 ret
= lttng::utils::container_of(expr
,
202 <tng_event_expr_field::parent
)->name
;
208 const char *lttng_event_expr_channel_context_field_get_name(
209 const struct lttng_event_expr
*expr
)
211 const char *ret
= NULL
;
213 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
) {
217 ret
= lttng::utils::container_of(expr
,
218 <tng_event_expr_field::parent
)->name
;
224 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
225 const struct lttng_event_expr
*expr
)
227 const char *ret
= NULL
;
229 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
233 ret
= lttng::utils::container_of(expr
,
234 <tng_event_expr_app_specific_context_field::parent
)->provider_name
;
240 const char *lttng_event_expr_app_specific_context_field_get_type_name(
241 const struct lttng_event_expr
*expr
)
243 const char *ret
= NULL
;
245 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
249 ret
= lttng::utils::container_of(expr
,
250 <tng_event_expr_app_specific_context_field::parent
)->type_name
;
256 const struct lttng_event_expr
*
257 lttng_event_expr_array_field_element_get_parent_expr(
258 const struct lttng_event_expr
*expr
)
260 const struct lttng_event_expr
*ret
= NULL
;
262 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
) {
266 ret
= lttng::utils::container_of(expr
,
267 <tng_event_expr_array_field_element::parent
)->array_field_expr
;
273 enum lttng_event_expr_status
lttng_event_expr_array_field_element_get_index(
274 const struct lttng_event_expr
*expr
, unsigned int *index
)
276 enum lttng_event_expr_status ret
= LTTNG_EVENT_EXPR_STATUS_OK
;
278 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
||
280 ret
= LTTNG_EVENT_EXPR_STATUS_INVALID
;
284 *index
= lttng::utils::container_of(expr
,
285 <tng_event_expr_array_field_element::parent
)->index
;
291 bool lttng_event_expr_is_equal(const struct lttng_event_expr
*expr_a
,
292 const struct lttng_event_expr
*expr_b
)
294 bool is_equal
= true;
296 if (!expr_a
&& !expr_b
) {
297 /* Both `NULL`: equal */
301 if (!expr_a
|| !expr_b
) {
302 /* Only one `NULL`: not equal */
306 if (expr_a
->type
!= expr_b
->type
) {
307 /* Different types: not equal */
311 switch (expr_a
->type
) {
312 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
313 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
315 const struct lttng_event_expr_field
*field_expr_a
=
316 lttng::utils::container_of(expr_a
,
317 <tng_event_expr_field::parent
);
318 const struct lttng_event_expr_field
*field_expr_b
=
319 lttng::utils::container_of(expr_b
,
320 <tng_event_expr_field::parent
);
322 if (strcmp(field_expr_a
->name
, field_expr_b
->name
) != 0) {
328 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
330 const struct lttng_event_expr_app_specific_context_field
*field_expr_a
=
331 lttng::utils::container_of(expr_a
,
332 <tng_event_expr_app_specific_context_field::parent
);
333 const struct lttng_event_expr_app_specific_context_field
*field_expr_b
=
334 lttng::utils::container_of(expr_b
,
335 <tng_event_expr_app_specific_context_field::parent
);
337 if (strcmp(field_expr_a
->provider_name
,
338 field_expr_b
->provider_name
) != 0) {
342 if (strcmp(field_expr_a
->type_name
,
343 field_expr_b
->type_name
) != 0) {
349 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
351 const struct lttng_event_expr_array_field_element
*elem_expr_a
=
352 lttng::utils::container_of(expr_a
,
353 <tng_event_expr_array_field_element::parent
);
354 const struct lttng_event_expr_array_field_element
*elem_expr_b
=
355 lttng::utils::container_of(expr_b
,
356 <tng_event_expr_array_field_element::parent
);
358 if (!lttng_event_expr_is_equal(elem_expr_a
->array_field_expr
,
359 elem_expr_b
->array_field_expr
)) {
363 if (elem_expr_a
->index
!= elem_expr_b
->index
) {
382 void lttng_event_expr_destroy(struct lttng_event_expr
*expr
)
388 switch (expr
->type
) {
389 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
390 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
392 struct lttng_event_expr_field
*field_expr
=
393 lttng::utils::container_of(expr
,
394 <tng_event_expr_field::parent
);
396 free(field_expr
->name
);
399 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
401 struct lttng_event_expr_app_specific_context_field
*field_expr
=
402 lttng::utils::container_of(expr
,
403 <tng_event_expr_app_specific_context_field::parent
);
405 free(field_expr
->provider_name
);
406 free(field_expr
->type_name
);
409 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
411 struct lttng_event_expr_array_field_element
*elem_expr
=
412 lttng::utils::container_of(expr
,
413 <tng_event_expr_array_field_element::parent
);
415 lttng_event_expr_destroy(elem_expr
->array_field_expr
);
428 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr
*expr
,
429 struct lttng_bytecode_alloc
**bytecode
,
430 struct lttng_bytecode_alloc
**bytecode_reloc
)
433 enum lttng_event_expr_status event_expr_status
;
435 switch (lttng_event_expr_get_type(expr
)) {
436 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
440 status
= bytecode_push_get_payload_root(bytecode
);
442 ERR("Failed to get payload root from bytecode");
446 name
= lttng_event_expr_event_payload_field_get_name(expr
);
448 ERR("Failed to get payload field name from event expression");
453 status
= bytecode_push_get_symbol(
454 bytecode
, bytecode_reloc
, name
);
456 ERR("Failed to push 'get symbol %s' in bytecode", name
);
462 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
466 status
= bytecode_push_get_context_root(bytecode
);
468 ERR("Failed to get context root from bytecode");
472 name
= lttng_event_expr_channel_context_field_get_name(expr
);
474 ERR("Failed to get channel context field name from event expression");
479 status
= bytecode_push_get_symbol(
480 bytecode
, bytecode_reloc
, name
);
482 ERR("Failed to push 'get symbol %s' in bytecode", name
);
488 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
492 const char *provider_name
, *type_name
;
494 status
= bytecode_push_get_app_context_root(bytecode
);
496 ERR("Failed to get application context root from bytecode");
500 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
502 if (!provider_name
) {
503 ERR("Failed to get application context provider name from event expression");
508 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
511 ERR("Failed to get application context type name from event expression");
517 * Reconstitute the app context field name from its two parts.
519 ret
= asprintf(&name
, "%s:%s", provider_name
, type_name
);
521 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
522 provider_name
, type_name
);
527 status
= bytecode_push_get_symbol(
528 bytecode
, bytecode_reloc
, name
);
531 ERR("Failed to push 'get symbol %s:%s' in bytecode",
532 provider_name
, type_name
);
538 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
541 const struct lttng_event_expr
*parent
;
543 parent
= lttng_event_expr_array_field_element_get_parent_expr(
546 ERR("Failed to get parent expression from array event expression");
551 status
= event_expr_to_bytecode_recursive(
552 parent
, bytecode
, bytecode_reloc
);
558 lttng_event_expr_array_field_element_get_index(
560 if (event_expr_status
!= LTTNG_EVENT_EXPR_STATUS_OK
) {
561 ERR("Failed to get array field element index from event expression");
566 status
= bytecode_push_get_index_u64(bytecode
, index
);
568 ERR("Failed to push 'get index %u' in bytecode", index
);
583 int lttng_event_expr_to_bytecode(const struct lttng_event_expr
*expr
,
584 struct lttng_bytecode
**bytecode_out
)
587 struct return_op ret_insn
;
588 struct lttng_bytecode_alloc
*bytecode
= NULL
;
589 struct lttng_bytecode_alloc
*bytecode_reloc
= NULL
;
591 status
= bytecode_init(&bytecode
);
593 ERR("Failed to initialize bytecode");
597 status
= bytecode_init(&bytecode_reloc
);
599 ERR("Failed to initialize relocation bytecode");
603 status
= event_expr_to_bytecode_recursive(
604 expr
, &bytecode
, &bytecode_reloc
);
606 /* Errors already logged. */
610 ret_insn
.op
= BYTECODE_OP_RETURN
;
611 bytecode_push(&bytecode
, &ret_insn
, 1, sizeof(ret_insn
));
613 /* Append symbol table to bytecode. */
614 bytecode
->b
.reloc_table_offset
= bytecode_get_len(&bytecode
->b
);
615 status
= bytecode_push(&bytecode
, bytecode_reloc
->b
.data
, 1,
616 bytecode_get_len(&bytecode_reloc
->b
));
618 ERR("Failed to push symbol table to bytecode");
622 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
623 *bytecode_out
= lttng_bytecode_copy(&bytecode
->b
);
624 if (!*bytecode_out
) {
634 if (bytecode_reloc
) {
635 free(bytecode_reloc
);
642 enum lttng_error_code
lttng_event_expr_event_payload_field_mi_serialize(
643 const struct lttng_event_expr
*expression
,
644 struct mi_writer
*writer
)
647 enum lttng_error_code ret_code
;
648 const char *name
= NULL
;
650 LTTNG_ASSERT(expression
);
651 LTTNG_ASSERT(writer
);
652 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
);
654 name
= lttng_event_expr_event_payload_field_get_name(expression
);
657 /* Open event expr payload field element. */
658 ret
= mi_lttng_writer_open_element(
659 writer
, mi_lttng_element_event_expr_payload_field
);
665 ret
= mi_lttng_writer_write_element_string(
666 writer
, config_element_name
, name
);
671 /* Close event expr payload field element. */
672 ret
= mi_lttng_writer_close_element(writer
);
681 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
687 enum lttng_error_code
lttng_event_expr_channel_context_field_mi_serialize(
688 const struct lttng_event_expr
*expression
,
689 struct mi_writer
*writer
)
692 enum lttng_error_code ret_code
;
693 const char *name
= NULL
;
695 LTTNG_ASSERT(expression
);
696 LTTNG_ASSERT(writer
);
697 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
);
699 name
= lttng_event_expr_channel_context_field_get_name(expression
);
702 /* Open event expr channel context field element. */
703 ret
= mi_lttng_writer_open_element(writer
,
704 mi_lttng_element_event_expr_channel_context_field
);
710 ret
= mi_lttng_writer_write_element_string(
711 writer
, config_element_name
, name
);
716 /* Close event expr channel context field element. */
717 ret
= mi_lttng_writer_close_element(writer
);
726 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
732 enum lttng_error_code
lttng_event_expr_app_specific_context_field_mi_serialize(
733 const struct lttng_event_expr
*expression
,
734 struct mi_writer
*writer
)
737 enum lttng_error_code ret_code
;
738 const char *provider_name
= NULL
;
739 const char *type_name
= NULL
;
741 LTTNG_ASSERT(expression
);
742 LTTNG_ASSERT(writer
);
743 LTTNG_ASSERT(expression
->type
==
744 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
);
746 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
748 LTTNG_ASSERT(provider_name
);
750 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
752 LTTNG_ASSERT(provider_name
);
754 /* Open event expr app specific context field element. */
755 ret
= mi_lttng_writer_open_element(writer
,
756 mi_lttng_element_event_expr_app_specific_context_field
);
762 ret
= mi_lttng_writer_write_element_string(writer
,
763 mi_lttng_element_event_expr_provider_name
,
770 ret
= mi_lttng_writer_write_element_string(writer
,
771 mi_lttng_element_event_expr_type_name
, type_name
);
776 /* Close event expr app specific context field element. */
777 ret
= mi_lttng_writer_close_element(writer
);
786 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
792 enum lttng_error_code
lttng_event_expr_array_field_element_mi_serialize(
793 const struct lttng_event_expr
*expression
,
794 struct mi_writer
*writer
)
797 enum lttng_error_code ret_code
;
798 enum lttng_event_expr_status status
;
799 const struct lttng_event_expr
*parent_expr
= NULL
;
802 LTTNG_ASSERT(expression
);
803 LTTNG_ASSERT(writer
);
804 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
);
806 status
= lttng_event_expr_array_field_element_get_index(
808 LTTNG_ASSERT(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
810 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
812 LTTNG_ASSERT(parent_expr
!= NULL
);
814 /* Open event expr array field element. */
815 ret
= mi_lttng_writer_open_element(writer
,
816 mi_lttng_element_event_expr_array_field_element
);
822 ret
= mi_lttng_writer_write_element_unsigned_int(
823 writer
, mi_lttng_element_event_expr_index
, index
);
828 /* Parent expression. */
829 ret_code
= lttng_event_expr_mi_serialize(parent_expr
, writer
);
830 if (ret_code
!= LTTNG_OK
) {
834 /* Close event expr array field element. */
835 ret
= mi_lttng_writer_close_element(writer
);
844 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
849 enum lttng_error_code
lttng_event_expr_mi_serialize(
850 const struct lttng_event_expr
*expression
,
851 struct mi_writer
*writer
)
854 enum lttng_error_code ret_code
;
856 LTTNG_ASSERT(expression
);
857 LTTNG_ASSERT(writer
);
859 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr
);
864 switch (expression
->type
) {
865 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
866 ret_code
= lttng_event_expr_event_payload_field_mi_serialize(
869 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
870 ret_code
= lttng_event_expr_channel_context_field_mi_serialize(
873 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
874 ret_code
= lttng_event_expr_app_specific_context_field_mi_serialize(
877 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
878 ret_code
= lttng_event_expr_array_field_element_mi_serialize(
885 if (ret_code
!= LTTNG_OK
) {
889 ret
= mi_lttng_writer_close_element(writer
);
898 ret_code
= LTTNG_ERR_MI_IO_FAIL
;