Generate bytecodes related to the trigger on reception
[lttng-tools.git] / src / common / event-rule / tracepoint.c
1 /*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
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 <lttng/event-rule/event-rule-internal.h>
16 #include <lttng/event-rule/tracepoint-internal.h>
17
18 #define IS_TRACEPOINT_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT)
20
21 static void lttng_event_rule_tracepoint_destroy(struct lttng_event_rule *rule)
22 {
23 struct lttng_event_rule_tracepoint *tracepoint;
24
25 if (rule == NULL) {
26 return;
27 }
28
29 tracepoint = container_of(
30 rule, struct lttng_event_rule_tracepoint, parent);
31
32 lttng_dynamic_pointer_array_reset(&tracepoint->exclusions);
33 free(tracepoint->pattern);
34 free(tracepoint->filter_expression);
35 free(tracepoint->internal_filter.filter);
36 free(tracepoint->internal_filter.bytecode);
37 free(tracepoint);
38 }
39
40 static bool lttng_event_rule_tracepoint_validate(
41 const struct lttng_event_rule *rule)
42 {
43 bool valid = false;
44 struct lttng_event_rule_tracepoint *tracepoint;
45
46 if (!rule) {
47 goto end;
48 }
49
50 tracepoint = container_of(
51 rule, struct lttng_event_rule_tracepoint, parent);
52
53 /* Required field. */
54 if (!tracepoint->pattern) {
55 ERR("Invalid tracepoint event rule: a pattern must be set.");
56 goto end;
57 }
58
59 /* Required field. */
60 if (tracepoint->domain == LTTNG_DOMAIN_NONE) {
61 ERR("Invalid tracepoint event rule: a domain must be set.");
62 goto end;
63 }
64
65 valid = true;
66 end:
67 return valid;
68 }
69
70 static int lttng_event_rule_tracepoint_serialize(
71 const struct lttng_event_rule *rule,
72 struct lttng_payload *payload)
73 {
74 int ret, i;
75 size_t pattern_len, filter_expression_len, exclusions_len;
76 struct lttng_event_rule_tracepoint *tracepoint;
77 struct lttng_event_rule_tracepoint_comm tracepoint_comm;
78 enum lttng_event_rule_status status;
79 unsigned int exclusion_count;
80 size_t exclusions_appended_len = 0;
81
82 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
83 ret = -1;
84 goto end;
85 }
86
87 DBG("Serializing tracepoint event rule.");
88 tracepoint = container_of(
89 rule, struct lttng_event_rule_tracepoint, parent);
90
91 status = lttng_event_rule_tracepoint_get_exclusions_count(rule, &exclusion_count);
92 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
93
94 pattern_len = strlen(tracepoint->pattern) + 1;
95
96 if (tracepoint->filter_expression != NULL) {
97 filter_expression_len =
98 strlen(tracepoint->filter_expression) + 1;
99 } else {
100 filter_expression_len = 0;
101 }
102
103 exclusions_len = 0;
104 for (i = 0; i < exclusion_count; i++) {
105 const char *exclusion;
106
107 status = lttng_event_rule_tracepoint_get_exclusion_at_index(
108 rule, i, &exclusion);
109 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
110
111 /* Length field. */
112 exclusions_len += sizeof(uint32_t);
113 /* Payload (null terminated). */
114 exclusions_len += strlen(exclusion) + 1;
115 }
116
117 tracepoint_comm.domain_type = (int8_t) tracepoint->domain;
118 tracepoint_comm.loglevel_type = (int8_t) tracepoint->loglevel.type;
119 tracepoint_comm.loglevel_value = tracepoint->loglevel.value;
120 tracepoint_comm.pattern_len = pattern_len;
121 tracepoint_comm.filter_expression_len = filter_expression_len;
122 tracepoint_comm.exclusions_count = exclusion_count;
123 tracepoint_comm.exclusions_len = exclusions_len;
124
125 ret = lttng_dynamic_buffer_append(&payload->buffer, &tracepoint_comm,
126 sizeof(tracepoint_comm));
127 if (ret) {
128 goto end;
129 }
130
131 ret = lttng_dynamic_buffer_append(
132 &payload->buffer, tracepoint->pattern, pattern_len);
133 if (ret) {
134 goto end;
135 }
136
137 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->filter_expression,
138 filter_expression_len);
139 if (ret) {
140 goto end;
141 }
142
143 for (i = 0; i < exclusion_count; i++) {
144 size_t len;
145 const char *exclusion;
146
147 status = lttng_event_rule_tracepoint_get_exclusion_at_index(
148 rule, i, &exclusion);
149 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
150
151 len = strlen(exclusion) + 1;
152 /* Append exclusion length, includes the null terminator. */
153 ret = lttng_dynamic_buffer_append(
154 &payload->buffer, &len, sizeof(uint32_t));
155 if (ret) {
156 goto end;
157 }
158
159 exclusions_appended_len += sizeof(uint32_t);
160
161 /* Include the '\0' in the payload. */
162 ret = lttng_dynamic_buffer_append(
163 &payload->buffer, exclusion, len);
164 if (ret) {
165 goto end;
166 }
167
168 exclusions_appended_len += len;
169 }
170
171 assert(exclusions_len == exclusions_appended_len);
172
173 end:
174 return ret;
175 }
176
177 static bool lttng_event_rule_tracepoint_is_equal(
178 const struct lttng_event_rule *_a,
179 const struct lttng_event_rule *_b)
180 {
181 int i;
182 bool is_equal = false;
183 struct lttng_event_rule_tracepoint *a, *b;
184 unsigned int count_a, count_b;
185 enum lttng_event_rule_status status;
186
187 a = container_of(_a, struct lttng_event_rule_tracepoint, parent);
188 b = container_of(_b, struct lttng_event_rule_tracepoint, parent);
189
190 status = lttng_event_rule_tracepoint_get_exclusions_count(_a, &count_a);
191 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
192 status = lttng_event_rule_tracepoint_get_exclusions_count(_b, &count_b);
193 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
194
195 /* Quick checks. */
196 if (a->domain != b->domain) {
197 goto end;
198 }
199
200 if (count_a != count_b) {
201 goto end;
202 }
203
204 if (!!a->filter_expression != !!b->filter_expression) {
205 goto end;
206 }
207
208 /* Long check. */
209 assert(a->pattern);
210 assert(b->pattern);
211 if (strcmp(a->pattern, b->pattern)) {
212 goto end;
213 }
214
215 if (a->filter_expression && b->filter_expression) {
216 if (strcmp(a->filter_expression, b->filter_expression)) {
217 goto end;
218 }
219 } else if (!!a->filter_expression != !!b->filter_expression) {
220 /* One is set; not the other. */
221 goto end;
222 }
223
224 if (a->loglevel.type != b->loglevel.type) {
225 goto end;
226 }
227
228 if (a->loglevel.value != b->loglevel.value) {
229 goto end;
230 }
231
232 for (i = 0; i < count_a; i++) {
233 const char *exclusion_a, *exclusion_b;
234
235 status = lttng_event_rule_tracepoint_get_exclusion_at_index(
236 _a, i, &exclusion_a);
237 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
238 status = lttng_event_rule_tracepoint_get_exclusion_at_index(
239 _b, i, &exclusion_b);
240 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
241 if (strcmp(exclusion_a, exclusion_b)) {
242 goto end;
243 }
244 }
245
246 is_equal = true;
247 end:
248 return is_equal;
249 }
250
251 /*
252 * On success ret is 0;
253 *
254 * On error ret is negative.
255 *
256 * An event with NO loglevel and the name is * will return NULL.
257 */
258 static int generate_agent_filter(
259 const struct lttng_event_rule *rule, char **_agent_filter)
260 {
261 int err;
262 int ret = 0;
263 char *agent_filter = NULL;
264 const char *pattern;
265 const char *filter;
266 enum lttng_loglevel_type loglevel_type;
267 enum lttng_event_rule_status status;
268
269 assert(rule);
270 assert(_agent_filter);
271
272 status = lttng_event_rule_tracepoint_get_pattern(rule, &pattern);
273 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
274 ret = -1;
275 goto end;
276 }
277
278 status = lttng_event_rule_tracepoint_get_filter(rule, &filter);
279 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
280 filter = NULL;
281 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
282 ret = -1;
283 goto end;
284 }
285
286 status = lttng_event_rule_tracepoint_get_log_level_type(
287 rule, &loglevel_type);
288 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
289 ret = -1;
290 goto end;
291 }
292
293 /* Don't add filter for the '*' event. */
294 if (strcmp(pattern, "*") != 0) {
295 if (filter) {
296 err = asprintf(&agent_filter,
297 "(%s) && (logger_name == \"%s\")",
298 filter, pattern);
299 } else {
300 err = asprintf(&agent_filter, "logger_name == \"%s\"",
301 pattern);
302 }
303
304 if (err < 0) {
305 PERROR("Failed to format agent filter string");
306 ret = -1;
307 goto end;
308 }
309 }
310
311 if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
312 const char *op;
313 int loglevel_value;
314
315 status = lttng_event_rule_tracepoint_get_log_level(
316 rule, &loglevel_value);
317 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
318 ret = -1;
319 goto end;
320 }
321
322 if (loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) {
323 op = ">=";
324 } else {
325 op = "==";
326 }
327
328 if (filter || agent_filter) {
329 char *new_filter;
330
331 err = asprintf(&new_filter,
332 "(%s) && (int_loglevel %s %d)",
333 agent_filter ? agent_filter : filter,
334 op, loglevel_value);
335 if (agent_filter) {
336 free(agent_filter);
337 }
338 agent_filter = new_filter;
339 } else {
340 err = asprintf(&agent_filter, "int_loglevel %s %d", op,
341 loglevel_value);
342 }
343
344 if (err < 0) {
345 PERROR("Failed to format agent filter string");
346 ret = -1;
347 goto end;
348 }
349 }
350
351 *_agent_filter = agent_filter;
352 agent_filter = NULL;
353
354 end:
355 free(agent_filter);
356 return ret;
357 }
358
359 static enum lttng_error_code
360 lttng_event_rule_tracepoint_generate_filter_bytecode(
361 struct lttng_event_rule *rule,
362 const struct lttng_credentials *creds)
363 {
364 int ret;
365 enum lttng_error_code ret_code;
366 struct lttng_event_rule_tracepoint *tracepoint;
367 enum lttng_domain_type domain_type;
368 enum lttng_event_rule_status status;
369 const char *filter;
370 struct lttng_filter_bytecode *bytecode = NULL;
371
372 assert(rule);
373
374 tracepoint = container_of(
375 rule, struct lttng_event_rule_tracepoint, parent);
376
377 status = lttng_event_rule_tracepoint_get_filter(rule, &filter);
378 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
379 filter = NULL;
380 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
381 ret_code = LTTNG_ERR_FILTER_INVAL;
382 goto end;
383 }
384
385 if (filter && filter[0] == '\0') {
386 ret_code = LTTNG_ERR_FILTER_INVAL;
387 goto error;
388 }
389
390 status = lttng_event_rule_tracepoint_get_domain_type(
391 rule, &domain_type);
392 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
393 ret_code = LTTNG_ERR_UNK;
394 goto error;
395 }
396
397 switch (domain_type) {
398 case LTTNG_DOMAIN_LOG4J:
399 case LTTNG_DOMAIN_JUL:
400 case LTTNG_DOMAIN_PYTHON:
401 {
402 char *agent_filter;
403
404 ret = generate_agent_filter(rule, &agent_filter);
405 if (ret) {
406 ret_code = LTTNG_ERR_FILTER_INVAL;
407 goto error;
408 }
409
410 tracepoint->internal_filter.filter = agent_filter;
411 break;
412 }
413 default:
414 {
415 if (filter) {
416 tracepoint->internal_filter.filter = strdup(filter);
417 if (tracepoint->internal_filter.filter == NULL) {
418 ret_code = LTTNG_ERR_NOMEM;
419 goto error;
420 }
421 } else {
422 tracepoint->internal_filter.filter = NULL;
423 }
424 break;
425 }
426 }
427
428 if (tracepoint->internal_filter.filter == NULL) {
429 ret_code = LTTNG_OK;
430 goto end;
431 }
432
433 ret = run_as_generate_filter_bytecode(
434 tracepoint->internal_filter.filter, creds,
435 &bytecode);
436 if (ret) {
437 ret_code = LTTNG_ERR_FILTER_INVAL;
438 goto end;
439 }
440
441 tracepoint->internal_filter.bytecode = bytecode;
442 bytecode = NULL;
443 ret_code = LTTNG_OK;
444
445 error:
446 end:
447 free(bytecode);
448 return ret_code;
449 }
450
451 static const char *lttng_event_rule_tracepoint_get_internal_filter(
452 const struct lttng_event_rule *rule)
453 {
454 struct lttng_event_rule_tracepoint *tracepoint;
455
456 assert(rule);
457 tracepoint = container_of(
458 rule, struct lttng_event_rule_tracepoint, parent);
459 return tracepoint->internal_filter.filter;
460 }
461
462 static const struct lttng_filter_bytecode *
463 lttng_event_rule_tracepoint_get_internal_filter_bytecode(
464 const struct lttng_event_rule *rule)
465 {
466 struct lttng_event_rule_tracepoint *tracepoint;
467
468 assert(rule);
469 tracepoint = container_of(
470 rule, struct lttng_event_rule_tracepoint, parent);
471 return tracepoint->internal_filter.bytecode;
472 }
473
474 static struct lttng_event_exclusion *
475 lttng_event_rule_tracepoint_generate_exclusions(
476 const struct lttng_event_rule *rule)
477 {
478 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
479 enum lttng_event_rule_status status;
480 struct lttng_event_exclusion *local_exclusions = NULL;
481 struct lttng_event_exclusion *ret_exclusions = NULL;
482 unsigned int nb_exclusions = 0;
483 unsigned int i;
484
485 status = lttng_event_rule_tracepoint_get_domain_type(rule, &domain_type);
486 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
487
488 switch (domain_type) {
489 case LTTNG_DOMAIN_KERNEL:
490 case LTTNG_DOMAIN_JUL:
491 case LTTNG_DOMAIN_LOG4J:
492 case LTTNG_DOMAIN_PYTHON:
493 /* Not supported. */
494 ret_exclusions = NULL;
495 goto end;
496 case LTTNG_DOMAIN_UST:
497 /* Exclusions supported. */
498 break;
499 default:
500 abort();
501 }
502
503 status = lttng_event_rule_tracepoint_get_exclusions_count(
504 rule, &nb_exclusions);
505 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
506 if (nb_exclusions == 0) {
507 /* Nothing to do. */
508 ret_exclusions = NULL;
509 goto end;
510 }
511
512 local_exclusions = zmalloc(sizeof(struct lttng_event_exclusion) +
513 (LTTNG_SYMBOL_NAME_LEN * nb_exclusions));
514 if (!local_exclusions) {
515 PERROR("Failed to allocate exclusions buffer");
516 ret_exclusions = NULL;
517 goto end;
518 }
519
520 local_exclusions->count = nb_exclusions;
521 for (i = 0; i < nb_exclusions; i++) {
522 /* Truncation is already checked at the setter level. */
523 const char *tmp;
524
525 status = lttng_event_rule_tracepoint_get_exclusion_at_index(
526 rule, i, &tmp);
527 assert(status == LTTNG_EVENT_RULE_STATUS_OK);
528 strncpy(local_exclusions->names[i], tmp, LTTNG_SYMBOL_NAME_LEN);
529 local_exclusions->names[i][LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
530 }
531
532 /* Pass ownership. */
533 ret_exclusions = local_exclusions;
534 local_exclusions = NULL;
535 end:
536 free(local_exclusions);
537 return ret_exclusions;
538 }
539
540 static void destroy_lttng_exclusions_element(void *ptr)
541 {
542 free(ptr);
543 }
544
545 struct lttng_event_rule *lttng_event_rule_tracepoint_create(
546 enum lttng_domain_type domain_type)
547 {
548 struct lttng_event_rule *rule = NULL;
549 struct lttng_event_rule_tracepoint *tp_rule;
550
551 if (domain_type == LTTNG_DOMAIN_NONE) {
552 goto end;
553 }
554
555 tp_rule = zmalloc(sizeof(struct lttng_event_rule_tracepoint));
556 if (!tp_rule) {
557 goto end;
558 }
559
560 rule = &tp_rule->parent;
561 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
562 tp_rule->parent.validate = lttng_event_rule_tracepoint_validate;
563 tp_rule->parent.serialize = lttng_event_rule_tracepoint_serialize;
564 tp_rule->parent.equal = lttng_event_rule_tracepoint_is_equal;
565 tp_rule->parent.destroy = lttng_event_rule_tracepoint_destroy;
566 tp_rule->parent.generate_filter_bytecode =
567 lttng_event_rule_tracepoint_generate_filter_bytecode;
568 tp_rule->parent.get_filter =
569 lttng_event_rule_tracepoint_get_internal_filter;
570 tp_rule->parent.get_filter_bytecode =
571 lttng_event_rule_tracepoint_get_internal_filter_bytecode;
572 tp_rule->parent.generate_exclusions =
573 lttng_event_rule_tracepoint_generate_exclusions;
574
575 tp_rule->domain = domain_type;
576 tp_rule->loglevel.type = LTTNG_EVENT_LOGLEVEL_ALL;
577
578 lttng_dynamic_pointer_array_init(&tp_rule->exclusions,
579 destroy_lttng_exclusions_element);
580 end:
581 return rule;
582 }
583
584 LTTNG_HIDDEN
585 ssize_t lttng_event_rule_tracepoint_create_from_payload(
586 struct lttng_payload_view *view,
587 struct lttng_event_rule **_event_rule)
588 {
589 ssize_t ret, offset = 0;
590 int i;
591 enum lttng_event_rule_status status;
592 enum lttng_domain_type domain_type;
593 enum lttng_loglevel_type loglevel_type;
594 const struct lttng_event_rule_tracepoint_comm *tracepoint_comm;
595 const char *pattern;
596 const char *filter_expression = NULL;
597 const char **exclusions = NULL;
598 const uint32_t *exclusion_len;
599 const char *exclusion;
600 struct lttng_buffer_view current_buffer_view;
601 struct lttng_event_rule *rule = NULL;
602
603 if (!_event_rule) {
604 ret = -1;
605 goto end;
606 }
607
608 current_buffer_view = lttng_buffer_view_from_view(
609 &view->buffer, offset, sizeof(*tracepoint_comm));
610 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
611 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
612 ret = -1;
613 goto end;
614 }
615
616 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
617
618 if (tracepoint_comm->domain_type <= LTTNG_DOMAIN_NONE ||
619 tracepoint_comm->domain_type > LTTNG_DOMAIN_PYTHON) {
620 /* Invalid domain value. */
621 ERR("Invalid domain type value (%i) found in tracepoint_comm buffer.",
622 (int) tracepoint_comm->domain_type);
623 ret = -1;
624 goto end;
625 }
626
627 domain_type = (enum lttng_domain_type) tracepoint_comm->domain_type;
628 rule = lttng_event_rule_tracepoint_create(domain_type);
629 if (!rule) {
630 ERR("Failed to create event rule tracepoint.");
631 ret = -1;
632 goto end;
633 }
634
635 loglevel_type = (enum lttng_loglevel_type)
636 tracepoint_comm->loglevel_type;
637 switch (loglevel_type) {
638 case LTTNG_EVENT_LOGLEVEL_ALL:
639 status = lttng_event_rule_tracepoint_set_log_level_all(rule);
640 break;
641 case LTTNG_EVENT_LOGLEVEL_RANGE:
642 status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound(rule,
643 (enum lttng_loglevel_type) tracepoint_comm
644 ->loglevel_value);
645 break;
646 case LTTNG_EVENT_LOGLEVEL_SINGLE:
647 status = lttng_event_rule_tracepoint_set_log_level(rule,
648 (enum lttng_loglevel_type) tracepoint_comm
649 ->loglevel_value);
650 break;
651 default:
652 ERR("Failed to set event rule tracepoint loglevel: unknown loglevel type.");
653 ret = -1;
654 goto end;
655 }
656
657 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
658 ERR("Failed to set event rule tracepoint loglevel.");
659 }
660
661 /* Skip to payload. */
662 offset += current_buffer_view.size;
663
664 /* Map the pattern. */
665 current_buffer_view = lttng_buffer_view_from_view(
666 &view->buffer, offset, tracepoint_comm->pattern_len);
667
668 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
669 ret = -1;
670 goto end;
671 }
672
673 pattern = current_buffer_view.data;
674 if (!lttng_buffer_view_contains_string(&current_buffer_view, pattern,
675 tracepoint_comm->pattern_len)) {
676 ret = -1;
677 goto end;
678 }
679
680 /* Skip after the pattern. */
681 offset += tracepoint_comm->pattern_len;
682
683 if (!tracepoint_comm->filter_expression_len) {
684 goto skip_filter_expression;
685 }
686
687 /* Map the filter_expression. */
688 current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
689 tracepoint_comm->filter_expression_len);
690 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
691 ret = -1;
692 goto end;
693 }
694
695 filter_expression = current_buffer_view.data;
696 if (!lttng_buffer_view_contains_string(&current_buffer_view,
697 filter_expression,
698 tracepoint_comm->filter_expression_len)) {
699 ret = -1;
700 goto end;
701 }
702
703 /* Skip after the pattern. */
704 offset += tracepoint_comm->filter_expression_len;
705
706 skip_filter_expression:
707 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
708 current_buffer_view = lttng_buffer_view_from_view(
709 &view->buffer, offset, sizeof(*exclusion_len));
710 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
711 ret = -1;
712 goto end;
713 }
714
715 exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
716 offset += sizeof(*exclusion_len);
717
718 current_buffer_view = lttng_buffer_view_from_view(
719 &view->buffer, offset, *exclusion_len);
720 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
721 ret = -1;
722 goto end;
723 }
724
725 exclusion = current_buffer_view.data;
726 if (!lttng_buffer_view_contains_string(&current_buffer_view,
727 exclusion, *exclusion_len)) {
728 ret = -1;
729 goto end;
730 }
731
732 status = lttng_event_rule_tracepoint_add_exclusion(rule, exclusion);
733 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
734 ERR("Failed to add event rule tracepoint exclusion \"%s\".",
735 exclusion);
736 ret = -1;
737 goto end;
738 }
739
740 /* Skip to next exclusion. */
741 offset += *exclusion_len;
742 }
743
744 status = lttng_event_rule_tracepoint_set_pattern(rule, pattern);
745 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
746 ERR("Failed to set event rule tracepoint pattern.");
747 ret = -1;
748 goto end;
749 }
750
751 if (filter_expression) {
752 status = lttng_event_rule_tracepoint_set_filter(
753 rule, filter_expression);
754 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
755 ERR("Failed to set event rule tracepoint pattern.");
756 ret = -1;
757 goto end;
758 }
759 }
760
761 *_event_rule = rule;
762 rule = NULL;
763 ret = offset;
764 end:
765 free(exclusions);
766 lttng_event_rule_destroy(rule);
767 return ret;
768 }
769
770 enum lttng_event_rule_status lttng_event_rule_tracepoint_set_pattern(
771 struct lttng_event_rule *rule, const char *pattern)
772 {
773 char *pattern_copy = NULL;
774 struct lttng_event_rule_tracepoint *tracepoint;
775 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
776
777 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !pattern ||
778 strlen(pattern) == 0) {
779 status = LTTNG_EVENT_RULE_STATUS_INVALID;
780 goto end;
781 }
782
783 tracepoint = container_of(
784 rule, struct lttng_event_rule_tracepoint, parent);
785 pattern_copy = strdup(pattern);
786 if (!pattern_copy) {
787 status = LTTNG_EVENT_RULE_STATUS_ERROR;
788 goto end;
789 }
790
791 free(tracepoint->pattern);
792
793 tracepoint->pattern = pattern_copy;
794 pattern_copy = NULL;
795 end:
796 return status;
797 }
798
799 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_pattern(
800 const struct lttng_event_rule *rule, const char **pattern)
801 {
802 struct lttng_event_rule_tracepoint *tracepoint;
803 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
804
805 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
806 status = LTTNG_EVENT_RULE_STATUS_INVALID;
807 goto end;
808 }
809
810 tracepoint = container_of(
811 rule, struct lttng_event_rule_tracepoint, parent);
812 if (!tracepoint->pattern) {
813 status = LTTNG_EVENT_RULE_STATUS_UNSET;
814 goto end;
815 }
816
817 *pattern = tracepoint->pattern;
818 end:
819 return status;
820 }
821
822 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_domain_type(
823 const struct lttng_event_rule *rule,
824 enum lttng_domain_type *type)
825 {
826 struct lttng_event_rule_tracepoint *tracepoint;
827 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
828
829 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !type) {
830 status = LTTNG_EVENT_RULE_STATUS_INVALID;
831 goto end;
832 }
833
834 tracepoint = container_of(
835 rule, struct lttng_event_rule_tracepoint, parent);
836 *type = tracepoint->domain;
837 end:
838 return status;
839 }
840
841 enum lttng_event_rule_status lttng_event_rule_tracepoint_set_filter(
842 struct lttng_event_rule *rule, const char *expression)
843 {
844 char *expression_copy = NULL;
845 struct lttng_event_rule_tracepoint *tracepoint;
846 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
847
848 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !expression ||
849 strlen(expression) == 0) {
850 status = LTTNG_EVENT_RULE_STATUS_INVALID;
851 goto end;
852 }
853
854 tracepoint = container_of(
855 rule, struct lttng_event_rule_tracepoint, parent);
856 expression_copy = strdup(expression);
857 if (!expression_copy) {
858 PERROR("Failed to copy filter expression");
859 status = LTTNG_EVENT_RULE_STATUS_ERROR;
860 goto end;
861 }
862
863 if (tracepoint->filter_expression) {
864 free(tracepoint->filter_expression);
865 }
866
867 tracepoint->filter_expression = expression_copy;
868 expression_copy = NULL;
869 end:
870 return status;
871 }
872
873 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_filter(
874 const struct lttng_event_rule *rule, const char **expression)
875 {
876 struct lttng_event_rule_tracepoint *tracepoint;
877 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
878
879 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !expression) {
880 status = LTTNG_EVENT_RULE_STATUS_INVALID;
881 goto end;
882 }
883
884 tracepoint = container_of(
885 rule, struct lttng_event_rule_tracepoint, parent);
886 if (!tracepoint->filter_expression) {
887 status = LTTNG_EVENT_RULE_STATUS_UNSET;
888 goto end;
889 }
890
891 *expression = tracepoint->filter_expression;
892 end:
893 return status;
894 }
895
896 static bool log_level_value_valid(
897 int level, enum lttng_domain_type domain)
898 {
899 bool valid = false;
900
901 switch (domain) {
902 case LTTNG_DOMAIN_KERNEL:
903 case LTTNG_DOMAIN_UST:
904 if (level < LTTNG_LOGLEVEL_EMERG) {
905 /* Invalid. */
906 goto end;
907 }
908 if (level > LTTNG_LOGLEVEL_DEBUG) {
909 /* Invalid. */
910 goto end;
911 }
912
913 valid = true;
914 break;
915 case LTTNG_DOMAIN_JUL:
916 case LTTNG_DOMAIN_LOG4J:
917 case LTTNG_DOMAIN_PYTHON:
918 /*
919 * For both JUL and LOG4J custom log level are possible and can
920 * spawn the entire int32 range.
921 * For python, custom log level are possible, it is not clear if
922 * negative value are accepted (NOTSET == 0) but the source code
923 * validate against the int type implying that negative values
924 * are accepted.
925 */
926 valid = true;
927 goto end;
928
929 case LTTNG_DOMAIN_NONE:
930 default:
931 abort();
932 }
933
934 end:
935 return valid;
936 }
937
938 enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level(
939 struct lttng_event_rule *rule, int level)
940 {
941 struct lttng_event_rule_tracepoint *tracepoint;
942 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
943
944 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
945 status = LTTNG_EVENT_RULE_STATUS_INVALID;
946 goto end;
947 }
948
949 tracepoint = container_of(
950 rule, struct lttng_event_rule_tracepoint, parent);
951
952 if (!log_level_value_valid(level, tracepoint->domain)) {
953 status = LTTNG_EVENT_RULE_STATUS_INVALID;
954 goto end;
955 }
956
957 tracepoint->loglevel.value = level;
958 tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_SINGLE;
959 end:
960 return status;
961 }
962
963 enum lttng_event_rule_status
964 lttng_event_rule_tracepoint_set_log_level_range_lower_bound(
965 struct lttng_event_rule *rule, int level)
966 {
967 struct lttng_event_rule_tracepoint *tracepoint;
968 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
969
970 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
971 status = LTTNG_EVENT_RULE_STATUS_INVALID;
972 goto end;
973 }
974
975 tracepoint = container_of(
976 rule, struct lttng_event_rule_tracepoint, parent);
977
978 if (!log_level_value_valid(level, tracepoint->domain)) {
979 status = LTTNG_EVENT_RULE_STATUS_INVALID;
980 goto end;
981 }
982
983 tracepoint->loglevel.value = level;
984 tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_RANGE;
985 end:
986 return status;
987 }
988
989 enum lttng_event_rule_status lttng_event_rule_tracepoint_set_log_level_all(
990 struct lttng_event_rule *rule)
991 {
992 struct lttng_event_rule_tracepoint *tracepoint;
993 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
994
995 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule)) {
996 status = LTTNG_EVENT_RULE_STATUS_INVALID;
997 goto end;
998 }
999
1000 tracepoint = container_of(
1001 rule, struct lttng_event_rule_tracepoint, parent);
1002 tracepoint->loglevel.type = LTTNG_EVENT_LOGLEVEL_ALL;
1003 end:
1004 return status;
1005 }
1006
1007 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level_type(
1008 const struct lttng_event_rule *rule,
1009 enum lttng_loglevel_type *type)
1010 {
1011 struct lttng_event_rule_tracepoint *tracepoint;
1012 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1013
1014 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !type) {
1015 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1016 goto end;
1017 }
1018
1019 tracepoint = container_of(
1020 rule, struct lttng_event_rule_tracepoint, parent);
1021 *type = tracepoint->loglevel.type;
1022 end:
1023 return status;
1024 }
1025
1026 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_log_level(
1027 const struct lttng_event_rule *rule, int *level)
1028 {
1029 struct lttng_event_rule_tracepoint *tracepoint;
1030 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1031
1032 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !level) {
1033 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1034 goto end;
1035 }
1036
1037 tracepoint = container_of(
1038 rule, struct lttng_event_rule_tracepoint, parent);
1039 if (tracepoint->loglevel.type == LTTNG_EVENT_LOGLEVEL_ALL) {
1040 status = LTTNG_EVENT_RULE_STATUS_UNSET;
1041 goto end;
1042 }
1043
1044 *level = tracepoint->loglevel.value;
1045 end:
1046 return status;
1047 }
1048
1049 enum lttng_event_rule_status lttng_event_rule_tracepoint_add_exclusion(
1050 struct lttng_event_rule *rule,
1051 const char *exclusion)
1052 {
1053 int ret;
1054 char *exclusion_copy = NULL;
1055 struct lttng_event_rule_tracepoint *tracepoint;
1056 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1057 enum lttng_domain_type domain_type;
1058
1059 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) ||
1060 !exclusion) {
1061 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1062 goto end;
1063 }
1064
1065 tracepoint = container_of(
1066 rule, struct lttng_event_rule_tracepoint, parent);
1067
1068 status = lttng_event_rule_tracepoint_get_domain_type(
1069 rule, &domain_type);
1070 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
1071 goto end;
1072 }
1073
1074 switch (domain_type) {
1075 case LTTNG_DOMAIN_KERNEL:
1076 case LTTNG_DOMAIN_JUL:
1077 case LTTNG_DOMAIN_LOG4J:
1078 case LTTNG_DOMAIN_PYTHON:
1079 status = LTTNG_EVENT_RULE_STATUS_UNSUPPORTED;
1080 goto end;
1081 case LTTNG_DOMAIN_UST:
1082 /* Exclusions supported. */
1083 break;
1084 default:
1085 abort();
1086 }
1087
1088 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
1089 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1090 goto end;
1091 }
1092
1093 exclusion_copy = strdup(exclusion);
1094 if (!exclusion_copy) {
1095 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1096 goto end;
1097 }
1098
1099 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions,
1100 exclusion_copy);
1101 if (ret < 0) {
1102 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1103 goto end;
1104 }
1105
1106 exclusion_copy = NULL;
1107 end:
1108 free(exclusion_copy);
1109 return status;
1110 }
1111
1112 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_exclusions_count(
1113 const struct lttng_event_rule *rule, unsigned int *count)
1114 {
1115 struct lttng_event_rule_tracepoint *tracepoint;
1116 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1117
1118 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !count) {
1119 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1120 goto end;
1121 }
1122
1123 tracepoint = container_of(
1124 rule, struct lttng_event_rule_tracepoint, parent);
1125 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1126 end:
1127 return status;
1128 }
1129
1130 enum lttng_event_rule_status lttng_event_rule_tracepoint_get_exclusion_at_index(
1131 const struct lttng_event_rule *rule,
1132 unsigned int index,
1133 const char **exclusion)
1134 {
1135 unsigned int count;
1136 struct lttng_event_rule_tracepoint *tracepoint;
1137 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1138
1139 if (!rule || !IS_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
1140 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1141 goto end;
1142 }
1143
1144 tracepoint = container_of(
1145 rule, struct lttng_event_rule_tracepoint, parent);
1146 if (lttng_event_rule_tracepoint_get_exclusions_count(rule, &count) !=
1147 LTTNG_EVENT_RULE_STATUS_OK) {
1148 goto end;
1149 }
1150
1151 if (index >= count) {
1152 goto end;
1153 }
1154
1155 *exclusion = lttng_dynamic_pointer_array_get_pointer(
1156 &tracepoint->exclusions, index);
1157 end:
1158 return status;
1159 }
This page took 0.083887 seconds and 4 git commands to generate.