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>
19 #include <lttng/event.h>
21 #define IS_TRACEPOINT_EVENT_RULE(rule) \
22 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
24 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule
*rule
)
26 struct lttng_event_rule_tracepoint
*tracepoint
;
32 tracepoint
= container_of(
33 rule
, struct lttng_event_rule_tracepoint
, parent
);
35 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
36 free(tracepoint
->pattern
);
37 free(tracepoint
->filter_expression
);
38 free(tracepoint
->internal_filter
.filter
);
39 free(tracepoint
->internal_filter
.bytecode
);
43 static bool lttng_event_rule_tracepoint_validate(
44 const struct lttng_event_rule
*rule
)
47 struct lttng_event_rule_tracepoint
*tracepoint
;
53 tracepoint
= container_of(
54 rule
, struct lttng_event_rule_tracepoint
, parent
);
57 if (!tracepoint
->pattern
) {
58 ERR("Invalid tracepoint event rule: a pattern must be set.");
63 if (tracepoint
->domain
== LTTNG_DOMAIN_NONE
) {
64 ERR("Invalid tracepoint event rule: a domain must be set.");
73 static int lttng_event_rule_tracepoint_serialize(
74 const struct lttng_event_rule
*rule
,
75 struct lttng_payload
*payload
)
78 size_t pattern_len
, filter_expression_len
, exclusions_len
;
79 struct lttng_event_rule_tracepoint
*tracepoint
;
80 struct lttng_event_rule_tracepoint_comm tracepoint_comm
;
81 enum lttng_event_rule_status status
;
82 unsigned int exclusion_count
;
83 size_t exclusions_appended_len
= 0;
85 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
90 DBG("Serializing tracepoint event rule.");
91 tracepoint
= container_of(
92 rule
, struct lttng_event_rule_tracepoint
, parent
);
94 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
, &exclusion_count
);
95 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
97 pattern_len
= strlen(tracepoint
->pattern
) + 1;
99 if (tracepoint
->filter_expression
!= NULL
) {
100 filter_expression_len
=
101 strlen(tracepoint
->filter_expression
) + 1;
103 filter_expression_len
= 0;
107 for (i
= 0; i
< exclusion_count
; i
++) {
108 const char *exclusion
;
110 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
111 rule
, i
, &exclusion
);
112 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
115 exclusions_len
+= sizeof(uint32_t);
116 /* Payload (null terminated). */
117 exclusions_len
+= strlen(exclusion
) + 1;
120 tracepoint_comm
.domain_type
= (int8_t) tracepoint
->domain
;
121 tracepoint_comm
.loglevel_type
= (int8_t) tracepoint
->loglevel
.type
;
122 tracepoint_comm
.loglevel_value
= tracepoint
->loglevel
.value
;
123 tracepoint_comm
.pattern_len
= pattern_len
;
124 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
125 tracepoint_comm
.exclusions_count
= exclusion_count
;
126 tracepoint_comm
.exclusions_len
= exclusions_len
;
128 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
129 sizeof(tracepoint_comm
));
134 ret
= lttng_dynamic_buffer_append(
135 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
140 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
141 filter_expression_len
);
146 for (i
= 0; i
< exclusion_count
; i
++) {
148 const char *exclusion
;
150 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
151 rule
, i
, &exclusion
);
152 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
154 len
= strlen(exclusion
) + 1;
155 /* Append exclusion length, includes the null terminator. */
156 ret
= lttng_dynamic_buffer_append(
157 &payload
->buffer
, &len
, sizeof(uint32_t));
162 exclusions_appended_len
+= sizeof(uint32_t);
164 /* Include the '\0' in the payload. */
165 ret
= lttng_dynamic_buffer_append(
166 &payload
->buffer
, exclusion
, len
);
171 exclusions_appended_len
+= len
;
174 assert(exclusions_len
== exclusions_appended_len
);
180 static bool lttng_event_rule_tracepoint_is_equal(
181 const struct lttng_event_rule
*_a
,
182 const struct lttng_event_rule
*_b
)
185 bool is_equal
= false;
186 struct lttng_event_rule_tracepoint
*a
, *b
;
187 unsigned int count_a
, count_b
;
188 enum lttng_event_rule_status status
;
190 a
= container_of(_a
, struct lttng_event_rule_tracepoint
, parent
);
191 b
= container_of(_b
, struct lttng_event_rule_tracepoint
, parent
);
193 status
= lttng_event_rule_tracepoint_get_exclusions_count(_a
, &count_a
);
194 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
195 status
= lttng_event_rule_tracepoint_get_exclusions_count(_b
, &count_b
);
196 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
199 if (a
->domain
!= b
->domain
) {
203 if (count_a
!= count_b
) {
207 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
214 if (strcmp(a
->pattern
, b
->pattern
)) {
218 if (a
->filter_expression
&& b
->filter_expression
) {
219 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
222 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
223 /* One is set; not the other. */
227 if (a
->loglevel
.type
!= b
->loglevel
.type
) {
231 if (a
->loglevel
.value
!= b
->loglevel
.value
) {
235 for (i
= 0; i
< count_a
; i
++) {
236 const char *exclusion_a
, *exclusion_b
;
238 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
239 _a
, i
, &exclusion_a
);
240 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
241 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
242 _b
, i
, &exclusion_b
);
243 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
244 if (strcmp(exclusion_a
, exclusion_b
)) {
255 * On success ret is 0;
257 * On error ret is negative.
259 * An event with NO loglevel and the name is * will return NULL.
261 static int generate_agent_filter(
262 const struct lttng_event_rule
*rule
, char **_agent_filter
)
266 char *agent_filter
= NULL
;
269 enum lttng_loglevel_type loglevel_type
;
270 enum lttng_event_rule_status status
;
273 assert(_agent_filter
);
275 status
= lttng_event_rule_tracepoint_get_pattern(rule
, &pattern
);
276 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
281 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
282 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
284 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
289 status
= lttng_event_rule_tracepoint_get_log_level_type(
290 rule
, &loglevel_type
);
291 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
296 /* Don't add filter for the '*' event. */
297 if (strcmp(pattern
, "*") != 0) {
299 err
= asprintf(&agent_filter
,
300 "(%s) && (logger_name == \"%s\")",
303 err
= asprintf(&agent_filter
, "logger_name == \"%s\"",
308 PERROR("Failed to format agent filter string");
314 if (loglevel_type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
318 status
= lttng_event_rule_tracepoint_get_log_level(
319 rule
, &loglevel_value
);
320 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
325 if (loglevel_type
== LTTNG_EVENT_LOGLEVEL_RANGE
) {
331 if (filter
|| agent_filter
) {
334 err
= asprintf(&new_filter
,
335 "(%s) && (int_loglevel %s %d)",
336 agent_filter
? agent_filter
: filter
,
341 agent_filter
= new_filter
;
343 err
= asprintf(&agent_filter
, "int_loglevel %s %d", op
,
348 PERROR("Failed to format agent filter string");
354 *_agent_filter
= agent_filter
;
362 static enum lttng_error_code
363 lttng_event_rule_tracepoint_generate_filter_bytecode(
364 struct lttng_event_rule
*rule
,
365 const struct lttng_credentials
*creds
)
368 enum lttng_error_code ret_code
;
369 struct lttng_event_rule_tracepoint
*tracepoint
;
370 enum lttng_domain_type domain_type
;
371 enum lttng_event_rule_status status
;
373 struct lttng_filter_bytecode
*bytecode
= NULL
;
377 tracepoint
= container_of(
378 rule
, struct lttng_event_rule_tracepoint
, parent
);
380 status
= lttng_event_rule_tracepoint_get_filter(rule
, &filter
);
381 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
383 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
384 ret_code
= LTTNG_ERR_FILTER_INVAL
;
388 if (filter
&& filter
[0] == '\0') {
389 ret_code
= LTTNG_ERR_FILTER_INVAL
;
393 status
= lttng_event_rule_tracepoint_get_domain_type(
395 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
396 ret_code
= LTTNG_ERR_UNK
;
400 switch (domain_type
) {
401 case LTTNG_DOMAIN_LOG4J
:
402 case LTTNG_DOMAIN_JUL
:
403 case LTTNG_DOMAIN_PYTHON
:
407 ret
= generate_agent_filter(rule
, &agent_filter
);
409 ret_code
= LTTNG_ERR_FILTER_INVAL
;
413 tracepoint
->internal_filter
.filter
= agent_filter
;
419 tracepoint
->internal_filter
.filter
= strdup(filter
);
420 if (tracepoint
->internal_filter
.filter
== NULL
) {
421 ret_code
= LTTNG_ERR_NOMEM
;
425 tracepoint
->internal_filter
.filter
= NULL
;
431 if (tracepoint
->internal_filter
.filter
== NULL
) {
436 ret
= run_as_generate_filter_bytecode(
437 tracepoint
->internal_filter
.filter
, creds
,
440 ret_code
= LTTNG_ERR_FILTER_INVAL
;
444 tracepoint
->internal_filter
.bytecode
= bytecode
;
454 static const char *lttng_event_rule_tracepoint_get_internal_filter(
455 const struct lttng_event_rule
*rule
)
457 struct lttng_event_rule_tracepoint
*tracepoint
;
460 tracepoint
= container_of(
461 rule
, struct lttng_event_rule_tracepoint
, parent
);
462 return tracepoint
->internal_filter
.filter
;
465 static const struct lttng_filter_bytecode
*
466 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
467 const struct lttng_event_rule
*rule
)
469 struct lttng_event_rule_tracepoint
*tracepoint
;
472 tracepoint
= container_of(
473 rule
, struct lttng_event_rule_tracepoint
, parent
);
474 return tracepoint
->internal_filter
.bytecode
;
477 static enum lttng_event_rule_generate_exclusions_status
478 lttng_event_rule_tracepoint_generate_exclusions(
479 const struct lttng_event_rule
*rule
,
480 struct lttng_event_exclusion
**_exclusions
)
482 unsigned int nb_exclusions
= 0, i
;
483 enum lttng_domain_type domain_type
;
484 struct lttng_event_exclusion
*exclusions
;
485 enum lttng_event_rule_status event_rule_status
;
486 enum lttng_event_rule_generate_exclusions_status ret_status
;
490 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
492 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
494 switch (domain_type
) {
495 case LTTNG_DOMAIN_KERNEL
:
496 case LTTNG_DOMAIN_JUL
:
497 case LTTNG_DOMAIN_LOG4J
:
498 case LTTNG_DOMAIN_PYTHON
:
501 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
503 case LTTNG_DOMAIN_UST
:
504 /* Exclusions supported. */
507 /* Unknown domain. */
511 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
512 rule
, &nb_exclusions
);
513 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
514 if (nb_exclusions
== 0) {
517 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
521 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
522 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
524 PERROR("Failed to allocate exclusions buffer");
525 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
529 exclusions
->count
= nb_exclusions
;
530 for (i
= 0; i
< nb_exclusions
; i
++) {
532 const char *exclusion_str
;
535 lttng_event_rule_tracepoint_get_exclusion_at_index(
536 rule
, i
, &exclusion_str
);
537 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
539 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
540 LTTNG_SYMBOL_NAME_LEN
);
544 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
549 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
552 *_exclusions
= exclusions
;
556 static void destroy_lttng_exclusions_element(void *ptr
)
561 static unsigned long lttng_event_rule_tracepoint_hash(
562 const struct lttng_event_rule
*rule
)
565 unsigned int i
, exclusion_count
;
566 enum lttng_event_rule_status status
;
567 struct lttng_event_rule_tracepoint
*tp_rule
=
568 container_of(rule
, typeof(*tp_rule
), parent
);
570 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_TRACEPOINT
,
572 hash
^= hash_key_ulong((void *) tp_rule
->domain
, lttng_ht_seed
);
573 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
575 if (tp_rule
->filter_expression
) {
576 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
579 hash
^= hash_key_ulong((void *) tp_rule
->loglevel
.type
,
581 if (tp_rule
->loglevel
.type
!= LTTNG_EVENT_LOGLEVEL_ALL
) {
582 hash
^= hash_key_ulong(
583 (void *) (unsigned long) tp_rule
->loglevel
.value
,
587 status
= lttng_event_rule_tracepoint_get_exclusions_count(rule
,
589 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
591 for (i
= 0; i
< exclusion_count
; i
++) {
592 const char *exclusion
;
594 status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
595 rule
, i
, &exclusion
);
596 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
597 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
603 static struct lttng_event
*lttng_event_rule_tracepoint_generate_lttng_event(
604 const struct lttng_event_rule
*rule
)
607 const struct lttng_event_rule_tracepoint
*tracepoint
;
608 struct lttng_event
*local_event
= NULL
;
609 struct lttng_event
*event
= NULL
;
611 tracepoint
= container_of(
612 rule
, const struct lttng_event_rule_tracepoint
, parent
);
614 local_event
= zmalloc(sizeof(*local_event
));
619 local_event
->type
= LTTNG_EVENT_TRACEPOINT
;
620 ret
= lttng_strncpy(local_event
->name
, tracepoint
->pattern
,
621 sizeof(local_event
->name
));
623 ERR("Truncation occurred when copying event rule pattern to `lttng_event` structure: pattern = '%s'",
624 tracepoint
->pattern
);
628 local_event
->loglevel_type
= tracepoint
->loglevel
.type
;
629 local_event
->loglevel
= tracepoint
->loglevel
.value
;
638 struct lttng_event_rule
*lttng_event_rule_tracepoint_create(
639 enum lttng_domain_type domain_type
)
641 struct lttng_event_rule
*rule
= NULL
;
642 struct lttng_event_rule_tracepoint
*tp_rule
;
644 if (domain_type
== LTTNG_DOMAIN_NONE
) {
648 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
653 rule
= &tp_rule
->parent
;
654 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
655 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
656 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
657 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
658 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
659 tp_rule
->parent
.generate_filter_bytecode
=
660 lttng_event_rule_tracepoint_generate_filter_bytecode
;
661 tp_rule
->parent
.get_filter
=
662 lttng_event_rule_tracepoint_get_internal_filter
;
663 tp_rule
->parent
.get_filter_bytecode
=
664 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
665 tp_rule
->parent
.generate_exclusions
=
666 lttng_event_rule_tracepoint_generate_exclusions
;
667 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
668 tp_rule
->parent
.generate_lttng_event
=
669 lttng_event_rule_tracepoint_generate_lttng_event
;
671 tp_rule
->domain
= domain_type
;
672 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
674 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
675 destroy_lttng_exclusions_element
);
681 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
682 struct lttng_payload_view
*view
,
683 struct lttng_event_rule
**_event_rule
)
685 ssize_t ret
, offset
= 0;
687 enum lttng_event_rule_status status
;
688 enum lttng_domain_type domain_type
;
689 enum lttng_loglevel_type loglevel_type
;
690 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
692 const char *filter_expression
= NULL
;
693 const char **exclusions
= NULL
;
694 const uint32_t *exclusion_len
;
695 const char *exclusion
;
696 struct lttng_buffer_view current_buffer_view
;
697 struct lttng_event_rule
*rule
= NULL
;
704 current_buffer_view
= lttng_buffer_view_from_view(
705 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
706 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
707 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
712 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
714 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
715 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
716 /* Invalid domain value. */
717 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
718 (int) tracepoint_comm
->domain_type
);
723 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
724 rule
= lttng_event_rule_tracepoint_create(domain_type
);
726 ERR("Failed to create event rule tracepoint.");
731 loglevel_type
= (enum lttng_loglevel_type
)
732 tracepoint_comm
->loglevel_type
;
733 switch (loglevel_type
) {
734 case LTTNG_EVENT_LOGLEVEL_ALL
:
735 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
737 case LTTNG_EVENT_LOGLEVEL_RANGE
:
738 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
739 (enum lttng_loglevel_type
) tracepoint_comm
742 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
743 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
744 (enum lttng_loglevel_type
) tracepoint_comm
748 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
753 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
754 ERR("Failed to set event rule tracepoint loglevel.");
757 /* Skip to payload. */
758 offset
+= current_buffer_view
.size
;
760 /* Map the pattern. */
761 current_buffer_view
= lttng_buffer_view_from_view(
762 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
764 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
769 pattern
= current_buffer_view
.data
;
770 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
771 tracepoint_comm
->pattern_len
)) {
776 /* Skip after the pattern. */
777 offset
+= tracepoint_comm
->pattern_len
;
779 if (!tracepoint_comm
->filter_expression_len
) {
780 goto skip_filter_expression
;
783 /* Map the filter_expression. */
784 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
785 tracepoint_comm
->filter_expression_len
);
786 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
791 filter_expression
= current_buffer_view
.data
;
792 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
794 tracepoint_comm
->filter_expression_len
)) {
799 /* Skip after the pattern. */
800 offset
+= tracepoint_comm
->filter_expression_len
;
802 skip_filter_expression
:
803 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
804 current_buffer_view
= lttng_buffer_view_from_view(
805 &view
->buffer
, offset
, sizeof(*exclusion_len
));
806 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
811 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
812 offset
+= sizeof(*exclusion_len
);
814 current_buffer_view
= lttng_buffer_view_from_view(
815 &view
->buffer
, offset
, *exclusion_len
);
816 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
821 exclusion
= current_buffer_view
.data
;
822 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
823 exclusion
, *exclusion_len
)) {
828 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
829 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
830 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
836 /* Skip to next exclusion. */
837 offset
+= *exclusion_len
;
840 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
841 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
842 ERR("Failed to set event rule tracepoint pattern.");
847 if (filter_expression
) {
848 status
= lttng_event_rule_tracepoint_set_filter(
849 rule
, filter_expression
);
850 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
851 ERR("Failed to set event rule tracepoint pattern.");
862 lttng_event_rule_destroy(rule
);
866 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
867 struct lttng_event_rule
*rule
, const char *pattern
)
869 char *pattern_copy
= NULL
;
870 struct lttng_event_rule_tracepoint
*tracepoint
;
871 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
873 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
874 strlen(pattern
) == 0) {
875 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
879 tracepoint
= container_of(
880 rule
, struct lttng_event_rule_tracepoint
, parent
);
881 pattern_copy
= strdup(pattern
);
883 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
887 free(tracepoint
->pattern
);
889 tracepoint
->pattern
= pattern_copy
;
895 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
896 const struct lttng_event_rule
*rule
, const char **pattern
)
898 struct lttng_event_rule_tracepoint
*tracepoint
;
899 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
901 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
902 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
906 tracepoint
= container_of(
907 rule
, struct lttng_event_rule_tracepoint
, parent
);
908 if (!tracepoint
->pattern
) {
909 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
913 *pattern
= tracepoint
->pattern
;
918 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
919 const struct lttng_event_rule
*rule
,
920 enum lttng_domain_type
*type
)
922 struct lttng_event_rule_tracepoint
*tracepoint
;
923 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
925 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
926 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
930 tracepoint
= container_of(
931 rule
, struct lttng_event_rule_tracepoint
, parent
);
932 *type
= tracepoint
->domain
;
937 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
938 struct lttng_event_rule
*rule
, const char *expression
)
940 char *expression_copy
= NULL
;
941 struct lttng_event_rule_tracepoint
*tracepoint
;
942 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
944 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
945 strlen(expression
) == 0) {
946 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
950 tracepoint
= container_of(
951 rule
, struct lttng_event_rule_tracepoint
, parent
);
952 expression_copy
= strdup(expression
);
953 if (!expression_copy
) {
954 PERROR("Failed to copy filter expression");
955 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
959 if (tracepoint
->filter_expression
) {
960 free(tracepoint
->filter_expression
);
963 tracepoint
->filter_expression
= expression_copy
;
964 expression_copy
= NULL
;
969 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
970 const struct lttng_event_rule
*rule
, const char **expression
)
972 struct lttng_event_rule_tracepoint
*tracepoint
;
973 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
975 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
976 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
980 tracepoint
= container_of(
981 rule
, struct lttng_event_rule_tracepoint
, parent
);
982 if (!tracepoint
->filter_expression
) {
983 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
987 *expression
= tracepoint
->filter_expression
;
992 static bool log_level_value_valid(
993 int level
, enum lttng_domain_type domain
)
998 case LTTNG_DOMAIN_KERNEL
:
999 case LTTNG_DOMAIN_UST
:
1000 if (level
< LTTNG_LOGLEVEL_EMERG
) {
1004 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
1011 case LTTNG_DOMAIN_JUL
:
1012 case LTTNG_DOMAIN_LOG4J
:
1013 case LTTNG_DOMAIN_PYTHON
:
1015 * For both JUL and LOG4J custom log level are possible and can
1016 * spawn the entire int32 range.
1017 * For python, custom log level are possible, it is not clear if
1018 * negative value are accepted (NOTSET == 0) but the source code
1019 * validate against the int type implying that negative values
1025 case LTTNG_DOMAIN_NONE
:
1034 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
1035 struct lttng_event_rule
*rule
, int level
)
1037 struct lttng_event_rule_tracepoint
*tracepoint
;
1038 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1040 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1041 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1045 tracepoint
= container_of(
1046 rule
, struct lttng_event_rule_tracepoint
, parent
);
1048 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1049 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1053 tracepoint
->loglevel
.value
= level
;
1054 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
1059 enum lttng_event_rule_status
1060 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
1061 struct lttng_event_rule
*rule
, int level
)
1063 struct lttng_event_rule_tracepoint
*tracepoint
;
1064 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1066 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1067 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1071 tracepoint
= container_of(
1072 rule
, struct lttng_event_rule_tracepoint
, parent
);
1074 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1075 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1079 tracepoint
->loglevel
.value
= level
;
1080 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1085 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
1086 struct lttng_event_rule
*rule
)
1088 struct lttng_event_rule_tracepoint
*tracepoint
;
1089 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1091 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1092 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1096 tracepoint
= container_of(
1097 rule
, struct lttng_event_rule_tracepoint
, parent
);
1098 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1103 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1104 const struct lttng_event_rule
*rule
,
1105 enum lttng_loglevel_type
*type
)
1107 struct lttng_event_rule_tracepoint
*tracepoint
;
1108 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1110 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1111 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1115 tracepoint
= container_of(
1116 rule
, struct lttng_event_rule_tracepoint
, parent
);
1117 *type
= tracepoint
->loglevel
.type
;
1122 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1123 const struct lttng_event_rule
*rule
, int *level
)
1125 struct lttng_event_rule_tracepoint
*tracepoint
;
1126 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1128 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1129 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1133 tracepoint
= container_of(
1134 rule
, struct lttng_event_rule_tracepoint
, parent
);
1135 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1136 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1140 *level
= tracepoint
->loglevel
.value
;
1145 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1146 struct lttng_event_rule
*rule
,
1147 const char *exclusion
)
1150 char *exclusion_copy
= NULL
;
1151 struct lttng_event_rule_tracepoint
*tracepoint
;
1152 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1153 enum lttng_domain_type domain_type
;
1155 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1157 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1161 tracepoint
= container_of(
1162 rule
, struct lttng_event_rule_tracepoint
, parent
);
1164 status
= lttng_event_rule_tracepoint_get_domain_type(
1165 rule
, &domain_type
);
1166 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1170 switch (domain_type
) {
1171 case LTTNG_DOMAIN_KERNEL
:
1172 case LTTNG_DOMAIN_JUL
:
1173 case LTTNG_DOMAIN_LOG4J
:
1174 case LTTNG_DOMAIN_PYTHON
:
1175 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1177 case LTTNG_DOMAIN_UST
:
1178 /* Exclusions supported. */
1184 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1185 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1189 exclusion_copy
= strdup(exclusion
);
1190 if (!exclusion_copy
) {
1191 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1195 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1198 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1202 exclusion_copy
= NULL
;
1204 free(exclusion_copy
);
1208 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1209 const struct lttng_event_rule
*rule
, unsigned int *count
)
1211 struct lttng_event_rule_tracepoint
*tracepoint
;
1212 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1214 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1215 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1219 tracepoint
= container_of(
1220 rule
, struct lttng_event_rule_tracepoint
, parent
);
1221 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1226 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1227 const struct lttng_event_rule
*rule
,
1229 const char **exclusion
)
1232 struct lttng_event_rule_tracepoint
*tracepoint
;
1233 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1235 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1236 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1240 tracepoint
= container_of(
1241 rule
, struct lttng_event_rule_tracepoint
, parent
);
1242 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1243 LTTNG_EVENT_RULE_STATUS_OK
) {
1247 if (index
>= count
) {
1251 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1252 &tracepoint
->exclusions
, index
);