1 // SPDX-License-Identifier: MIT
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 #include <side/trace.h>
16 /* TODO: optionally print caller address. */
17 static bool print_caller
= false;
19 enum tracer_display_base
{
20 TRACER_DISPLAY_BASE_2
,
21 TRACER_DISPLAY_BASE_8
,
22 TRACER_DISPLAY_BASE_10
,
23 TRACER_DISPLAY_BASE_16
,
27 uint64_t u
[NR_SIDE_INTEGER128_SPLIT
];
28 int64_t s
[NR_SIDE_INTEGER128_SPLIT
];
31 static struct side_tracer_handle
*tracer_handle
;
33 static uint64_t tracer_key
;
36 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
38 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
);
40 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
42 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
);
44 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
);
46 void tracer_print_dynamic(const struct side_arg
*dynamic_item
, bool print_brackets
);
48 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
50 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
52 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
53 enum tracer_display_base default_base
);
55 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
57 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
59 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
);
61 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
);
63 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
);
65 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
66 const void *_length_ptr
);
68 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
);
71 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
72 size_t *strlen_with_null
,
75 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
, input_size
;
76 const char *str
= p
, *fromcode
;
77 char *inbuf
= (char *) p
, *outbuf
, *buf
;
83 *strlen_with_null
= strlen(str
) + 1;
84 *output_str
= (char *) str
;
88 const uint16_t *p16
= p
;
91 case SIDE_TYPE_BYTE_ORDER_LE
:
93 fromcode
= "UTF-16LE";
96 case SIDE_TYPE_BYTE_ORDER_BE
:
98 fromcode
= "UTF-16BE";
102 fprintf(stderr
, "Unknown byte order\n");
107 input_size
= inbytesleft
+ 2;
109 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
110 * { ef, bf, bf } UTF-8 (3 bytes).
112 bufsize
= inbytesleft
/ 2 * 3 + 1;
117 const uint32_t *p32
= p
;
119 switch (byte_order
) {
120 case SIDE_TYPE_BYTE_ORDER_LE
:
122 fromcode
= "UTF-32LE";
125 case SIDE_TYPE_BYTE_ORDER_BE
:
127 fromcode
= "UTF-32BE";
131 fprintf(stderr
, "Unknown byte order\n");
136 input_size
= inbytesleft
+ 4;
138 * Each 4-byte UTF-32 character converts to at most a
139 * 4-byte UTF-8 character.
141 bufsize
= inbytesleft
+ 1;
145 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
149 cd
= iconv_open("UTF8", fromcode
);
150 if (cd
== (iconv_t
) -1) {
151 perror("iconv_open");
154 buf
= malloc(bufsize
);
158 outbuf
= (char *) buf
;
159 outbytesleft
= bufsize
;
160 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
161 if (ret
== (size_t) -1) {
166 fprintf(stderr
, "Buffer too small to convert string input\n");
170 if (iconv_close(cd
) == -1) {
171 perror("iconv_close");
174 if (strlen_with_null
)
175 *strlen_with_null
= input_size
;
180 void tracer_print_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
181 size_t *strlen_with_null
)
183 char *output_str
= NULL
;
185 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
186 printf("\"%s\"", output_str
);
192 void side_check_value_u64(union int_value v
)
194 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
]) {
195 fprintf(stderr
, "Unexpected integer value\n");
201 void side_check_value_s64(union int_value v
)
203 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63)) {
204 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] != ~0LL) {
205 fprintf(stderr
, "Unexpected integer value\n");
209 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
]) {
210 fprintf(stderr
, "Unexpected integer value\n");
217 int64_t get_attr_integer64_value(const struct side_attr
*attr
)
221 switch (side_enum_get(attr
->value
.type
)) {
222 case SIDE_ATTR_TYPE_U8
:
223 val
= attr
->value
.u
.integer_value
.side_u8
;
225 case SIDE_ATTR_TYPE_U16
:
226 val
= attr
->value
.u
.integer_value
.side_u16
;
228 case SIDE_ATTR_TYPE_U32
:
229 val
= attr
->value
.u
.integer_value
.side_u32
;
231 case SIDE_ATTR_TYPE_U64
:
232 val
= attr
->value
.u
.integer_value
.side_u64
;
234 case SIDE_ATTR_TYPE_U128
:
236 union int_value v
= {
238 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
],
239 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
242 side_check_value_u64(v
);
243 val
= v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
246 case SIDE_ATTR_TYPE_S8
:
247 val
= attr
->value
.u
.integer_value
.side_s8
;
249 case SIDE_ATTR_TYPE_S16
:
250 val
= attr
->value
.u
.integer_value
.side_s16
;
252 case SIDE_ATTR_TYPE_S32
:
253 val
= attr
->value
.u
.integer_value
.side_s32
;
255 case SIDE_ATTR_TYPE_S64
:
256 val
= attr
->value
.u
.integer_value
.side_s64
;
258 case SIDE_ATTR_TYPE_S128
:
260 union int_value v
= {
262 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
],
263 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
266 side_check_value_s64(v
);
267 val
= v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
271 fprintf(stderr
, "Unexpected attribute type\n");
278 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
279 enum tracer_display_base default_base
)
283 for (i
= 0; i
< nr_attr
; i
++) {
284 const struct side_attr
*attr
= &_attr
[i
];
285 char *utf8_str
= NULL
;
288 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
289 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
290 cmp
= strcmp(utf8_str
, "std.integer.base");
291 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
294 int64_t val
= get_attr_integer64_value(attr
);
298 return TRACER_DISPLAY_BASE_2
;
300 return TRACER_DISPLAY_BASE_8
;
302 return TRACER_DISPLAY_BASE_10
;
304 return TRACER_DISPLAY_BASE_16
;
306 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
311 return default_base
; /* Default */
315 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
317 char *utf8_str
= NULL
;
319 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
320 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
321 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
322 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
324 switch (side_enum_get(attr
->value
.type
)) {
325 case SIDE_ATTR_TYPE_BOOL
:
326 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
328 case SIDE_ATTR_TYPE_U8
:
329 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
331 case SIDE_ATTR_TYPE_U16
:
332 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
334 case SIDE_ATTR_TYPE_U32
:
335 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
337 case SIDE_ATTR_TYPE_U64
:
338 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
340 case SIDE_ATTR_TYPE_U128
:
341 if (attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
342 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
344 printf("0x%" PRIx64
"%016" PRIx64
,
345 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
346 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
349 case SIDE_ATTR_TYPE_S8
:
350 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
352 case SIDE_ATTR_TYPE_S16
:
353 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
355 case SIDE_ATTR_TYPE_S32
:
356 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
358 case SIDE_ATTR_TYPE_S64
:
359 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
361 case SIDE_ATTR_TYPE_S128
:
362 if (attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
363 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
365 printf("0x%" PRIx64
"%016" PRIx64
,
366 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
367 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
370 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
372 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
375 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
378 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
380 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
383 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
386 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
388 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
391 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
394 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
396 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
399 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
402 case SIDE_ATTR_TYPE_STRING
:
403 tracer_print_string(side_ptr_get(attr
->value
.u
.string_value
.p
),
404 attr
->value
.u
.string_value
.unit_size
,
405 side_enum_get(attr
->value
.u
.string_value
.byte_order
), NULL
);
408 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
415 void print_attributes(const char *prefix_str
, const char *separator
,
416 const struct side_attr
*attr
, uint32_t nr_attr
)
422 printf("%s%s [ ", prefix_str
, separator
);
423 for (i
= 0; i
< nr_attr
; i
++) {
424 printf("%s", i
? ", " : "");
425 tracer_print_attr_type(separator
, &attr
[i
]);
431 union int_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
432 const union side_integer_value
*value
,
433 uint16_t offset_bits
, uint16_t *_len_bits
)
435 union int_value v
= {};
439 if (!type_integer
->len_bits
)
440 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
442 len_bits
= type_integer
->len_bits
;
443 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
445 reverse_bo
= side_enum_get(type_integer
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
446 switch (type_integer
->integer_size
) {
448 if (type_integer
->signedness
)
449 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s8
;
451 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u8
;
454 if (type_integer
->signedness
) {
457 side_s16
= value
->side_s16
;
459 side_s16
= side_bswap_16(side_s16
);
460 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s16
;
464 side_u16
= value
->side_u16
;
466 side_u16
= side_bswap_16(side_u16
);
467 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u16
;
471 if (type_integer
->signedness
) {
474 side_s32
= value
->side_s32
;
476 side_s32
= side_bswap_32(side_s32
);
477 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s32
;
481 side_u32
= value
->side_u32
;
483 side_u32
= side_bswap_32(side_u32
);
484 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u32
;
488 if (type_integer
->signedness
) {
491 side_s64
= value
->side_s64
;
493 side_s64
= side_bswap_64(side_s64
);
494 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
;
498 side_u64
= value
->side_u64
;
500 side_u64
= side_bswap_64(side_u64
);
501 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
;
505 if (type_integer
->signedness
) {
506 int64_t side_s64
[NR_SIDE_INTEGER128_SPLIT
];
508 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
];
509 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
511 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_LOW
]);
512 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_HIGH
]);
513 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
514 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
516 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
517 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
520 uint64_t side_u64
[NR_SIDE_INTEGER128_SPLIT
];
522 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
];
523 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
525 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_LOW
]);
526 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_HIGH
]);
527 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
528 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
530 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
531 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
538 if (type_integer
->integer_size
<= 8) {
539 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >>= offset_bits
;
541 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
542 if (type_integer
->signedness
) {
544 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (len_bits
- 1))) {
545 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] |= ~((1ULL << len_bits
) - 1);
546 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = ~0ULL;
551 //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits
552 if (len_bits
< 128 || offset_bits
!= 0)
556 *_len_bits
= len_bits
;
561 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int_value v
)
563 uint32_t i
, print_count
= 0;
565 side_check_value_s64(v
);
566 printf(", labels: [ ");
567 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
568 const struct side_enum_mapping
*mapping
= &side_ptr_get(mappings
->mappings
)[i
];
570 if (mapping
->range_end
< mapping
->range_begin
) {
571 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
572 mapping
->range_begin
, mapping
->range_end
);
575 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= mapping
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= mapping
->range_end
) {
576 printf("%s", print_count
++ ? ", " : "");
577 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
578 side_enum_get(mapping
->label
.byte_order
), NULL
);
582 printf("<NO LABEL>");
587 void tracer_print_enum(const struct side_type
*type_desc
, const struct side_arg
*item
)
589 const struct side_enum_mappings
*mappings
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
590 const struct side_type
*elem_type
= side_ptr_get(type_desc
->u
.side_enum
.elem_type
);
593 if (side_enum_get(elem_type
->type
) != side_enum_get(item
->type
)) {
594 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
597 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
598 &item
->u
.side_static
.integer_value
, 0, NULL
);
599 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
600 printf("%s", mappings
->nr_attr
? ", " : "");
601 tracer_print_type(elem_type
, item
);
602 print_enum_labels(mappings
, v
);
606 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
610 switch (side_enum_get(elem_type
->type
)) {
625 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
627 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
634 void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
635 const struct side_arg
*item
)
637 const struct side_enum_bitmap_mappings
*side_enum_mappings
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
638 const struct side_type
*enum_elem_type
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.elem_type
), *elem_type
;
639 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
640 const struct side_arg
*array_item
;
642 switch (side_enum_get(enum_elem_type
->type
)) {
643 case SIDE_TYPE_U8
: /* Fall-through */
644 case SIDE_TYPE_BYTE
: /* Fall-through */
645 case SIDE_TYPE_U16
: /* Fall-through */
646 case SIDE_TYPE_U32
: /* Fall-through */
647 case SIDE_TYPE_U64
: /* Fall-through */
648 case SIDE_TYPE_U128
: /* Fall-through */
649 case SIDE_TYPE_S8
: /* Fall-through */
650 case SIDE_TYPE_S16
: /* Fall-through */
651 case SIDE_TYPE_S32
: /* Fall-through */
652 case SIDE_TYPE_S64
: /* Fall-through */
654 elem_type
= enum_elem_type
;
658 case SIDE_TYPE_ARRAY
:
659 elem_type
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
660 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_array
)->sav
);
661 nr_items
= type_desc
->u
.side_array
.length
;
664 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
665 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_vla
)->sav
);
666 nr_items
= side_ptr_get(item
->u
.side_static
.side_vla
)->len
;
669 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
672 stride_bit
= elem_type_to_stride(elem_type
);
674 print_attributes("attr", ":", side_ptr_get(side_enum_mappings
->attr
), side_enum_mappings
->nr_attr
);
675 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
676 printf("labels: [ ");
677 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
678 const struct side_enum_bitmap_mapping
*mapping
= &side_ptr_get(side_enum_mappings
->mappings
)[i
];
682 if (mapping
->range_end
< mapping
->range_begin
) {
683 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
684 mapping
->range_begin
, mapping
->range_end
);
687 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
688 if (bit
> (nr_items
* stride_bit
) - 1)
690 if (side_enum_get(elem_type
->type
) == SIDE_TYPE_BYTE
) {
691 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
692 if (v
& (1ULL << (bit
% 8))) {
697 union int_value v
= {};
699 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
700 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
702 side_check_value_u64(v
);
703 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (bit
% stride_bit
))) {
711 printf("%s", print_count
++ ? ", " : "");
712 tracer_print_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
713 side_enum_get(mapping
->label
.byte_order
), NULL
);
717 printf("<NO LABEL>");
722 void print_integer_binary(uint64_t v
[NR_SIDE_INTEGER128_SPLIT
], int bits
)
729 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 64 - bits
;
730 for (bit
= 0; bit
< bits
; bit
++) {
731 printf("%c", v
[SIDE_INTEGER128_SPLIT_HIGH
] & (1ULL << 63) ? '1' : '0');
732 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 1;
736 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 64 - bits
;
737 for (bit
= 0; bit
< bits
; bit
++) {
738 printf("%c", v
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63) ? '1' : '0');
739 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 1;
744 void tracer_print_type_header(const char *separator
,
745 const struct side_attr
*attr
, uint32_t nr_attr
)
747 print_attributes("attr", separator
, attr
, nr_attr
);
748 printf("%s", nr_attr
? ", " : "");
749 printf("value%s ", separator
);
753 void tracer_print_type_bool(const char *separator
,
754 const struct side_type_bool
*type_bool
,
755 const union side_bool_value
*value
,
756 uint16_t offset_bits
)
762 if (!type_bool
->len_bits
)
763 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
765 len_bits
= type_bool
->len_bits
;
766 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
768 reverse_bo
= side_enum_get(type_bool
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
769 switch (type_bool
->bool_size
) {
771 v
= value
->side_bool8
;
777 side_u16
= value
->side_bool16
;
779 side_u16
= side_bswap_16(side_u16
);
787 side_u32
= value
->side_bool32
;
789 side_u32
= side_bswap_32(side_u32
);
797 side_u64
= value
->side_bool64
;
799 side_u64
= side_bswap_64(side_u64
);
808 v
&= (1ULL << len_bits
) - 1;
809 tracer_print_type_header(separator
, side_ptr_get(type_bool
->attr
), type_bool
->nr_attr
);
810 printf("%s", v
? "true" : "false");
814 #define U128_BASE_10_ARRAY_LEN sizeof("340282366920938463463374607431768211455")
816 #define S128_BASE_10_ARRAY_LEN sizeof("-170141183460469231731687303715884105728")
819 * u128_tostring_base_10 is inspired from https://stackoverflow.com/a/4364365
822 void u128_tostring_base_10(union int_value v
, char str
[U128_BASE_10_ARRAY_LEN
])
824 int d
[39] = {}, i
, j
, str_i
= 0;
826 for (i
= 63; i
> -1; i
--) {
827 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
829 for (j
= 0; j
< 39; j
++)
831 for (j
= 0; j
< 38; j
++) {
832 d
[j
+ 1] += d
[j
] / 10;
836 for (i
= 63; i
> -1; i
--) {
837 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
840 for (j
= 0; j
< 39; j
++)
843 for (j
= 0; j
< 38; j
++) {
844 d
[j
+ 1] += d
[j
] / 10;
848 for (i
= 38; i
> 0; i
--)
851 for (; i
> -1; i
--) {
852 str
[str_i
++] = '0' + d
[i
];
858 void s128_tostring_base_10(union int_value v
, char str
[S128_BASE_10_ARRAY_LEN
])
860 uint64_t low
, high
, tmp
;
862 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] >= 0) {
864 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
865 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
866 u128_tostring_base_10(v
, str
);
872 /* Special-case minimum value, which has no positive signed representation. */
873 if ((v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] == INT64_MIN
) && (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] == 0)) {
874 memcpy(str
, "-170141183460469231731687303715884105728", S128_BASE_10_ARRAY_LEN
);
877 /* Convert from two's complement. */
878 high
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
879 low
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
883 /* Clear overflow to sign bit. */
884 high
&= ~0x8000000000000000ULL
;
886 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = tmp
;
887 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = high
;
889 u128_tostring_base_10(v
, str
+ 1);
893 #define U128_BASE_8_ARRAY_LEN sizeof("3777777777777777777777777777777777777777777")
896 void u128_tostring_base_8(union int_value v
, char str
[U128_BASE_8_ARRAY_LEN
])
898 int d
[43] = {}, i
, j
, str_i
= 0;
900 for (i
= 63; i
> -1; i
--) {
901 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
903 for (j
= 0; j
< 43; j
++)
905 for (j
= 0; j
< 42; j
++) {
906 d
[j
+ 1] += d
[j
] / 8;
910 for (i
= 63; i
> -1; i
--) {
911 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
914 for (j
= 0; j
< 43; j
++)
917 for (j
= 0; j
< 42; j
++) {
918 d
[j
+ 1] += d
[j
] / 8;
922 for (i
= 42; i
> 0; i
--)
925 for (; i
> -1; i
--) {
926 str
[str_i
++] = '0' + d
[i
];
932 void tracer_print_type_integer(const char *separator
,
933 const struct side_type_integer
*type_integer
,
934 const union side_integer_value
*value
,
935 uint16_t offset_bits
,
936 enum tracer_display_base default_base
)
938 enum tracer_display_base base
;
942 v
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
943 tracer_print_type_header(separator
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
944 base
= get_attr_display_base(side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
, default_base
);
946 case TRACER_DISPLAY_BASE_2
:
947 print_integer_binary(v
.u
, len_bits
);
949 case TRACER_DISPLAY_BASE_8
:
950 /* Clear sign bits beyond len_bits */
952 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
953 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
954 } else if (len_bits
< 128) {
955 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
957 if (len_bits
<= 64) {
958 printf("0o%" PRIo64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
960 char str
[U128_BASE_8_ARRAY_LEN
];
962 u128_tostring_base_8(v
, str
);
966 case TRACER_DISPLAY_BASE_10
:
967 if (len_bits
<= 64) {
968 if (type_integer
->signedness
)
969 printf("%" PRId64
, v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
971 printf("%" PRIu64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
973 if (type_integer
->signedness
) {
974 char str
[S128_BASE_10_ARRAY_LEN
];
975 s128_tostring_base_10(v
, str
);
978 char str
[U128_BASE_10_ARRAY_LEN
];
979 u128_tostring_base_10(v
, str
);
984 case TRACER_DISPLAY_BASE_16
:
985 /* Clear sign bits beyond len_bits */
987 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
988 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
989 } else if (len_bits
< 128) {
990 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
992 if (len_bits
<= 64 || v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
993 printf("0x%" PRIx64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
995 printf("0x%" PRIx64
"%016" PRIx64
,
996 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
],
997 v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
1006 void tracer_print_type_float(const char *separator
,
1007 const struct side_type_float
*type_float
,
1008 const union side_float_value
*value
)
1012 tracer_print_type_header(separator
, side_ptr_get(type_float
->attr
), type_float
->nr_attr
);
1013 reverse_bo
= side_enum_get(type_float
->byte_order
) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
1014 switch (type_float
->float_size
) {
1022 .f
= value
->side_float_binary16
,
1026 float16
.u
= side_bswap_16(float16
.u
);
1027 printf("%g", (double) float16
.f
);
1030 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
1041 .f
= value
->side_float_binary32
,
1045 float32
.u
= side_bswap_32(float32
.u
);
1046 printf("%g", (double) float32
.f
);
1049 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
1060 .f
= value
->side_float_binary64
,
1064 float64
.u
= side_bswap_64(float64
.u
);
1065 printf("%g", (double) float64
.f
);
1068 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
1079 .f
= value
->side_float_binary128
,
1083 side_bswap_128p(float128
.arr
);
1084 printf("%Lg", (long double) float128
.f
);
1087 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
1092 fprintf(stderr
, "ERROR: Unknown float size\n");
1098 void tracer_print_type(const struct side_type
*type_desc
, const struct side_arg
*item
)
1100 enum side_type_label type
;
1102 switch (side_enum_get(type_desc
->type
)) {
1103 case SIDE_TYPE_ENUM
:
1104 switch (side_enum_get(item
->type
)) {
1109 case SIDE_TYPE_U128
:
1114 case SIDE_TYPE_S128
:
1117 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1123 case SIDE_TYPE_ENUM_BITMAP
:
1124 switch (side_enum_get(item
->type
)) {
1126 case SIDE_TYPE_BYTE
:
1130 case SIDE_TYPE_U128
:
1131 case SIDE_TYPE_ARRAY
:
1135 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1141 case SIDE_TYPE_GATHER_ENUM
:
1142 switch (side_enum_get(item
->type
)) {
1143 case SIDE_TYPE_GATHER_INTEGER
:
1146 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1152 case SIDE_TYPE_DYNAMIC
:
1153 switch (side_enum_get(item
->type
)) {
1154 case SIDE_TYPE_DYNAMIC_NULL
:
1155 case SIDE_TYPE_DYNAMIC_BOOL
:
1156 case SIDE_TYPE_DYNAMIC_INTEGER
:
1157 case SIDE_TYPE_DYNAMIC_BYTE
:
1158 case SIDE_TYPE_DYNAMIC_POINTER
:
1159 case SIDE_TYPE_DYNAMIC_FLOAT
:
1160 case SIDE_TYPE_DYNAMIC_STRING
:
1161 case SIDE_TYPE_DYNAMIC_STRUCT
:
1162 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1163 case SIDE_TYPE_DYNAMIC_VLA
:
1164 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1167 fprintf(stderr
, "ERROR: Unexpected dynamic type\n");
1174 if (side_enum_get(type_desc
->type
) != side_enum_get(item
->type
)) {
1175 fprintf(stderr
, "ERROR: type mismatch between description and arguments\n");
1181 if (side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_ENUM_BITMAP
|| side_enum_get(type_desc
->type
) == SIDE_TYPE_GATHER_ENUM
)
1182 type
= side_enum_get(type_desc
->type
);
1184 type
= side_enum_get(item
->type
);
1188 /* Stack-copy basic types */
1189 case SIDE_TYPE_NULL
:
1190 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
1191 type_desc
->u
.side_null
.nr_attr
);
1192 printf("<NULL TYPE>");
1195 case SIDE_TYPE_BOOL
:
1196 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
1203 case SIDE_TYPE_U128
:
1208 case SIDE_TYPE_S128
:
1209 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1210 TRACER_DISPLAY_BASE_10
);
1213 case SIDE_TYPE_BYTE
:
1214 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
1215 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
1218 case SIDE_TYPE_POINTER
:
1219 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0,
1220 TRACER_DISPLAY_BASE_16
);
1223 case SIDE_TYPE_FLOAT_BINARY16
:
1224 case SIDE_TYPE_FLOAT_BINARY32
:
1225 case SIDE_TYPE_FLOAT_BINARY64
:
1226 case SIDE_TYPE_FLOAT_BINARY128
:
1227 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
1230 case SIDE_TYPE_STRING_UTF8
:
1231 case SIDE_TYPE_STRING_UTF16
:
1232 case SIDE_TYPE_STRING_UTF32
:
1233 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
1234 tracer_print_string(side_ptr_get(item
->u
.side_static
.string_value
),
1235 type_desc
->u
.side_string
.unit_size
, side_enum_get(type_desc
->u
.side_string
.byte_order
), NULL
);
1238 /* Stack-copy compound types */
1239 case SIDE_TYPE_STRUCT
:
1240 tracer_print_struct(type_desc
, side_ptr_get(item
->u
.side_static
.side_struct
));
1242 case SIDE_TYPE_VARIANT
:
1243 tracer_print_variant(type_desc
, side_ptr_get(item
->u
.side_static
.side_variant
));
1245 case SIDE_TYPE_ARRAY
:
1246 tracer_print_array(type_desc
, side_ptr_get(item
->u
.side_static
.side_array
));
1249 tracer_print_vla(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla
));
1251 case SIDE_TYPE_VLA_VISITOR
:
1252 tracer_print_vla_visitor(type_desc
, side_ptr_get(item
->u
.side_static
.side_vla_visitor
));
1255 /* Stack-copy enumeration types */
1256 case SIDE_TYPE_ENUM
:
1257 tracer_print_enum(type_desc
, item
);
1259 case SIDE_TYPE_ENUM_BITMAP
:
1260 tracer_print_enum_bitmap(type_desc
, item
);
1263 /* Gather basic types */
1264 case SIDE_TYPE_GATHER_BOOL
:
1265 (void) tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_bool_gather_ptr
));
1267 case SIDE_TYPE_GATHER_INTEGER
:
1268 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1269 TRACER_DISPLAY_BASE_10
);
1271 case SIDE_TYPE_GATHER_BYTE
:
1272 (void) tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_byte_gather_ptr
));
1274 case SIDE_TYPE_GATHER_POINTER
:
1275 (void) tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
),
1276 TRACER_DISPLAY_BASE_16
);
1278 case SIDE_TYPE_GATHER_FLOAT
:
1279 (void) tracer_print_gather_float_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_float_gather_ptr
));
1281 case SIDE_TYPE_GATHER_STRING
:
1282 (void) tracer_print_gather_string_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_string_gather_ptr
));
1285 /* Gather compound type */
1286 case SIDE_TYPE_GATHER_STRUCT
:
1287 (void) tracer_print_gather_struct(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_struct_gather_ptr
));
1289 case SIDE_TYPE_GATHER_ARRAY
:
1290 (void) tracer_print_gather_array(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_array_gather_ptr
));
1292 case SIDE_TYPE_GATHER_VLA
:
1293 (void) tracer_print_gather_vla(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_vla_gather
.ptr
),
1294 side_ptr_get(item
->u
.side_static
.side_vla_gather
.length_ptr
));
1297 /* Gather enumeration types */
1298 case SIDE_TYPE_GATHER_ENUM
:
1299 (void) tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, side_ptr_get(item
->u
.side_static
.side_integer_gather_ptr
));
1302 /* Dynamic basic types */
1303 case SIDE_TYPE_DYNAMIC_NULL
:
1304 case SIDE_TYPE_DYNAMIC_BOOL
:
1305 case SIDE_TYPE_DYNAMIC_INTEGER
:
1306 case SIDE_TYPE_DYNAMIC_BYTE
:
1307 case SIDE_TYPE_DYNAMIC_POINTER
:
1308 case SIDE_TYPE_DYNAMIC_FLOAT
:
1309 case SIDE_TYPE_DYNAMIC_STRING
:
1311 /* Dynamic compound types */
1312 case SIDE_TYPE_DYNAMIC_STRUCT
:
1313 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
1314 case SIDE_TYPE_DYNAMIC_VLA
:
1315 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
1316 tracer_print_dynamic(item
, false);
1319 fprintf(stderr
, "<UNKNOWN TYPE>\n");
1326 void tracer_print_field(const struct side_event_field
*item_desc
, const struct side_arg
*item
)
1328 printf("%s: ", side_ptr_get(item_desc
->field_name
));
1329 tracer_print_type(&item_desc
->side_type
, item
);
1333 void tracer_print_struct(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1335 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1336 const struct side_type_struct
*side_struct
= side_ptr_get(type_desc
->u
.side_struct
);
1337 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1339 if (side_struct
->nr_fields
!= side_sav_len
) {
1340 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments of structure\n");
1343 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1344 printf("%s", side_struct
->nr_attr
? ", " : "");
1345 printf("fields: { ");
1346 for (i
= 0; i
< side_sav_len
; i
++) {
1347 printf("%s", i
? ", " : "");
1348 tracer_print_field(&side_ptr_get(side_struct
->fields
)[i
], &sav
[i
]);
1354 void tracer_print_variant(const struct side_type
*type_desc
, const struct side_arg_variant
*side_arg_variant
)
1356 const struct side_type_variant
*side_type_variant
= side_ptr_get(type_desc
->u
.side_variant
);
1357 const struct side_type
*selector_type
= &side_type_variant
->selector
;
1361 if (side_enum_get(selector_type
->type
) != side_enum_get(side_arg_variant
->selector
.type
)) {
1362 fprintf(stderr
, "ERROR: Unexpected variant selector type\n");
1365 switch (side_enum_get(selector_type
->type
)) {
1370 case SIDE_TYPE_U128
:
1375 case SIDE_TYPE_S128
:
1378 fprintf(stderr
, "ERROR: Expecting integer variant selector type\n");
1381 v
= tracer_load_integer_value(&selector_type
->u
.side_integer
,
1382 &side_arg_variant
->selector
.u
.side_static
.integer_value
, 0, NULL
);
1383 side_check_value_u64(v
);
1384 for (i
= 0; i
< side_type_variant
->nr_options
; i
++) {
1385 const struct side_variant_option
*option
= &side_ptr_get(side_type_variant
->options
)[i
];
1387 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= option
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= option
->range_end
) {
1388 tracer_print_type(&option
->side_type
, &side_arg_variant
->option
);
1392 fprintf(stderr
, "ERROR: Variant selector value unknown %" PRId64
"\n", v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
1397 void tracer_print_array(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1399 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1400 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1402 if (type_desc
->u
.side_array
.length
!= side_sav_len
) {
1403 fprintf(stderr
, "ERROR: length mismatch between description and arguments of array\n");
1406 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_array
.attr
), type_desc
->u
.side_array
.nr_attr
);
1407 printf("%s", type_desc
->u
.side_array
.nr_attr
? ", " : "");
1408 printf("elements: ");
1410 for (i
= 0; i
< side_sav_len
; i
++) {
1411 printf("%s", i
? ", " : "");
1412 tracer_print_type(side_ptr_get(type_desc
->u
.side_array
.elem_type
), &sav
[i
]);
1418 void tracer_print_vla(const struct side_type
*type_desc
, const struct side_arg_vec
*side_arg_vec
)
1420 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
1421 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
1423 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla
.attr
), type_desc
->u
.side_vla
.nr_attr
);
1424 printf("%s", type_desc
->u
.side_vla
.nr_attr
? ", " : "");
1425 printf("elements: ");
1427 for (i
= 0; i
< side_sav_len
; i
++) {
1428 printf("%s", i
? ", " : "");
1429 tracer_print_type(side_ptr_get(type_desc
->u
.side_vla
.elem_type
), &sav
[i
]);
1435 const char *tracer_gather_access(enum side_type_gather_access_mode access_mode
, const char *ptr
)
1437 switch (access_mode
) {
1438 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1440 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1441 /* Dereference pointer */
1442 memcpy(&ptr
, ptr
, sizeof(const char *));
1450 uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode
, uint32_t len
)
1452 switch (access_mode
) {
1453 case SIDE_TYPE_GATHER_ACCESS_DIRECT
:
1455 case SIDE_TYPE_GATHER_ACCESS_POINTER
:
1456 return sizeof(void *);
1463 union int_value
tracer_load_gather_integer_value(const struct side_type_gather_integer
*side_integer
,
1466 enum side_type_gather_access_mode access_mode
=
1467 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1468 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1469 const char *ptr
= (const char *) _ptr
;
1470 union side_integer_value value
;
1472 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1473 memcpy(&value
, ptr
, integer_size_bytes
);
1474 return tracer_load_integer_value(&side_integer
->type
, &value
,
1475 side_integer
->offset_bits
, NULL
);
1479 uint32_t tracer_print_gather_bool_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1481 enum side_type_gather_access_mode access_mode
=
1482 (enum side_type_gather_access_mode
) type_gather
->u
.side_bool
.access_mode
;
1483 uint32_t bool_size_bytes
= type_gather
->u
.side_bool
.type
.bool_size
;
1484 const char *ptr
= (const char *) _ptr
;
1485 union side_bool_value value
;
1487 switch (bool_size_bytes
) {
1496 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_bool
.offset
);
1497 memcpy(&value
, ptr
, bool_size_bytes
);
1498 tracer_print_type_bool(":", &type_gather
->u
.side_bool
.type
, &value
,
1499 type_gather
->u
.side_bool
.offset_bits
);
1500 return tracer_gather_size(access_mode
, bool_size_bytes
);
1504 uint32_t tracer_print_gather_byte_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1506 enum side_type_gather_access_mode access_mode
=
1507 (enum side_type_gather_access_mode
) type_gather
->u
.side_byte
.access_mode
;
1508 const char *ptr
= (const char *) _ptr
;
1511 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_byte
.offset
);
1512 memcpy(&value
, ptr
, 1);
1513 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_byte
.type
.attr
),
1514 type_gather
->u
.side_byte
.type
.nr_attr
);
1515 printf("0x%" PRIx8
, value
);
1516 return tracer_gather_size(access_mode
, 1);
1520 uint32_t tracer_print_gather_integer_type(const struct side_type_gather
*type_gather
, const void *_ptr
,
1521 enum tracer_display_base default_base
)
1523 enum side_type_gather_access_mode access_mode
=
1524 (enum side_type_gather_access_mode
) type_gather
->u
.side_integer
.access_mode
;
1525 uint32_t integer_size_bytes
= type_gather
->u
.side_integer
.type
.integer_size
;
1526 const char *ptr
= (const char *) _ptr
;
1527 union side_integer_value value
;
1529 switch (integer_size_bytes
) {
1539 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_integer
.offset
);
1540 memcpy(&value
, ptr
, integer_size_bytes
);
1541 tracer_print_type_integer(":", &type_gather
->u
.side_integer
.type
, &value
,
1542 type_gather
->u
.side_integer
.offset_bits
, default_base
);
1543 return tracer_gather_size(access_mode
, integer_size_bytes
);
1547 uint32_t tracer_print_gather_float_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1549 enum side_type_gather_access_mode access_mode
=
1550 (enum side_type_gather_access_mode
) type_gather
->u
.side_float
.access_mode
;
1551 uint32_t float_size_bytes
= type_gather
->u
.side_float
.type
.float_size
;
1552 const char *ptr
= (const char *) _ptr
;
1553 union side_float_value value
;
1555 switch (float_size_bytes
) {
1564 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_float
.offset
);
1565 memcpy(&value
, ptr
, float_size_bytes
);
1566 tracer_print_type_float(":", &type_gather
->u
.side_float
.type
, &value
);
1567 return tracer_gather_size(access_mode
, float_size_bytes
);
1571 uint32_t tracer_print_gather_string_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1573 enum side_type_gather_access_mode access_mode
=
1574 (enum side_type_gather_access_mode
) type_gather
->u
.side_string
.access_mode
;
1575 const char *ptr
= (const char *) _ptr
;
1578 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_string
.offset
);
1579 tracer_print_type_header(":", side_ptr_get(type_gather
->u
.side_string
.type
.attr
),
1580 type_gather
->u
.side_string
.type
.nr_attr
);
1582 tracer_print_string(ptr
, type_gather
->u
.side_string
.type
.unit_size
,
1583 side_enum_get(type_gather
->u
.side_string
.type
.byte_order
), &string_len
);
1586 string_len
= type_gather
->u
.side_string
.type
.unit_size
;
1588 return tracer_gather_size(access_mode
, string_len
);
1592 uint32_t tracer_print_gather_type(const struct side_type
*type_desc
, const void *ptr
)
1597 switch (side_enum_get(type_desc
->type
)) {
1598 /* Gather basic types */
1599 case SIDE_TYPE_GATHER_BOOL
:
1600 len
= tracer_print_gather_bool_type(&type_desc
->u
.side_gather
, ptr
);
1602 case SIDE_TYPE_GATHER_INTEGER
:
1603 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1604 TRACER_DISPLAY_BASE_10
);
1606 case SIDE_TYPE_GATHER_BYTE
:
1607 len
= tracer_print_gather_byte_type(&type_desc
->u
.side_gather
, ptr
);
1609 case SIDE_TYPE_GATHER_POINTER
:
1610 len
= tracer_print_gather_integer_type(&type_desc
->u
.side_gather
, ptr
,
1611 TRACER_DISPLAY_BASE_16
);
1613 case SIDE_TYPE_GATHER_FLOAT
:
1614 len
= tracer_print_gather_float_type(&type_desc
->u
.side_gather
, ptr
);
1616 case SIDE_TYPE_GATHER_STRING
:
1617 len
= tracer_print_gather_string_type(&type_desc
->u
.side_gather
, ptr
);
1620 /* Gather enum types */
1621 case SIDE_TYPE_GATHER_ENUM
:
1622 len
= tracer_print_gather_enum_type(&type_desc
->u
.side_gather
, ptr
);
1625 /* Gather compound types */
1626 case SIDE_TYPE_GATHER_STRUCT
:
1627 len
= tracer_print_gather_struct(&type_desc
->u
.side_gather
, ptr
);
1629 case SIDE_TYPE_GATHER_ARRAY
:
1630 len
= tracer_print_gather_array(&type_desc
->u
.side_gather
, ptr
);
1632 case SIDE_TYPE_GATHER_VLA
:
1633 len
= tracer_print_gather_vla(&type_desc
->u
.side_gather
, ptr
, ptr
);
1636 fprintf(stderr
, "<UNKNOWN GATHER TYPE>");
1644 uint32_t tracer_print_gather_enum_type(const struct side_type_gather
*type_gather
, const void *_ptr
)
1646 const struct side_enum_mappings
*mappings
= side_ptr_get(type_gather
->u
.side_enum
.mappings
);
1647 const struct side_type
*enum_elem_type
= side_ptr_get(type_gather
->u
.side_enum
.elem_type
);
1648 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1649 enum side_type_gather_access_mode access_mode
=
1650 (enum side_type_gather_access_mode
) side_integer
->access_mode
;
1651 uint32_t integer_size_bytes
= side_integer
->type
.integer_size
;
1652 const char *ptr
= (const char *) _ptr
;
1653 union side_integer_value value
;
1656 switch (integer_size_bytes
) {
1666 ptr
= tracer_gather_access(access_mode
, ptr
+ side_integer
->offset
);
1667 memcpy(&value
, ptr
, integer_size_bytes
);
1668 v
= tracer_load_gather_integer_value(side_integer
, &value
);
1669 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1670 printf("%s", mappings
->nr_attr
? ", " : "");
1671 tracer_print_gather_type(enum_elem_type
, ptr
);
1672 print_enum_labels(mappings
, v
);
1673 return tracer_gather_size(access_mode
, integer_size_bytes
);
1677 void tracer_print_gather_field(const struct side_event_field
*field
, const void *ptr
)
1679 printf("%s: ", side_ptr_get(field
->field_name
));
1680 (void) tracer_print_gather_type(&field
->side_type
, ptr
);
1684 uint32_t tracer_print_gather_struct(const struct side_type_gather
*type_gather
, const void *_ptr
)
1686 enum side_type_gather_access_mode access_mode
=
1687 (enum side_type_gather_access_mode
) type_gather
->u
.side_struct
.access_mode
;
1688 const struct side_type_struct
*side_struct
= side_ptr_get(type_gather
->u
.side_struct
.type
);
1689 const char *ptr
= (const char *) _ptr
;
1692 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_struct
.offset
);
1693 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1694 printf("%s", side_struct
->nr_attr
? ", " : "");
1695 printf("fields: { ");
1696 for (i
= 0; i
< side_struct
->nr_fields
; i
++) {
1697 printf("%s", i
? ", " : "");
1698 tracer_print_gather_field(&side_ptr_get(side_struct
->fields
)[i
], ptr
);
1701 return tracer_gather_size(access_mode
, type_gather
->u
.side_struct
.size
);
1705 uint32_t tracer_print_gather_array(const struct side_type_gather
*type_gather
, const void *_ptr
)
1707 enum side_type_gather_access_mode access_mode
=
1708 (enum side_type_gather_access_mode
) type_gather
->u
.side_array
.access_mode
;
1709 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1712 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_array
.offset
);
1714 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_array
.type
.attr
), type_gather
->u
.side_array
.type
.nr_attr
);
1715 printf("%s", type_gather
->u
.side_array
.type
.nr_attr
? ", " : "");
1716 printf("elements: ");
1718 for (i
= 0; i
< type_gather
->u
.side_array
.type
.length
; i
++) {
1719 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_array
.type
.elem_type
);
1721 switch (side_enum_get(elem_type
->type
)) {
1722 case SIDE_TYPE_GATHER_VLA
:
1723 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1728 printf("%s", i
? ", " : "");
1729 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1732 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1736 uint32_t tracer_print_gather_vla(const struct side_type_gather
*type_gather
, const void *_ptr
,
1737 const void *_length_ptr
)
1739 enum side_type_gather_access_mode access_mode
=
1740 (enum side_type_gather_access_mode
) type_gather
->u
.side_vla
.access_mode
;
1741 const struct side_type
*length_type
= side_ptr_get(type_gather
->u
.side_vla
.length_type
);
1742 const char *ptr
= (const char *) _ptr
, *orig_ptr
;
1743 const char *length_ptr
= (const char *) _length_ptr
;
1744 union int_value v
= {};
1748 switch (side_enum_get(length_type
->type
)) {
1749 case SIDE_TYPE_GATHER_INTEGER
:
1752 fprintf(stderr
, "<gather VLA expects integer gather length type>\n");
1755 v
= tracer_load_gather_integer_value(&length_type
->u
.side_gather
.u
.side_integer
,
1757 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] || v
.u
[SIDE_INTEGER128_SPLIT_LOW
] > UINT32_MAX
) {
1758 fprintf(stderr
, "Unexpected vla length value\n");
1761 length
= (uint32_t) v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
1762 ptr
= tracer_gather_access(access_mode
, ptr
+ type_gather
->u
.side_vla
.offset
);
1764 print_attributes("attr", ":", side_ptr_get(type_gather
->u
.side_vla
.type
.attr
), type_gather
->u
.side_vla
.type
.nr_attr
);
1765 printf("%s", type_gather
->u
.side_vla
.type
.nr_attr
? ", " : "");
1766 printf("elements: ");
1768 for (i
= 0; i
< length
; i
++) {
1769 const struct side_type
*elem_type
= side_ptr_get(type_gather
->u
.side_vla
.type
.elem_type
);
1771 switch (side_enum_get(elem_type
->type
)) {
1772 case SIDE_TYPE_GATHER_VLA
:
1773 fprintf(stderr
, "<gather VLA only supported within gather structures>\n");
1778 printf("%s", i
? ", " : "");
1779 ptr
+= tracer_print_gather_type(elem_type
, ptr
);
1782 return tracer_gather_size(access_mode
, ptr
- orig_ptr
);
1785 struct tracer_visitor_priv
{
1786 const struct side_type
*elem_type
;
1791 enum side_visitor_status
tracer_write_elem_cb(const struct side_tracer_visitor_ctx
*tracer_ctx
,
1792 const struct side_arg
*elem
)
1794 struct tracer_visitor_priv
*tracer_priv
= (struct tracer_visitor_priv
*) tracer_ctx
->priv
;
1796 printf("%s", tracer_priv
->i
++ ? ", " : "");
1797 tracer_print_type(tracer_priv
->elem_type
, elem
);
1798 return SIDE_VISITOR_STATUS_OK
;
1802 void tracer_print_vla_visitor(const struct side_type
*type_desc
, struct side_arg_vla_visitor
*vla_visitor
)
1805 enum side_visitor_status status
;
1806 struct tracer_visitor_priv tracer_priv
= {
1807 .elem_type
= side_ptr_get(type_desc
->u
.side_vla_visitor
.elem_type
),
1810 const struct side_tracer_visitor_ctx tracer_ctx
= {
1811 .write_elem
= tracer_write_elem_cb
,
1812 .priv
= &tracer_priv
,
1814 side_visitor_func func
;
1818 app_ctx
= side_ptr_get(vla_visitor
->app_ctx
);
1819 print_attributes("attr", ":", side_ptr_get(type_desc
->u
.side_vla_visitor
.attr
), type_desc
->u
.side_vla_visitor
.nr_attr
);
1820 printf("%s", type_desc
->u
.side_vla_visitor
.nr_attr
? ", " : "");
1821 printf("elements: ");
1823 func
= side_ptr_get(type_desc
->u
.side_vla_visitor
.visitor
);
1824 status
= func(&tracer_ctx
, app_ctx
);
1826 case SIDE_VISITOR_STATUS_OK
:
1828 case SIDE_VISITOR_STATUS_ERROR
:
1829 fprintf(stderr
, "ERROR: Visitor error\n");
1836 void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct
*dynamic_struct
)
1838 const struct side_arg_dynamic_field
*fields
= side_ptr_get(dynamic_struct
->fields
);
1839 uint32_t i
, len
= dynamic_struct
->len
;
1841 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1842 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1843 printf("fields:: ");
1845 for (i
= 0; i
< len
; i
++) {
1846 printf("%s", i
? ", " : "");
1847 printf("%s:: ", side_ptr_get(fields
[i
].field_name
));
1848 tracer_print_dynamic(&fields
[i
].elem
, true);
1853 struct tracer_dynamic_struct_visitor_priv
{
1858 enum side_visitor_status
tracer_dynamic_struct_write_elem_cb(
1859 const struct side_tracer_dynamic_struct_visitor_ctx
*tracer_ctx
,
1860 const struct side_arg_dynamic_field
*dynamic_field
)
1862 struct tracer_dynamic_struct_visitor_priv
*tracer_priv
=
1863 (struct tracer_dynamic_struct_visitor_priv
*) tracer_ctx
->priv
;
1865 printf("%s", tracer_priv
->i
++ ? ", " : "");
1866 printf("%s:: ", side_ptr_get(dynamic_field
->field_name
));
1867 tracer_print_dynamic(&dynamic_field
->elem
, true);
1868 return SIDE_VISITOR_STATUS_OK
;
1872 void tracer_print_dynamic_struct_visitor(const struct side_arg
*item
)
1874 struct side_arg_dynamic_struct_visitor
*dynamic_struct_visitor
;
1875 struct tracer_dynamic_struct_visitor_priv tracer_priv
= {
1878 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx
= {
1879 .write_field
= tracer_dynamic_struct_write_elem_cb
,
1880 .priv
= &tracer_priv
,
1882 enum side_visitor_status status
;
1885 dynamic_struct_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
);
1886 if (!dynamic_struct_visitor
)
1888 app_ctx
= side_ptr_get(dynamic_struct_visitor
->app_ctx
);
1889 print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor
->attr
), dynamic_struct_visitor
->nr_attr
);
1890 printf("%s", dynamic_struct_visitor
->nr_attr
? ", " : "");
1891 printf("fields:: ");
1893 status
= side_ptr_get(dynamic_struct_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1895 case SIDE_VISITOR_STATUS_OK
:
1897 case SIDE_VISITOR_STATUS_ERROR
:
1898 fprintf(stderr
, "ERROR: Visitor error\n");
1905 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla
*vla
)
1907 const struct side_arg
*sav
= side_ptr_get(vla
->sav
);
1908 uint32_t i
, side_sav_len
= vla
->len
;
1910 print_attributes("attr", "::", side_ptr_get(vla
->attr
), vla
->nr_attr
);
1911 printf("%s", vla
->nr_attr
? ", " : "");
1912 printf("elements:: ");
1914 for (i
= 0; i
< side_sav_len
; i
++) {
1915 printf("%s", i
? ", " : "");
1916 tracer_print_dynamic(&sav
[i
], true);
1921 struct tracer_dynamic_vla_visitor_priv
{
1926 enum side_visitor_status
tracer_dynamic_vla_write_elem_cb(
1927 const struct side_tracer_visitor_ctx
*tracer_ctx
,
1928 const struct side_arg
*elem
)
1930 struct tracer_dynamic_vla_visitor_priv
*tracer_priv
=
1931 (struct tracer_dynamic_vla_visitor_priv
*) tracer_ctx
->priv
;
1933 printf("%s", tracer_priv
->i
++ ? ", " : "");
1934 tracer_print_dynamic(elem
, true);
1935 return SIDE_VISITOR_STATUS_OK
;
1939 void tracer_print_dynamic_vla_visitor(const struct side_arg
*item
)
1941 struct side_arg_dynamic_vla_visitor
*dynamic_vla_visitor
;
1942 struct tracer_dynamic_vla_visitor_priv tracer_priv
= {
1945 const struct side_tracer_visitor_ctx tracer_ctx
= {
1946 .write_elem
= tracer_dynamic_vla_write_elem_cb
,
1947 .priv
= &tracer_priv
,
1949 enum side_visitor_status status
;
1952 dynamic_vla_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
);
1953 if (!dynamic_vla_visitor
)
1955 app_ctx
= side_ptr_get(dynamic_vla_visitor
->app_ctx
);
1956 print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor
->attr
), dynamic_vla_visitor
->nr_attr
);
1957 printf("%s", dynamic_vla_visitor
->nr_attr
? ", " : "");
1958 printf("elements:: ");
1960 status
= side_ptr_get(dynamic_vla_visitor
->visitor
)(&tracer_ctx
, app_ctx
);
1962 case SIDE_VISITOR_STATUS_OK
:
1964 case SIDE_VISITOR_STATUS_ERROR
:
1965 fprintf(stderr
, "ERROR: Visitor error\n");
1972 void tracer_print_dynamic(const struct side_arg
*item
, bool print_brackets
)
1976 switch (side_enum_get(item
->type
)) {
1977 /* Dynamic basic types */
1978 case SIDE_TYPE_DYNAMIC_NULL
:
1979 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1980 item
->u
.side_dynamic
.side_null
.nr_attr
);
1981 printf("<NULL TYPE>");
1983 case SIDE_TYPE_DYNAMIC_BOOL
:
1984 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1986 case SIDE_TYPE_DYNAMIC_INTEGER
:
1987 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1988 TRACER_DISPLAY_BASE_10
);
1990 case SIDE_TYPE_DYNAMIC_BYTE
:
1991 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1992 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1994 case SIDE_TYPE_DYNAMIC_POINTER
:
1995 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1996 TRACER_DISPLAY_BASE_16
);
1998 case SIDE_TYPE_DYNAMIC_FLOAT
:
1999 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
2000 &item
->u
.side_dynamic
.side_float
.value
);
2002 case SIDE_TYPE_DYNAMIC_STRING
:
2003 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
2004 tracer_print_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
2005 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
2006 side_enum_get(item
->u
.side_dynamic
.side_string
.type
.byte_order
), NULL
);
2009 /* Dynamic compound types */
2010 case SIDE_TYPE_DYNAMIC_STRUCT
:
2011 tracer_print_dynamic_struct(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct
));
2013 case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
:
2014 tracer_print_dynamic_struct_visitor(item
);
2016 case SIDE_TYPE_DYNAMIC_VLA
:
2017 tracer_print_dynamic_vla(side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla
));
2019 case SIDE_TYPE_DYNAMIC_VLA_VISITOR
:
2020 tracer_print_dynamic_vla_visitor(item
);
2023 fprintf(stderr
, "<UNKNOWN TYPE>\n");
2031 void tracer_print_static_fields(const struct side_event_description
*desc
,
2032 const struct side_arg_vec
*side_arg_vec
,
2033 uint32_t *nr_items
, void *caller_addr
)
2035 const struct side_arg
*sav
= side_ptr_get(side_arg_vec
->sav
);
2036 uint32_t i
, side_sav_len
= side_arg_vec
->len
;
2039 printf("caller: [%p] ", caller_addr
);
2040 printf("provider: %s, event: %s",
2041 side_ptr_get(desc
->provider_name
),
2042 side_ptr_get(desc
->event_name
));
2043 if (desc
->nr_fields
!= side_sav_len
) {
2044 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
2047 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
2048 printf("%s", side_sav_len
? ", fields: [ " : "");
2049 for (i
= 0; i
< side_sav_len
; i
++) {
2050 printf("%s", i
? ", " : "");
2051 tracer_print_field(&side_ptr_get(desc
->fields
)[i
], &sav
[i
]);
2060 void tracer_call(const struct side_event_description
*desc
,
2061 const struct side_arg_vec
*side_arg_vec
,
2062 void *priv
__attribute__((unused
)),
2065 uint32_t nr_fields
= 0;
2067 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2072 void tracer_call_variadic(const struct side_event_description
*desc
,
2073 const struct side_arg_vec
*side_arg_vec
,
2074 const struct side_arg_dynamic_struct
*var_struct
,
2075 void *priv
__attribute__((unused
)),
2078 uint32_t nr_fields
= 0, i
, var_struct_len
= var_struct
->len
;
2080 tracer_print_static_fields(desc
, side_arg_vec
, &nr_fields
, caller_addr
);
2082 if (side_unlikely(!(desc
->flags
& SIDE_EVENT_FLAG_VARIADIC
))) {
2083 fprintf(stderr
, "ERROR: unexpected non-variadic event description\n");
2086 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
2087 printf("%s", var_struct_len
? ", fields:: [ " : "");
2088 for (i
= 0; i
< var_struct_len
; i
++, nr_fields
++) {
2089 printf("%s", i
? ", " : "");
2090 printf("%s:: ", side_ptr_get(side_ptr_get(var_struct
->fields
)[i
].field_name
));
2091 tracer_print_dynamic(&side_ptr_get(var_struct
->fields
)[i
].elem
, true);
2099 void tracer_event_notification(enum side_tracer_notification notif
,
2100 struct side_event_description
**events
, uint32_t nr_events
,
2101 void *priv
__attribute__((unused
)))
2106 printf("----------------------------------------------------------\n");
2107 printf("Tracer notified of events %s\n",
2108 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
2109 for (i
= 0; i
< nr_events
; i
++) {
2110 struct side_event_description
*event
= events
[i
];
2112 /* Skip NULL pointers */
2115 if (event
->version
!= SIDE_EVENT_DESCRIPTION_ABI_VERSION
) {
2116 printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n",
2117 event
->version
, SIDE_EVENT_DESCRIPTION_ABI_VERSION
);
2120 printf("provider: %s, event: %s\n",
2121 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2122 if (event
->struct_size
!= side_offsetofend(struct side_event_description
, side_event_description_orig_abi_last
)) {
2123 printf("Warning: Event %s.%s description contains fields unknown to the tracer\n",
2124 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
2126 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
2127 if (event
->nr_side_type_label
> _NR_SIDE_TYPE_LABEL
) {
2128 printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
2129 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2130 event
->nr_side_type_label
- _NR_SIDE_TYPE_LABEL
);
2132 if (event
->nr_side_attr_type
> _NR_SIDE_ATTR_TYPE
) {
2133 printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n",
2134 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
2135 event
->nr_side_attr_type
- _NR_SIDE_ATTR_TYPE
);
2137 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2138 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
, tracer_key
);
2142 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
, tracer_key
);
2147 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
2148 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
, tracer_key
);
2152 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
, tracer_key
);
2158 printf("----------------------------------------------------------\n");
2161 static __attribute__((constructor
))
2162 void tracer_init(void);
2164 void tracer_init(void)
2166 if (side_tracer_request_key(&tracer_key
))
2168 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
2173 static __attribute__((destructor
))
2174 void tracer_exit(void);
2176 void tracer_exit(void)
2178 side_tracer_event_notification_unregister(tracer_handle
);