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
;
30 static uint64_t tracer_key
;
33 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
35 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
);
37 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
39 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
41 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
);
43 void tracer_print_dynamic(const struct side_arg
*dynamic_item
);
45 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
47 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
49 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
50 enum tracer_display_base default_base
);
52 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
54 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
56 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
58 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
60 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
62 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
63 const void *_length_ptr
);
65 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
);
68 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
69 size_t *strlen_with_null
,
72 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
;
73 const char *str
= p
, *fromcode
;
74 char *inbuf
= (char *) p
, *outbuf
, *buf
;
80 *strlen_with_null
= strlen(str
) + 1;
81 *output_str
= (char *) str
;
85 const uint16_t *p16
= p
;
88 case SIDE_TYPE_BYTE_ORDER_LE
:
90 fromcode
= "UTF-16LE";
93 case SIDE_TYPE_BYTE_ORDER_BE
:
95 fromcode
= "UTF-16BE";
99 fprintf(stderr
, "Unknown byte order\n");
105 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
106 * { ef, bf, bf } UTF-8 (3 bytes).
108 bufsize
= inbytesleft
/ 2 * 3 + 1;
113 const uint32_t *p32
= p
;
115 switch (byte_order
) {
116 case SIDE_TYPE_BYTE_ORDER_LE
:
118 fromcode
= "UTF-32LE";
121 case SIDE_TYPE_BYTE_ORDER_BE
:
123 fromcode
= "UTF-32BE";
127 fprintf(stderr
, "Unknown byte order\n");
133 * Each 4-byte UTF-32 character converts to at most a
134 * 4-byte UTF-8 character.
136 bufsize
= inbytesleft
+ 1;
140 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
144 cd
= iconv_open("UTF8", fromcode
);
145 if (cd
== (iconv_t
) -1) {
146 perror("iconv_open");
149 buf
= malloc(bufsize
);
153 outbuf
= (char *) buf
;
154 outbytesleft
= bufsize
;
155 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
156 if (ret
== (size_t) -1) {
161 fprintf(stderr
, "Buffer too small to convert string input\n");
165 if (iconv_close(cd
) == -1) {
166 perror("iconv_close");
169 if (strlen_with_null
)
170 *strlen_with_null
= outbuf
- buf
;
175 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
176 size_t *strlen_with_null
)
178 char *output_str
= NULL
;
180 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
181 printf("\"%s\"", output_str
);
187 void side_check_value_u64(union int_value v
)
189 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
]) {
190 fprintf(stderr
, "Unexpected integer value\n");
196 void side_check_value_s64(union int_value v
)
198 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63)) {
199 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] != ~0LL) {
200 fprintf(stderr
, "Unexpected integer value\n");
204 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
]) {
205 fprintf(stderr
, "Unexpected integer value\n");
212 int64_t get_attr_integer64_value(const struct side_attr
*attr
)
216 switch (side_enum_get(attr
->value
.type
)) {
217 case SIDE_ATTR_TYPE_U8
:
218 val
= attr
->value
.u
.integer_value
.side_u8
;
220 case SIDE_ATTR_TYPE_U16
:
221 val
= attr
->value
.u
.integer_value
.side_u16
;
223 case SIDE_ATTR_TYPE_U32
:
224 val
= attr
->value
.u
.integer_value
.side_u32
;
226 case SIDE_ATTR_TYPE_U64
:
227 val
= attr
->value
.u
.integer_value
.side_u64
;
229 case SIDE_ATTR_TYPE_U128
:
231 union int_value v
= {
233 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
],
234 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
237 side_check_value_u64(v
);
238 val
= v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
241 case SIDE_ATTR_TYPE_S8
:
242 val
= attr
->value
.u
.integer_value
.side_s8
;
244 case SIDE_ATTR_TYPE_S16
:
245 val
= attr
->value
.u
.integer_value
.side_s16
;
247 case SIDE_ATTR_TYPE_S32
:
248 val
= attr
->value
.u
.integer_value
.side_s32
;
250 case SIDE_ATTR_TYPE_S64
:
251 val
= attr
->value
.u
.integer_value
.side_s64
;
253 case SIDE_ATTR_TYPE_S128
:
255 union int_value v
= {
257 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
],
258 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
261 side_check_value_s64(v
);
262 val
= v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
266 fprintf(stderr
, "Unexpected attribute type\n");
273 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
274 enum tracer_display_base default_base
)
278 for (i
= 0; i
< nr_attr
; i
++) {
279 const struct side_attr
*attr
= &_attr
[i
];
280 char *utf8_str
= NULL
;
283 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
284 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
285 cmp
= strcmp(utf8_str
, "std.integer.base");
286 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
289 int64_t val
= get_attr_integer64_value(attr
);
293 return TRACER_DISPLAY_BASE_2
;
295 return TRACER_DISPLAY_BASE_8
;
297 return TRACER_DISPLAY_BASE_10
;
299 return TRACER_DISPLAY_BASE_16
;
301 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
306 return default_base
; /* Default */
310 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
312 char *utf8_str
= NULL
;
314 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
315 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
316 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
317 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
319 switch (side_enum_get(attr
->value
.type
)) {
320 case SIDE_ATTR_TYPE_BOOL
:
321 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
323 case SIDE_ATTR_TYPE_U8
:
324 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
326 case SIDE_ATTR_TYPE_U16
:
327 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
329 case SIDE_ATTR_TYPE_U32
:
330 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
332 case SIDE_ATTR_TYPE_U64
:
333 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
335 case SIDE_ATTR_TYPE_U128
:
336 if (attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
337 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
339 printf("0x%" PRIx64
"%016" PRIx64
,
340 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
341 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
344 case SIDE_ATTR_TYPE_S8
:
345 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
347 case SIDE_ATTR_TYPE_S16
:
348 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
350 case SIDE_ATTR_TYPE_S32
:
351 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
353 case SIDE_ATTR_TYPE_S64
:
354 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
356 case SIDE_ATTR_TYPE_S128
:
357 if (attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
358 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
360 printf("0x%" PRIx64
"%016" PRIx64
,
361 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
362 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
365 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
367 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
370 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
373 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
375 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
378 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
381 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
383 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
386 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
389 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
391 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
394 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
397 case SIDE_ATTR_TYPE_STRING
:
398 tracer_print_string(side_ptr_get(attr
->value
.u
.string_value
.p
),
399 attr
->value
.u
.string_value
.unit_size
,
400 side_enum_get(attr
->value
.u
.string_value
.byte_order
), NULL
);
403 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
410 void print_attributes(const char *prefix_str
, const char *separator
,
411 const struct side_attr
*attr
, uint32_t nr_attr
)
417 printf("%s%s [ ", prefix_str
, separator
);
418 for (i
= 0; i
< nr_attr
; i
++) {
419 printf("%s", i
? ", " : "");
420 tracer_print_attr_type(separator
, &attr
[i
]);
426 union int_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
427 const union side_integer_value
*value
,
428 uint16_t offset_bits
, uint16_t *_len_bits
)
430 union int_value v
= {};
434 if (!type_integer
->len_bits
)
435 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
437 len_bits
= type_integer
->len_bits
;
438 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
440 reverse_bo
= side_enum_get(type_integer
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
441 switch (type_integer
->integer_size
) {
443 if (type_integer
->signedness
)
444 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s8
;
446 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u8
;
449 if (type_integer
->signedness
) {
452 side_s16
= value
->side_s16
;
454 side_s16
= side_bswap_16(side_s16
);
455 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s16
;
459 side_u16
= value
->side_u16
;
461 side_u16
= side_bswap_16(side_u16
);
462 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u16
;
466 if (type_integer
->signedness
) {
469 side_s32
= value
->side_s32
;
471 side_s32
= side_bswap_32(side_s32
);
472 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s32
;
476 side_u32
= value
->side_u32
;
478 side_u32
= side_bswap_32(side_u32
);
479 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u32
;
483 if (type_integer
->signedness
) {
486 side_s64
= value
->side_s64
;
488 side_s64
= side_bswap_64(side_s64
);
489 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
;
493 side_u64
= value
->side_u64
;
495 side_u64
= side_bswap_64(side_u64
);
496 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
;
500 if (type_integer
->signedness
) {
501 int64_t side_s64
[NR_SIDE_INTEGER128_SPLIT
];
503 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
];
504 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
506 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_LOW
]);
507 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_HIGH
]);
508 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
509 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
511 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
512 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
515 uint64_t side_u64
[NR_SIDE_INTEGER128_SPLIT
];
517 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
];
518 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
520 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_LOW
]);
521 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_HIGH
]);
522 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
523 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
525 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
526 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
533 if (type_integer
->integer_size
<= 8) {
534 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >>= offset_bits
;
536 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
537 if (type_integer
->signedness
) {
539 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (len_bits
- 1))) {
540 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] |= ~((1ULL << len_bits
) - 1);
541 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = ~0ULL;
546 //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits
547 if (len_bits
< 128 || offset_bits
!= 0)
551 *_len_bits
= len_bits
;
556 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int_value v
)
558 uint32_t i
, print_count
= 0;
560 side_check_value_s64(v
);
561 printf(", labels: [ ");
562 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
563 const struct side_enum_mapping
*mapping
= &side_ptr_get(mappings
->mappings
)[i
];
565 if (mapping
->range_end
< mapping
->range_begin
) {
566 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
567 mapping
->range_begin
, mapping
->range_end
);
570 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= mapping
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= mapping
->range_end
) {
571 printf("%s", print_count
++ ? ", " : "");
572 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
573 side_enum_get(mapping
->label
.byte_order
), NULL
);
577 printf("<NO LABEL>");
582 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
584 const struct side_enum_mappings
*mappings
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
585 const struct side_type
*elem_type
= side_ptr_get(type_desc
->u
.side_enum
.elem_type
);
588 if (side_enum_get(elem_type
->type
) != side_enum_get(item
->type
)) {
589 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
592 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
593 &item
->u
.side_static
.integer_value
, 0, NULL
);
594 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
595 printf("%s", mappings
->nr_attr
? ", " : "");
596 tracer_print_type(elem_type
, item
);
597 print_enum_labels(mappings
, v
);
601 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
605 switch (side_enum_get(elem_type
->type
)) {
620 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
622 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
629 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
630 const struct side_arg
*item
)
632 const struct side_enum_bitmap_mappings
*side_enum_mappings
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
633 const struct side_type
*enum_elem_type
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.elem_type
), *elem_type
;
634 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
635 const struct side_arg
*array_item
;
637 switch (side_enum_get(enum_elem_type
->type
)) {
638 case SIDE_TYPE_U8
: /* Fall-through */
639 case SIDE_TYPE_BYTE
: /* Fall-through */
640 case SIDE_TYPE_U16
: /* Fall-through */
641 case SIDE_TYPE_U32
: /* Fall-through */
642 case SIDE_TYPE_U64
: /* Fall-through */
643 case SIDE_TYPE_U128
: /* Fall-through */
644 case SIDE_TYPE_S8
: /* Fall-through */
645 case SIDE_TYPE_S16
: /* Fall-through */
646 case SIDE_TYPE_S32
: /* Fall-through */
647 case SIDE_TYPE_S64
: /* Fall-through */
649 elem_type
= enum_elem_type
;
653 case SIDE_TYPE_ARRAY
:
654 elem_type
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
655 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_array
)->sav
);
656 nr_items
= type_desc
->u
.side_array
.length
;
659 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
660 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_vla
)->sav
);
661 nr_items
= side_ptr_get(item
->u
.side_static
.side_vla
)->len
;
664 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
667 stride_bit
= elem_type_to_stride(elem_type
);
669 print_attributes("attr", ":", side_ptr_get(side_enum_mappings
->attr
), side_enum_mappings
->nr_attr
);
670 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
671 printf("labels: [ ");
672 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
673 const struct side_enum_bitmap_mapping
*mapping
= &side_ptr_get(side_enum_mappings
->mappings
)[i
];
677 if (mapping
->range_end
< mapping
->range_begin
) {
678 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
679 mapping
->range_begin
, mapping
->range_end
);
682 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
683 if (bit
> (nr_items
* stride_bit
) - 1)
685 if (side_enum_get(elem_type
->type
) == SIDE_TYPE_BYTE
) {
686 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
687 if (v
& (1ULL << (bit
% 8))) {
692 union int_value v
= {};
694 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
695 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
697 side_check_value_u64(v
);
698 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (bit
% stride_bit
))) {
706 printf("%s", print_count
++ ? ", " : "");
707 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
708 side_enum_get(mapping
->label
.byte_order
), NULL
);
712 printf("<NO LABEL>");
717 void print_integer_binary(uint64_t v
[NR_SIDE_INTEGER128_SPLIT
], int bits
)
724 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 64 - bits
;
725 for (bit
= 0; bit
< bits
; bit
++) {
726 printf("%c", v
[SIDE_INTEGER128_SPLIT_HIGH
] & (1ULL << 63) ? '1' : '0');
727 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 1;
731 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 64 - bits
;
732 for (bit
= 0; bit
< bits
; bit
++) {
733 printf("%c", v
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63) ? '1' : '0');
734 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 1;
739 void tracer_print_type_header(const char *separator
,
740 const struct side_attr
*attr
, uint32_t nr_attr
)
742 print_attributes("attr", separator
, attr
, nr_attr
);
743 printf("%s", nr_attr
? ", " : "");
744 printf("value%s ", separator
);
748 void tracer_print_type_bool(const char *separator
,
749 const struct side_type_bool
*type_bool
,
750 const union side_bool_value
*value
,
751 uint16_t offset_bits
)
757 if (!type_bool
->len_bits
)
758 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
760 len_bits
= type_bool
->len_bits
;
761 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
763 reverse_bo
= side_enum_get(type_bool
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
764 switch (type_bool
->bool_size
) {
766 v
= value
->side_bool8
;
772 side_u16
= value
->side_bool16
;
774 side_u16
= side_bswap_16(side_u16
);
782 side_u32
= value
->side_bool32
;
784 side_u32
= side_bswap_32(side_u32
);
792 side_u64
= value
->side_bool64
;
794 side_u64
= side_bswap_64(side_u64
);
803 v
&= (1ULL << len_bits
) - 1;
804 tracer_print_type_header(separator
, side_ptr_get(type_bool
->attr
), type_bool
->nr_attr
);
805 printf("%s", v
? "true" : "false");
809 #define U128_BASE_10_ARRAY_LEN sizeof("340282366920938463463374607431768211455")
811 #define S128_BASE_10_ARRAY_LEN sizeof("-170141183460469231731687303715884105728")
814 * u128_tostring_base_10 is inspired from https://stackoverflow.com/a/4364365
817 void u128_tostring_base_10(union int_value v
, char str
[U128_BASE_10_ARRAY_LEN
])
819 int d
[39] = {}, i
, j
, str_i
= 0;
821 for (i
= 63; i
> -1; i
--) {
822 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
824 for (j
= 0; j
< 39; j
++)
826 for (j
= 0; j
< 38; j
++) {
827 d
[j
+ 1] += d
[j
] / 10;
831 for (i
= 63; i
> -1; i
--) {
832 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
835 for (j
= 0; j
< 39; j
++)
838 for (j
= 0; j
< 38; j
++) {
839 d
[j
+ 1] += d
[j
] / 10;
843 for (i
= 38; i
> 0; i
--)
846 for (; i
> -1; i
--) {
847 str
[str_i
++] = '0' + d
[i
];
853 void s128_tostring_base_10(union int_value v
, char str
[S128_BASE_10_ARRAY_LEN
])
855 uint64_t low
, high
, tmp
;
857 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] >= 0) {
859 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
860 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
861 u128_tostring_base_10(v
, str
);
867 /* Special-case minimum value, which has no positive signed representation. */
868 if ((v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] == INT64_MIN
) && (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] == 0)) {
869 memcpy(str
, "-170141183460469231731687303715884105728", S128_BASE_10_ARRAY_LEN
);
872 /* Convert from two's complement. */
873 high
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
874 low
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
878 /* Clear overflow to sign bit. */
879 high
&= ~0x8000000000000000ULL
;
881 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = tmp
;
882 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = high
;
884 u128_tostring_base_10(v
, str
+ 1);
888 #define U128_BASE_8_ARRAY_LEN sizeof("3777777777777777777777777777777777777777777")
891 void u128_tostring_base_8(union int_value v
, char str
[U128_BASE_8_ARRAY_LEN
])
893 int d
[43] = {}, i
, j
, str_i
= 0;
895 for (i
= 63; i
> -1; i
--) {
896 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
898 for (j
= 0; j
< 43; j
++)
900 for (j
= 0; j
< 42; j
++) {
901 d
[j
+ 1] += d
[j
] / 8;
905 for (i
= 63; i
> -1; i
--) {
906 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
909 for (j
= 0; j
< 43; j
++)
912 for (j
= 0; j
< 42; j
++) {
913 d
[j
+ 1] += d
[j
] / 8;
917 for (i
= 42; i
> 0; i
--)
920 for (; i
> -1; i
--) {
921 str
[str_i
++] = '0' + d
[i
];
927 void tracer_print_type_integer(const char *separator
,
928 const struct side_type_integer
*type_integer
,
929 const union side_integer_value
*value
,
930 uint16_t offset_bits
,
931 enum tracer_display_base default_base
)
933 enum tracer_display_base base
;
937 v
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
938 tracer_print_type_header(separator
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
939 base
= get_attr_display_base(side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
, default_base
);
941 case TRACER_DISPLAY_BASE_2
:
942 print_integer_binary(v
.u
, len_bits
);
944 case TRACER_DISPLAY_BASE_8
:
945 /* Clear sign bits beyond len_bits */
947 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
948 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
949 } else if (len_bits
< 128) {
950 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
952 if (len_bits
<= 64) {
953 printf("0o%" PRIo64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
955 char str
[U128_BASE_8_ARRAY_LEN
];
957 u128_tostring_base_8(v
, str
);
961 case TRACER_DISPLAY_BASE_10
:
962 if (len_bits
<= 64) {
963 if (type_integer
->signedness
)
964 printf("%" PRId64
, v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
966 printf("%" PRIu64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
968 if (type_integer
->signedness
) {
969 char str
[S128_BASE_10_ARRAY_LEN
];
970 s128_tostring_base_10(v
, str
);
973 char str
[U128_BASE_10_ARRAY_LEN
];
974 u128_tostring_base_10(v
, str
);
979 case TRACER_DISPLAY_BASE_16
:
980 /* Clear sign bits beyond len_bits */
982 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
983 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
984 } else if (len_bits
< 128) {
985 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
987 if (len_bits
<= 64 || v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
988 printf("0x%" PRIx64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
990 printf("0x%" PRIx64
"%016" PRIx64
,
991 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
],
992 v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
1001 void tracer_print_type_float(const char *separator
,
1002 const struct side_type_float
*type_float
,
1003 const union side_float_value
*value
)
1007 tracer_print_type_header(separator
, side_ptr_get(type_float
->attr
), type_float
->nr_attr
);
1008 reverse_bo
= side_enum_get(type_float
->byte_order
) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
1009 switch (type_float
->float_size
) {
1017 .f
= value
->side_float_binary16
,
1021 float16
.u
= side_bswap_16(float16
.u
);
1022 printf("%g", (double) float16
.f
);
1025 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
1036 .f
= value
->side_float_binary32
,
1040 float32
.u
= side_bswap_32(float32
.u
);
1041 printf("%g", (double) float32
.f
);
1044 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
1055 .f
= value
->side_float_binary64
,
1059 float64
.u
= side_bswap_64(float64
.u
);
1060 printf("%g", (double) float64
.f
);
1063 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
1074 .f
= value
->side_float_binary128
,
1078 side_bswap_128p(float128
.arr
);
1079 printf("%Lg", (long double) float128
.f
);
1082 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
1087 fprintf(stderr
, "ERROR: Unknown float size\n");
1093 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
)
1095 enum side_type_label type
;
1097 switch (side_enum_get(type_desc
->type
)) {
1098 case SIDE_TYPE_ENUM
:
1099 switch (side_enum_get(item
->type
)) {
1104 case SIDE_TYPE_U128
:
1109 case SIDE_TYPE_S128
:
1112 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1118 case SIDE_TYPE_ENUM_BITMAP
:
1119 switch (side_enum_get(item
->type
)) {
1121 case SIDE_TYPE_BYTE
:
1125 case SIDE_TYPE_U128
:
1126 case SIDE_TYPE_ARRAY
:
1130 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1136 case SIDE_TYPE_GATHER_ENUM
:
1137 switch (side_enum_get(item
->type
)) {
1138 case SIDE_TYPE_GATHER_INTEGER
:
1141 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1147 case SIDE_TYPE_DYNAMIC
:
1148 switch (side_enum_get(item
->type
)) {
1149 case SIDE_TYPE_DYNAMIC_NULL
:
1150 case SIDE_TYPE_DYNAMIC_BOOL
:
1151 case SIDE_TYPE_DYNAMIC_INTEGER
:
1152 case SIDE_TYPE_DYNAMIC_BYTE
:
1153 case SIDE_TYPE_DYNAMIC_POINTER
:
1154 case SIDE_TYPE_DYNAMIC_FLOAT
:
1155 case SIDE_TYPE_DYNAMIC_STRING
:
1156 case SIDE_TYPE_DYNAMIC_STRUCT
:
1157 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1158 case SIDE_TYPE_DYNAMIC_VLA
:
1159 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1162 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
1169 if (side_enum_get(type_desc
->type
) != side_enum_get(item
->type
)) {
1170 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1176 if (side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM_BITMAP
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_GATHER_ENUM
)
1177 type
= side_enum_get(type_desc
->type
);
1179 type
= side_enum_get(item
->type
);
1183 /* Stack-copy basic types */
1184 case SIDE_TYPE_NULL
:
1185 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
1186 type_desc
->u
.side_null
.nr_attr
);
1187 printf("<NULL TYPE>");
1190 case SIDE_TYPE_BOOL
:
1191 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
1198 case SIDE_TYPE_U128
:
1203 case SIDE_TYPE_S128
:
1204 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1205 TRACER_DISPLAY_BASE_10
);
1208 case SIDE_TYPE_BYTE
:
1209 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
1210 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
1213 case SIDE_TYPE_POINTER
:
1214 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1215 TRACER_DISPLAY_BASE_16
);
1218 case SIDE_TYPE_FLOAT_BINARY16
:
1219 case SIDE_TYPE_FLOAT_BINARY32
:
1220 case SIDE_TYPE_FLOAT_BINARY64
:
1221 case SIDE_TYPE_FLOAT_BINARY128
:
1222 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
1225 case SIDE_TYPE_STRING_UTF8
:
1226 case SIDE_TYPE_STRING_UTF16
:
1227 case SIDE_TYPE_STRING_UTF32
:
1228 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
1229 tracer_print_string(side_ptr_get(item
->u
.side_static
.string_value
),
1230 type_desc
->u
.side_string
.unit_size
, side_enum_get(type_desc
->u
.side_string
.byte_order
), NULL
);
1233 /* Stack-copy compound types */
1234 case SIDE_TYPE_STRUCT
:
1235 tracer_print_struct(type_desc
, side_ptr_get(item
->u
.side_static
.side_struct
));
1237 case SIDE_TYPE_VARIANT
:
1238 tracer_print_variant(type_desc
, side_ptr_get(item
->u
.side_static
.side_variant
));
1240 case SIDE_TYPE_ARRAY
:
1241 tracer_print_array(type_desc
, side_ptr_get(item
->u
.side_static
.side_array
));
1244 tracer_print_vla(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla
));
1246 case SIDE_TYPE_VLA_VISITOR
:
1247 tracer_print_vla_visitor(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla_visitor
));
1250 /* Stack-copy enumeration types */
1251 case SIDE_TYPE_ENUM
:
1252 tracer_print_enum(type_desc
, item
);
1254 case SIDE_TYPE_ENUM_BITMAP
:
1255 tracer_print_enum_bitmap(type_desc
, item
);
1258 /* Gather basic types */
1259 case SIDE_TYPE_GATHER_BOOL
:
1260 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_bool_gather_ptr
));
1262 case SIDE_TYPE_GATHER_INTEGER
:
1263 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1264 TRACER_DISPLAY_BASE_10
);
1266 case SIDE_TYPE_GATHER_BYTE
:
1267 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_byte_gather_ptr
));
1269 case SIDE_TYPE_GATHER_POINTER
:
1270 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1271 TRACER_DISPLAY_BASE_16
);
1273 case SIDE_TYPE_GATHER_FLOAT
:
1274 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_float_gather_ptr
));
1276 case SIDE_TYPE_GATHER_STRING
:
1277 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_string_gather_ptr
));
1280 /* Gather compound type */
1281 case SIDE_TYPE_GATHER_STRUCT
:
1282 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_struct_gather_ptr
));
1284 case SIDE_TYPE_GATHER_ARRAY
:
1285 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_array_gather_ptr
));
1287 case SIDE_TYPE_GATHER_VLA
:
1288 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_vla_gather
.ptr
),
1289 side_ptr_get(item
->u
.side_static
.side_vla_gather
.length_ptr
));
1292 /* Gather enumeration types */
1293 case SIDE_TYPE_GATHER_ENUM
:
1294 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
));
1297 /* Dynamic basic types */
1298 case SIDE_TYPE_DYNAMIC_NULL
:
1299 case SIDE_TYPE_DYNAMIC_BOOL
:
1300 case SIDE_TYPE_DYNAMIC_INTEGER
:
1301 case SIDE_TYPE_DYNAMIC_BYTE
:
1302 case SIDE_TYPE_DYNAMIC_POINTER
:
1303 case SIDE_TYPE_DYNAMIC_FLOAT
:
1304 case SIDE_TYPE_DYNAMIC_STRING
:
1306 /* Dynamic compound types */
1307 case SIDE_TYPE_DYNAMIC_STRUCT
:
1308 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1309 case SIDE_TYPE_DYNAMIC_VLA
:
1310 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1311 tracer_print_dynamic(item
);
1314 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1321 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1323 printf("%s: ", side_ptr_get(item_desc
->field_name
));
1324 tracer_print_type(&item_desc
->side_type
, item
);
1328 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1330 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1331 const struct side_type_struct
*side_struct
= side_ptr_get(type_desc
->u
.side_struct
);
1332 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1334 if (side_struct
->nr_fields
!= side_sav_len
) {
1335 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1338 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1339 printf("%s", side_struct
->nr_attr
? ", " : "");
1340 printf("fields: { ");
1341 for (i
= 0; i
< side_sav_len
; i
++) {
1342 printf("%s", i
? ", " : "");
1343 tracer_print_field(&side_ptr_get(side_struct
->fields
)[i
], &sav
[i
]);
1349 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1351 const struct side_type_variant
*side_type_variant
= side_ptr_get(type_desc
->u
.side_variant
);
1352 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1356 if (side_enum_get(selector_type
->type
) != side_enum_get(side_arg_variant
->selector
.type
)) {
1357 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1360 switch (side_enum_get(selector_type
->type
)) {
1365 case SIDE_TYPE_U128
:
1370 case SIDE_TYPE_S128
:
1373 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1376 v
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1377 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1378 side_check_value_u64(v
);
1379 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1380 const struct side_variant_option
*option
= &side_ptr_get(side_type_variant
->options
)[i
];
1382 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= option
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= option
->range_end
) {
1383 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
);
1387 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
1392 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1394 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1395 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1397 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1398 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1401 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_array
.attr
), type_desc
->u
.side_array
.nr_attr
);
1402 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1403 printf("elements: ");
1405 for (i
= 0; i
< side_sav_len
; i
++) {
1406 printf("%s", i
? ", " : "");
1407 tracer_print_type(side_ptr_get(type_desc
->u
.side_array
.elem_type
), &sav
[i
]);
1413 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1415 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1416 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1418 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla
.attr
), type_desc
->u
.side_vla
.nr_attr
);
1419 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1420 printf("elements: ");
1422 for (i
= 0; i
< side_sav_len
; i
++) {
1423 printf("%s", i
? ", " : "");
1424 tracer_print_type(side_ptr_get(type_desc
->u
.side_vla
.elem_type
), &sav
[i
]);
1430 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1432 switch (access_mode
) {
1433 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1435 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1436 /* Dereference pointer */
1437 memcpy(&ptr
, ptr
, sizeof(const char *));
1445 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1447 switch (access_mode
) {
1448 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1450 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1451 return sizeof(void *);
1458 union int_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1461 enum side_type_gather_access_mode access_mode
=
1462 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1463 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1464 const char *ptr
= (const char *) _ptr
;
1465 union side_integer_value value
;
1467 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1468 memcpy(&value
, ptr
, integer_size_bytes
);
1469 return tracer_load_integer_value(&side_integer
->type
, &value
,
1470 side_integer
->offset_bits
, NULL
);
1474 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1476 enum side_type_gather_access_mode access_mode
=
1477 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1478 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1479 const char *ptr
= (const char *) _ptr
;
1480 union side_bool_value value
;
1482 switch (bool_size_bytes
) {
1491 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1492 memcpy(&value
, ptr
, bool_size_bytes
);
1493 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1494 type_gather
->u
.side_bool
.offset_bits
);
1495 return tracer_gather_size(access_mode
, bool_size_bytes
);
1499 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1501 enum side_type_gather_access_mode access_mode
=
1502 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1503 const char *ptr
= (const char *) _ptr
;
1506 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1507 memcpy(&value
, ptr
, 1);
1508 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_byte
.type
.attr
),
1509 type_gather
->u
.side_byte
.type
.nr_attr
);
1510 printf("0x%" PRIx8
, value
);
1511 return tracer_gather_size(access_mode
, 1);
1515 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1516 enum tracer_display_base default_base
)
1518 enum side_type_gather_access_mode access_mode
=
1519 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1520 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1521 const char *ptr
= (const char *) _ptr
;
1522 union side_integer_value value
;
1524 switch (integer_size_bytes
) {
1534 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1535 memcpy(&value
, ptr
, integer_size_bytes
);
1536 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1537 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1538 return tracer_gather_size(access_mode
, integer_size_bytes
);
1542 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1544 enum side_type_gather_access_mode access_mode
=
1545 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1546 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1547 const char *ptr
= (const char *) _ptr
;
1548 union side_float_value value
;
1550 switch (float_size_bytes
) {
1559 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1560 memcpy(&value
, ptr
, float_size_bytes
);
1561 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1562 return tracer_gather_size(access_mode
, float_size_bytes
);
1566 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1568 enum side_type_gather_access_mode access_mode
=
1569 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1570 const char *ptr
= (const char *) _ptr
;
1573 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1574 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_string
.type
.attr
),
1575 type_gather
->u
.side_string
.type
.nr_attr
);
1577 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1578 side_enum_get(type_gather
->u
.side_string
.type
.byte_order
), &string_len
);
1581 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1583 return tracer_gather_size(access_mode
, string_len
);
1587 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1592 switch (side_enum_get(type_desc
->type
)) {
1593 /* Gather basic types */
1594 case SIDE_TYPE_GATHER_BOOL
:
1595 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1597 case SIDE_TYPE_GATHER_INTEGER
:
1598 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1599 TRACER_DISPLAY_BASE_10
);
1601 case SIDE_TYPE_GATHER_BYTE
:
1602 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1604 case SIDE_TYPE_GATHER_POINTER
:
1605 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1606 TRACER_DISPLAY_BASE_16
);
1608 case SIDE_TYPE_GATHER_FLOAT
:
1609 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1611 case SIDE_TYPE_GATHER_STRING
:
1612 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1615 /* Gather enum types */
1616 case SIDE_TYPE_GATHER_ENUM
:
1617 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1620 /* Gather compound types */
1621 case SIDE_TYPE_GATHER_STRUCT
:
1622 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1624 case SIDE_TYPE_GATHER_ARRAY
:
1625 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1627 case SIDE_TYPE_GATHER_VLA
:
1628 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1631 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1639 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1641 const struct side_enum_mappings
*mappings
= side_ptr_get(type_gather
->u
.side_enum
.mappings
);
1642 const struct side_type
*enum_elem_type
= side_ptr_get(type_gather
->u
.side_enum
.elem_type
);
1643 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1644 enum side_type_gather_access_mode access_mode
=
1645 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1646 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1647 const char *ptr
= (const char *) _ptr
;
1648 union side_integer_value value
;
1651 switch (integer_size_bytes
) {
1661 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1662 memcpy(&value
, ptr
, integer_size_bytes
);
1663 v
= tracer_load_gather_integer_value(side_integer
, &value
);
1664 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1665 printf("%s", mappings
->nr_attr
? ", " : "");
1666 tracer_print_gather_type(enum_elem_type
, ptr
);
1667 print_enum_labels(mappings
, v
);
1668 return tracer_gather_size(access_mode
, integer_size_bytes
);
1672 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1674 printf("%s: ", side_ptr_get(field
->field_name
));
1675 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1679 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1681 enum side_type_gather_access_mode access_mode
=
1682 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1683 const struct side_type_struct
*side_struct
= side_ptr_get(type_gather
->u
.side_struct
.type
);
1684 const char *ptr
= (const char *) _ptr
;
1687 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1688 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1689 printf("%s", side_struct
->nr_attr
? ", " : "");
1690 printf("fields: { ");
1691 for (i
= 0; i
< side_struct
->nr_fields
; i
++) {
1692 printf("%s", i
? ", " : "");
1693 tracer_print_gather_field(&side_ptr_get(side_struct
->fields
)[i
], ptr
);
1696 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1700 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1702 enum side_type_gather_access_mode access_mode
=
1703 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1704 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1707 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1709 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_array
.type
.attr
), type_gather
->u
.side_array
.type
.nr_attr
);
1710 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1711 printf("elements: ");
1713 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1714 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_array
.type
.elem_type
);
1716 switch (side_enum_get(elem_type
->type
)) {
1717 case SIDE_TYPE_GATHER_VLA
:
1718 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1723 printf("%s", i
? ", " : "");
1724 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1727 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1731 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1732 const void *_length_ptr
)
1734 enum side_type_gather_access_mode access_mode
=
1735 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1736 const struct side_type
*length_type
= side_ptr_get(type_gather
->u
.side_vla
.length_type
);
1737 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1738 const char *length_ptr
= (const char *) _length_ptr
;
1739 union int_value v
= {};
1743 switch (side_enum_get(length_type
->type
)) {
1744 case SIDE_TYPE_GATHER_INTEGER
:
1747 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1750 v
= tracer_load_gather_integer_value(&length_type
->u
.side_gather
.u
.side_integer
,
1752 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] || v
.u
[SIDE_INTEGER128_SPLIT_LOW
] > UINT32_MAX
) {
1753 fprintf(stderr
, "Unexpected vla length value\n");
1756 length
= (uint32_t) v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
1757 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1759 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_vla
.type
.attr
), type_gather
->u
.side_vla
.type
.nr_attr
);
1760 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1761 printf("elements: ");
1763 for (i
= 0; i
< length
; i
++) {
1764 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_vla
.type
.elem_type
);
1766 switch (side_enum_get(elem_type
->type
)) {
1767 case SIDE_TYPE_GATHER_VLA
:
1768 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1773 printf("%s", i
? ", " : "");
1774 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1777 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1780 struct tracer_visitor_priv
{
1781 const struct side_type
*elem_type
;
1786 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1787 const struct side_arg
*elem
)
1789 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1791 printf("%s", tracer_priv
->i
++ ? ", " : "");
1792 tracer_print_type(tracer_priv
->elem_type
, elem
);
1793 return SIDE_VISITOR_STATUS_OK
;
1797 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
)
1800 enum side_visitor_status status
;
1801 struct tracer_visitor_priv tracer_priv
= {
1802 .elem_type
= side_ptr_get(type_desc
->u
.side_vla_visitor
.elem_type
),
1805 const struct side_tracer_visitor_ctx tracer_ctx
= {
1806 .write_elem
= tracer_write_elem_cb
,
1807 .priv
= &tracer_priv
,
1809 side_visitor_func func
;
1813 app_ctx
= side_ptr_get(vla_visitor
->app_ctx
);
1814 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla_visitor
.attr
), type_desc
->u
.side_vla_visitor
.nr_attr
);
1815 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1816 printf("elements: ");
1818 func
= side_ptr_get(type_desc
->u
.side_vla_visitor
.visitor
);
1819 status
= func(&tracer_ctx
, app_ctx
);
1821 case SIDE_VISITOR_STATUS_OK
:
1823 case SIDE_VISITOR_STATUS_ERROR
:
1824 fprintf(stderr
, "ERROR: Visitor error\n");
1831 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1833 const struct side_arg_dynamic_field
*fields
= side_ptr_get(dynamic_struct
->fields
);
1834 uint32_t i
, len
= dynamic_struct
->len
;
1836 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1837 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1838 printf("fields:: ");
1840 for (i
= 0; i
< len
; i
++) {
1841 printf("%s", i
? ", " : "");
1842 printf("%s:: ", side_ptr_get(fields
[i
].field_name
));
1843 tracer_print_dynamic(&fields
[i
].elem
);
1848 struct tracer_dynamic_struct_visitor_priv
{
1853 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1854 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1855 const struct side_arg_dynamic_field
*dynamic_field
)
1857 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1858 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1860 printf("%s", tracer_priv
->i
++ ? ", " : "");
1861 printf("%s:: ", side_ptr_get(dynamic_field
->field_name
));
1862 tracer_print_dynamic(&dynamic_field
->elem
);
1863 return SIDE_VISITOR_STATUS_OK
;
1867 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1869 struct side_arg_dynamic_struct_visitor
*dynamic_struct_visitor
;
1870 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1873 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1874 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1875 .priv
= &tracer_priv
,
1877 enum side_visitor_status status
;
1880 dynamic_struct_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
);
1881 if (!dynamic_struct_visitor
)
1883 app_ctx
= side_ptr_get(dynamic_struct_visitor
->app_ctx
);
1884 print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor
->attr
), dynamic_struct_visitor
->nr_attr
);
1885 printf("%s", dynamic_struct_visitor
->nr_attr
? ", " : "");
1886 printf("fields:: ");
1888 status
= side_ptr_get(dynamic_struct_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1890 case SIDE_VISITOR_STATUS_OK
:
1892 case SIDE_VISITOR_STATUS_ERROR
:
1893 fprintf(stderr
, "ERROR: Visitor error\n");
1900 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1902 const struct side_arg
*sav
= side_ptr_get(vla
->sav
);
1903 uint32_t i
, side_sav_len
= vla
->len
;
1905 print_attributes("attr", "::", side_ptr_get(vla
->attr
), vla
->nr_attr
);
1906 printf("%s", vla
->nr_attr
? ", " : "");
1907 printf("elements:: ");
1909 for (i
= 0; i
< side_sav_len
; i
++) {
1910 printf("%s", i
? ", " : "");
1911 tracer_print_dynamic(&sav
[i
]);
1916 struct tracer_dynamic_vla_visitor_priv
{
1921 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1922 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1923 const struct side_arg
*elem
)
1925 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1926 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1928 printf("%s", tracer_priv
->i
++ ? ", " : "");
1929 tracer_print_dynamic(elem
);
1930 return SIDE_VISITOR_STATUS_OK
;
1934 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1936 struct side_arg_dynamic_vla_visitor
*dynamic_vla_visitor
;
1937 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1940 const struct side_tracer_visitor_ctx tracer_ctx
= {
1941 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1942 .priv
= &tracer_priv
,
1944 enum side_visitor_status status
;
1947 dynamic_vla_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
);
1948 if (!dynamic_vla_visitor
)
1950 app_ctx
= side_ptr_get(dynamic_vla_visitor
->app_ctx
);
1951 print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor
->attr
), dynamic_vla_visitor
->nr_attr
);
1952 printf("%s", dynamic_vla_visitor
->nr_attr
? ", " : "");
1953 printf("elements:: ");
1955 status
= side_ptr_get(dynamic_vla_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1957 case SIDE_VISITOR_STATUS_OK
:
1959 case SIDE_VISITOR_STATUS_ERROR
:
1960 fprintf(stderr
, "ERROR: Visitor error\n");
1967 void tracer_print_dynamic(const struct side_arg
*item
)
1970 switch (side_enum_get(item
->type
)) {
1971 /* Dynamic basic types */
1972 case SIDE_TYPE_DYNAMIC_NULL
:
1973 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1974 item
->u
.side_dynamic
.side_null
.nr_attr
);
1975 printf("<NULL TYPE>");
1977 case SIDE_TYPE_DYNAMIC_BOOL
:
1978 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1980 case SIDE_TYPE_DYNAMIC_INTEGER
:
1981 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1982 TRACER_DISPLAY_BASE_10
);
1984 case SIDE_TYPE_DYNAMIC_BYTE
:
1985 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1986 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1988 case SIDE_TYPE_DYNAMIC_POINTER
:
1989 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1990 TRACER_DISPLAY_BASE_16
);
1992 case SIDE_TYPE_DYNAMIC_FLOAT
:
1993 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1994 &item
->u
.side_dynamic
.side_float
.value
);
1996 case SIDE_TYPE_DYNAMIC_STRING
:
1997 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1998 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1999 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
2000 side_enum_get(item
->u
.side_dynamic
.side_string
.type
.byte_order
), NULL
);
2003 /* Dynamic compound types */
2004 case SIDE_TYPE_DYNAMIC_STRUCT
:
2005 tracer_print_dynamic_struct(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct
));
2007 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
2008 tracer_print_dynamic_struct_visitor(item
);
2010 case SIDE_TYPE_DYNAMIC_VLA
:
2011 tracer_print_dynamic_vla(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla
));
2013 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
2014 tracer_print_dynamic_vla_visitor(item
);
2017 fprintf(stderr
, "<UNKNOWN TYPE>\n");
2024 void tracer_print_static_fields(const struct side_event_description
*desc
,
2025 const struct side_arg_vec
*side_arg_vec
,
2026 uint32_t *nr_items
, void *caller_addr
)
2028 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
2029 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
2031 printf("caller: [%p], provider: %s, event: %s", caller_addr
,
2032 side_ptr_get(desc
->provider_name
),
2033 side_ptr_get(desc
->event_name
));
2034 if (desc
->nr_fields
!= side_sav_len
) {
2035 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
2038 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
2039 printf("%s", side_sav_len
? ", fields: [ " : "");
2040 for (i
= 0; i
< side_sav_len
; i
++) {
2041 printf("%s", i
? ", " : "");
2042 tracer_print_field(&side_ptr_get(desc
->fields
)[i
], &sav
[i
]);
2051 void tracer_call(const struct side_event_description
*desc
,
2052 const struct side_arg_vec
*side_arg_vec
,
2053 void *priv
__attribute__((unused
)),
2056 uint32_t nr_fields
= 0;
2058 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2063 void tracer_call_variadic(const struct side_event_description
*desc
,
2064 const struct side_arg_vec
*side_arg_vec
,
2065 const struct side_arg_dynamic_struct
*var_struct
,
2066 void *priv
__attribute__((unused
)),
2069 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
2071 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2073 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
2074 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
2077 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
2078 printf("%s", var_struct_len
? ", fields:: [ " : "");
2079 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
2080 printf("%s", i
? ", " : "");
2081 printf("%s:: ", side_ptr_get(side_ptr_get(var_struct
->fields
)[i
].field_name
));
2082 tracer_print_dynamic(&side_ptr_get(var_struct
->fields
)[i
].elem
);
2090 void tracer_event_notification(enum side_tracer_notification notif
,
2091 struct side_event_description
**events
, uint32_t nr_events
,
2092 void *priv
__attribute__((unused
)))
2097 printf("----------------------------------------------------------\n");
2098 printf("Tracer notified of events %s\n",
2099 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
2100 for (i
= 0; i
< nr_events
; i
++) {
2101 struct side_event_description
*event
= events
[i
];
2103 /* Skip NULL pointers */
2106 if (event
->version
!= SIDE_EVENT_DESCRIPTION_ABI_VERSION
) {
2107 printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n",
2108 event
->version
, SIDE_EVENT_DESCRIPTION_ABI_VERSION
);
2111 printf("provider: %s, event: %s\n",
2112 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2113 if (event
->struct_size
!= side_offsetofend(struct side_event_description
, side_event_description_orig_abi_last
)) {
2114 printf("Warning: Event %s.%s description contains fields unknown to the tracer\n",
2115 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2117 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
2118 if (event
->nr_side_type_label
> _NR_SIDE_TYPE_LABEL
) {
2119 printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
2120 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2121 event
->nr_side_type_label
- _NR_SIDE_TYPE_LABEL
);
2123 if (event
->nr_side_attr_type
> _NR_SIDE_ATTR_TYPE
) {
2124 printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n",
2125 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2126 event
->nr_side_attr_type
- _NR_SIDE_ATTR_TYPE
);
2128 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2129 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
, tracer_key
);
2133 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
, tracer_key
);
2138 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2139 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
, tracer_key
);
2143 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
, tracer_key
);
2149 printf("----------------------------------------------------------\n");
2152 static __attribute__((constructor
))
2153 void tracer_init(void);
2155 void tracer_init(void)
2157 if (side_tracer_request_key(&tracer_key
))
2159 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
2164 static __attribute__((destructor
))
2165 void tracer_exit(void);
2167 void tracer_exit(void)
2169 side_tracer_event_notification_unregister(tracer_handle
);