Fix: `ctf` plugin: use element FC's alignment as array/seq. FC alignment
[babeltrace.git] / src / plugins / ctf / common / metadata / ctf-meta-update-alignments.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2020 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #include <babeltrace2/babeltrace.h>
8 #include "common/macros.h"
9 #include "common/assert.h"
10 #include <glib.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <inttypes.h>
14
15 #include "ctf-meta-visitors.h"
16
17 static inline
18 int set_alignments(struct ctf_field_class *fc)
19 {
20 int ret = 0;
21 uint64_t i;
22
23 if (!fc) {
24 goto end;
25 }
26
27 switch (fc->type) {
28 case CTF_FIELD_CLASS_TYPE_STRUCT:
29 {
30 struct ctf_field_class_struct *struct_fc = (void *) fc;
31
32 for (i = 0; i < struct_fc->members->len; i++) {
33 struct ctf_named_field_class *named_fc =
34 ctf_field_class_struct_borrow_member_by_index(
35 struct_fc, i);
36
37 ret = set_alignments(named_fc->fc);
38 if (ret) {
39 goto end;
40 }
41
42 if (named_fc->fc->alignment > fc->alignment) {
43 fc->alignment = named_fc->fc->alignment;
44 }
45 }
46
47 break;
48 }
49 case CTF_FIELD_CLASS_TYPE_VARIANT:
50 {
51 struct ctf_field_class_variant *var_fc = (void *) fc;
52
53 for (i = 0; i < var_fc->options->len; i++) {
54 struct ctf_named_field_class *named_fc =
55 ctf_field_class_variant_borrow_option_by_index(
56 var_fc, i);
57
58 ret = set_alignments(named_fc->fc);
59 if (ret) {
60 goto end;
61 }
62 }
63
64 break;
65 }
66 case CTF_FIELD_CLASS_TYPE_ARRAY:
67 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
68 {
69 struct ctf_field_class_array_base *array_fc = (void *) fc;
70
71 ret = set_alignments(array_fc->elem_fc);
72 if (ret) {
73 goto end;
74 }
75
76 /*
77 * Use the alignment of the array/sequence field class's
78 * element FC as its own alignment.
79 *
80 * This is especially important when the array/sequence
81 * field's effective length is zero: as per CTF 1.8, the
82 * stream data decoding process still needs to align the
83 * cursor using the element's alignment [1]:
84 *
85 * > Arrays are always aligned on their element
86 * > alignment requirement.
87 *
88 * For example:
89 *
90 * struct {
91 * integer { size = 8; } a;
92 * integer { size = 8; align = 16; } b[0];
93 * integer { size = 8; } c;
94 * };
95 *
96 * When using this to decode the bytes 1, 2, and 3, then
97 * the decoded values are:
98 *
99 * `a`: 1
100 * `b`: []
101 * `c`: 3
102 *
103 * [1]: https://diamon.org/ctf/#spec4.2.3
104 */
105 array_fc->base.alignment = array_fc->elem_fc->alignment;
106 break;
107 }
108 default:
109 break;
110 }
111
112 end:
113 return ret;
114 }
115
116 BT_HIDDEN
117 int ctf_trace_class_update_alignments(
118 struct ctf_trace_class *ctf_tc)
119 {
120 int ret = 0;
121 uint64_t i;
122
123 if (!ctf_tc->is_translated) {
124 ret = set_alignments(ctf_tc->packet_header_fc);
125 if (ret) {
126 goto end;
127 }
128 }
129
130 for (i = 0; i < ctf_tc->stream_classes->len; i++) {
131 struct ctf_stream_class *sc = ctf_tc->stream_classes->pdata[i];
132 uint64_t j;
133
134 if (!sc->is_translated) {
135 ret = set_alignments(sc->packet_context_fc);
136 if (ret) {
137 goto end;
138 }
139
140 ret = set_alignments(sc->event_header_fc);
141 if (ret) {
142 goto end;
143 }
144
145 ret = set_alignments(sc->event_common_context_fc);
146 if (ret) {
147 goto end;
148 }
149 }
150
151 for (j = 0; j < sc->event_classes->len; j++) {
152 struct ctf_event_class *ec =
153 sc->event_classes->pdata[j];
154
155 if (ec->is_translated) {
156 continue;
157 }
158
159 ret = set_alignments(ec->spec_context_fc);
160 if (ret) {
161 goto end;
162 }
163
164 ret = set_alignments(ec->payload_fc);
165 if (ret) {
166 goto end;
167 }
168 }
169 }
170
171 end:
172 return ret;
173 }
This page took 0.032684 seconds and 4 git commands to generate.