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