Fix: relayd: missing session unlock on error path
[lttng-tools.git] / src / common / event.cpp
CommitLineData
76fcf151 1/*
ab5be9fa 2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
76fcf151 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
76fcf151 5 *
76fcf151
JG
6 */
7
8ddd72ef
JR
8#include "common/compat/string.h"
9#include "common/macros.h"
10#include "lttng/lttng-error.h"
11#include <assert.h>
12#include <common/buffer-view.h>
13#include <common/dynamic-array.h>
14#include <common/dynamic-buffer.h>
76fcf151 15#include <common/error.h>
8ddd72ef
JR
16#include <common/sessiond-comm/sessiond-comm.h>
17#include <common/align.h>
18#include <lttng/constant.h>
19#include <lttng/event-internal.h>
20#include <lttng/event.h>
21#include <lttng/userspace-probe-internal.h>
22#include <stdint.h>
23#include <string.h>
24
25struct event_list_element {
26 struct lttng_event *event;
27 struct lttng_event_exclusion *exclusions;
28 char *filter_expression;
29};
30
31static void event_list_destructor(void *ptr)
32{
33 struct event_list_element *element = (struct event_list_element *) ptr;
34
35 free(element->filter_expression);
36 free(element->exclusions);
37 lttng_event_destroy(element->event);
38 free(element);
39}
76fcf151 40
76fcf151
JG
41struct lttng_event *lttng_event_copy(const struct lttng_event *event)
42{
43 struct lttng_event *new_event;
44 struct lttng_event_extended *new_event_extended;
45
a6bc4ca9 46 new_event = (lttng_event *) zmalloc(sizeof(*event));
76fcf151
JG
47 if (!new_event) {
48 PERROR("Error allocating event structure");
49 goto end;
50 }
51
52 /* Copy the content of the old event. */
53 memcpy(new_event, event, sizeof(*event));
54
55 /*
56 * We need to create a new extended since the previous pointer is now
57 * invalid.
58 */
a6bc4ca9 59 new_event_extended = (lttng_event_extended *) zmalloc(sizeof(*new_event_extended));
76fcf151
JG
60 if (!new_event_extended) {
61 PERROR("Error allocating event extended structure");
62 goto error;
63 }
64
65 new_event->extended.ptr = new_event_extended;
66end:
67 return new_event;
68error:
69 free(new_event);
37750a61 70 new_event = NULL;
76fcf151
JG
71 goto end;
72}
8ddd72ef
JR
73
74static int lttng_event_probe_attr_serialize(
75 const struct lttng_event_probe_attr *probe,
76 struct lttng_payload *payload)
77{
78 int ret;
79 size_t symbol_name_len;
1c9a0b0e 80 struct lttng_event_probe_attr_comm comm = {};
8ddd72ef
JR
81
82 symbol_name_len = lttng_strnlen(probe->symbol_name, LTTNG_SYMBOL_NAME_LEN);
83 if (symbol_name_len == LTTNG_SYMBOL_NAME_LEN) {
84 /* Not null-termintated. */
85 ret = -1;
86 goto end;
87 }
88
89 /* Include the null terminator. */
90 symbol_name_len += 1;
91
92 comm.symbol_name_len = (uint32_t) symbol_name_len;
93 comm.addr = probe->addr;
94 comm.offset = probe->addr;
95
96 ret = lttng_dynamic_buffer_append(
97 &payload->buffer, &comm, sizeof(comm));
98 if (ret < 0) {
99 ret = -1;
100 goto end;
101 }
102
103 ret = lttng_dynamic_buffer_append(
104 &payload->buffer, probe->symbol_name, symbol_name_len);
105end:
106 return ret;
107}
108
109static int lttng_event_function_attr_serialize(
110 const struct lttng_event_function_attr *function,
111 struct lttng_payload *payload)
112{
113 int ret;
114 size_t symbol_name_len;
115 struct lttng_event_function_attr_comm comm = { 0 };
116
117 symbol_name_len = lttng_strnlen(function->symbol_name, LTTNG_SYMBOL_NAME_LEN);
118 if (symbol_name_len == LTTNG_SYMBOL_NAME_LEN) {
119 /* Not null-termintated. */
120 ret = -1;
121 goto end;
122 }
123
124 /* Include the null terminator. */
125 symbol_name_len += 1;
126
127 comm.symbol_name_len = (uint32_t) symbol_name_len;
128
129 ret = lttng_dynamic_buffer_append(
130 &payload->buffer, &comm, sizeof(comm));
131 if (ret < 0) {
132 ret = -1;
133 goto end;
134 }
135
136 ret = lttng_dynamic_buffer_append(&payload->buffer,
137 function->symbol_name, symbol_name_len);
138end:
139 return ret;
140}
141
142static ssize_t lttng_event_probe_attr_create_from_payload(
143 struct lttng_payload_view *view,
144 struct lttng_event_probe_attr **probe_attr)
145{
146 ssize_t ret, offset = 0;
147 const struct lttng_event_probe_attr_comm *comm;
148 struct lttng_event_probe_attr *local_attr = NULL;
149 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
150 view, offset, sizeof(*comm));
151
152 if (!lttng_payload_view_is_valid(&comm_view)) {
153 ret = -1;
154 goto end;
155 }
156
157 comm = (typeof(comm)) comm_view.buffer.data;
158 offset += sizeof(*comm);
159
160 local_attr = (struct lttng_event_probe_attr *) zmalloc(
161 sizeof(*local_attr));
162 if (local_attr == NULL) {
163 ret = -1;
164 goto end;
165 }
166
167 local_attr->addr = comm->addr;
168 local_attr->offset = comm->offset;
169
170 {
171 const char *name;
172 struct lttng_payload_view name_view =
173 lttng_payload_view_from_view(view, offset,
174 comm->symbol_name_len);
175
176 if (!lttng_payload_view_is_valid(&name_view)) {
177 ret = -1;
178 goto end;
179 }
180
181 name = name_view.buffer.data;
182
183 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
184 comm->symbol_name_len)) {
185 ret = -1;
186 goto end;
187 }
188
189 ret = lttng_strncpy(local_attr->symbol_name, name,
190 LTTNG_SYMBOL_NAME_LEN);
191 if (ret) {
192 ret = -1;
193 goto end;
194 }
195
196 offset += comm->symbol_name_len;
197 }
198
199 *probe_attr = local_attr;
200 local_attr = NULL;
201 ret = offset;
202end:
9eb895d7 203 free(local_attr);
8ddd72ef
JR
204 return ret;
205}
206
207static ssize_t lttng_event_function_attr_create_from_payload(
208 struct lttng_payload_view *view,
209 struct lttng_event_function_attr **function_attr)
210{
211 ssize_t ret, offset = 0;
212 const struct lttng_event_function_attr_comm *comm;
213 struct lttng_event_function_attr *local_attr = NULL;
214 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
215 view, offset, sizeof(*comm));
216
217 if (!lttng_payload_view_is_valid(&comm_view)) {
218 ret = -1;
219 goto end;
220 }
221
222 comm = (typeof(comm)) view->buffer.data;
223 offset += sizeof(*comm);
224
225 local_attr = (struct lttng_event_function_attr *) zmalloc(
226 sizeof(*local_attr));
227 if (local_attr == NULL) {
228 ret = -1;
229 goto end;
230 }
231
232 {
233 const char *name;
234 struct lttng_payload_view name_view =
235 lttng_payload_view_from_view(view, offset,
236 comm->symbol_name_len);
237
238 if (!lttng_payload_view_is_valid(&name_view)) {
239 ret = -1;
240 goto end;
241 }
242
243 name = name_view.buffer.data;
244
245 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
246 comm->symbol_name_len)) {
247 ret = -1;
248 goto end;
249 }
250
251 ret = lttng_strncpy(local_attr->symbol_name, name,
252 LTTNG_SYMBOL_NAME_LEN);
253 if (ret) {
254 ret = -1;
255 goto end;
256 }
257
258 offset += comm->symbol_name_len;
259 }
260
261 *function_attr = local_attr;
262 local_attr = NULL;
263 ret = offset;
264end:
9eb895d7 265 free(local_attr);
8ddd72ef
JR
266 return ret;
267}
268
269static ssize_t lttng_event_exclusions_create_from_payload(
270 struct lttng_payload_view *view,
271 uint32_t count,
272 struct lttng_event_exclusion **exclusions)
273{
274 ssize_t ret, offset = 0;
275 size_t size = (count * LTTNG_SYMBOL_NAME_LEN);
276 uint32_t i;
277 const struct lttng_event_exclusion_comm *comm;
278 struct lttng_event_exclusion *local_exclusions;
279
280 local_exclusions = (struct lttng_event_exclusion *) zmalloc(
281 sizeof(struct lttng_event_exclusion) + size);
282 if (!local_exclusions) {
283 ret = -1;
284 goto end;
285 }
286
287 local_exclusions->count = count;
288
289 for (i = 0; i < count; i++) {
290 const char *string;
291 struct lttng_buffer_view string_view;
292 const struct lttng_buffer_view comm_view =
293 lttng_buffer_view_from_view(&view->buffer,
294 offset, sizeof(*comm));
295
296 if (!lttng_buffer_view_is_valid(&comm_view)) {
297 ret = -1;
298 goto end;
299 }
300
301 comm = (typeof(comm)) comm_view.data;
302 offset += sizeof(*comm);
303
304 string_view = lttng_buffer_view_from_view(
305 &view->buffer, offset, comm->len);
306
307 if (!lttng_buffer_view_is_valid(&string_view)) {
308 ret = -1;
309 goto end;
310 }
311
312 string = string_view.data;
313
314 if (!lttng_buffer_view_contains_string(
315 &string_view, string, comm->len)) {
316 ret = -1;
317 goto end;
318 }
319
320 ret = lttng_strncpy(local_exclusions->names[i],
321 string, LTTNG_SYMBOL_NAME_LEN);
322 if (ret) {
323 ret = -1;
324 goto end;
325 }
326
327 offset += comm->len;
328 }
329
330 *exclusions = local_exclusions;
331 local_exclusions = NULL;
332 ret = offset;
333end:
334 free(local_exclusions);
335 return ret;
336}
337
338ssize_t lttng_event_create_from_payload(struct lttng_payload_view *view,
339 struct lttng_event **out_event,
340 struct lttng_event_exclusion **out_exclusion,
341 char **out_filter_expression,
342 struct lttng_bytecode **out_bytecode)
343{
344 ssize_t ret, offset = 0;
345 struct lttng_event *local_event = NULL;
346 struct lttng_event_exclusion *local_exclusions = NULL;
347 struct lttng_bytecode *local_bytecode = NULL;
348 char *local_filter_expression = NULL;
349 const struct lttng_event_comm *event_comm;
350 struct lttng_event_function_attr *local_function_attr = NULL;
351 struct lttng_event_probe_attr *local_probe_attr = NULL;
352 struct lttng_userspace_probe_location *local_userspace_probe_location =
353 NULL;
354
355 /*
356 * Only event is obligatory, the other output argument are optional and
357 * depends on what the caller is interested in.
358 */
359 assert(out_event);
360 assert(view);
361
362 {
363 struct lttng_payload_view comm_view =
364 lttng_payload_view_from_view(view, offset,
365 sizeof(*event_comm));
366
367 if (!lttng_payload_view_is_valid(&comm_view)) {
368 ret = -1;
369 goto end;
370 }
371
372 /* lttng_event_comm header */
373 event_comm = (typeof(event_comm)) comm_view.buffer.data;
374 offset += sizeof(*event_comm);
375 }
376
377 local_event = lttng_event_create();
378 if (local_event == NULL) {
379 ret = -1;
380 goto end;
381 }
382
383 local_event->type = (enum lttng_event_type) event_comm->event_type;
384 local_event->loglevel_type = (enum lttng_loglevel_type) event_comm->loglevel_type;
385 local_event->loglevel = event_comm->loglevel;
386 local_event->enabled = event_comm->enabled;
387 local_event->pid = event_comm->pid;
388 local_event->flags = (enum lttng_event_flag) event_comm->flags;
389
390 {
391 const char *name;
392 const struct lttng_buffer_view name_view =
393 lttng_buffer_view_from_view(&view->buffer,
394 offset, event_comm->name_len);
395
396 if (!lttng_buffer_view_is_valid(&name_view)) {
397 ret = -1;
398 goto end;
399 }
400
401 name = (const char *) name_view.data;
402
403 if (!lttng_buffer_view_contains_string(
404 &name_view, name, event_comm->name_len)) {
405 ret = -1;
406 goto end;
407 }
408
409 ret = lttng_strncpy(
410 local_event->name, name, LTTNG_SYMBOL_NAME_LEN);
411 if (ret) {
412 ret = -1;
413 goto end;
414 }
415
416 offset += event_comm->name_len;
417 }
418
419 /* Exclusions */
420 if (event_comm->exclusion_count == 0) {
421 goto deserialize_filter_expression;
422 }
423
424 {
425 struct lttng_payload_view exclusions_view =
426 lttng_payload_view_from_view(
427 view, offset, -1);
428
429 if (!lttng_payload_view_is_valid(&exclusions_view)) {
430 ret = -1;
431 goto end;
432 }
433
434 ret = lttng_event_exclusions_create_from_payload(&exclusions_view,
435 event_comm->exclusion_count, &local_exclusions);
436 if (ret < 0) {
437 ret = -1;
438 goto end;
439 }
440 offset += ret;
441
442 local_event->exclusion = 1;
443 }
444
445deserialize_filter_expression:
446
447 if (event_comm->filter_expression_len == 0) {
448 if (event_comm->bytecode_len != 0) {
449 /*
450 * This is an invalid event payload.
451 *
452 * Filter expression without bytecode is possible but
453 * not the other way around.
454 * */
455 ret = -1;
456 goto end;
457 }
458 goto deserialize_event_type_payload;
459 }
460
461 {
462 const char *filter_expression_buffer;
463 struct lttng_buffer_view filter_expression_view =
464 lttng_buffer_view_from_view(&view->buffer, offset,
465 event_comm->filter_expression_len);
466
467 if (!lttng_buffer_view_is_valid(&filter_expression_view)) {
468 ret = -1;
469 goto end;
470 }
471
472 filter_expression_buffer = filter_expression_view.data;
473
474 if (!lttng_buffer_view_contains_string(&filter_expression_view,
475 filter_expression_buffer,
476 event_comm->filter_expression_len)) {
477 ret = -1;
478 goto end;
479 }
480
481 local_filter_expression = lttng_strndup(
482 filter_expression_buffer,
483 event_comm->filter_expression_len);
484 if (!local_filter_expression) {
485 ret = -1;
486 goto end;
487 }
488
489 local_event->filter = 1;
490
491 offset += event_comm->filter_expression_len;
492 }
493
494 if (event_comm->bytecode_len == 0) {
495 /*
496 * Filter expression can be present but without bytecode
497 * when dealing with event listing.
498 */
499 goto deserialize_event_type_payload;
500 }
501
502 /* Bytecode */
503 {
504 struct lttng_payload_view bytecode_view =
505 lttng_payload_view_from_view(view, offset,
506 event_comm->bytecode_len);
507
508 if (!lttng_payload_view_is_valid(&bytecode_view)) {
509 ret = -1;
510 goto end;
511 }
512
513 local_bytecode = (struct lttng_bytecode *) zmalloc(
514 event_comm->bytecode_len);
515 if (!local_bytecode) {
516 ret = -1;
517 goto end;
518 }
519
520 memcpy(local_bytecode, bytecode_view.buffer.data,
521 event_comm->bytecode_len);
522 if ((local_bytecode->len + sizeof(*local_bytecode)) !=
523 event_comm->bytecode_len) {
524 ret = -1;
525 goto end;
526 }
527
528 offset += event_comm->bytecode_len;
529 }
530
531deserialize_event_type_payload:
532 /* Event type specific payload */
533 switch (local_event->type) {
534 case LTTNG_EVENT_FUNCTION:
535 /* Fallthrough */
536 case LTTNG_EVENT_PROBE:
537 {
538 struct lttng_payload_view probe_attr_view =
539 lttng_payload_view_from_view(view, offset,
540 event_comm->lttng_event_probe_attr_len);
541
542 if (event_comm->lttng_event_probe_attr_len == 0) {
543 ret = -1;
544 goto end;
545 }
546
547 if (!lttng_payload_view_is_valid(&probe_attr_view)) {
548 ret = -1;
549 goto end;
550 }
551
552 ret = lttng_event_probe_attr_create_from_payload(
553 &probe_attr_view, &local_probe_attr);
554 if (ret < 0 || ret != event_comm->lttng_event_probe_attr_len) {
555 ret = -1;
556 goto end;
557 }
558
559 /* Copy to the local event. */
560 memcpy(&local_event->attr.probe, local_probe_attr,
561 sizeof(local_event->attr.probe));
562
563 offset += ret;
564 break;
565 }
566 case LTTNG_EVENT_FUNCTION_ENTRY:
567 {
568 struct lttng_payload_view function_attr_view =
569 lttng_payload_view_from_view(view, offset,
570 event_comm->lttng_event_function_attr_len);
571
572 if (event_comm->lttng_event_function_attr_len == 0) {
573 ret = -1;
574 goto end;
575 }
576
577 if (!lttng_payload_view_is_valid(&function_attr_view)) {
578 ret = -1;
579 goto end;
580 }
581
582 ret = lttng_event_function_attr_create_from_payload(
583 &function_attr_view, &local_function_attr);
584 if (ret < 0 || ret != event_comm->lttng_event_function_attr_len) {
585 ret = -1;
586 goto end;
587 }
588
589 /* Copy to the local event. */
590 memcpy(&local_event->attr.ftrace, local_function_attr,
591 sizeof(local_event->attr.ftrace));
592
593 offset += ret;
594
595 break;
596 }
597 case LTTNG_EVENT_USERSPACE_PROBE:
598 {
599 struct lttng_payload_view userspace_probe_location_view =
600 lttng_payload_view_from_view(view, offset,
601 event_comm->userspace_probe_location_len);
602
603 if (event_comm->userspace_probe_location_len == 0) {
604 ret = -1;
605 goto end;
606 }
607
608 if (!lttng_payload_view_is_valid(
609 &userspace_probe_location_view)) {
610 ret = -1;
611 goto end;
612 }
613
614 ret = lttng_userspace_probe_location_create_from_payload(
615 &userspace_probe_location_view,
616 &local_userspace_probe_location);
617 if (ret < 0) {
618 WARN("Failed to create a userspace probe location from the received buffer");
619 ret = -1;
620 goto end;
621 }
622
623 if (ret != event_comm->userspace_probe_location_len) {
8899bce1 624 WARN("Userspace probe location from the received buffer is not the advertised length: header length = %" PRIu32 ", payload length = %zd", event_comm->userspace_probe_location_len, ret);
8ddd72ef
JR
625 ret = -1;
626 goto end;
627 }
628
629 /* Attach the probe location to the event. */
630 ret = lttng_event_set_userspace_probe_location(
631 local_event, local_userspace_probe_location);
632 if (ret) {
633 ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
634 goto end;
635 }
636
637 /*
638 * Userspace probe location object ownership transfered to the
639 * event object.
640 */
641 local_userspace_probe_location = NULL;
642 offset += event_comm->userspace_probe_location_len;
643 break;
644 }
645 case LTTNG_EVENT_TRACEPOINT:
646 /* Fallthrough */
647 case LTTNG_EVENT_ALL:
648 /* Fallthrough */
649 case LTTNG_EVENT_SYSCALL:
650 /* Fallthrough */
651 case LTTNG_EVENT_NOOP:
652 /* Nothing to do here */
653 break;
654 default:
655 ret = LTTNG_ERR_UND;
656 goto end;
657 break;
658 }
659
660 /* Transfer ownership to the caller. */
661 *out_event = local_event;
662 local_event = NULL;
663
664 if (out_bytecode) {
665 *out_bytecode = local_bytecode;
666 local_bytecode = NULL;
667 }
668
669 if (out_exclusion) {
670 *out_exclusion = local_exclusions;
671 local_exclusions = NULL;
672 }
673
674 if (out_filter_expression) {
675 *out_filter_expression = local_filter_expression;
676 local_filter_expression = NULL;
677 }
678
679 ret = offset;
680end:
681 lttng_event_destroy(local_event);
682 lttng_userspace_probe_location_destroy(local_userspace_probe_location);
683 free(local_filter_expression);
684 free(local_exclusions);
685 free(local_bytecode);
686 free(local_function_attr);
687 free(local_probe_attr);
688 return ret;
689}
690
691int lttng_event_serialize(const struct lttng_event *event,
692 unsigned int exclusion_count,
693 char **exclusion_list,
694 char *filter_expression,
695 size_t bytecode_len,
696 struct lttng_bytecode *bytecode,
697 struct lttng_payload *payload)
698{
699 int ret;
700 unsigned int i;
701 size_t header_offset, size_before_payload;
702 size_t name_len;
1c9a0b0e 703 struct lttng_event_comm event_comm = {};
8ddd72ef
JR
704 struct lttng_event_comm *header;
705
706 assert(event);
707 assert(payload);
708 assert(exclusion_count == 0 || exclusion_list);
709
710 /* Save the header location for later in-place header update. */
711 header_offset = payload->buffer.size;
712
713 name_len = lttng_strnlen(event->name, LTTNG_SYMBOL_NAME_LEN);
714 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
715 /* Event name is not NULL-terminated. */
716 ret = -1;
717 goto end;
718 }
719
720 /* Add null termination. */
721 name_len += 1;
722
723 if (exclusion_count > UINT32_MAX) {
724 /* Possible overflow. */
725 ret = -1;
726 goto end;
727 }
728
729 if (bytecode_len > UINT32_MAX) {
730 /* Possible overflow. */
731 ret = -1;
732 goto end;
733 }
734
735 event_comm.name_len = (uint32_t) name_len;
736 event_comm.event_type = (int8_t) event->type;
737 event_comm.loglevel_type = (int8_t) event->loglevel_type;
738 event_comm.loglevel = (int32_t) event->loglevel;
739 event_comm.enabled = (int8_t) event->enabled;
740 event_comm.pid = (int32_t) event->pid;
741 event_comm.exclusion_count = (uint32_t) exclusion_count;
742 event_comm.bytecode_len = (uint32_t) bytecode_len;
743 event_comm.flags = (int32_t) event->flags;
744
745 if (filter_expression) {
746 event_comm.filter_expression_len =
747 strlen(filter_expression) + 1;
748 }
749
750 /* Header */
751 ret = lttng_dynamic_buffer_append(
752 &payload->buffer, &event_comm, sizeof(event_comm));
753 if (ret) {
754 goto end;
755 }
756
757 /* Event name */
758 ret = lttng_dynamic_buffer_append(
759 &payload->buffer, event->name, name_len);
760 if (ret) {
761 goto end;
762 }
763
764 /* Exclusions */
765 for (i = 0; i < exclusion_count; i++) {
766 const size_t exclusion_len = lttng_strnlen(
767 *(exclusion_list + i), LTTNG_SYMBOL_NAME_LEN);
768 const struct lttng_event_exclusion_comm exclusion_header = {
769 .len = (uint32_t) exclusion_len + 1,
770 };
771
772 if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) {
773 /* Exclusion is not NULL-terminated. */
774 ret = -1;
775 goto end;
776 }
777
778 ret = lttng_dynamic_buffer_append(&payload->buffer,
779 &exclusion_header, sizeof(exclusion_header));
780 if (ret) {
781 goto end;
782 }
783
784 ret = lttng_dynamic_buffer_append(&payload->buffer,
785 *(exclusion_list + i), exclusion_len + 1);
786 if (ret) {
787 goto end;
788 }
789 }
790
791 /* Filter expression and its bytecode */
792 if (filter_expression) {
793 ret = lttng_dynamic_buffer_append(&payload->buffer,
794 filter_expression,
795 event_comm.filter_expression_len);
796 if (ret) {
797 goto end;
798 }
799
800 /*
801 * Bytecode can be absent when we serialize to the client
802 * for listing.
803 */
804 if (bytecode) {
805 ret = lttng_dynamic_buffer_append(&payload->buffer,
806 bytecode, bytecode_len);
807 if (ret) {
808 goto end;
809 }
810 }
811 }
812
813 size_before_payload = payload->buffer.size;
814
815 /* Event type specific payload */
816 switch (event->type) {
817 case LTTNG_EVENT_FUNCTION:
818 /* Fallthrough */
819 case LTTNG_EVENT_PROBE:
820 ret = lttng_event_probe_attr_serialize(&event->attr.probe, payload);
821 if (ret) {
822 ret = -1;
823 goto end;
824 }
825
826 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
827 header_offset);
828 header->lttng_event_probe_attr_len =
829 payload->buffer.size - size_before_payload;
830
831 break;
832 case LTTNG_EVENT_FUNCTION_ENTRY:
833 ret = lttng_event_function_attr_serialize(
834 &event->attr.ftrace, payload);
835 if (ret) {
836 ret = -1;
837 goto end;
838 }
839
840 /* Update the lttng_event_function_attr len. */
841 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
842 header_offset);
843 header->lttng_event_function_attr_len =
844 payload->buffer.size - size_before_payload;
845
846 break;
847 case LTTNG_EVENT_USERSPACE_PROBE:
848 {
849 const struct lttng_event_extended *ev_ext =
850 (const struct lttng_event_extended *)
851 event->extended.ptr;
852
853 assert(event->extended.ptr);
854 assert(ev_ext->probe_location);
855
856 size_before_payload = payload->buffer.size;
857 if (ev_ext->probe_location) {
858 /*
859 * lttng_userspace_probe_location_serialize returns the
860 * number of bytes that were appended to the buffer.
861 */
862 ret = lttng_userspace_probe_location_serialize(
863 ev_ext->probe_location, payload);
864 if (ret < 0) {
865 goto end;
866 }
867
868 ret = 0;
869
870 /* Update the userspace probe location len. */
871 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
872 header_offset);
873 header->userspace_probe_location_len =
874 payload->buffer.size - size_before_payload;
875 }
876 break;
877 }
878 case LTTNG_EVENT_TRACEPOINT:
879 /* Fallthrough */
880 case LTTNG_EVENT_ALL:
881 /* Fallthrough */
882 default:
883 /* Nothing to do here. */
884 break;
885 }
886
887end:
888 return ret;
889}
890
26e1c61f
JR
891static ssize_t lttng_event_context_app_populate_from_payload(
892 const struct lttng_payload_view *view,
893 struct lttng_event_context *event_ctx)
894{
895 ssize_t ret, offset = 0;
896 const struct lttng_event_context_app_comm *comm;
897 char *provider_name = NULL, *context_name = NULL;
898 size_t provider_name_len, context_name_len;
899 const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
900 &view->buffer, offset, sizeof(*comm));
901
902 assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
903
904 if (!lttng_buffer_view_is_valid(&comm_view)) {
905 ret = -1;
906 goto end;
907 }
908
909 comm = (typeof(comm)) comm_view.data;
910 offset += sizeof(*comm);
911
912 provider_name_len = comm->provider_name_len;
913 context_name_len = comm->ctx_name_len;
914
915 if (provider_name_len == 0 || context_name_len == 0) {
916 /*
917 * Application provider and context names MUST
918 * be provided.
919 */
920 ret = -1;
921 goto end;
922 }
923
924 {
925 const char *name;
926 const struct lttng_buffer_view provider_name_view =
927 lttng_buffer_view_from_view(&view->buffer,
928 offset,
929 provider_name_len);
930
931 if (!lttng_buffer_view_is_valid(&provider_name_view)) {
932 ret = -1;
933 goto end;
934 }
935
936 name = provider_name_view.data;
937
938 if (!lttng_buffer_view_contains_string(&provider_name_view,
939 name, provider_name_len)) {
940 ret = -1;
941 goto end;
942 }
943
944 provider_name = lttng_strndup(name, provider_name_len);
945 if (!provider_name) {
946 ret = -1;
947 goto end;
948 }
949
950 offset += provider_name_len;
951 }
952
953 {
954 const char *name;
955 const struct lttng_buffer_view context_name_view =
956 lttng_buffer_view_from_view(
957 &view->buffer, offset,
958 context_name_len);
959
960 if (!lttng_buffer_view_is_valid(&context_name_view)) {
961 ret = -1;
962 goto end;
963 }
964
965 name = context_name_view.data;
966
967 if (!lttng_buffer_view_contains_string(&context_name_view, name,
968 context_name_len)) {
969 ret = -1;
970 goto end;
971 }
972
973 context_name = lttng_strndup(name, context_name_len);
974 if (!context_name) {
975 ret = -1;
976 goto end;
977 }
978
979 offset += context_name_len;
980 }
981
982 /* Transfer ownership of the strings */
983 event_ctx->u.app_ctx.provider_name = provider_name;
984 event_ctx->u.app_ctx.ctx_name = context_name;
985 provider_name = NULL;
986 context_name = NULL;
987
988 ret = offset;
989end:
990 free(provider_name);
991 free(context_name);
992
993 return ret;
994}
995
996static ssize_t lttng_event_context_perf_counter_populate_from_payload(
997 const struct lttng_payload_view *view,
998 struct lttng_event_context *event_ctx)
999{
531e96a7
JR
1000 int ret;
1001 ssize_t consumed, offset = 0;
26e1c61f
JR
1002 const struct lttng_event_context_perf_counter_comm *comm;
1003 size_t name_len;
1004 const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1005 &view->buffer, offset, sizeof(*comm));
1006
1007 assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER ||
1008 event_ctx->ctx ==
1009 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER ||
1010 event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER);
1011
1012 if (!lttng_buffer_view_is_valid(&comm_view)) {
531e96a7 1013 consumed = -1;
26e1c61f
JR
1014 goto end;
1015 }
1016
1017 comm = (typeof(comm)) comm_view.data;
1018 offset += sizeof(*comm);
1019
1020 name_len = comm->name_len;
1021
1022 {
1023 const char *name;
1024 const struct lttng_buffer_view provider_name_view =
1025 lttng_buffer_view_from_view(
1026 &view->buffer, offset,
1027 name_len);
1028
1029 if (!lttng_buffer_view_is_valid(&provider_name_view)) {
531e96a7 1030 consumed = -1;
26e1c61f
JR
1031 goto end;
1032 }
1033
1034 name = provider_name_view.data;
1035
1036 if (!lttng_buffer_view_contains_string(
1037 &provider_name_view, name, name_len)) {
531e96a7 1038 consumed = -1;
26e1c61f
JR
1039 goto end;
1040 }
1041
531e96a7
JR
1042 ret = lttng_strncpy(event_ctx->u.perf_counter.name, name, name_len);
1043 if (ret) {
1044 consumed = -1;
1045 goto end;
1046 }
26e1c61f
JR
1047 offset += name_len;
1048 }
1049
1050 event_ctx->u.perf_counter.config = comm->config;
1051 event_ctx->u.perf_counter.type = comm->type;
1052
531e96a7 1053 consumed = offset;
26e1c61f
JR
1054
1055end:
531e96a7 1056 return consumed;
26e1c61f
JR
1057}
1058
1059ssize_t lttng_event_context_create_from_payload(
1060 struct lttng_payload_view *view,
1061 struct lttng_event_context **event_ctx)
1062{
1063 ssize_t ret, offset = 0;
1064 const struct lttng_event_context_comm *comm;
1065 struct lttng_event_context *local_context = NULL;
1066 struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1067 &view->buffer, offset, sizeof(*comm));
1068
1069 assert(event_ctx);
1070 assert(view);
1071
1072 if (!lttng_buffer_view_is_valid(&comm_view)) {
1073 ret = -1;
1074 goto end;
1075 }
1076
1077 comm = (typeof(comm)) comm_view.data;
1078 offset += sizeof(*comm);
1079
1080 local_context = (struct lttng_event_context *)
1081 zmalloc(sizeof(*local_context));
1082 if (!local_context) {
1083 ret = -1;
1084 goto end;
1085 }
1086
1087 local_context->ctx = (lttng_event_context_type) comm->type;
1088
1089 {
1090 struct lttng_payload_view subtype_view =
1091 lttng_payload_view_from_view(view, offset, -1);
1092
1093 switch (local_context->ctx) {
1094 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1095 ret = lttng_event_context_app_populate_from_payload(
1096 &subtype_view, local_context);
1097 break;
1098 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1099 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1100 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1101 ret = lttng_event_context_perf_counter_populate_from_payload(
1102 &subtype_view, local_context);
1103 break;
1104 default:
1105 /* Nothing else to deserialize. */
1106 ret = 0;
1107 break;
1108 }
1109 }
1110
1111 if (ret < 0) {
1112 goto end;
1113 }
1114
1115 offset += ret;
1116
1117 *event_ctx = local_context;
1118 local_context = NULL;
1119 ret = offset;
1120
1121end:
1122 free(local_context);
1123 return ret;
1124}
1125
1126static int lttng_event_context_app_serialize(
1127 struct lttng_event_context *context,
1128 struct lttng_payload *payload)
1129{
1130 int ret;
1c9a0b0e 1131 struct lttng_event_context_app_comm comm = {};
26e1c61f
JR
1132 size_t provider_len, ctx_len;
1133 const char *provider_name;
1134 const char *ctx_name;
1135
1136 assert(payload);
1137 assert(context);
1138 assert(context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
1139
1140 provider_name = context->u.app_ctx.provider_name;
1141 ctx_name = context->u.app_ctx.ctx_name;
1142
1143 if (!provider_name || !ctx_name) {
1144 ret = -LTTNG_ERR_INVALID;
1145 goto end;
1146 }
1147
1148 provider_len = strlen(provider_name);
1149 if (provider_len == 0) {
1150 ret = -LTTNG_ERR_INVALID;
1151 goto end;
1152 }
1153
1154 /* Include the null terminator. */
f4f239b3
JR
1155 provider_len += 1;
1156 comm.provider_name_len = provider_len;
26e1c61f
JR
1157
1158 ctx_len = strlen(ctx_name);
1159 if (ctx_len == 0) {
1160 ret = -LTTNG_ERR_INVALID;
1161 goto end;
1162 }
1163
1164 /* Include the null terminator. */
f4f239b3
JR
1165 ctx_len += 1;
1166 comm.ctx_name_len = ctx_len;
26e1c61f
JR
1167
1168 /* Header */
1169 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
1170 sizeof(comm));
1171 if (ret) {
1172 ret = -1;
1173 goto end;
1174 }
1175
1176 ret = lttng_dynamic_buffer_append(&payload->buffer, provider_name,
1177 provider_len);
1178 if (ret) {
1179 ret = -1;
1180 goto end;
1181 }
1182
1183 ret = lttng_dynamic_buffer_append(&payload->buffer, ctx_name,
1184 ctx_len);
1185 if (ret) {
1186 ret = -1;
1187 goto end;
1188 }
1189
1190end:
1191 return ret;
1192}
1193
1194static int lttng_event_context_perf_counter_serialize(
1195 struct lttng_event_perf_counter_ctx *context,
1196 struct lttng_payload *payload)
1197{
1198 int ret;
1c9a0b0e 1199 struct lttng_event_context_perf_counter_comm comm = {};
26e1c61f
JR
1200
1201 assert(payload);
1202 assert(context);
1203
1204 comm.config = context->config;
1205 comm.type = context->type;
1206 comm.name_len = lttng_strnlen(context->name, LTTNG_SYMBOL_NAME_LEN);
1207
1208 if (comm.name_len == LTTNG_SYMBOL_NAME_LEN) {
1209 ret = -1;
1210 goto end;
1211 }
1212
1213 /* Include the null terminator. */
1214 comm.name_len += 1;
1215
1216 /* Header */
1217 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
1218 sizeof(comm));
1219 if (ret) {
1220 ret = -1;
1221 goto end;
1222 }
1223
1224 ret = lttng_dynamic_buffer_append(&payload->buffer, context->name,
1225 comm.name_len);
1226 if (ret) {
1227 ret = -1;
1228 goto end;
1229 }
1230
1231end:
1232 return ret;
1233}
1234
1235int lttng_event_context_serialize(struct lttng_event_context *context,
1236 struct lttng_payload *payload)
1237{
1238 int ret;
1239 struct lttng_event_context_comm context_comm = { 0 };
1240
1241 assert(context);
1242 assert(payload);
1243
1244 context_comm.type = (uint32_t) context->ctx;
1245
1246 /* Header */
1247 ret = lttng_dynamic_buffer_append(
1248 &payload->buffer, &context_comm, sizeof(context_comm));
1249 if (ret) {
1250 goto end;
1251 }
1252
1253 switch (context->ctx) {
1254 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1255 ret = lttng_event_context_app_serialize(context, payload);
1256 break;
1257 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1258 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1259 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1260 ret = lttng_event_context_perf_counter_serialize(
1261 &context->u.perf_counter, payload);
1262 break;
1263 default:
1264 /* Nothing else to serialize. */
1265 break;
1266 }
1267
1268 if (ret) {
1269 goto end;
1270 }
1271
1272end:
1273 return ret;
1274}
1275
1276void lttng_event_context_destroy(struct lttng_event_context *context)
1277{
1278 if (!context) {
1279 return;
1280 }
1281
1282 if (context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
1283 free(context->u.app_ctx.provider_name);
1284 free(context->u.app_ctx.ctx_name);
1285 }
1286
1287 free(context);
1288}
1289
b2d68839
JR
1290/*
1291 * This is a specialized populate for lttng_event_field since it ignores
1292 * the extension field of the lttng_event struct and simply copies what it can
1293 * to the internal struct lttng_event of a lttng_event_field.
1294 */
1295static void lttng_event_field_populate_lttng_event_from_event(
1296 const struct lttng_event *src, struct lttng_event *destination)
1297{
1298 memcpy(destination, src, sizeof(*destination));
1299
1300 /* Remove all possible dynamic data from the destination event rule. */
1301 destination->extended.ptr = NULL;
1302}
1303
1304ssize_t lttng_event_field_create_from_payload(
1305 struct lttng_payload_view *view,
1306 struct lttng_event_field **field)
1307{
1308 ssize_t ret, offset = 0;
1309 struct lttng_event_field *local_event_field = NULL;
1310 struct lttng_event *event = NULL;
1311 const struct lttng_event_field_comm *comm;
1312 const char* name = NULL;
1313
1314 assert(field);
1315 assert(view);
1316
1317 {
1318 const struct lttng_buffer_view comm_view =
1319 lttng_buffer_view_from_view(
1320 &view->buffer, offset,
1321 sizeof(*comm));
1322
1323 if (!lttng_buffer_view_is_valid(&comm_view)) {
1324 ret = -1;
1325 goto end;
1326 }
1327
1328 /* lttng_event_field_comm header */
1329 comm = (const lttng_event_field_comm *) comm_view.data;
1330 offset += sizeof(*comm);
1331 }
1332
1333 local_event_field = (struct lttng_event_field *)
1334 zmalloc(sizeof(*local_event_field));
1335 if (!local_event_field) {
1336 ret = -1;
1337 goto end;
1338 }
1339
1340 local_event_field->type = (lttng_event_field_type) comm->type;
1341 local_event_field->nowrite = comm->nowrite;
1342
1343 /* Field name */
1344 {
1345 const struct lttng_buffer_view name_view =
1346 lttng_buffer_view_from_view(
1347 &view->buffer, offset,
1348 comm->name_len);
1349
1350 if (!lttng_buffer_view_is_valid(&name_view)) {
1351 ret = -1;
1352 goto end;
1353 }
1354
1355 name = name_view.data;
1356
1357 if (!lttng_buffer_view_contains_string(&name_view,
1358 name_view.data, comm->name_len)) {
1359 ret = -1;
1360 goto end;
1361 }
1362
1363 if (comm->name_len > LTTNG_SYMBOL_NAME_LEN - 1) {
1364 /* Name is too long.*/
1365 ret = -1;
1366 goto end;
1367 }
1368
1369 offset += comm->name_len;
1370 }
1371
1372 /* Event */
1373 {
1374 struct lttng_payload_view event_view =
1375 lttng_payload_view_from_view(
1376 view, offset,
1377 comm->event_len);
1378
1379 if (!lttng_payload_view_is_valid(&event_view)) {
1380 ret = -1;
1381 goto end;
1382 }
1383
1384 ret = lttng_event_create_from_payload(&event_view, &event, NULL,
1385 NULL, NULL);
1386 if (ret != comm->event_len) {
1387 ret = -1;
1388 goto end;
1389 }
1390
1391 offset += ret;
1392 }
1393
1394 assert(name);
1395 assert(event);
1396
1397 if (lttng_strncpy(local_event_field->field_name, name , LTTNG_SYMBOL_NAME_LEN)) {
1398 ret = -1;
1399 goto end;
1400 }
1401
1402 lttng_event_field_populate_lttng_event_from_event(
1403 event, &local_event_field->event);
1404
1405 *field = local_event_field;
1406 local_event_field = NULL;
1407 ret = offset;
1408end:
1409 lttng_event_destroy(event);
1410 free(local_event_field);
1411 return ret;
1412}
1413
1414int lttng_event_field_serialize(const struct lttng_event_field *field,
1415 struct lttng_payload *payload)
1416{
1417 int ret;
1418 size_t header_offset, size_before_event;
1419 size_t name_len;
1c9a0b0e 1420 struct lttng_event_field_comm event_field_comm = {};
b2d68839
JR
1421 struct lttng_event_field_comm *header;
1422
1423 assert(field);
1424 assert(payload);
1425
1426 /* Save the header location for later in-place header update. */
1427 header_offset = payload->buffer.size;
1428
1429 name_len = strnlen(field->field_name, LTTNG_SYMBOL_NAME_LEN);
1430 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
1431 /* Event name is not NULL-terminated. */
1432 ret = -1;
1433 goto end;
1434 }
1435
1436 /* Add null termination. */
1437 name_len += 1;
1438
1439 event_field_comm.type = field->type;
1440 event_field_comm.nowrite = (uint8_t)field->nowrite;
1441 event_field_comm.name_len = name_len;
1442
1443 /* Header */
1444 ret = lttng_dynamic_buffer_append(
1445 &payload->buffer, &event_field_comm,
1446 sizeof(event_field_comm));
1447 if (ret) {
1448 goto end;
1449 }
1450
1451 /* Field name */
1452 ret = lttng_dynamic_buffer_append(&payload->buffer, field->field_name,
1453 name_len);
1454 if (ret) {
1455 goto end;
1456 }
1457
1458 size_before_event = payload->buffer.size;
1459 ret = lttng_event_serialize(
1460 &field->event, 0, NULL, NULL, 0, 0, payload);
1461 if (ret) {
1462 ret = -1;
1463 goto end;
1464 }
1465
1466 /* Update the event len. */
1467 header = (struct lttng_event_field_comm *)
1468 ((char *) payload->buffer.data +
1469 header_offset);
1470 header->event_len = payload->buffer.size - size_before_event;
1471
1472end:
1473 return ret;
1474}
1475
8ddd72ef
JR
1476static enum lttng_error_code compute_flattened_size(
1477 struct lttng_dynamic_pointer_array *events, size_t *size)
1478{
1479 enum lttng_error_code ret_code;
1480 int ret = 0;
1481 size_t storage_req, event_count, i;
1482
1483 assert(size);
1484 assert(events);
1485
1486 event_count = lttng_dynamic_pointer_array_get_count(events);
1487
1488 /* The basic struct lttng_event */
1489 storage_req = event_count * sizeof(struct lttng_event);
1490
fc33156e
JG
1491 /* The struct·lttng_event_extended */
1492 storage_req += event_count * sizeof(struct lttng_event_extended);
1493
8ddd72ef
JR
1494 for (i = 0; i < event_count; i++) {
1495 int probe_storage_req = 0;
1496 const struct event_list_element *element = (const struct event_list_element *)
1497 lttng_dynamic_pointer_array_get_pointer(
1498 events, i);
1499 const struct lttng_userspace_probe_location *location = NULL;
1500
1501 location = lttng_event_get_userspace_probe_location(
1502 element->event);
1503 if (location) {
1504 ret = lttng_userspace_probe_location_flatten(
1505 location, NULL);
1506 if (ret < 0) {
1507 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1508 goto end;
1509 }
1510
1511 probe_storage_req = ret;
1512 }
1513
8ddd72ef
JR
1514 if (element->filter_expression) {
1515 storage_req += strlen(element->filter_expression) + 1;
1516 }
1517
1518 if (element->exclusions) {
1519 storage_req += element->exclusions->count *
1520 LTTNG_SYMBOL_NAME_LEN;
1521 }
1522
1523 /* Padding to ensure the flat probe is aligned. */
1524 storage_req = lttng_align_ceil(storage_req, sizeof(uint64_t));
1525 storage_req += probe_storage_req;
1526 }
1527
1528 *size = storage_req;
1529 ret_code = LTTNG_OK;
1530
1531end:
1532 return ret_code;
1533}
1534
1535/*
1536 * Flatten a list of struct lttng_event.
1537 *
1538 * The buffer that is returned to the API client must contain a "flat" version
1539 * of the events that are returned. In other words, all pointers within an
1540 * lttng_event must point to a location within the returned buffer so that the
1541 * user may free everything by simply calling free() on the returned buffer.
1542 * This is needed in order to maintain API compatibility.
1543 *
1544 * A first pass is performed to compute the size of the buffer that must be
1545 * allocated. A second pass is then performed to setup the returned events so
1546 * that their members always point within the buffer.
1547 *
1548 * The layout of the returned buffer is as follows:
1549 * - struct lttng_event[nb_events],
1550 * - nb_events times the following:
1551 * - struct lttng_event_extended,
1552 * - filter_expression
1553 * - exclusions
1554 * - padding to align to 64-bits
1555 * - flattened version of userspace_probe_location
1556 */
1557static enum lttng_error_code flatten_lttng_events(
1558 struct lttng_dynamic_pointer_array *events,
1559 struct lttng_event **flattened_events)
1560{
1561 enum lttng_error_code ret_code;
1562 int ret, i;
1563 size_t storage_req;
1564 struct lttng_dynamic_buffer local_flattened_events;
1565 int nb_events;
1566
1567 assert(events);
1568 assert(flattened_events);
1569
1570 lttng_dynamic_buffer_init(&local_flattened_events);
1571 nb_events = lttng_dynamic_pointer_array_get_count(events);
1572
1573 ret_code = compute_flattened_size(events, &storage_req);
1574 if (ret_code != LTTNG_OK) {
1575 goto end;
1576 }
1577
1578 /*
1579 * We must ensure that "local_flattened_events" is never resized so as
1580 * to preserve the validity of the flattened objects.
1581 */
1582 ret = lttng_dynamic_buffer_set_capacity(
1583 &local_flattened_events, storage_req);
1584 if (ret) {
1585 ret_code = LTTNG_ERR_NOMEM;
1586 goto end;
1587 }
1588
1589 /* Start by laying the struct lttng_event */
1590 for (i = 0; i < nb_events; i++) {
1591 const struct event_list_element *element = (const struct event_list_element *)
1592 lttng_dynamic_pointer_array_get_pointer(
1593 events, i);
1594
1595 if (!element) {
1596 ret_code = LTTNG_ERR_FATAL;
1597 goto end;
1598 }
1599
1600 ret = lttng_dynamic_buffer_append(&local_flattened_events,
1601 element->event, sizeof(struct lttng_event));
1602 if (ret) {
1603 ret_code = LTTNG_ERR_NOMEM;
1604 goto end;
1605 }
1606 }
1607
1608 for (i = 0; i < nb_events; i++) {
1609 const struct event_list_element *element = (const struct event_list_element *)
1610 lttng_dynamic_pointer_array_get_pointer(events, i);
1611 struct lttng_event *event = (struct lttng_event *)
1612 (local_flattened_events.data + (sizeof(struct lttng_event) * i));
1613 struct lttng_event_extended *event_extended =
1614 (struct lttng_event_extended *)
1615 (local_flattened_events.data + local_flattened_events.size);
1616 const struct lttng_userspace_probe_location *location = NULL;
1617
1618 assert(element);
1619
1620 /* Insert struct lttng_event_extended. */
1621 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1622 local_flattened_events.size +
1623 sizeof(*event_extended));
1624 if (ret) {
1625 ret_code = LTTNG_ERR_NOMEM;
1626 goto end;
1627 }
1628 event->extended.ptr = event_extended;
1629
1630 /* Insert filter expression. */
1631 if (element->filter_expression) {
1632 const size_t len = strlen(element->filter_expression) + 1;
1633
1634 event_extended->filter_expression =
1635 local_flattened_events.data +
1636 local_flattened_events.size;
1637 ret = lttng_dynamic_buffer_append(
1638 &local_flattened_events,
1639 element->filter_expression, len);
1640 if (ret) {
1641 ret_code = LTTNG_ERR_NOMEM;
1642 goto end;
1643 }
1644 }
1645
1646 /* Insert exclusions. */
1647 if (element->exclusions) {
1648 event_extended->exclusions.count =
1649 element->exclusions->count;
1650 event_extended->exclusions.strings =
1651 local_flattened_events.data +
1652 local_flattened_events.size;
1653
1654 ret = lttng_dynamic_buffer_append(
1655 &local_flattened_events,
1656 element->exclusions->names,
1657 element->exclusions->count *
1658 LTTNG_SYMBOL_NAME_LEN);
1659 if (ret) {
1660 ret_code = LTTNG_ERR_NOMEM;
1661 goto end;
1662 }
1663 }
1664
1665 /* Insert padding to align to 64-bits. */
1666 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1667 lttng_align_ceil(local_flattened_events.size,
1668 sizeof(uint64_t)));
1669 if (ret) {
1670 ret_code = LTTNG_ERR_NOMEM;
1671 goto end;
1672 }
1673
1674 location = lttng_event_get_userspace_probe_location(
1675 element->event);
1676 if (location) {
1677 event_extended->probe_location = (struct lttng_userspace_probe_location *)
1678 (local_flattened_events.data + local_flattened_events.size);
1679 ret = lttng_userspace_probe_location_flatten(
1680 location, &local_flattened_events);
1681 if (ret < 0) {
1682 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1683 goto end;
1684 }
1685 }
1686 }
1687
1688 /* Don't reset local_flattened_events buffer as we return its content. */
1689 *flattened_events = (struct lttng_event *) local_flattened_events.data;
1690 lttng_dynamic_buffer_init(&local_flattened_events);
1691 ret_code = LTTNG_OK;
1692end:
1693 lttng_dynamic_buffer_reset(&local_flattened_events);
1694 return ret_code;
1695}
1696
1697static enum lttng_error_code event_list_create_from_payload(
1698 struct lttng_payload_view *view,
1699 unsigned int count,
1700 struct lttng_dynamic_pointer_array *event_list)
1701{
1702 enum lttng_error_code ret_code;
1703 int ret;
1704 unsigned int i;
1705 int offset = 0;
1706
1707 assert(view);
1708 assert(event_list);
1709
1710 for (i = 0; i < count; i++) {
1711 ssize_t event_size;
1712 struct lttng_payload_view event_view =
1713 lttng_payload_view_from_view(view, offset, -1);
1714 struct event_list_element *element =
1715 (struct event_list_element *) zmalloc(sizeof(*element));
1716
1717 if (!element) {
1718 ret_code = LTTNG_ERR_NOMEM;
1719 goto end;
1720 }
1721
1722 /*
1723 * Lifetime and management of the object is now bound to the
1724 * array.
1725 */
1726 ret = lttng_dynamic_pointer_array_add_pointer(
1727 event_list, element);
1728 if (ret) {
1729 event_list_destructor(element);
1730 ret_code = LTTNG_ERR_NOMEM;
1731 goto end;
1732 }
1733
1734 /*
1735 * Bytecode is not transmitted on listing in any case we do not
1736 * care about it.
1737 */
1738 event_size = lttng_event_create_from_payload(&event_view,
1739 &element->event,
1740 &element->exclusions,
1741 &element->filter_expression, NULL);
1742 if (event_size < 0) {
1743 ret_code = LTTNG_ERR_INVALID;
1744 goto end;
1745 }
1746
1747 offset += event_size;
1748 }
1749
1750 if (view->buffer.size != offset) {
1751 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
1752 goto end;
1753 }
1754
1755 ret_code = LTTNG_OK;
1756
1757end:
1758 return ret_code;
1759}
1760
1761enum lttng_error_code lttng_events_create_and_flatten_from_payload(
1762 struct lttng_payload_view *payload,
1763 unsigned int count,
1764 struct lttng_event **events)
1765{
1766 enum lttng_error_code ret = LTTNG_OK;
1767 struct lttng_dynamic_pointer_array local_events;
1768
1769 lttng_dynamic_pointer_array_init(&local_events, event_list_destructor);
1770
1771 /* Deserialize the events. */
1772 {
1773 struct lttng_payload_view events_view =
1774 lttng_payload_view_from_view(payload, 0, -1);
1775
1776 ret = event_list_create_from_payload(
1777 &events_view, count, &local_events);
1778 if (ret != LTTNG_OK) {
1779 goto end;
1780 }
1781 }
1782
1783 ret = flatten_lttng_events(&local_events, events);
1784 if (ret != LTTNG_OK) {
1785 goto end;
1786 }
1787
1788end:
1789 lttng_dynamic_pointer_array_reset(&local_events);
1790 return ret;
1791}
b2d68839
JR
1792
1793static enum lttng_error_code flatten_lttng_event_fields(
1794 struct lttng_dynamic_pointer_array *event_fields,
1795 struct lttng_event_field **flattened_event_fields)
1796{
1797 int ret, i;
1798 enum lttng_error_code ret_code;
1799 size_t storage_req = 0;
1800 struct lttng_dynamic_buffer local_flattened_event_fields;
1801 int nb_event_field;
1802
1803 assert(event_fields);
1804 assert(flattened_event_fields);
1805
1806 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1807 nb_event_field = lttng_dynamic_pointer_array_get_count(event_fields);
1808
1809 /*
1810 * Here even if the event field contains a `struct lttng_event` that
1811 * could contain dynamic data, in reality it is not the case.
1812 * Dynamic data is not present. Here the flattening is mostly a direct
1813 * memcpy. This is less than ideal but this code is still better than
1814 * direct usage of an unpacked lttng_event_field array.
1815 */
1816 storage_req += sizeof(struct lttng_event_field) * nb_event_field;
1817
1818 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1819
1820 /*
1821 * We must ensure that "local_flattened_event_fields" is never resized
1822 * so as to preserve the validity of the flattened objects.
1823 */
1824 ret = lttng_dynamic_buffer_set_capacity(
1825 &local_flattened_event_fields, storage_req);
1826 if (ret) {
1827 ret_code = LTTNG_ERR_NOMEM;
1828 goto end;
1829 }
1830
1831 for (i = 0; i < nb_event_field; i++) {
1832 const struct lttng_event_field *element =
1833 (const struct lttng_event_field *)
1834 lttng_dynamic_pointer_array_get_pointer(
1835 event_fields, i);
1836
1837 if (!element) {
1838 ret_code = LTTNG_ERR_FATAL;
1839 goto end;
1840 }
1841 ret = lttng_dynamic_buffer_append(&local_flattened_event_fields,
1842 element, sizeof(struct lttng_event_field));
1843 if (ret) {
1844 ret_code = LTTNG_ERR_NOMEM;
1845 goto end;
1846 }
1847 }
1848
1849 /* Don't reset local_flattened_channels buffer as we return its content. */
1850 *flattened_event_fields = (struct lttng_event_field *) local_flattened_event_fields.data;
1851 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1852 ret_code = LTTNG_OK;
1853end:
1854 lttng_dynamic_buffer_reset(&local_flattened_event_fields);
1855 return ret_code;
1856}
1857
1858static enum lttng_error_code event_field_list_create_from_payload(
1859 struct lttng_payload_view *view,
1860 unsigned int count,
1861 struct lttng_dynamic_pointer_array **event_field_list)
1862{
1863 enum lttng_error_code ret_code;
1864 int ret, offset = 0;
1865 unsigned int i;
1866 struct lttng_dynamic_pointer_array *list = NULL;
1867
1868 assert(view);
1869 assert(event_field_list);
1870
1871 list = (struct lttng_dynamic_pointer_array *) zmalloc(sizeof(*list));
1872 if (!list) {
1873 ret_code = LTTNG_ERR_NOMEM;
1874 goto end;
1875 }
1876
1877 lttng_dynamic_pointer_array_init(list, free);
1878
1879 for (i = 0; i < count; i++) {
1880 ssize_t event_field_size;
1881 struct lttng_event_field *field = NULL;
1882 struct lttng_payload_view event_field_view =
1883 lttng_payload_view_from_view(view, offset, -1);
1884
1885 event_field_size = lttng_event_field_create_from_payload(
1886 &event_field_view, &field);
1887 if (event_field_size < 0) {
1888 ret_code = LTTNG_ERR_INVALID;
1889 goto end;
1890 }
1891
1892 /* Lifetime and management of the object is now bound to the array. */
1893 ret = lttng_dynamic_pointer_array_add_pointer(list, field);
1894 if (ret) {
1895 free(field);
1896 ret_code = LTTNG_ERR_NOMEM;
1897 goto end;
1898 }
1899
1900 offset += event_field_size;
1901 }
1902
1903 if (view->buffer.size != offset) {
1904 ret_code = LTTNG_ERR_INVALID;
1905 goto end;
1906 }
1907
1908 *event_field_list = list;
1909 list = NULL;
1910 ret_code = LTTNG_OK;
1911
1912end:
1913 if (list) {
1914 lttng_dynamic_pointer_array_reset(list);
1915 free(list);
1916 }
1917
1918 return ret_code;
1919}
1920
1921enum lttng_error_code lttng_event_fields_create_and_flatten_from_payload(
1922 struct lttng_payload_view *view,
1923 unsigned int count,
1924 struct lttng_event_field **fields)
1925{
1926 enum lttng_error_code ret_code;
1927 struct lttng_dynamic_pointer_array *local_event_fields = NULL;
1928
1929 ret_code = event_field_list_create_from_payload(
1930 view, count, &local_event_fields);
1931 if (ret_code != LTTNG_OK) {
1932 goto end;
1933 }
1934
1935 ret_code = flatten_lttng_event_fields(local_event_fields, fields);
1936 if (ret_code != LTTNG_OK) {
1937 goto end;
1938 }
1939end:
1940 if (local_event_fields) {
1941 lttng_dynamic_pointer_array_reset(local_event_fields);
1942 free(local_event_fields);
1943 }
1944
1945 return ret_code;
1946}
This page took 0.112474 seconds and 4 git commands to generate.