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(side_ptr_get(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
!= side_ptr_get(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(side_ptr_get(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
!= side_ptr_get(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(side_ptr_get(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
= &side_ptr_get(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(side_ptr_get(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
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
475 const struct side_type
*elem_type
= side_ptr_get(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", ":", side_ptr_get(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
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
521 const struct side_type
*enum_elem_type
= side_ptr_get(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
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
541 array_item
= side_ptr_get(item
->u
.side_static
.side_array
)->sav
;
542 nr_items
= type_desc
->u
.side_array
.length
;
545 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
546 array_item
= side_ptr_get(item
->u
.side_static
.side_vla
)->sav
;
547 nr_items
= side_ptr_get(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_ptr_get(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_ptr_get(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(side_ptr_get(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
, side_ptr_get(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
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
696 base
= get_attr_display_base(side_ptr_get(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
, side_ptr_get(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(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
908 type_desc
->u
.side_null
.nr_attr
);
909 printf("<NULL TYPE>");
913 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
924 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
925 TRACER_DISPLAY_BASE_10
);
929 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
930 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
933 case SIDE_TYPE_POINTER
:
934 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
935 TRACER_DISPLAY_BASE_16
);
938 case SIDE_TYPE_FLOAT_BINARY16
:
939 case SIDE_TYPE_FLOAT_BINARY32
:
940 case SIDE_TYPE_FLOAT_BINARY64
:
941 case SIDE_TYPE_FLOAT_BINARY128
:
942 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
945 case SIDE_TYPE_STRING_UTF8
:
946 case SIDE_TYPE_STRING_UTF16
:
947 case SIDE_TYPE_STRING_UTF32
:
948 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
949 tracer_print_string((const void *)(uintptr_t) item
->u
.side_static
.string_value
,
950 type_desc
->u
.side_string
.unit_size
, type_desc
->u
.side_string
.byte_order
, NULL
);
953 /* Stack-copy compound types */
954 case SIDE_TYPE_STRUCT
:
955 tracer_print_struct(type_desc
, side_ptr_get(item
->u
.side_static
.side_struct
));
957 case SIDE_TYPE_VARIANT
:
958 tracer_print_variant(type_desc
, side_ptr_get(item
->u
.side_static
.side_variant
));
960 case SIDE_TYPE_ARRAY
:
961 tracer_print_array(type_desc
, side_ptr_get(item
->u
.side_static
.side_array
));
964 tracer_print_vla(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla
));
966 case SIDE_TYPE_VLA_VISITOR
:
967 tracer_print_vla_visitor(type_desc
, item
->u
.side_static
.side_vla_app_visitor_ctx
);
970 /* Stack-copy enumeration types */
972 tracer_print_enum(type_desc
, item
);
974 case SIDE_TYPE_ENUM_BITMAP
:
975 tracer_print_enum_bitmap(type_desc
, item
);
978 /* Gather basic types */
979 case SIDE_TYPE_GATHER_BOOL
:
980 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_bool_gather_ptr
);
982 case SIDE_TYPE_GATHER_INTEGER
:
983 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
984 TRACER_DISPLAY_BASE_10
);
986 case SIDE_TYPE_GATHER_BYTE
:
987 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_byte_gather_ptr
);
989 case SIDE_TYPE_GATHER_POINTER
:
990 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
991 TRACER_DISPLAY_BASE_16
);
993 case SIDE_TYPE_GATHER_FLOAT
:
994 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_float_gather_ptr
);
996 case SIDE_TYPE_GATHER_STRING
:
997 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_string_gather_ptr
);
1000 /* Gather compound type */
1001 case SIDE_TYPE_GATHER_STRUCT
:
1002 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_struct_gather_ptr
);
1004 case SIDE_TYPE_GATHER_ARRAY
:
1005 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_array_gather_ptr
);
1007 case SIDE_TYPE_GATHER_VLA
:
1008 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_vla_gather
.ptr
,
1009 item
->u
.side_static
.side_vla_gather
.length_ptr
);
1012 /* Gather enumeration types */
1013 case SIDE_TYPE_GATHER_ENUM
:
1014 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
);
1017 /* Dynamic basic types */
1018 case SIDE_TYPE_DYNAMIC_NULL
:
1019 case SIDE_TYPE_DYNAMIC_BOOL
:
1020 case SIDE_TYPE_DYNAMIC_INTEGER
:
1021 case SIDE_TYPE_DYNAMIC_BYTE
:
1022 case SIDE_TYPE_DYNAMIC_POINTER
:
1023 case SIDE_TYPE_DYNAMIC_FLOAT
:
1024 case SIDE_TYPE_DYNAMIC_STRING
:
1026 /* Dynamic compound types */
1027 case SIDE_TYPE_DYNAMIC_STRUCT
:
1028 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1029 case SIDE_TYPE_DYNAMIC_VLA
:
1030 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1031 tracer_print_dynamic(item
);
1034 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1041 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1043 printf("%s: ", side_ptr_get(item_desc
->field_name
));
1044 tracer_print_type(&item_desc
->side_type
, item
);
1048 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1050 const struct side_arg
*sav
= side_arg_vec
->sav
;
1051 const struct side_type_struct
*side_struct
= side_ptr_get(type_desc
->u
.side_struct
);
1052 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1054 if (side_struct
->nr_fields
!= side_sav_len
) {
1055 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1058 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1059 printf("%s", side_struct
->nr_attr
? ", " : "");
1060 printf("fields: { ");
1061 for (i
= 0; i
< side_sav_len
; i
++) {
1062 printf("%s", i
? ", " : "");
1063 tracer_print_field(&side_ptr_get(side_struct
->fields
)[i
], &sav
[i
]);
1069 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1071 const struct side_type_variant
*side_type_variant
= side_ptr_get(type_desc
->u
.side_variant
);
1072 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1073 union int64_value v64
;
1076 if (selector_type
->type
!= side_arg_variant
->selector
.type
) {
1077 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1080 switch (selector_type
->type
) {
1091 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1094 v64
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1095 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1096 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1097 const struct side_variant_option
*option
= &side_ptr_get(side_type_variant
->options
)[i
];
1099 if (v64
.s
>= option
->range_begin
&& v64
.s
<= option
->range_end
) {
1100 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
);
1104 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v64
.s
);
1109 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1111 const struct side_arg
*sav
= side_arg_vec
->sav
;
1112 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1114 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1115 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1118 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_array
.attr
), type_desc
->u
.side_array
.nr_attr
);
1119 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1120 printf("elements: ");
1122 for (i
= 0; i
< side_sav_len
; i
++) {
1123 printf("%s", i
? ", " : "");
1124 tracer_print_type(side_ptr_get(type_desc
->u
.side_array
.elem_type
), &sav
[i
]);
1130 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1132 const struct side_arg
*sav
= side_arg_vec
->sav
;
1133 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1135 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla
.attr
), type_desc
->u
.side_vla
.nr_attr
);
1136 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1137 printf("elements: ");
1139 for (i
= 0; i
< side_sav_len
; i
++) {
1140 printf("%s", i
? ", " : "");
1141 tracer_print_type(side_ptr_get(type_desc
->u
.side_vla
.elem_type
), &sav
[i
]);
1147 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1149 switch (access_mode
) {
1150 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1152 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1153 /* Dereference pointer */
1154 memcpy(&ptr
, ptr
, sizeof(const char *));
1162 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1164 switch (access_mode
) {
1165 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1167 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1168 return sizeof(void *);
1175 union int64_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1178 enum side_type_gather_access_mode access_mode
=
1179 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1180 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1181 const char *ptr
= (const char *) _ptr
;
1182 union side_integer_value value
;
1184 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1185 memcpy(&value
, ptr
, integer_size_bytes
);
1186 return tracer_load_integer_value(&side_integer
->type
, &value
,
1187 side_integer
->offset_bits
, NULL
);
1191 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1193 enum side_type_gather_access_mode access_mode
=
1194 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1195 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1196 const char *ptr
= (const char *) _ptr
;
1197 union side_bool_value value
;
1199 switch (bool_size_bytes
) {
1208 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1209 memcpy(&value
, ptr
, bool_size_bytes
);
1210 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1211 type_gather
->u
.side_bool
.offset_bits
);
1212 return tracer_gather_size(access_mode
, bool_size_bytes
);
1216 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1218 enum side_type_gather_access_mode access_mode
=
1219 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1220 const char *ptr
= (const char *) _ptr
;
1223 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1224 memcpy(&value
, ptr
, 1);
1225 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_byte
.type
.attr
),
1226 type_gather
->u
.side_byte
.type
.nr_attr
);
1227 printf("0x%" PRIx8
, value
);
1228 return tracer_gather_size(access_mode
, 1);
1232 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1233 enum tracer_display_base default_base
)
1235 enum side_type_gather_access_mode access_mode
=
1236 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1237 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1238 const char *ptr
= (const char *) _ptr
;
1239 union side_integer_value value
;
1241 switch (integer_size_bytes
) {
1250 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1251 memcpy(&value
, ptr
, integer_size_bytes
);
1252 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1253 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1254 return tracer_gather_size(access_mode
, integer_size_bytes
);
1258 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1260 enum side_type_gather_access_mode access_mode
=
1261 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1262 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1263 const char *ptr
= (const char *) _ptr
;
1264 union side_float_value value
;
1266 switch (float_size_bytes
) {
1275 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1276 memcpy(&value
, ptr
, float_size_bytes
);
1277 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1278 return tracer_gather_size(access_mode
, float_size_bytes
);
1282 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1284 enum side_type_gather_access_mode access_mode
=
1285 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1286 const char *ptr
= (const char *) _ptr
;
1289 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1290 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_string
.type
.attr
),
1291 type_gather
->u
.side_string
.type
.nr_attr
);
1293 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1294 type_gather
->u
.side_string
.type
.byte_order
, &string_len
);
1297 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1299 return tracer_gather_size(access_mode
, string_len
);
1303 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1308 switch (type_desc
->type
) {
1309 /* Gather basic types */
1310 case SIDE_TYPE_GATHER_BOOL
:
1311 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1313 case SIDE_TYPE_GATHER_INTEGER
:
1314 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1315 TRACER_DISPLAY_BASE_10
);
1317 case SIDE_TYPE_GATHER_BYTE
:
1318 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1320 case SIDE_TYPE_GATHER_POINTER
:
1321 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1322 TRACER_DISPLAY_BASE_16
);
1324 case SIDE_TYPE_GATHER_FLOAT
:
1325 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1327 case SIDE_TYPE_GATHER_STRING
:
1328 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1331 /* Gather enum types */
1332 case SIDE_TYPE_GATHER_ENUM
:
1333 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1336 /* Gather compound types */
1337 case SIDE_TYPE_GATHER_STRUCT
:
1338 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1340 case SIDE_TYPE_GATHER_ARRAY
:
1341 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1343 case SIDE_TYPE_GATHER_VLA
:
1344 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1347 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1355 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1357 const struct side_enum_mappings
*mappings
= side_ptr_get(type_gather
->u
.side_enum
.mappings
);
1358 const struct side_type
*enum_elem_type
= side_ptr_get(type_gather
->u
.side_enum
.elem_type
);
1359 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1360 enum side_type_gather_access_mode access_mode
=
1361 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1362 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1363 const char *ptr
= (const char *) _ptr
;
1364 union side_integer_value value
;
1365 union int64_value v64
;
1367 switch (integer_size_bytes
) {
1376 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1377 memcpy(&value
, ptr
, integer_size_bytes
);
1378 v64
= tracer_load_gather_integer_value(side_integer
, &value
);
1379 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1380 printf("%s", mappings
->nr_attr
? ", " : "");
1381 tracer_print_gather_type(enum_elem_type
, ptr
);
1382 print_enum_labels(mappings
, v64
);
1383 return tracer_gather_size(access_mode
, integer_size_bytes
);
1387 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1389 printf("%s: ", side_ptr_get(field
->field_name
));
1390 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1394 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1396 enum side_type_gather_access_mode access_mode
=
1397 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1398 const struct side_type_struct
*side_struct
= side_ptr_get(type_gather
->u
.side_struct
.type
);
1399 const char *ptr
= (const char *) _ptr
;
1402 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1403 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1404 printf("%s", side_struct
->nr_attr
? ", " : "");
1405 printf("fields: { ");
1406 for (i
= 0; i
< side_struct
->nr_fields
; i
++) {
1407 printf("%s", i
? ", " : "");
1408 tracer_print_gather_field(&side_ptr_get(side_struct
->fields
)[i
], ptr
);
1411 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1415 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1417 enum side_type_gather_access_mode access_mode
=
1418 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1419 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1422 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1424 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_array
.type
.attr
), type_gather
->u
.side_array
.type
.nr_attr
);
1425 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1426 printf("elements: ");
1428 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1429 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_array
.type
.elem_type
);
1431 switch (elem_type
->type
) {
1432 case SIDE_TYPE_GATHER_VLA
:
1433 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1438 printf("%s", i
? ", " : "");
1439 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1442 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1446 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1447 const void *_length_ptr
)
1449 enum side_type_gather_access_mode access_mode
=
1450 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1451 const struct side_type
*length_type
= side_ptr_get(type_gather
->u
.side_vla
.length_type
);
1452 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1453 const char *length_ptr
= (const char *) _length_ptr
;
1454 union int64_value v64
;
1458 switch (length_type
->type
) {
1459 case SIDE_TYPE_GATHER_INTEGER
:
1462 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1465 v64
= tracer_load_gather_integer_value(&length_type
->u
.side_gather
.u
.side_integer
,
1467 length
= (uint32_t) v64
.u
;
1468 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1470 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_vla
.type
.attr
), type_gather
->u
.side_vla
.type
.nr_attr
);
1471 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1472 printf("elements: ");
1474 for (i
= 0; i
< length
; i
++) {
1475 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_vla
.type
.elem_type
);
1477 switch (elem_type
->type
) {
1478 case SIDE_TYPE_GATHER_VLA
:
1479 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1484 printf("%s", i
? ", " : "");
1485 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1488 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1491 struct tracer_visitor_priv
{
1492 const struct side_type
*elem_type
;
1497 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1498 const struct side_arg
*elem
)
1500 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1502 printf("%s", tracer_priv
->i
++ ? ", " : "");
1503 tracer_print_type(tracer_priv
->elem_type
, elem
);
1504 return SIDE_VISITOR_STATUS_OK
;
1508 void tracer_print_vla_visitor(const struct side_type
*type_desc
, void *app_ctx
)
1510 enum side_visitor_status status
;
1511 struct tracer_visitor_priv tracer_priv
= {
1512 .elem_type
= side_ptr_get(type_desc
->u
.side_vla_visitor
.elem_type
),
1515 const struct side_tracer_visitor_ctx tracer_ctx
= {
1516 .write_elem
= tracer_write_elem_cb
,
1517 .priv
= &tracer_priv
,
1520 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla_visitor
.attr
), type_desc
->u
.side_vla_visitor
.nr_attr
);
1521 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1522 printf("elements: ");
1524 status
= type_desc
->u
.side_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1526 case SIDE_VISITOR_STATUS_OK
:
1528 case SIDE_VISITOR_STATUS_ERROR
:
1529 fprintf(stderr
, "ERROR: Visitor error\n");
1536 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1538 const struct side_arg_dynamic_field
*fields
= dynamic_struct
->fields
;
1539 uint32_t i
, len
= dynamic_struct
->len
;
1541 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1542 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1543 printf("fields:: ");
1545 for (i
= 0; i
< len
; i
++) {
1546 printf("%s", i
? ", " : "");
1547 printf("%s:: ", fields
[i
].field_name
);
1548 tracer_print_dynamic(&fields
[i
].elem
);
1553 struct tracer_dynamic_struct_visitor_priv
{
1558 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1559 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1560 const struct side_arg_dynamic_field
*dynamic_field
)
1562 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1563 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1565 printf("%s", tracer_priv
->i
++ ? ", " : "");
1566 printf("%s:: ", dynamic_field
->field_name
);
1567 tracer_print_dynamic(&dynamic_field
->elem
);
1568 return SIDE_VISITOR_STATUS_OK
;
1572 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1574 enum side_visitor_status status
;
1575 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1578 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1579 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1580 .priv
= &tracer_priv
,
1582 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.app_ctx
;
1584 print_attributes("attr", "::", side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
.attr
), item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
);
1585 printf("%s", item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
? ", " : "");
1586 printf("fields:: ");
1588 status
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.visitor(&tracer_ctx
, app_ctx
);
1590 case SIDE_VISITOR_STATUS_OK
:
1592 case SIDE_VISITOR_STATUS_ERROR
:
1593 fprintf(stderr
, "ERROR: Visitor error\n");
1600 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1602 const struct side_arg
*sav
= vla
->sav
;
1603 uint32_t i
, side_sav_len
= vla
->len
;
1605 print_attributes("attr", "::", side_ptr_get(vla
->attr
), vla
->nr_attr
);
1606 printf("%s", vla
->nr_attr
? ", " : "");
1607 printf("elements:: ");
1609 for (i
= 0; i
< side_sav_len
; i
++) {
1610 printf("%s", i
? ", " : "");
1611 tracer_print_dynamic(&sav
[i
]);
1616 struct tracer_dynamic_vla_visitor_priv
{
1621 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1622 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1623 const struct side_arg
*elem
)
1625 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1626 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1628 printf("%s", tracer_priv
->i
++ ? ", " : "");
1629 tracer_print_dynamic(elem
);
1630 return SIDE_VISITOR_STATUS_OK
;
1634 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1636 enum side_visitor_status status
;
1637 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1640 const struct side_tracer_visitor_ctx tracer_ctx
= {
1641 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1642 .priv
= &tracer_priv
,
1644 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.app_ctx
;
1646 print_attributes("attr", "::", side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
.attr
), item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
);
1647 printf("%s", item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
? ", " : "");
1648 printf("elements:: ");
1650 status
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1652 case SIDE_VISITOR_STATUS_OK
:
1654 case SIDE_VISITOR_STATUS_ERROR
:
1655 fprintf(stderr
, "ERROR: Visitor error\n");
1662 void tracer_print_dynamic(const struct side_arg
*item
)
1665 switch (item
->type
) {
1666 /* Dynamic basic types */
1667 case SIDE_TYPE_DYNAMIC_NULL
:
1668 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1669 item
->u
.side_dynamic
.side_null
.nr_attr
);
1670 printf("<NULL TYPE>");
1672 case SIDE_TYPE_DYNAMIC_BOOL
:
1673 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1675 case SIDE_TYPE_DYNAMIC_INTEGER
:
1676 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1677 TRACER_DISPLAY_BASE_10
);
1679 case SIDE_TYPE_DYNAMIC_BYTE
:
1680 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1681 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1683 case SIDE_TYPE_DYNAMIC_POINTER
:
1684 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1685 TRACER_DISPLAY_BASE_16
);
1687 case SIDE_TYPE_DYNAMIC_FLOAT
:
1688 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1689 &item
->u
.side_dynamic
.side_float
.value
);
1691 case SIDE_TYPE_DYNAMIC_STRING
:
1692 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1693 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1694 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
1695 item
->u
.side_dynamic
.side_string
.type
.byte_order
, NULL
);
1698 /* Dynamic compound types */
1699 case SIDE_TYPE_DYNAMIC_STRUCT
:
1700 tracer_print_dynamic_struct(item
->u
.side_dynamic
.side_dynamic_struct
);
1702 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1703 tracer_print_dynamic_struct_visitor(item
);
1705 case SIDE_TYPE_DYNAMIC_VLA
:
1706 tracer_print_dynamic_vla(item
->u
.side_dynamic
.side_dynamic_vla
);
1708 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1709 tracer_print_dynamic_vla_visitor(item
);
1712 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1719 void tracer_print_static_fields(const struct side_event_description
*desc
,
1720 const struct side_arg_vec
*side_arg_vec
,
1723 const struct side_arg
*sav
= side_arg_vec
->sav
;
1724 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1726 printf("provider: %s, event: %s", desc
->provider_name
, desc
->event_name
);
1727 if (desc
->nr_fields
!= side_sav_len
) {
1728 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
1731 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
1732 printf("%s", side_sav_len
? ", fields: [ " : "");
1733 for (i
= 0; i
< side_sav_len
; i
++) {
1734 printf("%s", i
? ", " : "");
1735 tracer_print_field(&desc
->fields
[i
], &sav
[i
]);
1744 void tracer_call(const struct side_event_description
*desc
,
1745 const struct side_arg_vec
*side_arg_vec
,
1746 void *priv
__attribute__((unused
)))
1748 uint32_t nr_fields
= 0;
1750 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1755 void tracer_call_variadic(const struct side_event_description
*desc
,
1756 const struct side_arg_vec
*side_arg_vec
,
1757 const struct side_arg_dynamic_struct
*var_struct
,
1758 void *priv
__attribute__((unused
)))
1760 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
1762 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1764 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
1765 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
1768 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
1769 printf("%s", var_struct_len
? ", fields:: [ " : "");
1770 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
1771 printf("%s", i
? ", " : "");
1772 printf("%s:: ", var_struct
->fields
[i
].field_name
);
1773 tracer_print_dynamic(&var_struct
->fields
[i
].elem
);
1781 void tracer_event_notification(enum side_tracer_notification notif
,
1782 struct side_event_description
**events
, uint32_t nr_events
,
1783 void *priv
__attribute__((unused
)))
1788 printf("----------------------------------------------------------\n");
1789 printf("Tracer notified of events %s\n",
1790 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
1791 for (i
= 0; i
< nr_events
; i
++) {
1792 struct side_event_description
*event
= events
[i
];
1794 /* Skip NULL pointers */
1797 printf("provider: %s, event: %s\n",
1798 event
->provider_name
, event
->event_name
);
1799 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
1800 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1801 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
);
1805 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
);
1810 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1811 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
);
1815 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
);
1821 printf("----------------------------------------------------------\n");
1824 static __attribute__((constructor
))
1825 void tracer_init(void);
1827 void tracer_init(void)
1829 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
1834 static __attribute__((destructor
))
1835 void tracer_exit(void);
1837 void tracer_exit(void)
1839 side_tracer_event_notification_unregister(tracer_handle
);