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