static void safe_event_disassemble(void * x) { DisassembleCmdArgs * args = (DisassembleCmdArgs *)x; if (!is_channel_closed(args->c)) { cache_enter(disassemble_cache_client, args->c, args, sizeof(DisassembleCmdArgs)); } channel_unlock(args->c); loc_free(args); }
void cache_enter(CacheClient * client, Channel * channel, void * args, size_t args_size) { assert(is_dispatch_thread()); assert(client != NULL); assert(channel != NULL); assert(!is_channel_closed(channel)); assert(current_client.client == NULL); current_client.client = client; current_client.channel = channel; current_client.args = args; current_client.args_size = args_size; current_client.args_copy = 0; run_cache_client(); }
static void port_connection_open(PortServer * server, int fd) { PortConnection * conn; if (server->channel == NULL || is_channel_closed(server->channel)) { closesocket(fd); return; } conn = loc_alloc_zero(sizeof(PortConnection)); if (conn == NULL) { closesocket(fd); } else { int idx = 0; conn->recv_req.client_data = conn; conn->recv_req.done = done_recv_request; conn->recv_req.type = server->is_udp ? AsyncReqRecvFrom : AsyncReqRecv; conn->recv_req.u.sio.sock = fd; conn->recv_req.u.sio.flags = 0; conn->recv_req.u.sio.bufp = conn->inbuf; conn->recv_req.u.sio.bufsz = IN_BUF_SIZE; conn->recv_req.u.sio.addr = &server->client_addr; conn->recv_req.u.sio.addrlen = sizeof(conn->server->client_addr); conn->send_req.client_data = conn; conn->send_req.done = done_send_request; conn->send_req.type = server->is_udp ? AsyncReqSendTo : AsyncReqSend; conn->send_req.u.sio.sock = fd; conn->send_req.u.sio.flags = 0; conn->send_in_progress = -1; /* no send request in progress */ for (idx = 0; idx < MAX_STREAM_READ; idx++) { conn->read_info[idx].idx = idx; conn->read_info[idx].conn = conn; } conn->fd = fd; conn->server = server; conn->next = server->list; server->list = conn; connect_port(conn); } }
static void connect_done(void * args, int error, Channel * c2) { ConnectInfo * info = (ConnectInfo *)args; Channel * c1 = info->c1; if (!is_channel_closed(c1)) { assert(c1->state == ChannelStateRedirectReceived); if (error) { fprintf(stderr, "cannot connect to peer: %s\n", dest_url); channel_close(c1); } else { proxy_create(c1, c2); } } else if (!error) { channel_close(c2); } channel_unlock(c1); peer_server_free(info->ps); loc_free(info); }
static void command_get_capabilities_cache_client(void * x) { int error = 0; Context * ctx = NULL; ContextExtensionDS * ext = NULL; GetCapabilitiesCmdArgs * args = (GetCapabilitiesCmdArgs *)x; Channel * c = cache_channel(); ctx = id2ctx(args->id); if (ctx == NULL) error = ERR_INV_CONTEXT; else if (ctx->exited) error = ERR_ALREADY_EXITED; else ext = EXT(context_get_group(ctx, CONTEXT_GROUP_CPU)); cache_exit(); if (!is_channel_closed(c)) { OutputStream * out = &c->out; write_stringz(out, "R"); write_stringz(out, args->token); write_errno(out, error); write_stream(out, '['); if (ext != NULL) { unsigned i; for (i = 0; i < ext->disassemblers_cnt; i++) { if (i > 0) write_stream(out, ','); write_stream(out, '{'); json_write_string(out, "ISA"); write_stream(out, ':'); json_write_string(out, ext->disassemblers[i].isa); write_stream(out, '}'); } } write_stream(out, ']'); write_stream(out, 0); write_stream(out, MARKER_EOM); } }
static void safe_memory_fill(void * parm) { MemoryCommandArgs * args = (MemoryCommandArgs *)parm; Channel * c = args->c; Context * ctx = args->ctx; if (!is_channel_closed(c)) { Trap trap; if (set_trap(&trap)) { InputStream * inp = &c->inp; OutputStream * out = &c->out; char * token = args->token; ContextAddress addr0 = args->addr; ContextAddress addr = args->addr; unsigned long size = args->size; MemoryErrorInfo err_info; MemoryFillBuffer buf; char * tmp = NULL; int err = 0; memset(&err_info, 0, sizeof(err_info)); if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED; memset(&buf, 0, sizeof(buf)); buf.buf = (char *)tmp_alloc(buf.max = BUF_SIZE); if (err) json_skip_object(inp); else json_read_array(inp, read_memory_fill_array_cb, &buf); json_test_char(inp, MARKER_EOA); json_test_char(inp, MARKER_EOM); while (err == 0 && buf.pos < size && buf.pos <= buf.max / 2) { if (buf.pos == 0) { buf.buf[buf.pos++] = 0; } else { memcpy(buf.buf + buf.pos, buf.buf, buf.pos); buf.pos *= 2; } } while (err == 0 && addr < addr0 + size) { /* Note: context_write_mem() modifies buffer contents */ unsigned wr = (unsigned)(addr0 + size - addr); if (tmp == NULL) tmp = (char *)tmp_alloc(buf.pos); if (wr > buf.pos) wr = buf.pos; /* TODO: word size, mode */ memcpy(tmp, buf.buf, wr); if (context_write_mem(ctx, addr, tmp, wr) < 0) { err = errno; #if ENABLE_ExtendedMemoryErrorReports context_get_mem_error_info(&err_info); #endif } else { addr += wr; } } send_event_memory_changed(ctx, addr0, size); write_stringz(out, "R"); write_stringz(out, token); write_errno(out, err); if (err == 0) { write_stringz(out, "null"); } else { write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_WRITE, &err_info); } write_stream(out, MARKER_EOM); clear_trap(&trap); } else { trace(LOG_ALWAYS, "Exception in Memory.fill: %s", errno_to_str(trap.error)); channel_close(c); } } channel_unlock(c); context_unlock(ctx); loc_free(args); }
static void safe_memory_get(void * parm) { MemoryCommandArgs * args = (MemoryCommandArgs *)parm; Channel * c = args->c; Context * ctx = args->ctx; if (!is_channel_closed(c)) { Trap trap; if (set_trap(&trap)) { OutputStream * out = &args->c->out; char * token = args->token; ContextAddress addr0 = args->addr; ContextAddress addr = args->addr; unsigned long size = args->size; unsigned long pos = 0; char buf[BUF_SIZE]; int err = 0; MemoryErrorInfo err_info; JsonWriteBinaryState state; memset(&err_info, 0, sizeof(err_info)); if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED; write_stringz(out, "R"); write_stringz(out, token); json_write_binary_start(&state, out, size); while (pos < size) { int rd = size - pos; if (rd > BUF_SIZE) rd = BUF_SIZE; /* TODO: word size, mode */ memset(buf, 0, rd); if (err == 0) { if (context_read_mem(ctx, addr, buf, rd) < 0) { err = errno; #if ENABLE_ExtendedMemoryErrorReports context_get_mem_error_info(&err_info); #endif } else { addr += rd; } } json_write_binary_data(&state, buf, rd); pos += rd; } json_write_binary_end(&state); write_stream(out, 0); write_errno(out, err); if (err == 0) { write_stringz(out, "null"); } else { write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_READ, &err_info); } write_stream(out, MARKER_EOM); clear_trap(&trap); } else { trace(LOG_ALWAYS, "Exception in Memory.get: %s", errno_to_str(trap.error)); channel_close(c); } } channel_unlock(c); context_unlock(ctx); loc_free(args); }
static void safe_memory_set(void * parm) { MemoryCommandArgs * args = (MemoryCommandArgs *)parm; Channel * c = args->c; Context * ctx = args->ctx; if (!is_channel_closed(c)) { Trap trap; if (set_trap(&trap)) { InputStream * inp = &c->inp; OutputStream * out = &c->out; char * token = args->token; ContextAddress addr0 = args->addr; ContextAddress addr = args->addr; unsigned long size = 0; char buf[BUF_SIZE]; int err = 0; MemoryErrorInfo err_info; JsonReadBinaryState state; memset(&err_info, 0, sizeof(err_info)); if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED; json_read_binary_start(&state, inp); for (;;) { int rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (err == 0) { /* TODO: word size, mode */ if (context_write_mem(ctx, addr, buf, rd) < 0) { err = errno; #if ENABLE_ExtendedMemoryErrorReports context_get_mem_error_info(&err_info); #endif } else { addr += rd; } } size += rd; } json_read_binary_end(&state); json_test_char(inp, MARKER_EOA); json_test_char(inp, MARKER_EOM); send_event_memory_changed(ctx, addr0, size); write_stringz(out, "R"); write_stringz(out, token); write_errno(out, err); if (err == 0) { write_stringz(out, "null"); } else { write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_WRITE, &err_info); } write_stream(out, MARKER_EOM); clear_trap(&trap); } else { trace(LOG_ALWAYS, "Exception in Memory.set: %s", errno_to_str(trap.error)); channel_close(c); } } channel_unlock(c); context_unlock(ctx); loc_free(args); }
static void disassemble_cache_client(void * x) { DisassembleCmdArgs * args = (DisassembleCmdArgs *)x; int error = 0; Context * ctx = NULL; uint8_t * mem_buf = NULL; ContextAddress buf_addr = 0; ContextAddress buf_size = 0; size_t mem_size = 0; ByteArrayOutputStream buf; OutputStream * buf_out = create_byte_array_output_stream(&buf); Channel * c = cache_channel(); char * data = NULL; size_t size = 0; ContextISA isa; memset(&isa, 0, sizeof(isa)); ctx = id2ctx(args->id); if (ctx == NULL) error = ERR_INV_CONTEXT; else if (ctx->exited) error = ERR_ALREADY_EXITED; if (!error) check_all_stopped(ctx); if (!error) { ContextAddress sym_addr = 0; ContextAddress sym_size = 0; int sym_addr_ok = 0; int sym_size_ok = 0; #if SERVICE_Symbols { Symbol * sym = NULL; if (find_symbol_by_addr(ctx, STACK_NO_FRAME, args->addr, &sym) == 0) { if (get_symbol_address(sym, &sym_addr) == 0) sym_addr_ok = 1; if (get_symbol_size(sym, &sym_size) == 0) sym_size_ok = 1; } if (sym_addr_ok && sym_addr <= args->addr) { if (args->addr - sym_addr >= 0x1000) { sym_addr_ok = 0; sym_size_ok = 0; } else if (sym_size_ok && sym_addr + sym_size > args->addr + args->size) { sym_size = args->addr + args->size - sym_addr; } } } #endif #if SERVICE_LineNumbers if (!sym_addr_ok || !sym_size_ok) { CodeArea * area = NULL; address_to_line(ctx, args->addr, args->addr + 1, address_to_line_cb, &area); if (area != NULL) { sym_addr = area->start_address; sym_size = area->end_address - area->start_address; sym_addr_ok = 1; sym_size_ok = 1; } } #endif if (sym_addr_ok && sym_size_ok && sym_addr <= args->addr && sym_addr + sym_size > args->addr) { buf_addr = sym_addr; buf_size = sym_size; mem_size = (size_t)sym_size; } else if (sym_addr_ok && sym_addr < args->addr) { if (get_isa(ctx, sym_addr, &isa) < 0) { error = errno; } else { buf_addr = sym_addr; buf_size = args->addr + args->size - sym_addr; if (isa.max_instruction_size > 0) { mem_size = (size_t)(buf_size + isa.max_instruction_size); } else { mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE); } } } else { /* Use default address alignment */ if (get_isa(ctx, args->addr, &isa) < 0) { error = errno; } else { if (isa.alignment > 0) { buf_addr = args->addr & ~(ContextAddress)(isa.alignment - 1); } else { buf_addr = args->addr & ~(ContextAddress)(DEFAULT_ALIGMENT - 1); } buf_size = args->addr + args->size - buf_addr; if (isa.max_instruction_size > 0) { mem_size = (size_t)(buf_size + isa.max_instruction_size); } else { mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE); } } } if (!error) { mem_buf = (uint8_t *)tmp_alloc(mem_size); if (context_read_mem(ctx, buf_addr, mem_buf, mem_size) < 0) error = errno; if (error) { #if ENABLE_ExtendedMemoryErrorReports MemoryErrorInfo info; if (context_get_mem_error_info(&info) == 0 && info.size_valid > 0) { mem_size = info.size_valid; error = 0; } #endif } } } if (!error && disassemble_block( ctx, buf_out, mem_buf, buf_addr, buf_size, mem_size, &isa, args) < 0) error = errno; if (get_error_code(error) == ERR_CACHE_MISS) { loc_free(buf.mem); buf.mem = NULL; buf.max = 0; buf.pos = 0; } cache_exit(); get_byte_array_output_stream_data(&buf, &data, &size); if (!is_channel_closed(c)) { OutputStream * out = &c->out; write_stringz(out, "R"); write_stringz(out, args->token); write_errno(out, error); if (size > 0) { write_block_stream(out, data, size); } else { write_string(out, "null"); } write_stream(out, 0); write_stream(out, MARKER_EOM); } loc_free(data); }