Fix: liblttng-ctl comm: lttng_event 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
949static enum lttng_error_code compute_flattened_size(
950 struct lttng_dynamic_pointer_array *events, size_t *size)
951{
952 enum lttng_error_code ret_code;
953 int ret = 0;
954 size_t storage_req, event_count, i;
955
956 assert(size);
957 assert(events);
958
959 event_count = lttng_dynamic_pointer_array_get_count(events);
960
961 /* The basic struct lttng_event */
962 storage_req = event_count * sizeof(struct lttng_event);
963
964 for (i = 0; i < event_count; i++) {
965 int probe_storage_req = 0;
966 const struct event_list_element *element =
967 lttng_dynamic_pointer_array_get_pointer(
968 events, i);
969 const struct lttng_userspace_probe_location *location = NULL;
970
971 location = lttng_event_get_userspace_probe_location(
972 element->event);
973 if (location) {
974 ret = lttng_userspace_probe_location_flatten(
975 location, NULL);
976 if (ret < 0) {
977 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
978 goto end;
979 }
980
981 probe_storage_req = ret;
982 }
983
984 /* The struct·lttng_event_extended */
985 storage_req += event_count *
986 sizeof(struct lttng_event_extended);
987
988 if (element->filter_expression) {
989 storage_req += strlen(element->filter_expression) + 1;
990 }
991
992 if (element->exclusions) {
993 storage_req += element->exclusions->count *
994 LTTNG_SYMBOL_NAME_LEN;
995 }
996
997 /* Padding to ensure the flat probe is aligned. */
998 storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
999 storage_req += probe_storage_req;
1000 }
1001
1002 *size = storage_req;
1003 ret_code = LTTNG_OK;
1004
1005end:
1006 return ret_code;
1007}
1008
1009/*
1010 * Flatten a list of struct lttng_event.
1011 *
1012 * The buffer that is returned to the API client must contain a "flat" version
1013 * of the events that are returned. In other words, all pointers within an
1014 * lttng_event must point to a location within the returned buffer so that the
1015 * user may free everything by simply calling free() on the returned buffer.
1016 * This is needed in order to maintain API compatibility.
1017 *
1018 * A first pass is performed to compute the size of the buffer that must be
1019 * allocated. A second pass is then performed to setup the returned events so
1020 * that their members always point within the buffer.
1021 *
1022 * The layout of the returned buffer is as follows:
1023 * - struct lttng_event[nb_events],
1024 * - nb_events times the following:
1025 * - struct lttng_event_extended,
1026 * - filter_expression
1027 * - exclusions
1028 * - padding to align to 64-bits
1029 * - flattened version of userspace_probe_location
1030 */
1031static enum lttng_error_code flatten_lttng_events(
1032 struct lttng_dynamic_pointer_array *events,
1033 struct lttng_event **flattened_events)
1034{
1035 enum lttng_error_code ret_code;
1036 int ret, i;
1037 size_t storage_req;
1038 struct lttng_dynamic_buffer local_flattened_events;
1039 int nb_events;
1040
1041 assert(events);
1042 assert(flattened_events);
1043
1044 lttng_dynamic_buffer_init(&local_flattened_events);
1045 nb_events = lttng_dynamic_pointer_array_get_count(events);
1046
1047 ret_code = compute_flattened_size(events, &storage_req);
1048 if (ret_code != LTTNG_OK) {
1049 goto end;
1050 }
1051
1052 /*
1053 * We must ensure that "local_flattened_events" is never resized so as
1054 * to preserve the validity of the flattened objects.
1055 */
1056 ret = lttng_dynamic_buffer_set_capacity(
1057 &local_flattened_events, storage_req);
1058 if (ret) {
1059 ret_code = LTTNG_ERR_NOMEM;
1060 goto end;
1061 }
1062
1063 /* Start by laying the struct lttng_event */
1064 for (i = 0; i < nb_events; i++) {
1065 struct event_list_element *element =
1066 lttng_dynamic_pointer_array_get_pointer(
1067 events, i);
1068
1069 if (!element) {
1070 ret_code = LTTNG_ERR_FATAL;
1071 goto end;
1072 }
1073 ret = lttng_dynamic_buffer_append(&local_flattened_events,
1074 element->event, sizeof(struct lttng_event));
1075 if (ret) {
1076 ret_code = LTTNG_ERR_NOMEM;
1077 goto end;
1078 }
1079 }
1080
1081 for (i = 0; i < nb_events; i++) {
1082 struct event_list_element *element = lttng_dynamic_pointer_array_get_pointer(events, i);
1083 struct lttng_event *event = (struct lttng_event *)
1084 (local_flattened_events.data + (sizeof(struct lttng_event) * i));
1085 struct lttng_event_extended *event_extended =
1086 (struct lttng_event_extended *)
1087 (local_flattened_events.data + local_flattened_events.size);
1088 const struct lttng_userspace_probe_location *location = NULL;
1089
1090 assert(element);
1091
1092 /* Insert struct lttng_event_extended. */
1093 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1094 local_flattened_events.size +
1095 sizeof(*event_extended));
1096 if (ret) {
1097 ret_code = LTTNG_ERR_NOMEM;
1098 goto end;
1099 }
1100 event->extended.ptr = event_extended;
1101
1102 /* Insert filter expression. */
1103 if (element->filter_expression) {
1104 size_t len = strlen(element->filter_expression) + 1;
1105
1106 event_extended->filter_expression =
1107 local_flattened_events.data +
1108 local_flattened_events.size;
1109 ret = lttng_dynamic_buffer_append(
1110 &local_flattened_events,
1111 element->filter_expression, len);
1112 if (ret) {
1113 ret_code = LTTNG_ERR_NOMEM;
1114 goto end;
1115 }
1116 }
1117
1118 /* Insert exclusions. */
1119 if (element->exclusions) {
1120 event_extended->exclusions.count =
1121 element->exclusions->count;
1122 event_extended->exclusions.strings =
1123 local_flattened_events.data +
1124 local_flattened_events.size;
1125
1126 ret = lttng_dynamic_buffer_append(
1127 &local_flattened_events,
1128 element->exclusions->names,
1129 element->exclusions->count *
1130 LTTNG_SYMBOL_NAME_LEN);
1131 if (ret) {
1132 ret_code = LTTNG_ERR_NOMEM;
1133 goto end;
1134 }
1135 }
1136
1137 /* Insert padding to align to 64-bits. */
1138 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1139 ALIGN_TO(local_flattened_events.size,
1140 sizeof(uint64_t)));
1141 if (ret) {
1142 ret_code = LTTNG_ERR_NOMEM;
1143 goto end;
1144 }
1145
1146 location = lttng_event_get_userspace_probe_location(
1147 element->event);
1148 if (location) {
1149 event_extended->probe_location = (struct lttng_userspace_probe_location *)
1150 (local_flattened_events.data + local_flattened_events.size);
1151 ret = lttng_userspace_probe_location_flatten(
1152 location, &local_flattened_events);
1153 if (ret < 0) {
1154 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1155 goto end;
1156 }
1157 }
1158 }
1159
1160 /* Don't reset local_flattened_events buffer as we return its content. */
1161 *flattened_events = (struct lttng_event *) local_flattened_events.data;
1162 lttng_dynamic_buffer_init(&local_flattened_events);
1163 ret_code = LTTNG_OK;
1164end:
1165 lttng_dynamic_buffer_reset(&local_flattened_events);
1166 return ret_code;
1167}
1168
1169static enum lttng_error_code event_list_create_from_buffer(
1170 const struct lttng_buffer_view *view,
1171 unsigned int count,
1172 struct lttng_dynamic_pointer_array *event_list)
1173{
1174 enum lttng_error_code ret_code;
1175 int ret;
1176 unsigned int i;
1177 int offset = 0;
1178
1179 assert(view);
1180 assert(event_list);
1181
1182 for (i = 0; i < count; i++) {
1183 ssize_t event_size;
1184 const struct lttng_buffer_view event_view =
1185 lttng_buffer_view_from_view(view, offset, -1);
1186 struct event_list_element *element = zmalloc(sizeof(*element));
1187
1188 if (!element) {
1189 ret_code = LTTNG_ERR_NOMEM;
1190 goto end;
1191 }
1192
1193 /*
1194 * Lifetime and management of the object is now bound to the
1195 * array.
1196 */
1197 ret = lttng_dynamic_pointer_array_add_pointer(
1198 event_list, element);
1199 if (ret) {
1200 event_list_destructor(element);
1201 ret_code = LTTNG_ERR_NOMEM;
1202 goto end;
1203 }
1204
1205 /*
1206 * Bytecode is not transmitted on listing in any case we do not
1207 * care about it.
1208 */
1209 event_size = lttng_event_create_from_buffer(&event_view,
1210 &element->event,
1211 &element->exclusions,
1212 &element->filter_expression, NULL, -1);
1213 if (event_size < 0) {
1214 ret_code = LTTNG_ERR_INVALID;
1215 goto end;
1216 }
1217
1218 offset += event_size;
1219 }
1220
1221 if (view->size != offset) {
1222 ret_code = LTTNG_ERR_INVALID;
1223 goto end;
1224 }
1225
1226 ret_code = LTTNG_OK;
1227
1228end:
1229 return ret_code;
1230}
1231
1232LTTNG_HIDDEN
1233enum lttng_error_code lttng_events_create_and_flatten_from_buffer(
1234 const struct lttng_buffer_view *view,
1235 unsigned int count,
1236 struct lttng_event **events)
1237{
1238 enum lttng_error_code ret = LTTNG_OK;
1239 struct lttng_dynamic_pointer_array local_events;
1240
1241 lttng_dynamic_pointer_array_init(&local_events, event_list_destructor);
1242
1243 /* Deserialize the events */
1244 {
1245 const struct lttng_buffer_view events_view =
1246 lttng_buffer_view_from_view(view, 0, -1);
1247
1248 ret = event_list_create_from_buffer(
1249 &events_view, count, &local_events);
1250 if (ret != LTTNG_OK) {
1251 goto end;
1252 }
1253 }
1254
1255 ret = flatten_lttng_events(&local_events, events);
1256 if (ret != LTTNG_OK) {
1257 goto end;
1258 }
1259
1260end:
1261 lttng_dynamic_pointer_array_reset(&local_events);
1262 return ret;
1263}
This page took 0.081461 seconds and 4 git commands to generate.