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_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
35 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
37 void tracer_print_vla_visitor(const struct side_type
*type_desc
, void *app_ctx
);
39 void tracer_print_dynamic(const struct side_arg
*dynamic_item
);
41 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
43 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
45 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
46 enum tracer_display_base default_base
);
48 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
50 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
52 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
54 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
56 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
58 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
59 const void *_length_ptr
);
61 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
);
64 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
65 size_t *strlen_with_null
,
68 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
;
69 const char *str
= p
, *fromcode
;
70 char *inbuf
= (char *) p
, *outbuf
, *buf
;
76 *strlen_with_null
= strlen(str
) + 1;
77 *output_str
= (char *) str
;
81 const uint16_t *p16
= p
;
84 case SIDE_TYPE_BYTE_ORDER_LE
:
86 fromcode
= "UTF-16LE";
89 case SIDE_TYPE_BYTE_ORDER_BE
:
91 fromcode
= "UTF-16BE";
95 fprintf(stderr
, "Unknown byte order\n");
101 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
102 * { ef, bf, bf } UTF-8 (3 bytes).
104 bufsize
= inbytesleft
/ 2 * 3 + 1;
109 const uint32_t *p32
= p
;
111 switch (byte_order
) {
112 case SIDE_TYPE_BYTE_ORDER_LE
:
114 fromcode
= "UTF-32LE";
117 case SIDE_TYPE_BYTE_ORDER_BE
:
119 fromcode
= "UTF-32BE";
123 fprintf(stderr
, "Unknown byte order\n");
129 * Each 4-byte UTF-32 character converts to at most a
130 * 4-byte UTF-8 character.
132 bufsize
= inbytesleft
+ 1;
136 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
140 cd
= iconv_open("UTF8", fromcode
);
141 if (cd
== (iconv_t
) -1) {
142 perror("iconv_open");
145 buf
= malloc(bufsize
);
149 outbuf
= (char *) buf
;
150 outbytesleft
= bufsize
;
151 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
152 if (ret
== (size_t) -1) {
157 fprintf(stderr
, "Buffer too small to convert string input\n");
161 if (iconv_close(cd
) == -1) {
162 perror("iconv_close");
165 if (strlen_with_null
)
166 *strlen_with_null
= outbuf
- buf
;
171 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
172 size_t *strlen_with_null
)
174 char *output_str
= NULL
;
176 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
177 printf("\"%s\"", output_str
);
183 int64_t get_attr_integer_value(const struct side_attr
*attr
)
187 switch (attr
->value
.type
) {
188 case SIDE_ATTR_TYPE_U8
:
189 val
= attr
->value
.u
.integer_value
.side_u8
;
191 case SIDE_ATTR_TYPE_U16
:
192 val
= attr
->value
.u
.integer_value
.side_u16
;
194 case SIDE_ATTR_TYPE_U32
:
195 val
= attr
->value
.u
.integer_value
.side_u32
;
197 case SIDE_ATTR_TYPE_U64
:
198 val
= attr
->value
.u
.integer_value
.side_u64
;
200 case SIDE_ATTR_TYPE_S8
:
201 val
= attr
->value
.u
.integer_value
.side_s8
;
203 case SIDE_ATTR_TYPE_S16
:
204 val
= attr
->value
.u
.integer_value
.side_s16
;
206 case SIDE_ATTR_TYPE_S32
:
207 val
= attr
->value
.u
.integer_value
.side_s32
;
209 case SIDE_ATTR_TYPE_S64
:
210 val
= attr
->value
.u
.integer_value
.side_s64
;
213 fprintf(stderr
, "Unexpected attribute type\n");
220 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
221 enum tracer_display_base default_base
)
225 for (i
= 0; i
< nr_attr
; i
++) {
226 const struct side_attr
*attr
= &_attr
[i
];
227 char *utf8_str
= NULL
;
230 tracer_convert_string_to_utf8(attr
->key
.p
, attr
->key
.unit_size
,
231 attr
->key
.byte_order
, NULL
, &utf8_str
);
232 cmp
= strcmp(utf8_str
, "std.integer.base");
233 if (utf8_str
!= attr
->key
.p
)
236 int64_t val
= get_attr_integer_value(attr
);
240 return TRACER_DISPLAY_BASE_2
;
242 return TRACER_DISPLAY_BASE_8
;
244 return TRACER_DISPLAY_BASE_10
;
246 return TRACER_DISPLAY_BASE_16
;
248 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
253 return default_base
; /* Default */
257 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
259 char *utf8_str
= NULL
;
261 tracer_convert_string_to_utf8(attr
->key
.p
, attr
->key
.unit_size
,
262 attr
->key
.byte_order
, NULL
, &utf8_str
);
263 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
264 if (utf8_str
!= attr
->key
.p
)
266 switch (attr
->value
.type
) {
267 case SIDE_ATTR_TYPE_BOOL
:
268 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
270 case SIDE_ATTR_TYPE_U8
:
271 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
273 case SIDE_ATTR_TYPE_U16
:
274 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
276 case SIDE_ATTR_TYPE_U32
:
277 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
279 case SIDE_ATTR_TYPE_U64
:
280 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
282 case SIDE_ATTR_TYPE_S8
:
283 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
285 case SIDE_ATTR_TYPE_S16
:
286 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
288 case SIDE_ATTR_TYPE_S32
:
289 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
291 case SIDE_ATTR_TYPE_S64
:
292 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
294 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
296 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
299 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
302 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
304 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
307 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
310 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
312 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
315 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
318 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
320 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
323 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
326 case SIDE_ATTR_TYPE_STRING_UTF8
:
327 tracer_print_string((const void *)(uintptr_t) attr
->value
.u
.string_value
,
328 1, SIDE_TYPE_BYTE_ORDER_HOST
, NULL
);
330 case SIDE_ATTR_TYPE_STRING_UTF16
:
331 tracer_print_string((const void *)(uintptr_t) attr
->value
.u
.string_value
,
332 2, SIDE_TYPE_BYTE_ORDER_HOST
, NULL
);
334 case SIDE_ATTR_TYPE_STRING_UTF32
:
335 tracer_print_string((const void *)(uintptr_t) attr
->value
.u
.string_value
,
336 4, SIDE_TYPE_BYTE_ORDER_HOST
, NULL
);
339 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
346 void print_attributes(const char *prefix_str
, const char *separator
,
347 const struct side_attr
*attr
, uint32_t nr_attr
)
353 printf("%s%s [ ", prefix_str
, separator
);
354 for (i
= 0; i
< nr_attr
; i
++) {
355 printf("%s", i
? ", " : "");
356 tracer_print_attr_type(separator
, &attr
[i
]);
362 union int64_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
363 const union side_integer_value
*value
,
364 uint16_t offset_bits
, uint16_t *_len_bits
)
366 union int64_value v64
;
370 if (!type_integer
->len_bits
)
371 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
373 len_bits
= type_integer
->len_bits
;
374 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
376 reverse_bo
= type_integer
->byte_order
!= SIDE_TYPE_BYTE_ORDER_HOST
;
377 switch (type_integer
->integer_size
) {
379 if (type_integer
->signedness
)
380 v64
.s
= value
->side_s8
;
382 v64
.u
= value
->side_u8
;
385 if (type_integer
->signedness
) {
388 side_s16
= value
->side_s16
;
390 side_s16
= side_bswap_16(side_s16
);
395 side_u16
= value
->side_u16
;
397 side_u16
= side_bswap_16(side_u16
);
402 if (type_integer
->signedness
) {
405 side_s32
= value
->side_s32
;
407 side_s32
= side_bswap_32(side_s32
);
412 side_u32
= value
->side_u32
;
414 side_u32
= side_bswap_32(side_u32
);
419 if (type_integer
->signedness
) {
422 side_s64
= value
->side_s64
;
424 side_s64
= side_bswap_64(side_s64
);
429 side_u64
= value
->side_u64
;
431 side_u64
= side_bswap_64(side_u64
);
438 v64
.u
>>= offset_bits
;
440 v64
.u
&= (1ULL << len_bits
) - 1;
441 if (type_integer
->signedness
) {
443 if (v64
.u
& (1ULL << (len_bits
- 1)))
444 v64
.u
|= ~((1ULL << len_bits
) - 1);
448 *_len_bits
= len_bits
;
453 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int64_value v64
)
455 uint32_t i
, print_count
= 0;
457 printf(", labels: [ ");
458 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
459 const struct side_enum_mapping
*mapping
= &mappings
->mappings
[i
];
461 if (mapping
->range_end
< mapping
->range_begin
) {
462 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
463 mapping
->range_begin
, mapping
->range_end
);
466 if (v64
.s
>= mapping
->range_begin
&& v64
.s
<= mapping
->range_end
) {
467 printf("%s", print_count
++ ? ", " : "");
468 tracer_print_string(mapping
->label
.p
, mapping
->label
.unit_size
, mapping
->label
.byte_order
, NULL
);
472 printf("<NO LABEL>");
477 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
479 const struct side_enum_mappings
*mappings
= type_desc
->u
.side_enum
.mappings
;
480 const struct side_type
*elem_type
= type_desc
->u
.side_enum
.elem_type
;
481 union int64_value v64
;
483 if (elem_type
->type
!= item
->type
) {
484 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
487 v64
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
488 &item
->u
.side_static
.integer_value
, 0, NULL
);
489 print_attributes("attr", ":", mappings
->attr
, mappings
->nr_attr
);
490 printf("%s", mappings
->nr_attr
? ", " : "");
491 tracer_print_type(elem_type
, item
);
492 print_enum_labels(mappings
, v64
);
496 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
500 switch (elem_type
->type
) {
513 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
515 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
522 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
523 const struct side_arg
*item
)
525 const struct side_enum_bitmap_mappings
*side_enum_mappings
= type_desc
->u
.side_enum_bitmap
.mappings
;
526 const struct side_type
*enum_elem_type
= type_desc
->u
.side_enum_bitmap
.elem_type
, *elem_type
;
527 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
528 const struct side_arg
*array_item
;
530 switch (enum_elem_type
->type
) {
531 case SIDE_TYPE_U8
: /* Fall-through */
532 case SIDE_TYPE_BYTE
: /* Fall-through */
533 case SIDE_TYPE_U16
: /* Fall-through */
534 case SIDE_TYPE_U32
: /* Fall-through */
535 case SIDE_TYPE_U64
: /* Fall-through */
536 case SIDE_TYPE_S8
: /* Fall-through */
537 case SIDE_TYPE_S16
: /* Fall-through */
538 case SIDE_TYPE_S32
: /* Fall-through */
540 elem_type
= enum_elem_type
;
544 case SIDE_TYPE_ARRAY
:
545 elem_type
= enum_elem_type
->u
.side_array
.elem_type
;
546 array_item
= item
->u
.side_static
.side_array
->sav
;
547 nr_items
= type_desc
->u
.side_array
.length
;
550 elem_type
= enum_elem_type
->u
.side_vla
.elem_type
;
551 array_item
= item
->u
.side_static
.side_vla
->sav
;
552 nr_items
= item
->u
.side_static
.side_vla
->len
;
555 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
558 stride_bit
= elem_type_to_stride(elem_type
);
560 print_attributes("attr", ":", side_enum_mappings
->attr
, side_enum_mappings
->nr_attr
);
561 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
562 printf("labels: [ ");
563 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
564 const struct side_enum_bitmap_mapping
*mapping
= &side_enum_mappings
->mappings
[i
];
568 if (mapping
->range_end
< mapping
->range_begin
) {
569 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
570 mapping
->range_begin
, mapping
->range_end
);
573 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
574 if (bit
> (nr_items
* stride_bit
) - 1)
576 if (elem_type
->type
== SIDE_TYPE_BYTE
) {
577 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
578 if (v
& (1ULL << (bit
% 8))) {
583 union int64_value v64
;
585 v64
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
586 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
588 if (v64
.u
& (1ULL << (bit
% stride_bit
))) {
596 printf("%s", print_count
++ ? ", " : "");
597 tracer_print_string(mapping
->label
.p
, mapping
->label
.unit_size
, mapping
->label
.byte_order
, NULL
);
601 printf("<NO LABEL>");
606 void print_integer_binary(uint64_t v
, int bits
)
612 for (i
= 0; i
< bits
; i
++) {
613 printf("%c", v
& (1ULL << 63) ? '1' : '0');
619 void tracer_print_type_header(const char *separator
,
620 const struct side_attr
*attr
, uint32_t nr_attr
)
622 print_attributes("attr", separator
, attr
, nr_attr
);
623 printf("%s", nr_attr
? ", " : "");
624 printf("value%s ", separator
);
628 void tracer_print_type_bool(const char *separator
,
629 const struct side_type_bool
*type_bool
,
630 const union side_bool_value
*value
,
631 uint16_t offset_bits
)
637 if (!type_bool
->len_bits
)
638 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
640 len_bits
= type_bool
->len_bits
;
641 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
643 reverse_bo
= type_bool
->byte_order
!= SIDE_TYPE_BYTE_ORDER_HOST
;
644 switch (type_bool
->bool_size
) {
646 v
= value
->side_bool8
;
652 side_u16
= value
->side_bool16
;
654 side_u16
= side_bswap_16(side_u16
);
662 side_u32
= value
->side_bool32
;
664 side_u32
= side_bswap_32(side_u32
);
672 side_u64
= value
->side_bool64
;
674 side_u64
= side_bswap_64(side_u64
);
683 v
&= (1ULL << len_bits
) - 1;
684 tracer_print_type_header(separator
, type_bool
->attr
, type_bool
->nr_attr
);
685 printf("%s", v
? "true" : "false");
689 void tracer_print_type_integer(const char *separator
,
690 const struct side_type_integer
*type_integer
,
691 const union side_integer_value
*value
,
692 uint16_t offset_bits
,
693 enum tracer_display_base default_base
)
695 enum tracer_display_base base
;
696 union int64_value v64
;
699 v64
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
700 tracer_print_type_header(separator
, type_integer
->attr
, type_integer
->nr_attr
);
701 base
= get_attr_display_base(type_integer
->attr
, type_integer
->nr_attr
, default_base
);
703 case TRACER_DISPLAY_BASE_2
:
704 print_integer_binary(v64
.u
, len_bits
);
706 case TRACER_DISPLAY_BASE_8
:
707 /* Clear sign bits beyond len_bits */
709 v64
.u
&= (1ULL << len_bits
) - 1;
710 printf("0%" PRIo64
, v64
.u
);
712 case TRACER_DISPLAY_BASE_10
:
713 if (type_integer
->signedness
)
714 printf("%" PRId64
, v64
.s
);
716 printf("%" PRIu64
, v64
.u
);
718 case TRACER_DISPLAY_BASE_16
:
719 /* Clear sign bits beyond len_bits */
721 v64
.u
&= (1ULL << len_bits
) - 1;
722 printf("0x%" PRIx64
, v64
.u
);
730 void tracer_print_type_float(const char *separator
,
731 const struct side_type_float
*type_float
,
732 const union side_float_value
*value
)
736 tracer_print_type_header(separator
, type_float
->attr
, type_float
->nr_attr
);
737 reverse_bo
= type_float
->byte_order
!= SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
738 switch (type_float
->float_size
) {
746 .f
= value
->side_float_binary16
,
750 float16
.u
= side_bswap_16(float16
.u
);
751 printf("%g", (double) float16
.f
);
754 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
765 .f
= value
->side_float_binary32
,
769 float32
.u
= side_bswap_32(float32
.u
);
770 printf("%g", (double) float32
.f
);
773 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
784 .f
= value
->side_float_binary64
,
788 float64
.u
= side_bswap_64(float64
.u
);
789 printf("%g", (double) float64
.f
);
792 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
803 .f
= value
->side_float_binary128
,
807 side_bswap_128p(float128
.arr
);
808 printf("%Lg", (long double) float128
.f
);
811 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
816 fprintf(stderr
, "ERROR: Unknown float size\n");
822 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
)
824 enum side_type_label type
;
826 switch (type_desc
->type
) {
828 switch (item
->type
) {
839 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
845 case SIDE_TYPE_ENUM_BITMAP
:
846 switch (item
->type
) {
852 case SIDE_TYPE_ARRAY
:
856 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
862 case SIDE_TYPE_GATHER_ENUM
:
863 switch (item
->type
) {
864 case SIDE_TYPE_GATHER_INTEGER
:
867 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
873 case SIDE_TYPE_DYNAMIC
:
874 switch (item
->type
) {
875 case SIDE_TYPE_DYNAMIC_NULL
:
876 case SIDE_TYPE_DYNAMIC_BOOL
:
877 case SIDE_TYPE_DYNAMIC_INTEGER
:
878 case SIDE_TYPE_DYNAMIC_BYTE
:
879 case SIDE_TYPE_DYNAMIC_POINTER
:
880 case SIDE_TYPE_DYNAMIC_FLOAT
:
881 case SIDE_TYPE_DYNAMIC_STRING
:
882 case SIDE_TYPE_DYNAMIC_STRUCT
:
883 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
884 case SIDE_TYPE_DYNAMIC_VLA
:
885 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
888 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
895 if (type_desc
->type
!= item
->type
) {
896 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
902 if (type_desc
->type
== SIDE_TYPE_ENUM
|| type_desc
->type
== SIDE_TYPE_ENUM_BITMAP
||
903 type_desc
->type
== SIDE_TYPE_GATHER_ENUM
)
904 type
= (enum side_type_label
) type_desc
->type
;
906 type
= (enum side_type_label
) item
->type
;
910 /* Stack-copy basic types */
912 tracer_print_type_header(":", type_desc
->u
.side_null
.attr
, type_desc
->u
.side_null
.nr_attr
);
913 printf("<NULL TYPE>");
917 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
928 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
929 TRACER_DISPLAY_BASE_10
);
933 tracer_print_type_header(":", type_desc
->u
.side_byte
.attr
, type_desc
->u
.side_byte
.nr_attr
);
934 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
937 case SIDE_TYPE_POINTER
:
938 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
939 TRACER_DISPLAY_BASE_16
);
942 case SIDE_TYPE_FLOAT_BINARY16
:
943 case SIDE_TYPE_FLOAT_BINARY32
:
944 case SIDE_TYPE_FLOAT_BINARY64
:
945 case SIDE_TYPE_FLOAT_BINARY128
:
946 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
949 case SIDE_TYPE_STRING_UTF8
:
950 case SIDE_TYPE_STRING_UTF16
:
951 case SIDE_TYPE_STRING_UTF32
:
952 tracer_print_type_header(":", type_desc
->u
.side_string
.attr
, type_desc
->u
.side_string
.nr_attr
);
953 tracer_print_string((const void *)(uintptr_t) item
->u
.side_static
.string_value
,
954 type_desc
->u
.side_string
.unit_size
, type_desc
->u
.side_string
.byte_order
, NULL
);
957 /* Stack-copy compound types */
958 case SIDE_TYPE_STRUCT
:
959 tracer_print_struct(type_desc
, item
->u
.side_static
.side_struct
);
961 case SIDE_TYPE_ARRAY
:
962 tracer_print_array(type_desc
, item
->u
.side_static
.side_array
);
965 tracer_print_vla(type_desc
, item
->u
.side_static
.side_vla
);
967 case SIDE_TYPE_VLA_VISITOR
:
968 tracer_print_vla_visitor(type_desc
, item
->u
.side_static
.side_vla_app_visitor_ctx
);
971 /* Stack-copy enumeration types */
973 tracer_print_enum(type_desc
, item
);
975 case SIDE_TYPE_ENUM_BITMAP
:
976 tracer_print_enum_bitmap(type_desc
, item
);
979 /* Gather basic types */
980 case SIDE_TYPE_GATHER_BOOL
:
981 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_bool_gather_ptr
);
983 case SIDE_TYPE_GATHER_INTEGER
:
984 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
985 TRACER_DISPLAY_BASE_10
);
987 case SIDE_TYPE_GATHER_BYTE
:
988 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_byte_gather_ptr
);
990 case SIDE_TYPE_GATHER_POINTER
:
991 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
,
992 TRACER_DISPLAY_BASE_16
);
994 case SIDE_TYPE_GATHER_FLOAT
:
995 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_float_gather_ptr
);
997 case SIDE_TYPE_GATHER_STRING
:
998 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_string_gather_ptr
);
1001 /* Gather compound type */
1002 case SIDE_TYPE_GATHER_STRUCT
:
1003 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_struct_gather_ptr
);
1005 case SIDE_TYPE_GATHER_ARRAY
:
1006 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_array_gather_ptr
);
1008 case SIDE_TYPE_GATHER_VLA
:
1009 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_vla_gather
.ptr
,
1010 item
->u
.side_static
.side_vla_gather
.length_ptr
);
1013 /* Gather enumeration types */
1014 case SIDE_TYPE_GATHER_ENUM
:
1015 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, item
->u
.side_static
.side_integer_gather_ptr
);
1018 /* Dynamic basic types */
1019 case SIDE_TYPE_DYNAMIC_NULL
:
1020 case SIDE_TYPE_DYNAMIC_BOOL
:
1021 case SIDE_TYPE_DYNAMIC_INTEGER
:
1022 case SIDE_TYPE_DYNAMIC_BYTE
:
1023 case SIDE_TYPE_DYNAMIC_POINTER
:
1024 case SIDE_TYPE_DYNAMIC_FLOAT
:
1025 case SIDE_TYPE_DYNAMIC_STRING
:
1027 /* Dynamic compound types */
1028 case SIDE_TYPE_DYNAMIC_STRUCT
:
1029 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1030 case SIDE_TYPE_DYNAMIC_VLA
:
1031 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1032 tracer_print_dynamic(item
);
1035 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1042 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1044 printf("%s: ", item_desc
->field_name
);
1045 tracer_print_type(&item_desc
->side_type
, item
);
1049 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1051 const struct side_arg
*sav
= side_arg_vec
->sav
;
1052 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1054 if (type_desc
->u
.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", ":", type_desc
->u
.side_struct
->attr
, type_desc
->u
.side_struct
->nr_attr
);
1059 printf("%s", type_desc
->u
.side_struct
->nr_attr
? ", " : "");
1060 printf("fields: { ");
1061 for (i
= 0; i
< side_sav_len
; i
++) {
1062 printf("%s", i
? ", " : "");
1063 tracer_print_field(&type_desc
->u
.side_struct
->fields
[i
], &sav
[i
]);
1069 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1071 const struct side_arg
*sav
= side_arg_vec
->sav
;
1072 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1074 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1075 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1078 print_attributes("attr", ":", type_desc
->u
.side_array
.attr
, type_desc
->u
.side_array
.nr_attr
);
1079 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1080 printf("elements: ");
1082 for (i
= 0; i
< side_sav_len
; i
++) {
1083 printf("%s", i
? ", " : "");
1084 tracer_print_type(type_desc
->u
.side_array
.elem_type
, &sav
[i
]);
1090 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1092 const struct side_arg
*sav
= side_arg_vec
->sav
;
1093 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1095 print_attributes("attr", ":", type_desc
->u
.side_vla
.attr
, type_desc
->u
.side_vla
.nr_attr
);
1096 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1097 printf("elements: ");
1099 for (i
= 0; i
< side_sav_len
; i
++) {
1100 printf("%s", i
? ", " : "");
1101 tracer_print_type(type_desc
->u
.side_vla
.elem_type
, &sav
[i
]);
1107 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1109 switch (access_mode
) {
1110 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1112 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1113 /* Dereference pointer */
1114 memcpy(&ptr
, ptr
, sizeof(ptr
));
1122 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1124 switch (access_mode
) {
1125 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1127 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1128 return sizeof(void *);
1135 union int64_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1138 enum side_type_gather_access_mode access_mode
=
1139 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1140 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1141 const char *ptr
= (const char *) _ptr
;
1142 union side_integer_value value
;
1144 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1145 memcpy(&value
, ptr
, integer_size_bytes
);
1146 return tracer_load_integer_value(&side_integer
->type
, &value
,
1147 side_integer
->offset_bits
, NULL
);
1151 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1153 enum side_type_gather_access_mode access_mode
=
1154 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1155 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1156 const char *ptr
= (const char *) _ptr
;
1157 union side_bool_value value
;
1159 switch (bool_size_bytes
) {
1168 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1169 memcpy(&value
, ptr
, bool_size_bytes
);
1170 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1171 type_gather
->u
.side_bool
.offset_bits
);
1172 return tracer_gather_size(access_mode
, bool_size_bytes
);
1176 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1178 enum side_type_gather_access_mode access_mode
=
1179 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1180 const char *ptr
= (const char *) _ptr
;
1183 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1184 memcpy(&value
, ptr
, 1);
1185 tracer_print_type_header(":", type_gather
->u
.side_byte
.type
.attr
,
1186 type_gather
->u
.side_byte
.type
.nr_attr
);
1187 printf("0x%" PRIx8
, value
);
1188 return tracer_gather_size(access_mode
, 1);
1192 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1193 enum tracer_display_base default_base
)
1195 enum side_type_gather_access_mode access_mode
=
1196 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1197 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1198 const char *ptr
= (const char *) _ptr
;
1199 union side_integer_value value
;
1201 switch (integer_size_bytes
) {
1210 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1211 memcpy(&value
, ptr
, integer_size_bytes
);
1212 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1213 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1214 return tracer_gather_size(access_mode
, integer_size_bytes
);
1218 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1220 enum side_type_gather_access_mode access_mode
=
1221 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1222 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1223 const char *ptr
= (const char *) _ptr
;
1224 union side_float_value value
;
1226 switch (float_size_bytes
) {
1235 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1236 memcpy(&value
, ptr
, float_size_bytes
);
1237 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1238 return tracer_gather_size(access_mode
, float_size_bytes
);
1242 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1244 enum side_type_gather_access_mode access_mode
=
1245 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1246 const char *ptr
= (const char *) _ptr
;
1249 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1250 tracer_print_type_header(":", type_gather
->u
.side_string
.type
.attr
,
1251 type_gather
->u
.side_string
.type
.nr_attr
);
1253 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1254 type_gather
->u
.side_string
.type
.byte_order
, &string_len
);
1257 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1259 return tracer_gather_size(access_mode
, string_len
);
1263 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1268 switch (type_desc
->type
) {
1269 /* Gather basic types */
1270 case SIDE_TYPE_GATHER_BOOL
:
1271 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1273 case SIDE_TYPE_GATHER_INTEGER
:
1274 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1275 TRACER_DISPLAY_BASE_10
);
1277 case SIDE_TYPE_GATHER_BYTE
:
1278 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1280 case SIDE_TYPE_GATHER_POINTER
:
1281 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1282 TRACER_DISPLAY_BASE_16
);
1284 case SIDE_TYPE_GATHER_FLOAT
:
1285 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1287 case SIDE_TYPE_GATHER_STRING
:
1288 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1291 /* Gather enum types */
1292 case SIDE_TYPE_GATHER_ENUM
:
1293 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1296 /* Gather compound types */
1297 case SIDE_TYPE_GATHER_STRUCT
:
1298 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1300 case SIDE_TYPE_GATHER_ARRAY
:
1301 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1303 case SIDE_TYPE_GATHER_VLA
:
1304 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1307 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1315 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1317 const struct side_enum_mappings
*mappings
= type_gather
->u
.side_enum
.mappings
;
1318 const struct side_type
*enum_elem_type
= type_gather
->u
.side_enum
.elem_type
;
1319 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1320 enum side_type_gather_access_mode access_mode
=
1321 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1322 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1323 const char *ptr
= (const char *) _ptr
;
1324 union side_integer_value value
;
1325 union int64_value v64
;
1327 switch (integer_size_bytes
) {
1336 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1337 memcpy(&value
, ptr
, integer_size_bytes
);
1338 v64
= tracer_load_gather_integer_value(side_integer
, &value
);
1339 print_attributes("attr", ":", mappings
->attr
, mappings
->nr_attr
);
1340 printf("%s", mappings
->nr_attr
? ", " : "");
1341 tracer_print_gather_type(enum_elem_type
, ptr
);
1342 print_enum_labels(mappings
, v64
);
1343 return tracer_gather_size(access_mode
, integer_size_bytes
);
1347 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1349 printf("%s: ", field
->field_name
);
1350 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1354 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1356 enum side_type_gather_access_mode access_mode
=
1357 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1358 const char *ptr
= (const char *) _ptr
;
1361 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1362 print_attributes("attr", ":", type_gather
->u
.side_struct
.type
->attr
, type_gather
->u
.side_struct
.type
->nr_attr
);
1363 printf("%s", type_gather
->u
.side_struct
.type
->nr_attr
? ", " : "");
1364 printf("fields: { ");
1365 for (i
= 0; i
< type_gather
->u
.side_struct
.type
->nr_fields
; i
++) {
1366 printf("%s", i
? ", " : "");
1367 tracer_print_gather_field(&type_gather
->u
.side_struct
.type
->fields
[i
], ptr
);
1370 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1374 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1376 enum side_type_gather_access_mode access_mode
=
1377 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1378 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1381 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1383 print_attributes("attr", ":", type_gather
->u
.side_array
.type
.attr
, type_gather
->u
.side_array
.type
.nr_attr
);
1384 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1385 printf("elements: ");
1387 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1388 switch (type_gather
->u
.side_array
.type
.elem_type
->type
) {
1389 case SIDE_TYPE_GATHER_VLA
:
1390 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1395 printf("%s", i
? ", " : "");
1396 ptr
+= tracer_print_gather_type(type_gather
->u
.side_array
.type
.elem_type
, ptr
);
1399 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1403 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1404 const void *_length_ptr
)
1406 enum side_type_gather_access_mode access_mode
=
1407 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1408 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1409 const char *length_ptr
= (const char *) _length_ptr
;
1410 union int64_value v64
;
1414 switch (type_gather
->u
.side_vla
.length_type
->type
) {
1415 case SIDE_TYPE_GATHER_INTEGER
:
1418 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1421 v64
= tracer_load_gather_integer_value(&type_gather
->u
.side_vla
.length_type
->u
.side_gather
.u
.side_integer
,
1423 length
= (uint32_t) v64
.u
;
1424 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1426 print_attributes("attr", ":", type_gather
->u
.side_vla
.type
.attr
, type_gather
->u
.side_vla
.type
.nr_attr
);
1427 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1428 printf("elements: ");
1430 for (i
= 0; i
< length
; i
++) {
1431 switch (type_gather
->u
.side_vla
.type
.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(type_gather
->u
.side_vla
.type
.elem_type
, ptr
);
1442 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1445 struct tracer_visitor_priv
{
1446 const struct side_type
*elem_type
;
1451 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1452 const struct side_arg
*elem
)
1454 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1456 printf("%s", tracer_priv
->i
++ ? ", " : "");
1457 tracer_print_type(tracer_priv
->elem_type
, elem
);
1458 return SIDE_VISITOR_STATUS_OK
;
1462 void tracer_print_vla_visitor(const struct side_type
*type_desc
, void *app_ctx
)
1464 enum side_visitor_status status
;
1465 struct tracer_visitor_priv tracer_priv
= {
1466 .elem_type
= type_desc
->u
.side_vla_visitor
.elem_type
,
1469 const struct side_tracer_visitor_ctx tracer_ctx
= {
1470 .write_elem
= tracer_write_elem_cb
,
1471 .priv
= &tracer_priv
,
1474 print_attributes("attr", ":", type_desc
->u
.side_vla_visitor
.attr
, type_desc
->u
.side_vla_visitor
.nr_attr
);
1475 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1476 printf("elements: ");
1478 status
= type_desc
->u
.side_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1480 case SIDE_VISITOR_STATUS_OK
:
1482 case SIDE_VISITOR_STATUS_ERROR
:
1483 fprintf(stderr
, "ERROR: Visitor error\n");
1490 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1492 const struct side_arg_dynamic_field
*fields
= dynamic_struct
->fields
;
1493 uint32_t i
, len
= dynamic_struct
->len
;
1495 print_attributes("attr", "::", dynamic_struct
->attr
, dynamic_struct
->nr_attr
);
1496 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1497 printf("fields:: ");
1499 for (i
= 0; i
< len
; i
++) {
1500 printf("%s", i
? ", " : "");
1501 printf("%s:: ", fields
[i
].field_name
);
1502 tracer_print_dynamic(&fields
[i
].elem
);
1507 struct tracer_dynamic_struct_visitor_priv
{
1512 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1513 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1514 const struct side_arg_dynamic_field
*dynamic_field
)
1516 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1517 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1519 printf("%s", tracer_priv
->i
++ ? ", " : "");
1520 printf("%s:: ", dynamic_field
->field_name
);
1521 tracer_print_dynamic(&dynamic_field
->elem
);
1522 return SIDE_VISITOR_STATUS_OK
;
1526 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1528 enum side_visitor_status status
;
1529 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1532 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1533 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1534 .priv
= &tracer_priv
,
1536 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.app_ctx
;
1538 print_attributes("attr", "::", item
->u
.side_dynamic
.side_dynamic_struct_visitor
.attr
, item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
);
1539 printf("%s", item
->u
.side_dynamic
.side_dynamic_struct_visitor
.nr_attr
? ", " : "");
1540 printf("fields:: ");
1542 status
= item
->u
.side_dynamic
.side_dynamic_struct_visitor
.visitor(&tracer_ctx
, app_ctx
);
1544 case SIDE_VISITOR_STATUS_OK
:
1546 case SIDE_VISITOR_STATUS_ERROR
:
1547 fprintf(stderr
, "ERROR: Visitor error\n");
1554 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1556 const struct side_arg
*sav
= vla
->sav
;
1557 uint32_t i
, side_sav_len
= vla
->len
;
1559 print_attributes("attr", "::", vla
->attr
, vla
->nr_attr
);
1560 printf("%s", vla
->nr_attr
? ", " : "");
1561 printf("elements:: ");
1563 for (i
= 0; i
< side_sav_len
; i
++) {
1564 printf("%s", i
? ", " : "");
1565 tracer_print_dynamic(&sav
[i
]);
1570 struct tracer_dynamic_vla_visitor_priv
{
1575 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1576 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1577 const struct side_arg
*elem
)
1579 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1580 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1582 printf("%s", tracer_priv
->i
++ ? ", " : "");
1583 tracer_print_dynamic(elem
);
1584 return SIDE_VISITOR_STATUS_OK
;
1588 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1590 enum side_visitor_status status
;
1591 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1594 const struct side_tracer_visitor_ctx tracer_ctx
= {
1595 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1596 .priv
= &tracer_priv
,
1598 void *app_ctx
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.app_ctx
;
1600 print_attributes("attr", "::", item
->u
.side_dynamic
.side_dynamic_vla_visitor
.attr
, item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
);
1601 printf("%s", item
->u
.side_dynamic
.side_dynamic_vla_visitor
.nr_attr
? ", " : "");
1602 printf("elements:: ");
1604 status
= item
->u
.side_dynamic
.side_dynamic_vla_visitor
.visitor(&tracer_ctx
, app_ctx
);
1606 case SIDE_VISITOR_STATUS_OK
:
1608 case SIDE_VISITOR_STATUS_ERROR
:
1609 fprintf(stderr
, "ERROR: Visitor error\n");
1616 void tracer_print_dynamic(const struct side_arg
*item
)
1619 switch (item
->type
) {
1620 /* Dynamic basic types */
1621 case SIDE_TYPE_DYNAMIC_NULL
:
1622 tracer_print_type_header("::", item
->u
.side_dynamic
.side_null
.attr
, item
->u
.side_dynamic
.side_null
.nr_attr
);
1623 printf("<NULL TYPE>");
1625 case SIDE_TYPE_DYNAMIC_BOOL
:
1626 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1628 case SIDE_TYPE_DYNAMIC_INTEGER
:
1629 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1630 TRACER_DISPLAY_BASE_10
);
1632 case SIDE_TYPE_DYNAMIC_BYTE
:
1633 tracer_print_type_header("::", item
->u
.side_dynamic
.side_byte
.type
.attr
, item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1634 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1636 case SIDE_TYPE_DYNAMIC_POINTER
:
1637 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1638 TRACER_DISPLAY_BASE_16
);
1640 case SIDE_TYPE_DYNAMIC_FLOAT
:
1641 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1642 &item
->u
.side_dynamic
.side_float
.value
);
1644 case SIDE_TYPE_DYNAMIC_STRING
:
1645 tracer_print_type_header("::", item
->u
.side_dynamic
.side_string
.type
.attr
, item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1646 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1647 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
1648 item
->u
.side_dynamic
.side_string
.type
.byte_order
, NULL
);
1651 /* Dynamic compound types */
1652 case SIDE_TYPE_DYNAMIC_STRUCT
:
1653 tracer_print_dynamic_struct(item
->u
.side_dynamic
.side_dynamic_struct
);
1655 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1656 tracer_print_dynamic_struct_visitor(item
);
1658 case SIDE_TYPE_DYNAMIC_VLA
:
1659 tracer_print_dynamic_vla(item
->u
.side_dynamic
.side_dynamic_vla
);
1661 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1662 tracer_print_dynamic_vla_visitor(item
);
1665 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1672 void tracer_print_static_fields(const struct side_event_description
*desc
,
1673 const struct side_arg_vec
*side_arg_vec
,
1676 const struct side_arg
*sav
= side_arg_vec
->sav
;
1677 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1679 printf("provider: %s, event: %s", desc
->provider_name
, desc
->event_name
);
1680 if (desc
->nr_fields
!= side_sav_len
) {
1681 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
1684 print_attributes(", attr", ":", desc
->attr
, desc
->nr_attr
);
1685 printf("%s", side_sav_len
? ", fields: [ " : "");
1686 for (i
= 0; i
< side_sav_len
; i
++) {
1687 printf("%s", i
? ", " : "");
1688 tracer_print_field(&desc
->fields
[i
], &sav
[i
]);
1696 void tracer_call(const struct side_event_description
*desc
,
1697 const struct side_arg_vec
*side_arg_vec
,
1698 void *priv
__attribute__((unused
)))
1700 uint32_t nr_fields
= 0;
1702 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1706 void tracer_call_variadic(const struct side_event_description
*desc
,
1707 const struct side_arg_vec
*side_arg_vec
,
1708 const struct side_arg_dynamic_struct
*var_struct
,
1709 void *priv
__attribute__((unused
)))
1711 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
1713 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
);
1715 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
1716 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
1719 print_attributes(", attr ", "::", var_struct
->attr
, var_struct
->nr_attr
);
1720 printf("%s", var_struct_len
? ", fields:: [ " : "");
1721 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
1722 printf("%s", i
? ", " : "");
1723 printf("%s:: ", var_struct
->fields
[i
].field_name
);
1724 tracer_print_dynamic(&var_struct
->fields
[i
].elem
);
1731 void tracer_event_notification(enum side_tracer_notification notif
,
1732 struct side_event_description
**events
, uint32_t nr_events
, void *priv
)
1737 printf("----------------------------------------------------------\n");
1738 printf("Tracer notified of events %s\n",
1739 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
1740 for (i
= 0; i
< nr_events
; i
++) {
1741 struct side_event_description
*event
= events
[i
];
1743 /* Skip NULL pointers */
1746 printf("provider: %s, event: %s\n",
1747 event
->provider_name
, event
->event_name
);
1748 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
1749 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1750 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
);
1754 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
);
1759 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1760 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
);
1764 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
);
1770 printf("----------------------------------------------------------\n");
1773 static __attribute__((constructor
))
1774 void tracer_init(void);
1776 void tracer_init(void)
1778 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
1783 static __attribute__((destructor
))
1784 void tracer_exit(void);
1786 void tracer_exit(void)
1788 side_tracer_event_notification_unregister(tracer_handle
);