1 // SPDX-License-Identifier: MIT
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 #include <side/trace.h>
16 enum tracer_display_base
{
17 TRACER_DISPLAY_BASE_2
,
18 TRACER_DISPLAY_BASE_8
,
19 TRACER_DISPLAY_BASE_10
,
20 TRACER_DISPLAY_BASE_16
,
24 uint64_t u
[NR_SIDE_INTEGER128_SPLIT
];
25 int64_t s
[NR_SIDE_INTEGER128_SPLIT
];
28 static struct side_tracer_handle
*tracer_handle
;
31 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
33 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
);
35 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
37 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
39 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
);
41 void tracer_print_dynamic(const struct side_arg
*dynamic_item
);
43 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
45 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
47 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
48 enum tracer_display_base default_base
);
50 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
52 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
54 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
56 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
58 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
60 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
61 const void *_length_ptr
);
63 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
);
66 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
67 size_t *strlen_with_null
,
70 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
;
71 const char *str
= p
, *fromcode
;
72 char *inbuf
= (char *) p
, *outbuf
, *buf
;
78 *strlen_with_null
= strlen(str
) + 1;
79 *output_str
= (char *) str
;
83 const uint16_t *p16
= p
;
86 case SIDE_TYPE_BYTE_ORDER_LE
:
88 fromcode
= "UTF-16LE";
91 case SIDE_TYPE_BYTE_ORDER_BE
:
93 fromcode
= "UTF-16BE";
97 fprintf(stderr
, "Unknown byte order\n");
103 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
104 * { ef, bf, bf } UTF-8 (3 bytes).
106 bufsize
= inbytesleft
/ 2 * 3 + 1;
111 const uint32_t *p32
= p
;
113 switch (byte_order
) {
114 case SIDE_TYPE_BYTE_ORDER_LE
:
116 fromcode
= "UTF-32LE";
119 case SIDE_TYPE_BYTE_ORDER_BE
:
121 fromcode
= "UTF-32BE";
125 fprintf(stderr
, "Unknown byte order\n");
131 * Each 4-byte UTF-32 character converts to at most a
132 * 4-byte UTF-8 character.
134 bufsize
= inbytesleft
+ 1;
138 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
142 cd
= iconv_open("UTF8", fromcode
);
143 if (cd
== (iconv_t
) -1) {
144 perror("iconv_open");
147 buf
= malloc(bufsize
);
151 outbuf
= (char *) buf
;
152 outbytesleft
= bufsize
;
153 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
154 if (ret
== (size_t) -1) {
159 fprintf(stderr
, "Buffer too small to convert string input\n");
163 if (iconv_close(cd
) == -1) {
164 perror("iconv_close");
167 if (strlen_with_null
)
168 *strlen_with_null
= outbuf
- buf
;
173 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
174 size_t *strlen_with_null
)
176 char *output_str
= NULL
;
178 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
179 printf("\"%s\"", output_str
);
185 void side_check_value_u64(union int_value v
)
187 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
]) {
188 fprintf(stderr
, "Unexpected integer value\n");
194 void side_check_value_s64(union int_value v
)
196 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63)) {
197 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] != ~0LL) {
198 fprintf(stderr
, "Unexpected integer value\n");
202 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
]) {
203 fprintf(stderr
, "Unexpected integer value\n");
210 int64_t get_attr_integer64_value(const struct side_attr
*attr
)
214 switch (side_enum_get(attr
->value
.type
)) {
215 case SIDE_ATTR_TYPE_U8
:
216 val
= attr
->value
.u
.integer_value
.side_u8
;
218 case SIDE_ATTR_TYPE_U16
:
219 val
= attr
->value
.u
.integer_value
.side_u16
;
221 case SIDE_ATTR_TYPE_U32
:
222 val
= attr
->value
.u
.integer_value
.side_u32
;
224 case SIDE_ATTR_TYPE_U64
:
225 val
= attr
->value
.u
.integer_value
.side_u64
;
227 case SIDE_ATTR_TYPE_U128
:
229 union int_value v
= {
231 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
],
232 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
235 side_check_value_u64(v
);
236 val
= v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
239 case SIDE_ATTR_TYPE_S8
:
240 val
= attr
->value
.u
.integer_value
.side_s8
;
242 case SIDE_ATTR_TYPE_S16
:
243 val
= attr
->value
.u
.integer_value
.side_s16
;
245 case SIDE_ATTR_TYPE_S32
:
246 val
= attr
->value
.u
.integer_value
.side_s32
;
248 case SIDE_ATTR_TYPE_S64
:
249 val
= attr
->value
.u
.integer_value
.side_s64
;
251 case SIDE_ATTR_TYPE_S128
:
253 union int_value v
= {
255 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
],
256 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
259 side_check_value_s64(v
);
260 val
= v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
264 fprintf(stderr
, "Unexpected attribute type\n");
271 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
272 enum tracer_display_base default_base
)
276 for (i
= 0; i
< nr_attr
; i
++) {
277 const struct side_attr
*attr
= &_attr
[i
];
278 char *utf8_str
= NULL
;
281 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
282 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
283 cmp
= strcmp(utf8_str
, "std.integer.base");
284 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
287 int64_t val
= get_attr_integer64_value(attr
);
291 return TRACER_DISPLAY_BASE_2
;
293 return TRACER_DISPLAY_BASE_8
;
295 return TRACER_DISPLAY_BASE_10
;
297 return TRACER_DISPLAY_BASE_16
;
299 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
304 return default_base
; /* Default */
308 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
310 char *utf8_str
= NULL
;
312 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
313 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
314 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
315 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
317 switch (side_enum_get(attr
->value
.type
)) {
318 case SIDE_ATTR_TYPE_BOOL
:
319 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
321 case SIDE_ATTR_TYPE_U8
:
322 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
324 case SIDE_ATTR_TYPE_U16
:
325 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
327 case SIDE_ATTR_TYPE_U32
:
328 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
330 case SIDE_ATTR_TYPE_U64
:
331 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
333 case SIDE_ATTR_TYPE_U128
:
334 if (attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
335 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
337 printf("0x%" PRIx64
"%016" PRIx64
,
338 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
339 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
342 case SIDE_ATTR_TYPE_S8
:
343 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
345 case SIDE_ATTR_TYPE_S16
:
346 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
348 case SIDE_ATTR_TYPE_S32
:
349 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
351 case SIDE_ATTR_TYPE_S64
:
352 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
354 case SIDE_ATTR_TYPE_S128
:
355 if (attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
356 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
358 printf("0x%" PRIx64
"%016" PRIx64
,
359 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
360 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
363 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
365 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
368 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
371 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
373 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
376 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
379 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
381 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
384 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
387 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
389 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
392 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
395 case SIDE_ATTR_TYPE_STRING
:
396 tracer_print_string(side_ptr_get(attr
->value
.u
.string_value
.p
),
397 attr
->value
.u
.string_value
.unit_size
,
398 side_enum_get(attr
->value
.u
.string_value
.byte_order
), NULL
);
401 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
408 void print_attributes(const char *prefix_str
, const char *separator
,
409 const struct side_attr
*attr
, uint32_t nr_attr
)
415 printf("%s%s [ ", prefix_str
, separator
);
416 for (i
= 0; i
< nr_attr
; i
++) {
417 printf("%s", i
? ", " : "");
418 tracer_print_attr_type(separator
, &attr
[i
]);
424 union int_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
425 const union side_integer_value
*value
,
426 uint16_t offset_bits
, uint16_t *_len_bits
)
428 union int_value v
= {};
432 if (!type_integer
->len_bits
)
433 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
435 len_bits
= type_integer
->len_bits
;
436 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
438 reverse_bo
= side_enum_get(type_integer
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
439 switch (type_integer
->integer_size
) {
441 if (type_integer
->signedness
)
442 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s8
;
444 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u8
;
447 if (type_integer
->signedness
) {
450 side_s16
= value
->side_s16
;
452 side_s16
= side_bswap_16(side_s16
);
453 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s16
;
457 side_u16
= value
->side_u16
;
459 side_u16
= side_bswap_16(side_u16
);
460 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u16
;
464 if (type_integer
->signedness
) {
467 side_s32
= value
->side_s32
;
469 side_s32
= side_bswap_32(side_s32
);
470 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s32
;
474 side_u32
= value
->side_u32
;
476 side_u32
= side_bswap_32(side_u32
);
477 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u32
;
481 if (type_integer
->signedness
) {
484 side_s64
= value
->side_s64
;
486 side_s64
= side_bswap_64(side_s64
);
487 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
;
491 side_u64
= value
->side_u64
;
493 side_u64
= side_bswap_64(side_u64
);
494 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
;
498 if (type_integer
->signedness
) {
499 int64_t side_s64
[NR_SIDE_INTEGER128_SPLIT
];
501 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
];
502 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
504 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_LOW
]);
505 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_HIGH
]);
506 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
507 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
509 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
510 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
513 uint64_t side_u64
[NR_SIDE_INTEGER128_SPLIT
];
515 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
];
516 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
518 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_LOW
]);
519 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_HIGH
]);
520 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
521 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
523 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
524 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
531 if (type_integer
->integer_size
<= 8) {
532 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >>= offset_bits
;
534 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
535 if (type_integer
->signedness
) {
537 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (len_bits
- 1))) {
538 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] |= ~((1ULL << len_bits
) - 1);
539 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = ~0ULL;
544 //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits
545 if (len_bits
< 128 || offset_bits
!= 0)
549 *_len_bits
= len_bits
;
554 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int_value v
)
556 uint32_t i
, print_count
= 0;
558 side_check_value_s64(v
);
559 printf(", labels: [ ");
560 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
561 const struct side_enum_mapping
*mapping
= &side_ptr_get(mappings
->mappings
)[i
];
563 if (mapping
->range_end
< mapping
->range_begin
) {
564 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
565 mapping
->range_begin
, mapping
->range_end
);
568 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= mapping
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= mapping
->range_end
) {
569 printf("%s", print_count
++ ? ", " : "");
570 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
571 side_enum_get(mapping
->label
.byte_order
), NULL
);
575 printf("<NO LABEL>");
580 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
582 const struct side_enum_mappings
*mappings
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
583 const struct side_type
*elem_type
= side_ptr_get(type_desc
->u
.side_enum
.elem_type
);
586 if (side_enum_get(elem_type
->type
) != side_enum_get(item
->type
)) {
587 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
590 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
591 &item
->u
.side_static
.integer_value
, 0, NULL
);
592 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
593 printf("%s", mappings
->nr_attr
? ", " : "");
594 tracer_print_type(elem_type
, item
);
595 print_enum_labels(mappings
, v
);
599 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
603 switch (side_enum_get(elem_type
->type
)) {
618 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
620 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
627 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
628 const struct side_arg
*item
)
630 const struct side_enum_bitmap_mappings
*side_enum_mappings
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
631 const struct side_type
*enum_elem_type
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.elem_type
), *elem_type
;
632 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
633 const struct side_arg
*array_item
;
635 switch (side_enum_get(enum_elem_type
->type
)) {
636 case SIDE_TYPE_U8
: /* Fall-through */
637 case SIDE_TYPE_BYTE
: /* Fall-through */
638 case SIDE_TYPE_U16
: /* Fall-through */
639 case SIDE_TYPE_U32
: /* Fall-through */
640 case SIDE_TYPE_U64
: /* Fall-through */
641 case SIDE_TYPE_U128
: /* Fall-through */
642 case SIDE_TYPE_S8
: /* Fall-through */
643 case SIDE_TYPE_S16
: /* Fall-through */
644 case SIDE_TYPE_S32
: /* Fall-through */
645 case SIDE_TYPE_S64
: /* Fall-through */
647 elem_type
= enum_elem_type
;
651 case SIDE_TYPE_ARRAY
:
652 elem_type
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
653 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_array
)->sav
);
654 nr_items
= type_desc
->u
.side_array
.length
;
657 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
658 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_vla
)->sav
);
659 nr_items
= side_ptr_get(item
->u
.side_static
.side_vla
)->len
;
662 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
665 stride_bit
= elem_type_to_stride(elem_type
);
667 print_attributes("attr", ":", side_ptr_get(side_enum_mappings
->attr
), side_enum_mappings
->nr_attr
);
668 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
669 printf("labels: [ ");
670 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
671 const struct side_enum_bitmap_mapping
*mapping
= &side_ptr_get(side_enum_mappings
->mappings
)[i
];
675 if (mapping
->range_end
< mapping
->range_begin
) {
676 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
677 mapping
->range_begin
, mapping
->range_end
);
680 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
681 if (bit
> (nr_items
* stride_bit
) - 1)
683 if (side_enum_get(elem_type
->type
) == SIDE_TYPE_BYTE
) {
684 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
685 if (v
& (1ULL << (bit
% 8))) {
690 union int_value v
= {};
692 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
693 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
695 side_check_value_u64(v
);
696 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (bit
% stride_bit
))) {
704 printf("%s", print_count
++ ? ", " : "");
705 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
706 side_enum_get(mapping
->label
.byte_order
), NULL
);
710 printf("<NO LABEL>");
715 void print_integer_binary(uint64_t v
[NR_SIDE_INTEGER128_SPLIT
], int bits
)
722 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 64 - bits
;
723 for (bit
= 0; bit
< bits
; bit
++) {
724 printf("%c", v
[SIDE_INTEGER128_SPLIT_HIGH
] & (1ULL << 63) ? '1' : '0');
725 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 1;
729 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 64 - bits
;
730 for (bit
= 0; bit
< bits
; bit
++) {
731 printf("%c", v
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63) ? '1' : '0');
732 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 1;
737 void tracer_print_type_header(const char *separator
,
738 const struct side_attr
*attr
, uint32_t nr_attr
)
740 print_attributes("attr", separator
, attr
, nr_attr
);
741 printf("%s", nr_attr
? ", " : "");
742 printf("value%s ", separator
);
746 void tracer_print_type_bool(const char *separator
,
747 const struct side_type_bool
*type_bool
,
748 const union side_bool_value
*value
,
749 uint16_t offset_bits
)
755 if (!type_bool
->len_bits
)
756 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
758 len_bits
= type_bool
->len_bits
;
759 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
761 reverse_bo
= side_enum_get(type_bool
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
762 switch (type_bool
->bool_size
) {
764 v
= value
->side_bool8
;
770 side_u16
= value
->side_bool16
;
772 side_u16
= side_bswap_16(side_u16
);
780 side_u32
= value
->side_bool32
;
782 side_u32
= side_bswap_32(side_u32
);
790 side_u64
= value
->side_bool64
;
792 side_u64
= side_bswap_64(side_u64
);
801 v
&= (1ULL << len_bits
) - 1;
802 tracer_print_type_header(separator
, side_ptr_get(type_bool
->attr
), type_bool
->nr_attr
);
803 printf("%s", v
? "true" : "false");
807 #define U128_BASE_10_ARRAY_LEN sizeof("340282366920938463463374607431768211455")
809 #define S128_BASE_10_ARRAY_LEN sizeof("-170141183460469231731687303715884105728")
812 * u128_tostring_base_10 is inspired from https://stackoverflow.com/a/4364365
815 void u128_tostring_base_10(union int_value v
, char str
[U128_BASE_10_ARRAY_LEN
])
817 int d
[39] = {}, i
, j
, str_i
= 0;
819 for (i
= 63; i
> -1; i
--) {
820 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
822 for (j
= 0; j
< 39; j
++)
824 for (j
= 0; j
< 38; j
++) {
825 d
[j
+ 1] += d
[j
] / 10;
829 for (i
= 63; i
> -1; i
--) {
830 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
833 for (j
= 0; j
< 39; j
++)
836 for (j
= 0; j
< 38; j
++) {
837 d
[j
+ 1] += d
[j
] / 10;
841 for (i
= 38; i
> 0; i
--)
844 for (; i
> -1; i
--) {
845 str
[str_i
++] = '0' + d
[i
];
851 void s128_tostring_base_10(union int_value v
, char str
[S128_BASE_10_ARRAY_LEN
])
853 uint64_t low
, high
, tmp
;
855 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] >= 0) {
857 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
858 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
859 u128_tostring_base_10(v
, str
);
865 /* Special-case minimum value, which has no positive signed representation. */
866 if ((v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] == INT64_MIN
) && (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] == 0)) {
867 memcpy(str
, "-170141183460469231731687303715884105728", S128_BASE_10_ARRAY_LEN
);
870 /* Convert from two's complement. */
871 high
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
872 low
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
876 /* Clear overflow to sign bit. */
877 high
&= ~0x8000000000000000ULL
;
879 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = tmp
;
880 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = high
;
882 u128_tostring_base_10(v
, str
+ 1);
886 #define U128_BASE_8_ARRAY_LEN sizeof("3777777777777777777777777777777777777777777")
889 void u128_tostring_base_8(union int_value v
, char str
[U128_BASE_8_ARRAY_LEN
])
891 int d
[43] = {}, i
, j
, str_i
= 0;
893 for (i
= 63; i
> -1; i
--) {
894 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
896 for (j
= 0; j
< 43; j
++)
898 for (j
= 0; j
< 42; j
++) {
899 d
[j
+ 1] += d
[j
] / 8;
903 for (i
= 63; i
> -1; i
--) {
904 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
907 for (j
= 0; j
< 43; j
++)
910 for (j
= 0; j
< 42; j
++) {
911 d
[j
+ 1] += d
[j
] / 8;
915 for (i
= 42; i
> 0; i
--)
918 for (; i
> -1; i
--) {
919 str
[str_i
++] = '0' + d
[i
];
925 void tracer_print_type_integer(const char *separator
,
926 const struct side_type_integer
*type_integer
,
927 const union side_integer_value
*value
,
928 uint16_t offset_bits
,
929 enum tracer_display_base default_base
)
931 enum tracer_display_base base
;
935 v
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
936 tracer_print_type_header(separator
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
937 base
= get_attr_display_base(side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
, default_base
);
939 case TRACER_DISPLAY_BASE_2
:
940 print_integer_binary(v
.u
, len_bits
);
942 case TRACER_DISPLAY_BASE_8
:
943 /* Clear sign bits beyond len_bits */
945 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
946 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
947 } else if (len_bits
< 128) {
948 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
950 if (len_bits
<= 64) {
951 printf("0o%" PRIo64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
953 char str
[U128_BASE_8_ARRAY_LEN
];
955 u128_tostring_base_8(v
, str
);
959 case TRACER_DISPLAY_BASE_10
:
960 if (len_bits
<= 64) {
961 if (type_integer
->signedness
)
962 printf("%" PRId64
, v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
964 printf("%" PRIu64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
966 if (type_integer
->signedness
) {
967 char str
[S128_BASE_10_ARRAY_LEN
];
968 s128_tostring_base_10(v
, str
);
971 char str
[U128_BASE_10_ARRAY_LEN
];
972 u128_tostring_base_10(v
, str
);
977 case TRACER_DISPLAY_BASE_16
:
978 /* Clear sign bits beyond len_bits */
980 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
981 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
982 } else if (len_bits
< 128) {
983 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
985 if (len_bits
<= 64 || v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
986 printf("0x%" PRIx64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
988 printf("0x%" PRIx64
"%016" PRIx64
,
989 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
],
990 v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
999 void tracer_print_type_float(const char *separator
,
1000 const struct side_type_float
*type_float
,
1001 const union side_float_value
*value
)
1005 tracer_print_type_header(separator
, side_ptr_get(type_float
->attr
), type_float
->nr_attr
);
1006 reverse_bo
= side_enum_get(type_float
->byte_order
) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
1007 switch (type_float
->float_size
) {
1015 .f
= value
->side_float_binary16
,
1019 float16
.u
= side_bswap_16(float16
.u
);
1020 printf("%g", (double) float16
.f
);
1023 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
1034 .f
= value
->side_float_binary32
,
1038 float32
.u
= side_bswap_32(float32
.u
);
1039 printf("%g", (double) float32
.f
);
1042 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
1053 .f
= value
->side_float_binary64
,
1057 float64
.u
= side_bswap_64(float64
.u
);
1058 printf("%g", (double) float64
.f
);
1061 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
1072 .f
= value
->side_float_binary128
,
1076 side_bswap_128p(float128
.arr
);
1077 printf("%Lg", (long double) float128
.f
);
1080 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
1085 fprintf(stderr
, "ERROR: Unknown float size\n");
1091 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
)
1093 enum side_type_label type
;
1095 switch (side_enum_get(type_desc
->type
)) {
1096 case SIDE_TYPE_ENUM
:
1097 switch (side_enum_get(item
->type
)) {
1102 case SIDE_TYPE_U128
:
1107 case SIDE_TYPE_S128
:
1110 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1116 case SIDE_TYPE_ENUM_BITMAP
:
1117 switch (side_enum_get(item
->type
)) {
1119 case SIDE_TYPE_BYTE
:
1123 case SIDE_TYPE_U128
:
1124 case SIDE_TYPE_ARRAY
:
1128 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1134 case SIDE_TYPE_GATHER_ENUM
:
1135 switch (side_enum_get(item
->type
)) {
1136 case SIDE_TYPE_GATHER_INTEGER
:
1139 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1145 case SIDE_TYPE_DYNAMIC
:
1146 switch (side_enum_get(item
->type
)) {
1147 case SIDE_TYPE_DYNAMIC_NULL
:
1148 case SIDE_TYPE_DYNAMIC_BOOL
:
1149 case SIDE_TYPE_DYNAMIC_INTEGER
:
1150 case SIDE_TYPE_DYNAMIC_BYTE
:
1151 case SIDE_TYPE_DYNAMIC_POINTER
:
1152 case SIDE_TYPE_DYNAMIC_FLOAT
:
1153 case SIDE_TYPE_DYNAMIC_STRING
:
1154 case SIDE_TYPE_DYNAMIC_STRUCT
:
1155 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1156 case SIDE_TYPE_DYNAMIC_VLA
:
1157 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1160 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
1167 if (side_enum_get(type_desc
->type
) != side_enum_get(item
->type
)) {
1168 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1174 if (side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM_BITMAP
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_GATHER_ENUM
)
1175 type
= side_enum_get(type_desc
->type
);
1177 type
= side_enum_get(item
->type
);
1181 /* Stack-copy basic types */
1182 case SIDE_TYPE_NULL
:
1183 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
1184 type_desc
->u
.side_null
.nr_attr
);
1185 printf("<NULL TYPE>");
1188 case SIDE_TYPE_BOOL
:
1189 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
1196 case SIDE_TYPE_U128
:
1201 case SIDE_TYPE_S128
:
1202 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1203 TRACER_DISPLAY_BASE_10
);
1206 case SIDE_TYPE_BYTE
:
1207 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
1208 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
1211 case SIDE_TYPE_POINTER
:
1212 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1213 TRACER_DISPLAY_BASE_16
);
1216 case SIDE_TYPE_FLOAT_BINARY16
:
1217 case SIDE_TYPE_FLOAT_BINARY32
:
1218 case SIDE_TYPE_FLOAT_BINARY64
:
1219 case SIDE_TYPE_FLOAT_BINARY128
:
1220 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
1223 case SIDE_TYPE_STRING_UTF8
:
1224 case SIDE_TYPE_STRING_UTF16
:
1225 case SIDE_TYPE_STRING_UTF32
:
1226 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
1227 tracer_print_string(side_ptr_get(item
->u
.side_static
.string_value
),
1228 type_desc
->u
.side_string
.unit_size
, side_enum_get(type_desc
->u
.side_string
.byte_order
), NULL
);
1231 /* Stack-copy compound types */
1232 case SIDE_TYPE_STRUCT
:
1233 tracer_print_struct(type_desc
, side_ptr_get(item
->u
.side_static
.side_struct
));
1235 case SIDE_TYPE_VARIANT
:
1236 tracer_print_variant(type_desc
, side_ptr_get(item
->u
.side_static
.side_variant
));
1238 case SIDE_TYPE_ARRAY
:
1239 tracer_print_array(type_desc
, side_ptr_get(item
->u
.side_static
.side_array
));
1242 tracer_print_vla(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla
));
1244 case SIDE_TYPE_VLA_VISITOR
:
1245 tracer_print_vla_visitor(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla_visitor
));
1248 /* Stack-copy enumeration types */
1249 case SIDE_TYPE_ENUM
:
1250 tracer_print_enum(type_desc
, item
);
1252 case SIDE_TYPE_ENUM_BITMAP
:
1253 tracer_print_enum_bitmap(type_desc
, item
);
1256 /* Gather basic types */
1257 case SIDE_TYPE_GATHER_BOOL
:
1258 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_bool_gather_ptr
));
1260 case SIDE_TYPE_GATHER_INTEGER
:
1261 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1262 TRACER_DISPLAY_BASE_10
);
1264 case SIDE_TYPE_GATHER_BYTE
:
1265 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_byte_gather_ptr
));
1267 case SIDE_TYPE_GATHER_POINTER
:
1268 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1269 TRACER_DISPLAY_BASE_16
);
1271 case SIDE_TYPE_GATHER_FLOAT
:
1272 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_float_gather_ptr
));
1274 case SIDE_TYPE_GATHER_STRING
:
1275 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_string_gather_ptr
));
1278 /* Gather compound type */
1279 case SIDE_TYPE_GATHER_STRUCT
:
1280 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_struct_gather_ptr
));
1282 case SIDE_TYPE_GATHER_ARRAY
:
1283 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_array_gather_ptr
));
1285 case SIDE_TYPE_GATHER_VLA
:
1286 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_vla_gather
.ptr
),
1287 side_ptr_get(item
->u
.side_static
.side_vla_gather
.length_ptr
));
1290 /* Gather enumeration types */
1291 case SIDE_TYPE_GATHER_ENUM
:
1292 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
));
1295 /* Dynamic basic types */
1296 case SIDE_TYPE_DYNAMIC_NULL
:
1297 case SIDE_TYPE_DYNAMIC_BOOL
:
1298 case SIDE_TYPE_DYNAMIC_INTEGER
:
1299 case SIDE_TYPE_DYNAMIC_BYTE
:
1300 case SIDE_TYPE_DYNAMIC_POINTER
:
1301 case SIDE_TYPE_DYNAMIC_FLOAT
:
1302 case SIDE_TYPE_DYNAMIC_STRING
:
1304 /* Dynamic compound types */
1305 case SIDE_TYPE_DYNAMIC_STRUCT
:
1306 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1307 case SIDE_TYPE_DYNAMIC_VLA
:
1308 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1309 tracer_print_dynamic(item
);
1312 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1319 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1321 printf("%s: ", side_ptr_get(item_desc
->field_name
));
1322 tracer_print_type(&item_desc
->side_type
, item
);
1326 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1328 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1329 const struct side_type_struct
*side_struct
= side_ptr_get(type_desc
->u
.side_struct
);
1330 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1332 if (side_struct
->nr_fields
!= side_sav_len
) {
1333 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1336 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1337 printf("%s", side_struct
->nr_attr
? ", " : "");
1338 printf("fields: { ");
1339 for (i
= 0; i
< side_sav_len
; i
++) {
1340 printf("%s", i
? ", " : "");
1341 tracer_print_field(&side_ptr_get(side_struct
->fields
)[i
], &sav
[i
]);
1347 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1349 const struct side_type_variant
*side_type_variant
= side_ptr_get(type_desc
->u
.side_variant
);
1350 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1354 if (side_enum_get(selector_type
->type
) != side_enum_get(side_arg_variant
->selector
.type
)) {
1355 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1358 switch (side_enum_get(selector_type
->type
)) {
1363 case SIDE_TYPE_U128
:
1368 case SIDE_TYPE_S128
:
1371 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1374 v
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1375 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1376 side_check_value_u64(v
);
1377 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1378 const struct side_variant_option
*option
= &side_ptr_get(side_type_variant
->options
)[i
];
1380 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= option
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= option
->range_end
) {
1381 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
);
1385 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
1390 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1392 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1393 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1395 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1396 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1399 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_array
.attr
), type_desc
->u
.side_array
.nr_attr
);
1400 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1401 printf("elements: ");
1403 for (i
= 0; i
< side_sav_len
; i
++) {
1404 printf("%s", i
? ", " : "");
1405 tracer_print_type(side_ptr_get(type_desc
->u
.side_array
.elem_type
), &sav
[i
]);
1411 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1413 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1414 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1416 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla
.attr
), type_desc
->u
.side_vla
.nr_attr
);
1417 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1418 printf("elements: ");
1420 for (i
= 0; i
< side_sav_len
; i
++) {
1421 printf("%s", i
? ", " : "");
1422 tracer_print_type(side_ptr_get(type_desc
->u
.side_vla
.elem_type
), &sav
[i
]);
1428 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1430 switch (access_mode
) {
1431 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1433 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1434 /* Dereference pointer */
1435 memcpy(&ptr
, ptr
, sizeof(const char *));
1443 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1445 switch (access_mode
) {
1446 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1448 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1449 return sizeof(void *);
1456 union int_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1459 enum side_type_gather_access_mode access_mode
=
1460 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1461 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1462 const char *ptr
= (const char *) _ptr
;
1463 union side_integer_value value
;
1465 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1466 memcpy(&value
, ptr
, integer_size_bytes
);
1467 return tracer_load_integer_value(&side_integer
->type
, &value
,
1468 side_integer
->offset_bits
, NULL
);
1472 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1474 enum side_type_gather_access_mode access_mode
=
1475 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1476 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1477 const char *ptr
= (const char *) _ptr
;
1478 union side_bool_value value
;
1480 switch (bool_size_bytes
) {
1489 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1490 memcpy(&value
, ptr
, bool_size_bytes
);
1491 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1492 type_gather
->u
.side_bool
.offset_bits
);
1493 return tracer_gather_size(access_mode
, bool_size_bytes
);
1497 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1499 enum side_type_gather_access_mode access_mode
=
1500 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1501 const char *ptr
= (const char *) _ptr
;
1504 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1505 memcpy(&value
, ptr
, 1);
1506 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_byte
.type
.attr
),
1507 type_gather
->u
.side_byte
.type
.nr_attr
);
1508 printf("0x%" PRIx8
, value
);
1509 return tracer_gather_size(access_mode
, 1);
1513 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1514 enum tracer_display_base default_base
)
1516 enum side_type_gather_access_mode access_mode
=
1517 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1518 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1519 const char *ptr
= (const char *) _ptr
;
1520 union side_integer_value value
;
1522 switch (integer_size_bytes
) {
1532 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1533 memcpy(&value
, ptr
, integer_size_bytes
);
1534 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1535 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1536 return tracer_gather_size(access_mode
, integer_size_bytes
);
1540 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1542 enum side_type_gather_access_mode access_mode
=
1543 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1544 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1545 const char *ptr
= (const char *) _ptr
;
1546 union side_float_value value
;
1548 switch (float_size_bytes
) {
1557 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1558 memcpy(&value
, ptr
, float_size_bytes
);
1559 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1560 return tracer_gather_size(access_mode
, float_size_bytes
);
1564 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1566 enum side_type_gather_access_mode access_mode
=
1567 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1568 const char *ptr
= (const char *) _ptr
;
1571 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1572 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_string
.type
.attr
),
1573 type_gather
->u
.side_string
.type
.nr_attr
);
1575 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1576 side_enum_get(type_gather
->u
.side_string
.type
.byte_order
), &string_len
);
1579 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1581 return tracer_gather_size(access_mode
, string_len
);
1585 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1590 switch (side_enum_get(type_desc
->type
)) {
1591 /* Gather basic types */
1592 case SIDE_TYPE_GATHER_BOOL
:
1593 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1595 case SIDE_TYPE_GATHER_INTEGER
:
1596 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1597 TRACER_DISPLAY_BASE_10
);
1599 case SIDE_TYPE_GATHER_BYTE
:
1600 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1602 case SIDE_TYPE_GATHER_POINTER
:
1603 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1604 TRACER_DISPLAY_BASE_16
);
1606 case SIDE_TYPE_GATHER_FLOAT
:
1607 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1609 case SIDE_TYPE_GATHER_STRING
:
1610 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1613 /* Gather enum types */
1614 case SIDE_TYPE_GATHER_ENUM
:
1615 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1618 /* Gather compound types */
1619 case SIDE_TYPE_GATHER_STRUCT
:
1620 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1622 case SIDE_TYPE_GATHER_ARRAY
:
1623 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1625 case SIDE_TYPE_GATHER_VLA
:
1626 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1629 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1637 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1639 const struct side_enum_mappings
*mappings
= side_ptr_get(type_gather
->u
.side_enum
.mappings
);
1640 const struct side_type
*enum_elem_type
= side_ptr_get(type_gather
->u
.side_enum
.elem_type
);
1641 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1642 enum side_type_gather_access_mode access_mode
=
1643 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1644 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1645 const char *ptr
= (const char *) _ptr
;
1646 union side_integer_value value
;
1649 switch (integer_size_bytes
) {
1659 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1660 memcpy(&value
, ptr
, integer_size_bytes
);
1661 v
= tracer_load_gather_integer_value(side_integer
, &value
);
1662 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1663 printf("%s", mappings
->nr_attr
? ", " : "");
1664 tracer_print_gather_type(enum_elem_type
, ptr
);
1665 print_enum_labels(mappings
, v
);
1666 return tracer_gather_size(access_mode
, integer_size_bytes
);
1670 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1672 printf("%s: ", side_ptr_get(field
->field_name
));
1673 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1677 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1679 enum side_type_gather_access_mode access_mode
=
1680 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1681 const struct side_type_struct
*side_struct
= side_ptr_get(type_gather
->u
.side_struct
.type
);
1682 const char *ptr
= (const char *) _ptr
;
1685 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1686 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1687 printf("%s", side_struct
->nr_attr
? ", " : "");
1688 printf("fields: { ");
1689 for (i
= 0; i
< side_struct
->nr_fields
; i
++) {
1690 printf("%s", i
? ", " : "");
1691 tracer_print_gather_field(&side_ptr_get(side_struct
->fields
)[i
], ptr
);
1694 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1698 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1700 enum side_type_gather_access_mode access_mode
=
1701 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1702 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1705 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1707 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_array
.type
.attr
), type_gather
->u
.side_array
.type
.nr_attr
);
1708 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1709 printf("elements: ");
1711 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1712 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_array
.type
.elem_type
);
1714 switch (side_enum_get(elem_type
->type
)) {
1715 case SIDE_TYPE_GATHER_VLA
:
1716 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1721 printf("%s", i
? ", " : "");
1722 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1725 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1729 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1730 const void *_length_ptr
)
1732 enum side_type_gather_access_mode access_mode
=
1733 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1734 const struct side_type
*length_type
= side_ptr_get(type_gather
->u
.side_vla
.length_type
);
1735 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1736 const char *length_ptr
= (const char *) _length_ptr
;
1737 union int_value v
= {};
1741 switch (side_enum_get(length_type
->type
)) {
1742 case SIDE_TYPE_GATHER_INTEGER
:
1745 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1748 v
= tracer_load_gather_integer_value(&length_type
->u
.side_gather
.u
.side_integer
,
1750 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] || v
.u
[SIDE_INTEGER128_SPLIT_LOW
] > UINT32_MAX
) {
1751 fprintf(stderr
, "Unexpected vla length value\n");
1754 length
= (uint32_t) v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
1755 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1757 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_vla
.type
.attr
), type_gather
->u
.side_vla
.type
.nr_attr
);
1758 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1759 printf("elements: ");
1761 for (i
= 0; i
< length
; i
++) {
1762 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_vla
.type
.elem_type
);
1764 switch (side_enum_get(elem_type
->type
)) {
1765 case SIDE_TYPE_GATHER_VLA
:
1766 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1771 printf("%s", i
? ", " : "");
1772 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1775 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1778 struct tracer_visitor_priv
{
1779 const struct side_type
*elem_type
;
1784 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1785 const struct side_arg
*elem
)
1787 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1789 printf("%s", tracer_priv
->i
++ ? ", " : "");
1790 tracer_print_type(tracer_priv
->elem_type
, elem
);
1791 return SIDE_VISITOR_STATUS_OK
;
1795 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
)
1798 enum side_visitor_status status
;
1799 struct tracer_visitor_priv tracer_priv
= {
1800 .elem_type
= side_ptr_get(type_desc
->u
.side_vla_visitor
.elem_type
),
1803 const struct side_tracer_visitor_ctx tracer_ctx
= {
1804 .write_elem
= tracer_write_elem_cb
,
1805 .priv
= &tracer_priv
,
1807 side_visitor_func func
;
1811 app_ctx
= side_ptr_get(vla_visitor
->app_ctx
);
1812 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla_visitor
.attr
), type_desc
->u
.side_vla_visitor
.nr_attr
);
1813 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1814 printf("elements: ");
1816 func
= side_ptr_get(type_desc
->u
.side_vla_visitor
.visitor
);
1817 status
= func(&tracer_ctx
, app_ctx
);
1819 case SIDE_VISITOR_STATUS_OK
:
1821 case SIDE_VISITOR_STATUS_ERROR
:
1822 fprintf(stderr
, "ERROR: Visitor error\n");
1829 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1831 const struct side_arg_dynamic_field
*fields
= side_ptr_get(dynamic_struct
->fields
);
1832 uint32_t i
, len
= dynamic_struct
->len
;
1834 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1835 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1836 printf("fields:: ");
1838 for (i
= 0; i
< len
; i
++) {
1839 printf("%s", i
? ", " : "");
1840 printf("%s:: ", side_ptr_get(fields
[i
].field_name
));
1841 tracer_print_dynamic(&fields
[i
].elem
);
1846 struct tracer_dynamic_struct_visitor_priv
{
1851 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1852 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1853 const struct side_arg_dynamic_field
*dynamic_field
)
1855 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1856 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1858 printf("%s", tracer_priv
->i
++ ? ", " : "");
1859 printf("%s:: ", side_ptr_get(dynamic_field
->field_name
));
1860 tracer_print_dynamic(&dynamic_field
->elem
);
1861 return SIDE_VISITOR_STATUS_OK
;
1865 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1867 struct side_arg_dynamic_struct_visitor
*dynamic_struct_visitor
;
1868 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1871 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1872 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1873 .priv
= &tracer_priv
,
1875 enum side_visitor_status status
;
1878 dynamic_struct_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
);
1879 if (!dynamic_struct_visitor
)
1881 app_ctx
= side_ptr_get(dynamic_struct_visitor
->app_ctx
);
1882 print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor
->attr
), dynamic_struct_visitor
->nr_attr
);
1883 printf("%s", dynamic_struct_visitor
->nr_attr
? ", " : "");
1884 printf("fields:: ");
1886 status
= side_ptr_get(dynamic_struct_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1888 case SIDE_VISITOR_STATUS_OK
:
1890 case SIDE_VISITOR_STATUS_ERROR
:
1891 fprintf(stderr
, "ERROR: Visitor error\n");
1898 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1900 const struct side_arg
*sav
= side_ptr_get(vla
->sav
);
1901 uint32_t i
, side_sav_len
= vla
->len
;
1903 print_attributes("attr", "::", side_ptr_get(vla
->attr
), vla
->nr_attr
);
1904 printf("%s", vla
->nr_attr
? ", " : "");
1905 printf("elements:: ");
1907 for (i
= 0; i
< side_sav_len
; i
++) {
1908 printf("%s", i
? ", " : "");
1909 tracer_print_dynamic(&sav
[i
]);
1914 struct tracer_dynamic_vla_visitor_priv
{
1919 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1920 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1921 const struct side_arg
*elem
)
1923 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1924 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1926 printf("%s", tracer_priv
->i
++ ? ", " : "");
1927 tracer_print_dynamic(elem
);
1928 return SIDE_VISITOR_STATUS_OK
;
1932 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1934 struct side_arg_dynamic_vla_visitor
*dynamic_vla_visitor
;
1935 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1938 const struct side_tracer_visitor_ctx tracer_ctx
= {
1939 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1940 .priv
= &tracer_priv
,
1942 enum side_visitor_status status
;
1945 dynamic_vla_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
);
1946 if (!dynamic_vla_visitor
)
1948 app_ctx
= side_ptr_get(dynamic_vla_visitor
->app_ctx
);
1949 print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor
->attr
), dynamic_vla_visitor
->nr_attr
);
1950 printf("%s", dynamic_vla_visitor
->nr_attr
? ", " : "");
1951 printf("elements:: ");
1953 status
= side_ptr_get(dynamic_vla_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1955 case SIDE_VISITOR_STATUS_OK
:
1957 case SIDE_VISITOR_STATUS_ERROR
:
1958 fprintf(stderr
, "ERROR: Visitor error\n");
1965 void tracer_print_dynamic(const struct side_arg
*item
)
1968 switch (side_enum_get(item
->type
)) {
1969 /* Dynamic basic types */
1970 case SIDE_TYPE_DYNAMIC_NULL
:
1971 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1972 item
->u
.side_dynamic
.side_null
.nr_attr
);
1973 printf("<NULL TYPE>");
1975 case SIDE_TYPE_DYNAMIC_BOOL
:
1976 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1978 case SIDE_TYPE_DYNAMIC_INTEGER
:
1979 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1980 TRACER_DISPLAY_BASE_10
);
1982 case SIDE_TYPE_DYNAMIC_BYTE
:
1983 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1984 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1986 case SIDE_TYPE_DYNAMIC_POINTER
:
1987 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1988 TRACER_DISPLAY_BASE_16
);
1990 case SIDE_TYPE_DYNAMIC_FLOAT
:
1991 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1992 &item
->u
.side_dynamic
.side_float
.value
);
1994 case SIDE_TYPE_DYNAMIC_STRING
:
1995 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1996 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1997 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
1998 side_enum_get(item
->u
.side_dynamic
.side_string
.type
.byte_order
), NULL
);
2001 /* Dynamic compound types */
2002 case SIDE_TYPE_DYNAMIC_STRUCT
:
2003 tracer_print_dynamic_struct(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct
));
2005 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
2006 tracer_print_dynamic_struct_visitor(item
);
2008 case SIDE_TYPE_DYNAMIC_VLA
:
2009 tracer_print_dynamic_vla(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla
));
2011 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
2012 tracer_print_dynamic_vla_visitor(item
);
2015 fprintf(stderr
, "<UNKNOWN TYPE>\n");
2022 void tracer_print_static_fields(const struct side_event_description
*desc
,
2023 const struct side_arg_vec
*side_arg_vec
,
2026 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
2027 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
2029 printf("provider: %s, event: %s", side_ptr_get(desc
->provider_name
), side_ptr_get(desc
->event_name
));
2030 if (desc
->nr_fields
!= side_sav_len
) {
2031 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
2034 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
2035 printf("%s", side_sav_len
? ", fields: [ " : "");
2036 for (i
= 0; i
< side_sav_len
; i
++) {
2037 printf("%s", i
? ", " : "");
2038 tracer_print_field(&side_ptr_get(desc
->fields
)[i
], &sav
[i
]);
2047 void tracer_call(const struct side_event_description
*desc
,
2048 const struct side_arg_vec
*side_arg_vec
,
2049 void *priv
__attribute__((unused
)))
2051 uint32_t nr_fields
= 0;
2053 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
2058 void tracer_call_variadic(const struct side_event_description
*desc
,
2059 const struct side_arg_vec
*side_arg_vec
,
2060 const struct side_arg_dynamic_struct
*var_struct
,
2061 void *priv
__attribute__((unused
)))
2063 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
2065 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
2067 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
2068 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
2071 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
2072 printf("%s", var_struct_len
? ", fields:: [ " : "");
2073 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
2074 printf("%s", i
? ", " : "");
2075 printf("%s:: ", side_ptr_get(side_ptr_get(var_struct
->fields
)[i
].field_name
));
2076 tracer_print_dynamic(&side_ptr_get(var_struct
->fields
)[i
].elem
);
2084 void tracer_event_notification(enum side_tracer_notification notif
,
2085 struct side_event_description
**events
, uint32_t nr_events
,
2086 void *priv
__attribute__((unused
)))
2091 printf("----------------------------------------------------------\n");
2092 printf("Tracer notified of events %s\n",
2093 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
2094 for (i
= 0; i
< nr_events
; i
++) {
2095 struct side_event_description
*event
= events
[i
];
2097 /* Skip NULL pointers */
2100 if (event
->version
!= SIDE_EVENT_DESCRIPTION_ABI_VERSION
) {
2101 printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n",
2102 event
->version
, SIDE_EVENT_DESCRIPTION_ABI_VERSION
);
2105 printf("provider: %s, event: %s\n",
2106 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2107 if (event
->struct_size
!= side_offsetofend(struct side_event_description
, side_event_description_orig_abi_last
)) {
2108 printf("Warning: Event %s.%s description contains fields unknown to the tracer\n",
2109 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2111 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
2112 if (event
->nr_side_type_label
> _NR_SIDE_TYPE_LABEL
) {
2113 printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
2114 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2115 event
->nr_side_type_label
- _NR_SIDE_TYPE_LABEL
);
2117 if (event
->nr_side_attr_type
> _NR_SIDE_ATTR_TYPE
) {
2118 printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n",
2119 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2120 event
->nr_side_attr_type
- _NR_SIDE_ATTR_TYPE
);
2122 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2123 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
);
2127 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
);
2132 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2133 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
);
2137 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
);
2143 printf("----------------------------------------------------------\n");
2146 static __attribute__((constructor
))
2147 void tracer_init(void);
2149 void tracer_init(void)
2151 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
2156 static __attribute__((destructor
))
2157 void tracer_exit(void);
2159 void tracer_exit(void)
2161 side_tracer_event_notification_unregister(tracer_handle
);