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
,
28 static struct side_tracer_handle
*tracer_handle
;
31 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
33 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
);
35 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
37 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
39 void tracer_print_vla_visitor(const struct side_type
*type_desc
, void *app_ctx
);
41 void tracer_print_dynamic(const struct side_arg
*dynamic_item
);
43 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
45 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
47 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
48 enum tracer_display_base default_base
);
50 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
52 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
54 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
56 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
58 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
60 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
61 const void *_length_ptr
);
63 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
);
66 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
67 size_t *strlen_with_null
,
70 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
;
71 const char *str
= p
, *fromcode
;
72 char *inbuf
= (char *) p
, *outbuf
, *buf
;
78 *strlen_with_null
= strlen(str
) + 1;
79 *output_str
= (char *) str
;
83 const uint16_t *p16
= p
;
86 case SIDE_TYPE_BYTE_ORDER_LE
:
88 fromcode
= "UTF-16LE";
91 case SIDE_TYPE_BYTE_ORDER_BE
:
93 fromcode
= "UTF-16BE";
97 fprintf(stderr
, "Unknown byte order\n");
103 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
104 * { ef, bf, bf } UTF-8 (3 bytes).
106 bufsize
= inbytesleft
/ 2 * 3 + 1;
111 const uint32_t *p32
= p
;
113 switch (byte_order
) {
114 case SIDE_TYPE_BYTE_ORDER_LE
:
116 fromcode
= "UTF-32LE";
119 case SIDE_TYPE_BYTE_ORDER_BE
:
121 fromcode
= "UTF-32BE";
125 fprintf(stderr
, "Unknown byte order\n");
131 * Each 4-byte UTF-32 character converts to at most a
132 * 4-byte UTF-8 character.
134 bufsize
= inbytesleft
+ 1;
138 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
142 cd
= iconv_open("UTF8", fromcode
);
143 if (cd
== (iconv_t
) -1) {
144 perror("iconv_open");
147 buf
= malloc(bufsize
);
151 outbuf
= (char *) buf
;
152 outbytesleft
= bufsize
;
153 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
154 if (ret
== (size_t) -1) {
159 fprintf(stderr
, "Buffer too small to convert string input\n");
163 if (iconv_close(cd
) == -1) {
164 perror("iconv_close");
167 if (strlen_with_null
)
168 *strlen_with_null
= outbuf
- buf
;
173 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
174 size_t *strlen_with_null
)
176 char *output_str
= NULL
;
178 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
179 printf("\"%s\"", output_str
);
185 int64_t get_attr_integer_value(const struct side_attr
*attr
)
189 switch (attr
->value
.type
) {
190 case SIDE_ATTR_TYPE_U8
:
191 val
= attr
->value
.u
.integer_value
.side_u8
;
193 case SIDE_ATTR_TYPE_U16
:
194 val
= attr
->value
.u
.integer_value
.side_u16
;
196 case SIDE_ATTR_TYPE_U32
:
197 val
= attr
->value
.u
.integer_value
.side_u32
;
199 case SIDE_ATTR_TYPE_U64
:
200 val
= attr
->value
.u
.integer_value
.side_u64
;
202 case SIDE_ATTR_TYPE_S8
:
203 val
= attr
->value
.u
.integer_value
.side_s8
;
205 case SIDE_ATTR_TYPE_S16
:
206 val
= attr
->value
.u
.integer_value
.side_s16
;
208 case SIDE_ATTR_TYPE_S32
:
209 val
= attr
->value
.u
.integer_value
.side_s32
;
211 case SIDE_ATTR_TYPE_S64
:
212 val
= attr
->value
.u
.integer_value
.side_s64
;
215 fprintf(stderr
, "Unexpected attribute type\n");
222 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
223 enum tracer_display_base default_base
)
227 for (i
= 0; i
< nr_attr
; i
++) {
228 const struct side_attr
*attr
= &_attr
[i
];
229 char *utf8_str
= NULL
;
232 tracer_convert_string_to_utf8(attr
->key
.p
, attr
->key
.unit_size
,
233 attr
->key
.byte_order
, NULL
, &utf8_str
);
234 cmp
= strcmp(utf8_str
, "std.integer.base");
235 if (utf8_str
!= attr
->key
.p
)
238 int64_t val
= get_attr_integer_value(attr
);
242 return TRACER_DISPLAY_BASE_2
;
244 return TRACER_DISPLAY_BASE_8
;
246 return TRACER_DISPLAY_BASE_10
;
248 return TRACER_DISPLAY_BASE_16
;
250 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
255 return default_base
; /* Default */
259 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
261 char *utf8_str
= NULL
;
263 tracer_convert_string_to_utf8(attr
->key
.p
, attr
->key
.unit_size
,
264 attr
->key
.byte_order
, NULL
, &utf8_str
);
265 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
266 if (utf8_str
!= attr
->key
.p
)
268 switch (attr
->value
.type
) {
269 case SIDE_ATTR_TYPE_BOOL
:
270 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
272 case SIDE_ATTR_TYPE_U8
:
273 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
275 case SIDE_ATTR_TYPE_U16
:
276 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
278 case SIDE_ATTR_TYPE_U32
:
279 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
281 case SIDE_ATTR_TYPE_U64
:
282 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
284 case SIDE_ATTR_TYPE_S8
:
285 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
287 case SIDE_ATTR_TYPE_S16
:
288 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
290 case SIDE_ATTR_TYPE_S32
:
291 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
293 case SIDE_ATTR_TYPE_S64
:
294 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
296 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
298 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
301 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
304 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
306 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
309 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
312 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
314 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
317 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
320 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
322 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
325 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
328 case SIDE_ATTR_TYPE_STRING
:
329 tracer_print_string(attr
->value
.u
.string_value
.p
,
330 attr
->value
.u
.string_value
.unit_size
,
331 attr
->value
.u
.string_value
.byte_order
, NULL
);
334 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
341 void print_attributes(const char *prefix_str
, const char *separator
,
342 const struct side_attr
*attr
, uint32_t nr_attr
)
348 printf("%s%s [ ", prefix_str
, separator
);
349 for (i
= 0; i
< nr_attr
; i
++) {
350 printf("%s", i
? ", " : "");
351 tracer_print_attr_type(separator
, &attr
[i
]);
357 union int64_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
358 const union side_integer_value
*value
,
359 uint16_t offset_bits
, uint16_t *_len_bits
)
361 union int64_value v64
;
365 if (!type_integer
->len_bits
)
366 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
368 len_bits
= type_integer
->len_bits
;
369 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
371 reverse_bo
= type_integer
->byte_order
!= SIDE_TYPE_BYTE_ORDER_HOST
;
372 switch (type_integer
->integer_size
) {
374 if (type_integer
->signedness
)
375 v64
.s
= value
->side_s8
;
377 v64
.u
= value
->side_u8
;
380 if (type_integer
->signedness
) {
383 side_s16
= value
->side_s16
;
385 side_s16
= side_bswap_16(side_s16
);
390 side_u16
= value
->side_u16
;
392 side_u16
= side_bswap_16(side_u16
);
397 if (type_integer
->signedness
) {
400 side_s32
= value
->side_s32
;
402 side_s32
= side_bswap_32(side_s32
);
407 side_u32
= value
->side_u32
;
409 side_u32
= side_bswap_32(side_u32
);
414 if (type_integer
->signedness
) {
417 side_s64
= value
->side_s64
;
419 side_s64
= side_bswap_64(side_s64
);
424 side_u64
= value
->side_u64
;
426 side_u64
= side_bswap_64(side_u64
);
433 v64
.u
>>= offset_bits
;
435 v64
.u
&= (1ULL << len_bits
) - 1;
436 if (type_integer
->signedness
) {
438 if (v64
.u
& (1ULL << (len_bits
- 1)))
439 v64
.u
|= ~((1ULL << len_bits
) - 1);
443 *_len_bits
= len_bits
;
448 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int64_value v64
)
450 uint32_t i
, print_count
= 0;
452 printf(", labels: [ ");
453 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
454 const struct side_enum_mapping
*mapping
= &mappings
->mappings
[i
];
456 if (mapping
->range_end
< mapping
->range_begin
) {
457 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
458 mapping
->range_begin
, mapping
->range_end
);
461 if (v64
.s
>= mapping
->range_begin
&& v64
.s
<= mapping
->range_end
) {
462 printf("%s", print_count
++ ? ", " : "");
463 tracer_print_string(mapping
->label
.p
, mapping
->label
.unit_size
, mapping
->label
.byte_order
, NULL
);
467 printf("<NO LABEL>");
472 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
474 const struct side_enum_mappings
*mappings
= type_desc
->u
.side_enum
.mappings
;
475 const struct side_type
*elem_type
= type_desc
->u
.side_enum
.elem_type
;
476 union int64_value v64
;
478 if (elem_type
->type
!= item
->type
) {
479 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
482 v64
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
483 &item
->u
.side_static
.integer_value
, 0, NULL
);
484 print_attributes("attr", ":", mappings
->attr
, mappings
->nr_attr
);
485 printf("%s", mappings
->nr_attr
? ", " : "");
486 tracer_print_type(elem_type
, item
);
487 print_enum_labels(mappings
, v64
);
491 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
495 switch (elem_type
->type
) {
508 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
510 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
517 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
518 const struct side_arg
*item
)
520 const struct side_enum_bitmap_mappings
*side_enum_mappings
= type_desc
->u
.side_enum_bitmap
.mappings
;
521 const struct side_type
*enum_elem_type
= type_desc
->u
.side_enum_bitmap
.elem_type
, *elem_type
;
522 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
523 const struct side_arg
*array_item
;
525 switch (enum_elem_type
->type
) {
526 case SIDE_TYPE_U8
: /* Fall-through */
527 case SIDE_TYPE_BYTE
: /* Fall-through */
528 case SIDE_TYPE_U16
: /* Fall-through */
529 case SIDE_TYPE_U32
: /* Fall-through */
530 case SIDE_TYPE_U64
: /* Fall-through */
531 case SIDE_TYPE_S8
: /* Fall-through */
532 case SIDE_TYPE_S16
: /* Fall-through */
533 case SIDE_TYPE_S32
: /* Fall-through */
535 elem_type
= enum_elem_type
;
539 case SIDE_TYPE_ARRAY
:
540 elem_type
= enum_elem_type
->u
.side_array
.elem_type
;
541 array_item
= item
->u
.side_static
.side_array
->sav
;
542 nr_items
= type_desc
->u
.side_array
.length
;
545 elem_type
= enum_elem_type
->u
.side_vla
.elem_type
;
546 array_item
= item
->u
.side_static
.side_vla
->sav
;
547 nr_items
= item
->u
.side_static
.side_vla
->len
;
550 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
553 stride_bit
= elem_type_to_stride(elem_type
);
555 print_attributes("attr", ":", side_enum_mappings
->attr
, side_enum_mappings
->nr_attr
);
556 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
557 printf("labels: [ ");
558 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
559 const struct side_enum_bitmap_mapping
*mapping
= &side_enum_mappings
->mappings
[i
];
563 if (mapping
->range_end
< mapping
->range_begin
) {
564 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
565 mapping
->range_begin
, mapping
->range_end
);
568 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
569 if (bit
> (nr_items
* stride_bit
) - 1)
571 if (elem_type
->type
== SIDE_TYPE_BYTE
) {
572 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
573 if (v
& (1ULL << (bit
% 8))) {
578 union int64_value v64
;
580 v64
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
581 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
583 if (v64
.u
& (1ULL << (bit
% stride_bit
))) {
591 printf("%s", print_count
++ ? ", " : "");
592 tracer_print_string(mapping
->label
.p
, mapping
->label
.unit_size
, mapping
->label
.byte_order
, NULL
);
596 printf("<NO LABEL>");
601 void print_integer_binary(uint64_t v
, int bits
)
607 for (i
= 0; i
< bits
; i
++) {
608 printf("%c", v
& (1ULL << 63) ? '1' : '0');
614 void tracer_print_type_header(const char *separator
,
615 const struct side_attr
*attr
, uint32_t nr_attr
)
617 print_attributes("attr", separator
, attr
, nr_attr
);
618 printf("%s", nr_attr
? ", " : "");
619 printf("value%s ", separator
);
623 void tracer_print_type_bool(const char *separator
,
624 const struct side_type_bool
*type_bool
,
625 const union side_bool_value
*value
,
626 uint16_t offset_bits
)
632 if (!type_bool
->len_bits
)
633 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
635 len_bits
= type_bool
->len_bits
;
636 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
638 reverse_bo
= type_bool
->byte_order
!= SIDE_TYPE_BYTE_ORDER_HOST
;
639 switch (type_bool
->bool_size
) {
641 v
= value
->side_bool8
;
647 side_u16
= value
->side_bool16
;
649 side_u16
= side_bswap_16(side_u16
);
657 side_u32
= value
->side_bool32
;
659 side_u32
= side_bswap_32(side_u32
);
667 side_u64
= value
->side_bool64
;
669 side_u64
= side_bswap_64(side_u64
);
678 v
&= (1ULL << len_bits
) - 1;
679 tracer_print_type_header(separator
, type_bool
->attr
, type_bool
->nr_attr
);
680 printf("%s", v
? "true" : "false");
684 void tracer_print_type_integer(const char *separator
,
685 const struct side_type_integer
*type_integer
,
686 const union side_integer_value
*value
,
687 uint16_t offset_bits
,
688 enum tracer_display_base default_base
)
690 enum tracer_display_base base
;
691 union int64_value v64
;
694 v64
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
695 tracer_print_type_header(separator
, type_integer
->attr
, type_integer
->nr_attr
);
696 base
= get_attr_display_base(type_integer
->attr
, type_integer
->nr_attr
, default_base
);
698 case TRACER_DISPLAY_BASE_2
:
699 print_integer_binary(v64
.u
, len_bits
);
701 case TRACER_DISPLAY_BASE_8
:
702 /* Clear sign bits beyond len_bits */
704 v64
.u
&= (1ULL << len_bits
) - 1;
705 printf("0%" PRIo64
, v64
.u
);
707 case TRACER_DISPLAY_BASE_10
:
708 if (type_integer
->signedness
)
709 printf("%" PRId64
, v64
.s
);
711 printf("%" PRIu64
, v64
.u
);
713 case TRACER_DISPLAY_BASE_16
:
714 /* Clear sign bits beyond len_bits */
716 v64
.u
&= (1ULL << len_bits
) - 1;
717 printf("0x%" PRIx64
, v64
.u
);
725 void tracer_print_type_float(const char *separator
,
726 const struct side_type_float
*type_float
,
727 const union side_float_value
*value
)
731 tracer_print_type_header(separator
, type_float
->attr
, type_float
->nr_attr
);
732 reverse_bo
= type_float
->byte_order
!= SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
733 switch (type_float
->float_size
) {
741 .f
= value
->side_float_binary16
,
745 float16
.u
= side_bswap_16(float16
.u
);
746 printf("%g", (double) float16
.f
);
749 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
760 .f
= value
->side_float_binary32
,
764 float32
.u
= side_bswap_32(float32
.u
);
765 printf("%g", (double) float32
.f
);
768 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
779 .f
= value
->side_float_binary64
,
783 float64
.u
= side_bswap_64(float64
.u
);
784 printf("%g", (double) float64
.f
);
787 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
798 .f
= value
->side_float_binary128
,
802 side_bswap_128p(float128
.arr
);
803 printf("%Lg", (long double) float128
.f
);
806 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
811 fprintf(stderr
, "ERROR: Unknown float size\n");
817 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
)
819 enum side_type_label type
;
821 switch (type_desc
->type
) {
823 switch (item
->type
) {
834 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
840 case SIDE_TYPE_ENUM_BITMAP
:
841 switch (item
->type
) {
847 case SIDE_TYPE_ARRAY
:
851 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
857 case SIDE_TYPE_GATHER_ENUM
:
858 switch (item
->type
) {
859 case SIDE_TYPE_GATHER_INTEGER
:
862 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
868 case SIDE_TYPE_DYNAMIC
:
869 switch (item
->type
) {
870 case SIDE_TYPE_DYNAMIC_NULL
:
871 case SIDE_TYPE_DYNAMIC_BOOL
:
872 case SIDE_TYPE_DYNAMIC_INTEGER
:
873 case SIDE_TYPE_DYNAMIC_BYTE
:
874 case SIDE_TYPE_DYNAMIC_POINTER
:
875 case SIDE_TYPE_DYNAMIC_FLOAT
:
876 case SIDE_TYPE_DYNAMIC_STRING
:
877 case SIDE_TYPE_DYNAMIC_STRUCT
:
878 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
879 case SIDE_TYPE_DYNAMIC_VLA
:
880 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
883 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
890 if (type_desc
->type
!= item
->type
) {
891 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
897 if (type_desc
->type
== SIDE_TYPE_ENUM
|| type_desc
->type
== SIDE_TYPE_ENUM_BITMAP
||
898 type_desc
->type
== SIDE_TYPE_GATHER_ENUM
)
899 type
= (enum side_type_label
) type_desc
->type
;
901 type
= (enum side_type_label
) item
->type
;
905 /* Stack-copy basic types */
907 tracer_print_type_header(":", type_desc
->u
.side_null
.attr
, type_desc
->u
.side_null
.nr_attr
);
908 printf("<NULL TYPE>");
912 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
923 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
924 TRACER_DISPLAY_BASE_10
);
928 tracer_print_type_header(":", type_desc
->u
.side_byte
.attr
, type_desc
->u
.side_byte
.nr_attr
);
929 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
932 case SIDE_TYPE_POINTER
:
933 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
934 TRACER_DISPLAY_BASE_16
);
937 case SIDE_TYPE_FLOAT_BINARY16
:
938 case SIDE_TYPE_FLOAT_BINARY32
:
939 case SIDE_TYPE_FLOAT_BINARY64
:
940 case SIDE_TYPE_FLOAT_BINARY128
:
941 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
944 case SIDE_TYPE_STRING_UTF8
:
945 case SIDE_TYPE_STRING_UTF16
:
946 case SIDE_TYPE_STRING_UTF32
:
947 tracer_print_type_header(":", type_desc
->u
.side_string
.attr
, type_desc
->u
.side_string
.nr_attr
);
948 tracer_print_string((const void *)(uintptr_t) item
->u
.side_static
.string_value
,
949 type_desc
->u
.side_string
.unit_size
, type_desc
->u
.side_string
.byte_order
, NULL
);
952 /* Stack-copy compound types */
953 case SIDE_TYPE_STRUCT
:
954 tracer_print_struct(type_desc
, item
->u
.side_static
.side_struct
);
956 case SIDE_TYPE_VARIANT
:
957 tracer_print_variant(type_desc
, item
->u
.side_static
.side_variant
);
959 case SIDE_TYPE_ARRAY
:
960 tracer_print_array(type_desc
, item
->u
.side_static
.side_array
);
963 tracer_print_vla(type_desc
, item
->u
.side_static
.side_vla
);
965 case SIDE_TYPE_VLA_VISITOR
:
966 tracer_print_vla_visitor(type_desc
, item
->u
.side_static
.side_vla_app_visitor_ctx
);
969 /* Stack-copy enumeration types */
971 tracer_print_enum(type_desc
, item
);
973 case SIDE_TYPE_ENUM_BITMAP
:
974 tracer_print_enum_bitmap(type_desc
, item
);
977 /* Gather basic types */
978 case SIDE_TYPE_GATHER_BOOL
:
979 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_bool_gather_ptr
);
981 case SIDE_TYPE_GATHER_INTEGER
:
982 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
983 TRACER_DISPLAY_BASE_10
);
985 case SIDE_TYPE_GATHER_BYTE
:
986 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_byte_gather_ptr
);
988 case SIDE_TYPE_GATHER_POINTER
:
989 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
990 TRACER_DISPLAY_BASE_16
);
992 case SIDE_TYPE_GATHER_FLOAT
:
993 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_float_gather_ptr
);
995 case SIDE_TYPE_GATHER_STRING
:
996 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_string_gather_ptr
);
999 /* Gather compound type */
1000 case SIDE_TYPE_GATHER_STRUCT
:
1001 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_struct_gather_ptr
);
1003 case SIDE_TYPE_GATHER_ARRAY
:
1004 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_array_gather_ptr
);
1006 case SIDE_TYPE_GATHER_VLA
:
1007 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_vla_gather
.ptr
,
1008 item
->u
.side_static
.side_vla_gather
.length_ptr
);
1011 /* Gather enumeration types */
1012 case SIDE_TYPE_GATHER_ENUM
:
1013 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
);
1016 /* Dynamic basic types */
1017 case SIDE_TYPE_DYNAMIC_NULL
:
1018 case SIDE_TYPE_DYNAMIC_BOOL
:
1019 case SIDE_TYPE_DYNAMIC_INTEGER
:
1020 case SIDE_TYPE_DYNAMIC_BYTE
:
1021 case SIDE_TYPE_DYNAMIC_POINTER
:
1022 case SIDE_TYPE_DYNAMIC_FLOAT
:
1023 case SIDE_TYPE_DYNAMIC_STRING
:
1025 /* Dynamic compound types */
1026 case SIDE_TYPE_DYNAMIC_STRUCT
:
1027 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1028 case SIDE_TYPE_DYNAMIC_VLA
:
1029 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1030 tracer_print_dynamic(item
);
1033 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1040 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1042 printf("%s: ", item_desc
->field_name
);
1043 tracer_print_type(&item_desc
->side_type
, item
);
1047 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1049 const struct side_arg
*sav
= side_arg_vec
->sav
;
1050 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1052 if (type_desc
->u
.side_struct
->nr_fields
!= side_sav_len
) {
1053 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1056 print_attributes("attr", ":", type_desc
->u
.side_struct
->attr
, type_desc
->u
.side_struct
->nr_attr
);
1057 printf("%s", type_desc
->u
.side_struct
->nr_attr
? ", " : "");
1058 printf("fields: { ");
1059 for (i
= 0; i
< side_sav_len
; i
++) {
1060 printf("%s", i
? ", " : "");
1061 tracer_print_field(&type_desc
->u
.side_struct
->fields
[i
], &sav
[i
]);
1067 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1069 const struct side_type_variant
*side_type_variant
= type_desc
->u
.side_variant
;
1070 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1071 union int64_value v64
;
1074 if (selector_type
->type
!= side_arg_variant
->selector
.type
) {
1075 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1078 switch (selector_type
->type
) {
1089 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1092 v64
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1093 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1094 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1095 const struct side_variant_option
*option
= &side_type_variant
->options
[i
];
1097 if (v64
.s
>= option
->range_begin
&& v64
.s
<= option
->range_end
) {
1098 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
);
1102 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v64
.s
);
1107 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1109 const struct side_arg
*sav
= side_arg_vec
->sav
;
1110 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1112 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1113 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1116 print_attributes("attr", ":", type_desc
->u
.side_array
.attr
, type_desc
->u
.side_array
.nr_attr
);
1117 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1118 printf("elements: ");
1120 for (i
= 0; i
< side_sav_len
; i
++) {
1121 printf("%s", i
? ", " : "");
1122 tracer_print_type(type_desc
->u
.side_array
.elem_type
, &sav
[i
]);
1128 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1130 const struct side_arg
*sav
= side_arg_vec
->sav
;
1131 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1133 print_attributes("attr", ":", type_desc
->u
.side_vla
.attr
, type_desc
->u
.side_vla
.nr_attr
);
1134 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1135 printf("elements: ");
1137 for (i
= 0; i
< side_sav_len
; i
++) {
1138 printf("%s", i
? ", " : "");
1139 tracer_print_type(type_desc
->u
.side_vla
.elem_type
, &sav
[i
]);
1145 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1147 switch (access_mode
) {
1148 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1150 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1151 /* Dereference pointer */
1152 memcpy(&ptr
, ptr
, sizeof(ptr
));
1160 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1162 switch (access_mode
) {
1163 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1165 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1166 return sizeof(void *);
1173 union int64_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1176 enum side_type_gather_access_mode access_mode
=
1177 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1178 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1179 const char *ptr
= (const char *) _ptr
;
1180 union side_integer_value value
;
1182 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1183 memcpy(&value
, ptr
, integer_size_bytes
);
1184 return tracer_load_integer_value(&side_integer
->type
, &value
,
1185 side_integer
->offset_bits
, NULL
);
1189 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1191 enum side_type_gather_access_mode access_mode
=
1192 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1193 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1194 const char *ptr
= (const char *) _ptr
;
1195 union side_bool_value value
;
1197 switch (bool_size_bytes
) {
1206 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1207 memcpy(&value
, ptr
, bool_size_bytes
);
1208 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1209 type_gather
->u
.side_bool
.offset_bits
);
1210 return tracer_gather_size(access_mode
, bool_size_bytes
);
1214 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1216 enum side_type_gather_access_mode access_mode
=
1217 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1218 const char *ptr
= (const char *) _ptr
;
1221 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1222 memcpy(&value
, ptr
, 1);
1223 tracer_print_type_header(":", type_gather
->u
.side_byte
.type
.attr
,
1224 type_gather
->u
.side_byte
.type
.nr_attr
);
1225 printf("0x%" PRIx8
, value
);
1226 return tracer_gather_size(access_mode
, 1);
1230 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1231 enum tracer_display_base default_base
)
1233 enum side_type_gather_access_mode access_mode
=
1234 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1235 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1236 const char *ptr
= (const char *) _ptr
;
1237 union side_integer_value value
;
1239 switch (integer_size_bytes
) {
1248 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1249 memcpy(&value
, ptr
, integer_size_bytes
);
1250 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1251 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1252 return tracer_gather_size(access_mode
, integer_size_bytes
);
1256 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1258 enum side_type_gather_access_mode access_mode
=
1259 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1260 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1261 const char *ptr
= (const char *) _ptr
;
1262 union side_float_value value
;
1264 switch (float_size_bytes
) {
1273 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1274 memcpy(&value
, ptr
, float_size_bytes
);
1275 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1276 return tracer_gather_size(access_mode
, float_size_bytes
);
1280 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1282 enum side_type_gather_access_mode access_mode
=
1283 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1284 const char *ptr
= (const char *) _ptr
;
1287 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1288 tracer_print_type_header(":", type_gather
->u
.side_string
.type
.attr
,
1289 type_gather
->u
.side_string
.type
.nr_attr
);
1291 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1292 type_gather
->u
.side_string
.type
.byte_order
, &string_len
);
1295 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1297 return tracer_gather_size(access_mode
, string_len
);
1301 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1306 switch (type_desc
->type
) {
1307 /* Gather basic types */
1308 case SIDE_TYPE_GATHER_BOOL
:
1309 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1311 case SIDE_TYPE_GATHER_INTEGER
:
1312 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1313 TRACER_DISPLAY_BASE_10
);
1315 case SIDE_TYPE_GATHER_BYTE
:
1316 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1318 case SIDE_TYPE_GATHER_POINTER
:
1319 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1320 TRACER_DISPLAY_BASE_16
);
1322 case SIDE_TYPE_GATHER_FLOAT
:
1323 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1325 case SIDE_TYPE_GATHER_STRING
:
1326 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1329 /* Gather enum types */
1330 case SIDE_TYPE_GATHER_ENUM
:
1331 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1334 /* Gather compound types */
1335 case SIDE_TYPE_GATHER_STRUCT
:
1336 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1338 case SIDE_TYPE_GATHER_ARRAY
:
1339 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1341 case SIDE_TYPE_GATHER_VLA
:
1342 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1345 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1353 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1355 const struct side_enum_mappings
*mappings
= type_gather
->u
.side_enum
.mappings
;
1356 const struct side_type
*enum_elem_type
= type_gather
->u
.side_enum
.elem_type
;
1357 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1358 enum side_type_gather_access_mode access_mode
=
1359 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1360 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1361 const char *ptr
= (const char *) _ptr
;
1362 union side_integer_value value
;
1363 union int64_value v64
;
1365 switch (integer_size_bytes
) {
1374 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1375 memcpy(&value
, ptr
, integer_size_bytes
);
1376 v64
= tracer_load_gather_integer_value(side_integer
, &value
);
1377 print_attributes("attr", ":", mappings
->attr
, mappings
->nr_attr
);
1378 printf("%s", mappings
->nr_attr
? ", " : "");
1379 tracer_print_gather_type(enum_elem_type
, ptr
);
1380 print_enum_labels(mappings
, v64
);
1381 return tracer_gather_size(access_mode
, integer_size_bytes
);
1385 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1387 printf("%s: ", field
->field_name
);
1388 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1392 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1394 enum side_type_gather_access_mode access_mode
=
1395 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1396 const char *ptr
= (const char *) _ptr
;
1399 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1400 print_attributes("attr", ":", type_gather
->u
.side_struct
.type
->attr
, type_gather
->u
.side_struct
.type
->nr_attr
);
1401 printf("%s", type_gather
->u
.side_struct
.type
->nr_attr
? ", " : "");
1402 printf("fields: { ");
1403 for (i
= 0; i
< type_gather
->u
.side_struct
.type
->nr_fields
; i
++) {
1404 printf("%s", i
? ", " : "");
1405 tracer_print_gather_field(&type_gather
->u
.side_struct
.type
->fields
[i
], ptr
);
1408 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1412 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1414 enum side_type_gather_access_mode access_mode
=
1415 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1416 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1419 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1421 print_attributes("attr", ":", type_gather
->u
.side_array
.type
.attr
, type_gather
->u
.side_array
.type
.nr_attr
);
1422 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1423 printf("elements: ");
1425 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1426 switch (type_gather
->u
.side_array
.type
.elem_type
->type
) {
1427 case SIDE_TYPE_GATHER_VLA
:
1428 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1433 printf("%s", i
? ", " : "");
1434 ptr
+= tracer_print_gather_type(type_gather
->u
.side_array
.type
.elem_type
, ptr
);
1437 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1441 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1442 const void *_length_ptr
)
1444 enum side_type_gather_access_mode access_mode
=
1445 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1446 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1447 const char *length_ptr
= (const char *) _length_ptr
;
1448 union int64_value v64
;
1452 switch (type_gather
->u
.side_vla
.length_type
->type
) {
1453 case SIDE_TYPE_GATHER_INTEGER
:
1456 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1459 v64
= tracer_load_gather_integer_value(&type_gather
->u
.side_vla
.length_type
->u
.side_gather
.u
.side_integer
,
1461 length
= (uint32_t) v64
.u
;
1462 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1464 print_attributes("attr", ":", type_gather
->u
.side_vla
.type
.attr
, type_gather
->u
.side_vla
.type
.nr_attr
);
1465 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1466 printf("elements: ");
1468 for (i
= 0; i
< length
; i
++) {
1469 switch (type_gather
->u
.side_vla
.type
.elem_type
->type
) {
1470 case SIDE_TYPE_GATHER_VLA
:
1471 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1476 printf("%s", i
? ", " : "");
1477 ptr
+= tracer_print_gather_type(type_gather
->u
.side_vla
.type
.elem_type
, ptr
);
1480 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1483 struct tracer_visitor_priv
{
1484 const struct side_type
*elem_type
;
1489 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1490 const struct side_arg
*elem
)
1492 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1494 printf("%s", tracer_priv
->i
++ ? ", " : "");
1495 tracer_print_type(tracer_priv
->elem_type
, elem
);
1496 return SIDE_VISITOR_STATUS_OK
;
1500 void tracer_print_vla_visitor(const struct side_type
*type_desc
, void *app_ctx
)
1502 enum side_visitor_status status
;
1503 struct tracer_visitor_priv tracer_priv
= {
1504 .elem_type
= type_desc
->u
.side_vla_visitor
.elem_type
,
1507 const struct side_tracer_visitor_ctx tracer_ctx
= {
1508 .write_elem
= tracer_write_elem_cb
,
1509 .priv
= &tracer_priv
,
1512 print_attributes("attr", ":", type_desc
->u
.side_vla_visitor
.attr
, type_desc
->u
.side_vla_visitor
.nr_attr
);
1513 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1514 printf("elements: ");
1516 status
= type_desc
->u
.side_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1518 case SIDE_VISITOR_STATUS_OK
:
1520 case SIDE_VISITOR_STATUS_ERROR
:
1521 fprintf(stderr
, "ERROR: Visitor error\n");
1528 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1530 const struct side_arg_dynamic_field
*fields
= dynamic_struct
->fields
;
1531 uint32_t i
, len
= dynamic_struct
->len
;
1533 print_attributes("attr", "::", dynamic_struct
->attr
, dynamic_struct
->nr_attr
);
1534 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1535 printf("fields:: ");
1537 for (i
= 0; i
< len
; i
++) {
1538 printf("%s", i
? ", " : "");
1539 printf("%s:: ", fields
[i
].field_name
);
1540 tracer_print_dynamic(&fields
[i
].elem
);
1545 struct tracer_dynamic_struct_visitor_priv
{
1550 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1551 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1552 const struct side_arg_dynamic_field
*dynamic_field
)
1554 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1555 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1557 printf("%s", tracer_priv
->i
++ ? ", " : "");
1558 printf("%s:: ", dynamic_field
->field_name
);
1559 tracer_print_dynamic(&dynamic_field
->elem
);
1560 return SIDE_VISITOR_STATUS_OK
;
1564 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1566 enum side_visitor_status status
;
1567 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1570 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1571 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1572 .priv
= &tracer_priv
,
1574 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.app_ctx
;
1576 print_attributes("attr", "::", item
->u
.side_dynamic
.side_dynamic_struct_visitor
.attr
, item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
);
1577 printf("%s", item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
? ", " : "");
1578 printf("fields:: ");
1580 status
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.visitor(&tracer_ctx
, app_ctx
);
1582 case SIDE_VISITOR_STATUS_OK
:
1584 case SIDE_VISITOR_STATUS_ERROR
:
1585 fprintf(stderr
, "ERROR: Visitor error\n");
1592 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1594 const struct side_arg
*sav
= vla
->sav
;
1595 uint32_t i
, side_sav_len
= vla
->len
;
1597 print_attributes("attr", "::", vla
->attr
, vla
->nr_attr
);
1598 printf("%s", vla
->nr_attr
? ", " : "");
1599 printf("elements:: ");
1601 for (i
= 0; i
< side_sav_len
; i
++) {
1602 printf("%s", i
? ", " : "");
1603 tracer_print_dynamic(&sav
[i
]);
1608 struct tracer_dynamic_vla_visitor_priv
{
1613 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1614 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1615 const struct side_arg
*elem
)
1617 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1618 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1620 printf("%s", tracer_priv
->i
++ ? ", " : "");
1621 tracer_print_dynamic(elem
);
1622 return SIDE_VISITOR_STATUS_OK
;
1626 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1628 enum side_visitor_status status
;
1629 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1632 const struct side_tracer_visitor_ctx tracer_ctx
= {
1633 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1634 .priv
= &tracer_priv
,
1636 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.app_ctx
;
1638 print_attributes("attr", "::", item
->u
.side_dynamic
.side_dynamic_vla_visitor
.attr
, item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
);
1639 printf("%s", item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
? ", " : "");
1640 printf("elements:: ");
1642 status
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1644 case SIDE_VISITOR_STATUS_OK
:
1646 case SIDE_VISITOR_STATUS_ERROR
:
1647 fprintf(stderr
, "ERROR: Visitor error\n");
1654 void tracer_print_dynamic(const struct side_arg
*item
)
1657 switch (item
->type
) {
1658 /* Dynamic basic types */
1659 case SIDE_TYPE_DYNAMIC_NULL
:
1660 tracer_print_type_header("::", item
->u
.side_dynamic
.side_null
.attr
, item
->u
.side_dynamic
.side_null
.nr_attr
);
1661 printf("<NULL TYPE>");
1663 case SIDE_TYPE_DYNAMIC_BOOL
:
1664 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1666 case SIDE_TYPE_DYNAMIC_INTEGER
:
1667 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1668 TRACER_DISPLAY_BASE_10
);
1670 case SIDE_TYPE_DYNAMIC_BYTE
:
1671 tracer_print_type_header("::", item
->u
.side_dynamic
.side_byte
.type
.attr
, item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1672 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1674 case SIDE_TYPE_DYNAMIC_POINTER
:
1675 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1676 TRACER_DISPLAY_BASE_16
);
1678 case SIDE_TYPE_DYNAMIC_FLOAT
:
1679 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1680 &item
->u
.side_dynamic
.side_float
.value
);
1682 case SIDE_TYPE_DYNAMIC_STRING
:
1683 tracer_print_type_header("::", item
->u
.side_dynamic
.side_string
.type
.attr
, item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1684 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1685 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
1686 item
->u
.side_dynamic
.side_string
.type
.byte_order
, NULL
);
1689 /* Dynamic compound types */
1690 case SIDE_TYPE_DYNAMIC_STRUCT
:
1691 tracer_print_dynamic_struct(item
->u
.side_dynamic
.side_dynamic_struct
);
1693 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1694 tracer_print_dynamic_struct_visitor(item
);
1696 case SIDE_TYPE_DYNAMIC_VLA
:
1697 tracer_print_dynamic_vla(item
->u
.side_dynamic
.side_dynamic_vla
);
1699 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1700 tracer_print_dynamic_vla_visitor(item
);
1703 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1710 void tracer_print_static_fields(const struct side_event_description
*desc
,
1711 const struct side_arg_vec
*side_arg_vec
,
1714 const struct side_arg
*sav
= side_arg_vec
->sav
;
1715 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1717 printf("provider: %s, event: %s", desc
->provider_name
, desc
->event_name
);
1718 if (desc
->nr_fields
!= side_sav_len
) {
1719 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
1722 print_attributes(", attr", ":", desc
->attr
, desc
->nr_attr
);
1723 printf("%s", side_sav_len
? ", fields: [ " : "");
1724 for (i
= 0; i
< side_sav_len
; i
++) {
1725 printf("%s", i
? ", " : "");
1726 tracer_print_field(&desc
->fields
[i
], &sav
[i
]);
1735 void tracer_call(const struct side_event_description
*desc
,
1736 const struct side_arg_vec
*side_arg_vec
,
1737 void *priv
__attribute__((unused
)))
1739 uint32_t nr_fields
= 0;
1741 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1746 void tracer_call_variadic(const struct side_event_description
*desc
,
1747 const struct side_arg_vec
*side_arg_vec
,
1748 const struct side_arg_dynamic_struct
*var_struct
,
1749 void *priv
__attribute__((unused
)))
1751 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
1753 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1755 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
1756 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
1759 print_attributes(", attr ", "::", var_struct
->attr
, var_struct
->nr_attr
);
1760 printf("%s", var_struct_len
? ", fields:: [ " : "");
1761 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
1762 printf("%s", i
? ", " : "");
1763 printf("%s:: ", var_struct
->fields
[i
].field_name
);
1764 tracer_print_dynamic(&var_struct
->fields
[i
].elem
);
1772 void tracer_event_notification(enum side_tracer_notification notif
,
1773 struct side_event_description
**events
, uint32_t nr_events
,
1774 void *priv
__attribute__((unused
)))
1779 printf("----------------------------------------------------------\n");
1780 printf("Tracer notified of events %s\n",
1781 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
1782 for (i
= 0; i
< nr_events
; i
++) {
1783 struct side_event_description
*event
= events
[i
];
1785 /* Skip NULL pointers */
1788 printf("provider: %s, event: %s\n",
1789 event
->provider_name
, event
->event_name
);
1790 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
1791 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1792 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
);
1796 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
);
1801 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1802 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
);
1806 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
);
1812 printf("----------------------------------------------------------\n");
1815 static __attribute__((constructor
))
1816 void tracer_init(void);
1818 void tracer_init(void)
1820 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
1825 static __attribute__((destructor
))
1826 void tracer_exit(void);
1828 void tracer_exit(void)
1830 side_tracer_event_notification_unregister(tracer_handle
);