Tracer test event registration notification
[libside.git] / src / tracer.c
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>
10 #include <stdbool.h>
11
12 #include <side/trace.h>
13
14 static struct side_tracer_handle *tracer_handle;
15
16 static
17 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
18 static
19 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
20 static
21 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
22 static
23 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx);
24 static
25 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
26 static
27 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item);
28 static
29 void tracer_print_dynamic(const struct side_arg_dynamic_vec *dynamic_item);
30 static
31 void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item);
32
33 static
34 void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
35 {
36 printf("{ key%s \"%s\", value%s ", separator, attr->key, separator);
37 switch (attr->value.type) {
38 case SIDE_ATTR_TYPE_BOOL:
39 printf("%s", attr->value.u.side_bool ? "true" : "false");
40 break;
41 case SIDE_ATTR_TYPE_U8:
42 printf("%" PRIu8, attr->value.u.side_u8);
43 break;
44 case SIDE_ATTR_TYPE_U16:
45 printf("%" PRIu16, attr->value.u.side_u16);
46 break;
47 case SIDE_ATTR_TYPE_U32:
48 printf("%" PRIu32, attr->value.u.side_u32);
49 break;
50 case SIDE_ATTR_TYPE_U64:
51 printf("%" PRIu64, attr->value.u.side_u64);
52 break;
53 case SIDE_ATTR_TYPE_S8:
54 printf("%" PRId8, attr->value.u.side_s8);
55 break;
56 case SIDE_ATTR_TYPE_S16:
57 printf("%" PRId16, attr->value.u.side_s16);
58 break;
59 case SIDE_ATTR_TYPE_S32:
60 printf("%" PRId32, attr->value.u.side_s32);
61 break;
62 case SIDE_ATTR_TYPE_S64:
63 printf("%" PRId64, attr->value.u.side_s64);
64 break;
65 case SIDE_ATTR_TYPE_FLOAT_BINARY16:
66 #if __HAVE_FLOAT16
67 printf("%g", (double) attr->value.u.side_float_binary16);
68 break;
69 #else
70 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
71 abort();
72 #endif
73 case SIDE_ATTR_TYPE_FLOAT_BINARY32:
74 #if __HAVE_FLOAT32
75 printf("%g", (double) attr->value.u.side_float_binary32);
76 break;
77 #else
78 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
79 abort();
80 #endif
81 case SIDE_ATTR_TYPE_FLOAT_BINARY64:
82 #if __HAVE_FLOAT64
83 printf("%g", (double) attr->value.u.side_float_binary64);
84 break;
85 #else
86 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
87 abort();
88 #endif
89 case SIDE_ATTR_TYPE_FLOAT_BINARY128:
90 #if __HAVE_FLOAT128
91 printf("%Lg", (long double) attr->value.u.side_float_binary128);
92 break;
93 #else
94 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
95 abort();
96 #endif
97 case SIDE_ATTR_TYPE_STRING:
98 printf("\"%s\"", attr->value.u.string);
99 break;
100 default:
101 fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
102 abort();
103 }
104 printf(" }");
105 }
106
107 static
108 void print_attributes(const char *prefix_str, const char *separator,
109 const struct side_attr *attr, uint32_t nr_attr)
110 {
111 int i;
112
113 if (!nr_attr)
114 return;
115 printf("%s%s [ ", prefix_str, separator);
116 for (i = 0; i < nr_attr; i++) {
117 printf("%s", i ? ", " : "");
118 tracer_print_attr_type(separator, &attr[i]);
119 }
120 printf(" ]");
121 }
122
123 static
124 void print_enum(const struct side_type_description *type_desc, const struct side_arg_vec *item)
125 {
126 const struct side_enum_mappings *mappings = type_desc->u.side_enum.mappings;
127 int i, print_count = 0;
128 int64_t value;
129
130 if (type_desc->u.side_enum.elem_type->type != item->type) {
131 fprintf(stderr, "ERROR: Unexpected enum element type\n");
132 abort();
133 }
134 switch (item->type) {
135 case SIDE_TYPE_U8:
136 value = (int64_t) item->u.side_u8;
137 break;
138 case SIDE_TYPE_U16:
139 value = (int64_t) item->u.side_u16;
140 break;
141 case SIDE_TYPE_U32:
142 value = (int64_t) item->u.side_u32;
143 break;
144 case SIDE_TYPE_U64:
145 value = (int64_t) item->u.side_u64;
146 break;
147 case SIDE_TYPE_S8:
148 value = (int64_t) item->u.side_s8;
149 break;
150 case SIDE_TYPE_S16:
151 value = (int64_t) item->u.side_s16;
152 break;
153 case SIDE_TYPE_S32:
154 value = (int64_t) item->u.side_s32;
155 break;
156 case SIDE_TYPE_S64:
157 value = (int64_t) item->u.side_s64;
158 break;
159 default:
160 fprintf(stderr, "ERROR: Unexpected enum element type\n");
161 abort();
162 }
163 print_attributes("attr", ":", mappings->attr, mappings->nr_attr);
164 printf("%s", mappings->nr_attr ? ", " : "");
165 tracer_print_type(type_desc->u.side_enum.elem_type, item);
166 printf(", labels: [ ");
167 for (i = 0; i < mappings->nr_mappings; i++) {
168 const struct side_enum_mapping *mapping = &mappings->mappings[i];
169
170 if (mapping->range_end < mapping->range_begin) {
171 fprintf(stderr, "ERROR: Unexpected enum range: %" PRIu64 "-%" PRIu64 "\n",
172 mapping->range_begin, mapping->range_end);
173 abort();
174 }
175 if (value >= mapping->range_begin && value <= mapping->range_end) {
176 printf("%s", print_count++ ? ", " : "");
177 printf("\"%s\"", mapping->label);
178 }
179 }
180 if (!print_count)
181 printf("<NO LABEL>");
182 printf(" ]");
183 }
184
185 static
186 uint32_t enum_elem_type_to_stride(const struct side_type_description *elem_type)
187 {
188 uint32_t stride_bit;
189
190 switch (elem_type->type) {
191 case SIDE_TYPE_U8: /* Fall-through */
192 case SIDE_TYPE_BYTE:
193 stride_bit = 8;
194 break;
195 case SIDE_TYPE_U16:
196 stride_bit = 16;
197 break;
198 case SIDE_TYPE_U32:
199 stride_bit = 32;
200 break;
201 case SIDE_TYPE_U64:
202 stride_bit = 64;
203 break;
204 default:
205 fprintf(stderr, "ERROR: Unexpected enum element type\n");
206 abort();
207 }
208 return stride_bit;
209 }
210
211 static
212 void print_enum_bitmap(const struct side_type_description *type_desc,
213 const struct side_arg_vec *item)
214 {
215 const struct side_type_description *elem_type = type_desc->u.side_enum_bitmap.elem_type;
216 const struct side_enum_bitmap_mappings *side_enum_mappings = type_desc->u.side_enum_bitmap.mappings;
217 int i, print_count = 0;
218 uint32_t stride_bit, nr_items;
219 const struct side_arg_vec *array_item;
220
221 switch (elem_type->type) {
222 case SIDE_TYPE_U8: /* Fall-through */
223 case SIDE_TYPE_BYTE: /* Fall-through */
224 case SIDE_TYPE_U16: /* Fall-through */
225 case SIDE_TYPE_U32: /* Fall-through */
226 case SIDE_TYPE_U64:
227 stride_bit = enum_elem_type_to_stride(elem_type);
228 array_item = item;
229 nr_items = 1;
230 break;
231 case SIDE_TYPE_ARRAY:
232 stride_bit = enum_elem_type_to_stride(elem_type->u.side_array.elem_type);
233 array_item = item->u.side_array->sav;
234 nr_items = type_desc->u.side_array.length;
235 break;
236 case SIDE_TYPE_VLA:
237 stride_bit = enum_elem_type_to_stride(elem_type->u.side_vla.elem_type);
238 array_item = item->u.side_vla->sav;
239 nr_items = item->u.side_vla->len;
240 break;
241 default:
242 fprintf(stderr, "ERROR: Unexpected enum element type\n");
243 abort();
244 }
245
246 print_attributes("attr", ":", side_enum_mappings->attr, side_enum_mappings->nr_attr);
247 printf("%s", side_enum_mappings->nr_attr ? ", " : "");
248 printf("labels: [ ");
249 for (i = 0; i < side_enum_mappings->nr_mappings; i++) {
250 const struct side_enum_bitmap_mapping *mapping = &side_enum_mappings->mappings[i];
251 bool match = false;
252 uint64_t bit;
253
254 if (mapping->range_end < mapping->range_begin) {
255 fprintf(stderr, "ERROR: Unexpected enum bitmap range: %" PRIu64 "-%" PRIu64 "\n",
256 mapping->range_begin, mapping->range_end);
257 abort();
258 }
259 for (bit = mapping->range_begin; bit <= mapping->range_end; bit++) {
260 if (bit > (nr_items * stride_bit) - 1)
261 break;
262 switch (stride_bit) {
263 case 8:
264 {
265 uint8_t v = array_item[bit / 8].u.side_u8;
266 if (v & (1ULL << (bit % 8))) {
267 match = true;
268 goto match;
269 }
270 break;
271 }
272 case 16:
273 {
274 uint16_t v = array_item[bit / 16].u.side_u16;
275 if (v & (1ULL << (bit % 16))) {
276 match = true;
277 goto match;
278 }
279 break;
280 }
281 case 32:
282 {
283 uint32_t v = array_item[bit / 32].u.side_u32;
284 if (v & (1ULL << (bit % 32))) {
285 match = true;
286 goto match;
287 }
288 break;
289 }
290 case 64:
291 {
292 uint64_t v = array_item[bit / 64].u.side_u64;
293 if (v & (1ULL << (bit % 64))) {
294 match = true;
295 goto match;
296 }
297 break;
298 }
299 default:
300 abort();
301 }
302 }
303 match:
304 if (match) {
305 printf("%s", print_count++ ? ", " : "");
306 printf("\"%s\"", mapping->label);
307 }
308 }
309 if (!print_count)
310 printf("<NO LABEL>");
311 printf(" ]");
312 }
313
314 static
315 void tracer_print_basic_type_header(const struct side_type_description *type_desc)
316 {
317 print_attributes("attr", ":", type_desc->u.side_basic.attr, type_desc->u.side_basic.nr_attr);
318 printf("%s", type_desc->u.side_basic.nr_attr ? ", " : "");
319 printf("value: ");
320 }
321
322 static
323 void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item)
324 {
325 enum side_type type;
326
327 switch (type_desc->type) {
328 case SIDE_TYPE_ARRAY:
329 switch (item->type) {
330 case SIDE_TYPE_ARRAY_U8:
331 case SIDE_TYPE_ARRAY_U16:
332 case SIDE_TYPE_ARRAY_U32:
333 case SIDE_TYPE_ARRAY_U64:
334 case SIDE_TYPE_ARRAY_S8:
335 case SIDE_TYPE_ARRAY_S16:
336 case SIDE_TYPE_ARRAY_S32:
337 case SIDE_TYPE_ARRAY_S64:
338 case SIDE_TYPE_ARRAY_BYTE:
339 case SIDE_TYPE_ARRAY:
340 break;
341 default:
342 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
343 abort();
344 break;
345 }
346 break;
347
348 case SIDE_TYPE_VLA:
349 switch (item->type) {
350 case SIDE_TYPE_VLA_U8:
351 case SIDE_TYPE_VLA_U16:
352 case SIDE_TYPE_VLA_U32:
353 case SIDE_TYPE_VLA_U64:
354 case SIDE_TYPE_VLA_S8:
355 case SIDE_TYPE_VLA_S16:
356 case SIDE_TYPE_VLA_S32:
357 case SIDE_TYPE_VLA_S64:
358 case SIDE_TYPE_VLA_BYTE:
359 case SIDE_TYPE_VLA:
360 break;
361 default:
362 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
363 abort();
364 break;
365 }
366 break;
367
368 case SIDE_TYPE_ENUM:
369 switch (item->type) {
370 case SIDE_TYPE_U8:
371 case SIDE_TYPE_U16:
372 case SIDE_TYPE_U32:
373 case SIDE_TYPE_U64:
374 case SIDE_TYPE_S8:
375 case SIDE_TYPE_S16:
376 case SIDE_TYPE_S32:
377 case SIDE_TYPE_S64:
378 break;
379 default:
380 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
381 abort();
382 break;
383 }
384 break;
385
386 case SIDE_TYPE_ENUM_BITMAP:
387 switch (item->type) {
388 case SIDE_TYPE_U8:
389 case SIDE_TYPE_BYTE:
390 case SIDE_TYPE_U16:
391 case SIDE_TYPE_U32:
392 case SIDE_TYPE_U64:
393 case SIDE_TYPE_ARRAY:
394 case SIDE_TYPE_VLA:
395 break;
396 default:
397 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
398 abort();
399 break;
400 }
401 break;
402
403 default:
404 if (type_desc->type != item->type) {
405 fprintf(stderr, "ERROR: type mismatch between description and arguments\n");
406 abort();
407 }
408 break;
409 }
410
411 if (type_desc->type == SIDE_TYPE_ENUM || type_desc->type == SIDE_TYPE_ENUM_BITMAP)
412 type = type_desc->type;
413 else
414 type = item->type;
415
416 printf("{ ");
417 switch (type) {
418 case SIDE_TYPE_BOOL:
419 tracer_print_basic_type_header(type_desc);
420 printf("%s", item->u.side_bool ? "true" : "false");
421 break;
422 case SIDE_TYPE_U8:
423 tracer_print_basic_type_header(type_desc);
424 printf("%" PRIu8, item->u.side_u8);
425 break;
426 case SIDE_TYPE_U16:
427 tracer_print_basic_type_header(type_desc);
428 printf("%" PRIu16, item->u.side_u16);
429 break;
430 case SIDE_TYPE_U32:
431 tracer_print_basic_type_header(type_desc);
432 printf("%" PRIu32, item->u.side_u32);
433 break;
434 case SIDE_TYPE_U64:
435 tracer_print_basic_type_header(type_desc);
436 printf("%" PRIu64, item->u.side_u64);
437 break;
438 case SIDE_TYPE_S8:
439 tracer_print_basic_type_header(type_desc);
440 printf("%" PRId8, item->u.side_s8);
441 break;
442 case SIDE_TYPE_S16:
443 tracer_print_basic_type_header(type_desc);
444 printf("%" PRId16, item->u.side_s16);
445 break;
446 case SIDE_TYPE_S32:
447 tracer_print_basic_type_header(type_desc);
448 printf("%" PRId32, item->u.side_s32);
449 break;
450 case SIDE_TYPE_S64:
451 tracer_print_basic_type_header(type_desc);
452 printf("%" PRId64, item->u.side_s64);
453 break;
454 case SIDE_TYPE_BYTE:
455 tracer_print_basic_type_header(type_desc);
456 printf("0x%" PRIx8, item->u.side_byte);
457 break;
458
459 case SIDE_TYPE_ENUM:
460 print_enum(type_desc, item);
461 break;
462
463 case SIDE_TYPE_ENUM_BITMAP:
464 print_enum_bitmap(type_desc, item);
465 break;
466
467 case SIDE_TYPE_FLOAT_BINARY16:
468 tracer_print_basic_type_header(type_desc);
469 #if __HAVE_FLOAT16
470 printf("%g", (double) item->u.side_float_binary16);
471 break;
472 #else
473 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
474 abort();
475 #endif
476 case SIDE_TYPE_FLOAT_BINARY32:
477 tracer_print_basic_type_header(type_desc);
478 #if __HAVE_FLOAT32
479 printf("%g", (double) item->u.side_float_binary32);
480 break;
481 #else
482 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
483 abort();
484 #endif
485 case SIDE_TYPE_FLOAT_BINARY64:
486 tracer_print_basic_type_header(type_desc);
487 #if __HAVE_FLOAT64
488 printf("%g", (double) item->u.side_float_binary64);
489 break;
490 #else
491 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
492 abort();
493 #endif
494 case SIDE_TYPE_FLOAT_BINARY128:
495 tracer_print_basic_type_header(type_desc);
496 #if __HAVE_FLOAT128
497 printf("%Lg", (long double) item->u.side_float_binary128);
498 break;
499 #else
500 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
501 abort();
502 #endif
503 case SIDE_TYPE_STRING:
504 tracer_print_basic_type_header(type_desc);
505 printf("\"%s\"", item->u.string);
506 break;
507 case SIDE_TYPE_STRUCT:
508 tracer_print_struct(type_desc, item->u.side_struct);
509 break;
510 case SIDE_TYPE_ARRAY:
511 tracer_print_array(type_desc, item->u.side_array);
512 break;
513 case SIDE_TYPE_VLA:
514 tracer_print_vla(type_desc, item->u.side_vla);
515 break;
516 case SIDE_TYPE_VLA_VISITOR:
517 tracer_print_vla_visitor(type_desc, item->u.side_vla_app_visitor_ctx);
518 break;
519 case SIDE_TYPE_ARRAY_U8:
520 case SIDE_TYPE_ARRAY_U16:
521 case SIDE_TYPE_ARRAY_U32:
522 case SIDE_TYPE_ARRAY_U64:
523 case SIDE_TYPE_ARRAY_S8:
524 case SIDE_TYPE_ARRAY_S16:
525 case SIDE_TYPE_ARRAY_S32:
526 case SIDE_TYPE_ARRAY_S64:
527 case SIDE_TYPE_ARRAY_BYTE:
528 tracer_print_array_fixint(type_desc, item);
529 break;
530 case SIDE_TYPE_VLA_U8:
531 case SIDE_TYPE_VLA_U16:
532 case SIDE_TYPE_VLA_U32:
533 case SIDE_TYPE_VLA_U64:
534 case SIDE_TYPE_VLA_S8:
535 case SIDE_TYPE_VLA_S16:
536 case SIDE_TYPE_VLA_S32:
537 case SIDE_TYPE_VLA_S64:
538 case SIDE_TYPE_VLA_BYTE:
539 tracer_print_vla_fixint(type_desc, item);
540 break;
541 case SIDE_TYPE_DYNAMIC:
542 tracer_print_basic_type_header(type_desc);
543 tracer_print_dynamic(&item->u.dynamic);
544 break;
545 default:
546 fprintf(stderr, "<UNKNOWN TYPE>");
547 abort();
548 }
549 printf(" }");
550 }
551
552 static
553 void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg_vec *item)
554 {
555 printf("%s: ", item_desc->field_name);
556 tracer_print_type(&item_desc->side_type, item);
557 }
558
559 static
560 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
561 {
562 const struct side_arg_vec *sav = sav_desc->sav;
563 uint32_t side_sav_len = sav_desc->len;
564 int i;
565
566 if (type_desc->u.side_struct->nr_fields != side_sav_len) {
567 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n");
568 abort();
569 }
570 print_attributes("attr", ":", type_desc->u.side_struct->attr, type_desc->u.side_struct->nr_attr);
571 printf("%s", type_desc->u.side_struct->nr_attr ? ", " : "");
572 printf("fields: { ");
573 for (i = 0; i < side_sav_len; i++) {
574 printf("%s", i ? ", " : "");
575 tracer_print_field(&type_desc->u.side_struct->fields[i], &sav[i]);
576 }
577 printf(" }");
578 }
579
580 static
581 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
582 {
583 const struct side_arg_vec *sav = sav_desc->sav;
584 uint32_t side_sav_len = sav_desc->len;
585 int i;
586
587 if (type_desc->u.side_array.length != side_sav_len) {
588 fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n");
589 abort();
590 }
591 print_attributes("attr", ":", type_desc->u.side_array.attr, type_desc->u.side_array.nr_attr);
592 printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
593 printf("elements: ");
594 printf("[ ");
595 for (i = 0; i < side_sav_len; i++) {
596 printf("%s", i ? ", " : "");
597 tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
598 }
599 printf(" ]");
600 }
601
602 static
603 void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
604 {
605 const struct side_arg_vec *sav = sav_desc->sav;
606 uint32_t side_sav_len = sav_desc->len;
607 int i;
608
609 print_attributes("attr", ":", type_desc->u.side_vla.attr, type_desc->u.side_vla.nr_attr);
610 printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
611 printf("elements: ");
612 printf("[ ");
613 for (i = 0; i < side_sav_len; i++) {
614 printf("%s", i ? ", " : "");
615 tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
616 }
617 printf(" ]");
618 }
619
620 struct tracer_visitor_priv {
621 const struct side_type_description *elem_type;
622 int i;
623 };
624
625 static
626 enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx,
627 const struct side_arg_vec *elem)
628 {
629 struct tracer_visitor_priv *tracer_priv = tracer_ctx->priv;
630
631 printf("%s", tracer_priv->i++ ? ", " : "");
632 tracer_print_type(tracer_priv->elem_type, elem);
633 return SIDE_VISITOR_STATUS_OK;
634 }
635
636 static
637 void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *app_ctx)
638 {
639 enum side_visitor_status status;
640 struct tracer_visitor_priv tracer_priv = {
641 .elem_type = type_desc->u.side_vla_visitor.elem_type,
642 .i = 0,
643 };
644 const struct side_tracer_visitor_ctx tracer_ctx = {
645 .write_elem = tracer_write_elem_cb,
646 .priv = &tracer_priv,
647 };
648
649 print_attributes("attr", ":", type_desc->u.side_vla_visitor.attr, type_desc->u.side_vla_visitor.nr_attr);
650 printf("%s", type_desc->u.side_vla_visitor.nr_attr ? ", " : "");
651 printf("elements: ");
652 printf("[ ");
653 status = type_desc->u.side_vla_visitor.visitor(&tracer_ctx, app_ctx);
654 switch (status) {
655 case SIDE_VISITOR_STATUS_OK:
656 break;
657 case SIDE_VISITOR_STATUS_ERROR:
658 fprintf(stderr, "ERROR: Visitor error\n");
659 abort();
660 }
661 printf(" ]");
662 }
663
664 void tracer_print_array_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
665 {
666 const struct side_type_description *elem_type = type_desc->u.side_array.elem_type;
667 uint32_t side_sav_len = type_desc->u.side_array.length;
668 void *p = item->u.side_array_fixint;
669 enum side_type side_type;
670 int i;
671
672 print_attributes("attr", ":", type_desc->u.side_array.attr, type_desc->u.side_array.nr_attr);
673 printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
674 printf("elements: ");
675 switch (item->type) {
676 case SIDE_TYPE_ARRAY_U8:
677 if (elem_type->type != SIDE_TYPE_U8)
678 goto type_error;
679 break;
680 case SIDE_TYPE_ARRAY_U16:
681 if (elem_type->type != SIDE_TYPE_U16)
682 goto type_error;
683 break;
684 case SIDE_TYPE_ARRAY_U32:
685 if (elem_type->type != SIDE_TYPE_U32)
686 goto type_error;
687 break;
688 case SIDE_TYPE_ARRAY_U64:
689 if (elem_type->type != SIDE_TYPE_U64)
690 goto type_error;
691 break;
692 case SIDE_TYPE_ARRAY_S8:
693 if (elem_type->type != SIDE_TYPE_S8)
694 goto type_error;
695 break;
696 case SIDE_TYPE_ARRAY_S16:
697 if (elem_type->type != SIDE_TYPE_S16)
698 goto type_error;
699 break;
700 case SIDE_TYPE_ARRAY_S32:
701 if (elem_type->type != SIDE_TYPE_S32)
702 goto type_error;
703 break;
704 case SIDE_TYPE_ARRAY_S64:
705 if (elem_type->type != SIDE_TYPE_S64)
706 goto type_error;
707 break;
708 case SIDE_TYPE_ARRAY_BYTE:
709 if (elem_type->type != SIDE_TYPE_BYTE)
710 goto type_error;
711 break;
712 default:
713 goto type_error;
714 }
715 side_type = elem_type->type;
716
717 printf("[ ");
718 for (i = 0; i < side_sav_len; i++) {
719 struct side_arg_vec sav_elem = {
720 .type = side_type,
721 };
722
723 switch (side_type) {
724 case SIDE_TYPE_U8:
725 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
726 break;
727 case SIDE_TYPE_S8:
728 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
729 break;
730 case SIDE_TYPE_U16:
731 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
732 break;
733 case SIDE_TYPE_S16:
734 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
735 break;
736 case SIDE_TYPE_U32:
737 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
738 break;
739 case SIDE_TYPE_S32:
740 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
741 break;
742 case SIDE_TYPE_U64:
743 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
744 break;
745 case SIDE_TYPE_S64:
746 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
747 break;
748 case SIDE_TYPE_BYTE:
749 sav_elem.u.side_byte = ((const uint8_t *) p)[i];
750 break;
751
752 default:
753 fprintf(stderr, "ERROR: Unexpected type\n");
754 abort();
755 }
756
757 printf("%s", i ? ", " : "");
758 tracer_print_type(elem_type, &sav_elem);
759 }
760 printf(" ]");
761 return;
762
763 type_error:
764 fprintf(stderr, "ERROR: type mismatch\n");
765 abort();
766 }
767
768 void tracer_print_vla_fixint(const struct side_type_description *type_desc, const struct side_arg_vec *item)
769 {
770 const struct side_type_description *elem_type = type_desc->u.side_vla.elem_type;
771 uint32_t side_sav_len = item->u.side_vla_fixint.length;
772 void *p = item->u.side_vla_fixint.p;
773 enum side_type side_type;
774 int i;
775
776 print_attributes("attr", ":", type_desc->u.side_vla.attr, type_desc->u.side_vla.nr_attr);
777 printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
778 printf("elements: ");
779 switch (item->type) {
780 case SIDE_TYPE_VLA_U8:
781 if (elem_type->type != SIDE_TYPE_U8)
782 goto type_error;
783 break;
784 case SIDE_TYPE_VLA_U16:
785 if (elem_type->type != SIDE_TYPE_U16)
786 goto type_error;
787 break;
788 case SIDE_TYPE_VLA_U32:
789 if (elem_type->type != SIDE_TYPE_U32)
790 goto type_error;
791 break;
792 case SIDE_TYPE_VLA_U64:
793 if (elem_type->type != SIDE_TYPE_U64)
794 goto type_error;
795 break;
796 case SIDE_TYPE_VLA_S8:
797 if (elem_type->type != SIDE_TYPE_S8)
798 goto type_error;
799 break;
800 case SIDE_TYPE_VLA_S16:
801 if (elem_type->type != SIDE_TYPE_S16)
802 goto type_error;
803 break;
804 case SIDE_TYPE_VLA_S32:
805 if (elem_type->type != SIDE_TYPE_S32)
806 goto type_error;
807 break;
808 case SIDE_TYPE_VLA_S64:
809 if (elem_type->type != SIDE_TYPE_S64)
810 goto type_error;
811 break;
812 case SIDE_TYPE_VLA_BYTE:
813 if (elem_type->type != SIDE_TYPE_BYTE)
814 goto type_error;
815 break;
816 default:
817 goto type_error;
818 }
819 side_type = elem_type->type;
820
821 printf("[ ");
822 for (i = 0; i < side_sav_len; i++) {
823 struct side_arg_vec sav_elem = {
824 .type = side_type,
825 };
826
827 switch (side_type) {
828 case SIDE_TYPE_U8:
829 sav_elem.u.side_u8 = ((const uint8_t *) p)[i];
830 break;
831 case SIDE_TYPE_S8:
832 sav_elem.u.side_s8 = ((const int8_t *) p)[i];
833 break;
834 case SIDE_TYPE_U16:
835 sav_elem.u.side_u16 = ((const uint16_t *) p)[i];
836 break;
837 case SIDE_TYPE_S16:
838 sav_elem.u.side_s16 = ((const int16_t *) p)[i];
839 break;
840 case SIDE_TYPE_U32:
841 sav_elem.u.side_u32 = ((const uint32_t *) p)[i];
842 break;
843 case SIDE_TYPE_S32:
844 sav_elem.u.side_s32 = ((const int32_t *) p)[i];
845 break;
846 case SIDE_TYPE_U64:
847 sav_elem.u.side_u64 = ((const uint64_t *) p)[i];
848 break;
849 case SIDE_TYPE_S64:
850 sav_elem.u.side_s64 = ((const int64_t *) p)[i];
851 break;
852 case SIDE_TYPE_BYTE:
853 sav_elem.u.side_byte = ((const uint8_t *) p)[i];
854 break;
855
856 default:
857 fprintf(stderr, "ERROR: Unexpected type\n");
858 abort();
859 }
860
861 printf("%s", i ? ", " : "");
862 tracer_print_type(elem_type, &sav_elem);
863 }
864 printf(" ]");
865 return;
866
867 type_error:
868 fprintf(stderr, "ERROR: type mismatch\n");
869 abort();
870 }
871
872 static
873 void tracer_print_dynamic_struct(const struct side_arg_dynamic_event_struct *dynamic_struct)
874 {
875 const struct side_arg_dynamic_event_field *fields = dynamic_struct->fields;
876 uint32_t len = dynamic_struct->len;
877 int i;
878
879 print_attributes("attr", "::", dynamic_struct->attr, dynamic_struct->nr_attr);
880 printf("%s", dynamic_struct->nr_attr ? ", " : "");
881 printf("fields:: ");
882 printf("[ ");
883 for (i = 0; i < len; i++) {
884 printf("%s", i ? ", " : "");
885 printf("%s:: ", fields[i].field_name);
886 tracer_print_dynamic(&fields[i].elem);
887 }
888 printf(" ]");
889 }
890
891 struct tracer_dynamic_struct_visitor_priv {
892 int i;
893 };
894
895 static
896 enum side_visitor_status tracer_dynamic_struct_write_elem_cb(
897 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
898 const struct side_arg_dynamic_event_field *dynamic_field)
899 {
900 struct tracer_dynamic_struct_visitor_priv *tracer_priv = tracer_ctx->priv;
901
902 printf("%s", tracer_priv->i++ ? ", " : "");
903 printf("%s:: ", dynamic_field->field_name);
904 tracer_print_dynamic(&dynamic_field->elem);
905 return SIDE_VISITOR_STATUS_OK;
906 }
907
908 static
909 void tracer_print_dynamic_struct_visitor(const struct side_arg_dynamic_vec *item)
910 {
911 enum side_visitor_status status;
912 struct tracer_dynamic_struct_visitor_priv tracer_priv = {
913 .i = 0,
914 };
915 const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = {
916 .write_field = tracer_dynamic_struct_write_elem_cb,
917 .priv = &tracer_priv,
918 };
919 void *app_ctx = item->u.side_dynamic_struct_visitor.app_ctx;
920
921 print_attributes("attr", "::", item->u.side_dynamic_struct_visitor.attr, item->u.side_dynamic_struct_visitor.nr_attr);
922 printf("%s", item->u.side_dynamic_struct_visitor.nr_attr ? ", " : "");
923 printf("fields:: ");
924 printf("[ ");
925 status = item->u.side_dynamic_struct_visitor.visitor(&tracer_ctx, app_ctx);
926 switch (status) {
927 case SIDE_VISITOR_STATUS_OK:
928 break;
929 case SIDE_VISITOR_STATUS_ERROR:
930 fprintf(stderr, "ERROR: Visitor error\n");
931 abort();
932 }
933 printf(" ]");
934 }
935
936 static
937 void tracer_print_dynamic_vla(const struct side_arg_dynamic_vec_vla *vla)
938 {
939 const struct side_arg_dynamic_vec *sav = vla->sav;
940 uint32_t side_sav_len = vla->len;
941 int i;
942
943 print_attributes("attr", "::", vla->attr, vla->nr_attr);
944 printf("%s", vla->nr_attr ? ", " : "");
945 printf("elements:: ");
946 printf("[ ");
947 for (i = 0; i < side_sav_len; i++) {
948 printf("%s", i ? ", " : "");
949 tracer_print_dynamic(&sav[i]);
950 }
951 printf(" ]");
952 }
953
954 struct tracer_dynamic_vla_visitor_priv {
955 int i;
956 };
957
958 static
959 enum side_visitor_status tracer_dynamic_vla_write_elem_cb(
960 const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
961 const struct side_arg_dynamic_vec *elem)
962 {
963 struct tracer_dynamic_vla_visitor_priv *tracer_priv = tracer_ctx->priv;
964
965 printf("%s", tracer_priv->i++ ? ", " : "");
966 tracer_print_dynamic(elem);
967 return SIDE_VISITOR_STATUS_OK;
968 }
969
970 static
971 void tracer_print_dynamic_vla_visitor(const struct side_arg_dynamic_vec *item)
972 {
973 enum side_visitor_status status;
974 struct tracer_dynamic_vla_visitor_priv tracer_priv = {
975 .i = 0,
976 };
977 const struct side_tracer_dynamic_vla_visitor_ctx tracer_ctx = {
978 .write_elem = tracer_dynamic_vla_write_elem_cb,
979 .priv = &tracer_priv,
980 };
981 void *app_ctx = item->u.side_dynamic_vla_visitor.app_ctx;
982
983 print_attributes("attr", "::", item->u.side_dynamic_vla_visitor.attr, item->u.side_dynamic_vla_visitor.nr_attr);
984 printf("%s", item->u.side_dynamic_vla_visitor.nr_attr ? ", " : "");
985 printf("elements:: ");
986 printf("[ ");
987 status = item->u.side_dynamic_vla_visitor.visitor(&tracer_ctx, app_ctx);
988 switch (status) {
989 case SIDE_VISITOR_STATUS_OK:
990 break;
991 case SIDE_VISITOR_STATUS_ERROR:
992 fprintf(stderr, "ERROR: Visitor error\n");
993 abort();
994 }
995 printf(" ]");
996 }
997
998 static
999 void tracer_print_dynamic_basic_type_header(const struct side_arg_dynamic_vec *item)
1000 {
1001 print_attributes("attr", "::", item->u.side_basic.attr, item->u.side_basic.nr_attr);
1002 printf("%s", item->u.side_basic.nr_attr ? ", " : "");
1003 printf("value:: ");
1004 }
1005
1006 static
1007 void tracer_print_dynamic(const struct side_arg_dynamic_vec *item)
1008 {
1009 printf("{ ");
1010 switch (item->dynamic_type) {
1011 case SIDE_DYNAMIC_TYPE_NULL:
1012 tracer_print_dynamic_basic_type_header(item);
1013 printf("<NULL TYPE>");
1014 break;
1015 case SIDE_DYNAMIC_TYPE_BOOL:
1016 tracer_print_dynamic_basic_type_header(item);
1017 printf("%s", item->u.side_basic.u.side_bool ? "true" : "false");
1018 break;
1019 case SIDE_DYNAMIC_TYPE_U8:
1020 tracer_print_dynamic_basic_type_header(item);
1021 printf("%" PRIu8, item->u.side_basic.u.side_u8);
1022 break;
1023 case SIDE_DYNAMIC_TYPE_U16:
1024 tracer_print_dynamic_basic_type_header(item);
1025 printf("%" PRIu16, item->u.side_basic.u.side_u16);
1026 break;
1027 case SIDE_DYNAMIC_TYPE_U32:
1028 tracer_print_dynamic_basic_type_header(item);
1029 printf("%" PRIu32, item->u.side_basic.u.side_u32);
1030 break;
1031 case SIDE_DYNAMIC_TYPE_U64:
1032 tracer_print_dynamic_basic_type_header(item);
1033 printf("%" PRIu64, item->u.side_basic.u.side_u64);
1034 break;
1035 case SIDE_DYNAMIC_TYPE_S8:
1036 tracer_print_dynamic_basic_type_header(item);
1037 printf("%" PRId8, item->u.side_basic.u.side_s8);
1038 break;
1039 case SIDE_DYNAMIC_TYPE_S16:
1040 tracer_print_dynamic_basic_type_header(item);
1041 printf("%" PRId16, item->u.side_basic.u.side_s16);
1042 break;
1043 case SIDE_DYNAMIC_TYPE_S32:
1044 tracer_print_dynamic_basic_type_header(item);
1045 printf("%" PRId32, item->u.side_basic.u.side_s32);
1046 break;
1047 case SIDE_DYNAMIC_TYPE_S64:
1048 tracer_print_dynamic_basic_type_header(item);
1049 printf("%" PRId64, item->u.side_basic.u.side_s64);
1050 break;
1051 case SIDE_DYNAMIC_TYPE_BYTE:
1052 tracer_print_dynamic_basic_type_header(item);
1053 printf("0x%" PRIx8, item->u.side_basic.u.side_byte);
1054 break;
1055
1056 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY16:
1057 tracer_print_dynamic_basic_type_header(item);
1058 #if __HAVE_FLOAT16
1059 printf("%g", (double) item->u.side_basic.u.side_float_binary16);
1060 break;
1061 #else
1062 fprintf(stderr, "ERROR: Unsupported binary16 float type\n");
1063 abort();
1064 #endif
1065 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY32:
1066 tracer_print_dynamic_basic_type_header(item);
1067 #if __HAVE_FLOAT32
1068 printf("%g", (double) item->u.side_basic.u.side_float_binary32);
1069 break;
1070 #else
1071 fprintf(stderr, "ERROR: Unsupported binary32 float type\n");
1072 abort();
1073 #endif
1074 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY64:
1075 tracer_print_dynamic_basic_type_header(item);
1076 #if __HAVE_FLOAT64
1077 printf("%g", (double) item->u.side_basic.u.side_float_binary64);
1078 break;
1079 #else
1080 fprintf(stderr, "ERROR: Unsupported binary64 float type\n");
1081 abort();
1082 #endif
1083 case SIDE_DYNAMIC_TYPE_FLOAT_BINARY128:
1084 tracer_print_dynamic_basic_type_header(item);
1085 #if __HAVE_FLOAT128
1086 printf("%Lg", (long double) item->u.side_basic.u.side_float_binary128);
1087 break;
1088 #else
1089 fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
1090 abort();
1091 #endif
1092 case SIDE_DYNAMIC_TYPE_STRING:
1093 tracer_print_dynamic_basic_type_header(item);
1094 printf("\"%s\"", item->u.side_basic.u.string);
1095 break;
1096 case SIDE_DYNAMIC_TYPE_STRUCT:
1097 tracer_print_dynamic_struct(item->u.side_dynamic_struct);
1098 break;
1099 case SIDE_DYNAMIC_TYPE_STRUCT_VISITOR:
1100 tracer_print_dynamic_struct_visitor(item);
1101 break;
1102 case SIDE_DYNAMIC_TYPE_VLA:
1103 tracer_print_dynamic_vla(item->u.side_dynamic_vla);
1104 break;
1105 case SIDE_DYNAMIC_TYPE_VLA_VISITOR:
1106 tracer_print_dynamic_vla_visitor(item);
1107 break;
1108 default:
1109 fprintf(stderr, "<UNKNOWN TYPE>");
1110 abort();
1111 }
1112 printf(" }");
1113 }
1114
1115 static
1116 void tracer_print_static_fields(const struct side_event_description *desc,
1117 const struct side_arg_vec_description *sav_desc,
1118 int *nr_items)
1119 {
1120 const struct side_arg_vec *sav = sav_desc->sav;
1121 uint32_t side_sav_len = sav_desc->len;
1122 int i;
1123
1124 printf("provider: %s, event: %s", desc->provider_name, desc->event_name);
1125 if (desc->nr_fields != side_sav_len) {
1126 fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n");
1127 abort();
1128 }
1129 print_attributes(", attr", ":", desc->attr, desc->nr_attr);
1130 printf("%s", side_sav_len ? ", fields: [ " : "");
1131 for (i = 0; i < side_sav_len; i++) {
1132 printf("%s", i ? ", " : "");
1133 tracer_print_field(&desc->fields[i], &sav[i]);
1134 }
1135 if (nr_items)
1136 *nr_items = i;
1137 if (side_sav_len)
1138 printf(" ]");
1139 }
1140
1141 void tracer_call(const struct side_event_description *desc,
1142 const struct side_arg_vec_description *sav_desc,
1143 void *priv __attribute__((unused)))
1144 {
1145 int nr_fields = 0;
1146
1147 tracer_print_static_fields(desc, sav_desc, &nr_fields);
1148 printf("\n");
1149 }
1150
1151 void tracer_call_variadic(const struct side_event_description *desc,
1152 const struct side_arg_vec_description *sav_desc,
1153 const struct side_arg_dynamic_event_struct *var_struct,
1154 void *priv __attribute__((unused)))
1155 {
1156 uint32_t var_struct_len = var_struct->len;
1157 int nr_fields = 0, i;
1158
1159 tracer_print_static_fields(desc, sav_desc, &nr_fields);
1160
1161 if (side_unlikely(!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))) {
1162 fprintf(stderr, "ERROR: unexpected non-variadic event description\n");
1163 abort();
1164 }
1165 print_attributes(", attr ", "::", var_struct->attr, var_struct->nr_attr);
1166 printf("%s", var_struct_len ? ", fields:: [ " : "");
1167 for (i = 0; i < var_struct_len; i++, nr_fields++) {
1168 printf("%s", i ? ", " : "");
1169 printf("%s:: ", var_struct->fields[i].field_name);
1170 tracer_print_dynamic(&var_struct->fields[i].elem);
1171 }
1172 if (i)
1173 printf(" ]");
1174 printf("\n");
1175 }
1176
1177 void tracer_event_notification(enum side_tracer_notification notif,
1178 struct side_event_description **events, uint32_t nr_events, void *priv)
1179 {
1180 uint32_t i;
1181
1182 printf("----------------------------------------------------------\n");
1183 printf("Tracer notified of events %s\n",
1184 SIDE_TRACER_NOTIFICATION_INSERT_EVENTS ? "inserted" : "removed");
1185 for (i = 0; i < nr_events; i++) {
1186 struct side_event_description *event = events[i];
1187
1188 /* Skip NULL pointers */
1189 if (!event)
1190 continue;
1191 printf("provider: %s, event: %s\n",
1192 event->provider_name, event->event_name);
1193 }
1194 printf("----------------------------------------------------------\n");
1195 }
1196
1197 static __attribute__((constructor))
1198 void tracer_init(void);
1199 static
1200 void tracer_init(void)
1201 {
1202 tracer_handle = side_tracer_event_notification_register(tracer_event_notification, NULL);
1203 if (!tracer_handle)
1204 abort();
1205 }
1206
1207 static __attribute__((destructor))
1208 void tracer_exit(void);
1209 static
1210 void tracer_exit(void)
1211 {
1212 side_tracer_event_notification_unregister(tracer_handle);
1213 }
This page took 0.056323 seconds and 5 git commands to generate.