407 lines
12 KiB
C++
407 lines
12 KiB
C++
//
|
|
//
|
|
// This file contains win32 specific implementations of win32_debugger_module class
|
|
// server-side functionality only
|
|
//
|
|
//
|
|
|
|
#include <pro.h>
|
|
#include "win32_rpc.h"
|
|
#include "win32_debmod.h"
|
|
#include "dbg_rpc_hlp.h"
|
|
|
|
bool ida_export idb_utf8(qstring *, const char *, int, int) { return false; }
|
|
|
|
#include "tilfuncs.hpp"
|
|
|
|
//---------------------------------------------------------- main thread ---
|
|
static AS_PRINTF(3, 4) int pdb_ioctl_error(void **poutbuf, ssize_t *poutsize, const char *format, ...)
|
|
{
|
|
char buf[MAXSTR];
|
|
va_list va;
|
|
va_start(va, format);
|
|
int len = qvsnprintf(buf, sizeof(buf), format, va);
|
|
va_end(va);
|
|
msg("%s", buf);
|
|
|
|
*poutsize = len + 1;
|
|
*poutbuf = qstrdup(buf);
|
|
return pdb_error;
|
|
}
|
|
|
|
//---------------------------------------------------------- main thread ---
|
|
void win32_debmod_t::handle_pdb_thread_request(void *_pdb_rsess)
|
|
{
|
|
pdb_remote_session_t *pdb_rsess = (pdb_remote_session_t *) _pdb_rsess;
|
|
pdb_remote_session_t::client_read_request_t &rr = pdb_rsess->client_read_request;
|
|
if ( rr.kind == READ_INPUT_FILE )
|
|
{
|
|
// read input file
|
|
bytevec_t req;
|
|
req.pack_dq(rr.off_ea);
|
|
req.pack_dd(rr.size);
|
|
void *outbuf = NULL;
|
|
ssize_t outsize = 0;
|
|
// send request to IDA
|
|
int rc = send_ioctl(WIN32_IOCTL_READFILE, req.begin(), req.size(), &outbuf, &outsize);
|
|
if ( rc == 1 && outbuf != NULL )
|
|
{
|
|
// OK
|
|
size_t copylen = qmin(rr.size, outsize);
|
|
memcpy(rr.buffer, outbuf, copylen);
|
|
rr.size = copylen;
|
|
rr.result = true;
|
|
}
|
|
else
|
|
{
|
|
rr.result = false;
|
|
}
|
|
if ( outbuf != NULL )
|
|
qfree(outbuf);
|
|
}
|
|
else if ( rr.kind == READ_MEMORY )
|
|
{
|
|
// read memory
|
|
ea_t ea = ea_t(rr.off_ea);
|
|
void *buf = rr.buffer;
|
|
size_t size = rr.size;
|
|
ssize_t rc = _read_memory(ea, buf, size);
|
|
if ( rc >= 0 )
|
|
rr.size = rc;
|
|
rr.result = rc >= 0;
|
|
}
|
|
else
|
|
{
|
|
// unknown request
|
|
rr.result = false;
|
|
}
|
|
|
|
rr.read_complete();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
pdb_remote_session_t *win32_debmod_t::get_pdb_session(int id)
|
|
{
|
|
for ( size_t i = 0; i < pdb_remote_sessions.size(); ++i )
|
|
if ( pdb_remote_sessions[i]->get_id() == id )
|
|
return pdb_remote_sessions[i];
|
|
return NULL;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void win32_debmod_t::delete_pdb_session(int id)
|
|
{
|
|
for ( size_t i = 0; i < pdb_remote_sessions.size(); ++i )
|
|
{
|
|
if ( pdb_remote_sessions[i]->get_id() == id )
|
|
{
|
|
pdb_remote_sessions[i]->stop();
|
|
delete pdb_remote_sessions[i];
|
|
pdb_remote_sessions.erase(pdb_remote_sessions.begin() + i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void close_pdb_remote_session(pdb_remote_session_t *session)
|
|
{
|
|
session->stop();
|
|
delete session;
|
|
}
|
|
|
|
//---------------------------------------------------------- main thread ---
|
|
int idaapi win32_debmod_t::handle_ioctl(
|
|
int fn,
|
|
const void *buf,
|
|
size_t size,
|
|
void **poutbuf,
|
|
ssize_t *poutsize)
|
|
{
|
|
qnotused(size);
|
|
int sid = 0; // pdb_remote_session_t ID
|
|
pdb_remote_session_t *pdb_rsess = NULL;
|
|
switch ( fn )
|
|
{
|
|
case WIN32_IOCTL_RDMSR:
|
|
QASSERT(30119, size == sizeof(uval_t));
|
|
{
|
|
uint64 value;
|
|
uval_t reg = *(uval_t *)buf;
|
|
int code = rdmsr(reg, &value);
|
|
if ( SUCCEEDED(code) )
|
|
{
|
|
*poutbuf = qalloc(sizeof(value));
|
|
if ( *poutbuf != NULL )
|
|
{
|
|
memcpy(*poutbuf, &value, sizeof(value));
|
|
*poutsize = sizeof(value);
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
case WIN32_IOCTL_WRMSR:
|
|
QASSERT(30120, size == sizeof(win32_wrmsr_t));
|
|
{
|
|
win32_wrmsr_t &msr = *(win32_wrmsr_t *)buf;
|
|
return wrmsr(msr.reg, msr.value);
|
|
}
|
|
|
|
#define ENSURE_PDB_THREAD() \
|
|
do \
|
|
{ \
|
|
if ( !pdb_thread.is_running() ) \
|
|
return pdb_ioctl_error( \
|
|
poutbuf, poutsize, "PDB thread not running?!?\n"); \
|
|
} while ( false )
|
|
|
|
#define GET_OPENED_SESSION() \
|
|
do \
|
|
{ \
|
|
if ( mmdsr.empty() ) \
|
|
return pdb_error; \
|
|
sid = mmdsr.unpack_dd(); \
|
|
pdb_rsess = get_pdb_session(sid); \
|
|
} while ( false )
|
|
|
|
#define ENSURE_SESSION_OPENED() \
|
|
do \
|
|
{ \
|
|
GET_OPENED_SESSION(); \
|
|
if ( pdb_rsess == NULL ) \
|
|
return pdb_ioctl_error( \
|
|
poutbuf, poutsize, "Unknown PDB session #%d\n", sid); \
|
|
} while ( false )
|
|
|
|
#define FLUSH_PDB_REQUEST_STORAGE() \
|
|
do \
|
|
{ \
|
|
size_t sz = pdb_rsess->storage.size(); \
|
|
uint8 *raw = (uint8 *) qalloc(sz); \
|
|
if ( raw == NULL ) \
|
|
return pdb_error; \
|
|
memcpy(raw, pdb_rsess->storage.begin(), sz); \
|
|
*poutbuf = raw; \
|
|
*poutsize = sz; \
|
|
} while ( false )
|
|
|
|
case WIN32_IOCTL_PDB_OPEN:
|
|
{
|
|
pdb_thread.start_if_needed();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
|
|
pdb_rsess = new pdb_remote_session_t();
|
|
pdb_remote_sessions.push_back(pdb_rsess);
|
|
|
|
compiler_info_t cci;
|
|
mmdsr.unpack_obj(&cci, sizeof(cci));
|
|
pdbargs_t args;
|
|
args.pdb_path = mmdsr.unpack_str();
|
|
args.input_path = mmdsr.unpack_str();
|
|
mmdsr.unpack_obj(&args.pdb_sign, sizeof(args.pdb_sign));
|
|
args.spath = mmdsr.unpack_str();
|
|
args.loaded_base = mmdsr.unpack_ea64();
|
|
args.flags = mmdsr.unpack_dd();
|
|
pdb_rsess->open(cci, args);
|
|
bytevec_t storage;
|
|
storage.pack_dd(pdb_rsess->get_id());
|
|
*poutsize = storage.size();
|
|
*poutbuf = storage.extract();
|
|
pdb_rsess->is_opening = true;
|
|
}
|
|
return pdb_ok;
|
|
|
|
case WIN32_IOCTL_PDB_OPERATION_COMPLETE:
|
|
// This is used, in a polling fashion, by the the client,
|
|
// to check on completeness of the fetch. At the same time,
|
|
// this is our wake-up call for looking whether the
|
|
// fetch thread requires more information.
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
// If we've got a read request, handle it now
|
|
if ( pdb_rsess->client_read_request.pending() )
|
|
handle_pdb_thread_request(pdb_rsess);
|
|
|
|
bytevec_t storage;
|
|
bool done = pdb_rsess->is_done();
|
|
if ( done )
|
|
{
|
|
pdb_rsess->is_opening = false;
|
|
const char *fname = pdb_rsess->session_ref.session->get_used_fname();
|
|
local_pdb_access_t *acc = pdb_rsess->session_ref.session->pdb_access;
|
|
HRESULT hr = acc != NULL ? S_OK : E_FAIL;
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
storage.pack_dd(uint32(pdb_op_complete));
|
|
storage.pack_dd(acc->get_global_symbol_id());
|
|
storage.pack_dd(acc->get_machine_type());
|
|
storage.pack_dd(acc->get_dia_version());
|
|
storage.pack_str(fname);
|
|
}
|
|
else
|
|
{
|
|
storage.pack_dd(uint32(pdb_op_failure));
|
|
qstring errmsg;
|
|
errmsg.sprnt("%s: %s\n", fname, pdberr(hr));
|
|
storage.pack_str(errmsg.c_str());
|
|
delete_pdb_session(sid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
storage.pack_dd(uint32(pdb_op_not_complete));
|
|
}
|
|
|
|
*poutsize = storage.size();
|
|
*poutbuf = storage.extract();
|
|
return pdb_ok;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_FETCH_SYMBOL:
|
|
case WIN32_IOCTL_PDB_FETCH_CHILDREN:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
DWORD sym_id = mmdsr.unpack_dd();
|
|
// msg("Fetch%s 0x%x\n",
|
|
// (fn == WIN32_IOCTL_PDB_FETCH_CHILDREN ? " children for" : ""),
|
|
// (uint32) sym);
|
|
bool ok;
|
|
if ( fn == WIN32_IOCTL_PDB_FETCH_SYMBOL )
|
|
{
|
|
// Symbol
|
|
ok = pdb_rsess->fetch_symbol(sym_id);
|
|
}
|
|
else
|
|
{
|
|
// Children
|
|
enum SymTagEnum children_type = (enum SymTagEnum) mmdsr.unpack_dd();
|
|
ok = pdb_rsess->fetch_children(sym_id, children_type);
|
|
}
|
|
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_CLOSE:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
GET_OPENED_SESSION();
|
|
if ( pdb_rsess != NULL )
|
|
delete_pdb_session(sid);
|
|
|
|
return pdb_ok;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_LINES_BY_VA:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
ea_t va = mmdsr.unpack_ea64();
|
|
uint64 length = mmdsr.unpack_dq();
|
|
|
|
bool ok = pdb_rsess->fetch_lines_by_va(
|
|
va, length);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_LINES_BY_COORDS:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
DWORD file_id = mmdsr.unpack_dd();
|
|
DWORD lnnum = mmdsr.unpack_dd();
|
|
DWORD colnum = mmdsr.unpack_dd();
|
|
bool ok = pdb_rsess->fetch_lines_by_coords(file_id, lnnum, colnum);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_SYMBOLS_AT_VA:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
ea_t va = mmdsr.unpack_ea64();
|
|
uint64 length = mmdsr.unpack_dq();
|
|
enum SymTagEnum type = (enum SymTagEnum) mmdsr.unpack_dd();
|
|
bool ok = pdb_rsess->fetch_symbols_at_va(va, length, type);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_FILE_COMPILANDS:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
uint32 file_id = mmdsr.unpack_dd();
|
|
bool ok = pdb_rsess->fetch_file_compilands(file_id);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_FILE_PATH:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
uint32 file_id = mmdsr.unpack_dd();
|
|
bool ok = pdb_rsess->fetch_file_path(file_id);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FETCH_SYMBOL_FILES:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
DWORD sym_id = mmdsr.unpack_dd();
|
|
bool ok = pdb_rsess->fetch_symbol_files(sym_id);
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
case WIN32_IOCTL_PDB_SIP_FIND_FILES:
|
|
{
|
|
ENSURE_PDB_THREAD();
|
|
memory_deserializer_t mmdsr(buf, size);
|
|
ENSURE_SESSION_OPENED();
|
|
|
|
qstring fname = mmdsr.unpack_str();
|
|
bool ok = pdb_rsess->fetch_files(fname.c_str());
|
|
if ( ok )
|
|
FLUSH_PDB_REQUEST_STORAGE();
|
|
return ok ? pdb_ok : pdb_error;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|