56af0caaa063979148b85bd967be689ac7fd4871
[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 for (i = 0; i < event_count; i++) {
1529 int probe_storage_req = 0;
1530 const struct event_list_element *element =
1531 lttng_dynamic_pointer_array_get_pointer(
1532 events, i);
1533 const struct lttng_userspace_probe_location *location = NULL;
1534
1535 location = lttng_event_get_userspace_probe_location(
1536 element->event);
1537 if (location) {
1538 ret = lttng_userspace_probe_location_flatten(
1539 location, NULL);
1540 if (ret < 0) {
1541 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1542 goto end;
1543 }
1544
1545 probe_storage_req = ret;
1546 }
1547
1548 /* The struct·lttng_event_extended */
1549 storage_req += event_count *
1550 sizeof(struct lttng_event_extended);
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.064674 seconds and 3 git commands to generate.