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