update
This commit is contained in:
246
idasdk75/dbg/dbg_rpc_client.cpp
Normal file
246
idasdk75/dbg/dbg_rpc_client.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
|
||||
// This file is included in the debugger stub that runs on the computer with IDA
|
||||
|
||||
#include <pro.h>
|
||||
#include <name.hpp>
|
||||
#include <diskio.hpp>
|
||||
|
||||
#include "dbg_rpc_client.h"
|
||||
#include "dbg_rpc_hlp.h"
|
||||
#include "debmod.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// check and send to the remote server the specified stub
|
||||
// do it only if its crc does not match the specified crc
|
||||
// this function runs on the local machine with ida interface
|
||||
static uchar *sync_stub(const char *fname, uint32 crc, size_t *psize)
|
||||
{
|
||||
bool complain = true;
|
||||
uchar *retval = NULL;
|
||||
char path[QMAXPATH];
|
||||
if ( getsysfile(path, sizeof(path), fname, NULL) != NULL )
|
||||
{
|
||||
linput_t *li = open_linput(path, false);
|
||||
if ( li != NULL )
|
||||
{
|
||||
int64 size = qlsize(li);
|
||||
if ( size > 0 )
|
||||
{
|
||||
bytevec_t buf;
|
||||
buf.resize(size);
|
||||
if ( qlread(li, buf.begin(), size) == size )
|
||||
{
|
||||
complain = false;
|
||||
if ( calc_crc32(0, buf.begin(), size) != crc )
|
||||
{
|
||||
*psize = size;
|
||||
retval = buf.extract();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("Kernel debugger stub is up to date...\n");
|
||||
*psize = 1; // signal ok
|
||||
}
|
||||
}
|
||||
}
|
||||
close_linput(li);
|
||||
}
|
||||
}
|
||||
if ( complain )
|
||||
warning("AUTOHIDE NONE\nCould not find/read debugger stub %s", fname);
|
||||
return retval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
dbg_rpc_client_t::dbg_rpc_client_t(idarpc_stream_t *_irs)
|
||||
: dbg_rpc_engine_t(/*is_client=*/ true),
|
||||
client_irs(_irs)
|
||||
{
|
||||
pending_event.clear_all();
|
||||
verbose = false;
|
||||
recv_timeout = RECV_TIMEOUT_PERIOD;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void dbg_rpc_client_t::my_update_wait_dialog(
|
||||
const char *message,
|
||||
const rpc_packet_t *rp)
|
||||
{
|
||||
if ( send_request_data.wait_dialog_displayed )
|
||||
{
|
||||
if ( rp->code != send_request_data.code )
|
||||
replace_wait_box("%s", message);
|
||||
}
|
||||
else
|
||||
{
|
||||
show_wait_box("%s", message);
|
||||
send_request_data.wait_dialog_displayed = true;
|
||||
}
|
||||
send_request_data.code = rp->code;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// requests received from the server.
|
||||
// here the client handles certain server -> client requests
|
||||
bytevec_t dbg_rpc_client_t::on_send_request_interrupt(const rpc_packet_t *rp)
|
||||
{
|
||||
memory_deserializer_t mmdsr(rp+1, rp->length);
|
||||
bytevec_t req = prepare_rpc_packet(RPC_OK);
|
||||
|
||||
switch ( rp->code )
|
||||
{
|
||||
// send_debug_names_to_ida() is thread safe
|
||||
case RPC_SET_DEBUG_NAMES:
|
||||
{
|
||||
my_update_wait_dialog("Downloading Symbols", rp);
|
||||
int qty = mmdsr.unpack_dd();
|
||||
ea_t *addrs = OPERATOR_NEW(ea_t, qty);
|
||||
char **names = OPERATOR_NEW(char *, qty);
|
||||
qstring name;
|
||||
ea_t old = 0;
|
||||
for ( int i=0; i < qty; i++ )
|
||||
{
|
||||
adiff_t o2 = mmdsr.unpack_ea64();
|
||||
if ( mmdsr.unpack_dd() )
|
||||
o2 = -o2;
|
||||
old += o2;
|
||||
addrs[i] = old;
|
||||
int oldlen = mmdsr.unpack_dd();
|
||||
QASSERT(1203, oldlen >= 0 && oldlen <= name.length());
|
||||
//keep the prefix
|
||||
name.resize(oldlen);
|
||||
if ( !mmdsr.unpack_str(&name) )
|
||||
INTERR(1294);
|
||||
names[i] = qstrdup(name.c_str());
|
||||
}
|
||||
int result = send_debug_names_to_ida(addrs, names, qty);
|
||||
verb(("set_debug_name(qty=%d) => %d\n", qty, result));
|
||||
req.pack_dd(result);
|
||||
for ( int i=0; i < qty; i++ )
|
||||
qfree(names[i]);
|
||||
delete [] addrs;
|
||||
delete [] names;
|
||||
}
|
||||
break;
|
||||
|
||||
// import_dll() is thread safe
|
||||
case RPC_IMPORT_DLL:
|
||||
{
|
||||
my_update_wait_dialog("Importing DLLs", rp);
|
||||
ea_t base = mmdsr.unpack_ea64();
|
||||
const char *path = mmdsr.unpack_str();
|
||||
int n = mmdsr.unpack_dd();
|
||||
const void *bytes = mmdsr.unpack_obj_inplace(n);
|
||||
bytevec_t uuid(bytes, n);
|
||||
int result = import_dll(import_request_t(base, path, uuid));
|
||||
verb(("import_dll(base=%a, path=%s) => %d\n", base, path, result));
|
||||
req.pack_dd(result);
|
||||
}
|
||||
break;
|
||||
|
||||
// send_debug_event_to_ida() is thread safe
|
||||
case RPC_HANDLE_DEBUG_EVENT:
|
||||
{
|
||||
debug_event_t ev;
|
||||
extract_debug_event(&ev, mmdsr);
|
||||
int rqflags = mmdsr.unpack_dd();
|
||||
int code = send_debug_event_to_ida(&ev, rqflags);
|
||||
req.pack_dd(code);
|
||||
}
|
||||
break;
|
||||
|
||||
// sync_stub() is thread safe
|
||||
case RPC_SYNC_STUB:
|
||||
{
|
||||
const char *fname = mmdsr.unpack_str();
|
||||
uint32 crc = mmdsr.unpack_dd();
|
||||
|
||||
// security problem: the debugger server should not be able to
|
||||
// read an arbitrary file on the local computer. therefore we completely
|
||||
// ignore the file name and use a hardcoded name.
|
||||
qnotused(fname);
|
||||
fname = "ida_kdstub.dll";
|
||||
|
||||
size_t size = 0;
|
||||
uchar *contents = sync_stub(fname, crc, &size);
|
||||
req.pack_dd((uint32)size);
|
||||
if ( contents != NULL )
|
||||
{
|
||||
req.append(contents, size);
|
||||
qfree(contents);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// msg/error/warning are thread safe
|
||||
case RPC_ERROR:
|
||||
case RPC_MSG:
|
||||
case RPC_WARNING:
|
||||
{
|
||||
const char *str = mmdsr.unpack_str();
|
||||
if ( *str != '\0' )
|
||||
{
|
||||
if ( rp->code == RPC_MSG )
|
||||
msg("%s", str);
|
||||
else if ( rp->code == RPC_ERROR )
|
||||
error("%s", str);
|
||||
else
|
||||
warning("%s", str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// no external functions are called
|
||||
case RPC_EVENT:
|
||||
{
|
||||
extract_debug_event(&pending_event, mmdsr);
|
||||
has_pending_event = true;
|
||||
req = prepare_rpc_packet(RPC_EVOK);
|
||||
verbev(("got event, storing it and sending RPC_EVOK\n"));
|
||||
}
|
||||
break;
|
||||
|
||||
// i doubt that this code is used on the client side
|
||||
// ioctl_handler is NULL
|
||||
case RPC_IOCTL:
|
||||
{
|
||||
int code = handle_ioctl_packet(req, mmdsr.ptr, mmdsr.end);
|
||||
if ( code != RPC_OK )
|
||||
return prepare_rpc_packet((uchar)code);
|
||||
}
|
||||
break;
|
||||
|
||||
// report_idc_error() is thread safe
|
||||
case RPC_REPORT_IDC_ERROR:
|
||||
{
|
||||
ea_t ea = mmdsr.unpack_ea64();
|
||||
error_t code = mmdsr.unpack_dd();
|
||||
const char *errprm;
|
||||
ssize_t errval;
|
||||
if ( mmdsr.unpack_db() )
|
||||
{
|
||||
errprm = mmdsr.unpack_str();
|
||||
errval = (ssize_t)errprm;
|
||||
}
|
||||
else
|
||||
{
|
||||
errprm = NULL;
|
||||
errval = mmdsr.unpack_ea64();
|
||||
}
|
||||
report_idc_error(NULL, ea, code, errval, errprm);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return prepare_rpc_packet(RPC_UNK);
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void dbg_rpc_client_t::on_send_request_end(const rpc_packet_t *)
|
||||
{
|
||||
if ( send_request_data.wait_dialog_displayed )
|
||||
hide_wait_box();
|
||||
send_request_data.reset();
|
||||
}
|
||||
Reference in New Issue
Block a user