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/optional.h>
13 #include <common/payload.h>
14 #include <common/payload-view.h>
15 #include <common/runas.h>
16 #include <common/hashtable/hashtable.h>
17 #include <common/hashtable/utils.h>
18 #include <lttng/event-rule/event-rule-internal.h>
19 #include <lttng/event-rule/tracepoint-internal.h>
20 #include <lttng/log-level-rule.h>
21 #include <lttng/event.h>
23 #define IS_TRACEPOINT_EVENT_RULE(rule) \
24 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
26 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
28 struct lttng_event_rule_tracepoint
*tracepoint
;
34 tracepoint
= container_of(
35 rule
, struct lttng_event_rule_tracepoint
, parent
);
37 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
38 free(tracepoint
->pattern
);
39 free(tracepoint
->filter_expression
);
40 free(tracepoint
->internal_filter
.filter
);
41 free(tracepoint
->internal_filter
.bytecode
);
45 static bool lttng_event_rule_tracepoint_validate(
46 const struct lttng_event_rule
*rule
)
49 struct lttng_event_rule_tracepoint
*tracepoint
;
55 tracepoint
= container_of(
56 rule
, struct lttng_event_rule_tracepoint
, parent
);
59 if (!tracepoint
->pattern
) {
60 ERR("Invalid tracepoint event rule: a pattern must be set.");
65 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
66 ERR("Invalid tracepoint event rule: a domain must be set.");
75 static int lttng_event_rule_tracepoint_serialize(
76 const struct lttng_event_rule
*rule
,
77 struct lttng_payload
*payload
)
80 size_t pattern_len
, filter_expression_len
, exclusions_len
, header_offset
;
81 size_t size_before_log_level_rule
;
82 struct lttng_event_rule_tracepoint
*tracepoint
;
83 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
84 enum lttng_event_rule_status status
;
85 unsigned int exclusion_count
;
86 size_t exclusions_appended_len
= 0;
87 struct lttng_event_rule_tracepoint_comm
*header
;
89 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
94 header_offset
= payload
->buffer
.size
;
96 DBG("Serializing tracepoint event rule.");
97 tracepoint
= container_of(
98 rule
, struct lttng_event_rule_tracepoint
, parent
);
100 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
101 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
103 pattern_len
= strlen(tracepoint
->pattern
) + 1;
105 if (tracepoint
->filter_expression
!= NULL
) {
106 filter_expression_len
=
107 strlen(tracepoint
->filter_expression
) + 1;
109 filter_expression_len
= 0;
113 for (i
= 0; i
< exclusion_count
; i
++) {
114 const char *exclusion
;
116 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
117 rule
, i
, &exclusion
);
118 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
121 exclusions_len
+= sizeof(uint32_t);
122 /* Payload (null terminated). */
123 exclusions_len
+= strlen(exclusion
) + 1;
126 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
127 tracepoint_comm
.pattern_len
= pattern_len
;
128 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
129 tracepoint_comm
.exclusions_count
= exclusion_count
;
130 tracepoint_comm
.exclusions_len
= exclusions_len
;
132 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
133 sizeof(tracepoint_comm
));
138 ret
= lttng_dynamic_buffer_append(
139 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
144 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
145 filter_expression_len
);
150 size_before_log_level_rule
= payload
->buffer
.size
;
152 ret
= lttng_log_level_rule_serialize(tracepoint
->log_level_rule
, payload
);
157 header
= (typeof(header
)) ((char *) payload
->buffer
.data
+ header_offset
);
158 header
->log_level_rule_len
= payload
->buffer
.size
- size_before_log_level_rule
;
160 for (i
= 0; i
< exclusion_count
; i
++) {
162 const char *exclusion
;
164 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
165 rule
, i
, &exclusion
);
166 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
168 len
= strlen(exclusion
) + 1;
169 /* Append exclusion length, includes the null terminator. */
170 ret
= lttng_dynamic_buffer_append(
171 &payload
->buffer
, &len
, sizeof(uint32_t));
176 exclusions_appended_len
+= sizeof(uint32_t);
178 /* Include the '\0' in the payload. */
179 ret
= lttng_dynamic_buffer_append(
180 &payload
->buffer
, exclusion
, len
);
185 exclusions_appended_len
+= len
;
188 assert(exclusions_len
== exclusions_appended_len
);
194 static bool lttng_event_rule_tracepoint_is_equal(
195 const struct lttng_event_rule
*_a
,
196 const struct lttng_event_rule
*_b
)
199 bool is_equal
= false;
200 struct lttng_event_rule_tracepoint
*a
, *b
;
201 unsigned int count_a
, count_b
;
202 enum lttng_event_rule_status status
;
204 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
205 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
207 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
208 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
209 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
210 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
213 if (a
->domain
!= b
->domain
) {
217 if (count_a
!= count_b
) {
221 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
228 if (strcmp(a
->pattern
, b
->pattern
)) {
232 if (a
->filter_expression
&& b
->filter_expression
) {
233 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
236 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
237 /* One is set; not the other. */
241 if (!lttng_log_level_rule_is_equal(a
->log_level_rule
, b
->log_level_rule
)) {
245 for (i
= 0; i
< count_a
; i
++) {
246 const char *exclusion_a
, *exclusion_b
;
248 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
249 _a
, i
, &exclusion_a
);
250 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
251 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
252 _b
, i
, &exclusion_b
);
253 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
254 if (strcmp(exclusion_a
, exclusion_b
)) {
265 * On success ret is 0;
267 * On error ret is negative.
269 * An event with NO loglevel and the name is * will return NULL.
271 static int generate_agent_filter(
272 const struct lttng_event_rule
*rule
, char **_agent_filter
)
276 char *agent_filter
= NULL
;
279 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
280 enum lttng_event_rule_status status
;
283 assert(_agent_filter
);
285 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
286 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
291 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
292 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
294 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
300 /* Don't add filter for the '*' event. */
301 if (strcmp(pattern
, "*") != 0) {
303 err
= asprintf(&agent_filter
,
304 "(%s) && (logger_name == \"%s\")",
307 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
312 PERROR("Failed to format agent filter string");
318 status
= lttng_event_rule_tracepoint_get_log_level_rule(
319 rule
, &log_level_rule
);
320 if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
321 enum lttng_log_level_rule_status llr_status
;
325 switch (lttng_log_level_rule_get_type(log_level_rule
))
327 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
328 llr_status
= lttng_log_level_rule_exactly_get_level(
329 log_level_rule
, &level
);
332 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
333 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
334 log_level_rule
, &level
);
341 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
346 if (filter
|| agent_filter
) {
349 err
= asprintf(&new_filter
,
350 "(%s) && (int_loglevel %s %d)",
351 agent_filter
? agent_filter
: filter
,
356 agent_filter
= new_filter
;
358 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
363 PERROR("Failed to format agent filter string");
369 *_agent_filter
= agent_filter
;
377 static enum lttng_error_code
378 lttng_event_rule_tracepoint_generate_filter_bytecode(
379 struct lttng_event_rule
*rule
,
380 const struct lttng_credentials
*creds
)
383 enum lttng_error_code ret_code
;
384 struct lttng_event_rule_tracepoint
*tracepoint
;
385 enum lttng_domain_type domain_type
;
386 enum lttng_event_rule_status status
;
388 struct lttng_bytecode
*bytecode
= NULL
;
392 tracepoint
= container_of(
393 rule
, struct lttng_event_rule_tracepoint
, parent
);
395 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
396 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
398 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
399 ret_code
= LTTNG_ERR_FILTER_INVAL
;
403 if (filter
&& filter
[0] == '\0') {
404 ret_code
= LTTNG_ERR_FILTER_INVAL
;
408 status
= lttng_event_rule_tracepoint_get_domain_type(
410 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
411 ret_code
= LTTNG_ERR_UNK
;
415 switch (domain_type
) {
416 case LTTNG_DOMAIN_LOG4J
:
417 case LTTNG_DOMAIN_JUL
:
418 case LTTNG_DOMAIN_PYTHON
:
422 ret
= generate_agent_filter(rule
, &agent_filter
);
424 ret_code
= LTTNG_ERR_FILTER_INVAL
;
428 tracepoint
->internal_filter
.filter
= agent_filter
;
434 tracepoint
->internal_filter
.filter
= strdup(filter
);
435 if (tracepoint
->internal_filter
.filter
== NULL
) {
436 ret_code
= LTTNG_ERR_NOMEM
;
440 tracepoint
->internal_filter
.filter
= NULL
;
446 if (tracepoint
->internal_filter
.filter
== NULL
) {
451 ret
= run_as_generate_filter_bytecode(
452 tracepoint
->internal_filter
.filter
, creds
,
455 ret_code
= LTTNG_ERR_FILTER_INVAL
;
459 tracepoint
->internal_filter
.bytecode
= bytecode
;
469 static const char *lttng_event_rule_tracepoint_get_internal_filter(
470 const struct lttng_event_rule
*rule
)
472 struct lttng_event_rule_tracepoint
*tracepoint
;
475 tracepoint
= container_of(
476 rule
, struct lttng_event_rule_tracepoint
, parent
);
477 return tracepoint
->internal_filter
.filter
;
480 static const struct lttng_bytecode
*
481 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
482 const struct lttng_event_rule
*rule
)
484 struct lttng_event_rule_tracepoint
*tracepoint
;
487 tracepoint
= container_of(
488 rule
, struct lttng_event_rule_tracepoint
, parent
);
489 return tracepoint
->internal_filter
.bytecode
;
492 static enum lttng_event_rule_generate_exclusions_status
493 lttng_event_rule_tracepoint_generate_exclusions(
494 const struct lttng_event_rule
*rule
,
495 struct lttng_event_exclusion
**_exclusions
)
497 unsigned int nb_exclusions
= 0, i
;
498 enum lttng_domain_type domain_type
;
499 struct lttng_event_exclusion
*exclusions
;
500 enum lttng_event_rule_status event_rule_status
;
501 enum lttng_event_rule_generate_exclusions_status ret_status
;
505 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
507 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
509 switch (domain_type
) {
510 case LTTNG_DOMAIN_KERNEL
:
511 case LTTNG_DOMAIN_JUL
:
512 case LTTNG_DOMAIN_LOG4J
:
513 case LTTNG_DOMAIN_PYTHON
:
516 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
518 case LTTNG_DOMAIN_UST
:
519 /* Exclusions supported. */
522 /* Unknown domain. */
526 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
527 rule
, &nb_exclusions
);
528 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
529 if (nb_exclusions
== 0) {
532 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
536 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
537 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
539 PERROR("Failed to allocate exclusions buffer");
540 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
544 exclusions
->count
= nb_exclusions
;
545 for (i
= 0; i
< nb_exclusions
; i
++) {
547 const char *exclusion_str
;
550 lttng_event_rule_tracepoint_get_exclusion_at_index(
551 rule
, i
, &exclusion_str
);
552 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
554 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
555 LTTNG_SYMBOL_NAME_LEN
);
559 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
564 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
567 *_exclusions
= exclusions
;
571 static void destroy_lttng_exclusions_element(void *ptr
)
576 static unsigned long lttng_event_rule_tracepoint_hash(
577 const struct lttng_event_rule
*rule
)
580 unsigned int i
, exclusion_count
;
581 enum lttng_event_rule_status status
;
582 struct lttng_event_rule_tracepoint
*tp_rule
=
583 container_of(rule
, typeof(*tp_rule
), parent
);
585 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT
,
587 hash
^= hash_key_ulong((void *) tp_rule
->domain
, lttng_ht_seed
);
588 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
590 if (tp_rule
->filter_expression
) {
591 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
594 if (tp_rule
->log_level_rule
) {
595 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
598 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
,
600 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
602 for (i
= 0; i
< exclusion_count
; i
++) {
603 const char *exclusion
;
605 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
606 rule
, i
, &exclusion
);
607 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
608 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
614 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
615 const struct lttng_event_rule
*rule
)
618 const struct lttng_event_rule_tracepoint
*tracepoint
;
619 struct lttng_event
*local_event
= NULL
;
620 struct lttng_event
*event
= NULL
;
621 enum lttng_loglevel_type loglevel_type
;
622 int loglevel_value
= 0;
623 enum lttng_event_rule_status status
;
624 const struct lttng_log_level_rule
*log_level_rule
;
626 tracepoint
= container_of(
627 rule
, const struct lttng_event_rule_tracepoint
, parent
);
629 local_event
= zmalloc(sizeof(*local_event
));
634 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
635 ret
= lttng_strncpy(local_event
->name
, tracepoint
->pattern
,
636 sizeof(local_event
->name
));
638 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
639 tracepoint
->pattern
);
644 /* Map the log level rule to an equivalent lttng_loglevel */
645 status
= lttng_event_rule_tracepoint_get_log_level_rule(rule
, &log_level_rule
);
646 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
647 loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
649 } else if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
650 enum lttng_log_level_rule_status llr_status
;
652 switch (lttng_log_level_rule_get_type(log_level_rule
)) {
653 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
654 llr_status
= lttng_log_level_rule_exactly_get_level(
655 log_level_rule
, &loglevel_value
);
656 loglevel_type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
658 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
659 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
660 log_level_rule
, &loglevel_value
);
661 loglevel_type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
668 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
675 local_event
->loglevel_type
= loglevel_type
;
676 local_event
->loglevel
= loglevel_value
;
685 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
686 enum lttng_domain_type domain_type
)
688 struct lttng_event_rule
*rule
= NULL
;
689 struct lttng_event_rule_tracepoint
*tp_rule
;
690 enum lttng_event_rule_status status
;
692 if (domain_type
== LTTNG_DOMAIN_NONE
) {
696 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
701 rule
= &tp_rule
->parent
;
702 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
703 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
704 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
705 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
706 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
707 tp_rule
->parent
.generate_filter_bytecode
=
708 lttng_event_rule_tracepoint_generate_filter_bytecode
;
709 tp_rule
->parent
.get_filter
=
710 lttng_event_rule_tracepoint_get_internal_filter
;
711 tp_rule
->parent
.get_filter_bytecode
=
712 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
713 tp_rule
->parent
.generate_exclusions
=
714 lttng_event_rule_tracepoint_generate_exclusions
;
715 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
716 tp_rule
->parent
.generate_lttng_event
=
717 lttng_event_rule_tracepoint_generate_lttng_event
;
719 tp_rule
->domain
= domain_type
;
720 tp_rule
->log_level_rule
= NULL
;
722 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
723 destroy_lttng_exclusions_element
);
725 /* Default pattern is '*' */
726 status
= lttng_event_rule_tracepoint_set_pattern(rule
, "*");
727 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
728 lttng_event_rule_destroy(rule
);
737 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
738 struct lttng_payload_view
*view
,
739 struct lttng_event_rule
**_event_rule
)
741 ssize_t ret
, offset
= 0;
743 enum lttng_event_rule_status status
;
744 enum lttng_domain_type domain_type
;
745 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
747 const char *filter_expression
= NULL
;
748 const char **exclusions
= NULL
;
749 const uint32_t *exclusion_len
;
750 const char *exclusion
;
751 struct lttng_buffer_view current_buffer_view
;
752 struct lttng_event_rule
*rule
= NULL
;
753 struct lttng_log_level_rule
*log_level_rule
= NULL
;
760 current_buffer_view
= lttng_buffer_view_from_view(
761 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
762 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
763 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
768 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
770 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
771 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
772 /* Invalid domain value. */
773 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
774 (int) tracepoint_comm
->domain_type
);
779 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
780 rule
= lttng_event_rule_tracepoint_create(domain_type
);
782 ERR("Failed to create event rule tracepoint.");
787 /* Skip to payload. */
788 offset
+= current_buffer_view
.size
;
790 /* Map the pattern. */
791 current_buffer_view
= lttng_buffer_view_from_view(
792 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
794 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
799 pattern
= current_buffer_view
.data
;
800 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
801 tracepoint_comm
->pattern_len
)) {
806 /* Skip after the pattern. */
807 offset
+= tracepoint_comm
->pattern_len
;
809 if (!tracepoint_comm
->filter_expression_len
) {
810 goto skip_filter_expression
;
813 /* Map the filter_expression. */
814 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
815 tracepoint_comm
->filter_expression_len
);
816 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
821 filter_expression
= current_buffer_view
.data
;
822 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
824 tracepoint_comm
->filter_expression_len
)) {
829 /* Skip after the pattern. */
830 offset
+= tracepoint_comm
->filter_expression_len
;
832 skip_filter_expression
:
833 if (!tracepoint_comm
->log_level_rule_len
) {
834 goto skip_log_level_rule
;
838 /* Map the log level rule. */
839 struct lttng_payload_view current_payload_view
=
840 lttng_payload_view_from_view(view
, offset
,
841 tracepoint_comm
->log_level_rule_len
);
842 ret
= lttng_log_level_rule_create_from_payload(
843 ¤t_payload_view
, &log_level_rule
);
849 assert(ret
== tracepoint_comm
->log_level_rule_len
);
852 /* Skip after the log level rule. */
853 offset
+= tracepoint_comm
->log_level_rule_len
;
856 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
857 current_buffer_view
= lttng_buffer_view_from_view(
858 &view
->buffer
, offset
, sizeof(*exclusion_len
));
859 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
864 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
865 offset
+= sizeof(*exclusion_len
);
867 current_buffer_view
= lttng_buffer_view_from_view(
868 &view
->buffer
, offset
, *exclusion_len
);
869 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
874 exclusion
= current_buffer_view
.data
;
875 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
876 exclusion
, *exclusion_len
)) {
881 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
882 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
883 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
889 /* Skip to next exclusion. */
890 offset
+= *exclusion_len
;
893 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
894 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
895 ERR("Failed to set event rule tracepoint pattern.");
900 if (filter_expression
) {
901 status
= lttng_event_rule_tracepoint_set_filter(
902 rule
, filter_expression
);
903 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
904 ERR("Failed to set event rule tracepoint pattern.");
910 if (log_level_rule
) {
911 status
= lttng_event_rule_tracepoint_set_log_level_rule(
912 rule
, log_level_rule
);
913 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
914 ERR("Failed to set event rule tracepoint log level rule.");
925 lttng_log_level_rule_destroy(log_level_rule
);
926 lttng_event_rule_destroy(rule
);
930 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
931 struct lttng_event_rule
*rule
, const char *pattern
)
933 char *pattern_copy
= NULL
;
934 struct lttng_event_rule_tracepoint
*tracepoint
;
935 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
937 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
938 strlen(pattern
) == 0) {
939 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
943 tracepoint
= container_of(
944 rule
, struct lttng_event_rule_tracepoint
, parent
);
945 pattern_copy
= strdup(pattern
);
947 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
951 free(tracepoint
->pattern
);
953 tracepoint
->pattern
= pattern_copy
;
959 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
960 const struct lttng_event_rule
*rule
, const char **pattern
)
962 struct lttng_event_rule_tracepoint
*tracepoint
;
963 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
965 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
966 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
970 tracepoint
= container_of(
971 rule
, struct lttng_event_rule_tracepoint
, parent
);
972 if (!tracepoint
->pattern
) {
973 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
977 *pattern
= tracepoint
->pattern
;
982 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
983 const struct lttng_event_rule
*rule
,
984 enum lttng_domain_type
*type
)
986 struct lttng_event_rule_tracepoint
*tracepoint
;
987 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
989 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
990 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
994 tracepoint
= container_of(
995 rule
, struct lttng_event_rule_tracepoint
, parent
);
996 *type
= tracepoint
->domain
;
1001 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
1002 struct lttng_event_rule
*rule
, const char *expression
)
1004 char *expression_copy
= NULL
;
1005 struct lttng_event_rule_tracepoint
*tracepoint
;
1006 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1008 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
1009 strlen(expression
) == 0) {
1010 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1014 tracepoint
= container_of(
1015 rule
, struct lttng_event_rule_tracepoint
, parent
);
1016 expression_copy
= strdup(expression
);
1017 if (!expression_copy
) {
1018 PERROR("Failed to copy filter expression");
1019 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1023 if (tracepoint
->filter_expression
) {
1024 free(tracepoint
->filter_expression
);
1027 tracepoint
->filter_expression
= expression_copy
;
1028 expression_copy
= NULL
;
1033 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
1034 const struct lttng_event_rule
*rule
, const char **expression
)
1036 struct lttng_event_rule_tracepoint
*tracepoint
;
1037 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1039 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
1040 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1044 tracepoint
= container_of(
1045 rule
, struct lttng_event_rule_tracepoint
, parent
);
1046 if (!tracepoint
->filter_expression
) {
1047 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1051 *expression
= tracepoint
->filter_expression
;
1056 static bool log_level_rule_valid(
1057 const struct lttng_log_level_rule
*rule
, enum lttng_domain_type domain
)
1060 enum lttng_log_level_rule_status status
;
1063 switch(lttng_log_level_rule_get_type(rule
)) {
1064 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
1065 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
1067 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
1068 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(rule
, &level
);
1074 assert(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
1077 case LTTNG_DOMAIN_KERNEL
:
1078 case LTTNG_DOMAIN_UST
:
1079 if (level
< LTTNG_LOGLEVEL_EMERG
) {
1083 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
1090 case LTTNG_DOMAIN_JUL
:
1091 case LTTNG_DOMAIN_LOG4J
:
1092 case LTTNG_DOMAIN_PYTHON
:
1094 * For both JUL and LOG4J custom log level are possible and can
1095 * spawn the entire int32 range.
1096 * For python, custom log level are possible, it is not clear if
1097 * negative value are accepted (NOTSET == 0) but the source code
1098 * validate against the int type implying that negative values
1104 case LTTNG_DOMAIN_NONE
:
1113 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_rule(
1114 struct lttng_event_rule
*rule
,
1115 const struct lttng_log_level_rule
*log_level_rule
)
1117 struct lttng_event_rule_tracepoint
*tracepoint
;
1118 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1119 struct lttng_log_level_rule
*copy
= NULL
;
1121 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1122 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1126 tracepoint
= container_of(
1127 rule
, struct lttng_event_rule_tracepoint
, parent
);
1129 if (!log_level_rule_valid(log_level_rule
, tracepoint
->domain
)) {
1130 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1134 copy
= lttng_log_level_rule_copy(log_level_rule
);
1136 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1140 if (tracepoint
->log_level_rule
) {
1141 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
1144 tracepoint
->log_level_rule
= copy
;
1150 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_rule(
1151 const struct lttng_event_rule
*rule
,
1152 const struct lttng_log_level_rule
**log_level_rule
1155 struct lttng_event_rule_tracepoint
*tracepoint
;
1156 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1158 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
1159 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1163 tracepoint
= container_of(
1164 rule
, struct lttng_event_rule_tracepoint
, parent
);
1165 if (tracepoint
->log_level_rule
== NULL
) {
1166 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1170 *log_level_rule
= tracepoint
->log_level_rule
;
1175 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1176 struct lttng_event_rule
*rule
,
1177 const char *exclusion
)
1180 char *exclusion_copy
= NULL
;
1181 struct lttng_event_rule_tracepoint
*tracepoint
;
1182 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1183 enum lttng_domain_type domain_type
;
1185 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1187 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1191 tracepoint
= container_of(
1192 rule
, struct lttng_event_rule_tracepoint
, parent
);
1194 status
= lttng_event_rule_tracepoint_get_domain_type(
1195 rule
, &domain_type
);
1196 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1200 switch (domain_type
) {
1201 case LTTNG_DOMAIN_KERNEL
:
1202 case LTTNG_DOMAIN_JUL
:
1203 case LTTNG_DOMAIN_LOG4J
:
1204 case LTTNG_DOMAIN_PYTHON
:
1205 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1207 case LTTNG_DOMAIN_UST
:
1208 /* Exclusions supported. */
1214 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1215 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1219 exclusion_copy
= strdup(exclusion
);
1220 if (!exclusion_copy
) {
1221 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1225 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1228 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1232 exclusion_copy
= NULL
;
1234 free(exclusion_copy
);
1238 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1239 const struct lttng_event_rule
*rule
, unsigned int *count
)
1241 struct lttng_event_rule_tracepoint
*tracepoint
;
1242 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1244 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1245 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1249 tracepoint
= container_of(
1250 rule
, struct lttng_event_rule_tracepoint
, parent
);
1251 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1256 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1257 const struct lttng_event_rule
*rule
,
1259 const char **exclusion
)
1262 struct lttng_event_rule_tracepoint
*tracepoint
;
1263 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1265 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1266 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1270 tracepoint
= container_of(
1271 rule
, struct lttng_event_rule_tracepoint
, parent
);
1272 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1273 LTTNG_EVENT_RULE_STATUS_OK
) {
1277 if (index
>= count
) {
1281 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1282 &tracepoint
->exclusions
, index
);