//-------------------------------------------------------------------------- gdecode_t rpc_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) { if ( has_pending_event ) { verbev(("get_debug_event => has pending event, returning it\n")); *event = pending_event; has_pending_event = false; poll_debug_events = false; return GDE_ONE_EVENT; } gdecode_t result = GDE_NO_EVENT; if ( poll_debug_events ) { // do we have something waiting? // we must use TIMEOUT here to avoid competition between // IDA analyzer and the debugger program. // The analysis will be slow during the application run. // As soon as the program is suspended, the analysis will be fast // because get_debug_event() will not be called. if ( irs_ready(irs, TIMEOUT) != 0 ) { verbev(("get_debug_event => remote has an event for us\n")); // get the packet - it should be RPC_EVENT (nothing else can be) qstring empty; int flags = timeout_ms > 0 ? SET_PRF_TIMEOUT(timeout_ms) | PRF_POLL : PRF_DONT_POLL; rpc_packet_t *rp = process_request(empty, flags); verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event)); if ( rp != NULL || !has_pending_event ) { warning("rpc: event protocol error (rp=%p has_event=%d)", rp, has_pending_event); return GDE_ERROR; } } } else { verbev(("get_debug_event => first time, send GET_DEBUG_EVENT\n")); qstring cmd = prepare_rpc_packet(RPC_GET_DEBUG_EVENT); append_long(cmd, timeout_ms); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return GDE_ERROR; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; result = gdecode_t(extract_long(&answer, end)); if ( result >= GDE_ONE_EVENT ) extract_debug_event(&answer, end, event); else poll_debug_events = true; verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events)); qfree(rp); } return result; }
//-------------------------------------------------------------------------- gdecode_t idaapi rpc_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) { if ( has_pending_event ) { verbev(("get_debug_event => has pending event, returning it\n")); *event = pending_event; has_pending_event = false; poll_debug_events = false; return GDE_ONE_EVENT; } gdecode_t result = GDE_NO_EVENT; if ( poll_debug_events ) { // do we have something waiting? if ( irs_ready(irs, timeout_ms) != 0 ) { verbev(("get_debug_event => remote has an event for us\n")); // get the packet - it should be RPC_EVENT (nothing else can be) bytevec_t empty; rpc_packet_t *rp = process_request(empty); verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event)); if ( rp != NULL || !has_pending_event ) { warning("rpc: event protocol error (rp=%p has_event=%d)", rp, has_pending_event); return GDE_ERROR; } } } else { verbev(("get_debug_event => first time, send GET_DEBUG_EVENT\n")); bytevec_t req = prepare_rpc_packet(RPC_GET_DEBUG_EVENT); append_dd(req, timeout_ms); rpc_packet_t *rp = process_request(req); if ( rp == NULL ) return GDE_ERROR; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; result = gdecode_t(extract_long(&answer, end)); if ( result >= GDE_ONE_EVENT ) extract_debug_event(&answer, end, event); else poll_debug_events = true; verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events)); qfree(rp); } return result; }
//-------------------------------------------------------------------------- ea_t rpc_debmod_t::dbg_appcall( ea_t func_ea, thid_t tid, const struct func_type_info_t *fti, int nargs, const struct regobjs_t *regargs, struct relobj_t *stkargs, struct regobjs_t *retregs, qstring *errbuf, debug_event_t *event, int flags) { qstring cmd = prepare_rpc_packet(RPC_APPCALL); append_ea(cmd, func_ea); append_long(cmd, tid); append_long(cmd, nargs); append_long(cmd, flags); regobjs_t *rr = (flags & APPCALL_MANUAL) == 0 ? retregs : NULL; append_appcall(cmd, *fti, *regargs, *stkargs, rr); rpc_packet_t *rp = process_request(cmd); if ( rp == NULL ) return BADADDR; const uchar *answer = (uchar *)(rp+1); const uchar *end = answer + rp->length; ea_t sp = extract_ea(&answer, end); if ( sp == BADADDR ) { if ( (flags & APPCALL_DEBEV) != 0 ) extract_debug_event(&answer, end, event); if ( errbuf != NULL ) *errbuf = extract_str(&answer, end); } else if ( (flags & APPCALL_MANUAL) == 0 ) { if ( retregs != NULL ) extract_regobjs(&answer, end, retregs, true); } qfree(rp); return sp; }
//-------------------------------------------------------------------------- // requests received from the server. // here the client handles certain server -> client requests qstring rpc_client_t::perform_request(const rpc_packet_t *rp) { const uchar *ptr = (const uchar *)(rp + 1); const uchar *end = ptr + rp->length; qstring cmd = prepare_rpc_packet(RPC_OK); switch ( rp->code ) { case RPC_SET_DEBUG_NAMES: { int qty = extract_long(&ptr, end); ea_t *addrs = new ea_t[qty]; if ( addrs == NULL ) goto nomem; char **names = new char *[qty]; if ( names == NULL ) { delete [] addrs; goto nomem; } char name[MAXSTR]; ea_t old = 0; name[0] = '\0'; for ( int i=0; i < qty; i++ ) { adiff_t o2 = extract_ea(&ptr, end); if ( extract_long(&ptr, end) ) o2 = -o2; old += o2; addrs[i] = old; int oldlen = extract_long(&ptr, end); qstrncpy(&name[oldlen], extract_str(&ptr, end), sizeof(name)-oldlen); names[i] = qstrdup(name); } int result = set_debug_names(addrs, names, qty); verb(("set_debug_name(qty=%d) => %d\n", qty, result)); append_long(cmd, result); for ( int i=0; i < qty; i++ ) qfree(names[i]); delete [] addrs; delete [] names; } break; case RPC_HANDLE_DEBUG_EVENT: { debug_event_t ev; extract_debug_event(&ptr, end, &ev); int rqflags = extract_long(&ptr, end); int code = send_debug_event_to_ida(&ev, rqflags); append_long(cmd, code); } break; case RPC_SYNC_STUB: { char *fname = extract_str(&ptr, end); uint32 crc = extract_long(&ptr, end); size_t size = 0; uchar *contents = sync_stub(fname, crc, &size); append_long(cmd, (uint32)size); if ( contents != NULL ) { append_memory(cmd, contents, size); qfree(contents); } } break; case RPC_ERROR: case RPC_MSG: case RPC_WARNING: { char *str = extract_str(&ptr, end); if ( rp->code == RPC_MSG) msg("%s", str); else if ( rp->code == RPC_ERROR ) error("%s", str); else warning("%s", str); } break; case RPC_EVENT: { extract_debug_event(&ptr, end, &pending_event); has_pending_event = true; cmd = prepare_rpc_packet(RPC_EVOK); verbev(("got event, storing it and sending RPC_EVOK\n")); } break; case RPC_IOCTL: { int code = handle_ioctl_packet(cmd, ptr, end); if ( code != RPC_OK ) return prepare_rpc_packet((uchar)code); } break; default: return prepare_rpc_packet(RPC_UNK); nomem: return prepare_rpc_packet(RPC_MEM); } return cmd; }