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
++) {
58 bt_field_class_type fc_type
= bt_field_class_get_type(curr_fc
);
59 uint64_t curr_index
= bt_field_path_get_index_by_index(fp
, i
);
62 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
63 bt_field_class_structure_borrow_member_by_index_const(
64 curr_fc
, curr_index
, &fc_name
, &curr_fc
);
66 case BT_FIELD_CLASS_TYPE_VARIANT
:
67 bt_field_class_variant_borrow_option_by_index_const(
68 curr_fc
, curr_index
, &fc_name
, &curr_fc
);
79 const bt_field_class
*resolve_field_path_to_field_class(const bt_field_path
*fp
,
80 struct trace_ir_metadata_maps
*md_maps
)
82 struct field_class_resolving_context
*fc_resolving_ctx
;
83 const bt_field_class
*fc
;
86 BT_LOGD("Resolving field path: fp-addr=%p", fp
);
88 fc_resolving_ctx
= md_maps
->fc_resolving_ctx
;
89 fp_scope
= bt_field_path_get_root_scope(fp
);
92 case BT_SCOPE_PACKET_CONTEXT
:
93 fc
= walk_field_path(fp
, fc_resolving_ctx
->packet_context
);
95 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
96 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_common_context
);
98 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
99 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_specific_context
);
101 case BT_SCOPE_EVENT_PAYLOAD
:
102 fc
= walk_field_path(fp
, fc_resolving_ctx
->event_payload
);
112 void field_class_integer_set_props(const bt_field_class
*input_fc
,
113 bt_field_class
*output_fc
)
115 bt_field_class_integer_set_preferred_display_base(output_fc
,
116 bt_field_class_integer_get_preferred_display_base(input_fc
));
117 bt_field_class_integer_set_field_value_range(output_fc
,
118 bt_field_class_integer_get_field_value_range(input_fc
));
122 int field_class_unsigned_integer_copy(
123 struct trace_ir_metadata_maps
*md_maps
,
124 const bt_field_class
*in_field_class
,
125 bt_field_class
*out_field_class
)
127 BT_LOGD("Copying content of unsigned integer field class: "
128 "in-fc-addr=%p, out-fc-addr=%p",
129 in_field_class
, out_field_class
);
131 field_class_integer_set_props(in_field_class
, out_field_class
);
133 BT_LOGD("Copied content of unsigned integer field class: "
134 "in-fc-addr=%p, out-fc-addr=%p",
135 in_field_class
, out_field_class
);
140 int field_class_signed_integer_copy(
141 struct trace_ir_metadata_maps
*md_maps
,
142 const bt_field_class
*in_field_class
,
143 bt_field_class
*out_field_class
)
145 BT_LOGD("Copying content of signed integer field class: "
146 "in-fc-addr=%p, out-fc-addr=%p",
147 in_field_class
, out_field_class
);
149 field_class_integer_set_props(in_field_class
, out_field_class
);
151 BT_LOGD("Copied content of signed integer field class: "
152 "in-fc-addr=%p, out-fc-addr=%p",
153 in_field_class
, out_field_class
);
158 int field_class_unsigned_enumeration_copy(
159 struct trace_ir_metadata_maps
*md_maps
,
160 const bt_field_class
*in_field_class
,
161 bt_field_class
*out_field_class
)
163 uint64_t i
, enum_mapping_count
;
166 BT_LOGD("Copying content of unsigned enumeration field class: "
167 "in-fc-addr=%p, out-fc-addr=%p",
168 in_field_class
, out_field_class
);
170 /* Copy properties of the inner integer. */
171 field_class_integer_set_props(in_field_class
, out_field_class
);
173 /* Copy all enumeration entries. */
174 enum_mapping_count
= bt_field_class_enumeration_get_mapping_count(in_field_class
);
175 for (i
= 0; i
< enum_mapping_count
; i
++) {
177 const bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
;
178 uint64_t range_index
, range_count
;
180 /* Get the ranges and the range count. */
181 bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
182 in_field_class
, i
, &label
, &ranges
);
184 bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
187 * Iterate over all the ranges to add them to copied field
190 for (range_index
= 0; range_index
< range_count
; range_index
++) {
191 uint64_t lower
, upper
;
192 bt_field_class_status status
;
193 bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
194 ranges
, range_index
, &lower
, &upper
);
196 BT_LOGD("Copying range in enumeration field class: "
197 "label=%s, lower=%"PRId64
", upper=%"PRId64
,
198 label
, lower
, upper
);
200 /* Add the label and its range to the copy field class. */
201 status
= bt_field_class_unsigned_enumeration_map_range(
202 out_field_class
, label
, lower
, upper
);
204 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
205 BT_LOGE_STR("Failed to add range to unsigned "
207 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class
);
214 BT_LOGD("Copied content of unsigned enumeration field class: "
215 "in-fc-addr=%p, out-fc-addr=%p",
216 in_field_class
, out_field_class
);
223 int field_class_signed_enumeration_copy(
224 struct trace_ir_metadata_maps
*md_maps
,
225 const bt_field_class
*in_field_class
,
226 bt_field_class
*out_field_class
)
228 uint64_t i
, enum_mapping_count
;
231 BT_LOGD("Copying content of signed enumeration field class: "
232 "in-fc-addr=%p, out-fc-addr=%p",
233 in_field_class
, out_field_class
);
235 /* Copy properties of the inner integer. */
236 field_class_integer_set_props(in_field_class
, out_field_class
);
238 /* Copy all enumeration entries. */
240 bt_field_class_enumeration_get_mapping_count(in_field_class
);
241 for (i
= 0; i
< enum_mapping_count
; i
++) {
243 const bt_field_class_signed_enumeration_mapping_ranges
*ranges
;
244 uint64_t range_index
, range_count
;
246 /* Get the ranges and the range count. */
247 bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
248 in_field_class
, i
, &label
, &ranges
);
250 bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
253 * Iterate over all the ranges to add them to copied field
256 for (range_index
= 0; range_index
< range_count
; range_index
++) {
257 int64_t lower
, upper
;
258 bt_field_class_status status
;
259 bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
260 ranges
, range_index
, &lower
, &upper
);
262 BT_LOGD("Copying range in enumeration field class: "
263 "label=%s, lower=%ld, upper=%ld",
264 label
, lower
, upper
);
266 /* Add the label and its range to the copy field class. */
267 status
= bt_field_class_signed_enumeration_map_range(
268 out_field_class
, label
, lower
, upper
);
269 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
270 BT_LOGE_STR("Failed to add range to signed "
272 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_field_class
);
279 BT_LOGD("Copied content of signed enumeration field class: "
280 "in-fc-addr=%p, out-fc-addr=%p",
281 in_field_class
, out_field_class
);
288 int field_class_real_copy(
289 struct trace_ir_metadata_maps
*md_maps
,
290 const bt_field_class
*in_field_class
,
291 bt_field_class
*out_field_class
)
293 BT_LOGD("Copying content of real field class: "
294 "in-fc-addr=%p, out-fc-addr=%p",
295 in_field_class
, out_field_class
);
297 bt_field_class_real_set_is_single_precision(out_field_class
,
298 bt_field_class_real_is_single_precision(in_field_class
));
300 BT_LOGD("Copied content real field class: in-fc-addr=%p, "
301 "out-fc-addr=%p", in_field_class
, out_field_class
);
307 int field_class_structure_copy(
308 struct trace_ir_metadata_maps
*md_maps
,
309 const bt_field_class
*in_field_class
,
310 bt_field_class
*out_field_class
)
312 uint64_t i
, struct_member_count
;
313 bt_field_class_status status
;
316 BT_LOGD("Copying content of structure field class: "
317 "in-fc-addr=%p, out-fc-addr=%p",
318 in_field_class
, out_field_class
);
319 /* Get the number of member in that struct. */
320 struct_member_count
=
321 bt_field_class_structure_get_member_count(in_field_class
);
323 /* Iterate over all the members of the struct. */
324 for (i
= 0; i
< struct_member_count
; i
++) {
325 const char *member_name
;
326 const bt_field_class
*member_fc
;
327 bt_field_class
*out_member_field_class
;
329 bt_field_class_structure_borrow_member_by_index_const(
330 in_field_class
, i
, &member_name
, &member_fc
);
331 BT_LOGD("Copying structure field class's field: "
332 "index=%" PRId64
", "
333 "member-fc-addr=%p, field-name=\"%s\"",
334 i
, member_fc
, member_name
);
336 out_member_field_class
= create_field_class_copy(md_maps
,
338 if (!out_member_field_class
) {
339 BT_LOGE("Cannot copy structure field class's field: "
340 "index=%" PRId64
", "
341 "field-fc-addr=%p, field-name=\"%s\"",
342 i
, member_fc
, member_name
);
346 ret
= copy_field_class_content(md_maps
, member_fc
,
347 out_member_field_class
);
352 status
= bt_field_class_structure_append_member(out_field_class
,
353 member_name
, out_member_field_class
);
354 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
355 BT_LOGE("Cannot append structure field class's field: "
356 "index=%" PRId64
", "
357 "field-fc-addr=%p, field-name=\"%s\"",
358 i
, member_fc
, member_name
);
359 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_member_field_class
);
365 BT_LOGD("Copied structure field class: original-fc-addr=%p, copy-fc-addr=%p",
366 in_field_class
, out_field_class
);
373 int field_class_variant_copy(
374 struct trace_ir_metadata_maps
*md_maps
,
375 const bt_field_class
*in_field_class
,
376 bt_field_class
*out_field_class
)
378 bt_field_class
*out_tag_field_class
;
379 uint64_t i
, variant_option_count
;
380 const bt_field_path
*tag_fp
;
381 const bt_field_class
*tag_fc
;
384 BT_LOGD("Copying content of variant field class: "
385 "in-fc-addr=%p, out-fc-addr=%p",
386 in_field_class
, out_field_class
);
388 tag_fp
= bt_field_class_variant_borrow_selector_field_path_const(
391 tag_fc
= resolve_field_path_to_field_class(tag_fp
,
394 out_tag_field_class
= g_hash_table_lookup(
395 md_maps
->field_class_map
, tag_fc
);
396 if (!out_tag_field_class
) {
397 BT_LOGE_STR("Cannot find the tag field class.");
401 bt_field_class_variant_set_selector_field_class(out_field_class
,
402 out_tag_field_class
);
405 variant_option_count
=
406 bt_field_class_variant_get_option_count(in_field_class
);
407 for (i
= 0; i
< variant_option_count
; i
++) {
408 const bt_field_class
*option
;
409 const char *option_name
;
410 bt_field_class
*out_option_field_class
;
411 bt_field_class_status status
;
413 bt_field_class_variant_borrow_option_by_index_const(in_field_class
,
414 i
, &option_name
, &option
);
416 out_option_field_class
= create_field_class_copy_internal(
418 if (!out_option_field_class
) {
419 BT_LOGE_STR("Cannot copy field class.");
423 ret
= copy_field_class_content_internal(md_maps
, option
,
424 out_option_field_class
);
426 BT_LOGE_STR("Error copying content of option variant "
431 status
= bt_field_class_variant_append_option(
432 out_field_class
, option_name
,
433 out_option_field_class
);
434 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
435 BT_LOGE_STR("Cannot append option to variant field class'");
436 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_tag_field_class
);
442 BT_LOGD("Copied content of variant field class: in-fc-addr=%p, "
443 "out-fc-addr=%p", in_field_class
, out_field_class
);
450 int field_class_static_array_copy(
451 struct trace_ir_metadata_maps
*md_maps
,
452 const bt_field_class
*in_field_class
,
453 bt_field_class
*out_field_class
)
455 BT_LOGD("Copying content of static array field class: in-fc-addr=%p, "
456 "out-fc-addr=%p", in_field_class
, out_field_class
);
458 * There is no content to copy. Keep this function call anyway for
461 BT_LOGD("Copied content of static array field class: in-fc-addr=%p, "
462 "out-fc-addr=%p", in_field_class
, out_field_class
);
468 int field_class_dynamic_array_copy(
469 struct trace_ir_metadata_maps
*md_maps
,
470 const bt_field_class
*in_field_class
,
471 bt_field_class
*out_field_class
)
473 const bt_field_class
*element_fc
, *len_fc
;
474 const bt_field_path
*len_fp
;
475 bt_field_class_status status
;
476 bt_field_class
*out_len_field_class
;
479 BT_LOGD("Copying content of dynamic array field class: "
480 "in-fc-addr=%p, out-fc-addr=%p",
481 in_field_class
, out_field_class
);
483 element_fc
= bt_field_class_array_borrow_element_field_class_const(
485 len_fp
= bt_field_class_dynamic_array_borrow_length_field_path_const(
489 BT_LOGD("Copying dynamic array length field class using "
490 "field path: in-len-fp=%p", len_fp
);
491 len_fc
= resolve_field_path_to_field_class(
493 out_len_field_class
= g_hash_table_lookup(
494 md_maps
->field_class_map
, len_fc
);
495 if (!out_len_field_class
) {
496 BT_LOGE_STR("Cannot find the output matching length"
502 status
= bt_field_class_dynamic_array_set_length_field_class(
503 out_field_class
, out_len_field_class
);
504 if (status
!= BT_FIELD_CLASS_STATUS_OK
) {
505 BT_LOGE_STR("Cannot set dynamic array field class' "
506 "length field class.");
507 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_len_field_class
);
513 BT_LOGD("Copied dynamic array field class: in-fc-addr=%p, "
514 "out-fc-addr=%p", in_field_class
, out_field_class
);
521 int field_class_string_copy(struct trace_ir_metadata_maps
*md_maps
,
522 const bt_field_class
*in_field_class
,
523 bt_field_class
*out_field_class
)
525 BT_LOGD("Copying content of string field class: in-fc-addr=%p, "
526 "out-fc-addr=%p", in_field_class
, out_field_class
);
528 * There is no content to copy. Keep this function call anyway for
531 BT_LOGD("Copied content of string field class: in-fc-addr=%p, "
532 "out-fc-addr=%p", in_field_class
, out_field_class
);
538 bt_field_class
*copy_field_class_array_element(struct trace_ir_metadata_maps
*md_maps
,
539 const bt_field_class
*in_elem_fc
)
542 bt_field_class
*out_elem_fc
=
543 create_field_class_copy_internal(md_maps
, in_elem_fc
);
545 BT_LOGE("Error creating output elem field class "
546 "from input elem field class for static array: "
547 "in-fc-addr=%p", in_elem_fc
);
551 ret
= copy_field_class_content_internal(md_maps
, in_elem_fc
, out_elem_fc
);
553 BT_LOGE("Error creating output elem field class "
554 "from input elem field class for static array: "
555 "in-fc-addr=%p", in_elem_fc
);
556 BT_FIELD_CLASS_PUT_REF_AND_RESET(out_elem_fc
);
565 bt_field_class
*create_field_class_copy_internal(struct trace_ir_metadata_maps
*md_maps
,
566 const bt_field_class
*in_field_class
)
568 bt_field_class
*out_field_class
= NULL
;
570 BT_LOGD("Creating bare field class based on field class: in-fc-addr=%p",
573 switch(bt_field_class_get_type(in_field_class
)) {
574 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
575 out_field_class
= bt_field_class_unsigned_integer_create(
576 md_maps
->output_trace_class
);
578 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
579 out_field_class
= bt_field_class_signed_integer_create(
580 md_maps
->output_trace_class
);
582 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
583 out_field_class
= bt_field_class_unsigned_enumeration_create(
584 md_maps
->output_trace_class
);
586 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
587 out_field_class
= bt_field_class_signed_enumeration_create(
588 md_maps
->output_trace_class
);
590 case BT_FIELD_CLASS_TYPE_REAL
:
591 out_field_class
= bt_field_class_real_create(
592 md_maps
->output_trace_class
);
594 case BT_FIELD_CLASS_TYPE_STRING
:
595 out_field_class
= bt_field_class_string_create(
596 md_maps
->output_trace_class
);
598 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
599 out_field_class
= bt_field_class_structure_create(
600 md_maps
->output_trace_class
);
602 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
604 const bt_field_class
*in_elem_fc
=
605 bt_field_class_array_borrow_element_field_class_const(
608 bt_field_class_static_array_get_length(in_field_class
);
610 bt_field_class
*out_elem_fc
= copy_field_class_array_element(
611 md_maps
, in_elem_fc
);
613 out_field_class
= NULL
;
617 out_field_class
= bt_field_class_static_array_create(
618 md_maps
->output_trace_class
,
619 out_elem_fc
, array_len
);
622 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
624 const bt_field_class
*in_elem_fc
=
625 bt_field_class_array_borrow_element_field_class_const(
628 bt_field_class
*out_elem_fc
= copy_field_class_array_element(
629 md_maps
, in_elem_fc
);
631 out_field_class
= NULL
;
635 out_field_class
= bt_field_class_dynamic_array_create(
636 md_maps
->output_trace_class
,
640 case BT_FIELD_CLASS_TYPE_VARIANT
:
641 out_field_class
= bt_field_class_variant_create(
642 md_maps
->output_trace_class
);
649 * Add mapping from in_field_class to out_field_class. This simplifies
650 * the resolution of field paths in variant and dynamic array field
653 g_hash_table_insert(md_maps
->field_class_map
,
654 (gpointer
) in_field_class
, out_field_class
);
658 BT_LOGD("Created bare field class based on field class: in-fc-addr=%p, "
659 "out-fc-addr=%p", in_field_class
, out_field_class
);
661 BT_LOGE("Error creating output field class from input field "
662 "class: in-fc-addr=%p", in_field_class
);
665 return out_field_class
;
669 int copy_field_class_content_internal(
670 struct trace_ir_metadata_maps
*md_maps
,
671 const bt_field_class
*in_field_class
,
672 bt_field_class
*out_field_class
)
675 switch(bt_field_class_get_type(in_field_class
)) {
676 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
677 ret
= field_class_unsigned_integer_copy(md_maps
,
678 in_field_class
, out_field_class
);
680 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
681 ret
= field_class_signed_integer_copy(md_maps
,
682 in_field_class
, out_field_class
);
684 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
685 ret
= field_class_unsigned_enumeration_copy(md_maps
,
686 in_field_class
, out_field_class
);
688 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
689 ret
= field_class_signed_enumeration_copy(md_maps
,
690 in_field_class
, out_field_class
);
692 case BT_FIELD_CLASS_TYPE_REAL
:
693 ret
= field_class_real_copy(md_maps
,
694 in_field_class
, out_field_class
);
696 case BT_FIELD_CLASS_TYPE_STRING
:
697 ret
= field_class_string_copy(md_maps
,
698 in_field_class
, out_field_class
);
700 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
701 ret
= field_class_structure_copy(md_maps
,
702 in_field_class
, out_field_class
);
704 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
705 ret
= field_class_static_array_copy(md_maps
,
706 in_field_class
, out_field_class
);
708 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
709 ret
= field_class_dynamic_array_copy(md_maps
,
710 in_field_class
, out_field_class
);
712 case BT_FIELD_CLASS_TYPE_VARIANT
:
713 ret
= field_class_variant_copy(md_maps
,
714 in_field_class
, out_field_class
);