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