2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/runas.h>
15 #include <common/hashtable/hashtable.h>
16 #include <common/hashtable/utils.h>
17 #include <lttng/event-rule/event-rule-internal.h>
18 #include <lttng/event-rule/tracepoint-internal.h>
20 #define IS_TRACEPOINT_EVENT_RULE(rule) \
21 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
23 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
25 struct lttng_event_rule_tracepoint
*tracepoint
;
31 tracepoint
= container_of(
32 rule
, struct lttng_event_rule_tracepoint
, parent
);
34 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
35 free(tracepoint
->pattern
);
36 free(tracepoint
->filter_expression
);
37 free(tracepoint
->internal_filter
.filter
);
38 free(tracepoint
->internal_filter
.bytecode
);
42 static bool lttng_event_rule_tracepoint_validate(
43 const struct lttng_event_rule
*rule
)
46 struct lttng_event_rule_tracepoint
*tracepoint
;
52 tracepoint
= container_of(
53 rule
, struct lttng_event_rule_tracepoint
, parent
);
56 if (!tracepoint
->pattern
) {
57 ERR("Invalid tracepoint event rule: a pattern must be set.");
62 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
63 ERR("Invalid tracepoint event rule: a domain must be set.");
72 static int lttng_event_rule_tracepoint_serialize(
73 const struct lttng_event_rule
*rule
,
74 struct lttng_payload
*payload
)
77 size_t pattern_len
, filter_expression_len
, exclusions_len
;
78 struct lttng_event_rule_tracepoint
*tracepoint
;
79 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
80 enum lttng_event_rule_status status
;
81 unsigned int exclusion_count
;
82 size_t exclusions_appended_len
= 0;
84 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
89 DBG("Serializing tracepoint event rule.");
90 tracepoint
= container_of(
91 rule
, struct lttng_event_rule_tracepoint
, parent
);
93 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
94 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
96 pattern_len
= strlen(tracepoint
->pattern
) + 1;
98 if (tracepoint
->filter_expression
!= NULL
) {
99 filter_expression_len
=
100 strlen(tracepoint
->filter_expression
) + 1;
102 filter_expression_len
= 0;
106 for (i
= 0; i
< exclusion_count
; i
++) {
107 const char *exclusion
;
109 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
110 rule
, i
, &exclusion
);
111 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
114 exclusions_len
+= sizeof(uint32_t);
115 /* Payload (null terminated). */
116 exclusions_len
+= strlen(exclusion
) + 1;
119 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
120 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
121 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
122 tracepoint_comm
.pattern_len
= pattern_len
;
123 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
124 tracepoint_comm
.exclusions_count
= exclusion_count
;
125 tracepoint_comm
.exclusions_len
= exclusions_len
;
127 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
128 sizeof(tracepoint_comm
));
133 ret
= lttng_dynamic_buffer_append(
134 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
139 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
140 filter_expression_len
);
145 for (i
= 0; i
< exclusion_count
; i
++) {
147 const char *exclusion
;
149 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
150 rule
, i
, &exclusion
);
151 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
153 len
= strlen(exclusion
) + 1;
154 /* Append exclusion length, includes the null terminator. */
155 ret
= lttng_dynamic_buffer_append(
156 &payload
->buffer
, &len
, sizeof(uint32_t));
161 exclusions_appended_len
+= sizeof(uint32_t);
163 /* Include the '\0' in the payload. */
164 ret
= lttng_dynamic_buffer_append(
165 &payload
->buffer
, exclusion
, len
);
170 exclusions_appended_len
+= len
;
173 assert(exclusions_len
== exclusions_appended_len
);
179 static bool lttng_event_rule_tracepoint_is_equal(
180 const struct lttng_event_rule
*_a
,
181 const struct lttng_event_rule
*_b
)
184 bool is_equal
= false;
185 struct lttng_event_rule_tracepoint
*a
, *b
;
186 unsigned int count_a
, count_b
;
187 enum lttng_event_rule_status status
;
189 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
190 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
192 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
193 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
194 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
195 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
198 if (a
->domain
!= b
->domain
) {
202 if (count_a
!= count_b
) {
206 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
213 if (strcmp(a
->pattern
, b
->pattern
)) {
217 if (a
->filter_expression
&& b
->filter_expression
) {
218 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
221 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
222 /* One is set; not the other. */
226 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
230 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
234 for (i
= 0; i
< count_a
; i
++) {
235 const char *exclusion_a
, *exclusion_b
;
237 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
238 _a
, i
, &exclusion_a
);
239 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
240 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
241 _b
, i
, &exclusion_b
);
242 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
243 if (strcmp(exclusion_a
, exclusion_b
)) {
254 * On success ret is 0;
256 * On error ret is negative.
258 * An event with NO loglevel and the name is * will return NULL.
260 static int generate_agent_filter(
261 const struct lttng_event_rule
*rule
, char **_agent_filter
)
265 char *agent_filter
= NULL
;
268 enum lttng_loglevel_type loglevel_type
;
269 enum lttng_event_rule_status status
;
272 assert(_agent_filter
);
274 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
275 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
280 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
281 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
283 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
288 status
= lttng_event_rule_tracepoint_get_log_level_type(
289 rule
, &loglevel_type
);
290 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
295 /* Don't add filter for the '*' event. */
296 if (strcmp(pattern
, "*") != 0) {
298 err
= asprintf(&agent_filter
,
299 "(%s) && (logger_name == \"%s\")",
302 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
307 PERROR("Failed to format agent filter string");
313 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
317 status
= lttng_event_rule_tracepoint_get_log_level(
318 rule
, &loglevel_value
);
319 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
324 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
330 if (filter
|| agent_filter
) {
333 err
= asprintf(&new_filter
,
334 "(%s) && (int_loglevel %s %d)",
335 agent_filter
? agent_filter
: filter
,
340 agent_filter
= new_filter
;
342 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
347 PERROR("Failed to format agent filter string");
353 *_agent_filter
= agent_filter
;
361 static enum lttng_error_code
362 lttng_event_rule_tracepoint_generate_filter_bytecode(
363 struct lttng_event_rule
*rule
,
364 const struct lttng_credentials
*creds
)
367 enum lttng_error_code ret_code
;
368 struct lttng_event_rule_tracepoint
*tracepoint
;
369 enum lttng_domain_type domain_type
;
370 enum lttng_event_rule_status status
;
372 struct lttng_filter_bytecode
*bytecode
= NULL
;
376 tracepoint
= container_of(
377 rule
, struct lttng_event_rule_tracepoint
, parent
);
379 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
380 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
382 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
383 ret_code
= LTTNG_ERR_FILTER_INVAL
;
387 if (filter
&& filter
[0] == '\0') {
388 ret_code
= LTTNG_ERR_FILTER_INVAL
;
392 status
= lttng_event_rule_tracepoint_get_domain_type(
394 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
395 ret_code
= LTTNG_ERR_UNK
;
399 switch (domain_type
) {
400 case LTTNG_DOMAIN_LOG4J
:
401 case LTTNG_DOMAIN_JUL
:
402 case LTTNG_DOMAIN_PYTHON
:
406 ret
= generate_agent_filter(rule
, &agent_filter
);
408 ret_code
= LTTNG_ERR_FILTER_INVAL
;
412 tracepoint
->internal_filter
.filter
= agent_filter
;
418 tracepoint
->internal_filter
.filter
= strdup(filter
);
419 if (tracepoint
->internal_filter
.filter
== NULL
) {
420 ret_code
= LTTNG_ERR_NOMEM
;
424 tracepoint
->internal_filter
.filter
= NULL
;
430 if (tracepoint
->internal_filter
.filter
== NULL
) {
435 ret
= run_as_generate_filter_bytecode(
436 tracepoint
->internal_filter
.filter
, creds
,
439 ret_code
= LTTNG_ERR_FILTER_INVAL
;
443 tracepoint
->internal_filter
.bytecode
= bytecode
;
453 static const char *lttng_event_rule_tracepoint_get_internal_filter(
454 const struct lttng_event_rule
*rule
)
456 struct lttng_event_rule_tracepoint
*tracepoint
;
459 tracepoint
= container_of(
460 rule
, struct lttng_event_rule_tracepoint
, parent
);
461 return tracepoint
->internal_filter
.filter
;
464 static const struct lttng_filter_bytecode
*
465 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
466 const struct lttng_event_rule
*rule
)
468 struct lttng_event_rule_tracepoint
*tracepoint
;
471 tracepoint
= container_of(
472 rule
, struct lttng_event_rule_tracepoint
, parent
);
473 return tracepoint
->internal_filter
.bytecode
;
476 static enum lttng_event_rule_generate_exclusions_status
477 lttng_event_rule_tracepoint_generate_exclusions(
478 const struct lttng_event_rule
*rule
,
479 struct lttng_event_exclusion
**_exclusions
)
481 unsigned int nb_exclusions
= 0, i
;
482 enum lttng_domain_type domain_type
;
483 struct lttng_event_exclusion
*exclusions
;
484 enum lttng_event_rule_status event_rule_status
;
485 enum lttng_event_rule_generate_exclusions_status ret_status
;
489 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
491 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
493 switch (domain_type
) {
494 case LTTNG_DOMAIN_KERNEL
:
495 case LTTNG_DOMAIN_JUL
:
496 case LTTNG_DOMAIN_LOG4J
:
497 case LTTNG_DOMAIN_PYTHON
:
500 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
502 case LTTNG_DOMAIN_UST
:
503 /* Exclusions supported. */
506 /* Unknown domain. */
510 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
511 rule
, &nb_exclusions
);
512 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
513 if (nb_exclusions
== 0) {
516 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
520 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
521 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
523 PERROR("Failed to allocate exclusions buffer");
524 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
528 exclusions
->count
= nb_exclusions
;
529 for (i
= 0; i
< nb_exclusions
; i
++) {
531 const char *exclusion_str
;
534 lttng_event_rule_tracepoint_get_exclusion_at_index(
535 rule
, i
, &exclusion_str
);
536 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
538 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
539 LTTNG_SYMBOL_NAME_LEN
);
543 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
548 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
551 *_exclusions
= exclusions
;
555 static void destroy_lttng_exclusions_element(void *ptr
)
560 static unsigned long lttng_event_rule_tracepoint_hash(
561 const struct lttng_event_rule
*rule
)
564 unsigned int i
, exclusion_count
;
565 enum lttng_event_rule_status status
;
566 struct lttng_event_rule_tracepoint
*tp_rule
=
567 container_of(rule
, typeof(*tp_rule
), parent
);
569 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT
,
571 hash
^= hash_key_ulong((void *) tp_rule
->domain
, lttng_ht_seed
);
572 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
574 if (tp_rule
->filter_expression
) {
575 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
578 hash
^= hash_key_ulong((void *) tp_rule
->loglevel
.type
,
580 if (tp_rule
->loglevel
.type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
581 hash
^= hash_key_ulong(
582 (void *) (unsigned long) tp_rule
->loglevel
.value
,
586 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
,
588 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
590 for (i
= 0; i
< exclusion_count
; i
++) {
591 const char *exclusion
;
593 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
594 rule
, i
, &exclusion
);
595 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
596 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
602 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
603 enum lttng_domain_type domain_type
)
605 struct lttng_event_rule
*rule
= NULL
;
606 struct lttng_event_rule_tracepoint
*tp_rule
;
608 if (domain_type
== LTTNG_DOMAIN_NONE
) {
612 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
617 rule
= &tp_rule
->parent
;
618 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
619 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
620 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
621 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
622 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
623 tp_rule
->parent
.generate_filter_bytecode
=
624 lttng_event_rule_tracepoint_generate_filter_bytecode
;
625 tp_rule
->parent
.get_filter
=
626 lttng_event_rule_tracepoint_get_internal_filter
;
627 tp_rule
->parent
.get_filter_bytecode
=
628 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
629 tp_rule
->parent
.generate_exclusions
=
630 lttng_event_rule_tracepoint_generate_exclusions
;
631 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
633 tp_rule
->domain
= domain_type
;
634 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
636 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
637 destroy_lttng_exclusions_element
);
643 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
644 struct lttng_payload_view
*view
,
645 struct lttng_event_rule
**_event_rule
)
647 ssize_t ret
, offset
= 0;
649 enum lttng_event_rule_status status
;
650 enum lttng_domain_type domain_type
;
651 enum lttng_loglevel_type loglevel_type
;
652 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
654 const char *filter_expression
= NULL
;
655 const char **exclusions
= NULL
;
656 const uint32_t *exclusion_len
;
657 const char *exclusion
;
658 struct lttng_buffer_view current_buffer_view
;
659 struct lttng_event_rule
*rule
= NULL
;
666 current_buffer_view
= lttng_buffer_view_from_view(
667 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
668 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
669 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
674 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
676 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
677 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
678 /* Invalid domain value. */
679 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
680 (int) tracepoint_comm
->domain_type
);
685 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
686 rule
= lttng_event_rule_tracepoint_create(domain_type
);
688 ERR("Failed to create event rule tracepoint.");
693 loglevel_type
= (enum lttng_loglevel_type
)
694 tracepoint_comm
->loglevel_type
;
695 switch (loglevel_type
) {
696 case LTTNG_EVENT_LOGLEVEL_ALL
:
697 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
699 case LTTNG_EVENT_LOGLEVEL_RANGE
:
700 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
701 (enum lttng_loglevel_type
) tracepoint_comm
704 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
705 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
706 (enum lttng_loglevel_type
) tracepoint_comm
710 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
715 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
716 ERR("Failed to set event rule tracepoint loglevel.");
719 /* Skip to payload. */
720 offset
+= current_buffer_view
.size
;
722 /* Map the pattern. */
723 current_buffer_view
= lttng_buffer_view_from_view(
724 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
726 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
731 pattern
= current_buffer_view
.data
;
732 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
733 tracepoint_comm
->pattern_len
)) {
738 /* Skip after the pattern. */
739 offset
+= tracepoint_comm
->pattern_len
;
741 if (!tracepoint_comm
->filter_expression_len
) {
742 goto skip_filter_expression
;
745 /* Map the filter_expression. */
746 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
747 tracepoint_comm
->filter_expression_len
);
748 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
753 filter_expression
= current_buffer_view
.data
;
754 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
756 tracepoint_comm
->filter_expression_len
)) {
761 /* Skip after the pattern. */
762 offset
+= tracepoint_comm
->filter_expression_len
;
764 skip_filter_expression
:
765 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
766 current_buffer_view
= lttng_buffer_view_from_view(
767 &view
->buffer
, offset
, sizeof(*exclusion_len
));
768 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
773 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
774 offset
+= sizeof(*exclusion_len
);
776 current_buffer_view
= lttng_buffer_view_from_view(
777 &view
->buffer
, offset
, *exclusion_len
);
778 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
783 exclusion
= current_buffer_view
.data
;
784 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
785 exclusion
, *exclusion_len
)) {
790 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
791 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
792 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
798 /* Skip to next exclusion. */
799 offset
+= *exclusion_len
;
802 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
803 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
804 ERR("Failed to set event rule tracepoint pattern.");
809 if (filter_expression
) {
810 status
= lttng_event_rule_tracepoint_set_filter(
811 rule
, filter_expression
);
812 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
813 ERR("Failed to set event rule tracepoint pattern.");
824 lttng_event_rule_destroy(rule
);
828 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
829 struct lttng_event_rule
*rule
, const char *pattern
)
831 char *pattern_copy
= NULL
;
832 struct lttng_event_rule_tracepoint
*tracepoint
;
833 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
835 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
836 strlen(pattern
) == 0) {
837 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
841 tracepoint
= container_of(
842 rule
, struct lttng_event_rule_tracepoint
, parent
);
843 pattern_copy
= strdup(pattern
);
845 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
849 free(tracepoint
->pattern
);
851 tracepoint
->pattern
= pattern_copy
;
857 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
858 const struct lttng_event_rule
*rule
, const char **pattern
)
860 struct lttng_event_rule_tracepoint
*tracepoint
;
861 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
863 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
864 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
868 tracepoint
= container_of(
869 rule
, struct lttng_event_rule_tracepoint
, parent
);
870 if (!tracepoint
->pattern
) {
871 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
875 *pattern
= tracepoint
->pattern
;
880 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
881 const struct lttng_event_rule
*rule
,
882 enum lttng_domain_type
*type
)
884 struct lttng_event_rule_tracepoint
*tracepoint
;
885 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
887 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
888 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
892 tracepoint
= container_of(
893 rule
, struct lttng_event_rule_tracepoint
, parent
);
894 *type
= tracepoint
->domain
;
899 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
900 struct lttng_event_rule
*rule
, const char *expression
)
902 char *expression_copy
= NULL
;
903 struct lttng_event_rule_tracepoint
*tracepoint
;
904 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
906 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
907 strlen(expression
) == 0) {
908 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
912 tracepoint
= container_of(
913 rule
, struct lttng_event_rule_tracepoint
, parent
);
914 expression_copy
= strdup(expression
);
915 if (!expression_copy
) {
916 PERROR("Failed to copy filter expression");
917 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
921 if (tracepoint
->filter_expression
) {
922 free(tracepoint
->filter_expression
);
925 tracepoint
->filter_expression
= expression_copy
;
926 expression_copy
= NULL
;
931 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
932 const struct lttng_event_rule
*rule
, const char **expression
)
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
) || !expression
) {
938 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
942 tracepoint
= container_of(
943 rule
, struct lttng_event_rule_tracepoint
, parent
);
944 if (!tracepoint
->filter_expression
) {
945 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
949 *expression
= tracepoint
->filter_expression
;
954 static bool log_level_value_valid(
955 int level
, enum lttng_domain_type domain
)
960 case LTTNG_DOMAIN_KERNEL
:
961 case LTTNG_DOMAIN_UST
:
962 if (level
< LTTNG_LOGLEVEL_EMERG
) {
966 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
973 case LTTNG_DOMAIN_JUL
:
974 case LTTNG_DOMAIN_LOG4J
:
975 case LTTNG_DOMAIN_PYTHON
:
977 * For both JUL and LOG4J custom log level are possible and can
978 * spawn the entire int32 range.
979 * For python, custom log level are possible, it is not clear if
980 * negative value are accepted (NOTSET == 0) but the source code
981 * validate against the int type implying that negative values
987 case LTTNG_DOMAIN_NONE
:
996 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
997 struct lttng_event_rule
*rule
, int level
)
999 struct lttng_event_rule_tracepoint
*tracepoint
;
1000 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1002 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1003 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1007 tracepoint
= container_of(
1008 rule
, struct lttng_event_rule_tracepoint
, parent
);
1010 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1011 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1015 tracepoint
->loglevel
.value
= level
;
1016 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
1021 enum lttng_event_rule_status
1022 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
1023 struct lttng_event_rule
*rule
, int level
)
1025 struct lttng_event_rule_tracepoint
*tracepoint
;
1026 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1028 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1029 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1033 tracepoint
= container_of(
1034 rule
, struct lttng_event_rule_tracepoint
, parent
);
1036 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1037 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1041 tracepoint
->loglevel
.value
= level
;
1042 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1047 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
1048 struct lttng_event_rule
*rule
)
1050 struct lttng_event_rule_tracepoint
*tracepoint
;
1051 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1053 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1054 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1058 tracepoint
= container_of(
1059 rule
, struct lttng_event_rule_tracepoint
, parent
);
1060 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1065 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1066 const struct lttng_event_rule
*rule
,
1067 enum lttng_loglevel_type
*type
)
1069 struct lttng_event_rule_tracepoint
*tracepoint
;
1070 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1072 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1073 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1077 tracepoint
= container_of(
1078 rule
, struct lttng_event_rule_tracepoint
, parent
);
1079 *type
= tracepoint
->loglevel
.type
;
1084 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1085 const struct lttng_event_rule
*rule
, int *level
)
1087 struct lttng_event_rule_tracepoint
*tracepoint
;
1088 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1090 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1091 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1095 tracepoint
= container_of(
1096 rule
, struct lttng_event_rule_tracepoint
, parent
);
1097 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1098 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1102 *level
= tracepoint
->loglevel
.value
;
1107 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1108 struct lttng_event_rule
*rule
,
1109 const char *exclusion
)
1112 char *exclusion_copy
= NULL
;
1113 struct lttng_event_rule_tracepoint
*tracepoint
;
1114 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1115 enum lttng_domain_type domain_type
;
1117 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1119 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1123 tracepoint
= container_of(
1124 rule
, struct lttng_event_rule_tracepoint
, parent
);
1126 status
= lttng_event_rule_tracepoint_get_domain_type(
1127 rule
, &domain_type
);
1128 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1132 switch (domain_type
) {
1133 case LTTNG_DOMAIN_KERNEL
:
1134 case LTTNG_DOMAIN_JUL
:
1135 case LTTNG_DOMAIN_LOG4J
:
1136 case LTTNG_DOMAIN_PYTHON
:
1137 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1139 case LTTNG_DOMAIN_UST
:
1140 /* Exclusions supported. */
1146 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1147 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1151 exclusion_copy
= strdup(exclusion
);
1152 if (!exclusion_copy
) {
1153 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1157 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1160 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1164 exclusion_copy
= NULL
;
1166 free(exclusion_copy
);
1170 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1171 const struct lttng_event_rule
*rule
, unsigned int *count
)
1173 struct lttng_event_rule_tracepoint
*tracepoint
;
1174 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1176 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1177 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1181 tracepoint
= container_of(
1182 rule
, struct lttng_event_rule_tracepoint
, parent
);
1183 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1188 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1189 const struct lttng_event_rule
*rule
,
1191 const char **exclusion
)
1194 struct lttng_event_rule_tracepoint
*tracepoint
;
1195 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1197 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1198 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1202 tracepoint
= container_of(
1203 rule
, struct lttng_event_rule_tracepoint
, parent
);
1204 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1205 LTTNG_EVENT_RULE_STATUS_OK
) {
1209 if (index
>= count
) {
1213 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1214 &tracepoint
->exclusions
, index
);