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