Fix: waiter: futex wait: handle spurious futex wakeups
[lttng-tools.git] / src / common / event-rule / user-tracepoint.cpp
CommitLineData
0a23a07d
JR
1/*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
8#include <common/credentials.hpp>
9#include <common/error.hpp>
10#include <common/hashtable/hashtable.hpp>
11#include <common/hashtable/utils.hpp>
12#include <common/macros.hpp>
13#include <common/mi-lttng.hpp>
14#include <common/optional.hpp>
15#include <common/payload-view.hpp>
16#include <common/payload.hpp>
17#include <common/runas.hpp>
18#include <common/string-utils/string-utils.hpp>
19#include <lttng/event-rule/event-rule-internal.hpp>
20#include <lttng/event-rule/user-tracepoint-internal.hpp>
0a23a07d 21#include <lttng/event.h>
6a751b95 22#include <lttng/log-level-rule.h>
0a23a07d
JR
23
24#define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
26
27static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule *rule)
28{
29 struct lttng_event_rule_user_tracepoint *tracepoint;
30
31 if (rule == NULL) {
32 return;
33 }
34
0114db0e
JG
35 tracepoint = lttng::utils::container_of(
36 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
37
38 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
39 lttng_dynamic_pointer_array_reset(&tracepoint->exclusions);
40 free(tracepoint->pattern);
41 free(tracepoint->filter_expression);
42 free(tracepoint->internal_filter.filter);
43 free(tracepoint->internal_filter.bytecode);
44 free(tracepoint);
45}
46
47static bool lttng_event_rule_user_tracepoint_validate(
48 const struct lttng_event_rule *rule)
49{
50 bool valid = false;
51 struct lttng_event_rule_user_tracepoint *tracepoint;
52
53 if (!rule) {
54 goto end;
55 }
56
0114db0e
JG
57 tracepoint = lttng::utils::container_of(
58 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
59
60 /* Required field. */
61 if (!tracepoint->pattern) {
62 ERR("Invalid user tracepoint event rule: a pattern must be set.");
63 goto end;
64 }
65
66 valid = true;
67end:
68 return valid;
69}
70
71static int lttng_event_rule_user_tracepoint_serialize(
72 const struct lttng_event_rule *rule,
73 struct lttng_payload *payload)
74{
75 int ret, i;
76 size_t pattern_len, filter_expression_len, exclusions_len, header_offset;
77 size_t size_before_log_level_rule;
78 struct lttng_event_rule_user_tracepoint *tracepoint;
79 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm;
80 enum lttng_event_rule_status status;
81 unsigned int exclusion_count;
82 size_t exclusions_appended_len = 0;
83 struct lttng_event_rule_user_tracepoint_comm *header;
84
85 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
86 ret = -1;
87 goto end;
88 }
89
90 header_offset = payload->buffer.size;
91
92 DBG("Serializing user tracepoint event rule.");
0114db0e
JG
93 tracepoint = lttng::utils::container_of(
94 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
95
96 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &exclusion_count);
a0377dfe 97 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
98
99 pattern_len = strlen(tracepoint->pattern) + 1;
100
101 if (tracepoint->filter_expression != NULL) {
102 filter_expression_len =
103 strlen(tracepoint->filter_expression) + 1;
104 } else {
105 filter_expression_len = 0;
106 }
107
108 exclusions_len = 0;
109 for (i = 0; i < exclusion_count; i++) {
110 const char *exclusion;
111
112 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
113 rule, i, &exclusion);
a0377dfe 114 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
115
116 /* Length field. */
117 exclusions_len += sizeof(uint32_t);
118 /* Payload (null terminated). */
119 exclusions_len += strlen(exclusion) + 1;
120 }
121
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;
126
127 ret = lttng_dynamic_buffer_append(&payload->buffer, &tracepoint_comm,
128 sizeof(tracepoint_comm));
129 if (ret) {
130 goto end;
131 }
132
133 ret = lttng_dynamic_buffer_append(
134 &payload->buffer, tracepoint->pattern, pattern_len);
135 if (ret) {
136 goto end;
137 }
138
139 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->filter_expression,
140 filter_expression_len);
141 if (ret) {
142 goto end;
143 }
144
145 size_before_log_level_rule = payload->buffer.size;
146
147 ret = lttng_log_level_rule_serialize(tracepoint->log_level_rule, payload);
148 if (ret < 0) {
149 goto end;
150 }
151
152 header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
153 header->log_level_rule_len =
154 payload->buffer.size - size_before_log_level_rule;
155
156 for (i = 0; i < exclusion_count; i++) {
157 size_t len;
158 const char *exclusion;
159
160 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
161 rule, i, &exclusion);
a0377dfe 162 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
163
164 len = strlen(exclusion) + 1;
165 /* Append exclusion length, includes the null terminator. */
166 ret = lttng_dynamic_buffer_append(
167 &payload->buffer, &len, sizeof(uint32_t));
168 if (ret) {
169 goto end;
170 }
171
172 exclusions_appended_len += sizeof(uint32_t);
173
174 /* Include the '\0' in the payload. */
175 ret = lttng_dynamic_buffer_append(
176 &payload->buffer, exclusion, len);
177 if (ret) {
178 goto end;
179 }
180
181 exclusions_appended_len += len;
182 }
183
a0377dfe 184 LTTNG_ASSERT(exclusions_len == exclusions_appended_len);
0a23a07d
JR
185
186end:
187 return ret;
188}
189
190static bool lttng_event_rule_user_tracepoint_is_equal(
191 const struct lttng_event_rule *_a,
192 const struct lttng_event_rule *_b)
193{
194 int i;
195 bool is_equal = false;
196 struct lttng_event_rule_user_tracepoint *a, *b;
197 unsigned int count_a, count_b;
198 enum lttng_event_rule_status status;
199
0114db0e
JG
200 a = lttng::utils::container_of(_a, &lttng_event_rule_user_tracepoint::parent);
201 b = lttng::utils::container_of(_b, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
202
203 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a, &count_a);
a0377dfe 204 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 205 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b, &count_b);
a0377dfe 206 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
207
208 /* Quick checks. */
209 if (count_a != count_b) {
210 goto end;
211 }
212
213 if (!!a->filter_expression != !!b->filter_expression) {
214 goto end;
215 }
216
217 /* Long check. */
a0377dfe
FD
218 LTTNG_ASSERT(a->pattern);
219 LTTNG_ASSERT(b->pattern);
0a23a07d
JR
220 if (strcmp(a->pattern, b->pattern)) {
221 goto end;
222 }
223
224 if (a->filter_expression && b->filter_expression) {
225 if (strcmp(a->filter_expression, b->filter_expression)) {
226 goto end;
227 }
228 } else if (!!a->filter_expression != !!b->filter_expression) {
229 /* One is set; not the other. */
230 goto end;
231 }
232
233 if (!lttng_log_level_rule_is_equal(
234 a->log_level_rule, b->log_level_rule)) {
235 goto end;
236 }
237
238 for (i = 0; i < count_a; i++) {
239 const char *exclusion_a, *exclusion_b;
240
241 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
242 _a, i, &exclusion_a);
a0377dfe 243 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
244 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
245 _b, i, &exclusion_b);
a0377dfe 246 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
247 if (strcmp(exclusion_a, exclusion_b)) {
248 goto end;
249 }
250 }
251
252 is_equal = true;
253end:
254 return is_equal;
255}
256
257static enum lttng_error_code
258lttng_event_rule_user_tracepoint_generate_filter_bytecode(
259 struct lttng_event_rule *rule,
260 const struct lttng_credentials *creds)
261{
262 int ret;
263 enum lttng_error_code ret_code;
264 struct lttng_event_rule_user_tracepoint *tracepoint;
265 enum lttng_event_rule_status status;
266 const char *filter;
267 struct lttng_bytecode *bytecode = NULL;
268
a0377dfe 269 LTTNG_ASSERT(rule);
0a23a07d 270
0114db0e
JG
271 tracepoint = lttng::utils::container_of(
272 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
273
274 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
275 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
276 filter = NULL;
277 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
278 ret_code = LTTNG_ERR_FILTER_INVAL;
279 goto end;
280 }
281
282 if (filter && filter[0] == '\0') {
283 ret_code = LTTNG_ERR_FILTER_INVAL;
284 goto error;
285 }
286
287 if (filter) {
288 tracepoint->internal_filter.filter = strdup(filter);
289 if (tracepoint->internal_filter.filter == NULL) {
290 ret_code = LTTNG_ERR_NOMEM;
291 goto error;
292 }
293 } else {
294 tracepoint->internal_filter.filter = NULL;
295 }
296
297 if (tracepoint->internal_filter.filter == NULL) {
298 ret_code = LTTNG_OK;
299 goto end;
300 }
301
302 ret = run_as_generate_filter_bytecode(
303 tracepoint->internal_filter.filter, creds,
304 &bytecode);
305 if (ret) {
306 ret_code = LTTNG_ERR_FILTER_INVAL;
307 goto end;
308 }
309
310 tracepoint->internal_filter.bytecode = bytecode;
311 bytecode = NULL;
312 ret_code = LTTNG_OK;
313
314error:
315end:
316 free(bytecode);
317 return ret_code;
318}
319
320static const char *lttng_event_rule_user_tracepoint_get_internal_filter(
321 const struct lttng_event_rule *rule)
322{
323 struct lttng_event_rule_user_tracepoint *tracepoint;
324
a0377dfe 325 LTTNG_ASSERT(rule);
0114db0e
JG
326 tracepoint = lttng::utils::container_of(
327 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
328 return tracepoint->internal_filter.filter;
329}
330
331static const struct lttng_bytecode *
332lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(
333 const struct lttng_event_rule *rule)
334{
335 struct lttng_event_rule_user_tracepoint *tracepoint;
336
a0377dfe 337 LTTNG_ASSERT(rule);
0114db0e
JG
338 tracepoint = lttng::utils::container_of(
339 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
340 return tracepoint->internal_filter.bytecode;
341}
342
343static enum lttng_event_rule_generate_exclusions_status
344lttng_event_rule_user_tracepoint_generate_exclusions(
345 const struct lttng_event_rule *rule,
346 struct lttng_event_exclusion **_exclusions)
347{
348 unsigned int nb_exclusions = 0, i;
349 struct lttng_event_exclusion *exclusions;
350 enum lttng_event_rule_status event_rule_status;
351 enum lttng_event_rule_generate_exclusions_status ret_status;
352
a0377dfe 353 LTTNG_ASSERT(_exclusions);
0a23a07d
JR
354
355 event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
356 rule, &nb_exclusions);
a0377dfe 357 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
358 if (nb_exclusions == 0) {
359 /* Nothing to do. */
360 exclusions = NULL;
361 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
362 goto end;
363 }
364
64803277 365 exclusions = zmalloc<lttng_event_exclusion>(sizeof(struct lttng_event_exclusion) + (LTTNG_SYMBOL_NAME_LEN * nb_exclusions));
0a23a07d
JR
366 if (!exclusions) {
367 PERROR("Failed to allocate exclusions buffer");
368 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY;
369 goto end;
370 }
371
372 exclusions->count = nb_exclusions;
373 for (i = 0; i < nb_exclusions; i++) {
374 int copy_ret;
375 const char *exclusion_str;
376
377 event_rule_status =
378 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
379 rule, i, &exclusion_str);
a0377dfe 380 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 381
73b3df71
JG
382 copy_ret = lttng_strncpy(
383 LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i),
384 exclusion_str,
385 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i)));
0a23a07d
JR
386 if (copy_ret) {
387 free(exclusions);
388 exclusions = NULL;
389 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR;
390 goto end;
391 }
392 }
393
394 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK;
395
396end:
397 *_exclusions = exclusions;
398 return ret_status;
399}
400
401static void destroy_lttng_exclusions_element(void *ptr)
402{
403 free(ptr);
404}
405
406static unsigned long lttng_event_rule_user_tracepoint_hash(
407 const struct lttng_event_rule *rule)
408{
409 unsigned long hash;
410 unsigned int i, exclusion_count;
411 enum lttng_event_rule_status status;
412 struct lttng_event_rule_user_tracepoint *tp_rule =
0114db0e 413 lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
414
415 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT,
416 lttng_ht_seed);
417 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
418
419 if (tp_rule->filter_expression) {
420 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
421 }
422
423 if (tp_rule->log_level_rule) {
424 hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
425 }
426
427 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule,
428 &exclusion_count);
a0377dfe 429 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
430
431 for (i = 0; i < exclusion_count; i++) {
432 const char *exclusion;
433
434 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
435 rule, i, &exclusion);
a0377dfe 436 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
437 hash ^= hash_key_str(exclusion, lttng_ht_seed);
438 }
439
440 return hash;
441}
442
6a751b95
JR
443static enum lttng_error_code lttng_event_rule_user_tracepoint_mi_serialize(
444 const struct lttng_event_rule *rule, struct mi_writer *writer)
445{
446 int ret;
447 enum lttng_error_code ret_code;
448 enum lttng_event_rule_status status;
449 const char *filter = NULL;
450 const char *name_pattern = NULL;
451 const struct lttng_log_level_rule *log_level_rule = NULL;
452 unsigned int exclusion_count = 0;
453
a0377dfe
FD
454 LTTNG_ASSERT(rule);
455 LTTNG_ASSERT(writer);
456 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule));
6a751b95
JR
457
458 status = lttng_event_rule_user_tracepoint_get_name_pattern(
459 rule, &name_pattern);
a0377dfe
FD
460 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
461 LTTNG_ASSERT(name_pattern);
6a751b95
JR
462
463 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
a0377dfe 464 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
6a751b95
JR
465 status == LTTNG_EVENT_RULE_STATUS_UNSET);
466
467 status = lttng_event_rule_user_tracepoint_get_log_level_rule(
468 rule, &log_level_rule);
a0377dfe 469 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
6a751b95
JR
470 status == LTTNG_EVENT_RULE_STATUS_UNSET);
471
472 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
473 rule, &exclusion_count);
a0377dfe 474 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95
JR
475
476 /* Open event rule user tracepoint element. */
477 ret = mi_lttng_writer_open_element(
478 writer, mi_lttng_element_event_rule_user_tracepoint);
479 if (ret) {
480 goto mi_error;
481 }
482
483 /* Name pattern. */
484 ret = mi_lttng_writer_write_element_string(writer,
485 mi_lttng_element_event_rule_name_pattern, name_pattern);
486 if (ret) {
487 goto mi_error;
488 }
489
490 /* Filter expression. */
491 if (filter != NULL) {
492 ret = mi_lttng_writer_write_element_string(writer,
493 mi_lttng_element_event_rule_filter_expression,
494 filter);
495 if (ret) {
496 goto mi_error;
497 }
498 }
499
500 /* Log level rule. */
501 if (log_level_rule) {
502 ret_code = lttng_log_level_rule_mi_serialize(
503 log_level_rule, writer);
504 if (ret_code != LTTNG_OK) {
505 goto end;
506 }
507 }
508
509 if (exclusion_count != 0) {
510 int i;
511
512 /* Open the exclusion list. */
513 ret = mi_lttng_writer_open_element(writer,
514 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions);
515 if (ret) {
516 goto mi_error;
517 }
518
519 for (i = 0; i < exclusion_count; i++) {
520 const char *exclusion;
521
522 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
523 rule, i, &exclusion);
a0377dfe 524 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95
JR
525
526 ret = mi_lttng_writer_write_element_string(writer,
527 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion,
528 exclusion);
529 if (ret) {
530 goto mi_error;
531 }
532 }
533
534 /* Close the list. */
535 ret = mi_lttng_writer_close_element(writer);
536 if (ret) {
537 goto mi_error;
538 }
539 }
540
541 /* Close event rule user tracepoint element. */
542 ret = mi_lttng_writer_close_element(writer);
543 if (ret) {
544 goto mi_error;
545 }
546
547 ret_code = LTTNG_OK;
548 goto end;
549
550mi_error:
551 ret_code = LTTNG_ERR_MI_IO_FAIL;
552end:
553 return ret_code;
554}
555
0a23a07d
JR
556struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void)
557{
558 struct lttng_event_rule *rule = NULL;
559 struct lttng_event_rule_user_tracepoint *tp_rule;
560 enum lttng_event_rule_status status;
561
64803277 562 tp_rule = zmalloc<lttng_event_rule_user_tracepoint>();
0a23a07d
JR
563 if (!tp_rule) {
564 goto end;
565 }
566
567 rule = &tp_rule->parent;
568 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
569 tp_rule->parent.validate = lttng_event_rule_user_tracepoint_validate;
570 tp_rule->parent.serialize = lttng_event_rule_user_tracepoint_serialize;
571 tp_rule->parent.equal = lttng_event_rule_user_tracepoint_is_equal;
572 tp_rule->parent.destroy = lttng_event_rule_user_tracepoint_destroy;
573 tp_rule->parent.generate_filter_bytecode =
574 lttng_event_rule_user_tracepoint_generate_filter_bytecode;
575 tp_rule->parent.get_filter =
576 lttng_event_rule_user_tracepoint_get_internal_filter;
577 tp_rule->parent.get_filter_bytecode =
578 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode;
579 tp_rule->parent.generate_exclusions =
580 lttng_event_rule_user_tracepoint_generate_exclusions;
581 tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash;
6a751b95 582 tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize;
0a23a07d
JR
583
584 /* Not necessary for now. */
585 tp_rule->parent.generate_lttng_event = NULL;
586
587 tp_rule->log_level_rule = NULL;
588
589 lttng_dynamic_pointer_array_init(&tp_rule->exclusions,
590 destroy_lttng_exclusions_element);
591
592 /* Default pattern is '*'. */
593 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, "*");
594 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
595 lttng_event_rule_destroy(rule);
596 rule = NULL;
597 }
598
599end:
600 return rule;
601}
602
0a23a07d
JR
603ssize_t lttng_event_rule_user_tracepoint_create_from_payload(
604 struct lttng_payload_view *view,
605 struct lttng_event_rule **_event_rule)
606{
607 ssize_t ret, offset = 0;
608 int i;
609 enum lttng_event_rule_status status;
610 const struct lttng_event_rule_user_tracepoint_comm *tracepoint_comm;
611 const char *pattern;
612 const char *filter_expression = NULL;
613 const char **exclusions = NULL;
614 const uint32_t *exclusion_len;
615 const char *exclusion;
616 struct lttng_buffer_view current_buffer_view;
617 struct lttng_event_rule *rule = NULL;
618 struct lttng_log_level_rule *log_level_rule = NULL;
619
620 if (!_event_rule) {
621 ret = -1;
622 goto end;
623 }
624
625 current_buffer_view = lttng_buffer_view_from_view(
626 &view->buffer, offset, sizeof(*tracepoint_comm));
627 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
628 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
629 ret = -1;
630 goto end;
631 }
632
633 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
634
635 rule = lttng_event_rule_user_tracepoint_create();
636 if (!rule) {
637 ERR("Failed to create event rule user tracepoint.");
638 ret = -1;
639 goto end;
640 }
641
642 /* Skip to payload. */
643 offset += current_buffer_view.size;
644
645 /* Map the pattern. */
646 current_buffer_view = lttng_buffer_view_from_view(
647 &view->buffer, offset, tracepoint_comm->pattern_len);
648
649 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
650 ret = -1;
651 goto end;
652 }
653
654 pattern = current_buffer_view.data;
655 if (!lttng_buffer_view_contains_string(&current_buffer_view, pattern,
656 tracepoint_comm->pattern_len)) {
657 ret = -1;
658 goto end;
659 }
660
661 /* Skip after the pattern. */
662 offset += tracepoint_comm->pattern_len;
663
664 if (!tracepoint_comm->filter_expression_len) {
665 goto skip_filter_expression;
666 }
667
668 /* Map the filter_expression. */
669 current_buffer_view = lttng_buffer_view_from_view(&view->buffer, offset,
670 tracepoint_comm->filter_expression_len);
671 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
672 ret = -1;
673 goto end;
674 }
675
676 filter_expression = current_buffer_view.data;
677 if (!lttng_buffer_view_contains_string(&current_buffer_view,
678 filter_expression,
679 tracepoint_comm->filter_expression_len)) {
680 ret = -1;
681 goto end;
682 }
683
684 /* Skip after the pattern. */
685 offset += tracepoint_comm->filter_expression_len;
686
687skip_filter_expression:
688 if (!tracepoint_comm->log_level_rule_len) {
689 goto skip_log_level_rule;
690 }
691
692 {
693 /* Map the log level rule. */
694 struct lttng_payload_view current_payload_view =
695 lttng_payload_view_from_view(view, offset,
696 tracepoint_comm->log_level_rule_len);
697
698 ret = lttng_log_level_rule_create_from_payload(
699 &current_payload_view, &log_level_rule);
700 if (ret < 0) {
701 ret = -1;
702 goto end;
703 }
704
a0377dfe 705 LTTNG_ASSERT(ret == tracepoint_comm->log_level_rule_len);
0a23a07d
JR
706 }
707
708 /* Skip after the log level rule. */
709 offset += tracepoint_comm->log_level_rule_len;
710
711skip_log_level_rule:
712 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
713 current_buffer_view = lttng_buffer_view_from_view(
714 &view->buffer, offset, sizeof(*exclusion_len));
715 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
716 ret = -1;
717 goto end;
718 }
719
720 exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
721 offset += sizeof(*exclusion_len);
722
723 current_buffer_view = lttng_buffer_view_from_view(
724 &view->buffer, offset, *exclusion_len);
725 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
726 ret = -1;
727 goto end;
728 }
729
730 exclusion = current_buffer_view.data;
731 if (!lttng_buffer_view_contains_string(&current_buffer_view,
732 exclusion, *exclusion_len)) {
733 ret = -1;
734 goto end;
735 }
736
737 status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule, exclusion);
738 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
739 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
740 exclusion);
741 ret = -1;
742 goto end;
743 }
744
745 /* Skip to next exclusion. */
746 offset += *exclusion_len;
747 }
748
749 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, pattern);
750 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
751 ERR("Failed to set event rule user tracepoint pattern.");
752 ret = -1;
753 goto end;
754 }
755
756 if (filter_expression) {
757 status = lttng_event_rule_user_tracepoint_set_filter(
758 rule, filter_expression);
759 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
760 ERR("Failed to set event rule user tracepoint pattern.");
761 ret = -1;
762 goto end;
763 }
764 }
765
766 if (log_level_rule) {
767 status = lttng_event_rule_user_tracepoint_set_log_level_rule(
768 rule, log_level_rule);
769 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
770 ERR("Failed to set event rule user tracepoint log level rule.");
771 ret = -1;
772 goto end;
773 }
774 }
775
776 *_event_rule = rule;
777 rule = NULL;
778 ret = offset;
779end:
780 free(exclusions);
781 lttng_log_level_rule_destroy(log_level_rule);
782 lttng_event_rule_destroy(rule);
783 return ret;
784}
785
786enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_name_pattern(
787 struct lttng_event_rule *rule, const char *pattern)
788{
789 char *pattern_copy = NULL;
790 struct lttng_event_rule_user_tracepoint *tracepoint;
791 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
792
793 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern ||
794 strlen(pattern) == 0) {
795 status = LTTNG_EVENT_RULE_STATUS_INVALID;
796 goto end;
797 }
798
0114db0e
JG
799 tracepoint = lttng::utils::container_of(
800 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
801 pattern_copy = strdup(pattern);
802 if (!pattern_copy) {
803 status = LTTNG_EVENT_RULE_STATUS_ERROR;
804 goto end;
805 }
806
807 /* Normalize the pattern. */
808 strutils_normalize_star_glob_pattern(pattern_copy);
809
810 free(tracepoint->pattern);
811
812 tracepoint->pattern = pattern_copy;
813 pattern_copy = NULL;
814end:
815 return status;
816}
817
818enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern(
819 const struct lttng_event_rule *rule, const char **pattern)
820{
821 struct lttng_event_rule_user_tracepoint *tracepoint;
822 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
823
824 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
825 status = LTTNG_EVENT_RULE_STATUS_INVALID;
826 goto end;
827 }
828
0114db0e
JG
829 tracepoint = lttng::utils::container_of(
830 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
831 if (!tracepoint->pattern) {
832 status = LTTNG_EVENT_RULE_STATUS_UNSET;
833 goto end;
834 }
835
836 *pattern = tracepoint->pattern;
837end:
838 return status;
839}
840
841enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_filter(
842 struct lttng_event_rule *rule, const char *expression)
843{
844 char *expression_copy = NULL;
845 struct lttng_event_rule_user_tracepoint *tracepoint;
846 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
847
848 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression ||
849 strlen(expression) == 0) {
850 status = LTTNG_EVENT_RULE_STATUS_INVALID;
851 goto end;
852 }
853
0114db0e
JG
854 tracepoint = lttng::utils::container_of(
855 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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;
869end:
870 return status;
871}
872
873enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_filter(
874 const struct lttng_event_rule *rule, const char **expression)
875{
876 struct lttng_event_rule_user_tracepoint *tracepoint;
877 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
878
879 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression) {
880 status = LTTNG_EVENT_RULE_STATUS_INVALID;
881 goto end;
882 }
883
0114db0e
JG
884 tracepoint = lttng::utils::container_of(
885 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
886 if (!tracepoint->filter_expression) {
887 status = LTTNG_EVENT_RULE_STATUS_UNSET;
888 goto end;
889 }
890
891 *expression = tracepoint->filter_expression;
892end:
893 return status;
894}
895
896static bool log_level_rule_valid(const struct lttng_log_level_rule *rule)
897{
898 bool valid = false;
899 enum lttng_log_level_rule_status status;
900 int level;
901
902 switch (lttng_log_level_rule_get_type(rule)) {
903 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
904 status = lttng_log_level_rule_exactly_get_level(rule, &level);
905 break;
906 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
907 status = lttng_log_level_rule_at_least_as_severe_as_get_level(
908 rule, &level);
909 break;
910 default:
911 abort();
912 }
913
a0377dfe 914 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
0a23a07d
JR
915
916 if (level < LTTNG_LOGLEVEL_EMERG) {
917 /* Invalid. */
918 goto end;
919 }
920 if (level > LTTNG_LOGLEVEL_DEBUG) {
921 /* Invalid. */
922 goto end;
923 }
924
925 valid = true;
926
927end:
928 return valid;
929}
930
931enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_log_level_rule(
932 struct lttng_event_rule *rule,
933 const struct lttng_log_level_rule *log_level_rule)
934{
935 struct lttng_event_rule_user_tracepoint *tracepoint;
936 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
937 struct lttng_log_level_rule *copy = NULL;
938
939 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
940 status = LTTNG_EVENT_RULE_STATUS_INVALID;
941 goto end;
942 }
943
0114db0e
JG
944 tracepoint = lttng::utils::container_of(
945 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
946
947 if (!log_level_rule_valid(log_level_rule)) {
948 status = LTTNG_EVENT_RULE_STATUS_INVALID;
949 goto end;
950 }
951
952 copy = lttng_log_level_rule_copy(log_level_rule);
953 if (copy == NULL) {
954 status = LTTNG_EVENT_RULE_STATUS_ERROR;
955 goto end;
956 }
957
958 if (tracepoint->log_level_rule) {
959 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
960 }
961
962 tracepoint->log_level_rule = copy;
963
964end:
965 return status;
966}
967
968enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_log_level_rule(
969 const struct lttng_event_rule *rule,
970 const struct lttng_log_level_rule **log_level_rule
971 )
972{
973 struct lttng_event_rule_user_tracepoint *tracepoint;
974 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
975
976 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !log_level_rule) {
977 status = LTTNG_EVENT_RULE_STATUS_INVALID;
978 goto end;
979 }
980
0114db0e
JG
981 tracepoint = lttng::utils::container_of(
982 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
983 if (tracepoint->log_level_rule == NULL) {
984 status = LTTNG_EVENT_RULE_STATUS_UNSET;
985 goto end;
986 }
987
988 *log_level_rule = tracepoint->log_level_rule;
989end:
990 return status;
991}
992
993enum lttng_event_rule_status lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
994 struct lttng_event_rule *rule,
995 const char *exclusion)
996{
997 int ret;
998 char *exclusion_copy = NULL;
999 struct lttng_event_rule_user_tracepoint *tracepoint;
1000 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1001
1002 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) ||
1003 !exclusion) {
1004 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1005 goto end;
1006 }
1007
0114db0e
JG
1008 tracepoint = lttng::utils::container_of(
1009 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
1010
1011 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
1012 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1013 goto end;
1014 }
1015
1016 exclusion_copy = strdup(exclusion);
1017 if (!exclusion_copy) {
1018 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1019 goto end;
1020 }
1021
1022 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions,
1023 exclusion_copy);
1024 if (ret < 0) {
1025 status = LTTNG_EVENT_RULE_STATUS_ERROR;
1026 goto end;
1027 }
1028
1029 exclusion_copy = NULL;
1030end:
1031 free(exclusion_copy);
1032 return status;
1033}
1034
1035enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1036 const struct lttng_event_rule *rule, unsigned int *count)
1037{
1038 struct lttng_event_rule_user_tracepoint *tracepoint;
1039 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1040
1041 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !count) {
1042 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1043 goto end;
1044 }
1045
0114db0e
JG
1046 tracepoint = lttng::utils::container_of(
1047 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
1048 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1049end:
1050 return status;
1051}
1052
1053enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1054 const struct lttng_event_rule *rule,
1055 unsigned int index,
1056 const char **exclusion)
1057{
1058 unsigned int count;
1059 struct lttng_event_rule_user_tracepoint *tracepoint;
1060 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1061
1062 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
1063 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1064 goto end;
1065 }
1066
0114db0e
JG
1067 tracepoint = lttng::utils::container_of(
1068 rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
1069 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &count) !=
1070 LTTNG_EVENT_RULE_STATUS_OK) {
1071 goto end;
1072 }
1073
1074 if (index >= count) {
1075 goto end;
1076 }
1077
a6bc4ca9 1078 *exclusion = (const char *) lttng_dynamic_pointer_array_get_pointer(
0a23a07d
JR
1079 &tracepoint->exclusions, index);
1080end:
1081 return status;
1082}
This page took 0.086125 seconds and 4 git commands to generate.