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