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