2 * SPDX-License-Identifier: MIT
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Common Trace Format Metadata Semantic Validator.
9 #define BT_COMP_LOG_SELF_COMP (log_cfg->self_comp)
10 #define BT_LOG_OUTPUT_LEVEL (log_cfg->log_level)
11 #define BT_LOG_TAG "PLUGIN/CTF/META/SEMANTIC-VALIDATOR-VISITOR"
12 #include "logging/comp-logging.h"
18 #include "common/assert.h"
22 #include "common/list.h"
27 #define _bt_list_first_entry(ptr, type, member) \
28 bt_list_entry((ptr)->next, type, member)
31 int _ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
,
32 struct meta_log_config
*log_cfg
);
35 int ctf_visitor_unary_expression(int depth
, struct ctf_node
*node
,
36 struct meta_log_config
*log_cfg
)
38 struct ctf_node
*iter
;
39 int is_ctf_exp
= 0, is_ctf_exp_left
= 0;
41 switch (node
->parent
->type
) {
42 case NODE_CTF_EXPRESSION
:
44 bt_list_for_each_entry(iter
, &node
->parent
->u
.ctf_expression
.left
,
49 * We are a left child of a ctf expression.
50 * We are only allowed to be a string.
52 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
53 _BT_COMP_LOGE_LINENO(node
->lineno
,
54 "Left child of a CTF expression is only allowed to be a string.");
60 /* Right child of a ctf expression can be any type of unary exp. */
62 case NODE_TYPE_DECLARATOR
:
64 * We are the length of a type declarator.
66 switch (node
->u
.unary_expression
.type
) {
67 case UNARY_UNSIGNED_CONSTANT
:
71 _BT_COMP_LOGE_LINENO(node
->lineno
,
72 "Children of field class declarator and `enum` can only be unsigned numeric constants or references to fields (e.g., `a.b.c`).");
79 * We are the size of a struct align attribute.
81 switch (node
->u
.unary_expression
.type
) {
82 case UNARY_UNSIGNED_CONSTANT
:
85 _BT_COMP_LOGE_LINENO(node
->lineno
,
86 "Structure alignment attribute can only be an unsigned numeric constant.");
92 /* The enumerator's parent has validated its validity already. */
95 case NODE_UNARY_EXPRESSION
:
97 * We disallow nested unary expressions and "sbrac" unary
100 _BT_COMP_LOGE_LINENO(node
->lineno
,
101 "Nested unary expressions not allowed (`()` and `[]`).");
112 case NODE_TYPEALIAS_TARGET
:
113 case NODE_TYPEALIAS_ALIAS
:
115 case NODE_TYPE_SPECIFIER
:
117 case NODE_FLOATING_POINT
:
121 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
127 switch (node
->u
.unary_expression
.link
) {
128 case UNARY_LINK_UNKNOWN
:
129 /* We don't allow empty link except on the first node of the list */
130 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
131 &node
->parent
->u
.ctf_expression
.left
:
132 &node
->parent
->u
.ctf_expression
.right
,
135 _BT_COMP_LOGE_LINENO(node
->lineno
,
136 "Empty link is not allowed except on first node of unary expression (need to separate nodes with `.` or `->`).");
141 case UNARY_ARROWLINK
:
142 /* We only allow -> and . links between children of ctf_expression. */
143 if (node
->parent
->type
!= NODE_CTF_EXPRESSION
) {
144 _BT_COMP_LOGE_LINENO(node
->lineno
,
145 "Links `.` and `->` are only allowed as children of CTF expression.");
149 * Only strings can be separated linked by . or ->.
150 * This includes "", '' and non-quoted identifiers.
152 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
153 _BT_COMP_LOGE_LINENO(node
->lineno
,
154 "Links `.` and `->` are only allowed to separate strings and identifiers.");
157 /* We don't allow link on the first node of the list */
158 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
159 &node
->parent
->u
.ctf_expression
.left
:
160 &node
->parent
->u
.ctf_expression
.right
,
163 _BT_COMP_LOGE_LINENO(node
->lineno
,
164 "Links `.` and `->` are not allowed before first node of the unary expression list.");
168 case UNARY_DOTDOTDOT
:
169 /* We only allow ... link between children of enumerator. */
170 if (node
->parent
->type
!= NODE_ENUMERATOR
) {
171 _BT_COMP_LOGE_LINENO(node
->lineno
,
172 "Link `...` is only allowed within enumerator.");
175 /* We don't allow link on the first node of the list */
176 if (_bt_list_first_entry(&node
->parent
->u
.enumerator
.values
,
179 _BT_COMP_LOGE_LINENO(node
->lineno
,
180 "Link `...` is not allowed on the first node of the unary expression list.");
185 _BT_COMP_LOGE_LINENO(node
->lineno
,
186 "Unknown expression link type: type=%d",
187 node
->u
.unary_expression
.link
);
193 _BT_COMP_LOGE_LINENO(node
->lineno
,
194 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
195 node_type(node
), node_type(node
->parent
));
196 return -EINVAL
; /* Incoherent structure */
199 _BT_COMP_LOGE_LINENO(node
->lineno
,
200 "Semantic error: node-type=%s, parent-node-type=%s",
201 node_type(node
), node_type(node
->parent
));
202 return -EPERM
; /* Structure not allowed */
206 int ctf_visitor_field_class_specifier_list(int depth
, struct ctf_node
*node
,
207 struct meta_log_config
*log_cfg
)
209 switch (node
->parent
->type
) {
210 case NODE_CTF_EXPRESSION
:
211 case NODE_TYPE_DECLARATOR
:
213 case NODE_TYPEALIAS_TARGET
:
214 case NODE_TYPEALIAS_ALIAS
:
216 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
226 case NODE_UNARY_EXPRESSION
:
228 case NODE_TYPE_SPECIFIER
:
229 case NODE_TYPE_SPECIFIER_LIST
:
231 case NODE_FLOATING_POINT
:
234 case NODE_ENUMERATOR
:
242 _BT_COMP_LOGE_LINENO(node
->lineno
,
243 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
244 node_type(node
), node_type(node
->parent
));
245 return -EINVAL
; /* Incoherent structure */
249 int ctf_visitor_field_class_specifier(int depth
, struct ctf_node
*node
,
250 struct meta_log_config
*log_cfg
)
252 switch (node
->parent
->type
) {
253 case NODE_TYPE_SPECIFIER_LIST
:
256 case NODE_CTF_EXPRESSION
:
257 case NODE_TYPE_DECLARATOR
:
259 case NODE_TYPEALIAS_TARGET
:
260 case NODE_TYPEALIAS_ALIAS
:
262 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
270 case NODE_UNARY_EXPRESSION
:
272 case NODE_TYPE_SPECIFIER
:
274 case NODE_FLOATING_POINT
:
277 case NODE_ENUMERATOR
:
285 _BT_COMP_LOGE_LINENO(node
->lineno
,
286 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
287 node_type(node
), node_type(node
->parent
));
288 return -EINVAL
; /* Incoherent structure */
292 int ctf_visitor_field_class_declarator(int depth
, struct ctf_node
*node
,
293 struct meta_log_config
*log_cfg
)
296 struct ctf_node
*iter
;
300 switch (node
->parent
->type
) {
301 case NODE_TYPE_DECLARATOR
:
303 * A nested field class declarator is not allowed to
306 if (!bt_list_empty(&node
->u
.field_class_declarator
.pointers
))
309 case NODE_TYPEALIAS_TARGET
:
311 case NODE_TYPEALIAS_ALIAS
:
313 * Only accept alias name containing:
315 * - identifier * (any number of pointers)
316 * NOT accepting alias names containing [] (would otherwise
317 * cause semantic clash for later declarations of
318 * arrays/sequences of elements, where elements could be
319 * arrays/sequences themselves (if allowed in field class alias).
320 * NOT accepting alias with identifier. The declarator should
321 * be either empty or contain pointer(s).
323 if (node
->u
.field_class_declarator
.type
== TYPEDEC_NESTED
)
325 bt_list_for_each_entry(iter
, &node
->parent
->u
.field_class_alias_name
.field_class_specifier_list
->u
.field_class_specifier_list
.head
,
327 switch (iter
->u
.field_class_specifier
.type
) {
328 case TYPESPEC_FLOATING_POINT
:
329 case TYPESPEC_INTEGER
:
330 case TYPESPEC_STRING
:
331 case TYPESPEC_STRUCT
:
332 case TYPESPEC_VARIANT
:
334 if (bt_list_empty(&node
->u
.field_class_declarator
.pointers
))
341 if (node
->u
.field_class_declarator
.type
== TYPEDEC_ID
&&
342 node
->u
.field_class_declarator
.u
.id
)
346 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
356 case NODE_CTF_EXPRESSION
:
357 case NODE_UNARY_EXPRESSION
:
359 case NODE_TYPE_SPECIFIER
:
361 case NODE_FLOATING_POINT
:
364 case NODE_ENUMERATOR
:
372 bt_list_for_each_entry(iter
, &node
->u
.field_class_declarator
.pointers
,
374 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
, log_cfg
);
379 switch (node
->u
.field_class_declarator
.type
) {
384 if (node
->u
.field_class_declarator
.u
.nested
.field_class_declarator
) {
385 ret
= _ctf_visitor_semantic_check(depth
+ 1,
386 node
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
391 if (!node
->u
.field_class_declarator
.u
.nested
.abstract_array
) {
392 bt_list_for_each_entry(iter
, &node
->u
.field_class_declarator
.u
.nested
.length
,
394 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
395 _BT_COMP_LOGE_LINENO(node
->lineno
,
396 "Expecting unary expression as length: node-type=%s",
400 ret
= _ctf_visitor_semantic_check(depth
+ 1,
406 if (node
->parent
->type
== NODE_TYPEALIAS_TARGET
) {
407 _BT_COMP_LOGE_LINENO(node
->lineno
,
408 "Abstract array declarator not permitted as target of field class alias.");
412 if (node
->u
.field_class_declarator
.bitfield_len
) {
413 ret
= _ctf_visitor_semantic_check(depth
+ 1,
414 node
->u
.field_class_declarator
.bitfield_len
,
421 case TYPEDEC_UNKNOWN
:
423 _BT_COMP_LOGE_LINENO(node
->lineno
,
424 "Unknown field class declarator: type=%d",
425 node
->u
.field_class_declarator
.type
);
432 _BT_COMP_LOGE_LINENO(node
->lineno
,
433 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
434 node_type(node
), node_type(node
->parent
));
435 return -EINVAL
; /* Incoherent structure */
438 _BT_COMP_LOGE_LINENO(node
->lineno
,
439 "Semantic error: node-type=%s, parent-node-type=%s",
440 node_type(node
), node_type(node
->parent
));
441 return -EPERM
; /* Structure not allowed */
445 int _ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
,
446 struct meta_log_config
*log_cfg
)
449 struct ctf_node
*iter
;
454 switch (node
->type
) {
456 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
, siblings
) {
457 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
462 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
463 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
468 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
469 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
474 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
475 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
483 switch (node
->parent
->type
) {
490 bt_list_for_each_entry(iter
, &node
->u
.event
.declaration_list
, siblings
) {
491 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
498 switch (node
->parent
->type
) {
505 bt_list_for_each_entry(iter
, &node
->u
.stream
.declaration_list
, siblings
) {
506 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
513 switch (node
->parent
->type
) {
520 bt_list_for_each_entry(iter
, &node
->u
.env
.declaration_list
, siblings
) {
521 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
528 switch (node
->parent
->type
) {
535 bt_list_for_each_entry(iter
, &node
->u
.trace
.declaration_list
, siblings
) {
536 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
543 switch (node
->parent
->type
) {
550 bt_list_for_each_entry(iter
, &node
->u
.clock
.declaration_list
, siblings
) {
551 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
558 switch (node
->parent
->type
) {
565 bt_list_for_each_entry(iter
, &node
->u
.callsite
.declaration_list
, siblings
) {
566 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
573 case NODE_CTF_EXPRESSION
:
574 switch (node
->parent
->type
) {
582 case NODE_FLOATING_POINT
:
587 case NODE_CTF_EXPRESSION
:
588 case NODE_UNARY_EXPRESSION
:
590 case NODE_TYPEALIAS_TARGET
:
591 case NODE_TYPEALIAS_ALIAS
:
592 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
594 case NODE_TYPE_SPECIFIER
:
595 case NODE_TYPE_SPECIFIER_LIST
:
597 case NODE_TYPE_DECLARATOR
:
598 case NODE_ENUMERATOR
:
607 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.left
, siblings
) {
608 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
613 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.right
, siblings
) {
614 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
621 case NODE_UNARY_EXPRESSION
:
622 return ctf_visitor_unary_expression(depth
, node
, log_cfg
);
625 switch (node
->parent
->type
) {
634 case NODE_CTF_EXPRESSION
:
635 case NODE_UNARY_EXPRESSION
:
637 case NODE_TYPEALIAS_TARGET
:
638 case NODE_TYPEALIAS_ALIAS
:
640 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
641 case NODE_TYPE_SPECIFIER
:
642 case NODE_TYPE_SPECIFIER_LIST
:
644 case NODE_TYPE_DECLARATOR
:
645 case NODE_FLOATING_POINT
:
648 case NODE_ENUMERATOR
:
658 ret
= _ctf_visitor_semantic_check(depth
+ 1,
659 node
->u
.field_class_def
.field_class_specifier_list
,
663 bt_list_for_each_entry(iter
, &node
->u
.field_class_def
.field_class_declarators
, siblings
) {
664 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
671 case NODE_TYPEALIAS_TARGET
:
675 switch (node
->parent
->type
) {
683 ret
= _ctf_visitor_semantic_check(depth
+ 1,
684 node
->u
.field_class_alias_target
.field_class_specifier_list
,
689 bt_list_for_each_entry(iter
, &node
->u
.field_class_alias_target
.field_class_declarators
, siblings
) {
690 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
696 if (nr_declarators
> 1) {
697 _BT_COMP_LOGE_LINENO(node
->lineno
,
698 "Too many declarators in field class alias's name (maximum is 1): count=%d",
705 case NODE_TYPEALIAS_ALIAS
:
709 switch (node
->parent
->type
) {
717 ret
= _ctf_visitor_semantic_check(depth
+ 1,
718 node
->u
.field_class_alias_name
.field_class_specifier_list
,
723 bt_list_for_each_entry(iter
, &node
->u
.field_class_alias_name
.field_class_declarators
, siblings
) {
724 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
730 if (nr_declarators
> 1) {
731 _BT_COMP_LOGE_LINENO(node
->lineno
,
732 "Too many declarators in field class alias's name (maximum is 1): count=%d",
740 switch (node
->parent
->type
) {
749 case NODE_CTF_EXPRESSION
:
750 case NODE_UNARY_EXPRESSION
:
752 case NODE_TYPEALIAS_TARGET
:
753 case NODE_TYPEALIAS_ALIAS
:
755 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
756 case NODE_TYPE_SPECIFIER
:
757 case NODE_TYPE_SPECIFIER_LIST
:
759 case NODE_TYPE_DECLARATOR
:
760 case NODE_FLOATING_POINT
:
763 case NODE_ENUMERATOR
:
772 ret
= _ctf_visitor_semantic_check(depth
+ 1,
773 node
->u
.field_class_alias
.target
, log_cfg
);
776 ret
= _ctf_visitor_semantic_check(depth
+ 1,
777 node
->u
.field_class_alias
.alias
, log_cfg
);
782 case NODE_TYPE_SPECIFIER_LIST
:
783 ret
= ctf_visitor_field_class_specifier_list(depth
, node
,
788 case NODE_TYPE_SPECIFIER
:
789 ret
= ctf_visitor_field_class_specifier(depth
, node
,
795 switch (node
->parent
->type
) {
796 case NODE_TYPE_DECLARATOR
:
802 case NODE_TYPE_DECLARATOR
:
803 ret
= ctf_visitor_field_class_declarator(depth
, node
,
809 case NODE_FLOATING_POINT
:
810 switch (node
->parent
->type
) {
811 case NODE_TYPE_SPECIFIER
:
816 case NODE_UNARY_EXPRESSION
:
819 bt_list_for_each_entry(iter
, &node
->u
.floating_point
.expressions
, siblings
) {
820 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
827 switch (node
->parent
->type
) {
828 case NODE_TYPE_SPECIFIER
:
835 bt_list_for_each_entry(iter
, &node
->u
.integer
.expressions
, siblings
) {
836 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
843 switch (node
->parent
->type
) {
844 case NODE_TYPE_SPECIFIER
:
849 case NODE_UNARY_EXPRESSION
:
853 bt_list_for_each_entry(iter
, &node
->u
.string
.expressions
, siblings
) {
854 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
860 case NODE_ENUMERATOR
:
861 switch (node
->parent
->type
) {
868 * Enumerators are only allows to contain:
869 * numeric unary expression
870 * or num. unary exp. ... num. unary exp
875 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
,
878 case 0: if (iter
->type
!= NODE_UNARY_EXPRESSION
879 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
880 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
881 || iter
->u
.unary_expression
.link
!= UNARY_LINK_UNKNOWN
) {
882 _BT_COMP_LOGE_LINENO(iter
->lineno
,
883 "First unary expression of enumerator is unexpected.");
887 case 1: if (iter
->type
!= NODE_UNARY_EXPRESSION
888 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
889 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
890 || iter
->u
.unary_expression
.link
!= UNARY_DOTDOTDOT
) {
891 _BT_COMP_LOGE_LINENO(iter
->lineno
,
892 "Second unary expression of enumerator is unexpected.");
902 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
, siblings
) {
903 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
910 switch (node
->parent
->type
) {
911 case NODE_TYPE_SPECIFIER
:
916 case NODE_UNARY_EXPRESSION
:
921 ret
= _ctf_visitor_semantic_check(depth
+ 1,
922 node
->u
._enum
.container_field_class
, log_cfg
);
926 bt_list_for_each_entry(iter
, &node
->u
._enum
.enumerator_list
, siblings
) {
927 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
934 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
935 switch (node
->parent
->type
) {
942 ret
= _ctf_visitor_semantic_check(depth
+ 1,
943 node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
947 bt_list_for_each_entry(iter
, &node
->u
.struct_or_variant_declaration
.field_class_declarators
, siblings
) {
948 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
955 switch (node
->parent
->type
) {
956 case NODE_TYPE_SPECIFIER
:
961 case NODE_UNARY_EXPRESSION
:
964 bt_list_for_each_entry(iter
, &node
->u
.variant
.declaration_list
, siblings
) {
965 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
973 switch (node
->parent
->type
) {
974 case NODE_TYPE_SPECIFIER
:
979 case NODE_UNARY_EXPRESSION
:
982 bt_list_for_each_entry(iter
, &node
->u
._struct
.declaration_list
, siblings
) {
983 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
,
992 _BT_COMP_LOGE_LINENO(node
->lineno
,
993 "Unknown node type: type=%d", node
->type
);
999 _BT_COMP_LOGE_LINENO(node
->lineno
,
1000 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
1001 node_type(node
), node_type(node
->parent
));
1002 return -EINVAL
; /* Incoherent structure */
1005 _BT_COMP_LOGE_LINENO(node
->lineno
,
1006 "Semantic error: node-type=%s, parent-node-type=%s",
1007 node_type(node
), node_type(node
->parent
));
1008 return -EPERM
; /* Structure not allowed */
1011 int ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
,
1012 struct meta_log_config
*log_cfg
)
1017 * First make sure we create the parent links for all children. Let's
1018 * take the safe route and recreate them at each validation, just in
1019 * case the structure has changed.
1021 ret
= ctf_visitor_parent_links(depth
, node
, log_cfg
);
1023 _BT_COMP_LOGE_LINENO(node
->lineno
,
1024 "Cannot create parent links in metadata's AST: "
1029 ret
= _ctf_visitor_semantic_check(depth
, node
, log_cfg
);
1031 _BT_COMP_LOGE_LINENO(node
->lineno
,
1032 "Cannot check metadata's AST semantics: "