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