997 lines
27 KiB
C++
997 lines
27 KiB
C++
|
|
#include <segment.hpp>
|
|
#include <err.h>
|
|
#include <network.hpp>
|
|
|
|
#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;
|
|
}
|