Fix: liblttng-ctl comm: lttng_event_context is not packed
[lttng-tools.git] / src / common / event.c
1 /*
2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "common/compat/string.h"
9 #include "common/macros.h"
10 #include "lttng/lttng-error.h"
11 #include <assert.h>
12 #include <common/buffer-view.h>
13 #include <common/dynamic-array.h>
14 #include <common/dynamic-buffer.h>
15 #include <common/error.h>
16 #include <common/sessiond-comm/sessiond-comm.h>
17 #include <common/align.h>
18 #include <lttng/constant.h>
19 #include <lttng/event-internal.h>
20 #include <lttng/event.h>
21 #include <lttng/userspace-probe-internal.h>
22 #include <stdint.h>
23 #include <string.h>
24
25 struct event_list_element {
26 struct lttng_event *event;
27 struct lttng_event_exclusion *exclusions;
28 char *filter_expression;
29 };
30
31 static void event_list_destructor(void *ptr)
32 {
33 struct event_list_element *element = (struct event_list_element *) ptr;
34
35 free(element->filter_expression);
36 free(element->exclusions);
37 lttng_event_destroy(element->event);
38 free(element);
39 }
40
41 LTTNG_HIDDEN
42 struct lttng_event *lttng_event_copy(const struct lttng_event *event)
43 {
44 struct lttng_event *new_event;
45 struct lttng_event_extended *new_event_extended;
46
47 new_event = zmalloc(sizeof(*event));
48 if (!new_event) {
49 PERROR("Error allocating event structure");
50 goto end;
51 }
52
53 /* Copy the content of the old event. */
54 memcpy(new_event, event, sizeof(*event));
55
56 /*
57 * We need to create a new extended since the previous pointer is now
58 * invalid.
59 */
60 new_event_extended = zmalloc(sizeof(*new_event_extended));
61 if (!new_event_extended) {
62 PERROR("Error allocating event extended structure");
63 goto error;
64 }
65
66 new_event->extended.ptr = new_event_extended;
67 end:
68 return new_event;
69 error:
70 free(new_event);
71 new_event = NULL;
72 goto end;
73 }
74
75 static int lttng_event_probe_attr_serialize(
76 const struct lttng_event_probe_attr *probe,
77 struct lttng_payload *payload)
78 {
79 int ret;
80 size_t symbol_name_len;
81 struct lttng_event_probe_attr_comm comm = { 0 };
82
83 symbol_name_len = lttng_strnlen(probe->symbol_name, LTTNG_SYMBOL_NAME_LEN);
84 if (symbol_name_len == LTTNG_SYMBOL_NAME_LEN) {
85 /* Not null-termintated. */
86 ret = -1;
87 goto end;
88 }
89
90 /* Include the null terminator. */
91 symbol_name_len += 1;
92
93 comm.symbol_name_len = (uint32_t) symbol_name_len;
94 comm.addr = probe->addr;
95 comm.offset = probe->addr;
96
97 ret = lttng_dynamic_buffer_append(
98 &payload->buffer, &comm, sizeof(comm));
99 if (ret < 0) {
100 ret = -1;
101 goto end;
102 }
103
104 ret = lttng_dynamic_buffer_append(
105 &payload->buffer, probe->symbol_name, symbol_name_len);
106 end:
107 return ret;
108 }
109
110 static int lttng_event_function_attr_serialize(
111 const struct lttng_event_function_attr *function,
112 struct lttng_payload *payload)
113 {
114 int ret;
115 size_t symbol_name_len;
116 struct lttng_event_function_attr_comm comm = { 0 };
117
118 symbol_name_len = lttng_strnlen(function->symbol_name, LTTNG_SYMBOL_NAME_LEN);
119 if (symbol_name_len == LTTNG_SYMBOL_NAME_LEN) {
120 /* Not null-termintated. */
121 ret = -1;
122 goto end;
123 }
124
125 /* Include the null terminator. */
126 symbol_name_len += 1;
127
128 comm.symbol_name_len = (uint32_t) symbol_name_len;
129
130 ret = lttng_dynamic_buffer_append(
131 &payload->buffer, &comm, sizeof(comm));
132 if (ret < 0) {
133 ret = -1;
134 goto end;
135 }
136
137 ret = lttng_dynamic_buffer_append(&payload->buffer,
138 function->symbol_name, symbol_name_len);
139 end:
140 return ret;
141 }
142
143 static ssize_t lttng_event_probe_attr_create_from_payload(
144 struct lttng_payload_view *view,
145 struct lttng_event_probe_attr **probe_attr)
146 {
147 ssize_t ret, offset = 0;
148 const struct lttng_event_probe_attr_comm *comm;
149 struct lttng_event_probe_attr *local_attr = NULL;
150 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
151 view, offset, sizeof(*comm));
152
153 if (!lttng_payload_view_is_valid(&comm_view)) {
154 ret = -1;
155 goto end;
156 }
157
158 comm = (typeof(comm)) comm_view.buffer.data;
159 offset += sizeof(*comm);
160
161 local_attr = (struct lttng_event_probe_attr *) zmalloc(
162 sizeof(*local_attr));
163 if (local_attr == NULL) {
164 ret = -1;
165 goto end;
166 }
167
168 local_attr->addr = comm->addr;
169 local_attr->offset = comm->offset;
170
171 {
172 const char *name;
173 struct lttng_payload_view name_view =
174 lttng_payload_view_from_view(view, offset,
175 comm->symbol_name_len);
176
177 if (!lttng_payload_view_is_valid(&name_view)) {
178 ret = -1;
179 goto end;
180 }
181
182 name = name_view.buffer.data;
183
184 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
185 comm->symbol_name_len)) {
186 ret = -1;
187 goto end;
188 }
189
190 ret = lttng_strncpy(local_attr->symbol_name, name,
191 LTTNG_SYMBOL_NAME_LEN);
192 if (ret) {
193 ret = -1;
194 goto end;
195 }
196
197 offset += comm->symbol_name_len;
198 }
199
200 *probe_attr = local_attr;
201 local_attr = NULL;
202 ret = offset;
203 end:
204 return ret;
205 }
206
207 static ssize_t lttng_event_function_attr_create_from_payload(
208 struct lttng_payload_view *view,
209 struct lttng_event_function_attr **function_attr)
210 {
211 ssize_t ret, offset = 0;
212 const struct lttng_event_function_attr_comm *comm;
213 struct lttng_event_function_attr *local_attr = NULL;
214 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
215 view, offset, sizeof(*comm));
216
217 if (!lttng_payload_view_is_valid(&comm_view)) {
218 ret = -1;
219 goto end;
220 }
221
222 comm = (typeof(comm)) view->buffer.data;
223 offset += sizeof(*comm);
224
225 local_attr = (struct lttng_event_function_attr *) zmalloc(
226 sizeof(*local_attr));
227 if (local_attr == NULL) {
228 ret = -1;
229 goto end;
230 }
231
232 {
233 const char *name;
234 struct lttng_payload_view name_view =
235 lttng_payload_view_from_view(view, offset,
236 comm->symbol_name_len);
237
238 if (!lttng_payload_view_is_valid(&name_view)) {
239 ret = -1;
240 goto end;
241 }
242
243 name = name_view.buffer.data;
244
245 if (!lttng_buffer_view_contains_string(&name_view.buffer, name,
246 comm->symbol_name_len)) {
247 ret = -1;
248 goto end;
249 }
250
251 ret = lttng_strncpy(local_attr->symbol_name, name,
252 LTTNG_SYMBOL_NAME_LEN);
253 if (ret) {
254 ret = -1;
255 goto end;
256 }
257
258 offset += comm->symbol_name_len;
259 }
260
261 *function_attr = local_attr;
262 local_attr = NULL;
263 ret = offset;
264 end:
265 return ret;
266 }
267
268 static ssize_t lttng_event_exclusions_create_from_payload(
269 struct lttng_payload_view *view,
270 uint32_t count,
271 struct lttng_event_exclusion **exclusions)
272 {
273 ssize_t ret, offset = 0;
274 size_t size = (count * LTTNG_SYMBOL_NAME_LEN);
275 uint32_t i;
276 const struct lttng_event_exclusion_comm *comm;
277 struct lttng_event_exclusion *local_exclusions;
278
279 local_exclusions = (struct lttng_event_exclusion *) zmalloc(
280 sizeof(struct lttng_event_exclusion) + size);
281 if (!local_exclusions) {
282 ret = -1;
283 goto end;
284 }
285
286 local_exclusions->count = count;
287
288 for (i = 0; i < count; i++) {
289 const char *string;
290 struct lttng_buffer_view string_view;
291 const struct lttng_buffer_view comm_view =
292 lttng_buffer_view_from_view(&view->buffer,
293 offset, sizeof(*comm));
294
295 if (!lttng_buffer_view_is_valid(&comm_view)) {
296 ret = -1;
297 goto end;
298 }
299
300 comm = (typeof(comm)) comm_view.data;
301 offset += sizeof(*comm);
302
303 string_view = lttng_buffer_view_from_view(
304 &view->buffer, offset, comm->len);
305
306 if (!lttng_buffer_view_is_valid(&string_view)) {
307 ret = -1;
308 goto end;
309 }
310
311 string = string_view.data;
312
313 if (!lttng_buffer_view_contains_string(
314 &string_view, string, comm->len)) {
315 ret = -1;
316 goto end;
317 }
318
319 ret = lttng_strncpy(local_exclusions->names[i],
320 string, LTTNG_SYMBOL_NAME_LEN);
321 if (ret) {
322 ret = -1;
323 goto end;
324 }
325
326 offset += comm->len;
327 }
328
329 *exclusions = local_exclusions;
330 local_exclusions = NULL;
331 ret = offset;
332 end:
333 free(local_exclusions);
334 return ret;
335 }
336
337 ssize_t lttng_event_create_from_payload(struct lttng_payload_view *view,
338 struct lttng_event **out_event,
339 struct lttng_event_exclusion **out_exclusion,
340 char **out_filter_expression,
341 struct lttng_bytecode **out_bytecode)
342 {
343 ssize_t ret, offset = 0;
344 struct lttng_event *local_event = NULL;
345 struct lttng_event_exclusion *local_exclusions = NULL;
346 struct lttng_bytecode *local_bytecode = NULL;
347 char *local_filter_expression = NULL;
348 const struct lttng_event_comm *event_comm;
349 struct lttng_event_function_attr *local_function_attr = NULL;
350 struct lttng_event_probe_attr *local_probe_attr = NULL;
351 struct lttng_userspace_probe_location *local_userspace_probe_location =
352 NULL;
353
354 /*
355 * Only event is obligatory, the other output argument are optional and
356 * depends on what the caller is interested in.
357 */
358 assert(out_event);
359 assert(view);
360
361 {
362 struct lttng_payload_view comm_view =
363 lttng_payload_view_from_view(view, offset,
364 sizeof(*event_comm));
365
366 if (!lttng_payload_view_is_valid(&comm_view)) {
367 ret = -1;
368 goto end;
369 }
370
371 /* lttng_event_comm header */
372 event_comm = (typeof(event_comm)) comm_view.buffer.data;
373 offset += sizeof(*event_comm);
374 }
375
376 local_event = lttng_event_create();
377 if (local_event == NULL) {
378 ret = -1;
379 goto end;
380 }
381
382 local_event->type = (enum lttng_event_type) event_comm->event_type;
383 local_event->loglevel_type = (enum lttng_loglevel_type) event_comm->loglevel_type;
384 local_event->loglevel = event_comm->loglevel;
385 local_event->enabled = event_comm->enabled;
386 local_event->pid = event_comm->pid;
387 local_event->flags = (enum lttng_event_flag) event_comm->flags;
388
389 {
390 const char *name;
391 const struct lttng_buffer_view name_view =
392 lttng_buffer_view_from_view(&view->buffer,
393 offset, event_comm->name_len);
394
395 if (!lttng_buffer_view_is_valid(&name_view)) {
396 ret = -1;
397 goto end;
398 }
399
400 name = (const char *) name_view.data;
401
402 if (!lttng_buffer_view_contains_string(
403 &name_view, name, event_comm->name_len)) {
404 ret = -1;
405 goto end;
406 }
407
408 ret = lttng_strncpy(
409 local_event->name, name, LTTNG_SYMBOL_NAME_LEN);
410 if (ret) {
411 ret = -1;
412 goto end;
413 }
414
415 offset += event_comm->name_len;
416 }
417
418 /* Exclusions */
419 if (event_comm->exclusion_count == 0) {
420 goto deserialize_filter_expression;
421 }
422
423 {
424 struct lttng_payload_view exclusions_view =
425 lttng_payload_view_from_view(
426 view, offset, -1);
427
428 if (!lttng_payload_view_is_valid(&exclusions_view)) {
429 ret = -1;
430 goto end;
431 }
432
433 ret = lttng_event_exclusions_create_from_payload(&exclusions_view,
434 event_comm->exclusion_count, &local_exclusions);
435 if (ret < 0) {
436 ret = -1;
437 goto end;
438 }
439 offset += ret;
440
441 local_event->exclusion = 1;
442 }
443
444 deserialize_filter_expression:
445
446 if (event_comm->filter_expression_len == 0) {
447 if (event_comm->bytecode_len != 0) {
448 /*
449 * This is an invalid event payload.
450 *
451 * Filter expression without bytecode is possible but
452 * not the other way around.
453 * */
454 ret = -1;
455 goto end;
456 }
457 goto deserialize_event_type_payload;
458 }
459
460 {
461 const char *filter_expression_buffer;
462 struct lttng_buffer_view filter_expression_view =
463 lttng_buffer_view_from_view(&view->buffer, offset,
464 event_comm->filter_expression_len);
465
466 if (!lttng_buffer_view_is_valid(&filter_expression_view)) {
467 ret = -1;
468 goto end;
469 }
470
471 filter_expression_buffer = filter_expression_view.data;
472
473 if (!lttng_buffer_view_contains_string(&filter_expression_view,
474 filter_expression_buffer,
475 event_comm->filter_expression_len)) {
476 ret = -1;
477 goto end;
478 }
479
480 local_filter_expression = lttng_strndup(
481 filter_expression_buffer,
482 event_comm->filter_expression_len);
483 if (!local_filter_expression) {
484 ret = -1;
485 goto end;
486 }
487
488 local_event->filter = 1;
489
490 offset += event_comm->filter_expression_len;
491 }
492
493 if (event_comm->bytecode_len == 0) {
494 /*
495 * Filter expression can be present but without bytecode
496 * when dealing with event listing.
497 */
498 goto deserialize_event_type_payload;
499 }
500
501 /* Bytecode */
502 {
503 struct lttng_payload_view bytecode_view =
504 lttng_payload_view_from_view(view, offset,
505 event_comm->bytecode_len);
506
507 if (!lttng_payload_view_is_valid(&bytecode_view)) {
508 ret = -1;
509 goto end;
510 }
511
512 local_bytecode = (struct lttng_bytecode *) zmalloc(
513 event_comm->bytecode_len);
514 if (!local_bytecode) {
515 ret = -1;
516 goto end;
517 }
518
519 memcpy(local_bytecode, bytecode_view.buffer.data,
520 event_comm->bytecode_len);
521 if ((local_bytecode->len + sizeof(*local_bytecode)) !=
522 event_comm->bytecode_len) {
523 ret = -1;
524 goto end;
525 }
526
527 offset += event_comm->bytecode_len;
528 }
529
530 deserialize_event_type_payload:
531 /* Event type specific payload */
532 switch (local_event->type) {
533 case LTTNG_EVENT_FUNCTION:
534 /* Fallthrough */
535 case LTTNG_EVENT_PROBE:
536 {
537 struct lttng_payload_view probe_attr_view =
538 lttng_payload_view_from_view(view, offset,
539 event_comm->lttng_event_probe_attr_len);
540
541 if (event_comm->lttng_event_probe_attr_len == 0) {
542 ret = -1;
543 goto end;
544 }
545
546 if (!lttng_payload_view_is_valid(&probe_attr_view)) {
547 ret = -1;
548 goto end;
549 }
550
551 ret = lttng_event_probe_attr_create_from_payload(
552 &probe_attr_view, &local_probe_attr);
553 if (ret < 0 || ret != event_comm->lttng_event_probe_attr_len) {
554 ret = -1;
555 goto end;
556 }
557
558 /* Copy to the local event. */
559 memcpy(&local_event->attr.probe, local_probe_attr,
560 sizeof(local_event->attr.probe));
561
562 offset += ret;
563 break;
564 }
565 case LTTNG_EVENT_FUNCTION_ENTRY:
566 {
567 struct lttng_payload_view function_attr_view =
568 lttng_payload_view_from_view(view, offset,
569 event_comm->lttng_event_function_attr_len);
570
571 if (event_comm->lttng_event_function_attr_len == 0) {
572 ret = -1;
573 goto end;
574 }
575
576 if (!lttng_payload_view_is_valid(&function_attr_view)) {
577 ret = -1;
578 goto end;
579 }
580
581 ret = lttng_event_function_attr_create_from_payload(
582 &function_attr_view, &local_function_attr);
583 if (ret < 0 || ret != event_comm->lttng_event_function_attr_len) {
584 ret = -1;
585 goto end;
586 }
587
588 /* Copy to the local event. */
589 memcpy(&local_event->attr.ftrace, local_function_attr,
590 sizeof(local_event->attr.ftrace));
591
592 offset += ret;
593
594 break;
595 }
596 case LTTNG_EVENT_USERSPACE_PROBE:
597 {
598 struct lttng_payload_view userspace_probe_location_view =
599 lttng_payload_view_from_view(view, offset,
600 event_comm->userspace_probe_location_len);
601
602 if (event_comm->userspace_probe_location_len == 0) {
603 ret = -1;
604 goto end;
605 }
606
607 if (!lttng_payload_view_is_valid(
608 &userspace_probe_location_view)) {
609 ret = -1;
610 goto end;
611 }
612
613 ret = lttng_userspace_probe_location_create_from_payload(
614 &userspace_probe_location_view,
615 &local_userspace_probe_location);
616 if (ret < 0) {
617 WARN("Failed to create a userspace probe location from the received buffer");
618 ret = -1;
619 goto end;
620 }
621
622 if (ret != event_comm->userspace_probe_location_len) {
623 WARN("Userspace probe location from the received buffer is not the advertised length: header length = %" PRIu32 ", payload length = %lu", event_comm->userspace_probe_location_len, ret);
624 ret = -1;
625 goto end;
626 }
627
628 /* Attach the probe location to the event. */
629 ret = lttng_event_set_userspace_probe_location(
630 local_event, local_userspace_probe_location);
631 if (ret) {
632 ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
633 goto end;
634 }
635
636 /*
637 * Userspace probe location object ownership transfered to the
638 * event object.
639 */
640 local_userspace_probe_location = NULL;
641 offset += event_comm->userspace_probe_location_len;
642 break;
643 }
644 case LTTNG_EVENT_TRACEPOINT:
645 /* Fallthrough */
646 case LTTNG_EVENT_ALL:
647 /* Fallthrough */
648 case LTTNG_EVENT_SYSCALL:
649 /* Fallthrough */
650 case LTTNG_EVENT_NOOP:
651 /* Nothing to do here */
652 break;
653 default:
654 ret = LTTNG_ERR_UND;
655 goto end;
656 break;
657 }
658
659 /* Transfer ownership to the caller. */
660 *out_event = local_event;
661 local_event = NULL;
662
663 if (out_bytecode) {
664 *out_bytecode = local_bytecode;
665 local_bytecode = NULL;
666 }
667
668 if (out_exclusion) {
669 *out_exclusion = local_exclusions;
670 local_exclusions = NULL;
671 }
672
673 if (out_filter_expression) {
674 *out_filter_expression = local_filter_expression;
675 local_filter_expression = NULL;
676 }
677
678 ret = offset;
679 end:
680 lttng_event_destroy(local_event);
681 lttng_userspace_probe_location_destroy(local_userspace_probe_location);
682 free(local_filter_expression);
683 free(local_exclusions);
684 free(local_bytecode);
685 free(local_function_attr);
686 free(local_probe_attr);
687 return ret;
688 }
689
690 int lttng_event_serialize(const struct lttng_event *event,
691 unsigned int exclusion_count,
692 char **exclusion_list,
693 char *filter_expression,
694 size_t bytecode_len,
695 struct lttng_bytecode *bytecode,
696 struct lttng_payload *payload)
697 {
698 int ret;
699 unsigned int i;
700 size_t header_offset, size_before_payload;
701 size_t name_len;
702 struct lttng_event_comm event_comm = { 0 };
703 struct lttng_event_comm *header;
704
705 assert(event);
706 assert(payload);
707 assert(exclusion_count == 0 || exclusion_list);
708
709 /* Save the header location for later in-place header update. */
710 header_offset = payload->buffer.size;
711
712 name_len = lttng_strnlen(event->name, LTTNG_SYMBOL_NAME_LEN);
713 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
714 /* Event name is not NULL-terminated. */
715 ret = -1;
716 goto end;
717 }
718
719 /* Add null termination. */
720 name_len += 1;
721
722 if (exclusion_count > UINT32_MAX) {
723 /* Possible overflow. */
724 ret = -1;
725 goto end;
726 }
727
728 if (bytecode_len > UINT32_MAX) {
729 /* Possible overflow. */
730 ret = -1;
731 goto end;
732 }
733
734 event_comm.name_len = (uint32_t) name_len;
735 event_comm.event_type = (int8_t) event->type;
736 event_comm.loglevel_type = (int8_t) event->loglevel_type;
737 event_comm.loglevel = (int32_t) event->loglevel;
738 event_comm.enabled = (int8_t) event->enabled;
739 event_comm.pid = (int32_t) event->pid;
740 event_comm.exclusion_count = (uint32_t) exclusion_count;
741 event_comm.bytecode_len = (uint32_t) bytecode_len;
742 event_comm.flags = (int32_t) event->flags;
743
744 if (filter_expression) {
745 event_comm.filter_expression_len =
746 strlen(filter_expression) + 1;
747 }
748
749 /* Header */
750 ret = lttng_dynamic_buffer_append(
751 &payload->buffer, &event_comm, sizeof(event_comm));
752 if (ret) {
753 goto end;
754 }
755
756 /* Event name */
757 ret = lttng_dynamic_buffer_append(
758 &payload->buffer, event->name, name_len);
759 if (ret) {
760 goto end;
761 }
762
763 /* Exclusions */
764 for (i = 0; i < exclusion_count; i++) {
765 const size_t exclusion_len = lttng_strnlen(
766 *(exclusion_list + i), LTTNG_SYMBOL_NAME_LEN);
767 const struct lttng_event_exclusion_comm exclusion_header = {
768 .len = (uint32_t) exclusion_len + 1,
769 };
770
771 if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) {
772 /* Exclusion is not NULL-terminated. */
773 ret = -1;
774 goto end;
775 }
776
777 ret = lttng_dynamic_buffer_append(&payload->buffer,
778 &exclusion_header, sizeof(exclusion_header));
779 if (ret) {
780 goto end;
781 }
782
783 ret = lttng_dynamic_buffer_append(&payload->buffer,
784 *(exclusion_list + i), exclusion_len + 1);
785 if (ret) {
786 goto end;
787 }
788 }
789
790 /* Filter expression and its bytecode */
791 if (filter_expression) {
792 ret = lttng_dynamic_buffer_append(&payload->buffer,
793 filter_expression,
794 event_comm.filter_expression_len);
795 if (ret) {
796 goto end;
797 }
798
799 /*
800 * Bytecode can be absent when we serialize to the client
801 * for listing.
802 */
803 if (bytecode) {
804 ret = lttng_dynamic_buffer_append(&payload->buffer,
805 bytecode, bytecode_len);
806 if (ret) {
807 goto end;
808 }
809 }
810 }
811
812 size_before_payload = payload->buffer.size;
813
814 /* Event type specific payload */
815 switch (event->type) {
816 case LTTNG_EVENT_FUNCTION:
817 /* Fallthrough */
818 case LTTNG_EVENT_PROBE:
819 ret = lttng_event_probe_attr_serialize(&event->attr.probe, payload);
820 if (ret) {
821 ret = -1;
822 goto end;
823 }
824
825 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
826 header_offset);
827 header->lttng_event_probe_attr_len =
828 payload->buffer.size - size_before_payload;
829
830 break;
831 case LTTNG_EVENT_FUNCTION_ENTRY:
832 ret = lttng_event_function_attr_serialize(
833 &event->attr.ftrace, payload);
834 if (ret) {
835 ret = -1;
836 goto end;
837 }
838
839 /* Update the lttng_event_function_attr len. */
840 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
841 header_offset);
842 header->lttng_event_function_attr_len =
843 payload->buffer.size - size_before_payload;
844
845 break;
846 case LTTNG_EVENT_USERSPACE_PROBE:
847 {
848 const struct lttng_event_extended *ev_ext =
849 (const struct lttng_event_extended *)
850 event->extended.ptr;
851
852 assert(event->extended.ptr);
853 assert(ev_ext->probe_location);
854
855 size_before_payload = payload->buffer.size;
856 if (ev_ext->probe_location) {
857 /*
858 * lttng_userspace_probe_location_serialize returns the
859 * number of bytes that were appended to the buffer.
860 */
861 ret = lttng_userspace_probe_location_serialize(
862 ev_ext->probe_location, payload);
863 if (ret < 0) {
864 goto end;
865 }
866
867 ret = 0;
868
869 /* Update the userspace probe location len. */
870 header = (struct lttng_event_comm *) ((char *) payload->buffer.data +
871 header_offset);
872 header->userspace_probe_location_len =
873 payload->buffer.size - size_before_payload;
874 }
875 break;
876 }
877 case LTTNG_EVENT_TRACEPOINT:
878 /* Fallthrough */
879 case LTTNG_EVENT_ALL:
880 /* Fallthrough */
881 default:
882 /* Nothing to do here. */
883 break;
884 }
885
886 end:
887 return ret;
888 }
889
890 static ssize_t lttng_event_context_app_populate_from_payload(
891 const struct lttng_payload_view *view,
892 struct lttng_event_context *event_ctx)
893 {
894 ssize_t ret, offset = 0;
895 const struct lttng_event_context_app_comm *comm;
896 char *provider_name = NULL, *context_name = NULL;
897 size_t provider_name_len, context_name_len;
898 const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
899 &view->buffer, offset, sizeof(*comm));
900
901 assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
902
903 if (!lttng_buffer_view_is_valid(&comm_view)) {
904 ret = -1;
905 goto end;
906 }
907
908 comm = (typeof(comm)) comm_view.data;
909 offset += sizeof(*comm);
910
911 provider_name_len = comm->provider_name_len;
912 context_name_len = comm->ctx_name_len;
913
914 if (provider_name_len == 0 || context_name_len == 0) {
915 /*
916 * Application provider and context names MUST
917 * be provided.
918 */
919 ret = -1;
920 goto end;
921 }
922
923 {
924 const char *name;
925 const struct lttng_buffer_view provider_name_view =
926 lttng_buffer_view_from_view(&view->buffer,
927 offset,
928 provider_name_len);
929
930 if (!lttng_buffer_view_is_valid(&provider_name_view)) {
931 ret = -1;
932 goto end;
933 }
934
935 name = provider_name_view.data;
936
937 if (!lttng_buffer_view_contains_string(&provider_name_view,
938 name, provider_name_len)) {
939 ret = -1;
940 goto end;
941 }
942
943 provider_name = lttng_strndup(name, provider_name_len);
944 if (!provider_name) {
945 ret = -1;
946 goto end;
947 }
948
949 offset += provider_name_len;
950 }
951
952 {
953 const char *name;
954 const struct lttng_buffer_view context_name_view =
955 lttng_buffer_view_from_view(
956 &view->buffer, offset,
957 context_name_len);
958
959 if (!lttng_buffer_view_is_valid(&context_name_view)) {
960 ret = -1;
961 goto end;
962 }
963
964 name = context_name_view.data;
965
966 if (!lttng_buffer_view_contains_string(&context_name_view, name,
967 context_name_len)) {
968 ret = -1;
969 goto end;
970 }
971
972 context_name = lttng_strndup(name, context_name_len);
973 if (!context_name) {
974 ret = -1;
975 goto end;
976 }
977
978 offset += context_name_len;
979 }
980
981 /* Transfer ownership of the strings */
982 event_ctx->u.app_ctx.provider_name = provider_name;
983 event_ctx->u.app_ctx.ctx_name = context_name;
984 provider_name = NULL;
985 context_name = NULL;
986
987 ret = offset;
988 end:
989 free(provider_name);
990 free(context_name);
991
992 return ret;
993 }
994
995 static ssize_t lttng_event_context_perf_counter_populate_from_payload(
996 const struct lttng_payload_view *view,
997 struct lttng_event_context *event_ctx)
998 {
999 ssize_t ret, offset = 0;
1000 const struct lttng_event_context_perf_counter_comm *comm;
1001 size_t name_len;
1002 const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1003 &view->buffer, offset, sizeof(*comm));
1004
1005 assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER ||
1006 event_ctx->ctx ==
1007 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER ||
1008 event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER);
1009
1010 if (!lttng_buffer_view_is_valid(&comm_view)) {
1011 ret = -1;
1012 goto end;
1013 }
1014
1015 comm = (typeof(comm)) comm_view.data;
1016 offset += sizeof(*comm);
1017
1018 name_len = comm->name_len;
1019
1020 {
1021 const char *name;
1022 const struct lttng_buffer_view provider_name_view =
1023 lttng_buffer_view_from_view(
1024 &view->buffer, offset,
1025 name_len);
1026
1027 if (!lttng_buffer_view_is_valid(&provider_name_view)) {
1028 ret = -1;
1029 goto end;
1030 }
1031
1032 name = provider_name_view.data;
1033
1034 if (!lttng_buffer_view_contains_string(
1035 &provider_name_view, name, name_len)) {
1036 ret = -1;
1037 goto end;
1038 }
1039
1040 lttng_strncpy(event_ctx->u.perf_counter.name, name, name_len);
1041 offset += name_len;
1042 }
1043
1044 event_ctx->u.perf_counter.config = comm->config;
1045 event_ctx->u.perf_counter.type = comm->type;
1046
1047 ret = offset;
1048
1049 end:
1050 return ret;
1051 }
1052
1053 ssize_t lttng_event_context_create_from_payload(
1054 struct lttng_payload_view *view,
1055 struct lttng_event_context **event_ctx)
1056 {
1057 ssize_t ret, offset = 0;
1058 const struct lttng_event_context_comm *comm;
1059 struct lttng_event_context *local_context = NULL;
1060 struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
1061 &view->buffer, offset, sizeof(*comm));
1062
1063 assert(event_ctx);
1064 assert(view);
1065
1066 if (!lttng_buffer_view_is_valid(&comm_view)) {
1067 ret = -1;
1068 goto end;
1069 }
1070
1071 comm = (typeof(comm)) comm_view.data;
1072 offset += sizeof(*comm);
1073
1074 local_context = (struct lttng_event_context *)
1075 zmalloc(sizeof(*local_context));
1076 if (!local_context) {
1077 ret = -1;
1078 goto end;
1079 }
1080
1081 local_context->ctx = (enum lttng_event_context_type) comm->type;
1082
1083 {
1084 struct lttng_payload_view subtype_view =
1085 lttng_payload_view_from_view(view, offset, -1);
1086
1087 switch (local_context->ctx) {
1088 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
1089 ret = lttng_event_context_app_populate_from_payload(
1090 &subtype_view, local_context);
1091 break;
1092 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
1093 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
1094 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
1095 ret = lttng_event_context_perf_counter_populate_from_payload(
1096 &subtype_view, local_context);
1097 break;
1098 default:
1099 /* Nothing else to deserialize. */
1100 ret = 0;
1101 break;
1102 }
1103 }
1104
1105 if (ret < 0) {
1106 goto end;
1107 }
1108
1109 offset += ret;
1110
1111 *event_ctx = local_context;
1112 local_context = NULL;
1113 ret = offset;
1114
1115 end:
1116 free(local_context);
1117 return ret;
1118 }
1119
1120 static int lttng_event_context_app_serialize(
1121 struct lttng_event_context *context,
1122 struct lttng_payload *payload)
1123 {
1124 int ret;
1125 struct lttng_event_context_app_comm comm = { 0 };
1126 size_t provider_len, ctx_len;
1127 const char *provider_name;
1128 const char *ctx_name;
1129
1130 assert(payload);
1131 assert(context);
1132 assert(context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
1133
1134 provider_name = context->u.app_ctx.provider_name;
1135 ctx_name = context->u.app_ctx.ctx_name;
1136
1137 if (!provider_name || !ctx_name) {
1138 ret = -LTTNG_ERR_INVALID;
1139 goto end;
1140 }
1141
1142 provider_len = strlen(provider_name);
1143 if (provider_len == 0) {
1144 ret = -LTTNG_ERR_INVALID;
1145 goto end;
1146 }
1147
1148 /* Include the null terminator. */
1149 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
1182 end:
1183 return ret;
1184 }
1185
1186 static 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
1223 end:
1224 return ret;
1225 }
1226
1227 int 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
1264 end:
1265 return ret;
1266 }
1267
1268 void 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
1282 static enum lttng_error_code compute_flattened_size(
1283 struct lttng_dynamic_pointer_array *events, size_t *size)
1284 {
1285 enum lttng_error_code ret_code;
1286 int ret = 0;
1287 size_t storage_req, event_count, i;
1288
1289 assert(size);
1290 assert(events);
1291
1292 event_count = lttng_dynamic_pointer_array_get_count(events);
1293
1294 /* The basic struct lttng_event */
1295 storage_req = event_count * sizeof(struct lttng_event);
1296
1297 for (i = 0; i < event_count; i++) {
1298 int probe_storage_req = 0;
1299 const struct event_list_element *element = (const struct event_list_element *)
1300 lttng_dynamic_pointer_array_get_pointer(
1301 events, i);
1302 const struct lttng_userspace_probe_location *location = NULL;
1303
1304 location = lttng_event_get_userspace_probe_location(
1305 element->event);
1306 if (location) {
1307 ret = lttng_userspace_probe_location_flatten(
1308 location, NULL);
1309 if (ret < 0) {
1310 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1311 goto end;
1312 }
1313
1314 probe_storage_req = ret;
1315 }
1316
1317 /* The struct·lttng_event_extended */
1318 storage_req += event_count *
1319 sizeof(struct lttng_event_extended);
1320
1321 if (element->filter_expression) {
1322 storage_req += strlen(element->filter_expression) + 1;
1323 }
1324
1325 if (element->exclusions) {
1326 storage_req += element->exclusions->count *
1327 LTTNG_SYMBOL_NAME_LEN;
1328 }
1329
1330 /* Padding to ensure the flat probe is aligned. */
1331 storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
1332 storage_req += probe_storage_req;
1333 }
1334
1335 *size = storage_req;
1336 ret_code = LTTNG_OK;
1337
1338 end:
1339 return ret_code;
1340 }
1341
1342 /*
1343 * Flatten a list of struct lttng_event.
1344 *
1345 * The buffer that is returned to the API client must contain a "flat" version
1346 * of the events that are returned. In other words, all pointers within an
1347 * lttng_event must point to a location within the returned buffer so that the
1348 * user may free everything by simply calling free() on the returned buffer.
1349 * This is needed in order to maintain API compatibility.
1350 *
1351 * A first pass is performed to compute the size of the buffer that must be
1352 * allocated. A second pass is then performed to setup the returned events so
1353 * that their members always point within the buffer.
1354 *
1355 * The layout of the returned buffer is as follows:
1356 * - struct lttng_event[nb_events],
1357 * - nb_events times the following:
1358 * - struct lttng_event_extended,
1359 * - filter_expression
1360 * - exclusions
1361 * - padding to align to 64-bits
1362 * - flattened version of userspace_probe_location
1363 */
1364 static enum lttng_error_code flatten_lttng_events(
1365 struct lttng_dynamic_pointer_array *events,
1366 struct lttng_event **flattened_events)
1367 {
1368 enum lttng_error_code ret_code;
1369 int ret, i;
1370 size_t storage_req;
1371 struct lttng_dynamic_buffer local_flattened_events;
1372 int nb_events;
1373
1374 assert(events);
1375 assert(flattened_events);
1376
1377 lttng_dynamic_buffer_init(&local_flattened_events);
1378 nb_events = lttng_dynamic_pointer_array_get_count(events);
1379
1380 ret_code = compute_flattened_size(events, &storage_req);
1381 if (ret_code != LTTNG_OK) {
1382 goto end;
1383 }
1384
1385 /*
1386 * We must ensure that "local_flattened_events" is never resized so as
1387 * to preserve the validity of the flattened objects.
1388 */
1389 ret = lttng_dynamic_buffer_set_capacity(
1390 &local_flattened_events, storage_req);
1391 if (ret) {
1392 ret_code = LTTNG_ERR_NOMEM;
1393 goto end;
1394 }
1395
1396 /* Start by laying the struct lttng_event */
1397 for (i = 0; i < nb_events; i++) {
1398 const struct event_list_element *element = (const struct event_list_element *)
1399 lttng_dynamic_pointer_array_get_pointer(
1400 events, i);
1401
1402 if (!element) {
1403 ret_code = LTTNG_ERR_FATAL;
1404 goto end;
1405 }
1406
1407 ret = lttng_dynamic_buffer_append(&local_flattened_events,
1408 element->event, sizeof(struct lttng_event));
1409 if (ret) {
1410 ret_code = LTTNG_ERR_NOMEM;
1411 goto end;
1412 }
1413 }
1414
1415 for (i = 0; i < nb_events; i++) {
1416 const struct event_list_element *element = (const struct event_list_element *)
1417 lttng_dynamic_pointer_array_get_pointer(events, i);
1418 struct lttng_event *event = (struct lttng_event *)
1419 (local_flattened_events.data + (sizeof(struct lttng_event) * i));
1420 struct lttng_event_extended *event_extended =
1421 (struct lttng_event_extended *)
1422 (local_flattened_events.data + local_flattened_events.size);
1423 const struct lttng_userspace_probe_location *location = NULL;
1424
1425 assert(element);
1426
1427 /* Insert struct lttng_event_extended. */
1428 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1429 local_flattened_events.size +
1430 sizeof(*event_extended));
1431 if (ret) {
1432 ret_code = LTTNG_ERR_NOMEM;
1433 goto end;
1434 }
1435 event->extended.ptr = event_extended;
1436
1437 /* Insert filter expression. */
1438 if (element->filter_expression) {
1439 const size_t len = strlen(element->filter_expression) + 1;
1440
1441 event_extended->filter_expression =
1442 local_flattened_events.data +
1443 local_flattened_events.size;
1444 ret = lttng_dynamic_buffer_append(
1445 &local_flattened_events,
1446 element->filter_expression, len);
1447 if (ret) {
1448 ret_code = LTTNG_ERR_NOMEM;
1449 goto end;
1450 }
1451 }
1452
1453 /* Insert exclusions. */
1454 if (element->exclusions) {
1455 event_extended->exclusions.count =
1456 element->exclusions->count;
1457 event_extended->exclusions.strings =
1458 local_flattened_events.data +
1459 local_flattened_events.size;
1460
1461 ret = lttng_dynamic_buffer_append(
1462 &local_flattened_events,
1463 element->exclusions->names,
1464 element->exclusions->count *
1465 LTTNG_SYMBOL_NAME_LEN);
1466 if (ret) {
1467 ret_code = LTTNG_ERR_NOMEM;
1468 goto end;
1469 }
1470 }
1471
1472 /* Insert padding to align to 64-bits. */
1473 ret = lttng_dynamic_buffer_set_size(&local_flattened_events,
1474 ALIGN_TO(local_flattened_events.size,
1475 sizeof(uint64_t)));
1476 if (ret) {
1477 ret_code = LTTNG_ERR_NOMEM;
1478 goto end;
1479 }
1480
1481 location = lttng_event_get_userspace_probe_location(
1482 element->event);
1483 if (location) {
1484 event_extended->probe_location = (struct lttng_userspace_probe_location *)
1485 (local_flattened_events.data + local_flattened_events.size);
1486 ret = lttng_userspace_probe_location_flatten(
1487 location, &local_flattened_events);
1488 if (ret < 0) {
1489 ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
1490 goto end;
1491 }
1492 }
1493 }
1494
1495 /* Don't reset local_flattened_events buffer as we return its content. */
1496 *flattened_events = (struct lttng_event *) local_flattened_events.data;
1497 lttng_dynamic_buffer_init(&local_flattened_events);
1498 ret_code = LTTNG_OK;
1499 end:
1500 lttng_dynamic_buffer_reset(&local_flattened_events);
1501 return ret_code;
1502 }
1503
1504 static enum lttng_error_code event_list_create_from_payload(
1505 struct lttng_payload_view *view,
1506 unsigned int count,
1507 struct lttng_dynamic_pointer_array *event_list)
1508 {
1509 enum lttng_error_code ret_code;
1510 int ret;
1511 unsigned int i;
1512 int offset = 0;
1513
1514 assert(view);
1515 assert(event_list);
1516
1517 for (i = 0; i < count; i++) {
1518 ssize_t event_size;
1519 struct lttng_payload_view event_view =
1520 lttng_payload_view_from_view(view, offset, -1);
1521 struct event_list_element *element =
1522 (struct event_list_element *) zmalloc(sizeof(*element));
1523
1524 if (!element) {
1525 ret_code = LTTNG_ERR_NOMEM;
1526 goto end;
1527 }
1528
1529 /*
1530 * Lifetime and management of the object is now bound to the
1531 * array.
1532 */
1533 ret = lttng_dynamic_pointer_array_add_pointer(
1534 event_list, element);
1535 if (ret) {
1536 event_list_destructor(element);
1537 ret_code = LTTNG_ERR_NOMEM;
1538 goto end;
1539 }
1540
1541 /*
1542 * Bytecode is not transmitted on listing in any case we do not
1543 * care about it.
1544 */
1545 event_size = lttng_event_create_from_payload(&event_view,
1546 &element->event,
1547 &element->exclusions,
1548 &element->filter_expression, NULL);
1549 if (event_size < 0) {
1550 ret_code = LTTNG_ERR_INVALID;
1551 goto end;
1552 }
1553
1554 offset += event_size;
1555 }
1556
1557 if (view->buffer.size != offset) {
1558 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
1559 goto end;
1560 }
1561
1562 ret_code = LTTNG_OK;
1563
1564 end:
1565 return ret_code;
1566 }
1567
1568 enum lttng_error_code lttng_events_create_and_flatten_from_payload(
1569 struct lttng_payload_view *payload,
1570 unsigned int count,
1571 struct lttng_event **events)
1572 {
1573 enum lttng_error_code ret = LTTNG_OK;
1574 struct lttng_dynamic_pointer_array local_events;
1575
1576 lttng_dynamic_pointer_array_init(&local_events, event_list_destructor);
1577
1578 /* Deserialize the events. */
1579 {
1580 struct lttng_payload_view events_view =
1581 lttng_payload_view_from_view(payload, 0, -1);
1582
1583 ret = event_list_create_from_payload(
1584 &events_view, count, &local_events);
1585 if (ret != LTTNG_OK) {
1586 goto end;
1587 }
1588 }
1589
1590 ret = flatten_lttng_events(&local_events, events);
1591 if (ret != LTTNG_OK) {
1592 goto end;
1593 }
1594
1595 end:
1596 lttng_dynamic_pointer_array_reset(&local_events);
1597 return ret;
1598 }
This page took 0.091217 seconds and 4 git commands to generate.