4 * Babeltrace - CTF IR: Validation of trace, stream class, and event class
6 * Copyright 2016-2018 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/assert-pre-internal.h>
31 #include <babeltrace/ctf-ir/validation-internal.h>
32 #include <babeltrace/ctf-ir/resolve-internal.h>
33 #include <babeltrace/ctf-ir/trace-internal.h>
34 #include <babeltrace/ctf-ir/stream-class-internal.h>
35 #include <babeltrace/ctf-ir/field-types-internal.h>
36 #include <babeltrace/ctf-ir/event-class-internal.h>
37 #include <babeltrace/ctf-ir/field-types-internal.h>
38 #include <babeltrace/values.h>
39 #include <babeltrace/babeltrace-internal.h>
40 #include <babeltrace/ref.h>
43 * This function resolves and validates the field types of an event
44 * class. Only `event_context_type` and `event_payload_type` are
45 * resolved and validated; the other field types are used as eventual
48 * All parameters are owned by the caller.
51 int validate_event_class_types(struct bt_value
*environment
,
52 struct bt_field_type
*packet_header_type
,
53 struct bt_field_type
*packet_context_type
,
54 struct bt_field_type
*event_header_type
,
55 struct bt_field_type
*stream_event_ctx_type
,
56 struct bt_field_type
*event_context_type
,
57 struct bt_field_type
*event_payload_type
)
61 BT_LOGV("Validating event class field types: "
62 "packet-header-ft-addr=%p, "
63 "packet-context-ft-addr=%p, "
64 "event-header-ft-addr=%p, "
65 "stream-event-context-ft-addr=%p, "
66 "event-context-ft-addr=%p, "
67 "event-payload-ft-addr=%p",
68 packet_header_type
, packet_context_type
, event_header_type
,
69 stream_event_ctx_type
, event_context_type
, event_payload_type
);
71 /* Resolve sequence type lengths and variant type tags first */
72 ret
= bt_resolve_types(environment
, packet_header_type
,
73 packet_context_type
, event_header_type
, stream_event_ctx_type
,
74 event_context_type
, event_payload_type
,
75 BT_RESOLVE_FLAG_EVENT_CONTEXT
|
76 BT_RESOLVE_FLAG_EVENT_PAYLOAD
);
78 BT_LOGW("Cannot resolve event class field types: ret=%d",
83 /* Validate field types individually */
84 if (event_context_type
) {
85 ret
= bt_field_type_validate(event_context_type
);
87 BT_LOGW("Invalid event class's context field type: "
93 if (event_payload_type
) {
94 ret
= bt_field_type_validate(event_payload_type
);
96 BT_LOGW("Invalid event class's payload field type: "
107 * This function resolves and validates the field types of a stream
108 * class. Only `packet_context_type`, `event_header_type`, and
109 * `stream_event_ctx_type` are resolved and validated; the other field
110 * type is used as an eventual resolving target.
112 * All parameters are owned by the caller.
115 int validate_stream_class_types(struct bt_value
*environment
,
116 struct bt_field_type
*packet_header_type
,
117 struct bt_field_type
*packet_context_type
,
118 struct bt_field_type
*event_header_type
,
119 struct bt_field_type
*stream_event_ctx_type
)
123 BT_LOGV("Validating stream class field types: "
124 "packet-header-ft-addr=%p, "
125 "packet-context-ft-addr=%p, "
126 "event-header-ft-addr=%p, "
127 "stream-event-context-ft-addr=%p",
128 packet_header_type
, packet_context_type
, event_header_type
,
129 stream_event_ctx_type
);
131 /* Resolve sequence type lengths and variant type tags first */
132 ret
= bt_resolve_types(environment
, packet_header_type
,
133 packet_context_type
, event_header_type
, stream_event_ctx_type
,
135 BT_RESOLVE_FLAG_PACKET_CONTEXT
|
136 BT_RESOLVE_FLAG_EVENT_HEADER
|
137 BT_RESOLVE_FLAG_STREAM_EVENT_CTX
);
139 BT_LOGW("Cannot resolve stream class field types: ret=%d",
144 /* Validate field types individually */
145 if (packet_context_type
) {
146 ret
= bt_field_type_validate(packet_context_type
);
148 BT_LOGW("Invalid stream class's packet context field type: "
154 if (event_header_type
) {
155 ret
= bt_field_type_validate(event_header_type
);
157 BT_LOGW("Invalid stream class's event header field type: "
163 if (stream_event_ctx_type
) {
164 ret
= bt_field_type_validate(
165 stream_event_ctx_type
);
167 BT_LOGW("Invalid stream class's event context field type: "
178 * This function resolves and validates the field types of a trace.
180 * All parameters are owned by the caller.
183 int validate_trace_types(struct bt_value
*environment
,
184 struct bt_field_type
*packet_header_type
)
188 BT_LOGV("Validating event class field types: "
189 "packet-header-ft-addr=%p", packet_header_type
);
191 /* Resolve sequence type lengths and variant type tags first */
192 ret
= bt_resolve_types(environment
, packet_header_type
,
193 NULL
, NULL
, NULL
, NULL
, NULL
,
194 BT_RESOLVE_FLAG_PACKET_HEADER
);
196 BT_LOGW("Cannot resolve trace field types: ret=%d",
201 /* Validate field types individually */
202 if (packet_header_type
) {
203 ret
= bt_field_type_validate(packet_header_type
);
205 BT_LOGW("Invalid trace's packet header field type: "
216 * Checks whether or not `field_type` contains a variant or a sequence
217 * field type, recursively. Returns 1 if it's the case.
219 * `field_type` is owned by the caller.
222 int field_type_contains_sequence_or_variant_ft(struct bt_field_type
*type
)
225 enum bt_field_type_id type_id
= bt_field_type_get_type_id(type
);
228 case BT_FIELD_TYPE_ID_SEQUENCE
:
229 case BT_FIELD_TYPE_ID_VARIANT
:
232 case BT_FIELD_TYPE_ID_ARRAY
:
233 case BT_FIELD_TYPE_ID_STRUCT
:
236 int field_count
= bt_field_type_get_field_count(type
);
238 if (field_count
< 0) {
243 for (i
= 0; i
< field_count
; ++i
) {
244 struct bt_field_type
*child_type
=
245 bt_field_type_borrow_field_at_index(
248 ret
= field_type_contains_sequence_or_variant_ft(
265 int bt_validate_class_types(struct bt_value
*environment
,
266 struct bt_field_type
*packet_header_type
,
267 struct bt_field_type
*packet_context_type
,
268 struct bt_field_type
*event_header_type
,
269 struct bt_field_type
*stream_event_ctx_type
,
270 struct bt_field_type
*event_context_type
,
271 struct bt_field_type
*event_payload_type
,
272 int trace_valid
, int stream_class_valid
, int event_class_valid
,
273 struct bt_validation_output
*output
,
274 enum bt_validation_flag validate_flags
,
275 bt_validation_flag_copy_field_type_func copy_field_type_func
)
278 int contains_seq_var
;
281 BT_LOGV("Validating field types: "
282 "packet-header-ft-addr=%p, "
283 "packet-context-ft-addr=%p, "
284 "event-header-ft-addr=%p, "
285 "stream-event-context-ft-addr=%p, "
286 "event-context-ft-addr=%p, "
287 "event-payload-ft-addr=%p, "
288 "trace-is-valid=%d, stream-class-is-valid=%d, "
289 "event-class-is-valid=%d, validation-flags=%x",
290 packet_header_type
, packet_context_type
, event_header_type
,
291 stream_event_ctx_type
, event_context_type
, event_payload_type
,
292 trace_valid
, stream_class_valid
, event_class_valid
,
293 (unsigned int) validate_flags
);
295 /* Clean output values */
296 memset(output
, 0, sizeof(*output
));
298 /* Set initial valid flags according to valid parameters */
300 output
->valid_flags
|= BT_VALIDATION_FLAG_TRACE
;
303 if (stream_class_valid
) {
304 output
->valid_flags
|= BT_VALIDATION_FLAG_STREAM
;
307 if (event_class_valid
) {
308 output
->valid_flags
|= BT_VALIDATION_FLAG_EVENT
;
311 /* Own the type parameters */
312 bt_get(packet_header_type
);
313 bt_get(packet_context_type
);
314 bt_get(event_header_type
);
315 bt_get(stream_event_ctx_type
);
316 bt_get(event_context_type
);
317 bt_get(event_payload_type
);
320 if ((validate_flags
& BT_VALIDATION_FLAG_TRACE
) && !trace_valid
) {
321 struct bt_field_type
*packet_header_type_copy
= NULL
;
323 /* Create field type copies */
324 if (packet_header_type
) {
326 field_type_contains_sequence_or_variant_ft(
328 if (contains_seq_var
< 0) {
329 ret
= contains_seq_var
;
331 } else if (!contains_seq_var
) {
332 /* No copy is needed */
333 packet_header_type_copy
= packet_header_type
;
334 bt_get(packet_header_type_copy
);
335 goto skip_packet_header_type_copy
;
338 BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
339 packet_header_type_copy
=
340 copy_field_type_func(packet_header_type
);
341 if (!packet_header_type_copy
) {
343 BT_LOGE_STR("Cannot copy packet header field type.");
348 * Freeze this copy: if it's returned to the
349 * caller, it cannot be modified any way since
350 * it will be resolved.
352 bt_field_type_freeze(packet_header_type_copy
);
355 skip_packet_header_type_copy
:
356 /* Put original reference and move copy */
357 BT_MOVE(packet_header_type
, packet_header_type_copy
);
359 /* Validate trace field types */
360 valid_ret
= validate_trace_types(environment
,
362 if (valid_ret
== 0) {
364 output
->valid_flags
|= BT_VALIDATION_FLAG_TRACE
;
368 /* Validate stream class */
369 if ((validate_flags
& BT_VALIDATION_FLAG_STREAM
) &&
370 !stream_class_valid
) {
371 struct bt_field_type
*packet_context_type_copy
= NULL
;
372 struct bt_field_type
*event_header_type_copy
= NULL
;
373 struct bt_field_type
*stream_event_ctx_type_copy
= NULL
;
375 if (packet_context_type
) {
377 field_type_contains_sequence_or_variant_ft(
378 packet_context_type
);
379 if (contains_seq_var
< 0) {
380 ret
= contains_seq_var
;
382 } else if (!contains_seq_var
) {
383 /* No copy is needed */
384 packet_context_type_copy
= packet_context_type
;
385 bt_get(packet_context_type_copy
);
386 goto skip_packet_context_type_copy
;
389 BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
390 packet_context_type_copy
=
391 copy_field_type_func(packet_context_type
);
392 if (!packet_context_type_copy
) {
393 BT_LOGE_STR("Cannot copy packet context field type.");
394 goto sc_validation_error
;
398 * Freeze this copy: if it's returned to the
399 * caller, it cannot be modified any way since
400 * it will be resolved.
402 bt_field_type_freeze(packet_context_type_copy
);
405 skip_packet_context_type_copy
:
406 if (event_header_type
) {
408 field_type_contains_sequence_or_variant_ft(
410 if (contains_seq_var
< 0) {
411 ret
= contains_seq_var
;
413 } else if (!contains_seq_var
) {
414 /* No copy is needed */
415 event_header_type_copy
= event_header_type
;
416 bt_get(event_header_type_copy
);
417 goto skip_event_header_type_copy
;
420 BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
421 event_header_type_copy
=
422 copy_field_type_func(event_header_type
);
423 if (!event_header_type_copy
) {
424 BT_LOGE_STR("Cannot copy event header field type.");
425 goto sc_validation_error
;
429 * Freeze this copy: if it's returned to the
430 * caller, it cannot be modified any way since
431 * it will be resolved.
433 bt_field_type_freeze(event_header_type_copy
);
436 skip_event_header_type_copy
:
437 if (stream_event_ctx_type
) {
439 field_type_contains_sequence_or_variant_ft(
440 stream_event_ctx_type
);
441 if (contains_seq_var
< 0) {
442 ret
= contains_seq_var
;
444 } else if (!contains_seq_var
) {
445 /* No copy is needed */
446 stream_event_ctx_type_copy
=
447 stream_event_ctx_type
;
448 bt_get(stream_event_ctx_type_copy
);
449 goto skip_stream_event_ctx_type_copy
;
452 BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
453 stream_event_ctx_type_copy
=
454 copy_field_type_func(stream_event_ctx_type
);
455 if (!stream_event_ctx_type_copy
) {
456 BT_LOGE_STR("Cannot copy stream event context field type.");
457 goto sc_validation_error
;
461 * Freeze this copy: if it's returned to the
462 * caller, it cannot be modified any way since
463 * it will be resolved.
465 bt_field_type_freeze(stream_event_ctx_type_copy
);
468 skip_stream_event_ctx_type_copy
:
469 /* Put original references and move copies */
470 BT_MOVE(packet_context_type
, packet_context_type_copy
);
471 BT_MOVE(event_header_type
, event_header_type_copy
);
472 BT_MOVE(stream_event_ctx_type
, stream_event_ctx_type_copy
);
474 /* Validate stream class field types */
475 valid_ret
= validate_stream_class_types(environment
,
476 packet_header_type
, packet_context_type
,
477 event_header_type
, stream_event_ctx_type
);
478 if (valid_ret
== 0) {
479 /* Stream class is valid */
480 output
->valid_flags
|= BT_VALIDATION_FLAG_STREAM
;
483 goto sc_validation_done
;
486 BT_PUT(packet_context_type_copy
);
487 BT_PUT(event_header_type_copy
);
488 BT_PUT(stream_event_ctx_type_copy
);
494 /* Validate event class */
495 if ((validate_flags
& BT_VALIDATION_FLAG_EVENT
) &&
496 !event_class_valid
) {
497 struct bt_field_type
*event_context_type_copy
= NULL
;
498 struct bt_field_type
*event_payload_type_copy
= NULL
;
500 if (event_context_type
) {
502 field_type_contains_sequence_or_variant_ft(
504 if (contains_seq_var
< 0) {
505 ret
= contains_seq_var
;
507 } else if (!contains_seq_var
) {
508 /* No copy is needed */
509 event_context_type_copy
= event_context_type
;
510 bt_get(event_context_type_copy
);
511 goto skip_event_context_type_copy
;
514 BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
515 event_context_type_copy
=
516 copy_field_type_func(event_context_type
);
517 if (!event_context_type_copy
) {
518 BT_LOGE_STR("Cannot copy event context field type.");
519 goto ec_validation_error
;
523 * Freeze this copy: if it's returned to the
524 * caller, it cannot be modified any way since
525 * it will be resolved.
527 bt_field_type_freeze(event_context_type_copy
);
530 skip_event_context_type_copy
:
531 if (event_payload_type
) {
533 field_type_contains_sequence_or_variant_ft(
535 if (contains_seq_var
< 0) {
536 ret
= contains_seq_var
;
538 } else if (!contains_seq_var
) {
539 /* No copy is needed */
540 event_payload_type_copy
= event_payload_type
;
541 bt_get(event_payload_type_copy
);
542 goto skip_event_payload_type_copy
;
545 BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
546 event_payload_type_copy
=
547 copy_field_type_func(event_payload_type
);
548 if (!event_payload_type_copy
) {
549 BT_LOGE_STR("Cannot copy event payload field type.");
550 goto ec_validation_error
;
554 * Freeze this copy: if it's returned to the
555 * caller, it cannot be modified any way since
556 * it will be resolved.
558 bt_field_type_freeze(event_payload_type_copy
);
561 skip_event_payload_type_copy
:
562 /* Put original references and move copies */
563 BT_MOVE(event_context_type
, event_context_type_copy
);
564 BT_MOVE(event_payload_type
, event_payload_type_copy
);
566 /* Validate event class field types */
567 valid_ret
= validate_event_class_types(environment
,
568 packet_header_type
, packet_context_type
,
569 event_header_type
, stream_event_ctx_type
,
570 event_context_type
, event_payload_type
);
571 if (valid_ret
== 0) {
572 /* Event class is valid */
573 output
->valid_flags
|= BT_VALIDATION_FLAG_EVENT
;
576 goto ec_validation_done
;
579 BT_PUT(event_context_type_copy
);
580 BT_PUT(event_payload_type_copy
);
587 * Validation is complete. Move the field types that were used
588 * to validate (and that were possibly altered by the validation
589 * process) to the output values.
591 BT_MOVE(output
->packet_header_type
, packet_header_type
);
592 BT_MOVE(output
->packet_context_type
, packet_context_type
);
593 BT_MOVE(output
->event_header_type
, event_header_type
);
594 BT_MOVE(output
->stream_event_ctx_type
, stream_event_ctx_type
);
595 BT_MOVE(output
->event_context_type
, event_context_type
);
596 BT_MOVE(output
->event_payload_type
, event_payload_type
);
600 BT_PUT(packet_header_type
);
601 BT_PUT(packet_context_type
);
602 BT_PUT(event_header_type
);
603 BT_PUT(stream_event_ctx_type
);
604 BT_PUT(event_context_type
);
605 BT_PUT(event_payload_type
);
610 void bt_validation_replace_types(struct bt_trace
*trace
,
611 struct bt_stream_class
*stream_class
,
612 struct bt_event_class
*event_class
,
613 struct bt_validation_output
*output
,
614 enum bt_validation_flag replace_flags
)
616 if ((replace_flags
& BT_VALIDATION_FLAG_TRACE
) && trace
) {
617 bt_field_type_freeze(trace
->packet_header_field_type
);
618 BT_MOVE(trace
->packet_header_field_type
,
619 output
->packet_header_type
);
622 if ((replace_flags
& BT_VALIDATION_FLAG_STREAM
) && stream_class
) {
623 bt_field_type_freeze(stream_class
->packet_context_field_type
);
624 bt_field_type_freeze(stream_class
->event_header_field_type
);
625 bt_field_type_freeze(stream_class
->event_context_field_type
);
626 BT_MOVE(stream_class
->packet_context_field_type
,
627 output
->packet_context_type
);
628 BT_MOVE(stream_class
->event_header_field_type
,
629 output
->event_header_type
);
630 BT_MOVE(stream_class
->event_context_field_type
,
631 output
->stream_event_ctx_type
);
634 if ((replace_flags
& BT_VALIDATION_FLAG_EVENT
) && event_class
) {
635 bt_field_type_freeze(event_class
->context_field_type
);
636 bt_field_type_freeze(event_class
->payload_field_type
);
637 BT_MOVE(event_class
->context_field_type
, output
->event_context_type
);
638 BT_MOVE(event_class
->payload_field_type
, output
->event_payload_type
);
643 void bt_validation_output_put_types(
644 struct bt_validation_output
*output
)
646 BT_PUT(output
->packet_header_type
);
647 BT_PUT(output
->packet_context_type
);
648 BT_PUT(output
->event_header_type
);
649 BT_PUT(output
->stream_event_ctx_type
);
650 BT_PUT(output
->event_context_type
);
651 BT_PUT(output
->event_payload_type
);