+void tracer_convert_string_to_utf8(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order,
+ size_t *strlen_with_null,
+ char **output_str)
+{
+ size_t ret, inbytesleft = 0, outbytesleft, bufsize;
+ const char *str = p, *fromcode;
+ char *inbuf = (char *) p, *outbuf, *buf;
+ iconv_t cd;
+
+ switch (unit_size) {
+ case 1:
+ if (strlen_with_null)
+ *strlen_with_null = strlen(str) + 1;
+ *output_str = (char *) str;
+ return;
+ case 2:
+ {
+ const uint16_t *p16 = p;
+
+ switch (byte_order) {
+ case SIDE_TYPE_BYTE_ORDER_LE:
+ {
+ fromcode = "UTF-16LE";
+ break;
+ }
+ case SIDE_TYPE_BYTE_ORDER_BE:
+ {
+ fromcode = "UTF-16BE";
+ break;
+ }
+ default:
+ fprintf(stderr, "Unknown byte order\n");
+ abort();
+ }
+ for (; *p16; p16++)
+ inbytesleft += 2;
+ /*
+ * Worse case is U+FFFF UTF-16 (2 bytes) converting to
+ * { ef, bf, bf } UTF-8 (3 bytes).
+ */
+ bufsize = inbytesleft / 2 * 3 + 1;
+ break;
+ }
+ case 4:
+ {
+ const uint32_t *p32 = p;
+
+ switch (byte_order) {
+ case SIDE_TYPE_BYTE_ORDER_LE:
+ {
+ fromcode = "UTF-32LE";
+ break;
+ }
+ case SIDE_TYPE_BYTE_ORDER_BE:
+ {
+ fromcode = "UTF-32BE";
+ break;
+ }
+ default:
+ fprintf(stderr, "Unknown byte order\n");
+ abort();
+ }
+ for (; *p32; p32++)
+ inbytesleft += 4;
+ /*
+ * Each 4-byte UTF-32 character converts to at most a
+ * 4-byte UTF-8 character.
+ */
+ bufsize = inbytesleft + 1;
+ break;
+ }
+ default:
+ fprintf(stderr, "Unknown string unit size %" PRIu8 "\n", unit_size);
+ abort();
+ }
+
+ cd = iconv_open("UTF8", fromcode);
+ if (cd == (iconv_t) -1) {
+ perror("iconv_open");
+ abort();
+ }
+ buf = malloc(bufsize);
+ if (!buf) {
+ abort();
+ }
+ outbuf = (char *) buf;
+ outbytesleft = bufsize;
+ ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ if (ret == (size_t) -1) {
+ perror("iconv");
+ abort();
+ }
+ if (inbytesleft) {
+ fprintf(stderr, "Buffer too small to convert string input\n");
+ abort();
+ }
+ (*outbuf++) = '\0';
+ if (iconv_close(cd) == -1) {
+ perror("iconv_close");
+ abort();
+ }
+ if (strlen_with_null)
+ *strlen_with_null = outbuf - buf;
+ *output_str = buf;
+}
+
+static
+void tracer_print_string(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order,
+ size_t *strlen_with_null)
+{
+ char *output_str = NULL;
+
+ tracer_convert_string_to_utf8(p, unit_size, byte_order, strlen_with_null, &output_str);
+ printf("\"%s\"", output_str);
+ if (output_str != p)
+ free(output_str);
+}
+
+static
+void side_check_value_u64(union int_value v)
+{
+ if (v.u[SIDE_INTEGER128_SPLIT_HIGH]) {
+ fprintf(stderr, "Unexpected integer value\n");
+ abort();
+ }
+}
+
+static
+void side_check_value_s64(union int_value v)
+{
+ if (v.s[SIDE_INTEGER128_SPLIT_LOW] & (1ULL << 63)) {
+ if (v.s[SIDE_INTEGER128_SPLIT_HIGH] != ~0LL) {
+ fprintf(stderr, "Unexpected integer value\n");
+ abort();
+ }
+ } else {
+ if (v.s[SIDE_INTEGER128_SPLIT_HIGH]) {
+ fprintf(stderr, "Unexpected integer value\n");
+ abort();
+ }
+ }
+}
+
+static
+int64_t get_attr_integer64_value(const struct side_attr *attr)