Commit | Line | Data |
---|---|---|
44c440bc | 1 | /* |
0235b0db | 2 | * SPDX-License-Identifier: MIT |
44c440bc | 3 | * |
0235b0db | 4 | * Copyright 2018 Philippe Proulx <pproulx@efficios.com> |
44c440bc PP |
5 | */ |
6 | ||
0f5c5d5c | 7 | #include <babeltrace2/babeltrace.h> |
c802cacb | 8 | |
0f5c5d5c | 9 | #include "cpp-common/bt2c/logging.hpp" |
44c440bc | 10 | |
087cd0f5 | 11 | #include "ctf-meta-visitors.hpp" |
44c440bc | 12 | |
0f5c5d5c | 13 | static int validate_stream_class(struct ctf_stream_class *sc, const bt2c::Logger& logger) |
44c440bc | 14 | { |
4164020e SM |
15 | int ret = 0; |
16 | struct ctf_field_class_int *int_fc; | |
17 | struct ctf_field_class *fc; | |
18 | ||
19 | if (sc->is_translated) { | |
20 | goto end; | |
21 | } | |
22 | ||
23 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
24 | ctf_field_class_as_struct(sc->packet_context_fc), "timestamp_begin"); | |
25 | if (fc) { | |
26 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
27 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
28 | "Invalid packet context field class: " | |
29 | "`timestamp_begin` member is not an integer field class."); | |
4164020e SM |
30 | goto invalid; |
31 | } | |
32 | ||
33 | int_fc = ctf_field_class_as_int(fc); | |
34 | ||
35 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
36 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
37 | "`timestamp_begin` member is signed."); | |
4164020e SM |
38 | goto invalid; |
39 | } | |
40 | } | |
41 | ||
42 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
43 | ctf_field_class_as_struct(sc->packet_context_fc), "timestamp_end"); | |
44 | if (fc) { | |
45 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
46 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
47 | "Invalid packet context field class: " | |
48 | "`timestamp_end` member is not an integer field class."); | |
4164020e SM |
49 | goto invalid; |
50 | } | |
51 | ||
52 | int_fc = ctf_field_class_as_int(fc); | |
53 | ||
54 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
55 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
56 | "`timestamp_end` member is signed."); | |
4164020e SM |
57 | goto invalid; |
58 | } | |
59 | } | |
60 | ||
61 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
62 | ctf_field_class_as_struct(sc->packet_context_fc), "events_discarded"); | |
63 | if (fc) { | |
64 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
65 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
66 | logger, "Invalid packet context field class: " | |
67 | "`events_discarded` member is not an integer field class."); | |
4164020e SM |
68 | goto invalid; |
69 | } | |
70 | ||
71 | int_fc = ctf_field_class_as_int(fc); | |
72 | ||
73 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
74 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
75 | "`events_discarded` member is signed."); | |
4164020e SM |
76 | goto invalid; |
77 | } | |
78 | } | |
79 | ||
80 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
81 | ctf_field_class_as_struct(sc->packet_context_fc), "packet_seq_num"); | |
82 | if (fc) { | |
83 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
84 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
85 | "Invalid packet context field class: " | |
86 | "`packet_seq_num` member is not an integer field class."); | |
4164020e SM |
87 | goto invalid; |
88 | } | |
89 | ||
90 | int_fc = ctf_field_class_as_int(fc); | |
91 | ||
92 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
93 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
94 | "`packet_seq_num` member is signed."); | |
4164020e SM |
95 | goto invalid; |
96 | } | |
97 | } | |
98 | ||
99 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
100 | ctf_field_class_as_struct(sc->packet_context_fc), "packet_size"); | |
101 | if (fc) { | |
102 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
103 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
104 | "Invalid packet context field class: " | |
105 | "`packet_size` member is not an integer field class."); | |
4164020e SM |
106 | goto invalid; |
107 | } | |
108 | ||
109 | int_fc = ctf_field_class_as_int(fc); | |
110 | ||
111 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
112 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
113 | "`packet_size` member is signed."); | |
4164020e SM |
114 | goto invalid; |
115 | } | |
116 | } | |
117 | ||
118 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
119 | ctf_field_class_as_struct(sc->packet_context_fc), "content_size"); | |
120 | if (fc) { | |
121 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
122 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
123 | "Invalid packet context field class: " | |
124 | "`content_size` member is not an integer field class."); | |
4164020e SM |
125 | goto invalid; |
126 | } | |
127 | ||
128 | int_fc = ctf_field_class_as_int(fc); | |
129 | ||
130 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
131 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet context field class: " |
132 | "`content_size` member is signed."); | |
4164020e SM |
133 | goto invalid; |
134 | } | |
135 | } | |
136 | ||
137 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
138 | ctf_field_class_as_struct(sc->event_header_fc), "id"); | |
139 | if (fc) { | |
140 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
141 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid event header field class: " |
142 | "`id` member is not an integer field class."); | |
4164020e SM |
143 | goto invalid; |
144 | } | |
145 | ||
146 | int_fc = ctf_field_class_as_int(fc); | |
147 | ||
148 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
149 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid event header field class: " |
150 | "`id` member is signed."); | |
4164020e SM |
151 | goto invalid; |
152 | } | |
153 | } else { | |
154 | if (sc->event_classes->len > 1) { | |
0f5c5d5c SM |
155 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid event header field class: " |
156 | "missing `id` member as there's " | |
157 | "more than one event class."); | |
4164020e SM |
158 | goto invalid; |
159 | } | |
160 | } | |
161 | ||
162 | goto end; | |
44c440bc PP |
163 | |
164 | invalid: | |
4164020e | 165 | ret = -1; |
44c440bc PP |
166 | |
167 | end: | |
4164020e | 168 | return ret; |
44c440bc PP |
169 | } |
170 | ||
0f5c5d5c | 171 | int ctf_trace_class_validate(struct ctf_trace_class *ctf_tc, const bt2c::Logger& parentLogger) |
44c440bc | 172 | { |
4164020e SM |
173 | int ret = 0; |
174 | struct ctf_field_class_int *int_fc; | |
175 | uint64_t i; | |
176 | ||
0f5c5d5c SM |
177 | bt2c::Logger logger {parentLogger, "PLUGIN/CTF/META/VALIDATE"}; |
178 | ||
4164020e SM |
179 | if (!ctf_tc->is_translated) { |
180 | struct ctf_field_class *fc; | |
181 | ||
182 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
183 | ctf_field_class_as_struct(ctf_tc->packet_header_fc), "magic"); | |
184 | if (fc) { | |
185 | struct ctf_named_field_class *named_fc = ctf_field_class_struct_borrow_member_by_index( | |
186 | ctf_field_class_as_struct(ctf_tc->packet_header_fc), 0); | |
187 | ||
188 | if (named_fc->fc != fc) { | |
0f5c5d5c SM |
189 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
190 | "`magic` member is not the first member."); | |
4164020e SM |
191 | goto invalid; |
192 | } | |
193 | ||
194 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
195 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
196 | "Invalid packet header field class: " | |
197 | "`magic` member is not an integer field class."); | |
4164020e SM |
198 | goto invalid; |
199 | } | |
200 | ||
201 | int_fc = ctf_field_class_as_int(fc); | |
202 | ||
203 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
204 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
205 | "`magic` member is signed."); | |
4164020e SM |
206 | goto invalid; |
207 | } | |
208 | ||
209 | if (int_fc->base.size != 32) { | |
0f5c5d5c SM |
210 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
211 | "`magic` member is not 32-bit."); | |
4164020e SM |
212 | goto invalid; |
213 | } | |
214 | } | |
215 | ||
216 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
217 | ctf_field_class_as_struct(ctf_tc->packet_header_fc), "stream_id"); | |
218 | if (fc) { | |
219 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
220 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, |
221 | "Invalid packet header field class: " | |
222 | "`stream_id` member is not an integer field class."); | |
4164020e SM |
223 | goto invalid; |
224 | } | |
225 | ||
226 | int_fc = ctf_field_class_as_int(fc); | |
227 | ||
228 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
229 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
230 | "`stream_id` member is signed."); | |
4164020e SM |
231 | goto invalid; |
232 | } | |
233 | } else { | |
234 | if (ctf_tc->stream_classes->len > 1) { | |
0f5c5d5c SM |
235 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
236 | "missing `stream_id` member as there's " | |
237 | "more than one stream class."); | |
4164020e SM |
238 | goto invalid; |
239 | } | |
240 | } | |
241 | ||
242 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
243 | ctf_field_class_as_struct(ctf_tc->packet_header_fc), "stream_instance_id"); | |
244 | if (fc) { | |
245 | if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) { | |
0f5c5d5c SM |
246 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
247 | logger, "Invalid packet header field class: " | |
248 | "`stream_instance_id` member is not an integer field class."); | |
4164020e SM |
249 | goto invalid; |
250 | } | |
251 | ||
252 | int_fc = ctf_field_class_as_int(fc); | |
253 | ||
254 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
255 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
256 | "`stream_instance_id` member is signed."); | |
4164020e SM |
257 | goto invalid; |
258 | } | |
259 | } | |
260 | ||
261 | fc = ctf_field_class_struct_borrow_member_field_class_by_name( | |
262 | ctf_field_class_as_struct(ctf_tc->packet_header_fc), "uuid"); | |
263 | if (fc) { | |
264 | if (fc->type != CTF_FIELD_CLASS_TYPE_ARRAY) { | |
0f5c5d5c SM |
265 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
266 | "`uuid` member is not an array field class."); | |
4164020e SM |
267 | goto invalid; |
268 | } | |
269 | ||
270 | ctf_field_class_array *array_fc = ctf_field_class_as_array(fc); | |
271 | ||
272 | if (array_fc->length != 16) { | |
0f5c5d5c SM |
273 | BT_CPPLOGE_APPEND_CAUSE_SPEC( |
274 | logger, "Invalid packet header field class: " | |
275 | "`uuid` member is not a 16-element array field class."); | |
4164020e SM |
276 | goto invalid; |
277 | } | |
278 | ||
279 | if (array_fc->base.elem_fc->type != CTF_FIELD_CLASS_TYPE_INT) { | |
0f5c5d5c SM |
280 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
281 | "`uuid` member's element field class is not " | |
282 | "an integer field class."); | |
4164020e SM |
283 | goto invalid; |
284 | } | |
285 | ||
286 | int_fc = ctf_field_class_as_int(array_fc->base.elem_fc); | |
287 | ||
288 | if (int_fc->is_signed) { | |
0f5c5d5c SM |
289 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
290 | "`uuid` member's element field class " | |
291 | "is a signed integer field class."); | |
4164020e SM |
292 | goto invalid; |
293 | } | |
294 | ||
295 | if (int_fc->base.size != 8) { | |
0f5c5d5c SM |
296 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
297 | "`uuid` member's element field class " | |
298 | "is not an 8-bit integer field class."); | |
4164020e SM |
299 | goto invalid; |
300 | } | |
301 | ||
302 | if (int_fc->base.base.alignment != 8) { | |
0f5c5d5c SM |
303 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid packet header field class: " |
304 | "`uuid` member's element field class's " | |
305 | "alignment is not 8."); | |
4164020e SM |
306 | goto invalid; |
307 | } | |
308 | } | |
309 | } | |
310 | ||
311 | for (i = 0; i < ctf_tc->stream_classes->len; i++) { | |
312 | struct ctf_stream_class *sc = (ctf_stream_class *) ctf_tc->stream_classes->pdata[i]; | |
313 | ||
0f5c5d5c | 314 | ret = validate_stream_class(sc, logger); |
4164020e | 315 | if (ret) { |
0f5c5d5c | 316 | BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Invalid stream class: sc-id={}", sc->id); |
4164020e SM |
317 | goto invalid; |
318 | } | |
319 | } | |
320 | ||
321 | goto end; | |
44c440bc PP |
322 | |
323 | invalid: | |
4164020e | 324 | ret = -1; |
44c440bc PP |
325 | |
326 | end: | |
4164020e | 327 | return ret; |
44c440bc | 328 | } |