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 <common/string-utils/string-utils.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/tracepoint-internal.h>
21 #include <lttng/log-level-rule.h>
22 #include <lttng/event.h>
24 #define IS_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
27 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
29 struct lttng_event_rule_tracepoint
*tracepoint
;
35 tracepoint
= container_of(
36 rule
, struct lttng_event_rule_tracepoint
, parent
);
38 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
39 free(tracepoint
->pattern
);
40 free(tracepoint
->filter_expression
);
41 free(tracepoint
->internal_filter
.filter
);
42 free(tracepoint
->internal_filter
.bytecode
);
46 static bool lttng_event_rule_tracepoint_validate(
47 const struct lttng_event_rule
*rule
)
50 struct lttng_event_rule_tracepoint
*tracepoint
;
56 tracepoint
= container_of(
57 rule
, struct lttng_event_rule_tracepoint
, parent
);
60 if (!tracepoint
->pattern
) {
61 ERR("Invalid tracepoint event rule: a pattern must be set.");
66 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
67 ERR("Invalid tracepoint event rule: a domain must be set.");
76 static int lttng_event_rule_tracepoint_serialize(
77 const struct lttng_event_rule
*rule
,
78 struct lttng_payload
*payload
)
81 size_t pattern_len
, filter_expression_len
, exclusions_len
, header_offset
;
82 size_t size_before_log_level_rule
;
83 struct lttng_event_rule_tracepoint
*tracepoint
;
84 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
85 enum lttng_event_rule_status status
;
86 unsigned int exclusion_count
;
87 size_t exclusions_appended_len
= 0;
88 struct lttng_event_rule_tracepoint_comm
*header
;
90 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
95 header_offset
= payload
->buffer
.size
;
97 DBG("Serializing tracepoint event rule.");
98 tracepoint
= container_of(
99 rule
, struct lttng_event_rule_tracepoint
, parent
);
101 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
102 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
104 pattern_len
= strlen(tracepoint
->pattern
) + 1;
106 if (tracepoint
->filter_expression
!= NULL
) {
107 filter_expression_len
=
108 strlen(tracepoint
->filter_expression
) + 1;
110 filter_expression_len
= 0;
114 for (i
= 0; i
< exclusion_count
; i
++) {
115 const char *exclusion
;
117 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
118 rule
, i
, &exclusion
);
119 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
122 exclusions_len
+= sizeof(uint32_t);
123 /* Payload (null terminated). */
124 exclusions_len
+= strlen(exclusion
) + 1;
127 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
128 tracepoint_comm
.pattern_len
= pattern_len
;
129 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
130 tracepoint_comm
.exclusions_count
= exclusion_count
;
131 tracepoint_comm
.exclusions_len
= exclusions_len
;
133 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
134 sizeof(tracepoint_comm
));
139 ret
= lttng_dynamic_buffer_append(
140 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
145 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
146 filter_expression_len
);
151 size_before_log_level_rule
= payload
->buffer
.size
;
153 ret
= lttng_log_level_rule_serialize(tracepoint
->log_level_rule
, payload
);
158 header
= (typeof(header
)) ((char *) payload
->buffer
.data
+ header_offset
);
159 header
->log_level_rule_len
=
160 payload
->buffer
.size
- size_before_log_level_rule
;
162 for (i
= 0; i
< exclusion_count
; i
++) {
164 const char *exclusion
;
166 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
167 rule
, i
, &exclusion
);
168 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
170 len
= strlen(exclusion
) + 1;
171 /* Append exclusion length, includes the null terminator. */
172 ret
= lttng_dynamic_buffer_append(
173 &payload
->buffer
, &len
, sizeof(uint32_t));
178 exclusions_appended_len
+= sizeof(uint32_t);
180 /* Include the '\0' in the payload. */
181 ret
= lttng_dynamic_buffer_append(
182 &payload
->buffer
, exclusion
, len
);
187 exclusions_appended_len
+= len
;
190 assert(exclusions_len
== exclusions_appended_len
);
196 static bool lttng_event_rule_tracepoint_is_equal(
197 const struct lttng_event_rule
*_a
,
198 const struct lttng_event_rule
*_b
)
201 bool is_equal
= false;
202 struct lttng_event_rule_tracepoint
*a
, *b
;
203 unsigned int count_a
, count_b
;
204 enum lttng_event_rule_status status
;
206 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
207 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
209 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
210 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
211 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
212 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
215 if (a
->domain
!= b
->domain
) {
219 if (count_a
!= count_b
) {
223 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
230 if (strcmp(a
->pattern
, b
->pattern
)) {
234 if (a
->filter_expression
&& b
->filter_expression
) {
235 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
238 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
239 /* One is set; not the other. */
243 if (!lttng_log_level_rule_is_equal(
244 a
->log_level_rule
, b
->log_level_rule
)) {
248 for (i
= 0; i
< count_a
; i
++) {
249 const char *exclusion_a
, *exclusion_b
;
251 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
252 _a
, i
, &exclusion_a
);
253 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
254 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
255 _b
, i
, &exclusion_b
);
256 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
257 if (strcmp(exclusion_a
, exclusion_b
)) {
268 * On success ret is 0;
270 * On error ret is negative.
272 * An event with NO loglevel and the name is * will return NULL.
274 static int generate_agent_filter(
275 const struct lttng_event_rule
*rule
, char **_agent_filter
)
279 char *agent_filter
= NULL
;
282 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
283 enum lttng_event_rule_status status
;
286 assert(_agent_filter
);
288 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
289 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
294 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
295 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
297 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
303 /* Don't add filter for the '*' event. */
304 if (strcmp(pattern
, "*") != 0) {
306 err
= asprintf(&agent_filter
,
307 "(%s) && (logger_name == \"%s\")",
310 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
315 PERROR("Failed to format agent filter string");
321 status
= lttng_event_rule_tracepoint_get_log_level_rule(
322 rule
, &log_level_rule
);
323 if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
324 enum lttng_log_level_rule_status llr_status
;
328 switch (lttng_log_level_rule_get_type(log_level_rule
))
330 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
331 llr_status
= lttng_log_level_rule_exactly_get_level(
332 log_level_rule
, &level
);
335 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
336 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
337 log_level_rule
, &level
);
344 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
349 if (filter
|| agent_filter
) {
352 err
= asprintf(&new_filter
,
353 "(%s) && (int_loglevel %s %d)",
354 agent_filter
? agent_filter
: filter
,
359 agent_filter
= new_filter
;
361 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
366 PERROR("Failed to format agent filter string");
372 *_agent_filter
= agent_filter
;
380 static enum lttng_error_code
381 lttng_event_rule_tracepoint_generate_filter_bytecode(
382 struct lttng_event_rule
*rule
,
383 const struct lttng_credentials
*creds
)
386 enum lttng_error_code ret_code
;
387 struct lttng_event_rule_tracepoint
*tracepoint
;
388 enum lttng_domain_type domain_type
;
389 enum lttng_event_rule_status status
;
391 struct lttng_bytecode
*bytecode
= NULL
;
395 tracepoint
= container_of(
396 rule
, struct lttng_event_rule_tracepoint
, parent
);
398 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
399 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
401 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
402 ret_code
= LTTNG_ERR_FILTER_INVAL
;
406 if (filter
&& filter
[0] == '\0') {
407 ret_code
= LTTNG_ERR_FILTER_INVAL
;
411 status
= lttng_event_rule_tracepoint_get_domain_type(
413 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
414 ret_code
= LTTNG_ERR_UNK
;
418 switch (domain_type
) {
419 case LTTNG_DOMAIN_LOG4J
:
420 case LTTNG_DOMAIN_JUL
:
421 case LTTNG_DOMAIN_PYTHON
:
425 ret
= generate_agent_filter(rule
, &agent_filter
);
427 ret_code
= LTTNG_ERR_FILTER_INVAL
;
431 tracepoint
->internal_filter
.filter
= agent_filter
;
437 tracepoint
->internal_filter
.filter
= strdup(filter
);
438 if (tracepoint
->internal_filter
.filter
== NULL
) {
439 ret_code
= LTTNG_ERR_NOMEM
;
443 tracepoint
->internal_filter
.filter
= NULL
;
449 if (tracepoint
->internal_filter
.filter
== NULL
) {
454 ret
= run_as_generate_filter_bytecode(
455 tracepoint
->internal_filter
.filter
, creds
,
458 ret_code
= LTTNG_ERR_FILTER_INVAL
;
462 tracepoint
->internal_filter
.bytecode
= bytecode
;
472 static const char *lttng_event_rule_tracepoint_get_internal_filter(
473 const struct lttng_event_rule
*rule
)
475 struct lttng_event_rule_tracepoint
*tracepoint
;
478 tracepoint
= container_of(
479 rule
, struct lttng_event_rule_tracepoint
, parent
);
480 return tracepoint
->internal_filter
.filter
;
483 static const struct lttng_bytecode
*
484 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
485 const struct lttng_event_rule
*rule
)
487 struct lttng_event_rule_tracepoint
*tracepoint
;
490 tracepoint
= container_of(
491 rule
, struct lttng_event_rule_tracepoint
, parent
);
492 return tracepoint
->internal_filter
.bytecode
;
495 static enum lttng_event_rule_generate_exclusions_status
496 lttng_event_rule_tracepoint_generate_exclusions(
497 const struct lttng_event_rule
*rule
,
498 struct lttng_event_exclusion
**_exclusions
)
500 unsigned int nb_exclusions
= 0, i
;
501 enum lttng_domain_type domain_type
;
502 struct lttng_event_exclusion
*exclusions
;
503 enum lttng_event_rule_status event_rule_status
;
504 enum lttng_event_rule_generate_exclusions_status ret_status
;
508 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
510 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
512 switch (domain_type
) {
513 case LTTNG_DOMAIN_KERNEL
:
514 case LTTNG_DOMAIN_JUL
:
515 case LTTNG_DOMAIN_LOG4J
:
516 case LTTNG_DOMAIN_PYTHON
:
519 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
521 case LTTNG_DOMAIN_UST
:
522 /* Exclusions supported. */
525 /* Unknown domain. */
529 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
530 rule
, &nb_exclusions
);
531 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
532 if (nb_exclusions
== 0) {
535 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
539 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
540 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
542 PERROR("Failed to allocate exclusions buffer");
543 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
547 exclusions
->count
= nb_exclusions
;
548 for (i
= 0; i
< nb_exclusions
; i
++) {
550 const char *exclusion_str
;
553 lttng_event_rule_tracepoint_get_exclusion_at_index(
554 rule
, i
, &exclusion_str
);
555 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
557 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
558 LTTNG_SYMBOL_NAME_LEN
);
562 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
567 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
570 *_exclusions
= exclusions
;
574 static void destroy_lttng_exclusions_element(void *ptr
)
579 static unsigned long lttng_event_rule_tracepoint_hash(
580 const struct lttng_event_rule
*rule
)
583 unsigned int i
, exclusion_count
;
584 enum lttng_event_rule_status status
;
585 struct lttng_event_rule_tracepoint
*tp_rule
=
586 container_of(rule
, typeof(*tp_rule
), parent
);
588 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT
,
590 hash
^= hash_key_ulong((void *) tp_rule
->domain
, lttng_ht_seed
);
591 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
593 if (tp_rule
->filter_expression
) {
594 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
597 if (tp_rule
->log_level_rule
) {
598 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
601 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
,
603 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
605 for (i
= 0; i
< exclusion_count
; i
++) {
606 const char *exclusion
;
608 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
609 rule
, i
, &exclusion
);
610 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
611 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
617 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
618 const struct lttng_event_rule
*rule
)
621 const struct lttng_event_rule_tracepoint
*tracepoint
;
622 struct lttng_event
*local_event
= NULL
;
623 struct lttng_event
*event
= NULL
;
624 enum lttng_loglevel_type loglevel_type
;
625 int loglevel_value
= 0;
626 enum lttng_event_rule_status status
;
627 const struct lttng_log_level_rule
*log_level_rule
;
629 tracepoint
= container_of(
630 rule
, const struct lttng_event_rule_tracepoint
, parent
);
632 local_event
= zmalloc(sizeof(*local_event
));
637 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
638 ret
= lttng_strncpy(local_event
->name
, tracepoint
->pattern
,
639 sizeof(local_event
->name
));
641 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
642 tracepoint
->pattern
);
647 /* Map the log level rule to an equivalent lttng_loglevel. */
648 status
= lttng_event_rule_tracepoint_get_log_level_rule(
649 rule
, &log_level_rule
);
650 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
651 loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
653 } else if (status
== LTTNG_EVENT_RULE_STATUS_OK
) {
654 enum lttng_log_level_rule_status llr_status
;
656 switch (lttng_log_level_rule_get_type(log_level_rule
)) {
657 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
658 llr_status
= lttng_log_level_rule_exactly_get_level(
659 log_level_rule
, &loglevel_value
);
660 loglevel_type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
662 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
663 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
664 log_level_rule
, &loglevel_value
);
665 loglevel_type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
672 if (llr_status
!= LTTNG_LOG_LEVEL_RULE_STATUS_OK
) {
679 local_event
->loglevel_type
= loglevel_type
;
680 local_event
->loglevel
= loglevel_value
;
689 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
690 enum lttng_domain_type domain_type
)
692 struct lttng_event_rule
*rule
= NULL
;
693 struct lttng_event_rule_tracepoint
*tp_rule
;
694 enum lttng_event_rule_status status
;
696 if (domain_type
== LTTNG_DOMAIN_NONE
) {
700 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
705 rule
= &tp_rule
->parent
;
706 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
707 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
708 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
709 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
710 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
711 tp_rule
->parent
.generate_filter_bytecode
=
712 lttng_event_rule_tracepoint_generate_filter_bytecode
;
713 tp_rule
->parent
.get_filter
=
714 lttng_event_rule_tracepoint_get_internal_filter
;
715 tp_rule
->parent
.get_filter_bytecode
=
716 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
717 tp_rule
->parent
.generate_exclusions
=
718 lttng_event_rule_tracepoint_generate_exclusions
;
719 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
720 tp_rule
->parent
.generate_lttng_event
=
721 lttng_event_rule_tracepoint_generate_lttng_event
;
723 tp_rule
->domain
= domain_type
;
724 tp_rule
->log_level_rule
= NULL
;
726 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
727 destroy_lttng_exclusions_element
);
729 /* Default pattern is '*'. */
730 status
= lttng_event_rule_tracepoint_set_pattern(rule
, "*");
731 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
732 lttng_event_rule_destroy(rule
);
741 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
742 struct lttng_payload_view
*view
,
743 struct lttng_event_rule
**_event_rule
)
745 ssize_t ret
, offset
= 0;
747 enum lttng_event_rule_status status
;
748 enum lttng_domain_type domain_type
;
749 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
751 const char *filter_expression
= NULL
;
752 const char **exclusions
= NULL
;
753 const uint32_t *exclusion_len
;
754 const char *exclusion
;
755 struct lttng_buffer_view current_buffer_view
;
756 struct lttng_event_rule
*rule
= NULL
;
757 struct lttng_log_level_rule
*log_level_rule
= NULL
;
764 current_buffer_view
= lttng_buffer_view_from_view(
765 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
766 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
767 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
772 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
774 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
775 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
776 /* Invalid domain value. */
777 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
778 (int) tracepoint_comm
->domain_type
);
783 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
784 rule
= lttng_event_rule_tracepoint_create(domain_type
);
786 ERR("Failed to create event rule tracepoint.");
791 /* Skip to payload. */
792 offset
+= current_buffer_view
.size
;
794 /* Map the pattern. */
795 current_buffer_view
= lttng_buffer_view_from_view(
796 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
798 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
803 pattern
= current_buffer_view
.data
;
804 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
805 tracepoint_comm
->pattern_len
)) {
810 /* Skip after the pattern. */
811 offset
+= tracepoint_comm
->pattern_len
;
813 if (!tracepoint_comm
->filter_expression_len
) {
814 goto skip_filter_expression
;
817 /* Map the filter_expression. */
818 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
819 tracepoint_comm
->filter_expression_len
);
820 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
825 filter_expression
= current_buffer_view
.data
;
826 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
828 tracepoint_comm
->filter_expression_len
)) {
833 /* Skip after the pattern. */
834 offset
+= tracepoint_comm
->filter_expression_len
;
836 skip_filter_expression
:
837 if (!tracepoint_comm
->log_level_rule_len
) {
838 goto skip_log_level_rule
;
842 /* Map the log level rule. */
843 struct lttng_payload_view current_payload_view
=
844 lttng_payload_view_from_view(view
, offset
,
845 tracepoint_comm
->log_level_rule_len
);
847 ret
= lttng_log_level_rule_create_from_payload(
848 ¤t_payload_view
, &log_level_rule
);
854 assert(ret
== tracepoint_comm
->log_level_rule_len
);
857 /* Skip after the log level rule. */
858 offset
+= tracepoint_comm
->log_level_rule_len
;
861 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
862 current_buffer_view
= lttng_buffer_view_from_view(
863 &view
->buffer
, offset
, sizeof(*exclusion_len
));
864 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
869 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
870 offset
+= sizeof(*exclusion_len
);
872 current_buffer_view
= lttng_buffer_view_from_view(
873 &view
->buffer
, offset
, *exclusion_len
);
874 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
879 exclusion
= current_buffer_view
.data
;
880 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
881 exclusion
, *exclusion_len
)) {
886 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
887 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
888 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
894 /* Skip to next exclusion. */
895 offset
+= *exclusion_len
;
898 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
899 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
900 ERR("Failed to set event rule tracepoint pattern.");
905 if (filter_expression
) {
906 status
= lttng_event_rule_tracepoint_set_filter(
907 rule
, filter_expression
);
908 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
909 ERR("Failed to set event rule tracepoint pattern.");
915 if (log_level_rule
) {
916 status
= lttng_event_rule_tracepoint_set_log_level_rule(
917 rule
, log_level_rule
);
918 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
919 ERR("Failed to set event rule tracepoint log level rule.");
930 lttng_log_level_rule_destroy(log_level_rule
);
931 lttng_event_rule_destroy(rule
);
935 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
936 struct lttng_event_rule
*rule
, const char *pattern
)
938 char *pattern_copy
= NULL
;
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
) || !pattern
||
943 strlen(pattern
) == 0) {
944 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
948 tracepoint
= container_of(
949 rule
, struct lttng_event_rule_tracepoint
, parent
);
950 pattern_copy
= strdup(pattern
);
952 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
956 /* Normalize the pattern. */
957 strutils_normalize_star_glob_pattern(pattern_copy
);
959 free(tracepoint
->pattern
);
961 tracepoint
->pattern
= pattern_copy
;
967 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
968 const struct lttng_event_rule
*rule
, const char **pattern
)
970 struct lttng_event_rule_tracepoint
*tracepoint
;
971 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
973 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
974 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
978 tracepoint
= container_of(
979 rule
, struct lttng_event_rule_tracepoint
, parent
);
980 if (!tracepoint
->pattern
) {
981 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
985 *pattern
= tracepoint
->pattern
;
990 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
991 const struct lttng_event_rule
*rule
,
992 enum lttng_domain_type
*type
)
994 struct lttng_event_rule_tracepoint
*tracepoint
;
995 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
997 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
998 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1002 tracepoint
= container_of(
1003 rule
, struct lttng_event_rule_tracepoint
, parent
);
1004 *type
= tracepoint
->domain
;
1009 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
1010 struct lttng_event_rule
*rule
, const char *expression
)
1012 char *expression_copy
= NULL
;
1013 struct lttng_event_rule_tracepoint
*tracepoint
;
1014 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1016 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
1017 strlen(expression
) == 0) {
1018 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1022 tracepoint
= container_of(
1023 rule
, struct lttng_event_rule_tracepoint
, parent
);
1024 expression_copy
= strdup(expression
);
1025 if (!expression_copy
) {
1026 PERROR("Failed to copy filter expression");
1027 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1031 if (tracepoint
->filter_expression
) {
1032 free(tracepoint
->filter_expression
);
1035 tracepoint
->filter_expression
= expression_copy
;
1036 expression_copy
= NULL
;
1041 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
1042 const struct lttng_event_rule
*rule
, const char **expression
)
1044 struct lttng_event_rule_tracepoint
*tracepoint
;
1045 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1047 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
1048 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1052 tracepoint
= container_of(
1053 rule
, struct lttng_event_rule_tracepoint
, parent
);
1054 if (!tracepoint
->filter_expression
) {
1055 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1059 *expression
= tracepoint
->filter_expression
;
1064 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
,
1065 enum lttng_domain_type domain
)
1068 enum lttng_log_level_rule_status status
;
1071 switch (lttng_log_level_rule_get_type(rule
)) {
1072 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
1073 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
1075 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
1076 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
1083 assert(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
1086 case LTTNG_DOMAIN_KERNEL
:
1089 case LTTNG_DOMAIN_UST
:
1090 if (level
< LTTNG_LOGLEVEL_EMERG
) {
1094 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
1101 case LTTNG_DOMAIN_JUL
:
1102 case LTTNG_DOMAIN_LOG4J
:
1103 case LTTNG_DOMAIN_PYTHON
:
1105 * For both JUL and LOG4J custom log level are possible and can
1106 * span the entire int32 range.
1108 * For python, custom log level are possible, it is not clear if
1109 * negative value are accepted (NOTSET == 0) but the source code
1110 * validates against the int type implying that negative values
1115 case LTTNG_DOMAIN_NONE
:
1124 static bool domain_supports_log_levels(enum lttng_domain_type domain
)
1129 case LTTNG_DOMAIN_KERNEL
:
1132 case LTTNG_DOMAIN_UST
:
1133 case LTTNG_DOMAIN_JUL
:
1134 case LTTNG_DOMAIN_LOG4J
:
1135 case LTTNG_DOMAIN_PYTHON
:
1145 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_rule(
1146 struct lttng_event_rule
*rule
,
1147 const struct lttng_log_level_rule
*log_level_rule
)
1149 struct lttng_event_rule_tracepoint
*tracepoint
;
1150 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1151 struct lttng_log_level_rule
*copy
= NULL
;
1153 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1154 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1158 tracepoint
= container_of(
1159 rule
, struct lttng_event_rule_tracepoint
, parent
);
1161 if (!domain_supports_log_levels(tracepoint
->domain
)) {
1162 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1166 if (!log_level_rule_valid(log_level_rule
, tracepoint
->domain
)) {
1167 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1171 copy
= lttng_log_level_rule_copy(log_level_rule
);
1173 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1177 if (tracepoint
->log_level_rule
) {
1178 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
1181 tracepoint
->log_level_rule
= copy
;
1187 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_rule(
1188 const struct lttng_event_rule
*rule
,
1189 const struct lttng_log_level_rule
**log_level_rule
1192 struct lttng_event_rule_tracepoint
*tracepoint
;
1193 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1195 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
1196 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1200 tracepoint
= container_of(
1201 rule
, struct lttng_event_rule_tracepoint
, parent
);
1202 if (tracepoint
->log_level_rule
== NULL
) {
1203 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1207 *log_level_rule
= tracepoint
->log_level_rule
;
1212 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1213 struct lttng_event_rule
*rule
,
1214 const char *exclusion
)
1217 char *exclusion_copy
= NULL
;
1218 struct lttng_event_rule_tracepoint
*tracepoint
;
1219 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1220 enum lttng_domain_type domain_type
;
1222 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1224 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1228 tracepoint
= container_of(
1229 rule
, struct lttng_event_rule_tracepoint
, parent
);
1231 status
= lttng_event_rule_tracepoint_get_domain_type(
1232 rule
, &domain_type
);
1233 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1237 switch (domain_type
) {
1238 case LTTNG_DOMAIN_KERNEL
:
1239 case LTTNG_DOMAIN_JUL
:
1240 case LTTNG_DOMAIN_LOG4J
:
1241 case LTTNG_DOMAIN_PYTHON
:
1242 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1244 case LTTNG_DOMAIN_UST
:
1245 /* Exclusions supported. */
1251 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1252 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1256 exclusion_copy
= strdup(exclusion
);
1257 if (!exclusion_copy
) {
1258 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1262 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1265 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1269 exclusion_copy
= NULL
;
1271 free(exclusion_copy
);
1275 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1276 const struct lttng_event_rule
*rule
, unsigned int *count
)
1278 struct lttng_event_rule_tracepoint
*tracepoint
;
1279 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1281 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1282 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1286 tracepoint
= container_of(
1287 rule
, struct lttng_event_rule_tracepoint
, parent
);
1288 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1293 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1294 const struct lttng_event_rule
*rule
,
1296 const char **exclusion
)
1299 struct lttng_event_rule_tracepoint
*tracepoint
;
1300 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1302 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1303 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1307 tracepoint
= container_of(
1308 rule
, struct lttng_event_rule_tracepoint
, parent
);
1309 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1310 LTTNG_EVENT_RULE_STATUS_OK
) {
1314 if (index
>= count
) {
1318 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1319 &tracepoint
->exclusions
, index
);