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