`ctf` plugin: `bt_bfcr`: use object's log level
[babeltrace.git] / src / plugins / ctf / common / bfcr / bfcr.c
1 /*
2 * Babeltrace - CTF binary field class reader (BFCR)
3 *
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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
23 * SOFTWARE.
24 */
25
26 #define BT_LOG_OUTPUT_LEVEL (bfcr->log_level)
27 #define BT_LOG_TAG "PLUGIN/CTF/BFCR"
28 #include "logging/log.h"
29
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <inttypes.h>
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <stdbool.h>
36 #include "common/assert.h"
37 #include <string.h>
38 #include "compat/bitfield.h"
39 #include "common/common.h"
40 #include <babeltrace2/babeltrace.h>
41 #include "common/align.h"
42 #include <glib.h>
43
44 #include "bfcr.h"
45 #include "../metadata/ctf-meta.h"
46
47 #define DIV8(_x) ((_x) >> 3)
48 #define BYTES_TO_BITS(_x) ((_x) * 8)
49 #define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
50 #define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
51 #define IN_BYTE_OFFSET(_at) ((_at) & 7)
52
53 /* A visit stack entry */
54 struct stack_entry {
55 /*
56 * Current class of base field, one of:
57 *
58 * * Structure
59 * * Array
60 * * Sequence
61 * * Variant
62 */
63 struct ctf_field_class *base_class;
64
65 /* Length of base field (always 1 for a variant class) */
66 int64_t base_len;
67
68 /* Index of next field to read */
69 int64_t index;
70 };
71
72 struct bt_bfcr;
73
74 /* Visit stack */
75 struct stack {
76 struct bt_bfcr *bfcr;
77
78 /* Entries (struct stack_entry) */
79 GArray *entries;
80
81 /* Number of active entries */
82 size_t size;
83 };
84
85 /* Reading states */
86 enum bfcr_state {
87 BFCR_STATE_NEXT_FIELD,
88 BFCR_STATE_ALIGN_BASIC,
89 BFCR_STATE_ALIGN_COMPOUND,
90 BFCR_STATE_READ_BASIC_BEGIN,
91 BFCR_STATE_READ_BASIC_CONTINUE,
92 BFCR_STATE_DONE,
93 };
94
95 /* Binary class reader */
96 struct bt_bfcr {
97 bt_logging_level log_level;
98
99 /* BFCR stack */
100 struct stack *stack;
101
102 /* Current basic field class */
103 struct ctf_field_class *cur_basic_field_class;
104
105 /* Current state */
106 enum bfcr_state state;
107
108 /*
109 * Last basic field class's byte order.
110 *
111 * This is used to detect errors since two contiguous basic
112 * classes for which the common boundary is not the boundary of
113 * a byte cannot have different byte orders.
114 *
115 * This is set to -1 on reset and when the last basic field class
116 * was a string class.
117 */
118 enum ctf_byte_order last_bo;
119
120 /* Current byte order (copied to last_bo after a successful read) */
121 enum ctf_byte_order cur_bo;
122
123 /* Stitch buffer infos */
124 struct {
125 /* Stitch buffer */
126 uint8_t buf[16];
127
128 /* Offset, within stitch buffer, of first bit */
129 size_t offset;
130
131 /* Length (bits) of data in stitch buffer from offset */
132 size_t at;
133 } stitch;
134
135 /* User buffer infos */
136 struct {
137 /* Address */
138 const uint8_t *addr;
139
140 /* Offset of data from address (bits) */
141 size_t offset;
142
143 /* Current position from offset (bits) */
144 size_t at;
145
146 /* Offset of offset within whole packet (bits) */
147 size_t packet_offset;
148
149 /* Data size in buffer (bits) */
150 size_t sz;
151
152 /* Buffer size (bytes) */
153 size_t buf_sz;
154 } buf;
155
156 /* User stuff */
157 struct {
158 /* Callback functions */
159 struct bt_bfcr_cbs cbs;
160
161 /* Private data */
162 void *data;
163 } user;
164 };
165
166 static inline
167 const char *bfcr_state_string(enum bfcr_state state)
168 {
169 switch (state) {
170 case BFCR_STATE_NEXT_FIELD:
171 return "BFCR_STATE_NEXT_FIELD";
172 case BFCR_STATE_ALIGN_BASIC:
173 return "BFCR_STATE_ALIGN_BASIC";
174 case BFCR_STATE_ALIGN_COMPOUND:
175 return "BFCR_STATE_ALIGN_COMPOUND";
176 case BFCR_STATE_READ_BASIC_BEGIN:
177 return "BFCR_STATE_READ_BASIC_BEGIN";
178 case BFCR_STATE_READ_BASIC_CONTINUE:
179 return "BFCR_STATE_READ_BASIC_CONTINUE";
180 case BFCR_STATE_DONE:
181 return "BFCR_STATE_DONE";
182 default:
183 return "(unknown)";
184 }
185 }
186
187 static
188 struct stack *stack_new(struct bt_bfcr *bfcr)
189 {
190 struct stack *stack = NULL;
191
192 stack = g_new0(struct stack, 1);
193 if (!stack) {
194 BT_LOGE_STR("Failed to allocate one stack.");
195 goto error;
196 }
197
198 stack->bfcr = bfcr;
199 stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry));
200 if (!stack->entries) {
201 BT_LOGE_STR("Failed to allocate a GArray.");
202 goto error;
203 }
204
205 BT_LOGD("Created stack: addr=%p", stack);
206 return stack;
207
208 error:
209 g_free(stack);
210 return NULL;
211 }
212
213 static
214 void stack_destroy(struct stack *stack)
215 {
216 struct bt_bfcr *bfcr;
217
218 if (!stack) {
219 return;
220 }
221
222 bfcr = stack->bfcr;
223 BT_LOGD("Destroying stack: addr=%p", stack);
224
225 if (stack->entries) {
226 g_array_free(stack->entries, TRUE);
227 }
228
229 g_free(stack);
230 }
231
232 static
233 int stack_push(struct stack *stack, struct ctf_field_class *base_class,
234 size_t base_len)
235 {
236 struct stack_entry *entry;
237 struct bt_bfcr *bfcr;
238
239 BT_ASSERT(stack);
240 BT_ASSERT(base_class);
241 bfcr = stack->bfcr;
242 BT_LOGV("Pushing field class on stack: stack-addr=%p, "
243 "fc-addr=%p, fc-type=%d, base-length=%zu, "
244 "stack-size-before=%zu, stack-size-after=%zu",
245 stack, base_class, base_class->type,
246 base_len, stack->size, stack->size + 1);
247
248 if (stack->entries->len == stack->size) {
249 g_array_set_size(stack->entries, stack->size + 1);
250 }
251
252 entry = &g_array_index(stack->entries, struct stack_entry, stack->size);
253 entry->base_class = base_class;
254 entry->base_len = base_len;
255 entry->index = 0;
256 stack->size++;
257 return 0;
258 }
259
260 static inline
261 int64_t get_compound_field_class_length(struct bt_bfcr *bfcr,
262 struct ctf_field_class *fc)
263 {
264 int64_t length;
265
266 switch (fc->type) {
267 case CTF_FIELD_CLASS_TYPE_STRUCT:
268 {
269 struct ctf_field_class_struct *struct_fc = (void *) fc;
270
271 length = (int64_t) struct_fc->members->len;
272 break;
273 }
274 case CTF_FIELD_CLASS_TYPE_VARIANT:
275 {
276 /* Variant field classes always "contain" a single class */
277 length = 1;
278 break;
279 }
280 case CTF_FIELD_CLASS_TYPE_ARRAY:
281 {
282 struct ctf_field_class_array *array_fc = (void *) fc;
283
284 length = (int64_t) array_fc->length;
285 break;
286 }
287 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
288 length = bfcr->user.cbs.query.get_sequence_length(fc,
289 bfcr->user.data);
290 break;
291 default:
292 abort();
293 }
294
295 return length;
296 }
297
298 static
299 int stack_push_with_len(struct bt_bfcr *bfcr, struct ctf_field_class *base_class)
300 {
301 int ret;
302 int64_t length = get_compound_field_class_length(bfcr, base_class);
303
304 if (length < 0) {
305 BT_LOGW("Cannot get compound field class's field count: "
306 "bfcr-addr=%p, fc-addr=%p, fc-type=%d",
307 bfcr, base_class, base_class->type);
308 ret = BT_BFCR_STATUS_ERROR;
309 goto end;
310 }
311
312 ret = stack_push(bfcr->stack, base_class, (size_t) length);
313
314 end:
315 return ret;
316 }
317
318 static inline
319 unsigned int stack_size(struct stack *stack)
320 {
321 BT_ASSERT(stack);
322 return stack->size;
323 }
324
325 static
326 void stack_pop(struct stack *stack)
327 {
328 struct bt_bfcr *bfcr;
329
330 BT_ASSERT(stack);
331 BT_ASSERT(stack_size(stack));
332 bfcr = stack->bfcr;
333 BT_LOGV("Popping from stack: "
334 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
335 stack, stack->entries->len, stack->entries->len - 1);
336 stack->size--;
337 }
338
339 static inline
340 bool stack_empty(struct stack *stack)
341 {
342 return stack_size(stack) == 0;
343 }
344
345 static
346 void stack_clear(struct stack *stack)
347 {
348 BT_ASSERT(stack);
349 stack->size = 0;
350 }
351
352 static inline
353 struct stack_entry *stack_top(struct stack *stack)
354 {
355 BT_ASSERT(stack);
356 BT_ASSERT(stack_size(stack));
357 return &g_array_index(stack->entries, struct stack_entry,
358 stack->size - 1);
359 }
360
361 static inline
362 size_t available_bits(struct bt_bfcr *bfcr)
363 {
364 return bfcr->buf.sz - bfcr->buf.at;
365 }
366
367 static inline
368 void consume_bits(struct bt_bfcr *bfcr, size_t incr)
369 {
370 BT_LOGV("Advancing cursor: bfcr-addr=%p, cur-before=%zu, cur-after=%zu",
371 bfcr, bfcr->buf.at, bfcr->buf.at + incr);
372 bfcr->buf.at += incr;
373 }
374
375 static inline
376 bool has_enough_bits(struct bt_bfcr *bfcr, size_t sz)
377 {
378 return available_bits(bfcr) >= sz;
379 }
380
381 static inline
382 bool at_least_one_bit_left(struct bt_bfcr *bfcr)
383 {
384 return has_enough_bits(bfcr, 1);
385 }
386
387 static inline
388 size_t packet_at(struct bt_bfcr *bfcr)
389 {
390 return bfcr->buf.packet_offset + bfcr->buf.at;
391 }
392
393 static inline
394 size_t buf_at_from_addr(struct bt_bfcr *bfcr)
395 {
396 /*
397 * Considering this:
398 *
399 * ====== offset ===== (17)
400 *
401 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
402 * ^
403 * addr (0) ==== at ==== (12)
404 *
405 * We want this:
406 *
407 * =============================== (29)
408 */
409 return bfcr->buf.offset + bfcr->buf.at;
410 }
411
412 static
413 void stitch_reset(struct bt_bfcr *bfcr)
414 {
415 bfcr->stitch.offset = 0;
416 bfcr->stitch.at = 0;
417 }
418
419 static inline
420 size_t stitch_at_from_addr(struct bt_bfcr *bfcr)
421 {
422 return bfcr->stitch.offset + bfcr->stitch.at;
423 }
424
425 static
426 void stitch_append_from_buf(struct bt_bfcr *bfcr, size_t sz)
427 {
428 size_t stitch_byte_at;
429 size_t buf_byte_at;
430 size_t nb_bytes;
431
432 if (sz == 0) {
433 return;
434 }
435
436 stitch_byte_at =
437 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(bfcr));
438 buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr));
439 nb_bytes = BITS_TO_BYTES_CEIL(sz);
440 BT_ASSERT(nb_bytes > 0);
441 BT_ASSERT(bfcr->buf.addr);
442 memcpy(&bfcr->stitch.buf[stitch_byte_at], &bfcr->buf.addr[buf_byte_at],
443 nb_bytes);
444 bfcr->stitch.at += sz;
445 consume_bits(bfcr, sz);
446 }
447
448 static
449 void stitch_append_from_remaining_buf(struct bt_bfcr *bfcr)
450 {
451 stitch_append_from_buf(bfcr, available_bits(bfcr));
452 }
453
454 static
455 void stitch_set_from_remaining_buf(struct bt_bfcr *bfcr)
456 {
457 stitch_reset(bfcr);
458 bfcr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(bfcr));
459 stitch_append_from_remaining_buf(bfcr);
460 }
461
462 static inline
463 void read_unsigned_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at,
464 unsigned int field_size, enum ctf_byte_order bo,
465 uint64_t *v)
466 {
467 switch (bo) {
468 case CTF_BYTE_ORDER_BIG:
469 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
470 break;
471 case CTF_BYTE_ORDER_LITTLE:
472 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
473 break;
474 default:
475 abort();
476 }
477
478 BT_LOGV("Read unsigned bit array: cur=%zu, size=%u, "
479 "bo=%d, val=%" PRIu64, at, field_size, bo, *v);
480 }
481
482 static inline
483 void read_signed_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at,
484 unsigned int field_size, enum ctf_byte_order bo, int64_t *v)
485 {
486 switch (bo) {
487 case CTF_BYTE_ORDER_BIG:
488 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
489 break;
490 case CTF_BYTE_ORDER_LITTLE:
491 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
492 break;
493 default:
494 abort();
495 }
496
497 BT_LOGV("Read signed bit array: cur=%zu, size=%u, "
498 "bo=%d, val=%" PRId64, at, field_size, bo, *v);
499 }
500
501 typedef enum bt_bfcr_status (* read_basic_and_call_cb_t)(struct bt_bfcr *,
502 const uint8_t *, size_t);
503
504 static inline
505 enum bt_bfcr_status validate_contiguous_bo(struct bt_bfcr *bfcr,
506 enum ctf_byte_order next_bo)
507 {
508 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
509
510 /* Always valid when at a byte boundary */
511 if (packet_at(bfcr) % 8 == 0) {
512 goto end;
513 }
514
515 /* Always valid if last byte order is unknown */
516 if (bfcr->last_bo == -1) {
517 goto end;
518 }
519
520 /* Always valid if next byte order is unknown */
521 if (next_bo == -1) {
522 goto end;
523 }
524
525 /* Make sure last byte order is compatible with the next byte order */
526 switch (bfcr->last_bo) {
527 case CTF_BYTE_ORDER_BIG:
528 if (next_bo != CTF_BYTE_ORDER_BIG) {
529 status = BT_BFCR_STATUS_ERROR;
530 }
531 break;
532 case CTF_BYTE_ORDER_LITTLE:
533 if (next_bo != CTF_BYTE_ORDER_LITTLE) {
534 status = BT_BFCR_STATUS_ERROR;
535 }
536 break;
537 default:
538 status = BT_BFCR_STATUS_ERROR;
539 }
540
541 end:
542 if (status < 0) {
543 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
544 "bfcr-addr=%p, last-bo=%d, next-bo=%d",
545 bfcr, bfcr->last_bo, next_bo);
546 }
547
548 return status;
549 }
550
551 static
552 enum bt_bfcr_status read_basic_float_and_call_cb(struct bt_bfcr *bfcr,
553 const uint8_t *buf, size_t at)
554 {
555 double dblval;
556 unsigned int field_size;
557 enum ctf_byte_order bo;
558 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
559 struct ctf_field_class_float *fc = (void *) bfcr->cur_basic_field_class;
560
561 BT_ASSERT(fc);
562 field_size = fc->base.size;
563 bo = fc->base.byte_order;
564 bfcr->cur_bo = bo;
565
566 switch (field_size) {
567 case 32:
568 {
569 uint64_t v;
570 union {
571 uint32_t u;
572 float f;
573 } f32;
574
575 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v);
576 f32.u = (uint32_t) v;
577 dblval = (double) f32.f;
578 break;
579 }
580 case 64:
581 {
582 union {
583 uint64_t u;
584 double d;
585 } f64;
586
587 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &f64.u);
588 dblval = f64.d;
589 break;
590 }
591 default:
592 /* Only 32-bit and 64-bit fields are supported currently */
593 abort();
594 }
595
596 BT_LOGV("Read floating point number value: bfcr=%p, cur=%zu, val=%f",
597 bfcr, at, dblval);
598
599 if (bfcr->user.cbs.classes.floating_point) {
600 BT_LOGV("Calling user function (floating point number).");
601 status = bfcr->user.cbs.classes.floating_point(dblval,
602 bfcr->cur_basic_field_class, bfcr->user.data);
603 BT_LOGV("User function returned: status=%s",
604 bt_bfcr_status_string(status));
605 if (status != BT_BFCR_STATUS_OK) {
606 BT_LOGW("User function failed: bfcr-addr=%p, status=%s",
607 bfcr, bt_bfcr_status_string(status));
608 }
609 }
610
611 return status;
612 }
613
614 static inline
615 enum bt_bfcr_status read_basic_int_and_call_cb(struct bt_bfcr *bfcr,
616 const uint8_t *buf, size_t at)
617 {
618 unsigned int field_size;
619 enum ctf_byte_order bo;
620 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
621 struct ctf_field_class_int *fc = (void *) bfcr->cur_basic_field_class;
622
623 field_size = fc->base.size;
624 bo = fc->base.byte_order;
625
626 /*
627 * Update current byte order now because we could be reading
628 * the integer value of an enumeration class, and thus we know
629 * here the actual supporting integer class's byte order.
630 */
631 bfcr->cur_bo = bo;
632
633 if (fc->is_signed) {
634 int64_t v;
635
636 read_signed_bitfield(bfcr, buf, at, field_size, bo, &v);
637
638 if (bfcr->user.cbs.classes.signed_int) {
639 BT_LOGV("Calling user function (signed integer).");
640 status = bfcr->user.cbs.classes.signed_int(v,
641 bfcr->cur_basic_field_class, bfcr->user.data);
642 BT_LOGV("User function returned: status=%s",
643 bt_bfcr_status_string(status));
644 if (status != BT_BFCR_STATUS_OK) {
645 BT_LOGW("User function failed: "
646 "bfcr-addr=%p, status=%s",
647 bfcr, bt_bfcr_status_string(status));
648 }
649 }
650 } else {
651 uint64_t v;
652
653 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v);
654
655 if (bfcr->user.cbs.classes.unsigned_int) {
656 BT_LOGV("Calling user function (unsigned integer).");
657 status = bfcr->user.cbs.classes.unsigned_int(v,
658 bfcr->cur_basic_field_class, bfcr->user.data);
659 BT_LOGV("User function returned: status=%s",
660 bt_bfcr_status_string(status));
661 if (status != BT_BFCR_STATUS_OK) {
662 BT_LOGW("User function failed: "
663 "bfcr-addr=%p, status=%s",
664 bfcr, bt_bfcr_status_string(status));
665 }
666 }
667 }
668
669 return status;
670 }
671
672 static inline
673 enum bt_bfcr_status read_bit_array_class_and_call_continue(struct bt_bfcr *bfcr,
674 read_basic_and_call_cb_t read_basic_and_call_cb)
675 {
676 size_t available;
677 size_t needed_bits;
678 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
679 struct ctf_field_class_bit_array *fc =
680 (void *) bfcr->cur_basic_field_class;
681
682 if (!at_least_one_bit_left(bfcr)) {
683 BT_LOGV("Reached end of data: bfcr-addr=%p", bfcr);
684 status = BT_BFCR_STATUS_EOF;
685 goto end;
686 }
687
688 available = available_bits(bfcr);
689 needed_bits = fc->size - bfcr->stitch.at;
690 BT_LOGV("Continuing basic field decoding: "
691 "bfcr-addr=%p, field-size=%u, needed-size=%zu, "
692 "available-size=%zu",
693 bfcr, fc->size, needed_bits, available);
694 if (needed_bits <= available) {
695 /* We have all the bits; append to stitch, then decode */
696 stitch_append_from_buf(bfcr, needed_bits);
697 status = read_basic_and_call_cb(bfcr, bfcr->stitch.buf,
698 bfcr->stitch.offset);
699 if (status != BT_BFCR_STATUS_OK) {
700 BT_LOGW("Cannot read basic field: "
701 "bfcr-addr=%p, fc-addr=%p, status=%s",
702 bfcr, bfcr->cur_basic_field_class,
703 bt_bfcr_status_string(status));
704 goto end;
705 }
706
707 if (stack_empty(bfcr->stack)) {
708 /* Root is a basic class */
709 bfcr->state = BFCR_STATE_DONE;
710 } else {
711 /* Go to next field */
712 stack_top(bfcr->stack)->index++;
713 bfcr->state = BFCR_STATE_NEXT_FIELD;
714 bfcr->last_bo = bfcr->cur_bo;
715 }
716 goto end;
717 }
718
719 /* We are here; it means we don't have enough data to decode this */
720 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
721 stitch_append_from_remaining_buf(bfcr);
722 status = BT_BFCR_STATUS_EOF;
723
724 end:
725 return status;
726 }
727
728 static inline
729 enum bt_bfcr_status read_bit_array_class_and_call_begin(struct bt_bfcr *bfcr,
730 read_basic_and_call_cb_t read_basic_and_call_cb)
731 {
732 size_t available;
733 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
734 struct ctf_field_class_bit_array *fc =
735 (void *) bfcr->cur_basic_field_class;
736
737 if (!at_least_one_bit_left(bfcr)) {
738 BT_LOGV("Reached end of data: bfcr-addr=%p", bfcr);
739 status = BT_BFCR_STATUS_EOF;
740 goto end;
741 }
742
743 status = validate_contiguous_bo(bfcr, fc->byte_order);
744 if (status != BT_BFCR_STATUS_OK) {
745 /* validate_contiguous_bo() logs errors */
746 goto end;
747 }
748
749 available = available_bits(bfcr);
750
751 if (fc->size <= available) {
752 /* We have all the bits; decode and set now */
753 BT_ASSERT(bfcr->buf.addr);
754 status = read_basic_and_call_cb(bfcr, bfcr->buf.addr,
755 buf_at_from_addr(bfcr));
756 if (status != BT_BFCR_STATUS_OK) {
757 BT_LOGW("Cannot read basic field: "
758 "bfcr-addr=%p, fc-addr=%p, status=%s",
759 bfcr, bfcr->cur_basic_field_class,
760 bt_bfcr_status_string(status));
761 goto end;
762 }
763
764 consume_bits(bfcr, fc->size);
765
766 if (stack_empty(bfcr->stack)) {
767 /* Root is a basic class */
768 bfcr->state = BFCR_STATE_DONE;
769 } else {
770 /* Go to next field */
771 stack_top(bfcr->stack)->index++;
772 bfcr->state = BFCR_STATE_NEXT_FIELD;
773 bfcr->last_bo = bfcr->cur_bo;
774 }
775
776 goto end;
777 }
778
779 /* We are here; it means we don't have enough data to decode this */
780 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
781 stitch_set_from_remaining_buf(bfcr);
782 bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE;
783 status = BT_BFCR_STATUS_EOF;
784
785 end:
786 return status;
787 }
788
789 static inline
790 enum bt_bfcr_status read_basic_int_class_and_call_begin(
791 struct bt_bfcr *bfcr)
792 {
793 return read_bit_array_class_and_call_begin(bfcr, read_basic_int_and_call_cb);
794 }
795
796 static inline
797 enum bt_bfcr_status read_basic_int_class_and_call_continue(
798 struct bt_bfcr *bfcr)
799 {
800 return read_bit_array_class_and_call_continue(bfcr,
801 read_basic_int_and_call_cb);
802 }
803
804 static inline
805 enum bt_bfcr_status read_basic_float_class_and_call_begin(
806 struct bt_bfcr *bfcr)
807 {
808 return read_bit_array_class_and_call_begin(bfcr,
809 read_basic_float_and_call_cb);
810 }
811
812 static inline
813 enum bt_bfcr_status read_basic_float_class_and_call_continue(
814 struct bt_bfcr *bfcr)
815 {
816 return read_bit_array_class_and_call_continue(bfcr,
817 read_basic_float_and_call_cb);
818 }
819
820 static inline
821 enum bt_bfcr_status read_basic_string_class_and_call(
822 struct bt_bfcr *bfcr, bool begin)
823 {
824 size_t buf_at_bytes;
825 const uint8_t *result;
826 size_t available_bytes;
827 const uint8_t *first_chr;
828 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
829
830 if (!at_least_one_bit_left(bfcr)) {
831 BT_LOGV("Reached end of data: bfcr-addr=%p", bfcr);
832 status = BT_BFCR_STATUS_EOF;
833 goto end;
834 }
835
836 BT_ASSERT(buf_at_from_addr(bfcr) % 8 == 0);
837 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(bfcr));
838 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr));
839 BT_ASSERT(bfcr->buf.addr);
840 first_chr = &bfcr->buf.addr[buf_at_bytes];
841 result = memchr(first_chr, '\0', available_bytes);
842
843 if (begin && bfcr->user.cbs.classes.string_begin) {
844 BT_LOGV("Calling user function (string, beginning).");
845 status = bfcr->user.cbs.classes.string_begin(
846 bfcr->cur_basic_field_class, bfcr->user.data);
847 BT_LOGV("User function returned: status=%s",
848 bt_bfcr_status_string(status));
849 if (status != BT_BFCR_STATUS_OK) {
850 BT_LOGW("User function failed: bfcr-addr=%p, status=%s",
851 bfcr, bt_bfcr_status_string(status));
852 goto end;
853 }
854 }
855
856 if (!result) {
857 /* No null character yet */
858 if (bfcr->user.cbs.classes.string) {
859 BT_LOGV("Calling user function (substring).");
860 status = bfcr->user.cbs.classes.string(
861 (const char *) first_chr,
862 available_bytes, bfcr->cur_basic_field_class,
863 bfcr->user.data);
864 BT_LOGV("User function returned: status=%s",
865 bt_bfcr_status_string(status));
866 if (status != BT_BFCR_STATUS_OK) {
867 BT_LOGW("User function failed: "
868 "bfcr-addr=%p, status=%s",
869 bfcr, bt_bfcr_status_string(status));
870 goto end;
871 }
872 }
873
874 consume_bits(bfcr, BYTES_TO_BITS(available_bytes));
875 bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE;
876 status = BT_BFCR_STATUS_EOF;
877 } else {
878 /* Found the null character */
879 size_t result_len = (size_t) (result - first_chr);
880
881 if (bfcr->user.cbs.classes.string && result_len) {
882 BT_LOGV("Calling user function (substring).");
883 status = bfcr->user.cbs.classes.string(
884 (const char *) first_chr,
885 result_len, bfcr->cur_basic_field_class,
886 bfcr->user.data);
887 BT_LOGV("User function returned: status=%s",
888 bt_bfcr_status_string(status));
889 if (status != BT_BFCR_STATUS_OK) {
890 BT_LOGW("User function failed: "
891 "bfcr-addr=%p, status=%s",
892 bfcr, bt_bfcr_status_string(status));
893 goto end;
894 }
895 }
896
897 if (bfcr->user.cbs.classes.string_end) {
898 BT_LOGV("Calling user function (string, end).");
899 status = bfcr->user.cbs.classes.string_end(
900 bfcr->cur_basic_field_class, bfcr->user.data);
901 BT_LOGV("User function returned: status=%s",
902 bt_bfcr_status_string(status));
903 if (status != BT_BFCR_STATUS_OK) {
904 BT_LOGW("User function failed: "
905 "bfcr-addr=%p, status=%s",
906 bfcr, bt_bfcr_status_string(status));
907 goto end;
908 }
909 }
910
911 consume_bits(bfcr, BYTES_TO_BITS(result_len + 1));
912
913 if (stack_empty(bfcr->stack)) {
914 /* Root is a basic class */
915 bfcr->state = BFCR_STATE_DONE;
916 } else {
917 /* Go to next field */
918 stack_top(bfcr->stack)->index++;
919 bfcr->state = BFCR_STATE_NEXT_FIELD;
920 bfcr->last_bo = bfcr->cur_bo;
921 }
922 }
923
924 end:
925 return status;
926 }
927
928 static inline
929 enum bt_bfcr_status read_basic_begin_state(struct bt_bfcr *bfcr)
930 {
931 enum bt_bfcr_status status;
932
933 BT_ASSERT(bfcr->cur_basic_field_class);
934
935 switch (bfcr->cur_basic_field_class->type) {
936 case CTF_FIELD_CLASS_TYPE_INT:
937 case CTF_FIELD_CLASS_TYPE_ENUM:
938 status = read_basic_int_class_and_call_begin(bfcr);
939 break;
940 case CTF_FIELD_CLASS_TYPE_FLOAT:
941 status = read_basic_float_class_and_call_begin(bfcr);
942 break;
943 case CTF_FIELD_CLASS_TYPE_STRING:
944 status = read_basic_string_class_and_call(bfcr, true);
945 break;
946 default:
947 abort();
948 }
949
950 return status;
951 }
952
953 static inline
954 enum bt_bfcr_status read_basic_continue_state(struct bt_bfcr *bfcr)
955 {
956 enum bt_bfcr_status status;
957
958 BT_ASSERT(bfcr->cur_basic_field_class);
959
960 switch (bfcr->cur_basic_field_class->type) {
961 case CTF_FIELD_CLASS_TYPE_INT:
962 case CTF_FIELD_CLASS_TYPE_ENUM:
963 status = read_basic_int_class_and_call_continue(bfcr);
964 break;
965 case CTF_FIELD_CLASS_TYPE_FLOAT:
966 status = read_basic_float_class_and_call_continue(bfcr);
967 break;
968 case CTF_FIELD_CLASS_TYPE_STRING:
969 status = read_basic_string_class_and_call(bfcr, false);
970 break;
971 default:
972 abort();
973 }
974
975 return status;
976 }
977
978 static inline
979 size_t bits_to_skip_to_align_to(struct bt_bfcr *bfcr, size_t align)
980 {
981 size_t aligned_packet_at;
982
983 aligned_packet_at = ALIGN(packet_at(bfcr), align);
984 return aligned_packet_at - packet_at(bfcr);
985 }
986
987 static inline
988 enum bt_bfcr_status align_class_state(struct bt_bfcr *bfcr,
989 struct ctf_field_class *field_class, enum bfcr_state next_state)
990 {
991 unsigned int field_alignment;
992 size_t skip_bits;
993 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
994
995 /* Get field's alignment */
996 field_alignment = field_class->alignment;
997
998 /*
999 * 0 means "undefined" for variants; what we really want is 1
1000 * (always aligned)
1001 */
1002 BT_ASSERT(field_alignment >= 1);
1003
1004 /* Compute how many bits we need to skip */
1005 skip_bits = bits_to_skip_to_align_to(bfcr, (size_t) field_alignment);
1006
1007 /* Nothing to skip? aligned */
1008 if (skip_bits == 0) {
1009 bfcr->state = next_state;
1010 goto end;
1011 }
1012
1013 /* Make sure there's at least one bit left */
1014 if (!at_least_one_bit_left(bfcr)) {
1015 status = BT_BFCR_STATUS_EOF;
1016 goto end;
1017 }
1018
1019 /* Consume as many bits as possible in what's left */
1020 consume_bits(bfcr, MIN(available_bits(bfcr), skip_bits));
1021
1022 /* Are we done now? */
1023 skip_bits = bits_to_skip_to_align_to(bfcr, field_alignment);
1024 if (skip_bits == 0) {
1025 /* Yes: go to next state */
1026 bfcr->state = next_state;
1027 goto end;
1028 } else {
1029 /* No: need more data */
1030 BT_LOGV("Reached end of data when aligning: bfcr-addr=%p", bfcr);
1031 status = BT_BFCR_STATUS_EOF;
1032 }
1033
1034 end:
1035 return status;
1036 }
1037
1038 static inline
1039 enum bt_bfcr_status next_field_state(struct bt_bfcr *bfcr)
1040 {
1041 int ret;
1042 struct stack_entry *top;
1043 struct ctf_field_class *next_field_class = NULL;
1044 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
1045
1046 if (stack_empty(bfcr->stack)) {
1047 goto end;
1048 }
1049
1050 top = stack_top(bfcr->stack);
1051
1052 /* Are we done with this base class? */
1053 while (top->index == top->base_len) {
1054 if (bfcr->user.cbs.classes.compound_end) {
1055 BT_LOGV("Calling user function (compound, end).");
1056 status = bfcr->user.cbs.classes.compound_end(
1057 top->base_class, bfcr->user.data);
1058 BT_LOGV("User function returned: status=%s",
1059 bt_bfcr_status_string(status));
1060 if (status != BT_BFCR_STATUS_OK) {
1061 BT_LOGW("User function failed: bfcr-addr=%p, status=%s",
1062 bfcr, bt_bfcr_status_string(status));
1063 goto end;
1064 }
1065 }
1066
1067 stack_pop(bfcr->stack);
1068
1069 /* Are we done with the root class? */
1070 if (stack_empty(bfcr->stack)) {
1071 bfcr->state = BFCR_STATE_DONE;
1072 goto end;
1073 }
1074
1075 top = stack_top(bfcr->stack);
1076 top->index++;
1077 }
1078
1079 /* Get next field's class */
1080 switch (top->base_class->type) {
1081 case CTF_FIELD_CLASS_TYPE_STRUCT:
1082 next_field_class = ctf_field_class_struct_borrow_member_by_index(
1083 (void *) top->base_class, (uint64_t) top->index)->fc;
1084 break;
1085 case CTF_FIELD_CLASS_TYPE_ARRAY:
1086 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
1087 {
1088 struct ctf_field_class_array_base *array_fc =
1089 (void *) top->base_class;
1090
1091 next_field_class = array_fc->elem_fc;
1092 break;
1093 }
1094 case CTF_FIELD_CLASS_TYPE_VARIANT:
1095 /* Variant classes are dynamic: the user should know! */
1096 next_field_class =
1097 bfcr->user.cbs.query.borrow_variant_selected_field_class(
1098 top->base_class, bfcr->user.data);
1099 break;
1100 default:
1101 break;
1102 }
1103
1104 if (!next_field_class) {
1105 BT_LOGW("Cannot get the field class of the next field: "
1106 "bfcr-addr=%p, base-fc-addr=%p, base-fc-type=%d, "
1107 "index=%" PRId64,
1108 bfcr, top->base_class, top->base_class->type,
1109 top->index);
1110 status = BT_BFCR_STATUS_ERROR;
1111 goto end;
1112 }
1113
1114 if (next_field_class->is_compound) {
1115 if (bfcr->user.cbs.classes.compound_begin) {
1116 BT_LOGV("Calling user function (compound, begin).");
1117 status = bfcr->user.cbs.classes.compound_begin(
1118 next_field_class, bfcr->user.data);
1119 BT_LOGV("User function returned: status=%s",
1120 bt_bfcr_status_string(status));
1121 if (status != BT_BFCR_STATUS_OK) {
1122 BT_LOGW("User function failed: bfcr-addr=%p, status=%s",
1123 bfcr, bt_bfcr_status_string(status));
1124 goto end;
1125 }
1126 }
1127
1128 ret = stack_push_with_len(bfcr, next_field_class);
1129 if (ret) {
1130 /* stack_push_with_len() logs errors */
1131 status = BT_BFCR_STATUS_ERROR;
1132 goto end;
1133 }
1134
1135 /* Next state: align a compound class */
1136 bfcr->state = BFCR_STATE_ALIGN_COMPOUND;
1137 } else {
1138 /* Replace current basic field class */
1139 BT_LOGV("Replacing current basic field class: "
1140 "bfcr-addr=%p, cur-basic-fc-addr=%p, "
1141 "next-basic-fc-addr=%p",
1142 bfcr, bfcr->cur_basic_field_class, next_field_class);
1143 bfcr->cur_basic_field_class = next_field_class;
1144
1145 /* Next state: align a basic class */
1146 bfcr->state = BFCR_STATE_ALIGN_BASIC;
1147 }
1148
1149 end:
1150 return status;
1151 }
1152
1153 static inline
1154 enum bt_bfcr_status handle_state(struct bt_bfcr *bfcr)
1155 {
1156 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
1157
1158 BT_LOGV("Handling state: bfcr-addr=%p, state=%s",
1159 bfcr, bfcr_state_string(bfcr->state));
1160
1161 switch (bfcr->state) {
1162 case BFCR_STATE_NEXT_FIELD:
1163 status = next_field_state(bfcr);
1164 break;
1165 case BFCR_STATE_ALIGN_BASIC:
1166 status = align_class_state(bfcr, bfcr->cur_basic_field_class,
1167 BFCR_STATE_READ_BASIC_BEGIN);
1168 break;
1169 case BFCR_STATE_ALIGN_COMPOUND:
1170 status = align_class_state(bfcr, stack_top(bfcr->stack)->base_class,
1171 BFCR_STATE_NEXT_FIELD);
1172 break;
1173 case BFCR_STATE_READ_BASIC_BEGIN:
1174 status = read_basic_begin_state(bfcr);
1175 break;
1176 case BFCR_STATE_READ_BASIC_CONTINUE:
1177 status = read_basic_continue_state(bfcr);
1178 break;
1179 case BFCR_STATE_DONE:
1180 break;
1181 }
1182
1183 BT_LOGV("Handled state: bfcr-addr=%p, status=%s",
1184 bfcr, bt_bfcr_status_string(status));
1185 return status;
1186 }
1187
1188 BT_HIDDEN
1189 struct bt_bfcr *bt_bfcr_create(struct bt_bfcr_cbs cbs, void *data,
1190 bt_logging_level log_level)
1191 {
1192 struct bt_bfcr *bfcr;
1193
1194 BT_LOG_WRITE_CUR_LVL(BT_LOG_DEBUG, log_level, BT_LOG_TAG,
1195 "Creating binary field class reader (BFCR).");
1196 bfcr = g_new0(struct bt_bfcr, 1);
1197 if (!bfcr) {
1198 BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
1199 "Failed to allocate one binary class reader.");
1200 goto end;
1201 }
1202
1203 bfcr->log_level = log_level;
1204 bfcr->stack = stack_new(bfcr);
1205 if (!bfcr->stack) {
1206 BT_LOGE_STR("Cannot create BFCR's stack.");
1207 bt_bfcr_destroy(bfcr);
1208 bfcr = NULL;
1209 goto end;
1210 }
1211
1212 bfcr->state = BFCR_STATE_NEXT_FIELD;
1213 bfcr->user.cbs = cbs;
1214 bfcr->user.data = data;
1215 BT_LOGD("Created BFCR: addr=%p", bfcr);
1216
1217 end:
1218 return bfcr;
1219 }
1220
1221 BT_HIDDEN
1222 void bt_bfcr_destroy(struct bt_bfcr *bfcr)
1223 {
1224 if (bfcr->stack) {
1225 stack_destroy(bfcr->stack);
1226 }
1227
1228 BT_LOGD("Destroying BFCR: addr=%p", bfcr);
1229 g_free(bfcr);
1230 }
1231
1232 static
1233 void reset(struct bt_bfcr *bfcr)
1234 {
1235 BT_LOGD("Resetting BFCR: addr=%p", bfcr);
1236 stack_clear(bfcr->stack);
1237 stitch_reset(bfcr);
1238 bfcr->buf.addr = NULL;
1239 bfcr->last_bo = -1;
1240 }
1241
1242 static
1243 void update_packet_offset(struct bt_bfcr *bfcr)
1244 {
1245 BT_LOGV("Updating packet offset for next call: "
1246 "bfcr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1247 bfcr, bfcr->buf.packet_offset,
1248 bfcr->buf.packet_offset + bfcr->buf.at);
1249 bfcr->buf.packet_offset += bfcr->buf.at;
1250 }
1251
1252 BT_HIDDEN
1253 size_t bt_bfcr_start(struct bt_bfcr *bfcr,
1254 struct ctf_field_class *cls, const uint8_t *buf,
1255 size_t offset, size_t packet_offset, size_t sz,
1256 enum bt_bfcr_status *status)
1257 {
1258 BT_ASSERT(bfcr);
1259 BT_ASSERT(BYTES_TO_BITS(sz) >= offset);
1260 reset(bfcr);
1261 bfcr->buf.addr = buf;
1262 bfcr->buf.offset = offset;
1263 bfcr->buf.at = 0;
1264 bfcr->buf.packet_offset = packet_offset;
1265 bfcr->buf.buf_sz = sz;
1266 bfcr->buf.sz = BYTES_TO_BITS(sz) - offset;
1267 *status = BT_BFCR_STATUS_OK;
1268
1269 BT_LOGV("Starting decoding: bfcr-addr=%p, fc-addr=%p, "
1270 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1271 "packet-offset=%zu",
1272 bfcr, cls, buf, sz, offset, packet_offset);
1273
1274 /* Set root class */
1275 if (cls->is_compound) {
1276 /* Compound class: push on visit stack */
1277 int stack_ret;
1278
1279 if (bfcr->user.cbs.classes.compound_begin) {
1280 BT_LOGV("Calling user function (compound, begin).");
1281 *status = bfcr->user.cbs.classes.compound_begin(
1282 cls, bfcr->user.data);
1283 BT_LOGV("User function returned: status=%s",
1284 bt_bfcr_status_string(*status));
1285 if (*status != BT_BFCR_STATUS_OK) {
1286 BT_LOGW("User function failed: bfcr-addr=%p, status=%s",
1287 bfcr, bt_bfcr_status_string(*status));
1288 goto end;
1289 }
1290 }
1291
1292 stack_ret = stack_push_with_len(bfcr, cls);
1293 if (stack_ret) {
1294 /* stack_push_with_len() logs errors */
1295 *status = BT_BFCR_STATUS_ERROR;
1296 goto end;
1297 }
1298
1299 bfcr->state = BFCR_STATE_ALIGN_COMPOUND;
1300 } else {
1301 /* Basic class: set as current basic class */
1302 bfcr->cur_basic_field_class = cls;
1303 bfcr->state = BFCR_STATE_ALIGN_BASIC;
1304 }
1305
1306 /* Run the machine! */
1307 BT_LOGV_STR("Running the state machine.");
1308
1309 while (true) {
1310 *status = handle_state(bfcr);
1311 if (*status != BT_BFCR_STATUS_OK ||
1312 bfcr->state == BFCR_STATE_DONE) {
1313 break;
1314 }
1315 }
1316
1317 /* Update packet offset for next time */
1318 update_packet_offset(bfcr);
1319
1320 end:
1321 return bfcr->buf.at;
1322 }
1323
1324 BT_HIDDEN
1325 size_t bt_bfcr_continue(struct bt_bfcr *bfcr, const uint8_t *buf, size_t sz,
1326 enum bt_bfcr_status *status)
1327 {
1328 BT_ASSERT(bfcr);
1329 BT_ASSERT(buf);
1330 BT_ASSERT(sz > 0);
1331 bfcr->buf.addr = buf;
1332 bfcr->buf.offset = 0;
1333 bfcr->buf.at = 0;
1334 bfcr->buf.buf_sz = sz;
1335 bfcr->buf.sz = BYTES_TO_BITS(sz);
1336 *status = BT_BFCR_STATUS_OK;
1337
1338 BT_LOGV("Continuing decoding: bfcr-addr=%p, buf-addr=%p, buf-size=%zu",
1339 bfcr, buf, sz);
1340
1341 /* Continue running the machine */
1342 BT_LOGV_STR("Running the state machine.");
1343
1344 while (true) {
1345 *status = handle_state(bfcr);
1346 if (*status != BT_BFCR_STATUS_OK ||
1347 bfcr->state == BFCR_STATE_DONE) {
1348 break;
1349 }
1350 }
1351
1352 /* Update packet offset for next time */
1353 update_packet_offset(bfcr);
1354 return bfcr->buf.at;
1355 }
1356
1357 BT_HIDDEN
1358 void bt_bfcr_set_unsigned_int_cb(struct bt_bfcr *bfcr,
1359 bt_bfcr_unsigned_int_cb_func cb)
1360 {
1361 BT_ASSERT(bfcr);
1362 BT_ASSERT(cb);
1363 bfcr->user.cbs.classes.unsigned_int = cb;
1364 }
This page took 0.087518 seconds and 5 git commands to generate.