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_TAG "PLUGIN-CTF-BTR"
37 #include <babeltrace/bitfield-internal.h>
38 #include <babeltrace/ctf-ir/field-types.h>
39 #include <babeltrace/ctf-ir/field-types-internal.h>
40 #include <babeltrace/ref.h>
41 #include <babeltrace/align-internal.h>
46 #define PRINT_ERR_STREAM (btr ? btr->err_stream : stderr)
47 #define PRINT_PREFIX "ctf-btr"
50 #define DIV8(_x) ((_x) >> 3)
51 #define BYTES_TO_BITS(_x) ((_x) * 8)
52 #define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
53 #define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
54 #define IN_BYTE_OFFSET(_at) ((_at) & 7)
56 /* A visit stack entry */
59 * Current type of base field, one of:
68 struct bt_ctf_field_type
*base_type
;
70 /* Length of base field (always 1 for variant types) */
73 /* Lndex of next field to read */
79 /* Entries (struct stack_entry *) (top is last element) */
86 BTR_STATE_ALIGN_BASIC
,
87 BTR_STATE_ALIGN_COMPOUND
,
88 BTR_STATE_READ_BASIC_BEGIN
,
89 BTR_STATE_READ_BASIC_CONTINUE
,
93 /* Binary type reader */
101 /* Current basic field type */
102 struct bt_ctf_field_type
*cur_basic_field_type
;
105 enum btr_state state
;
108 * Last basic field type's byte order.
110 * This is used to detect errors since two contiguous basic
111 * types for which the common boundary is not the boundary of
112 * a byte cannot have different byte orders.
114 * This is set to BT_CTF_BYTE_ORDER_UNKNOWN on reset and when
115 * the last basic field type was a string type.
117 enum bt_ctf_byte_order last_bo
;
119 /* Current byte order (copied to last_bo after a successful read) */
120 enum bt_ctf_byte_order cur_bo
;
122 /* Stitch buffer infos */
127 /* Offset, within stitch buffer, of first bit */
130 /* Length (bits) of data in stitch buffer from offset */
134 /* User buffer infos */
139 /* Offset of data from address (bits) */
142 /* Current position from offset (bits) */
145 /* Offset of offset within whole packet (bits) */
146 size_t packet_offset
;
148 /* Data size in buffer (bits) */
151 /* Buffer size (bytes) */
157 /* Callback functions */
158 struct bt_ctf_btr_cbs cbs
;
166 const char *btr_state_string(enum btr_state state
)
169 case BTR_STATE_NEXT_FIELD
:
170 return "BTR_STATE_NEXT_FIELD";
171 case BTR_STATE_ALIGN_BASIC
:
172 return "BTR_STATE_ALIGN_BASIC";
173 case BTR_STATE_ALIGN_COMPOUND
:
174 return "BTR_STATE_ALIGN_COMPOUND";
175 case BTR_STATE_READ_BASIC_BEGIN
:
176 return "BTR_STATE_READ_BASIC_BEGIN";
177 case BTR_STATE_READ_BASIC_CONTINUE
:
178 return "BTR_STATE_READ_BASIC_CONTINUE";
180 return "BTR_STATE_DONE";
187 void stack_entry_free_func(gpointer data
)
189 struct stack_entry
*entry
= data
;
191 BT_PUT(entry
->base_type
);
196 struct stack
*stack_new(void)
198 struct stack
*stack
= NULL
;
200 stack
= g_new0(struct stack
, 1);
202 BT_LOGE_STR("Failed to allocate one stack.");
206 stack
->entries
= g_ptr_array_new_with_free_func(stack_entry_free_func
);
207 if (!stack
->entries
) {
208 BT_LOGE_STR("Failed to allocate a GPtrArray.");
212 BT_LOGD("Created stack: addr=%p", stack
);
222 void stack_destroy(struct stack
*stack
)
228 BT_LOGD("Destroying stack: addr=%p", stack
);
229 g_ptr_array_free(stack
->entries
, TRUE
);
234 int64_t get_compound_field_type_length(struct bt_ctf_btr
*btr
,
235 struct bt_ctf_field_type
*field_type
)
239 switch (bt_ctf_field_type_get_type_id(field_type
)) {
240 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
241 length
= (int64_t) bt_ctf_field_type_structure_get_field_count(
244 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
245 /* Variant field types always "contain" a single type */
248 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
249 length
= bt_ctf_field_type_array_get_length(field_type
);
251 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
252 length
= btr
->user
.cbs
.query
.get_sequence_length(field_type
,
256 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
257 "ft-addr=%p, ft-id=%s",
259 bt_ctf_field_type_id_string(
260 bt_ctf_field_type_get_type_id(field_type
)));
261 length
= BT_CTF_BTR_STATUS_ERROR
;
268 int stack_push(struct stack
*stack
, struct bt_ctf_field_type
*base_type
,
272 struct stack_entry
*entry
;
277 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
278 "ft-addr=%p, ft-id=%s, base-length=%zu, "
279 "stack-size-before=%u, stack-size-after=%u",
280 stack
, base_type
, bt_ctf_field_type_id_string(
281 bt_ctf_field_type_get_type_id(base_type
)),
282 base_len
, stack
->entries
->len
, stack
->entries
->len
+ 1);
283 entry
= g_new0(struct stack_entry
, 1);
285 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
287 ret
= BT_CTF_BTR_STATUS_ERROR
;
291 entry
->base_type
= base_type
;
292 bt_get(entry
->base_type
);
293 entry
->base_len
= base_len
;
294 g_ptr_array_add(stack
->entries
, entry
);
301 int stack_push_with_len(struct bt_ctf_btr
*btr
,
302 struct bt_ctf_field_type
*base_type
)
305 int64_t base_len
= get_compound_field_type_length(btr
, base_type
);
308 BT_LOGW("Cannot get compound field type's field count: "
309 "btr-addr=%p, ft-addr=%p, ft-id=%s",
310 btr
, base_type
, bt_ctf_field_type_id_string(
311 bt_ctf_field_type_get_type_id(base_type
)));
312 ret
= BT_CTF_BTR_STATUS_ERROR
;
316 ret
= stack_push(btr
->stack
, base_type
, (size_t) base_len
);
323 unsigned int stack_size(struct stack
*stack
)
327 return stack
->entries
->len
;
331 void stack_pop(struct stack
*stack
)
334 assert(stack_size(stack
));
335 BT_LOGV("Popping from stack: "
336 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
337 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
338 g_ptr_array_remove_index(stack
->entries
, stack
->entries
->len
- 1);
342 bool stack_empty(struct stack
*stack
)
344 return stack_size(stack
) == 0;
348 void stack_clear(struct stack
*stack
)
352 if (!stack_empty(stack
)) {
353 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
356 assert(stack_empty(stack
));
360 struct stack_entry
*stack_top(struct stack
*stack
)
363 assert(stack_size(stack
));
365 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
369 size_t available_bits(struct bt_ctf_btr
*btr
)
371 return btr
->buf
.sz
- btr
->buf
.at
;
375 void consume_bits(struct bt_ctf_btr
*btr
, size_t incr
)
377 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
378 btr
, btr
->buf
.at
, btr
->buf
.at
+ incr
);
383 bool has_enough_bits(struct bt_ctf_btr
*btr
, size_t sz
)
385 return available_bits(btr
) >= sz
;
389 bool at_least_one_bit_left(struct bt_ctf_btr
*btr
)
391 return has_enough_bits(btr
, 1);
395 size_t packet_at(struct bt_ctf_btr
*btr
)
397 return btr
->buf
.packet_offset
+ btr
->buf
.at
;
401 size_t buf_at_from_addr(struct bt_ctf_btr
*btr
)
406 * ====== offset ===== (17)
408 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
410 * addr (0) ==== at ==== (12)
414 * =============================== (29)
416 return btr
->buf
.offset
+ btr
->buf
.at
;
420 int get_basic_field_type_size(struct bt_ctf_btr
*btr
,
421 struct bt_ctf_field_type
*field_type
)
425 switch (bt_ctf_field_type_get_type_id(field_type
)) {
426 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
427 size
= bt_ctf_field_type_integer_get_size(field_type
);
429 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
431 int exp_dig
, mant_dig
;
434 bt_ctf_field_type_floating_point_get_exponent_digits(
437 bt_ctf_field_type_floating_point_get_mantissa_digits(
439 assert(exp_dig
>= 0);
440 assert(mant_dig
>= 0);
441 size
= exp_dig
+ mant_dig
;
444 case BT_CTF_FIELD_TYPE_ID_ENUM
:
446 struct bt_ctf_field_type
*int_type
;
448 int_type
= bt_ctf_field_type_enumeration_get_container_type(
451 size
= get_basic_field_type_size(btr
, int_type
);
456 size
= BT_CTF_BTR_STATUS_ERROR
;
464 void stitch_reset(struct bt_ctf_btr
*btr
)
466 btr
->stitch
.offset
= 0;
471 size_t stitch_at_from_addr(struct bt_ctf_btr
*btr
)
473 return btr
->stitch
.offset
+ btr
->stitch
.at
;
477 void stitch_append_from_buf(struct bt_ctf_btr
*btr
, size_t sz
)
479 size_t stitch_byte_at
;
488 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr
));
489 buf_byte_at
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
490 nb_bytes
= BITS_TO_BYTES_CEIL(sz
);
491 assert(nb_bytes
> 0);
492 memcpy(&btr
->stitch
.buf
[stitch_byte_at
], &btr
->buf
.addr
[buf_byte_at
],
494 btr
->stitch
.at
+= sz
;
495 consume_bits(btr
, sz
);
499 void stitch_append_from_remaining_buf(struct bt_ctf_btr
*btr
)
501 stitch_append_from_buf(btr
, available_bits(btr
));
505 void stitch_set_from_remaining_buf(struct bt_ctf_btr
*btr
)
508 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
509 stitch_append_from_remaining_buf(btr
);
513 enum bt_ctf_btr_status
read_unsigned_bitfield(const uint8_t *buf
, size_t at
,
514 int64_t field_size
, enum bt_ctf_byte_order bo
, uint64_t *v
)
516 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
519 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
520 case BT_CTF_BYTE_ORDER_NETWORK
:
521 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
523 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
524 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
527 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
531 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64
", "
532 "bo=%s, val=%" PRIu64
, at
, field_size
,
533 bt_ctf_byte_order_string(bo
), *v
);
538 enum bt_ctf_btr_status
read_signed_bitfield(const uint8_t *buf
, size_t at
,
539 int64_t field_size
, enum bt_ctf_byte_order bo
, int64_t *v
)
541 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
544 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
545 case BT_CTF_BYTE_ORDER_NETWORK
:
546 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
548 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
549 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
552 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
556 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64
", "
557 "bo=%s, val=%" PRId64
, at
, field_size
,
558 bt_ctf_byte_order_string(bo
), *v
);
562 typedef enum bt_ctf_btr_status (* read_basic_and_call_cb_t
)(struct bt_ctf_btr
*,
563 const uint8_t *, size_t);
566 enum bt_ctf_btr_status
validate_contiguous_bo(struct bt_ctf_btr
*btr
,
567 enum bt_ctf_byte_order next_bo
)
569 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
571 /* Always valid when at a byte boundary */
572 if (packet_at(btr
) % 8 == 0) {
576 /* Always valid if last byte order is unknown */
577 if (btr
->last_bo
== BT_CTF_BYTE_ORDER_UNKNOWN
) {
581 /* Always valid if next byte order is unknown */
582 if (next_bo
== BT_CTF_BYTE_ORDER_UNKNOWN
) {
586 /* Make sure last byte order is compatible with the next byte order */
587 switch (btr
->last_bo
) {
588 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
589 case BT_CTF_BYTE_ORDER_NETWORK
:
590 if (next_bo
!= BT_CTF_BYTE_ORDER_BIG_ENDIAN
&&
591 next_bo
!= BT_CTF_BYTE_ORDER_NETWORK
) {
592 status
= BT_CTF_BTR_STATUS_ERROR
;
595 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
596 if (next_bo
!= BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
) {
597 status
= BT_CTF_BTR_STATUS_ERROR
;
601 status
= BT_CTF_BTR_STATUS_ERROR
;
606 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
607 "btr-addr=%p, last-bo=%s, next-bo=%s",
608 btr
, bt_ctf_byte_order_string(btr
->last_bo
),
609 bt_ctf_byte_order_string(next_bo
));
616 enum bt_ctf_btr_status
read_basic_float_and_call_cb(struct bt_ctf_btr
*btr
,
617 const uint8_t *buf
, size_t at
)
622 enum bt_ctf_byte_order bo
;
623 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
625 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
626 bo
= bt_ctf_field_type_get_byte_order(btr
->cur_basic_field_type
);
629 switch (field_size
) {
638 ret
= bt_ctf_field_type_floating_point_get_mantissa_digits(
639 btr
->cur_basic_field_type
);
641 ret
= bt_ctf_field_type_floating_point_get_exponent_digits(
642 btr
->cur_basic_field_type
);
644 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
645 if (status
!= BT_CTF_BTR_STATUS_OK
) {
646 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
647 "btr-addr=%p, status=%s",
648 btr
, bt_ctf_btr_status_string(status
));
652 f32
.u
= (uint32_t) v
;
653 dblval
= (double) f32
.f
;
663 ret
= bt_ctf_field_type_floating_point_get_mantissa_digits(
664 btr
->cur_basic_field_type
);
666 ret
= bt_ctf_field_type_floating_point_get_exponent_digits(
667 btr
->cur_basic_field_type
);
669 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
,
671 if (status
!= BT_CTF_BTR_STATUS_OK
) {
672 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
673 "btr-addr=%p, status=%s",
674 btr
, bt_ctf_btr_status_string(status
));
682 /* Only 32-bit and 64-bit fields are supported currently */
683 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
685 status
= BT_CTF_BTR_STATUS_ERROR
;
689 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
692 if (btr
->user
.cbs
.types
.floating_point
) {
693 BT_LOGV("Calling user function (floating point number).");
694 status
= btr
->user
.cbs
.types
.floating_point(dblval
,
695 btr
->cur_basic_field_type
, btr
->user
.data
);
696 BT_LOGV("User function returned: status=%s",
697 bt_ctf_btr_status_string(status
));
698 if (status
!= BT_CTF_BTR_STATUS_OK
) {
699 BT_LOGW("User function failed: btr-addr=%p, status=%s",
700 btr
, bt_ctf_btr_status_string(status
));
709 enum bt_ctf_btr_status
read_basic_int_and_call(struct bt_ctf_btr
*btr
,
710 const uint8_t *buf
, size_t at
,
711 struct bt_ctf_field_type
*int_type
,
712 struct bt_ctf_field_type
*orig_type
)
716 enum bt_ctf_byte_order bo
;
717 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
719 signd
= bt_ctf_field_type_integer_get_signed(int_type
);
720 field_size
= get_basic_field_type_size(btr
, int_type
);
721 if (field_size
< 1) {
722 BT_LOGW("Cannot get integer field type's size: "
723 "btr=%p, at=%zu, ft-addr=%p",
725 status
= BT_CTF_BTR_STATUS_ERROR
;
729 bo
= bt_ctf_field_type_get_byte_order(int_type
);
732 * Update current byte order now because we could be reading
733 * the integer value of an enumeration type, and thus we know
734 * here the actual supporting integer type's byte order.
741 status
= read_signed_bitfield(buf
, at
, field_size
, bo
, &v
);
742 if (status
!= BT_CTF_BTR_STATUS_OK
) {
743 BT_LOGW("Cannot read signed bit array for signed integer field: "
744 "btr-addr=%p, status=%s",
745 btr
, bt_ctf_btr_status_string(status
));
749 if (btr
->user
.cbs
.types
.signed_int
) {
750 BT_LOGV("Calling user function (signed integer).");
751 status
= btr
->user
.cbs
.types
.signed_int(v
,
752 btr
->cur_basic_field_type
, btr
->user
.data
);
753 BT_LOGV("User function returned: status=%s",
754 bt_ctf_btr_status_string(status
));
755 if (status
!= BT_CTF_BTR_STATUS_OK
) {
756 BT_LOGW("User function failed: "
757 "btr-addr=%p, status=%s",
758 btr
, bt_ctf_btr_status_string(status
));
764 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
765 if (status
!= BT_CTF_BTR_STATUS_OK
) {
766 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
767 "btr-addr=%p, status=%s",
768 btr
, bt_ctf_btr_status_string(status
));
772 if (btr
->user
.cbs
.types
.unsigned_int
) {
773 BT_LOGV("Calling user function (unsigned integer).");
774 status
= btr
->user
.cbs
.types
.unsigned_int(v
,
775 btr
->cur_basic_field_type
, btr
->user
.data
);
776 BT_LOGV("User function returned: status=%s",
777 bt_ctf_btr_status_string(status
));
778 if (status
!= BT_CTF_BTR_STATUS_OK
) {
779 BT_LOGW("User function failed: "
780 "btr-addr=%p, status=%s",
781 btr
, bt_ctf_btr_status_string(status
));
791 enum bt_ctf_btr_status
read_basic_int_and_call_cb(struct bt_ctf_btr
*btr
,
792 const uint8_t *buf
, size_t at
)
794 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
795 btr
->cur_basic_field_type
);
799 enum bt_ctf_btr_status
read_basic_enum_and_call_cb(struct bt_ctf_btr
*btr
,
800 const uint8_t *buf
, size_t at
)
802 struct bt_ctf_field_type
*int_field_type
;
803 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
805 int_field_type
= bt_ctf_field_type_enumeration_get_container_type(
806 btr
->cur_basic_field_type
);
807 assert(int_field_type
);
808 status
= read_basic_int_and_call(btr
, buf
, at
,
809 int_field_type
, btr
->cur_basic_field_type
);
810 bt_put(int_field_type
);
815 enum bt_ctf_btr_status
read_basic_type_and_call_continue(struct bt_ctf_btr
*btr
,
816 read_basic_and_call_cb_t read_basic_and_call_cb
)
821 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
823 if (!at_least_one_bit_left(btr
)) {
824 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
825 status
= BT_CTF_BTR_STATUS_EOF
;
829 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
830 if (field_size
< 1) {
831 BT_LOGW("Cannot get basic field type's size: "
832 "btr-addr=%p, ft-addr=%p",
833 btr
, btr
->cur_basic_field_type
);
834 status
= BT_CTF_BTR_STATUS_ERROR
;
838 available
= available_bits(btr
);
839 needed_bits
= field_size
- btr
->stitch
.at
;
840 BT_LOGV("Continuing basic field decoding: "
841 "btr-addr=%p, field-size=%" PRId64
", needed-size=%" PRId64
", "
842 "available-size=%zu",
843 btr
, field_size
, needed_bits
, available
);
844 if (needed_bits
<= available
) {
845 /* We have all the bits; append to stitch, then decode */
846 stitch_append_from_buf(btr
, needed_bits
);
847 status
= read_basic_and_call_cb(btr
, btr
->stitch
.buf
,
849 if (status
!= BT_CTF_BTR_STATUS_OK
) {
850 BT_LOGW("Cannot read basic field: "
851 "btr-addr=%p, ft-addr=%p, status=%s",
852 btr
, btr
->cur_basic_field_type
,
853 bt_ctf_btr_status_string(status
));
857 if (stack_empty(btr
->stack
)) {
858 /* Root is a basic type */
859 btr
->state
= BTR_STATE_DONE
;
861 /* Go to next field */
862 stack_top(btr
->stack
)->index
++;
863 btr
->state
= BTR_STATE_NEXT_FIELD
;
864 btr
->last_bo
= btr
->cur_bo
;
869 /* We are here; it means we don't have enough data to decode this */
870 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
871 stitch_append_from_remaining_buf(btr
);
872 status
= BT_CTF_BTR_STATUS_EOF
;
879 enum bt_ctf_btr_status
read_basic_type_and_call_begin(struct bt_ctf_btr
*btr
,
880 read_basic_and_call_cb_t read_basic_and_call_cb
)
884 enum bt_ctf_byte_order bo
;
885 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
887 if (!at_least_one_bit_left(btr
)) {
888 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
889 status
= BT_CTF_BTR_STATUS_EOF
;
893 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
894 if (field_size
< 1) {
895 BT_LOGW("Cannot get basic field type's size: "
896 "btr-addr=%p, ft-addr=%p",
897 btr
, btr
->cur_basic_field_type
);
898 status
= BT_CTF_BTR_STATUS_ERROR
;
902 bo
= bt_ctf_field_type_get_byte_order(btr
->cur_basic_field_type
);
903 status
= validate_contiguous_bo(btr
, bo
);
904 if (status
!= BT_CTF_BTR_STATUS_OK
) {
905 /* validate_contiguous_bo() logs errors */
909 available
= available_bits(btr
);
911 if (field_size
<= available
) {
912 /* We have all the bits; decode and set now */
913 status
= read_basic_and_call_cb(btr
, btr
->buf
.addr
,
914 buf_at_from_addr(btr
));
915 if (status
!= BT_CTF_BTR_STATUS_OK
) {
916 BT_LOGW("Cannot read basic field: "
917 "btr-addr=%p, ft-addr=%p, status=%s",
918 btr
, btr
->cur_basic_field_type
,
919 bt_ctf_btr_status_string(status
));
923 consume_bits(btr
, field_size
);
925 if (stack_empty(btr
->stack
)) {
926 /* Root is a basic type */
927 btr
->state
= BTR_STATE_DONE
;
929 /* Go to next field */
930 stack_top(btr
->stack
)->index
++;
931 btr
->state
= BTR_STATE_NEXT_FIELD
;
932 btr
->last_bo
= btr
->cur_bo
;
938 /* We are here; it means we don't have enough data to decode this */
939 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
940 stitch_set_from_remaining_buf(btr
);
941 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
942 status
= BT_CTF_BTR_STATUS_EOF
;
949 enum bt_ctf_btr_status
read_basic_int_type_and_call_begin(
950 struct bt_ctf_btr
*btr
)
952 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
956 enum bt_ctf_btr_status
read_basic_int_type_and_call_continue(
957 struct bt_ctf_btr
*btr
)
959 return read_basic_type_and_call_continue(btr
,
960 read_basic_int_and_call_cb
);
964 enum bt_ctf_btr_status
read_basic_float_type_and_call_begin(
965 struct bt_ctf_btr
*btr
)
967 return read_basic_type_and_call_begin(btr
,
968 read_basic_float_and_call_cb
);
972 enum bt_ctf_btr_status
read_basic_float_type_and_call_continue(
973 struct bt_ctf_btr
*btr
)
975 return read_basic_type_and_call_continue(btr
,
976 read_basic_float_and_call_cb
);
980 enum bt_ctf_btr_status
read_basic_enum_type_and_call_begin(
981 struct bt_ctf_btr
*btr
)
983 return read_basic_type_and_call_begin(btr
,
984 read_basic_enum_and_call_cb
);
988 enum bt_ctf_btr_status
read_basic_enum_type_and_call_continue(
989 struct bt_ctf_btr
*btr
)
991 return read_basic_type_and_call_continue(btr
,
992 read_basic_enum_and_call_cb
);
996 enum bt_ctf_btr_status
read_basic_string_type_and_call(
997 struct bt_ctf_btr
*btr
, bool begin
)
1000 const uint8_t *result
;
1001 size_t available_bytes
;
1002 const uint8_t *first_chr
;
1003 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1005 if (!at_least_one_bit_left(btr
)) {
1006 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
1007 status
= BT_CTF_BTR_STATUS_EOF
;
1011 assert(buf_at_from_addr(btr
) % 8 == 0);
1012 available_bytes
= BITS_TO_BYTES_FLOOR(available_bits(btr
));
1013 buf_at_bytes
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
1014 first_chr
= &btr
->buf
.addr
[buf_at_bytes
];
1015 result
= memchr(first_chr
, '\0', available_bytes
);
1017 if (begin
&& btr
->user
.cbs
.types
.string_begin
) {
1018 BT_LOGV("Calling user function (string, beginning).");
1019 status
= btr
->user
.cbs
.types
.string_begin(
1020 btr
->cur_basic_field_type
, btr
->user
.data
);
1021 BT_LOGV("User function returned: status=%s",
1022 bt_ctf_btr_status_string(status
));
1023 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1024 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1025 btr
, bt_ctf_btr_status_string(status
));
1031 /* No null character yet */
1032 if (btr
->user
.cbs
.types
.string
) {
1033 BT_LOGV("Calling user function (substring).");
1034 status
= btr
->user
.cbs
.types
.string(
1035 (const char *) first_chr
,
1036 available_bytes
, btr
->cur_basic_field_type
,
1038 BT_LOGV("User function returned: status=%s",
1039 bt_ctf_btr_status_string(status
));
1040 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1041 BT_LOGW("User function failed: "
1042 "btr-addr=%p, status=%s",
1043 btr
, bt_ctf_btr_status_string(status
));
1048 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1049 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1050 status
= BT_CTF_BTR_STATUS_EOF
;
1052 /* Found the null character */
1053 size_t result_len
= (size_t) (result
- first_chr
);
1055 if (btr
->user
.cbs
.types
.string
&& result_len
) {
1056 BT_LOGV("Calling user function (substring).");
1057 status
= btr
->user
.cbs
.types
.string(
1058 (const char *) first_chr
,
1059 result_len
, btr
->cur_basic_field_type
,
1061 BT_LOGV("User function returned: status=%s",
1062 bt_ctf_btr_status_string(status
));
1063 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1064 BT_LOGW("User function failed: "
1065 "btr-addr=%p, status=%s",
1066 btr
, bt_ctf_btr_status_string(status
));
1071 if (btr
->user
.cbs
.types
.string_end
) {
1072 BT_LOGV("Calling user function (string, end).");
1073 status
= btr
->user
.cbs
.types
.string_end(
1074 btr
->cur_basic_field_type
, btr
->user
.data
);
1075 BT_LOGV("User function returned: status=%s",
1076 bt_ctf_btr_status_string(status
));
1077 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1078 BT_LOGW("User function failed: "
1079 "btr-addr=%p, status=%s",
1080 btr
, bt_ctf_btr_status_string(status
));
1085 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1087 if (stack_empty(btr
->stack
)) {
1088 /* Root is a basic type */
1089 btr
->state
= BTR_STATE_DONE
;
1091 /* Go to next field */
1092 stack_top(btr
->stack
)->index
++;
1093 btr
->state
= BTR_STATE_NEXT_FIELD
;
1094 btr
->last_bo
= btr
->cur_bo
;
1103 enum bt_ctf_btr_status
read_basic_begin_state(struct bt_ctf_btr
*btr
)
1105 enum bt_ctf_btr_status status
;
1107 assert(btr
->cur_basic_field_type
);
1109 switch (bt_ctf_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1110 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1111 status
= read_basic_int_type_and_call_begin(btr
);
1113 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
1114 status
= read_basic_float_type_and_call_begin(btr
);
1116 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1117 status
= read_basic_enum_type_and_call_begin(btr
);
1119 case BT_CTF_FIELD_TYPE_ID_STRING
:
1120 status
= read_basic_string_type_and_call(btr
, true);
1123 BT_LOGF("Unknown basic field type ID: "
1124 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1125 btr
, btr
->cur_basic_field_type
,
1126 bt_ctf_field_type_id_string(
1127 bt_ctf_field_type_get_type_id(
1128 btr
->cur_basic_field_type
)));
1136 enum bt_ctf_btr_status
read_basic_continue_state(struct bt_ctf_btr
*btr
)
1138 enum bt_ctf_btr_status status
;
1140 assert(btr
->cur_basic_field_type
);
1142 switch (bt_ctf_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1143 case BT_CTF_FIELD_TYPE_ID_INTEGER
:
1144 status
= read_basic_int_type_and_call_continue(btr
);
1146 case BT_CTF_FIELD_TYPE_ID_FLOAT
:
1147 status
= read_basic_float_type_and_call_continue(btr
);
1149 case BT_CTF_FIELD_TYPE_ID_ENUM
:
1150 status
= read_basic_enum_type_and_call_continue(btr
);
1152 case BT_CTF_FIELD_TYPE_ID_STRING
:
1153 status
= read_basic_string_type_and_call(btr
, false);
1156 BT_LOGF("Unknown basic field type ID: "
1157 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1158 btr
, btr
->cur_basic_field_type
,
1159 bt_ctf_field_type_id_string(
1160 bt_ctf_field_type_get_type_id(
1161 btr
->cur_basic_field_type
)));
1169 size_t bits_to_skip_to_align_to(struct bt_ctf_btr
*btr
, size_t align
)
1171 size_t aligned_packet_at
;
1173 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1174 return aligned_packet_at
- packet_at(btr
);
1178 enum bt_ctf_btr_status
align_type_state(struct bt_ctf_btr
*btr
,
1179 struct bt_ctf_field_type
*field_type
, enum btr_state next_state
)
1181 int field_alignment
;
1183 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1185 /* Get field's alignment */
1186 field_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1187 if (field_alignment
< 0) {
1188 BT_LOGW("Cannot get field type's alignment: "
1189 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1191 bt_ctf_field_type_id_string(
1192 bt_ctf_field_type_get_type_id(field_type
)));
1193 status
= BT_CTF_BTR_STATUS_ERROR
;
1198 * 0 means "undefined" for variants; what we really want is 1
1201 if (field_alignment
== 0) {
1202 field_alignment
= 1;
1205 /* Compute how many bits we need to skip */
1206 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1208 /* Nothing to skip? aligned */
1209 if (skip_bits
== 0) {
1210 btr
->state
= next_state
;
1214 /* Make sure there's at least one bit left */
1215 if (!at_least_one_bit_left(btr
)) {
1216 status
= BT_CTF_BTR_STATUS_EOF
;
1220 /* Consume as many bits as possible in what's left */
1221 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
1223 /* Are we done now? */
1224 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1225 if (skip_bits
== 0) {
1226 /* Yes: go to next state */
1227 btr
->state
= next_state
;
1230 /* No: need more data */
1231 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1232 status
= BT_CTF_BTR_STATUS_EOF
;
1240 bool is_compound_type(struct bt_ctf_field_type
*field_type
)
1242 enum bt_ctf_field_type_id id
= bt_ctf_field_type_get_type_id(field_type
);
1244 return id
== BT_CTF_FIELD_TYPE_ID_STRUCT
|| id
== BT_CTF_FIELD_TYPE_ID_ARRAY
||
1245 id
== BT_CTF_FIELD_TYPE_ID_SEQUENCE
|| id
== BT_CTF_FIELD_TYPE_ID_VARIANT
;
1249 enum bt_ctf_btr_status
next_field_state(struct bt_ctf_btr
*btr
)
1252 struct stack_entry
*top
;
1253 struct bt_ctf_field_type
*next_field_type
= NULL
;
1254 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1256 if (stack_empty(btr
->stack
)) {
1260 top
= stack_top(btr
->stack
);
1262 /* Are we done with this base type? */
1263 while (top
->index
== top
->base_len
) {
1264 if (btr
->user
.cbs
.types
.compound_end
) {
1265 BT_LOGV("Calling user function (compound, end).");
1266 status
= btr
->user
.cbs
.types
.compound_end(
1267 top
->base_type
, btr
->user
.data
);
1268 BT_LOGV("User function returned: status=%s",
1269 bt_ctf_btr_status_string(status
));
1270 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1271 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1272 btr
, bt_ctf_btr_status_string(status
));
1277 stack_pop(btr
->stack
);
1279 /* Are we done with the root type? */
1280 if (stack_empty(btr
->stack
)) {
1281 btr
->state
= BTR_STATE_DONE
;
1285 top
= stack_top(btr
->stack
);
1289 /* Get next field's type */
1290 switch (bt_ctf_field_type_get_type_id(top
->base_type
)) {
1291 case BT_CTF_FIELD_TYPE_ID_STRUCT
:
1292 ret
= bt_ctf_field_type_structure_get_field(
1293 top
->base_type
, NULL
, &next_field_type
,
1296 next_field_type
= NULL
;
1299 case BT_CTF_FIELD_TYPE_ID_ARRAY
:
1301 bt_ctf_field_type_array_get_element_type(
1304 case BT_CTF_FIELD_TYPE_ID_SEQUENCE
:
1306 bt_ctf_field_type_sequence_get_element_type(
1309 case BT_CTF_FIELD_TYPE_ID_VARIANT
:
1310 /* Variant types are dynamic: query the user, he should know! */
1312 btr
->user
.cbs
.query
.get_variant_type(
1313 top
->base_type
, btr
->user
.data
);
1319 if (!next_field_type
) {
1320 BT_LOGW("Cannot get the field type of the next field: "
1321 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1323 btr
, top
->base_type
,
1324 bt_ctf_field_type_id_string(
1325 bt_ctf_field_type_get_type_id(top
->base_type
)),
1327 status
= BT_CTF_BTR_STATUS_ERROR
;
1331 if (is_compound_type(next_field_type
)) {
1332 if (btr
->user
.cbs
.types
.compound_begin
) {
1333 BT_LOGV("Calling user function (compound, begin).");
1334 status
= btr
->user
.cbs
.types
.compound_begin(
1335 next_field_type
, btr
->user
.data
);
1336 BT_LOGV("User function returned: status=%s",
1337 bt_ctf_btr_status_string(status
));
1338 if (status
!= BT_CTF_BTR_STATUS_OK
) {
1339 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1340 btr
, bt_ctf_btr_status_string(status
));
1345 ret
= stack_push_with_len(btr
, next_field_type
);
1347 /* stack_push_with_len() logs errors */
1348 status
= BT_CTF_BTR_STATUS_ERROR
;
1352 /* Next state: align a compound type */
1353 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1355 /* Replace current basic field type */
1356 BT_LOGV("Replacing current basic field type: "
1357 "btr-addr=%p, cur-basic-ft-addr=%p, "
1358 "next-basic-ft-addr=%p",
1359 btr
, btr
->cur_basic_field_type
, next_field_type
);
1360 BT_MOVE(btr
->cur_basic_field_type
, next_field_type
);
1362 /* Next state: align a basic type */
1363 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1367 BT_PUT(next_field_type
);
1373 enum bt_ctf_btr_status
handle_state(struct bt_ctf_btr
*btr
)
1375 enum bt_ctf_btr_status status
= BT_CTF_BTR_STATUS_OK
;
1377 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1378 btr
, btr_state_string(btr
->state
));
1380 switch (btr
->state
) {
1381 case BTR_STATE_NEXT_FIELD
:
1382 status
= next_field_state(btr
);
1384 case BTR_STATE_ALIGN_BASIC
:
1385 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1386 BTR_STATE_READ_BASIC_BEGIN
);
1388 case BTR_STATE_ALIGN_COMPOUND
:
1389 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1390 BTR_STATE_NEXT_FIELD
);
1392 case BTR_STATE_READ_BASIC_BEGIN
:
1393 status
= read_basic_begin_state(btr
);
1395 case BTR_STATE_READ_BASIC_CONTINUE
:
1396 status
= read_basic_continue_state(btr
);
1398 case BTR_STATE_DONE
:
1402 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1403 btr
, bt_ctf_btr_status_string(status
));
1407 struct bt_ctf_btr
*bt_ctf_btr_create(struct bt_ctf_btr_cbs cbs
, void *data
,
1410 struct bt_ctf_btr
*btr
;
1412 BT_LOGD_STR("Creating binary type reader (BTR).");
1413 btr
= g_new0(struct bt_ctf_btr
, 1);
1415 BT_LOGE_STR("Failed to allocate one binary type reader.");
1419 btr
->stack
= stack_new();
1421 BT_LOGE_STR("Cannot create BTR's stack.");
1422 bt_ctf_btr_destroy(btr
);
1427 btr
->state
= BTR_STATE_NEXT_FIELD
;
1428 btr
->user
.cbs
= cbs
;
1429 btr
->user
.data
= data
;
1430 btr
->err_stream
= err_stream
;
1431 BT_LOGD("Created BTR: addr=%p", btr
);
1437 void bt_ctf_btr_destroy(struct bt_ctf_btr
*btr
)
1440 stack_destroy(btr
->stack
);
1443 BT_LOGD("Destroying BTR: addr=%p", btr
);
1444 BT_PUT(btr
->cur_basic_field_type
);
1449 void reset(struct bt_ctf_btr
*btr
)
1451 BT_LOGD("Resetting BTR: addr=%p", btr
);
1452 stack_clear(btr
->stack
);
1453 BT_PUT(btr
->cur_basic_field_type
);
1455 btr
->buf
.addr
= NULL
;
1456 btr
->last_bo
= BT_CTF_BYTE_ORDER_UNKNOWN
;
1460 void update_packet_offset(struct bt_ctf_btr
*btr
)
1462 BT_LOGV("Updating packet offset for next call: "
1463 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1464 btr
, btr
->buf
.packet_offset
,
1465 btr
->buf
.packet_offset
+ btr
->buf
.at
);
1466 btr
->buf
.packet_offset
+= btr
->buf
.at
;
1469 size_t bt_ctf_btr_start(struct bt_ctf_btr
*btr
,
1470 struct bt_ctf_field_type
*type
, const uint8_t *buf
,
1471 size_t offset
, size_t packet_offset
, size_t sz
,
1472 enum bt_ctf_btr_status
*status
)
1477 assert(BYTES_TO_BITS(sz
) > offset
);
1479 btr
->buf
.addr
= buf
;
1480 btr
->buf
.offset
= offset
;
1482 btr
->buf
.packet_offset
= packet_offset
;
1483 btr
->buf
.buf_sz
= sz
;
1484 btr
->buf
.sz
= BYTES_TO_BITS(sz
) - offset
;
1485 *status
= BT_CTF_BTR_STATUS_OK
;
1487 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1488 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1489 "packet-offset=%zu",
1490 btr
, type
, buf
, sz
, offset
, packet_offset
);
1493 if (is_compound_type(type
)) {
1494 /* Compound type: push on visit stack */
1497 if (btr
->user
.cbs
.types
.compound_begin
) {
1498 BT_LOGV("Calling user function (compound, begin).");
1499 *status
= btr
->user
.cbs
.types
.compound_begin(
1500 type
, btr
->user
.data
);
1501 BT_LOGV("User function returned: status=%s",
1502 bt_ctf_btr_status_string(*status
));
1503 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1504 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1505 btr
, bt_ctf_btr_status_string(*status
));
1510 stack_ret
= stack_push_with_len(btr
, type
);
1512 /* stack_push_with_len() logs errors */
1513 *status
= BT_CTF_BTR_STATUS_ERROR
;
1517 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1519 /* Basic type: set as current basic type */
1520 btr
->cur_basic_field_type
= type
;
1521 bt_get(btr
->cur_basic_field_type
);
1522 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1525 /* Run the machine! */
1526 BT_LOGV_STR("Running the state machine.");
1529 *status
= handle_state(btr
);
1530 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1532 } else if (btr
->state
== BTR_STATE_DONE
) {
1537 /* Update packet offset for next time */
1538 update_packet_offset(btr
);
1544 size_t bt_ctf_btr_continue(struct bt_ctf_btr
*btr
,
1545 const uint8_t *buf
, size_t sz
,
1546 enum bt_ctf_btr_status
*status
)
1551 btr
->buf
.addr
= buf
;
1552 btr
->buf
.offset
= 0;
1554 btr
->buf
.buf_sz
= sz
;
1555 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1556 *status
= BT_CTF_BTR_STATUS_OK
;
1558 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1561 /* Continue running the machine */
1562 BT_LOGV_STR("Running the state machine.");
1565 *status
= handle_state(btr
);
1566 if (*status
!= BT_CTF_BTR_STATUS_OK
) {
1568 } else if (btr
->state
== BTR_STATE_DONE
) {
1573 /* Update packet offset for next time */
1574 update_packet_offset(btr
);