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