+ const struct side_arg *sav = side_arg_vec->sav;
+ uint32_t i, side_sav_len = side_arg_vec->len;
+
+ if (type_desc->u.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", ":", type_desc->u.side_struct->attr, type_desc->u.side_struct->nr_attr);
+ printf("%s", type_desc->u.side_struct->nr_attr ? ", " : "");
+ printf("fields: { ");
+ for (i = 0; i < side_sav_len; i++) {
+ printf("%s", i ? ", " : "");
+ tracer_print_field(&type_desc->u.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 = 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_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", ":", 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(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", ":", 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(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(ptr));
+ 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(":", 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(":", 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);
+ break;
+ case SIDE_TYPE_GATHER_ARRAY:
+ len = tracer_print_gather_array(&type_desc->u.side_gather, ptr);
+ break;
+ case SIDE_TYPE_GATHER_VLA:
+ len = tracer_print_gather_vla(&type_desc->u.side_gather, ptr, ptr);
+ break;
+ default:
+ fprintf(stderr, "<UNKNOWN GATHER TYPE>");
+ abort();
+ }
+ printf(" }");
+ return len;
+}
+
+static
+uint32_t tracer_print_gather_enum_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+ const struct side_enum_mappings *mappings = type_gather->u.side_enum.mappings;
+ const struct side_type *enum_elem_type = type_gather->u.side_enum.elem_type;
+ const struct side_type_gather_integer *side_integer = &enum_elem_type->u.side_gather.u.side_integer;
+ 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;
+ union int64_value v64;
+
+ switch (integer_size_bytes) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ abort();
+ }
+ ptr = tracer_gather_access(access_mode, ptr + side_integer->offset);
+ memcpy(&value, ptr, integer_size_bytes);
+ v64 = tracer_load_gather_integer_value(side_integer, &value);
+ print_attributes("attr", ":", mappings->attr, mappings->nr_attr);
+ printf("%s", mappings->nr_attr ? ", " : "");
+ tracer_print_gather_type(enum_elem_type, ptr);
+ print_enum_labels(mappings, v64);
+ return tracer_gather_size(access_mode, integer_size_bytes);
+}
+
+static
+void tracer_print_gather_field(const struct side_event_field *field, const void *ptr)
+{
+ printf("%s: ", field->field_name);
+ (void) tracer_print_gather_type(&field->side_type, ptr);
+}
+
+static
+uint32_t tracer_print_gather_struct(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_struct.access_mode;
+ const char *ptr = (const char *) _ptr;
+ uint32_t i;