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>
17 #define IS_TRACEPOINT_EVENT_RULE(rule) \
18 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
20 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
22 struct lttng_event_rule_tracepoint
*tracepoint
;
28 tracepoint
= container_of(
29 rule
, struct lttng_event_rule_tracepoint
, parent
);
31 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
32 free(tracepoint
->pattern
);
33 free(tracepoint
->filter_expression
);
34 free(tracepoint
->internal_filter
.filter
);
35 free(tracepoint
->internal_filter
.bytecode
);
39 static bool lttng_event_rule_tracepoint_validate(
40 const struct lttng_event_rule
*rule
)
43 struct lttng_event_rule_tracepoint
*tracepoint
;
49 tracepoint
= container_of(
50 rule
, struct lttng_event_rule_tracepoint
, parent
);
53 if (!tracepoint
->pattern
) {
54 ERR("Invalid tracepoint event rule: a pattern must be set.");
59 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
60 ERR("Invalid tracepoint event rule: a domain must be set.");
69 static int lttng_event_rule_tracepoint_serialize(
70 const struct lttng_event_rule
*rule
,
71 struct lttng_payload
*payload
)
74 size_t pattern_len
, filter_expression_len
, exclusions_len
;
75 struct lttng_event_rule_tracepoint
*tracepoint
;
76 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
77 enum lttng_event_rule_status status
;
78 unsigned int exclusion_count
;
79 size_t exclusions_appended_len
= 0;
81 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
86 DBG("Serializing tracepoint event rule.");
87 tracepoint
= container_of(
88 rule
, struct lttng_event_rule_tracepoint
, parent
);
90 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
91 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
93 pattern_len
= strlen(tracepoint
->pattern
) + 1;
95 if (tracepoint
->filter_expression
!= NULL
) {
96 filter_expression_len
=
97 strlen(tracepoint
->filter_expression
) + 1;
99 filter_expression_len
= 0;
103 for (i
= 0; i
< exclusion_count
; i
++) {
104 const char *exclusion
;
106 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
107 rule
, i
, &exclusion
);
108 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
111 exclusions_len
+= sizeof(uint32_t);
112 /* Payload (null terminated). */
113 exclusions_len
+= strlen(exclusion
) + 1;
116 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
117 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
118 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
119 tracepoint_comm
.pattern_len
= pattern_len
;
120 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
121 tracepoint_comm
.exclusions_count
= exclusion_count
;
122 tracepoint_comm
.exclusions_len
= exclusions_len
;
124 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
125 sizeof(tracepoint_comm
));
130 ret
= lttng_dynamic_buffer_append(
131 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
136 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
137 filter_expression_len
);
142 for (i
= 0; i
< exclusion_count
; i
++) {
144 const char *exclusion
;
146 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
147 rule
, i
, &exclusion
);
148 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
150 len
= strlen(exclusion
) + 1;
151 /* Append exclusion length, includes the null terminator. */
152 ret
= lttng_dynamic_buffer_append(
153 &payload
->buffer
, &len
, sizeof(uint32_t));
158 exclusions_appended_len
+= sizeof(uint32_t);
160 /* Include the '\0' in the payload. */
161 ret
= lttng_dynamic_buffer_append(
162 &payload
->buffer
, exclusion
, len
);
167 exclusions_appended_len
+= len
;
170 assert(exclusions_len
== exclusions_appended_len
);
176 static bool lttng_event_rule_tracepoint_is_equal(
177 const struct lttng_event_rule
*_a
,
178 const struct lttng_event_rule
*_b
)
181 bool is_equal
= false;
182 struct lttng_event_rule_tracepoint
*a
, *b
;
183 unsigned int count_a
, count_b
;
184 enum lttng_event_rule_status status
;
186 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
187 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
189 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
190 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
191 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
192 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
195 if (a
->domain
!= b
->domain
) {
199 if (count_a
!= count_b
) {
203 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
210 if (strcmp(a
->pattern
, b
->pattern
)) {
214 if (a
->filter_expression
&& b
->filter_expression
) {
215 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
218 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
219 /* One is set; not the other. */
223 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
227 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
231 for (i
= 0; i
< count_a
; i
++) {
232 const char *exclusion_a
, *exclusion_b
;
234 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
235 _a
, i
, &exclusion_a
);
236 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
237 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
238 _b
, i
, &exclusion_b
);
239 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
240 if (strcmp(exclusion_a
, exclusion_b
)) {
251 * On success ret is 0;
253 * On error ret is negative.
255 * An event with NO loglevel and the name is * will return NULL.
257 static int generate_agent_filter(
258 const struct lttng_event_rule
*rule
, char **_agent_filter
)
262 char *agent_filter
= NULL
;
265 enum lttng_loglevel_type loglevel_type
;
266 enum lttng_event_rule_status status
;
269 assert(_agent_filter
);
271 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
272 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
277 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
278 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
280 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
285 status
= lttng_event_rule_tracepoint_get_log_level_type(
286 rule
, &loglevel_type
);
287 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
292 /* Don't add filter for the '*' event. */
293 if (strcmp(pattern
, "*") != 0) {
295 err
= asprintf(&agent_filter
,
296 "(%s) && (logger_name == \"%s\")",
299 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
304 PERROR("Failed to format agent filter string");
310 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
314 status
= lttng_event_rule_tracepoint_get_log_level(
315 rule
, &loglevel_value
);
316 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
321 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
327 if (filter
|| agent_filter
) {
330 err
= asprintf(&new_filter
,
331 "(%s) && (int_loglevel %s %d)",
332 agent_filter
? agent_filter
: filter
,
337 agent_filter
= new_filter
;
339 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
344 PERROR("Failed to format agent filter string");
350 *_agent_filter
= agent_filter
;
358 static enum lttng_error_code
359 lttng_event_rule_tracepoint_generate_filter_bytecode(
360 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
363 enum lttng_error_code ret_code
;
364 struct lttng_event_rule_tracepoint
*tracepoint
;
365 enum lttng_domain_type domain_type
;
366 enum lttng_event_rule_status status
;
368 struct lttng_filter_bytecode
*bytecode
= NULL
;
372 tracepoint
= container_of(
373 rule
, struct lttng_event_rule_tracepoint
, parent
);
375 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
376 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
378 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
379 ret_code
= LTTNG_ERR_FILTER_INVAL
;
383 if (filter
&& filter
[0] == '\0') {
384 ret_code
= LTTNG_ERR_FILTER_INVAL
;
388 status
= lttng_event_rule_tracepoint_get_domain_type(
390 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
391 ret_code
= LTTNG_ERR_UNK
;
395 switch (domain_type
) {
396 case LTTNG_DOMAIN_LOG4J
:
397 case LTTNG_DOMAIN_JUL
:
398 case LTTNG_DOMAIN_PYTHON
:
402 ret
= generate_agent_filter(rule
, &agent_filter
);
404 ret_code
= LTTNG_ERR_FILTER_INVAL
;
408 tracepoint
->internal_filter
.filter
= agent_filter
;
414 tracepoint
->internal_filter
.filter
= strdup(filter
);
415 if (tracepoint
->internal_filter
.filter
== NULL
) {
416 ret_code
= LTTNG_ERR_NOMEM
;
420 tracepoint
->internal_filter
.filter
= NULL
;
426 if (tracepoint
->internal_filter
.filter
== NULL
) {
431 ret
= run_as_generate_filter_bytecode(
432 tracepoint
->internal_filter
.filter
, uid
, gid
,
435 ret_code
= LTTNG_ERR_FILTER_INVAL
;
439 tracepoint
->internal_filter
.bytecode
= bytecode
;
449 static const char *lttng_event_rule_tracepoint_get_internal_filter(
450 const struct lttng_event_rule
*rule
)
452 struct lttng_event_rule_tracepoint
*tracepoint
;
455 tracepoint
= container_of(
456 rule
, struct lttng_event_rule_tracepoint
, parent
);
457 return tracepoint
->internal_filter
.filter
;
460 static const struct lttng_filter_bytecode
*
461 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
462 const struct lttng_event_rule
*rule
)
464 struct lttng_event_rule_tracepoint
*tracepoint
;
467 tracepoint
= container_of(
468 rule
, struct lttng_event_rule_tracepoint
, parent
);
469 return tracepoint
->internal_filter
.bytecode
;
472 static struct lttng_event_exclusion
*
473 lttng_event_rule_tracepoint_generate_exclusions(
474 const struct lttng_event_rule
*rule
)
476 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
477 enum lttng_event_rule_status status
;
478 struct lttng_event_exclusion
*local_exclusions
= NULL
;
479 struct lttng_event_exclusion
*ret_exclusions
= NULL
;
480 unsigned int nb_exclusions
= 0;
483 status
= lttng_event_rule_tracepoint_get_domain_type(rule
, &domain_type
);
484 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
486 switch (domain_type
) {
487 case LTTNG_DOMAIN_KERNEL
:
488 case LTTNG_DOMAIN_JUL
:
489 case LTTNG_DOMAIN_LOG4J
:
490 case LTTNG_DOMAIN_PYTHON
:
492 ret_exclusions
= NULL
;
494 case LTTNG_DOMAIN_UST
:
495 /* Exclusions supported. */
501 status
= lttng_event_rule_tracepoint_get_exclusions_count(
502 rule
, &nb_exclusions
);
503 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
504 if (nb_exclusions
== 0) {
506 ret_exclusions
= NULL
;
510 local_exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
511 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
512 if (!local_exclusions
) {
513 PERROR("Failed to allocate exclusions buffer");
514 ret_exclusions
= NULL
;
518 local_exclusions
->count
= nb_exclusions
;
519 for (i
= 0; i
< nb_exclusions
; i
++) {
520 /* Truncation is already checked at the setter level. */
523 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
525 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
526 strncpy(local_exclusions
->names
[i
], tmp
, LTTNG_SYMBOL_NAME_LEN
);
527 local_exclusions
->names
[i
][LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
530 /* Pass ownership. */
531 ret_exclusions
= local_exclusions
;
532 local_exclusions
= NULL
;
534 free(local_exclusions
);
535 return ret_exclusions
;
538 static void destroy_lttng_exclusions_element(void *ptr
)
543 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
544 enum lttng_domain_type domain_type
)
546 struct lttng_event_rule
*rule
= NULL
;
547 struct lttng_event_rule_tracepoint
*tp_rule
;
549 if (domain_type
== LTTNG_DOMAIN_NONE
) {
553 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
558 rule
= &tp_rule
->parent
;
559 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
560 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
561 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
562 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
563 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
564 tp_rule
->parent
.generate_filter_bytecode
=
565 lttng_event_rule_tracepoint_generate_filter_bytecode
;
566 tp_rule
->parent
.get_filter
=
567 lttng_event_rule_tracepoint_get_internal_filter
;
568 tp_rule
->parent
.get_filter_bytecode
=
569 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
570 tp_rule
->parent
.generate_exclusions
=
571 lttng_event_rule_tracepoint_generate_exclusions
;
573 tp_rule
->domain
= domain_type
;
574 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
576 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
577 destroy_lttng_exclusions_element
);
583 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
584 struct lttng_payload_view
*view
,
585 struct lttng_event_rule
**_event_rule
)
587 ssize_t ret
, offset
= 0;
589 enum lttng_event_rule_status status
;
590 enum lttng_domain_type domain_type
;
591 enum lttng_loglevel_type loglevel_type
;
592 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
594 const char *filter_expression
= NULL
;
595 const char **exclusions
= NULL
;
596 const uint32_t *exclusion_len
;
597 const char *exclusion
;
598 struct lttng_buffer_view current_buffer_view
;
599 struct lttng_event_rule
*rule
= NULL
;
606 current_buffer_view
= lttng_buffer_view_from_view(
607 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
608 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
609 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
614 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
616 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
617 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
618 /* Invalid domain value. */
619 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
620 (int) tracepoint_comm
->domain_type
);
625 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
626 rule
= lttng_event_rule_tracepoint_create(domain_type
);
628 ERR("Failed to create event rule tracepoint.");
633 loglevel_type
= (enum lttng_loglevel_type
)
634 tracepoint_comm
->loglevel_type
;
635 switch (loglevel_type
) {
636 case LTTNG_EVENT_LOGLEVEL_ALL
:
637 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
639 case LTTNG_EVENT_LOGLEVEL_RANGE
:
640 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
641 (enum lttng_loglevel_type
) tracepoint_comm
644 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
645 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
646 (enum lttng_loglevel_type
) tracepoint_comm
650 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
655 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
656 ERR("Failed to set event rule tracepoint loglevel.");
659 /* Skip to payload. */
660 offset
+= current_buffer_view
.size
;
662 /* Map the pattern. */
663 current_buffer_view
= lttng_buffer_view_from_view(
664 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
666 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
671 pattern
= current_buffer_view
.data
;
672 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
673 tracepoint_comm
->pattern_len
)) {
678 /* Skip after the pattern. */
679 offset
+= tracepoint_comm
->pattern_len
;
681 if (!tracepoint_comm
->filter_expression_len
) {
682 goto skip_filter_expression
;
685 /* Map the filter_expression. */
686 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
687 tracepoint_comm
->filter_expression_len
);
688 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
693 filter_expression
= current_buffer_view
.data
;
694 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
696 tracepoint_comm
->filter_expression_len
)) {
701 /* Skip after the pattern. */
702 offset
+= tracepoint_comm
->filter_expression_len
;
704 skip_filter_expression
:
705 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
706 current_buffer_view
= lttng_buffer_view_from_view(
707 &view
->buffer
, offset
, sizeof(*exclusion_len
));
708 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
713 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
714 offset
+= sizeof(*exclusion_len
);
716 current_buffer_view
= lttng_buffer_view_from_view(
717 &view
->buffer
, offset
, *exclusion_len
);
718 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
723 exclusion
= current_buffer_view
.data
;
724 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
725 exclusion
, *exclusion_len
)) {
730 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
731 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
732 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
738 /* Skip to next exclusion. */
739 offset
+= *exclusion_len
;
742 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
743 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
744 ERR("Failed to set event rule tracepoint pattern.");
749 if (filter_expression
) {
750 status
= lttng_event_rule_tracepoint_set_filter(
751 rule
, filter_expression
);
752 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
753 ERR("Failed to set event rule tracepoint pattern.");
764 lttng_event_rule_destroy(rule
);
768 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
769 struct lttng_event_rule
*rule
, const char *pattern
)
771 char *pattern_copy
= NULL
;
772 struct lttng_event_rule_tracepoint
*tracepoint
;
773 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
775 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
776 strlen(pattern
) == 0) {
777 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
781 tracepoint
= container_of(
782 rule
, struct lttng_event_rule_tracepoint
, parent
);
783 pattern_copy
= strdup(pattern
);
785 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
789 free(tracepoint
->pattern
);
791 tracepoint
->pattern
= pattern_copy
;
797 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
798 const struct lttng_event_rule
*rule
, const char **pattern
)
800 struct lttng_event_rule_tracepoint
*tracepoint
;
801 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
803 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
804 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
808 tracepoint
= container_of(
809 rule
, struct lttng_event_rule_tracepoint
, parent
);
810 if (!tracepoint
->pattern
) {
811 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
815 *pattern
= tracepoint
->pattern
;
820 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
821 const struct lttng_event_rule
*rule
,
822 enum lttng_domain_type
*type
)
824 struct lttng_event_rule_tracepoint
*tracepoint
;
825 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
827 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
828 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
832 tracepoint
= container_of(
833 rule
, struct lttng_event_rule_tracepoint
, parent
);
834 *type
= tracepoint
->domain
;
839 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
840 struct lttng_event_rule
*rule
, const char *expression
)
842 char *expression_copy
= NULL
;
843 struct lttng_event_rule_tracepoint
*tracepoint
;
844 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
846 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
847 strlen(expression
) == 0) {
848 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
852 tracepoint
= container_of(
853 rule
, struct lttng_event_rule_tracepoint
, parent
);
854 expression_copy
= strdup(expression
);
855 if (!expression_copy
) {
856 PERROR("Failed to copy filter expression");
857 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
861 if (tracepoint
->filter_expression
) {
862 free(tracepoint
->filter_expression
);
865 tracepoint
->filter_expression
= expression_copy
;
866 expression_copy
= NULL
;
871 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
872 const struct lttng_event_rule
*rule
, const char **expression
)
874 struct lttng_event_rule_tracepoint
*tracepoint
;
875 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
877 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
878 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
882 tracepoint
= container_of(
883 rule
, struct lttng_event_rule_tracepoint
, parent
);
884 if (!tracepoint
->filter_expression
) {
885 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
889 *expression
= tracepoint
->filter_expression
;
894 static bool log_level_value_valid(
895 int level
, enum lttng_domain_type domain
)
900 case LTTNG_DOMAIN_KERNEL
:
901 case LTTNG_DOMAIN_UST
:
902 if (level
< LTTNG_LOGLEVEL_EMERG
) {
906 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
913 case LTTNG_DOMAIN_JUL
:
914 case LTTNG_DOMAIN_LOG4J
:
915 case LTTNG_DOMAIN_PYTHON
:
917 * For both JUL and LOG4J custom log level are possible and can
918 * spawn the entire int32 range.
919 * For python, custom log level are possible, it is not clear if
920 * negative value are accepted (NOTSET == 0) but the source code
921 * validate against the int type implying that negative values
927 case LTTNG_DOMAIN_NONE
:
936 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
937 struct lttng_event_rule
*rule
, int level
)
939 struct lttng_event_rule_tracepoint
*tracepoint
;
940 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
942 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
943 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
947 tracepoint
= container_of(
948 rule
, struct lttng_event_rule_tracepoint
, parent
);
950 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
951 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
955 tracepoint
->loglevel
.value
= level
;
956 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
961 enum lttng_event_rule_status
962 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
963 struct lttng_event_rule
*rule
, int level
)
965 struct lttng_event_rule_tracepoint
*tracepoint
;
966 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
968 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
969 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
973 tracepoint
= container_of(
974 rule
, struct lttng_event_rule_tracepoint
, parent
);
976 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
977 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
981 tracepoint
->loglevel
.value
= level
;
982 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
987 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
988 struct lttng_event_rule
*rule
)
990 struct lttng_event_rule_tracepoint
*tracepoint
;
991 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
993 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
994 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
998 tracepoint
= container_of(
999 rule
, struct lttng_event_rule_tracepoint
, parent
);
1000 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1005 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1006 const struct lttng_event_rule
*rule
,
1007 enum lttng_loglevel_type
*type
)
1009 struct lttng_event_rule_tracepoint
*tracepoint
;
1010 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1012 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1013 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1017 tracepoint
= container_of(
1018 rule
, struct lttng_event_rule_tracepoint
, parent
);
1019 *type
= tracepoint
->loglevel
.type
;
1024 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1025 const struct lttng_event_rule
*rule
, int *level
)
1027 struct lttng_event_rule_tracepoint
*tracepoint
;
1028 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1030 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1031 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1035 tracepoint
= container_of(
1036 rule
, struct lttng_event_rule_tracepoint
, parent
);
1037 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1038 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1042 *level
= tracepoint
->loglevel
.value
;
1047 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1048 struct lttng_event_rule
*rule
,
1049 const char *exclusion
)
1052 char *exclusion_copy
= NULL
;
1053 struct lttng_event_rule_tracepoint
*tracepoint
;
1054 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1055 enum lttng_domain_type domain_type
;
1057 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1059 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1063 tracepoint
= container_of(
1064 rule
, struct lttng_event_rule_tracepoint
, parent
);
1066 status
= lttng_event_rule_tracepoint_get_domain_type(
1067 rule
, &domain_type
);
1068 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1072 switch (domain_type
) {
1073 case LTTNG_DOMAIN_KERNEL
:
1074 case LTTNG_DOMAIN_JUL
:
1075 case LTTNG_DOMAIN_LOG4J
:
1076 case LTTNG_DOMAIN_PYTHON
:
1077 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1079 case LTTNG_DOMAIN_UST
:
1080 /* Exclusions supported. */
1086 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1087 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1091 exclusion_copy
= strdup(exclusion
);
1092 if (!exclusion_copy
) {
1093 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1097 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1100 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1104 exclusion_copy
= NULL
;
1106 free(exclusion_copy
);
1110 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1111 const struct lttng_event_rule
*rule
, unsigned int *count
)
1113 struct lttng_event_rule_tracepoint
*tracepoint
;
1114 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1116 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1117 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1121 tracepoint
= container_of(
1122 rule
, struct lttng_event_rule_tracepoint
, parent
);
1123 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1128 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1129 const struct lttng_event_rule
*rule
,
1131 const char **exclusion
)
1134 struct lttng_event_rule_tracepoint
*tracepoint
;
1135 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1137 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1138 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1142 tracepoint
= container_of(
1143 rule
, struct lttng_event_rule_tracepoint
, parent
);
1144 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1145 LTTNG_EVENT_RULE_STATUS_OK
) {
1149 if (index
>= count
) {
1153 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1154 &tracepoint
->exclusions
, index
);