4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
11 #include <common/bytecode/bytecode.hpp>
12 #include <common/error.hpp>
13 #include <common/macros.hpp>
14 #include <common/mi-lttng.hpp>
16 #include <lttng/event-expr-internal.hpp>
17 #include <lttng/event-expr.h>
22 enum lttng_event_expr_type
lttng_event_expr_get_type(const struct lttng_event_expr
*expr
)
24 enum lttng_event_expr_type type
;
27 type
= LTTNG_EVENT_EXPR_TYPE_INVALID
;
37 static struct lttng_event_expr
*create_empty_expr(enum lttng_event_expr_type type
, size_t size
)
39 struct lttng_event_expr
*expr
;
41 expr
= zmalloc
<lttng_event_expr
>(size
);
52 static struct lttng_event_expr_field
*create_field_event_expr(enum lttng_event_expr_type type
,
55 struct lttng_event_expr_field
*expr
= lttng::utils::container_of(
56 create_empty_expr(type
, sizeof(*expr
)), <tng_event_expr_field::parent
);
63 expr
->name
= strdup(name
);
72 lttng_event_expr_destroy(&expr
->parent
);
80 struct lttng_event_expr
*lttng_event_expr_event_payload_field_create(const char *field_name
)
82 struct lttng_event_expr
*expr
= NULL
;
88 expr
= &create_field_event_expr(LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
, field_name
)
95 struct lttng_event_expr
*lttng_event_expr_channel_context_field_create(const char *field_name
)
97 struct lttng_event_expr
*expr
= NULL
;
103 expr
= &create_field_event_expr(LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
, field_name
)
110 struct lttng_event_expr
*
111 lttng_event_expr_app_specific_context_field_create(const char *provider_name
, const char *type_name
)
113 struct lttng_event_expr_app_specific_context_field
*expr
= NULL
;
114 struct lttng_event_expr
*ret_parent_expr
;
116 if (!type_name
|| !provider_name
) {
120 expr
= lttng::utils::container_of(
121 create_empty_expr(LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
, sizeof(*expr
)),
122 <tng_event_expr_app_specific_context_field::parent
);
127 expr
->provider_name
= strdup(provider_name
);
128 if (!expr
->provider_name
) {
132 expr
->type_name
= strdup(type_name
);
133 if (!expr
->type_name
) {
137 ret_parent_expr
= &expr
->parent
;
142 lttng_event_expr_destroy(&expr
->parent
);
144 ret_parent_expr
= NULL
;
147 return ret_parent_expr
;
150 struct lttng_event_expr
*
151 lttng_event_expr_array_field_element_create(struct lttng_event_expr
*array_field_expr
,
154 struct lttng_event_expr_array_field_element
*expr
= NULL
;
155 struct lttng_event_expr
*ret_parent_expr
;
157 /* The parent array field expression must be an l-value */
158 if (!array_field_expr
|| !lttng_event_expr_is_lvalue(array_field_expr
)) {
162 expr
= lttng::utils::container_of(
163 create_empty_expr(LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
, sizeof(*expr
)),
164 <tng_event_expr_array_field_element::parent
);
169 expr
->array_field_expr
= array_field_expr
;
171 ret_parent_expr
= &expr
->parent
;
175 ret_parent_expr
= NULL
;
178 return ret_parent_expr
;
181 const char *lttng_event_expr_event_payload_field_get_name(const struct lttng_event_expr
*expr
)
183 const char *ret
= NULL
;
185 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
) {
189 ret
= lttng::utils::container_of(expr
, <tng_event_expr_field::parent
)->name
;
195 const char *lttng_event_expr_channel_context_field_get_name(const struct lttng_event_expr
*expr
)
197 const char *ret
= NULL
;
199 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
) {
203 ret
= lttng::utils::container_of(expr
, <tng_event_expr_field::parent
)->name
;
210 lttng_event_expr_app_specific_context_field_get_provider_name(const struct lttng_event_expr
*expr
)
212 const char *ret
= NULL
;
214 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
218 ret
= lttng::utils::container_of(expr
, <tng_event_expr_app_specific_context_field::parent
)
226 lttng_event_expr_app_specific_context_field_get_type_name(const struct lttng_event_expr
*expr
)
228 const char *ret
= NULL
;
230 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
234 ret
= lttng::utils::container_of(expr
, <tng_event_expr_app_specific_context_field::parent
)
241 const struct lttng_event_expr
*
242 lttng_event_expr_array_field_element_get_parent_expr(const struct lttng_event_expr
*expr
)
244 const struct lttng_event_expr
*ret
= NULL
;
246 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
) {
250 ret
= lttng::utils::container_of(expr
, <tng_event_expr_array_field_element::parent
)
257 enum lttng_event_expr_status
258 lttng_event_expr_array_field_element_get_index(const struct lttng_event_expr
*expr
,
261 enum lttng_event_expr_status ret
= LTTNG_EVENT_EXPR_STATUS_OK
;
263 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
|| !index
) {
264 ret
= LTTNG_EVENT_EXPR_STATUS_INVALID
;
268 *index
= lttng::utils::container_of(expr
, <tng_event_expr_array_field_element::parent
)
275 bool lttng_event_expr_is_equal(const struct lttng_event_expr
*expr_a
,
276 const struct lttng_event_expr
*expr_b
)
278 bool is_equal
= true;
280 if (!expr_a
&& !expr_b
) {
281 /* Both `NULL`: equal */
285 if (!expr_a
|| !expr_b
) {
286 /* Only one `NULL`: not equal */
290 if (expr_a
->type
!= expr_b
->type
) {
291 /* Different types: not equal */
295 switch (expr_a
->type
) {
296 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
297 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
299 const struct lttng_event_expr_field
*field_expr_a
=
300 lttng::utils::container_of(expr_a
, <tng_event_expr_field::parent
);
301 const struct lttng_event_expr_field
*field_expr_b
=
302 lttng::utils::container_of(expr_b
, <tng_event_expr_field::parent
);
304 if (strcmp(field_expr_a
->name
, field_expr_b
->name
) != 0) {
310 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
312 const struct lttng_event_expr_app_specific_context_field
*field_expr_a
=
313 lttng::utils::container_of(
314 expr_a
, <tng_event_expr_app_specific_context_field::parent
);
315 const struct lttng_event_expr_app_specific_context_field
*field_expr_b
=
316 lttng::utils::container_of(
317 expr_b
, <tng_event_expr_app_specific_context_field::parent
);
319 if (strcmp(field_expr_a
->provider_name
, field_expr_b
->provider_name
) != 0) {
323 if (strcmp(field_expr_a
->type_name
, field_expr_b
->type_name
) != 0) {
329 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
331 const struct lttng_event_expr_array_field_element
*elem_expr_a
=
332 lttng::utils::container_of(expr_a
,
333 <tng_event_expr_array_field_element::parent
);
334 const struct lttng_event_expr_array_field_element
*elem_expr_b
=
335 lttng::utils::container_of(expr_b
,
336 <tng_event_expr_array_field_element::parent
);
338 if (!lttng_event_expr_is_equal(elem_expr_a
->array_field_expr
,
339 elem_expr_b
->array_field_expr
)) {
343 if (elem_expr_a
->index
!= elem_expr_b
->index
) {
362 void lttng_event_expr_destroy(struct lttng_event_expr
*expr
)
368 switch (expr
->type
) {
369 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
370 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
372 struct lttng_event_expr_field
*field_expr
=
373 lttng::utils::container_of(expr
, <tng_event_expr_field::parent
);
375 free(field_expr
->name
);
378 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
380 struct lttng_event_expr_app_specific_context_field
*field_expr
=
381 lttng::utils::container_of(
382 expr
, <tng_event_expr_app_specific_context_field::parent
);
384 free(field_expr
->provider_name
);
385 free(field_expr
->type_name
);
388 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
390 struct lttng_event_expr_array_field_element
*elem_expr
= lttng::utils::container_of(
391 expr
, <tng_event_expr_array_field_element::parent
);
393 lttng_event_expr_destroy(elem_expr
->array_field_expr
);
406 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr
*expr
,
407 struct lttng_bytecode_alloc
**bytecode
,
408 struct lttng_bytecode_alloc
**bytecode_reloc
)
411 enum lttng_event_expr_status event_expr_status
;
413 switch (lttng_event_expr_get_type(expr
)) {
414 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
418 status
= bytecode_push_get_payload_root(bytecode
);
420 ERR("Failed to get payload root from bytecode");
424 name
= lttng_event_expr_event_payload_field_get_name(expr
);
426 ERR("Failed to get payload field name from event expression");
431 status
= bytecode_push_get_symbol(bytecode
, bytecode_reloc
, name
);
433 ERR("Failed to push 'get symbol %s' in bytecode", name
);
439 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
443 status
= bytecode_push_get_context_root(bytecode
);
445 ERR("Failed to get context root from bytecode");
449 name
= lttng_event_expr_channel_context_field_get_name(expr
);
451 ERR("Failed to get channel context field name from event expression");
456 status
= bytecode_push_get_symbol(bytecode
, bytecode_reloc
, name
);
458 ERR("Failed to push 'get symbol %s' in bytecode", name
);
464 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
468 const char *provider_name
, *type_name
;
470 status
= bytecode_push_get_app_context_root(bytecode
);
472 ERR("Failed to get application context root from bytecode");
476 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(expr
);
477 if (!provider_name
) {
478 ERR("Failed to get application context provider name from event expression");
483 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(expr
);
485 ERR("Failed to get application context type name from event expression");
491 * Reconstitute the app context field name from its two parts.
493 ret
= asprintf(&name
, "%s:%s", provider_name
, type_name
);
495 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
502 status
= bytecode_push_get_symbol(bytecode
, bytecode_reloc
, name
);
505 ERR("Failed to push 'get symbol %s:%s' in bytecode",
513 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
516 const struct lttng_event_expr
*parent
;
518 parent
= lttng_event_expr_array_field_element_get_parent_expr(expr
);
520 ERR("Failed to get parent expression from array event expression");
525 status
= event_expr_to_bytecode_recursive(parent
, bytecode
, bytecode_reloc
);
530 event_expr_status
= lttng_event_expr_array_field_element_get_index(expr
, &index
);
531 if (event_expr_status
!= LTTNG_EVENT_EXPR_STATUS_OK
) {
532 ERR("Failed to get array field element index from event expression");
537 status
= bytecode_push_get_index_u64(bytecode
, index
);
539 ERR("Failed to push 'get index %u' in bytecode", index
);
554 int lttng_event_expr_to_bytecode(const struct lttng_event_expr
*expr
,
555 struct lttng_bytecode
**bytecode_out
)
558 struct return_op ret_insn
;
559 struct lttng_bytecode_alloc
*bytecode
= NULL
;
560 struct lttng_bytecode_alloc
*bytecode_reloc
= NULL
;
562 status
= bytecode_init(&bytecode
);
564 ERR("Failed to initialize bytecode");
568 status
= bytecode_init(&bytecode_reloc
);
570 ERR("Failed to initialize relocation bytecode");
574 status
= event_expr_to_bytecode_recursive(expr
, &bytecode
, &bytecode_reloc
);
576 /* Errors already logged. */
580 ret_insn
.op
= BYTECODE_OP_RETURN
;
581 bytecode_push(&bytecode
, &ret_insn
, 1, sizeof(ret_insn
));
583 /* Append symbol table to bytecode. */
584 bytecode
->b
.reloc_table_offset
= bytecode_get_len(&bytecode
->b
);
585 status
= bytecode_push(
586 &bytecode
, bytecode_reloc
->b
.data
, 1, bytecode_get_len(&bytecode_reloc
->b
));
588 ERR("Failed to push symbol table to bytecode");
592 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
593 *bytecode_out
= lttng_bytecode_copy(&bytecode
->b
);
594 if (!*bytecode_out
) {
604 if (bytecode_reloc
) {
605 free(bytecode_reloc
);
611 static enum lttng_error_code
612 lttng_event_expr_event_payload_field_mi_serialize(const struct lttng_event_expr
*expression
,
613 struct mi_writer
*writer
)
616 enum lttng_error_code ret_code
;
617 const char *name
= NULL
;
619 LTTNG_ASSERT(expression
);
620 LTTNG_ASSERT(writer
);
621 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
);
623 name
= lttng_event_expr_event_payload_field_get_name(expression
);
626 /* Open event expr payload field element. */
627 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr_payload_field
);
633 ret
= mi_lttng_writer_write_element_string(writer
, config_element_name
, name
);
638 /* Close event expr payload field element. */
639 ret
= mi_lttng_writer_close_element(writer
);
648 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
653 static enum lttng_error_code
654 lttng_event_expr_channel_context_field_mi_serialize(const struct lttng_event_expr
*expression
,
655 struct mi_writer
*writer
)
658 enum lttng_error_code ret_code
;
659 const char *name
= NULL
;
661 LTTNG_ASSERT(expression
);
662 LTTNG_ASSERT(writer
);
663 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
);
665 name
= lttng_event_expr_channel_context_field_get_name(expression
);
668 /* Open event expr channel context field element. */
669 ret
= mi_lttng_writer_open_element(writer
,
670 mi_lttng_element_event_expr_channel_context_field
);
676 ret
= mi_lttng_writer_write_element_string(writer
, config_element_name
, name
);
681 /* Close event expr channel context field element. */
682 ret
= mi_lttng_writer_close_element(writer
);
691 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
696 static enum lttng_error_code
697 lttng_event_expr_app_specific_context_field_mi_serialize(const struct lttng_event_expr
*expression
,
698 struct mi_writer
*writer
)
701 enum lttng_error_code ret_code
;
702 const char *provider_name
= NULL
;
703 const char *type_name
= NULL
;
705 LTTNG_ASSERT(expression
);
706 LTTNG_ASSERT(writer
);
707 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
);
709 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(expression
);
710 LTTNG_ASSERT(provider_name
);
712 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(expression
);
713 LTTNG_ASSERT(provider_name
);
715 /* Open event expr app specific context field element. */
716 ret
= mi_lttng_writer_open_element(writer
,
717 mi_lttng_element_event_expr_app_specific_context_field
);
723 ret
= mi_lttng_writer_write_element_string(
724 writer
, mi_lttng_element_event_expr_provider_name
, provider_name
);
730 ret
= mi_lttng_writer_write_element_string(
731 writer
, mi_lttng_element_event_expr_type_name
, type_name
);
736 /* Close event expr app specific context field element. */
737 ret
= mi_lttng_writer_close_element(writer
);
746 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
751 static enum lttng_error_code
752 lttng_event_expr_array_field_element_mi_serialize(const struct lttng_event_expr
*expression
,
753 struct mi_writer
*writer
)
756 enum lttng_error_code ret_code
;
757 enum lttng_event_expr_status status
;
758 const struct lttng_event_expr
*parent_expr
= NULL
;
761 LTTNG_ASSERT(expression
);
762 LTTNG_ASSERT(writer
);
763 LTTNG_ASSERT(expression
->type
== LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
);
765 status
= lttng_event_expr_array_field_element_get_index(expression
, &index
);
766 LTTNG_ASSERT(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
768 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(expression
);
769 LTTNG_ASSERT(parent_expr
!= NULL
);
771 /* Open event expr array field element. */
772 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr_array_field_element
);
778 ret
= mi_lttng_writer_write_element_unsigned_int(
779 writer
, mi_lttng_element_event_expr_index
, index
);
784 /* Parent expression. */
785 ret_code
= lttng_event_expr_mi_serialize(parent_expr
, writer
);
786 if (ret_code
!= LTTNG_OK
) {
790 /* Close event expr array field element. */
791 ret
= mi_lttng_writer_close_element(writer
);
800 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
805 enum lttng_error_code
lttng_event_expr_mi_serialize(const struct lttng_event_expr
*expression
,
806 struct mi_writer
*writer
)
809 enum lttng_error_code ret_code
;
811 LTTNG_ASSERT(expression
);
812 LTTNG_ASSERT(writer
);
814 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_expr
);
819 switch (expression
->type
) {
820 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
821 ret_code
= lttng_event_expr_event_payload_field_mi_serialize(expression
, writer
);
823 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
824 ret_code
= lttng_event_expr_channel_context_field_mi_serialize(expression
, writer
);
826 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
827 ret_code
= lttng_event_expr_app_specific_context_field_mi_serialize(expression
,
830 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
831 ret_code
= lttng_event_expr_array_field_element_mi_serialize(expression
, writer
);
837 if (ret_code
!= LTTNG_OK
) {
841 ret
= mi_lttng_writer_close_element(writer
);
850 ret_code
= LTTNG_ERR_MI_IO_FAIL
;