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