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