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
=
159 payload
->buffer
.size
- size_before_log_level_rule
;
161 for (i
= 0; i
< exclusion_count
; i
++) {
163 const char *exclusion
;
165 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
166 rule
, i
, &exclusion
);
167 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
169 len
= strlen(exclusion
) + 1;
170 /* Append exclusion length, includes the null terminator. */
171 ret
= lttng_dynamic_buffer_append(
172 &payload
->buffer
, &len
, sizeof(uint32_t));
177 exclusions_appended_len
+= sizeof(uint32_t);
179 /* Include the '\0' in the payload. */
180 ret
= lttng_dynamic_buffer_append(
181 &payload
->buffer
, exclusion
, len
);
186 exclusions_appended_len
+= len
;
189 assert(exclusions_len
== exclusions_appended_len
);
195 static bool lttng_event_rule_tracepoint_is_equal(
196 const struct lttng_event_rule
*_a
,
197 const struct lttng_event_rule
*_b
)
200 bool is_equal
= false;
201 struct lttng_event_rule_tracepoint
*a
, *b
;
202 unsigned int count_a
, count_b
;
203 enum lttng_event_rule_status status
;
205 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
206 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
208 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
209 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
210 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
211 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
214 if (a
->domain
!= b
->domain
) {
218 if (count_a
!= count_b
) {
222 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
229 if (strcmp(a
->pattern
, b
->pattern
)) {
233 if (a
->filter_expression
&& b
->filter_expression
) {
234 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
237 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
238 /* One is set; not the other. */
242 if (!lttng_log_level_rule_is_equal(
243 a
->log_level_rule
, b
->log_level_rule
)) {
247 for (i
= 0; i
< count_a
; i
++) {
248 const char *exclusion_a
, *exclusion_b
;
250 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
251 _a
, i
, &exclusion_a
);
252 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
253 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
254 _b
, i
, &exclusion_b
);
255 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
256 if (strcmp(exclusion_a
, exclusion_b
)) {
267 * On success ret is 0;
269 * On error ret is negative.
271 * An event with NO loglevel and the name is * will return NULL.
273 static int generate_agent_filter(
274 const struct lttng_event_rule
*rule
, char **_agent_filter
)
278 char *agent_filter
= NULL
;
281 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
282 enum lttng_event_rule_status status
;
285 assert(_agent_filter
);
287 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
288 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
293 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
294 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
296 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
302 /* Don't add filter for the '*' event. */
303 if (strcmp(pattern
, "*") != 0) {
305 err
= asprintf(&agent_filter
,
306 "(%s) && (logger_name == \"%s\")",
309 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
314 PERROR("Failed to format agent filter string");
320 status
= lttng_event_rule_tracepoint_get_log_level_rule(
321 rule
, &log_level_rule
);
322 if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
323 enum lttng_log_level_rule_status llr_status
;
327 switch (lttng_log_level_rule_get_type(log_level_rule
))
329 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
330 llr_status
= lttng_log_level_rule_exactly_get_level(
331 log_level_rule
, &level
);
334 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
335 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
336 log_level_rule
, &level
);
343 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
348 if (filter
|| agent_filter
) {
351 err
= asprintf(&new_filter
,
352 "(%s) && (int_loglevel %s %d)",
353 agent_filter
? agent_filter
: filter
,
358 agent_filter
= new_filter
;
360 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
365 PERROR("Failed to format agent filter string");
371 *_agent_filter
= agent_filter
;
379 static enum lttng_error_code
380 lttng_event_rule_tracepoint_generate_filter_bytecode(
381 struct lttng_event_rule
*rule
,
382 const struct lttng_credentials
*creds
)
385 enum lttng_error_code ret_code
;
386 struct lttng_event_rule_tracepoint
*tracepoint
;
387 enum lttng_domain_type domain_type
;
388 enum lttng_event_rule_status status
;
390 struct lttng_bytecode
*bytecode
= NULL
;
394 tracepoint
= container_of(
395 rule
, struct lttng_event_rule_tracepoint
, parent
);
397 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
398 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
400 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
401 ret_code
= LTTNG_ERR_FILTER_INVAL
;
405 if (filter
&& filter
[0] == '\0') {
406 ret_code
= LTTNG_ERR_FILTER_INVAL
;
410 status
= lttng_event_rule_tracepoint_get_domain_type(
412 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
413 ret_code
= LTTNG_ERR_UNK
;
417 switch (domain_type
) {
418 case LTTNG_DOMAIN_LOG4J
:
419 case LTTNG_DOMAIN_JUL
:
420 case LTTNG_DOMAIN_PYTHON
:
424 ret
= generate_agent_filter(rule
, &agent_filter
);
426 ret_code
= LTTNG_ERR_FILTER_INVAL
;
430 tracepoint
->internal_filter
.filter
= agent_filter
;
436 tracepoint
->internal_filter
.filter
= strdup(filter
);
437 if (tracepoint
->internal_filter
.filter
== NULL
) {
438 ret_code
= LTTNG_ERR_NOMEM
;
442 tracepoint
->internal_filter
.filter
= NULL
;
448 if (tracepoint
->internal_filter
.filter
== NULL
) {
453 ret
= run_as_generate_filter_bytecode(
454 tracepoint
->internal_filter
.filter
, creds
,
457 ret_code
= LTTNG_ERR_FILTER_INVAL
;
461 tracepoint
->internal_filter
.bytecode
= bytecode
;
471 static const char *lttng_event_rule_tracepoint_get_internal_filter(
472 const struct lttng_event_rule
*rule
)
474 struct lttng_event_rule_tracepoint
*tracepoint
;
477 tracepoint
= container_of(
478 rule
, struct lttng_event_rule_tracepoint
, parent
);
479 return tracepoint
->internal_filter
.filter
;
482 static const struct lttng_bytecode
*
483 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
484 const struct lttng_event_rule
*rule
)
486 struct lttng_event_rule_tracepoint
*tracepoint
;
489 tracepoint
= container_of(
490 rule
, struct lttng_event_rule_tracepoint
, parent
);
491 return tracepoint
->internal_filter
.bytecode
;
494 static enum lttng_event_rule_generate_exclusions_status
495 lttng_event_rule_tracepoint_generate_exclusions(
496 const struct lttng_event_rule
*rule
,
497 struct lttng_event_exclusion
**_exclusions
)
499 unsigned int nb_exclusions
= 0, i
;
500 enum lttng_domain_type domain_type
;
501 struct lttng_event_exclusion
*exclusions
;
502 enum lttng_event_rule_status event_rule_status
;
503 enum lttng_event_rule_generate_exclusions_status ret_status
;
507 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
509 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
511 switch (domain_type
) {
512 case LTTNG_DOMAIN_KERNEL
:
513 case LTTNG_DOMAIN_JUL
:
514 case LTTNG_DOMAIN_LOG4J
:
515 case LTTNG_DOMAIN_PYTHON
:
518 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
520 case LTTNG_DOMAIN_UST
:
521 /* Exclusions supported. */
524 /* Unknown domain. */
528 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
529 rule
, &nb_exclusions
);
530 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
531 if (nb_exclusions
== 0) {
534 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
538 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
539 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
541 PERROR("Failed to allocate exclusions buffer");
542 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
546 exclusions
->count
= nb_exclusions
;
547 for (i
= 0; i
< nb_exclusions
; i
++) {
549 const char *exclusion_str
;
552 lttng_event_rule_tracepoint_get_exclusion_at_index(
553 rule
, i
, &exclusion_str
);
554 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
556 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
557 LTTNG_SYMBOL_NAME_LEN
);
561 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
566 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
569 *_exclusions
= exclusions
;
573 static void destroy_lttng_exclusions_element(void *ptr
)
578 static unsigned long lttng_event_rule_tracepoint_hash(
579 const struct lttng_event_rule
*rule
)
582 unsigned int i
, exclusion_count
;
583 enum lttng_event_rule_status status
;
584 struct lttng_event_rule_tracepoint
*tp_rule
=
585 container_of(rule
, typeof(*tp_rule
), parent
);
587 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT
,
589 hash
^= hash_key_ulong((void *) tp_rule
->domain
, lttng_ht_seed
);
590 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
592 if (tp_rule
->filter_expression
) {
593 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
596 if (tp_rule
->log_level_rule
) {
597 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
600 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
,
602 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
604 for (i
= 0; i
< exclusion_count
; i
++) {
605 const char *exclusion
;
607 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
608 rule
, i
, &exclusion
);
609 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
610 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
616 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
617 const struct lttng_event_rule
*rule
)
620 const struct lttng_event_rule_tracepoint
*tracepoint
;
621 struct lttng_event
*local_event
= NULL
;
622 struct lttng_event
*event
= NULL
;
623 enum lttng_loglevel_type loglevel_type
;
624 int loglevel_value
= 0;
625 enum lttng_event_rule_status status
;
626 const struct lttng_log_level_rule
*log_level_rule
;
628 tracepoint
= container_of(
629 rule
, const struct lttng_event_rule_tracepoint
, parent
);
631 local_event
= zmalloc(sizeof(*local_event
));
636 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
637 ret
= lttng_strncpy(local_event
->name
, tracepoint
->pattern
,
638 sizeof(local_event
->name
));
640 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
641 tracepoint
->pattern
);
646 /* Map the log level rule to an equivalent lttng_loglevel. */
647 status
= lttng_event_rule_tracepoint_get_log_level_rule(
648 rule
, &log_level_rule
);
649 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
650 loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
652 } else if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
653 enum lttng_log_level_rule_status llr_status
;
655 switch (lttng_log_level_rule_get_type(log_level_rule
)) {
656 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
657 llr_status
= lttng_log_level_rule_exactly_get_level(
658 log_level_rule
, &loglevel_value
);
659 loglevel_type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
661 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
662 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
663 log_level_rule
, &loglevel_value
);
664 loglevel_type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
671 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
678 local_event
->loglevel_type
= loglevel_type
;
679 local_event
->loglevel
= loglevel_value
;
688 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
689 enum lttng_domain_type domain_type
)
691 struct lttng_event_rule
*rule
= NULL
;
692 struct lttng_event_rule_tracepoint
*tp_rule
;
693 enum lttng_event_rule_status status
;
695 if (domain_type
== LTTNG_DOMAIN_NONE
) {
699 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
704 rule
= &tp_rule
->parent
;
705 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
706 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
707 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
708 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
709 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
710 tp_rule
->parent
.generate_filter_bytecode
=
711 lttng_event_rule_tracepoint_generate_filter_bytecode
;
712 tp_rule
->parent
.get_filter
=
713 lttng_event_rule_tracepoint_get_internal_filter
;
714 tp_rule
->parent
.get_filter_bytecode
=
715 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
716 tp_rule
->parent
.generate_exclusions
=
717 lttng_event_rule_tracepoint_generate_exclusions
;
718 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
719 tp_rule
->parent
.generate_lttng_event
=
720 lttng_event_rule_tracepoint_generate_lttng_event
;
722 tp_rule
->domain
= domain_type
;
723 tp_rule
->log_level_rule
= NULL
;
725 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
726 destroy_lttng_exclusions_element
);
728 /* Default pattern is '*'. */
729 status
= lttng_event_rule_tracepoint_set_pattern(rule
, "*");
730 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
731 lttng_event_rule_destroy(rule
);
740 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
741 struct lttng_payload_view
*view
,
742 struct lttng_event_rule
**_event_rule
)
744 ssize_t ret
, offset
= 0;
746 enum lttng_event_rule_status status
;
747 enum lttng_domain_type domain_type
;
748 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
750 const char *filter_expression
= NULL
;
751 const char **exclusions
= NULL
;
752 const uint32_t *exclusion_len
;
753 const char *exclusion
;
754 struct lttng_buffer_view current_buffer_view
;
755 struct lttng_event_rule
*rule
= NULL
;
756 struct lttng_log_level_rule
*log_level_rule
= NULL
;
763 current_buffer_view
= lttng_buffer_view_from_view(
764 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
765 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
766 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
771 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
773 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
774 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
775 /* Invalid domain value. */
776 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
777 (int) tracepoint_comm
->domain_type
);
782 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
783 rule
= lttng_event_rule_tracepoint_create(domain_type
);
785 ERR("Failed to create event rule tracepoint.");
790 /* Skip to payload. */
791 offset
+= current_buffer_view
.size
;
793 /* Map the pattern. */
794 current_buffer_view
= lttng_buffer_view_from_view(
795 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
797 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
802 pattern
= current_buffer_view
.data
;
803 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
804 tracepoint_comm
->pattern_len
)) {
809 /* Skip after the pattern. */
810 offset
+= tracepoint_comm
->pattern_len
;
812 if (!tracepoint_comm
->filter_expression_len
) {
813 goto skip_filter_expression
;
816 /* Map the filter_expression. */
817 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
818 tracepoint_comm
->filter_expression_len
);
819 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
824 filter_expression
= current_buffer_view
.data
;
825 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
827 tracepoint_comm
->filter_expression_len
)) {
832 /* Skip after the pattern. */
833 offset
+= tracepoint_comm
->filter_expression_len
;
835 skip_filter_expression
:
836 if (!tracepoint_comm
->log_level_rule_len
) {
837 goto skip_log_level_rule
;
841 /* Map the log level rule. */
842 struct lttng_payload_view current_payload_view
=
843 lttng_payload_view_from_view(view
, offset
,
844 tracepoint_comm
->log_level_rule_len
);
846 ret
= lttng_log_level_rule_create_from_payload(
847 ¤t_payload_view
, &log_level_rule
);
853 assert(ret
== tracepoint_comm
->log_level_rule_len
);
856 /* Skip after the log level rule. */
857 offset
+= tracepoint_comm
->log_level_rule_len
;
860 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
861 current_buffer_view
= lttng_buffer_view_from_view(
862 &view
->buffer
, offset
, sizeof(*exclusion_len
));
863 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
868 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
869 offset
+= sizeof(*exclusion_len
);
871 current_buffer_view
= lttng_buffer_view_from_view(
872 &view
->buffer
, offset
, *exclusion_len
);
873 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
878 exclusion
= current_buffer_view
.data
;
879 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
880 exclusion
, *exclusion_len
)) {
885 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
886 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
887 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
893 /* Skip to next exclusion. */
894 offset
+= *exclusion_len
;
897 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
898 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
899 ERR("Failed to set event rule tracepoint pattern.");
904 if (filter_expression
) {
905 status
= lttng_event_rule_tracepoint_set_filter(
906 rule
, filter_expression
);
907 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
908 ERR("Failed to set event rule tracepoint pattern.");
914 if (log_level_rule
) {
915 status
= lttng_event_rule_tracepoint_set_log_level_rule(
916 rule
, log_level_rule
);
917 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
918 ERR("Failed to set event rule tracepoint log level rule.");
929 lttng_log_level_rule_destroy(log_level_rule
);
930 lttng_event_rule_destroy(rule
);
934 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
935 struct lttng_event_rule
*rule
, const char *pattern
)
937 char *pattern_copy
= NULL
;
938 struct lttng_event_rule_tracepoint
*tracepoint
;
939 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
941 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
942 strlen(pattern
) == 0) {
943 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
947 tracepoint
= container_of(
948 rule
, struct lttng_event_rule_tracepoint
, parent
);
949 pattern_copy
= strdup(pattern
);
951 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
955 free(tracepoint
->pattern
);
957 tracepoint
->pattern
= pattern_copy
;
963 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
964 const struct lttng_event_rule
*rule
, const char **pattern
)
966 struct lttng_event_rule_tracepoint
*tracepoint
;
967 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
969 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
970 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
974 tracepoint
= container_of(
975 rule
, struct lttng_event_rule_tracepoint
, parent
);
976 if (!tracepoint
->pattern
) {
977 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
981 *pattern
= tracepoint
->pattern
;
986 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
987 const struct lttng_event_rule
*rule
,
988 enum lttng_domain_type
*type
)
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
) || !type
) {
994 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
998 tracepoint
= container_of(
999 rule
, struct lttng_event_rule_tracepoint
, parent
);
1000 *type
= tracepoint
->domain
;
1005 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
1006 struct lttng_event_rule
*rule
, const char *expression
)
1008 char *expression_copy
= NULL
;
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
) || !expression
||
1013 strlen(expression
) == 0) {
1014 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1018 tracepoint
= container_of(
1019 rule
, struct lttng_event_rule_tracepoint
, parent
);
1020 expression_copy
= strdup(expression
);
1021 if (!expression_copy
) {
1022 PERROR("Failed to copy filter expression");
1023 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1027 if (tracepoint
->filter_expression
) {
1028 free(tracepoint
->filter_expression
);
1031 tracepoint
->filter_expression
= expression_copy
;
1032 expression_copy
= NULL
;
1037 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
1038 const struct lttng_event_rule
*rule
, const char **expression
)
1040 struct lttng_event_rule_tracepoint
*tracepoint
;
1041 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1043 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
1044 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1048 tracepoint
= container_of(
1049 rule
, struct lttng_event_rule_tracepoint
, parent
);
1050 if (!tracepoint
->filter_expression
) {
1051 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1055 *expression
= tracepoint
->filter_expression
;
1060 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
,
1061 enum lttng_domain_type domain
)
1064 enum lttng_log_level_rule_status status
;
1067 switch (lttng_log_level_rule_get_type(rule
)) {
1068 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
1069 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
1071 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
1072 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
1079 assert(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
1082 case LTTNG_DOMAIN_KERNEL
:
1085 case LTTNG_DOMAIN_UST
:
1086 if (level
< LTTNG_LOGLEVEL_EMERG
) {
1090 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
1097 case LTTNG_DOMAIN_JUL
:
1098 case LTTNG_DOMAIN_LOG4J
:
1099 case LTTNG_DOMAIN_PYTHON
:
1101 * For both JUL and LOG4J custom log level are possible and can
1102 * span the entire int32 range.
1104 * For python, custom log level are possible, it is not clear if
1105 * negative value are accepted (NOTSET == 0) but the source code
1106 * validates against the int type implying that negative values
1111 case LTTNG_DOMAIN_NONE
:
1120 static bool domain_supports_log_levels(enum lttng_domain_type domain
)
1125 case LTTNG_DOMAIN_KERNEL
:
1128 case LTTNG_DOMAIN_UST
:
1129 case LTTNG_DOMAIN_JUL
:
1130 case LTTNG_DOMAIN_LOG4J
:
1131 case LTTNG_DOMAIN_PYTHON
:
1141 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_rule(
1142 struct lttng_event_rule
*rule
,
1143 const struct lttng_log_level_rule
*log_level_rule
)
1145 struct lttng_event_rule_tracepoint
*tracepoint
;
1146 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1147 struct lttng_log_level_rule
*copy
= NULL
;
1149 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1150 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1154 tracepoint
= container_of(
1155 rule
, struct lttng_event_rule_tracepoint
, parent
);
1157 if (!domain_supports_log_levels(tracepoint
->domain
)) {
1158 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1162 if (!log_level_rule_valid(log_level_rule
, tracepoint
->domain
)) {
1163 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1167 copy
= lttng_log_level_rule_copy(log_level_rule
);
1169 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1173 if (tracepoint
->log_level_rule
) {
1174 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
1177 tracepoint
->log_level_rule
= copy
;
1183 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_rule(
1184 const struct lttng_event_rule
*rule
,
1185 const struct lttng_log_level_rule
**log_level_rule
1188 struct lttng_event_rule_tracepoint
*tracepoint
;
1189 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1191 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
1192 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1196 tracepoint
= container_of(
1197 rule
, struct lttng_event_rule_tracepoint
, parent
);
1198 if (tracepoint
->log_level_rule
== NULL
) {
1199 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1203 *log_level_rule
= tracepoint
->log_level_rule
;
1208 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1209 struct lttng_event_rule
*rule
,
1210 const char *exclusion
)
1213 char *exclusion_copy
= NULL
;
1214 struct lttng_event_rule_tracepoint
*tracepoint
;
1215 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1216 enum lttng_domain_type domain_type
;
1218 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1220 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1224 tracepoint
= container_of(
1225 rule
, struct lttng_event_rule_tracepoint
, parent
);
1227 status
= lttng_event_rule_tracepoint_get_domain_type(
1228 rule
, &domain_type
);
1229 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1233 switch (domain_type
) {
1234 case LTTNG_DOMAIN_KERNEL
:
1235 case LTTNG_DOMAIN_JUL
:
1236 case LTTNG_DOMAIN_LOG4J
:
1237 case LTTNG_DOMAIN_PYTHON
:
1238 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1240 case LTTNG_DOMAIN_UST
:
1241 /* Exclusions supported. */
1247 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1248 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1252 exclusion_copy
= strdup(exclusion
);
1253 if (!exclusion_copy
) {
1254 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1258 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1261 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1265 exclusion_copy
= NULL
;
1267 free(exclusion_copy
);
1271 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1272 const struct lttng_event_rule
*rule
, unsigned int *count
)
1274 struct lttng_event_rule_tracepoint
*tracepoint
;
1275 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1277 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1278 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1282 tracepoint
= container_of(
1283 rule
, struct lttng_event_rule_tracepoint
, parent
);
1284 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1289 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1290 const struct lttng_event_rule
*rule
,
1292 const char **exclusion
)
1295 struct lttng_event_rule_tracepoint
*tracepoint
;
1296 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1298 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1299 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1303 tracepoint
= container_of(
1304 rule
, struct lttng_event_rule_tracepoint
, parent
);
1305 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1306 LTTNG_EVENT_RULE_STATUS_OK
) {
1310 if (index
>= count
) {
1314 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1315 &tracepoint
->exclusions
, index
);