Introduce tracer_load_integer_value
[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 union int64_value {
23 uint64_t u;
24 int64_t s;
25 };
26
27 static struct side_tracer_handle *tracer_handle;
28
29 static
30 void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
31 static
32 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
33 static
34 void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
35 static
36 void tracer_print_vla_visitor(const struct side_type *type_desc, void *app_ctx);
37 static
38 void tracer_print_dynamic(const struct side_arg *dynamic_item);
39 static
40 uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr);
41 static
42 uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr);
43 static
44 uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr,
45 enum tracer_display_base default_base);
46 static
47 uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr);
48 static
49 uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr);
50 static
51 uint32_t tracer_print_gather_array(const struct side_type_gather *type_gather, const void *_ptr);
52 static
53 uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, const void *_ptr,
54 const void *_length_ptr);
55 static
56 void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item);
57
58 static
59 int64_t get_attr_integer_value(const struct side_attr *attr)
60 {
61 int64_t val;
62
63 switch (attr->value.type) {
64 case SIDE_ATTR_TYPE_U8:
65 val = attr->value.u.integer_value.side_u8;
66 break;
67 case SIDE_ATTR_TYPE_U16:
68 val = attr->value.u.integer_value.side_u16;
69 break;
70 case SIDE_ATTR_TYPE_U32:
71 val = attr->value.u.integer_value.side_u32;
72 break;
73 case SIDE_ATTR_TYPE_U64:
74 val = attr->value.u.integer_value.side_u64;
75 break;
76 case SIDE_ATTR_TYPE_S8:
77 val = attr->value.u.integer_value.side_s8;
78 break;
79 case SIDE_ATTR_TYPE_S16:
80 val = attr->value.u.integer_value.side_s16;
81 break;
82 case SIDE_ATTR_TYPE_S32:
83 val = attr->value.u.integer_value.side_s32;
84 break;
85 case SIDE_ATTR_TYPE_S64:
86 val = attr->value.u.integer_value.side_s64;
87 break;
88 default:
89 fprintf(stderr, "Unexpected attribute type\n");
90 abort();
91 }
92 return val;
93 }
94
95 static
96 enum tracer_display_base get_attr_display_base(const struct side_attr *_attr, uint32_t nr_attr,
97 enum tracer_display_base default_base)
98 {
99 uint32_t i;
100
101 for (i = 0; i < nr_attr; i++) {
102 const struct side_attr *attr = &_attr[i];
103
104 if (!strcmp(attr->key, "std.integer.base")) {
105 int64_t val = get_attr_integer_value(attr);
106
107 switch (val) {
108 case 2:
109 return TRACER_DISPLAY_BASE_2;
110 case 8:
111 return TRACER_DISPLAY_BASE_8;
112 case 10:
113 return TRACER_DISPLAY_BASE_10;
114 case 16:
115 return TRACER_DISPLAY_BASE_16;
116 default:
117 fprintf(stderr, "Unexpected integer display base: %" PRId64 "\n", val);
118 abort();
119 }
120 }
121 }
122 return default_base; /* Default */
123 }
124
125 static
126 bool type_to_host_reverse_bo(const struct side_type *type_desc)
127 {
128 switch (type_desc->type) {
129 case SIDE_TYPE_U8:
130 case SIDE_TYPE_S8:
131 case SIDE_TYPE_BYTE:
132 return false;
133 case SIDE_TYPE_U16:
134 case SIDE_TYPE_U32:
135 case SIDE_TYPE_U64:
136 case SIDE_TYPE_S16:
137 case SIDE_TYPE_S32:
138 case SIDE_TYPE_S64:
139 case SIDE_TYPE_POINTER:
140 if (type_desc->u.side_integer.byte_order != SIDE_TYPE_BYTE_ORDER_HOST)
141 return true;
142 else
143 return false;
144 break;
145 case SIDE_TYPE_FLOAT_BINARY16:
146 case SIDE_TYPE_FLOAT_BINARY32:
147 case SIDE_TYPE_FLOAT_BINARY64:
148 case SIDE_TYPE_FLOAT_BINARY128:
149 if (type_desc->u.side_float.byte_order != SIDE_TYPE_FLOAT_WORD_ORDER_HOST)
150 return true;
151 else
152 return false;
153 break;
154 default:
155 fprintf(stderr, "Unexpected type\n");
156 abort();
157 }
158 }
159
160 static
161 void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
162 {
163 printf("{ key%s \"%s\", value%s ", separator, attr->key, separator);
164 switch (attr->value.type) {
165 case SIDE_ATTR_TYPE_BOOL:
166 printf("%s", attr->value.u.bool_value ? "true" : "false");
167 break;
168 case SIDE_ATTR_TYPE_U8:
169 printf("%" PRIu8, attr->value.u.integer_value.side_u8);
170 break;
171 case SIDE_ATTR_TYPE_U16:
172 printf("%" PRIu16, attr->value.u.integer_value.side_u16);
173 break;
174 case SIDE_ATTR_TYPE_U32:
175 printf("%" PRIu32, attr->value.u.integer_value.side_u32);
176 break;
177 case SIDE_ATTR_TYPE_U64:
178 printf("%" PRIu64, attr->value.u.integer_value.side_u64);
179 break;
180 case SIDE_ATTR_TYPE_S8:
181 printf("%" PRId8, attr->value.u.integer_value.side_s8);
182 break;
183 case SIDE_ATTR_TYPE_S16:
184 printf("%" PRId16, attr->value.u.integer_value.side_s16);
185 break;
186 case SIDE_ATTR_TYPE_S32:
187 printf("%" PRId32, attr->value.u.integer_value.side_s32);
188 break;
189 case SIDE_ATTR_TYPE_S64:
190 printf("%" PRId64, attr->value.u.integer_value.side_s64);
191 break;
192 case SIDE_ATTR_TYPE_FLOAT_BINARY16:
193 #if __HAVE_FLOAT16
194 printf("%g", (double) attr->value.u.float_value.side_float_binary16);
195 break;
196 #else
197 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
198 abort();
199 #endif
200 case SIDE_ATTR_TYPE_FLOAT_BINARY32:
201 #if __HAVE_FLOAT32
202 printf("%g", (double) attr->value.u.float_value.side_float_binary32);
203 break;
204 #else
205 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
206 abort();
207 #endif
208 case SIDE_ATTR_TYPE_FLOAT_BINARY64:
209 #if __HAVE_FLOAT64
210 printf("%g", (double) attr->value.u.float_value.side_float_binary64);
211 break;
212 #else
213 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
214 abort();
215 #endif
216 case SIDE_ATTR_TYPE_FLOAT_BINARY128:
217 #if __HAVE_FLOAT128
218 printf("%Lg", (long double) attr->value.u.float_value.side_float_binary128);
219 break;
220 #else
221 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
222 abort();
223 #endif
224 case SIDE_ATTR_TYPE_STRING:
225 printf("\"%s\"", (const char *)(uintptr_t) attr->value.u.string_value);
226 break;
227 default:
228 fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
229 abort();
230 }
231 printf(" }");
232 }
233
234 static
235 void print_attributes(const char *prefix_str, const char *separator,
236 const struct side_attr *attr, uint32_t nr_attr)
237 {
238 uint32_t i;
239
240 if (!nr_attr)
241 return;
242 printf("%s%s [ ", prefix_str, separator);
243 for (i = 0; i < nr_attr; i++) {
244 printf("%s", i ? ", " : "");
245 tracer_print_attr_type(separator, &attr[i]);
246 }
247 printf(" ]");
248 }
249
250 static
251 void print_enum(const struct side_type *type_desc, const struct side_arg *item)
252 {
253 const struct side_enum_mappings *mappings = type_desc->u.side_enum.mappings;
254 const struct side_type *elem_type = type_desc->u.side_enum.elem_type;
255 uint32_t i, print_count = 0;
256 int64_t value;
257
258 if (elem_type->type != item->type) {
259 fprintf(stderr, "ERROR: Unexpected enum element type\n");
260 abort();
261 }
262 switch (item->type) {
263 case SIDE_TYPE_U8:
264 value = (int64_t) item->u.side_static.integer_value.side_u8;
265 break;
266 case SIDE_TYPE_U16:
267 {
268 uint16_t v;
269
270 v = item->u.side_static.integer_value.side_u16;
271 if (type_to_host_reverse_bo(elem_type))
272 v = side_bswap_16(v);
273 value = (int64_t) v;
274 break;
275 }
276 case SIDE_TYPE_U32:
277 {
278 uint32_t v;
279
280 v = item->u.side_static.integer_value.side_u32;
281 if (type_to_host_reverse_bo(elem_type))
282 v = side_bswap_32(v);
283 value = (int64_t) v;
284 break;
285 }
286 case SIDE_TYPE_U64:
287 {
288 uint64_t v;
289
290 v = item->u.side_static.integer_value.side_u64;
291 if (type_to_host_reverse_bo(elem_type))
292 v = side_bswap_64(v);
293 value = (int64_t) v;
294 break;
295 }
296 case SIDE_TYPE_S8:
297 value = (int64_t) item->u.side_static.integer_value.side_s8;
298 break;
299 case SIDE_TYPE_S16:
300 {
301 int16_t v;
302
303 v = item->u.side_static.integer_value.side_s16;
304 if (type_to_host_reverse_bo(elem_type))
305 v = side_bswap_16(v);
306 value = (int64_t) v;
307 break;
308 }
309 case SIDE_TYPE_S32:
310 {
311 int32_t v;
312
313 v = item->u.side_static.integer_value.side_s32;
314 if (type_to_host_reverse_bo(elem_type))
315 v = side_bswap_32(v);
316 value = (int64_t) v;
317 break;
318 }
319 case SIDE_TYPE_S64:
320 {
321 int64_t v;
322
323 v = item->u.side_static.integer_value.side_s64;
324 if (type_to_host_reverse_bo(elem_type))
325 v = side_bswap_64(v);
326 value = v;
327 break;
328 }
329 default:
330 fprintf(stderr, "ERROR: Unexpected enum element type\n");
331 abort();
332 }
333 print_attributes("attr", ":", mappings->attr, mappings->nr_attr);
334 printf("%s", mappings->nr_attr ? ", " : "");
335 tracer_print_type(type_desc->u.side_enum.elem_type, item);
336 printf(", labels: [ ");
337 for (i = 0; i < mappings->nr_mappings; i++) {
338 const struct side_enum_mapping *mapping = &mappings->mappings[i];
339
340 if (mapping->range_end < mapping->range_begin) {
341 fprintf(stderr, "ERROR: Unexpected enum range: %" PRIu64 "-%" PRIu64 "\n",
342 mapping->range_begin, mapping->range_end);
343 abort();
344 }
345 if (value >= mapping->range_begin && value <= mapping->range_end) {
346 printf("%s", print_count++ ? ", " : "");
347 printf("\"%s\"", mapping->label);
348 }
349 }
350 if (!print_count)
351 printf("<NO LABEL>");
352 printf(" ]");
353 }
354
355 static
356 uint32_t enum_elem_type_to_stride(const struct side_type *elem_type)
357 {
358 uint32_t stride_bit;
359
360 switch (elem_type->type) {
361 case SIDE_TYPE_U8: /* Fall-through */
362 case SIDE_TYPE_BYTE:
363 stride_bit = 8;
364 break;
365 case SIDE_TYPE_U16:
366 stride_bit = 16;
367 break;
368 case SIDE_TYPE_U32:
369 stride_bit = 32;
370 break;
371 case SIDE_TYPE_U64:
372 stride_bit = 64;
373 break;
374 default:
375 fprintf(stderr, "ERROR: Unexpected enum element type\n");
376 abort();
377 }
378 return stride_bit;
379 }
380
381 static
382 void print_enum_bitmap(const struct side_type *type_desc,
383 const struct side_arg *item)
384 {
385 const struct side_type *elem_type = type_desc->u.side_enum_bitmap.elem_type;
386 const struct side_enum_bitmap_mappings *side_enum_mappings = type_desc->u.side_enum_bitmap.mappings;
387 uint32_t i, print_count = 0, stride_bit, nr_items;
388 bool reverse_byte_order = false;
389 const struct side_arg *array_item;
390
391 switch (elem_type->type) {
392 case SIDE_TYPE_U8: /* Fall-through */
393 case SIDE_TYPE_BYTE: /* Fall-through */
394 case SIDE_TYPE_U16: /* Fall-through */
395 case SIDE_TYPE_U32: /* Fall-through */
396 case SIDE_TYPE_U64:
397 stride_bit = enum_elem_type_to_stride(elem_type);
398 reverse_byte_order = type_to_host_reverse_bo(elem_type);
399 array_item = item;
400 nr_items = 1;
401 break;
402 case SIDE_TYPE_ARRAY:
403 stride_bit = enum_elem_type_to_stride(elem_type->u.side_array.elem_type);
404 reverse_byte_order = type_to_host_reverse_bo(elem_type->u.side_array.elem_type);
405 array_item = item->u.side_static.side_array->sav;
406 nr_items = type_desc->u.side_array.length;
407 break;
408 case SIDE_TYPE_VLA:
409 stride_bit = enum_elem_type_to_stride(elem_type->u.side_vla.elem_type);
410 reverse_byte_order = type_to_host_reverse_bo(elem_type->u.side_vla.elem_type);
411 array_item = item->u.side_static.side_vla->sav;
412 nr_items = item->u.side_static.side_vla->len;
413 break;
414 default:
415 fprintf(stderr, "ERROR: Unexpected enum element type\n");
416 abort();
417 }
418
419 print_attributes("attr", ":", side_enum_mappings->attr, side_enum_mappings->nr_attr);
420 printf("%s", side_enum_mappings->nr_attr ? ", " : "");
421 printf("labels: [ ");
422 for (i = 0; i < side_enum_mappings->nr_mappings; i++) {
423 const struct side_enum_bitmap_mapping *mapping = &side_enum_mappings->mappings[i];
424 bool match = false;
425 uint64_t bit;
426
427 if (mapping->range_end < mapping->range_begin) {
428 fprintf(stderr, "ERROR: Unexpected enum bitmap range: %" PRIu64 "-%" PRIu64 "\n",
429 mapping->range_begin, mapping->range_end);
430 abort();
431 }
432 for (bit = mapping->range_begin; bit <= mapping->range_end; bit++) {
433 if (bit > (nr_items * stride_bit) - 1)
434 break;
435 switch (stride_bit) {
436 case 8:
437 {
438 uint8_t v = array_item[bit / 8].u.side_static.integer_value.side_u8;
439 if (v & (1ULL << (bit % 8))) {
440 match = true;
441 goto match;
442 }
443 break;
444 }
445 case 16:
446 {
447 uint16_t v = array_item[bit / 16].u.side_static.integer_value.side_u16;
448 if (reverse_byte_order)
449 v = side_bswap_16(v);
450 if (v & (1ULL << (bit % 16))) {
451 match = true;
452 goto match;
453 }
454 break;
455 }
456 case 32:
457 {
458 uint32_t v = array_item[bit / 32].u.side_static.integer_value.side_u32;
459 if (reverse_byte_order)
460 v = side_bswap_32(v);
461 if (v & (1ULL << (bit % 32))) {
462 match = true;
463 goto match;
464 }
465 break;
466 }
467 case 64:
468 {
469 uint64_t v = array_item[bit / 64].u.side_static.integer_value.side_u64;
470 if (reverse_byte_order)
471 v = side_bswap_64(v);
472 if (v & (1ULL << (bit % 64))) {
473 match = true;
474 goto match;
475 }
476 break;
477 }
478 default:
479 abort();
480 }
481 }
482 match:
483 if (match) {
484 printf("%s", print_count++ ? ", " : "");
485 printf("\"%s\"", mapping->label);
486 }
487 }
488 if (!print_count)
489 printf("<NO LABEL>");
490 printf(" ]");
491 }
492
493 static
494 void print_integer_binary(uint64_t v, int bits)
495 {
496 int i;
497
498 printf("0b");
499 v <<= 64 - bits;
500 for (i = 0; i < bits; i++) {
501 printf("%c", v & (1ULL << 63) ? '1' : '0');
502 v <<= 1;
503 }
504 }
505
506 static
507 void tracer_print_type_header(const char *separator,
508 const struct side_attr *attr, uint32_t nr_attr)
509 {
510 print_attributes("attr", separator, attr, nr_attr);
511 printf("%s", nr_attr ? ", " : "");
512 printf("value%s ", separator);
513 }
514
515 static
516 void tracer_print_type_bool(const char *separator,
517 const struct side_type_bool *type_bool,
518 const union side_bool_value *value,
519 uint16_t offset_bits)
520 {
521 uint32_t len_bits;
522 bool reverse_bo;
523 uint64_t v;
524
525 if (!type_bool->len_bits)
526 len_bits = type_bool->bool_size * CHAR_BIT;
527 else
528 len_bits = type_bool->len_bits;
529 if (len_bits + offset_bits > type_bool->bool_size * CHAR_BIT)
530 abort();
531 reverse_bo = type_bool->byte_order != SIDE_TYPE_BYTE_ORDER_HOST;
532 switch (type_bool->bool_size) {
533 case 1:
534 v = value->side_bool8;
535 break;
536 case 2:
537 {
538 uint16_t side_u16;
539
540 side_u16 = value->side_bool16;
541 if (reverse_bo)
542 side_u16 = side_bswap_16(side_u16);
543 v = side_u16;
544 break;
545 }
546 case 4:
547 {
548 uint32_t side_u32;
549
550 side_u32 = value->side_bool32;
551 if (reverse_bo)
552 side_u32 = side_bswap_32(side_u32);
553 v = side_u32;
554 break;
555 }
556 case 8:
557 {
558 uint64_t side_u64;
559
560 side_u64 = value->side_bool64;
561 if (reverse_bo)
562 side_u64 = side_bswap_64(side_u64);
563 v = side_u64;
564 break;
565 }
566 default:
567 abort();
568 }
569 v >>= offset_bits;
570 if (len_bits < 64)
571 v &= (1ULL << len_bits) - 1;
572 tracer_print_type_header(separator, type_bool->attr, type_bool->nr_attr);
573 printf("%s", v ? "true" : "false");
574 }
575
576 static
577 union int64_value tracer_load_integer_value(const struct side_type_integer *type_integer,
578 const union side_integer_value *value,
579 uint16_t offset_bits, uint16_t *_len_bits)
580 {
581 union int64_value v64;
582 uint16_t len_bits;
583 bool reverse_bo;
584
585 if (!type_integer->len_bits)
586 len_bits = type_integer->integer_size * CHAR_BIT;
587 else
588 len_bits = type_integer->len_bits;
589 if (len_bits + offset_bits > type_integer->integer_size * CHAR_BIT)
590 abort();
591 reverse_bo = type_integer->byte_order != SIDE_TYPE_BYTE_ORDER_HOST;
592 switch (type_integer->integer_size) {
593 case 1:
594 if (type_integer->signedness)
595 v64.s = value->side_s8;
596 else
597 v64.u = value->side_u8;
598 break;
599 case 2:
600 if (type_integer->signedness) {
601 int16_t side_s16;
602
603 side_s16 = value->side_s16;
604 if (reverse_bo)
605 side_s16 = side_bswap_16(side_s16);
606 v64.s = side_s16;
607 } else {
608 uint16_t side_u16;
609
610 side_u16 = value->side_u16;
611 if (reverse_bo)
612 side_u16 = side_bswap_16(side_u16);
613 v64.u = side_u16;
614 }
615 break;
616 case 4:
617 if (type_integer->signedness) {
618 int32_t side_s32;
619
620 side_s32 = value->side_s32;
621 if (reverse_bo)
622 side_s32 = side_bswap_32(side_s32);
623 v64.s = side_s32;
624 } else {
625 uint32_t side_u32;
626
627 side_u32 = value->side_u32;
628 if (reverse_bo)
629 side_u32 = side_bswap_32(side_u32);
630 v64.u = side_u32;
631 }
632 break;
633 case 8:
634 if (type_integer->signedness) {
635 int64_t side_s64;
636
637 side_s64 = value->side_s64;
638 if (reverse_bo)
639 side_s64 = side_bswap_64(side_s64);
640 v64.s = side_s64;
641 } else {
642 uint64_t side_u64;
643
644 side_u64 = value->side_u64;
645 if (reverse_bo)
646 side_u64 = side_bswap_64(side_u64);
647 v64.u = side_u64;
648 }
649 break;
650 default:
651 abort();
652 }
653 v64.u >>= offset_bits;
654 if (len_bits < 64)
655 v64.u &= (1ULL << len_bits) - 1;
656 if (_len_bits)
657 *_len_bits = len_bits;
658 return v64;
659 }
660
661 static
662 void tracer_print_type_integer(const char *separator,
663 const struct side_type_integer *type_integer,
664 const union side_integer_value *value,
665 uint16_t offset_bits,
666 enum tracer_display_base default_base)
667 {
668 enum tracer_display_base base;
669 union int64_value v64;
670 uint16_t len_bits;
671
672 v64 = tracer_load_integer_value(type_integer, value, offset_bits, &len_bits);
673 tracer_print_type_header(separator, type_integer->attr, type_integer->nr_attr);
674 base = get_attr_display_base(type_integer->attr, type_integer->nr_attr, default_base);
675 switch (base) {
676 case TRACER_DISPLAY_BASE_2:
677 print_integer_binary(v64.u, len_bits);
678 break;
679 case TRACER_DISPLAY_BASE_8:
680 printf("0%" PRIo64, v64.u);
681 break;
682 case TRACER_DISPLAY_BASE_10:
683 if (type_integer->signedness) {
684 /* Sign-extend. */
685 if (len_bits < 64) {
686 if (v64.u & (1ULL << (len_bits - 1)))
687 v64.u |= ~((1ULL << len_bits) - 1);
688 }
689 printf("%" PRId64, v64.s);
690 } else {
691 printf("%" PRIu64, v64.u);
692 }
693 break;
694 case TRACER_DISPLAY_BASE_16:
695 printf("0x%" PRIx64, v64.u);
696 break;
697 default:
698 abort();
699 }
700 }
701
702 static
703 void tracer_print_type_float(const char *separator,
704 const struct side_type_float *type_float,
705 const union side_float_value *value)
706 {
707 bool reverse_bo;
708
709 tracer_print_type_header(separator, type_float->attr, type_float->nr_attr);
710 reverse_bo = type_float->byte_order != SIDE_TYPE_FLOAT_WORD_ORDER_HOST;
711 switch (type_float->float_size) {
712 case 2:
713 {
714 #if __HAVE_FLOAT16
715 union {
716 _Float16 f;
717 uint16_t u;
718 } float16 = {
719 .f = value->side_float_binary16,
720 };
721
722 if (reverse_bo)
723 float16.u = side_bswap_16(float16.u);
724 printf("%g", (double) float16.f);
725 break;
726 #else
727 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
728 abort();
729 #endif
730 }
731 case 4:
732 {
733 #if __HAVE_FLOAT32
734 union {
735 _Float32 f;
736 uint32_t u;
737 } float32 = {
738 .f = value->side_float_binary32,
739 };
740
741 if (reverse_bo)
742 float32.u = side_bswap_32(float32.u);
743 printf("%g", (double) float32.f);
744 break;
745 #else
746 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
747 abort();
748 #endif
749 }
750 case 8:
751 {
752 #if __HAVE_FLOAT64
753 union {
754 _Float64 f;
755 uint64_t u;
756 } float64 = {
757 .f = value->side_float_binary64,
758 };
759
760 if (reverse_bo)
761 float64.u = side_bswap_64(float64.u);
762 printf("%g", (double) float64.f);
763 break;
764 #else
765 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
766 abort();
767 #endif
768 }
769 case 16:
770 {
771 #if __HAVE_FLOAT128
772 union {
773 _Float128 f;
774 char arr[16];
775 } float128 = {
776 .f = value->side_float_binary128,
777 };
778
779 if (reverse_bo)
780 side_bswap_128p(float128.arr);
781 printf("%Lg", (long double) float128.f);
782 break;
783 #else
784 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
785 abort();
786 #endif
787 }
788 default:
789 fprintf(stderr, "ERROR: Unknown float size\n");
790 abort();
791 }
792 }
793
794 static
795 void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item)
796 {
797 enum side_type_label type;
798
799 switch (type_desc->type) {
800 case SIDE_TYPE_ENUM:
801 switch (item->type) {
802 case SIDE_TYPE_U8:
803 case SIDE_TYPE_U16:
804 case SIDE_TYPE_U32:
805 case SIDE_TYPE_U64:
806 case SIDE_TYPE_S8:
807 case SIDE_TYPE_S16:
808 case SIDE_TYPE_S32:
809 case SIDE_TYPE_S64:
810 break;
811 default:
812 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
813 abort();
814 break;
815 }
816 break;
817
818 case SIDE_TYPE_ENUM_BITMAP:
819 switch (item->type) {
820 case SIDE_TYPE_U8:
821 case SIDE_TYPE_BYTE:
822 case SIDE_TYPE_U16:
823 case SIDE_TYPE_U32:
824 case SIDE_TYPE_U64:
825 case SIDE_TYPE_ARRAY:
826 case SIDE_TYPE_VLA:
827 break;
828 default:
829 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
830 abort();
831 break;
832 }
833 break;
834
835 case SIDE_TYPE_DYNAMIC:
836 switch (item->type) {
837 case SIDE_TYPE_DYNAMIC_NULL:
838 case SIDE_TYPE_DYNAMIC_BOOL:
839 case SIDE_TYPE_DYNAMIC_INTEGER:
840 case SIDE_TYPE_DYNAMIC_BYTE:
841 case SIDE_TYPE_DYNAMIC_POINTER:
842 case SIDE_TYPE_DYNAMIC_FLOAT:
843 case SIDE_TYPE_DYNAMIC_STRING:
844 case SIDE_TYPE_DYNAMIC_STRUCT:
845 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR:
846 case SIDE_TYPE_DYNAMIC_VLA:
847 case SIDE_TYPE_DYNAMIC_VLA_VISITOR:
848 break;
849 default:
850 fprintf(stderr, "ERROR: Unexpected dynamic type\n");
851 abort();
852 break;
853 }
854 break;
855
856 default:
857 if (type_desc->type != item->type) {
858 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
859 abort();
860 }
861 break;
862 }
863
864 if (type_desc->type == SIDE_TYPE_ENUM || type_desc->type == SIDE_TYPE_ENUM_BITMAP)
865 type = (enum side_type_label) type_desc->type;
866 else
867 type = (enum side_type_label) item->type;
868
869 printf("{ ");
870 switch (type) {
871 /* Stack-copy basic types */
872 case SIDE_TYPE_NULL:
873 tracer_print_type_header(":", type_desc->u.side_null.attr, type_desc->u.side_null.nr_attr);
874 printf("<NULL TYPE>");
875 break;
876
877 case SIDE_TYPE_BOOL:
878 tracer_print_type_bool(":", &type_desc->u.side_bool, &item->u.side_static.bool_value, 0);
879 break;
880
881 case SIDE_TYPE_U8:
882 case SIDE_TYPE_U16:
883 case SIDE_TYPE_U32:
884 case SIDE_TYPE_U64:
885 case SIDE_TYPE_S8:
886 case SIDE_TYPE_S16:
887 case SIDE_TYPE_S32:
888 case SIDE_TYPE_S64:
889 tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0,
890 TRACER_DISPLAY_BASE_10);
891 break;
892
893 case SIDE_TYPE_BYTE:
894 tracer_print_type_header(":", type_desc->u.side_byte.attr, type_desc->u.side_byte.nr_attr);
895 printf("0x%" PRIx8, item->u.side_static.byte_value);
896 break;
897
898 case SIDE_TYPE_POINTER:
899 tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0,
900 TRACER_DISPLAY_BASE_16);
901 break;
902
903 case SIDE_TYPE_FLOAT_BINARY16:
904 case SIDE_TYPE_FLOAT_BINARY32:
905 case SIDE_TYPE_FLOAT_BINARY64:
906 case SIDE_TYPE_FLOAT_BINARY128:
907 tracer_print_type_float(":", &type_desc->u.side_float, &item->u.side_static.float_value);
908 break;
909
910 case SIDE_TYPE_STRING:
911 tracer_print_type_header(":", type_desc->u.side_string.attr, type_desc->u.side_string.nr_attr);
912 printf("\"%s\"", (const char *)(uintptr_t) item->u.side_static.string_value);
913 break;
914
915 /* Stack-copy compound types */
916 case SIDE_TYPE_STRUCT:
917 tracer_print_struct(type_desc, item->u.side_static.side_struct);
918 break;
919 case SIDE_TYPE_ARRAY:
920 tracer_print_array(type_desc, item->u.side_static.side_array);
921 break;
922 case SIDE_TYPE_VLA:
923 tracer_print_vla(type_desc, item->u.side_static.side_vla);
924 break;
925 case SIDE_TYPE_VLA_VISITOR:
926 tracer_print_vla_visitor(type_desc, item->u.side_static.side_vla_app_visitor_ctx);
927 break;
928
929 /* Stack-copy enumeration types */
930 case SIDE_TYPE_ENUM:
931 print_enum(type_desc, item);
932 break;
933 case SIDE_TYPE_ENUM_BITMAP:
934 print_enum_bitmap(type_desc, item);
935 break;
936
937 /* Gather basic types */
938 case SIDE_TYPE_GATHER_BOOL:
939 (void) tracer_print_gather_bool_type(&type_desc->u.side_gather, item->u.side_static.side_bool_gather_ptr);
940 break;
941 case SIDE_TYPE_GATHER_INTEGER:
942 (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, item->u.side_static.side_integer_gather_ptr,
943 TRACER_DISPLAY_BASE_10);
944 break;
945 case SIDE_TYPE_GATHER_BYTE:
946 (void) tracer_print_gather_byte_type(&type_desc->u.side_gather, item->u.side_static.side_byte_gather_ptr);
947 break;
948 case SIDE_TYPE_GATHER_POINTER:
949 (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, item->u.side_static.side_integer_gather_ptr,
950 TRACER_DISPLAY_BASE_16);
951 break;
952 case SIDE_TYPE_GATHER_FLOAT:
953 (void) tracer_print_gather_float_type(&type_desc->u.side_gather, item->u.side_static.side_float_gather_ptr);
954 break;
955
956 /* Gather compound type */
957 case SIDE_TYPE_GATHER_STRUCT:
958 (void) tracer_print_gather_struct(&type_desc->u.side_gather, item->u.side_static.side_struct_gather_ptr);
959 break;
960 case SIDE_TYPE_GATHER_ARRAY:
961 (void) tracer_print_gather_array(&type_desc->u.side_gather, item->u.side_static.side_array_gather_ptr);
962 break;
963 case SIDE_TYPE_GATHER_VLA:
964 (void) tracer_print_gather_vla(&type_desc->u.side_gather, item->u.side_static.side_vla_gather.ptr,
965 item->u.side_static.side_vla_gather.length_ptr);
966 break;
967
968 /* Dynamic basic types */
969 case SIDE_TYPE_DYNAMIC_NULL:
970 case SIDE_TYPE_DYNAMIC_BOOL:
971 case SIDE_TYPE_DYNAMIC_INTEGER:
972 case SIDE_TYPE_DYNAMIC_BYTE:
973 case SIDE_TYPE_DYNAMIC_POINTER:
974 case SIDE_TYPE_DYNAMIC_FLOAT:
975 case SIDE_TYPE_DYNAMIC_STRING:
976
977 /* Dynamic compound types */
978 case SIDE_TYPE_DYNAMIC_STRUCT:
979 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR:
980 case SIDE_TYPE_DYNAMIC_VLA:
981 case SIDE_TYPE_DYNAMIC_VLA_VISITOR:
982 tracer_print_dynamic(item);
983 break;
984 default:
985 fprintf(stderr, "<UNKNOWN TYPE>\n");
986 abort();
987 }
988 printf(" }");
989 }
990
991 static
992 void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg *item)
993 {
994 printf("%s: ", item_desc->field_name);
995 tracer_print_type(&item_desc->side_type, item);
996 }
997
998 static
999 void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
1000 {
1001 const struct side_arg *sav = side_arg_vec->sav;
1002 uint32_t i, side_sav_len = side_arg_vec->len;
1003
1004 if (type_desc->u.side_struct->nr_fields != side_sav_len) {
1005 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n");
1006 abort();
1007 }
1008 print_attributes("attr", ":", type_desc->u.side_struct->attr, type_desc->u.side_struct->nr_attr);
1009 printf("%s", type_desc->u.side_struct->nr_attr ? ", " : "");
1010 printf("fields: { ");
1011 for (i = 0; i < side_sav_len; i++) {
1012 printf("%s", i ? ", " : "");
1013 tracer_print_field(&type_desc->u.side_struct->fields[i], &sav[i]);
1014 }
1015 printf(" }");
1016 }
1017
1018 static
1019 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
1020 {
1021 const struct side_arg *sav = side_arg_vec->sav;
1022 uint32_t i, side_sav_len = side_arg_vec->len;
1023
1024 if (type_desc->u.side_array.length != side_sav_len) {
1025 fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n");
1026 abort();
1027 }
1028 print_attributes("attr", ":", type_desc->u.side_array.attr, type_desc->u.side_array.nr_attr);
1029 printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
1030 printf("elements: ");
1031 printf("[ ");
1032 for (i = 0; i < side_sav_len; i++) {
1033 printf("%s", i ? ", " : "");
1034 tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
1035 }
1036 printf(" ]");
1037 }
1038
1039 static
1040 void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
1041 {
1042 const struct side_arg *sav = side_arg_vec->sav;
1043 uint32_t i, side_sav_len = side_arg_vec->len;
1044
1045 print_attributes("attr", ":", type_desc->u.side_vla.attr, type_desc->u.side_vla.nr_attr);
1046 printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
1047 printf("elements: ");
1048 printf("[ ");
1049 for (i = 0; i < side_sav_len; i++) {
1050 printf("%s", i ? ", " : "");
1051 tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
1052 }
1053 printf(" ]");
1054 }
1055
1056 static
1057 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode, const char *ptr)
1058 {
1059 switch (access_mode) {
1060 case SIDE_TYPE_GATHER_ACCESS_DIRECT:
1061 return ptr;
1062 case SIDE_TYPE_GATHER_ACCESS_POINTER:
1063 /* Dereference pointer */
1064 memcpy(&ptr, ptr, sizeof(ptr));
1065 return ptr;
1066 default:
1067 abort();
1068 }
1069 }
1070
1071 static
1072 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode, uint32_t len)
1073 {
1074 switch (access_mode) {
1075 case SIDE_TYPE_GATHER_ACCESS_DIRECT:
1076 return len;
1077 case SIDE_TYPE_GATHER_ACCESS_POINTER:
1078 return sizeof(void *);
1079 default:
1080 abort();
1081 }
1082 }
1083
1084 static
1085 union int64_value tracer_load_gather_integer_value(const struct side_type_gather *type_gather,
1086 const void *_ptr, uint16_t offset_bits)
1087 {
1088 enum side_type_gather_access_mode access_mode =
1089 (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode;
1090 uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size;
1091 const char *ptr = (const char *) _ptr;
1092 union side_integer_value value;
1093
1094 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset);
1095 memcpy(&value, ptr, integer_size_bytes);
1096 return tracer_load_integer_value(&type_gather->u.side_integer.type, &value, offset_bits, NULL);
1097 }
1098
1099 static
1100 uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr)
1101 {
1102 enum side_type_gather_access_mode access_mode =
1103 (enum side_type_gather_access_mode) type_gather->u.side_bool.access_mode;
1104 uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size;
1105 const char *ptr = (const char *) _ptr;
1106 union side_bool_value value;
1107
1108 switch (bool_size_bytes) {
1109 case 1:
1110 case 2:
1111 case 4:
1112 case 8:
1113 break;
1114 default:
1115 abort();
1116 }
1117 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset);
1118 memcpy(&value, ptr, bool_size_bytes);
1119 tracer_print_type_bool(":", &type_gather->u.side_bool.type, &value,
1120 type_gather->u.side_bool.offset_bits);
1121 return tracer_gather_size(access_mode, bool_size_bytes);
1122 }
1123
1124 static
1125 uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr)
1126 {
1127 enum side_type_gather_access_mode access_mode =
1128 (enum side_type_gather_access_mode) type_gather->u.side_byte.access_mode;
1129 const char *ptr = (const char *) _ptr;
1130 uint8_t value;
1131
1132 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset);
1133 memcpy(&value, ptr, 1);
1134 tracer_print_type_header(":", type_gather->u.side_byte.type.attr,
1135 type_gather->u.side_byte.type.nr_attr);
1136 printf("0x%" PRIx8, value);
1137 return tracer_gather_size(access_mode, 1);
1138 }
1139
1140 static
1141 uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr,
1142 enum tracer_display_base default_base)
1143 {
1144 enum side_type_gather_access_mode access_mode =
1145 (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode;
1146 uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size;
1147 const char *ptr = (const char *) _ptr;
1148 union side_integer_value value;
1149
1150 switch (integer_size_bytes) {
1151 case 1:
1152 case 2:
1153 case 4:
1154 case 8:
1155 break;
1156 default:
1157 abort();
1158 }
1159 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset);
1160 memcpy(&value, ptr, integer_size_bytes);
1161 tracer_print_type_integer(":", &type_gather->u.side_integer.type, &value,
1162 type_gather->u.side_integer.offset_bits, default_base);
1163 return tracer_gather_size(access_mode, integer_size_bytes);
1164 }
1165
1166 static
1167 uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr)
1168 {
1169 enum side_type_gather_access_mode access_mode =
1170 (enum side_type_gather_access_mode) type_gather->u.side_float.access_mode;
1171 uint32_t float_size_bytes = type_gather->u.side_float.type.float_size;
1172 const char *ptr = (const char *) _ptr;
1173 union side_float_value value;
1174
1175 switch (float_size_bytes) {
1176 case 2:
1177 case 4:
1178 case 8:
1179 case 16:
1180 break;
1181 default:
1182 abort();
1183 }
1184 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset);
1185 memcpy(&value, ptr, float_size_bytes);
1186 tracer_print_type_float(":", &type_gather->u.side_float.type, &value);
1187 return tracer_gather_size(access_mode, float_size_bytes);
1188 }
1189
1190 static
1191 uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void *ptr)
1192 {
1193 uint32_t len;
1194
1195 printf("{ ");
1196 switch (type_desc->type) {
1197 /* Gather basic types */
1198 case SIDE_TYPE_GATHER_BOOL:
1199 len = tracer_print_gather_bool_type(&type_desc->u.side_gather, ptr);
1200 break;
1201 case SIDE_TYPE_GATHER_INTEGER:
1202 len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr,
1203 TRACER_DISPLAY_BASE_10);
1204 break;
1205 case SIDE_TYPE_GATHER_BYTE:
1206 len = tracer_print_gather_byte_type(&type_desc->u.side_gather, ptr);
1207 break;
1208 case SIDE_TYPE_GATHER_POINTER:
1209 len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr,
1210 TRACER_DISPLAY_BASE_16);
1211 break;
1212 case SIDE_TYPE_GATHER_FLOAT:
1213 len = tracer_print_gather_float_type(&type_desc->u.side_gather, ptr);
1214 break;
1215
1216 /* Gather compound types */
1217 case SIDE_TYPE_GATHER_STRUCT:
1218 len = tracer_print_gather_struct(&type_desc->u.side_gather, ptr);
1219 break;
1220 case SIDE_TYPE_GATHER_ARRAY:
1221 len = tracer_print_gather_array(&type_desc->u.side_gather, ptr);
1222 break;
1223 case SIDE_TYPE_GATHER_VLA:
1224 len = tracer_print_gather_vla(&type_desc->u.side_gather, ptr, ptr);
1225 break;
1226 default:
1227 fprintf(stderr, "<UNKNOWN GATHER TYPE>");
1228 abort();
1229 }
1230 printf(" }");
1231 return len;
1232 }
1233
1234 static
1235 void tracer_print_gather_field(const struct side_event_field *field, const void *ptr)
1236 {
1237 printf("%s: ", field->field_name);
1238 (void) tracer_print_gather_type(&field->side_type, ptr);
1239 }
1240
1241 static
1242 uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr)
1243 {
1244 enum side_type_gather_access_mode access_mode =
1245 (enum side_type_gather_access_mode) type_gather->u.side_struct.access_mode;
1246 const char *ptr = (const char *) _ptr;
1247 uint32_t i;
1248
1249 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_struct.offset);
1250 print_attributes("attr", ":", type_gather->u.side_struct.type->attr, type_gather->u.side_struct.type->nr_attr);
1251 printf("%s", type_gather->u.side_struct.type->nr_attr ? ", " : "");
1252 printf("fields: { ");
1253 for (i = 0; i < type_gather->u.side_struct.type->nr_fields; i++) {
1254 printf("%s", i ? ", " : "");
1255 tracer_print_gather_field(&type_gather->u.side_struct.type->fields[i], ptr);
1256 }
1257 printf(" }");
1258 return tracer_gather_size(access_mode, type_gather->u.side_struct.size);
1259 }
1260
1261 static
1262 uint32_t tracer_print_gather_array(const struct side_type_gather *type_gather, const void *_ptr)
1263 {
1264 enum side_type_gather_access_mode access_mode =
1265 (enum side_type_gather_access_mode) type_gather->u.side_array.access_mode;
1266 const char *ptr = (const char *) _ptr, *orig_ptr;
1267 uint32_t i;
1268
1269 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_array.offset);
1270 orig_ptr = ptr;
1271 print_attributes("attr", ":", type_gather->u.side_array.type.attr, type_gather->u.side_array.type.nr_attr);
1272 printf("%s", type_gather->u.side_array.type.nr_attr ? ", " : "");
1273 printf("elements: ");
1274 printf("[ ");
1275 for (i = 0; i < type_gather->u.side_array.type.length; i++) {
1276 switch (type_gather->u.side_array.type.elem_type->type) {
1277 case SIDE_TYPE_GATHER_VLA:
1278 fprintf(stderr, "<gather VLA only supported within gather structures>\n");
1279 abort();
1280 default:
1281 break;
1282 }
1283 printf("%s", i ? ", " : "");
1284 ptr += tracer_print_gather_type(type_gather->u.side_array.type.elem_type, ptr);
1285 }
1286 printf(" ]");
1287 return tracer_gather_size(access_mode, ptr - orig_ptr);
1288 }
1289
1290 static
1291 uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, const void *_ptr,
1292 const void *_length_ptr)
1293 {
1294 enum side_type_gather_access_mode access_mode =
1295 (enum side_type_gather_access_mode) type_gather->u.side_vla.access_mode;
1296 const char *ptr = (const char *) _ptr, *orig_ptr;
1297 const char *length_ptr = (const char *) _length_ptr;
1298 union int64_value v64;
1299 uint32_t i, length;
1300
1301 /* Access length */
1302 switch (type_gather->u.side_vla.length_type->type) {
1303 case SIDE_TYPE_GATHER_INTEGER:
1304 break;
1305 default:
1306 fprintf(stderr, "<gather VLA expects integer gather length type>\n");
1307 abort();
1308 }
1309 v64 = tracer_load_gather_integer_value(&type_gather->u.side_vla.length_type->u.side_gather,
1310 length_ptr, 0);
1311 length = (uint32_t) v64.u;
1312 ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_vla.offset);
1313 orig_ptr = ptr;
1314 print_attributes("attr", ":", type_gather->u.side_vla.type.attr, type_gather->u.side_vla.type.nr_attr);
1315 printf("%s", type_gather->u.side_vla.type.nr_attr ? ", " : "");
1316 printf("elements: ");
1317 printf("[ ");
1318 for (i = 0; i < length; i++) {
1319 switch (type_gather->u.side_vla.type.elem_type->type) {
1320 case SIDE_TYPE_GATHER_VLA:
1321 fprintf(stderr, "<gather VLA only supported within gather structures>\n");
1322 abort();
1323 default:
1324 break;
1325 }
1326 printf("%s", i ? ", " : "");
1327 ptr += tracer_print_gather_type(type_gather->u.side_vla.type.elem_type, ptr);
1328 }
1329 printf(" ]");
1330 return tracer_gather_size(access_mode, ptr - orig_ptr);
1331 }
1332
1333 struct tracer_visitor_priv {
1334 const struct side_type *elem_type;
1335 int i;
1336 };
1337
1338 static
1339 enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx,
1340 const struct side_arg *elem)
1341 {
1342 struct tracer_visitor_priv *tracer_priv = (struct tracer_visitor_priv *) tracer_ctx->priv;
1343
1344 printf("%s", tracer_priv->i++ ? ", " : "");
1345 tracer_print_type(tracer_priv->elem_type, elem);
1346 return SIDE_VISITOR_STATUS_OK;
1347 }
1348
1349 static
1350 void tracer_print_vla_visitor(const struct side_type *type_desc, void *app_ctx)
1351 {
1352 enum side_visitor_status status;
1353 struct tracer_visitor_priv tracer_priv = {
1354 .elem_type = type_desc->u.side_vla_visitor.elem_type,
1355 .i = 0,
1356 };
1357 const struct side_tracer_visitor_ctx tracer_ctx = {
1358 .write_elem = tracer_write_elem_cb,
1359 .priv = &tracer_priv,
1360 };
1361
1362 print_attributes("attr", ":", type_desc->u.side_vla_visitor.attr, type_desc->u.side_vla_visitor.nr_attr);
1363 printf("%s", type_desc->u.side_vla_visitor.nr_attr ? ", " : "");
1364 printf("elements: ");
1365 printf("[ ");
1366 status = type_desc->u.side_vla_visitor.visitor(&tracer_ctx, app_ctx);
1367 switch (status) {
1368 case SIDE_VISITOR_STATUS_OK:
1369 break;
1370 case SIDE_VISITOR_STATUS_ERROR:
1371 fprintf(stderr, "ERROR: Visitor error\n");
1372 abort();
1373 }
1374 printf(" ]");
1375 }
1376
1377 static
1378 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct *dynamic_struct)
1379 {
1380 const struct side_arg_dynamic_field *fields = dynamic_struct->fields;
1381 uint32_t i, len = dynamic_struct->len;
1382
1383 print_attributes("attr", "::", dynamic_struct->attr, dynamic_struct->nr_attr);
1384 printf("%s", dynamic_struct->nr_attr ? ", " : "");
1385 printf("fields:: ");
1386 printf("[ ");
1387 for (i = 0; i < len; i++) {
1388 printf("%s", i ? ", " : "");
1389 printf("%s:: ", fields[i].field_name);
1390 tracer_print_dynamic(&fields[i].elem);
1391 }
1392 printf(" ]");
1393 }
1394
1395 struct tracer_dynamic_struct_visitor_priv {
1396 int i;
1397 };
1398
1399 static
1400 enum side_visitor_status tracer_dynamic_struct_write_elem_cb(
1401 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
1402 const struct side_arg_dynamic_field *dynamic_field)
1403 {
1404 struct tracer_dynamic_struct_visitor_priv *tracer_priv =
1405 (struct tracer_dynamic_struct_visitor_priv *) tracer_ctx->priv;
1406
1407 printf("%s", tracer_priv->i++ ? ", " : "");
1408 printf("%s:: ", dynamic_field->field_name);
1409 tracer_print_dynamic(&dynamic_field->elem);
1410 return SIDE_VISITOR_STATUS_OK;
1411 }
1412
1413 static
1414 void tracer_print_dynamic_struct_visitor(const struct side_arg *item)
1415 {
1416 enum side_visitor_status status;
1417 struct tracer_dynamic_struct_visitor_priv tracer_priv = {
1418 .i = 0,
1419 };
1420 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = {
1421 .write_field = tracer_dynamic_struct_write_elem_cb,
1422 .priv = &tracer_priv,
1423 };
1424 void *app_ctx = item->u.side_dynamic.side_dynamic_struct_visitor.app_ctx;
1425
1426 print_attributes("attr", "::", item->u.side_dynamic.side_dynamic_struct_visitor.attr, item->u.side_dynamic.side_dynamic_struct_visitor.nr_attr);
1427 printf("%s", item->u.side_dynamic.side_dynamic_struct_visitor.nr_attr ? ", " : "");
1428 printf("fields:: ");
1429 printf("[ ");
1430 status = item->u.side_dynamic.side_dynamic_struct_visitor.visitor(&tracer_ctx, app_ctx);
1431 switch (status) {
1432 case SIDE_VISITOR_STATUS_OK:
1433 break;
1434 case SIDE_VISITOR_STATUS_ERROR:
1435 fprintf(stderr, "ERROR: Visitor error\n");
1436 abort();
1437 }
1438 printf(" ]");
1439 }
1440
1441 static
1442 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla *vla)
1443 {
1444 const struct side_arg *sav = vla->sav;
1445 uint32_t i, side_sav_len = vla->len;
1446
1447 print_attributes("attr", "::", vla->attr, vla->nr_attr);
1448 printf("%s", vla->nr_attr ? ", " : "");
1449 printf("elements:: ");
1450 printf("[ ");
1451 for (i = 0; i < side_sav_len; i++) {
1452 printf("%s", i ? ", " : "");
1453 tracer_print_dynamic(&sav[i]);
1454 }
1455 printf(" ]");
1456 }
1457
1458 struct tracer_dynamic_vla_visitor_priv {
1459 int i;
1460 };
1461
1462 static
1463 enum side_visitor_status tracer_dynamic_vla_write_elem_cb(
1464 const struct side_tracer_visitor_ctx *tracer_ctx,
1465 const struct side_arg *elem)
1466 {
1467 struct tracer_dynamic_vla_visitor_priv *tracer_priv =
1468 (struct tracer_dynamic_vla_visitor_priv *) tracer_ctx->priv;
1469
1470 printf("%s", tracer_priv->i++ ? ", " : "");
1471 tracer_print_dynamic(elem);
1472 return SIDE_VISITOR_STATUS_OK;
1473 }
1474
1475 static
1476 void tracer_print_dynamic_vla_visitor(const struct side_arg *item)
1477 {
1478 enum side_visitor_status status;
1479 struct tracer_dynamic_vla_visitor_priv tracer_priv = {
1480 .i = 0,
1481 };
1482 const struct side_tracer_visitor_ctx tracer_ctx = {
1483 .write_elem = tracer_dynamic_vla_write_elem_cb,
1484 .priv = &tracer_priv,
1485 };
1486 void *app_ctx = item->u.side_dynamic.side_dynamic_vla_visitor.app_ctx;
1487
1488 print_attributes("attr", "::", item->u.side_dynamic.side_dynamic_vla_visitor.attr, item->u.side_dynamic.side_dynamic_vla_visitor.nr_attr);
1489 printf("%s", item->u.side_dynamic.side_dynamic_vla_visitor.nr_attr ? ", " : "");
1490 printf("elements:: ");
1491 printf("[ ");
1492 status = item->u.side_dynamic.side_dynamic_vla_visitor.visitor(&tracer_ctx, app_ctx);
1493 switch (status) {
1494 case SIDE_VISITOR_STATUS_OK:
1495 break;
1496 case SIDE_VISITOR_STATUS_ERROR:
1497 fprintf(stderr, "ERROR: Visitor error\n");
1498 abort();
1499 }
1500 printf(" ]");
1501 }
1502
1503 static
1504 void tracer_print_dynamic(const struct side_arg *item)
1505 {
1506 printf("{ ");
1507 switch (item->type) {
1508 /* Dynamic basic types */
1509 case SIDE_TYPE_DYNAMIC_NULL:
1510 tracer_print_type_header("::", item->u.side_dynamic.side_null.attr, item->u.side_dynamic.side_null.nr_attr);
1511 printf("<NULL TYPE>");
1512 break;
1513 case SIDE_TYPE_DYNAMIC_BOOL:
1514 tracer_print_type_bool("::", &item->u.side_dynamic.side_bool.type, &item->u.side_dynamic.side_bool.value, 0);
1515 break;
1516 case SIDE_TYPE_DYNAMIC_INTEGER:
1517 tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0,
1518 TRACER_DISPLAY_BASE_10);
1519 break;
1520 case SIDE_TYPE_DYNAMIC_BYTE:
1521 tracer_print_type_header("::", item->u.side_dynamic.side_byte.type.attr, item->u.side_dynamic.side_byte.type.nr_attr);
1522 printf("0x%" PRIx8, item->u.side_dynamic.side_byte.value);
1523 break;
1524 case SIDE_TYPE_DYNAMIC_POINTER:
1525 tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0,
1526 TRACER_DISPLAY_BASE_16);
1527 break;
1528 case SIDE_TYPE_DYNAMIC_FLOAT:
1529 tracer_print_type_float("::", &item->u.side_dynamic.side_float.type,
1530 &item->u.side_dynamic.side_float.value);
1531 break;
1532 case SIDE_TYPE_DYNAMIC_STRING:
1533 tracer_print_type_header("::", item->u.side_dynamic.side_string.type.attr, item->u.side_dynamic.side_string.type.nr_attr);
1534 printf("\"%s\"", (const char *)(uintptr_t) item->u.side_dynamic.side_string.value);
1535 break;
1536
1537 /* Dynamic compound types */
1538 case SIDE_TYPE_DYNAMIC_STRUCT:
1539 tracer_print_dynamic_struct(item->u.side_dynamic.side_dynamic_struct);
1540 break;
1541 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR:
1542 tracer_print_dynamic_struct_visitor(item);
1543 break;
1544 case SIDE_TYPE_DYNAMIC_VLA:
1545 tracer_print_dynamic_vla(item->u.side_dynamic.side_dynamic_vla);
1546 break;
1547 case SIDE_TYPE_DYNAMIC_VLA_VISITOR:
1548 tracer_print_dynamic_vla_visitor(item);
1549 break;
1550 default:
1551 fprintf(stderr, "<UNKNOWN TYPE>\n");
1552 abort();
1553 }
1554 printf(" }");
1555 }
1556
1557 static
1558 void tracer_print_static_fields(const struct side_event_description *desc,
1559 const struct side_arg_vec *side_arg_vec,
1560 uint32_t *nr_items)
1561 {
1562 const struct side_arg *sav = side_arg_vec->sav;
1563 uint32_t i, side_sav_len = side_arg_vec->len;
1564
1565 printf("provider: %s, event: %s", desc->provider_name, desc->event_name);
1566 if (desc->nr_fields != side_sav_len) {
1567 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n");
1568 abort();
1569 }
1570 print_attributes(", attr", ":", desc->attr, desc->nr_attr);
1571 printf("%s", side_sav_len ? ", fields: [ " : "");
1572 for (i = 0; i < side_sav_len; i++) {
1573 printf("%s", i ? ", " : "");
1574 tracer_print_field(&desc->fields[i], &sav[i]);
1575 }
1576 if (nr_items)
1577 *nr_items = i;
1578 if (side_sav_len)
1579 printf(" ]");
1580 }
1581
1582 void tracer_call(const struct side_event_description *desc,
1583 const struct side_arg_vec *side_arg_vec,
1584 void *priv __attribute__((unused)))
1585 {
1586 uint32_t nr_fields = 0;
1587
1588 tracer_print_static_fields(desc, side_arg_vec, &nr_fields);
1589 printf("\n");
1590 }
1591
1592 void tracer_call_variadic(const struct side_event_description *desc,
1593 const struct side_arg_vec *side_arg_vec,
1594 const struct side_arg_dynamic_struct *var_struct,
1595 void *priv __attribute__((unused)))
1596 {
1597 uint32_t nr_fields = 0, i, var_struct_len = var_struct->len;
1598
1599 tracer_print_static_fields(desc, side_arg_vec, &nr_fields);
1600
1601 if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) {
1602 fprintf(stderr, "ERROR: unexpected non-variadic event description\n");
1603 abort();
1604 }
1605 print_attributes(", attr ", "::", var_struct->attr, var_struct->nr_attr);
1606 printf("%s", var_struct_len ? ", fields:: [ " : "");
1607 for (i = 0; i < var_struct_len; i++, nr_fields++) {
1608 printf("%s", i ? ", " : "");
1609 printf("%s:: ", var_struct->fields[i].field_name);
1610 tracer_print_dynamic(&var_struct->fields[i].elem);
1611 }
1612 if (i)
1613 printf(" ]");
1614 printf("\n");
1615 }
1616
1617 void tracer_event_notification(enum side_tracer_notification notif,
1618 struct side_event_description **events, uint32_t nr_events, void *priv)
1619 {
1620 uint32_t i;
1621 int ret;
1622
1623 printf("----------------------------------------------------------\n");
1624 printf("Tracer notified of events %s\n",
1625 notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS ? "inserted" : "removed");
1626 for (i = 0; i < nr_events; i++) {
1627 struct side_event_description *event = events[i];
1628
1629 /* Skip NULL pointers */
1630 if (!event)
1631 continue;
1632 printf("provider: %s, event: %s\n",
1633 event->provider_name, event->event_name);
1634 if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) {
1635 if (event->flags & SIDE_EVENT_FLAG_VARIADIC) {
1636 ret = side_tracer_callback_variadic_register(event, tracer_call_variadic, NULL);
1637 if (ret)
1638 abort();
1639 } else {
1640 ret = side_tracer_callback_register(event, tracer_call, NULL);
1641 if (ret)
1642 abort();
1643 }
1644 } else {
1645 if (event->flags & SIDE_EVENT_FLAG_VARIADIC) {
1646 ret = side_tracer_callback_variadic_unregister(event, tracer_call_variadic, NULL);
1647 if (ret)
1648 abort();
1649 } else {
1650 ret = side_tracer_callback_unregister(event, tracer_call, NULL);
1651 if (ret)
1652 abort();
1653 }
1654 }
1655 }
1656 printf("----------------------------------------------------------\n");
1657 }
1658
1659 static __attribute__((constructor))
1660 void tracer_init(void);
1661 static
1662 void tracer_init(void)
1663 {
1664 tracer_handle = side_tracer_event_notification_register(tracer_event_notification, NULL);
1665 if (!tracer_handle)
1666 abort();
1667 }
1668
1669 static __attribute__((destructor))
1670 void tracer_exit(void);
1671 static
1672 void tracer_exit(void)
1673 {
1674 side_tracer_event_notification_unregister(tracer_handle);
1675 }
This page took 0.0807 seconds and 4 git commands to generate.