Rename C++ header files to .hpp
[lttng-tools.git] / src / common / event.cpp
CommitLineData
76fcf151 1/*
ab5be9fa 2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
76fcf151 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
76fcf151 5 *
76fcf151
JG
6 */
7
c9e313bc
SM
8#include <common/align.hpp>
9#include <common/buffer-view.hpp>
10#include <common/compat/string.hpp>
11#include <common/dynamic-array.hpp>
12#include <common/dynamic-buffer.hpp>
13#include <common/error.hpp>
14#include <common/macros.hpp>
15#include <common/sessiond-comm/sessiond-comm.hpp>
16
8ddd72ef 17#include <lttng/constant.h>
c9e313bc 18#include <lttng/event-internal.hpp>
8ddd72ef 19#include <lttng/event.h>
c9e313bc
SM
20#include <lttng/lttng-error.h>
21#include <lttng/userspace-probe-internal.hpp>
8ddd72ef
JR
22
23struct event_list_element {
24 struct lttng_event *event;
25 struct lttng_event_exclusion *exclusions;
26 char *filter_expression;
27};
28
29static void event_list_destructor(void *ptr)
30{
31 struct event_list_element *element = (struct event_list_element *) ptr;
32
33 free(element->filter_expression);
34 free(element->exclusions);
35 lttng_event_destroy(element->event);
36 free(element);
37}
76fcf151 38
76fcf151
JG
39struct lttng_event *lttng_event_copy(const struct lttng_event *event)
40{
41 struct lttng_event *new_event;
42 struct lttng_event_extended *new_event_extended;
43
a6bc4ca9 44 new_event = (lttng_event *) zmalloc(sizeof(*event));
76fcf151
JG
45 if (!new_event) {
46 PERROR("Error allocating event structure");
47 goto end;
48 }
49
50 /* Copy the content of the old event. */
51 memcpy(new_event, event, sizeof(*event));
52
53 /*
54 * We need to create a new extended since the previous pointer is now
55 * invalid.
56 */
a6bc4ca9 57 new_event_extended = (lttng_event_extended *) zmalloc(sizeof(*new_event_extended));
76fcf151
JG
58 if (!new_event_extended) {
59 PERROR("Error allocating event extended structure");
60 goto error;
61 }
62
63 new_event->extended.ptr = new_event_extended;
64end:
65 return new_event;
66error:
67 free(new_event);
37750a61 68 new_event = NULL;
76fcf151
JG
69 goto end;
70}
8ddd72ef
JR
71
72static int lttng_event_probe_attr_serialize(
73 const struct lttng_event_probe_attr *probe,
74 struct lttng_payload *payload)
75{
76 int ret;
77 size_t symbol_name_len;
1c9a0b0e 78 struct lttng_event_probe_attr_comm comm = {};
8ddd72ef 79
2d6df81a
JG
80 symbol_name_len = lttng_strnlen(
81 probe->symbol_name, sizeof(probe->symbol_name));
82 if (symbol_name_len == sizeof(probe->symbol_name)) {
8ddd72ef
JR
83 /* Not null-termintated. */
84 ret = -1;
85 goto end;
86 }
87
88 /* Include the null terminator. */
89 symbol_name_len += 1;
90
91 comm.symbol_name_len = (uint32_t) symbol_name_len;
92 comm.addr = probe->addr;
93 comm.offset = probe->addr;
94
95 ret = lttng_dynamic_buffer_append(
96 &payload->buffer, &comm, sizeof(comm));
97 if (ret < 0) {
98 ret = -1;
99 goto end;
100 }
101
102 ret = lttng_dynamic_buffer_append(
103 &payload->buffer, probe->symbol_name, symbol_name_len);
104end:
105 return ret;
106}
107
108static int lttng_event_function_attr_serialize(
109 const struct lttng_event_function_attr *function,
110 struct lttng_payload *payload)
111{
112 int ret;
113 size_t symbol_name_len;
114 struct lttng_event_function_attr_comm comm = { 0 };
115
2d6df81a
JG
116 symbol_name_len = lttng_strnlen(
117 function->symbol_name, sizeof(function->symbol_name));
118 if (symbol_name_len == sizeof(function->symbol_name)) {
8ddd72ef
JR
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);
138end:
139 return ret;
140}
141
142static 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,
2d6df81a 190 sizeof(local_attr->symbol_name));
8ddd72ef
JR
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;
202end:
9eb895d7 203 free(local_attr);
8ddd72ef
JR
204 return ret;
205}
206
207static 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,
2d6df81a 252 sizeof(local_attr->symbol_name));
8ddd72ef
JR
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;
264end:
9eb895d7 265 free(local_attr);
8ddd72ef
JR
266 return ret;
267}
268
269static 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
62e6775c
JG
320 ret = lttng_strncpy(LTTNG_EVENT_EXCLUSION_NAME_AT(local_exclusions, i), string,
321 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(local_exclusions, i)));
8ddd72ef
JR
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;
333end:
334 free(local_exclusions);
335 return ret;
336}
337
338ssize_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
2d6df81a
JG
409 ret = lttng_strncpy(local_event->name, name,
410 sizeof(local_event->name));
8ddd72ef
JR
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
445deserialize_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
531deserialize_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) {
8899bce1 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);
8ddd72ef
JR
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;
680end:
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
691int 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;
1c9a0b0e 703 struct lttng_event_comm event_comm = {};
8ddd72ef
JR
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
2d6df81a
JG
713 name_len = lttng_strnlen(event->name, sizeof(event->name));
714 if (name_len == sizeof(event->name)) {
8ddd72ef
JR
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
887end:
888 return ret;
889}
890
26e1c61f
JR
891static 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;
989end:
990 free(provider_name);
991 free(context_name);
992
993 return ret;
994}
995
996static 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{
531e96a7
JR
1000 int ret;
1001 ssize_t consumed, offset = 0;
26e1c61f
JR
1002 const struct lttng_event_context_perf_counter_comm *comm;
1003 size_t name_len;
1004 const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1005 &view->buffer, offset, sizeof(*comm));
1006
1007 assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER ||
1008 event_ctx->ctx ==
1009 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER ||
1010 event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER);
1011
1012 if (!lttng_buffer_view_is_valid(&comm_view)) {
531e96a7 1013 consumed = -1;
26e1c61f
JR
1014 goto end;
1015 }
1016
1017 comm = (typeof(comm)) comm_view.data;
1018 offset += sizeof(*comm);
1019
1020 name_len = comm->name_len;
1021
1022 {
1023 const char *name;
1024 const struct lttng_buffer_view provider_name_view =
1025 lttng_buffer_view_from_view(
1026 &view->buffer, offset,
1027 name_len);
1028
1029 if (!lttng_buffer_view_is_valid(&provider_name_view)) {
531e96a7 1030 consumed = -1;
26e1c61f
JR
1031 goto end;
1032 }
1033
1034 name = provider_name_view.data;
1035
1036 if (!lttng_buffer_view_contains_string(
1037 &provider_name_view, name, name_len)) {
531e96a7 1038 consumed = -1;
26e1c61f
JR
1039 goto end;
1040 }
1041
97f9ed7d
JG
1042 ret = lttng_strncpy(event_ctx->u.perf_counter.name, name,
1043 sizeof(event_ctx->u.perf_counter.name));
531e96a7
JR
1044 if (ret) {
1045 consumed = -1;
1046 goto end;
1047 }
26e1c61f
JR
1048 offset += name_len;
1049 }
1050
1051 event_ctx->u.perf_counter.config = comm->config;
1052 event_ctx->u.perf_counter.type = comm->type;
1053
531e96a7 1054 consumed = offset;
26e1c61f
JR
1055
1056end:
531e96a7 1057 return consumed;
26e1c61f
JR
1058}
1059
1060ssize_t lttng_event_context_create_from_payload(
1061 struct lttng_payload_view *view,
1062 struct lttng_event_context **event_ctx)
1063{
1064 ssize_t ret, offset = 0;
1065 const struct lttng_event_context_comm *comm;
1066 struct lttng_event_context *local_context = NULL;
1067 struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1068 &view->buffer, offset, sizeof(*comm));
1069
1070 assert(event_ctx);
1071 assert(view);
1072
1073 if (!lttng_buffer_view_is_valid(&comm_view)) {
1074 ret = -1;
1075 goto end;
1076 }
1077
1078 comm = (typeof(comm)) comm_view.data;
1079 offset += sizeof(*comm);
1080
1081 local_context = (struct lttng_event_context *)
1082 zmalloc(sizeof(*local_context));
1083 if (!local_context) {
1084 ret = -1;
1085 goto end;
1086 }
1087
1088 local_context->ctx = (lttng_event_context_type) comm->type;
1089
1090 {
1091 struct lttng_payload_view subtype_view =
1092 lttng_payload_view_from_view(view, offset, -1);
1093
1094 switch (local_context->ctx) {
1095 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1096 ret = lttng_event_context_app_populate_from_payload(
1097 &subtype_view, local_context);
1098 break;
1099 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1100 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1101 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1102 ret = lttng_event_context_perf_counter_populate_from_payload(
1103 &subtype_view, local_context);
1104 break;
1105 default:
1106 /* Nothing else to deserialize. */
1107 ret = 0;
1108 break;
1109 }
1110 }
1111
1112 if (ret < 0) {
1113 goto end;
1114 }
1115
1116 offset += ret;
1117
1118 *event_ctx = local_context;
1119 local_context = NULL;
1120 ret = offset;
1121
1122end:
1123 free(local_context);
1124 return ret;
1125}
1126
1127static int lttng_event_context_app_serialize(
1128 struct lttng_event_context *context,
1129 struct lttng_payload *payload)
1130{
1131 int ret;
1c9a0b0e 1132 struct lttng_event_context_app_comm comm = {};
26e1c61f
JR
1133 size_t provider_len, ctx_len;
1134 const char *provider_name;
1135 const char *ctx_name;
1136
1137 assert(payload);
1138 assert(context);
1139 assert(context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
1140
1141 provider_name = context->u.app_ctx.provider_name;
1142 ctx_name = context->u.app_ctx.ctx_name;
1143
1144 if (!provider_name || !ctx_name) {
1145 ret = -LTTNG_ERR_INVALID;
1146 goto end;
1147 }
1148
1149 provider_len = strlen(provider_name);
1150 if (provider_len == 0) {
1151 ret = -LTTNG_ERR_INVALID;
1152 goto end;
1153 }
1154
1155 /* Include the null terminator. */
f4f239b3
JR
1156 provider_len += 1;
1157 comm.provider_name_len = provider_len;
26e1c61f
JR
1158
1159 ctx_len = strlen(ctx_name);
1160 if (ctx_len == 0) {
1161 ret = -LTTNG_ERR_INVALID;
1162 goto end;
1163 }
1164
1165 /* Include the null terminator. */
f4f239b3
JR
1166 ctx_len += 1;
1167 comm.ctx_name_len = ctx_len;
26e1c61f
JR
1168
1169 /* Header */
1170 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
1171 sizeof(comm));
1172 if (ret) {
1173 ret = -1;
1174 goto end;
1175 }
1176
1177 ret = lttng_dynamic_buffer_append(&payload->buffer, provider_name,
1178 provider_len);
1179 if (ret) {
1180 ret = -1;
1181 goto end;
1182 }
1183
1184 ret = lttng_dynamic_buffer_append(&payload->buffer, ctx_name,
1185 ctx_len);
1186 if (ret) {
1187 ret = -1;
1188 goto end;
1189 }
1190
1191end:
1192 return ret;
1193}
1194
1195static int lttng_event_context_perf_counter_serialize(
1196 struct lttng_event_perf_counter_ctx *context,
1197 struct lttng_payload *payload)
1198{
1199 int ret;
1c9a0b0e 1200 struct lttng_event_context_perf_counter_comm comm = {};
26e1c61f
JR
1201
1202 assert(payload);
1203 assert(context);
1204
1205 comm.config = context->config;
1206 comm.type = context->type;
2d6df81a 1207 comm.name_len = lttng_strnlen(context->name, sizeof(context->name));
26e1c61f 1208
2d6df81a 1209 if (comm.name_len == sizeof(context->name)) {
26e1c61f
JR
1210 ret = -1;
1211 goto end;
1212 }
1213
1214 /* Include the null terminator. */
1215 comm.name_len += 1;
1216
1217 /* Header */
1218 ret = lttng_dynamic_buffer_append(&payload->buffer, &comm,
1219 sizeof(comm));
1220 if (ret) {
1221 ret = -1;
1222 goto end;
1223 }
1224
1225 ret = lttng_dynamic_buffer_append(&payload->buffer, context->name,
1226 comm.name_len);
1227 if (ret) {
1228 ret = -1;
1229 goto end;
1230 }
1231
1232end:
1233 return ret;
1234}
1235
1236int lttng_event_context_serialize(struct lttng_event_context *context,
1237 struct lttng_payload *payload)
1238{
1239 int ret;
1240 struct lttng_event_context_comm context_comm = { 0 };
1241
1242 assert(context);
1243 assert(payload);
1244
1245 context_comm.type = (uint32_t) context->ctx;
1246
1247 /* Header */
1248 ret = lttng_dynamic_buffer_append(
1249 &payload->buffer, &context_comm, sizeof(context_comm));
1250 if (ret) {
1251 goto end;
1252 }
1253
1254 switch (context->ctx) {
1255 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1256 ret = lttng_event_context_app_serialize(context, payload);
1257 break;
1258 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1259 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1260 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1261 ret = lttng_event_context_perf_counter_serialize(
1262 &context->u.perf_counter, payload);
1263 break;
1264 default:
1265 /* Nothing else to serialize. */
1266 break;
1267 }
1268
1269 if (ret) {
1270 goto end;
1271 }
1272
1273end:
1274 return ret;
1275}
1276
1277void lttng_event_context_destroy(struct lttng_event_context *context)
1278{
1279 if (!context) {
1280 return;
1281 }
1282
1283 if (context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
1284 free(context->u.app_ctx.provider_name);
1285 free(context->u.app_ctx.ctx_name);
1286 }
1287
1288 free(context);
1289}
1290
b2d68839
JR
1291/*
1292 * This is a specialized populate for lttng_event_field since it ignores
1293 * the extension field of the lttng_event struct and simply copies what it can
1294 * to the internal struct lttng_event of a lttng_event_field.
1295 */
1296static void lttng_event_field_populate_lttng_event_from_event(
1297 const struct lttng_event *src, struct lttng_event *destination)
1298{
1299 memcpy(destination, src, sizeof(*destination));
1300
1301 /* Remove all possible dynamic data from the destination event rule. */
1302 destination->extended.ptr = NULL;
1303}
1304
1305ssize_t lttng_event_field_create_from_payload(
1306 struct lttng_payload_view *view,
1307 struct lttng_event_field **field)
1308{
1309 ssize_t ret, offset = 0;
1310 struct lttng_event_field *local_event_field = NULL;
1311 struct lttng_event *event = NULL;
1312 const struct lttng_event_field_comm *comm;
1313 const char* name = NULL;
1314
1315 assert(field);
1316 assert(view);
1317
1318 {
1319 const struct lttng_buffer_view comm_view =
1320 lttng_buffer_view_from_view(
1321 &view->buffer, offset,
1322 sizeof(*comm));
1323
1324 if (!lttng_buffer_view_is_valid(&comm_view)) {
1325 ret = -1;
1326 goto end;
1327 }
1328
1329 /* lttng_event_field_comm header */
1330 comm = (const lttng_event_field_comm *) comm_view.data;
1331 offset += sizeof(*comm);
1332 }
1333
1334 local_event_field = (struct lttng_event_field *)
1335 zmalloc(sizeof(*local_event_field));
1336 if (!local_event_field) {
1337 ret = -1;
1338 goto end;
1339 }
1340
1341 local_event_field->type = (lttng_event_field_type) comm->type;
1342 local_event_field->nowrite = comm->nowrite;
1343
1344 /* Field name */
1345 {
1346 const struct lttng_buffer_view name_view =
1347 lttng_buffer_view_from_view(
1348 &view->buffer, offset,
1349 comm->name_len);
1350
1351 if (!lttng_buffer_view_is_valid(&name_view)) {
1352 ret = -1;
1353 goto end;
1354 }
1355
1356 name = name_view.data;
1357
1358 if (!lttng_buffer_view_contains_string(&name_view,
1359 name_view.data, comm->name_len)) {
1360 ret = -1;
1361 goto end;
1362 }
1363
1364 if (comm->name_len > LTTNG_SYMBOL_NAME_LEN - 1) {
1365 /* Name is too long.*/
1366 ret = -1;
1367 goto end;
1368 }
1369
1370 offset += comm->name_len;
1371 }
1372
1373 /* Event */
1374 {
1375 struct lttng_payload_view event_view =
1376 lttng_payload_view_from_view(
1377 view, offset,
1378 comm->event_len);
1379
1380 if (!lttng_payload_view_is_valid(&event_view)) {
1381 ret = -1;
1382 goto end;
1383 }
1384
1385 ret = lttng_event_create_from_payload(&event_view, &event, NULL,
1386 NULL, NULL);
1387 if (ret != comm->event_len) {
1388 ret = -1;
1389 goto end;
1390 }
1391
1392 offset += ret;
1393 }
1394
1395 assert(name);
1396 assert(event);
1397
2d6df81a
JG
1398 if (lttng_strncpy(local_event_field->field_name, name,
1399 sizeof(local_event_field->field_name))) {
b2d68839
JR
1400 ret = -1;
1401 goto end;
1402 }
1403
1404 lttng_event_field_populate_lttng_event_from_event(
1405 event, &local_event_field->event);
1406
1407 *field = local_event_field;
1408 local_event_field = NULL;
1409 ret = offset;
1410end:
1411 lttng_event_destroy(event);
1412 free(local_event_field);
1413 return ret;
1414}
1415
1416int lttng_event_field_serialize(const struct lttng_event_field *field,
1417 struct lttng_payload *payload)
1418{
1419 int ret;
1420 size_t header_offset, size_before_event;
1421 size_t name_len;
1c9a0b0e 1422 struct lttng_event_field_comm event_field_comm = {};
b2d68839
JR
1423 struct lttng_event_field_comm *header;
1424
1425 assert(field);
1426 assert(payload);
1427
1428 /* Save the header location for later in-place header update. */
1429 header_offset = payload->buffer.size;
1430
2d6df81a
JG
1431 name_len = strnlen(field->field_name, sizeof(field->field_name));
1432 if (name_len == sizeof(field->field_name)) {
b2d68839
JR
1433 /* Event name is not NULL-terminated. */
1434 ret = -1;
1435 goto end;
1436 }
1437
1438 /* Add null termination. */
1439 name_len += 1;
1440
1441 event_field_comm.type = field->type;
1442 event_field_comm.nowrite = (uint8_t)field->nowrite;
1443 event_field_comm.name_len = name_len;
1444
1445 /* Header */
1446 ret = lttng_dynamic_buffer_append(
1447 &payload->buffer, &event_field_comm,
1448 sizeof(event_field_comm));
1449 if (ret) {
1450 goto end;
1451 }
1452
1453 /* Field name */
1454 ret = lttng_dynamic_buffer_append(&payload->buffer, field->field_name,
1455 name_len);
1456 if (ret) {
1457 goto end;
1458 }
1459
1460 size_before_event = payload->buffer.size;
1461 ret = lttng_event_serialize(
1462 &field->event, 0, NULL, NULL, 0, 0, payload);
1463 if (ret) {
1464 ret = -1;
1465 goto end;
1466 }
1467
1468 /* Update the event len. */
1469 header = (struct lttng_event_field_comm *)
1470 ((char *) payload->buffer.data +
1471 header_offset);
1472 header->event_len = payload->buffer.size - size_before_event;
1473
1474end:
1475 return ret;
1476}
1477
8ddd72ef
JR
1478static enum lttng_error_code compute_flattened_size(
1479 struct lttng_dynamic_pointer_array *events, size_t *size)
1480{
1481 enum lttng_error_code ret_code;
1482 int ret = 0;
1483 size_t storage_req, event_count, i;
1484
1485 assert(size);
1486 assert(events);
1487
1488 event_count = lttng_dynamic_pointer_array_get_count(events);
1489
1490 /* The basic struct lttng_event */
1491 storage_req = event_count * sizeof(struct lttng_event);
1492
fc33156e
JG
1493 /* The struct·lttng_event_extended */
1494 storage_req += event_count * sizeof(struct lttng_event_extended);
1495
8ddd72ef
JR
1496 for (i = 0; i < event_count; i++) {
1497 int probe_storage_req = 0;
1498 const struct event_list_element *element = (const struct event_list_element *)
1499 lttng_dynamic_pointer_array_get_pointer(
1500 events, i);
1501 const struct lttng_userspace_probe_location *location = NULL;
1502
1503 location = lttng_event_get_userspace_probe_location(
1504 element->event);
1505 if (location) {
1506 ret = lttng_userspace_probe_location_flatten(
1507 location, NULL);
1508 if (ret < 0) {
1509 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1510 goto end;
1511 }
1512
1513 probe_storage_req = ret;
1514 }
1515
8ddd72ef
JR
1516 if (element->filter_expression) {
1517 storage_req += strlen(element->filter_expression) + 1;
1518 }
1519
1520 if (element->exclusions) {
1521 storage_req += element->exclusions->count *
1522 LTTNG_SYMBOL_NAME_LEN;
1523 }
1524
1525 /* Padding to ensure the flat probe is aligned. */
1526 storage_req = lttng_align_ceil(storage_req, sizeof(uint64_t));
1527 storage_req += probe_storage_req;
1528 }
1529
1530 *size = storage_req;
1531 ret_code = LTTNG_OK;
1532
1533end:
1534 return ret_code;
1535}
1536
1537/*
1538 * Flatten a list of struct lttng_event.
1539 *
1540 * The buffer that is returned to the API client must contain a "flat" version
1541 * of the events that are returned. In other words, all pointers within an
1542 * lttng_event must point to a location within the returned buffer so that the
1543 * user may free everything by simply calling free() on the returned buffer.
1544 * This is needed in order to maintain API compatibility.
1545 *
1546 * A first pass is performed to compute the size of the buffer that must be
1547 * allocated. A second pass is then performed to setup the returned events so
1548 * that their members always point within the buffer.
1549 *
1550 * The layout of the returned buffer is as follows:
1551 * - struct lttng_event[nb_events],
1552 * - nb_events times the following:
1553 * - struct lttng_event_extended,
1554 * - filter_expression
1555 * - exclusions
1556 * - padding to align to 64-bits
1557 * - flattened version of userspace_probe_location
1558 */
1559static enum lttng_error_code flatten_lttng_events(
1560 struct lttng_dynamic_pointer_array *events,
1561 struct lttng_event **flattened_events)
1562{
1563 enum lttng_error_code ret_code;
1564 int ret, i;
1565 size_t storage_req;
1566 struct lttng_dynamic_buffer local_flattened_events;
1567 int nb_events;
1568
1569 assert(events);
1570 assert(flattened_events);
1571
1572 lttng_dynamic_buffer_init(&local_flattened_events);
1573 nb_events = lttng_dynamic_pointer_array_get_count(events);
1574
1575 ret_code = compute_flattened_size(events, &storage_req);
1576 if (ret_code != LTTNG_OK) {
1577 goto end;
1578 }
1579
1580 /*
1581 * We must ensure that "local_flattened_events" is never resized so as
1582 * to preserve the validity of the flattened objects.
1583 */
1584 ret = lttng_dynamic_buffer_set_capacity(
1585 &local_flattened_events, storage_req);
1586 if (ret) {
1587 ret_code = LTTNG_ERR_NOMEM;
1588 goto end;
1589 }
1590
1591 /* Start by laying the struct lttng_event */
1592 for (i = 0; i < nb_events; i++) {
1593 const struct event_list_element *element = (const struct event_list_element *)
1594 lttng_dynamic_pointer_array_get_pointer(
1595 events, i);
1596
1597 if (!element) {
1598 ret_code = LTTNG_ERR_FATAL;
1599 goto end;
1600 }
1601
1602 ret = lttng_dynamic_buffer_append(&local_flattened_events,
1603 element->event, sizeof(struct lttng_event));
1604 if (ret) {
1605 ret_code = LTTNG_ERR_NOMEM;
1606 goto end;
1607 }
1608 }
1609
1610 for (i = 0; i < nb_events; i++) {
1611 const struct event_list_element *element = (const struct event_list_element *)
1612 lttng_dynamic_pointer_array_get_pointer(events, i);
1613 struct lttng_event *event = (struct lttng_event *)
1614 (local_flattened_events.data + (sizeof(struct lttng_event) * i));
1615 struct lttng_event_extended *event_extended =
1616 (struct lttng_event_extended *)
1617 (local_flattened_events.data + local_flattened_events.size);
1618 const struct lttng_userspace_probe_location *location = NULL;
1619
1620 assert(element);
1621
1622 /* Insert struct lttng_event_extended. */
1623 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1624 local_flattened_events.size +
1625 sizeof(*event_extended));
1626 if (ret) {
1627 ret_code = LTTNG_ERR_NOMEM;
1628 goto end;
1629 }
1630 event->extended.ptr = event_extended;
1631
1632 /* Insert filter expression. */
1633 if (element->filter_expression) {
1634 const size_t len = strlen(element->filter_expression) + 1;
1635
1636 event_extended->filter_expression =
1637 local_flattened_events.data +
1638 local_flattened_events.size;
1639 ret = lttng_dynamic_buffer_append(
1640 &local_flattened_events,
1641 element->filter_expression, len);
1642 if (ret) {
1643 ret_code = LTTNG_ERR_NOMEM;
1644 goto end;
1645 }
1646 }
1647
1648 /* Insert exclusions. */
1649 if (element->exclusions) {
1650 event_extended->exclusions.count =
1651 element->exclusions->count;
1652 event_extended->exclusions.strings =
1653 local_flattened_events.data +
1654 local_flattened_events.size;
1655
1656 ret = lttng_dynamic_buffer_append(
1657 &local_flattened_events,
1658 element->exclusions->names,
1659 element->exclusions->count *
1660 LTTNG_SYMBOL_NAME_LEN);
1661 if (ret) {
1662 ret_code = LTTNG_ERR_NOMEM;
1663 goto end;
1664 }
1665 }
1666
1667 /* Insert padding to align to 64-bits. */
1668 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1669 lttng_align_ceil(local_flattened_events.size,
1670 sizeof(uint64_t)));
1671 if (ret) {
1672 ret_code = LTTNG_ERR_NOMEM;
1673 goto end;
1674 }
1675
1676 location = lttng_event_get_userspace_probe_location(
1677 element->event);
1678 if (location) {
1679 event_extended->probe_location = (struct lttng_userspace_probe_location *)
1680 (local_flattened_events.data + local_flattened_events.size);
1681 ret = lttng_userspace_probe_location_flatten(
1682 location, &local_flattened_events);
1683 if (ret < 0) {
1684 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1685 goto end;
1686 }
1687 }
1688 }
1689
1690 /* Don't reset local_flattened_events buffer as we return its content. */
1691 *flattened_events = (struct lttng_event *) local_flattened_events.data;
1692 lttng_dynamic_buffer_init(&local_flattened_events);
1693 ret_code = LTTNG_OK;
1694end:
1695 lttng_dynamic_buffer_reset(&local_flattened_events);
1696 return ret_code;
1697}
1698
1699static enum lttng_error_code event_list_create_from_payload(
1700 struct lttng_payload_view *view,
1701 unsigned int count,
1702 struct lttng_dynamic_pointer_array *event_list)
1703{
1704 enum lttng_error_code ret_code;
1705 int ret;
1706 unsigned int i;
1707 int offset = 0;
1708
1709 assert(view);
1710 assert(event_list);
1711
1712 for (i = 0; i < count; i++) {
1713 ssize_t event_size;
1714 struct lttng_payload_view event_view =
1715 lttng_payload_view_from_view(view, offset, -1);
1716 struct event_list_element *element =
1717 (struct event_list_element *) zmalloc(sizeof(*element));
1718
1719 if (!element) {
1720 ret_code = LTTNG_ERR_NOMEM;
1721 goto end;
1722 }
1723
1724 /*
1725 * Lifetime and management of the object is now bound to the
1726 * array.
1727 */
1728 ret = lttng_dynamic_pointer_array_add_pointer(
1729 event_list, element);
1730 if (ret) {
1731 event_list_destructor(element);
1732 ret_code = LTTNG_ERR_NOMEM;
1733 goto end;
1734 }
1735
1736 /*
1737 * Bytecode is not transmitted on listing in any case we do not
1738 * care about it.
1739 */
1740 event_size = lttng_event_create_from_payload(&event_view,
1741 &element->event,
1742 &element->exclusions,
1743 &element->filter_expression, NULL);
1744 if (event_size < 0) {
1745 ret_code = LTTNG_ERR_INVALID;
1746 goto end;
1747 }
1748
1749 offset += event_size;
1750 }
1751
1752 if (view->buffer.size != offset) {
1753 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
1754 goto end;
1755 }
1756
1757 ret_code = LTTNG_OK;
1758
1759end:
1760 return ret_code;
1761}
1762
1763enum lttng_error_code lttng_events_create_and_flatten_from_payload(
1764 struct lttng_payload_view *payload,
1765 unsigned int count,
1766 struct lttng_event **events)
1767{
1768 enum lttng_error_code ret = LTTNG_OK;
1769 struct lttng_dynamic_pointer_array local_events;
1770
1771 lttng_dynamic_pointer_array_init(&local_events, event_list_destructor);
1772
1773 /* Deserialize the events. */
1774 {
1775 struct lttng_payload_view events_view =
1776 lttng_payload_view_from_view(payload, 0, -1);
1777
1778 ret = event_list_create_from_payload(
1779 &events_view, count, &local_events);
1780 if (ret != LTTNG_OK) {
1781 goto end;
1782 }
1783 }
1784
1785 ret = flatten_lttng_events(&local_events, events);
1786 if (ret != LTTNG_OK) {
1787 goto end;
1788 }
1789
1790end:
1791 lttng_dynamic_pointer_array_reset(&local_events);
1792 return ret;
1793}
b2d68839
JR
1794
1795static enum lttng_error_code flatten_lttng_event_fields(
1796 struct lttng_dynamic_pointer_array *event_fields,
1797 struct lttng_event_field **flattened_event_fields)
1798{
1799 int ret, i;
1800 enum lttng_error_code ret_code;
1801 size_t storage_req = 0;
1802 struct lttng_dynamic_buffer local_flattened_event_fields;
1803 int nb_event_field;
1804
1805 assert(event_fields);
1806 assert(flattened_event_fields);
1807
1808 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1809 nb_event_field = lttng_dynamic_pointer_array_get_count(event_fields);
1810
1811 /*
1812 * Here even if the event field contains a `struct lttng_event` that
1813 * could contain dynamic data, in reality it is not the case.
1814 * Dynamic data is not present. Here the flattening is mostly a direct
1815 * memcpy. This is less than ideal but this code is still better than
1816 * direct usage of an unpacked lttng_event_field array.
1817 */
1818 storage_req += sizeof(struct lttng_event_field) * nb_event_field;
1819
1820 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1821
1822 /*
1823 * We must ensure that "local_flattened_event_fields" is never resized
1824 * so as to preserve the validity of the flattened objects.
1825 */
1826 ret = lttng_dynamic_buffer_set_capacity(
1827 &local_flattened_event_fields, storage_req);
1828 if (ret) {
1829 ret_code = LTTNG_ERR_NOMEM;
1830 goto end;
1831 }
1832
1833 for (i = 0; i < nb_event_field; i++) {
1834 const struct lttng_event_field *element =
1835 (const struct lttng_event_field *)
1836 lttng_dynamic_pointer_array_get_pointer(
1837 event_fields, i);
1838
1839 if (!element) {
1840 ret_code = LTTNG_ERR_FATAL;
1841 goto end;
1842 }
1843 ret = lttng_dynamic_buffer_append(&local_flattened_event_fields,
1844 element, sizeof(struct lttng_event_field));
1845 if (ret) {
1846 ret_code = LTTNG_ERR_NOMEM;
1847 goto end;
1848 }
1849 }
1850
1851 /* Don't reset local_flattened_channels buffer as we return its content. */
1852 *flattened_event_fields = (struct lttng_event_field *) local_flattened_event_fields.data;
1853 lttng_dynamic_buffer_init(&local_flattened_event_fields);
1854 ret_code = LTTNG_OK;
1855end:
1856 lttng_dynamic_buffer_reset(&local_flattened_event_fields);
1857 return ret_code;
1858}
1859
1860static enum lttng_error_code event_field_list_create_from_payload(
1861 struct lttng_payload_view *view,
1862 unsigned int count,
1863 struct lttng_dynamic_pointer_array **event_field_list)
1864{
1865 enum lttng_error_code ret_code;
1866 int ret, offset = 0;
1867 unsigned int i;
1868 struct lttng_dynamic_pointer_array *list = NULL;
1869
1870 assert(view);
1871 assert(event_field_list);
1872
1873 list = (struct lttng_dynamic_pointer_array *) zmalloc(sizeof(*list));
1874 if (!list) {
1875 ret_code = LTTNG_ERR_NOMEM;
1876 goto end;
1877 }
1878
1879 lttng_dynamic_pointer_array_init(list, free);
1880
1881 for (i = 0; i < count; i++) {
1882 ssize_t event_field_size;
1883 struct lttng_event_field *field = NULL;
1884 struct lttng_payload_view event_field_view =
1885 lttng_payload_view_from_view(view, offset, -1);
1886
1887 event_field_size = lttng_event_field_create_from_payload(
1888 &event_field_view, &field);
1889 if (event_field_size < 0) {
1890 ret_code = LTTNG_ERR_INVALID;
1891 goto end;
1892 }
1893
1894 /* Lifetime and management of the object is now bound to the array. */
1895 ret = lttng_dynamic_pointer_array_add_pointer(list, field);
1896 if (ret) {
1897 free(field);
1898 ret_code = LTTNG_ERR_NOMEM;
1899 goto end;
1900 }
1901
1902 offset += event_field_size;
1903 }
1904
1905 if (view->buffer.size != offset) {
1906 ret_code = LTTNG_ERR_INVALID;
1907 goto end;
1908 }
1909
1910 *event_field_list = list;
1911 list = NULL;
1912 ret_code = LTTNG_OK;
1913
1914end:
1915 if (list) {
1916 lttng_dynamic_pointer_array_reset(list);
1917 free(list);
1918 }
1919
1920 return ret_code;
1921}
1922
1923enum lttng_error_code lttng_event_fields_create_and_flatten_from_payload(
1924 struct lttng_payload_view *view,
1925 unsigned int count,
1926 struct lttng_event_field **fields)
1927{
1928 enum lttng_error_code ret_code;
1929 struct lttng_dynamic_pointer_array *local_event_fields = NULL;
1930
1931 ret_code = event_field_list_create_from_payload(
1932 view, count, &local_event_fields);
1933 if (ret_code != LTTNG_OK) {
1934 goto end;
1935 }
1936
1937 ret_code = flatten_lttng_event_fields(local_event_fields, fields);
1938 if (ret_code != LTTNG_OK) {
1939 goto end;
1940 }
1941end:
1942 if (local_event_fields) {
1943 lttng_dynamic_pointer_array_reset(local_event_fields);
1944 free(local_event_fields);
1945 }
1946
1947 return ret_code;
1948}
This page took 0.116903 seconds and 4 git commands to generate.