2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/runas.h>
15 #include <lttng/event-rule/event-rule-internal.h>
16 #include <lttng/event-rule/tracepoint-internal.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
,
362 const struct lttng_credentials
*creds
)
365 enum lttng_error_code ret_code
;
366 struct lttng_event_rule_tracepoint
*tracepoint
;
367 enum lttng_domain_type domain_type
;
368 enum lttng_event_rule_status status
;
370 struct lttng_filter_bytecode
*bytecode
= NULL
;
374 tracepoint
= container_of(
375 rule
, struct lttng_event_rule_tracepoint
, parent
);
377 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
378 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
380 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
381 ret_code
= LTTNG_ERR_FILTER_INVAL
;
385 if (filter
&& filter
[0] == '\0') {
386 ret_code
= LTTNG_ERR_FILTER_INVAL
;
390 status
= lttng_event_rule_tracepoint_get_domain_type(
392 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
393 ret_code
= LTTNG_ERR_UNK
;
397 switch (domain_type
) {
398 case LTTNG_DOMAIN_LOG4J
:
399 case LTTNG_DOMAIN_JUL
:
400 case LTTNG_DOMAIN_PYTHON
:
404 ret
= generate_agent_filter(rule
, &agent_filter
);
406 ret_code
= LTTNG_ERR_FILTER_INVAL
;
410 tracepoint
->internal_filter
.filter
= agent_filter
;
416 tracepoint
->internal_filter
.filter
= strdup(filter
);
417 if (tracepoint
->internal_filter
.filter
== NULL
) {
418 ret_code
= LTTNG_ERR_NOMEM
;
422 tracepoint
->internal_filter
.filter
= NULL
;
428 if (tracepoint
->internal_filter
.filter
== NULL
) {
433 ret
= run_as_generate_filter_bytecode(
434 tracepoint
->internal_filter
.filter
, creds
,
437 ret_code
= LTTNG_ERR_FILTER_INVAL
;
441 tracepoint
->internal_filter
.bytecode
= bytecode
;
451 static const char *lttng_event_rule_tracepoint_get_internal_filter(
452 const struct lttng_event_rule
*rule
)
454 struct lttng_event_rule_tracepoint
*tracepoint
;
457 tracepoint
= container_of(
458 rule
, struct lttng_event_rule_tracepoint
, parent
);
459 return tracepoint
->internal_filter
.filter
;
462 static const struct lttng_filter_bytecode
*
463 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
464 const struct lttng_event_rule
*rule
)
466 struct lttng_event_rule_tracepoint
*tracepoint
;
469 tracepoint
= container_of(
470 rule
, struct lttng_event_rule_tracepoint
, parent
);
471 return tracepoint
->internal_filter
.bytecode
;
474 static struct lttng_event_exclusion
*
475 lttng_event_rule_tracepoint_generate_exclusions(
476 const struct lttng_event_rule
*rule
)
478 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
479 enum lttng_event_rule_status status
;
480 struct lttng_event_exclusion
*local_exclusions
= NULL
;
481 struct lttng_event_exclusion
*ret_exclusions
= NULL
;
482 unsigned int nb_exclusions
= 0;
485 status
= lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
486 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
488 switch (domain_type
) {
489 case LTTNG_DOMAIN_KERNEL
:
490 case LTTNG_DOMAIN_JUL
:
491 case LTTNG_DOMAIN_LOG4J
:
492 case LTTNG_DOMAIN_PYTHON
:
494 ret_exclusions
= NULL
;
496 case LTTNG_DOMAIN_UST
:
497 /* Exclusions supported. */
503 status
= lttng_event_rule_tracepoint_get_exclusions_count(
504 rule
, &nb_exclusions
);
505 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
506 if (nb_exclusions
== 0) {
508 ret_exclusions
= NULL
;
512 local_exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
513 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
514 if (!local_exclusions
) {
515 PERROR("Failed to allocate exclusions buffer");
516 ret_exclusions
= NULL
;
520 local_exclusions
->count
= nb_exclusions
;
521 for (i
= 0; i
< nb_exclusions
; i
++) {
522 /* Truncation is already checked at the setter level. */
525 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
527 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
528 strncpy(local_exclusions
->names
[i
], tmp
, LTTNG_SYMBOL_NAME_LEN
);
529 local_exclusions
->names
[i
][LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
532 /* Pass ownership. */
533 ret_exclusions
= local_exclusions
;
534 local_exclusions
= NULL
;
536 free(local_exclusions
);
537 return ret_exclusions
;
540 static void destroy_lttng_exclusions_element(void *ptr
)
545 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
546 enum lttng_domain_type domain_type
)
548 struct lttng_event_rule
*rule
= NULL
;
549 struct lttng_event_rule_tracepoint
*tp_rule
;
551 if (domain_type
== LTTNG_DOMAIN_NONE
) {
555 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
560 rule
= &tp_rule
->parent
;
561 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
562 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
563 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
564 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
565 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
566 tp_rule
->parent
.generate_filter_bytecode
=
567 lttng_event_rule_tracepoint_generate_filter_bytecode
;
568 tp_rule
->parent
.get_filter
=
569 lttng_event_rule_tracepoint_get_internal_filter
;
570 tp_rule
->parent
.get_filter_bytecode
=
571 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
572 tp_rule
->parent
.generate_exclusions
=
573 lttng_event_rule_tracepoint_generate_exclusions
;
575 tp_rule
->domain
= domain_type
;
576 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
578 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
579 destroy_lttng_exclusions_element
);
585 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
586 struct lttng_payload_view
*view
,
587 struct lttng_event_rule
**_event_rule
)
589 ssize_t ret
, offset
= 0;
591 enum lttng_event_rule_status status
;
592 enum lttng_domain_type domain_type
;
593 enum lttng_loglevel_type loglevel_type
;
594 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
596 const char *filter_expression
= NULL
;
597 const char **exclusions
= NULL
;
598 const uint32_t *exclusion_len
;
599 const char *exclusion
;
600 struct lttng_buffer_view current_buffer_view
;
601 struct lttng_event_rule
*rule
= NULL
;
608 current_buffer_view
= lttng_buffer_view_from_view(
609 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
610 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
611 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
616 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
618 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
619 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
620 /* Invalid domain value. */
621 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
622 (int) tracepoint_comm
->domain_type
);
627 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
628 rule
= lttng_event_rule_tracepoint_create(domain_type
);
630 ERR("Failed to create event rule tracepoint.");
635 loglevel_type
= (enum lttng_loglevel_type
)
636 tracepoint_comm
->loglevel_type
;
637 switch (loglevel_type
) {
638 case LTTNG_EVENT_LOGLEVEL_ALL
:
639 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
641 case LTTNG_EVENT_LOGLEVEL_RANGE
:
642 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
643 (enum lttng_loglevel_type
) tracepoint_comm
646 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
647 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
648 (enum lttng_loglevel_type
) tracepoint_comm
652 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
657 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
658 ERR("Failed to set event rule tracepoint loglevel.");
661 /* Skip to payload. */
662 offset
+= current_buffer_view
.size
;
664 /* Map the pattern. */
665 current_buffer_view
= lttng_buffer_view_from_view(
666 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
668 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
673 pattern
= current_buffer_view
.data
;
674 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
675 tracepoint_comm
->pattern_len
)) {
680 /* Skip after the pattern. */
681 offset
+= tracepoint_comm
->pattern_len
;
683 if (!tracepoint_comm
->filter_expression_len
) {
684 goto skip_filter_expression
;
687 /* Map the filter_expression. */
688 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
689 tracepoint_comm
->filter_expression_len
);
690 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
695 filter_expression
= current_buffer_view
.data
;
696 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
698 tracepoint_comm
->filter_expression_len
)) {
703 /* Skip after the pattern. */
704 offset
+= tracepoint_comm
->filter_expression_len
;
706 skip_filter_expression
:
707 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
708 current_buffer_view
= lttng_buffer_view_from_view(
709 &view
->buffer
, offset
, sizeof(*exclusion_len
));
710 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
715 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
716 offset
+= sizeof(*exclusion_len
);
718 current_buffer_view
= lttng_buffer_view_from_view(
719 &view
->buffer
, offset
, *exclusion_len
);
720 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
725 exclusion
= current_buffer_view
.data
;
726 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
727 exclusion
, *exclusion_len
)) {
732 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
733 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
734 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
740 /* Skip to next exclusion. */
741 offset
+= *exclusion_len
;
744 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
745 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
746 ERR("Failed to set event rule tracepoint pattern.");
751 if (filter_expression
) {
752 status
= lttng_event_rule_tracepoint_set_filter(
753 rule
, filter_expression
);
754 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
755 ERR("Failed to set event rule tracepoint pattern.");
766 lttng_event_rule_destroy(rule
);
770 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
771 struct lttng_event_rule
*rule
, const char *pattern
)
773 char *pattern_copy
= NULL
;
774 struct lttng_event_rule_tracepoint
*tracepoint
;
775 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
777 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
778 strlen(pattern
) == 0) {
779 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
783 tracepoint
= container_of(
784 rule
, struct lttng_event_rule_tracepoint
, parent
);
785 pattern_copy
= strdup(pattern
);
787 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
791 free(tracepoint
->pattern
);
793 tracepoint
->pattern
= pattern_copy
;
799 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
800 const struct lttng_event_rule
*rule
, const char **pattern
)
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 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
810 tracepoint
= container_of(
811 rule
, struct lttng_event_rule_tracepoint
, parent
);
812 if (!tracepoint
->pattern
) {
813 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
817 *pattern
= tracepoint
->pattern
;
822 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
823 const struct lttng_event_rule
*rule
,
824 enum lttng_domain_type
*type
)
826 struct lttng_event_rule_tracepoint
*tracepoint
;
827 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
829 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
830 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
834 tracepoint
= container_of(
835 rule
, struct lttng_event_rule_tracepoint
, parent
);
836 *type
= tracepoint
->domain
;
841 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
842 struct lttng_event_rule
*rule
, const char *expression
)
844 char *expression_copy
= NULL
;
845 struct lttng_event_rule_tracepoint
*tracepoint
;
846 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
848 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
849 strlen(expression
) == 0) {
850 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
854 tracepoint
= container_of(
855 rule
, struct lttng_event_rule_tracepoint
, parent
);
856 expression_copy
= strdup(expression
);
857 if (!expression_copy
) {
858 PERROR("Failed to copy filter expression");
859 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
863 if (tracepoint
->filter_expression
) {
864 free(tracepoint
->filter_expression
);
867 tracepoint
->filter_expression
= expression_copy
;
868 expression_copy
= NULL
;
873 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
874 const struct lttng_event_rule
*rule
, const char **expression
)
876 struct lttng_event_rule_tracepoint
*tracepoint
;
877 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
879 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
880 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
884 tracepoint
= container_of(
885 rule
, struct lttng_event_rule_tracepoint
, parent
);
886 if (!tracepoint
->filter_expression
) {
887 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
891 *expression
= tracepoint
->filter_expression
;
896 static bool log_level_value_valid(
897 int level
, enum lttng_domain_type domain
)
902 case LTTNG_DOMAIN_KERNEL
:
903 case LTTNG_DOMAIN_UST
:
904 if (level
< LTTNG_LOGLEVEL_EMERG
) {
908 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
915 case LTTNG_DOMAIN_JUL
:
916 case LTTNG_DOMAIN_LOG4J
:
917 case LTTNG_DOMAIN_PYTHON
:
919 * For both JUL and LOG4J custom log level are possible and can
920 * spawn the entire int32 range.
921 * For python, custom log level are possible, it is not clear if
922 * negative value are accepted (NOTSET == 0) but the source code
923 * validate against the int type implying that negative values
929 case LTTNG_DOMAIN_NONE
:
938 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
939 struct lttng_event_rule
*rule
, int level
)
941 struct lttng_event_rule_tracepoint
*tracepoint
;
942 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
944 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
945 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
949 tracepoint
= container_of(
950 rule
, struct lttng_event_rule_tracepoint
, parent
);
952 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
953 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
957 tracepoint
->loglevel
.value
= level
;
958 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
963 enum lttng_event_rule_status
964 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
965 struct lttng_event_rule
*rule
, int level
)
967 struct lttng_event_rule_tracepoint
*tracepoint
;
968 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
970 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
971 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
975 tracepoint
= container_of(
976 rule
, struct lttng_event_rule_tracepoint
, parent
);
978 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
979 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
983 tracepoint
->loglevel
.value
= level
;
984 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
989 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
990 struct lttng_event_rule
*rule
)
992 struct lttng_event_rule_tracepoint
*tracepoint
;
993 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
995 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
996 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1000 tracepoint
= container_of(
1001 rule
, struct lttng_event_rule_tracepoint
, parent
);
1002 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1007 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1008 const struct lttng_event_rule
*rule
,
1009 enum lttng_loglevel_type
*type
)
1011 struct lttng_event_rule_tracepoint
*tracepoint
;
1012 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1014 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1015 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1019 tracepoint
= container_of(
1020 rule
, struct lttng_event_rule_tracepoint
, parent
);
1021 *type
= tracepoint
->loglevel
.type
;
1026 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1027 const struct lttng_event_rule
*rule
, int *level
)
1029 struct lttng_event_rule_tracepoint
*tracepoint
;
1030 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1032 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1033 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1037 tracepoint
= container_of(
1038 rule
, struct lttng_event_rule_tracepoint
, parent
);
1039 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1040 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1044 *level
= tracepoint
->loglevel
.value
;
1049 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1050 struct lttng_event_rule
*rule
,
1051 const char *exclusion
)
1054 char *exclusion_copy
= NULL
;
1055 struct lttng_event_rule_tracepoint
*tracepoint
;
1056 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1057 enum lttng_domain_type domain_type
;
1059 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1061 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1065 tracepoint
= container_of(
1066 rule
, struct lttng_event_rule_tracepoint
, parent
);
1068 status
= lttng_event_rule_tracepoint_get_domain_type(
1069 rule
, &domain_type
);
1070 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1074 switch (domain_type
) {
1075 case LTTNG_DOMAIN_KERNEL
:
1076 case LTTNG_DOMAIN_JUL
:
1077 case LTTNG_DOMAIN_LOG4J
:
1078 case LTTNG_DOMAIN_PYTHON
:
1079 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1081 case LTTNG_DOMAIN_UST
:
1082 /* Exclusions supported. */
1088 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1089 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1093 exclusion_copy
= strdup(exclusion
);
1094 if (!exclusion_copy
) {
1095 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1099 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1102 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1106 exclusion_copy
= NULL
;
1108 free(exclusion_copy
);
1112 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1113 const struct lttng_event_rule
*rule
, unsigned int *count
)
1115 struct lttng_event_rule_tracepoint
*tracepoint
;
1116 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1118 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1119 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1123 tracepoint
= container_of(
1124 rule
, struct lttng_event_rule_tracepoint
, parent
);
1125 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1130 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1131 const struct lttng_event_rule
*rule
,
1133 const char **exclusion
)
1136 struct lttng_event_rule_tracepoint
*tracepoint
;
1137 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1139 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1140 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1144 tracepoint
= container_of(
1145 rule
, struct lttng_event_rule_tracepoint
, parent
);
1146 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1147 LTTNG_EVENT_RULE_STATUS_OK
) {
1151 if (index
>= count
) {
1155 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1156 &tracepoint
->exclusions
, index
);