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