#include #include #include #include "rpc_debmod.h" #include "dbg_rpc_hlp.h" //------------------------------------------------------------------------- inline drc_t unpack_drc(memory_deserializer_t &mmdsr) { return drc_t(mmdsr.unpack_dd()); } //-------------------------------------------------------------------------- rpc_debmod_t::rpc_debmod_t(const char *default_platform) : dbg_rpc_client_t(NULL) { nregs = debugger.nregs; for ( int i=0; i < nregs; i++ ) { const register_info_t &ri = debugger.regs(i); if ( (ri.flags & REGISTER_SP) != 0 ) sp_idx = i; if ( (ri.flags & REGISTER_IP) != 0 ) pc_idx = i; } bpt_code.append(debugger.bpt_bytes, debugger.bpt_size); rpc = this; set_platform(default_platform); } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::handle_ioctl( //-V524 equivalent to 'send_ioctl' int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { return rpc_engine_t::send_ioctl(fn, buf, size, poutbuf, poutsize); } //-------------------------------------------------------------------------- inline int get_expected_addrsize(void) { if ( is_miniidb() ) #ifdef __EA64__ return 8; #else return 4; #endif return inf_is_64bit() ? 8 : 4; } //-------------------------------------------------------------------------- bool idaapi rpc_debmod_t::open_remote( const char *hostname, int port_number, const char *password, qstring *errbuf) { if ( hostname[0] == '\0' ) { if ( errbuf != NULL ) *errbuf = "Please specify the hostname in Debugger, Process options"; return false; } rpc_packet_t *rp = NULL; network_error = false; client_irs = irs_new(); if ( !irs_init_client(client_irs, hostname, port_number) ) { FAILURE: if ( rp != NULL ) qfree(rp); if ( errbuf != NULL ) *errbuf = irs_strerror(client_irs); irs_term(&client_irs); return false; } rp = recv_packet(); if ( rp == NULL || rp->code != RPC_OPEN ) // is this an ida debugger server? { dbg_rpc_client_t::dwarning("ICON ERROR\nAUTOHIDE NONE\n" "Bogus or irresponsive remote server"); goto FAILURE; } memory_deserializer_t mmdsr(rp+1, rp->length); int version = mmdsr.unpack_dd(); int remote_debugger_id = mmdsr.unpack_dd(); int easize = mmdsr.unpack_dd(); qstring errstr; if ( version != IDD_INTERFACE_VERSION ) errstr.sprnt("protocol version is %d, expected %d", version, IDD_INTERFACE_VERSION); else if ( remote_debugger_id != debugger.id ) errstr.sprnt("debugger id is %d, expected %d (%s)", remote_debugger_id, debugger.id, debugger.name); else if ( easize < get_expected_addrsize() ) errstr.sprnt("address size is %d bytes, expected at least %d", easize, get_expected_addrsize()); if ( !errstr.empty() ) { bytevec_t req = prepare_rpc_packet(RPC_OK); req.pack_dd(false); send_data(req); warning("ICON ERROR\nAUTOHIDE NONE\n" "Incompatible debugging server:\n" "%s", errstr.c_str()); goto FAILURE; } qfree(rp); bytevec_t req = prepare_rpc_packet(RPC_OK); req.pack_dd(true); req.pack_str(password); send_data(req); rp = recv_packet(); if ( rp == NULL || rp->code != RPC_OK ) goto FAILURE; memory_deserializer_t mmdsr2(rp+1, rp->length); bool password_ok = mmdsr2.unpack_dd() != 0; if ( !password_ok ) // is this an ida debugger server? { warning("ICON ERROR\nAUTOHIDE NONE\n" "Bad password"); goto FAILURE; } qfree(rp); return true; } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_add_bpt(bytevec_t *, bpttype_t, ea_t, int) { INTERR(30114); } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_del_bpt(bpttype_t, ea_t, const uchar *, int) { INTERR(30115); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_update_lowcnds( int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf) { ea_t ea = 0; bytevec_t req = prepare_rpc_packet(RPC_UPDATE_LOWCNDS); req.pack_dd(nlowcnds); const lowcnd_t *lc = lowcnds; for ( int i=0; i < nlowcnds; i++, lc++ ) { req.pack_ea64(lc->ea-ea); ea = lc->ea; req.pack_str(lc->cndbody); if ( !lc->cndbody.empty() ) { req.pack_dd(lc->type); if ( lc->type != BPT_SOFT ) req.pack_dd(lc->size); req.pack_db(lc->orgbytes.size()); req.append(lc->orgbytes.begin(), lc->orgbytes.size()); req.pack_ea64(lc->cmd.ea); if ( lc->cmd.ea != BADADDR ) req.append(&lc->cmd, sizeof(lc->cmd)); } } rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); int ret_nupdated = mmdsr.unpack_dd(); if ( nupdated != NULL ) *nupdated = ret_nupdated; if ( errbuf != NULL && drc != DRC_NONE ) *errbuf = mmdsr.unpack_str(); qfree(rp); return drc; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_EVAL_LOWCND); req.pack_dd(tid); req.pack_ea64(ea); return send_request_get_drc_result(req, errbuf); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_update_bpts( int *nbpts, update_bpt_info_t *ubpts, int nadd, int ndel, qstring *errbuf) { int skipped = 0; update_bpt_info_t *b; update_bpt_info_t *bend = ubpts + nadd; for ( b=ubpts; b != bend; b++ ) if ( b->code != BPT_OK ) skipped++; if ( skipped == nadd && ndel == 0 ) { if ( nbpts != NULL ) *nbpts = 0; // no bpts to update return DRC_OK; } bytevec_t req = prepare_rpc_packet(RPC_UPDATE_BPTS); req.pack_dd(nadd-skipped); req.pack_dd(ndel); ea_t ea = 0; for ( b=ubpts; b != bend; b++ ) { if ( b->code == BPT_OK ) { req.pack_ea64(b->ea-ea); ea = b->ea; req.pack_dd(b->size); req.pack_dd(b->type); req.pack_dd(b->pid); req.pack_dd(b->tid); } } ea = 0; bend += ndel; for ( ; b != bend; b++ ) { req.pack_ea64(b->ea-ea); ea = b->ea; req.pack_db(b->orgbytes.size()); req.append(b->orgbytes.begin(), b->orgbytes.size()); req.pack_dd(b->type); req.pack_dd(b->pid); req.pack_dd(b->tid); } rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); int ret_nbpts = mmdsr.unpack_dd(); if ( nbpts != NULL ) *nbpts = ret_nbpts; bend = ubpts + nadd; for ( b=ubpts; b != bend; b++ ) { if ( b->code == BPT_OK ) { b->code = mmdsr.unpack_db(); if ( b->code == BPT_OK && b->type == BPT_SOFT ) { uchar len = mmdsr.unpack_db(); b->orgbytes.resize(len); mmdsr.unpack_obj(b->orgbytes.begin(), len); } } } bend += ndel; for ( ; b != bend; b++ ) b->code = mmdsr.unpack_db(); if ( errbuf != NULL && drc != DRC_NONE ) *errbuf = mmdsr.unpack_str(); return drc; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_thread_get_sreg_base(ea_t *ea, thid_t tid, int sreg_value, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_GET_SREG_BASE); req.pack_dd(tid); req.pack_dd(sreg_value); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); if ( drc == DRC_OK ) *ea = mmdsr.unpack_ea64(); else if ( errbuf != NULL ) *errbuf = mmdsr.unpack_str(); qfree(rp); return drc; } //-------------------------------------------------------------------------- void idaapi rpc_debmod_t::dbg_set_exception_info(const exception_info_t *table, int qty) { bytevec_t req = prepare_rpc_packet(RPC_SET_EXCEPTION_INFO); req.pack_dd(qty); append_exception_info(req, table, qty); qfree(send_request_and_receive_reply(req)); } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_open_file(const char *file, uint64 *fsize, bool readonly) { bytevec_t req = prepare_rpc_packet(RPC_OPEN_FILE); req.pack_str(file); req.pack_dd(readonly); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return -1; memory_deserializer_t mmdsr(rp+1, rp->length); int fn = mmdsr.unpack_dd(); if ( fn != -1 ) { if ( fsize != NULL && readonly ) *fsize = mmdsr.unpack_dq(); } else { qerrcode(mmdsr.unpack_dd()); } qfree(rp); return fn; } //-------------------------------------------------------------------------- void idaapi rpc_debmod_t::dbg_close_file(int fn) { bytevec_t req = prepare_rpc_packet(RPC_CLOSE_FILE); req.pack_dd(fn); qfree(send_request_and_receive_reply(req)); } //-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_read_file(int fn, qoff64_t off, void *buf, size_t size) { bytevec_t req = prepare_rpc_packet(RPC_READ_FILE); req.pack_dd(fn); req.pack_dq(off); req.pack_dd((uint32)size); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return -1; memory_deserializer_t mmdsr(rp+1, rp->length); int32 rsize = mmdsr.unpack_dd(); if ( size != rsize ) qerrcode(mmdsr.unpack_dd()); if ( rsize > 0 ) { QASSERT(1204, rsize <= size); mmdsr.unpack_obj(buf, rsize); } qfree(rp); return rsize; } //-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_write_file(int fn, qoff64_t off, const void *buf, size_t size) { bytevec_t req = prepare_rpc_packet(RPC_WRITE_FILE); req.pack_dd(fn); req.pack_dq(off); req.pack_buf(buf, size); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return -1; memory_deserializer_t mmdsr(rp+1, rp->length); int32 rsize = mmdsr.unpack_dd(); if ( size != rsize ) qerrcode(mmdsr.unpack_dd()); qfree(rp); return rsize; } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) { bytevec_t req = prepare_rpc_packet(RPC_ISOK_BPT); req.pack_dd(type); req.pack_ea64(ea); req.pack_dd(len+1); return send_request_get_long_result(req); } //-------------------------------------------------------------------------- void idaapi rpc_debmod_t::dbg_set_debugging(bool _debug_debugger) { debug_debugger = _debug_debugger; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_init(uint32_t *_flags2, qstring *errbuf) { has_pending_event = false; poll_debug_events = false; bytevec_t req = prepare_rpc_packet(RPC_INIT); req.pack_dd(debugger.flags); req.pack_dd(debug_debugger); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == nullptr ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); uint32_t flags2 = mmdsr.unpack_dd(); if ( _flags2 != nullptr ) *_flags2 = flags2; if ( drc != DRC_OK && errbuf != nullptr ) *errbuf = mmdsr.unpack_str(); qfree(rp); return drc; } //-------------------------------------------------------------------------- void idaapi rpc_debmod_t::dbg_term(void) { bytevec_t req = prepare_rpc_packet(RPC_TERM); qfree(send_request_and_receive_reply(req)); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_get_processes(procinfo_vec_t *procs, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_GET_PROCESSES); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); procs->qclear(); drc_t drc = unpack_drc(mmdsr); if ( drc == DRC_OK ) extract_process_info_vec(procs, mmdsr); else if ( errbuf != NULL ) *errbuf = mmdsr.unpack_str(); qfree(rp); return drc; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_detach_process(void) { return get_drc(RPC_DETACH_PROCESS); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_start_process( const char *path, const char *args, const char *startdir, int flags, const char *input_path, uint32 input_file_crc32, qstring *errbuf) { if ( inf_test_mode() ) flags |= DBG_HIDE_WINDOW; bytevec_t req = prepare_rpc_packet(RPC_START_PROCESS); req.pack_str(path); req.pack_str(args); req.pack_str(startdir); req.pack_dd(flags); req.pack_str(input_path); req.pack_dd(input_file_crc32); return process_start_or_attach(req, errbuf); } //-------------------------------------------------------------------------- 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(client_irs, timeout_ms) > 0 ) { verbev(("get_debug_event => remote has a packet for us\n")); // get the packet - it can RPC_EVENT or RPC_MSG/RPC_WARNING/RPC_ERROR bytevec_t empty; rpc_packet_t *rp = send_request_and_receive_reply(empty, PREQ_GET_EVENT); verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event)); if ( rp != NULL ) { 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); req.pack_dd(timeout_ms); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return GDE_ERROR; memory_deserializer_t mmdsr(rp+1, rp->length); result = gdecode_t(mmdsr.unpack_dd()); if ( result >= GDE_ONE_EVENT ) extract_debug_event(event, mmdsr); else poll_debug_events = true; verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events)); qfree(rp); } return result; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_attach_process(pid_t _pid, int event_id, int flags, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_ATTACH_PROCESS); req.pack_dd(_pid); req.pack_dd(event_id); req.pack_dd(flags); return process_start_or_attach(req, errbuf); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_prepare_to_pause_process(qstring *errbuf) { return get_drc(RPC_PREPARE_TO_PAUSE_PROCESS, errbuf); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_exit_process(qstring *errbuf) { return get_drc(RPC_EXIT_PROCESS, errbuf); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_continue_after_event(const debug_event_t *event) { bytevec_t req = prepare_rpc_packet(RPC_CONTINUE_AFTER_EVENT); append_debug_event(req, event); return send_request_get_drc_result(req, NULL); } //-------------------------------------------------------------------------- void idaapi rpc_debmod_t::dbg_stopped_at_debug_event( import_infos_t *, bool dlls_added, thread_name_vec_t *thr_names) { bytevec_t req = prepare_rpc_packet(RPC_STOPPED_AT_DEBUG_EVENT); req.pack_db(dlls_added); bool ask_thr_names = thr_names != NULL; req.pack_db(ask_thr_names); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return; if ( ask_thr_names ) { memory_deserializer_t mmdsr(rp+1, rp->length); uint32 n = mmdsr.unpack_dd(); thr_names->resize(n); for ( uint32 i=0; i < n; ++i ) { thread_name_t &tn = (*thr_names)[i]; tn.tid = mmdsr.unpack_dd(); tn.name = mmdsr.unpack_str(); } } qfree(rp); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_thread_suspend(thid_t tid) { return get_drc_int(RPC_TH_SUSPEND, tid); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_thread_continue(thid_t tid) { return get_drc_int(RPC_TH_CONTINUE, tid); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) { bytevec_t req = prepare_rpc_packet(RPC_SET_RESUME_MODE); req.pack_dd(tid); req.pack_dd(resmod); return send_request_get_drc_result(req, NULL); } //-------------------------------------------------------------------------- // prepare bitmap of registers belonging to the specified classes // return size of the bitmap in bits (always the total number of registers) static int calc_regmap(bytevec_t *regmap, int clsmask) { int nregs = debugger.nregs; regmap->resize((nregs+7)/8, 0); for ( int i=0; i < nregs; i++ ) if ( (debugger.regs(i).register_class & clsmask) != 0 ) regmap->set_bit(i); return nregs; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_read_registers( thid_t tid, int clsmask, regval_t *values, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_READ_REGS); req.pack_dd(tid); req.pack_dd(clsmask); // append additional information about the class structure bytevec_t regmap; int n_regs = calc_regmap(®map, clsmask); req.pack_dd(n_regs); req.append(regmap.begin(), regmap.size()); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); if ( drc == DRC_OK ) unpack_regvals(values, n_regs, regmap.begin(), mmdsr); else if ( errbuf != NULL ) *errbuf = mmdsr.unpack_str(); qfree(rp); return drc; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_write_register( thid_t tid, int reg_idx, const regval_t *value, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_WRITE_REG); req.pack_dd(tid); req.pack_dd(reg_idx); append_regvals(req, value, 1, NULL); return send_request_get_drc_result(req, errbuf); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_get_memory_info(meminfo_vec_t &areas, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_GET_MEMORY_INFO); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = drc_t(mmdsr.unpack_dd() + DRC_IDBSEG); if ( drc > DRC_NONE ) { int n = mmdsr.unpack_dd(); areas.resize(n); for ( int i=0; i < n; i++ ) extract_memory_info(&areas[i], mmdsr); } else if ( errbuf != NULL ) { *errbuf = mmdsr.unpack_str(); } qfree(rp); return drc; } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_get_scattered_image(scattered_image_t &si, ea_t base) { bytevec_t req = prepare_rpc_packet(RPC_GET_SCATTERED_IMAGE); req.pack_ea64(base); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return false; memory_deserializer_t mmdsr(rp+1, rp->length); int result = mmdsr.unpack_dd() - 2; if ( result > 0 ) { int n = mmdsr.unpack_dd(); si.resize(n); for ( int i=0; i < n; i++ ) extract_scattered_segm(&si[i], mmdsr); } qfree(rp); return result; } //-------------------------------------------------------------------------- bool idaapi rpc_debmod_t::dbg_get_image_uuid(bytevec_t *uuid, ea_t base) { bytevec_t req = prepare_rpc_packet(RPC_GET_IMAGE_UUID); req.pack_ea64(base); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return false; memory_deserializer_t mmdsr(rp+1, rp->length); bool result = mmdsr.unpack_dd() != 0; if ( result ) { int n = mmdsr.unpack_dd(); uuid->append(mmdsr.ptr, n); } qfree(rp); return result; } //-------------------------------------------------------------------------- ea_t idaapi rpc_debmod_t::dbg_get_segm_start(ea_t base, const qstring &segname) { bytevec_t req = prepare_rpc_packet(RPC_GET_SEGM_START); req.pack_ea64(base); req.pack_str(segname.c_str()); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return false; memory_deserializer_t mmdsr(rp+1, rp->length); ea_t result = mmdsr.unpack_ea64(); qfree(rp); return result; } //-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_READ_MEMORY); req.pack_ea64(ea); req.pack_dd((uint32)size); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return -1; memory_deserializer_t mmdsr(rp+1, rp->length); int result = mmdsr.unpack_dd(); if ( result > 0 ) { QASSERT(1205, result <= size); mmdsr.unpack_obj(buffer, result); } else if ( errbuf != NULL ) { *errbuf = mmdsr.unpack_str(); } qfree(rp); return result; } //-------------------------------------------------------------------------- ssize_t idaapi rpc_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_WRITE_MEMORY); req.pack_ea64(ea); req.pack_buf(buffer, size); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return -1; memory_deserializer_t mmdsr(rp+1, rp->length); int result = mmdsr.unpack_dd(); if ( errbuf != NULL && result <= 0 ) *errbuf = mmdsr.unpack_str(); qfree(rp); return result; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_update_call_stack(thid_t tid, call_stack_t *trace) { bytevec_t req = prepare_rpc_packet(RPC_UPDATE_CALL_STACK); req.pack_dd(tid); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); if ( drc == DRC_OK ) extract_call_stack(trace, mmdsr); qfree(rp); return drc; } //-------------------------------------------------------------------------- ea_t idaapi rpc_debmod_t::dbg_appcall( ea_t func_ea, thid_t tid, int stkarg_nbytes, const struct regobjs_t *regargs, struct relobj_t *stkargs, struct regobjs_t *retregs, qstring *errbuf, debug_event_t *event, int flags) { bytevec_t req = prepare_rpc_packet(RPC_APPCALL); req.pack_ea64(func_ea); req.pack_dd(tid); req.pack_dd(stkarg_nbytes); req.pack_dd(flags); regobjs_t *rr = (flags & APPCALL_MANUAL) == 0 ? retregs : NULL; append_appcall(req, *regargs, *stkargs, rr); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return BADADDR; memory_deserializer_t mmdsr(rp+1, rp->length); ea_t sp = mmdsr.unpack_ea64(); if ( sp == BADADDR ) { if ( (flags & APPCALL_DEBEV) != 0 ) extract_debug_event(event, mmdsr); if ( errbuf != NULL ) *errbuf = mmdsr.unpack_str(); } else if ( (flags & APPCALL_MANUAL) == 0 ) { if ( retregs != NULL ) extract_regobjs(retregs, true, mmdsr); } qfree(rp); return sp; } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_cleanup_appcall(thid_t tid) { bytevec_t req = prepare_rpc_packet(RPC_CLEANUP_APPCALL); req.pack_dd(tid); return send_request_get_drc_result(req, NULL); } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::dbg_rexec(const char *cmdline) { bytevec_t req = prepare_rpc_packet(RPC_REXEC); req.pack_str(cmdline); return send_request_get_long_result(req); } //-------------------------------------------------------------------------- drc_t idaapi rpc_debmod_t::dbg_bin_search( ea_t *pea, ea_t start_ea, ea_t end_ea, const compiled_binpat_vec_t &ptns, int srch_flags, qstring *errbuf) { bytevec_t req = prepare_rpc_packet(RPC_BIN_SEARCH); req.pack_ea64(start_ea); req.pack_ea64(end_ea); // compiled_binpat_vec_t int sz = ptns.size(); req.pack_dd(sz); for ( compiled_binpat_vec_t::const_iterator p=ptns.begin(); p != ptns.end(); ++p ) { // compiled_binpat_t sz = p->bytes.size(); req.pack_buf(p->bytes.begin(), sz); sz = p->mask.size(); req.pack_buf(p->mask.begin(), sz); sz = p->strlits.size(); req.pack_dd(sz); for ( int i=0; i < sz; ++i ) { req.pack_ea64(p->strlits[i].start_ea); req.pack_ea64(p->strlits[i].end_ea); } req.pack_dd(p->encidx); } req.pack_dd(srch_flags); rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); if ( drc == DRC_OK ) { if ( pea != NULL ) *pea = mmdsr.unpack_ea64(); } else if ( drc != DRC_FAILED ) // DRC_FAILED means not found { if ( errbuf != NULL ) *errbuf = mmdsr.unpack_str(); } qfree(rp); return drc; } //-------------------------------------------------------------------------- drc_t rpc_debmod_t::close_remote() { bytevec_t req = prepare_rpc_packet(RPC_OK); send_data(req); irs_term(&client_irs); network_error = false; return DRC_OK; } //-------------------------------------------------------------------------- int idaapi rpc_debmod_t::get_system_specific_errno(void) const { return irs_get_error(client_irs); } //------------------------------------------------------------------------- drc_t rpc_debmod_t::process_start_or_attach(bytevec_t &req, qstring *errbuf) { rpc_packet_t *rp = send_request_and_receive_reply(req); if ( rp == NULL ) return DRC_NETERR; memory_deserializer_t mmdsr(rp+1, rp->length); drc_t drc = unpack_drc(mmdsr); if ( drc > DRC_NONE ) { extract_debapp_attrs(&debapp_attrs, mmdsr); extract_dynamic_register_set(&idaregs, mmdsr); } else if ( errbuf != NULL ) { *errbuf = mmdsr.unpack_str(); } qfree(rp); return drc; }