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