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