1 // SPDX-License-Identifier: MIT
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 #include <side/trace.h>
16 /* TODO: optionally print caller address. */
17 static bool print_caller
= false;
19 enum tracer_display_base
{
20 TRACER_DISPLAY_BASE_2
,
21 TRACER_DISPLAY_BASE_8
,
22 TRACER_DISPLAY_BASE_10
,
23 TRACER_DISPLAY_BASE_16
,
27 uint64_t u
[NR_SIDE_INTEGER128_SPLIT
];
28 int64_t s
[NR_SIDE_INTEGER128_SPLIT
];
31 static struct side_tracer_handle
*tracer_handle
;
33 static uint64_t tracer_key
;
36 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
38 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
);
40 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
42 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
44 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
);
46 void tracer_print_dynamic(const struct side_arg
*dynamic_item
, bool print_brackets
);
48 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
50 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
52 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
53 enum tracer_display_base default_base
);
55 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
57 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
59 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
61 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
63 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
65 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
66 const void *_length_ptr
);
68 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
, bool print_brackets
);
71 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
72 size_t *strlen_with_null
,
75 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
, input_size
;
76 const char *str
= p
, *fromcode
;
77 char *inbuf
= (char *) p
, *outbuf
, *buf
;
83 *strlen_with_null
= strlen(str
) + 1;
84 *output_str
= (char *) str
;
88 const uint16_t *p16
= p
;
91 case SIDE_TYPE_BYTE_ORDER_LE
:
93 fromcode
= "UTF-16LE";
96 case SIDE_TYPE_BYTE_ORDER_BE
:
98 fromcode
= "UTF-16BE";
102 fprintf(stderr
, "Unknown byte order\n");
107 input_size
= inbytesleft
+ 2;
109 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
110 * { ef, bf, bf } UTF-8 (3 bytes).
112 bufsize
= inbytesleft
/ 2 * 3 + 1;
117 const uint32_t *p32
= p
;
119 switch (byte_order
) {
120 case SIDE_TYPE_BYTE_ORDER_LE
:
122 fromcode
= "UTF-32LE";
125 case SIDE_TYPE_BYTE_ORDER_BE
:
127 fromcode
= "UTF-32BE";
131 fprintf(stderr
, "Unknown byte order\n");
136 input_size
= inbytesleft
+ 4;
138 * Each 4-byte UTF-32 character converts to at most a
139 * 4-byte UTF-8 character.
141 bufsize
= inbytesleft
+ 1;
145 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
149 cd
= iconv_open("UTF8", fromcode
);
150 if (cd
== (iconv_t
) -1) {
151 perror("iconv_open");
154 buf
= malloc(bufsize
);
158 outbuf
= (char *) buf
;
159 outbytesleft
= bufsize
;
160 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
161 if (ret
== (size_t) -1) {
166 fprintf(stderr
, "Buffer too small to convert string input\n");
170 if (iconv_close(cd
) == -1) {
171 perror("iconv_close");
174 if (strlen_with_null
)
175 *strlen_with_null
= input_size
;
180 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
181 size_t *strlen_with_null
)
183 char *output_str
= NULL
;
185 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
186 printf("\"%s\"", output_str
);
192 void side_check_value_u64(union int_value v
)
194 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
]) {
195 fprintf(stderr
, "Unexpected integer value\n");
201 void side_check_value_s64(union int_value v
)
203 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63)) {
204 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] != ~0LL) {
205 fprintf(stderr
, "Unexpected integer value\n");
209 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
]) {
210 fprintf(stderr
, "Unexpected integer value\n");
217 int64_t get_attr_integer64_value(const struct side_attr
*attr
)
221 switch (side_enum_get(attr
->value
.type
)) {
222 case SIDE_ATTR_TYPE_U8
:
223 val
= attr
->value
.u
.integer_value
.side_u8
;
225 case SIDE_ATTR_TYPE_U16
:
226 val
= attr
->value
.u
.integer_value
.side_u16
;
228 case SIDE_ATTR_TYPE_U32
:
229 val
= attr
->value
.u
.integer_value
.side_u32
;
231 case SIDE_ATTR_TYPE_U64
:
232 val
= attr
->value
.u
.integer_value
.side_u64
;
234 case SIDE_ATTR_TYPE_U128
:
236 union int_value v
= {
238 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
],
239 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
242 side_check_value_u64(v
);
243 val
= v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
246 case SIDE_ATTR_TYPE_S8
:
247 val
= attr
->value
.u
.integer_value
.side_s8
;
249 case SIDE_ATTR_TYPE_S16
:
250 val
= attr
->value
.u
.integer_value
.side_s16
;
252 case SIDE_ATTR_TYPE_S32
:
253 val
= attr
->value
.u
.integer_value
.side_s32
;
255 case SIDE_ATTR_TYPE_S64
:
256 val
= attr
->value
.u
.integer_value
.side_s64
;
258 case SIDE_ATTR_TYPE_S128
:
260 union int_value v
= {
262 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
],
263 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
266 side_check_value_s64(v
);
267 val
= v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
271 fprintf(stderr
, "Unexpected attribute type\n");
278 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
279 enum tracer_display_base default_base
)
283 for (i
= 0; i
< nr_attr
; i
++) {
284 const struct side_attr
*attr
= &_attr
[i
];
285 char *utf8_str
= NULL
;
288 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
289 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
290 cmp
= strcmp(utf8_str
, "std.integer.base");
291 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
294 int64_t val
= get_attr_integer64_value(attr
);
298 return TRACER_DISPLAY_BASE_2
;
300 return TRACER_DISPLAY_BASE_8
;
302 return TRACER_DISPLAY_BASE_10
;
304 return TRACER_DISPLAY_BASE_16
;
306 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
311 return default_base
; /* Default */
315 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
317 char *utf8_str
= NULL
;
319 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
320 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
321 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
322 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
324 switch (side_enum_get(attr
->value
.type
)) {
325 case SIDE_ATTR_TYPE_BOOL
:
326 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
328 case SIDE_ATTR_TYPE_U8
:
329 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
331 case SIDE_ATTR_TYPE_U16
:
332 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
334 case SIDE_ATTR_TYPE_U32
:
335 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
337 case SIDE_ATTR_TYPE_U64
:
338 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
340 case SIDE_ATTR_TYPE_U128
:
341 if (attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
342 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
344 printf("0x%" PRIx64
"%016" PRIx64
,
345 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
346 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
349 case SIDE_ATTR_TYPE_S8
:
350 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
352 case SIDE_ATTR_TYPE_S16
:
353 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
355 case SIDE_ATTR_TYPE_S32
:
356 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
358 case SIDE_ATTR_TYPE_S64
:
359 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
361 case SIDE_ATTR_TYPE_S128
:
362 if (attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
363 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
365 printf("0x%" PRIx64
"%016" PRIx64
,
366 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
367 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
370 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
372 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
375 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
378 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
380 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
383 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
386 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
388 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
391 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
394 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
396 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
399 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
402 case SIDE_ATTR_TYPE_STRING
:
403 tracer_print_string(side_ptr_get(attr
->value
.u
.string_value
.p
),
404 attr
->value
.u
.string_value
.unit_size
,
405 side_enum_get(attr
->value
.u
.string_value
.byte_order
), NULL
);
408 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
415 void print_attributes(const char *prefix_str
, const char *separator
,
416 const struct side_attr
*attr
, uint32_t nr_attr
)
422 printf("%s%s [ ", prefix_str
, separator
);
423 for (i
= 0; i
< nr_attr
; i
++) {
424 printf("%s", i
? ", " : "");
425 tracer_print_attr_type(separator
, &attr
[i
]);
431 union int_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
432 const union side_integer_value
*value
,
433 uint16_t offset_bits
, uint16_t *_len_bits
)
435 union int_value v
= {};
439 if (!type_integer
->len_bits
)
440 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
442 len_bits
= type_integer
->len_bits
;
443 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
445 reverse_bo
= side_enum_get(type_integer
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
446 switch (type_integer
->integer_size
) {
448 if (type_integer
->signedness
)
449 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s8
;
451 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u8
;
454 if (type_integer
->signedness
) {
457 side_s16
= value
->side_s16
;
459 side_s16
= side_bswap_16(side_s16
);
460 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s16
;
464 side_u16
= value
->side_u16
;
466 side_u16
= side_bswap_16(side_u16
);
467 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u16
;
471 if (type_integer
->signedness
) {
474 side_s32
= value
->side_s32
;
476 side_s32
= side_bswap_32(side_s32
);
477 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s32
;
481 side_u32
= value
->side_u32
;
483 side_u32
= side_bswap_32(side_u32
);
484 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u32
;
488 if (type_integer
->signedness
) {
491 side_s64
= value
->side_s64
;
493 side_s64
= side_bswap_64(side_s64
);
494 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
;
498 side_u64
= value
->side_u64
;
500 side_u64
= side_bswap_64(side_u64
);
501 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
;
505 if (type_integer
->signedness
) {
506 int64_t side_s64
[NR_SIDE_INTEGER128_SPLIT
];
508 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
];
509 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
511 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_LOW
]);
512 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_HIGH
]);
513 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
514 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
516 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
517 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
520 uint64_t side_u64
[NR_SIDE_INTEGER128_SPLIT
];
522 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
];
523 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
525 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_LOW
]);
526 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_HIGH
]);
527 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
528 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
530 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
531 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
538 if (type_integer
->integer_size
<= 8) {
539 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >>= offset_bits
;
541 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
542 if (type_integer
->signedness
) {
544 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (len_bits
- 1))) {
545 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] |= ~((1ULL << len_bits
) - 1);
546 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = ~0ULL;
551 //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits
552 if (len_bits
< 128 || offset_bits
!= 0)
556 *_len_bits
= len_bits
;
561 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int_value v
)
563 uint32_t i
, print_count
= 0;
565 side_check_value_s64(v
);
566 printf(", labels: [ ");
567 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
568 const struct side_enum_mapping
*mapping
= &side_ptr_get(mappings
->mappings
)[i
];
570 if (mapping
->range_end
< mapping
->range_begin
) {
571 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
572 mapping
->range_begin
, mapping
->range_end
);
575 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= mapping
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= mapping
->range_end
) {
576 printf("%s", print_count
++ ? ", " : "");
577 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
578 side_enum_get(mapping
->label
.byte_order
), NULL
);
582 printf("<NO LABEL>");
587 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
589 const struct side_enum_mappings
*mappings
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
590 const struct side_type
*elem_type
= side_ptr_get(type_desc
->u
.side_enum
.elem_type
);
593 if (side_enum_get(elem_type
->type
) != side_enum_get(item
->type
)) {
594 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
597 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
598 &item
->u
.side_static
.integer_value
, 0, NULL
);
599 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
600 printf("%s", mappings
->nr_attr
? ", " : "");
601 tracer_print_type(elem_type
, item
, true);
602 print_enum_labels(mappings
, v
);
606 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
610 switch (side_enum_get(elem_type
->type
)) {
625 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
627 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
634 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
635 const struct side_arg
*item
)
637 const struct side_enum_bitmap_mappings
*side_enum_mappings
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
638 const struct side_type
*enum_elem_type
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.elem_type
), *elem_type
;
639 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
640 const struct side_arg
*array_item
;
642 switch (side_enum_get(enum_elem_type
->type
)) {
643 case SIDE_TYPE_U8
: /* Fall-through */
644 case SIDE_TYPE_BYTE
: /* Fall-through */
645 case SIDE_TYPE_U16
: /* Fall-through */
646 case SIDE_TYPE_U32
: /* Fall-through */
647 case SIDE_TYPE_U64
: /* Fall-through */
648 case SIDE_TYPE_U128
: /* Fall-through */
649 case SIDE_TYPE_S8
: /* Fall-through */
650 case SIDE_TYPE_S16
: /* Fall-through */
651 case SIDE_TYPE_S32
: /* Fall-through */
652 case SIDE_TYPE_S64
: /* Fall-through */
654 elem_type
= enum_elem_type
;
658 case SIDE_TYPE_ARRAY
:
659 elem_type
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
660 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_array
)->sav
);
661 nr_items
= type_desc
->u
.side_array
.length
;
664 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
665 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_vla
)->sav
);
666 nr_items
= side_ptr_get(item
->u
.side_static
.side_vla
)->len
;
669 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
672 stride_bit
= elem_type_to_stride(elem_type
);
674 print_attributes("attr", ":", side_ptr_get(side_enum_mappings
->attr
), side_enum_mappings
->nr_attr
);
675 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
676 printf("labels: [ ");
677 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
678 const struct side_enum_bitmap_mapping
*mapping
= &side_ptr_get(side_enum_mappings
->mappings
)[i
];
682 if (mapping
->range_end
< mapping
->range_begin
) {
683 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
684 mapping
->range_begin
, mapping
->range_end
);
687 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
688 if (bit
> (nr_items
* stride_bit
) - 1)
690 if (side_enum_get(elem_type
->type
) == SIDE_TYPE_BYTE
) {
691 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
692 if (v
& (1ULL << (bit
% 8))) {
697 union int_value v
= {};
699 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
700 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
702 side_check_value_u64(v
);
703 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (bit
% stride_bit
))) {
711 printf("%s", print_count
++ ? ", " : "");
712 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
713 side_enum_get(mapping
->label
.byte_order
), NULL
);
717 printf("<NO LABEL>");
722 void print_integer_binary(uint64_t v
[NR_SIDE_INTEGER128_SPLIT
], int bits
)
729 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 64 - bits
;
730 for (bit
= 0; bit
< bits
; bit
++) {
731 printf("%c", v
[SIDE_INTEGER128_SPLIT_HIGH
] & (1ULL << 63) ? '1' : '0');
732 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 1;
736 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 64 - bits
;
737 for (bit
= 0; bit
< bits
; bit
++) {
738 printf("%c", v
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63) ? '1' : '0');
739 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 1;
744 void tracer_print_type_header(const char *separator
,
745 const struct side_attr
*attr
, uint32_t nr_attr
)
747 print_attributes("attr", separator
, attr
, nr_attr
);
748 printf("%s", nr_attr
? ", " : "");
749 printf("value%s ", separator
);
753 void tracer_print_type_bool(const char *separator
,
754 const struct side_type_bool
*type_bool
,
755 const union side_bool_value
*value
,
756 uint16_t offset_bits
)
762 if (!type_bool
->len_bits
)
763 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
765 len_bits
= type_bool
->len_bits
;
766 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
768 reverse_bo
= side_enum_get(type_bool
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
769 switch (type_bool
->bool_size
) {
771 v
= value
->side_bool8
;
777 side_u16
= value
->side_bool16
;
779 side_u16
= side_bswap_16(side_u16
);
787 side_u32
= value
->side_bool32
;
789 side_u32
= side_bswap_32(side_u32
);
797 side_u64
= value
->side_bool64
;
799 side_u64
= side_bswap_64(side_u64
);
808 v
&= (1ULL << len_bits
) - 1;
809 tracer_print_type_header(separator
, side_ptr_get(type_bool
->attr
), type_bool
->nr_attr
);
810 printf("%s", v
? "true" : "false");
814 #define U128_BASE_10_ARRAY_LEN sizeof("340282366920938463463374607431768211455")
816 #define S128_BASE_10_ARRAY_LEN sizeof("-170141183460469231731687303715884105728")
819 * u128_tostring_base_10 is inspired from https://stackoverflow.com/a/4364365
822 void u128_tostring_base_10(union int_value v
, char str
[U128_BASE_10_ARRAY_LEN
])
824 int d
[39] = {}, i
, j
, str_i
= 0;
826 for (i
= 63; i
> -1; i
--) {
827 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
829 for (j
= 0; j
< 39; j
++)
831 for (j
= 0; j
< 38; j
++) {
832 d
[j
+ 1] += d
[j
] / 10;
836 for (i
= 63; i
> -1; i
--) {
837 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
840 for (j
= 0; j
< 39; j
++)
843 for (j
= 0; j
< 38; j
++) {
844 d
[j
+ 1] += d
[j
] / 10;
848 for (i
= 38; i
> 0; i
--)
851 for (; i
> -1; i
--) {
852 str
[str_i
++] = '0' + d
[i
];
858 void s128_tostring_base_10(union int_value v
, char str
[S128_BASE_10_ARRAY_LEN
])
860 uint64_t low
, high
, tmp
;
862 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] >= 0) {
864 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
865 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
866 u128_tostring_base_10(v
, str
);
872 /* Special-case minimum value, which has no positive signed representation. */
873 if ((v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] == INT64_MIN
) && (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] == 0)) {
874 memcpy(str
, "-170141183460469231731687303715884105728", S128_BASE_10_ARRAY_LEN
);
877 /* Convert from two's complement. */
878 high
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
879 low
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
883 /* Clear overflow to sign bit. */
884 high
&= ~0x8000000000000000ULL
;
886 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = tmp
;
887 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = high
;
889 u128_tostring_base_10(v
, str
+ 1);
893 #define U128_BASE_8_ARRAY_LEN sizeof("3777777777777777777777777777777777777777777")
896 void u128_tostring_base_8(union int_value v
, char str
[U128_BASE_8_ARRAY_LEN
])
898 int d
[43] = {}, i
, j
, str_i
= 0;
900 for (i
= 63; i
> -1; i
--) {
901 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
903 for (j
= 0; j
< 43; j
++)
905 for (j
= 0; j
< 42; j
++) {
906 d
[j
+ 1] += d
[j
] / 8;
910 for (i
= 63; i
> -1; i
--) {
911 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
914 for (j
= 0; j
< 43; j
++)
917 for (j
= 0; j
< 42; j
++) {
918 d
[j
+ 1] += d
[j
] / 8;
922 for (i
= 42; i
> 0; i
--)
925 for (; i
> -1; i
--) {
926 str
[str_i
++] = '0' + d
[i
];
932 void tracer_print_type_integer(const char *separator
,
933 const struct side_type_integer
*type_integer
,
934 const union side_integer_value
*value
,
935 uint16_t offset_bits
,
936 enum tracer_display_base default_base
)
938 enum tracer_display_base base
;
942 v
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
943 tracer_print_type_header(separator
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
944 base
= get_attr_display_base(side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
, default_base
);
946 case TRACER_DISPLAY_BASE_2
:
947 print_integer_binary(v
.u
, len_bits
);
949 case TRACER_DISPLAY_BASE_8
:
950 /* Clear sign bits beyond len_bits */
952 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
953 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
954 } else if (len_bits
< 128) {
955 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
957 if (len_bits
<= 64) {
958 printf("0o%" PRIo64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
960 char str
[U128_BASE_8_ARRAY_LEN
];
962 u128_tostring_base_8(v
, str
);
966 case TRACER_DISPLAY_BASE_10
:
967 if (len_bits
<= 64) {
968 if (type_integer
->signedness
)
969 printf("%" PRId64
, v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
971 printf("%" PRIu64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
973 if (type_integer
->signedness
) {
974 char str
[S128_BASE_10_ARRAY_LEN
];
975 s128_tostring_base_10(v
, str
);
978 char str
[U128_BASE_10_ARRAY_LEN
];
979 u128_tostring_base_10(v
, str
);
984 case TRACER_DISPLAY_BASE_16
:
985 /* Clear sign bits beyond len_bits */
987 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
988 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
989 } else if (len_bits
< 128) {
990 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
992 if (len_bits
<= 64 || v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
993 printf("0x%" PRIx64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
995 printf("0x%" PRIx64
"%016" PRIx64
,
996 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
],
997 v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
1006 void tracer_print_type_float(const char *separator
,
1007 const struct side_type_float
*type_float
,
1008 const union side_float_value
*value
)
1012 tracer_print_type_header(separator
, side_ptr_get(type_float
->attr
), type_float
->nr_attr
);
1013 reverse_bo
= side_enum_get(type_float
->byte_order
) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
1014 switch (type_float
->float_size
) {
1022 .f
= value
->side_float_binary16
,
1026 float16
.u
= side_bswap_16(float16
.u
);
1027 printf("%g", (double) float16
.f
);
1030 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
1041 .f
= value
->side_float_binary32
,
1045 float32
.u
= side_bswap_32(float32
.u
);
1046 printf("%g", (double) float32
.f
);
1049 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
1060 .f
= value
->side_float_binary64
,
1064 float64
.u
= side_bswap_64(float64
.u
);
1065 printf("%g", (double) float64
.f
);
1068 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
1079 .f
= value
->side_float_binary128
,
1083 side_bswap_128p(float128
.arr
);
1084 printf("%Lg", (long double) float128
.f
);
1087 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
1092 fprintf(stderr
, "ERROR: Unknown float size\n");
1098 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
, bool print_brackets
)
1100 enum side_type_label type
;
1102 switch (side_enum_get(type_desc
->type
)) {
1103 case SIDE_TYPE_ENUM
:
1104 switch (side_enum_get(item
->type
)) {
1109 case SIDE_TYPE_U128
:
1114 case SIDE_TYPE_S128
:
1117 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1123 case SIDE_TYPE_ENUM_BITMAP
:
1124 switch (side_enum_get(item
->type
)) {
1126 case SIDE_TYPE_BYTE
:
1130 case SIDE_TYPE_U128
:
1131 case SIDE_TYPE_ARRAY
:
1135 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1141 case SIDE_TYPE_GATHER_ENUM
:
1142 switch (side_enum_get(item
->type
)) {
1143 case SIDE_TYPE_GATHER_INTEGER
:
1146 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1152 case SIDE_TYPE_DYNAMIC
:
1153 switch (side_enum_get(item
->type
)) {
1154 case SIDE_TYPE_DYNAMIC_NULL
:
1155 case SIDE_TYPE_DYNAMIC_BOOL
:
1156 case SIDE_TYPE_DYNAMIC_INTEGER
:
1157 case SIDE_TYPE_DYNAMIC_BYTE
:
1158 case SIDE_TYPE_DYNAMIC_POINTER
:
1159 case SIDE_TYPE_DYNAMIC_FLOAT
:
1160 case SIDE_TYPE_DYNAMIC_STRING
:
1161 case SIDE_TYPE_DYNAMIC_STRUCT
:
1162 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1163 case SIDE_TYPE_DYNAMIC_VLA
:
1164 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1167 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
1174 if (side_enum_get(type_desc
->type
) != side_enum_get(item
->type
)) {
1175 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1181 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
)
1182 type
= side_enum_get(type_desc
->type
);
1184 type
= side_enum_get(item
->type
);
1189 /* Stack-copy basic types */
1190 case SIDE_TYPE_NULL
:
1191 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
1192 type_desc
->u
.side_null
.nr_attr
);
1193 printf("<NULL TYPE>");
1196 case SIDE_TYPE_BOOL
:
1197 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
1204 case SIDE_TYPE_U128
:
1209 case SIDE_TYPE_S128
:
1210 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1211 TRACER_DISPLAY_BASE_10
);
1214 case SIDE_TYPE_BYTE
:
1215 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
1216 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
1219 case SIDE_TYPE_POINTER
:
1220 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1221 TRACER_DISPLAY_BASE_16
);
1224 case SIDE_TYPE_FLOAT_BINARY16
:
1225 case SIDE_TYPE_FLOAT_BINARY32
:
1226 case SIDE_TYPE_FLOAT_BINARY64
:
1227 case SIDE_TYPE_FLOAT_BINARY128
:
1228 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
1231 case SIDE_TYPE_STRING_UTF8
:
1232 case SIDE_TYPE_STRING_UTF16
:
1233 case SIDE_TYPE_STRING_UTF32
:
1234 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
1235 tracer_print_string(side_ptr_get(item
->u
.side_static
.string_value
),
1236 type_desc
->u
.side_string
.unit_size
, side_enum_get(type_desc
->u
.side_string
.byte_order
), NULL
);
1239 /* Stack-copy compound types */
1240 case SIDE_TYPE_STRUCT
:
1241 tracer_print_struct(type_desc
, side_ptr_get(item
->u
.side_static
.side_struct
));
1243 case SIDE_TYPE_VARIANT
:
1244 tracer_print_variant(type_desc
, side_ptr_get(item
->u
.side_static
.side_variant
));
1246 case SIDE_TYPE_ARRAY
:
1247 tracer_print_array(type_desc
, side_ptr_get(item
->u
.side_static
.side_array
));
1250 tracer_print_vla(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla
));
1252 case SIDE_TYPE_VLA_VISITOR
:
1253 tracer_print_vla_visitor(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla_visitor
));
1256 /* Stack-copy enumeration types */
1257 case SIDE_TYPE_ENUM
:
1258 tracer_print_enum(type_desc
, item
);
1260 case SIDE_TYPE_ENUM_BITMAP
:
1261 tracer_print_enum_bitmap(type_desc
, item
);
1264 /* Gather basic types */
1265 case SIDE_TYPE_GATHER_BOOL
:
1266 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_bool_gather_ptr
));
1268 case SIDE_TYPE_GATHER_INTEGER
:
1269 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1270 TRACER_DISPLAY_BASE_10
);
1272 case SIDE_TYPE_GATHER_BYTE
:
1273 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_byte_gather_ptr
));
1275 case SIDE_TYPE_GATHER_POINTER
:
1276 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1277 TRACER_DISPLAY_BASE_16
);
1279 case SIDE_TYPE_GATHER_FLOAT
:
1280 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_float_gather_ptr
));
1282 case SIDE_TYPE_GATHER_STRING
:
1283 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_string_gather_ptr
));
1286 /* Gather compound type */
1287 case SIDE_TYPE_GATHER_STRUCT
:
1288 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_struct_gather_ptr
));
1290 case SIDE_TYPE_GATHER_ARRAY
:
1291 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_array_gather_ptr
));
1293 case SIDE_TYPE_GATHER_VLA
:
1294 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_vla_gather
.ptr
),
1295 side_ptr_get(item
->u
.side_static
.side_vla_gather
.length_ptr
));
1298 /* Gather enumeration types */
1299 case SIDE_TYPE_GATHER_ENUM
:
1300 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
));
1303 /* Dynamic basic types */
1304 case SIDE_TYPE_DYNAMIC_NULL
:
1305 case SIDE_TYPE_DYNAMIC_BOOL
:
1306 case SIDE_TYPE_DYNAMIC_INTEGER
:
1307 case SIDE_TYPE_DYNAMIC_BYTE
:
1308 case SIDE_TYPE_DYNAMIC_POINTER
:
1309 case SIDE_TYPE_DYNAMIC_FLOAT
:
1310 case SIDE_TYPE_DYNAMIC_STRING
:
1312 /* Dynamic compound types */
1313 case SIDE_TYPE_DYNAMIC_STRUCT
:
1314 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1315 case SIDE_TYPE_DYNAMIC_VLA
:
1316 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1317 tracer_print_dynamic(item
, false);
1320 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1328 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1330 printf("%s: ", side_ptr_get(item_desc
->field_name
));
1331 tracer_print_type(&item_desc
->side_type
, item
, true);
1335 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1337 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1338 const struct side_type_struct
*side_struct
= side_ptr_get(type_desc
->u
.side_struct
);
1339 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1341 if (side_struct
->nr_fields
!= side_sav_len
) {
1342 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1345 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1346 printf("%s", side_struct
->nr_attr
? ", " : "");
1347 printf("fields: { ");
1348 for (i
= 0; i
< side_sav_len
; i
++) {
1349 printf("%s", i
? ", " : "");
1350 tracer_print_field(&side_ptr_get(side_struct
->fields
)[i
], &sav
[i
]);
1356 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1358 const struct side_type_variant
*side_type_variant
= side_ptr_get(type_desc
->u
.side_variant
);
1359 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1363 if (side_enum_get(selector_type
->type
) != side_enum_get(side_arg_variant
->selector
.type
)) {
1364 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1367 switch (side_enum_get(selector_type
->type
)) {
1372 case SIDE_TYPE_U128
:
1377 case SIDE_TYPE_S128
:
1380 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1383 v
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1384 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1385 side_check_value_u64(v
);
1386 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1387 const struct side_variant_option
*option
= &side_ptr_get(side_type_variant
->options
)[i
];
1389 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= option
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= option
->range_end
) {
1390 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
, false);
1394 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
1399 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1401 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1402 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1404 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1405 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1408 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_array
.attr
), type_desc
->u
.side_array
.nr_attr
);
1409 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1410 printf("elements: ");
1412 for (i
= 0; i
< side_sav_len
; i
++) {
1413 printf("%s", i
? ", " : "");
1414 tracer_print_type(side_ptr_get(type_desc
->u
.side_array
.elem_type
), &sav
[i
], true);
1420 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1422 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1423 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1425 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla
.attr
), type_desc
->u
.side_vla
.nr_attr
);
1426 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1427 printf("elements: ");
1429 for (i
= 0; i
< side_sav_len
; i
++) {
1430 printf("%s", i
? ", " : "");
1431 tracer_print_type(side_ptr_get(type_desc
->u
.side_vla
.elem_type
), &sav
[i
], true);
1437 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1439 switch (access_mode
) {
1440 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1442 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1443 /* Dereference pointer */
1444 memcpy(&ptr
, ptr
, sizeof(const char *));
1452 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1454 switch (access_mode
) {
1455 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1457 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1458 return sizeof(void *);
1465 union int_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1468 enum side_type_gather_access_mode access_mode
=
1469 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1470 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1471 const char *ptr
= (const char *) _ptr
;
1472 union side_integer_value value
;
1474 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1475 memcpy(&value
, ptr
, integer_size_bytes
);
1476 return tracer_load_integer_value(&side_integer
->type
, &value
,
1477 side_integer
->offset_bits
, NULL
);
1481 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1483 enum side_type_gather_access_mode access_mode
=
1484 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1485 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1486 const char *ptr
= (const char *) _ptr
;
1487 union side_bool_value value
;
1489 switch (bool_size_bytes
) {
1498 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1499 memcpy(&value
, ptr
, bool_size_bytes
);
1500 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1501 type_gather
->u
.side_bool
.offset_bits
);
1502 return tracer_gather_size(access_mode
, bool_size_bytes
);
1506 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1508 enum side_type_gather_access_mode access_mode
=
1509 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1510 const char *ptr
= (const char *) _ptr
;
1513 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1514 memcpy(&value
, ptr
, 1);
1515 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_byte
.type
.attr
),
1516 type_gather
->u
.side_byte
.type
.nr_attr
);
1517 printf("0x%" PRIx8
, value
);
1518 return tracer_gather_size(access_mode
, 1);
1522 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1523 enum tracer_display_base default_base
)
1525 enum side_type_gather_access_mode access_mode
=
1526 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1527 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1528 const char *ptr
= (const char *) _ptr
;
1529 union side_integer_value value
;
1531 switch (integer_size_bytes
) {
1541 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1542 memcpy(&value
, ptr
, integer_size_bytes
);
1543 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1544 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1545 return tracer_gather_size(access_mode
, integer_size_bytes
);
1549 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1551 enum side_type_gather_access_mode access_mode
=
1552 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1553 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1554 const char *ptr
= (const char *) _ptr
;
1555 union side_float_value value
;
1557 switch (float_size_bytes
) {
1566 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1567 memcpy(&value
, ptr
, float_size_bytes
);
1568 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1569 return tracer_gather_size(access_mode
, float_size_bytes
);
1573 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1575 enum side_type_gather_access_mode access_mode
=
1576 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1577 const char *ptr
= (const char *) _ptr
;
1580 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1581 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_string
.type
.attr
),
1582 type_gather
->u
.side_string
.type
.nr_attr
);
1584 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1585 side_enum_get(type_gather
->u
.side_string
.type
.byte_order
), &string_len
);
1588 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1590 return tracer_gather_size(access_mode
, string_len
);
1594 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1599 switch (side_enum_get(type_desc
->type
)) {
1600 /* Gather basic types */
1601 case SIDE_TYPE_GATHER_BOOL
:
1602 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1604 case SIDE_TYPE_GATHER_INTEGER
:
1605 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1606 TRACER_DISPLAY_BASE_10
);
1608 case SIDE_TYPE_GATHER_BYTE
:
1609 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1611 case SIDE_TYPE_GATHER_POINTER
:
1612 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1613 TRACER_DISPLAY_BASE_16
);
1615 case SIDE_TYPE_GATHER_FLOAT
:
1616 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1618 case SIDE_TYPE_GATHER_STRING
:
1619 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1622 /* Gather enum types */
1623 case SIDE_TYPE_GATHER_ENUM
:
1624 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1627 /* Gather compound types */
1628 case SIDE_TYPE_GATHER_STRUCT
:
1629 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1631 case SIDE_TYPE_GATHER_ARRAY
:
1632 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1634 case SIDE_TYPE_GATHER_VLA
:
1635 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1638 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1646 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1648 const struct side_enum_mappings
*mappings
= side_ptr_get(type_gather
->u
.side_enum
.mappings
);
1649 const struct side_type
*enum_elem_type
= side_ptr_get(type_gather
->u
.side_enum
.elem_type
);
1650 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1651 enum side_type_gather_access_mode access_mode
=
1652 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1653 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1654 const char *ptr
= (const char *) _ptr
;
1655 union side_integer_value value
;
1658 switch (integer_size_bytes
) {
1668 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1669 memcpy(&value
, ptr
, integer_size_bytes
);
1670 v
= tracer_load_gather_integer_value(side_integer
, &value
);
1671 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1672 printf("%s", mappings
->nr_attr
? ", " : "");
1673 tracer_print_gather_type(enum_elem_type
, ptr
);
1674 print_enum_labels(mappings
, v
);
1675 return tracer_gather_size(access_mode
, integer_size_bytes
);
1679 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1681 printf("%s: ", side_ptr_get(field
->field_name
));
1682 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1686 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1688 enum side_type_gather_access_mode access_mode
=
1689 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1690 const struct side_type_struct
*side_struct
= side_ptr_get(type_gather
->u
.side_struct
.type
);
1691 const char *ptr
= (const char *) _ptr
;
1694 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1695 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1696 printf("%s", side_struct
->nr_attr
? ", " : "");
1697 printf("fields: { ");
1698 for (i
= 0; i
< side_struct
->nr_fields
; i
++) {
1699 printf("%s", i
? ", " : "");
1700 tracer_print_gather_field(&side_ptr_get(side_struct
->fields
)[i
], ptr
);
1703 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1707 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1709 enum side_type_gather_access_mode access_mode
=
1710 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1711 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1714 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1716 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_array
.type
.attr
), type_gather
->u
.side_array
.type
.nr_attr
);
1717 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1718 printf("elements: ");
1720 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1721 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_array
.type
.elem_type
);
1723 switch (side_enum_get(elem_type
->type
)) {
1724 case SIDE_TYPE_GATHER_VLA
:
1725 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1730 printf("%s", i
? ", " : "");
1731 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1734 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1738 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1739 const void *_length_ptr
)
1741 enum side_type_gather_access_mode access_mode
=
1742 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1743 const struct side_type
*length_type
= side_ptr_get(type_gather
->u
.side_vla
.length_type
);
1744 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1745 const char *length_ptr
= (const char *) _length_ptr
;
1746 union int_value v
= {};
1750 switch (side_enum_get(length_type
->type
)) {
1751 case SIDE_TYPE_GATHER_INTEGER
:
1754 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1757 v
= tracer_load_gather_integer_value(&length_type
->u
.side_gather
.u
.side_integer
,
1759 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] || v
.u
[SIDE_INTEGER128_SPLIT_LOW
] > UINT32_MAX
) {
1760 fprintf(stderr
, "Unexpected vla length value\n");
1763 length
= (uint32_t) v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
1764 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1766 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_vla
.type
.attr
), type_gather
->u
.side_vla
.type
.nr_attr
);
1767 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1768 printf("elements: ");
1770 for (i
= 0; i
< length
; i
++) {
1771 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_vla
.type
.elem_type
);
1773 switch (side_enum_get(elem_type
->type
)) {
1774 case SIDE_TYPE_GATHER_VLA
:
1775 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1780 printf("%s", i
? ", " : "");
1781 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1784 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1787 struct tracer_visitor_priv
{
1788 const struct side_type
*elem_type
;
1793 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1794 const struct side_arg
*elem
)
1796 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1798 printf("%s", tracer_priv
->i
++ ? ", " : "");
1799 tracer_print_type(tracer_priv
->elem_type
, elem
, true);
1800 return SIDE_VISITOR_STATUS_OK
;
1804 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
)
1807 enum side_visitor_status status
;
1808 struct tracer_visitor_priv tracer_priv
= {
1809 .elem_type
= side_ptr_get(type_desc
->u
.side_vla_visitor
.elem_type
),
1812 const struct side_tracer_visitor_ctx tracer_ctx
= {
1813 .write_elem
= tracer_write_elem_cb
,
1814 .priv
= &tracer_priv
,
1816 side_visitor_func func
;
1820 app_ctx
= side_ptr_get(vla_visitor
->app_ctx
);
1821 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla_visitor
.attr
), type_desc
->u
.side_vla_visitor
.nr_attr
);
1822 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1823 printf("elements: ");
1825 func
= side_ptr_get(type_desc
->u
.side_vla_visitor
.visitor
);
1826 status
= func(&tracer_ctx
, app_ctx
);
1828 case SIDE_VISITOR_STATUS_OK
:
1830 case SIDE_VISITOR_STATUS_ERROR
:
1831 fprintf(stderr
, "ERROR: Visitor error\n");
1838 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1840 const struct side_arg_dynamic_field
*fields
= side_ptr_get(dynamic_struct
->fields
);
1841 uint32_t i
, len
= dynamic_struct
->len
;
1843 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1844 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1845 printf("fields:: ");
1847 for (i
= 0; i
< len
; i
++) {
1848 printf("%s", i
? ", " : "");
1849 printf("%s:: ", side_ptr_get(fields
[i
].field_name
));
1850 tracer_print_dynamic(&fields
[i
].elem
, true);
1855 struct tracer_dynamic_struct_visitor_priv
{
1860 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1861 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1862 const struct side_arg_dynamic_field
*dynamic_field
)
1864 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1865 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1867 printf("%s", tracer_priv
->i
++ ? ", " : "");
1868 printf("%s:: ", side_ptr_get(dynamic_field
->field_name
));
1869 tracer_print_dynamic(&dynamic_field
->elem
, true);
1870 return SIDE_VISITOR_STATUS_OK
;
1874 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1876 struct side_arg_dynamic_struct_visitor
*dynamic_struct_visitor
;
1877 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1880 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1881 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1882 .priv
= &tracer_priv
,
1884 enum side_visitor_status status
;
1887 dynamic_struct_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
);
1888 if (!dynamic_struct_visitor
)
1890 app_ctx
= side_ptr_get(dynamic_struct_visitor
->app_ctx
);
1891 print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor
->attr
), dynamic_struct_visitor
->nr_attr
);
1892 printf("%s", dynamic_struct_visitor
->nr_attr
? ", " : "");
1893 printf("fields:: ");
1895 status
= side_ptr_get(dynamic_struct_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1897 case SIDE_VISITOR_STATUS_OK
:
1899 case SIDE_VISITOR_STATUS_ERROR
:
1900 fprintf(stderr
, "ERROR: Visitor error\n");
1907 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1909 const struct side_arg
*sav
= side_ptr_get(vla
->sav
);
1910 uint32_t i
, side_sav_len
= vla
->len
;
1912 print_attributes("attr", "::", side_ptr_get(vla
->attr
), vla
->nr_attr
);
1913 printf("%s", vla
->nr_attr
? ", " : "");
1914 printf("elements:: ");
1916 for (i
= 0; i
< side_sav_len
; i
++) {
1917 printf("%s", i
? ", " : "");
1918 tracer_print_dynamic(&sav
[i
], true);
1923 struct tracer_dynamic_vla_visitor_priv
{
1928 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1929 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1930 const struct side_arg
*elem
)
1932 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1933 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1935 printf("%s", tracer_priv
->i
++ ? ", " : "");
1936 tracer_print_dynamic(elem
, true);
1937 return SIDE_VISITOR_STATUS_OK
;
1941 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1943 struct side_arg_dynamic_vla_visitor
*dynamic_vla_visitor
;
1944 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1947 const struct side_tracer_visitor_ctx tracer_ctx
= {
1948 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1949 .priv
= &tracer_priv
,
1951 enum side_visitor_status status
;
1954 dynamic_vla_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
);
1955 if (!dynamic_vla_visitor
)
1957 app_ctx
= side_ptr_get(dynamic_vla_visitor
->app_ctx
);
1958 print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor
->attr
), dynamic_vla_visitor
->nr_attr
);
1959 printf("%s", dynamic_vla_visitor
->nr_attr
? ", " : "");
1960 printf("elements:: ");
1962 status
= side_ptr_get(dynamic_vla_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1964 case SIDE_VISITOR_STATUS_OK
:
1966 case SIDE_VISITOR_STATUS_ERROR
:
1967 fprintf(stderr
, "ERROR: Visitor error\n");
1974 void tracer_print_dynamic(const struct side_arg
*item
, bool print_brackets
)
1978 switch (side_enum_get(item
->type
)) {
1979 /* Dynamic basic types */
1980 case SIDE_TYPE_DYNAMIC_NULL
:
1981 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1982 item
->u
.side_dynamic
.side_null
.nr_attr
);
1983 printf("<NULL TYPE>");
1985 case SIDE_TYPE_DYNAMIC_BOOL
:
1986 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1988 case SIDE_TYPE_DYNAMIC_INTEGER
:
1989 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1990 TRACER_DISPLAY_BASE_10
);
1992 case SIDE_TYPE_DYNAMIC_BYTE
:
1993 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1994 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1996 case SIDE_TYPE_DYNAMIC_POINTER
:
1997 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1998 TRACER_DISPLAY_BASE_16
);
2000 case SIDE_TYPE_DYNAMIC_FLOAT
:
2001 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
2002 &item
->u
.side_dynamic
.side_float
.value
);
2004 case SIDE_TYPE_DYNAMIC_STRING
:
2005 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
2006 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
2007 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
2008 side_enum_get(item
->u
.side_dynamic
.side_string
.type
.byte_order
), NULL
);
2011 /* Dynamic compound types */
2012 case SIDE_TYPE_DYNAMIC_STRUCT
:
2013 tracer_print_dynamic_struct(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct
));
2015 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
2016 tracer_print_dynamic_struct_visitor(item
);
2018 case SIDE_TYPE_DYNAMIC_VLA
:
2019 tracer_print_dynamic_vla(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla
));
2021 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
2022 tracer_print_dynamic_vla_visitor(item
);
2025 fprintf(stderr
, "<UNKNOWN TYPE>\n");
2033 void tracer_print_static_fields(const struct side_event_description
*desc
,
2034 const struct side_arg_vec
*side_arg_vec
,
2035 uint32_t *nr_items
, void *caller_addr
)
2037 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
2038 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
2041 printf("caller: [%p], ", caller_addr
);
2042 printf("provider: %s, event: %s",
2043 side_ptr_get(desc
->provider_name
),
2044 side_ptr_get(desc
->event_name
));
2045 if (desc
->nr_fields
!= side_sav_len
) {
2046 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
2049 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
2050 printf("%s", side_sav_len
? ", fields: { " : "");
2051 for (i
= 0; i
< side_sav_len
; i
++) {
2052 printf("%s", i
? ", " : "");
2053 tracer_print_field(&side_ptr_get(desc
->fields
)[i
], &sav
[i
]);
2062 void tracer_call(const struct side_event_description
*desc
,
2063 const struct side_arg_vec
*side_arg_vec
,
2064 void *priv
__attribute__((unused
)),
2067 uint32_t nr_fields
= 0;
2069 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2074 void tracer_call_variadic(const struct side_event_description
*desc
,
2075 const struct side_arg_vec
*side_arg_vec
,
2076 const struct side_arg_dynamic_struct
*var_struct
,
2077 void *priv
__attribute__((unused
)),
2080 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
2082 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2084 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
2085 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
2088 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
2089 printf("%s", var_struct_len
? ", fields:: { " : "");
2090 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
2091 printf("%s", i
? ", " : "");
2092 printf("%s:: ", side_ptr_get(side_ptr_get(var_struct
->fields
)[i
].field_name
));
2093 tracer_print_dynamic(&side_ptr_get(var_struct
->fields
)[i
].elem
, true);
2101 void tracer_event_notification(enum side_tracer_notification notif
,
2102 struct side_event_description
**events
, uint32_t nr_events
,
2103 void *priv
__attribute__((unused
)))
2108 printf("----------------------------------------------------------\n");
2109 printf("Tracer notified of events %s\n",
2110 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
2111 for (i
= 0; i
< nr_events
; i
++) {
2112 struct side_event_description
*event
= events
[i
];
2114 /* Skip NULL pointers */
2117 if (event
->version
!= SIDE_EVENT_DESCRIPTION_ABI_VERSION
) {
2118 printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n",
2119 event
->version
, SIDE_EVENT_DESCRIPTION_ABI_VERSION
);
2122 printf("provider: %s, event: %s\n",
2123 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2124 if (event
->struct_size
!= side_offsetofend(struct side_event_description
, side_event_description_orig_abi_last
)) {
2125 printf("Warning: Event %s.%s description contains fields unknown to the tracer\n",
2126 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2128 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
2129 if (event
->nr_side_type_label
> _NR_SIDE_TYPE_LABEL
) {
2130 printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
2131 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2132 event
->nr_side_type_label
- _NR_SIDE_TYPE_LABEL
);
2134 if (event
->nr_side_attr_type
> _NR_SIDE_ATTR_TYPE
) {
2135 printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n",
2136 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2137 event
->nr_side_attr_type
- _NR_SIDE_ATTR_TYPE
);
2139 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2140 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
, tracer_key
);
2144 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
, tracer_key
);
2149 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2150 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
, tracer_key
);
2154 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
, tracer_key
);
2160 printf("----------------------------------------------------------\n");
2163 static __attribute__((constructor
))
2164 void tracer_init(void);
2166 void tracer_init(void)
2168 if (side_tracer_request_key(&tracer_key
))
2170 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
2175 static __attribute__((destructor
))
2176 void tracer_exit(void);
2178 void tracer_exit(void)
2180 side_tracer_event_notification_unregister(tracer_handle
);