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 |
8dace71a | 68 | void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item, bool print_brackets); |
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 | 600 | printf("%s", mappings->nr_attr ? ", " : ""); |
8dace71a | 601 | tracer_print_type(elem_type, item, true); |
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 |
8dace71a | 1098 | void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item, bool print_brackets) |
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 | |
8dace71a MD |
1186 | if (print_brackets) |
1187 | printf("{ "); | |
d8be25de | 1188 | switch (type) { |
55fb50b7 | 1189 | /* Stack-copy basic types */ |
67337c4a | 1190 | case SIDE_TYPE_NULL: |
b313067b MD |
1191 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_null.attr), |
1192 | type_desc->u.side_null.nr_attr); | |
9b641221 MD |
1193 | printf("<NULL TYPE>"); |
1194 | break; | |
1195 | ||
67337c4a MD |
1196 | case SIDE_TYPE_BOOL: |
1197 | tracer_print_type_bool(":", &type_desc->u.side_bool, &item->u.side_static.bool_value, 0); | |
4f40d951 | 1198 | break; |
1d9c515c | 1199 | |
67337c4a MD |
1200 | case SIDE_TYPE_U8: |
1201 | case SIDE_TYPE_U16: | |
1202 | case SIDE_TYPE_U32: | |
1203 | case SIDE_TYPE_U64: | |
0cbdadb5 | 1204 | case SIDE_TYPE_U128: |
67337c4a MD |
1205 | case SIDE_TYPE_S8: |
1206 | case SIDE_TYPE_S16: | |
1207 | case SIDE_TYPE_S32: | |
1208 | case SIDE_TYPE_S64: | |
0cbdadb5 | 1209 | case SIDE_TYPE_S128: |
67337c4a | 1210 | tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0, |
f0dafd60 | 1211 | TRACER_DISPLAY_BASE_10); |
f611d0c3 | 1212 | break; |
56c21987 | 1213 | |
67337c4a | 1214 | case SIDE_TYPE_BYTE: |
12d787db | 1215 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_byte.attr), type_desc->u.side_byte.nr_attr); |
67337c4a | 1216 | printf("0x%" PRIx8, item->u.side_static.byte_value); |
7aec0d09 | 1217 | break; |
79f677ba | 1218 | |
67337c4a MD |
1219 | case SIDE_TYPE_POINTER: |
1220 | tracer_print_type_integer(":", &type_desc->u.side_integer, &item->u.side_static.integer_value, 0, | |
55fb50b7 | 1221 | TRACER_DISPLAY_BASE_16); |
ea32e5fc MD |
1222 | break; |
1223 | ||
67337c4a MD |
1224 | case SIDE_TYPE_FLOAT_BINARY16: |
1225 | case SIDE_TYPE_FLOAT_BINARY32: | |
1226 | case SIDE_TYPE_FLOAT_BINARY64: | |
1227 | case SIDE_TYPE_FLOAT_BINARY128: | |
1228 | tracer_print_type_float(":", &type_desc->u.side_float, &item->u.side_static.float_value); | |
fb25b355 | 1229 | break; |
3aa7ca5e | 1230 | |
67337c4a MD |
1231 | case SIDE_TYPE_STRING_UTF8: |
1232 | case SIDE_TYPE_STRING_UTF16: | |
1233 | case SIDE_TYPE_STRING_UTF32: | |
12d787db | 1234 | tracer_print_type_header(":", side_ptr_get(type_desc->u.side_string.attr), type_desc->u.side_string.nr_attr); |
6910c28c | 1235 | tracer_print_string(side_ptr_get(item->u.side_static.string_value), |
3bc9ba43 | 1236 | type_desc->u.side_string.unit_size, side_enum_get(type_desc->u.side_string.byte_order), NULL); |
f611d0c3 | 1237 | break; |
55fb50b7 MD |
1238 | |
1239 | /* Stack-copy compound types */ | |
67337c4a | 1240 | case SIDE_TYPE_STRUCT: |
bac71609 | 1241 | tracer_print_struct(type_desc, side_ptr_get(item->u.side_static.side_struct)); |
f611d0c3 | 1242 | break; |
5530345d | 1243 | case SIDE_TYPE_VARIANT: |
bac71609 | 1244 | tracer_print_variant(type_desc, side_ptr_get(item->u.side_static.side_variant)); |
5530345d | 1245 | break; |
67337c4a | 1246 | case SIDE_TYPE_ARRAY: |
bac71609 | 1247 | tracer_print_array(type_desc, side_ptr_get(item->u.side_static.side_array)); |
d9359cfa | 1248 | break; |
67337c4a | 1249 | case SIDE_TYPE_VLA: |
bac71609 | 1250 | tracer_print_vla(type_desc, side_ptr_get(item->u.side_static.side_vla)); |
33956c71 | 1251 | break; |
67337c4a | 1252 | case SIDE_TYPE_VLA_VISITOR: |
c6af61dc | 1253 | tracer_print_vla_visitor(type_desc, side_ptr_get(item->u.side_static.side_vla_visitor)); |
80429681 | 1254 | break; |
55fb50b7 MD |
1255 | |
1256 | /* Stack-copy enumeration types */ | |
67337c4a | 1257 | case SIDE_TYPE_ENUM: |
f6a2a8ed | 1258 | tracer_print_enum(type_desc, item); |
55fb50b7 | 1259 | break; |
67337c4a | 1260 | case SIDE_TYPE_ENUM_BITMAP: |
7f8e7e97 | 1261 | tracer_print_enum_bitmap(type_desc, item); |
55fb50b7 MD |
1262 | break; |
1263 | ||
1264 | /* Gather basic types */ | |
67337c4a | 1265 | case SIDE_TYPE_GATHER_BOOL: |
155b1756 | 1266 | (void) tracer_print_gather_bool_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_bool_gather_ptr)); |
8ad2f385 | 1267 | break; |
67337c4a | 1268 | case SIDE_TYPE_GATHER_INTEGER: |
155b1756 | 1269 | (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), |
55fb50b7 MD |
1270 | TRACER_DISPLAY_BASE_10); |
1271 | break; | |
67337c4a | 1272 | case SIDE_TYPE_GATHER_BYTE: |
155b1756 | 1273 | (void) tracer_print_gather_byte_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_byte_gather_ptr)); |
d69918cc | 1274 | break; |
67337c4a | 1275 | case SIDE_TYPE_GATHER_POINTER: |
155b1756 | 1276 | (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), |
4e1b0e0e MD |
1277 | TRACER_DISPLAY_BASE_16); |
1278 | break; | |
67337c4a | 1279 | case SIDE_TYPE_GATHER_FLOAT: |
155b1756 | 1280 | (void) tracer_print_gather_float_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_float_gather_ptr)); |
905f68e3 | 1281 | break; |
67337c4a | 1282 | case SIDE_TYPE_GATHER_STRING: |
155b1756 | 1283 | (void) tracer_print_gather_string_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_string_gather_ptr)); |
7d34edfc | 1284 | break; |
55fb50b7 MD |
1285 | |
1286 | /* Gather compound type */ | |
67337c4a | 1287 | case SIDE_TYPE_GATHER_STRUCT: |
155b1756 | 1288 | (void) tracer_print_gather_struct(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_struct_gather_ptr)); |
f611d0c3 | 1289 | break; |
67337c4a | 1290 | case SIDE_TYPE_GATHER_ARRAY: |
155b1756 | 1291 | (void) tracer_print_gather_array(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr)); |
f611d0c3 | 1292 | break; |
67337c4a | 1293 | case SIDE_TYPE_GATHER_VLA: |
155b1756 MD |
1294 | (void) tracer_print_gather_vla(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_vla_gather.ptr), |
1295 | side_ptr_get(item->u.side_static.side_vla_gather.length_ptr)); | |
f611d0c3 | 1296 | break; |
66de373e | 1297 | |
0519cb86 | 1298 | /* Gather enumeration types */ |
67337c4a | 1299 | case SIDE_TYPE_GATHER_ENUM: |
155b1756 | 1300 | (void) tracer_print_gather_enum_type(&type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr)); |
0519cb86 MD |
1301 | break; |
1302 | ||
55fb50b7 | 1303 | /* Dynamic basic types */ |
67337c4a MD |
1304 | case SIDE_TYPE_DYNAMIC_NULL: |
1305 | case SIDE_TYPE_DYNAMIC_BOOL: | |
1306 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
1307 | case SIDE_TYPE_DYNAMIC_BYTE: | |
1308 | case SIDE_TYPE_DYNAMIC_POINTER: | |
1309 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
1310 | case SIDE_TYPE_DYNAMIC_STRING: | |
55fb50b7 MD |
1311 | |
1312 | /* Dynamic compound types */ | |
67337c4a MD |
1313 | case SIDE_TYPE_DYNAMIC_STRUCT: |
1314 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
1315 | case SIDE_TYPE_DYNAMIC_VLA: | |
1316 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
0160d2c0 | 1317 | tracer_print_dynamic(item, false); |
a2e2357e | 1318 | break; |
f611d0c3 | 1319 | default: |
f6c02218 | 1320 | fprintf(stderr, "<UNKNOWN TYPE>\n"); |
f611d0c3 MD |
1321 | abort(); |
1322 | } | |
8dace71a MD |
1323 | if (print_brackets) |
1324 | printf(" }"); | |
f611d0c3 MD |
1325 | } |
1326 | ||
1327 | static | |
67337c4a | 1328 | void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg *item) |
f611d0c3 | 1329 | { |
c5789285 | 1330 | printf("%s: ", side_ptr_get(item_desc->field_name)); |
8dace71a | 1331 | tracer_print_type(&item_desc->side_type, item, true); |
f611d0c3 MD |
1332 | } |
1333 | ||
1334 | static | |
67337c4a | 1335 | void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
f611d0c3 | 1336 | { |
f13253cb | 1337 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
c5789285 | 1338 | const struct side_type_struct *side_struct = side_ptr_get(type_desc->u.side_struct); |
67337c4a | 1339 | uint32_t i, side_sav_len = side_arg_vec->len; |
f611d0c3 | 1340 | |
c5789285 | 1341 | if (side_struct->nr_fields != side_sav_len) { |
de1b3cd2 | 1342 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n"); |
f611d0c3 MD |
1343 | abort(); |
1344 | } | |
c5789285 MD |
1345 | print_attributes("attr", ":", side_ptr_get(side_struct->attr), side_struct->nr_attr); |
1346 | printf("%s", side_struct->nr_attr ? ", " : ""); | |
73b2b0c2 | 1347 | printf("fields: { "); |
67337c4a | 1348 | for (i = 0; i < side_sav_len; i++) { |
f611d0c3 | 1349 | printf("%s", i ? ", " : ""); |
c5789285 | 1350 | tracer_print_field(&side_ptr_get(side_struct->fields)[i], &sav[i]); |
f611d0c3 | 1351 | } |
d4328528 | 1352 | printf(" }"); |
f611d0c3 MD |
1353 | } |
1354 | ||
5530345d MD |
1355 | static |
1356 | void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant) | |
1357 | { | |
c5789285 | 1358 | const struct side_type_variant *side_type_variant = side_ptr_get(type_desc->u.side_variant); |
5530345d | 1359 | const struct side_type *selector_type = &side_type_variant->selector; |
0cbdadb5 | 1360 | union int_value v; |
5530345d MD |
1361 | uint32_t i; |
1362 | ||
3ce69bfa | 1363 | if (side_enum_get(selector_type->type) != side_enum_get(side_arg_variant->selector.type)) { |
5530345d MD |
1364 | fprintf(stderr, "ERROR: Unexpected variant selector type\n"); |
1365 | abort(); | |
1366 | } | |
3ce69bfa | 1367 | switch (side_enum_get(selector_type->type)) { |
5530345d MD |
1368 | case SIDE_TYPE_U8: |
1369 | case SIDE_TYPE_U16: | |
1370 | case SIDE_TYPE_U32: | |
1371 | case SIDE_TYPE_U64: | |
0cbdadb5 | 1372 | case SIDE_TYPE_U128: |
5530345d MD |
1373 | case SIDE_TYPE_S8: |
1374 | case SIDE_TYPE_S16: | |
1375 | case SIDE_TYPE_S32: | |
1376 | case SIDE_TYPE_S64: | |
0cbdadb5 | 1377 | case SIDE_TYPE_S128: |
5530345d MD |
1378 | break; |
1379 | default: | |
1380 | fprintf(stderr, "ERROR: Expecting integer variant selector type\n"); | |
1381 | abort(); | |
1382 | } | |
0cbdadb5 | 1383 | v = tracer_load_integer_value(&selector_type->u.side_integer, |
5530345d | 1384 | &side_arg_variant->selector.u.side_static.integer_value, 0, NULL); |
0cbdadb5 | 1385 | side_check_value_u64(v); |
5530345d | 1386 | for (i = 0; i < side_type_variant->nr_options; i++) { |
c5789285 | 1387 | const struct side_variant_option *option = &side_ptr_get(side_type_variant->options)[i]; |
5530345d | 1388 | |
0cbdadb5 | 1389 | if (v.s[SIDE_INTEGER128_SPLIT_LOW] >= option->range_begin && v.s[SIDE_INTEGER128_SPLIT_LOW] <= option->range_end) { |
8dace71a | 1390 | tracer_print_type(&option->side_type, &side_arg_variant->option, false); |
5530345d MD |
1391 | return; |
1392 | } | |
1393 | } | |
0cbdadb5 | 1394 | fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v.s[SIDE_INTEGER128_SPLIT_LOW]); |
5530345d MD |
1395 | abort(); |
1396 | } | |
1397 | ||
7a1cb105 | 1398 | static |
67337c4a | 1399 | void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
d9359cfa | 1400 | { |
f13253cb | 1401 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 1402 | uint32_t i, side_sav_len = side_arg_vec->len; |
d9359cfa | 1403 | |
67337c4a | 1404 | if (type_desc->u.side_array.length != side_sav_len) { |
d9359cfa MD |
1405 | fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n"); |
1406 | abort(); | |
1407 | } | |
12d787db | 1408 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_array.attr), type_desc->u.side_array.nr_attr); |
67337c4a | 1409 | printf("%s", type_desc->u.side_array.nr_attr ? ", " : ""); |
d9359cfa MD |
1410 | printf("elements: "); |
1411 | printf("[ "); | |
67337c4a | 1412 | for (i = 0; i < side_sav_len; i++) { |
d9359cfa | 1413 | printf("%s", i ? ", " : ""); |
8dace71a | 1414 | tracer_print_type(side_ptr_get(type_desc->u.side_array.elem_type), &sav[i], true); |
d9359cfa MD |
1415 | } |
1416 | printf(" ]"); | |
1417 | } | |
1418 | ||
1419 | static | |
67337c4a | 1420 | void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec) |
d9359cfa | 1421 | { |
f13253cb | 1422 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 1423 | uint32_t i, side_sav_len = side_arg_vec->len; |
d9359cfa | 1424 | |
12d787db | 1425 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_vla.attr), type_desc->u.side_vla.nr_attr); |
67337c4a | 1426 | printf("%s", type_desc->u.side_vla.nr_attr ? ", " : ""); |
d9359cfa MD |
1427 | printf("elements: "); |
1428 | printf("[ "); | |
67337c4a | 1429 | for (i = 0; i < side_sav_len; i++) { |
d9359cfa | 1430 | printf("%s", i ? ", " : ""); |
8dace71a | 1431 | tracer_print_type(side_ptr_get(type_desc->u.side_vla.elem_type), &sav[i], true); |
d9359cfa MD |
1432 | } |
1433 | printf(" ]"); | |
1434 | } | |
1435 | ||
dd7947bf | 1436 | static |
67337c4a | 1437 | const char *tracer_gather_access(enum side_type_gather_access_mode access_mode, const char *ptr) |
dd7947bf | 1438 | { |
65b8734a | 1439 | switch (access_mode) { |
67337c4a | 1440 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: |
dd7947bf | 1441 | return ptr; |
67337c4a | 1442 | case SIDE_TYPE_GATHER_ACCESS_POINTER: |
dd7947bf | 1443 | /* Dereference pointer */ |
dc9567a6 | 1444 | memcpy(&ptr, ptr, sizeof(const char *)); |
dd7947bf MD |
1445 | return ptr; |
1446 | default: | |
1447 | abort(); | |
1448 | } | |
1449 | } | |
1450 | ||
1451 | static | |
67337c4a | 1452 | uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode, uint32_t len) |
dd7947bf | 1453 | { |
65b8734a | 1454 | switch (access_mode) { |
67337c4a | 1455 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: |
dd7947bf | 1456 | return len; |
67337c4a | 1457 | case SIDE_TYPE_GATHER_ACCESS_POINTER: |
dd7947bf MD |
1458 | return sizeof(void *); |
1459 | default: | |
1460 | abort(); | |
1461 | } | |
1462 | } | |
1463 | ||
d9359cfa | 1464 | static |
0cbdadb5 | 1465 | union int_value tracer_load_gather_integer_value(const struct side_type_gather_integer *side_integer, |
0519cb86 | 1466 | const void *_ptr) |
7a1cb105 | 1467 | { |
67337c4a MD |
1468 | enum side_type_gather_access_mode access_mode = |
1469 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
1470 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
7a1cb105 | 1471 | const char *ptr = (const char *) _ptr; |
67337c4a | 1472 | union side_integer_value value; |
65b8734a | 1473 | |
67337c4a | 1474 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); |
65b8734a | 1475 | memcpy(&value, ptr, integer_size_bytes); |
67337c4a MD |
1476 | return tracer_load_integer_value(&side_integer->type, &value, |
1477 | side_integer->offset_bits, NULL); | |
65b8734a MD |
1478 | } |
1479 | ||
8ad2f385 | 1480 | static |
67337c4a | 1481 | uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr) |
8ad2f385 | 1482 | { |
67337c4a MD |
1483 | enum side_type_gather_access_mode access_mode = |
1484 | (enum side_type_gather_access_mode) type_gather->u.side_bool.access_mode; | |
1485 | uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size; | |
8ad2f385 | 1486 | const char *ptr = (const char *) _ptr; |
67337c4a | 1487 | union side_bool_value value; |
8ad2f385 | 1488 | |
88bab79c MD |
1489 | switch (bool_size_bytes) { |
1490 | case 1: | |
1491 | case 2: | |
1492 | case 4: | |
8ad2f385 | 1493 | case 8: |
8ad2f385 MD |
1494 | break; |
1495 | default: | |
1496 | abort(); | |
1497 | } | |
67337c4a | 1498 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset); |
8ad2f385 | 1499 | memcpy(&value, ptr, bool_size_bytes); |
67337c4a MD |
1500 | tracer_print_type_bool(":", &type_gather->u.side_bool.type, &value, |
1501 | type_gather->u.side_bool.offset_bits); | |
8ad2f385 MD |
1502 | return tracer_gather_size(access_mode, bool_size_bytes); |
1503 | } | |
1504 | ||
d69918cc | 1505 | static |
67337c4a | 1506 | uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr) |
d69918cc | 1507 | { |
67337c4a MD |
1508 | enum side_type_gather_access_mode access_mode = |
1509 | (enum side_type_gather_access_mode) type_gather->u.side_byte.access_mode; | |
d69918cc MD |
1510 | const char *ptr = (const char *) _ptr; |
1511 | uint8_t value; | |
1512 | ||
67337c4a | 1513 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset); |
d69918cc | 1514 | memcpy(&value, ptr, 1); |
12d787db | 1515 | tracer_print_type_header(":", side_ptr_get(type_gather->u.side_byte.type.attr), |
67337c4a | 1516 | type_gather->u.side_byte.type.nr_attr); |
d69918cc MD |
1517 | printf("0x%" PRIx8, value); |
1518 | return tracer_gather_size(access_mode, 1); | |
1519 | } | |
1520 | ||
65b8734a | 1521 | static |
67337c4a | 1522 | uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr, |
4e1b0e0e | 1523 | enum tracer_display_base default_base) |
65b8734a | 1524 | { |
67337c4a MD |
1525 | enum side_type_gather_access_mode access_mode = |
1526 | (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode; | |
1527 | uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size; | |
65b8734a | 1528 | const char *ptr = (const char *) _ptr; |
67337c4a | 1529 | union side_integer_value value; |
7a1cb105 | 1530 | |
88bab79c MD |
1531 | switch (integer_size_bytes) { |
1532 | case 1: | |
1533 | case 2: | |
1534 | case 4: | |
33956c71 | 1535 | case 8: |
0cbdadb5 | 1536 | case 16: |
9b641221 | 1537 | break; |
33956c71 MD |
1538 | default: |
1539 | abort(); | |
1540 | } | |
67337c4a | 1541 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset); |
dd7947bf | 1542 | memcpy(&value, ptr, integer_size_bytes); |
67337c4a MD |
1543 | tracer_print_type_integer(":", &type_gather->u.side_integer.type, &value, |
1544 | type_gather->u.side_integer.offset_bits, default_base); | |
d41cb7ee | 1545 | return tracer_gather_size(access_mode, integer_size_bytes); |
33956c71 | 1546 | } |
9b641221 | 1547 | |
905f68e3 | 1548 | static |
67337c4a | 1549 | uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr) |
905f68e3 | 1550 | { |
67337c4a MD |
1551 | enum side_type_gather_access_mode access_mode = |
1552 | (enum side_type_gather_access_mode) type_gather->u.side_float.access_mode; | |
1553 | uint32_t float_size_bytes = type_gather->u.side_float.type.float_size; | |
905f68e3 | 1554 | const char *ptr = (const char *) _ptr; |
67337c4a | 1555 | union side_float_value value; |
905f68e3 | 1556 | |
88bab79c MD |
1557 | switch (float_size_bytes) { |
1558 | case 2: | |
1559 | case 4: | |
1560 | case 8: | |
905f68e3 | 1561 | case 16: |
905f68e3 MD |
1562 | break; |
1563 | default: | |
1564 | abort(); | |
1565 | } | |
67337c4a | 1566 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset); |
dd7947bf | 1567 | memcpy(&value, ptr, float_size_bytes); |
67337c4a | 1568 | tracer_print_type_float(":", &type_gather->u.side_float.type, &value); |
d41cb7ee | 1569 | return tracer_gather_size(access_mode, float_size_bytes); |
905f68e3 MD |
1570 | } |
1571 | ||
7d34edfc | 1572 | static |
67337c4a | 1573 | uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr) |
7d34edfc | 1574 | { |
67337c4a MD |
1575 | enum side_type_gather_access_mode access_mode = |
1576 | (enum side_type_gather_access_mode) type_gather->u.side_string.access_mode; | |
7d34edfc MD |
1577 | const char *ptr = (const char *) _ptr; |
1578 | size_t string_len; | |
1579 | ||
67337c4a | 1580 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset); |
12d787db | 1581 | tracer_print_type_header(":", side_ptr_get(type_gather->u.side_string.type.attr), |
67337c4a | 1582 | type_gather->u.side_string.type.nr_attr); |
7d34edfc | 1583 | if (ptr) { |
67337c4a | 1584 | tracer_print_string(ptr, type_gather->u.side_string.type.unit_size, |
3bc9ba43 | 1585 | side_enum_get(type_gather->u.side_string.type.byte_order), &string_len); |
7d34edfc MD |
1586 | } else { |
1587 | printf("<NULL>"); | |
67337c4a | 1588 | string_len = type_gather->u.side_string.type.unit_size; |
7d34edfc MD |
1589 | } |
1590 | return tracer_gather_size(access_mode, string_len); | |
1591 | } | |
1592 | ||
33956c71 | 1593 | static |
67337c4a | 1594 | uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void *ptr) |
33956c71 | 1595 | { |
d9359cfa MD |
1596 | uint32_t len; |
1597 | ||
33956c71 | 1598 | printf("{ "); |
3ce69bfa | 1599 | switch (side_enum_get(type_desc->type)) { |
55fb50b7 | 1600 | /* Gather basic types */ |
67337c4a MD |
1601 | case SIDE_TYPE_GATHER_BOOL: |
1602 | len = tracer_print_gather_bool_type(&type_desc->u.side_gather, ptr); | |
8ad2f385 | 1603 | break; |
67337c4a MD |
1604 | case SIDE_TYPE_GATHER_INTEGER: |
1605 | len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr, | |
55fb50b7 MD |
1606 | TRACER_DISPLAY_BASE_10); |
1607 | break; | |
67337c4a MD |
1608 | case SIDE_TYPE_GATHER_BYTE: |
1609 | len = tracer_print_gather_byte_type(&type_desc->u.side_gather, ptr); | |
d69918cc | 1610 | break; |
67337c4a MD |
1611 | case SIDE_TYPE_GATHER_POINTER: |
1612 | len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr, | |
4e1b0e0e MD |
1613 | TRACER_DISPLAY_BASE_16); |
1614 | break; | |
67337c4a MD |
1615 | case SIDE_TYPE_GATHER_FLOAT: |
1616 | len = tracer_print_gather_float_type(&type_desc->u.side_gather, ptr); | |
33956c71 | 1617 | break; |
67337c4a MD |
1618 | case SIDE_TYPE_GATHER_STRING: |
1619 | len = tracer_print_gather_string_type(&type_desc->u.side_gather, ptr); | |
7d34edfc | 1620 | break; |
55fb50b7 | 1621 | |
0519cb86 | 1622 | /* Gather enum types */ |
67337c4a MD |
1623 | case SIDE_TYPE_GATHER_ENUM: |
1624 | len = tracer_print_gather_enum_type(&type_desc->u.side_gather, ptr); | |
0519cb86 MD |
1625 | break; |
1626 | ||
55fb50b7 | 1627 | /* Gather compound types */ |
67337c4a MD |
1628 | case SIDE_TYPE_GATHER_STRUCT: |
1629 | len = tracer_print_gather_struct(&type_desc->u.side_gather, ptr); | |
d9359cfa | 1630 | break; |
67337c4a MD |
1631 | case SIDE_TYPE_GATHER_ARRAY: |
1632 | len = tracer_print_gather_array(&type_desc->u.side_gather, ptr); | |
9b641221 | 1633 | break; |
67337c4a MD |
1634 | case SIDE_TYPE_GATHER_VLA: |
1635 | len = tracer_print_gather_vla(&type_desc->u.side_gather, ptr, ptr); | |
65b8734a | 1636 | break; |
9b641221 | 1637 | default: |
d41cb7ee | 1638 | fprintf(stderr, "<UNKNOWN GATHER TYPE>"); |
9b641221 | 1639 | abort(); |
7a1cb105 MD |
1640 | } |
1641 | printf(" }"); | |
d9359cfa | 1642 | return len; |
7a1cb105 MD |
1643 | } |
1644 | ||
0519cb86 | 1645 | static |
67337c4a | 1646 | uint32_t tracer_print_gather_enum_type(const struct side_type_gather *type_gather, const void *_ptr) |
0519cb86 | 1647 | { |
64037418 | 1648 | const struct side_enum_mappings *mappings = side_ptr_get(type_gather->u.side_enum.mappings); |
c5789285 | 1649 | const struct side_type *enum_elem_type = side_ptr_get(type_gather->u.side_enum.elem_type); |
67337c4a MD |
1650 | const struct side_type_gather_integer *side_integer = &enum_elem_type->u.side_gather.u.side_integer; |
1651 | enum side_type_gather_access_mode access_mode = | |
1652 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
1653 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
0519cb86 | 1654 | const char *ptr = (const char *) _ptr; |
67337c4a | 1655 | union side_integer_value value; |
0cbdadb5 | 1656 | union int_value v; |
0519cb86 MD |
1657 | |
1658 | switch (integer_size_bytes) { | |
1659 | case 1: | |
1660 | case 2: | |
1661 | case 4: | |
1662 | case 8: | |
0cbdadb5 | 1663 | case 16: |
0519cb86 MD |
1664 | break; |
1665 | default: | |
1666 | abort(); | |
1667 | } | |
67337c4a | 1668 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); |
0519cb86 | 1669 | memcpy(&value, ptr, integer_size_bytes); |
0cbdadb5 | 1670 | v = tracer_load_gather_integer_value(side_integer, &value); |
12d787db | 1671 | print_attributes("attr", ":", side_ptr_get(mappings->attr), mappings->nr_attr); |
0519cb86 MD |
1672 | printf("%s", mappings->nr_attr ? ", " : ""); |
1673 | tracer_print_gather_type(enum_elem_type, ptr); | |
0cbdadb5 | 1674 | print_enum_labels(mappings, v); |
0519cb86 MD |
1675 | return tracer_gather_size(access_mode, integer_size_bytes); |
1676 | } | |
1677 | ||
7a1cb105 | 1678 | static |
67337c4a | 1679 | void tracer_print_gather_field(const struct side_event_field *field, const void *ptr) |
7a1cb105 | 1680 | { |
c5789285 | 1681 | printf("%s: ", side_ptr_get(field->field_name)); |
67337c4a | 1682 | (void) tracer_print_gather_type(&field->side_type, ptr); |
7a1cb105 MD |
1683 | } |
1684 | ||
1685 | static | |
67337c4a | 1686 | uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr) |
7a1cb105 | 1687 | { |
67337c4a MD |
1688 | enum side_type_gather_access_mode access_mode = |
1689 | (enum side_type_gather_access_mode) type_gather->u.side_struct.access_mode; | |
c5789285 | 1690 | const struct side_type_struct *side_struct = side_ptr_get(type_gather->u.side_struct.type); |
dd7947bf | 1691 | const char *ptr = (const char *) _ptr; |
e65f9ce5 | 1692 | uint32_t i; |
7a1cb105 | 1693 | |
67337c4a | 1694 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_struct.offset); |
c5789285 MD |
1695 | print_attributes("attr", ":", side_ptr_get(side_struct->attr), side_struct->nr_attr); |
1696 | printf("%s", side_struct->nr_attr ? ", " : ""); | |
7a1cb105 | 1697 | printf("fields: { "); |
c5789285 | 1698 | for (i = 0; i < side_struct->nr_fields; i++) { |
7a1cb105 | 1699 | printf("%s", i ? ", " : ""); |
c5789285 | 1700 | tracer_print_gather_field(&side_ptr_get(side_struct->fields)[i], ptr); |
7a1cb105 MD |
1701 | } |
1702 | printf(" }"); | |
67337c4a | 1703 | return tracer_gather_size(access_mode, type_gather->u.side_struct.size); |
7a1cb105 MD |
1704 | } |
1705 | ||
f611d0c3 | 1706 | static |
67337c4a | 1707 | uint32_t tracer_print_gather_array(const struct side_type_gather *type_gather, const void *_ptr) |
f611d0c3 | 1708 | { |
67337c4a MD |
1709 | enum side_type_gather_access_mode access_mode = |
1710 | (enum side_type_gather_access_mode) type_gather->u.side_array.access_mode; | |
dd7947bf | 1711 | const char *ptr = (const char *) _ptr, *orig_ptr; |
d9359cfa | 1712 | uint32_t i; |
f611d0c3 | 1713 | |
67337c4a | 1714 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_array.offset); |
65b8734a | 1715 | orig_ptr = ptr; |
12d787db | 1716 | print_attributes("attr", ":", side_ptr_get(type_gather->u.side_array.type.attr), type_gather->u.side_array.type.nr_attr); |
67337c4a | 1717 | printf("%s", type_gather->u.side_array.type.nr_attr ? ", " : ""); |
65b8734a MD |
1718 | printf("elements: "); |
1719 | printf("[ "); | |
67337c4a | 1720 | for (i = 0; i < type_gather->u.side_array.type.length; i++) { |
c5789285 MD |
1721 | const struct side_type *elem_type = side_ptr_get(type_gather->u.side_array.type.elem_type); |
1722 | ||
3ce69bfa | 1723 | switch (side_enum_get(elem_type->type)) { |
67337c4a | 1724 | case SIDE_TYPE_GATHER_VLA: |
d41cb7ee | 1725 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); |
65b8734a MD |
1726 | abort(); |
1727 | default: | |
1728 | break; | |
1729 | } | |
1730 | printf("%s", i ? ", " : ""); | |
c5789285 | 1731 | ptr += tracer_print_gather_type(elem_type, ptr); |
65b8734a MD |
1732 | } |
1733 | printf(" ]"); | |
d41cb7ee | 1734 | return tracer_gather_size(access_mode, ptr - orig_ptr); |
65b8734a MD |
1735 | } |
1736 | ||
1737 | static | |
67337c4a | 1738 | uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, const void *_ptr, |
80429681 | 1739 | const void *_length_ptr) |
65b8734a | 1740 | { |
67337c4a MD |
1741 | enum side_type_gather_access_mode access_mode = |
1742 | (enum side_type_gather_access_mode) type_gather->u.side_vla.access_mode; | |
c5789285 | 1743 | const struct side_type *length_type = side_ptr_get(type_gather->u.side_vla.length_type); |
65b8734a | 1744 | const char *ptr = (const char *) _ptr, *orig_ptr; |
80429681 | 1745 | const char *length_ptr = (const char *) _length_ptr; |
0cbdadb5 | 1746 | union int_value v = {}; |
65b8734a MD |
1747 | uint32_t i, length; |
1748 | ||
1749 | /* Access length */ | |
3ce69bfa | 1750 | switch (side_enum_get(length_type->type)) { |
67337c4a | 1751 | case SIDE_TYPE_GATHER_INTEGER: |
65b8734a MD |
1752 | break; |
1753 | default: | |
d41cb7ee | 1754 | fprintf(stderr, "<gather VLA expects integer gather length type>\n"); |
65b8734a MD |
1755 | abort(); |
1756 | } | |
0cbdadb5 | 1757 | v = tracer_load_gather_integer_value(&length_type->u.side_gather.u.side_integer, |
0519cb86 | 1758 | length_ptr); |
0cbdadb5 MD |
1759 | if (v.u[SIDE_INTEGER128_SPLIT_HIGH] || v.u[SIDE_INTEGER128_SPLIT_LOW] > UINT32_MAX) { |
1760 | fprintf(stderr, "Unexpected vla length value\n"); | |
1761 | abort(); | |
1762 | } | |
1763 | length = (uint32_t) v.u[SIDE_INTEGER128_SPLIT_LOW]; | |
67337c4a | 1764 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_vla.offset); |
dd7947bf | 1765 | orig_ptr = ptr; |
12d787db | 1766 | print_attributes("attr", ":", side_ptr_get(type_gather->u.side_vla.type.attr), type_gather->u.side_vla.type.nr_attr); |
67337c4a | 1767 | printf("%s", type_gather->u.side_vla.type.nr_attr ? ", " : ""); |
20574104 | 1768 | printf("elements: "); |
f611d0c3 | 1769 | printf("[ "); |
65b8734a | 1770 | for (i = 0; i < length; i++) { |
c5789285 MD |
1771 | const struct side_type *elem_type = side_ptr_get(type_gather->u.side_vla.type.elem_type); |
1772 | ||
3ce69bfa | 1773 | switch (side_enum_get(elem_type->type)) { |
67337c4a | 1774 | case SIDE_TYPE_GATHER_VLA: |
d41cb7ee | 1775 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); |
65b8734a MD |
1776 | abort(); |
1777 | default: | |
1778 | break; | |
1779 | } | |
f611d0c3 | 1780 | printf("%s", i ? ", " : ""); |
c5789285 | 1781 | ptr += tracer_print_gather_type(elem_type, ptr); |
f611d0c3 MD |
1782 | } |
1783 | printf(" ]"); | |
d41cb7ee | 1784 | return tracer_gather_size(access_mode, ptr - orig_ptr); |
f611d0c3 MD |
1785 | } |
1786 | ||
352a4b77 | 1787 | struct tracer_visitor_priv { |
67337c4a | 1788 | const struct side_type *elem_type; |
352a4b77 MD |
1789 | int i; |
1790 | }; | |
1791 | ||
1792 | static | |
67337c4a MD |
1793 | enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx, |
1794 | const struct side_arg *elem) | |
352a4b77 | 1795 | { |
e65f9ce5 | 1796 | struct tracer_visitor_priv *tracer_priv = (struct tracer_visitor_priv *) tracer_ctx->priv; |
352a4b77 MD |
1797 | |
1798 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
8dace71a | 1799 | tracer_print_type(tracer_priv->elem_type, elem, true); |
67337c4a | 1800 | return SIDE_VISITOR_STATUS_OK; |
352a4b77 MD |
1801 | } |
1802 | ||
f611d0c3 | 1803 | static |
c6af61dc | 1804 | void tracer_print_vla_visitor(const struct side_type *type_desc, struct side_arg_vla_visitor *vla_visitor) |
f611d0c3 | 1805 | { |
c6af61dc | 1806 | void *app_ctx; |
67337c4a | 1807 | enum side_visitor_status status; |
352a4b77 | 1808 | struct tracer_visitor_priv tracer_priv = { |
c5789285 | 1809 | .elem_type = side_ptr_get(type_desc->u.side_vla_visitor.elem_type), |
352a4b77 MD |
1810 | .i = 0, |
1811 | }; | |
67337c4a | 1812 | const struct side_tracer_visitor_ctx tracer_ctx = { |
352a4b77 MD |
1813 | .write_elem = tracer_write_elem_cb, |
1814 | .priv = &tracer_priv, | |
1815 | }; | |
2e197497 | 1816 | side_visitor_func func; |
f611d0c3 | 1817 | |
c6af61dc MD |
1818 | if (!vla_visitor) |
1819 | abort(); | |
1820 | app_ctx = side_ptr_get(vla_visitor->app_ctx); | |
12d787db | 1821 | print_attributes("attr", ":", side_ptr_get(type_desc->u.side_vla_visitor.attr), type_desc->u.side_vla_visitor.nr_attr); |
67337c4a | 1822 | printf("%s", type_desc->u.side_vla_visitor.nr_attr ? ", " : ""); |
20574104 | 1823 | printf("elements: "); |
352a4b77 | 1824 | printf("[ "); |
2e197497 MD |
1825 | func = side_ptr_get(type_desc->u.side_vla_visitor.visitor); |
1826 | status = func(&tracer_ctx, app_ctx); | |
352a4b77 | 1827 | switch (status) { |
67337c4a | 1828 | case SIDE_VISITOR_STATUS_OK: |
352a4b77 | 1829 | break; |
67337c4a | 1830 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1831 | fprintf(stderr, "ERROR: Visitor error\n"); |
f611d0c3 | 1832 | abort(); |
f611d0c3 MD |
1833 | } |
1834 | printf(" ]"); | |
f611d0c3 MD |
1835 | } |
1836 | ||
a2e2357e | 1837 | static |
67337c4a | 1838 | void tracer_print_dynamic_struct(const struct side_arg_dynamic_struct *dynamic_struct) |
a2e2357e | 1839 | { |
f13253cb | 1840 | const struct side_arg_dynamic_field *fields = side_ptr_get(dynamic_struct->fields); |
e65f9ce5 | 1841 | uint32_t i, len = dynamic_struct->len; |
465e5e7e | 1842 | |
12d787db | 1843 | print_attributes("attr", "::", side_ptr_get(dynamic_struct->attr), dynamic_struct->nr_attr); |
8d20e708 | 1844 | printf("%s", dynamic_struct->nr_attr ? ", " : ""); |
f0061366 | 1845 | printf("fields:: "); |
5a983ec5 | 1846 | printf("{ "); |
465e5e7e MD |
1847 | for (i = 0; i < len; i++) { |
1848 | printf("%s", i ? ", " : ""); | |
f13253cb | 1849 | printf("%s:: ", side_ptr_get(fields[i].field_name)); |
0160d2c0 | 1850 | tracer_print_dynamic(&fields[i].elem, true); |
465e5e7e | 1851 | } |
5a983ec5 | 1852 | printf(" }"); |
a2e2357e MD |
1853 | } |
1854 | ||
2b359235 MD |
1855 | struct tracer_dynamic_struct_visitor_priv { |
1856 | int i; | |
1857 | }; | |
1858 | ||
1859 | static | |
67337c4a MD |
1860 | enum side_visitor_status tracer_dynamic_struct_write_elem_cb( |
1861 | const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx, | |
1862 | const struct side_arg_dynamic_field *dynamic_field) | |
2b359235 | 1863 | { |
e65f9ce5 MD |
1864 | struct tracer_dynamic_struct_visitor_priv *tracer_priv = |
1865 | (struct tracer_dynamic_struct_visitor_priv *) tracer_ctx->priv; | |
2b359235 MD |
1866 | |
1867 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
f13253cb | 1868 | printf("%s:: ", side_ptr_get(dynamic_field->field_name)); |
0160d2c0 | 1869 | tracer_print_dynamic(&dynamic_field->elem, true); |
67337c4a | 1870 | return SIDE_VISITOR_STATUS_OK; |
2b359235 MD |
1871 | } |
1872 | ||
a2e2357e | 1873 | static |
67337c4a | 1874 | void tracer_print_dynamic_struct_visitor(const struct side_arg *item) |
a2e2357e | 1875 | { |
c6af61dc | 1876 | struct side_arg_dynamic_struct_visitor *dynamic_struct_visitor; |
2b359235 MD |
1877 | struct tracer_dynamic_struct_visitor_priv tracer_priv = { |
1878 | .i = 0, | |
1879 | }; | |
67337c4a | 1880 | const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = { |
2b359235 MD |
1881 | .write_field = tracer_dynamic_struct_write_elem_cb, |
1882 | .priv = &tracer_priv, | |
1883 | }; | |
c6af61dc MD |
1884 | enum side_visitor_status status; |
1885 | void *app_ctx; | |
2b359235 | 1886 | |
c6af61dc MD |
1887 | dynamic_struct_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor); |
1888 | if (!dynamic_struct_visitor) | |
1889 | abort(); | |
1890 | app_ctx = side_ptr_get(dynamic_struct_visitor->app_ctx); | |
1891 | print_attributes("attr", "::", side_ptr_get(dynamic_struct_visitor->attr), dynamic_struct_visitor->nr_attr); | |
1892 | printf("%s", dynamic_struct_visitor->nr_attr ? ", " : ""); | |
f0061366 | 1893 | printf("fields:: "); |
5a983ec5 | 1894 | printf("{ "); |
c6af61dc | 1895 | status = side_ptr_get(dynamic_struct_visitor->visitor)(&tracer_ctx, app_ctx); |
2b359235 | 1896 | switch (status) { |
67337c4a | 1897 | case SIDE_VISITOR_STATUS_OK: |
2b359235 | 1898 | break; |
67337c4a | 1899 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1900 | fprintf(stderr, "ERROR: Visitor error\n"); |
2b359235 MD |
1901 | abort(); |
1902 | } | |
5a983ec5 | 1903 | printf(" }"); |
a2e2357e MD |
1904 | } |
1905 | ||
1906 | static | |
67337c4a | 1907 | void tracer_print_dynamic_vla(const struct side_arg_dynamic_vla *vla) |
a2e2357e | 1908 | { |
f13253cb | 1909 | const struct side_arg *sav = side_ptr_get(vla->sav); |
67337c4a | 1910 | uint32_t i, side_sav_len = vla->len; |
a2e2357e | 1911 | |
12d787db | 1912 | print_attributes("attr", "::", side_ptr_get(vla->attr), vla->nr_attr); |
8d20e708 | 1913 | printf("%s", vla->nr_attr ? ", " : ""); |
f0061366 | 1914 | printf("elements:: "); |
a2e2357e | 1915 | printf("[ "); |
67337c4a | 1916 | for (i = 0; i < side_sav_len; i++) { |
a2e2357e | 1917 | printf("%s", i ? ", " : ""); |
0160d2c0 | 1918 | tracer_print_dynamic(&sav[i], true); |
a2e2357e MD |
1919 | } |
1920 | printf(" ]"); | |
1921 | } | |
1922 | ||
8ceca0cd MD |
1923 | struct tracer_dynamic_vla_visitor_priv { |
1924 | int i; | |
1925 | }; | |
1926 | ||
1927 | static | |
67337c4a MD |
1928 | enum side_visitor_status tracer_dynamic_vla_write_elem_cb( |
1929 | const struct side_tracer_visitor_ctx *tracer_ctx, | |
1930 | const struct side_arg *elem) | |
8ceca0cd | 1931 | { |
e65f9ce5 MD |
1932 | struct tracer_dynamic_vla_visitor_priv *tracer_priv = |
1933 | (struct tracer_dynamic_vla_visitor_priv *) tracer_ctx->priv; | |
8ceca0cd MD |
1934 | |
1935 | printf("%s", tracer_priv->i++ ? ", " : ""); | |
0160d2c0 | 1936 | tracer_print_dynamic(elem, true); |
67337c4a | 1937 | return SIDE_VISITOR_STATUS_OK; |
8ceca0cd MD |
1938 | } |
1939 | ||
a2e2357e | 1940 | static |
67337c4a | 1941 | void tracer_print_dynamic_vla_visitor(const struct side_arg *item) |
a2e2357e | 1942 | { |
c6af61dc | 1943 | struct side_arg_dynamic_vla_visitor *dynamic_vla_visitor; |
8ceca0cd MD |
1944 | struct tracer_dynamic_vla_visitor_priv tracer_priv = { |
1945 | .i = 0, | |
1946 | }; | |
67337c4a | 1947 | const struct side_tracer_visitor_ctx tracer_ctx = { |
8ceca0cd MD |
1948 | .write_elem = tracer_dynamic_vla_write_elem_cb, |
1949 | .priv = &tracer_priv, | |
1950 | }; | |
c6af61dc MD |
1951 | enum side_visitor_status status; |
1952 | void *app_ctx; | |
8ceca0cd | 1953 | |
c6af61dc MD |
1954 | dynamic_vla_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor); |
1955 | if (!dynamic_vla_visitor) | |
1956 | abort(); | |
1957 | app_ctx = side_ptr_get(dynamic_vla_visitor->app_ctx); | |
1958 | print_attributes("attr", "::", side_ptr_get(dynamic_vla_visitor->attr), dynamic_vla_visitor->nr_attr); | |
1959 | printf("%s", dynamic_vla_visitor->nr_attr ? ", " : ""); | |
f0061366 | 1960 | printf("elements:: "); |
8ceca0cd | 1961 | printf("[ "); |
c6af61dc | 1962 | status = side_ptr_get(dynamic_vla_visitor->visitor)(&tracer_ctx, app_ctx); |
8ceca0cd | 1963 | switch (status) { |
67337c4a | 1964 | case SIDE_VISITOR_STATUS_OK: |
8ceca0cd | 1965 | break; |
67337c4a | 1966 | case SIDE_VISITOR_STATUS_ERROR: |
de1b3cd2 | 1967 | fprintf(stderr, "ERROR: Visitor error\n"); |
8ceca0cd MD |
1968 | abort(); |
1969 | } | |
1970 | printf(" ]"); | |
a2e2357e MD |
1971 | } |
1972 | ||
1973 | static | |
0160d2c0 | 1974 | void tracer_print_dynamic(const struct side_arg *item, bool print_brackets) |
a2e2357e | 1975 | { |
0160d2c0 MD |
1976 | if (print_brackets) |
1977 | printf("{ "); | |
3ce69bfa | 1978 | switch (side_enum_get(item->type)) { |
55fb50b7 | 1979 | /* Dynamic basic types */ |
67337c4a | 1980 | case SIDE_TYPE_DYNAMIC_NULL: |
b313067b MD |
1981 | tracer_print_type_header("::", side_ptr_get(item->u.side_dynamic.side_null.attr), |
1982 | item->u.side_dynamic.side_null.nr_attr); | |
a2e2357e MD |
1983 | printf("<NULL TYPE>"); |
1984 | break; | |
67337c4a MD |
1985 | case SIDE_TYPE_DYNAMIC_BOOL: |
1986 | tracer_print_type_bool("::", &item->u.side_dynamic.side_bool.type, &item->u.side_dynamic.side_bool.value, 0); | |
66de373e | 1987 | break; |
67337c4a MD |
1988 | case SIDE_TYPE_DYNAMIC_INTEGER: |
1989 | tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0, | |
f0dafd60 | 1990 | TRACER_DISPLAY_BASE_10); |
a2e2357e | 1991 | break; |
67337c4a | 1992 | case SIDE_TYPE_DYNAMIC_BYTE: |
12d787db | 1993 | 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 | 1994 | printf("0x%" PRIx8, item->u.side_dynamic.side_byte.value); |
199e7aa9 | 1995 | break; |
67337c4a MD |
1996 | case SIDE_TYPE_DYNAMIC_POINTER: |
1997 | tracer_print_type_integer("::", &item->u.side_dynamic.side_integer.type, &item->u.side_dynamic.side_integer.value, 0, | |
f0dafd60 | 1998 | TRACER_DISPLAY_BASE_16); |
f5e650d7 | 1999 | break; |
67337c4a MD |
2000 | case SIDE_TYPE_DYNAMIC_FLOAT: |
2001 | tracer_print_type_float("::", &item->u.side_dynamic.side_float.type, | |
2002 | &item->u.side_dynamic.side_float.value); | |
fb25b355 | 2003 | break; |
67337c4a | 2004 | case SIDE_TYPE_DYNAMIC_STRING: |
12d787db | 2005 | 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 |
2006 | tracer_print_string((const char *)(uintptr_t) item->u.side_dynamic.side_string.value, |
2007 | item->u.side_dynamic.side_string.type.unit_size, | |
3bc9ba43 | 2008 | side_enum_get(item->u.side_dynamic.side_string.type.byte_order), NULL); |
a2e2357e | 2009 | break; |
55fb50b7 MD |
2010 | |
2011 | /* Dynamic compound types */ | |
67337c4a | 2012 | case SIDE_TYPE_DYNAMIC_STRUCT: |
f13253cb | 2013 | tracer_print_dynamic_struct(side_ptr_get(item->u.side_dynamic.side_dynamic_struct)); |
a2e2357e | 2014 | break; |
67337c4a | 2015 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: |
c208889e | 2016 | tracer_print_dynamic_struct_visitor(item); |
a2e2357e | 2017 | break; |
67337c4a | 2018 | case SIDE_TYPE_DYNAMIC_VLA: |
f13253cb | 2019 | tracer_print_dynamic_vla(side_ptr_get(item->u.side_dynamic.side_dynamic_vla)); |
a2e2357e | 2020 | break; |
67337c4a | 2021 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: |
a2e2357e MD |
2022 | tracer_print_dynamic_vla_visitor(item); |
2023 | break; | |
2024 | default: | |
f6c02218 | 2025 | fprintf(stderr, "<UNKNOWN TYPE>\n"); |
a2e2357e MD |
2026 | abort(); |
2027 | } | |
0160d2c0 MD |
2028 | if (print_brackets) |
2029 | printf(" }"); | |
a2e2357e MD |
2030 | } |
2031 | ||
68f8cfbe | 2032 | static |
67337c4a MD |
2033 | void tracer_print_static_fields(const struct side_event_description *desc, |
2034 | const struct side_arg_vec *side_arg_vec, | |
5e523511 | 2035 | uint32_t *nr_items, void *caller_addr) |
f611d0c3 | 2036 | { |
f13253cb | 2037 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); |
67337c4a | 2038 | uint32_t i, side_sav_len = side_arg_vec->len; |
f611d0c3 | 2039 | |
0160d2c0 | 2040 | if (print_caller) |
cb6513ab | 2041 | printf("caller: [%p], ", caller_addr); |
0160d2c0 | 2042 | printf("provider: %s, event: %s", |
5e523511 MD |
2043 | side_ptr_get(desc->provider_name), |
2044 | side_ptr_get(desc->event_name)); | |
67337c4a | 2045 | if (desc->nr_fields != side_sav_len) { |
de1b3cd2 | 2046 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n"); |
f611d0c3 MD |
2047 | abort(); |
2048 | } | |
12d787db | 2049 | print_attributes(", attr", ":", side_ptr_get(desc->attr), desc->nr_attr); |
5a983ec5 | 2050 | printf("%s", side_sav_len ? ", fields: { " : ""); |
67337c4a | 2051 | for (i = 0; i < side_sav_len; i++) { |
f611d0c3 | 2052 | printf("%s", i ? ", " : ""); |
0b9e59d6 | 2053 | tracer_print_field(&side_ptr_get(desc->fields)[i], &sav[i]); |
f611d0c3 | 2054 | } |
68f8cfbe MD |
2055 | if (nr_items) |
2056 | *nr_items = i; | |
67337c4a | 2057 | if (side_sav_len) |
5a983ec5 | 2058 | printf(" }"); |
68f8cfbe MD |
2059 | } |
2060 | ||
9365e936 | 2061 | static |
67337c4a MD |
2062 | void tracer_call(const struct side_event_description *desc, |
2063 | const struct side_arg_vec *side_arg_vec, | |
5e523511 MD |
2064 | void *priv __attribute__((unused)), |
2065 | void *caller_addr) | |
68f8cfbe | 2066 | { |
e65f9ce5 | 2067 | uint32_t nr_fields = 0; |
a848763d | 2068 | |
5e523511 | 2069 | tracer_print_static_fields(desc, side_arg_vec, &nr_fields, caller_addr); |
f611d0c3 MD |
2070 | printf("\n"); |
2071 | } | |
19fa6aa2 | 2072 | |
9365e936 | 2073 | static |
67337c4a MD |
2074 | void tracer_call_variadic(const struct side_event_description *desc, |
2075 | const struct side_arg_vec *side_arg_vec, | |
2076 | const struct side_arg_dynamic_struct *var_struct, | |
5e523511 MD |
2077 | void *priv __attribute__((unused)), |
2078 | void *caller_addr) | |
19fa6aa2 | 2079 | { |
e65f9ce5 | 2080 | uint32_t nr_fields = 0, i, var_struct_len = var_struct->len; |
19fa6aa2 | 2081 | |
5e523511 | 2082 | tracer_print_static_fields(desc, side_arg_vec, &nr_fields, caller_addr); |
68f8cfbe | 2083 | |
67337c4a | 2084 | if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) { |
de1b3cd2 | 2085 | fprintf(stderr, "ERROR: unexpected non-variadic event description\n"); |
8a25ce77 MD |
2086 | abort(); |
2087 | } | |
12d787db | 2088 | print_attributes(", attr ", "::", side_ptr_get(var_struct->attr), var_struct->nr_attr); |
5a983ec5 | 2089 | printf("%s", var_struct_len ? ", fields:: { " : ""); |
68f8cfbe | 2090 | for (i = 0; i < var_struct_len; i++, nr_fields++) { |
c7d338e2 | 2091 | printf("%s", i ? ", " : ""); |
f13253cb | 2092 | printf("%s:: ", side_ptr_get(side_ptr_get(var_struct->fields)[i].field_name)); |
0160d2c0 | 2093 | tracer_print_dynamic(&side_ptr_get(var_struct->fields)[i].elem, true); |
19fa6aa2 | 2094 | } |
a848763d | 2095 | if (i) |
5a983ec5 | 2096 | printf(" }"); |
19fa6aa2 MD |
2097 | printf("\n"); |
2098 | } | |
1e8aec23 | 2099 | |
9365e936 | 2100 | static |
67337c4a MD |
2101 | void tracer_event_notification(enum side_tracer_notification notif, |
2102 | struct side_event_description **events, uint32_t nr_events, | |
9365e936 | 2103 | void *priv __attribute__((unused))) |
1e8aec23 MD |
2104 | { |
2105 | uint32_t i; | |
314c22c3 | 2106 | int ret; |
1e8aec23 MD |
2107 | |
2108 | printf("----------------------------------------------------------\n"); | |
2109 | printf("Tracer notified of events %s\n", | |
67337c4a | 2110 | notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS ? "inserted" : "removed"); |
1e8aec23 | 2111 | for (i = 0; i < nr_events; i++) { |
67337c4a | 2112 | struct side_event_description *event = events[i]; |
1e8aec23 MD |
2113 | |
2114 | /* Skip NULL pointers */ | |
2115 | if (!event) | |
2116 | continue; | |
b2a84b9f MD |
2117 | if (event->version != SIDE_EVENT_DESCRIPTION_ABI_VERSION) { |
2118 | printf("Error: event description ABI version (%u) does not match the version supported by the tracer (%u)\n", | |
2119 | event->version, SIDE_EVENT_DESCRIPTION_ABI_VERSION); | |
441235e7 MD |
2120 | return; |
2121 | } | |
1e8aec23 | 2122 | printf("provider: %s, event: %s\n", |
0b9e59d6 | 2123 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name)); |
441235e7 | 2124 | if (event->struct_size != side_offsetofend(struct side_event_description, side_event_description_orig_abi_last)) { |
b2a84b9f | 2125 | printf("Warning: Event %s.%s description contains fields unknown to the tracer\n", |
441235e7 MD |
2126 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name)); |
2127 | } | |
78dd4cc3 | 2128 | if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) { |
2d8e1a70 MD |
2129 | if (event->nr_side_type_label > _NR_SIDE_TYPE_LABEL) { |
2130 | printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n", | |
2131 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name), | |
2132 | event->nr_side_type_label - _NR_SIDE_TYPE_LABEL); | |
2133 | } | |
2134 | if (event->nr_side_attr_type > _NR_SIDE_ATTR_TYPE) { | |
2135 | printf("Warning: event %s:%s may contain unknown attribute types (%u unknown types)\n", | |
2136 | side_ptr_get(event->provider_name), side_ptr_get(event->event_name), | |
2137 | event->nr_side_attr_type - _NR_SIDE_ATTR_TYPE); | |
2138 | } | |
67337c4a | 2139 | if (event->flags & SIDE_EVENT_FLAG_VARIADIC) { |
bffe9ae3 | 2140 | ret = side_tracer_callback_variadic_register(event, tracer_call_variadic, NULL, tracer_key); |
314c22c3 MD |
2141 | if (ret) |
2142 | abort(); | |
2143 | } else { | |
bffe9ae3 | 2144 | ret = side_tracer_callback_register(event, tracer_call, NULL, tracer_key); |
314c22c3 MD |
2145 | if (ret) |
2146 | abort(); | |
2147 | } | |
2148 | } else { | |
67337c4a | 2149 | if (event->flags & SIDE_EVENT_FLAG_VARIADIC) { |
bffe9ae3 | 2150 | ret = side_tracer_callback_variadic_unregister(event, tracer_call_variadic, NULL, tracer_key); |
314c22c3 MD |
2151 | if (ret) |
2152 | abort(); | |
2153 | } else { | |
bffe9ae3 | 2154 | ret = side_tracer_callback_unregister(event, tracer_call, NULL, tracer_key); |
314c22c3 MD |
2155 | if (ret) |
2156 | abort(); | |
2157 | } | |
2158 | } | |
1e8aec23 MD |
2159 | } |
2160 | printf("----------------------------------------------------------\n"); | |
2161 | } | |
2162 | ||
2163 | static __attribute__((constructor)) | |
2164 | void tracer_init(void); | |
2165 | static | |
2166 | void tracer_init(void) | |
2167 | { | |
bffe9ae3 MD |
2168 | if (side_tracer_request_key(&tracer_key)) |
2169 | abort(); | |
67337c4a | 2170 | tracer_handle = side_tracer_event_notification_register(tracer_event_notification, NULL); |
1e8aec23 MD |
2171 | if (!tracer_handle) |
2172 | abort(); | |
2173 | } | |
2174 | ||
2175 | static __attribute__((destructor)) | |
2176 | void tracer_exit(void); | |
2177 | static | |
2178 | void tracer_exit(void) | |
2179 | { | |
67337c4a | 2180 | side_tracer_event_notification_unregister(tracer_handle); |
1e8aec23 | 2181 | } |