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