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