Ejemplo n.º 1
0
void json_write_string_len(OutputStream * out, const char * str, size_t len) {
    if (str == NULL) {
        write_string(out, "null");
    }
    else {
        const char * end = str + len;
        write_stream(out, '"');
        while (str < end) {
            const char * ptr = str;
            while (str < end && !char_escaping[(unsigned char)*str]) str++;
            if (ptr < str) {
                unsigned len = str - ptr;
                if (out->cur + len <= out->end) {
                    memcpy(out->cur, ptr, len);
                    out->cur += len;
                }
                else {
                    out->write_block(out, ptr, len);
                }
            }
            if (str == end) break;
            write_escape_seq(out, *str++);
        }
        write_stream(out, '"');
    }
}
Ejemplo n.º 2
0
static void command_read(char * token, Channel * c) {
    char id[256];
    size_t size;
    int err = 0;

    json_read_string(&c->inp, id, sizeof(id));
    json_test_char(&c->inp, MARKER_EOA);
    size = json_read_ulong(&c->inp);
    json_test_char(&c->inp, MARKER_EOA);
    json_test_char(&c->inp, MARKER_EOM);

    if (virtual_stream_read(c, token, id, size) < 0) err = errno;

    if (err != 0) {
        /*
         * Handle reply with an error. If none error was detected, the reply
         * was sent back by virtual_stream_read() or delayed.
         */
        write_stringz(&c->out, "R");
        write_stringz(&c->out, token);
        write_stringz(&c->out, "null");
        write_errno(&c->out, err);
        json_write_long(&c->out, 0);
        write_stream(&c->out, 0);
        json_write_boolean(&c->out, 0);
        write_stream(&c->out, 0);
        write_stream(&c->out, MARKER_EOM);
    }
}
Ejemplo n.º 3
0
static void command_get_children_cache_client(void * x) {
    CommandGetChildrenArgs * args = (CommandGetChildrenArgs *)x;
    Channel * c = cache_channel();
    int err = 0;
    Symbol * sym = NULL;
    Symbol ** list = NULL;
    int cnt = 0;

    if (id2symbol(args->id, &sym) < 0) err = errno;
    if (err == 0 && get_symbol_children(sym, &list, &cnt) < 0) err = errno;

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, err);

    if (err == 0) {
        int i;
        write_stream(&c->out, '[');
        for (i = 0; i < cnt; i++) {
            if (i > 0) write_stream(&c->out, ',');
            json_write_string(&c->out, symbol2id(list[i]));
        }
        write_stream(&c->out, ']');
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }

    write_stream(&c->out, MARKER_EOM);
}
Ejemplo n.º 4
0
static void command_get_context(char * token, Channel * c) {
    int err = 0;
    char id[256];
    int tid;
    Terminal * term = NULL;

    json_read_string(&c->inp, id, sizeof(id));
    json_test_char(&c->inp, MARKER_EOA);
    json_test_char(&c->inp, MARKER_EOM);

    tid = id2tid(id);
    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);

    if (tid == 0 || (term = find_terminal(tid)) == NULL) {
        err = ERR_INV_CONTEXT;
    }

    write_errno(&c->out, err);
    if (term != NULL) {
        write_context(&c->out, tid);
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }
    write_stream(&c->out, MARKER_EOM);
}
Ejemplo n.º 5
0
static void port_server_cmd_create(char * token, Channel * c) {
    int err = 0;
    PortAttribute * attrs = NULL;
    PortServer * server;
    Channel * port_channel;
    json_read_struct(&c->inp, read_port_server_property, &attrs);
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    /* In case the current channel is a proxy (value-add), use the
     * target channel. Otherwise, use the provided channel. */
    port_channel = proxy_get_target_channel(c);
    if (port_channel == NULL) port_channel = c;
    server = create_port_server(c, attrs, NULL, NULL, NULL, NULL);
    if (server == NULL) err = errno;
    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);
    if (err) write_stringz(&c->out, "null");
    else {
        write_port_server_info(&c->out, server);
        write_stream(&c->out, 0);
    }
    write_stream(&c->out, MARKER_EOM);
}
Ejemplo n.º 6
0
void send_event_memory_changed(Context * ctx, ContextAddress addr, unsigned long size) {
    OutputStream * out = &broadcast_group->out;

    if (!context_has_state(ctx) || is_intercepted(ctx)) {
        write_stringz(out, "E");
        write_stringz(out, MEMORY);
        write_stringz(out, "memoryChanged");

        json_write_string(out, ctx->id);
        write_stream(out, 0);

        /* <array of addres ranges> */
        write_stream(out, '[');
        write_stream(out, '{');

        json_write_string(out, "addr");
        write_stream(out, ':');
        json_write_uint64(out, addr);

        write_stream(out, ',');

        json_write_string(out, "size");
        write_stream(out, ':');
        json_write_ulong(out, size);

        write_stream(out, '}');
        write_stream(out, ']');
        write_stream(out, 0);

        write_stream(out, MARKER_EOM);
    }
}
Ejemplo n.º 7
0
static void command_get_signal_mask(char * token, Channel * c) {
    int err = 0;
    char id[256];
    pid_t pid;
    Context * ctx = NULL;

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    pid = id2pid(id, NULL);
    ctx = context_find_from_pid(pid);
    if (ctx == NULL) err = ERR_INV_CONTEXT;

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);

    if (ctx == NULL) {
        write_stringz(&c->out, "null");
        write_stringz(&c->out, "null");
        write_stringz(&c->out, "null");
    }
    else {
        json_write_long(&c->out, ctx->sig_dont_stop);
        write_stream(&c->out, 0);
        json_write_long(&c->out, ctx->sig_dont_pass);
        write_stream(&c->out, 0);
        json_write_long(&c->out, ctx->pending_signals);
        write_stream(&c->out, 0);
    }

    write_stream(&c->out, MARKER_EOM);
}
Ejemplo n.º 8
0
static void command_get_array_type_cache_client(void * x) {
    CommandGetArrayTypeArgs * args = (CommandGetArrayTypeArgs *)x;
    Channel * c = cache_channel();
    Symbol * sym = NULL;
    Symbol * arr = NULL;
    int err = 0;

    if (id2symbol(args->id, &sym) < 0) err = errno;
    if (err == 0 && get_array_symbol(sym, (ContextAddress)args->length, &arr) < 0) err = errno;

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, err);

    if (err == 0) {
        json_write_string(&c->out, symbol2id(arr));
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }

    write_stream(&c->out, MARKER_EOM);
}
static void port_server_cmd_create(char * token, Channel * c) {
    int err = 0;
    PortRedirectionInfo * port = loc_alloc_zero(sizeof(PortRedirectionInfo));
    PortServer * server;
    json_read_struct(&c->inp, read_port_server_property, port);
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    /* In case the current channel is a proxy (value-add), use the
     * target channel.
     */
    port->c = proxy_get_target_channel(c);
    if (port->c == NULL) port->c = c;
    server = create_port_redirection(port);
    if (server == NULL) err = errno;
    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);
    if (err) write_stringz(&c->out, "null");
    else {
        write_port_server_info(&c->out, server);
        write_stream(&c->out, 0);
    }
    write_stream(&c->out, MARKER_EOM);
}
static void delete_config_done(Channel *c, void *client_data, int error) {
    PortConnection * conn = (PortConnection *) client_data;
    Trap trap;

    if (set_trap(&trap)) {
        if (!error) {
            error = read_errno(&c->inp);
            json_test_char(&c->inp, MARKER_EOM);
        }
        clear_trap(&trap);
    }
    else {
        error = trap.error;
    }
    if (!conn->auto_connect_stream) {
        protocol_send_command(conn->server->channel, "Streams", "disconnect", disconnect_stream_done, conn);
        json_write_string(&conn->server->channel->out, conn->out_stream_id);
        write_stream(&conn->server->channel->out, MARKER_EOA);
        write_stream(&conn->server->channel->out, MARKER_EOM);
    }
    else {
        loc_free(conn->out_stream_id);
        conn->out_stream_id = NULL;
        loc_free(conn->in_stream_id);
        conn->in_stream_id = NULL;
        port_unlock(conn);
        port_connection_close(conn);
    }
}
Ejemplo n.º 11
0
static void command_get_state(char * token, Channel * c) {
    char id[256];
    Context * ctx;
    int err = 0;

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
    ctx = id2ctx(id);

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);

    if (ctx == NULL) err = ERR_INV_CONTEXT;
    else if (ctx->exited) err = ERR_ALREADY_EXITED;
    write_errno(&c->out, err);

    json_write_boolean(&c->out, ctx != NULL && ctx->intercepted);
    write_stream(&c->out, 0);

    if (err) {
        write_stringz(&c->out, "0");
        write_stringz(&c->out, "null");
        write_stringz(&c->out, "null");
    }
    else {
        write_context_state(&c->out, ctx);
    }

    write_stream(&c->out, MARKER_EOM);
}
Ejemplo n.º 12
0
void send_event_register_changed(const char * id) {
    unsigned i;
    Context * ctx = NULL;
    int frame = STACK_NO_FRAME;
    RegisterDefinition * def = NULL;
    OutputStream * out = &broadcast_group->out;

    id2register(id, &ctx, &frame, &def);
    if (ctx == NULL) return;

    for (i = 0; i < listener_cnt; i++) {
        Listener * l = listeners + i;
        if (l->func->register_changed == NULL) continue;
        l->func->register_changed(ctx, frame, def, l->args);
    }

    if (frame >= 0 && frame == get_top_frame(ctx)) {
        id = register2id(ctx, STACK_TOP_FRAME, def);
    }

    write_stringz(out, "E");
    write_stringz(out, REGISTERS);
    write_stringz(out, "registerChanged");

    json_write_string(out, id);
    write_stream(out, 0);

    write_stream(out, MARKER_EOM);
}
Ejemplo n.º 13
0
static void event_get_context(void * arg) {
    GetContextArgs * s = (GetContextArgs *)arg;
    Channel * c = s->c;
    Context * ctx = s->ctx;

    if (!is_stream_closed(c)) {
        int err = 0;

        write_stringz(&c->out, "R");
        write_stringz(&c->out, s->token);

        if (ctx->exited) err = ERR_ALREADY_EXITED;
        write_errno(&c->out, err);

        if (err == 0) {
            write_context(&c->out, ctx, s->parent != 0);
            write_stream(&c->out, 0);
        }
        else {
            write_stringz(&c->out, "null");
        }

        write_stream(&c->out, MARKER_EOM);
        flush_stream(&c->out);
    }
    stream_unlock(c);
    context_unlock(ctx);
    loc_free(s);
}
static int send_packet(PortConnection * conn, char * buffer, size_t size) {
    JsonWriteBinaryState state;

    assert (is_dispatch_thread());
    assert (conn->pending_write_request < MAX_STREAM_WRITE);
    protocol_send_command(conn->server->channel, "Streams", "write", write_stream_done,
            conn);
    json_write_string(&conn->server->channel->out, conn->out_stream_id);
    write_stream(&conn->server->channel->out, 0);
    json_write_long(&conn->server->channel->out, size);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    json_write_binary_start(&state, &conn->server->channel->out, size);
    json_write_binary_data(&state, buffer, size);
    json_write_binary_end(&state);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    write_stream(&conn->server->channel->out, MARKER_EOM);
    conn->pending_write_request ++;
    if (conn->pending_write_request  == MAX_STREAM_WRITE) {
        return 0;
    }
    else {
        send_packet_callback(conn, 0);
    }
    return 0;
}
static void send_eof_and_close(Channel * channel, int err) {
    ChannelNP * c = channel2np(channel);

    assert(c->magic == CHANNEL_MAGIC);
    if (channel->state == ChannelStateDisconnected) return;
    ibuf_flush(&c->ibuf);
    if (c->ibuf.handling_msg == HandleMsgTriggered) {
        /* Cancel pending message handling */
        cancel_event(handle_channel_msg, c, 0);
        c->ibuf.handling_msg = HandleMsgIdle;
    }
    write_stream(&c->chan.out, MARKER_EOS);
    write_errno(&c->chan.out, err);
    write_stream(&c->chan.out, MARKER_EOM);
    np_flush_with_flags(c, 0);
#if ENABLE_OutputQueue
    if (output_queue_is_empty(&c->out_queue))
#endif
        nopoll_conn_shutdown(c->np_socket);
    c->chan.state = ChannelStateDisconnected;
    np_post_read(&c->ibuf, c->ibuf.buf, c->ibuf.buf_size);
    notify_channel_closed(channel);
    if (channel->disconnected) {
        channel->disconnected(channel);
    }
    else {
        trace(LOG_PROTOCOL, "channel %#lx disconnected", c);
        if (channel->protocol != NULL) protocol_release(channel->protocol);
    }
    channel->protocol = NULL;
}
Ejemplo n.º 16
0
static void command_get_children(char * token, Channel * c) {
    int err = 0;
    char id[256];
    Symbol sym;
    Symbol * list = NULL;
    int cnt = 0;

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    if (id2symbol(id, &sym) < 0) err = errno;
    if (err == 0 && get_symbol_children(&sym, &list, &cnt) < 0) err = errno;

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);

    if (err == 0) {
        int i;
        write_stream(&c->out, '[');
        for (i = 0; i < cnt; i++) {
            if (i > 0) write_stream(&c->out, ',');
            json_write_string(&c->out, symbol2id(list + i));
        }
        write_stream(&c->out, ']');
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }

    write_stream(&c->out, MARKER_EOM);
    loc_free(list);
}
Ejemplo n.º 17
0
static void command_get_context(char * token, Channel * c) {
    int err = 0;
    char id[256];
    Context * ctx = NULL;

    json_read_string(&c->inp, id, sizeof(id));
    json_test_char(&c->inp, MARKER_EOA);
    json_test_char(&c->inp, MARKER_EOM);

    ctx = id2ctx(id);

    if (ctx == NULL || ctx->mem_access == 0) err = ERR_INV_CONTEXT;
    else if (ctx->exited) err = ERR_ALREADY_EXITED;

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);
    if (err == 0) {
        write_context(&c->out, ctx);
    }
    else {
        write_string(&c->out, "null");
    }
    write_stream(&c->out, 0);
    write_stream(&c->out, MARKER_EOM);
}
static void send_read_reply(StreamClient * client, char * token, size_t size) {
    VirtualStream * stream = client->stream;
    Channel * c = client->channel;
    unsigned lost = 0;
    unsigned read1 = 0;
    unsigned read2 = 0;
    int eos = 0;
    char * data1 = NULL;
    char * data2 = NULL;
    unsigned pos = 0;
    unsigned len = (stream->buf_inp + stream->buf_len - stream->buf_out) % stream->buf_len;

    assert(len > 0 || stream->eos);
    assert(client->pos <= stream->pos);
    if ((uint64_t)len < stream->pos - client->pos) {
        lost = (long)(stream->pos - client->pos - len);
    }
    else {
        len = (unsigned)(stream->pos - client->pos);
    }
    pos = (stream->buf_inp + stream->buf_len - len) % stream->buf_len;
    if (len > size) len = size;
    data1 = stream->buf + pos;
    if (pos + len <= stream->buf_len) {
        read1 = len;
    }
    else {
        read1 = stream->buf_len - pos;
        data2 = stream->buf;
        read2 = len - read1;
    }
    assert(read1 + read2 == len);
    client->pos += lost + read1 + read2;
    assert(client->pos <= stream->pos);
    if (client->pos == stream->pos && stream->eos) eos = 1;
    assert(eos || lost + read1 + read2 > 0);

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    if (read1 + read2 > 0) {
        JsonWriteBinaryState state;

        json_write_binary_start(&state, &c->out, read1 + read2);
        json_write_binary_data(&state, data1, read1);
        json_write_binary_data(&state, data2, read2);
        json_write_binary_end(&state);
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }
    write_errno(&c->out, 0);
    json_write_long(&c->out, lost);
    write_stream(&c->out, 0);
    json_write_boolean(&c->out, eos);
    write_stream(&c->out, 0);
    write_stream(&c->out, MARKER_EOM);
    flush_stream(&c->out);
}
Ejemplo n.º 19
0
static void write_boolean_member(OutputStream * out, const char * name, int val) {
    /* For this service FALSE is same as absence of the member */
    if (!val) return;
    write_stream(out, ',');
    json_write_string(out, name);
    write_stream(out, ':');
    json_write_boolean(out, 1);
}
Ejemplo n.º 20
0
void OopMap::copy_to(address addr) {
  memcpy(addr,this,sizeof(OopMap));
  memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
  OopMap* new_oop = (OopMap*)addr;
  new_oop->set_omv_data_size(write_stream()->position());
  new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
  new_oop->set_write_stream(NULL);
}
Ejemplo n.º 21
0
Archivo: json.c Proyecto: eswartz/emul
void json_write_char(OutputStream * out, char ch) {
    unsigned n = ch & 0xff;
    if (n < ' ') {
        write_stream(out, '\\');
        write_stream(out, 'u');
        write_stream(out, '0');
        write_stream(out, '0');
        write_stream(out, hex_digit(n >> 4));
        write_stream(out, hex_digit(n));
    }
Ejemplo n.º 22
0
static void reply_read(char * token, OutputStream * out, int err, void * buf, unsigned len, int eof) {
    write_stringz(out, "R");
    write_stringz(out, token);
    json_write_binary(out, buf, len);
    write_stream(out, 0);
    write_fs_errno(out, err);
    json_write_boolean(out, eof);
    write_stream(out, 0);
    write_stream(out, MARKER_EOM);
}
static void disconnect_port(PortConnection * conn) {
    assert (is_dispatch_thread());
    conn->shutdown_in_progress = 1;
    port_lock(conn);
    protocol_send_command(conn->server->channel, "PortForward", "delete",
            delete_config_done, conn);
    json_write_string(&conn->server->channel->out, conn->id);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    write_stream(&conn->server->channel->out, MARKER_EOM);
}
Ejemplo n.º 24
0
static void write_port_server_info(OutputStream * out, PortServer * server) {
    PortAttribute * attr = server->attrs;
    write_stream(out, '{');
    json_write_string(out, "ID");
    write_stream(out, ':');
    json_write_string(out, server->id);
    write_stream(out, ',');
    json_write_string(out, "AutoConnect");
    write_stream(out, ':');
    json_write_boolean(out, server->auto_connect);
    write_stream(out, ',');
    if (server->is_udp) json_write_string(out, "UdpPort");
    else json_write_string(out, "TcpPort");
    write_stream(out, ':');
    json_write_ulong(out, server->local_port);
    while (attr != NULL) {
        if (strcmp(attr->name, "AutoConnect") != 0) {
            write_stream(out, ',');
            json_write_string(out, attr->name);
            write_stream(out, ':');
            write_string(out, attr->value);
        }
        attr = attr->next;
    }
    write_stream(out, '}');
}
Ejemplo n.º 25
0
static void connect_port(PortConnection * conn) {
    assert(is_dispatch_thread());

    sprintf(conn->id, "%s@%" PRIu64, conn->server->id, conn->server->port_index++);
    port_lock(conn);
    conn->pending = protocol_send_command(conn->server->channel, "PortForward",
            "getCapabilities", getcapabilities_cb, conn);
    write_string(&conn->server->channel->out, "null");
    write_stream(&conn->server->channel->out, MARKER_EOA);
    write_stream(&conn->server->channel->out, MARKER_EOM);
}
Ejemplo n.º 26
0
int OopMap::heap_size() const {
  int size = sizeof(OopMap);
  int align = sizeof(void *) - 1;
  if(write_stream() != NULL) {
    size += write_stream()->position();
  } else {
    size += omv_data_size();
  }
  // Align to a reasonable ending point
  size = ((size+align) & ~align);
  return size;
}
Ejemplo n.º 27
0
static void send_event_process_exited(OutputStream * out, ChildProcess * prs) {
    write_stringz(out, "E");
    write_stringz(out, PROCESSES);
    write_stringz(out, "exited");

    json_write_string(out, pid2id(prs->pid, 0));
    write_stream(out, 0);

    json_write_long(out, prs->exit_code);
    write_stream(out, 0);

    write_stream(out, MARKER_EOM);
}
Ejemplo n.º 28
0
static void send_event_terminal_exited(OutputStream * out, Terminal * term) {
    write_stringz(out, "E");
    write_stringz(out, TERMINALS);
    write_stringz(out, "exited");

    json_write_string(out, tid2id(get_process_pid(term->prs)));
    write_stream(out, 0);

    json_write_ulong(out, get_process_exit_code(term->prs));
    write_stream(out, 0);

    write_stream(out, MARKER_EOM);
}
Ejemplo n.º 29
0
static void reply_stat(char * token, OutputStream * out, int err, struct stat * buf) {
    FileAttrs attrs;

    if (err == 0) fill_attrs(&attrs, buf);
    else memset(&attrs, 0, sizeof(attrs));

    write_stringz(out, "R");
    write_stringz(out, token);
    write_fs_errno(out, err);
    write_file_attrs(out, &attrs);
    write_stream(out, 0);
    write_stream(out, MARKER_EOM);
}
Ejemplo n.º 30
0
static void command_get_children_cache_client(void * x) {
    GetChildrenArgs * args = (GetChildrenArgs *)x;
    Channel * c  = cache_channel();
    Context * ctx = NULL;
    int frame = STACK_NO_FRAME;
    StackFrame * frame_info = NULL;
    RegisterDefinition * defs = NULL;
    RegisterDefinition * parent = NULL;
    Trap trap;

    if (set_trap(&trap)) {
        if (id2register(args->id, &ctx, &frame, &parent) == 0) {
            if (frame != STACK_TOP_FRAME && get_frame_info(ctx, frame, &frame_info) < 0) exception(errno);
        }
        else if (id2frame(args->id, &ctx, &frame) == 0) {
            if (get_frame_info(ctx, frame, &frame_info) < 0) exception(errno);
        }
        else {
            ctx = id2ctx(args->id);
            frame = STACK_TOP_FRAME;
        }
        if (ctx != NULL) defs = get_reg_definitions(ctx);
        clear_trap(&trap);
    }

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);

    write_errno(&c->out, trap.error);

    write_stream(&c->out, '[');
    if (defs != NULL) {
        int cnt = 0;
        RegisterDefinition * reg_def;
        for (reg_def = defs; reg_def->name != NULL; reg_def++) {
            if (reg_def->parent != parent) continue;
            if (frame < 0 || frame_info->is_top_frame ||
                    reg_def->size == 0 || read_reg_value(frame_info, reg_def, NULL) == 0) {
                if (cnt > 0) write_stream(&c->out, ',');
                json_write_string(&c->out, register2id(ctx, frame, reg_def));
                cnt++;
            }
        }
    }
    write_stream(&c->out, ']');
    write_stream(&c->out, 0);

    write_stream(&c->out, MARKER_EOM);
}