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