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