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