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 <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
;
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
;
191 lttng_event_expr_destroy(&expr
->parent
);
193 ret_parent_expr
= NULL
;
196 return ret_parent_expr
;
199 const char *lttng_event_expr_event_payload_field_get_name(
200 const struct lttng_event_expr
*expr
)
202 const char *ret
= NULL
;
204 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
) {
208 ret
= container_of(expr
,
209 const struct lttng_event_expr_field
, parent
)->name
;
215 const char *lttng_event_expr_channel_context_field_get_name(
216 const struct lttng_event_expr
*expr
)
218 const char *ret
= NULL
;
220 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
) {
224 ret
= container_of(expr
,
225 const struct lttng_event_expr_field
, parent
)->name
;
231 const char *lttng_event_expr_app_specific_context_field_get_provider_name(
232 const struct lttng_event_expr
*expr
)
234 const char *ret
= NULL
;
236 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
240 ret
= container_of(expr
,
241 const struct lttng_event_expr_app_specific_context_field
,
242 parent
)->provider_name
;
248 const char *lttng_event_expr_app_specific_context_field_get_type_name(
249 const struct lttng_event_expr
*expr
)
251 const char *ret
= NULL
;
253 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
) {
257 ret
= container_of(expr
,
258 const struct lttng_event_expr_app_specific_context_field
,
265 const struct lttng_event_expr
*
266 lttng_event_expr_array_field_element_get_parent_expr(
267 const struct lttng_event_expr
*expr
)
269 const struct lttng_event_expr
*ret
= NULL
;
271 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
) {
275 ret
= container_of(expr
,
276 const struct lttng_event_expr_array_field_element
,
277 parent
)->array_field_expr
;
283 enum lttng_event_expr_status
lttng_event_expr_array_field_element_get_index(
284 const struct lttng_event_expr
*expr
, unsigned int *index
)
286 enum lttng_event_expr_status ret
= LTTNG_EVENT_EXPR_STATUS_OK
;
288 if (!expr
|| expr
->type
!= LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
||
290 ret
= LTTNG_EVENT_EXPR_STATUS_INVALID
;
294 *index
= container_of(expr
,
295 const struct lttng_event_expr_array_field_element
,
302 bool lttng_event_expr_is_equal(const struct lttng_event_expr
*expr_a
,
303 const struct lttng_event_expr
*expr_b
)
305 bool is_equal
= true;
307 if (!expr_a
&& !expr_b
) {
308 /* Both `NULL`: equal */
312 if (!expr_a
|| !expr_b
) {
313 /* Only one `NULL`: not equal */
317 if (expr_a
->type
!= expr_b
->type
) {
318 /* Different types: not equal */
322 switch (expr_a
->type
) {
323 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
324 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
326 const struct lttng_event_expr_field
*field_expr_a
=
328 const struct lttng_event_expr_field
,
330 const struct lttng_event_expr_field
*field_expr_b
=
332 const struct lttng_event_expr_field
,
335 if (strcmp(field_expr_a
->name
, field_expr_b
->name
) != 0) {
341 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
343 const struct lttng_event_expr_app_specific_context_field
*field_expr_a
=
345 const struct lttng_event_expr_app_specific_context_field
,
347 const struct lttng_event_expr_app_specific_context_field
*field_expr_b
=
349 const struct lttng_event_expr_app_specific_context_field
,
352 if (strcmp(field_expr_a
->provider_name
,
353 field_expr_b
->provider_name
) != 0) {
357 if (strcmp(field_expr_a
->type_name
,
358 field_expr_b
->type_name
) != 0) {
364 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
366 const struct lttng_event_expr_array_field_element
*elem_expr_a
=
368 const struct lttng_event_expr_array_field_element
,
370 const struct lttng_event_expr_array_field_element
*elem_expr_b
=
372 const struct lttng_event_expr_array_field_element
,
375 if (!lttng_event_expr_is_equal(elem_expr_a
->array_field_expr
,
376 elem_expr_b
->array_field_expr
)) {
380 if (elem_expr_a
->index
!= elem_expr_b
->index
) {
399 void lttng_event_expr_destroy(struct lttng_event_expr
*expr
)
405 switch (expr
->type
) {
406 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
407 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
409 struct lttng_event_expr_field
*field_expr
=
411 struct lttng_event_expr_field
, parent
);
413 free(field_expr
->name
);
416 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
418 struct lttng_event_expr_app_specific_context_field
*field_expr
=
420 struct lttng_event_expr_app_specific_context_field
,
423 free(field_expr
->provider_name
);
424 free(field_expr
->type_name
);
427 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
429 struct lttng_event_expr_array_field_element
*elem_expr
=
431 struct lttng_event_expr_array_field_element
,
434 lttng_event_expr_destroy(elem_expr
->array_field_expr
);
447 static int event_expr_to_bytecode_recursive(const struct lttng_event_expr
*expr
,
448 struct lttng_bytecode_alloc
**bytecode
,
449 struct lttng_bytecode_alloc
**bytecode_reloc
)
452 enum lttng_event_expr_status event_expr_status
;
454 switch (lttng_event_expr_get_type(expr
)) {
455 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
459 status
= bytecode_push_get_payload_root(bytecode
);
461 ERR("Failed to get payload root from bytecode");
465 name
= lttng_event_expr_event_payload_field_get_name(expr
);
467 ERR("Failed to get payload field name from event expression");
472 status
= bytecode_push_get_symbol(
473 bytecode
, bytecode_reloc
, name
);
475 ERR("Failed to push 'get symbol %s' in bytecode", name
);
481 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
485 status
= bytecode_push_get_context_root(bytecode
);
487 ERR("Failed to get context root from bytecode");
491 name
= lttng_event_expr_channel_context_field_get_name(expr
);
493 ERR("Failed to get channel context field name from event expression");
498 status
= bytecode_push_get_symbol(
499 bytecode
, bytecode_reloc
, name
);
501 ERR("Failed to push 'get symbol %s' in bytecode", name
);
507 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
511 const char *provider_name
, *type_name
;
513 status
= bytecode_push_get_app_context_root(bytecode
);
515 ERR("Failed to get application context root from bytecode");
519 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
521 if (!provider_name
) {
522 ERR("Failed to get application context provider name from event expression");
527 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
530 ERR("Failed to get application context type name from event expression");
536 * Reconstitute the app context field name from its two parts.
538 ret
= asprintf(&name
, "%s:%s", provider_name
, type_name
);
540 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
541 provider_name
, type_name
);
546 status
= bytecode_push_get_symbol(
547 bytecode
, bytecode_reloc
, name
);
550 ERR("Failed to push 'get symbol %s:%s' in bytecode",
551 provider_name
, type_name
);
557 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
560 const struct lttng_event_expr
*parent
;
562 parent
= lttng_event_expr_array_field_element_get_parent_expr(
565 ERR("Failed to get parent expression from array event expression");
570 status
= event_expr_to_bytecode_recursive(
571 parent
, bytecode
, bytecode_reloc
);
577 lttng_event_expr_array_field_element_get_index(
579 if (event_expr_status
!= LTTNG_EVENT_EXPR_STATUS_OK
) {
580 ERR("Failed to get array field element index from event expression");
585 status
= bytecode_push_get_index_u64(bytecode
, index
);
587 ERR("Failed to push 'get index %u' in bytecode", index
);
603 int lttng_event_expr_to_bytecode(const struct lttng_event_expr
*expr
,
604 struct lttng_bytecode
**bytecode_out
)
607 struct return_op ret_insn
;
608 struct lttng_bytecode_alloc
*bytecode
= NULL
;
609 struct lttng_bytecode_alloc
*bytecode_reloc
= NULL
;
611 status
= bytecode_init(&bytecode
);
613 ERR("Failed to initialize bytecode");
617 status
= bytecode_init(&bytecode_reloc
);
619 ERR("Failed to initialize relocation bytecode");
623 status
= event_expr_to_bytecode_recursive(
624 expr
, &bytecode
, &bytecode_reloc
);
626 /* Errors already logged. */
630 ret_insn
.op
= BYTECODE_OP_RETURN
;
631 bytecode_push(&bytecode
, &ret_insn
, 1, sizeof(ret_insn
));
633 /* Append symbol table to bytecode. */
634 bytecode
->b
.reloc_table_offset
= bytecode_get_len(&bytecode
->b
);
635 status
= bytecode_push(&bytecode
, bytecode_reloc
->b
.data
, 1,
636 bytecode_get_len(&bytecode_reloc
->b
));
638 ERR("Failed to push symbol table to bytecode");
642 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
643 *bytecode_out
= lttng_bytecode_copy(&bytecode
->b
);
644 if (!*bytecode_out
) {
654 if (bytecode_reloc
) {
655 free(bytecode_reloc
);