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