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