2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <common/payload.h>
12 #include <common/payload-view.h>
13 #include <common/runas.h>
14 #include <lttng/event-rule/event-rule-internal.h>
15 #include <lttng/event-rule/tracepoint-internal.h>
16 #include <lttng/event.h>
18 #define IS_TRACEPOINT_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
21 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
23 struct lttng_event_rule_tracepoint
*tracepoint
;
29 tracepoint
= container_of(
30 rule
, struct lttng_event_rule_tracepoint
, parent
);
32 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
33 free(tracepoint
->pattern
);
34 free(tracepoint
->filter_expression
);
35 free(tracepoint
->internal_filter
.filter
);
36 free(tracepoint
->internal_filter
.bytecode
);
40 static bool lttng_event_rule_tracepoint_validate(
41 const struct lttng_event_rule
*rule
)
44 struct lttng_event_rule_tracepoint
*tracepoint
;
50 tracepoint
= container_of(
51 rule
, struct lttng_event_rule_tracepoint
, parent
);
54 if (!tracepoint
->pattern
) {
55 ERR("Invalid tracepoint event rule: a pattern must be set.");
60 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
61 ERR("Invalid tracepoint event rule: a domain must be set.");
70 static int lttng_event_rule_tracepoint_serialize(
71 const struct lttng_event_rule
*rule
,
72 struct lttng_payload
*payload
)
75 size_t pattern_len
, filter_expression_len
, exclusions_len
;
76 struct lttng_event_rule_tracepoint
*tracepoint
;
77 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
78 enum lttng_event_rule_status status
;
79 unsigned int exclusion_count
;
80 size_t exclusions_appended_len
= 0;
82 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
87 DBG("Serializing tracepoint event rule.");
88 tracepoint
= container_of(
89 rule
, struct lttng_event_rule_tracepoint
, parent
);
91 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
92 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
94 pattern_len
= strlen(tracepoint
->pattern
) + 1;
96 if (tracepoint
->filter_expression
!= NULL
) {
97 filter_expression_len
=
98 strlen(tracepoint
->filter_expression
) + 1;
100 filter_expression_len
= 0;
104 for (i
= 0; i
< exclusion_count
; i
++) {
105 const char *exclusion
;
107 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
108 rule
, i
, &exclusion
);
109 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
112 exclusions_len
+= sizeof(uint32_t);
113 /* Payload (null terminated). */
114 exclusions_len
+= strlen(exclusion
) + 1;
117 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
118 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
119 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
120 tracepoint_comm
.pattern_len
= pattern_len
;
121 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
122 tracepoint_comm
.exclusions_count
= exclusion_count
;
123 tracepoint_comm
.exclusions_len
= exclusions_len
;
125 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
126 sizeof(tracepoint_comm
));
131 ret
= lttng_dynamic_buffer_append(
132 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
137 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
138 filter_expression_len
);
143 for (i
= 0; i
< exclusion_count
; i
++) {
145 const char *exclusion
;
147 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
148 rule
, i
, &exclusion
);
149 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
151 len
= strlen(exclusion
) + 1;
152 /* Append exclusion length, includes the null terminator. */
153 ret
= lttng_dynamic_buffer_append(
154 &payload
->buffer
, &len
, sizeof(uint32_t));
159 exclusions_appended_len
+= sizeof(uint32_t);
161 /* Include the '\0' in the payload. */
162 ret
= lttng_dynamic_buffer_append(
163 &payload
->buffer
, exclusion
, len
);
168 exclusions_appended_len
+= len
;
171 assert(exclusions_len
== exclusions_appended_len
);
177 static bool lttng_event_rule_tracepoint_is_equal(
178 const struct lttng_event_rule
*_a
,
179 const struct lttng_event_rule
*_b
)
182 bool is_equal
= false;
183 struct lttng_event_rule_tracepoint
*a
, *b
;
184 unsigned int count_a
, count_b
;
185 enum lttng_event_rule_status status
;
187 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
188 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
190 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
191 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
192 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
193 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
196 if (a
->domain
!= b
->domain
) {
200 if (count_a
!= count_b
) {
204 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
211 if (strcmp(a
->pattern
, b
->pattern
)) {
215 if (a
->filter_expression
&& b
->filter_expression
) {
216 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
219 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
220 /* One is set; not the other. */
224 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
228 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
232 for (i
= 0; i
< count_a
; i
++) {
233 const char *exclusion_a
, *exclusion_b
;
235 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
236 _a
, i
, &exclusion_a
);
237 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
238 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
239 _b
, i
, &exclusion_b
);
240 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
241 if (strcmp(exclusion_a
, exclusion_b
)) {
252 * On success ret is 0;
254 * On error ret is negative.
256 * An event with NO loglevel and the name is * will return NULL.
258 static int generate_agent_filter(
259 const struct lttng_event_rule
*rule
, char **_agent_filter
)
263 char *agent_filter
= NULL
;
266 enum lttng_loglevel_type loglevel_type
;
267 enum lttng_event_rule_status status
;
270 assert(_agent_filter
);
272 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
273 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
278 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
279 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
281 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
286 status
= lttng_event_rule_tracepoint_get_log_level_type(
287 rule
, &loglevel_type
);
288 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
293 /* Don't add filter for the '*' event. */
294 if (strcmp(pattern
, "*") != 0) {
296 err
= asprintf(&agent_filter
,
297 "(%s) && (logger_name == \"%s\")",
300 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
305 PERROR("Failed to format agent filter string");
311 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
315 status
= lttng_event_rule_tracepoint_get_log_level(
316 rule
, &loglevel_value
);
317 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
322 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
328 if (filter
|| agent_filter
) {
331 err
= asprintf(&new_filter
,
332 "(%s) && (int_loglevel %s %d)",
333 agent_filter
? agent_filter
: filter
,
338 agent_filter
= new_filter
;
340 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
345 PERROR("Failed to format agent filter string");
351 *_agent_filter
= agent_filter
;
359 static enum lttng_error_code
360 lttng_event_rule_tracepoint_generate_filter_bytecode(
361 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
364 enum lttng_error_code ret_code
;
365 struct lttng_event_rule_tracepoint
*tracepoint
;
366 enum lttng_domain_type domain_type
;
367 enum lttng_event_rule_status status
;
369 struct lttng_bytecode
*bytecode
= NULL
;
373 tracepoint
= container_of(
374 rule
, struct lttng_event_rule_tracepoint
, parent
);
376 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
377 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
379 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
380 ret_code
= LTTNG_ERR_FILTER_INVAL
;
384 if (filter
&& filter
[0] == '\0') {
385 ret_code
= LTTNG_ERR_FILTER_INVAL
;
389 status
= lttng_event_rule_tracepoint_get_domain_type(
391 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
392 ret_code
= LTTNG_ERR_UNK
;
396 switch (domain_type
) {
397 case LTTNG_DOMAIN_LOG4J
:
398 case LTTNG_DOMAIN_JUL
:
399 case LTTNG_DOMAIN_PYTHON
:
403 ret
= generate_agent_filter(rule
, &agent_filter
);
405 ret_code
= LTTNG_ERR_FILTER_INVAL
;
409 tracepoint
->internal_filter
.filter
= agent_filter
;
415 tracepoint
->internal_filter
.filter
= strdup(filter
);
416 if (tracepoint
->internal_filter
.filter
== NULL
) {
417 ret_code
= LTTNG_ERR_NOMEM
;
421 tracepoint
->internal_filter
.filter
= NULL
;
427 if (tracepoint
->internal_filter
.filter
== NULL
) {
432 ret
= run_as_generate_filter_bytecode(
433 tracepoint
->internal_filter
.filter
, uid
, gid
,
436 ret_code
= LTTNG_ERR_FILTER_INVAL
;
440 tracepoint
->internal_filter
.bytecode
= bytecode
;
450 static const char *lttng_event_rule_tracepoint_get_internal_filter(
451 const struct lttng_event_rule
*rule
)
453 struct lttng_event_rule_tracepoint
*tracepoint
;
456 tracepoint
= container_of(
457 rule
, struct lttng_event_rule_tracepoint
, parent
);
458 return tracepoint
->internal_filter
.filter
;
461 static const struct lttng_bytecode
*
462 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
463 const struct lttng_event_rule
*rule
)
465 struct lttng_event_rule_tracepoint
*tracepoint
;
468 tracepoint
= container_of(
469 rule
, struct lttng_event_rule_tracepoint
, parent
);
470 return tracepoint
->internal_filter
.bytecode
;
473 static struct lttng_event_exclusion
*
474 lttng_event_rule_tracepoint_generate_exclusions(
475 const struct lttng_event_rule
*rule
)
477 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
478 enum lttng_event_rule_status status
;
479 struct lttng_event_exclusion
*local_exclusions
= NULL
;
480 struct lttng_event_exclusion
*ret_exclusions
= NULL
;
481 unsigned int nb_exclusions
= 0;
484 status
= lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
485 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
487 switch (domain_type
) {
488 case LTTNG_DOMAIN_KERNEL
:
489 case LTTNG_DOMAIN_JUL
:
490 case LTTNG_DOMAIN_LOG4J
:
491 case LTTNG_DOMAIN_PYTHON
:
493 ret_exclusions
= NULL
;
495 case LTTNG_DOMAIN_UST
:
496 /* Exclusions supported. */
502 status
= lttng_event_rule_tracepoint_get_exclusions_count(
503 rule
, &nb_exclusions
);
504 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
505 if (nb_exclusions
== 0) {
507 ret_exclusions
= NULL
;
511 local_exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
512 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
513 if (!local_exclusions
) {
514 PERROR("Failed to allocate exclusions buffer");
515 ret_exclusions
= NULL
;
519 local_exclusions
->count
= nb_exclusions
;
520 for (i
= 0; i
< nb_exclusions
; i
++) {
521 /* Truncation is already checked at the setter level. */
524 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
526 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
527 strncpy(local_exclusions
->names
[i
], tmp
, LTTNG_SYMBOL_NAME_LEN
);
528 local_exclusions
->names
[i
][LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
531 /* Pass ownership. */
532 ret_exclusions
= local_exclusions
;
533 local_exclusions
= NULL
;
535 free(local_exclusions
);
536 return ret_exclusions
;
539 static void destroy_lttng_exclusions_element(void *ptr
)
544 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
545 const struct lttng_event_rule
*rule
)
547 const struct lttng_event_rule_tracepoint
*tracepoint
;
548 struct lttng_event
*local_event
= NULL
;
549 struct lttng_event
*event
= NULL
;
551 tracepoint
= container_of(
552 rule
, const struct lttng_event_rule_tracepoint
, parent
);
554 local_event
= zmalloc(sizeof(*local_event
));
559 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
560 (void) strncpy(local_event
->name
, tracepoint
->pattern
,
561 sizeof(local_event
->name
) - 1);
562 local_event
->name
[sizeof(local_event
->name
) - 1] = '\0';
563 local_event
->loglevel_type
= tracepoint
->loglevel
.type
;
564 local_event
->loglevel
= tracepoint
->loglevel
.value
;
573 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
574 enum lttng_domain_type domain_type
)
576 struct lttng_event_rule
*rule
= NULL
;
577 struct lttng_event_rule_tracepoint
*tp_rule
;
579 if (domain_type
== LTTNG_DOMAIN_NONE
) {
583 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
588 rule
= &tp_rule
->parent
;
589 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
590 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
591 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
592 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
593 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
594 tp_rule
->parent
.generate_filter_bytecode
=
595 lttng_event_rule_tracepoint_generate_filter_bytecode
;
596 tp_rule
->parent
.get_filter
=
597 lttng_event_rule_tracepoint_get_internal_filter
;
598 tp_rule
->parent
.get_filter_bytecode
=
599 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
600 tp_rule
->parent
.generate_exclusions
=
601 lttng_event_rule_tracepoint_generate_exclusions
;
602 tp_rule
->parent
.generate_lttng_event
=
603 lttng_event_rule_tracepoint_generate_lttng_event
;
605 tp_rule
->domain
= domain_type
;
606 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
608 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
609 destroy_lttng_exclusions_element
);
615 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
616 struct lttng_payload_view
*view
,
617 struct lttng_event_rule
**_event_rule
)
619 ssize_t ret
, offset
= 0;
621 enum lttng_event_rule_status status
;
622 enum lttng_domain_type domain_type
;
623 enum lttng_loglevel_type loglevel_type
;
624 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
626 const char *filter_expression
= NULL
;
627 const char **exclusions
= NULL
;
628 const uint32_t *exclusion_len
;
629 const char *exclusion
;
630 struct lttng_buffer_view current_buffer_view
;
631 struct lttng_event_rule
*rule
= NULL
;
638 if (view
->buffer
.size
< sizeof(*tracepoint_comm
)) {
639 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
644 current_buffer_view
= lttng_buffer_view_from_view(
645 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
646 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
648 if (!tracepoint_comm
) {
653 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
654 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
655 /* Invalid domain value. */
656 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
657 (int) tracepoint_comm
->domain_type
);
662 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
663 rule
= lttng_event_rule_tracepoint_create(domain_type
);
665 ERR("Failed to create event rule tracepoint.");
670 loglevel_type
= (enum lttng_loglevel_type
)
671 tracepoint_comm
->loglevel_type
;
672 switch (loglevel_type
) {
673 case LTTNG_EVENT_LOGLEVEL_ALL
:
674 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
676 case LTTNG_EVENT_LOGLEVEL_RANGE
:
677 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
678 (enum lttng_loglevel_type
) tracepoint_comm
681 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
682 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
683 (enum lttng_loglevel_type
) tracepoint_comm
687 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
692 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
693 ERR("Failed to set event rule tracepoint loglevel.");
696 /* Skip to payload. */
697 offset
+= current_buffer_view
.size
;
699 /* Map the pattern. */
700 current_buffer_view
= lttng_buffer_view_from_view(
701 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
702 pattern
= current_buffer_view
.data
;
708 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
709 tracepoint_comm
->pattern_len
)) {
714 /* Skip after the pattern. */
715 offset
+= tracepoint_comm
->pattern_len
;
717 if (!tracepoint_comm
->filter_expression_len
) {
718 goto skip_filter_expression
;
721 /* Map the filter_expression. */
722 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
723 tracepoint_comm
->filter_expression_len
);
724 filter_expression
= current_buffer_view
.data
;
725 if (!filter_expression
) {
730 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
732 tracepoint_comm
->filter_expression_len
)) {
737 /* Skip after the pattern. */
738 offset
+= tracepoint_comm
->filter_expression_len
;
740 skip_filter_expression
:
741 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
742 current_buffer_view
= lttng_buffer_view_from_view(
743 &view
->buffer
, offset
, sizeof(*exclusion_len
));
744 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
745 if (!exclusion_len
) {
750 offset
+= sizeof(*exclusion_len
);
751 current_buffer_view
= lttng_buffer_view_from_view(
752 &view
->buffer
, offset
, *exclusion_len
);
753 exclusion
= current_buffer_view
.data
;
754 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
755 exclusion
, *exclusion_len
)) {
760 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
761 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
762 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
768 /* Skip to next exclusion. */
769 offset
+= *exclusion_len
;
772 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
773 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
774 ERR("Failed to set event rule tracepoint pattern.");
779 if (filter_expression
) {
780 status
= lttng_event_rule_tracepoint_set_filter(
781 rule
, filter_expression
);
782 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
783 ERR("Failed to set event rule tracepoint pattern.");
794 lttng_event_rule_destroy(rule
);
798 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
799 struct lttng_event_rule
*rule
, const char *pattern
)
801 char *pattern_copy
= NULL
;
802 struct lttng_event_rule_tracepoint
*tracepoint
;
803 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
805 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
806 strlen(pattern
) == 0) {
807 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
811 tracepoint
= container_of(
812 rule
, struct lttng_event_rule_tracepoint
, parent
);
813 pattern_copy
= strdup(pattern
);
815 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
819 free(tracepoint
->pattern
);
821 tracepoint
->pattern
= pattern_copy
;
827 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
828 const struct lttng_event_rule
*rule
, const char **pattern
)
830 struct lttng_event_rule_tracepoint
*tracepoint
;
831 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
833 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
834 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
838 tracepoint
= container_of(
839 rule
, struct lttng_event_rule_tracepoint
, parent
);
840 if (!tracepoint
->pattern
) {
841 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
845 *pattern
= tracepoint
->pattern
;
850 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
851 const struct lttng_event_rule
*rule
,
852 enum lttng_domain_type
*type
)
854 struct lttng_event_rule_tracepoint
*tracepoint
;
855 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
857 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
858 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
862 tracepoint
= container_of(
863 rule
, struct lttng_event_rule_tracepoint
, parent
);
864 *type
= tracepoint
->domain
;
869 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
870 struct lttng_event_rule
*rule
, const char *expression
)
872 char *expression_copy
= NULL
;
873 struct lttng_event_rule_tracepoint
*tracepoint
;
874 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
876 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
877 strlen(expression
) == 0) {
878 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
882 tracepoint
= container_of(
883 rule
, struct lttng_event_rule_tracepoint
, parent
);
884 expression_copy
= strdup(expression
);
885 if (!expression_copy
) {
886 PERROR("Failed to copy filter expression");
887 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
891 if (tracepoint
->filter_expression
) {
892 free(tracepoint
->filter_expression
);
895 tracepoint
->filter_expression
= expression_copy
;
896 expression_copy
= NULL
;
901 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
902 const struct lttng_event_rule
*rule
, const char **expression
)
904 struct lttng_event_rule_tracepoint
*tracepoint
;
905 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
907 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
908 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
912 tracepoint
= container_of(
913 rule
, struct lttng_event_rule_tracepoint
, parent
);
914 if (!tracepoint
->filter_expression
) {
915 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
919 *expression
= tracepoint
->filter_expression
;
924 static bool log_level_value_valid(
925 int level
, enum lttng_domain_type domain
)
930 case LTTNG_DOMAIN_KERNEL
:
931 case LTTNG_DOMAIN_UST
:
932 if (level
< LTTNG_LOGLEVEL_EMERG
) {
936 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
943 case LTTNG_DOMAIN_JUL
:
944 case LTTNG_DOMAIN_LOG4J
:
945 case LTTNG_DOMAIN_PYTHON
:
947 * For both JUL and LOG4J custom log level are possible and can
948 * spawn the entire int32 range.
949 * For python, custom log level are possible, it is not clear if
950 * negative value are accepted (NOTSET == 0) but the source code
951 * validate against the int type implying that negative values
957 case LTTNG_DOMAIN_NONE
:
966 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
967 struct lttng_event_rule
*rule
, int level
)
969 struct lttng_event_rule_tracepoint
*tracepoint
;
970 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
972 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
973 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
977 tracepoint
= container_of(
978 rule
, struct lttng_event_rule_tracepoint
, parent
);
980 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
981 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
985 tracepoint
->loglevel
.value
= level
;
986 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
991 enum lttng_event_rule_status
992 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
993 struct lttng_event_rule
*rule
, int level
)
995 struct lttng_event_rule_tracepoint
*tracepoint
;
996 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
998 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
999 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1003 tracepoint
= container_of(
1004 rule
, struct lttng_event_rule_tracepoint
, parent
);
1006 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1007 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1011 tracepoint
->loglevel
.value
= level
;
1012 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1017 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
1018 struct lttng_event_rule
*rule
)
1020 struct lttng_event_rule_tracepoint
*tracepoint
;
1021 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1023 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1024 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1028 tracepoint
= container_of(
1029 rule
, struct lttng_event_rule_tracepoint
, parent
);
1030 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1035 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1036 const struct lttng_event_rule
*rule
,
1037 enum lttng_loglevel_type
*type
)
1039 struct lttng_event_rule_tracepoint
*tracepoint
;
1040 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1042 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1043 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1047 tracepoint
= container_of(
1048 rule
, struct lttng_event_rule_tracepoint
, parent
);
1049 *type
= tracepoint
->loglevel
.type
;
1054 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1055 const struct lttng_event_rule
*rule
, int *level
)
1057 struct lttng_event_rule_tracepoint
*tracepoint
;
1058 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1060 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1061 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1065 tracepoint
= container_of(
1066 rule
, struct lttng_event_rule_tracepoint
, parent
);
1067 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1068 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1072 *level
= tracepoint
->loglevel
.value
;
1077 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1078 struct lttng_event_rule
*rule
,
1079 const char *exclusion
)
1082 char *exclusion_copy
= NULL
;
1083 struct lttng_event_rule_tracepoint
*tracepoint
;
1084 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1085 enum lttng_domain_type domain_type
;
1087 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1089 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1093 tracepoint
= container_of(
1094 rule
, struct lttng_event_rule_tracepoint
, parent
);
1096 status
= lttng_event_rule_tracepoint_get_domain_type(
1097 rule
, &domain_type
);
1098 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1102 switch (domain_type
) {
1103 case LTTNG_DOMAIN_KERNEL
:
1104 case LTTNG_DOMAIN_JUL
:
1105 case LTTNG_DOMAIN_LOG4J
:
1106 case LTTNG_DOMAIN_PYTHON
:
1107 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1109 case LTTNG_DOMAIN_UST
:
1110 /* Exclusions supported. */
1116 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1117 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1121 exclusion_copy
= strdup(exclusion
);
1122 if (!exclusion_copy
) {
1123 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1127 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1130 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1134 exclusion_copy
= NULL
;
1136 free(exclusion_copy
);
1140 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1141 const struct lttng_event_rule
*rule
, unsigned int *count
)
1143 struct lttng_event_rule_tracepoint
*tracepoint
;
1144 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1146 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1147 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1151 tracepoint
= container_of(
1152 rule
, struct lttng_event_rule_tracepoint
, parent
);
1153 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1158 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1159 const struct lttng_event_rule
*rule
,
1161 const char **exclusion
)
1164 struct lttng_event_rule_tracepoint
*tracepoint
;
1165 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1167 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1168 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1172 tracepoint
= container_of(
1173 rule
, struct lttng_event_rule_tracepoint
, parent
);
1174 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1175 LTTNG_EVENT_RULE_STATUS_OK
) {
1179 if (index
>= count
) {
1183 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1184 &tracepoint
->exclusions
, index
);