Fix: event: erroneous bound check on perf counter name size
[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,
1097 sizeof(event_ctx->u.perf_counter.name));
1098 if (ret) {
1099 consumed = -1;
1100 goto end;
1101 }
1102 offset += name_len;
1103 }
1104
1105 event_ctx->u.perf_counter.config = comm->config;
1106 event_ctx->u.perf_counter.type = comm->type;
1107
1108 consumed = offset;
1109
1110 end:
1111 return consumed;
1112 }
1113
1114 LTTNG_HIDDEN
1115 ssize_t lttng_event_context_create_from_buffer(
1116 const struct lttng_buffer_view *view,
1117 struct lttng_event_context **event_ctx)
1118 {
1119 ssize_t ret, offset = 0;
1120 const struct lttng_event_context_comm *comm;
1121 struct lttng_event_context *local_context = NULL;
1122 struct lttng_buffer_view subtype_view;
1123 struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1124 view, offset, sizeof(*comm));
1125
1126 assert(event_ctx);
1127 assert(view);
1128
1129 if (!lttng_buffer_view_is_valid(&comm_view)) {
1130 ret = -1;
1131 goto end;
1132 }
1133
1134 comm = (typeof(comm)) comm_view.data;
1135 offset += sizeof(*comm);
1136
1137 local_context = zmalloc(sizeof(*local_context));
1138 if (!local_context) {
1139 ret = -1;
1140 goto end;
1141 }
1142
1143 local_context->ctx = comm->type;
1144
1145 subtype_view = lttng_buffer_view_from_view(view, offset, -1);
1146
1147 switch (local_context->ctx) {
1148 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1149 ret = lttng_event_context_app_populate_from_buffer(
1150 &subtype_view, local_context);
1151 break;
1152 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1153 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1154 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1155 ret = lttng_event_context_perf_counter_populate_from_buffer(
1156 &subtype_view, local_context);
1157 break;
1158 default:
1159 /* Nothing else to deserialize. */
1160 ret = 0;
1161 break;
1162 }
1163
1164 if (ret < 0) {
1165 goto end;
1166 }
1167
1168 offset += ret;
1169
1170 *event_ctx = local_context;
1171 local_context = NULL;
1172 ret = offset;
1173
1174 end:
1175 free(local_context);
1176 return ret;
1177 }
1178
1179 static int lttng_event_context_app_serialize(
1180 struct lttng_event_context *context,
1181 struct lttng_dynamic_buffer *buffer)
1182 {
1183 int ret;
1184 struct lttng_event_context_app_comm comm = { 0 };
1185 size_t provider_len, ctx_len;
1186 const char *provider_name;
1187 const char *ctx_name;
1188
1189 assert(buffer);
1190 assert(context);
1191 assert(context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
1192
1193 provider_name = context->u.app_ctx.provider_name;
1194 ctx_name = context->u.app_ctx.ctx_name;
1195
1196 if (!provider_name || !ctx_name) {
1197 ret = -LTTNG_ERR_INVALID;
1198 goto end;
1199 }
1200
1201 provider_len = strlen(provider_name);
1202 if (provider_len == 0) {
1203 ret = -LTTNG_ERR_INVALID;
1204 goto end;
1205 }
1206
1207 /* Include the null terminator. */
1208 provider_len += 1;
1209 comm.provider_name_len = provider_len;
1210
1211 ctx_len = strlen(ctx_name);
1212 if (ctx_len == 0) {
1213 ret = -LTTNG_ERR_INVALID;
1214 goto end;
1215 }
1216
1217 /* Include the null terminator. */
1218 ctx_len += 1;
1219 comm.ctx_name_len = ctx_len;
1220
1221 /* Header */
1222 ret = lttng_dynamic_buffer_append(buffer, &comm, sizeof(comm));
1223 if (ret) {
1224 ret = -1;
1225 goto end;
1226 }
1227
1228 ret = lttng_dynamic_buffer_append(buffer, provider_name, provider_len);
1229 if (ret) {
1230 ret = -1;
1231 goto end;
1232 }
1233 ret = lttng_dynamic_buffer_append(buffer, ctx_name, ctx_len);
1234 if (ret) {
1235 ret = -1;
1236 goto end;
1237 }
1238
1239 end:
1240 return ret;
1241 }
1242
1243 static int lttng_event_context_perf_counter_serialize(
1244 struct lttng_event_perf_counter_ctx *context,
1245 struct lttng_dynamic_buffer *buffer)
1246 {
1247 int ret;
1248 struct lttng_event_context_perf_counter_comm comm = { 0 };
1249
1250 assert(buffer);
1251 assert(context);
1252
1253 comm.config = context->config;
1254 comm.type = context->type;
1255 comm.name_len = lttng_strnlen(context->name, LTTNG_SYMBOL_NAME_LEN);
1256
1257 if (comm.name_len == LTTNG_SYMBOL_NAME_LEN) {
1258 ret = -1;
1259 goto end;
1260 }
1261
1262 /* Include the null terminator. */
1263 comm.name_len += 1;
1264
1265 /* Header */
1266 ret = lttng_dynamic_buffer_append(buffer, &comm, sizeof(comm));
1267 if (ret) {
1268 ret = -1;
1269 goto end;
1270 }
1271
1272 ret = lttng_dynamic_buffer_append(buffer, context->name, comm.name_len);
1273 if (ret) {
1274 ret = -1;
1275 goto end;
1276 }
1277
1278 end:
1279 return ret;
1280 }
1281
1282 LTTNG_HIDDEN
1283 int lttng_event_context_serialize(struct lttng_event_context *context,
1284 struct lttng_dynamic_buffer *buf)
1285 {
1286 int ret;
1287 struct lttng_event_context_comm context_comm = { 0 };
1288
1289 assert(context);
1290 assert(buf);
1291
1292 context_comm.type = (uint32_t) context->ctx;
1293
1294 /* Header */
1295 ret = lttng_dynamic_buffer_append(
1296 buf, &context_comm, sizeof(context_comm));
1297 if (ret) {
1298 goto end;
1299 }
1300
1301 switch (context->ctx) {
1302 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1303 ret = lttng_event_context_app_serialize(context, buf);
1304 break;
1305 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1306 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1307 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1308 ret = lttng_event_context_perf_counter_serialize(
1309 &context->u.perf_counter, buf);
1310 break;
1311 default:
1312 /* Nothing else to serialize. */
1313 break;
1314 }
1315
1316 if (ret) {
1317 goto end;
1318 }
1319
1320 end:
1321 return ret;
1322 }
1323
1324 LTTNG_HIDDEN
1325 void lttng_event_context_destroy(struct lttng_event_context *context)
1326 {
1327 if (!context) {
1328 return;
1329 }
1330
1331 if (context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
1332 free(context->u.app_ctx.provider_name);
1333 free(context->u.app_ctx.ctx_name);
1334 }
1335
1336 free(context);
1337 }
1338
1339 /*
1340 * This is a specialized populate for lttng_event_field since it ignores
1341 * the extension field of the lttng_event struct and simply copies what it can
1342 * to the internal struct lttng_event of a lttng_event_field.
1343 */
1344 static void lttng_event_field_populate_lttng_event_from_event(
1345 const struct lttng_event *src, struct lttng_event *destination)
1346 {
1347 memcpy(destination, src, sizeof(*destination));
1348
1349 /* Remove all possible dynamic data from the destination event rule. */
1350 destination->extended.ptr = NULL;
1351 }
1352
1353 LTTNG_HIDDEN
1354 ssize_t lttng_event_field_create_from_buffer(
1355 const struct lttng_buffer_view *view,
1356 struct lttng_event_field **field)
1357 {
1358 ssize_t ret, offset = 0;
1359 struct lttng_event_field *local_event_field = NULL;
1360 struct lttng_event *event = NULL;
1361 const struct lttng_event_field_comm *comm;
1362 const char* name = NULL;
1363
1364 assert(field);
1365 assert(view);
1366
1367 {
1368 const struct lttng_buffer_view comm_view =
1369 lttng_buffer_view_from_view(
1370 view, offset, sizeof(*comm));
1371
1372 if (!lttng_buffer_view_is_valid(&comm_view)) {
1373 ret = -1;
1374 goto end;
1375 }
1376 /* lttng_event_field_comm header */
1377 comm = (const struct lttng_event_field_comm *) view->data;
1378 offset += sizeof(*comm);
1379 }
1380
1381 local_event_field = zmalloc(sizeof(*local_event_field));
1382 if (!local_event_field) {
1383 ret = -1;
1384 goto end;
1385 }
1386
1387 local_event_field->type = comm->type;
1388 local_event_field->nowrite = comm->nowrite;
1389
1390 /* Field name */
1391 {
1392 const struct lttng_buffer_view name_view =
1393 lttng_buffer_view_from_view(
1394 view, offset, comm->name_len);
1395
1396 if (!lttng_buffer_view_is_valid(&name_view)) {
1397 ret = -1;
1398 goto end;
1399 }
1400
1401 name = name_view.data;
1402
1403 if (!lttng_buffer_view_contains_string(&name_view, name_view.data, comm->name_len)) {
1404 ret = -1;
1405 goto end;
1406 }
1407
1408 if (comm->name_len > LTTNG_SYMBOL_NAME_LEN - 1) {
1409 /* Name is too long.*/
1410 ret = -1;
1411 goto end;
1412 }
1413 offset += comm->name_len;
1414 }
1415
1416 /* Event */
1417 {
1418 const struct lttng_buffer_view event_view =
1419 lttng_buffer_view_from_view(
1420 view, offset, comm->event_len);
1421
1422 if (!lttng_buffer_view_is_valid(&event_view)) {
1423 ret = -1;
1424 goto end;
1425 }
1426 ret = lttng_event_create_from_buffer(&event_view, &event, NULL,
1427 NULL, NULL, -1);
1428 if (ret != comm->event_len) {
1429 abort();
1430 }
1431 offset += ret;
1432 }
1433
1434 assert(name);
1435 assert(event);
1436
1437 if (lttng_strncpy(local_event_field->field_name, name , LTTNG_SYMBOL_NAME_LEN)) {
1438 ret = -1;
1439 goto end;
1440 }
1441
1442 lttng_event_field_populate_lttng_event_from_event(
1443 event, &local_event_field->event);
1444
1445 *field = local_event_field;
1446 local_event_field = NULL;
1447 ret = offset;
1448 end:
1449 lttng_event_destroy(event);
1450 free(local_event_field);
1451 return ret;
1452 }
1453
1454 LTTNG_HIDDEN
1455 int lttng_event_field_serialize(const struct lttng_event_field *field,
1456 struct lttng_dynamic_buffer *buffer)
1457 {
1458 int ret;
1459 size_t header_offset, size_before_event;
1460 size_t name_len;
1461 struct lttng_event_field_comm event_field_comm = { 0 };
1462 struct lttng_event_field_comm *header;
1463
1464 assert(field);
1465 assert(buffer);
1466
1467 /* Save the header location for later in-place header update. */
1468 header_offset = buffer->size;
1469
1470 name_len = strnlen(field->field_name, LTTNG_SYMBOL_NAME_LEN);
1471 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
1472 /* Event name is not NULL-terminated. */
1473 ret = -1;
1474 goto end;
1475 }
1476
1477 /* Add null termination. */
1478 name_len += 1;
1479
1480 event_field_comm.type = field->type;
1481 event_field_comm.nowrite = (uint8_t)field->nowrite;
1482 event_field_comm.name_len = name_len;
1483
1484 /* Header */
1485 ret = lttng_dynamic_buffer_append(
1486 buffer, &event_field_comm, sizeof(event_field_comm));
1487 if (ret) {
1488 goto end;
1489 }
1490
1491 /* Field name */
1492 ret = lttng_dynamic_buffer_append(buffer, field->field_name, name_len);
1493 if (ret) {
1494 goto end;
1495 }
1496
1497 size_before_event = buffer->size;
1498 ret = lttng_event_serialize(
1499 &field->event, 0, NULL, NULL, 0, 0, buffer, NULL);
1500 if (ret) {
1501 ret = -1;
1502 goto end;
1503 }
1504
1505 /* Update the event len. */
1506 header = (struct lttng_event_field_comm *) ((char *) buffer->data +
1507 header_offset);
1508 header->event_len = buffer->size - size_before_event;
1509
1510 end:
1511 return ret;
1512 }
1513
1514 static enum lttng_error_code compute_flattened_size(
1515 struct lttng_dynamic_pointer_array *events, size_t *size)
1516 {
1517 enum lttng_error_code ret_code;
1518 int ret = 0;
1519 size_t storage_req, event_count, i;
1520
1521 assert(size);
1522 assert(events);
1523
1524 event_count = lttng_dynamic_pointer_array_get_count(events);
1525
1526 /* The basic struct lttng_event */
1527 storage_req = event_count * sizeof(struct lttng_event);
1528
1529 /* The struct lttng_event_extended */
1530 storage_req += event_count * sizeof(struct lttng_event_extended);
1531
1532 for (i = 0; i < event_count; i++) {
1533 int probe_storage_req = 0;
1534 const struct event_list_element *element =
1535 lttng_dynamic_pointer_array_get_pointer(
1536 events, i);
1537 const struct lttng_userspace_probe_location *location = NULL;
1538
1539 location = lttng_event_get_userspace_probe_location(
1540 element->event);
1541 if (location) {
1542 ret = lttng_userspace_probe_location_flatten(
1543 location, NULL);
1544 if (ret < 0) {
1545 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1546 goto end;
1547 }
1548
1549 probe_storage_req = ret;
1550 }
1551
1552 if (element->filter_expression) {
1553 storage_req += strlen(element->filter_expression) + 1;
1554 }
1555
1556 if (element->exclusions) {
1557 storage_req += element->exclusions->count *
1558 LTTNG_SYMBOL_NAME_LEN;
1559 }
1560
1561 /* Padding to ensure the flat probe is aligned. */
1562 storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
1563 storage_req += probe_storage_req;
1564 }
1565
1566 *size = storage_req;
1567 ret_code = LTTNG_OK;
1568
1569 end:
1570 return ret_code;
1571 }
1572
1573 /*
1574 * Flatten a list of struct lttng_event.
1575 *
1576 * The buffer that is returned to the API client must contain a "flat" version
1577 * of the events that are returned. In other words, all pointers within an
1578 * lttng_event must point to a location within the returned buffer so that the
1579 * user may free everything by simply calling free() on the returned buffer.
1580 * This is needed in order to maintain API compatibility.
1581 *
1582 * A first pass is performed to compute the size of the buffer that must be
1583 * allocated. A second pass is then performed to setup the returned events so
1584 * that their members always point within the buffer.
1585 *
1586 * The layout of the returned buffer is as follows:
1587 * - struct lttng_event[nb_events],
1588 * - nb_events times the following:
1589 * - struct lttng_event_extended,
1590 * - filter_expression
1591 * - exclusions
1592 * - padding to align to 64-bits
1593 * - flattened version of userspace_probe_location
1594 */
1595 static enum lttng_error_code flatten_lttng_events(
1596 struct lttng_dynamic_pointer_array *events,
1597 struct lttng_event **flattened_events)
1598 {
1599 enum lttng_error_code ret_code;
1600 int ret, i;
1601 size_t storage_req;
1602 struct lttng_dynamic_buffer local_flattened_events;
1603 int nb_events;
1604
1605 assert(events);
1606 assert(flattened_events);
1607
1608 lttng_dynamic_buffer_init(&local_flattened_events);
1609 nb_events = lttng_dynamic_pointer_array_get_count(events);
1610
1611 ret_code = compute_flattened_size(events, &storage_req);
1612 if (ret_code != LTTNG_OK) {
1613 goto end;
1614 }
1615
1616 /*
1617 * We must ensure that "local_flattened_events" is never resized so as
1618 * to preserve the validity of the flattened objects.
1619 */
1620 ret = lttng_dynamic_buffer_set_capacity(
1621 &local_flattened_events, storage_req);
1622 if (ret) {
1623 ret_code = LTTNG_ERR_NOMEM;
1624 goto end;
1625 }
1626
1627 /* Start by laying the struct lttng_event */
1628 for (i = 0; i < nb_events; i++) {
1629 struct event_list_element *element =
1630 lttng_dynamic_pointer_array_get_pointer(
1631 events, i);
1632
1633 if (!element) {
1634 ret_code = LTTNG_ERR_FATAL;
1635 goto end;
1636 }
1637 ret = lttng_dynamic_buffer_append(&local_flattened_events,
1638 element->event, sizeof(struct lttng_event));
1639 if (ret) {
1640 ret_code = LTTNG_ERR_NOMEM;
1641 goto end;
1642 }
1643 }
1644
1645 for (i = 0; i < nb_events; i++) {
1646 struct event_list_element *element = lttng_dynamic_pointer_array_get_pointer(events, i);
1647 struct lttng_event *event = (struct lttng_event *)
1648 (local_flattened_events.data + (sizeof(struct lttng_event) * i));
1649 struct lttng_event_extended *event_extended =
1650 (struct lttng_event_extended *)
1651 (local_flattened_events.data + local_flattened_events.size);
1652 const struct lttng_userspace_probe_location *location = NULL;
1653
1654 assert(element);
1655
1656 /* Insert struct lttng_event_extended. */
1657 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1658 local_flattened_events.size +
1659 sizeof(*event_extended));
1660 if (ret) {
1661 ret_code = LTTNG_ERR_NOMEM;
1662 goto end;
1663 }
1664 event->extended.ptr = event_extended;
1665
1666 /* Insert filter expression. */
1667 if (element->filter_expression) {
1668 size_t len = strlen(element->filter_expression) + 1;
1669
1670 event_extended->filter_expression =
1671 local_flattened_events.data +
1672 local_flattened_events.size;
1673 ret = lttng_dynamic_buffer_append(
1674 &local_flattened_events,
1675 element->filter_expression, len);
1676 if (ret) {
1677 ret_code = LTTNG_ERR_NOMEM;
1678 goto end;
1679 }
1680 }
1681
1682 /* Insert exclusions. */
1683 if (element->exclusions) {
1684 event_extended->exclusions.count =
1685 element->exclusions->count;
1686 event_extended->exclusions.strings =
1687 local_flattened_events.data +
1688 local_flattened_events.size;
1689
1690 ret = lttng_dynamic_buffer_append(
1691 &local_flattened_events,
1692 element->exclusions->names,
1693 element->exclusions->count *
1694 LTTNG_SYMBOL_NAME_LEN);
1695 if (ret) {
1696 ret_code = LTTNG_ERR_NOMEM;
1697 goto end;
1698 }
1699 }
1700
1701 /* Insert padding to align to 64-bits. */
1702 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1703 ALIGN_TO(local_flattened_events.size,
1704 sizeof(uint64_t)));
1705 if (ret) {
1706 ret_code = LTTNG_ERR_NOMEM;
1707 goto end;
1708 }
1709
1710 location = lttng_event_get_userspace_probe_location(
1711 element->event);
1712 if (location) {
1713 event_extended->probe_location = (struct lttng_userspace_probe_location *)
1714 (local_flattened_events.data + local_flattened_events.size);
1715 ret = lttng_userspace_probe_location_flatten(
1716 location, &local_flattened_events);
1717 if (ret < 0) {
1718 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1719 goto end;
1720 }
1721 }
1722 }
1723
1724 /* Don't reset local_flattened_events buffer as we return its content. */
1725 *flattened_events = (struct lttng_event *) local_flattened_events.data;
1726 lttng_dynamic_buffer_init(&local_flattened_events);
1727 ret_code = LTTNG_OK;
1728 end:
1729 lttng_dynamic_buffer_reset(&local_flattened_events);
1730 return ret_code;
1731 }
1732
1733 static enum lttng_error_code event_list_create_from_buffer(
1734 const struct lttng_buffer_view *view,
1735 unsigned int count,
1736 struct lttng_dynamic_pointer_array *event_list)
1737 {
1738 enum lttng_error_code ret_code;
1739 int ret;
1740 unsigned int i;
1741 int offset = 0;
1742
1743 assert(view);
1744 assert(event_list);
1745
1746 for (i = 0; i < count; i++) {
1747 ssize_t event_size;
1748 const struct lttng_buffer_view event_view =
1749 lttng_buffer_view_from_view(view, offset, -1);
1750 struct event_list_element *element = zmalloc(sizeof(*element));
1751
1752 if (!element) {
1753 ret_code = LTTNG_ERR_NOMEM;
1754 goto end;
1755 }
1756
1757 /*
1758 * Lifetime and management of the object is now bound to the
1759 * array.
1760 */
1761 ret = lttng_dynamic_pointer_array_add_pointer(
1762 event_list, element);
1763 if (ret) {
1764 event_list_destructor(element);
1765 ret_code = LTTNG_ERR_NOMEM;
1766 goto end;
1767 }
1768
1769 /*
1770 * Bytecode is not transmitted on listing in any case we do not
1771 * care about it.
1772 */
1773 event_size = lttng_event_create_from_buffer(&event_view,
1774 &element->event,
1775 &element->exclusions,
1776 &element->filter_expression, NULL, -1);
1777 if (event_size < 0) {
1778 ret_code = LTTNG_ERR_INVALID;
1779 goto end;
1780 }
1781
1782 offset += event_size;
1783 }
1784
1785 if (view->size != offset) {
1786 ret_code = LTTNG_ERR_INVALID;
1787 goto end;
1788 }
1789
1790 ret_code = LTTNG_OK;
1791
1792 end:
1793 return ret_code;
1794 }
1795
1796 LTTNG_HIDDEN
1797 enum lttng_error_code lttng_events_create_and_flatten_from_buffer(
1798 const struct lttng_buffer_view *view,
1799 unsigned int count,
1800 struct lttng_event **events)
1801 {
1802 enum lttng_error_code ret = LTTNG_OK;
1803 struct lttng_dynamic_pointer_array local_events;
1804
1805 lttng_dynamic_pointer_array_init(&local_events, event_list_destructor);
1806
1807 /* Deserialize the events */
1808 {
1809 const struct lttng_buffer_view events_view =
1810 lttng_buffer_view_from_view(view, 0, -1);
1811
1812 ret = event_list_create_from_buffer(
1813 &events_view, count, &local_events);
1814 if (ret != LTTNG_OK) {
1815 goto end;
1816 }
1817 }
1818
1819 ret = flatten_lttng_events(&local_events, events);
1820 if (ret != LTTNG_OK) {
1821 goto end;
1822 }
1823
1824 end:
1825 lttng_dynamic_pointer_array_reset(&local_events);
1826 return ret;
1827 }
1828
1829 static enum lttng_error_code flatten_lttng_event_fields(
1830 struct lttng_dynamic_pointer_array *event_fields,
1831 struct lttng_event_field **flattened_event_fields)
1832 {
1833 int ret, i;
1834 enum lttng_error_code ret_code;
1835 size_t storage_req = 0;
1836 struct lttng_dynamic_buffer local_flattened_event_fields;
1837 int nb_event_field;
1838
1839 assert(event_fields);
1840 assert(flattened_event_fields);
1841
1842 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1843 nb_event_field = lttng_dynamic_pointer_array_get_count(event_fields);
1844
1845 /*
1846 * Here even if the event field contains a `struct lttng_event` that
1847 * could contain dynamic data, in reality it is not the case.
1848 * Dynamic data is not present. Here the flattening is mostly a direct
1849 * memcpy. This is less than ideal but this code is still better than
1850 * direct usage of an unpacked lttng_event_field array.
1851 */
1852 storage_req += sizeof(struct lttng_event_field) * nb_event_field;
1853
1854 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1855
1856 /*
1857 * We must ensure that "local_flattened_event_fields" is never resized
1858 * so as to preserve the validity of the flattened objects.
1859 */
1860 ret = lttng_dynamic_buffer_set_capacity(
1861 &local_flattened_event_fields, storage_req);
1862 if (ret) {
1863 ret_code = LTTNG_ERR_NOMEM;
1864 goto end;
1865 }
1866
1867 for (i = 0; i < nb_event_field; i++) {
1868 const struct lttng_event_field *element =
1869 lttng_dynamic_pointer_array_get_pointer(
1870 event_fields, i);
1871
1872 if (!element) {
1873 ret_code = LTTNG_ERR_FATAL;
1874 goto end;
1875 }
1876 ret = lttng_dynamic_buffer_append(&local_flattened_event_fields,
1877 element, sizeof(struct lttng_event_field));
1878 if (ret) {
1879 ret_code = LTTNG_ERR_NOMEM;
1880 goto end;
1881 }
1882 }
1883
1884 /* Don't reset local_flattened_channels buffer as we return its content. */
1885 *flattened_event_fields = (struct lttng_event_field *) local_flattened_event_fields.data;
1886 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1887 ret_code = LTTNG_OK;
1888 end:
1889 lttng_dynamic_buffer_reset(&local_flattened_event_fields);
1890 return ret_code;
1891 }
1892
1893 static enum lttng_error_code event_field_list_create_from_buffer(
1894 const struct lttng_buffer_view *view,
1895 unsigned int count,
1896 struct lttng_dynamic_pointer_array **event_field_list)
1897 {
1898 enum lttng_error_code ret_code;
1899 int ret, offset = 0;
1900 unsigned int i;
1901 struct lttng_dynamic_pointer_array *list = NULL;
1902
1903 assert(view);
1904 assert(event_field_list);
1905
1906 list = zmalloc(sizeof(*list));
1907 if (!list) {
1908 ret_code = LTTNG_ERR_NOMEM;
1909 goto end;
1910 }
1911
1912 lttng_dynamic_pointer_array_init(list, free);
1913
1914 for (i = 0; i < count; i++) {
1915 ssize_t event_field_size;
1916 struct lttng_event_field *field = NULL;
1917 const struct lttng_buffer_view event_field_view =
1918 lttng_buffer_view_from_view(view, offset, -1);
1919
1920 event_field_size = lttng_event_field_create_from_buffer(
1921 &event_field_view, &field);
1922 if (event_field_size < 0) {
1923 ret_code = LTTNG_ERR_INVALID;
1924 goto end;
1925 }
1926
1927 /* Lifetime and management of the object is now bound to the array. */
1928 ret = lttng_dynamic_pointer_array_add_pointer(list, field);
1929 if (ret) {
1930 free(field);
1931 ret_code = LTTNG_ERR_NOMEM;
1932 goto end;
1933 }
1934 offset += event_field_size;
1935 }
1936
1937 if (view->size != offset) {
1938 ret_code = LTTNG_ERR_INVALID;
1939 goto end;
1940 }
1941
1942 *event_field_list = list;
1943 list = NULL;
1944 ret_code = LTTNG_OK;
1945
1946 end:
1947 if (list) {
1948 lttng_dynamic_pointer_array_reset(list);
1949 free(list);
1950 }
1951 return ret_code;
1952 }
1953
1954 LTTNG_HIDDEN
1955 enum lttng_error_code lttng_event_fields_create_and_flatten_from_buffer(
1956 const struct lttng_buffer_view *view,
1957 unsigned int count,
1958 struct lttng_event_field **fields)
1959 {
1960 enum lttng_error_code ret;
1961 struct lttng_dynamic_pointer_array *local_event_fields = NULL;
1962
1963 ret = event_field_list_create_from_buffer(
1964 view, count, &local_event_fields);
1965 if (ret != LTTNG_OK) {
1966 goto end;
1967 }
1968
1969 ret = flatten_lttng_event_fields(local_event_fields, fields);
1970 if (ret != LTTNG_OK) {
1971 goto end;
1972 }
1973 end:
1974 if (local_event_fields) {
1975 lttng_dynamic_pointer_array_reset(local_event_fields);
1976 free(local_event_fields);
1977 }
1978 return ret;
1979 }
This page took 0.068185 seconds and 4 git commands to generate.