2 * Babeltrace - Trace IR field copy
4 * Copyright (c) 2015-2019 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2018 Philippe Proulx <pproulx@efficios.com>
6 * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@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 "PLUGIN-LTTNG-UTILS-DEBUG-INFO-TRACE-IR-METADATA-FC-COPY"
30 #include <babeltrace/assert-internal.h>
31 #include <babeltrace/common-internal.h>
32 #include <babeltrace/compiler-internal.h>
33 #include <babeltrace/babeltrace.h>
35 #include "trace-ir-metadata-copy.h"
36 #include "trace-ir-metadata-field-class-copy.h"
39 * This fonction walks througth the nested structures field class to resolve a
40 * field path object. A field path is made of indexes inside possibly nested
41 * structures ultimately leading to a field class.
44 const bt_field_class
*walk_field_path(const bt_field_path
*fp
,
45 const bt_field_class
*fc
)
47 uint64_t i
, fp_index_count
;
48 const bt_field_class
*curr_fc
;
50 BT_ASSERT(bt_field_class_get_type(fc
) == BT_FIELD_CLASS_TYPE_STRUCTURE
);
51 BT_LOGD("Walking field path on field class: fp-addr=%p, fc-addr=%p",
54 fp_index_count
= bt_field_path_get_index_count(fp
);
56 for (i
= 0; i
< fp_index_count
; i
++) {
57 bt_field_class_type fc_type
= bt_field_class_get_type(curr_fc
);
58 uint64_t curr_index
= bt_field_path_get_index_by_index(fp
, i
);
61 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
63 const bt_field_class_structure_member
*member
=
64 bt_field_class_structure_borrow_member_by_index_const(
66 curr_fc
= bt_field_class_structure_member_borrow_field_class_const(
70 case BT_FIELD_CLASS_TYPE_VARIANT
:
72 const bt_field_class_variant_option
*option
=
73 bt_field_class_variant_borrow_option_by_index_const(
75 curr_fc
= bt_field_class_variant_option_borrow_field_class_const(
88 const bt_field_class
*resolve_field_path_to_field_class(const bt_field_path
*fp
,
89 struct trace_ir_metadata_maps
*md_maps
)
91 struct field_class_resolving_context
*fc_resolving_ctx
;
92 const bt_field_class
*fc
;
95 BT_LOGD("Resolving field path: fp-addr=%p", fp
);
97 fc_resolving_ctx
= md_maps
->fc_resolving_ctx
;
98 fp_scope
= bt_field_path_get_root_scope(fp
);
101 case BT_SCOPE_PACKET_CONTEXT
:
102 fc
= walk_field_path(fp
, fc_resolving_ctx
->packet_context
);
104 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
105 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_common_context
);
107 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
108 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_specific_context
);
110 case BT_SCOPE_EVENT_PAYLOAD
:
111 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_payload
);
121 void field_class_integer_set_props(const bt_field_class
*input_fc
,
122 bt_field_class
*output_fc
)
124 bt_field_class_integer_set_preferred_display_base(output_fc
,
125 bt_field_class_integer_get_preferred_display_base(input_fc
));
126 bt_field_class_integer_set_field_value_range(output_fc
,
127 bt_field_class_integer_get_field_value_range(input_fc
));
131 int field_class_unsigned_integer_copy(
132 struct trace_ir_metadata_maps
*md_maps
,
133 const bt_field_class
*in_field_class
,
134 bt_field_class
*out_field_class
)
136 BT_LOGD("Copying content of unsigned integer field class: "
137 "in-fc-addr=%p, out-fc-addr=%p",
138 in_field_class
, out_field_class
);
140 field_class_integer_set_props(in_field_class
, out_field_class
);
142 BT_LOGD("Copied content of unsigned integer field class: "
143 "in-fc-addr=%p, out-fc-addr=%p",
144 in_field_class
, out_field_class
);
149 int field_class_signed_integer_copy(
150 struct trace_ir_metadata_maps
*md_maps
,
151 const bt_field_class
*in_field_class
,
152 bt_field_class
*out_field_class
)
154 BT_LOGD("Copying content of signed integer field class: "
155 "in-fc-addr=%p, out-fc-addr=%p",
156 in_field_class
, out_field_class
);
158 field_class_integer_set_props(in_field_class
, out_field_class
);
160 BT_LOGD("Copied content of signed integer field class: "
161 "in-fc-addr=%p, out-fc-addr=%p",
162 in_field_class
, out_field_class
);
167 int field_class_unsigned_enumeration_copy(
168 struct trace_ir_metadata_maps
*md_maps
,
169 const bt_field_class
*in_field_class
,
170 bt_field_class
*out_field_class
)
172 uint64_t i
, enum_mapping_count
;
175 BT_LOGD("Copying content of unsigned enumeration field class: "
176 "in-fc-addr=%p, out-fc-addr=%p",
177 in_field_class
, out_field_class
);
179 /* Copy properties of the inner integer. */
180 field_class_integer_set_props(in_field_class
, out_field_class
);
182 /* Copy all enumeration entries. */
183 enum_mapping_count
= bt_field_class_enumeration_get_mapping_count(in_field_class
);
184 for (i
= 0; i
< enum_mapping_count
; i
++) {
186 const bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
;
187 uint64_t range_index
, range_count
;
189 /* Get the ranges and the range count. */
190 bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
191 in_field_class
, i
, &label
, &ranges
);
193 bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
196 * Iterate over all the ranges to add them to copied field
199 for (range_index
= 0; range_index
< range_count
; range_index
++) {
200 uint64_t lower
, upper
;
201 bt_field_class_status status
;
202 bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
203 ranges
, range_index
, &lower
, &upper
);
205 BT_LOGD("Copying range in enumeration field class: "
206 "label=%s, lower=%"PRId64
", upper=%"PRId64
,
207 label
, lower
, upper
);
209 /* Add the label and its range to the copy field class. */
210 status
= bt_field_class_unsigned_enumeration_map_range(
211 out_field_class
, label
, lower
, upper
);
213 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
214 BT_LOGE_STR("Failed to add range to unsigned "
216 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class
);
223 BT_LOGD("Copied content of unsigned enumeration field class: "
224 "in-fc-addr=%p, out-fc-addr=%p",
225 in_field_class
, out_field_class
);
232 int field_class_signed_enumeration_copy(
233 struct trace_ir_metadata_maps
*md_maps
,
234 const bt_field_class
*in_field_class
,
235 bt_field_class
*out_field_class
)
237 uint64_t i
, enum_mapping_count
;
240 BT_LOGD("Copying content of signed enumeration field class: "
241 "in-fc-addr=%p, out-fc-addr=%p",
242 in_field_class
, out_field_class
);
244 /* Copy properties of the inner integer. */
245 field_class_integer_set_props(in_field_class
, out_field_class
);
247 /* Copy all enumeration entries. */
249 bt_field_class_enumeration_get_mapping_count(in_field_class
);
250 for (i
= 0; i
< enum_mapping_count
; i
++) {
252 const bt_field_class_signed_enumeration_mapping_ranges
*ranges
;
253 uint64_t range_index
, range_count
;
255 /* Get the ranges and the range count. */
256 bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
257 in_field_class
, i
, &label
, &ranges
);
259 bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
262 * Iterate over all the ranges to add them to copied field
265 for (range_index
= 0; range_index
< range_count
; range_index
++) {
266 int64_t lower
, upper
;
267 bt_field_class_status status
;
268 bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
269 ranges
, range_index
, &lower
, &upper
);
271 BT_LOGD("Copying range in enumeration field class: "
272 "label=%s, lower=%ld, upper=%ld",
273 label
, lower
, upper
);
275 /* Add the label and its range to the copy field class. */
276 status
= bt_field_class_signed_enumeration_map_range(
277 out_field_class
, label
, lower
, upper
);
278 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
279 BT_LOGE_STR("Failed to add range to signed "
281 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class
);
288 BT_LOGD("Copied content of signed enumeration field class: "
289 "in-fc-addr=%p, out-fc-addr=%p",
290 in_field_class
, out_field_class
);
297 int field_class_real_copy(
298 struct trace_ir_metadata_maps
*md_maps
,
299 const bt_field_class
*in_field_class
,
300 bt_field_class
*out_field_class
)
302 BT_LOGD("Copying content of real field class: "
303 "in-fc-addr=%p, out-fc-addr=%p",
304 in_field_class
, out_field_class
);
306 bt_field_class_real_set_is_single_precision(out_field_class
,
307 bt_field_class_real_is_single_precision(in_field_class
));
309 BT_LOGD("Copied content real field class: in-fc-addr=%p, "
310 "out-fc-addr=%p", in_field_class
, out_field_class
);
316 int field_class_structure_copy(
317 struct trace_ir_metadata_maps
*md_maps
,
318 const bt_field_class
*in_field_class
,
319 bt_field_class
*out_field_class
)
321 uint64_t i
, struct_member_count
;
322 bt_field_class_status status
;
325 BT_LOGD("Copying content of structure field class: "
326 "in-fc-addr=%p, out-fc-addr=%p",
327 in_field_class
, out_field_class
);
328 /* Get the number of member in that struct. */
329 struct_member_count
=
330 bt_field_class_structure_get_member_count(in_field_class
);
332 /* Iterate over all the members of the struct. */
333 for (i
= 0; i
< struct_member_count
; i
++) {
334 const bt_field_class_structure_member
*member
;
335 const char *member_name
;
336 const bt_field_class
*member_fc
;
337 bt_field_class
*out_member_field_class
;
339 member
= bt_field_class_structure_borrow_member_by_index_const(
341 member_fc
= bt_field_class_structure_member_borrow_field_class_const(
343 member_name
= bt_field_class_structure_member_get_name(member
);
344 BT_LOGD("Copying structure field class's field: "
345 "index=%" PRId64
", "
346 "member-fc-addr=%p, field-name=\"%s\"",
347 i
, member_fc
, member_name
);
349 out_member_field_class
= create_field_class_copy(md_maps
,
351 if (!out_member_field_class
) {
352 BT_LOGE("Cannot copy structure field class's field: "
353 "index=%" PRId64
", "
354 "field-fc-addr=%p, field-name=\"%s\"",
355 i
, member_fc
, member_name
);
359 ret
= copy_field_class_content(md_maps
, member_fc
,
360 out_member_field_class
);
365 status
= bt_field_class_structure_append_member(out_field_class
,
366 member_name
, out_member_field_class
);
367 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
368 BT_LOGE("Cannot append structure field class's field: "
369 "index=%" PRId64
", "
370 "field-fc-addr=%p, field-name=\"%s\"",
371 i
, member_fc
, member_name
);
372 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_member_field_class
);
378 BT_LOGD("Copied structure field class: original-fc-addr=%p, copy-fc-addr=%p",
379 in_field_class
, out_field_class
);
386 int field_class_variant_copy(
387 struct trace_ir_metadata_maps
*md_maps
,
388 const bt_field_class
*in_field_class
,
389 bt_field_class
*out_field_class
)
391 bt_field_class
*out_tag_field_class
;
392 uint64_t i
, variant_option_count
;
393 const bt_field_path
*tag_fp
;
394 const bt_field_class
*tag_fc
;
397 BT_LOGD("Copying content of variant field class: "
398 "in-fc-addr=%p, out-fc-addr=%p",
399 in_field_class
, out_field_class
);
401 tag_fp
= bt_field_class_variant_borrow_selector_field_path_const(
404 tag_fc
= resolve_field_path_to_field_class(tag_fp
,
407 out_tag_field_class
= g_hash_table_lookup(
408 md_maps
->field_class_map
, tag_fc
);
409 if (!out_tag_field_class
) {
410 BT_LOGE_STR("Cannot find the tag field class.");
414 bt_field_class_variant_set_selector_field_class(out_field_class
,
415 out_tag_field_class
);
418 variant_option_count
=
419 bt_field_class_variant_get_option_count(in_field_class
);
420 for (i
= 0; i
< variant_option_count
; i
++) {
421 const bt_field_class
*option_fc
;
422 const char *option_name
;
423 bt_field_class
*out_option_field_class
;
424 bt_field_class_status status
;
425 const bt_field_class_variant_option
*option
;
427 option
= bt_field_class_variant_borrow_option_by_index_const(
429 option_fc
= bt_field_class_variant_option_borrow_field_class_const(
431 option_name
= bt_field_class_variant_option_get_name(option
);
432 out_option_field_class
= create_field_class_copy_internal(
434 if (!out_option_field_class
) {
435 BT_LOGE_STR("Cannot copy field class.");
439 ret
= copy_field_class_content_internal(md_maps
, option_fc
,
440 out_option_field_class
);
442 BT_LOGE_STR("Error copying content of option variant "
447 status
= bt_field_class_variant_append_option(
448 out_field_class
, option_name
,
449 out_option_field_class
);
450 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
451 BT_LOGE_STR("Cannot append option to variant field class'");
452 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_tag_field_class
);
458 BT_LOGD("Copied content of variant field class: in-fc-addr=%p, "
459 "out-fc-addr=%p", in_field_class
, out_field_class
);
466 int field_class_static_array_copy(
467 struct trace_ir_metadata_maps
*md_maps
,
468 const bt_field_class
*in_field_class
,
469 bt_field_class
*out_field_class
)
471 BT_LOGD("Copying content of static array field class: in-fc-addr=%p, "
472 "out-fc-addr=%p", in_field_class
, out_field_class
);
474 * There is no content to copy. Keep this function call anyway for
477 BT_LOGD("Copied content of static array field class: in-fc-addr=%p, "
478 "out-fc-addr=%p", in_field_class
, out_field_class
);
484 int field_class_dynamic_array_copy(
485 struct trace_ir_metadata_maps
*md_maps
,
486 const bt_field_class
*in_field_class
,
487 bt_field_class
*out_field_class
)
489 const bt_field_class
*len_fc
;
490 const bt_field_path
*len_fp
;
491 bt_field_class_status status
;
492 bt_field_class
*out_len_field_class
;
495 BT_LOGD("Copying content of dynamic array field class: "
496 "in-fc-addr=%p, out-fc-addr=%p",
497 in_field_class
, out_field_class
);
499 len_fp
= bt_field_class_dynamic_array_borrow_length_field_path_const(
503 BT_LOGD("Copying dynamic array length field class using "
504 "field path: in-len-fp=%p", len_fp
);
505 len_fc
= resolve_field_path_to_field_class(
507 out_len_field_class
= g_hash_table_lookup(
508 md_maps
->field_class_map
, len_fc
);
509 if (!out_len_field_class
) {
510 BT_LOGE_STR("Cannot find the output matching length"
516 status
= bt_field_class_dynamic_array_set_length_field_class(
517 out_field_class
, out_len_field_class
);
518 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
519 BT_LOGE_STR("Cannot set dynamic array field class' "
520 "length field class.");
521 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_len_field_class
);
527 BT_LOGD("Copied dynamic array field class: in-fc-addr=%p, "
528 "out-fc-addr=%p", in_field_class
, out_field_class
);
535 int field_class_string_copy(struct trace_ir_metadata_maps
*md_maps
,
536 const bt_field_class
*in_field_class
,
537 bt_field_class
*out_field_class
)
539 BT_LOGD("Copying content of string field class: in-fc-addr=%p, "
540 "out-fc-addr=%p", in_field_class
, out_field_class
);
542 * There is no content to copy. Keep this function call anyway for
545 BT_LOGD("Copied content of string field class: in-fc-addr=%p, "
546 "out-fc-addr=%p", in_field_class
, out_field_class
);
552 bt_field_class
*copy_field_class_array_element(struct trace_ir_metadata_maps
*md_maps
,
553 const bt_field_class
*in_elem_fc
)
556 bt_field_class
*out_elem_fc
=
557 create_field_class_copy_internal(md_maps
, in_elem_fc
);
559 BT_LOGE("Error creating output elem field class "
560 "from input elem field class for static array: "
561 "in-fc-addr=%p", in_elem_fc
);
565 ret
= copy_field_class_content_internal(md_maps
, in_elem_fc
, out_elem_fc
);
567 BT_LOGE("Error creating output elem field class "
568 "from input elem field class for static array: "
569 "in-fc-addr=%p", in_elem_fc
);
570 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_elem_fc
);
579 bt_field_class
*create_field_class_copy_internal(struct trace_ir_metadata_maps
*md_maps
,
580 const bt_field_class
*in_field_class
)
582 bt_field_class
*out_field_class
= NULL
;
584 BT_LOGD("Creating bare field class based on field class: in-fc-addr=%p",
587 switch(bt_field_class_get_type(in_field_class
)) {
588 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
589 out_field_class
= bt_field_class_unsigned_integer_create(
590 md_maps
->output_trace_class
);
592 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
593 out_field_class
= bt_field_class_signed_integer_create(
594 md_maps
->output_trace_class
);
596 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
597 out_field_class
= bt_field_class_unsigned_enumeration_create(
598 md_maps
->output_trace_class
);
600 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
601 out_field_class
= bt_field_class_signed_enumeration_create(
602 md_maps
->output_trace_class
);
604 case BT_FIELD_CLASS_TYPE_REAL
:
605 out_field_class
= bt_field_class_real_create(
606 md_maps
->output_trace_class
);
608 case BT_FIELD_CLASS_TYPE_STRING
:
609 out_field_class
= bt_field_class_string_create(
610 md_maps
->output_trace_class
);
612 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
613 out_field_class
= bt_field_class_structure_create(
614 md_maps
->output_trace_class
);
616 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
618 const bt_field_class
*in_elem_fc
=
619 bt_field_class_array_borrow_element_field_class_const(
622 bt_field_class_static_array_get_length(in_field_class
);
624 bt_field_class
*out_elem_fc
= copy_field_class_array_element(
625 md_maps
, in_elem_fc
);
627 out_field_class
= NULL
;
631 out_field_class
= bt_field_class_static_array_create(
632 md_maps
->output_trace_class
,
633 out_elem_fc
, array_len
);
636 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
638 const bt_field_class
*in_elem_fc
=
639 bt_field_class_array_borrow_element_field_class_const(
642 bt_field_class
*out_elem_fc
= copy_field_class_array_element(
643 md_maps
, in_elem_fc
);
645 out_field_class
= NULL
;
649 out_field_class
= bt_field_class_dynamic_array_create(
650 md_maps
->output_trace_class
,
654 case BT_FIELD_CLASS_TYPE_VARIANT
:
655 out_field_class
= bt_field_class_variant_create(
656 md_maps
->output_trace_class
);
663 * Add mapping from in_field_class to out_field_class. This simplifies
664 * the resolution of field paths in variant and dynamic array field
667 g_hash_table_insert(md_maps
->field_class_map
,
668 (gpointer
) in_field_class
, out_field_class
);
672 BT_LOGD("Created bare field class based on field class: in-fc-addr=%p, "
673 "out-fc-addr=%p", in_field_class
, out_field_class
);
675 BT_LOGE("Error creating output field class from input field "
676 "class: in-fc-addr=%p", in_field_class
);
679 return out_field_class
;
683 int copy_field_class_content_internal(
684 struct trace_ir_metadata_maps
*md_maps
,
685 const bt_field_class
*in_field_class
,
686 bt_field_class
*out_field_class
)
689 switch(bt_field_class_get_type(in_field_class
)) {
690 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
691 ret
= field_class_unsigned_integer_copy(md_maps
,
692 in_field_class
, out_field_class
);
694 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
695 ret
= field_class_signed_integer_copy(md_maps
,
696 in_field_class
, out_field_class
);
698 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
699 ret
= field_class_unsigned_enumeration_copy(md_maps
,
700 in_field_class
, out_field_class
);
702 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
703 ret
= field_class_signed_enumeration_copy(md_maps
,
704 in_field_class
, out_field_class
);
706 case BT_FIELD_CLASS_TYPE_REAL
:
707 ret
= field_class_real_copy(md_maps
,
708 in_field_class
, out_field_class
);
710 case BT_FIELD_CLASS_TYPE_STRING
:
711 ret
= field_class_string_copy(md_maps
,
712 in_field_class
, out_field_class
);
714 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
715 ret
= field_class_structure_copy(md_maps
,
716 in_field_class
, out_field_class
);
718 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
719 ret
= field_class_static_array_copy(md_maps
,
720 in_field_class
, out_field_class
);
722 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
723 ret
= field_class_dynamic_array_copy(md_maps
,
724 in_field_class
, out_field_class
);
726 case BT_FIELD_CLASS_TYPE_VARIANT
:
727 ret
= field_class_variant_copy(md_maps
,
728 in_field_class
, out_field_class
);