Implement std.integer.base (display base 2, 8, 10, 16)
[libside.git] / src / tracer.c
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6 #include <stdint.h>
7 #include <inttypes.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <stdbool.h>
11 #include <string.h>
12
13 #include <side/trace.h>
14
15 enum tracer_display_base {
16 TRACER_DISPLAY_BASE_2,
17 TRACER_DISPLAY_BASE_8,
18 TRACER_DISPLAY_BASE_10,
19 TRACER_DISPLAY_BASE_16,
20 };
21
22 static struct side_tracer_handle *tracer_handle;
23
24 static
25 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
26 static
27 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
28 static
29 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
30 static
31 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx);
32 static
33 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
34 static
35 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
36 static
37 void tracer_print_dynamic(const struct side_arg_dynamic_vec *dynamic_item);
38 static
39 void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item);
40
41 static
42 int64_t get_attr_integer_value(const struct side_attr *attr)
43 {
44 int64_t val;
45
46 switch (attr->value.type) {
47 case SIDE_ATTR_TYPE_U8:
48 val = attr->value.u.side_u8;
49 break;
50 case SIDE_ATTR_TYPE_U16:
51 val = attr->value.u.side_u16;
52 break;
53 case SIDE_ATTR_TYPE_U32:
54 val = attr->value.u.side_u32;
55 break;
56 case SIDE_ATTR_TYPE_U64:
57 val = attr->value.u.side_u64;
58 break;
59 case SIDE_ATTR_TYPE_S8:
60 val = attr->value.u.side_s8;
61 break;
62 case SIDE_ATTR_TYPE_S16:
63 val = attr->value.u.side_s16;
64 break;
65 case SIDE_ATTR_TYPE_S32:
66 val = attr->value.u.side_s32;
67 break;
68 case SIDE_ATTR_TYPE_S64:
69 val = attr->value.u.side_s64;
70 break;
71 default:
72 fprintf(stderr, "Unexpected attribute type\n");
73 abort();
74 }
75 return val;
76 }
77
78 static
79 enum tracer_display_base get_attr_display_base(const struct side_attr *_attr, uint32_t nr_attr)
80 {
81 uint32_t i;
82
83 for (i = 0; i < nr_attr; i++) {
84 const struct side_attr *attr = &_attr[i];
85
86 if (!strcmp(attr->key, "std.integer.base")) {
87 int64_t val = get_attr_integer_value(attr);
88
89 switch (val) {
90 case 2:
91 return TRACER_DISPLAY_BASE_2;
92 case 8:
93 return TRACER_DISPLAY_BASE_8;
94 case 10:
95 return TRACER_DISPLAY_BASE_10;
96 case 16:
97 return TRACER_DISPLAY_BASE_16;
98 default:
99 fprintf(stderr, "Unexpected integer display base: %" PRId64 "\n", val);
100 abort();
101 }
102 }
103 }
104 return TRACER_DISPLAY_BASE_10; /* Default */
105 }
106
107 static
108 bool type_to_host_reverse_bo(const struct side_type_description *type_desc)
109 {
110 switch (type_desc->type) {
111 case SIDE_TYPE_U8:
112 case SIDE_TYPE_S8:
113 case SIDE_TYPE_BYTE:
114 return false;
115 case SIDE_TYPE_U16:
116 case SIDE_TYPE_U32:
117 case SIDE_TYPE_U64:
118 case SIDE_TYPE_S16:
119 case SIDE_TYPE_S32:
120 case SIDE_TYPE_S64:
121 case SIDE_TYPE_POINTER32:
122 case SIDE_TYPE_POINTER64:
123 if (type_desc->u.side_basic.byte_order != SIDE_TYPE_BYTE_ORDER_HOST)
124 return true;
125 else
126 return false;
127 break;
128 case SIDE_TYPE_FLOAT_BINARY16:
129 case SIDE_TYPE_FLOAT_BINARY32:
130 case SIDE_TYPE_FLOAT_BINARY64:
131 case SIDE_TYPE_FLOAT_BINARY128:
132 if (type_desc->u.side_basic.byte_order != SIDE_TYPE_FLOAT_WORD_ORDER_HOST)
133 return true;
134 else
135 return false;
136 break;
137 default:
138 fprintf(stderr, "Unexpected type\n");
139 abort();
140 }
141 }
142
143 static
144 bool dynamic_type_to_host_reverse_bo(const struct side_arg_dynamic_vec *item)
145 {
146 switch (item->dynamic_type) {
147 case SIDE_DYNAMIC_TYPE_U8:
148 case SIDE_DYNAMIC_TYPE_S8:
149 case SIDE_DYNAMIC_TYPE_BYTE:
150 return false;
151 case SIDE_DYNAMIC_TYPE_U16:
152 case SIDE_DYNAMIC_TYPE_U32:
153 case SIDE_DYNAMIC_TYPE_U64:
154 case SIDE_DYNAMIC_TYPE_S16:
155 case SIDE_DYNAMIC_TYPE_S32:
156 case SIDE_DYNAMIC_TYPE_S64:
157 case SIDE_DYNAMIC_TYPE_POINTER32:
158 case SIDE_DYNAMIC_TYPE_POINTER64:
159 if (item->u.side_basic.byte_order != SIDE_TYPE_BYTE_ORDER_HOST)
160 return true;
161 else
162 return false;
163 break;
164 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY16:
165 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY32:
166 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY64:
167 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY128:
168 if (item->u.side_basic.byte_order != SIDE_TYPE_FLOAT_WORD_ORDER_HOST)
169 return true;
170 else
171 return false;
172 break;
173 default:
174 fprintf(stderr, "Unexpected type\n");
175 abort();
176 }
177 }
178
179 static
180 void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
181 {
182 printf("{ key%s \"%s\", value%s ", separator, attr->key, separator);
183 switch (attr->value.type) {
184 case SIDE_ATTR_TYPE_BOOL:
185 printf("%s", attr->value.u.side_bool ? "true" : "false");
186 break;
187 case SIDE_ATTR_TYPE_U8:
188 printf("%" PRIu8, attr->value.u.side_u8);
189 break;
190 case SIDE_ATTR_TYPE_U16:
191 printf("%" PRIu16, attr->value.u.side_u16);
192 break;
193 case SIDE_ATTR_TYPE_U32:
194 printf("%" PRIu32, attr->value.u.side_u32);
195 break;
196 case SIDE_ATTR_TYPE_U64:
197 printf("%" PRIu64, attr->value.u.side_u64);
198 break;
199 case SIDE_ATTR_TYPE_S8:
200 printf("%" PRId8, attr->value.u.side_s8);
201 break;
202 case SIDE_ATTR_TYPE_S16:
203 printf("%" PRId16, attr->value.u.side_s16);
204 break;
205 case SIDE_ATTR_TYPE_S32:
206 printf("%" PRId32, attr->value.u.side_s32);
207 break;
208 case SIDE_ATTR_TYPE_S64:
209 printf("%" PRId64, attr->value.u.side_s64);
210 break;
211 case SIDE_ATTR_TYPE_POINTER32:
212 printf("0x%" PRIx32, attr->value.u.side_u32);
213 break;
214 case SIDE_ATTR_TYPE_POINTER64:
215 printf("0x%" PRIx64, attr->value.u.side_u64);
216 break;
217 case SIDE_ATTR_TYPE_FLOAT_BINARY16:
218 #if __HAVE_FLOAT16
219 printf("%g", (double) attr->value.u.side_float_binary16);
220 break;
221 #else
222 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
223 abort();
224 #endif
225 case SIDE_ATTR_TYPE_FLOAT_BINARY32:
226 #if __HAVE_FLOAT32
227 printf("%g", (double) attr->value.u.side_float_binary32);
228 break;
229 #else
230 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
231 abort();
232 #endif
233 case SIDE_ATTR_TYPE_FLOAT_BINARY64:
234 #if __HAVE_FLOAT64
235 printf("%g", (double) attr->value.u.side_float_binary64);
236 break;
237 #else
238 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
239 abort();
240 #endif
241 case SIDE_ATTR_TYPE_FLOAT_BINARY128:
242 #if __HAVE_FLOAT128
243 printf("%Lg", (long double) attr->value.u.side_float_binary128);
244 break;
245 #else
246 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
247 abort();
248 #endif
249 case SIDE_ATTR_TYPE_STRING:
250 printf("\"%s\"", (const char *)(uintptr_t) attr->value.u.string);
251 break;
252 default:
253 fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
254 abort();
255 }
256 printf(" }");
257 }
258
259 static
260 void print_attributes(const char *prefix_str, const char *separator,
261 const struct side_attr *attr, uint32_t nr_attr)
262 {
263 int i;
264
265 if (!nr_attr)
266 return;
267 printf("%s%s [ ", prefix_str, separator);
268 for (i = 0; i < nr_attr; i++) {
269 printf("%s", i ? ", " : "");
270 tracer_print_attr_type(separator, &attr[i]);
271 }
272 printf(" ]");
273 }
274
275 static
276 void print_enum(const struct side_type_description *type_desc, const struct side_arg_vec *item)
277 {
278 const struct side_enum_mappings *mappings = type_desc->u.side_enum.mappings;
279 const struct side_type_description *elem_type = type_desc->u.side_enum.elem_type;
280 int i, print_count = 0;
281 int64_t value;
282
283 if (elem_type->type != item->type) {
284 fprintf(stderr, "ERROR: Unexpected enum element type\n");
285 abort();
286 }
287 switch (item->type) {
288 case SIDE_TYPE_U8:
289 value = (int64_t) item->u.side_u8;
290 break;
291 case SIDE_TYPE_U16:
292 {
293 uint16_t v;
294
295 v = item->u.side_u16;
296 if (type_to_host_reverse_bo(elem_type))
297 v = side_bswap_16(v);
298 value = (int64_t) v;
299 break;
300 }
301 case SIDE_TYPE_U32:
302 {
303 uint32_t v;
304
305 v = item->u.side_u32;
306 if (type_to_host_reverse_bo(elem_type))
307 v = side_bswap_32(v);
308 value = (int64_t) v;
309 break;
310 }
311 case SIDE_TYPE_U64:
312 {
313 uint64_t v;
314
315 v = item->u.side_u64;
316 if (type_to_host_reverse_bo(elem_type))
317 v = side_bswap_64(v);
318 value = (int64_t) v;
319 break;
320 }
321 case SIDE_TYPE_S8:
322 value = (int64_t) item->u.side_s8;
323 break;
324 case SIDE_TYPE_S16:
325 {
326 int16_t v;
327
328 v = item->u.side_s16;
329 if (type_to_host_reverse_bo(elem_type))
330 v = side_bswap_16(v);
331 value = (int64_t) v;
332 break;
333 }
334 case SIDE_TYPE_S32:
335 {
336 int32_t v;
337
338 v = item->u.side_s32;
339 if (type_to_host_reverse_bo(elem_type))
340 v = side_bswap_32(v);
341 value = (int64_t) v;
342 break;
343 }
344 case SIDE_TYPE_S64:
345 {
346 int64_t v;
347
348 v = item->u.side_s64;
349 if (type_to_host_reverse_bo(elem_type))
350 v = side_bswap_64(v);
351 value = v;
352 break;
353 }
354 default:
355 fprintf(stderr, "ERROR: Unexpected enum element type\n");
356 abort();
357 }
358 print_attributes("attr", ":", mappings->attr, mappings->nr_attr);
359 printf("%s", mappings->nr_attr ? ", " : "");
360 tracer_print_type(type_desc->u.side_enum.elem_type, item);
361 printf(", labels: [ ");
362 for (i = 0; i < mappings->nr_mappings; i++) {
363 const struct side_enum_mapping *mapping = &mappings->mappings[i];
364
365 if (mapping->range_end < mapping->range_begin) {
366 fprintf(stderr, "ERROR: Unexpected enum range: %" PRIu64 "-%" PRIu64 "\n",
367 mapping->range_begin, mapping->range_end);
368 abort();
369 }
370 if (value >= mapping->range_begin && value <= mapping->range_end) {
371 printf("%s", print_count++ ? ", " : "");
372 printf("\"%s\"", mapping->label);
373 }
374 }
375 if (!print_count)
376 printf("<NO LABEL>");
377 printf(" ]");
378 }
379
380 static
381 uint32_t enum_elem_type_to_stride(const struct side_type_description *elem_type)
382 {
383 uint32_t stride_bit;
384
385 switch (elem_type->type) {
386 case SIDE_TYPE_U8: /* Fall-through */
387 case SIDE_TYPE_BYTE:
388 stride_bit = 8;
389 break;
390 case SIDE_TYPE_U16:
391 stride_bit = 16;
392 break;
393 case SIDE_TYPE_U32:
394 stride_bit = 32;
395 break;
396 case SIDE_TYPE_U64:
397 stride_bit = 64;
398 break;
399 default:
400 fprintf(stderr, "ERROR: Unexpected enum element type\n");
401 abort();
402 }
403 return stride_bit;
404 }
405
406 static
407 void print_enum_bitmap(const struct side_type_description *type_desc,
408 const struct side_arg_vec *item)
409 {
410 const struct side_type_description *elem_type = type_desc->u.side_enum_bitmap.elem_type;
411 const struct side_enum_bitmap_mappings *side_enum_mappings = type_desc->u.side_enum_bitmap.mappings;
412 int i, print_count = 0;
413 uint32_t stride_bit, nr_items;
414 bool reverse_byte_order = false;
415 const struct side_arg_vec *array_item;
416
417 switch (elem_type->type) {
418 case SIDE_TYPE_U8: /* Fall-through */
419 case SIDE_TYPE_BYTE: /* Fall-through */
420 case SIDE_TYPE_U16: /* Fall-through */
421 case SIDE_TYPE_U32: /* Fall-through */
422 case SIDE_TYPE_U64:
423 stride_bit = enum_elem_type_to_stride(elem_type);
424 reverse_byte_order = type_to_host_reverse_bo(elem_type);
425 array_item = item;
426 nr_items = 1;
427 break;
428 case SIDE_TYPE_ARRAY:
429 stride_bit = enum_elem_type_to_stride(elem_type->u.side_array.elem_type);
430 reverse_byte_order = type_to_host_reverse_bo(elem_type->u.side_array.elem_type);
431 array_item = item->u.side_array->sav;
432 nr_items = type_desc->u.side_array.length;
433 break;
434 case SIDE_TYPE_VLA:
435 stride_bit = enum_elem_type_to_stride(elem_type->u.side_vla.elem_type);
436 reverse_byte_order = type_to_host_reverse_bo(elem_type->u.side_vla.elem_type);
437 array_item = item->u.side_vla->sav;
438 nr_items = item->u.side_vla->len;
439 break;
440 default:
441 fprintf(stderr, "ERROR: Unexpected enum element type\n");
442 abort();
443 }
444
445 print_attributes("attr", ":", side_enum_mappings->attr, side_enum_mappings->nr_attr);
446 printf("%s", side_enum_mappings->nr_attr ? ", " : "");
447 printf("labels: [ ");
448 for (i = 0; i < side_enum_mappings->nr_mappings; i++) {
449 const struct side_enum_bitmap_mapping *mapping = &side_enum_mappings->mappings[i];
450 bool match = false;
451 uint64_t bit;
452
453 if (mapping->range_end < mapping->range_begin) {
454 fprintf(stderr, "ERROR: Unexpected enum bitmap range: %" PRIu64 "-%" PRIu64 "\n",
455 mapping->range_begin, mapping->range_end);
456 abort();
457 }
458 for (bit = mapping->range_begin; bit <= mapping->range_end; bit++) {
459 if (bit > (nr_items * stride_bit) - 1)
460 break;
461 switch (stride_bit) {
462 case 8:
463 {
464 uint8_t v = array_item[bit / 8].u.side_u8;
465 if (v & (1ULL << (bit % 8))) {
466 match = true;
467 goto match;
468 }
469 break;
470 }
471 case 16:
472 {
473 uint16_t v = array_item[bit / 16].u.side_u16;
474 if (reverse_byte_order)
475 v = side_bswap_16(v);
476 if (v & (1ULL << (bit % 16))) {
477 match = true;
478 goto match;
479 }
480 break;
481 }
482 case 32:
483 {
484 uint32_t v = array_item[bit / 32].u.side_u32;
485 if (reverse_byte_order)
486 v = side_bswap_32(v);
487 if (v & (1ULL << (bit % 32))) {
488 match = true;
489 goto match;
490 }
491 break;
492 }
493 case 64:
494 {
495 uint64_t v = array_item[bit / 64].u.side_u64;
496 if (reverse_byte_order)
497 v = side_bswap_64(v);
498 if (v & (1ULL << (bit % 64))) {
499 match = true;
500 goto match;
501 }
502 break;
503 }
504 default:
505 abort();
506 }
507 }
508 match:
509 if (match) {
510 printf("%s", print_count++ ? ", " : "");
511 printf("\"%s\"", mapping->label);
512 }
513 }
514 if (!print_count)
515 printf("<NO LABEL>");
516 printf(" ]");
517 }
518
519 static
520 void print_integer_binary(uint64_t v, int bits)
521 {
522 int i;
523
524 printf("0b");
525 v <<= 64 - bits;
526 for (i = 0; i < bits; i++) {
527 printf("%c", v & (1ULL << 63) ? '1' : '0');
528 v <<= 1;
529 }
530 }
531
532 static
533 void tracer_print_basic_type_header(const struct side_type_description *type_desc)
534 {
535 print_attributes("attr", ":", type_desc->u.side_basic.attr, type_desc->u.side_basic.nr_attr);
536 printf("%s", type_desc->u.side_basic.nr_attr ? ", " : "");
537 printf("value: ");
538 }
539
540 static
541 void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item)
542 {
543 enum side_type type;
544 enum tracer_display_base base = TRACER_DISPLAY_BASE_10;
545
546 switch (type_desc->type) {
547 case SIDE_TYPE_ARRAY:
548 switch (item->type) {
549 case SIDE_TYPE_ARRAY_U8:
550 case SIDE_TYPE_ARRAY_U16:
551 case SIDE_TYPE_ARRAY_U32:
552 case SIDE_TYPE_ARRAY_U64:
553 case SIDE_TYPE_ARRAY_S8:
554 case SIDE_TYPE_ARRAY_S16:
555 case SIDE_TYPE_ARRAY_S32:
556 case SIDE_TYPE_ARRAY_S64:
557 case SIDE_TYPE_ARRAY_POINTER32:
558 case SIDE_TYPE_ARRAY_POINTER64:
559 case SIDE_TYPE_ARRAY_BYTE:
560 case SIDE_TYPE_ARRAY:
561 break;
562 default:
563 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
564 abort();
565 break;
566 }
567 break;
568
569 case SIDE_TYPE_VLA:
570 switch (item->type) {
571 case SIDE_TYPE_VLA_U8:
572 case SIDE_TYPE_VLA_U16:
573 case SIDE_TYPE_VLA_U32:
574 case SIDE_TYPE_VLA_U64:
575 case SIDE_TYPE_VLA_S8:
576 case SIDE_TYPE_VLA_S16:
577 case SIDE_TYPE_VLA_S32:
578 case SIDE_TYPE_VLA_S64:
579 case SIDE_TYPE_VLA_BYTE:
580 case SIDE_TYPE_VLA_POINTER32:
581 case SIDE_TYPE_VLA_POINTER64:
582 case SIDE_TYPE_VLA:
583 break;
584 default:
585 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
586 abort();
587 break;
588 }
589 break;
590
591 case SIDE_TYPE_ENUM:
592 switch (item->type) {
593 case SIDE_TYPE_U8:
594 case SIDE_TYPE_U16:
595 case SIDE_TYPE_U32:
596 case SIDE_TYPE_U64:
597 case SIDE_TYPE_S8:
598 case SIDE_TYPE_S16:
599 case SIDE_TYPE_S32:
600 case SIDE_TYPE_S64:
601 break;
602 default:
603 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
604 abort();
605 break;
606 }
607 break;
608
609 case SIDE_TYPE_ENUM_BITMAP:
610 switch (item->type) {
611 case SIDE_TYPE_U8:
612 case SIDE_TYPE_BYTE:
613 case SIDE_TYPE_U16:
614 case SIDE_TYPE_U32:
615 case SIDE_TYPE_U64:
616 case SIDE_TYPE_ARRAY:
617 case SIDE_TYPE_VLA:
618 break;
619 default:
620 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
621 abort();
622 break;
623 }
624 break;
625
626 default:
627 if (type_desc->type != item->type) {
628 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
629 abort();
630 }
631 break;
632 }
633
634 if (type_desc->type == SIDE_TYPE_ENUM || type_desc->type == SIDE_TYPE_ENUM_BITMAP)
635 type = type_desc->type;
636 else
637 type = item->type;
638
639 switch (type) {
640 case SIDE_TYPE_U8:
641 case SIDE_TYPE_U16:
642 case SIDE_TYPE_U32:
643 case SIDE_TYPE_U64:
644 case SIDE_TYPE_S8:
645 case SIDE_TYPE_S16:
646 case SIDE_TYPE_S32:
647 case SIDE_TYPE_S64:
648 base = get_attr_display_base(type_desc->u.side_basic.attr,
649 type_desc->u.side_basic.nr_attr);
650 break;
651 default:
652 break;
653 }
654
655 printf("{ ");
656 switch (type) {
657 case SIDE_TYPE_BOOL:
658 tracer_print_basic_type_header(type_desc);
659 printf("%s", item->u.side_bool ? "true" : "false");
660 break;
661 case SIDE_TYPE_U8:
662 {
663 uint8_t v;
664
665 v = item->u.side_u8;
666 tracer_print_basic_type_header(type_desc);
667 switch (base) {
668 case TRACER_DISPLAY_BASE_2:
669 print_integer_binary(v, 8);
670 break;
671 case TRACER_DISPLAY_BASE_8:
672 printf("0%" PRIo8, v);
673 break;
674 case TRACER_DISPLAY_BASE_10:
675 printf("%" PRIu8, v);
676 break;
677 case TRACER_DISPLAY_BASE_16:
678 printf("0x%" PRIx8, v);
679 break;
680 default:
681 abort();
682 }
683 break;
684 }
685 case SIDE_TYPE_U16:
686 {
687 uint16_t v;
688
689 v = item->u.side_u16;
690 if (type_to_host_reverse_bo(type_desc))
691 v = side_bswap_16(v);
692 tracer_print_basic_type_header(type_desc);
693 switch (base) {
694 case TRACER_DISPLAY_BASE_2:
695 print_integer_binary(v, 16);
696 break;
697 case TRACER_DISPLAY_BASE_8:
698 printf("0%" PRIo16, v);
699 break;
700 case TRACER_DISPLAY_BASE_10:
701 printf("%" PRIu16, v);
702 break;
703 case TRACER_DISPLAY_BASE_16:
704 printf("0x%" PRIx16, v);
705 break;
706 default:
707 abort();
708 }
709 break;
710 }
711 case SIDE_TYPE_U32:
712 {
713 uint32_t v;
714
715 v = item->u.side_u32;
716 if (type_to_host_reverse_bo(type_desc))
717 v = side_bswap_32(v);
718 tracer_print_basic_type_header(type_desc);
719 switch (base) {
720 case TRACER_DISPLAY_BASE_2:
721 print_integer_binary(v, 32);
722 break;
723 case TRACER_DISPLAY_BASE_8:
724 printf("0%" PRIo32, v);
725 break;
726 case TRACER_DISPLAY_BASE_10:
727 printf("%" PRIu32, v);
728 break;
729 case TRACER_DISPLAY_BASE_16:
730 printf("0x%" PRIx32, v);
731 break;
732 default:
733 abort();
734 }
735 break;
736 }
737 case SIDE_TYPE_U64:
738 {
739 uint64_t v;
740
741 v = item->u.side_u64;
742 if (type_to_host_reverse_bo(type_desc))
743 v = side_bswap_64(v);
744 tracer_print_basic_type_header(type_desc);
745 switch (base) {
746 case TRACER_DISPLAY_BASE_2:
747 print_integer_binary(v, 64);
748 break;
749 case TRACER_DISPLAY_BASE_8:
750 printf("0%" PRIo64, v);
751 break;
752 case TRACER_DISPLAY_BASE_10:
753 printf("%" PRIu64, v);
754 break;
755 case TRACER_DISPLAY_BASE_16:
756 printf("0x%" PRIx64, v);
757 break;
758 default:
759 abort();
760 }
761 break;
762 }
763 case SIDE_TYPE_S8:
764 {
765 int8_t v;
766
767 v = item->u.side_s8;
768 tracer_print_basic_type_header(type_desc);
769 switch (base) {
770 case TRACER_DISPLAY_BASE_2:
771 print_integer_binary(v, 8);
772 break;
773 case TRACER_DISPLAY_BASE_8:
774 printf("0%" PRIo8, v);
775 break;
776 case TRACER_DISPLAY_BASE_10:
777 printf("%" PRId8, v);
778 break;
779 case TRACER_DISPLAY_BASE_16:
780 printf("0x%" PRIx8, v);
781 break;
782 default:
783 abort();
784 }
785 break;
786 }
787 case SIDE_TYPE_S16:
788 {
789 int16_t v;
790
791 v = item->u.side_s16;
792 if (type_to_host_reverse_bo(type_desc))
793 v = side_bswap_16(v);
794 tracer_print_basic_type_header(type_desc);
795 switch (base) {
796 case TRACER_DISPLAY_BASE_2:
797 print_integer_binary(v, 16);
798 break;
799 case TRACER_DISPLAY_BASE_8:
800 printf("0%" PRIo16, v);
801 break;
802 case TRACER_DISPLAY_BASE_10:
803 printf("%" PRId16, v);
804 break;
805 case TRACER_DISPLAY_BASE_16:
806 printf("0x%" PRIx16, v);
807 break;
808 default:
809 abort();
810 }
811 break;
812 }
813 case SIDE_TYPE_S32:
814 {
815 int32_t v;
816
817 v = item->u.side_s32;
818 if (type_to_host_reverse_bo(type_desc))
819 v = side_bswap_32(v);
820 tracer_print_basic_type_header(type_desc);
821 switch (base) {
822 case TRACER_DISPLAY_BASE_2:
823 print_integer_binary(v, 32);
824 break;
825 case TRACER_DISPLAY_BASE_8:
826 printf("0%" PRIo32, v);
827 break;
828 case TRACER_DISPLAY_BASE_10:
829 printf("%" PRId32, v);
830 break;
831 case TRACER_DISPLAY_BASE_16:
832 printf("0x%" PRIx32, v);
833 break;
834 default:
835 abort();
836 }
837 break;
838 }
839 case SIDE_TYPE_S64:
840 {
841 int64_t v;
842
843 v = item->u.side_s64;
844 if (type_to_host_reverse_bo(type_desc))
845 v = side_bswap_64(v);
846 tracer_print_basic_type_header(type_desc);
847 switch (base) {
848 case TRACER_DISPLAY_BASE_2:
849 print_integer_binary(v, 64);
850 break;
851 case TRACER_DISPLAY_BASE_8:
852 printf("0%" PRIo64, v);
853 break;
854 case TRACER_DISPLAY_BASE_10:
855 printf("%" PRId64, v);
856 break;
857 case TRACER_DISPLAY_BASE_16:
858 printf("0x%" PRIx64, v);
859 break;
860 default:
861 abort();
862 }
863 break;
864 }
865 case SIDE_TYPE_POINTER32:
866 {
867 uint32_t v;
868
869 v = item->u.side_u32;
870 if (type_to_host_reverse_bo(type_desc))
871 v = side_bswap_32(v);
872 tracer_print_basic_type_header(type_desc);
873 printf("0x%" PRIx32, v);
874 break;
875 }
876 case SIDE_TYPE_POINTER64:
877 {
878 uint64_t v;
879
880 v = item->u.side_u64;
881 if (type_to_host_reverse_bo(type_desc))
882 v = side_bswap_64(v);
883 tracer_print_basic_type_header(type_desc);
884 printf("0x%" PRIx64, v);
885 break;
886 }
887 case SIDE_TYPE_BYTE:
888 tracer_print_basic_type_header(type_desc);
889 printf("0x%" PRIx8, item->u.side_byte);
890 break;
891
892 case SIDE_TYPE_ENUM:
893 print_enum(type_desc, item);
894 break;
895
896 case SIDE_TYPE_ENUM_BITMAP:
897 print_enum_bitmap(type_desc, item);
898 break;
899
900 case SIDE_TYPE_FLOAT_BINARY16:
901 {
902 #if __HAVE_FLOAT16
903 union {
904 _Float16 f;
905 uint16_t u;
906 } float16 = {
907 .f = item->u.side_float_binary16,
908 };
909
910 if (type_to_host_reverse_bo(type_desc))
911 float16.u = side_bswap_16(float16.u);
912 tracer_print_basic_type_header(type_desc);
913 printf("%g", (double) float16.f);
914 break;
915 #else
916 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
917 abort();
918 #endif
919 }
920 case SIDE_TYPE_FLOAT_BINARY32:
921 {
922 #if __HAVE_FLOAT32
923 union {
924 _Float32 f;
925 uint32_t u;
926 } float32 = {
927 .f = item->u.side_float_binary32,
928 };
929
930 if (type_to_host_reverse_bo(type_desc))
931 float32.u = side_bswap_32(float32.u);
932 tracer_print_basic_type_header(type_desc);
933 printf("%g", (double) float32.f);
934 break;
935 #else
936 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
937 abort();
938 #endif
939 }
940 case SIDE_TYPE_FLOAT_BINARY64:
941 {
942 #if __HAVE_FLOAT64
943 union {
944 _Float64 f;
945 uint64_t u;
946 } float64 = {
947 .f = item->u.side_float_binary64,
948 };
949
950 if (type_to_host_reverse_bo(type_desc))
951 float64.u = side_bswap_64(float64.u);
952 tracer_print_basic_type_header(type_desc);
953 printf("%g", (double) float64.f);
954 break;
955 #else
956 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
957 abort();
958 #endif
959 }
960 case SIDE_TYPE_FLOAT_BINARY128:
961 {
962 #if __HAVE_FLOAT128
963 union {
964 _Float128 f;
965 char arr[16];
966 } float128 = {
967 .f = item->u.side_float_binary128,
968 };
969
970 if (type_to_host_reverse_bo(type_desc))
971 side_bswap_128p(float128.arr);
972 tracer_print_basic_type_header(type_desc);
973 printf("%Lg", (long double) float128.f);
974 break;
975 #else
976 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
977 abort();
978 #endif
979 }
980 case SIDE_TYPE_STRING:
981 tracer_print_basic_type_header(type_desc);
982 printf("\"%s\"", (const char *)(uintptr_t) item->u.string);
983 break;
984 case SIDE_TYPE_STRUCT:
985 tracer_print_struct(type_desc, item->u.side_struct);
986 break;
987 case SIDE_TYPE_ARRAY:
988 tracer_print_array(type_desc, item->u.side_array);
989 break;
990 case SIDE_TYPE_VLA:
991 tracer_print_vla(type_desc, item->u.side_vla);
992 break;
993 case SIDE_TYPE_VLA_VISITOR:
994 tracer_print_vla_visitor(type_desc, item->u.side_vla_app_visitor_ctx);
995 break;
996 case SIDE_TYPE_ARRAY_U8:
997 case SIDE_TYPE_ARRAY_U16:
998 case SIDE_TYPE_ARRAY_U32:
999 case SIDE_TYPE_ARRAY_U64:
1000 case SIDE_TYPE_ARRAY_S8:
1001 case SIDE_TYPE_ARRAY_S16:
1002 case SIDE_TYPE_ARRAY_S32:
1003 case SIDE_TYPE_ARRAY_S64:
1004 case SIDE_TYPE_ARRAY_BYTE:
1005 case SIDE_TYPE_ARRAY_POINTER32:
1006 case SIDE_TYPE_ARRAY_POINTER64:
1007 tracer_print_array_fixint(type_desc, item);
1008 break;
1009 case SIDE_TYPE_VLA_U8:
1010 case SIDE_TYPE_VLA_U16:
1011 case SIDE_TYPE_VLA_U32:
1012 case SIDE_TYPE_VLA_U64:
1013 case SIDE_TYPE_VLA_S8:
1014 case SIDE_TYPE_VLA_S16:
1015 case SIDE_TYPE_VLA_S32:
1016 case SIDE_TYPE_VLA_S64:
1017 case SIDE_TYPE_VLA_BYTE:
1018 case SIDE_TYPE_VLA_POINTER32:
1019 case SIDE_TYPE_VLA_POINTER64:
1020 tracer_print_vla_fixint(type_desc, item);
1021 break;
1022 case SIDE_TYPE_DYNAMIC:
1023 tracer_print_basic_type_header(type_desc);
1024 tracer_print_dynamic(&item->u.dynamic);
1025 break;
1026 default:
1027 fprintf(stderr, "<UNKNOWN TYPE>");
1028 abort();
1029 }
1030 printf(" }");
1031 }
1032
1033 static
1034 void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg_vec *item)
1035 {
1036 printf("%s: ", item_desc->field_name);
1037 tracer_print_type(&item_desc->side_type, item);
1038 }
1039
1040 static
1041 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
1042 {
1043 const struct side_arg_vec *sav = sav_desc->sav;
1044 uint32_t side_sav_len = sav_desc->len;
1045 int i;
1046
1047 if (type_desc->u.side_struct->nr_fields != side_sav_len) {
1048 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n");
1049 abort();
1050 }
1051 print_attributes("attr", ":", type_desc->u.side_struct->attr, type_desc->u.side_struct->nr_attr);
1052 printf("%s", type_desc->u.side_struct->nr_attr ? ", " : "");
1053 printf("fields: { ");
1054 for (i = 0; i < side_sav_len; i++) {
1055 printf("%s", i ? ", " : "");
1056 tracer_print_field(&type_desc->u.side_struct->fields[i], &sav[i]);
1057 }
1058 printf(" }");
1059 }
1060
1061 static
1062 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
1063 {
1064 const struct side_arg_vec *sav = sav_desc->sav;
1065 uint32_t side_sav_len = sav_desc->len;
1066 int i;
1067
1068 if (type_desc->u.side_array.length != side_sav_len) {
1069 fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n");
1070 abort();
1071 }
1072 print_attributes("attr", ":", type_desc->u.side_array.attr, type_desc->u.side_array.nr_attr);
1073 printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
1074 printf("elements: ");
1075 printf("[ ");
1076 for (i = 0; i < side_sav_len; i++) {
1077 printf("%s", i ? ", " : "");
1078 tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
1079 }
1080 printf(" ]");
1081 }
1082
1083 static
1084 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
1085 {
1086 const struct side_arg_vec *sav = sav_desc->sav;
1087 uint32_t side_sav_len = sav_desc->len;
1088 int i;
1089
1090 print_attributes("attr", ":", type_desc->u.side_vla.attr, type_desc->u.side_vla.nr_attr);
1091 printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
1092 printf("elements: ");
1093 printf("[ ");
1094 for (i = 0; i < side_sav_len; i++) {
1095 printf("%s", i ? ", " : "");
1096 tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
1097 }
1098 printf(" ]");
1099 }
1100
1101 struct tracer_visitor_priv {
1102 const struct side_type_description *elem_type;
1103 int i;
1104 };
1105
1106 static
1107 enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx,
1108 const struct side_arg_vec *elem)
1109 {
1110 struct tracer_visitor_priv *tracer_priv = tracer_ctx->priv;
1111
1112 printf("%s", tracer_priv->i++ ? ", " : "");
1113 tracer_print_type(tracer_priv->elem_type, elem);
1114 return SIDE_VISITOR_STATUS_OK;
1115 }
1116
1117 static
1118 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx)
1119 {
1120 enum side_visitor_status status;
1121 struct tracer_visitor_priv tracer_priv = {
1122 .elem_type = type_desc->u.side_vla_visitor.elem_type,
1123 .i = 0,
1124 };
1125 const struct side_tracer_visitor_ctx tracer_ctx = {
1126 .write_elem = tracer_write_elem_cb,
1127 .priv = &tracer_priv,
1128 };
1129
1130 print_attributes("attr", ":", type_desc->u.side_vla_visitor.attr, type_desc->u.side_vla_visitor.nr_attr);
1131 printf("%s", type_desc->u.side_vla_visitor.nr_attr ? ", " : "");
1132 printf("elements: ");
1133 printf("[ ");
1134 status = type_desc->u.side_vla_visitor.visitor(&tracer_ctx, app_ctx);
1135 switch (status) {
1136 case SIDE_VISITOR_STATUS_OK:
1137 break;
1138 case SIDE_VISITOR_STATUS_ERROR:
1139 fprintf(stderr, "ERROR: Visitor error\n");
1140 abort();
1141 }
1142 printf(" ]");
1143 }
1144
1145 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
1146 {
1147 const struct side_type_description *elem_type = type_desc->u.side_array.elem_type;
1148 uint32_t side_sav_len = type_desc->u.side_array.length;
1149 void *p = item->u.side_array_fixint;
1150 enum side_type side_type;
1151 int i;
1152
1153 print_attributes("attr", ":", type_desc->u.side_array.attr, type_desc->u.side_array.nr_attr);
1154 printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
1155 printf("elements: ");
1156 switch (item->type) {
1157 case SIDE_TYPE_ARRAY_U8:
1158 if (elem_type->type != SIDE_TYPE_U8)
1159 goto type_error;
1160 break;
1161 case SIDE_TYPE_ARRAY_U16:
1162 if (elem_type->type != SIDE_TYPE_U16)
1163 goto type_error;
1164 break;
1165 case SIDE_TYPE_ARRAY_U32:
1166 if (elem_type->type != SIDE_TYPE_U32)
1167 goto type_error;
1168 break;
1169 case SIDE_TYPE_ARRAY_U64:
1170 if (elem_type->type != SIDE_TYPE_U64)
1171 goto type_error;
1172 break;
1173 case SIDE_TYPE_ARRAY_S8:
1174 if (elem_type->type != SIDE_TYPE_S8)
1175 goto type_error;
1176 break;
1177 case SIDE_TYPE_ARRAY_S16:
1178 if (elem_type->type != SIDE_TYPE_S16)
1179 goto type_error;
1180 break;
1181 case SIDE_TYPE_ARRAY_S32:
1182 if (elem_type->type != SIDE_TYPE_S32)
1183 goto type_error;
1184 break;
1185 case SIDE_TYPE_ARRAY_S64:
1186 if (elem_type->type != SIDE_TYPE_S64)
1187 goto type_error;
1188 break;
1189 case SIDE_TYPE_ARRAY_BYTE:
1190 if (elem_type->type != SIDE_TYPE_BYTE)
1191 goto type_error;
1192 break;
1193 case SIDE_TYPE_ARRAY_POINTER32:
1194 if (elem_type->type != SIDE_TYPE_POINTER32)
1195 goto type_error;
1196 case SIDE_TYPE_ARRAY_POINTER64:
1197 if (elem_type->type != SIDE_TYPE_POINTER64)
1198 goto type_error;
1199 break;
1200 default:
1201 goto type_error;
1202 }
1203 side_type = elem_type->type;
1204
1205 printf("[ ");
1206 for (i = 0; i < side_sav_len; i++) {
1207 struct side_arg_vec sav_elem = {
1208 .type = side_type,
1209 };
1210
1211 switch (side_type) {
1212 case SIDE_TYPE_U8:
1213 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
1214 break;
1215 case SIDE_TYPE_S8:
1216 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
1217 break;
1218 case SIDE_TYPE_U16:
1219 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
1220 break;
1221 case SIDE_TYPE_S16:
1222 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
1223 break;
1224 case SIDE_TYPE_U32:
1225 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
1226 break;
1227 case SIDE_TYPE_S32:
1228 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
1229 break;
1230 case SIDE_TYPE_U64:
1231 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
1232 break;
1233 case SIDE_TYPE_S64:
1234 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
1235 break;
1236 case SIDE_TYPE_BYTE:
1237 sav_elem.u.side_byte = ((const uint8_t *) p)[i];
1238 break;
1239 case SIDE_TYPE_POINTER32:
1240 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
1241 break;
1242 case SIDE_TYPE_POINTER64:
1243 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
1244 break;
1245
1246 default:
1247 fprintf(stderr, "ERROR: Unexpected type\n");
1248 abort();
1249 }
1250
1251 printf("%s", i ? ", " : "");
1252 tracer_print_type(elem_type, &sav_elem);
1253 }
1254 printf(" ]");
1255 return;
1256
1257 type_error:
1258 fprintf(stderr, "ERROR: type mismatch\n");
1259 abort();
1260 }
1261
1262 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
1263 {
1264 const struct side_type_description *elem_type = type_desc->u.side_vla.elem_type;
1265 uint32_t side_sav_len = item->u.side_vla_fixint.length;
1266 void *p = item->u.side_vla_fixint.p;
1267 enum side_type side_type;
1268 int i;
1269
1270 print_attributes("attr", ":", type_desc->u.side_vla.attr, type_desc->u.side_vla.nr_attr);
1271 printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
1272 printf("elements: ");
1273 switch (item->type) {
1274 case SIDE_TYPE_VLA_U8:
1275 if (elem_type->type != SIDE_TYPE_U8)
1276 goto type_error;
1277 break;
1278 case SIDE_TYPE_VLA_U16:
1279 if (elem_type->type != SIDE_TYPE_U16)
1280 goto type_error;
1281 break;
1282 case SIDE_TYPE_VLA_U32:
1283 if (elem_type->type != SIDE_TYPE_U32)
1284 goto type_error;
1285 break;
1286 case SIDE_TYPE_VLA_U64:
1287 if (elem_type->type != SIDE_TYPE_U64)
1288 goto type_error;
1289 break;
1290 case SIDE_TYPE_VLA_S8:
1291 if (elem_type->type != SIDE_TYPE_S8)
1292 goto type_error;
1293 break;
1294 case SIDE_TYPE_VLA_S16:
1295 if (elem_type->type != SIDE_TYPE_S16)
1296 goto type_error;
1297 break;
1298 case SIDE_TYPE_VLA_S32:
1299 if (elem_type->type != SIDE_TYPE_S32)
1300 goto type_error;
1301 break;
1302 case SIDE_TYPE_VLA_S64:
1303 if (elem_type->type != SIDE_TYPE_S64)
1304 goto type_error;
1305 break;
1306 case SIDE_TYPE_VLA_BYTE:
1307 if (elem_type->type != SIDE_TYPE_BYTE)
1308 goto type_error;
1309 break;
1310 case SIDE_TYPE_VLA_POINTER32:
1311 if (elem_type->type != SIDE_TYPE_POINTER32)
1312 goto type_error;
1313 case SIDE_TYPE_VLA_POINTER64:
1314 if (elem_type->type != SIDE_TYPE_POINTER64)
1315 goto type_error;
1316 break;
1317 default:
1318 goto type_error;
1319 }
1320 side_type = elem_type->type;
1321
1322 printf("[ ");
1323 for (i = 0; i < side_sav_len; i++) {
1324 struct side_arg_vec sav_elem = {
1325 .type = side_type,
1326 };
1327
1328 switch (side_type) {
1329 case SIDE_TYPE_U8:
1330 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
1331 break;
1332 case SIDE_TYPE_S8:
1333 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
1334 break;
1335 case SIDE_TYPE_U16:
1336 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
1337 break;
1338 case SIDE_TYPE_S16:
1339 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
1340 break;
1341 case SIDE_TYPE_U32:
1342 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
1343 break;
1344 case SIDE_TYPE_S32:
1345 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
1346 break;
1347 case SIDE_TYPE_U64:
1348 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
1349 break;
1350 case SIDE_TYPE_S64:
1351 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
1352 break;
1353 case SIDE_TYPE_BYTE:
1354 sav_elem.u.side_byte = ((const uint8_t *) p)[i];
1355 break;
1356 case SIDE_TYPE_POINTER32:
1357 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
1358 break;
1359 case SIDE_TYPE_POINTER64:
1360 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
1361 break;
1362
1363 default:
1364 fprintf(stderr, "ERROR: Unexpected type\n");
1365 abort();
1366 }
1367
1368 printf("%s", i ? ", " : "");
1369 tracer_print_type(elem_type, &sav_elem);
1370 }
1371 printf(" ]");
1372 return;
1373
1374 type_error:
1375 fprintf(stderr, "ERROR: type mismatch\n");
1376 abort();
1377 }
1378
1379 static
1380 void tracer_print_dynamic_struct(const struct side_arg_dynamic_event_struct *dynamic_struct)
1381 {
1382 const struct side_arg_dynamic_event_field *fields = dynamic_struct->fields;
1383 uint32_t len = dynamic_struct->len;
1384 int i;
1385
1386 print_attributes("attr", "::", dynamic_struct->attr, dynamic_struct->nr_attr);
1387 printf("%s", dynamic_struct->nr_attr ? ", " : "");
1388 printf("fields:: ");
1389 printf("[ ");
1390 for (i = 0; i < len; i++) {
1391 printf("%s", i ? ", " : "");
1392 printf("%s:: ", fields[i].field_name);
1393 tracer_print_dynamic(&fields[i].elem);
1394 }
1395 printf(" ]");
1396 }
1397
1398 struct tracer_dynamic_struct_visitor_priv {
1399 int i;
1400 };
1401
1402 static
1403 enum side_visitor_status tracer_dynamic_struct_write_elem_cb(
1404 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
1405 const struct side_arg_dynamic_event_field *dynamic_field)
1406 {
1407 struct tracer_dynamic_struct_visitor_priv *tracer_priv = tracer_ctx->priv;
1408
1409 printf("%s", tracer_priv->i++ ? ", " : "");
1410 printf("%s:: ", dynamic_field->field_name);
1411 tracer_print_dynamic(&dynamic_field->elem);
1412 return SIDE_VISITOR_STATUS_OK;
1413 }
1414
1415 static
1416 void tracer_print_dynamic_struct_visitor(const struct side_arg_dynamic_vec *item)
1417 {
1418 enum side_visitor_status status;
1419 struct tracer_dynamic_struct_visitor_priv tracer_priv = {
1420 .i = 0,
1421 };
1422 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = {
1423 .write_field = tracer_dynamic_struct_write_elem_cb,
1424 .priv = &tracer_priv,
1425 };
1426 void *app_ctx = item->u.side_dynamic_struct_visitor.app_ctx;
1427
1428 print_attributes("attr", "::", item->u.side_dynamic_struct_visitor.attr, item->u.side_dynamic_struct_visitor.nr_attr);
1429 printf("%s", item->u.side_dynamic_struct_visitor.nr_attr ? ", " : "");
1430 printf("fields:: ");
1431 printf("[ ");
1432 status = item->u.side_dynamic_struct_visitor.visitor(&tracer_ctx, app_ctx);
1433 switch (status) {
1434 case SIDE_VISITOR_STATUS_OK:
1435 break;
1436 case SIDE_VISITOR_STATUS_ERROR:
1437 fprintf(stderr, "ERROR: Visitor error\n");
1438 abort();
1439 }
1440 printf(" ]");
1441 }
1442
1443 static
1444 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vec_vla *vla)
1445 {
1446 const struct side_arg_dynamic_vec *sav = vla->sav;
1447 uint32_t side_sav_len = vla->len;
1448 int i;
1449
1450 print_attributes("attr", "::", vla->attr, vla->nr_attr);
1451 printf("%s", vla->nr_attr ? ", " : "");
1452 printf("elements:: ");
1453 printf("[ ");
1454 for (i = 0; i < side_sav_len; i++) {
1455 printf("%s", i ? ", " : "");
1456 tracer_print_dynamic(&sav[i]);
1457 }
1458 printf(" ]");
1459 }
1460
1461 struct tracer_dynamic_vla_visitor_priv {
1462 int i;
1463 };
1464
1465 static
1466 enum side_visitor_status tracer_dynamic_vla_write_elem_cb(
1467 const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
1468 const struct side_arg_dynamic_vec *elem)
1469 {
1470 struct tracer_dynamic_vla_visitor_priv *tracer_priv = tracer_ctx->priv;
1471
1472 printf("%s", tracer_priv->i++ ? ", " : "");
1473 tracer_print_dynamic(elem);
1474 return SIDE_VISITOR_STATUS_OK;
1475 }
1476
1477 static
1478 void tracer_print_dynamic_vla_visitor(const struct side_arg_dynamic_vec *item)
1479 {
1480 enum side_visitor_status status;
1481 struct tracer_dynamic_vla_visitor_priv tracer_priv = {
1482 .i = 0,
1483 };
1484 const struct side_tracer_dynamic_vla_visitor_ctx tracer_ctx = {
1485 .write_elem = tracer_dynamic_vla_write_elem_cb,
1486 .priv = &tracer_priv,
1487 };
1488 void *app_ctx = item->u.side_dynamic_vla_visitor.app_ctx;
1489
1490 print_attributes("attr", "::", item->u.side_dynamic_vla_visitor.attr, item->u.side_dynamic_vla_visitor.nr_attr);
1491 printf("%s", item->u.side_dynamic_vla_visitor.nr_attr ? ", " : "");
1492 printf("elements:: ");
1493 printf("[ ");
1494 status = item->u.side_dynamic_vla_visitor.visitor(&tracer_ctx, app_ctx);
1495 switch (status) {
1496 case SIDE_VISITOR_STATUS_OK:
1497 break;
1498 case SIDE_VISITOR_STATUS_ERROR:
1499 fprintf(stderr, "ERROR: Visitor error\n");
1500 abort();
1501 }
1502 printf(" ]");
1503 }
1504
1505 static
1506 void tracer_print_dynamic_basic_type_header(const struct side_arg_dynamic_vec *item)
1507 {
1508 print_attributes("attr", "::", item->u.side_basic.attr, item->u.side_basic.nr_attr);
1509 printf("%s", item->u.side_basic.nr_attr ? ", " : "");
1510 printf("value:: ");
1511 }
1512
1513 static
1514 void tracer_print_dynamic(const struct side_arg_dynamic_vec *item)
1515 {
1516 enum tracer_display_base base = TRACER_DISPLAY_BASE_10;
1517
1518 switch (item->dynamic_type) {
1519 case SIDE_DYNAMIC_TYPE_U8:
1520 case SIDE_DYNAMIC_TYPE_U16:
1521 case SIDE_DYNAMIC_TYPE_U32:
1522 case SIDE_DYNAMIC_TYPE_U64:
1523 case SIDE_DYNAMIC_TYPE_S8:
1524 case SIDE_DYNAMIC_TYPE_S16:
1525 case SIDE_DYNAMIC_TYPE_S32:
1526 case SIDE_DYNAMIC_TYPE_S64:
1527 base = get_attr_display_base(item->u.side_basic.attr,
1528 item->u.side_basic.nr_attr);
1529 break;
1530 default:
1531 break;
1532 }
1533
1534
1535 printf("{ ");
1536 switch (item->dynamic_type) {
1537 case SIDE_DYNAMIC_TYPE_NULL:
1538 tracer_print_dynamic_basic_type_header(item);
1539 printf("<NULL TYPE>");
1540 break;
1541 case SIDE_DYNAMIC_TYPE_BOOL:
1542 tracer_print_dynamic_basic_type_header(item);
1543 printf("%s", item->u.side_basic.u.side_bool ? "true" : "false");
1544 break;
1545 case SIDE_DYNAMIC_TYPE_U8:
1546 {
1547 uint8_t v;
1548
1549 v = item->u.side_basic.u.side_u8;
1550 tracer_print_dynamic_basic_type_header(item);
1551 switch (base) {
1552 case TRACER_DISPLAY_BASE_2:
1553 print_integer_binary(v, 8);
1554 break;
1555 case TRACER_DISPLAY_BASE_8:
1556 printf("0%" PRIo8, v);
1557 break;
1558 case TRACER_DISPLAY_BASE_10:
1559 printf("%" PRIu8, v);
1560 break;
1561 case TRACER_DISPLAY_BASE_16:
1562 printf("0x%" PRIx8, v);
1563 break;
1564 default:
1565 abort();
1566 }
1567 break;
1568 }
1569 case SIDE_DYNAMIC_TYPE_U16:
1570 {
1571 uint16_t v;
1572
1573 v = item->u.side_basic.u.side_u16;
1574 if (dynamic_type_to_host_reverse_bo(item))
1575 v = side_bswap_16(v);
1576 tracer_print_dynamic_basic_type_header(item);
1577 switch (base) {
1578 case TRACER_DISPLAY_BASE_2:
1579 print_integer_binary(v, 16);
1580 break;
1581 case TRACER_DISPLAY_BASE_8:
1582 printf("0%" PRIo16, v);
1583 break;
1584 case TRACER_DISPLAY_BASE_10:
1585 printf("%" PRIu16, v);
1586 break;
1587 case TRACER_DISPLAY_BASE_16:
1588 printf("0x%" PRIx16, v);
1589 break;
1590 default:
1591 abort();
1592 }
1593 break;
1594 }
1595 case SIDE_DYNAMIC_TYPE_U32:
1596 {
1597 uint32_t v;
1598
1599 v = item->u.side_basic.u.side_u32;
1600 if (dynamic_type_to_host_reverse_bo(item))
1601 v = side_bswap_32(v);
1602 tracer_print_dynamic_basic_type_header(item);
1603 switch (base) {
1604 case TRACER_DISPLAY_BASE_2:
1605 print_integer_binary(v, 32);
1606 break;
1607 case TRACER_DISPLAY_BASE_8:
1608 printf("0%" PRIo32, v);
1609 break;
1610 case TRACER_DISPLAY_BASE_10:
1611 printf("%" PRIu32, v);
1612 break;
1613 case TRACER_DISPLAY_BASE_16:
1614 printf("0x%" PRIx32, v);
1615 break;
1616 default:
1617 abort();
1618 }
1619 break;
1620 }
1621 case SIDE_DYNAMIC_TYPE_U64:
1622 {
1623 uint64_t v;
1624
1625 v = item->u.side_basic.u.side_u64;
1626 if (dynamic_type_to_host_reverse_bo(item))
1627 v = side_bswap_64(v);
1628 tracer_print_dynamic_basic_type_header(item);
1629 switch (base) {
1630 case TRACER_DISPLAY_BASE_2:
1631 print_integer_binary(v, 64);
1632 break;
1633 case TRACER_DISPLAY_BASE_8:
1634 printf("0%" PRIo64, v);
1635 break;
1636 case TRACER_DISPLAY_BASE_10:
1637 printf("%" PRIu64, v);
1638 break;
1639 case TRACER_DISPLAY_BASE_16:
1640 printf("0x%" PRIx64, v);
1641 break;
1642 default:
1643 abort();
1644 }
1645 break;
1646 }
1647 case SIDE_DYNAMIC_TYPE_S8:
1648 {
1649 int8_t v;
1650
1651 v = item->u.side_basic.u.side_s8;
1652 tracer_print_dynamic_basic_type_header(item);
1653 switch (base) {
1654 case TRACER_DISPLAY_BASE_2:
1655 print_integer_binary(v, 8);
1656 break;
1657 case TRACER_DISPLAY_BASE_8:
1658 printf("0%" PRIo8, v);
1659 break;
1660 case TRACER_DISPLAY_BASE_10:
1661 printf("%" PRId8, v);
1662 break;
1663 case TRACER_DISPLAY_BASE_16:
1664 printf("0x%" PRIx8, v);
1665 break;
1666 default:
1667 abort();
1668 }
1669 break;
1670 }
1671 case SIDE_DYNAMIC_TYPE_S16:
1672 {
1673 int16_t v;
1674
1675 v = item->u.side_basic.u.side_u16;
1676 if (dynamic_type_to_host_reverse_bo(item))
1677 v = side_bswap_16(v);
1678 tracer_print_dynamic_basic_type_header(item);
1679 switch (base) {
1680 case TRACER_DISPLAY_BASE_2:
1681 print_integer_binary(v, 16);
1682 break;
1683 case TRACER_DISPLAY_BASE_8:
1684 printf("0%" PRIo16, v);
1685 break;
1686 case TRACER_DISPLAY_BASE_10:
1687 printf("%" PRId16, v);
1688 break;
1689 case TRACER_DISPLAY_BASE_16:
1690 printf("0x%" PRIx16, v);
1691 break;
1692 default:
1693 abort();
1694 }
1695 break;
1696 }
1697 case SIDE_DYNAMIC_TYPE_S32:
1698 {
1699 int32_t v;
1700
1701 v = item->u.side_basic.u.side_u32;
1702 if (dynamic_type_to_host_reverse_bo(item))
1703 v = side_bswap_32(v);
1704 tracer_print_dynamic_basic_type_header(item);
1705 switch (base) {
1706 case TRACER_DISPLAY_BASE_2:
1707 print_integer_binary(v, 32);
1708 break;
1709 case TRACER_DISPLAY_BASE_8:
1710 printf("0%" PRIo32, v);
1711 break;
1712 case TRACER_DISPLAY_BASE_10:
1713 printf("%" PRId32, v);
1714 break;
1715 case TRACER_DISPLAY_BASE_16:
1716 printf("0x%" PRIx32, v);
1717 break;
1718 default:
1719 abort();
1720 }
1721 break;
1722 }
1723 case SIDE_DYNAMIC_TYPE_S64:
1724 {
1725 int64_t v;
1726
1727 v = item->u.side_basic.u.side_u64;
1728 if (dynamic_type_to_host_reverse_bo(item))
1729 v = side_bswap_64(v);
1730 tracer_print_dynamic_basic_type_header(item);
1731 switch (base) {
1732 case TRACER_DISPLAY_BASE_2:
1733 print_integer_binary(v, 64);
1734 break;
1735 case TRACER_DISPLAY_BASE_8:
1736 printf("0%" PRIo64, v);
1737 break;
1738 case TRACER_DISPLAY_BASE_10:
1739 printf("%" PRId64, v);
1740 break;
1741 case TRACER_DISPLAY_BASE_16:
1742 printf("0x%" PRIx64, v);
1743 break;
1744 default:
1745 abort();
1746 }
1747 break;
1748 }
1749 case SIDE_DYNAMIC_TYPE_BYTE:
1750 tracer_print_dynamic_basic_type_header(item);
1751 printf("0x%" PRIx8, item->u.side_basic.u.side_byte);
1752 break;
1753 case SIDE_DYNAMIC_TYPE_POINTER32:
1754 {
1755 uint32_t v;
1756
1757 v = item->u.side_basic.u.side_u32;
1758 if (dynamic_type_to_host_reverse_bo(item))
1759 v = side_bswap_32(v);
1760 tracer_print_dynamic_basic_type_header(item);
1761 printf("0x%" PRIx32, v);
1762 break;
1763 }
1764
1765 case SIDE_DYNAMIC_TYPE_POINTER64:
1766 {
1767 uint64_t v;
1768
1769 v = item->u.side_basic.u.side_u64;
1770 if (dynamic_type_to_host_reverse_bo(item))
1771 v = side_bswap_64(v);
1772 tracer_print_dynamic_basic_type_header(item);
1773 printf("0x%" PRIx64, v);
1774 break;
1775 }
1776
1777 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY16:
1778 {
1779 #if __HAVE_FLOAT16
1780 union {
1781 _Float16 f;
1782 uint16_t u;
1783 } float16 = {
1784 .f = item->u.side_basic.u.side_float_binary16,
1785 };
1786
1787 if (dynamic_type_to_host_reverse_bo(item))
1788 float16.u = side_bswap_16(float16.u);
1789 tracer_print_dynamic_basic_type_header(item);
1790 printf("%g", (double) float16.f);
1791 break;
1792 #else
1793 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
1794 abort();
1795 #endif
1796 }
1797 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY32:
1798 {
1799 #if __HAVE_FLOAT32
1800 union {
1801 _Float32 f;
1802 uint32_t u;
1803 } float32 = {
1804 .f = item->u.side_basic.u.side_float_binary32,
1805 };
1806
1807 if (dynamic_type_to_host_reverse_bo(item))
1808 float32.u = side_bswap_32(float32.u);
1809 tracer_print_dynamic_basic_type_header(item);
1810 printf("%g", (double) float32.f);
1811 break;
1812 #else
1813 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
1814 abort();
1815 #endif
1816 }
1817 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY64:
1818 {
1819 #if __HAVE_FLOAT64
1820 union {
1821 _Float64 f;
1822 uint64_t u;
1823 } float64 = {
1824 .f = item->u.side_basic.u.side_float_binary64,
1825 };
1826
1827 if (dynamic_type_to_host_reverse_bo(item))
1828 float64.u = side_bswap_64(float64.u);
1829 tracer_print_dynamic_basic_type_header(item);
1830 printf("%g", (double) float64.f);
1831 break;
1832 #else
1833 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
1834 abort();
1835 #endif
1836 }
1837 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY128:
1838 {
1839 #if __HAVE_FLOAT128
1840 union {
1841 _Float128 f;
1842 char arr[16];
1843 } float128 = {
1844 .f = item->u.side_basic.u.side_float_binary128,
1845 };
1846
1847 if (dynamic_type_to_host_reverse_bo(item))
1848 side_bswap_128p(float128.arr);
1849 tracer_print_dynamic_basic_type_header(item);
1850 printf("%Lg", (long double) float128.f);
1851 break;
1852 #else
1853 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
1854 abort();
1855 #endif
1856 }
1857 case SIDE_DYNAMIC_TYPE_STRING:
1858 tracer_print_dynamic_basic_type_header(item);
1859 printf("\"%s\"", (const char *)(uintptr_t) item->u.side_basic.u.string);
1860 break;
1861 case SIDE_DYNAMIC_TYPE_STRUCT:
1862 tracer_print_dynamic_struct(item->u.side_dynamic_struct);
1863 break;
1864 case SIDE_DYNAMIC_TYPE_STRUCT_VISITOR:
1865 tracer_print_dynamic_struct_visitor(item);
1866 break;
1867 case SIDE_DYNAMIC_TYPE_VLA:
1868 tracer_print_dynamic_vla(item->u.side_dynamic_vla);
1869 break;
1870 case SIDE_DYNAMIC_TYPE_VLA_VISITOR:
1871 tracer_print_dynamic_vla_visitor(item);
1872 break;
1873 default:
1874 fprintf(stderr, "<UNKNOWN TYPE>");
1875 abort();
1876 }
1877 printf(" }");
1878 }
1879
1880 static
1881 void tracer_print_static_fields(const struct side_event_description *desc,
1882 const struct side_arg_vec_description *sav_desc,
1883 int *nr_items)
1884 {
1885 const struct side_arg_vec *sav = sav_desc->sav;
1886 uint32_t side_sav_len = sav_desc->len;
1887 int i;
1888
1889 printf("provider: %s, event: %s", desc->provider_name, desc->event_name);
1890 if (desc->nr_fields != side_sav_len) {
1891 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n");
1892 abort();
1893 }
1894 print_attributes(", attr", ":", desc->attr, desc->nr_attr);
1895 printf("%s", side_sav_len ? ", fields: [ " : "");
1896 for (i = 0; i < side_sav_len; i++) {
1897 printf("%s", i ? ", " : "");
1898 tracer_print_field(&desc->fields[i], &sav[i]);
1899 }
1900 if (nr_items)
1901 *nr_items = i;
1902 if (side_sav_len)
1903 printf(" ]");
1904 }
1905
1906 void tracer_call(const struct side_event_description *desc,
1907 const struct side_arg_vec_description *sav_desc,
1908 void *priv __attribute__((unused)))
1909 {
1910 int nr_fields = 0;
1911
1912 tracer_print_static_fields(desc, sav_desc, &nr_fields);
1913 printf("\n");
1914 }
1915
1916 void tracer_call_variadic(const struct side_event_description *desc,
1917 const struct side_arg_vec_description *sav_desc,
1918 const struct side_arg_dynamic_event_struct *var_struct,
1919 void *priv __attribute__((unused)))
1920 {
1921 uint32_t var_struct_len = var_struct->len;
1922 int nr_fields = 0, i;
1923
1924 tracer_print_static_fields(desc, sav_desc, &nr_fields);
1925
1926 if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) {
1927 fprintf(stderr, "ERROR: unexpected non-variadic event description\n");
1928 abort();
1929 }
1930 print_attributes(", attr ", "::", var_struct->attr, var_struct->nr_attr);
1931 printf("%s", var_struct_len ? ", fields:: [ " : "");
1932 for (i = 0; i < var_struct_len; i++, nr_fields++) {
1933 printf("%s", i ? ", " : "");
1934 printf("%s:: ", var_struct->fields[i].field_name);
1935 tracer_print_dynamic(&var_struct->fields[i].elem);
1936 }
1937 if (i)
1938 printf(" ]");
1939 printf("\n");
1940 }
1941
1942 void tracer_event_notification(enum side_tracer_notification notif,
1943 struct side_event_description **events, uint32_t nr_events, void *priv)
1944 {
1945 uint32_t i;
1946 int ret;
1947
1948 printf("----------------------------------------------------------\n");
1949 printf("Tracer notified of events %s\n",
1950 notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS ? "inserted" : "removed");
1951 for (i = 0; i < nr_events; i++) {
1952 struct side_event_description *event = events[i];
1953
1954 /* Skip NULL pointers */
1955 if (!event)
1956 continue;
1957 printf("provider: %s, event: %s\n",
1958 event->provider_name, event->event_name);
1959 if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) {
1960 if (event->flags & SIDE_EVENT_FLAG_VARIADIC) {
1961 ret = side_tracer_callback_variadic_register(event, tracer_call_variadic, NULL);
1962 if (ret)
1963 abort();
1964 } else {
1965 ret = side_tracer_callback_register(event, tracer_call, NULL);
1966 if (ret)
1967 abort();
1968 }
1969 } else {
1970 if (event->flags & SIDE_EVENT_FLAG_VARIADIC) {
1971 ret = side_tracer_callback_variadic_unregister(event, tracer_call_variadic, NULL);
1972 if (ret)
1973 abort();
1974 } else {
1975 ret = side_tracer_callback_unregister(event, tracer_call, NULL);
1976 if (ret)
1977 abort();
1978 }
1979 }
1980 }
1981 printf("----------------------------------------------------------\n");
1982 }
1983
1984 static __attribute__((constructor))
1985 void tracer_init(void);
1986 static
1987 void tracer_init(void)
1988 {
1989 tracer_handle = side_tracer_event_notification_register(tracer_event_notification, NULL);
1990 if (!tracer_handle)
1991 abort();
1992 }
1993
1994 static __attribute__((destructor))
1995 void tracer_exit(void);
1996 static
1997 void tracer_exit(void)
1998 {
1999 side_tracer_event_notification_unregister(tracer_handle);
2000 }
This page took 0.100064 seconds and 5 git commands to generate.