4 * Babeltrace - CTF IR: Validation of trace, stream class, and event class
6 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define BT_LOG_TAG "VALIDATION"
28 #include <babeltrace/lib-logging-internal.h>
30 #include <babeltrace/ctf-ir/validation-internal.h>
31 #include <babeltrace/ctf-ir/resolve-internal.h>
32 #include <babeltrace/ctf-ir/trace-internal.h>
33 #include <babeltrace/ctf-ir/stream-class-internal.h>
34 #include <babeltrace/ctf-ir/field-types-internal.h>
35 #include <babeltrace/ctf-ir/event-class-internal.h>
36 #include <babeltrace/values.h>
37 #include <babeltrace/babeltrace-internal.h>
38 #include <babeltrace/ref.h>
41 * This function resolves and validates the field types of an event
42 * class. Only `event_context_type` and `event_payload_type` are
43 * resolved and validated; the other field types are used as eventual
46 * All parameters are owned by the caller.
49 int validate_event_class_types(struct bt_value
*environment
,
50 struct bt_field_type
*packet_header_type
,
51 struct bt_field_type
*packet_context_type
,
52 struct bt_field_type
*event_header_type
,
53 struct bt_field_type
*stream_event_ctx_type
,
54 struct bt_field_type
*event_context_type
,
55 struct bt_field_type
*event_payload_type
)
59 BT_LOGV("Validating event class field types: "
60 "packet-header-ft-addr=%p, "
61 "packet-context-ft-addr=%p, "
62 "event-header-ft-addr=%p, "
63 "stream-event-context-ft-addr=%p, "
64 "event-context-ft-addr=%p, "
65 "event-payload-ft-addr=%p",
66 packet_header_type
, packet_context_type
, event_header_type
,
67 stream_event_ctx_type
, event_context_type
, event_payload_type
);
69 /* Resolve sequence type lengths and variant type tags first */
70 ret
= bt_resolve_types(environment
, packet_header_type
,
71 packet_context_type
, event_header_type
, stream_event_ctx_type
,
72 event_context_type
, event_payload_type
,
73 BT_RESOLVE_FLAG_EVENT_CONTEXT
|
74 BT_RESOLVE_FLAG_EVENT_PAYLOAD
);
76 BT_LOGW("Cannot resolve event class field types: ret=%d",
81 /* Validate field types individually */
82 if (event_context_type
) {
83 ret
= bt_field_type_validate(event_context_type
);
85 BT_LOGW("Invalid event class's context field type: "
91 if (event_payload_type
) {
92 ret
= bt_field_type_validate(event_payload_type
);
94 BT_LOGW("Invalid event class's payload field type: "
105 * This function resolves and validates the field types of a stream
106 * class. Only `packet_context_type`, `event_header_type`, and
107 * `stream_event_ctx_type` are resolved and validated; the other field
108 * type is used as an eventual resolving target.
110 * All parameters are owned by the caller.
113 int validate_stream_class_types(struct bt_value
*environment
,
114 struct bt_field_type
*packet_header_type
,
115 struct bt_field_type
*packet_context_type
,
116 struct bt_field_type
*event_header_type
,
117 struct bt_field_type
*stream_event_ctx_type
)
121 BT_LOGV("Validating stream class field types: "
122 "packet-header-ft-addr=%p, "
123 "packet-context-ft-addr=%p, "
124 "event-header-ft-addr=%p, "
125 "stream-event-context-ft-addr=%p",
126 packet_header_type
, packet_context_type
, event_header_type
,
127 stream_event_ctx_type
);
129 /* Resolve sequence type lengths and variant type tags first */
130 ret
= bt_resolve_types(environment
, packet_header_type
,
131 packet_context_type
, event_header_type
, stream_event_ctx_type
,
133 BT_RESOLVE_FLAG_PACKET_CONTEXT
|
134 BT_RESOLVE_FLAG_EVENT_HEADER
|
135 BT_RESOLVE_FLAG_STREAM_EVENT_CTX
);
137 BT_LOGW("Cannot resolve stream class field types: ret=%d",
142 /* Validate field types individually */
143 if (packet_context_type
) {
144 ret
= bt_field_type_validate(packet_context_type
);
146 BT_LOGW("Invalid stream class's packet context field type: "
152 if (event_header_type
) {
153 ret
= bt_field_type_validate(event_header_type
);
155 BT_LOGW("Invalid stream class's event header field type: "
161 if (stream_event_ctx_type
) {
162 ret
= bt_field_type_validate(
163 stream_event_ctx_type
);
165 BT_LOGW("Invalid stream class's event context field type: "
176 * This function resolves and validates the field types of a trace.
178 * All parameters are owned by the caller.
181 int validate_trace_types(struct bt_value
*environment
,
182 struct bt_field_type
*packet_header_type
)
186 BT_LOGV("Validating event class field types: "
187 "packet-header-ft-addr=%p", packet_header_type
);
189 /* Resolve sequence type lengths and variant type tags first */
190 ret
= bt_resolve_types(environment
, packet_header_type
,
191 NULL
, NULL
, NULL
, NULL
, NULL
,
192 BT_RESOLVE_FLAG_PACKET_HEADER
);
194 BT_LOGW("Cannot resolve trace field types: ret=%d",
199 /* Validate field types individually */
200 if (packet_header_type
) {
201 ret
= bt_field_type_validate(packet_header_type
);
203 BT_LOGW("Invalid trace's packet header field type: "
214 * Checks whether or not `field_type` contains a variant or a sequence
215 * field type, recursively. Returns 1 if it's the case.
217 * `field_type` is owned by the caller.
220 int field_type_contains_sequence_or_variant_ft(struct bt_field_type
*type
)
223 enum bt_field_type_id type_id
= bt_field_type_get_type_id(type
);
226 case BT_FIELD_TYPE_ID_SEQUENCE
:
227 case BT_FIELD_TYPE_ID_VARIANT
:
230 case BT_FIELD_TYPE_ID_ARRAY
:
231 case BT_FIELD_TYPE_ID_STRUCT
:
234 int field_count
= bt_field_type_get_field_count(type
);
236 if (field_count
< 0) {
241 for (i
= 0; i
< field_count
; ++i
) {
242 struct bt_field_type
*child_type
=
243 bt_field_type_get_field_at_index(type
, i
);
245 ret
= field_type_contains_sequence_or_variant_ft(
263 int bt_validate_class_types(struct bt_value
*environment
,
264 struct bt_field_type
*packet_header_type
,
265 struct bt_field_type
*packet_context_type
,
266 struct bt_field_type
*event_header_type
,
267 struct bt_field_type
*stream_event_ctx_type
,
268 struct bt_field_type
*event_context_type
,
269 struct bt_field_type
*event_payload_type
,
270 int trace_valid
, int stream_class_valid
, int event_class_valid
,
271 struct bt_validation_output
*output
,
272 enum bt_validation_flag validate_flags
)
275 int contains_seq_var
;
278 BT_LOGV("Validating field types: "
279 "packet-header-ft-addr=%p, "
280 "packet-context-ft-addr=%p, "
281 "event-header-ft-addr=%p, "
282 "stream-event-context-ft-addr=%p, "
283 "event-context-ft-addr=%p, "
284 "event-payload-ft-addr=%p, "
285 "trace-is-valid=%d, stream-class-is-valid=%d, "
286 "event-class-is-valid=%d, validation-flags=%x",
287 packet_header_type
, packet_context_type
, event_header_type
,
288 stream_event_ctx_type
, event_context_type
, event_payload_type
,
289 trace_valid
, stream_class_valid
, event_class_valid
,
290 (unsigned int) validate_flags
);
292 /* Clean output values */
293 memset(output
, 0, sizeof(*output
));
295 /* Set initial valid flags according to valid parameters */
297 output
->valid_flags
|= BT_VALIDATION_FLAG_TRACE
;
300 if (stream_class_valid
) {
301 output
->valid_flags
|= BT_VALIDATION_FLAG_STREAM
;
304 if (event_class_valid
) {
305 output
->valid_flags
|= BT_VALIDATION_FLAG_EVENT
;
308 /* Own the type parameters */
309 bt_get(packet_header_type
);
310 bt_get(packet_context_type
);
311 bt_get(event_header_type
);
312 bt_get(stream_event_ctx_type
);
313 bt_get(event_context_type
);
314 bt_get(event_payload_type
);
317 if ((validate_flags
& BT_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
318 struct bt_field_type
*packet_header_type_copy
= NULL
;
320 /* Create field type copies */
321 if (packet_header_type
) {
323 field_type_contains_sequence_or_variant_ft(
325 if (contains_seq_var
< 0) {
326 ret
= contains_seq_var
;
328 } else if (!contains_seq_var
) {
329 /* No copy is needed */
330 packet_header_type_copy
= packet_header_type
;
331 bt_get(packet_header_type_copy
);
332 goto skip_packet_header_type_copy
;
335 BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
336 packet_header_type_copy
=
337 bt_field_type_copy(packet_header_type
);
338 if (!packet_header_type_copy
) {
340 BT_LOGE_STR("Cannot copy packet header field type.");
345 * Freeze this copy: if it's returned to the
346 * caller, it cannot be modified any way since
347 * it will be resolved.
349 bt_field_type_freeze(packet_header_type_copy
);
352 skip_packet_header_type_copy
:
353 /* Put original reference and move copy */
354 BT_MOVE(packet_header_type
, packet_header_type_copy
);
356 /* Validate trace field types */
357 valid_ret
= validate_trace_types(environment
,
359 if (valid_ret
== 0) {
361 output
->valid_flags
|= BT_VALIDATION_FLAG_TRACE
;
365 /* Validate stream class */
366 if ((validate_flags
& BT_VALIDATION_FLAG_STREAM
) &&
367 !stream_class_valid
) {
368 struct bt_field_type
*packet_context_type_copy
= NULL
;
369 struct bt_field_type
*event_header_type_copy
= NULL
;
370 struct bt_field_type
*stream_event_ctx_type_copy
= NULL
;
372 if (packet_context_type
) {
374 field_type_contains_sequence_or_variant_ft(
375 packet_context_type
);
376 if (contains_seq_var
< 0) {
377 ret
= contains_seq_var
;
379 } else if (!contains_seq_var
) {
380 /* No copy is needed */
381 packet_context_type_copy
= packet_context_type
;
382 bt_get(packet_context_type_copy
);
383 goto skip_packet_context_type_copy
;
386 BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
387 packet_context_type_copy
=
388 bt_field_type_copy(packet_context_type
);
389 if (!packet_context_type_copy
) {
390 BT_LOGE_STR("Cannot copy packet context field type.");
391 goto sc_validation_error
;
395 * Freeze this copy: if it's returned to the
396 * caller, it cannot be modified any way since
397 * it will be resolved.
399 bt_field_type_freeze(packet_context_type_copy
);
402 skip_packet_context_type_copy
:
403 if (event_header_type
) {
405 field_type_contains_sequence_or_variant_ft(
407 if (contains_seq_var
< 0) {
408 ret
= contains_seq_var
;
410 } else if (!contains_seq_var
) {
411 /* No copy is needed */
412 event_header_type_copy
= event_header_type
;
413 bt_get(event_header_type_copy
);
414 goto skip_event_header_type_copy
;
417 BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
418 event_header_type_copy
=
419 bt_field_type_copy(event_header_type
);
420 if (!event_header_type_copy
) {
421 BT_LOGE_STR("Cannot copy event header field type.");
422 goto sc_validation_error
;
426 * Freeze this copy: if it's returned to the
427 * caller, it cannot be modified any way since
428 * it will be resolved.
430 bt_field_type_freeze(event_header_type_copy
);
433 skip_event_header_type_copy
:
434 if (stream_event_ctx_type
) {
436 field_type_contains_sequence_or_variant_ft(
437 stream_event_ctx_type
);
438 if (contains_seq_var
< 0) {
439 ret
= contains_seq_var
;
441 } else if (!contains_seq_var
) {
442 /* No copy is needed */
443 stream_event_ctx_type_copy
=
444 stream_event_ctx_type
;
445 bt_get(stream_event_ctx_type_copy
);
446 goto skip_stream_event_ctx_type_copy
;
449 BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
450 stream_event_ctx_type_copy
=
451 bt_field_type_copy(stream_event_ctx_type
);
452 if (!stream_event_ctx_type_copy
) {
453 BT_LOGE_STR("Cannot copy stream event context field type.");
454 goto sc_validation_error
;
458 * Freeze this copy: if it's returned to the
459 * caller, it cannot be modified any way since
460 * it will be resolved.
462 bt_field_type_freeze(stream_event_ctx_type_copy
);
465 skip_stream_event_ctx_type_copy
:
466 /* Put original references and move copies */
467 BT_MOVE(packet_context_type
, packet_context_type_copy
);
468 BT_MOVE(event_header_type
, event_header_type_copy
);
469 BT_MOVE(stream_event_ctx_type
, stream_event_ctx_type_copy
);
471 /* Validate stream class field types */
472 valid_ret
= validate_stream_class_types(environment
,
473 packet_header_type
, packet_context_type
,
474 event_header_type
, stream_event_ctx_type
);
475 if (valid_ret
== 0) {
476 /* Stream class is valid */
477 output
->valid_flags
|= BT_VALIDATION_FLAG_STREAM
;
480 goto sc_validation_done
;
483 BT_PUT(packet_context_type_copy
);
484 BT_PUT(event_header_type_copy
);
485 BT_PUT(stream_event_ctx_type_copy
);
491 /* Validate event class */
492 if ((validate_flags
& BT_VALIDATION_FLAG_EVENT
) &&
493 !event_class_valid
) {
494 struct bt_field_type
*event_context_type_copy
= NULL
;
495 struct bt_field_type
*event_payload_type_copy
= NULL
;
497 if (event_context_type
) {
499 field_type_contains_sequence_or_variant_ft(
501 if (contains_seq_var
< 0) {
502 ret
= contains_seq_var
;
504 } else if (!contains_seq_var
) {
505 /* No copy is needed */
506 event_context_type_copy
= event_context_type
;
507 bt_get(event_context_type_copy
);
508 goto skip_event_context_type_copy
;
511 BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
512 event_context_type_copy
=
513 bt_field_type_copy(event_context_type
);
514 if (!event_context_type_copy
) {
515 BT_LOGE_STR("Cannot copy event context field type.");
516 goto ec_validation_error
;
520 * Freeze this copy: if it's returned to the
521 * caller, it cannot be modified any way since
522 * it will be resolved.
524 bt_field_type_freeze(event_context_type_copy
);
527 skip_event_context_type_copy
:
528 if (event_payload_type
) {
530 field_type_contains_sequence_or_variant_ft(
532 if (contains_seq_var
< 0) {
533 ret
= contains_seq_var
;
535 } else if (!contains_seq_var
) {
536 /* No copy is needed */
537 event_payload_type_copy
= event_payload_type
;
538 bt_get(event_payload_type_copy
);
539 goto skip_event_payload_type_copy
;
542 BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
543 event_payload_type_copy
=
544 bt_field_type_copy(event_payload_type
);
545 if (!event_payload_type_copy
) {
546 BT_LOGE_STR("Cannot copy event payload field type.");
547 goto ec_validation_error
;
551 * Freeze this copy: if it's returned to the
552 * caller, it cannot be modified any way since
553 * it will be resolved.
555 bt_field_type_freeze(event_payload_type_copy
);
558 skip_event_payload_type_copy
:
559 /* Put original references and move copies */
560 BT_MOVE(event_context_type
, event_context_type_copy
);
561 BT_MOVE(event_payload_type
, event_payload_type_copy
);
563 /* Validate event class field types */
564 valid_ret
= validate_event_class_types(environment
,
565 packet_header_type
, packet_context_type
,
566 event_header_type
, stream_event_ctx_type
,
567 event_context_type
, event_payload_type
);
568 if (valid_ret
== 0) {
569 /* Event class is valid */
570 output
->valid_flags
|= BT_VALIDATION_FLAG_EVENT
;
573 goto ec_validation_done
;
576 BT_PUT(event_context_type_copy
);
577 BT_PUT(event_payload_type_copy
);
584 * Validation is complete. Move the field types that were used
585 * to validate (and that were possibly altered by the validation
586 * process) to the output values.
588 BT_MOVE(output
->packet_header_type
, packet_header_type
);
589 BT_MOVE(output
->packet_context_type
, packet_context_type
);
590 BT_MOVE(output
->event_header_type
, event_header_type
);
591 BT_MOVE(output
->stream_event_ctx_type
, stream_event_ctx_type
);
592 BT_MOVE(output
->event_context_type
, event_context_type
);
593 BT_MOVE(output
->event_payload_type
, event_payload_type
);
597 BT_PUT(packet_header_type
);
598 BT_PUT(packet_context_type
);
599 BT_PUT(event_header_type
);
600 BT_PUT(stream_event_ctx_type
);
601 BT_PUT(event_context_type
);
602 BT_PUT(event_payload_type
);
607 void bt_validation_replace_types(struct bt_trace
*trace
,
608 struct bt_stream_class
*stream_class
,
609 struct bt_event_class
*event_class
,
610 struct bt_validation_output
*output
,
611 enum bt_validation_flag replace_flags
)
613 if ((replace_flags
& BT_VALIDATION_FLAG_TRACE
) && trace
) {
614 bt_field_type_freeze(trace
->packet_header_type
);
615 BT_MOVE(trace
->packet_header_type
, output
->packet_header_type
);
618 if ((replace_flags
& BT_VALIDATION_FLAG_STREAM
) && stream_class
) {
619 bt_field_type_freeze(stream_class
->packet_context_type
);
620 bt_field_type_freeze(stream_class
->event_header_type
);
621 bt_field_type_freeze(stream_class
->event_context_type
);
622 BT_MOVE(stream_class
->packet_context_type
,
623 output
->packet_context_type
);
624 BT_MOVE(stream_class
->event_header_type
,
625 output
->event_header_type
);
626 BT_MOVE(stream_class
->event_context_type
,
627 output
->stream_event_ctx_type
);
630 if ((replace_flags
& BT_VALIDATION_FLAG_EVENT
) && event_class
) {
631 bt_field_type_freeze(event_class
->context
);
632 bt_field_type_freeze(event_class
->fields
);
633 BT_MOVE(event_class
->context
, output
->event_context_type
);
634 BT_MOVE(event_class
->fields
, output
->event_payload_type
);
639 void bt_validation_output_put_types(
640 struct bt_validation_output
*output
)
642 BT_PUT(output
->packet_header_type
);
643 BT_PUT(output
->packet_context_type
);
644 BT_PUT(output
->event_header_type
);
645 BT_PUT(output
->stream_event_ctx_type
);
646 BT_PUT(output
->event_context_type
);
647 BT_PUT(output
->event_payload_type
);