2 * Babeltrace - CTF binary type reader (BTR)
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #define BT_LOG_OUTPUT_LEVEL btr_log_level
27 #define BT_LOG_TAG "PLUGIN-CTF-BTR"
28 #include <babeltrace/logging-internal.h>
30 static int btr_log_level
= BT_LOG_NONE
;
40 #include <babeltrace/bitfield-internal.h>
41 #include <babeltrace/ctf-ir/field-types.h>
42 #include <babeltrace/ctf-ir/field-types-internal.h>
43 #include <babeltrace/ref.h>
44 #include <babeltrace/align-internal.h>
49 #define PRINT_ERR_STREAM (btr ? btr->err_stream : stderr)
50 #define PRINT_PREFIX "ctf-btr"
53 #define DIV8(_x) ((_x) >> 3)
54 #define BYTES_TO_BITS(_x) ((_x) * 8)
55 #define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
56 #define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
57 #define IN_BYTE_OFFSET(_at) ((_at) & 7)
59 /* A visit stack entry */
62 * Current type of base field, one of:
71 struct bt_ctf_field_type
*base_type
;
73 /* Length of base field (always 1 for variant types) */
76 /* Lndex of next field to read */
82 /* Entries (struct stack_entry *) (top is last element) */
89 BTR_STATE_ALIGN_BASIC
,
90 BTR_STATE_ALIGN_COMPOUND
,
91 BTR_STATE_READ_BASIC_BEGIN
,
92 BTR_STATE_READ_BASIC_CONTINUE
,
96 /* Binary type reader */
104 /* Current basic field type */
105 struct bt_ctf_field_type
*cur_basic_field_type
;
108 enum btr_state state
;
111 * Last basic field type's byte order.
113 * This is used to detect errors since two contiguous basic
114 * types for which the common boundary is not the boundary of
115 * a byte cannot have different byte orders.
117 * This is set to BT_CTF_BYTE_ORDER_UNKNOWN on reset and when
118 * the last basic field type was a string type.
120 enum bt_ctf_byte_order last_bo
;
122 /* Current byte order (copied to last_bo after a successful read) */
123 enum bt_ctf_byte_order cur_bo
;
125 /* Stitch buffer infos */
130 /* Offset, within stitch buffer, of first bit */
133 /* Length (bits) of data in stitch buffer from offset */
137 /* User buffer infos */
142 /* Offset of data from address (bits) */
145 /* Current position from offset (bits) */
148 /* Offset of offset within whole packet (bits) */
149 size_t packet_offset
;
151 /* Data size in buffer (bits) */
154 /* Buffer size (bytes) */
160 /* Callback functions */
161 struct bt_ctf_btr_cbs cbs
;
169 void __attribute__((constructor
)) logging_ctor(void)
172 bt_log_get_level_from_env("BABELTRACE_PLUGIN_CTF_BTR_LOG_LEVEL");
176 const char *btr_state_string(enum btr_state state
)
179 case BTR_STATE_NEXT_FIELD
:
180 return "BTR_STATE_NEXT_FIELD";
181 case BTR_STATE_ALIGN_BASIC
:
182 return "BTR_STATE_ALIGN_BASIC";
183 case BTR_STATE_ALIGN_COMPOUND
:
184 return "BTR_STATE_ALIGN_COMPOUND";
185 case BTR_STATE_READ_BASIC_BEGIN
:
186 return "BTR_STATE_READ_BASIC_BEGIN";
187 case BTR_STATE_READ_BASIC_CONTINUE
:
188 return "BTR_STATE_READ_BASIC_CONTINUE";
190 return "BTR_STATE_DONE";
197 void stack_entry_free_func(gpointer data
)
199 struct stack_entry
*entry
= data
;
201 BT_PUT(entry
->base_type
);
206 struct stack
*stack_new(void)
208 struct stack
*stack
= NULL
;
210 stack
= g_new0(struct stack
, 1);
212 BT_LOGE_STR("Failed to allocate one stack.");
216 stack
->entries
= g_ptr_array_new_with_free_func(stack_entry_free_func
);
217 if (!stack
->entries
) {
218 BT_LOGE_STR("Failed to allocate a GPtrArray.");
222 BT_LOGD("Created stack: addr=%p", stack
);
232 void stack_destroy(struct stack
*stack
)
238 BT_LOGD("Destroying stack: addr=%p", stack
);
239 g_ptr_array_free(stack
->entries
, TRUE
);
244 int64_t get_compound_field_type_length(struct bt_ctf_btr
*btr
,
245 struct bt_ctf_field_type
*field_type
)
249 switch (bt_ctf_field_type_get_type_id(field_type
)) {
250 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
251 length
= (int64_t) bt_ctf_field_type_structure_get_field_count(
254 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
255 /* Variant field types always "contain" a single type */
258 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
259 length
= bt_ctf_field_type_array_get_length(field_type
);
261 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
262 length
= btr
->user
.cbs
.query
.get_sequence_length(field_type
,
266 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
267 "ft-addr=%p, ft-id=%s",
269 bt_ctf_field_type_id_string(
270 bt_ctf_field_type_get_type_id(field_type
)));
271 length
= BT_CTF_BTR_STATUS_ERROR
;
278 int stack_push(struct stack
*stack
, struct bt_ctf_field_type
*base_type
,
282 struct stack_entry
*entry
;
287 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
288 "ft-addr=%p, ft-id=%s, base-length=%zu, "
289 "stack-size-before=%u, stack-size-after=%u",
290 stack
, base_type
, bt_ctf_field_type_id_string(
291 bt_ctf_field_type_get_type_id(base_type
)),
292 base_len
, stack
->entries
->len
, stack
->entries
->len
+ 1);
293 entry
= g_new0(struct stack_entry
, 1);
295 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
297 ret
= BT_CTF_BTR_STATUS_ERROR
;
301 entry
->base_type
= base_type
;
302 bt_get(entry
->base_type
);
303 entry
->base_len
= base_len
;
304 g_ptr_array_add(stack
->entries
, entry
);
311 int stack_push_with_len(struct bt_ctf_btr
*btr
,
312 struct bt_ctf_field_type
*base_type
)
315 int64_t base_len
= get_compound_field_type_length(btr
, base_type
);
318 BT_LOGW("Cannot get compound field type's field count: "
319 "btr-addr=%p, ft-addr=%p, ft-id=%s",
320 btr
, base_type
, bt_ctf_field_type_id_string(
321 bt_ctf_field_type_get_type_id(base_type
)));
322 ret
= BT_CTF_BTR_STATUS_ERROR
;
326 ret
= stack_push(btr
->stack
, base_type
, (size_t) base_len
);
333 unsigned int stack_size(struct stack
*stack
)
337 return stack
->entries
->len
;
341 void stack_pop(struct stack
*stack
)
344 assert(stack_size(stack
));
345 BT_LOGV("Popping from stack: "
346 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
347 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
348 g_ptr_array_remove_index(stack
->entries
, stack
->entries
->len
- 1);
352 bool stack_empty(struct stack
*stack
)
354 return stack_size(stack
) == 0;
358 void stack_clear(struct stack
*stack
)
362 if (!stack_empty(stack
)) {
363 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
366 assert(stack_empty(stack
));
370 struct stack_entry
*stack_top(struct stack
*stack
)
373 assert(stack_size(stack
));
375 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
379 size_t available_bits(struct bt_ctf_btr
*btr
)
381 return btr
->buf
.sz
- btr
->buf
.at
;
385 void consume_bits(struct bt_ctf_btr
*btr
, size_t incr
)
387 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
388 btr
, btr
->buf
.at
, btr
->buf
.at
+ incr
);
393 bool has_enough_bits(struct bt_ctf_btr
*btr
, size_t sz
)
395 return available_bits(btr
) >= sz
;
399 bool at_least_one_bit_left(struct bt_ctf_btr
*btr
)
401 return has_enough_bits(btr
, 1);
405 size_t packet_at(struct bt_ctf_btr
*btr
)
407 return btr
->buf
.packet_offset
+ btr
->buf
.at
;
411 size_t buf_at_from_addr(struct bt_ctf_btr
*btr
)
416 * ====== offset ===== (17)
418 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
420 * addr (0) ==== at ==== (12)
424 * =============================== (29)
426 return btr
->buf
.offset
+ btr
->buf
.at
;
430 int get_basic_field_type_size(struct bt_ctf_btr
*btr
,
431 struct bt_ctf_field_type
*field_type
)
435 switch (bt_ctf_field_type_get_type_id(field_type
)) {
436 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
437 size
= bt_ctf_field_type_integer_get_size(field_type
);
439 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
441 int exp_dig
, mant_dig
;
444 bt_ctf_field_type_floating_point_get_exponent_digits(
447 bt_ctf_field_type_floating_point_get_mantissa_digits(
449 assert(exp_dig
>= 0);
450 assert(mant_dig
>= 0);
451 size
= exp_dig
+ mant_dig
;
454 case BT_CTF_FIELD_TYPE_ID_ENUM
:
456 struct bt_ctf_field_type
*int_type
;
458 int_type
= bt_ctf_field_type_enumeration_get_container_type(
461 size
= get_basic_field_type_size(btr
, int_type
);
466 size
= BT_CTF_BTR_STATUS_ERROR
;
474 void stitch_reset(struct bt_ctf_btr
*btr
)
476 btr
->stitch
.offset
= 0;
481 size_t stitch_at_from_addr(struct bt_ctf_btr
*btr
)
483 return btr
->stitch
.offset
+ btr
->stitch
.at
;
487 void stitch_append_from_buf(struct bt_ctf_btr
*btr
, size_t sz
)
489 size_t stitch_byte_at
;
498 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr
));
499 buf_byte_at
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
500 nb_bytes
= BITS_TO_BYTES_CEIL(sz
);
501 assert(nb_bytes
> 0);
502 memcpy(&btr
->stitch
.buf
[stitch_byte_at
], &btr
->buf
.addr
[buf_byte_at
],
504 btr
->stitch
.at
+= sz
;
505 consume_bits(btr
, sz
);
509 void stitch_append_from_remaining_buf(struct bt_ctf_btr
*btr
)
511 stitch_append_from_buf(btr
, available_bits(btr
));
515 void stitch_set_from_remaining_buf(struct bt_ctf_btr
*btr
)
518 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
519 stitch_append_from_remaining_buf(btr
);
523 enum bt_ctf_btr_status
read_unsigned_bitfield(const uint8_t *buf
, size_t at
,
524 int64_t field_size
, enum bt_ctf_byte_order bo
, uint64_t *v
)
526 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
529 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
530 case BT_CTF_BYTE_ORDER_NETWORK
:
531 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
533 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
534 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
537 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
541 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64
", "
542 "bo=%s, val=%" PRIu64
, at
, field_size
,
543 bt_ctf_byte_order_string(bo
), *v
);
548 enum bt_ctf_btr_status
read_signed_bitfield(const uint8_t *buf
, size_t at
,
549 int64_t field_size
, enum bt_ctf_byte_order bo
, int64_t *v
)
551 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
554 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
555 case BT_CTF_BYTE_ORDER_NETWORK
:
556 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
558 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
559 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
562 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
566 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64
", "
567 "bo=%s, val=%" PRId64
, at
, field_size
,
568 bt_ctf_byte_order_string(bo
), *v
);
572 typedef enum bt_ctf_btr_status (* read_basic_and_call_cb_t
)(struct bt_ctf_btr
*,
573 const uint8_t *, size_t);
576 enum bt_ctf_btr_status
validate_contiguous_bo(struct bt_ctf_btr
*btr
,
577 enum bt_ctf_byte_order next_bo
)
579 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
581 /* Always valid when at a byte boundary */
582 if (packet_at(btr
) % 8 == 0) {
586 /* Always valid if last byte order is unknown */
587 if (btr
->last_bo
== BT_CTF_BYTE_ORDER_UNKNOWN
) {
591 /* Always valid if next byte order is unknown */
592 if (next_bo
== BT_CTF_BYTE_ORDER_UNKNOWN
) {
596 /* Make sure last byte order is compatible with the next byte order */
597 switch (btr
->last_bo
) {
598 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
599 case BT_CTF_BYTE_ORDER_NETWORK
:
600 if (next_bo
!= BT_CTF_BYTE_ORDER_BIG_ENDIAN
&&
601 next_bo
!= BT_CTF_BYTE_ORDER_NETWORK
) {
602 status
= BT_CTF_BTR_STATUS_ERROR
;
605 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
606 if (next_bo
!= BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
) {
607 status
= BT_CTF_BTR_STATUS_ERROR
;
611 status
= BT_CTF_BTR_STATUS_ERROR
;
616 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
617 "btr-addr=%p, last-bo=%s, next-bo=%s",
618 btr
, bt_ctf_byte_order_string(btr
->last_bo
),
619 bt_ctf_byte_order_string(next_bo
));
626 enum bt_ctf_btr_status
read_basic_float_and_call_cb(struct bt_ctf_btr
*btr
,
627 const uint8_t *buf
, size_t at
)
632 enum bt_ctf_byte_order bo
;
633 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
635 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
636 bo
= bt_ctf_field_type_get_byte_order(btr
->cur_basic_field_type
);
639 switch (field_size
) {
648 ret
= bt_ctf_field_type_floating_point_get_mantissa_digits(
649 btr
->cur_basic_field_type
);
651 ret
= bt_ctf_field_type_floating_point_get_exponent_digits(
652 btr
->cur_basic_field_type
);
654 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
655 if (status
!= BT_CTF_BTR_STATUS_OK
) {
656 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
657 "btr-addr=%p, status=%s",
658 btr
, bt_ctf_btr_status_string(status
));
662 f32
.u
= (uint32_t) v
;
663 dblval
= (double) f32
.f
;
673 ret
= bt_ctf_field_type_floating_point_get_mantissa_digits(
674 btr
->cur_basic_field_type
);
676 ret
= bt_ctf_field_type_floating_point_get_exponent_digits(
677 btr
->cur_basic_field_type
);
679 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
,
681 if (status
!= BT_CTF_BTR_STATUS_OK
) {
682 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
683 "btr-addr=%p, status=%s",
684 btr
, bt_ctf_btr_status_string(status
));
692 /* Only 32-bit and 64-bit fields are supported currently */
693 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
695 status
= BT_CTF_BTR_STATUS_ERROR
;
699 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
702 if (btr
->user
.cbs
.types
.floating_point
) {
703 BT_LOGV("Calling user function (floating point number).");
704 status
= btr
->user
.cbs
.types
.floating_point(dblval
,
705 btr
->cur_basic_field_type
, btr
->user
.data
);
706 BT_LOGV("User function returned: status=%s",
707 bt_ctf_btr_status_string(status
));
708 if (status
!= BT_CTF_BTR_STATUS_OK
) {
709 BT_LOGW("User function failed: btr-addr=%p, status=%s",
710 btr
, bt_ctf_btr_status_string(status
));
719 enum bt_ctf_btr_status
read_basic_int_and_call(struct bt_ctf_btr
*btr
,
720 const uint8_t *buf
, size_t at
,
721 struct bt_ctf_field_type
*int_type
,
722 struct bt_ctf_field_type
*orig_type
)
726 enum bt_ctf_byte_order bo
;
727 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
729 signd
= bt_ctf_field_type_integer_get_signed(int_type
);
730 field_size
= get_basic_field_type_size(btr
, int_type
);
731 if (field_size
< 1) {
732 BT_LOGW("Cannot get integer field type's size: "
733 "btr=%p, at=%zu, ft-addr=%p",
735 status
= BT_CTF_BTR_STATUS_ERROR
;
739 bo
= bt_ctf_field_type_get_byte_order(int_type
);
742 * Update current byte order now because we could be reading
743 * the integer value of an enumeration type, and thus we know
744 * here the actual supporting integer type's byte order.
751 status
= read_signed_bitfield(buf
, at
, field_size
, bo
, &v
);
752 if (status
!= BT_CTF_BTR_STATUS_OK
) {
753 BT_LOGW("Cannot read signed bit array for signed integer field: "
754 "btr-addr=%p, status=%s",
755 btr
, bt_ctf_btr_status_string(status
));
759 if (btr
->user
.cbs
.types
.signed_int
) {
760 BT_LOGV("Calling user function (signed integer).");
761 status
= btr
->user
.cbs
.types
.signed_int(v
,
762 btr
->cur_basic_field_type
, btr
->user
.data
);
763 BT_LOGV("User function returned: status=%s",
764 bt_ctf_btr_status_string(status
));
765 if (status
!= BT_CTF_BTR_STATUS_OK
) {
766 BT_LOGW("User function failed: "
767 "btr-addr=%p, status=%s",
768 btr
, bt_ctf_btr_status_string(status
));
774 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
775 if (status
!= BT_CTF_BTR_STATUS_OK
) {
776 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
777 "btr-addr=%p, status=%s",
778 btr
, bt_ctf_btr_status_string(status
));
782 if (btr
->user
.cbs
.types
.unsigned_int
) {
783 BT_LOGV("Calling user function (unsigned integer).");
784 status
= btr
->user
.cbs
.types
.unsigned_int(v
,
785 btr
->cur_basic_field_type
, btr
->user
.data
);
786 BT_LOGV("User function returned: status=%s",
787 bt_ctf_btr_status_string(status
));
788 if (status
!= BT_CTF_BTR_STATUS_OK
) {
789 BT_LOGW("User function failed: "
790 "btr-addr=%p, status=%s",
791 btr
, bt_ctf_btr_status_string(status
));
801 enum bt_ctf_btr_status
read_basic_int_and_call_cb(struct bt_ctf_btr
*btr
,
802 const uint8_t *buf
, size_t at
)
804 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
805 btr
->cur_basic_field_type
);
809 enum bt_ctf_btr_status
read_basic_enum_and_call_cb(struct bt_ctf_btr
*btr
,
810 const uint8_t *buf
, size_t at
)
812 struct bt_ctf_field_type
*int_field_type
;
813 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
815 int_field_type
= bt_ctf_field_type_enumeration_get_container_type(
816 btr
->cur_basic_field_type
);
817 assert(int_field_type
);
818 status
= read_basic_int_and_call(btr
, buf
, at
,
819 int_field_type
, btr
->cur_basic_field_type
);
820 bt_put(int_field_type
);
825 enum bt_ctf_btr_status
read_basic_type_and_call_continue(struct bt_ctf_btr
*btr
,
826 read_basic_and_call_cb_t read_basic_and_call_cb
)
831 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
833 if (!at_least_one_bit_left(btr
)) {
834 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
835 status
= BT_CTF_BTR_STATUS_EOF
;
839 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
840 if (field_size
< 1) {
841 BT_LOGW("Cannot get basic field type's size: "
842 "btr-addr=%p, ft-addr=%p",
843 btr
, btr
->cur_basic_field_type
);
844 status
= BT_CTF_BTR_STATUS_ERROR
;
848 available
= available_bits(btr
);
849 needed_bits
= field_size
- btr
->stitch
.at
;
850 BT_LOGV("Continuing basic field decoding: "
851 "btr-addr=%p, field-size=%" PRId64
", needed-size=%" PRId64
", "
852 "available-size=%zu",
853 btr
, field_size
, needed_bits
, available
);
854 if (needed_bits
<= available
) {
855 /* We have all the bits; append to stitch, then decode */
856 stitch_append_from_buf(btr
, needed_bits
);
857 status
= read_basic_and_call_cb(btr
, btr
->stitch
.buf
,
859 if (status
!= BT_CTF_BTR_STATUS_OK
) {
860 BT_LOGW("Cannot read basic field: "
861 "btr-addr=%p, ft-addr=%p, status=%s",
862 btr
, btr
->cur_basic_field_type
,
863 bt_ctf_btr_status_string(status
));
867 if (stack_empty(btr
->stack
)) {
868 /* Root is a basic type */
869 btr
->state
= BTR_STATE_DONE
;
871 /* Go to next field */
872 stack_top(btr
->stack
)->index
++;
873 btr
->state
= BTR_STATE_NEXT_FIELD
;
874 btr
->last_bo
= btr
->cur_bo
;
879 /* We are here; it means we don't have enough data to decode this */
880 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
881 stitch_append_from_remaining_buf(btr
);
882 status
= BT_CTF_BTR_STATUS_EOF
;
889 enum bt_ctf_btr_status
read_basic_type_and_call_begin(struct bt_ctf_btr
*btr
,
890 read_basic_and_call_cb_t read_basic_and_call_cb
)
894 enum bt_ctf_byte_order bo
;
895 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
897 if (!at_least_one_bit_left(btr
)) {
898 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
899 status
= BT_CTF_BTR_STATUS_EOF
;
903 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
904 if (field_size
< 1) {
905 BT_LOGW("Cannot get basic field type's size: "
906 "btr-addr=%p, ft-addr=%p",
907 btr
, btr
->cur_basic_field_type
);
908 status
= BT_CTF_BTR_STATUS_ERROR
;
912 bo
= bt_ctf_field_type_get_byte_order(btr
->cur_basic_field_type
);
913 status
= validate_contiguous_bo(btr
, bo
);
914 if (status
!= BT_CTF_BTR_STATUS_OK
) {
915 /* validate_contiguous_bo() logs errors */
919 available
= available_bits(btr
);
921 if (field_size
<= available
) {
922 /* We have all the bits; decode and set now */
923 status
= read_basic_and_call_cb(btr
, btr
->buf
.addr
,
924 buf_at_from_addr(btr
));
925 if (status
!= BT_CTF_BTR_STATUS_OK
) {
926 BT_LOGW("Cannot read basic field: "
927 "btr-addr=%p, ft-addr=%p, status=%s",
928 btr
, btr
->cur_basic_field_type
,
929 bt_ctf_btr_status_string(status
));
933 consume_bits(btr
, field_size
);
935 if (stack_empty(btr
->stack
)) {
936 /* Root is a basic type */
937 btr
->state
= BTR_STATE_DONE
;
939 /* Go to next field */
940 stack_top(btr
->stack
)->index
++;
941 btr
->state
= BTR_STATE_NEXT_FIELD
;
942 btr
->last_bo
= btr
->cur_bo
;
948 /* We are here; it means we don't have enough data to decode this */
949 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
950 stitch_set_from_remaining_buf(btr
);
951 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
952 status
= BT_CTF_BTR_STATUS_EOF
;
959 enum bt_ctf_btr_status
read_basic_int_type_and_call_begin(
960 struct bt_ctf_btr
*btr
)
962 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
966 enum bt_ctf_btr_status
read_basic_int_type_and_call_continue(
967 struct bt_ctf_btr
*btr
)
969 return read_basic_type_and_call_continue(btr
,
970 read_basic_int_and_call_cb
);
974 enum bt_ctf_btr_status
read_basic_float_type_and_call_begin(
975 struct bt_ctf_btr
*btr
)
977 return read_basic_type_and_call_begin(btr
,
978 read_basic_float_and_call_cb
);
982 enum bt_ctf_btr_status
read_basic_float_type_and_call_continue(
983 struct bt_ctf_btr
*btr
)
985 return read_basic_type_and_call_continue(btr
,
986 read_basic_float_and_call_cb
);
990 enum bt_ctf_btr_status
read_basic_enum_type_and_call_begin(
991 struct bt_ctf_btr
*btr
)
993 return read_basic_type_and_call_begin(btr
,
994 read_basic_enum_and_call_cb
);
998 enum bt_ctf_btr_status
read_basic_enum_type_and_call_continue(
999 struct bt_ctf_btr
*btr
)
1001 return read_basic_type_and_call_continue(btr
,
1002 read_basic_enum_and_call_cb
);
1006 enum bt_ctf_btr_status
read_basic_string_type_and_call(
1007 struct bt_ctf_btr
*btr
, bool begin
)
1009 size_t buf_at_bytes
;
1010 const uint8_t *result
;
1011 size_t available_bytes
;
1012 const uint8_t *first_chr
;
1013 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1015 if (!at_least_one_bit_left(btr
)) {
1016 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
1017 status
= BT_CTF_BTR_STATUS_EOF
;
1021 assert(buf_at_from_addr(btr
) % 8 == 0);
1022 available_bytes
= BITS_TO_BYTES_FLOOR(available_bits(btr
));
1023 buf_at_bytes
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
1024 first_chr
= &btr
->buf
.addr
[buf_at_bytes
];
1025 result
= memchr(first_chr
, '\0', available_bytes
);
1027 if (begin
&& btr
->user
.cbs
.types
.string_begin
) {
1028 BT_LOGV("Calling user function (string, beginning).");
1029 status
= btr
->user
.cbs
.types
.string_begin(
1030 btr
->cur_basic_field_type
, btr
->user
.data
);
1031 BT_LOGV("User function returned: status=%s",
1032 bt_ctf_btr_status_string(status
));
1033 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1034 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1035 btr
, bt_ctf_btr_status_string(status
));
1041 /* No null character yet */
1042 if (btr
->user
.cbs
.types
.string
) {
1043 BT_LOGV("Calling user function (substring).");
1044 status
= btr
->user
.cbs
.types
.string(
1045 (const char *) first_chr
,
1046 available_bytes
, btr
->cur_basic_field_type
,
1048 BT_LOGV("User function returned: status=%s",
1049 bt_ctf_btr_status_string(status
));
1050 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1051 BT_LOGW("User function failed: "
1052 "btr-addr=%p, status=%s",
1053 btr
, bt_ctf_btr_status_string(status
));
1058 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1059 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1060 status
= BT_CTF_BTR_STATUS_EOF
;
1062 /* Found the null character */
1063 size_t result_len
= (size_t) (result
- first_chr
);
1065 if (btr
->user
.cbs
.types
.string
&& result_len
) {
1066 BT_LOGV("Calling user function (substring).");
1067 status
= btr
->user
.cbs
.types
.string(
1068 (const char *) first_chr
,
1069 result_len
, btr
->cur_basic_field_type
,
1071 BT_LOGV("User function returned: status=%s",
1072 bt_ctf_btr_status_string(status
));
1073 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1074 BT_LOGW("User function failed: "
1075 "btr-addr=%p, status=%s",
1076 btr
, bt_ctf_btr_status_string(status
));
1081 if (btr
->user
.cbs
.types
.string_end
) {
1082 BT_LOGV("Calling user function (string, end).");
1083 status
= btr
->user
.cbs
.types
.string_end(
1084 btr
->cur_basic_field_type
, btr
->user
.data
);
1085 BT_LOGV("User function returned: status=%s",
1086 bt_ctf_btr_status_string(status
));
1087 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1088 BT_LOGW("User function failed: "
1089 "btr-addr=%p, status=%s",
1090 btr
, bt_ctf_btr_status_string(status
));
1095 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1097 if (stack_empty(btr
->stack
)) {
1098 /* Root is a basic type */
1099 btr
->state
= BTR_STATE_DONE
;
1101 /* Go to next field */
1102 stack_top(btr
->stack
)->index
++;
1103 btr
->state
= BTR_STATE_NEXT_FIELD
;
1104 btr
->last_bo
= btr
->cur_bo
;
1113 enum bt_ctf_btr_status
read_basic_begin_state(struct bt_ctf_btr
*btr
)
1115 enum bt_ctf_btr_status status
;
1117 assert(btr
->cur_basic_field_type
);
1119 switch (bt_ctf_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1120 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1121 status
= read_basic_int_type_and_call_begin(btr
);
1123 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
1124 status
= read_basic_float_type_and_call_begin(btr
);
1126 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1127 status
= read_basic_enum_type_and_call_begin(btr
);
1129 case BT_CTF_FIELD_TYPE_ID_STRING
:
1130 status
= read_basic_string_type_and_call(btr
, true);
1133 BT_LOGF("Unknown basic field type ID: "
1134 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1135 btr
, btr
->cur_basic_field_type
,
1136 bt_ctf_field_type_id_string(
1137 bt_ctf_field_type_get_type_id(
1138 btr
->cur_basic_field_type
)));
1146 enum bt_ctf_btr_status
read_basic_continue_state(struct bt_ctf_btr
*btr
)
1148 enum bt_ctf_btr_status status
;
1150 assert(btr
->cur_basic_field_type
);
1152 switch (bt_ctf_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1153 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1154 status
= read_basic_int_type_and_call_continue(btr
);
1156 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
1157 status
= read_basic_float_type_and_call_continue(btr
);
1159 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1160 status
= read_basic_enum_type_and_call_continue(btr
);
1162 case BT_CTF_FIELD_TYPE_ID_STRING
:
1163 status
= read_basic_string_type_and_call(btr
, false);
1166 BT_LOGF("Unknown basic field type ID: "
1167 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1168 btr
, btr
->cur_basic_field_type
,
1169 bt_ctf_field_type_id_string(
1170 bt_ctf_field_type_get_type_id(
1171 btr
->cur_basic_field_type
)));
1179 size_t bits_to_skip_to_align_to(struct bt_ctf_btr
*btr
, size_t align
)
1181 size_t aligned_packet_at
;
1183 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1184 return aligned_packet_at
- packet_at(btr
);
1188 enum bt_ctf_btr_status
align_type_state(struct bt_ctf_btr
*btr
,
1189 struct bt_ctf_field_type
*field_type
, enum btr_state next_state
)
1191 int field_alignment
;
1193 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1195 /* Get field's alignment */
1196 field_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1197 if (field_alignment
< 0) {
1198 BT_LOGW("Cannot get field type's alignment: "
1199 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1201 bt_ctf_field_type_id_string(
1202 bt_ctf_field_type_get_type_id(field_type
)));
1203 status
= BT_CTF_BTR_STATUS_ERROR
;
1208 * 0 means "undefined" for variants; what we really want is 1
1211 if (field_alignment
== 0) {
1212 field_alignment
= 1;
1215 /* Compute how many bits we need to skip */
1216 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1218 /* Nothing to skip? aligned */
1219 if (skip_bits
== 0) {
1220 btr
->state
= next_state
;
1224 /* Make sure there's at least one bit left */
1225 if (!at_least_one_bit_left(btr
)) {
1226 status
= BT_CTF_BTR_STATUS_EOF
;
1230 /* Consume as many bits as possible in what's left */
1231 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
1233 /* Are we done now? */
1234 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1235 if (skip_bits
== 0) {
1236 /* Yes: go to next state */
1237 btr
->state
= next_state
;
1240 /* No: need more data */
1241 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1242 status
= BT_CTF_BTR_STATUS_EOF
;
1250 bool is_compound_type(struct bt_ctf_field_type
*field_type
)
1252 enum bt_ctf_field_type_id id
= bt_ctf_field_type_get_type_id(field_type
);
1254 return id
== BT_CTF_FIELD_TYPE_ID_STRUCT
|| id
== BT_CTF_FIELD_TYPE_ID_ARRAY
||
1255 id
== BT_CTF_FIELD_TYPE_ID_SEQUENCE
|| id
== BT_CTF_FIELD_TYPE_ID_VARIANT
;
1259 enum bt_ctf_btr_status
next_field_state(struct bt_ctf_btr
*btr
)
1262 struct stack_entry
*top
;
1263 struct bt_ctf_field_type
*next_field_type
= NULL
;
1264 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1266 if (stack_empty(btr
->stack
)) {
1270 top
= stack_top(btr
->stack
);
1272 /* Are we done with this base type? */
1273 while (top
->index
== top
->base_len
) {
1274 if (btr
->user
.cbs
.types
.compound_end
) {
1275 BT_LOGV("Calling user function (compound, end).");
1276 status
= btr
->user
.cbs
.types
.compound_end(
1277 top
->base_type
, btr
->user
.data
);
1278 BT_LOGV("User function returned: status=%s",
1279 bt_ctf_btr_status_string(status
));
1280 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1281 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1282 btr
, bt_ctf_btr_status_string(status
));
1287 stack_pop(btr
->stack
);
1289 /* Are we done with the root type? */
1290 if (stack_empty(btr
->stack
)) {
1291 btr
->state
= BTR_STATE_DONE
;
1295 top
= stack_top(btr
->stack
);
1299 /* Get next field's type */
1300 switch (bt_ctf_field_type_get_type_id(top
->base_type
)) {
1301 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
1302 ret
= bt_ctf_field_type_structure_get_field(
1303 top
->base_type
, NULL
, &next_field_type
,
1306 next_field_type
= NULL
;
1309 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
1311 bt_ctf_field_type_array_get_element_type(
1314 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
1316 bt_ctf_field_type_sequence_get_element_type(
1319 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
1320 /* Variant types are dynamic: query the user, he should know! */
1322 btr
->user
.cbs
.query
.get_variant_type(
1323 top
->base_type
, btr
->user
.data
);
1329 if (!next_field_type
) {
1330 BT_LOGW("Cannot get the field type of the next field: "
1331 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1333 btr
, top
->base_type
,
1334 bt_ctf_field_type_id_string(
1335 bt_ctf_field_type_get_type_id(top
->base_type
)),
1337 status
= BT_CTF_BTR_STATUS_ERROR
;
1341 if (is_compound_type(next_field_type
)) {
1342 if (btr
->user
.cbs
.types
.compound_begin
) {
1343 BT_LOGV("Calling user function (compound, begin).");
1344 status
= btr
->user
.cbs
.types
.compound_begin(
1345 next_field_type
, btr
->user
.data
);
1346 BT_LOGV("User function returned: status=%s",
1347 bt_ctf_btr_status_string(status
));
1348 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1349 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1350 btr
, bt_ctf_btr_status_string(status
));
1355 ret
= stack_push_with_len(btr
, next_field_type
);
1357 /* stack_push_with_len() logs errors */
1358 status
= BT_CTF_BTR_STATUS_ERROR
;
1362 /* Next state: align a compound type */
1363 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1365 /* Replace current basic field type */
1366 BT_LOGV("Replacing current basic field type: "
1367 "btr-addr=%p, cur-basic-ft-addr=%p, "
1368 "next-basic-ft-addr=%p",
1369 btr
, btr
->cur_basic_field_type
, next_field_type
);
1370 BT_MOVE(btr
->cur_basic_field_type
, next_field_type
);
1372 /* Next state: align a basic type */
1373 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1377 BT_PUT(next_field_type
);
1383 enum bt_ctf_btr_status
handle_state(struct bt_ctf_btr
*btr
)
1385 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1387 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1388 btr
, btr_state_string(btr
->state
));
1390 switch (btr
->state
) {
1391 case BTR_STATE_NEXT_FIELD
:
1392 status
= next_field_state(btr
);
1394 case BTR_STATE_ALIGN_BASIC
:
1395 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1396 BTR_STATE_READ_BASIC_BEGIN
);
1398 case BTR_STATE_ALIGN_COMPOUND
:
1399 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1400 BTR_STATE_NEXT_FIELD
);
1402 case BTR_STATE_READ_BASIC_BEGIN
:
1403 status
= read_basic_begin_state(btr
);
1405 case BTR_STATE_READ_BASIC_CONTINUE
:
1406 status
= read_basic_continue_state(btr
);
1408 case BTR_STATE_DONE
:
1412 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1413 btr
, bt_ctf_btr_status_string(status
));
1417 struct bt_ctf_btr
*bt_ctf_btr_create(struct bt_ctf_btr_cbs cbs
, void *data
,
1420 struct bt_ctf_btr
*btr
;
1422 BT_LOGD_STR("Creating binary type reader (BTR).");
1423 btr
= g_new0(struct bt_ctf_btr
, 1);
1425 BT_LOGE_STR("Failed to allocate one binary type reader.");
1429 btr
->stack
= stack_new();
1431 BT_LOGE_STR("Cannot create BTR's stack.");
1432 bt_ctf_btr_destroy(btr
);
1437 btr
->state
= BTR_STATE_NEXT_FIELD
;
1438 btr
->user
.cbs
= cbs
;
1439 btr
->user
.data
= data
;
1440 btr
->err_stream
= err_stream
;
1441 BT_LOGD("Created BTR: addr=%p", btr
);
1447 void bt_ctf_btr_destroy(struct bt_ctf_btr
*btr
)
1450 stack_destroy(btr
->stack
);
1453 BT_LOGD("Destroying BTR: addr=%p", btr
);
1454 BT_PUT(btr
->cur_basic_field_type
);
1459 void reset(struct bt_ctf_btr
*btr
)
1461 BT_LOGD("Resetting BTR: addr=%p", btr
);
1462 stack_clear(btr
->stack
);
1463 BT_PUT(btr
->cur_basic_field_type
);
1465 btr
->buf
.addr
= NULL
;
1466 btr
->last_bo
= BT_CTF_BYTE_ORDER_UNKNOWN
;
1470 void update_packet_offset(struct bt_ctf_btr
*btr
)
1472 BT_LOGV("Updating packet offset for next call: "
1473 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1474 btr
, btr
->buf
.packet_offset
,
1475 btr
->buf
.packet_offset
+ btr
->buf
.at
);
1476 btr
->buf
.packet_offset
+= btr
->buf
.at
;
1479 size_t bt_ctf_btr_start(struct bt_ctf_btr
*btr
,
1480 struct bt_ctf_field_type
*type
, const uint8_t *buf
,
1481 size_t offset
, size_t packet_offset
, size_t sz
,
1482 enum bt_ctf_btr_status
*status
)
1487 assert(BYTES_TO_BITS(sz
) > offset
);
1489 btr
->buf
.addr
= buf
;
1490 btr
->buf
.offset
= offset
;
1492 btr
->buf
.packet_offset
= packet_offset
;
1493 btr
->buf
.buf_sz
= sz
;
1494 btr
->buf
.sz
= BYTES_TO_BITS(sz
) - offset
;
1495 *status
= BT_CTF_BTR_STATUS_OK
;
1497 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1498 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1499 "packet-offset=%zu",
1500 btr
, type
, buf
, sz
, offset
, packet_offset
);
1503 if (is_compound_type(type
)) {
1504 /* Compound type: push on visit stack */
1507 if (btr
->user
.cbs
.types
.compound_begin
) {
1508 BT_LOGV("Calling user function (compound, begin).");
1509 *status
= btr
->user
.cbs
.types
.compound_begin(
1510 type
, btr
->user
.data
);
1511 BT_LOGV("User function returned: status=%s",
1512 bt_ctf_btr_status_string(*status
));
1513 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1514 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1515 btr
, bt_ctf_btr_status_string(*status
));
1520 stack_ret
= stack_push_with_len(btr
, type
);
1522 /* stack_push_with_len() logs errors */
1523 *status
= BT_CTF_BTR_STATUS_ERROR
;
1527 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1529 /* Basic type: set as current basic type */
1530 btr
->cur_basic_field_type
= type
;
1531 bt_get(btr
->cur_basic_field_type
);
1532 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1535 /* Run the machine! */
1536 BT_LOGV_STR("Running the state machine.");
1539 *status
= handle_state(btr
);
1540 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1542 } else if (btr
->state
== BTR_STATE_DONE
) {
1547 /* Update packet offset for next time */
1548 update_packet_offset(btr
);
1554 size_t bt_ctf_btr_continue(struct bt_ctf_btr
*btr
,
1555 const uint8_t *buf
, size_t sz
,
1556 enum bt_ctf_btr_status
*status
)
1561 btr
->buf
.addr
= buf
;
1562 btr
->buf
.offset
= 0;
1564 btr
->buf
.buf_sz
= sz
;
1565 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1566 *status
= BT_CTF_BTR_STATUS_OK
;
1568 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1571 /* Continue running the machine */
1572 BT_LOGV_STR("Running the state machine.");
1575 *status
= handle_state(btr
);
1576 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1578 } else if (btr
->state
== BTR_STATE_DONE
) {
1583 /* Update packet offset for next time */
1584 update_packet_offset(btr
);