update to ida 7.6, add builds
This commit is contained in:
739
idasdk76/dbg/debmod.h
Normal file
739
idasdk76/dbg/debmod.h
Normal file
@@ -0,0 +1,739 @@
|
||||
#ifndef __DEBUGGER_MODULE__
|
||||
#define __DEBUGGER_MODULE__
|
||||
|
||||
//
|
||||
//
|
||||
// This is the base debmod_t class definition
|
||||
// From this class all debugger code must inherite and specialize
|
||||
//
|
||||
// Some OS specific functions must be implemented:
|
||||
// bool init_subsystem();
|
||||
// bool term_subsystem();
|
||||
// debmod_t *create_debug_session(void *);
|
||||
// int create_thread(thread_cb_t thread_cb, void *context);
|
||||
//
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <pro.h>
|
||||
#include <idd.hpp>
|
||||
#include <network.hpp>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
extern debugger_t debugger;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct name_info_t
|
||||
{
|
||||
eavec_t addrs;
|
||||
qvector<char *> names;
|
||||
void clear(void)
|
||||
{
|
||||
addrs.clear();
|
||||
names.clear();
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Extended process info
|
||||
struct ext_process_info_t : public process_info_t
|
||||
{
|
||||
int addrsize; // process bitness 32bit - 4, 64bit - 8, 0 - unknown
|
||||
qstring ext_name; // human-readable name (e.g. with command line agrs)
|
||||
void copy_to(process_info_t *dst)
|
||||
{
|
||||
dst->pid = pid;
|
||||
dst->name = ext_name.empty() ? name : ext_name;
|
||||
}
|
||||
};
|
||||
typedef qvector<ext_process_info_t> procvec_t;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Very simple class to store pending events
|
||||
enum queue_pos_t
|
||||
{
|
||||
IN_FRONT,
|
||||
IN_BACK
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct pagebpt_data_t
|
||||
{
|
||||
ea_t ea; // address of the bpt as specified by the user
|
||||
ea_t page_ea; // real address of the bpt as written to the process
|
||||
int user_len; // breakpoint length as specified by the user
|
||||
int aligned_len; // breakpoint length aligned to the page size
|
||||
int real_len; // real length of the breakpoint as written to the process
|
||||
uint32 old_prot; // old page protections (before writing the bpt to the process)
|
||||
// if 0, the bpt has not been written to the process yet.
|
||||
uint32 new_prot; // new page protections (when the bpt is active)
|
||||
bpttype_t type; // breakpoint type
|
||||
};
|
||||
|
||||
// Information about page breakpoints is stored in this data structure.
|
||||
// The map is indexed by the page start address (not the address specified
|
||||
// by the user!)
|
||||
typedef std::map<ea_t, pagebpt_data_t> page_bpts_t; // page_ea -> bpt info
|
||||
typedef qvector<page_bpts_t::iterator> pbpt_iterators_t; // list of iterators into page_bpts_t
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// set of addresses
|
||||
typedef std::set<ea_t> easet_t;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
class idc_value_t;
|
||||
class rpc_engine_t;
|
||||
error_t idaapi idc_get_reg_value(idc_value_t *argv, idc_value_t *r);
|
||||
error_t idaapi idc_set_reg_value(idc_value_t *argv, idc_value_t *r);
|
||||
void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm);
|
||||
|
||||
// IDC function name that is exported by a debugger module
|
||||
// to allow scripts to send debugger commands
|
||||
#define IDC_SENDDBG_CMD "send_dbg_command"
|
||||
#define IDC_READ_MSR "read_msr"
|
||||
#define IDC_WRITE_MSR "write_msr"
|
||||
#define IDC_STEP_BACK "step_back"
|
||||
#define IDC_SET_TEV "set_current_tev"
|
||||
#define IDC_GET_TEV "get_current_tev"
|
||||
|
||||
// A macro to convert a pointer to ea_t without sign extension.
|
||||
#define EA_T(ptr) (ea_t)(size_t)(ptr)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-V:debmod_bpt_t:730 not all members of a class are initialized inside the constructor: saved
|
||||
struct debmod_bpt_t
|
||||
{
|
||||
ea_t ea;
|
||||
uchar saved[8]; // size of the biggest supported bpt size (PPC64)
|
||||
uchar nsaved;
|
||||
int bid; // (epoc) breakpoint id (from TRK)
|
||||
debmod_bpt_t() : ea(BADADDR), nsaved(0), bid(0) {}
|
||||
debmod_bpt_t(ea_t _ea, uchar _nsaved) : ea(_ea), nsaved(_nsaved), bid(0) { QASSERT(1796, nsaved < sizeof(saved)); }
|
||||
};
|
||||
typedef std::map<ea_t, debmod_bpt_t> debmodbpt_map_t;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct eventlist_t : public std::deque<debug_event_t>
|
||||
{
|
||||
public:
|
||||
// save a pending event
|
||||
void enqueue(const debug_event_t &ev, queue_pos_t pos)
|
||||
{
|
||||
if ( pos != IN_BACK )
|
||||
push_front(ev);
|
||||
else
|
||||
push_back(ev);
|
||||
}
|
||||
|
||||
// retrieve a pending event
|
||||
bool retrieve(debug_event_t *event)
|
||||
{
|
||||
if ( empty() )
|
||||
return false;
|
||||
// get the first event and return it
|
||||
*event = front();
|
||||
pop_front();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int send_ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize);
|
||||
int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty);
|
||||
int send_debug_event_to_ida(const debug_event_t *ev, int rqflags);
|
||||
void set_arm_thumb_modes(ea_t *addrs, int qty);
|
||||
char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize);
|
||||
char *debug_event_str(const debug_event_t *ev); // returns static buf
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// describes a dll to be imported
|
||||
struct import_request_t
|
||||
{
|
||||
ea_t base;
|
||||
qstring path;
|
||||
bytevec_t uuid;
|
||||
import_request_t(ea_t _base, const qstring &_path, const bytevec_t &_uuid)
|
||||
: base(_base), path(_path), uuid(_uuid) {}
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(import_request_t);
|
||||
typedef qvector<import_request_t> import_infos_t;
|
||||
int import_dll(const import_request_t &req);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct regctx_t;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct regctx_entry_t
|
||||
{
|
||||
enum type_t
|
||||
{
|
||||
IVAL = 0,
|
||||
FVAL = 1,
|
||||
DATA = 2,
|
||||
FUNC = 3,
|
||||
} type;
|
||||
int reg_class;
|
||||
int reg_idx;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
size_t offset_in_ctx;
|
||||
size_t size_in_ctx;
|
||||
size_t reg_size;
|
||||
};
|
||||
struct
|
||||
{
|
||||
void (*read_func)(const regctx_t *, regval_t *, void *);
|
||||
void (*write_func)(regctx_t *, const regval_t *, void *);
|
||||
void *user_data;
|
||||
};
|
||||
};
|
||||
|
||||
uint64_t truncate_ival(uint64_t ival) const
|
||||
{
|
||||
switch ( reg_size )
|
||||
{
|
||||
case 1: ival = uint8_t(ival); break;
|
||||
case 2: ival = uint16_t(ival); break;
|
||||
case 4: ival = uint32_t(ival); break;
|
||||
}
|
||||
return ival;
|
||||
}
|
||||
|
||||
void read(regval_t *value, const uint8_t *ptr) const
|
||||
{
|
||||
if ( type == regctx_entry_t::FUNC )
|
||||
{
|
||||
read_func((regctx_t *) ptr, value, user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *p = ptr + offset_in_ctx;
|
||||
switch ( type )
|
||||
{
|
||||
case regctx_entry_t::IVAL:
|
||||
{
|
||||
uint64_t ival = 0;
|
||||
switch ( size_in_ctx )
|
||||
{
|
||||
case 1: ival = *(uint8_t *)p; break;
|
||||
case 2: ival = *(uint16_t *)p; break;
|
||||
case 4: ival = *(uint32_t *)p; break;
|
||||
case 8: ival = *(uint64_t *)p; break;
|
||||
}
|
||||
ival = truncate_ival(ival);
|
||||
value->ival = ival;
|
||||
}
|
||||
break;
|
||||
case regctx_entry_t::FVAL:
|
||||
// TODO: for x86, the value is converted to IEEE format in
|
||||
// x86_read_registers(). clean this up somehow.
|
||||
memcpy(&value->fval, p, size_in_ctx);
|
||||
value->rvtype = RVT_FLOAT;
|
||||
break;
|
||||
case regctx_entry_t::DATA:
|
||||
value->set_bytes(p, size_in_ctx);
|
||||
break;
|
||||
case regctx_entry_t::FUNC:
|
||||
// never happens; makes compiler happy.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool patch(uint8_t *ptr, const regval_t *value) const
|
||||
{
|
||||
if ( type == regctx_entry_t::FUNC )
|
||||
{
|
||||
write_func((regctx_t *) ptr, value, user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *p = ptr + offset_in_ctx;
|
||||
switch ( type )
|
||||
{
|
||||
case regctx_entry_t::IVAL:
|
||||
{
|
||||
uint64_t ival = value->ival;
|
||||
ival = truncate_ival(ival);
|
||||
switch ( size_in_ctx )
|
||||
{
|
||||
case 1: *(uint8_t *)p = ival; break;
|
||||
case 2: *(uint16_t *)p = ival; break;
|
||||
case 4: *(uint32_t *)p = ival; break;
|
||||
case 8: *(uint64_t *)p = ival; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case regctx_entry_t::FVAL:
|
||||
// TODO: for x86, the value is converted from IEEE format in
|
||||
// x86_write_register(). clean this up somehow.
|
||||
memcpy(p, &value->fval, size_in_ctx);
|
||||
break;
|
||||
case regctx_entry_t::DATA:
|
||||
if ( value->get_data_size() != size_in_ctx )
|
||||
return false;
|
||||
memcpy(p, value->get_data(), value->get_data_size());
|
||||
break;
|
||||
case regctx_entry_t::FUNC:
|
||||
// never happens; makes compiler happy.
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(regctx_entry_t);
|
||||
typedef qvector<regctx_entry_t> reg_ctx_entries_t;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct regctx_base_t
|
||||
{
|
||||
dynamic_register_set_t &idaregs; // linked to debmod_t's variable of the same name
|
||||
thid_t tid;
|
||||
int clsmask;
|
||||
|
||||
reg_ctx_entries_t entries;
|
||||
|
||||
void setup(thid_t _tid, int _clsmask=0)
|
||||
{
|
||||
tid = _tid;
|
||||
clsmask = _clsmask;
|
||||
}
|
||||
|
||||
void setup_reg(int dyn_reg_idx)
|
||||
{
|
||||
clsmask |= entries[dyn_reg_idx].reg_class;
|
||||
}
|
||||
|
||||
regctx_base_t(dynamic_register_set_t &_idaregs)
|
||||
: idaregs(_idaregs)
|
||||
{
|
||||
setup(0, 0);
|
||||
}
|
||||
|
||||
void add_idareg(register_info_t &ri)
|
||||
{
|
||||
idaregs.add_register(ri.name,
|
||||
ri.flags,
|
||||
ri.dtype,
|
||||
ri.register_class,
|
||||
ri.bit_strings,
|
||||
ri.default_bit_strings_mask);
|
||||
}
|
||||
|
||||
size_t add_entry(
|
||||
regctx_entry_t::type_t type,
|
||||
register_info_t &ri,
|
||||
size_t offset_in_ctx,
|
||||
size_t size_in_ctx,
|
||||
size_t reg_size)
|
||||
{
|
||||
size_t dyn_reg_idx = entries.size();
|
||||
regctx_entry_t &entry = entries.push_back();
|
||||
entry.type = type;
|
||||
entry.reg_class = ri.register_class;
|
||||
entry.reg_idx = dyn_reg_idx;
|
||||
entry.offset_in_ctx = offset_in_ctx;
|
||||
entry.size_in_ctx = size_in_ctx;
|
||||
entry.reg_size = reg_size;
|
||||
add_idareg(ri);
|
||||
return dyn_reg_idx;
|
||||
}
|
||||
|
||||
size_t add_ival(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx)
|
||||
{
|
||||
QASSERT(1797, size_in_ctx <= sizeof(regval_t::ival));
|
||||
size_t reg_size = ri.dtype == dt_word ? 2
|
||||
: ri.dtype == dt_dword ? 4
|
||||
: ri.dtype == dt_qword ? 8
|
||||
: 0;
|
||||
QASSERT(1798, reg_size != 0);
|
||||
return add_entry(regctx_entry_t::IVAL, ri, offset_in_ctx, size_in_ctx, reg_size);
|
||||
}
|
||||
|
||||
size_t add_fval(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx)
|
||||
{
|
||||
QASSERT(1799, size_in_ctx <= sizeof(regval_t::fval));
|
||||
return add_entry(regctx_entry_t::FVAL, ri, offset_in_ctx, size_in_ctx, size_in_ctx);
|
||||
}
|
||||
|
||||
size_t add_data(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx)
|
||||
{
|
||||
return add_entry(regctx_entry_t::DATA, ri, offset_in_ctx, size_in_ctx, size_in_ctx);
|
||||
}
|
||||
|
||||
size_t add_func(
|
||||
register_info_t &ri,
|
||||
void (*read_func)(const regctx_t *, regval_t *, void *),
|
||||
void (*write_func)(regctx_t *, const regval_t *, void *),
|
||||
void *user_data=nullptr)
|
||||
{
|
||||
size_t dyn_reg_idx = entries.size();
|
||||
regctx_entry_t &entry = entries.push_back();
|
||||
entry.type = regctx_entry_t::FUNC;
|
||||
entry.reg_class = ri.register_class;
|
||||
entry.reg_idx = dyn_reg_idx;
|
||||
entry.read_func = read_func;
|
||||
entry.write_func = write_func;
|
||||
entry.user_data = user_data;
|
||||
add_idareg(ri);
|
||||
return dyn_reg_idx;
|
||||
}
|
||||
|
||||
void read_all(regval_t *values)
|
||||
{
|
||||
for ( const regctx_entry_t &entry: entries )
|
||||
if ( (clsmask & entry.reg_class) != 0 )
|
||||
entry.read(&values[entry.reg_idx], (const uint8_t *) this);
|
||||
}
|
||||
|
||||
bool patch(int dyn_reg_idx, const regval_t *value)
|
||||
{
|
||||
return entries[dyn_reg_idx].patch((uint8_t *) this, value);
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Main class to represent a debugger module
|
||||
class debmod_t
|
||||
{
|
||||
protected:
|
||||
// processor_t &ph;
|
||||
typedef std::map<int, regval_t> regval_map_t;
|
||||
qvector<exception_info_t> exceptions;
|
||||
name_info_t dn_names;
|
||||
// Pending events. currently used only to store
|
||||
// exceptions that happen while attaching
|
||||
eventlist_t events;
|
||||
// The last event received via a successful get_debug_event()
|
||||
debug_event_t last_event;
|
||||
|
||||
// debugged process attributes (may be changed after process start/attach)
|
||||
debapp_attrs_t debapp_attrs;
|
||||
|
||||
procvec_t proclist;
|
||||
|
||||
// appcall contexts
|
||||
struct call_context_t
|
||||
{
|
||||
regvals_t saved_regs;
|
||||
ea_t sp;
|
||||
ea_t ctrl_ea;
|
||||
bool regs_spoiled;
|
||||
call_context_t() : sp(BADADDR), ctrl_ea(BADADDR), regs_spoiled(false) {}
|
||||
};
|
||||
typedef qstack<call_context_t> call_contexts_t;
|
||||
typedef std::map<thid_t, call_contexts_t> appcalls_t;
|
||||
appcalls_t appcalls;
|
||||
|
||||
int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize)
|
||||
{
|
||||
return ::send_ioctl(rpc, fn, buf, size, poutbuf, poutsize);
|
||||
}
|
||||
// If an IDC error occurs: we cannot prepare an error message on the server
|
||||
// side because we do not have access to error strings (they are in ida.hlp).
|
||||
// We pass the error code to IDA (with eventual arguments) so it can prepare
|
||||
// a nice error message for the user
|
||||
void report_idc_error(ea_t ea, error_t code, ssize_t errval, const char *errprm)
|
||||
{
|
||||
return ::report_idc_error(rpc, ea, code, errval, errprm);
|
||||
}
|
||||
|
||||
typedef std::map<ea_t, lowcnd_t> lowcnds_t;
|
||||
lowcnds_t cndmap;
|
||||
eavec_t handling_lowcnds;
|
||||
bool evaluate_and_handle_lowcnd(debug_event_t *event, int elc_flags=0);
|
||||
bool handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags);
|
||||
#define ELC_KEEP_EIP 0x0001 // do not reset eip before stepping
|
||||
#define ELC_KEEP_SUSP 0x0002 // keep suspended state, do not resume after stepping
|
||||
|
||||
// helper functions for programmatical single stepping
|
||||
virtual drc_t dbg_perform_single_step(debug_event_t *event, const insn_t &ins);
|
||||
virtual int dbg_freeze_threads_except(thid_t) { return 0; }
|
||||
virtual int dbg_thaw_threads_except(thid_t) { return 0; }
|
||||
drc_t resume_app_and_get_event(debug_event_t *dev);
|
||||
void set_platform(const char *platform_name);
|
||||
|
||||
// return number of processes, -1 - not implemented
|
||||
virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf);
|
||||
|
||||
public:
|
||||
// initialized by dbg_init()
|
||||
int debugger_flags;
|
||||
meminfo_vec_t old_ranges;
|
||||
rpc_engine_t *rpc;
|
||||
bool debug_debugger;
|
||||
// Is dynamic library?
|
||||
bool is_dll;
|
||||
|
||||
// indexes of sp and program counter registers.
|
||||
// Must be initialized by derived classes.
|
||||
int sp_idx;
|
||||
int pc_idx;
|
||||
|
||||
// index of frame pointer register
|
||||
int fp_idx;
|
||||
|
||||
// Total number of registers.
|
||||
// Must be initialized by derived classes.
|
||||
int nregs;
|
||||
|
||||
// Breakpoint code.
|
||||
// Must be initialized by derived classes.
|
||||
bytevec_t bpt_code;
|
||||
|
||||
qstring input_file_path;
|
||||
|
||||
page_bpts_t page_bpts;
|
||||
|
||||
// will either send as msg/warning/error through callui,
|
||||
// or through 'rpc' if it is present.
|
||||
DEFINE_ALL_NOTIFICATION_FUNCTIONS(rpc);
|
||||
AS_PRINTF(3,0) static ssize_t dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va);
|
||||
|
||||
bool broken_connection;
|
||||
pid_t pid;
|
||||
|
||||
debmodbpt_map_t bpts;
|
||||
update_bpt_vec_t deleted_bpts; // deleted bpts in the last update_bpts() call
|
||||
// if bpt EA was deleted then bpt raised in the same place for the
|
||||
// same thread does not belong to IDA
|
||||
bool is_ida_bpt(ea_t ea, thid_t tid)
|
||||
{
|
||||
if ( bpts.find(ea) != bpts.end() )
|
||||
return true;
|
||||
update_bpt_info_t b;
|
||||
b.ea = ea;
|
||||
return deleted_bpts.find(b) != deleted_bpts.end()
|
||||
&& (last_event.eid() != BREAKPOINT
|
||||
|| last_event.ea != ea
|
||||
|| last_event.tid != tid);
|
||||
}
|
||||
|
||||
static bool reuse_broken_connections;
|
||||
|
||||
//------------------------------------
|
||||
// Dynamic register set for debugger_t
|
||||
//------------------------------------
|
||||
dynamic_register_set_t idaregs;
|
||||
|
||||
//------------------------------------
|
||||
// Constructors and destructors
|
||||
//------------------------------------
|
||||
debmod_t();
|
||||
virtual ~debmod_t() { cleanup(); }
|
||||
|
||||
//------------------------------------
|
||||
// Debug names methods
|
||||
//------------------------------------
|
||||
void clear_debug_names();
|
||||
name_info_t *get_debug_names();
|
||||
void save_debug_name(ea_t ea, const char *name);
|
||||
int set_debug_names();
|
||||
int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty);
|
||||
int send_debug_event_to_ida(const debug_event_t *ev, int rqflags);
|
||||
ea_t find_debug_name(const char *name) const;
|
||||
//------------------------------------
|
||||
// Utility methods
|
||||
//------------------------------------
|
||||
void cleanup(void);
|
||||
AS_PRINTF(2, 3) void debdeb(const char *format, ...);
|
||||
AS_PRINTF(2, 3) bool deberr(const char *format, ...);
|
||||
bool same_as_oldmemcfg(const meminfo_vec_t &ranges) const;
|
||||
void save_oldmemcfg(const meminfo_vec_t &ranges);
|
||||
bool continue_after_last_event(bool handled = true);
|
||||
lowcnd_t *get_failed_lowcnd(thid_t tid, ea_t ea);
|
||||
page_bpts_t::iterator find_page_bpt(ea_t ea, int size=1);
|
||||
bool del_page_bpt(ea_t ea, bpttype_t type);
|
||||
void enable_page_bpts(bool enable);
|
||||
ea_t calc_page_base(ea_t ea) { return align_down(ea, dbg_memory_page_size()); }
|
||||
void log_exception(const debug_event_t *ev, const exception_info_t *ei);
|
||||
uint64 probe_file_size(int fn, uint64 step);
|
||||
void set_input_path(const char *input_path);
|
||||
int read_bpt_orgbytes(bytevec_t *buf, ea_t ea, int len);
|
||||
|
||||
//------------------------------------
|
||||
// Shared methods
|
||||
//------------------------------------
|
||||
virtual bool check_input_file_crc32(uint32 orig_crc);
|
||||
virtual const exception_info_t *find_exception(int code);
|
||||
virtual bool get_exception_name(int code, char *buf, size_t bufsize);
|
||||
virtual drc_t idaapi dbg_get_processes(procinfo_vec_t *info, qstring *errbuf);
|
||||
|
||||
//------------------------------------
|
||||
// Methods to be implemented
|
||||
//------------------------------------
|
||||
virtual void idaapi dbg_set_debugging(bool _debug_debugger) = 0;
|
||||
virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) = 0;
|
||||
virtual void idaapi dbg_term(void) = 0;
|
||||
virtual drc_t idaapi dbg_detach_process(void) = 0;
|
||||
virtual drc_t idaapi dbg_start_process(
|
||||
const char *path,
|
||||
const char *args,
|
||||
const char *startdir,
|
||||
int flags,
|
||||
const char *input_path,
|
||||
uint32 input_file_crc32,
|
||||
qstring *errbuf) = 0;
|
||||
virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_msecs) = 0;
|
||||
virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) = 0;
|
||||
virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) = 0;
|
||||
virtual drc_t idaapi dbg_exit_process(qstring *errbuf) = 0;
|
||||
virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) = 0;
|
||||
virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty);
|
||||
virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) = 0;
|
||||
virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) = 0;
|
||||
virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) = 0;
|
||||
virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) = 0;
|
||||
virtual drc_t idaapi dbg_read_registers(
|
||||
thid_t thread_id,
|
||||
int clsmask,
|
||||
regval_t *values,
|
||||
qstring *errbuf) = 0;
|
||||
virtual drc_t idaapi dbg_write_register(
|
||||
thid_t thread_id,
|
||||
int reg_idx,
|
||||
const regval_t *value,
|
||||
qstring *errbuf) = 0;
|
||||
virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) = 0;
|
||||
virtual ea_t idaapi map_address(ea_t ea, const regval_t *, int /* regnum */) { return ea; }
|
||||
virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) = 0;
|
||||
virtual int idaapi dbg_get_scattered_image(scattered_image_t & /*si*/, ea_t /*base*/) { return -1; }
|
||||
virtual bool idaapi dbg_get_image_uuid(bytevec_t * /*uuid*/, ea_t /*base*/) { return false; }
|
||||
virtual ea_t idaapi dbg_get_segm_start(ea_t /*base*/, const qstring & /*segname*/) { return BADADDR; }
|
||||
virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) = 0;
|
||||
virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) = 0;
|
||||
virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) = 0;
|
||||
// for swbpts, len may be -1 (unknown size, for example arm/thumb mode) or bpt opcode length
|
||||
// dbg_add_bpt returns 2 if it adds a page bpt
|
||||
virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) = 0;
|
||||
virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) = 0;
|
||||
virtual drc_t idaapi dbg_update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf);
|
||||
virtual int idaapi dbg_add_page_bpt(bpttype_t /*type*/, ea_t /*ea*/, int /*size*/) { return 0; }
|
||||
virtual bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator /*p*/, bool /*enable*/) { return false; }
|
||||
virtual drc_t idaapi dbg_update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf);
|
||||
virtual drc_t idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf);
|
||||
virtual int idaapi dbg_open_file(const char * /*file*/, uint64 * /*fsize*/, bool /*readonly*/) { return -1; }
|
||||
virtual void idaapi dbg_close_file(int /*fn*/) {}
|
||||
virtual ssize_t idaapi dbg_read_file(int /*fn*/, qoff64_t /*off*/, void * /*buf*/, size_t /*size*/) { return 0; }
|
||||
virtual ssize_t idaapi dbg_write_file(int /*fn*/, qoff64_t /*off*/, const void * /*buf*/, size_t /*size*/) { return 0; }
|
||||
virtual int idaapi handle_ioctl(
|
||||
int /*fn*/,
|
||||
const void * /*buf*/,
|
||||
size_t /*size*/,
|
||||
void ** /*outbuf*/,
|
||||
ssize_t * /*outsize*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int idaapi get_system_specific_errno(void) const; // this code must be acceptable by winerr()
|
||||
virtual drc_t idaapi dbg_update_call_stack(thid_t, call_stack_t *) { return DRC_NONE; }
|
||||
virtual ea_t idaapi 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*/);
|
||||
virtual drc_t idaapi dbg_cleanup_appcall(thid_t /*tid*/);
|
||||
virtual bool idaapi write_registers(
|
||||
thid_t /*tid*/,
|
||||
int /*start*/,
|
||||
int /*count*/,
|
||||
const regval_t * /*values*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// finalize appcall stack image
|
||||
// input: stack image contains the return address at the beginning
|
||||
virtual int finalize_appcall_stack(call_context_t &, regval_map_t &, bytevec_t &) { return 0; }
|
||||
virtual ea_t calc_appcall_stack(const regvals_t ®vals);
|
||||
virtual bool should_stop_appcall(thid_t tid, const debug_event_t *event, ea_t ea);
|
||||
virtual bool should_suspend_at_exception(const debug_event_t *event, const exception_info_t *ei);
|
||||
virtual bool preprocess_appcall_cleanup(thid_t, call_context_t &) { return true; }
|
||||
virtual int get_regidx(const char *regname, int *clsmask) = 0;
|
||||
virtual uint32 dbg_memory_page_size(void) { return 0x1000; }
|
||||
virtual bool idaapi dbg_prepare_broken_connection(void) { return false; }
|
||||
virtual bool idaapi dbg_continue_broken_connection(pid_t) { old_ranges.clear(); return true; }
|
||||
virtual bool idaapi dbg_enable_trace(thid_t, bool, int) { return false; }
|
||||
virtual bool idaapi dbg_is_tracing_enabled(thid_t, int) { return false; }
|
||||
virtual int idaapi dbg_rexec(const char *cmdline);
|
||||
virtual void adjust_swbpt(ea_t *, int *) {}
|
||||
virtual void dbg_get_debapp_attrs(debapp_attrs_t *out_pattrs) const;
|
||||
virtual bool idaapi dbg_get_srcinfo_path(qstring * /*path*/, ea_t /*base*/) const { return false; }
|
||||
virtual bool import_dll(const import_request_t & /*req*/) { return false; }
|
||||
virtual drc_t idaapi dbg_bin_search(
|
||||
ea_t *ea,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const compiled_binpat_vec_t &ptns,
|
||||
int srch_flags,
|
||||
qstring *errbuf);
|
||||
|
||||
bool restore_broken_breakpoints(void);
|
||||
void set_addr_size(int size) { debapp_attrs.addrsize = size; }
|
||||
void set_endianness(bool is_be) { debapp_attrs.is_be = is_be; }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Some functions, per OS implemented
|
||||
//
|
||||
bool init_subsystem();
|
||||
bool term_subsystem();
|
||||
debmod_t *create_debug_session(void *params);
|
||||
|
||||
//
|
||||
// Processor specific init/term
|
||||
//
|
||||
void processor_specific_init(void);
|
||||
void processor_specific_term(void);
|
||||
|
||||
// Perform an action on all existing debugger modules
|
||||
struct debmod_visitor_t
|
||||
{
|
||||
virtual int visit(debmod_t *debmod) = 0;
|
||||
};
|
||||
int for_all_debuggers(debmod_visitor_t &v);
|
||||
|
||||
|
||||
//
|
||||
// Utility functions
|
||||
//
|
||||
|
||||
// Common method between MacOS and Linux to launch a process
|
||||
drc_t idaapi maclnx_launch_process(
|
||||
debmod_t *debmod,
|
||||
const char *path,
|
||||
const char *args,
|
||||
const char *startdir,
|
||||
int flags,
|
||||
const char *input_path,
|
||||
uint32 input_file_crc32,
|
||||
void **child_pid,
|
||||
qstring *errbuf);
|
||||
|
||||
bool add_idc_funcs(const struct ext_idcfunc_t funcs[], size_t nfuncs, bool reg);
|
||||
|
||||
//
|
||||
// Externs
|
||||
//
|
||||
extern debmod_t *idc_debmod;
|
||||
extern thid_t idc_thread;
|
||||
extern bool ignore_sigint;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// server.cpp
|
||||
bool lock_begin();
|
||||
bool lock_end();
|
||||
|
||||
// bool srv_lock_begin(void);
|
||||
// bool srv_lock_end(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user