1 // SPDX-License-Identifier: MIT
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 #include <side/trace.h>
16 #include "visit-arg-vec.h"
18 /* TODO: optionally print caller address. */
19 static bool print_caller
= false;
21 #define MAX_NESTING 32
23 enum tracer_display_base
{
24 TRACER_DISPLAY_BASE_2
,
25 TRACER_DISPLAY_BASE_8
,
26 TRACER_DISPLAY_BASE_10
,
27 TRACER_DISPLAY_BASE_16
,
31 uint64_t u
[NR_SIDE_INTEGER128_SPLIT
];
32 int64_t s
[NR_SIDE_INTEGER128_SPLIT
];
36 int nesting
; /* Keep track of nesting, useful for tabulations. */
37 int item_nr
[MAX_NESTING
]; /* Item number in current nesting level, useful for comma-separated lists. */
40 static struct side_tracer_handle
*tracer_handle
;
42 static uint64_t tracer_key
;
45 void tracer_convert_string_to_utf8(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
46 size_t *strlen_with_null
,
49 size_t ret
, inbytesleft
= 0, outbytesleft
, bufsize
, input_size
;
50 const char *str
= p
, *fromcode
;
51 char *inbuf
= (char *) p
, *outbuf
, *buf
;
57 *strlen_with_null
= strlen(str
) + 1;
58 *output_str
= (char *) str
;
62 const uint16_t *p16
= p
;
65 case SIDE_TYPE_BYTE_ORDER_LE
:
67 fromcode
= "UTF-16LE";
70 case SIDE_TYPE_BYTE_ORDER_BE
:
72 fromcode
= "UTF-16BE";
76 fprintf(stderr
, "Unknown byte order\n");
81 input_size
= inbytesleft
+ 2;
83 * Worse case is U+FFFF UTF-16 (2 bytes) converting to
84 * { ef, bf, bf } UTF-8 (3 bytes).
86 bufsize
= inbytesleft
/ 2 * 3 + 1;
91 const uint32_t *p32
= p
;
94 case SIDE_TYPE_BYTE_ORDER_LE
:
96 fromcode
= "UTF-32LE";
99 case SIDE_TYPE_BYTE_ORDER_BE
:
101 fromcode
= "UTF-32BE";
105 fprintf(stderr
, "Unknown byte order\n");
110 input_size
= inbytesleft
+ 4;
112 * Each 4-byte UTF-32 character converts to at most a
113 * 4-byte UTF-8 character.
115 bufsize
= inbytesleft
+ 1;
119 fprintf(stderr
, "Unknown string unit size %" PRIu8
"\n", unit_size
);
123 cd
= iconv_open("UTF8", fromcode
);
124 if (cd
== (iconv_t
) -1) {
125 perror("iconv_open");
128 buf
= malloc(bufsize
);
132 outbuf
= (char *) buf
;
133 outbytesleft
= bufsize
;
134 ret
= iconv(cd
, &inbuf
, &inbytesleft
, &outbuf
, &outbytesleft
);
135 if (ret
== (size_t) -1) {
140 fprintf(stderr
, "Buffer too small to convert string input\n");
144 if (iconv_close(cd
) == -1) {
145 perror("iconv_close");
148 if (strlen_with_null
)
149 *strlen_with_null
= input_size
;
154 void tracer_print_type_string(const void *p
, uint8_t unit_size
, enum side_type_label_byte_order byte_order
,
155 size_t *strlen_with_null
)
157 char *output_str
= NULL
;
159 tracer_convert_string_to_utf8(p
, unit_size
, byte_order
, strlen_with_null
, &output_str
);
160 printf("\"%s\"", output_str
);
166 void side_check_value_u64(union int_value v
)
168 if (v
.u
[SIDE_INTEGER128_SPLIT_HIGH
]) {
169 fprintf(stderr
, "Unexpected integer value\n");
175 void side_check_value_s64(union int_value v
)
177 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63)) {
178 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] != ~0LL) {
179 fprintf(stderr
, "Unexpected integer value\n");
183 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
]) {
184 fprintf(stderr
, "Unexpected integer value\n");
191 int64_t get_attr_integer64_value(const struct side_attr
*attr
)
195 switch (side_enum_get(attr
->value
.type
)) {
196 case SIDE_ATTR_TYPE_U8
:
197 val
= attr
->value
.u
.integer_value
.side_u8
;
199 case SIDE_ATTR_TYPE_U16
:
200 val
= attr
->value
.u
.integer_value
.side_u16
;
202 case SIDE_ATTR_TYPE_U32
:
203 val
= attr
->value
.u
.integer_value
.side_u32
;
205 case SIDE_ATTR_TYPE_U64
:
206 val
= attr
->value
.u
.integer_value
.side_u64
;
208 case SIDE_ATTR_TYPE_U128
:
210 union int_value v
= {
212 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
],
213 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
216 side_check_value_u64(v
);
217 val
= v
.u
[SIDE_INTEGER128_SPLIT_LOW
];
220 case SIDE_ATTR_TYPE_S8
:
221 val
= attr
->value
.u
.integer_value
.side_s8
;
223 case SIDE_ATTR_TYPE_S16
:
224 val
= attr
->value
.u
.integer_value
.side_s16
;
226 case SIDE_ATTR_TYPE_S32
:
227 val
= attr
->value
.u
.integer_value
.side_s32
;
229 case SIDE_ATTR_TYPE_S64
:
230 val
= attr
->value
.u
.integer_value
.side_s64
;
232 case SIDE_ATTR_TYPE_S128
:
234 union int_value v
= {
236 [SIDE_INTEGER128_SPLIT_LOW
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
],
237 [SIDE_INTEGER128_SPLIT_HIGH
] = attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
240 side_check_value_s64(v
);
241 val
= v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
245 fprintf(stderr
, "Unexpected attribute type\n");
252 enum tracer_display_base
get_attr_display_base(const struct side_attr
*_attr
, uint32_t nr_attr
,
253 enum tracer_display_base default_base
)
257 for (i
= 0; i
< nr_attr
; i
++) {
258 const struct side_attr
*attr
= &_attr
[i
];
259 char *utf8_str
= NULL
;
262 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
263 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
264 cmp
= strcmp(utf8_str
, "std.integer.base");
265 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
268 int64_t val
= get_attr_integer64_value(attr
);
272 return TRACER_DISPLAY_BASE_2
;
274 return TRACER_DISPLAY_BASE_8
;
276 return TRACER_DISPLAY_BASE_10
;
278 return TRACER_DISPLAY_BASE_16
;
280 fprintf(stderr
, "Unexpected integer display base: %" PRId64
"\n", val
);
285 return default_base
; /* Default */
289 void tracer_print_attr_type(const char *separator
, const struct side_attr
*attr
)
291 char *utf8_str
= NULL
;
293 tracer_convert_string_to_utf8(side_ptr_get(attr
->key
.p
), attr
->key
.unit_size
,
294 side_enum_get(attr
->key
.byte_order
), NULL
, &utf8_str
);
295 printf("{ key%s \"%s\", value%s ", separator
, utf8_str
, separator
);
296 if (utf8_str
!= side_ptr_get(attr
->key
.p
))
298 switch (side_enum_get(attr
->value
.type
)) {
299 case SIDE_ATTR_TYPE_BOOL
:
300 printf("%s", attr
->value
.u
.bool_value
? "true" : "false");
302 case SIDE_ATTR_TYPE_U8
:
303 printf("%" PRIu8
, attr
->value
.u
.integer_value
.side_u8
);
305 case SIDE_ATTR_TYPE_U16
:
306 printf("%" PRIu16
, attr
->value
.u
.integer_value
.side_u16
);
308 case SIDE_ATTR_TYPE_U32
:
309 printf("%" PRIu32
, attr
->value
.u
.integer_value
.side_u32
);
311 case SIDE_ATTR_TYPE_U64
:
312 printf("%" PRIu64
, attr
->value
.u
.integer_value
.side_u64
);
314 case SIDE_ATTR_TYPE_U128
:
315 if (attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
316 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
318 printf("0x%" PRIx64
"%016" PRIx64
,
319 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
320 attr
->value
.u
.integer_value
.side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
323 case SIDE_ATTR_TYPE_S8
:
324 printf("%" PRId8
, attr
->value
.u
.integer_value
.side_s8
);
326 case SIDE_ATTR_TYPE_S16
:
327 printf("%" PRId16
, attr
->value
.u
.integer_value
.side_s16
);
329 case SIDE_ATTR_TYPE_S32
:
330 printf("%" PRId32
, attr
->value
.u
.integer_value
.side_s32
);
332 case SIDE_ATTR_TYPE_S64
:
333 printf("%" PRId64
, attr
->value
.u
.integer_value
.side_s64
);
335 case SIDE_ATTR_TYPE_S128
:
336 if (attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
337 printf("0x%" PRIx64
, attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
339 printf("0x%" PRIx64
"%016" PRIx64
,
340 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
],
341 attr
->value
.u
.integer_value
.side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
]);
344 case SIDE_ATTR_TYPE_FLOAT_BINARY16
:
346 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary16
);
349 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
352 case SIDE_ATTR_TYPE_FLOAT_BINARY32
:
354 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary32
);
357 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
360 case SIDE_ATTR_TYPE_FLOAT_BINARY64
:
362 printf("%g", (double) attr
->value
.u
.float_value
.side_float_binary64
);
365 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
368 case SIDE_ATTR_TYPE_FLOAT_BINARY128
:
370 printf("%Lg", (long double) attr
->value
.u
.float_value
.side_float_binary128
);
373 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
376 case SIDE_ATTR_TYPE_STRING
:
377 tracer_print_type_string(side_ptr_get(attr
->value
.u
.string_value
.p
),
378 attr
->value
.u
.string_value
.unit_size
,
379 side_enum_get(attr
->value
.u
.string_value
.byte_order
), NULL
);
382 fprintf(stderr
, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
389 void print_attributes(const char *prefix_str
, const char *separator
,
390 const struct side_attr
*attr
, uint32_t nr_attr
)
396 printf("%s%s [", prefix_str
, separator
);
397 for (i
= 0; i
< nr_attr
; i
++) {
398 printf("%s", i
? ", " : " ");
399 tracer_print_attr_type(separator
, &attr
[i
]);
405 union int_value
tracer_load_integer_value(const struct side_type_integer
*type_integer
,
406 const union side_integer_value
*value
,
407 uint16_t offset_bits
, uint16_t *_len_bits
)
409 union int_value v
= {};
413 if (!type_integer
->len_bits
)
414 len_bits
= type_integer
->integer_size
* CHAR_BIT
;
416 len_bits
= type_integer
->len_bits
;
417 if (len_bits
+ offset_bits
> type_integer
->integer_size
* CHAR_BIT
)
419 reverse_bo
= side_enum_get(type_integer
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
420 switch (type_integer
->integer_size
) {
422 if (type_integer
->signedness
)
423 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s8
;
425 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u8
;
428 if (type_integer
->signedness
) {
431 side_s16
= value
->side_s16
;
433 side_s16
= side_bswap_16(side_s16
);
434 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s16
;
438 side_u16
= value
->side_u16
;
440 side_u16
= side_bswap_16(side_u16
);
441 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u16
;
445 if (type_integer
->signedness
) {
448 side_s32
= value
->side_s32
;
450 side_s32
= side_bswap_32(side_s32
);
451 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s32
;
455 side_u32
= value
->side_u32
;
457 side_u32
= side_bswap_32(side_u32
);
458 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u32
;
462 if (type_integer
->signedness
) {
465 side_s64
= value
->side_s64
;
467 side_s64
= side_bswap_64(side_s64
);
468 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
;
472 side_u64
= value
->side_u64
;
474 side_u64
= side_bswap_64(side_u64
);
475 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
;
479 if (type_integer
->signedness
) {
480 int64_t side_s64
[NR_SIDE_INTEGER128_SPLIT
];
482 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_LOW
];
483 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_s128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
485 side_s64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_LOW
]);
486 side_s64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_s64
[SIDE_INTEGER128_SPLIT_HIGH
]);
487 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
488 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
490 v
.s
[SIDE_INTEGER128_SPLIT_LOW
] = side_s64
[SIDE_INTEGER128_SPLIT_LOW
];
491 v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] = side_s64
[SIDE_INTEGER128_SPLIT_HIGH
];
494 uint64_t side_u64
[NR_SIDE_INTEGER128_SPLIT
];
496 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_LOW
];
497 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = value
->side_u128_split
[SIDE_INTEGER128_SPLIT_HIGH
];
499 side_u64
[SIDE_INTEGER128_SPLIT_LOW
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_LOW
]);
500 side_u64
[SIDE_INTEGER128_SPLIT_HIGH
] = side_bswap_64(side_u64
[SIDE_INTEGER128_SPLIT_HIGH
]);
501 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
502 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
504 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = side_u64
[SIDE_INTEGER128_SPLIT_LOW
];
505 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = side_u64
[SIDE_INTEGER128_SPLIT_HIGH
];
512 if (type_integer
->integer_size
<= 8) {
513 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >>= offset_bits
;
515 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
516 if (type_integer
->signedness
) {
518 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (len_bits
- 1))) {
519 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] |= ~((1ULL << len_bits
) - 1);
520 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = ~0ULL;
525 //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits
526 if (len_bits
< 128 || offset_bits
!= 0)
530 *_len_bits
= len_bits
;
535 void print_enum_labels(const struct side_enum_mappings
*mappings
, union int_value v
)
537 uint32_t i
, print_count
= 0;
539 side_check_value_s64(v
);
540 printf(", labels: [ ");
541 for (i
= 0; i
< mappings
->nr_mappings
; i
++) {
542 const struct side_enum_mapping
*mapping
= &side_ptr_get(mappings
->mappings
)[i
];
544 if (mapping
->range_end
< mapping
->range_begin
) {
545 fprintf(stderr
, "ERROR: Unexpected enum range: %" PRIu64
"-%" PRIu64
"\n",
546 mapping
->range_begin
, mapping
->range_end
);
549 if (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] >= mapping
->range_begin
&& v
.s
[SIDE_INTEGER128_SPLIT_LOW
] <= mapping
->range_end
) {
550 printf("%s", print_count
++ ? ", " : "");
551 tracer_print_type_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
552 side_enum_get(mapping
->label
.byte_order
), NULL
);
556 printf("<NO LABEL>");
561 uint32_t elem_type_to_stride(const struct side_type
*elem_type
)
565 switch (side_enum_get(elem_type
->type
)) {
580 return elem_type
->u
.side_integer
.integer_size
* CHAR_BIT
;
582 fprintf(stderr
, "ERROR: Unexpected enum bitmap element type\n");
589 void print_integer_binary(uint64_t v
[NR_SIDE_INTEGER128_SPLIT
], int bits
)
596 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 64 - bits
;
597 for (bit
= 0; bit
< bits
; bit
++) {
598 printf("%c", v
[SIDE_INTEGER128_SPLIT_HIGH
] & (1ULL << 63) ? '1' : '0');
599 v
[SIDE_INTEGER128_SPLIT_HIGH
] <<= 1;
603 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 64 - bits
;
604 for (bit
= 0; bit
< bits
; bit
++) {
605 printf("%c", v
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << 63) ? '1' : '0');
606 v
[SIDE_INTEGER128_SPLIT_LOW
] <<= 1;
611 void tracer_print_type_header(const char *separator
,
612 const struct side_attr
*attr
, uint32_t nr_attr
)
614 print_attributes("attr", separator
, attr
, nr_attr
);
615 printf("%s", nr_attr
? ", " : "");
616 printf("value%s ", separator
);
620 void tracer_print_type_bool(const char *separator
,
621 const struct side_type_bool
*type_bool
,
622 const union side_bool_value
*value
,
623 uint16_t offset_bits
)
629 if (!type_bool
->len_bits
)
630 len_bits
= type_bool
->bool_size
* CHAR_BIT
;
632 len_bits
= type_bool
->len_bits
;
633 if (len_bits
+ offset_bits
> type_bool
->bool_size
* CHAR_BIT
)
635 reverse_bo
= side_enum_get(type_bool
->byte_order
) != SIDE_TYPE_BYTE_ORDER_HOST
;
636 switch (type_bool
->bool_size
) {
638 v
= value
->side_bool8
;
644 side_u16
= value
->side_bool16
;
646 side_u16
= side_bswap_16(side_u16
);
654 side_u32
= value
->side_bool32
;
656 side_u32
= side_bswap_32(side_u32
);
664 side_u64
= value
->side_bool64
;
666 side_u64
= side_bswap_64(side_u64
);
675 v
&= (1ULL << len_bits
) - 1;
676 tracer_print_type_header(separator
, side_ptr_get(type_bool
->attr
), type_bool
->nr_attr
);
677 printf("%s", v
? "true" : "false");
681 #define U128_BASE_10_ARRAY_LEN sizeof("340282366920938463463374607431768211455")
683 #define S128_BASE_10_ARRAY_LEN sizeof("-170141183460469231731687303715884105728")
686 * u128_tostring_base_10 is inspired from https://stackoverflow.com/a/4364365
689 void u128_tostring_base_10(union int_value v
, char str
[U128_BASE_10_ARRAY_LEN
])
691 int d
[39] = {}, i
, j
, str_i
= 0;
693 for (i
= 63; i
> -1; i
--) {
694 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
696 for (j
= 0; j
< 39; j
++)
698 for (j
= 0; j
< 38; j
++) {
699 d
[j
+ 1] += d
[j
] / 10;
703 for (i
= 63; i
> -1; i
--) {
704 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
707 for (j
= 0; j
< 39; j
++)
710 for (j
= 0; j
< 38; j
++) {
711 d
[j
+ 1] += d
[j
] / 10;
715 for (i
= 38; i
> 0; i
--)
718 for (; i
> -1; i
--) {
719 str
[str_i
++] = '0' + d
[i
];
725 void s128_tostring_base_10(union int_value v
, char str
[S128_BASE_10_ARRAY_LEN
])
727 uint64_t low
, high
, tmp
;
729 if (v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] >= 0) {
731 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
732 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = (uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
733 u128_tostring_base_10(v
, str
);
739 /* Special-case minimum value, which has no positive signed representation. */
740 if ((v
.s
[SIDE_INTEGER128_SPLIT_HIGH
] == INT64_MIN
) && (v
.s
[SIDE_INTEGER128_SPLIT_LOW
] == 0)) {
741 memcpy(str
, "-170141183460469231731687303715884105728", S128_BASE_10_ARRAY_LEN
);
744 /* Convert from two's complement. */
745 high
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_HIGH
];
746 low
= ~(uint64_t) v
.s
[SIDE_INTEGER128_SPLIT_LOW
];
750 /* Clear overflow to sign bit. */
751 high
&= ~0x8000000000000000ULL
;
753 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] = tmp
;
754 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = high
;
756 u128_tostring_base_10(v
, str
+ 1);
760 #define U128_BASE_8_ARRAY_LEN sizeof("3777777777777777777777777777777777777777777")
763 void u128_tostring_base_8(union int_value v
, char str
[U128_BASE_8_ARRAY_LEN
])
765 int d
[43] = {}, i
, j
, str_i
= 0;
767 for (i
= 63; i
> -1; i
--) {
768 if ((v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] >> i
) & 1)
770 for (j
= 0; j
< 43; j
++)
772 for (j
= 0; j
< 42; j
++) {
773 d
[j
+ 1] += d
[j
] / 8;
777 for (i
= 63; i
> -1; i
--) {
778 if ((v
.u
[SIDE_INTEGER128_SPLIT_LOW
] >> i
) & 1)
781 for (j
= 0; j
< 43; j
++)
784 for (j
= 0; j
< 42; j
++) {
785 d
[j
+ 1] += d
[j
] / 8;
789 for (i
= 42; i
> 0; i
--)
792 for (; i
> -1; i
--) {
793 str
[str_i
++] = '0' + d
[i
];
799 void tracer_print_type_integer(const char *separator
,
800 const struct side_type_integer
*type_integer
,
801 const union side_integer_value
*value
,
802 uint16_t offset_bits
,
803 enum tracer_display_base default_base
)
805 enum tracer_display_base base
;
809 v
= tracer_load_integer_value(type_integer
, value
, offset_bits
, &len_bits
);
810 tracer_print_type_header(separator
, side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
);
811 base
= get_attr_display_base(side_ptr_get(type_integer
->attr
), type_integer
->nr_attr
, default_base
);
813 case TRACER_DISPLAY_BASE_2
:
814 print_integer_binary(v
.u
, len_bits
);
816 case TRACER_DISPLAY_BASE_8
:
817 /* Clear sign bits beyond len_bits */
819 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
820 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
821 } else if (len_bits
< 128) {
822 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
824 if (len_bits
<= 64) {
825 printf("0o%" PRIo64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
827 char str
[U128_BASE_8_ARRAY_LEN
];
829 u128_tostring_base_8(v
, str
);
833 case TRACER_DISPLAY_BASE_10
:
834 if (len_bits
<= 64) {
835 if (type_integer
->signedness
)
836 printf("%" PRId64
, v
.s
[SIDE_INTEGER128_SPLIT_LOW
]);
838 printf("%" PRIu64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
840 if (type_integer
->signedness
) {
841 char str
[S128_BASE_10_ARRAY_LEN
];
842 s128_tostring_base_10(v
, str
);
845 char str
[U128_BASE_10_ARRAY_LEN
];
846 u128_tostring_base_10(v
, str
);
851 case TRACER_DISPLAY_BASE_16
:
852 /* Clear sign bits beyond len_bits */
854 v
.u
[SIDE_INTEGER128_SPLIT_LOW
] &= (1ULL << len_bits
) - 1;
855 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] = 0;
856 } else if (len_bits
< 128) {
857 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] &= (1ULL << (len_bits
- 64)) - 1;
859 if (len_bits
<= 64 || v
.u
[SIDE_INTEGER128_SPLIT_HIGH
] == 0) {
860 printf("0x%" PRIx64
, v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
862 printf("0x%" PRIx64
"%016" PRIx64
,
863 v
.u
[SIDE_INTEGER128_SPLIT_HIGH
],
864 v
.u
[SIDE_INTEGER128_SPLIT_LOW
]);
873 void tracer_print_type_float(const char *separator
,
874 const struct side_type_float
*type_float
,
875 const union side_float_value
*value
)
879 tracer_print_type_header(separator
, side_ptr_get(type_float
->attr
), type_float
->nr_attr
);
880 reverse_bo
= side_enum_get(type_float
->byte_order
) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST
;
881 switch (type_float
->float_size
) {
889 .f
= value
->side_float_binary16
,
893 float16
.u
= side_bswap_16(float16
.u
);
894 printf("%g", (double) float16
.f
);
897 fprintf(stderr
, "ERROR: Unsupported binary16 float type\n");
908 .f
= value
->side_float_binary32
,
912 float32
.u
= side_bswap_32(float32
.u
);
913 printf("%g", (double) float32
.f
);
916 fprintf(stderr
, "ERROR: Unsupported binary32 float type\n");
927 .f
= value
->side_float_binary64
,
931 float64
.u
= side_bswap_64(float64
.u
);
932 printf("%g", (double) float64
.f
);
935 fprintf(stderr
, "ERROR: Unsupported binary64 float type\n");
946 .f
= value
->side_float_binary128
,
950 side_bswap_128p(float128
.arr
);
951 printf("%Lg", (long double) float128
.f
);
954 fprintf(stderr
, "ERROR: Unsupported binary128 float type\n");
959 fprintf(stderr
, "ERROR: Unknown float size\n");
965 void push_nesting(struct print_ctx
*ctx
)
967 if (++ctx
->nesting
>= MAX_NESTING
) {
968 fprintf(stderr
, "ERROR: Nesting too deep.\n");
971 ctx
->item_nr
[ctx
->nesting
] = 0;
975 void pop_nesting(struct print_ctx
*ctx
)
977 ctx
->item_nr
[ctx
->nesting
] = 0;
978 if (ctx
->nesting
-- <= 0) {
979 fprintf(stderr
, "ERROR: Nesting underflow.\n");
985 int get_nested_item_nr(struct print_ctx
*ctx
)
987 return ctx
->item_nr
[ctx
->nesting
];
991 void inc_nested_item_nr(struct print_ctx
*ctx
)
993 ctx
->item_nr
[ctx
->nesting
]++;
997 void tracer_print_event(enum side_type_visitor_location loc
,
998 const struct side_event_description
*desc
,
999 const struct side_arg_vec
*side_arg_vec
,
1000 const struct side_arg_dynamic_struct
*var_struct
__attribute__((unused
)),
1001 void *caller_addr
, void *priv
__attribute__((unused
)))
1003 uint32_t side_sav_len
= side_arg_vec
->len
;
1005 if (desc
->nr_fields
!= side_sav_len
) {
1006 fprintf(stderr
, "ERROR: number of fields mismatch between description and arguments\n");
1011 case SIDE_TYPE_VISITOR_BEFORE
:
1013 printf("caller: [%p], ", caller_addr
);
1014 printf("provider: %s, event: %s",
1015 side_ptr_get(desc
->provider_name
),
1016 side_ptr_get(desc
->event_name
));
1017 print_attributes(", attr", ":", side_ptr_get(desc
->attr
), desc
->nr_attr
);
1019 case SIDE_TYPE_VISITOR_AFTER
:
1026 void tracer_print_static_fields(enum side_type_visitor_location loc
,
1027 const struct side_arg_vec
*side_arg_vec
,
1030 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1031 uint32_t side_sav_len
= side_arg_vec
->len
;
1034 case SIDE_TYPE_VISITOR_BEFORE
:
1035 printf("%s", side_sav_len
? ", fields: {" : "");
1038 case SIDE_TYPE_VISITOR_AFTER
:
1047 void tracer_print_variadic_fields(enum side_type_visitor_location loc
,
1048 const struct side_arg_dynamic_struct
*var_struct
,
1051 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1052 uint32_t var_struct_len
= var_struct
->len
;
1055 case SIDE_TYPE_VISITOR_BEFORE
:
1056 print_attributes(", attr ", "::", side_ptr_get(var_struct
->attr
), var_struct
->nr_attr
);
1057 printf("%s", var_struct_len
? ", fields:: {" : "");
1060 case SIDE_TYPE_VISITOR_AFTER
:
1069 void tracer_print_field(enum side_type_visitor_location loc
, const struct side_event_field
*item_desc
, void *priv
)
1071 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1074 case SIDE_TYPE_VISITOR_BEFORE
:
1075 if (get_nested_item_nr(ctx
) != 0)
1077 printf(" %s: { ", side_ptr_get(item_desc
->field_name
));
1079 case SIDE_TYPE_VISITOR_AFTER
:
1081 inc_nested_item_nr(ctx
);
1087 void tracer_print_elem(enum side_type_visitor_location loc
, const struct side_type
*type_desc
__attribute__((unused
)), void *priv
)
1089 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1092 case SIDE_TYPE_VISITOR_BEFORE
:
1093 if (get_nested_item_nr(ctx
) != 0)
1098 case SIDE_TYPE_VISITOR_AFTER
:
1100 inc_nested_item_nr(ctx
);
1106 void tracer_print_null(const struct side_type
*type_desc
,
1107 const struct side_arg
*item
__attribute__((unused
)),
1108 void *priv
__attribute__((unused
)))
1110 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_null
.attr
),
1111 type_desc
->u
.side_null
.nr_attr
);
1112 printf("<NULL TYPE>");
1116 void tracer_print_bool(const struct side_type
*type_desc
,
1117 const struct side_arg
*item
,
1118 void *priv
__attribute__((unused
)))
1120 tracer_print_type_bool(":", &type_desc
->u
.side_bool
, &item
->u
.side_static
.bool_value
, 0);
1124 void tracer_print_integer(const struct side_type
*type_desc
,
1125 const struct side_arg
*item
,
1126 void *priv
__attribute__((unused
)))
1128 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0, TRACER_DISPLAY_BASE_10
);
1132 void tracer_print_byte(const struct side_type
*type_desc
__attribute__((unused
)),
1133 const struct side_arg
*item
,
1134 void *priv
__attribute__((unused
)))
1136 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_byte
.attr
), type_desc
->u
.side_byte
.nr_attr
);
1137 printf("0x%" PRIx8
, item
->u
.side_static
.byte_value
);
1141 void tracer_print_pointer(const struct side_type
*type_desc
,
1142 const struct side_arg
*item
,
1143 void *priv
__attribute__((unused
)))
1145 tracer_print_type_integer(":", &type_desc
->u
.side_integer
, &item
->u
.side_static
.integer_value
, 0, TRACER_DISPLAY_BASE_16
);
1149 void tracer_print_float(const struct side_type
*type_desc
,
1150 const struct side_arg
*item
,
1151 void *priv
__attribute__((unused
)))
1153 tracer_print_type_float(":", &type_desc
->u
.side_float
, &item
->u
.side_static
.float_value
);
1157 void tracer_print_string(const struct side_type
*type_desc
,
1158 const struct side_arg
*item
,
1159 void *priv
__attribute__((unused
)))
1161 tracer_print_type_header(":", side_ptr_get(type_desc
->u
.side_string
.attr
), type_desc
->u
.side_string
.nr_attr
);
1162 tracer_print_type_string(side_ptr_get(item
->u
.side_static
.string_value
),
1163 type_desc
->u
.side_string
.unit_size
,
1164 side_enum_get(type_desc
->u
.side_string
.byte_order
), NULL
);
1168 void tracer_print_struct(enum side_type_visitor_location loc
,
1169 const struct side_type_struct
*side_struct
,
1170 const struct side_arg_vec
*side_arg_vec
__attribute__((unused
)), void *priv
)
1172 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1175 case SIDE_TYPE_VISITOR_BEFORE
:
1176 print_attributes("attr", ":", side_ptr_get(side_struct
->attr
), side_struct
->nr_attr
);
1177 printf("%s", side_struct
->nr_attr
? ", " : "");
1178 printf("fields: {");
1181 case SIDE_TYPE_VISITOR_AFTER
:
1189 void tracer_print_array(enum side_type_visitor_location loc
,
1190 const struct side_type_array
*side_array
,
1191 const struct side_arg_vec
*side_arg_vec
__attribute__((unused
)), void *priv
)
1193 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1196 case SIDE_TYPE_VISITOR_BEFORE
:
1197 print_attributes("attr", ":", side_ptr_get(side_array
->attr
), side_array
->nr_attr
);
1198 printf("%s", side_array
->nr_attr
? ", " : "");
1199 printf("elements: [");
1202 case SIDE_TYPE_VISITOR_AFTER
:
1210 void tracer_print_vla(enum side_type_visitor_location loc
,
1211 const struct side_type_vla
*side_vla
,
1212 const struct side_arg_vec
*side_arg_vec
__attribute__((unused
)), void *priv
)
1214 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1217 case SIDE_TYPE_VISITOR_BEFORE
:
1218 print_attributes("attr", ":", side_ptr_get(side_vla
->attr
), side_vla
->nr_attr
);
1219 printf("%s", side_vla
->nr_attr
? ", " : "");
1220 printf("elements: [");
1223 case SIDE_TYPE_VISITOR_AFTER
:
1231 void tracer_print_vla_visitor(enum side_type_visitor_location loc
,
1232 const struct side_type_vla_visitor
*side_vla_visitor
,
1233 const struct side_arg_vla_visitor
*side_arg_vla_visitor
__attribute__((unused
)), void *priv
)
1235 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1238 case SIDE_TYPE_VISITOR_BEFORE
:
1239 print_attributes("attr", ":", side_ptr_get(side_vla_visitor
->attr
), side_vla_visitor
->nr_attr
);
1240 printf("%s", side_vla_visitor
->nr_attr
? ", " : "");
1241 printf("elements: [");
1244 case SIDE_TYPE_VISITOR_AFTER
:
1251 static void tracer_print_enum(const struct side_type
*type_desc
,
1252 const struct side_arg
*item
, void *priv
)
1254 const struct side_enum_mappings
*mappings
= side_ptr_get(type_desc
->u
.side_enum
.mappings
);
1255 const struct side_type
*elem_type
= side_ptr_get(type_desc
->u
.side_enum
.elem_type
);
1258 if (side_enum_get(elem_type
->type
) != side_enum_get(item
->type
)) {
1259 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
1262 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
1263 &item
->u
.side_static
.integer_value
, 0, NULL
);
1264 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1265 printf("%s", mappings
->nr_attr
? ", " : "");
1267 tracer_print_integer(elem_type
, item
, priv
);
1269 print_enum_labels(mappings
, v
);
1272 static void tracer_print_enum_bitmap(const struct side_type
*type_desc
,
1273 const struct side_arg
*item
, void *priv
__attribute__((unused
)))
1275 const struct side_enum_bitmap_mappings
*side_enum_mappings
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.mappings
);
1276 const struct side_type
*enum_elem_type
= side_ptr_get(type_desc
->u
.side_enum_bitmap
.elem_type
), *elem_type
;
1277 uint32_t i
, print_count
= 0, stride_bit
, nr_items
;
1278 const struct side_arg
*array_item
;
1280 switch (side_enum_get(enum_elem_type
->type
)) {
1281 case SIDE_TYPE_U8
: /* Fall-through */
1282 case SIDE_TYPE_BYTE
: /* Fall-through */
1283 case SIDE_TYPE_U16
: /* Fall-through */
1284 case SIDE_TYPE_U32
: /* Fall-through */
1285 case SIDE_TYPE_U64
: /* Fall-through */
1286 case SIDE_TYPE_U128
: /* Fall-through */
1287 case SIDE_TYPE_S8
: /* Fall-through */
1288 case SIDE_TYPE_S16
: /* Fall-through */
1289 case SIDE_TYPE_S32
: /* Fall-through */
1290 case SIDE_TYPE_S64
: /* Fall-through */
1291 case SIDE_TYPE_S128
:
1292 elem_type
= enum_elem_type
;
1296 case SIDE_TYPE_ARRAY
:
1297 elem_type
= side_ptr_get(enum_elem_type
->u
.side_array
.elem_type
);
1298 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_array
)->sav
);
1299 nr_items
= type_desc
->u
.side_array
.length
;
1302 elem_type
= side_ptr_get(enum_elem_type
->u
.side_vla
.elem_type
);
1303 array_item
= side_ptr_get(side_ptr_get(item
->u
.side_static
.side_vla
)->sav
);
1304 nr_items
= side_ptr_get(item
->u
.side_static
.side_vla
)->len
;
1307 fprintf(stderr
, "ERROR: Unexpected enum element type\n");
1310 stride_bit
= elem_type_to_stride(elem_type
);
1312 print_attributes("attr", ":", side_ptr_get(side_enum_mappings
->attr
), side_enum_mappings
->nr_attr
);
1313 printf("%s", side_enum_mappings
->nr_attr
? ", " : "");
1314 printf("labels: [ ");
1315 for (i
= 0; i
< side_enum_mappings
->nr_mappings
; i
++) {
1316 const struct side_enum_bitmap_mapping
*mapping
= &side_ptr_get(side_enum_mappings
->mappings
)[i
];
1320 if (mapping
->range_end
< mapping
->range_begin
) {
1321 fprintf(stderr
, "ERROR: Unexpected enum bitmap range: %" PRIu64
"-%" PRIu64
"\n",
1322 mapping
->range_begin
, mapping
->range_end
);
1325 for (bit
= mapping
->range_begin
; bit
<= mapping
->range_end
; bit
++) {
1326 if (bit
> (nr_items
* stride_bit
) - 1)
1328 if (side_enum_get(elem_type
->type
) == SIDE_TYPE_BYTE
) {
1329 uint8_t v
= array_item
[bit
/ 8].u
.side_static
.byte_value
;
1330 if (v
& (1ULL << (bit
% 8))) {
1335 union int_value v
= {};
1337 v
= tracer_load_integer_value(&elem_type
->u
.side_integer
,
1338 &array_item
[bit
/ stride_bit
].u
.side_static
.integer_value
,
1340 side_check_value_u64(v
);
1341 if (v
.u
[SIDE_INTEGER128_SPLIT_LOW
] & (1ULL << (bit
% stride_bit
))) {
1349 printf("%s", print_count
++ ? ", " : "");
1350 tracer_print_type_string(side_ptr_get(mapping
->label
.p
), mapping
->label
.unit_size
,
1351 side_enum_get(mapping
->label
.byte_order
), NULL
);
1355 printf("<NO LABEL>");
1360 void tracer_print_gather_bool(const struct side_type_gather_bool
*type
,
1361 const union side_bool_value
*value
,
1362 void *priv
__attribute__((unused
)))
1364 tracer_print_type_bool(":", &type
->type
, value
, type
->offset_bits
);
1368 void tracer_print_gather_byte(const struct side_type_gather_byte
*type
,
1369 const uint8_t *_ptr
,
1370 void *priv
__attribute__((unused
)))
1372 tracer_print_type_header(":", side_ptr_get(type
->type
.attr
),
1373 type
->type
.nr_attr
);
1374 printf("0x%" PRIx8
, *_ptr
);
1378 void tracer_print_gather_integer(const struct side_type_gather_integer
*type
,
1379 const union side_integer_value
*value
,
1380 void *priv
__attribute__((unused
)))
1382 tracer_print_type_integer(":", &type
->type
, value
, type
->offset_bits
, TRACER_DISPLAY_BASE_10
);
1386 void tracer_print_gather_pointer(const struct side_type_gather_integer
*type
,
1387 const union side_integer_value
*value
,
1388 void *priv
__attribute__((unused
)))
1390 tracer_print_type_integer(":", &type
->type
, value
, type
->offset_bits
, TRACER_DISPLAY_BASE_16
);
1394 void tracer_print_gather_float(const struct side_type_gather_float
*type
,
1395 const union side_float_value
*value
,
1396 void *priv
__attribute__((unused
)))
1398 tracer_print_type_float(":", &type
->type
, value
);
1402 void tracer_print_gather_string(const struct side_type_gather_string
*type
,
1403 const void *p
, uint8_t unit_size
,
1404 enum side_type_label_byte_order byte_order
,
1405 size_t strlen_with_null
__attribute__((unused
)),
1406 void *priv
__attribute__((unused
)))
1408 //TODO use strlen_with_null input
1409 tracer_print_type_header(":", side_ptr_get(type
->type
.attr
),
1410 type
->type
.nr_attr
);
1411 tracer_print_type_string(p
, unit_size
, byte_order
, NULL
);
1415 void tracer_print_gather_struct(enum side_type_visitor_location loc
,
1416 const struct side_type_struct
*side_struct
,
1419 tracer_print_struct(loc
, side_struct
, NULL
, priv
);
1423 void tracer_print_gather_array(enum side_type_visitor_location loc
,
1424 const struct side_type_array
*side_array
,
1427 tracer_print_array(loc
, side_array
, NULL
, priv
);
1431 void tracer_print_gather_vla(enum side_type_visitor_location loc
,
1432 const struct side_type_vla
*side_vla
,
1433 uint32_t length
__attribute__((unused
)),
1436 tracer_print_vla(loc
, side_vla
, NULL
, priv
);
1440 void tracer_print_gather_enum(const struct side_type_gather_enum
*type
,
1441 const union side_integer_value
*value
,
1442 void *priv
__attribute__((unused
)))
1444 const struct side_enum_mappings
*mappings
= side_ptr_get(type
->mappings
);
1445 const struct side_type
*enum_elem_type
= side_ptr_get(type
->elem_type
);
1446 const struct side_type_gather_integer
*side_integer
= &enum_elem_type
->u
.side_gather
.u
.side_integer
;
1449 v
= tracer_load_integer_value(&side_integer
->type
, value
, 0, NULL
);
1450 print_attributes("attr", ":", side_ptr_get(mappings
->attr
), mappings
->nr_attr
);
1451 printf("%s", mappings
->nr_attr
? ", " : "");
1453 tracer_print_type_integer(":", &side_integer
->type
, value
, 0, TRACER_DISPLAY_BASE_10
);
1455 print_enum_labels(mappings
, v
);
1459 void tracer_print_dynamic_field(enum side_type_visitor_location loc
, const struct side_arg_dynamic_field
*field
, void *priv
)
1461 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1464 case SIDE_TYPE_VISITOR_BEFORE
:
1465 if (get_nested_item_nr(ctx
) != 0)
1467 printf(" %s:: { ", side_ptr_get(field
->field_name
));
1469 case SIDE_TYPE_VISITOR_AFTER
:
1471 inc_nested_item_nr(ctx
);
1477 void tracer_print_dynamic_elem(enum side_type_visitor_location loc
,
1478 const struct side_arg
*dynamic_item
__attribute__((unused
)), void *priv
)
1480 tracer_print_elem(loc
, NULL
, priv
);
1484 void tracer_print_dynamic_null(const struct side_arg
*item
,
1485 void *priv
__attribute__((unused
)))
1487 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_null
.attr
),
1488 item
->u
.side_dynamic
.side_null
.nr_attr
);
1489 printf("<NULL TYPE>");
1493 void tracer_print_dynamic_bool(const struct side_arg
*item
,
1494 void *priv
__attribute__((unused
)))
1496 tracer_print_type_bool("::", &item
->u
.side_dynamic
.side_bool
.type
, &item
->u
.side_dynamic
.side_bool
.value
, 0);
1500 void tracer_print_dynamic_integer(const struct side_arg
*item
,
1501 void *priv
__attribute__((unused
)))
1503 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1504 TRACER_DISPLAY_BASE_10
);
1508 void tracer_print_dynamic_byte(const struct side_arg
*item
,
1509 void *priv
__attribute__((unused
)))
1511 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_byte
.type
.attr
), item
->u
.side_dynamic
.side_byte
.type
.nr_attr
);
1512 printf("0x%" PRIx8
, item
->u
.side_dynamic
.side_byte
.value
);
1516 void tracer_print_dynamic_pointer(const struct side_arg
*item
,
1517 void *priv
__attribute__((unused
)))
1519 tracer_print_type_integer("::", &item
->u
.side_dynamic
.side_integer
.type
, &item
->u
.side_dynamic
.side_integer
.value
, 0,
1520 TRACER_DISPLAY_BASE_16
);
1524 void tracer_print_dynamic_float(const struct side_arg
*item
,
1525 void *priv
__attribute__((unused
)))
1527 tracer_print_type_float("::", &item
->u
.side_dynamic
.side_float
.type
,
1528 &item
->u
.side_dynamic
.side_float
.value
);
1532 void tracer_print_dynamic_string(const struct side_arg
*item
,
1533 void *priv
__attribute__((unused
)))
1535 tracer_print_type_header("::", side_ptr_get(item
->u
.side_dynamic
.side_string
.type
.attr
), item
->u
.side_dynamic
.side_string
.type
.nr_attr
);
1536 tracer_print_type_string((const char *)(uintptr_t) item
->u
.side_dynamic
.side_string
.value
,
1537 item
->u
.side_dynamic
.side_string
.type
.unit_size
,
1538 side_enum_get(item
->u
.side_dynamic
.side_string
.type
.byte_order
), NULL
);
1542 void tracer_print_dynamic_struct(enum side_type_visitor_location loc
,
1543 const struct side_arg_dynamic_struct
*dynamic_struct
,
1546 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1549 case SIDE_TYPE_VISITOR_BEFORE
:
1550 print_attributes("attr", "::", side_ptr_get(dynamic_struct
->attr
), dynamic_struct
->nr_attr
);
1551 printf("%s", dynamic_struct
->nr_attr
? ", " : "");
1552 printf("fields:: {");
1555 case SIDE_TYPE_VISITOR_AFTER
:
1563 void tracer_print_dynamic_struct_visitor(enum side_type_visitor_location loc
,
1564 const struct side_arg
*item
,
1567 struct side_arg_dynamic_struct_visitor
*dynamic_struct_visitor
;
1568 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1570 dynamic_struct_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_struct_visitor
);
1571 if (!dynamic_struct_visitor
)
1575 case SIDE_TYPE_VISITOR_BEFORE
:
1576 print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor
->attr
), dynamic_struct_visitor
->nr_attr
);
1577 printf("%s", dynamic_struct_visitor
->nr_attr
? ", " : "");
1578 printf("fields:: {");
1581 case SIDE_TYPE_VISITOR_AFTER
:
1589 void tracer_print_dynamic_vla(enum side_type_visitor_location loc
,
1590 const struct side_arg_dynamic_vla
*dynamic_vla
,
1593 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1596 case SIDE_TYPE_VISITOR_BEFORE
:
1597 print_attributes("attr", "::", side_ptr_get(dynamic_vla
->attr
), dynamic_vla
->nr_attr
);
1598 printf("%s", dynamic_vla
->nr_attr
? ", " : "");
1599 printf("elements:: [");
1602 case SIDE_TYPE_VISITOR_AFTER
:
1610 void tracer_print_dynamic_vla_visitor(enum side_type_visitor_location loc
,
1611 const struct side_arg
*item
,
1614 struct side_arg_dynamic_vla_visitor
*dynamic_vla_visitor
;
1615 struct print_ctx
*ctx
= (struct print_ctx
*) priv
;
1617 dynamic_vla_visitor
= side_ptr_get(item
->u
.side_dynamic
.side_dynamic_vla_visitor
);
1618 if (!dynamic_vla_visitor
)
1622 case SIDE_TYPE_VISITOR_BEFORE
:
1623 print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor
->attr
), dynamic_vla_visitor
->nr_attr
);
1624 printf("%s", dynamic_vla_visitor
->nr_attr
? ", " : "");
1625 printf("elements:: [");
1628 case SIDE_TYPE_VISITOR_AFTER
:
1635 static struct side_type_visitor type_visitor
= {
1636 .event_func
= tracer_print_event
,
1637 .static_fields_func
= tracer_print_static_fields
,
1638 .variadic_fields_func
= tracer_print_variadic_fields
,
1640 /* Stack-copy basic types. */
1641 .field_func
= tracer_print_field
,
1642 .elem_func
= tracer_print_elem
,
1643 .null_type_func
= tracer_print_null
,
1644 .bool_type_func
= tracer_print_bool
,
1645 .integer_type_func
= tracer_print_integer
,
1646 .byte_type_func
= tracer_print_byte
,
1647 .pointer_type_func
= tracer_print_pointer
,
1648 .float_type_func
= tracer_print_float
,
1649 .string_type_func
= tracer_print_string
,
1651 /* Stack-copy compound types. */
1652 .struct_type_func
= tracer_print_struct
,
1653 .array_type_func
= tracer_print_array
,
1654 .vla_type_func
= tracer_print_vla
,
1655 .vla_visitor_type_func
= tracer_print_vla_visitor
,
1657 /* Stack-copy enumeration types. */
1658 .enum_type_func
= tracer_print_enum
,
1659 .enum_bitmap_type_func
= tracer_print_enum_bitmap
,
1661 /* Gather basic types. */
1662 .gather_bool_type_func
= tracer_print_gather_bool
,
1663 .gather_byte_type_func
= tracer_print_gather_byte
,
1664 .gather_integer_type_func
= tracer_print_gather_integer
,
1665 .gather_pointer_type_func
= tracer_print_gather_pointer
,
1666 .gather_float_type_func
= tracer_print_gather_float
,
1667 .gather_string_type_func
= tracer_print_gather_string
,
1669 /* Gather compound types. */
1670 .gather_struct_type_func
= tracer_print_gather_struct
,
1671 .gather_array_type_func
= tracer_print_gather_array
,
1672 .gather_vla_type_func
= tracer_print_gather_vla
,
1674 /* Gather enumeration types. */
1675 .gather_enum_type_func
= tracer_print_gather_enum
,
1677 /* Dynamic basic types. */
1678 .dynamic_field_func
= tracer_print_dynamic_field
,
1679 .dynamic_elem_func
= tracer_print_dynamic_elem
,
1681 .dynamic_null_func
= tracer_print_dynamic_null
,
1682 .dynamic_bool_func
= tracer_print_dynamic_bool
,
1683 .dynamic_integer_func
= tracer_print_dynamic_integer
,
1684 .dynamic_byte_func
= tracer_print_dynamic_byte
,
1685 .dynamic_pointer_func
= tracer_print_dynamic_pointer
,
1686 .dynamic_float_func
= tracer_print_dynamic_float
,
1687 .dynamic_string_func
= tracer_print_dynamic_string
,
1689 /* Dynamic compound types. */
1690 .dynamic_struct_func
= tracer_print_dynamic_struct
,
1691 .dynamic_struct_visitor_func
= tracer_print_dynamic_struct_visitor
,
1692 .dynamic_vla_func
= tracer_print_dynamic_vla
,
1693 .dynamic_vla_visitor_func
= tracer_print_dynamic_vla_visitor
,
1697 void tracer_call(const struct side_event_description
*desc
,
1698 const struct side_arg_vec
*side_arg_vec
,
1699 void *priv
__attribute__((unused
)),
1702 struct print_ctx ctx
= {};
1704 type_visitor_event(&type_visitor
, desc
, side_arg_vec
, NULL
, caller_addr
, &ctx
);
1708 void tracer_call_variadic(const struct side_event_description
*desc
,
1709 const struct side_arg_vec
*side_arg_vec
,
1710 const struct side_arg_dynamic_struct
*var_struct
,
1711 void *priv
__attribute__((unused
)),
1714 struct print_ctx ctx
= {};
1716 type_visitor_event(&type_visitor
, desc
, side_arg_vec
, var_struct
, caller_addr
, &ctx
);
1720 void tracer_event_notification(enum side_tracer_notification notif
,
1721 struct side_event_description
**events
, uint32_t nr_events
,
1722 void *priv
__attribute__((unused
)))
1727 printf("----------------------------------------------------------\n");
1728 printf("Tracer notified of events %s\n",
1729 notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
? "inserted" : "removed");
1730 for (i
= 0; i
< nr_events
; i
++) {
1731 struct side_event_description
*event
= events
[i
];
1733 /* Skip NULL pointers */
1736 if (event
->version
!= SIDE_EVENT_DESCRIPTION_ABI_VERSION
) {
1737 printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n",
1738 event
->version
, SIDE_EVENT_DESCRIPTION_ABI_VERSION
);
1741 printf("provider: %s, event: %s\n",
1742 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
1743 if (event
->struct_size
!= side_offsetofend(struct side_event_description
, side_event_description_orig_abi_last
)) {
1744 printf("Warning: Event %s.%s description contains fields unknown to the tracer\n",
1745 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
));
1747 if (notif
== SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
) {
1748 if (event
->nr_side_type_label
> _NR_SIDE_TYPE_LABEL
) {
1749 printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
1750 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
1751 event
->nr_side_type_label
- _NR_SIDE_TYPE_LABEL
);
1753 if (event
->nr_side_attr_type
> _NR_SIDE_ATTR_TYPE
) {
1754 printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n",
1755 side_ptr_get(event
->provider_name
), side_ptr_get(event
->event_name
),
1756 event
->nr_side_attr_type
- _NR_SIDE_ATTR_TYPE
);
1758 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1759 ret
= side_tracer_callback_variadic_register(event
, tracer_call_variadic
, NULL
, tracer_key
);
1763 ret
= side_tracer_callback_register(event
, tracer_call
, NULL
, tracer_key
);
1768 if (event
->flags
& SIDE_EVENT_FLAG_VARIADIC
) {
1769 ret
= side_tracer_callback_variadic_unregister(event
, tracer_call_variadic
, NULL
, tracer_key
);
1773 ret
= side_tracer_callback_unregister(event
, tracer_call
, NULL
, tracer_key
);
1779 printf("----------------------------------------------------------\n");
1782 static __attribute__((constructor
))
1783 void tracer_init(void);
1785 void tracer_init(void)
1787 if (side_tracer_request_key(&tracer_key
))
1789 tracer_handle
= side_tracer_event_notification_register(tracer_event_notification
, NULL
);
1794 static __attribute__((destructor
))
1795 void tracer_exit(void);
1797 void tracer_exit(void)
1799 side_tracer_event_notification_unregister(tracer_handle
);