+ tracer_print_vla(type_desc, item->u.side_static.side_vla);
+ break;
+ case SIDE_TYPE_VLA_VISITOR:
+ tracer_print_vla_visitor(type_desc, item->u.side_static.side_vla_app_visitor_ctx);
+ break;
+
+ /* Stack-copy enumeration types */
+ case SIDE_TYPE_ENUM:
+ tracer_print_enum(type_desc, item);
+ break;
+ case SIDE_TYPE_ENUM_BITMAP:
+ tracer_print_enum_bitmap(type_desc, item);
+ break;
+
+ /* Gather basic types */
+ case SIDE_TYPE_GATHER_BOOL:
+ (void) tracer_print_gather_bool_type(&type_desc->u.side_gather, item->u.side_static.side_bool_gather_ptr);
+ break;
+ case SIDE_TYPE_GATHER_INTEGER:
+ (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, item->u.side_static.side_integer_gather_ptr,
+ TRACER_DISPLAY_BASE_10);
+ break;
+ case SIDE_TYPE_GATHER_BYTE:
+ (void) tracer_print_gather_byte_type(&type_desc->u.side_gather, item->u.side_static.side_byte_gather_ptr);
+ break;
+ case SIDE_TYPE_GATHER_POINTER:
+ (void) tracer_print_gather_integer_type(&type_desc->u.side_gather, item->u.side_static.side_integer_gather_ptr,
+ TRACER_DISPLAY_BASE_16);
+ break;
+ case SIDE_TYPE_GATHER_FLOAT:
+ (void) tracer_print_gather_float_type(&type_desc->u.side_gather, item->u.side_static.side_float_gather_ptr);
+ break;
+ case SIDE_TYPE_GATHER_STRING:
+ (void) tracer_print_gather_string_type(&type_desc->u.side_gather, item->u.side_static.side_string_gather_ptr);
+ break;
+
+ /* Gather compound type */
+ case SIDE_TYPE_GATHER_STRUCT:
+ (void) tracer_print_gather_struct(&type_desc->u.side_gather, item->u.side_static.side_struct_gather_ptr);
+ break;
+ case SIDE_TYPE_GATHER_ARRAY:
+ (void) tracer_print_gather_array(&type_desc->u.side_gather, item->u.side_static.side_array_gather_ptr);
+ break;
+ case SIDE_TYPE_GATHER_VLA:
+ (void) tracer_print_gather_vla(&type_desc->u.side_gather, item->u.side_static.side_vla_gather.ptr,
+ item->u.side_static.side_vla_gather.length_ptr);
+ break;
+
+ /* Gather enumeration types */
+ case SIDE_TYPE_GATHER_ENUM:
+ (void) tracer_print_gather_enum_type(&type_desc->u.side_gather, item->u.side_static.side_integer_gather_ptr);
+ break;
+
+ /* Dynamic basic types */
+ case SIDE_TYPE_DYNAMIC_NULL:
+ case SIDE_TYPE_DYNAMIC_BOOL:
+ case SIDE_TYPE_DYNAMIC_INTEGER:
+ case SIDE_TYPE_DYNAMIC_BYTE:
+ case SIDE_TYPE_DYNAMIC_POINTER:
+ case SIDE_TYPE_DYNAMIC_FLOAT:
+ case SIDE_TYPE_DYNAMIC_STRING:
+
+ /* Dynamic compound types */
+ case SIDE_TYPE_DYNAMIC_STRUCT:
+ case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR:
+ case SIDE_TYPE_DYNAMIC_VLA:
+ case SIDE_TYPE_DYNAMIC_VLA_VISITOR:
+ tracer_print_dynamic(item);
+ break;
+ default:
+ fprintf(stderr, "<UNKNOWN TYPE>\n");
+ abort();
+ }
+ printf(" }");
+}
+
+static
+void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg *item)
+{
+ printf("%s: ", side_ptr_get(item_desc->field_name));
+ tracer_print_type(&item_desc->side_type, item);
+}
+
+static
+void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
+{
+ const struct side_arg *sav = side_arg_vec->sav;
+ const struct side_type_struct *side_struct = side_ptr_get(type_desc->u.side_struct);
+ uint32_t i, side_sav_len = side_arg_vec->len;
+
+ if (side_struct->nr_fields != side_sav_len) {
+ fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n");
+ abort();
+ }
+ print_attributes("attr", ":", side_ptr_get(side_struct->attr), side_struct->nr_attr);
+ printf("%s", side_struct->nr_attr ? ", " : "");
+ printf("fields: { ");
+ for (i = 0; i < side_sav_len; i++) {
+ printf("%s", i ? ", " : "");
+ tracer_print_field(&side_ptr_get(side_struct->fields)[i], &sav[i]);
+ }
+ printf(" }");
+}
+
+static
+void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant)
+{
+ const struct side_type_variant *side_type_variant = side_ptr_get(type_desc->u.side_variant);
+ const struct side_type *selector_type = &side_type_variant->selector;
+ union int64_value v64;
+ uint32_t i;
+
+ if (selector_type->type != side_arg_variant->selector.type) {
+ fprintf(stderr, "ERROR: Unexpected variant selector type\n");
+ abort();
+ }
+ switch (selector_type->type) {
+ case SIDE_TYPE_U8:
+ case SIDE_TYPE_U16:
+ case SIDE_TYPE_U32:
+ case SIDE_TYPE_U64:
+ case SIDE_TYPE_S8:
+ case SIDE_TYPE_S16:
+ case SIDE_TYPE_S32:
+ case SIDE_TYPE_S64:
+ break;
+ default:
+ fprintf(stderr, "ERROR: Expecting integer variant selector type\n");
+ abort();
+ }
+ v64 = tracer_load_integer_value(&selector_type->u.side_integer,
+ &side_arg_variant->selector.u.side_static.integer_value, 0, NULL);
+ for (i = 0; i < side_type_variant->nr_options; i++) {
+ const struct side_variant_option *option = &side_ptr_get(side_type_variant->options)[i];
+
+ if (v64.s >= option->range_begin && v64.s <= option->range_end) {
+ tracer_print_type(&option->side_type, &side_arg_variant->option);
+ return;
+ }
+ }
+ fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v64.s);
+ abort();
+}
+
+static
+void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
+{
+ const struct side_arg *sav = side_arg_vec->sav;
+ uint32_t i, side_sav_len = side_arg_vec->len;
+
+ if (type_desc->u.side_array.length != side_sav_len) {
+ fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n");
+ abort();
+ }
+ print_attributes("attr", ":", side_ptr_get(type_desc->u.side_array.attr), type_desc->u.side_array.nr_attr);
+ printf("%s", type_desc->u.side_array.nr_attr ? ", " : "");
+ printf("elements: ");
+ printf("[ ");
+ for (i = 0; i < side_sav_len; i++) {
+ printf("%s", i ? ", " : "");
+ tracer_print_type(side_ptr_get(type_desc->u.side_array.elem_type), &sav[i]);
+ }
+ printf(" ]");
+}
+
+static
+void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
+{
+ const struct side_arg *sav = side_arg_vec->sav;
+ uint32_t i, side_sav_len = side_arg_vec->len;
+
+ print_attributes("attr", ":", side_ptr_get(type_desc->u.side_vla.attr), type_desc->u.side_vla.nr_attr);
+ printf("%s", type_desc->u.side_vla.nr_attr ? ", " : "");
+ printf("elements: ");
+ printf("[ ");
+ for (i = 0; i < side_sav_len; i++) {
+ printf("%s", i ? ", " : "");
+ tracer_print_type(side_ptr_get(type_desc->u.side_vla.elem_type), &sav[i]);
+ }
+ printf(" ]");
+}
+
+static
+const char *tracer_gather_access(enum side_type_gather_access_mode access_mode, const char *ptr)
+{
+ switch (access_mode) {
+ case SIDE_TYPE_GATHER_ACCESS_DIRECT:
+ return ptr;
+ case SIDE_TYPE_GATHER_ACCESS_POINTER:
+ /* Dereference pointer */
+ memcpy(&ptr, ptr, sizeof(const char *));
+ return ptr;
+ default:
+ abort();
+ }
+}
+
+static
+uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode, uint32_t len)
+{
+ switch (access_mode) {
+ case SIDE_TYPE_GATHER_ACCESS_DIRECT:
+ return len;
+ case SIDE_TYPE_GATHER_ACCESS_POINTER:
+ return sizeof(void *);
+ default:
+ abort();
+ }
+}
+
+static
+union int64_value tracer_load_gather_integer_value(const struct side_type_gather_integer *side_integer,
+ const void *_ptr)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) side_integer->access_mode;
+ uint32_t integer_size_bytes = side_integer->type.integer_size;
+ const char *ptr = (const char *) _ptr;
+ union side_integer_value value;
+
+ ptr = tracer_gather_access(access_mode, ptr + side_integer->offset);
+ memcpy(&value, ptr, integer_size_bytes);
+ return tracer_load_integer_value(&side_integer->type, &value,
+ side_integer->offset_bits, NULL);
+}
+
+static
+uint32_t tracer_print_gather_bool_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) type_gather->u.side_bool.access_mode;
+ uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size;
+ const char *ptr = (const char *) _ptr;
+ union side_bool_value value;
+
+ switch (bool_size_bytes) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ abort();
+ }
+ ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset);
+ memcpy(&value, ptr, bool_size_bytes);
+ tracer_print_type_bool(":", &type_gather->u.side_bool.type, &value,
+ type_gather->u.side_bool.offset_bits);
+ return tracer_gather_size(access_mode, bool_size_bytes);
+}
+
+static
+uint32_t tracer_print_gather_byte_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) type_gather->u.side_byte.access_mode;
+ const char *ptr = (const char *) _ptr;
+ uint8_t value;
+
+ ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset);
+ memcpy(&value, ptr, 1);
+ tracer_print_type_header(":", side_ptr_get(type_gather->u.side_byte.type.attr),
+ type_gather->u.side_byte.type.nr_attr);
+ printf("0x%" PRIx8, value);
+ return tracer_gather_size(access_mode, 1);
+}
+
+static
+uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_gather, const void *_ptr,
+ enum tracer_display_base default_base)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode;
+ uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size;
+ const char *ptr = (const char *) _ptr;
+ union side_integer_value value;
+
+ switch (integer_size_bytes) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ abort();
+ }
+ ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset);
+ memcpy(&value, ptr, integer_size_bytes);
+ tracer_print_type_integer(":", &type_gather->u.side_integer.type, &value,
+ type_gather->u.side_integer.offset_bits, default_base);
+ return tracer_gather_size(access_mode, integer_size_bytes);
+}
+
+static
+uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) type_gather->u.side_float.access_mode;
+ uint32_t float_size_bytes = type_gather->u.side_float.type.float_size;
+ const char *ptr = (const char *) _ptr;
+ union side_float_value value;
+
+ switch (float_size_bytes) {
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ break;
+ default:
+ abort();
+ }
+ ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset);
+ memcpy(&value, ptr, float_size_bytes);
+ tracer_print_type_float(":", &type_gather->u.side_float.type, &value);
+ return tracer_gather_size(access_mode, float_size_bytes);
+}
+
+static
+uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+ enum side_type_gather_access_mode access_mode =
+ (enum side_type_gather_access_mode) type_gather->u.side_string.access_mode;
+ const char *ptr = (const char *) _ptr;
+ size_t string_len;
+
+ ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset);
+ tracer_print_type_header(":", side_ptr_get(type_gather->u.side_string.type.attr),
+ type_gather->u.side_string.type.nr_attr);
+ if (ptr) {
+ tracer_print_string(ptr, type_gather->u.side_string.type.unit_size,
+ type_gather->u.side_string.type.byte_order, &string_len);
+ } else {
+ printf("<NULL>");
+ string_len = type_gather->u.side_string.type.unit_size;
+ }
+ return tracer_gather_size(access_mode, string_len);
+}
+
+static
+uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void *ptr)
+{
+ uint32_t len;
+
+ printf("{ ");
+ switch (type_desc->type) {
+ /* Gather basic types */
+ case SIDE_TYPE_GATHER_BOOL:
+ len = tracer_print_gather_bool_type(&type_desc->u.side_gather, ptr);
+ break;
+ case SIDE_TYPE_GATHER_INTEGER:
+ len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr,
+ TRACER_DISPLAY_BASE_10);
+ break;
+ case SIDE_TYPE_GATHER_BYTE:
+ len = tracer_print_gather_byte_type(&type_desc->u.side_gather, ptr);
+ break;
+ case SIDE_TYPE_GATHER_POINTER:
+ len = tracer_print_gather_integer_type(&type_desc->u.side_gather, ptr,
+ TRACER_DISPLAY_BASE_16);
+ break;
+ case SIDE_TYPE_GATHER_FLOAT:
+ len = tracer_print_gather_float_type(&type_desc->u.side_gather, ptr);
+ break;
+ case SIDE_TYPE_GATHER_STRING:
+ len = tracer_print_gather_string_type(&type_desc->u.side_gather, ptr);
+ break;
+
+ /* Gather enum types */
+ case SIDE_TYPE_GATHER_ENUM:
+ len = tracer_print_gather_enum_type(&type_desc->u.side_gather, ptr);
+ break;
+
+ /* Gather compound types */
+ case SIDE_TYPE_GATHER_STRUCT:
+ len = tracer_print_gather_struct(&type_desc->u.side_gather, ptr);