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_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_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
;
643 enum lttng_event_rule_status status
;
645 if (domain_type
== LTTNG_DOMAIN_NONE
) {
649 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_tracepoint
));
654 rule
= &tp_rule
->parent
;
655 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_TRACEPOINT
);
656 tp_rule
->parent
.validate
= lttng_event_rule_tracepoint_validate
;
657 tp_rule
->parent
.serialize
= lttng_event_rule_tracepoint_serialize
;
658 tp_rule
->parent
.equal
= lttng_event_rule_tracepoint_is_equal
;
659 tp_rule
->parent
.destroy
= lttng_event_rule_tracepoint_destroy
;
660 tp_rule
->parent
.generate_filter_bytecode
=
661 lttng_event_rule_tracepoint_generate_filter_bytecode
;
662 tp_rule
->parent
.get_filter
=
663 lttng_event_rule_tracepoint_get_internal_filter
;
664 tp_rule
->parent
.get_filter_bytecode
=
665 lttng_event_rule_tracepoint_get_internal_filter_bytecode
;
666 tp_rule
->parent
.generate_exclusions
=
667 lttng_event_rule_tracepoint_generate_exclusions
;
668 tp_rule
->parent
.hash
= lttng_event_rule_tracepoint_hash
;
669 tp_rule
->parent
.generate_lttng_event
=
670 lttng_event_rule_tracepoint_generate_lttng_event
;
672 tp_rule
->domain
= domain_type
;
673 tp_rule
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
675 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
676 destroy_lttng_exclusions_element
);
678 /* Default pattern is '*'. */
679 status
= lttng_event_rule_tracepoint_set_pattern(rule
, "*");
680 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
681 lttng_event_rule_destroy(rule
);
690 ssize_t
lttng_event_rule_tracepoint_create_from_payload(
691 struct lttng_payload_view
*view
,
692 struct lttng_event_rule
**_event_rule
)
694 ssize_t ret
, offset
= 0;
696 enum lttng_event_rule_status status
;
697 enum lttng_domain_type domain_type
;
698 enum lttng_loglevel_type loglevel_type
;
699 const struct lttng_event_rule_tracepoint_comm
*tracepoint_comm
;
701 const char *filter_expression
= NULL
;
702 const char **exclusions
= NULL
;
703 const uint32_t *exclusion_len
;
704 const char *exclusion
;
705 struct lttng_buffer_view current_buffer_view
;
706 struct lttng_event_rule
*rule
= NULL
;
713 current_buffer_view
= lttng_buffer_view_from_view(
714 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
715 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
716 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
721 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
723 if (tracepoint_comm
->domain_type
<= LTTNG_DOMAIN_NONE
||
724 tracepoint_comm
->domain_type
> LTTNG_DOMAIN_PYTHON
) {
725 /* Invalid domain value. */
726 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
727 (int) tracepoint_comm
->domain_type
);
732 domain_type
= (enum lttng_domain_type
) tracepoint_comm
->domain_type
;
733 rule
= lttng_event_rule_tracepoint_create(domain_type
);
735 ERR("Failed to create event rule tracepoint.");
740 loglevel_type
= (enum lttng_loglevel_type
)
741 tracepoint_comm
->loglevel_type
;
742 switch (loglevel_type
) {
743 case LTTNG_EVENT_LOGLEVEL_ALL
:
744 status
= lttng_event_rule_tracepoint_set_log_level_all(rule
);
746 case LTTNG_EVENT_LOGLEVEL_RANGE
:
747 status
= lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule
,
748 (enum lttng_loglevel_type
) tracepoint_comm
751 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
752 status
= lttng_event_rule_tracepoint_set_log_level(rule
,
753 (enum lttng_loglevel_type
) tracepoint_comm
757 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
762 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
763 ERR("Failed to set event rule tracepoint loglevel.");
766 /* Skip to payload. */
767 offset
+= current_buffer_view
.size
;
769 /* Map the pattern. */
770 current_buffer_view
= lttng_buffer_view_from_view(
771 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
773 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
778 pattern
= current_buffer_view
.data
;
779 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
780 tracepoint_comm
->pattern_len
)) {
785 /* Skip after the pattern. */
786 offset
+= tracepoint_comm
->pattern_len
;
788 if (!tracepoint_comm
->filter_expression_len
) {
789 goto skip_filter_expression
;
792 /* Map the filter_expression. */
793 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
794 tracepoint_comm
->filter_expression_len
);
795 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
800 filter_expression
= current_buffer_view
.data
;
801 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
803 tracepoint_comm
->filter_expression_len
)) {
808 /* Skip after the pattern. */
809 offset
+= tracepoint_comm
->filter_expression_len
;
811 skip_filter_expression
:
812 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
813 current_buffer_view
= lttng_buffer_view_from_view(
814 &view
->buffer
, offset
, sizeof(*exclusion_len
));
815 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
820 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
821 offset
+= sizeof(*exclusion_len
);
823 current_buffer_view
= lttng_buffer_view_from_view(
824 &view
->buffer
, offset
, *exclusion_len
);
825 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
830 exclusion
= current_buffer_view
.data
;
831 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
832 exclusion
, *exclusion_len
)) {
837 status
= lttng_event_rule_tracepoint_add_exclusion(rule
, exclusion
);
838 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
839 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
845 /* Skip to next exclusion. */
846 offset
+= *exclusion_len
;
849 status
= lttng_event_rule_tracepoint_set_pattern(rule
, pattern
);
850 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
851 ERR("Failed to set event rule tracepoint pattern.");
856 if (filter_expression
) {
857 status
= lttng_event_rule_tracepoint_set_filter(
858 rule
, filter_expression
);
859 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
860 ERR("Failed to set event rule tracepoint pattern.");
871 lttng_event_rule_destroy(rule
);
875 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_pattern(
876 struct lttng_event_rule
*rule
, const char *pattern
)
878 char *pattern_copy
= NULL
;
879 struct lttng_event_rule_tracepoint
*tracepoint
;
880 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
882 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
883 strlen(pattern
) == 0) {
884 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
888 tracepoint
= container_of(
889 rule
, struct lttng_event_rule_tracepoint
, parent
);
890 pattern_copy
= strdup(pattern
);
892 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
896 free(tracepoint
->pattern
);
898 tracepoint
->pattern
= pattern_copy
;
904 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_pattern(
905 const struct lttng_event_rule
*rule
, const char **pattern
)
907 struct lttng_event_rule_tracepoint
*tracepoint
;
908 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
910 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
911 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
915 tracepoint
= container_of(
916 rule
, struct lttng_event_rule_tracepoint
, parent
);
917 if (!tracepoint
->pattern
) {
918 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
922 *pattern
= tracepoint
->pattern
;
927 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_domain_type(
928 const struct lttng_event_rule
*rule
,
929 enum lttng_domain_type
*type
)
931 struct lttng_event_rule_tracepoint
*tracepoint
;
932 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
934 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
935 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
939 tracepoint
= container_of(
940 rule
, struct lttng_event_rule_tracepoint
, parent
);
941 *type
= tracepoint
->domain
;
946 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_filter(
947 struct lttng_event_rule
*rule
, const char *expression
)
949 char *expression_copy
= NULL
;
950 struct lttng_event_rule_tracepoint
*tracepoint
;
951 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
953 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
954 strlen(expression
) == 0) {
955 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
959 tracepoint
= container_of(
960 rule
, struct lttng_event_rule_tracepoint
, parent
);
961 expression_copy
= strdup(expression
);
962 if (!expression_copy
) {
963 PERROR("Failed to copy filter expression");
964 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
968 if (tracepoint
->filter_expression
) {
969 free(tracepoint
->filter_expression
);
972 tracepoint
->filter_expression
= expression_copy
;
973 expression_copy
= NULL
;
978 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_filter(
979 const struct lttng_event_rule
*rule
, const char **expression
)
981 struct lttng_event_rule_tracepoint
*tracepoint
;
982 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
984 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
985 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
989 tracepoint
= container_of(
990 rule
, struct lttng_event_rule_tracepoint
, parent
);
991 if (!tracepoint
->filter_expression
) {
992 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
996 *expression
= tracepoint
->filter_expression
;
1001 static bool log_level_value_valid(
1002 int level
, enum lttng_domain_type domain
)
1007 case LTTNG_DOMAIN_KERNEL
:
1008 case LTTNG_DOMAIN_UST
:
1009 if (level
< LTTNG_LOGLEVEL_EMERG
) {
1013 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
1020 case LTTNG_DOMAIN_JUL
:
1021 case LTTNG_DOMAIN_LOG4J
:
1022 case LTTNG_DOMAIN_PYTHON
:
1024 * For both JUL and LOG4J custom log level are possible and can
1025 * spawn the entire int32 range.
1026 * For python, custom log level are possible, it is not clear if
1027 * negative value are accepted (NOTSET == 0) but the source code
1028 * validate against the int type implying that negative values
1034 case LTTNG_DOMAIN_NONE
:
1043 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level(
1044 struct lttng_event_rule
*rule
, int level
)
1046 struct lttng_event_rule_tracepoint
*tracepoint
;
1047 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1049 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1050 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1054 tracepoint
= container_of(
1055 rule
, struct lttng_event_rule_tracepoint
, parent
);
1057 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1058 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1062 tracepoint
->loglevel
.value
= level
;
1063 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
1068 enum lttng_event_rule_status
1069 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
1070 struct lttng_event_rule
*rule
, int level
)
1072 struct lttng_event_rule_tracepoint
*tracepoint
;
1073 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1075 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1076 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1080 tracepoint
= container_of(
1081 rule
, struct lttng_event_rule_tracepoint
, parent
);
1083 if (!log_level_value_valid(level
, tracepoint
->domain
)) {
1084 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1088 tracepoint
->loglevel
.value
= level
;
1089 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1094 enum lttng_event_rule_status
lttng_event_rule_tracepoint_set_log_level_all(
1095 struct lttng_event_rule
*rule
)
1097 struct lttng_event_rule_tracepoint
*tracepoint
;
1098 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1100 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
)) {
1101 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1105 tracepoint
= container_of(
1106 rule
, struct lttng_event_rule_tracepoint
, parent
);
1107 tracepoint
->loglevel
.type
= LTTNG_EVENT_LOGLEVEL_ALL
;
1112 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level_type(
1113 const struct lttng_event_rule
*rule
,
1114 enum lttng_loglevel_type
*type
)
1116 struct lttng_event_rule_tracepoint
*tracepoint
;
1117 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1119 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !type
) {
1120 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1124 tracepoint
= container_of(
1125 rule
, struct lttng_event_rule_tracepoint
, parent
);
1126 *type
= tracepoint
->loglevel
.type
;
1131 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_log_level(
1132 const struct lttng_event_rule
*rule
, int *level
)
1134 struct lttng_event_rule_tracepoint
*tracepoint
;
1135 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1137 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !level
) {
1138 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1142 tracepoint
= container_of(
1143 rule
, struct lttng_event_rule_tracepoint
, parent
);
1144 if (tracepoint
->loglevel
.type
== LTTNG_EVENT_LOGLEVEL_ALL
) {
1145 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
1149 *level
= tracepoint
->loglevel
.value
;
1154 enum lttng_event_rule_status
lttng_event_rule_tracepoint_add_exclusion(
1155 struct lttng_event_rule
*rule
,
1156 const char *exclusion
)
1159 char *exclusion_copy
= NULL
;
1160 struct lttng_event_rule_tracepoint
*tracepoint
;
1161 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1162 enum lttng_domain_type domain_type
;
1164 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) ||
1166 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1170 tracepoint
= container_of(
1171 rule
, struct lttng_event_rule_tracepoint
, parent
);
1173 status
= lttng_event_rule_tracepoint_get_domain_type(
1174 rule
, &domain_type
);
1175 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
1179 switch (domain_type
) {
1180 case LTTNG_DOMAIN_KERNEL
:
1181 case LTTNG_DOMAIN_JUL
:
1182 case LTTNG_DOMAIN_LOG4J
:
1183 case LTTNG_DOMAIN_PYTHON
:
1184 status
= LTTNG_EVENT_RULE_STATUS_UNSUPPORTED
;
1186 case LTTNG_DOMAIN_UST
:
1187 /* Exclusions supported. */
1193 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1194 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1198 exclusion_copy
= strdup(exclusion
);
1199 if (!exclusion_copy
) {
1200 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1204 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1207 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1211 exclusion_copy
= NULL
;
1213 free(exclusion_copy
);
1217 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusions_count(
1218 const struct lttng_event_rule
*rule
, unsigned int *count
)
1220 struct lttng_event_rule_tracepoint
*tracepoint
;
1221 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1223 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1224 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1228 tracepoint
= container_of(
1229 rule
, struct lttng_event_rule_tracepoint
, parent
);
1230 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1235 enum lttng_event_rule_status
lttng_event_rule_tracepoint_get_exclusion_at_index(
1236 const struct lttng_event_rule
*rule
,
1238 const char **exclusion
)
1241 struct lttng_event_rule_tracepoint
*tracepoint
;
1242 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1244 if (!rule
|| !IS_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1245 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1249 tracepoint
= container_of(
1250 rule
, struct lttng_event_rule_tracepoint
, parent
);
1251 if (lttng_event_rule_tracepoint_get_exclusions_count(rule
, &count
) !=
1252 LTTNG_EVENT_RULE_STATUS_OK
) {
1256 if (index
>= count
) {
1260 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1261 &tracepoint
->exclusions
, index
);