Commit | Line | Data |
---|---|---|
f611d0c3 MD |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
4 | */ | |
5 | ||
6 | #include <stdint.h> | |
7 | #include <inttypes.h> | |
8 | #include <stdlib.h> | |
9 | #include <stdio.h> | |
ea32e5fc | 10 | #include <stdbool.h> |
1d9c515c | 11 | #include <string.h> |
52990f65 | 12 | #include <iconv.h> |
f611d0c3 | 13 | |
67337c4a | 14 | #include <side/trace.h> |
f611d0c3 | 15 | |
1d9c515c MD |
16 | enum tracer_display_base { |
17 | TRACER_DISPLAY_BASE_2, | |
18 | TRACER_DISPLAY_BASE_8, | |
19 | TRACER_DISPLAY_BASE_10, | |
20 | TRACER_DISPLAY_BASE_16, | |
21 | }; | |
22 | ||
4f5e1b67 MD |
23 | union int64_value { |
24 | uint64_t u; | |
25 | int64_t s; | |
26 | }; | |
27 | ||
67337c4a | 28 | static struct side_tracer_handle *tracer_handle; |
1e8aec23 | 29 | |
f611d0c3 | 30 | static |
67337c4a | 31 | void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec); |
f611d0c3 | 32 | static |
5530345d MD |
33 | void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant); |
34 | static | |
67337c4a | 35 | void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec); |
f611d0c3 | 36 | static |
67337c4a | 37 | void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec); |
f611d0c3 | 38 | static |
67337c4a | 39 | void tracer_print_vla_visitor(const struct side_type *type_desc, void *app_ctx); |
ba845af5 | 40 | static |
67337c4a | 41 | void tracer_print_dynamic(const struct side_arg *dynamic_item); |
d8be25de | 42 | static |
67337c4a | 43 | uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr); |
8ad2f385 | 44 | static |
67337c4a | 45 | uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr); |
d9359cfa | 46 | static |
67337c4a | 47 | uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr, |
4e1b0e0e | 48 | enum tracer_display_base default_base); |
d9359cfa | 49 | static |
67337c4a | 50 | uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr); |
d9359cfa | 51 | static |
67337c4a | 52 | uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr); |
7d34edfc | 53 | static |
67337c4a | 54 | uint32_t tracer_print_gather_enum_type(const struct side_type_gather *type_gather, const void *_ptr); |
0519cb86 | 55 | static |
67337c4a | 56 | uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr); |
d69918cc | 57 | static |
67337c4a | 58 | uint32_t tracer_print_gather_array(const struct side_type_gather *type_gather, const void *_ptr); |
d9359cfa | 59 | static |
67337c4a | 60 | uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, const void *_ptr, |
80429681 | 61 | const void *_length_ptr); |
65b8734a | 62 | static |
67337c4a | 63 | void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item); |
f611d0c3 | 64 | |
52990f65 | 65 | static |
67337c4a | 66 | void tracer_convert_string_to_utf8(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order, |
9ceac3e2 MD |
67 | size_t *strlen_with_null, |
68 | char **output_str) | |
52990f65 MD |
69 | { |
70 | size_t ret, inbytesleft = 0, outbytesleft, bufsize; | |
71 | const char *str = p, *fromcode; | |
72 | char *inbuf = (char *) p, *outbuf, *buf; | |
73 | iconv_t cd; | |
74 | ||
75 | switch (unit_size) { | |
76 | case 1: | |
52990f65 MD |
77 | if (strlen_with_null) |
78 | *strlen_with_null = strlen(str) + 1; | |
9ceac3e2 | 79 | *output_str = (char *) str; |
52990f65 MD |
80 | return; |
81 | case 2: | |
82 | { | |
83 | const uint16_t *p16 = p; | |
84 | ||
85 | switch (byte_order) { | |
67337c4a | 86 | case SIDE_TYPE_BYTE_ORDER_LE: |
52990f65 MD |
87 | { |
88 | fromcode = "UTF-16LE"; | |
89 | break; | |
90 | } | |
67337c4a | 91 | case SIDE_TYPE_BYTE_ORDER_BE: |
52990f65 MD |
92 | { |
93 | fromcode = "UTF-16BE"; | |
94 | break; | |
95 | } | |
96 | default: | |
97 | fprintf(stderr, "Unknown byte order\n"); | |
98 | abort(); | |
99 | } | |
100 | for (; *p16; p16++) | |
101 | inbytesleft += 2; | |
102 | /* | |
103 | * Worse case is U+FFFF UTF-16 (2 bytes) converting to | |
104 | * { ef, bf, bf } UTF-8 (3 bytes). | |
105 | */ | |
106 | bufsize = inbytesleft / 2 * 3 + 1; | |
107 | break; | |
108 | } | |
109 | case 4: | |
110 | { | |
111 | const uint32_t *p32 = p; | |
112 | ||
113 | switch (byte_order) { | |
67337c4a | 114 | case SIDE_TYPE_BYTE_ORDER_LE: |
52990f65 MD |
115 | { |
116 | fromcode = "UTF-32LE"; | |
117 | break; | |
118 | } | |
67337c4a | 119 | case SIDE_TYPE_BYTE_ORDER_BE: |
52990f65 MD |
120 | { |
121 | fromcode = "UTF-32BE"; | |
122 | break; | |
123 | } | |
124 | default: | |
125 | fprintf(stderr, "Unknown byte order\n"); | |
126 | abort(); | |
127 | } | |
128 | for (; *p32; p32++) | |
129 | inbytesleft += 4; | |
130 | /* | |
131 | * Each 4-byte UTF-32 character converts to at most a | |
132 | * 4-byte UTF-8 character. | |
133 | */ | |
134 | bufsize = inbytesleft + 1; | |
135 | break; | |
136 | } | |
137 | default: | |
138 | fprintf(stderr, "Unknown string unit size %" PRIu8 "\n", unit_size); | |
139 | abort(); | |
140 | } | |
141 | ||
142 | cd = iconv_open("UTF8", fromcode); | |
143 | if (cd == (iconv_t) -1) { | |
144 | perror("iconv_open"); | |
145 | abort(); | |
146 | } | |
147 | buf = malloc(bufsize); | |
148 | if (!buf) { | |
149 | abort(); | |
150 | } | |
151 | outbuf = (char *) buf; | |
152 | outbytesleft = bufsize; | |
153 | ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); | |
154 | if (ret == (size_t) -1) { | |
155 | perror("iconv"); | |
156 | abort(); | |
157 | } | |
158 | if (inbytesleft) { | |
159 | fprintf(stderr, "Buffer too small to convert string input\n"); | |
160 | abort(); | |
161 | } | |
162 | (*outbuf++) = '\0'; | |
52990f65 MD |
163 | if (iconv_close(cd) == -1) { |
164 | perror("iconv_close"); | |
165 | abort(); | |
166 | } | |
9ceac3e2 MD |
167 | if (strlen_with_null) |
168 | *strlen_with_null = outbuf - buf; | |
169 | *output_str = buf; | |
170 | } | |
171 | ||
172 | static | |
67337c4a | 173 | void tracer_print_string(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order, |
9ceac3e2 MD |
174 | size_t *strlen_with_null) |
175 | { | |
176 | char *output_str = NULL; | |
177 | ||
178 | tracer_convert_string_to_utf8(p, unit_size, byte_order, strlen_with_null, &output_str); | |
179 | printf("\"%s\"", output_str); | |
180 | if (output_str != p) | |
181 | free(output_str); | |
52990f65 MD |
182 | } |
183 | ||
1d9c515c | 184 | static |
67337c4a | 185 | int64_t get_attr_integer_value(const struct side_attr *attr) |
1d9c515c MD |
186 | { |
187 | int64_t val; | |
188 | ||
15f17024 | 189 | switch (side_enum_get(attr->value.type)) { |
67337c4a MD |
190 | case SIDE_ATTR_TYPE_U8: |
191 | val = attr->value.u.integer_value.side_u8; | |
1d9c515c | 192 | break; |
67337c4a MD |
193 | case SIDE_ATTR_TYPE_U16: |
194 | val = attr->value.u.integer_value.side_u16; | |
1d9c515c | 195 | break; |
67337c4a MD |
196 | case SIDE_ATTR_TYPE_U32: |
197 | val = attr->value.u.integer_value.side_u32; | |
1d9c515c | 198 | break; |
67337c4a MD |
199 | case SIDE_ATTR_TYPE_U64: |
200 | val = attr->value.u.integer_value.side_u64; | |
1d9c515c | 201 | break; |
67337c4a MD |
202 | case SIDE_ATTR_TYPE_S8: |
203 | val = attr->value.u.integer_value.side_s8; | |
1d9c515c | 204 | break; |
67337c4a MD |
205 | case SIDE_ATTR_TYPE_S16: |
206 | val = attr->value.u.integer_value.side_s16; | |
1d9c515c | 207 | break; |
67337c4a MD |
208 | case SIDE_ATTR_TYPE_S32: |
209 | val = attr->value.u.integer_value.side_s32; | |
1d9c515c | 210 | break; |
67337c4a MD |
211 | case SIDE_ATTR_TYPE_S64: |
212 | val = attr->value.u.integer_value.side_s64; | |
1d9c515c MD |
213 | break; |
214 | default: | |
215 | fprintf(stderr, "Unexpected attribute type\n"); | |
216 | abort(); | |
217 | } | |
218 | return val; | |
219 | } | |
220 | ||
221 | static | |
67337c4a | 222 | enum tracer_display_base get_attr_display_base(const struct side_attr *_attr, uint32_t nr_attr, |
f0dafd60 | 223 | enum tracer_display_base default_base) |
1d9c515c MD |
224 | { |
225 | uint32_t i; | |
226 | ||
227 | for (i = 0; i < nr_attr; i++) { | |
67337c4a | 228 | const struct side_attr *attr = &_attr[i]; |
9ceac3e2 MD |
229 | char *utf8_str = NULL; |
230 | bool cmp; | |
1d9c515c | 231 | |
3db2d8a1 | 232 | tracer_convert_string_to_utf8(side_ptr_get(attr->key.p), attr->key.unit_size, |
3bc9ba43 | 233 | side_enum_get(attr->key.byte_order), NULL, &utf8_str); |
9ceac3e2 | 234 | cmp = strcmp(utf8_str, "std.integer.base"); |
3db2d8a1 | 235 | if (utf8_str != side_ptr_get(attr->key.p)) |
9ceac3e2 MD |
236 | free(utf8_str); |
237 | if (!cmp) { | |
1d9c515c MD |
238 | int64_t val = get_attr_integer_value(attr); |
239 | ||
240 | switch (val) { | |
241 | case 2: | |
242 | return TRACER_DISPLAY_BASE_2; | |
243 | case 8: | |
244 | return TRACER_DISPLAY_BASE_8; | |
245 | case 10: | |
246 | return TRACER_DISPLAY_BASE_10; | |
247 | case 16: | |
248 | return TRACER_DISPLAY_BASE_16; | |
249 | default: | |
250 | fprintf(stderr, "Unexpected integer display base: %" PRId64 "\n", val); | |
251 | abort(); | |
252 | } | |
253 | } | |
254 | } | |
f0dafd60 | 255 | return default_base; /* Default */ |
1d9c515c MD |
256 | } |
257 | ||
bc3c89b3 | 258 | static |
67337c4a | 259 | void tracer_print_attr_type(const char *separator, const struct side_attr *attr) |
bc3c89b3 | 260 | { |
9ceac3e2 MD |
261 | char *utf8_str = NULL; |
262 | ||
3db2d8a1 | 263 | tracer_convert_string_to_utf8(side_ptr_get(attr->key.p), attr->key.unit_size, |
3bc9ba43 | 264 | side_enum_get(attr->key.byte_order), NULL, &utf8_str); |
9ceac3e2 | 265 | printf("{ key%s \"%s\", value%s ", separator, utf8_str, separator); |
3db2d8a1 | 266 | if (utf8_str != side_ptr_get(attr->key.p)) |
9ceac3e2 | 267 | free(utf8_str); |
15f17024 | 268 | switch (side_enum_get(attr->value.type)) { |
67337c4a | 269 | case SIDE_ATTR_TYPE_BOOL: |
5f82db91 | 270 | printf("%s", attr->value.u.bool_value ? "true" : "false"); |
bc3c89b3 | 271 | break; |
67337c4a MD |
272 | case SIDE_ATTR_TYPE_U8: |
273 | printf("%" PRIu8, attr->value.u.integer_value.side_u8); | |
bc3c89b3 | 274 | break; |
67337c4a MD |
275 | case SIDE_ATTR_TYPE_U16: |
276 | printf("%" PRIu16, attr->value.u.integer_value.side_u16); | |
bc3c89b3 | 277 | break; |
67337c4a MD |
278 | case SIDE_ATTR_TYPE_U32: |
279 | printf("%" PRIu32, attr->value.u.integer_value.side_u32); | |
bc3c89b3 | 280 | break; |
67337c4a MD |
281 | case SIDE_ATTR_TYPE_U64: |
282 | printf("%" PRIu64, attr->value.u.integer_value.side_u64); | |
bc3c89b3 | 283 | break; |
67337c4a MD |
284 | case SIDE_ATTR_TYPE_S8: |
285 | printf("%" PRId8, attr->value.u.integer_value.side_s8); | |
bc3c89b3 | 286 | break; |
67337c4a MD |
287 | case SIDE_ATTR_TYPE_S16: |
288 | printf("%" PRId16, attr->value.u.integer_value.side_s16); | |
bc3c89b3 | 289 | break; |
67337c4a MD |
290 | case SIDE_ATTR_TYPE_S32: |
291 | printf("%" PRId32, attr->value.u.integer_value.side_s32); | |
bc3c89b3 | 292 | break; |
67337c4a MD |
293 | case SIDE_ATTR_TYPE_S64: |
294 | printf("%" PRId64, attr->value.u.integer_value.side_s64); | |
bc3c89b3 | 295 | break; |
67337c4a | 296 | case SIDE_ATTR_TYPE_FLOAT_BINARY16: |
bc3c89b3 | 297 | #if __HAVE_FLOAT16 |
67337c4a | 298 | printf("%g", (double) attr->value.u.float_value.side_float_binary16); |
bc3c89b3 MD |
299 | break; |
300 | #else | |
de1b3cd2 | 301 | fprintf(stderr, "ERROR: Unsupported binary16 float type\n"); |
bc3c89b3 MD |
302 | abort(); |
303 | #endif | |
67337c4a | 304 | case SIDE_ATTR_TYPE_FLOAT_BINARY32: |
bc3c89b3 | 305 | #if __HAVE_FLOAT32 |
67337c4a | 306 | printf("%g", (double) attr->value.u.float_value.side_float_binary32); |
bc3c89b3 MD |
307 | break; |
308 | #else | |
de1b3cd2 | 309 | fprintf(stderr, "ERROR: Unsupported binary32 float type\n"); |
bc3c89b3 MD |
310 | abort(); |
311 | #endif | |
67337c4a | 312 | case SIDE_ATTR_TYPE_FLOAT_BINARY64: |
bc3c89b3 | 313 | #if __HAVE_FLOAT64 |
67337c4a | 314 | printf("%g", (double) attr->value.u.float_value.side_float_binary64); |
bc3c89b3 MD |
315 | break; |
316 | #else | |
de1b3cd2 | 317 | fprintf(stderr, "ERROR: Unsupported binary64 float type\n"); |
bc3c89b3 MD |
318 | abort(); |
319 | #endif | |
67337c4a | 320 | case SIDE_ATTR_TYPE_FLOAT_BINARY128: |
bc3c89b3 | 321 | #if __HAVE_FLOAT128 |
67337c4a | 322 | printf("%Lg", (long double) attr->value.u.float_value.side_float_binary128); |
bc3c89b3 MD |
323 | break; |
324 | #else | |
de1b3cd2 | 325 | fprintf(stderr, "ERROR: Unsupported binary128 float type\n"); |
bc3c89b3 MD |
326 | abort(); |
327 | #endif | |
67337c4a | 328 | case SIDE_ATTR_TYPE_STRING: |
3db2d8a1 | 329 | tracer_print_string(side_ptr_get(attr->value.u.string_value.p), |
ab8a626e | 330 | attr->value.u.string_value.unit_size, |
3bc9ba43 | 331 | side_enum_get(attr->value.u.string_value.byte_order), NULL); |
bc3c89b3 MD |
332 | break; |
333 | default: | |
de1b3cd2 | 334 | fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>"); |
bc3c89b3 MD |
335 | abort(); |
336 | } | |
337 | printf(" }"); | |
338 | } | |
339 | ||
7d21cf51 | 340 | static |
905c328e | 341 | void print_attributes(const char *prefix_str, const char *separator, |
67337c4a | 342 | const struct side_attr *attr, uint32_t nr_attr) |
7d21cf51 | 343 | { |
e65f9ce5 | 344 | uint32_t i; |
7d21cf51 MD |
345 | |
346 | if (!nr_attr) | |
347 | return; | |
905c328e | 348 | printf("%s%s [ ", prefix_str, separator); |
7d21cf51 MD |
349 | for (i = 0; i < nr_attr; i++) { |
350 | printf("%s", i ? ", " : ""); | |
905c328e | 351 | tracer_print_attr_type(separator, &attr[i]); |
7d21cf51 MD |
352 | } |
353 | printf(" ]"); | |
354 | } | |
355 | ||
79f677ba | 356 | static |
67337c4a MD |
357 | union int64_value tracer_load_integer_value(const struct side_type_integer *type_integer, |
358 | const union side_integer_value *value, | |
f6a2a8ed | 359 | uint16_t offset_bits, uint16_t *_len_bits) |
79f677ba | 360 | { |
f6a2a8ed MD |
361 | union int64_value v64; |
362 | uint16_t len_bits; | |
363 | bool reverse_bo; | |
79f677ba | 364 | |
f6a2a8ed MD |
365 | if (!type_integer->len_bits) |
366 | len_bits = type_integer->integer_size * CHAR_BIT; | |
367 | else | |
368 | len_bits = type_integer->len_bits; | |
369 | if (len_bits + offset_bits > type_integer->integer_size * CHAR_BIT) | |
d8be25de | 370 | abort(); |
3bc9ba43 | 371 | reverse_bo = side_enum_get(type_integer->byte_order) != SIDE_TYPE_BYTE_ORDER_HOST; |
f6a2a8ed MD |
372 | switch (type_integer->integer_size) { |
373 | case 1: | |
374 | if (type_integer->signedness) | |
67337c4a | 375 | v64.s = value->side_s8; |
f6a2a8ed | 376 | else |
67337c4a | 377 | v64.u = value->side_u8; |
d8be25de | 378 | break; |
f6a2a8ed MD |
379 | case 2: |
380 | if (type_integer->signedness) { | |
67337c4a | 381 | int16_t side_s16; |
8bdd5c12 | 382 | |
67337c4a | 383 | side_s16 = value->side_s16; |
f6a2a8ed | 384 | if (reverse_bo) |
67337c4a MD |
385 | side_s16 = side_bswap_16(side_s16); |
386 | v64.s = side_s16; | |
f6a2a8ed | 387 | } else { |
67337c4a | 388 | uint16_t side_u16; |
8bdd5c12 | 389 | |
67337c4a | 390 | side_u16 = value->side_u16; |
f6a2a8ed | 391 | if (reverse_bo) |
67337c4a MD |
392 | side_u16 = side_bswap_16(side_u16); |
393 | v64.u = side_u16; | |
f6a2a8ed | 394 | } |
d8be25de | 395 | break; |
f6a2a8ed MD |
396 | case 4: |
397 | if (type_integer->signedness) { | |
67337c4a | 398 | int32_t side_s32; |
8bdd5c12 | 399 | |
67337c4a | 400 | side_s32 = value->side_s32; |
f6a2a8ed | 401 | if (reverse_bo) |
67337c4a MD |
402 | side_s32 = side_bswap_32(side_s32); |
403 | v64.s = side_s32; | |
f6a2a8ed | 404 | } else { |
67337c4a | 405 | uint32_t side_u32; |
8bdd5c12 | 406 | |
67337c4a | 407 | side_u32 = value->side_u32; |
f6a2a8ed | 408 | if (reverse_bo) |
67337c4a MD |
409 | side_u32 = side_bswap_32(side_u32); |
410 | v64.u = side_u32; | |
f6a2a8ed | 411 | } |
d8be25de | 412 | break; |
f6a2a8ed MD |
413 | case 8: |
414 | if (type_integer->signedness) { | |
67337c4a | 415 | int64_t side_s64; |
8bdd5c12 | 416 | |
67337c4a | 417 | side_s64 = value->side_s64; |
f6a2a8ed | 418 | if (reverse_bo) |
67337c4a MD |
419 | side_s64 = side_bswap_64(side_s64); |
420 | v64.s = side_s64; | |
f6a2a8ed | 421 | } else { |
67337c4a | 422 | uint64_t side_u64; |
8bdd5c12 | 423 | |
67337c4a | 424 | side_u64 = value->side_u64; |
f6a2a8ed | 425 | if (reverse_bo) |
67337c4a MD |
426 | side_u64 = side_bswap_64(side_u64); |
427 | v64.u = side_u64; | |
f6a2a8ed | 428 | } |
d8be25de MD |
429 | break; |
430 | default: | |
d8be25de MD |
431 | abort(); |
432 | } | |
f6a2a8ed MD |
433 | v64.u >>= offset_bits; |
434 | if (len_bits < 64) { | |
435 | v64.u &= (1ULL << len_bits) - 1; | |
436 | if (type_integer->signedness) { | |
437 | /* Sign-extend. */ | |
438 | if (v64.u & (1ULL << (len_bits - 1))) | |
439 | v64.u |= ~((1ULL << len_bits) - 1); | |
440 | } | |
441 | } | |
442 | if (_len_bits) | |
443 | *_len_bits = len_bits; | |
444 | return v64; | |
445 | } | |
446 | ||
447 | static | |
67337c4a | 448 | void print_enum_labels(const struct side_enum_mappings *mappings, union int64_value v64) |
f6a2a8ed | 449 | { |
f6a2a8ed MD |
450 | uint32_t i, print_count = 0; |
451 | ||
d8be25de MD |
452 | printf(", labels: [ "); |
453 | for (i = 0; i < mappings->nr_mappings; i++) { | |
64037418 | 454 | const struct side_enum_mapping *mapping = &side_ptr_get(mappings->mappings)[i]; |
79f677ba | 455 | |
ea32e5fc | 456 | if (mapping->range_end < mapping->range_begin) { |
de1b3cd2 | 457 | fprintf(stderr, "ERROR: Unexpected enum range: %" PRIu64 "-%" PRIu64 "\n", |
ea32e5fc MD |
458 | mapping->range_begin, mapping->range_end); |
459 | abort(); | |
460 | } | |
f6a2a8ed | 461 | if (v64.s >= mapping->range_begin && v64.s <= mapping->range_end) { |
79f677ba | 462 | printf("%s", print_count++ ? ", " : ""); |
3bc9ba43 MD |
463 | tracer_print_string(side_ptr_get(mapping->label.p), mapping->label.unit_size, |
464 | side_enum_get(mapping->label.byte_order), NULL); | |
79f677ba MD |
465 | } |
466 | } | |
467 | if (!print_count) | |
468 | printf("<NO LABEL>"); | |
469 | printf(" ]"); | |
470 | } | |
471 | ||
f6a2a8ed | 472 | static |
67337c4a | 473 | void tracer_print_enum(const struct side_type *type_desc, const struct side_arg *item) |
f6a2a8ed | 474 | { |
64037418 | 475 | const struct side_enum_mappings *mappings = side_ptr_get(type_desc->u.side_enum.mappings); |
c5789285 | 476 | const struct side_type *elem_type = side_ptr_get(type_desc->u.side_enum.elem_type); |
f6a2a8ed MD |
477 | union int64_value v64; |
478 | ||
3ce69bfa | 479 | if (side_enum_get(elem_type->type) != side_enum_get(item->type)) { |
f6a2a8ed MD |
480 | fprintf(stderr, "ERROR: Unexpected enum element type\n"); |
481 | abort(); | |
482 | } | |
67337c4a MD |
483 | v64 = tracer_load_integer_value(&elem_type->u.side_integer, |
484 | &item->u.side_static.integer_value, 0, NULL); | |
12d787db | 485 | print_attributes("attr", ":", side_ptr_get(mappings->attr), mappings->nr_attr); |
f6a2a8ed MD |
486 | printf("%s", mappings->nr_attr ? ", " : ""); |
487 | tracer_print_type(elem_type, item); | |
0519cb86 | 488 | print_enum_labels(mappings, v64); |
f6a2a8ed MD |
489 | } |
490 | ||
ea32e5fc | 491 | static |
67337c4a | 492 | uint32_t elem_type_to_stride(const struct side_type *elem_type) |
ea32e5fc | 493 | { |
af6aa6e1 MD |
494 | uint32_t stride_bit; |
495 | ||
3ce69bfa | 496 | switch (side_enum_get(elem_type->type)) { |
67337c4a | 497 | case SIDE_TYPE_BYTE: |
af6aa6e1 MD |
498 | stride_bit = 8; |
499 | break; | |
8625d674 | 500 | |
67337c4a MD |
501 | case SIDE_TYPE_U8: |
502 | case SIDE_TYPE_U16: | |
503 | case SIDE_TYPE_U32: | |
504 | case SIDE_TYPE_U64: | |
505 | case SIDE_TYPE_S8: | |
506 | case SIDE_TYPE_S16: | |
507 | case SIDE_TYPE_S32: | |
508 | case SIDE_TYPE_S64: | |
509 | return elem_type->u.side_integer.integer_size * CHAR_BIT; | |
af6aa6e1 | 510 | default: |
8625d674 | 511 | fprintf(stderr, "ERROR: Unexpected enum bitmap element type\n"); |
af6aa6e1 MD |
512 | abort(); |
513 | } | |
514 | return stride_bit; | |
515 | } | |
516 | ||
517 | static | |
67337c4a MD |
518 | void tracer_print_enum_bitmap(const struct side_type *type_desc, |
519 | const struct side_arg *item) | |
af6aa6e1 | 520 | { |
64037418 | 521 | const struct side_enum_bitmap_mappings *side_enum_mappings = side_ptr_get(type_desc->u.side_enum_bitmap.mappings); |
c5789285 | 522 | const struct side_type *enum_elem_type = side_ptr_get(type_desc->u.side_enum_bitmap.elem_type), *elem_type; |
e65f9ce5 | 523 | uint32_t i, print_count = 0, stride_bit, nr_items; |
67337c4a | 524 | const struct side_arg *array_item; |
af6aa6e1 | 525 | |
3ce69bfa | 526 | switch (side_enum_get(enum_elem_type->type)) { |
67337c4a MD |
527 | case SIDE_TYPE_U8: /* Fall-through */ |
528 | case SIDE_TYPE_BYTE: /* Fall-through */ | |
529 | case SIDE_TYPE_U16: /* Fall-through */ | |
530 | case SIDE_TYPE_U32: /* Fall-through */ | |
531 | case SIDE_TYPE_U64: /* Fall-through */ | |
532 | case SIDE_TYPE_S8: /* Fall-through */ | |
533 | case SIDE_TYPE_S16: /* Fall-through */ | |
534 | case SIDE_TYPE_S32: /* Fall-through */ | |
535 | case SIDE_TYPE_S64: | |
7f8e7e97 | 536 | elem_type = enum_elem_type; |
af6aa6e1 MD |
537 | array_item = item; |
538 | nr_items = 1; | |
af6aa6e1 | 539 | break; |
67337c4a | 540 | case SIDE_TYPE_ARRAY: |
c5789285 | 541 | elem_type = side_ptr_get(enum_elem_type->u.side_array.elem_type); |
f13253cb | 542 | array_item = side_ptr_get(side_ptr_get(item->u.side_static.side_array)->sav); |
67337c4a | 543 | nr_items = type_desc->u.side_array.length; |
af6aa6e1 | 544 | break; |
67337c4a | 545 | case SIDE_TYPE_VLA: |
c5789285 | 546 | elem_type = side_ptr_get(enum_elem_type->u.side_vla.elem_type); |
f13253cb | 547 | array_item = side_ptr_get(side_ptr_get(item->u.side_static.side_vla)->sav); |
bac71609 | 548 | nr_items = side_ptr_get(item->u.side_static.side_vla)->len; |
af6aa6e1 MD |
549 | break; |
550 | default: | |
de1b3cd2 | 551 | fprintf(stderr, "ERROR: Unexpected enum element type\n"); |
af6aa6e1 MD |
552 | abort(); |
553 | } | |
7f8e7e97 | 554 | stride_bit = elem_type_to_stride(elem_type); |
ea32e5fc | 555 | |
12d787db | 556 | print_attributes("attr", ":", side_ptr_get(side_enum_mappings->attr), side_enum_mappings->nr_attr); |
67337c4a | 557 | printf("%s", side_enum_mappings->nr_attr ? ", " : ""); |
af6aa6e1 | 558 | printf("labels: [ "); |
67337c4a | 559 | for (i = 0; i < side_enum_mappings->nr_mappings; i++) { |
64037418 | 560 | const struct side_enum_bitmap_mapping *mapping = &side_ptr_get(side_enum_mappings->mappings)[i]; |
ea32e5fc | 561 | bool match = false; |
9ff49ee4 | 562 | uint64_t bit; |
ea32e5fc | 563 | |
9ff49ee4 | 564 | if (mapping->range_end < mapping->range_begin) { |
de1b3cd2 | 565 | fprintf(stderr, "ERROR: Unexpected enum bitmap range: %" PRIu64 "-%" PRIu64 "\n", |
ea32e5fc MD |
566 | mapping->range_begin, mapping->range_end); |
567 | abort(); | |
568 | } | |
569 | for (bit = mapping->range_begin; bit <= mapping->range_end; bit++) { | |
af6aa6e1 MD |
570 | if (bit > (nr_items * stride_bit) - 1) |
571 | break; | |
3ce69bfa | 572 | if (side_enum_get(elem_type->type) == SIDE_TYPE_BYTE) { |
67337c4a | 573 | uint8_t v = array_item[bit / 8].u.side_static.byte_value; |
af6aa6e1 MD |
574 | if (v & (1ULL << (bit % 8))) { |
575 | match = true; | |
576 | goto match; | |
577 | } | |
7f8e7e97 MD |
578 | } else { |
579 | union int64_value v64; | |
580 | ||
67337c4a MD |
581 | v64 = tracer_load_integer_value(&elem_type->u.side_integer, |
582 | &array_item[bit / stride_bit].u.side_static.integer_value, | |
7f8e7e97 MD |
583 | 0, NULL); |
584 | if (v64.u & (1ULL << (bit % stride_bit))) { | |
af6aa6e1 MD |
585 | match = true; |
586 | goto match; | |
587 | } | |
af6aa6e1 | 588 | } |
ea32e5fc | 589 | } |
af6aa6e1 | 590 | match: |
ea32e5fc MD |
591 | if (match) { |
592 | printf("%s", print_count++ ? ", " : ""); | |
3bc9ba43 MD |
593 | tracer_print_string(side_ptr_get(mapping->label.p), mapping->label.unit_size, |
594 | side_enum_get(mapping->label.byte_order), NULL); | |
ea32e5fc MD |
595 | } |
596 | } | |
597 | if (!print_count) | |
598 | printf("<NO LABEL>"); | |
599 | printf(" ]"); | |
600 | } | |
601 | ||
1d9c515c MD |
602 | static |
603 | void print_integer_binary(uint64_t v, int bits) | |
604 | { | |
605 | int i; | |
606 | ||
607 | printf("0b"); | |
608 | v <<= 64 - bits; | |
609 | for (i = 0; i < bits; i++) { | |
610 | printf("%c", v & (1ULL << 63) ? '1' : '0'); | |
611 | v <<= 1; | |
612 | } | |
613 | } | |
614 | ||
0e9be766 | 615 | static |
aac52685 | 616 | void tracer_print_type_header(const char *separator, |
67337c4a | 617 | const struct side_attr *attr, uint32_t nr_attr) |
ac81c466 | 618 | { |
aac52685 MD |
619 | print_attributes("attr", separator, attr, nr_attr); |
620 | printf("%s", nr_attr ? ", " : ""); | |
621 | printf("value%s ", separator); | |
ac81c466 MD |
622 | } |
623 | ||
8ad2f385 MD |
624 | static |
625 | void tracer_print_type_bool(const char *separator, | |
67337c4a MD |
626 | const struct side_type_bool *type_bool, |
627 | const union side_bool_value *value, | |
8ad2f385 MD |
628 | uint16_t offset_bits) |
629 | { | |
88bab79c | 630 | uint32_t len_bits; |
8ad2f385 MD |
631 | bool reverse_bo; |
632 | uint64_t v; | |
633 | ||
88bab79c MD |
634 | if (!type_bool->len_bits) |
635 | len_bits = type_bool->bool_size * CHAR_BIT; | |
636 | else | |
637 | len_bits = type_bool->len_bits; | |
638 | if (len_bits + offset_bits > type_bool->bool_size * CHAR_BIT) | |
8ad2f385 | 639 | abort(); |
3bc9ba43 | 640 | reverse_bo = side_enum_get(type_bool->byte_order) != SIDE_TYPE_BYTE_ORDER_HOST; |
88bab79c MD |
641 | switch (type_bool->bool_size) { |
642 | case 1: | |
67337c4a | 643 | v = value->side_bool8; |
8ad2f385 | 644 | break; |
88bab79c | 645 | case 2: |
8ad2f385 | 646 | { |
67337c4a | 647 | uint16_t side_u16; |
8ad2f385 | 648 | |
67337c4a | 649 | side_u16 = value->side_bool16; |
8ad2f385 | 650 | if (reverse_bo) |
67337c4a MD |
651 | side_u16 = side_bswap_16(side_u16); |
652 | v = side_u16; | |
8ad2f385 MD |
653 | break; |
654 | } | |
88bab79c | 655 | case 4: |
8ad2f385 | 656 | { |
67337c4a | 657 | uint32_t side_u32; |
8ad2f385 | 658 | |
67337c4a | 659 | side_u32 = value->side_bool32; |
8ad2f385 | 660 | if (reverse_bo) |
67337c4a MD |
661 | side_u32 = side_bswap_32(side_u32); |
662 | v = side_u32; | |
8ad2f385 MD |
663 | break; |
664 | } | |
88bab79c | 665 | case 8: |
8ad2f385 | 666 | { |
67337c4a | 667 | uint64_t side_u64; |
8ad2f385 | 668 | |
67337c4a | 669 | side_u64 = value->side_bool64; |
8ad2f385 | 670 | if (reverse_bo) |
67337c4a MD |
671 | side_u64 = side_bswap_64(side_u64); |
672 | v = side_u64; | |
8ad2f385 MD |
673 | break; |
674 | } | |
675 | default: | |
676 | abort(); | |
677 | } | |
678 | v >>= offset_bits; | |
88bab79c MD |
679 | if (len_bits < 64) |
680 | v &= (1ULL << len_bits) - 1; | |
db8df9b5 | 681 | tracer_print_type_header(separator, side_ptr_get(type_bool->attr), type_bool->nr_attr); |
8ad2f385 MD |
682 | printf("%s", v ? "true" : "false"); |
683 | } | |
684 | ||
4f5e1b67 MD |
685 | static |
686 | void tracer_print_type_integer(const char *separator, | |
67337c4a MD |
687 | const struct side_type_integer *type_integer, |
688 | const union side_integer_value *value, | |
4f5e1b67 MD |
689 | uint16_t offset_bits, |
690 | enum tracer_display_base default_base) | |
691 | { | |
692 | enum tracer_display_base base; | |
693 | union int64_value v64; | |
694 | uint16_t len_bits; | |
695 | ||
696 | v64 = tracer_load_integer_value(type_integer, value, offset_bits, &len_bits); | |
12d787db MD |
697 | tracer_print_type_header(separator, side_ptr_get(type_integer->attr), type_integer->nr_attr); |
698 | base = get_attr_display_base(side_ptr_get(type_integer->attr), type_integer->nr_attr, default_base); | |
56c21987 MD |
699 | switch (base) { |
700 | case TRACER_DISPLAY_BASE_2: | |
4f5e1b67 | 701 | print_integer_binary(v64.u, len_bits); |
56c21987 MD |
702 | break; |
703 | case TRACER_DISPLAY_BASE_8: | |
f6a2a8ed MD |
704 | /* Clear sign bits beyond len_bits */ |
705 | if (len_bits < 64) | |
706 | v64.u &= (1ULL << len_bits) - 1; | |
4f5e1b67 | 707 | printf("0%" PRIo64, v64.u); |
56c21987 MD |
708 | break; |
709 | case TRACER_DISPLAY_BASE_10: | |
f6a2a8ed | 710 | if (type_integer->signedness) |
4f5e1b67 | 711 | printf("%" PRId64, v64.s); |
f6a2a8ed | 712 | else |
4f5e1b67 | 713 | printf("%" PRIu64, v64.u); |
56c21987 MD |
714 | break; |
715 | case TRACER_DISPLAY_BASE_16: | |
f6a2a8ed MD |
716 | /* Clear sign bits beyond len_bits */ |
717 | if (len_bits < 64) | |
718 | v64.u &= (1ULL << len_bits) - 1; | |
4f5e1b67 | 719 | printf("0x%" PRIx64, v64.u); |
56c21987 MD |
720 | break; |
721 | default: | |
722 | abort(); | |
723 | } | |
724 | } | |
725 | ||
3aa7ca5e MD |
726 | static |
727 | void tracer_print_type_float(const char *separator, | |
67337c4a MD |
728 | const struct side_type_float *type_float, |
729 | const union side_float_value *value) | |
3aa7ca5e MD |
730 | { |
731 | bool reverse_bo; | |
732 | ||
12d787db | 733 | tracer_print_type_header(separator, side_ptr_get(type_float->attr), type_float->nr_attr); |
3bc9ba43 | 734 | reverse_bo = side_enum_get(type_float->byte_order) != SIDE_TYPE_FLOAT_WORD_ORDER_HOST; |
88bab79c MD |
735 | switch (type_float->float_size) { |
736 | case 2: | |
3aa7ca5e MD |
737 | { |
738 | #if __HAVE_FLOAT16 | |
739 | union { | |
740 | _Float16 f; | |
741 | uint16_t u; | |
742 | } float16 = { | |
67337c4a | 743 | .f = value->side_float_binary16, |
3aa7ca5e MD |
744 | }; |
745 | ||
746 | if (reverse_bo) | |
67337c4a | 747 | float16.u = side_bswap_16(float16.u); |
3aa7ca5e MD |
748 | printf("%g", (double) float16.f); |
749 | break; | |
750 | #else | |
751 | fprintf(stderr, "ERROR: Unsupported binary16 float type\n"); | |
752 | abort(); | |
753 | #endif | |
754 | } | |
88bab79c | 755 | case 4: |
3aa7ca5e MD |
756 | { |
757 | #if __HAVE_FLOAT32 | |
758 | union { | |
759 | _Float32 f; | |
760 | uint32_t u; | |
761 | } float32 = { | |
67337c4a | 762 | .f = value->side_float_binary32, |
3aa7ca5e MD |
763 | }; |
764 | ||
765 | if (reverse_bo) | |
67337c4a | 766 | float32.u = side_bswap_32(float32.u); |
3aa7ca5e MD |
767 | printf("%g", (double) float32.f); |
768 | break; | |
769 | #else | |
770 | fprintf(stderr, "ERROR: Unsupported binary32 float type\n"); | |
771 | abort(); | |
772 | #endif | |
773 | } | |
88bab79c | 774 | case 8: |
3aa7ca5e MD |
775 | { |
776 | #if __HAVE_FLOAT64 | |
777 | union { | |
778 | _Float64 f; | |
779 | uint64_t u; | |
780 | } float64 = { | |
67337c4a | 781 | .f = value->side_float_binary64, |
3aa7ca5e MD |
782 | }; |
783 | ||
784 | if (reverse_bo) | |
67337c4a | 785 | float64.u = side_bswap_64(float64.u); |
3aa7ca5e MD |
786 | printf("%g", (double) float64.f); |
787 | break; | |
788 | #else | |
789 | fprintf(stderr, "ERROR: Unsupported binary64 float type\n"); | |
790 | abort(); | |
791 | #endif | |
792 | } | |
88bab79c | 793 | case 16: |
3aa7ca5e MD |
794 | { |
795 | #if __HAVE_FLOAT128 | |
796 | union { | |
797 | _Float128 f; | |
798 | char arr[16]; | |
799 | } float128 = { | |
67337c4a | 800 | .f = value->side_float_binary128, |
3aa7ca5e MD |
801 | }; |
802 | ||
803 | if (reverse_bo) | |
67337c4a | 804 | side_bswap_128p(float128.arr); |
3aa7ca5e MD |
805 | printf("%Lg", (long double) float128.f); |
806 | break; | |
807 | #else | |
808 | fprintf(stderr, "ERROR: Unsupported binary128 float type\n"); | |
809 | abort(); | |
810 | #endif | |
811 | } | |
812 | default: | |
813 | fprintf(stderr, "ERROR: Unknown float size\n"); | |
814 | abort(); | |
815 | } | |
816 | } | |
817 | ||
f611d0c3 | 818 | static |
67337c4a | 819 | void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item) |
f611d0c3 | 820 | { |
67337c4a | 821 | enum side_type_label type; |
d8be25de | 822 | |
3ce69bfa | 823 | switch (side_enum_get(type_desc->type)) { |
67337c4a | 824 | case SIDE_TYPE_ENUM: |
3ce69bfa | 825 | switch (side_enum_get(item->type)) { |
67337c4a MD |
826 | case SIDE_TYPE_U8: |
827 | case SIDE_TYPE_U16: | |
828 | case SIDE_TYPE_U32: | |
829 | case SIDE_TYPE_U64: | |
830 | case SIDE_TYPE_S8: | |
831 | case SIDE_TYPE_S16: | |
832 | case SIDE_TYPE_S32: | |
833 | case SIDE_TYPE_S64: | |
bab5d6e4 MD |
834 | break; |
835 | default: | |
de1b3cd2 | 836 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); |
45392033 MD |
837 | abort(); |
838 | break; | |
839 | } | |
840 | break; | |
841 | ||
67337c4a | 842 | case SIDE_TYPE_ENUM_BITMAP: |
3ce69bfa | 843 | switch (side_enum_get(item->type)) { |
67337c4a MD |
844 | case SIDE_TYPE_U8: |
845 | case SIDE_TYPE_BYTE: | |
846 | case SIDE_TYPE_U16: | |
847 | case SIDE_TYPE_U32: | |
848 | case SIDE_TYPE_U64: | |
849 | case SIDE_TYPE_ARRAY: | |
850 | case SIDE_TYPE_VLA: | |
45392033 MD |
851 | break; |
852 | default: | |
de1b3cd2 | 853 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); |
45392033 MD |
854 | abort(); |
855 | break; | |
d8be25de MD |
856 | } |
857 | break; | |
858 | ||
67337c4a | 859 | case SIDE_TYPE_GATHER_ENUM: |
3ce69bfa | 860 | switch (side_enum_get(item->type)) { |
67337c4a | 861 | case SIDE_TYPE_GATHER_INTEGER: |
0519cb86 MD |
862 | break; |
863 | default: | |
864 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
865 | abort(); | |
866 | break; | |
867 | } | |
868 | break; | |
869 | ||
67337c4a | 870 | case SIDE_TYPE_DYNAMIC: |
3ce69bfa | 871 | switch (side_enum_get(item->type)) { |
67337c4a MD |
872 | case SIDE_TYPE_DYNAMIC_NULL: |
873 | case SIDE_TYPE_DYNAMIC_BOOL: | |
874 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
875 | case SIDE_TYPE_DYNAMIC_BYTE: | |
876 | case SIDE_TYPE_DYNAMIC_POINTER: | |
877 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
878 | case SIDE_TYPE_DYNAMIC_STRING: | |
879 | case SIDE_TYPE_DYNAMIC_STRUCT: | |
880 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
881 | case SIDE_TYPE_DYNAMIC_VLA: | |
882 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
66de373e MD |
883 | break; |
884 | default: | |
885 | fprintf(stderr, "ERROR: Unexpected dynamic type\n"); | |
886 | abort(); | |
887 | break; | |
888 | } | |
889 | break; | |
890 | ||
ba845af5 | 891 | default: |
3ce69bfa | 892 | if (side_enum_get(type_desc->type) != side_enum_get(item->type)) { |
de1b3cd2 | 893 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); |
ba845af5 MD |
894 | abort(); |
895 | } | |
896 | break; | |
f611d0c3 | 897 | } |
d8be25de | 898 | |
3ce69bfa MD |
899 | 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) |
900 | type = side_enum_get(type_desc->type); | |
d8be25de | 901 | else |
3ce69bfa | 902 | type = side_enum_get(item->type); |
d8be25de | 903 | |
a848763d | 904 | printf("{ "); |
d8be25de | 905 | switch (type) { |
55fb50b7 | 906 | /* Stack-copy basic types */ |
67337c4a | 907 | case SIDE_TYPE_NULL: |
b313067b MD |
908 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_null.attr), |
909 | type_desc->u.side_null.nr_attr); | |
9b641221 MD |
910 | printf("<NULL TYPE>"); |
911 | break; | |
912 | ||
67337c4a MD |
913 | case SIDE_TYPE_BOOL: |
914 | tracer_print_type_bool(":", &type_desc->u.side_bool, &item->u.side_static.bool_value, 0); | |
4f40d951 | 915 | break; |
1d9c515c | 916 | |
67337c4a MD |
917 | case SIDE_TYPE_U8: |
918 | case SIDE_TYPE_U16: | |
919 | case SIDE_TYPE_U32: | |
920 | case SIDE_TYPE_U64: | |
921 | case SIDE_TYPE_S8: | |
922 | case SIDE_TYPE_S16: | |
923 | case SIDE_TYPE_S32: | |
924 | case SIDE_TYPE_S64: | |
925 | tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0, | |
f0dafd60 | 926 | TRACER_DISPLAY_BASE_10); |
f611d0c3 | 927 | break; |
56c21987 | 928 | |
67337c4a | 929 | case SIDE_TYPE_BYTE: |
12d787db | 930 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_byte.attr), type_desc->u.side_byte.nr_attr); |
67337c4a | 931 | printf("0x%" PRIx8, item->u.side_static.byte_value); |
7aec0d09 | 932 | break; |
79f677ba | 933 | |
67337c4a MD |
934 | case SIDE_TYPE_POINTER: |
935 | tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0, | |
55fb50b7 | 936 | TRACER_DISPLAY_BASE_16); |
ea32e5fc MD |
937 | break; |
938 | ||
67337c4a MD |
939 | case SIDE_TYPE_FLOAT_BINARY16: |
940 | case SIDE_TYPE_FLOAT_BINARY32: | |
941 | case SIDE_TYPE_FLOAT_BINARY64: | |
942 | case SIDE_TYPE_FLOAT_BINARY128: | |
943 | tracer_print_type_float(":", &type_desc->u.side_float, &item->u.side_static.float_value); | |
fb25b355 | 944 | break; |
3aa7ca5e | 945 | |
67337c4a MD |
946 | case SIDE_TYPE_STRING_UTF8: |
947 | case SIDE_TYPE_STRING_UTF16: | |
948 | case SIDE_TYPE_STRING_UTF32: | |
12d787db | 949 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_string.attr), type_desc->u.side_string.nr_attr); |
6910c28c | 950 | tracer_print_string(side_ptr_get(item->u.side_static.string_value), |
3bc9ba43 | 951 | type_desc->u.side_string.unit_size, side_enum_get(type_desc->u.side_string.byte_order), NULL); |
f611d0c3 | 952 | break; |
55fb50b7 MD |
953 | |
954 | /* Stack-copy compound types */ | |
67337c4a | 955 | case SIDE_TYPE_STRUCT: |
bac71609 | 956 | tracer_print_struct(type_desc, side_ptr_get(item->u.side_static.side_struct)); |
f611d0c3 | 957 | break; |
5530345d | 958 | case SIDE_TYPE_VARIANT: |
bac71609 | 959 | tracer_print_variant(type_desc, side_ptr_get(item->u.side_static.side_variant)); |
5530345d | 960 | break; |
67337c4a | 961 | case SIDE_TYPE_ARRAY: |
bac71609 | 962 | tracer_print_array(type_desc, side_ptr_get(item->u.side_static.side_array)); |
d9359cfa | 963 | break; |
67337c4a | 964 | case SIDE_TYPE_VLA: |
bac71609 | 965 | tracer_print_vla(type_desc, side_ptr_get(item->u.side_static.side_vla)); |
33956c71 | 966 | break; |
67337c4a MD |
967 | case SIDE_TYPE_VLA_VISITOR: |
968 | tracer_print_vla_visitor(type_desc, item->u.side_static.side_vla_app_visitor_ctx); | |
80429681 | 969 | break; |
55fb50b7 MD |
970 | |
971 | /* Stack-copy enumeration types */ | |
67337c4a | 972 | case SIDE_TYPE_ENUM: |
f6a2a8ed | 973 | tracer_print_enum(type_desc, item); |
55fb50b7 | 974 | break; |
67337c4a | 975 | case SIDE_TYPE_ENUM_BITMAP: |
7f8e7e97 | 976 | tracer_print_enum_bitmap(type_desc, item); |
55fb50b7 MD |
977 | break; |
978 | ||
979 | /* Gather basic types */ | |
67337c4a | 980 | case SIDE_TYPE_GATHER_BOOL: |
155b1756 | 981 | (void) tracer_print_gather_bool_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_bool_gather_ptr)); |
8ad2f385 | 982 | break; |
67337c4a | 983 | case SIDE_TYPE_GATHER_INTEGER: |
155b1756 | 984 | (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), |
55fb50b7 MD |
985 | TRACER_DISPLAY_BASE_10); |
986 | break; | |
67337c4a | 987 | case SIDE_TYPE_GATHER_BYTE: |
155b1756 | 988 | (void) tracer_print_gather_byte_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_byte_gather_ptr)); |
d69918cc | 989 | break; |
67337c4a | 990 | case SIDE_TYPE_GATHER_POINTER: |
155b1756 | 991 | (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), |
4e1b0e0e MD |
992 | TRACER_DISPLAY_BASE_16); |
993 | break; | |
67337c4a | 994 | case SIDE_TYPE_GATHER_FLOAT: |
155b1756 | 995 | (void) tracer_print_gather_float_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_float_gather_ptr)); |
905f68e3 | 996 | break; |
67337c4a | 997 | case SIDE_TYPE_GATHER_STRING: |
155b1756 | 998 | (void) tracer_print_gather_string_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_string_gather_ptr)); |
7d34edfc | 999 | break; |
55fb50b7 MD |
1000 | |
1001 | /* Gather compound type */ | |
67337c4a | 1002 | case SIDE_TYPE_GATHER_STRUCT: |
155b1756 | 1003 | (void) tracer_print_gather_struct(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_struct_gather_ptr)); |
f611d0c3 | 1004 | break; |
67337c4a | 1005 | case SIDE_TYPE_GATHER_ARRAY: |
155b1756 | 1006 | (void) tracer_print_gather_array(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr)); |
f611d0c3 | 1007 | break; |
67337c4a | 1008 | case SIDE_TYPE_GATHER_VLA: |
155b1756 MD |
1009 | (void) tracer_print_gather_vla(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_vla_gather.ptr), |
1010 | side_ptr_get(item->u.side_static.side_vla_gather.length_ptr)); | |
f611d0c3 | 1011 | break; |
66de373e | 1012 | |
0519cb86 | 1013 | /* Gather enumeration types */ |
67337c4a | 1014 | case SIDE_TYPE_GATHER_ENUM: |
155b1756 | 1015 | (void) tracer_print_gather_enum_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr)); |
0519cb86 MD |
1016 | break; |
1017 | ||
55fb50b7 | 1018 | /* Dynamic basic types */ |
67337c4a MD |
1019 | case SIDE_TYPE_DYNAMIC_NULL: |
1020 | case SIDE_TYPE_DYNAMIC_BOOL: | |
1021 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
1022 | case SIDE_TYPE_DYNAMIC_BYTE: | |
1023 | case SIDE_TYPE_DYNAMIC_POINTER: | |
1024 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
1025 | case SIDE_TYPE_DYNAMIC_STRING: | |
55fb50b7 MD |
1026 | |
1027 | /* Dynamic compound types */ | |
67337c4a MD |
1028 | case SIDE_TYPE_DYNAMIC_STRUCT: |
1029 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
1030 | case SIDE_TYPE_DYNAMIC_VLA: | |
1031 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
66de373e | 1032 | tracer_print_dynamic(item); |
a2e2357e | 1033 | break; |
f611d0c3 | 1034 | default: |
f6c02218 | 1035 | fprintf(stderr, "<UNKNOWN TYPE>\n"); |
f611d0c3 MD |
1036 | abort(); |
1037 | } | |
a848763d | 1038 | printf(" }"); |
f611d0c3 MD |
1039 | } |
1040 | ||
1041 | static | |
67337c4a | 1042 | void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg *item) |
f611d0c3 | 1043 | { |
c5789285 | 1044 | printf("%s: ", side_ptr_get(item_desc->field_name)); |
67337c4a | 1045 | tracer_print_type(&item_desc->side_type, item); |
f611d0c3 MD |
1046 | } |
1047 | ||
1048 | static | |
67337c4a | 1049 | void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
f611d0c3 | 1050 | { |
f13253cb | 1051 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
c5789285 | 1052 | const struct side_type_struct *side_struct = side_ptr_get(type_desc->u.side_struct); |
67337c4a | 1053 | uint32_t i, side_sav_len = side_arg_vec->len; |
f611d0c3 | 1054 | |
c5789285 | 1055 | if (side_struct->nr_fields != side_sav_len) { |
de1b3cd2 | 1056 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n"); |
f611d0c3 MD |
1057 | abort(); |
1058 | } | |
c5789285 MD |
1059 | print_attributes("attr", ":", side_ptr_get(side_struct->attr), side_struct->nr_attr); |
1060 | printf("%s", side_struct->nr_attr ? ", " : ""); | |
73b2b0c2 | 1061 | printf("fields: { "); |
67337c4a | 1062 | for (i = 0; i < side_sav_len; i++) { |
f611d0c3 | 1063 | printf("%s", i ? ", " : ""); |
c5789285 | 1064 | tracer_print_field(&side_ptr_get(side_struct->fields)[i], &sav[i]); |
f611d0c3 | 1065 | } |
d4328528 | 1066 | printf(" }"); |
f611d0c3 MD |
1067 | } |
1068 | ||
5530345d MD |
1069 | static |
1070 | void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant) | |
1071 | { | |
c5789285 | 1072 | const struct side_type_variant *side_type_variant = side_ptr_get(type_desc->u.side_variant); |
5530345d MD |
1073 | const struct side_type *selector_type = &side_type_variant->selector; |
1074 | union int64_value v64; | |
1075 | uint32_t i; | |
1076 | ||
3ce69bfa | 1077 | if (side_enum_get(selector_type->type) != side_enum_get(side_arg_variant->selector.type)) { |
5530345d MD |
1078 | fprintf(stderr, "ERROR: Unexpected variant selector type\n"); |
1079 | abort(); | |
1080 | } | |
3ce69bfa | 1081 | switch (side_enum_get(selector_type->type)) { |
5530345d MD |
1082 | case SIDE_TYPE_U8: |
1083 | case SIDE_TYPE_U16: | |
1084 | case SIDE_TYPE_U32: | |
1085 | case SIDE_TYPE_U64: | |
1086 | case SIDE_TYPE_S8: | |
1087 | case SIDE_TYPE_S16: | |
1088 | case SIDE_TYPE_S32: | |
1089 | case SIDE_TYPE_S64: | |
1090 | break; | |
1091 | default: | |
1092 | fprintf(stderr, "ERROR: Expecting integer variant selector type\n"); | |
1093 | abort(); | |
1094 | } | |
1095 | v64 = tracer_load_integer_value(&selector_type->u.side_integer, | |
1096 | &side_arg_variant->selector.u.side_static.integer_value, 0, NULL); | |
1097 | for (i = 0; i < side_type_variant->nr_options; i++) { | |
c5789285 | 1098 | const struct side_variant_option *option = &side_ptr_get(side_type_variant->options)[i]; |
5530345d MD |
1099 | |
1100 | if (v64.s >= option->range_begin && v64.s <= option->range_end) { | |
1101 | tracer_print_type(&option->side_type, &side_arg_variant->option); | |
1102 | return; | |
1103 | } | |
1104 | } | |
1105 | fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v64.s); | |
1106 | abort(); | |
1107 | } | |
1108 | ||
7a1cb105 | 1109 | static |
67337c4a | 1110 | void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
d9359cfa | 1111 | { |
f13253cb | 1112 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 1113 | uint32_t i, side_sav_len = side_arg_vec->len; |
d9359cfa | 1114 | |
67337c4a | 1115 | if (type_desc->u.side_array.length != side_sav_len) { |
d9359cfa MD |
1116 | fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n"); |
1117 | abort(); | |
1118 | } | |
12d787db | 1119 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_array.attr), type_desc->u.side_array.nr_attr); |
67337c4a | 1120 | printf("%s", type_desc->u.side_array.nr_attr ? ", " : ""); |
d9359cfa MD |
1121 | printf("elements: "); |
1122 | printf("[ "); | |
67337c4a | 1123 | for (i = 0; i < side_sav_len; i++) { |
d9359cfa | 1124 | printf("%s", i ? ", " : ""); |
c5789285 | 1125 | tracer_print_type(side_ptr_get(type_desc->u.side_array.elem_type), &sav[i]); |
d9359cfa MD |
1126 | } |
1127 | printf(" ]"); | |
1128 | } | |
1129 | ||
1130 | static | |
67337c4a | 1131 | void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
d9359cfa | 1132 | { |
f13253cb | 1133 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 1134 | uint32_t i, side_sav_len = side_arg_vec->len; |
d9359cfa | 1135 | |
12d787db | 1136 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_vla.attr), type_desc->u.side_vla.nr_attr); |
67337c4a | 1137 | printf("%s", type_desc->u.side_vla.nr_attr ? ", " : ""); |
d9359cfa MD |
1138 | printf("elements: "); |
1139 | printf("[ "); | |
67337c4a | 1140 | for (i = 0; i < side_sav_len; i++) { |
d9359cfa | 1141 | printf("%s", i ? ", " : ""); |
c5789285 | 1142 | tracer_print_type(side_ptr_get(type_desc->u.side_vla.elem_type), &sav[i]); |
d9359cfa MD |
1143 | } |
1144 | printf(" ]"); | |
1145 | } | |
1146 | ||
dd7947bf | 1147 | static |
67337c4a | 1148 | const char *tracer_gather_access(enum side_type_gather_access_mode access_mode, const char *ptr) |
dd7947bf | 1149 | { |
65b8734a | 1150 | switch (access_mode) { |
67337c4a | 1151 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: |
dd7947bf | 1152 | return ptr; |
67337c4a | 1153 | case SIDE_TYPE_GATHER_ACCESS_POINTER: |
dd7947bf | 1154 | /* Dereference pointer */ |
dc9567a6 | 1155 | memcpy(&ptr, ptr, sizeof(const char *)); |
dd7947bf MD |
1156 | return ptr; |
1157 | default: | |
1158 | abort(); | |
1159 | } | |
1160 | } | |
1161 | ||
1162 | static | |
67337c4a | 1163 | uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode, uint32_t len) |
dd7947bf | 1164 | { |
65b8734a | 1165 | switch (access_mode) { |
67337c4a | 1166 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: |
dd7947bf | 1167 | return len; |
67337c4a | 1168 | case SIDE_TYPE_GATHER_ACCESS_POINTER: |
dd7947bf MD |
1169 | return sizeof(void *); |
1170 | default: | |
1171 | abort(); | |
1172 | } | |
1173 | } | |
1174 | ||
d9359cfa | 1175 | static |
67337c4a | 1176 | union int64_value tracer_load_gather_integer_value(const struct side_type_gather_integer *side_integer, |
0519cb86 | 1177 | const void *_ptr) |
7a1cb105 | 1178 | { |
67337c4a MD |
1179 | enum side_type_gather_access_mode access_mode = |
1180 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
1181 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
7a1cb105 | 1182 | const char *ptr = (const char *) _ptr; |
67337c4a | 1183 | union side_integer_value value; |
65b8734a | 1184 | |
67337c4a | 1185 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); |
65b8734a | 1186 | memcpy(&value, ptr, integer_size_bytes); |
67337c4a MD |
1187 | return tracer_load_integer_value(&side_integer->type, &value, |
1188 | side_integer->offset_bits, NULL); | |
65b8734a MD |
1189 | } |
1190 | ||
8ad2f385 | 1191 | static |
67337c4a | 1192 | uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr) |
8ad2f385 | 1193 | { |
67337c4a MD |
1194 | enum side_type_gather_access_mode access_mode = |
1195 | (enum side_type_gather_access_mode) type_gather->u.side_bool.access_mode; | |
1196 | uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size; | |
8ad2f385 | 1197 | const char *ptr = (const char *) _ptr; |
67337c4a | 1198 | union side_bool_value value; |
8ad2f385 | 1199 | |
88bab79c MD |
1200 | switch (bool_size_bytes) { |
1201 | case 1: | |
1202 | case 2: | |
1203 | case 4: | |
8ad2f385 | 1204 | case 8: |
8ad2f385 MD |
1205 | break; |
1206 | default: | |
1207 | abort(); | |
1208 | } | |
67337c4a | 1209 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset); |
8ad2f385 | 1210 | memcpy(&value, ptr, bool_size_bytes); |
67337c4a MD |
1211 | tracer_print_type_bool(":", &type_gather->u.side_bool.type, &value, |
1212 | type_gather->u.side_bool.offset_bits); | |
8ad2f385 MD |
1213 | return tracer_gather_size(access_mode, bool_size_bytes); |
1214 | } | |
1215 | ||
d69918cc | 1216 | static |
67337c4a | 1217 | uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr) |
d69918cc | 1218 | { |
67337c4a MD |
1219 | enum side_type_gather_access_mode access_mode = |
1220 | (enum side_type_gather_access_mode) type_gather->u.side_byte.access_mode; | |
d69918cc MD |
1221 | const char *ptr = (const char *) _ptr; |
1222 | uint8_t value; | |
1223 | ||
67337c4a | 1224 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset); |
d69918cc | 1225 | memcpy(&value, ptr, 1); |
12d787db | 1226 | tracer_print_type_header(":", side_ptr_get(type_gather->u.side_byte.type.attr), |
67337c4a | 1227 | type_gather->u.side_byte.type.nr_attr); |
d69918cc MD |
1228 | printf("0x%" PRIx8, value); |
1229 | return tracer_gather_size(access_mode, 1); | |
1230 | } | |
1231 | ||
65b8734a | 1232 | static |
67337c4a | 1233 | uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr, |
4e1b0e0e | 1234 | enum tracer_display_base default_base) |
65b8734a | 1235 | { |
67337c4a MD |
1236 | enum side_type_gather_access_mode access_mode = |
1237 | (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode; | |
1238 | uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size; | |
65b8734a | 1239 | const char *ptr = (const char *) _ptr; |
67337c4a | 1240 | union side_integer_value value; |
7a1cb105 | 1241 | |
88bab79c MD |
1242 | switch (integer_size_bytes) { |
1243 | case 1: | |
1244 | case 2: | |
1245 | case 4: | |
33956c71 | 1246 | case 8: |
9b641221 | 1247 | break; |
33956c71 MD |
1248 | default: |
1249 | abort(); | |
1250 | } | |
67337c4a | 1251 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset); |
dd7947bf | 1252 | memcpy(&value, ptr, integer_size_bytes); |
67337c4a MD |
1253 | tracer_print_type_integer(":", &type_gather->u.side_integer.type, &value, |
1254 | type_gather->u.side_integer.offset_bits, default_base); | |
d41cb7ee | 1255 | return tracer_gather_size(access_mode, integer_size_bytes); |
33956c71 | 1256 | } |
9b641221 | 1257 | |
905f68e3 | 1258 | static |
67337c4a | 1259 | uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr) |
905f68e3 | 1260 | { |
67337c4a MD |
1261 | enum side_type_gather_access_mode access_mode = |
1262 | (enum side_type_gather_access_mode) type_gather->u.side_float.access_mode; | |
1263 | uint32_t float_size_bytes = type_gather->u.side_float.type.float_size; | |
905f68e3 | 1264 | const char *ptr = (const char *) _ptr; |
67337c4a | 1265 | union side_float_value value; |
905f68e3 | 1266 | |
88bab79c MD |
1267 | switch (float_size_bytes) { |
1268 | case 2: | |
1269 | case 4: | |
1270 | case 8: | |
905f68e3 | 1271 | case 16: |
905f68e3 MD |
1272 | break; |
1273 | default: | |
1274 | abort(); | |
1275 | } | |
67337c4a | 1276 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset); |
dd7947bf | 1277 | memcpy(&value, ptr, float_size_bytes); |
67337c4a | 1278 | tracer_print_type_float(":", &type_gather->u.side_float.type, &value); |
d41cb7ee | 1279 | return tracer_gather_size(access_mode, float_size_bytes); |
905f68e3 MD |
1280 | } |
1281 | ||
7d34edfc | 1282 | static |
67337c4a | 1283 | uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr) |
7d34edfc | 1284 | { |
67337c4a MD |
1285 | enum side_type_gather_access_mode access_mode = |
1286 | (enum side_type_gather_access_mode) type_gather->u.side_string.access_mode; | |
7d34edfc MD |
1287 | const char *ptr = (const char *) _ptr; |
1288 | size_t string_len; | |
1289 | ||
67337c4a | 1290 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset); |
12d787db | 1291 | tracer_print_type_header(":", side_ptr_get(type_gather->u.side_string.type.attr), |
67337c4a | 1292 | type_gather->u.side_string.type.nr_attr); |
7d34edfc | 1293 | if (ptr) { |
67337c4a | 1294 | tracer_print_string(ptr, type_gather->u.side_string.type.unit_size, |
3bc9ba43 | 1295 | side_enum_get(type_gather->u.side_string.type.byte_order), &string_len); |
7d34edfc MD |
1296 | } else { |
1297 | printf("<NULL>"); | |
67337c4a | 1298 | string_len = type_gather->u.side_string.type.unit_size; |
7d34edfc MD |
1299 | } |
1300 | return tracer_gather_size(access_mode, string_len); | |
1301 | } | |
1302 | ||
33956c71 | 1303 | static |
67337c4a | 1304 | uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void *ptr) |
33956c71 | 1305 | { |
d9359cfa MD |
1306 | uint32_t len; |
1307 | ||
33956c71 | 1308 | printf("{ "); |
3ce69bfa | 1309 | switch (side_enum_get(type_desc->type)) { |
55fb50b7 | 1310 | /* Gather basic types */ |
67337c4a MD |
1311 | case SIDE_TYPE_GATHER_BOOL: |
1312 | len = tracer_print_gather_bool_type(&type_desc->u.side_gather, ptr); | |
8ad2f385 | 1313 | break; |
67337c4a MD |
1314 | case SIDE_TYPE_GATHER_INTEGER: |
1315 | len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr, | |
55fb50b7 MD |
1316 | TRACER_DISPLAY_BASE_10); |
1317 | break; | |
67337c4a MD |
1318 | case SIDE_TYPE_GATHER_BYTE: |
1319 | len = tracer_print_gather_byte_type(&type_desc->u.side_gather, ptr); | |
d69918cc | 1320 | break; |
67337c4a MD |
1321 | case SIDE_TYPE_GATHER_POINTER: |
1322 | len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr, | |
4e1b0e0e MD |
1323 | TRACER_DISPLAY_BASE_16); |
1324 | break; | |
67337c4a MD |
1325 | case SIDE_TYPE_GATHER_FLOAT: |
1326 | len = tracer_print_gather_float_type(&type_desc->u.side_gather, ptr); | |
33956c71 | 1327 | break; |
67337c4a MD |
1328 | case SIDE_TYPE_GATHER_STRING: |
1329 | len = tracer_print_gather_string_type(&type_desc->u.side_gather, ptr); | |
7d34edfc | 1330 | break; |
55fb50b7 | 1331 | |
0519cb86 | 1332 | /* Gather enum types */ |
67337c4a MD |
1333 | case SIDE_TYPE_GATHER_ENUM: |
1334 | len = tracer_print_gather_enum_type(&type_desc->u.side_gather, ptr); | |
0519cb86 MD |
1335 | break; |
1336 | ||
55fb50b7 | 1337 | /* Gather compound types */ |
67337c4a MD |
1338 | case SIDE_TYPE_GATHER_STRUCT: |
1339 | len = tracer_print_gather_struct(&type_desc->u.side_gather, ptr); | |
d9359cfa | 1340 | break; |
67337c4a MD |
1341 | case SIDE_TYPE_GATHER_ARRAY: |
1342 | len = tracer_print_gather_array(&type_desc->u.side_gather, ptr); | |
9b641221 | 1343 | break; |
67337c4a MD |
1344 | case SIDE_TYPE_GATHER_VLA: |
1345 | len = tracer_print_gather_vla(&type_desc->u.side_gather, ptr, ptr); | |
65b8734a | 1346 | break; |
9b641221 | 1347 | default: |
d41cb7ee | 1348 | fprintf(stderr, "<UNKNOWN GATHER TYPE>"); |
9b641221 | 1349 | abort(); |
7a1cb105 MD |
1350 | } |
1351 | printf(" }"); | |
d9359cfa | 1352 | return len; |
7a1cb105 MD |
1353 | } |
1354 | ||
0519cb86 | 1355 | static |
67337c4a | 1356 | uint32_t tracer_print_gather_enum_type(const struct side_type_gather *type_gather, const void *_ptr) |
0519cb86 | 1357 | { |
64037418 | 1358 | const struct side_enum_mappings *mappings = side_ptr_get(type_gather->u.side_enum.mappings); |
c5789285 | 1359 | const struct side_type *enum_elem_type = side_ptr_get(type_gather->u.side_enum.elem_type); |
67337c4a MD |
1360 | const struct side_type_gather_integer *side_integer = &enum_elem_type->u.side_gather.u.side_integer; |
1361 | enum side_type_gather_access_mode access_mode = | |
1362 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
1363 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
0519cb86 | 1364 | const char *ptr = (const char *) _ptr; |
67337c4a | 1365 | union side_integer_value value; |
0519cb86 MD |
1366 | union int64_value v64; |
1367 | ||
1368 | switch (integer_size_bytes) { | |
1369 | case 1: | |
1370 | case 2: | |
1371 | case 4: | |
1372 | case 8: | |
1373 | break; | |
1374 | default: | |
1375 | abort(); | |
1376 | } | |
67337c4a | 1377 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); |
0519cb86 | 1378 | memcpy(&value, ptr, integer_size_bytes); |
67337c4a | 1379 | v64 = tracer_load_gather_integer_value(side_integer, &value); |
12d787db | 1380 | print_attributes("attr", ":", side_ptr_get(mappings->attr), mappings->nr_attr); |
0519cb86 MD |
1381 | printf("%s", mappings->nr_attr ? ", " : ""); |
1382 | tracer_print_gather_type(enum_elem_type, ptr); | |
1383 | print_enum_labels(mappings, v64); | |
1384 | return tracer_gather_size(access_mode, integer_size_bytes); | |
1385 | } | |
1386 | ||
7a1cb105 | 1387 | static |
67337c4a | 1388 | void tracer_print_gather_field(const struct side_event_field *field, const void *ptr) |
7a1cb105 | 1389 | { |
c5789285 | 1390 | printf("%s: ", side_ptr_get(field->field_name)); |
67337c4a | 1391 | (void) tracer_print_gather_type(&field->side_type, ptr); |
7a1cb105 MD |
1392 | } |
1393 | ||
1394 | static | |
67337c4a | 1395 | uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr) |
7a1cb105 | 1396 | { |
67337c4a MD |
1397 | enum side_type_gather_access_mode access_mode = |
1398 | (enum side_type_gather_access_mode) type_gather->u.side_struct.access_mode; | |
c5789285 | 1399 | const struct side_type_struct *side_struct = side_ptr_get(type_gather->u.side_struct.type); |
dd7947bf | 1400 | const char *ptr = (const char *) _ptr; |
e65f9ce5 | 1401 | uint32_t i; |
7a1cb105 | 1402 | |
67337c4a | 1403 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_struct.offset); |
c5789285 MD |
1404 | print_attributes("attr", ":", side_ptr_get(side_struct->attr), side_struct->nr_attr); |
1405 | printf("%s", side_struct->nr_attr ? ", " : ""); | |
7a1cb105 | 1406 | printf("fields: { "); |
c5789285 | 1407 | for (i = 0; i < side_struct->nr_fields; i++) { |
7a1cb105 | 1408 | printf("%s", i ? ", " : ""); |
c5789285 | 1409 | tracer_print_gather_field(&side_ptr_get(side_struct->fields)[i], ptr); |
7a1cb105 MD |
1410 | } |
1411 | printf(" }"); | |
67337c4a | 1412 | return tracer_gather_size(access_mode, type_gather->u.side_struct.size); |
7a1cb105 MD |
1413 | } |
1414 | ||
f611d0c3 | 1415 | static |
67337c4a | 1416 | uint32_t tracer_print_gather_array(const struct side_type_gather *type_gather, const void *_ptr) |
f611d0c3 | 1417 | { |
67337c4a MD |
1418 | enum side_type_gather_access_mode access_mode = |
1419 | (enum side_type_gather_access_mode) type_gather->u.side_array.access_mode; | |
dd7947bf | 1420 | const char *ptr = (const char *) _ptr, *orig_ptr; |
d9359cfa | 1421 | uint32_t i; |
f611d0c3 | 1422 | |
67337c4a | 1423 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_array.offset); |
65b8734a | 1424 | orig_ptr = ptr; |
12d787db | 1425 | print_attributes("attr", ":", side_ptr_get(type_gather->u.side_array.type.attr), type_gather->u.side_array.type.nr_attr); |
67337c4a | 1426 | printf("%s", type_gather->u.side_array.type.nr_attr ? ", " : ""); |
65b8734a MD |
1427 | printf("elements: "); |
1428 | printf("[ "); | |
67337c4a | 1429 | for (i = 0; i < type_gather->u.side_array.type.length; i++) { |
c5789285 MD |
1430 | const struct side_type *elem_type = side_ptr_get(type_gather->u.side_array.type.elem_type); |
1431 | ||
3ce69bfa | 1432 | switch (side_enum_get(elem_type->type)) { |
67337c4a | 1433 | case SIDE_TYPE_GATHER_VLA: |
d41cb7ee | 1434 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); |
65b8734a MD |
1435 | abort(); |
1436 | default: | |
1437 | break; | |
1438 | } | |
1439 | printf("%s", i ? ", " : ""); | |
c5789285 | 1440 | ptr += tracer_print_gather_type(elem_type, ptr); |
65b8734a MD |
1441 | } |
1442 | printf(" ]"); | |
d41cb7ee | 1443 | return tracer_gather_size(access_mode, ptr - orig_ptr); |
65b8734a MD |
1444 | } |
1445 | ||
1446 | static | |
67337c4a | 1447 | uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, const void *_ptr, |
80429681 | 1448 | const void *_length_ptr) |
65b8734a | 1449 | { |
67337c4a MD |
1450 | enum side_type_gather_access_mode access_mode = |
1451 | (enum side_type_gather_access_mode) type_gather->u.side_vla.access_mode; | |
c5789285 | 1452 | const struct side_type *length_type = side_ptr_get(type_gather->u.side_vla.length_type); |
65b8734a | 1453 | const char *ptr = (const char *) _ptr, *orig_ptr; |
80429681 | 1454 | const char *length_ptr = (const char *) _length_ptr; |
4f5e1b67 | 1455 | union int64_value v64; |
65b8734a MD |
1456 | uint32_t i, length; |
1457 | ||
1458 | /* Access length */ | |
3ce69bfa | 1459 | switch (side_enum_get(length_type->type)) { |
67337c4a | 1460 | case SIDE_TYPE_GATHER_INTEGER: |
65b8734a MD |
1461 | break; |
1462 | default: | |
d41cb7ee | 1463 | fprintf(stderr, "<gather VLA expects integer gather length type>\n"); |
65b8734a MD |
1464 | abort(); |
1465 | } | |
c5789285 | 1466 | v64 = tracer_load_gather_integer_value(&length_type->u.side_gather.u.side_integer, |
0519cb86 | 1467 | length_ptr); |
4f5e1b67 | 1468 | length = (uint32_t) v64.u; |
67337c4a | 1469 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_vla.offset); |
dd7947bf | 1470 | orig_ptr = ptr; |
12d787db | 1471 | print_attributes("attr", ":", side_ptr_get(type_gather->u.side_vla.type.attr), type_gather->u.side_vla.type.nr_attr); |
67337c4a | 1472 | printf("%s", type_gather->u.side_vla.type.nr_attr ? ", " : ""); |
20574104 | 1473 | printf("elements: "); |
f611d0c3 | 1474 | printf("[ "); |
65b8734a | 1475 | for (i = 0; i < length; i++) { |
c5789285 MD |
1476 | const struct side_type *elem_type = side_ptr_get(type_gather->u.side_vla.type.elem_type); |
1477 | ||
3ce69bfa | 1478 | switch (side_enum_get(elem_type->type)) { |
67337c4a | 1479 | case SIDE_TYPE_GATHER_VLA: |
d41cb7ee | 1480 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); |
65b8734a MD |
1481 | abort(); |
1482 | default: | |
1483 | break; | |
1484 | } | |
f611d0c3 | 1485 | printf("%s", i ? ", " : ""); |
c5789285 | 1486 | ptr += tracer_print_gather_type(elem_type, ptr); |
f611d0c3 MD |
1487 | } |
1488 | printf(" ]"); | |
d41cb7ee | 1489 | return tracer_gather_size(access_mode, ptr - orig_ptr); |
f611d0c3 MD |
1490 | } |
1491 | ||
352a4b77 | 1492 | struct tracer_visitor_priv { |
67337c4a | 1493 | const struct side_type *elem_type; |
352a4b77 MD |
1494 | int i; |
1495 | }; | |
1496 | ||
1497 | static | |
67337c4a MD |
1498 | enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx, |
1499 | const struct side_arg *elem) | |
352a4b77 | 1500 | { |
e65f9ce5 | 1501 | struct tracer_visitor_priv *tracer_priv = (struct tracer_visitor_priv *) tracer_ctx->priv; |
352a4b77 MD |
1502 | |
1503 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
1504 | tracer_print_type(tracer_priv->elem_type, elem); | |
67337c4a | 1505 | return SIDE_VISITOR_STATUS_OK; |
352a4b77 MD |
1506 | } |
1507 | ||
f611d0c3 | 1508 | static |
67337c4a | 1509 | void tracer_print_vla_visitor(const struct side_type *type_desc, void *app_ctx) |
f611d0c3 | 1510 | { |
67337c4a | 1511 | enum side_visitor_status status; |
352a4b77 | 1512 | struct tracer_visitor_priv tracer_priv = { |
c5789285 | 1513 | .elem_type = side_ptr_get(type_desc->u.side_vla_visitor.elem_type), |
352a4b77 MD |
1514 | .i = 0, |
1515 | }; | |
67337c4a | 1516 | const struct side_tracer_visitor_ctx tracer_ctx = { |
352a4b77 MD |
1517 | .write_elem = tracer_write_elem_cb, |
1518 | .priv = &tracer_priv, | |
1519 | }; | |
2e197497 | 1520 | side_visitor_func func; |
f611d0c3 | 1521 | |
12d787db | 1522 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_vla_visitor.attr), type_desc->u.side_vla_visitor.nr_attr); |
67337c4a | 1523 | printf("%s", type_desc->u.side_vla_visitor.nr_attr ? ", " : ""); |
20574104 | 1524 | printf("elements: "); |
352a4b77 | 1525 | printf("[ "); |
2e197497 MD |
1526 | func = side_ptr_get(type_desc->u.side_vla_visitor.visitor); |
1527 | status = func(&tracer_ctx, app_ctx); | |
352a4b77 | 1528 | switch (status) { |
67337c4a | 1529 | case SIDE_VISITOR_STATUS_OK: |
352a4b77 | 1530 | break; |
67337c4a | 1531 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1532 | fprintf(stderr, "ERROR: Visitor error\n"); |
f611d0c3 | 1533 | abort(); |
f611d0c3 MD |
1534 | } |
1535 | printf(" ]"); | |
f611d0c3 MD |
1536 | } |
1537 | ||
a2e2357e | 1538 | static |
67337c4a | 1539 | void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct *dynamic_struct) |
a2e2357e | 1540 | { |
f13253cb | 1541 | const struct side_arg_dynamic_field *fields = side_ptr_get(dynamic_struct->fields); |
e65f9ce5 | 1542 | uint32_t i, len = dynamic_struct->len; |
465e5e7e | 1543 | |
12d787db | 1544 | print_attributes("attr", "::", side_ptr_get(dynamic_struct->attr), dynamic_struct->nr_attr); |
8d20e708 | 1545 | printf("%s", dynamic_struct->nr_attr ? ", " : ""); |
f0061366 | 1546 | printf("fields:: "); |
465e5e7e MD |
1547 | printf("[ "); |
1548 | for (i = 0; i < len; i++) { | |
1549 | printf("%s", i ? ", " : ""); | |
f13253cb | 1550 | printf("%s:: ", side_ptr_get(fields[i].field_name)); |
465e5e7e MD |
1551 | tracer_print_dynamic(&fields[i].elem); |
1552 | } | |
1553 | printf(" ]"); | |
a2e2357e MD |
1554 | } |
1555 | ||
2b359235 MD |
1556 | struct tracer_dynamic_struct_visitor_priv { |
1557 | int i; | |
1558 | }; | |
1559 | ||
1560 | static | |
67337c4a MD |
1561 | enum side_visitor_status tracer_dynamic_struct_write_elem_cb( |
1562 | const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx, | |
1563 | const struct side_arg_dynamic_field *dynamic_field) | |
2b359235 | 1564 | { |
e65f9ce5 MD |
1565 | struct tracer_dynamic_struct_visitor_priv *tracer_priv = |
1566 | (struct tracer_dynamic_struct_visitor_priv *) tracer_ctx->priv; | |
2b359235 MD |
1567 | |
1568 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
f13253cb | 1569 | printf("%s:: ", side_ptr_get(dynamic_field->field_name)); |
2b359235 | 1570 | tracer_print_dynamic(&dynamic_field->elem); |
67337c4a | 1571 | return SIDE_VISITOR_STATUS_OK; |
2b359235 MD |
1572 | } |
1573 | ||
a2e2357e | 1574 | static |
67337c4a | 1575 | void tracer_print_dynamic_struct_visitor(const struct side_arg *item) |
a2e2357e | 1576 | { |
67337c4a | 1577 | enum side_visitor_status status; |
2b359235 MD |
1578 | struct tracer_dynamic_struct_visitor_priv tracer_priv = { |
1579 | .i = 0, | |
1580 | }; | |
67337c4a | 1581 | const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = { |
2b359235 MD |
1582 | .write_field = tracer_dynamic_struct_write_elem_cb, |
1583 | .priv = &tracer_priv, | |
1584 | }; | |
2e197497 | 1585 | void *app_ctx = side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor.app_ctx); |
2b359235 | 1586 | |
12d787db | 1587 | print_attributes("attr", "::", side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor.attr), item->u.side_dynamic.side_dynamic_struct_visitor.nr_attr); |
67337c4a | 1588 | printf("%s", item->u.side_dynamic.side_dynamic_struct_visitor.nr_attr ? ", " : ""); |
f0061366 | 1589 | printf("fields:: "); |
2b359235 | 1590 | printf("[ "); |
2e197497 | 1591 | status = side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor.visitor)(&tracer_ctx, app_ctx); |
2b359235 | 1592 | switch (status) { |
67337c4a | 1593 | case SIDE_VISITOR_STATUS_OK: |
2b359235 | 1594 | break; |
67337c4a | 1595 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1596 | fprintf(stderr, "ERROR: Visitor error\n"); |
2b359235 MD |
1597 | abort(); |
1598 | } | |
1599 | printf(" ]"); | |
a2e2357e MD |
1600 | } |
1601 | ||
1602 | static | |
67337c4a | 1603 | void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla *vla) |
a2e2357e | 1604 | { |
f13253cb | 1605 | const struct side_arg *sav = side_ptr_get(vla->sav); |
67337c4a | 1606 | uint32_t i, side_sav_len = vla->len; |
a2e2357e | 1607 | |
12d787db | 1608 | print_attributes("attr", "::", side_ptr_get(vla->attr), vla->nr_attr); |
8d20e708 | 1609 | printf("%s", vla->nr_attr ? ", " : ""); |
f0061366 | 1610 | printf("elements:: "); |
a2e2357e | 1611 | printf("[ "); |
67337c4a | 1612 | for (i = 0; i < side_sav_len; i++) { |
a2e2357e MD |
1613 | printf("%s", i ? ", " : ""); |
1614 | tracer_print_dynamic(&sav[i]); | |
1615 | } | |
1616 | printf(" ]"); | |
1617 | } | |
1618 | ||
8ceca0cd MD |
1619 | struct tracer_dynamic_vla_visitor_priv { |
1620 | int i; | |
1621 | }; | |
1622 | ||
1623 | static | |
67337c4a MD |
1624 | enum side_visitor_status tracer_dynamic_vla_write_elem_cb( |
1625 | const struct side_tracer_visitor_ctx *tracer_ctx, | |
1626 | const struct side_arg *elem) | |
8ceca0cd | 1627 | { |
e65f9ce5 MD |
1628 | struct tracer_dynamic_vla_visitor_priv *tracer_priv = |
1629 | (struct tracer_dynamic_vla_visitor_priv *) tracer_ctx->priv; | |
8ceca0cd MD |
1630 | |
1631 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
1632 | tracer_print_dynamic(elem); | |
67337c4a | 1633 | return SIDE_VISITOR_STATUS_OK; |
8ceca0cd MD |
1634 | } |
1635 | ||
a2e2357e | 1636 | static |
67337c4a | 1637 | void tracer_print_dynamic_vla_visitor(const struct side_arg *item) |
a2e2357e | 1638 | { |
67337c4a | 1639 | enum side_visitor_status status; |
8ceca0cd MD |
1640 | struct tracer_dynamic_vla_visitor_priv tracer_priv = { |
1641 | .i = 0, | |
1642 | }; | |
67337c4a | 1643 | const struct side_tracer_visitor_ctx tracer_ctx = { |
8ceca0cd MD |
1644 | .write_elem = tracer_dynamic_vla_write_elem_cb, |
1645 | .priv = &tracer_priv, | |
1646 | }; | |
2e197497 | 1647 | void *app_ctx = side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor.app_ctx); |
8ceca0cd | 1648 | |
12d787db | 1649 | print_attributes("attr", "::", side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor.attr), item->u.side_dynamic.side_dynamic_vla_visitor.nr_attr); |
67337c4a | 1650 | printf("%s", item->u.side_dynamic.side_dynamic_vla_visitor.nr_attr ? ", " : ""); |
f0061366 | 1651 | printf("elements:: "); |
8ceca0cd | 1652 | printf("[ "); |
2e197497 | 1653 | status = side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor.visitor)(&tracer_ctx, app_ctx); |
8ceca0cd | 1654 | switch (status) { |
67337c4a | 1655 | case SIDE_VISITOR_STATUS_OK: |
8ceca0cd | 1656 | break; |
67337c4a | 1657 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1658 | fprintf(stderr, "ERROR: Visitor error\n"); |
8ceca0cd MD |
1659 | abort(); |
1660 | } | |
1661 | printf(" ]"); | |
a2e2357e MD |
1662 | } |
1663 | ||
1664 | static | |
67337c4a | 1665 | void tracer_print_dynamic(const struct side_arg *item) |
a2e2357e | 1666 | { |
808bd9bf | 1667 | printf("{ "); |
3ce69bfa | 1668 | switch (side_enum_get(item->type)) { |
55fb50b7 | 1669 | /* Dynamic basic types */ |
67337c4a | 1670 | case SIDE_TYPE_DYNAMIC_NULL: |
b313067b MD |
1671 | tracer_print_type_header("::", side_ptr_get(item->u.side_dynamic.side_null.attr), |
1672 | item->u.side_dynamic.side_null.nr_attr); | |
a2e2357e MD |
1673 | printf("<NULL TYPE>"); |
1674 | break; | |
67337c4a MD |
1675 | case SIDE_TYPE_DYNAMIC_BOOL: |
1676 | tracer_print_type_bool("::", &item->u.side_dynamic.side_bool.type, &item->u.side_dynamic.side_bool.value, 0); | |
66de373e | 1677 | break; |
67337c4a MD |
1678 | case SIDE_TYPE_DYNAMIC_INTEGER: |
1679 | tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0, | |
f0dafd60 | 1680 | TRACER_DISPLAY_BASE_10); |
a2e2357e | 1681 | break; |
67337c4a | 1682 | case SIDE_TYPE_DYNAMIC_BYTE: |
12d787db | 1683 | tracer_print_type_header("::", side_ptr_get(item->u.side_dynamic.side_byte.type.attr), item->u.side_dynamic.side_byte.type.nr_attr); |
67337c4a | 1684 | printf("0x%" PRIx8, item->u.side_dynamic.side_byte.value); |
199e7aa9 | 1685 | break; |
67337c4a MD |
1686 | case SIDE_TYPE_DYNAMIC_POINTER: |
1687 | tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0, | |
f0dafd60 | 1688 | TRACER_DISPLAY_BASE_16); |
f5e650d7 | 1689 | break; |
67337c4a MD |
1690 | case SIDE_TYPE_DYNAMIC_FLOAT: |
1691 | tracer_print_type_float("::", &item->u.side_dynamic.side_float.type, | |
1692 | &item->u.side_dynamic.side_float.value); | |
fb25b355 | 1693 | break; |
67337c4a | 1694 | case SIDE_TYPE_DYNAMIC_STRING: |
12d787db | 1695 | tracer_print_type_header("::", side_ptr_get(item->u.side_dynamic.side_string.type.attr), item->u.side_dynamic.side_string.type.nr_attr); |
67337c4a MD |
1696 | tracer_print_string((const char *)(uintptr_t) item->u.side_dynamic.side_string.value, |
1697 | item->u.side_dynamic.side_string.type.unit_size, | |
3bc9ba43 | 1698 | side_enum_get(item->u.side_dynamic.side_string.type.byte_order), NULL); |
a2e2357e | 1699 | break; |
55fb50b7 MD |
1700 | |
1701 | /* Dynamic compound types */ | |
67337c4a | 1702 | case SIDE_TYPE_DYNAMIC_STRUCT: |
f13253cb | 1703 | tracer_print_dynamic_struct(side_ptr_get(item->u.side_dynamic.side_dynamic_struct)); |
a2e2357e | 1704 | break; |
67337c4a | 1705 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: |
c208889e | 1706 | tracer_print_dynamic_struct_visitor(item); |
a2e2357e | 1707 | break; |
67337c4a | 1708 | case SIDE_TYPE_DYNAMIC_VLA: |
f13253cb | 1709 | tracer_print_dynamic_vla(side_ptr_get(item->u.side_dynamic.side_dynamic_vla)); |
a2e2357e | 1710 | break; |
67337c4a | 1711 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: |
a2e2357e MD |
1712 | tracer_print_dynamic_vla_visitor(item); |
1713 | break; | |
1714 | default: | |
f6c02218 | 1715 | fprintf(stderr, "<UNKNOWN TYPE>\n"); |
a2e2357e MD |
1716 | abort(); |
1717 | } | |
808bd9bf | 1718 | printf(" }"); |
a2e2357e MD |
1719 | } |
1720 | ||
68f8cfbe | 1721 | static |
67337c4a MD |
1722 | void tracer_print_static_fields(const struct side_event_description *desc, |
1723 | const struct side_arg_vec *side_arg_vec, | |
e65f9ce5 | 1724 | uint32_t *nr_items) |
f611d0c3 | 1725 | { |
f13253cb | 1726 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 1727 | uint32_t i, side_sav_len = side_arg_vec->len; |
f611d0c3 | 1728 | |
0b9e59d6 | 1729 | printf("provider: %s, event: %s", side_ptr_get(desc->provider_name), side_ptr_get(desc->event_name)); |
67337c4a | 1730 | if (desc->nr_fields != side_sav_len) { |
de1b3cd2 | 1731 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n"); |
f611d0c3 MD |
1732 | abort(); |
1733 | } | |
12d787db | 1734 | print_attributes(", attr", ":", side_ptr_get(desc->attr), desc->nr_attr); |
67337c4a MD |
1735 | printf("%s", side_sav_len ? ", fields: [ " : ""); |
1736 | for (i = 0; i < side_sav_len; i++) { | |
f611d0c3 | 1737 | printf("%s", i ? ", " : ""); |
0b9e59d6 | 1738 | tracer_print_field(&side_ptr_get(desc->fields)[i], &sav[i]); |
f611d0c3 | 1739 | } |
68f8cfbe MD |
1740 | if (nr_items) |
1741 | *nr_items = i; | |
67337c4a | 1742 | if (side_sav_len) |
c7d338e2 | 1743 | printf(" ]"); |
68f8cfbe MD |
1744 | } |
1745 | ||
9365e936 | 1746 | static |
67337c4a MD |
1747 | void tracer_call(const struct side_event_description *desc, |
1748 | const struct side_arg_vec *side_arg_vec, | |
4a7d8700 | 1749 | void *priv __attribute__((unused))) |
68f8cfbe | 1750 | { |
e65f9ce5 | 1751 | uint32_t nr_fields = 0; |
a848763d | 1752 | |
67337c4a | 1753 | tracer_print_static_fields(desc, side_arg_vec, &nr_fields); |
f611d0c3 MD |
1754 | printf("\n"); |
1755 | } | |
19fa6aa2 | 1756 | |
9365e936 | 1757 | static |
67337c4a MD |
1758 | void tracer_call_variadic(const struct side_event_description *desc, |
1759 | const struct side_arg_vec *side_arg_vec, | |
1760 | const struct side_arg_dynamic_struct *var_struct, | |
4a7d8700 | 1761 | void *priv __attribute__((unused))) |
19fa6aa2 | 1762 | { |
e65f9ce5 | 1763 | uint32_t nr_fields = 0, i, var_struct_len = var_struct->len; |
19fa6aa2 | 1764 | |
67337c4a | 1765 | tracer_print_static_fields(desc, side_arg_vec, &nr_fields); |
68f8cfbe | 1766 | |
67337c4a | 1767 | if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) { |
de1b3cd2 | 1768 | fprintf(stderr, "ERROR: unexpected non-variadic event description\n"); |
8a25ce77 MD |
1769 | abort(); |
1770 | } | |
12d787db | 1771 | print_attributes(", attr ", "::", side_ptr_get(var_struct->attr), var_struct->nr_attr); |
905c328e | 1772 | printf("%s", var_struct_len ? ", fields:: [ " : ""); |
68f8cfbe | 1773 | for (i = 0; i < var_struct_len; i++, nr_fields++) { |
c7d338e2 | 1774 | printf("%s", i ? ", " : ""); |
f13253cb MD |
1775 | printf("%s:: ", side_ptr_get(side_ptr_get(var_struct->fields)[i].field_name)); |
1776 | tracer_print_dynamic(&side_ptr_get(var_struct->fields)[i].elem); | |
19fa6aa2 | 1777 | } |
a848763d MD |
1778 | if (i) |
1779 | printf(" ]"); | |
19fa6aa2 MD |
1780 | printf("\n"); |
1781 | } | |
1e8aec23 | 1782 | |
9365e936 | 1783 | static |
67337c4a MD |
1784 | void tracer_event_notification(enum side_tracer_notification notif, |
1785 | struct side_event_description **events, uint32_t nr_events, | |
9365e936 | 1786 | void *priv __attribute__((unused))) |
1e8aec23 MD |
1787 | { |
1788 | uint32_t i; | |
314c22c3 | 1789 | int ret; |
1e8aec23 MD |
1790 | |
1791 | printf("----------------------------------------------------------\n"); | |
1792 | printf("Tracer notified of events %s\n", | |
67337c4a | 1793 | notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS ? "inserted" : "removed"); |
1e8aec23 | 1794 | for (i = 0; i < nr_events; i++) { |
67337c4a | 1795 | struct side_event_description *event = events[i]; |
1e8aec23 MD |
1796 | |
1797 | /* Skip NULL pointers */ | |
1798 | if (!event) | |
1799 | continue; | |
441235e7 MD |
1800 | if (event->version != SIDE_ABI_VERSION) { |
1801 | printf("Error: event SIDE ABI version (%u) does not match the SIDE ABI version supported by the tracer (%u)\n", | |
1802 | event->version, SIDE_ABI_VERSION); | |
1803 | return; | |
1804 | } | |
1e8aec23 | 1805 | printf("provider: %s, event: %s\n", |
0b9e59d6 | 1806 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name)); |
441235e7 MD |
1807 | if (event->struct_size != side_offsetofend(struct side_event_description, side_event_description_orig_abi_last)) { |
1808 | printf("Warning: Event %s.%s contains fields unknown to the tracer\n", | |
1809 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name)); | |
1810 | } | |
78dd4cc3 | 1811 | if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) { |
2d8e1a70 MD |
1812 | if (event->nr_side_type_label > _NR_SIDE_TYPE_LABEL) { |
1813 | printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n", | |
1814 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name), | |
1815 | event->nr_side_type_label - _NR_SIDE_TYPE_LABEL); | |
1816 | } | |
1817 | if (event->nr_side_attr_type > _NR_SIDE_ATTR_TYPE) { | |
1818 | printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n", | |
1819 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name), | |
1820 | event->nr_side_attr_type - _NR_SIDE_ATTR_TYPE); | |
1821 | } | |
67337c4a MD |
1822 | if (event->flags & SIDE_EVENT_FLAG_VARIADIC) { |
1823 | ret = side_tracer_callback_variadic_register(event, tracer_call_variadic, NULL); | |
314c22c3 MD |
1824 | if (ret) |
1825 | abort(); | |
1826 | } else { | |
67337c4a | 1827 | ret = side_tracer_callback_register(event, tracer_call, NULL); |
314c22c3 MD |
1828 | if (ret) |
1829 | abort(); | |
1830 | } | |
1831 | } else { | |
67337c4a MD |
1832 | if (event->flags & SIDE_EVENT_FLAG_VARIADIC) { |
1833 | ret = side_tracer_callback_variadic_unregister(event, tracer_call_variadic, NULL); | |
314c22c3 MD |
1834 | if (ret) |
1835 | abort(); | |
1836 | } else { | |
67337c4a | 1837 | ret = side_tracer_callback_unregister(event, tracer_call, NULL); |
314c22c3 MD |
1838 | if (ret) |
1839 | abort(); | |
1840 | } | |
1841 | } | |
1e8aec23 MD |
1842 | } |
1843 | printf("----------------------------------------------------------\n"); | |
1844 | } | |
1845 | ||
1846 | static __attribute__((constructor)) | |
1847 | void tracer_init(void); | |
1848 | static | |
1849 | void tracer_init(void) | |
1850 | { | |
67337c4a | 1851 | tracer_handle = side_tracer_event_notification_register(tracer_event_notification, NULL); |
1e8aec23 MD |
1852 | if (!tracer_handle) |
1853 | abort(); | |
1854 | } | |
1855 | ||
1856 | static __attribute__((destructor)) | |
1857 | void tracer_exit(void); | |
1858 | static | |
1859 | void tracer_exit(void) | |
1860 | { | |
67337c4a | 1861 | side_tracer_event_notification_unregister(tracer_handle); |
1e8aec23 | 1862 | } |