Files
sigmaker-ida/idasdk75/include/dbg.hpp
2021-06-05 21:10:25 +03:00

2625 lines
109 KiB
C++

/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2020 Hex-Rays
* ALL RIGHTS RESERVED.
*
*/
#ifndef DBG_HPP
#define DBG_HPP
#include <idp.hpp>
#include <idd.hpp>
#include <kernwin.hpp> // for callui() and ui_notification_t
/*! \file dbg.hpp
\brief Contains functions to control the debugging of a process.
See \ref dbg_funcs for a complete explanation of these functions.
These functions are inlined for the kernel.
They are not inlined for the user-interfaces.
*/
//--------------------------------------------------------------------
// D E B U G G E R I N F O R M A T I O N
//--------------------------------------------------------------------
/// This structure contains information about the current debugger.
/// (NULL if no debugger was loaded) - see idd.hpp for details about this structure.
///
/// All functions defined in this structure should only be called by the kernel !!!
idaman debugger_t ida_export_data *dbg;
//--------------------------------------------------------------------
// D E B U G G E R C A L L B A C K S
//--------------------------------------------------------------------
/// Debugger notification codes.
///
/// A plugin can receive notifications of all major events in the
/// debugger, by calling the hook_to_notification_point() function
/// with ::HT_DBG as ::hook_type_t (see loader.hpp for details about
/// installing and removing such callbacks).
///
/// IDA generates two major different types of debugger notifications:
///
/// - debugger event notification:
/// this notification monitors usual events occurring during the
/// execution of a process.
/// These event notifications are always generated for any process.
/// Some of these event notifications are interpreted by IDA
/// (high-level events), while others are directly generated by the
/// debugger module (low-level events).
/// Low-level events always return a ::debug_event_t structure as an argument.
///
/// - debugger asynchronous function result notification:
/// such a notification occurs only when a debugger properly terminated
/// the execution of an asynchronous function (see \ref dbg_funcs)
///
/// How to control the process execution (after the execution of all notification
/// handlers) from the notification handler:
///
/// - to force the process to STOP:
/// call suspend_process().
/// In this case, the current debugger command will be aborted and no new
/// request will be started.
///
/// - to force the process to CONTINUE:
/// call continue_process().
/// In this case, no new request will be started.
///
/// - to start new debugger command(s):
/// call as many request_COMMAND() as needed, then call run_requests().
/// In this case, the current debugger command (if any) will be aborted.
/// (see \ref dbg_funcs in this file for more details about requests)
///
/// - else, the process execution will depend on the current debugger options or
/// object settings. Some examples:
/// - a new loaded library will stop the process depending on the associated debugger option.
/// - a breakpoint will stop the process depending on its properties.
///
/// A plugin must not call asynchronous debugger functions from the notification handler!
/// Use the REQUEST QUEUE mechanism instead (request_...()).
///
/// If the plugin wants to access the process memory from a notification point,
/// it should call invalidate_dbgmem_config() and/or invalidate_dbgmem_contents()
/// functions. The invalidate_dbgmem_config() is really slow, so do not call it
/// unless the process memory config have changed after the last time the process
/// was suspended. The invalidate_dbgmem_contents() is fast and flushes the
/// memory cache in the ida kernel. Without it, functions like get_byte() would
/// return stale values!
enum dbg_notification_t
{
dbg_null = 0,
// debugger low-level event notifications (see IDD.HPP for details).
dbg_process_start, ///< \param event (const ::debug_event_t *)
///< \note This event notification is also an asynchronous
///< function result notification for start_process() !
dbg_process_exit, ///< \param event (const ::debug_event_t *)
///< \note This event notification is also an asynchronous
///< function result notification for start_process() !
dbg_process_attach, ///< \param event (const ::debug_event_t *)
///< \note This event notification is also an asynchronous
///< function result notification for start_process() !
dbg_process_detach, ///< \param event (const ::debug_event_t *)
///< \note This event notification is also an asynchronous
///< function result notification for start_process() !
dbg_thread_start, ///< \param event (const ::debug_event_t *)
dbg_thread_exit, ///< \param event (const ::debug_event_t *)
dbg_library_load, ///< \param event (const ::debug_event_t *)
dbg_library_unload, ///< \param event (const ::debug_event_t *)
dbg_information, ///< \param event (const ::debug_event_t *)
dbg_exception, ///< \param event (const ::debug_event_t *)
///< \param[out] warn (int *) filled with:
///< - -1: display an exception warning dialog
///< if the process is suspended.
///< - 0: never display an exception warning dialog.
///< - 1: always display an exception warning dialog.
// debugger high-level event notifications
dbg_suspend_process, ///< The process is now suspended.
///< \param event (const ::debug_event_t *)
///< \note This event notification is also an asynchronous
///< function result notification for suspend_process() !
dbg_bpt, ///< A user defined breakpoint was reached.
///< \param tid (::thid_t)
///< \param bptea (::ea_t)
///< \param[out] warn (int *) filled with:
///< - -1: display an exception warning dialog
///< if the process is suspended.
///< - 0: never display an exception warning dialog.
///< - 1: always display an exception warning dialog.
dbg_trace, ///< A step occurred (one instruction was executed). This event
///< notification is only generated if step tracing is enabled.
///< \param tid (::thid_t) thread ID
///< \param ip (::ea_t) current instruction pointer.
///< usually points after the executed instruction
///< \retval 1 do not log this trace event
///< \retval 0 log it
dbg_request_error, ///< An error occurred during the processing of a request.
///< \param failed_command (::ui_notification_t)
///< \param failed_dbg_notification (::dbg_notification_t)
// debugger asynchronous function result notifications
// Please note some low-level event notifications also act as asynchronous
// function result notifications.
dbg_step_into, ///< \param event (const ::debug_event_t *)
dbg_step_over, ///< \param event (const ::debug_event_t *)
dbg_run_to, ///< \param event (const ::debug_event_t *)
dbg_step_until_ret, ///< \param event (const ::debug_event_t *)
dbg_bpt_changed, ///< Breakpoint has been changed.
///< \param bptev_code (int) \ref BPTEV_
///< \param bpt (::bpt_t *)
dbg_started_loading_bpts, ///< Started loading breakpoint info from idb
dbg_finished_loading_bpts, ///< Finished loading breakpoint info from idb
dbg_last, ///< The last debugger notification code
};
/// \defgroup BPTEV_ Breakpoint modification events
/// Passed as 'bptev_code' parameter to ::dbg_bpt_changed callback
//@{
#define BPTEV_ADDED 0 ///< Breakpoint has been added
#define BPTEV_REMOVED 1 ///< Breakpoint has been removed
#define BPTEV_CHANGED 2 ///< Breakpoint has been modified
//@}
#ifndef __UI__
//--------------------------------------------------------------------
// D E B U G G E R F U N C T I O N S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs Debugger functions
///
/// Control the debugging of a process.
///
/// Debugger functions complete either SYNCHRONOUSLY or ASYNCHRONOUSLY:
///
/// - SYNCHRONOUS FUNCTIONS execute the entire action before the function returns.
///
/// - ASYNCHRONOUS FUNCTIONS return before the action has executed in its
/// entirety. They simply start the action, but the result of the action will
/// only be available later. For example, run_to() can execute a lot of
/// instructions before terminating.
/// Such functions provide a notification code to indicate the end of their
/// execution (see the 'Notification' keyword in the function documentation).
/// Install a callback using hook_to_notification_point() to be notified
/// when the action is terminated.
///
/// DEBUGGER COMMANDS are functions who influence the execution of the debugged
/// process. They are available in 2 forms:
///
/// - COMMAND(): (e.g. suspend_process())
/// In this mode, the command will be directly executed. However, it is forbidden
/// to use asynchronous commands in this mode from a debugger notification handler
/// (see ::dbg_notification_t).
///
/// - request_COMMAND(): (e.g. request_suspend_process())
/// In this mode, a REQUEST to run the command will be memorized at the end of
/// the REQUEST QUEUE (see below). This is mandatory to use this mode for asynchronous
/// commands from a debugger notification handler (see ::dbg_notification_t).
///
///
/// The REQUEST QUEUE contains a list of planned debugger commands.
/// These commands will be started only in the following cases:
///
/// - the previous command terminated, and no call to suspend_process()
/// or continue_process() occurred in the asynchronous function result
/// notification handler (if any).
///
/// - run_requests() was called.
/// Please note that when called from a debugger notification handler the
/// queued requests will only be started after the execution of all
/// notification handlers.
///
/// A request which fails to start (by returning 0) will generate a
/// ::dbg_request_error notification.
//@{
/// Execute requests until all requests are processed or an asynchronous
/// function is called.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return false if not all requests could be processed
/// (indicates an asynchronous function was started)
/// \note If called from a notification handler, the execution of requests will
/// be postponed to the end of the execution of all notification handlers.
inline bool idaapi run_requests(void) { return callui(ui_dbg_run_requests).cnd; }
/// Get the current running request.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return ui_null if no running request
inline ui_notification_t idaapi get_running_request(void) { return (ui_notification_t)callui(ui_dbg_get_running_request).i; }
/// Is a request currently running?
inline bool is_request_running(void) { return get_running_request() != ui_null; }
/// Get the notification associated (if any) with the current running request.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return dbg_null if no running request
inline dbg_notification_t idaapi get_running_notification(void) { return (dbg_notification_t)callui(ui_dbg_get_running_notification).i; }
/// Clear the queue of waiting requests.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \note If a request is currently running, this one isn't stopped.
inline void idaapi clear_requests_queue(void) { callui(ui_dbg_clear_requests_queue); }
//@} dbg_funcs
//--------------------------------------------------------------------
// P R O C E S S C O M M A N D S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_cmds Process commands
/// \ingroup dbg_funcs
///
/// Use these functions to manipulate the debugged process.
//@{
/// Return the state of the currently debugged process.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return one of \ref DSTATE_
inline int idaapi get_process_state(void) { return callui(ui_dbg_get_process_state).i; }
#endif // __UI__
/// \defgroup DSTATE_ Debugged process states
/// See get_process_state(), set_process_state(), invalidate_dbg_state()
//@{
#define DSTATE_SUSP -1 ///< process is suspended and will not continue
#define DSTATE_NOTASK 0 ///< no process is currently debugged
#define DSTATE_RUN 1 ///< process is running
//@}
/// \defgroup DBGINV_ Debugged process invalidation options
/// See set_process_state() and invalidate_dbg_state()
//@{
#define DBGINV_MEMORY 0x0001 ///< invalidate cached memory contents
#define DBGINV_MEMCFG 0x0002 ///< invalidate cached process segmentation
#define DBGINV_REGS 0x0004 ///< invalidate cached register values
#define DBGINV_ALL 0x7FFF ///< invalidate everything
#define DBGINV_REDRAW 0x8000 ///< refresh the screen
#define DBGINV_NONE 0 ///< invalidate nothing
//@}
#ifndef __UI__
/// Set new state for the debugged process.
/// Notifies the IDA kernel about the change of the debugged process state.
/// For example, a debugger module could call this function when it knows
/// that the process is suspended for a short period of time.
/// Some IDA API calls can be made only when the process is suspended.
/// The process state is usually restored before returning control to the caller.
/// You must know that it is ok to change the process state, doing it at arbitrary
/// moments may crash the application or IDA.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param newstate new process state (one of \ref DSTATE_)
/// if #DSTATE_NOTASK is passed then the state is not changed
/// \param p_thid ptr to new thread id. may be NULL or pointer to #NO_THREAD.
/// the pointed variable will contain the old thread id upon return
/// \param dbginv \ref DBGINV_
/// \return old debugger state (one of \ref DSTATE_)
inline int idaapi set_process_state(int newstate, thid_t *p_thid, int dbginv) { return callui(ui_dbg_set_process_state, newstate, p_thid, dbginv).i; }
/// Invalidate cached debugger information.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param dbginv \ref DBGINV_
/// \return current debugger state (one of \ref DSTATE_)
inline int idaapi invalidate_dbg_state(int dbginv)
{
return set_process_state(DSTATE_NOTASK, NULL, dbginv);
}
/// Start a process in the debugger.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_process_start}
/// \note You can also use the run_to() function to easily start the execution
/// of a process until a given address is reached.
/// \note For all parameters, a NULL value indicates the debugger will take
/// the value from the defined Process Options.
/// \param path path to the executable to start
/// \param args arguments to pass to process
/// \param sdir starting directory for the process
/// \retval -1 impossible to create the process
/// \retval 0 the starting of the process was cancelled by the user
/// \retval 1 the process was properly started
inline int idaapi start_process(
const char *path = NULL,
const char *args = NULL,
const char *sdir = NULL)
{
return callui(ui_dbg_start_process, path, args, sdir).i;
}
/// Post a start_process() request
inline int idaapi request_start_process(
const char *path = NULL,
const char *args = NULL,
const char *sdir = NULL)
{
return callui(ui_dbg_request_start_process, path, args, sdir).i;
}
/// Suspend the process in the debugger.
/// \sq{
/// Type,
/// - Synchronous function (if in a notification handler)
/// - Asynchronous function (everywhere else)
/// - available as Request,
/// Notification,
/// - none (if in a notification handler)
/// - ::dbg_suspend_process (everywhere else)
/// }
/// \note The suspend_process() function can be called from a notification
/// handler to force the stopping of the process.
/// In this case, no notification will be generated.
/// When you suspend a process, the running command is always aborted.
inline bool idaapi suspend_process(void) { return callui(ui_dbg_suspend_process).cnd; }
/// Post a suspend_process() request
inline bool idaapi request_suspend_process(void) { return callui(ui_dbg_request_suspend_process).cnd; }
/// Continue the execution of the process in the debugger.
/// \sq{Type, Synchronous function - available as Request,
/// Notification, none (synchronous function)}
/// \note The continue_process() function can be called from a notification
/// handler to force the continuation of the process. In this case
/// the request queue will not be examined, IDA will simply resume
/// execution. Usually it makes sense to call request_continue_process()
/// followed by run_requests(), so that IDA will first start a queued
/// request (if any) and then resume the application.
inline bool idaapi continue_process(void) { return callui(ui_dbg_continue_process).cnd; }
/// Post a continue_process() request.
/// \note This requires an explicit call to run_requests()
inline bool idaapi request_continue_process(void) { return callui(ui_dbg_request_continue_process).cnd; }
/// Terminate the debugging of the current process.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_process_exit}
inline bool idaapi exit_process(void) { return callui(ui_dbg_exit_process).cnd; }
/// Post an exit_process() request.
inline bool idaapi request_exit_process(void) { return callui(ui_dbg_request_exit_process).cnd; }
/// Take a snapshot of running processes and return their description.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param[out] array with information about each running process
/// \return number of processes or -1 on error
inline ssize_t idaapi get_processes(procinfo_vec_t *proclist) { return callui(ui_dbg_get_processes, proclist).ssize; }
/// Attach the debugger to a running process.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_process_attach}
/// \note This function shouldn't be called as a request if #NO_PROCESS is used.
/// \param pid PID of the process to attach to. If #NO_PROCESS, a dialog box
/// will interactively ask the user for the process to attach to.
/// \retval -4 debugger was not inited
/// \retval -3 the attaching is not supported
/// \retval -2 impossible to find a compatible process
/// \retval -1 impossible to attach to the given process (process died, privilege
/// needed, not supported by the debugger plugin, ...)
/// \retval 0 the user cancelled the attaching to the process
/// \retval 1 the debugger properly attached to the process
inline int idaapi attach_process(pid_t pid=NO_PROCESS, int event_id=-1) { return callui(ui_dbg_attach_process, pid, event_id).i; }
/// Post an attach_process() request
inline int idaapi request_attach_process(pid_t pid, int event_id) { return callui(ui_dbg_request_attach_process, pid, event_id).i; }
/// Detach the debugger from the debugged process.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_process_detach}
inline bool idaapi detach_process(void) { return callui(ui_dbg_detach_process).cnd; }
/// Post a detach_process() request
inline bool idaapi request_detach_process(void) { return callui(ui_dbg_request_detach_process).cnd; }
/// Is the debugger busy?.
/// Some debuggers do not accept any commands while the debugged application
/// is running. For such a debugger, it is unsafe to do anything with the
/// database (even simple queries like get_byte may lead to undesired consequences).
/// Returns: true if the debugged application is running under such a debugger
inline bool idaapi is_debugger_busy(void) { return callui(ui_dbg_is_busy).cnd; }
//@} dbg_funcs_cmds
//--------------------------------------------------------------------
// T H R E A D S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_threads Threads
/// \ingroup dbg_funcs
///
/// Inspect/Manipulate threads of debugged process.
//@{
/// Get number of threads.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_thread_qty(void) { return callui(ui_dbg_get_thread_qty).i; }
/// Get the ID of a thread.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of thread, is in range 0..get_thread_qty()-1
/// \return #NO_THREAD if the thread doesn't exist.
inline thid_t idaapi getn_thread(int n) { return (thid_t)callui(ui_dbg_getn_thread, n).i; }
/// Get current thread ID.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline thid_t idaapi get_current_thread(void) { return callui(ui_dbg_get_current_thread).i; }
/// Get the NAME of a thread
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of thread, is in range 0..get_thread_qty()-1
/// or -1 for the current thread
/// \return thread name or NULL if the thread doesn't exist.
inline const char *idaapi getn_thread_name(int n) { return callui(ui_dbg_getn_thread_name, n).cptr; }
/// Select the given thread as the current debugged thread.
/// All thread related execution functions will work on this thread.
/// The process must be suspended to select a new thread.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param tid ID of the thread to select
/// \return false if the thread doesn't exist.
inline bool idaapi select_thread(thid_t tid) { return callui(ui_dbg_select_thread, tid).cnd; }
/// Post a select_thread() request
inline bool idaapi request_select_thread(thid_t tid) { return callui(ui_dbg_request_select_thread, tid).cnd; }
/// Suspend thread.
/// Suspending a thread may deadlock the whole application if the suspended
/// was owning some synchronization objects.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param tid thread id
/// \retval -1 network error
/// \retval 0 failed
/// \retval 1 ok
inline int idaapi suspend_thread(thid_t tid) { return callui(ui_dbg_suspend_thread, tid).i; }
/// Post a suspend_thread() request
inline int idaapi request_suspend_thread(thid_t tid) { return callui(ui_dbg_request_suspend_thread, tid).i; }
/// Resume thread.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param tid thread id
/// \retval -1 network error
/// \retval 0 failed
/// \retval 1 ok
inline int idaapi resume_thread(thid_t tid) { return callui(ui_dbg_resume_thread, tid).i; }
/// Post a resume_thread() request
inline int idaapi request_resume_thread(thid_t tid) { return callui(ui_dbg_request_resume_thread, tid).i; }
//@} dbg_funcs_threads
//--------------------------------------------------------------------
// M O D U L E S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_modules Modules
/// \ingroup dbg_funcs
///
/// Functions to enumerate modules loaded into the process.
///
/// \param modinfo structure to receive the answer
/// \return false if there are no (more) modules
///
/// Typical loop to enumerate modules would look like:
/// \code
/// modinfo_t minfo;
/// for ( bool ok=get_first_module(&minfo); ok; ok=get_next_module(&minfo) )
/// ...
/// \endcode
//@{
inline bool idaapi get_first_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules
{ return callui(ui_dbg_get_first_module, modinfo).cnd; }
inline bool idaapi get_next_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules
{ return callui(ui_dbg_get_next_module, modinfo).cnd; }
//@}
//--------------------------------------------------------------------
// E X E C U T I O N F L O W C O N T R O L C O M M A N D S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_flow Execution flow control
/// \ingroup dbg_funcs
///
/// Use these functions to run instructions in the debugged process.
//@{
/// Execute one instruction in the current thread.
/// Other threads are kept suspended.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_step_into}
inline bool idaapi step_into(void) { return callui(ui_dbg_step_into).cnd; }
/// Post a step_into() request
inline bool idaapi request_step_into(void) { return callui(ui_dbg_request_step_into).cnd; }
/// Execute one instruction in the current thread,
/// but without entering into functions.
/// Others threads keep suspended.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_step_over}
inline bool idaapi step_over(void) { return callui(ui_dbg_step_over).cnd; }
/// Post a step_over() request
inline bool idaapi request_step_over(void) { return callui(ui_dbg_request_step_over).cnd; }
/// Execute the process until the given address is reached.
/// If no process is active, a new process is started.
/// Technically, the debugger sets up a temporary breakpoint at
/// the given address, and continues (or starts) the execution of
/// the whole process.
/// So, all threads continue their execution!
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_run_to}
/// \param ea target address
/// \param pid not used yet. please do not specify this parameter.
/// \param tid not used yet. please do not specify this parameter.
inline bool idaapi run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_run_to, ea, pid, tid).cnd; }
/// Post a run_to() request
inline bool idaapi request_run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_request_run_to, ea, pid, tid).cnd; }
/// Execute instructions in the current thread until
/// a function return instruction is executed (aka "step out").
/// Other threads are kept suspended.
/// \sq{Type, Asynchronous function - available as Request,
/// Notification, ::dbg_step_until_ret}
inline bool idaapi step_until_ret(void) { return callui(ui_dbg_step_until_ret).cnd; }
/// Post a step_until_ret() request
inline bool idaapi request_step_until_ret(void) { return callui(ui_dbg_request_step_until_ret).cnd; }
/// How to resume the application.
/// Set resume mode but do not resume process.
inline bool idaapi set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_set_resume_mode, tid, mode).cnd; }
/// Post a set_resume_mode() request
inline bool idaapi request_set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_request_set_resume_mode, tid, mode).cnd; }
//@} dbg_funcs_flow
//--------------------------------------------------------------------
// R E G I S T E R S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_regs Registers
/// \ingroup dbg_funcs
///
/// Inspect/Manipulate registers for debugged process.
/// The debugger structure defines a set of hardware registers in \dbg{registers}
/// IDA also recognizes register names for each defined bit in bit registers.
/// You can use all these names to set or get a register value.
///
/// For example, with the x86 Userland Win32 debugger you can use
/// register names like:
/// - "EAX", ... "EBP", "ESP", "EFL": for classical integer registers
/// - "CS", "DS", ... : for segment registers
/// - "ST0", "ST1", ... : for FPU registers
/// - "CF", "PF", "AF", "ZF", ... : for special bit values
//@{
/// Get register information
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi get_dbg_reg_info(const char *regname, register_info_t *ri) { return callui(ui_dbg_get_reg_info, regname, ri).cnd; }
/// Read a register value from the current thread.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi get_reg_val(const char *regname, regval_t *regval) { return callui(ui_dbg_get_reg_val, regname, regval).cnd; }
/// Get register value as an unsigned 64-bit int
inline bool idaapi get_reg_val(const char *regname, uint64 *ival) { return callui(ui_dbg_get_reg_val_i, regname, ival).cnd; }
/// Get value of the SP register for the current thread.
/// Requires a suspended debugger.
inline bool idaapi get_sp_val(ea_t *out) { return callui(ui_dbg_get_sp_val, out).cnd; }
/// Get value of the IP (program counter) register for the current thread.
/// Requires a suspended debugger.
inline bool idaapi get_ip_val(ea_t *out) { return callui(ui_dbg_get_ip_val, out).cnd; }
/// Write a register value to the current thread.
/// \sq{Type, Synchronous function - available as Request,
/// Notification, none (synchronous function)}
inline bool idaapi set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_set_reg_val, regname, regval).cnd; }
/// Write a register value to the current thread
inline bool idaapi set_reg_val(const char *regname, uint64 ival) { return callui(ui_dbg_set_reg_val_i, regname, ival).cnd; }
/// Post a set_reg_val() request
inline bool idaapi request_set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_request_set_reg_val, regname, regval).cnd; }
/// Does a register contain an integer value?
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_reg_integer(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_INT; }
/// Does a register contain a floating point value?
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_reg_float(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_FLOAT; }
/// Does a register contain a value of a custom data type?
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_reg_custom(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i >= 2; }
//@} dbg_funcs_regs
#endif // __UI__
//--------------------------------------------------------------------
// B R E A K P O I N T S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_bpts Breakpoints
/// \ingroup dbg_funcs
///
/// Work with debugger breakpoints.
//@{
/// Helper function for ::bpt_location_t
int idaapi set_bptloc_string(const char *s);
const char *idaapi get_bptloc_string(int i); ///< \copydoc set_bptloc_string()
/// Breakpoint location types
enum bpt_loctype_t
{
BPLT_ABS, ///< absolute address: ea
BPLT_REL, ///< relative address: module_path, offset
BPLT_SYM, ///< symbolic: symbol_name, offset
BPLT_SRC, ///< source level: filename, lineno
};
/// Describes a breakpoint location
struct bpt_location_t
{
//private:
ea_t info;
int index;
bpt_loctype_t loctype;
//public:
bpt_loctype_t type(void) const { return loctype; } ///< Get bpt type
bool is_empty_path(void) const { return index == 0; } ///< No path/filename specified? (::BPLT_REL, ::BPLT_SRC)
const char *path(void) const { return get_bptloc_string(index); } ///< Get path/filename (::BPLT_REL, ::BPLT_SRC)
const char *symbol(void) const { return get_bptloc_string(index); } ///< Get symbol name (::BPLT_SYM)
int lineno(void) const { return int(info); } ///< Get line number (::BPLT_SRC)
uval_t offset(void) const { return (uval_t)info; } ///< Get offset (::BPLT_REL, ::BPLT_SYM)
ea_t ea(void) const { return info; } ///< Get address (::BPLT_ABS)
bpt_location_t(void) : info(BADADDR), index(0), loctype(BPLT_ABS) {} ///< Constructor (default type is ::BPLT_ABS)
/// Specify an absolute address location
void set_abs_bpt(ea_t a)
{
info = a;
loctype = BPLT_ABS;
}
/// Specify a source level location
void set_src_bpt(const char *fn, int _lineno)
{
index = set_bptloc_string(fn);
info = _lineno;
loctype = BPLT_SRC;
}
/// Specify a symbolic location
void set_sym_bpt(const char *_symbol, uval_t _offset=0)
{
index = set_bptloc_string(_symbol);
info = _offset;
loctype = BPLT_SYM;
}
/// Specify a relative address location
void set_rel_bpt(const char *mod, uval_t _offset)
{
index = set_bptloc_string(mod);
info = _offset;
loctype = BPLT_REL;
}
/// Lexically compare two breakpoint locations.
/// Bpt locations are first compared based on type (i.e. ::BPLT_ABS < ::BPLT_REL).
/// ::BPLT_ABS locations are compared based on their ea values.
/// For all other location types, locations are first compared based on their
/// string (path/filename/symbol), then their offset/lineno.
int compare(const bpt_location_t &r) const { return callui(ui_dbg_compare_bpt_locs, this, &r).i; }
bool operator==(const bpt_location_t &r) const { return compare(r) == 0; }
bool operator!=(const bpt_location_t &r) const { return compare(r) != 0; }
bool operator< (const bpt_location_t &r) const { return compare(r) < 0; }
bool operator> (const bpt_location_t &r) const { return compare(r) > 0; }
bool operator<=(const bpt_location_t &r) const { return compare(r) <= 0; }
bool operator>=(const bpt_location_t &r) const { return compare(r) >= 0; }
/// Internal function
size_t print(qstring *buf) const;
};
/// Characteristics of a breakpoint
struct bpt_t
{
size_t cb; ///< size of this structure
qstring cndbody; ///< Condition as entered by the user
bpt_location_t loc; ///< Location
pid_t pid; ///< breakpoint process id
thid_t tid; ///< breakpoint thread id
ea_t ea; ///< Address, if known. For #BPLT_SRC, index into an internal data struct
bpttype_t type; ///< Breakpoint type
int pass_count; ///< Number of times the breakpoint is hit before stopping
///< (default is 0: stop always)
uint32 flags; ///< \ref BPT_T
/// \defgroup BPT_T Breakpoint property bits
/// Used by bpt_t::flags
//@{
#define BPT_BRK 0x001 ///< suspend execution upon hit
#define BPT_TRACE 0x002 ///< add trace information upon hit
#define BPT_UPDMEM 0x004 ///< refresh the memory layout and contents before evaluating bpt condition
#define BPT_ENABLED 0x008 ///< enabled?
#define BPT_LOWCND 0x010 ///< condition is calculated at low level (on the server side)
#define BPT_TRACEON 0x020 ///< enable tracing when the breakpoint is reached
#define BPT_TRACE_INSN 0x040 ///< instruction tracing
#define BPT_TRACE_FUNC 0x080 ///< function tracing
#define BPT_TRACE_BBLK 0x100 ///< basic block tracing
#define BPT_TRACE_TYPES (BPT_TRACE_INSN|BPT_TRACE_FUNC|BPT_TRACE_BBLK)
///< trace insns, functions, and basic blocks.
///< if any of #BPT_TRACE_TYPES bits are set but #BPT_TRACEON is clear,
///< then turn off tracing for the specified trace types
#define BPT_ELANG_MASK 0xF0000000u
#define BPT_ELANG_SHIFT 28 ///< index of the extlang (scripting language) of the condition
//@}
uint32 props; ///< \ref BKPT_
/// \defgroup BKPT_ Internal breakpoint properties
/// Used by bpt_t::props
//@{
#define BKPT_BADBPT 0x01 ///< failed to write the bpt to the process memory (at least one location)
#define BKPT_LISTBPT 0x02 ///< include in bpt list (user-defined bpt)
#define BKPT_TRACE 0x04 ///< trace bpt; should not be deleted when the process gets suspended
#define BKPT_ACTIVE 0x08 ///< active?
#define BKPT_PARTIAL 0x10 ///< partially active? (some locations were not written yet)
#define BKPT_CNDREADY 0x20 ///< condition has been compiled
#define BKPT_FAKEPEND 0x40 ///< fake pending bpt: it is inactive but another
///< bpt of the same type is active at the same address(es)
#define BKPT_PAGE 0x80 ///< written to the process as a page bpt. is available
///< only after writing the bpt to the process.
//@}
int size; ///< Size of the breakpoint (0 for software breakpoints)
int cndidx; ///< Internal number of the condition (<0-none)
bpt_t(void) : cb(sizeof(*this)), pid(NO_PROCESS), tid(NO_THREAD), ea(BADADDR),
type(BPT_SOFT), pass_count(0), flags(BPT_BRK|BPT_ENABLED),
props(0), size(0), cndidx(-1) {}
bool is_hwbpt(void) const { return type != BPT_SOFT; } ///< Is hardware breakpoint?
bool enabled(void) const { return (flags & BPT_ENABLED) != 0; } ///< Is breakpoint enabled?
bool is_low_level(void) const { return (flags & BPT_LOWCND) != 0; } ///< Is bpt condition calculated at low level?
bool badbpt(void) const { return (props & BKPT_BADBPT) != 0; } ///< Failed to write bpt to process memory?
bool listbpt(void) const { return (props & BKPT_LISTBPT) != 0; } ///< Include in the bpt list?
bool is_compiled(void) const { return (props & BKPT_CNDREADY) != 0; } ///< Condition has been compiled?
/// Written completely to process?
bool is_active(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == BKPT_ACTIVE; }
/// Written partially to process?
bool is_partially_active(void) const { return (props & BKPT_PARTIAL) != 0; }
/// Not written to process at all?
bool is_inactive(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == 0; }
/// Page breakpoint?
bool is_page_bpt(void) const { return (props & BKPT_PAGE) != 0; }
/// Get bpt size
int get_size(void) const { return is_hwbpt() ? size : 1; }
/// Set bpt location to an absolute address
void set_abs_bpt(ea_t a) { loc.set_abs_bpt(a); ea = a; }
/// Set bpt location to a source line
void set_src_bpt(const char *fn, int lineno) { loc.set_src_bpt(fn, lineno); ea = BADADDR; }
/// Set bpt location to a symbol
void set_sym_bpt(const char *sym, uval_t o) { loc.set_sym_bpt(sym, o); ea = BADADDR; }
/// Set bpt location to a relative address
void set_rel_bpt(const char *mod, uval_t o) { loc.set_rel_bpt(mod, o); ea = BADADDR; }
bool is_absbpt(void) const { return loc.type() == BPLT_ABS; } ///< Is absolute address breakpoint?
bool is_relbpt(void) const { return loc.type() == BPLT_REL; } ///< Is relative address breakpoint?
bool is_symbpt(void) const { return loc.type() == BPLT_SYM; } ///< Is symbolic breakpoint?
bool is_srcbpt(void) const { return loc.type() == BPLT_SRC; } ///< Is source level breakpoint?
/// Does breakpoint trace anything?
bool is_tracemodebpt(void) const { return (flags & BPT_TRACE_TYPES) != 0; }
/// Is this a tracing breakpoint, and is tracing enabled?
bool is_traceonbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) != 0; }
/// Is this a tracing breakpoint, and is tracing disabled?
bool is_traceoffbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) == 0; }
/// Configure tracing options
bool set_trace_action(bool enable, int trace_types)
{
trace_types &= BPT_TRACE_TYPES;
if ( trace_types == 0 )
return false;
flags |= trace_types;
setflag(flags, BPT_TRACEON, enable);
return true;
}
/// Get the scripting language name for the condition string
const char *get_cnd_elang() const;
/// Set the scripting language name for the condition string
/// \return false if too many languages were used
bool set_cnd_elang(const char *name);
size_t get_cnd_elang_idx() const { return flags >> BPT_ELANG_SHIFT; }
void set_cond(const char *cnd); ///< Internal function
bool eval_cond(ea_t ea, bool *fire, const char *bpt_type); ///< Internal function
};
typedef qvector<bpt_t> bpt_vec_t; ///< vector of breakpoints
enum movbpt_code_t
{
MOVBPT_OK, // moved ok
MOVBPT_NOT_FOUND, // source bpt not found
MOVBPT_DEST_BUSY, // destination location is busy (we already have such a bpt)
MOVBPT_BAD_TYPE, // BPLT_ABS is not supported
};
typedef qvector<movbpt_code_t> movbpt_codes_t;
struct movbpt_info_t
{
bpt_location_t from;
bpt_location_t to;
};
DECLARE_TYPE_AS_MOVABLE(movbpt_info_t);
typedef qvector<movbpt_info_t> movbpt_infos_t;
#ifndef __UI__
/// Get number of breakpoints.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_bpt_qty(void) { return callui(ui_dbg_get_bpt_qty).i; }
/// Get the characteristics of a breakpoint.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of breakpoint, is in range 0..get_bpt_qty()-1
/// \param[out] bpt filled with the characteristics.
/// \return false if no breakpoint exists
inline bool idaapi getn_bpt(int n, bpt_t *bpt) { return callui(ui_dbg_getn_bpt, n, bpt).cnd; }
/// Get the characteristics of a breakpoint.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param ea any address in the breakpoint range
/// \param[out] bpt if not NULL, is filled with the characteristics.
/// \return false if no breakpoint exists
inline bool idaapi get_bpt(ea_t ea, bpt_t *bpt) { return callui(ui_dbg_get_bpt, ea, bpt).cnd; }
/// Does a breakpoint exist at the given location?
inline bool exist_bpt(ea_t ea) { return get_bpt(ea, NULL); }
/// Add a new breakpoint in the debugged process.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \note Only one breakpoint can exist at a given address.
/// \param ea any address in the process memory space.
/// Depending on the architecture, hardware breakpoints
/// always be setup at random address. For example, on x86,
/// hardware breakpoints should be aligned depending on their size.
/// Moreover, on the x86 architecture, it is impossible to setup
/// more than 4 hardware breakpoints.
/// \param size size of the breakpoint (irrelevant for software breakpoints):
/// As for the address, hardware breakpoints can't always be setup
/// with random size.
/// \param type type of the breakpoint (#BPT_SOFT for software breakpoint)
/// special case #BPT_DEFAULT (#BPT_SOFT|#BPT_EXEC):
/// try to add instruction breakpoint of the appropriate type
/// as follows: software bpt if supported, hwbpt otherwise
inline bool idaapi add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_add_oldbpt, ea, size, type).cnd; }
/// Post an add_bpt(ea_t, asize_t, bpttype_t) request
inline bool idaapi request_add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_request_add_oldbpt, ea, size, type).cnd; }
/// Add a new breakpoint in the debugged process.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param bpt Breakpoint to add. It describes the break condition,
/// type, flags, location (module relative, source breakpoint
/// or absolute) and other attributes.
inline bool idaapi add_bpt(const bpt_t &bpt) { return callui(ui_dbg_add_bpt, &bpt).cnd; }
/// Post an add_bpt(const bpt_t &) request
inline bool idaapi request_add_bpt(const bpt_t &bpt) { return callui(ui_dbg_request_add_bpt, &bpt).cnd; }
/// Delete an existing breakpoint in the debugged process.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param ea any address in the breakpoint range
inline bool idaapi del_bpt(ea_t ea) { return callui(ui_dbg_del_oldbpt, ea).cnd; }
/// Post a del_bpt(ea_t) request
inline bool idaapi request_del_bpt(ea_t ea) { return callui(ui_dbg_request_del_oldbpt, ea).cnd; }
/// Delete an existing breakpoint in the debugged process.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param bptloc Breakpoint location
inline bool idaapi del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_del_bpt, &bptloc).cnd; }
/// Post a del_bpt(const bpt_location_t &) request
inline bool idaapi request_del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_request_del_bpt, &bptloc).cnd; }
/// Update modifiable characteristics of an existing breakpoint.
/// To update the breakpoint location, use change_bptlocs()
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \note Only the following fields can be modified:
/// - bpt_t::cndbody
/// - bpt_t::pass_count
/// - bpt_t::flags
/// - bpt_t::size
/// - bpt_t::type
/// \note Changing some properties will require removing and then re-adding
/// the breakpoint to the process memory (or the debugger backend), which
/// can lead to race conditions (i.e., breakpoint(s) can be missed) in
/// case the process is not suspended.
/// Here are a list of scenarios that will require the breakpoint
/// to be removed & then re-added:
/// - bpt_t::size is modified
/// - bpt_t::type is modified
/// - bpt_t::flags's BPT_ENABLED is modified
/// - bpt_t::flags's BPT_LOWCND is changed
/// - bpt_t::flags's BPT_LOWCND remains set, but cndbody changed
inline bool idaapi update_bpt(const bpt_t *bpt) { return callui(ui_dbg_update_bpt, bpt).cnd; }
/// Find a breakpoint by location.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param bptloc Breakpoint location
/// \param bpt bpt is filled if the breakpoint was found
inline bool idaapi find_bpt(const bpt_location_t &bptloc, bpt_t *bpt) { return callui(ui_dbg_find_bpt, &bptloc, bpt).cnd; }
/// Move breakpoint(s) from one location to another
/// \param movinfo what bpts to move and where to
/// \param codes vector of return codes, if detailed error info is required
/// \param del_hindering_bpts should delete hindering breakpoints?
/// \return number of moved bpts
inline int idaapi change_bptlocs(
const movbpt_infos_t &movinfo,
movbpt_codes_t *codes = NULL,
bool del_hindering_bpts = true)
{
return callui(ui_dbg_change_bptlocs, &movinfo, codes, del_hindering_bpts).i;
}
/// \name enable/disable breakpoints
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// Enable or disable an existing breakpoint.
/// A disabled breakpoint isn't available anymore in the process.
//@{
inline bool idaapi enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_enable_oldbpt, ea, enable).cnd; }
inline bool idaapi enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_enable_bpt, &bptloc, enable).cnd; }
inline bool disable_bpt(ea_t ea) { return enable_bpt(ea, false); }
inline bool disable_bpt(const bpt_location_t &bptloc) { return enable_bpt(bptloc, false); }
inline bool idaapi request_enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_request_enable_oldbpt, ea, enable).cnd; }
inline bool idaapi request_enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_request_enable_bpt, &bptloc, enable).cnd; }
inline bool request_disable_bpt(ea_t ea) { return request_enable_bpt(ea, false); }
inline bool request_disable_bpt(const bpt_location_t &bptloc) { return request_enable_bpt(bptloc, false); }
//@}
/// Check the breakpoint at the specified address.
/// \return one of \ref BPTCK_
inline int idaapi check_bpt(ea_t ea) { return callui(ui_dbg_check_bpt, ea).i; }
#endif // __UI__
/// \defgroup BPTCK_ Breakpoint status codes
/// Return values for check_bpt()
//@{
#define BPTCK_NONE -1 ///< breakpoint does not exist
#define BPTCK_NO 0 ///< breakpoint is disabled
#define BPTCK_YES 1 ///< breakpoint is enabled
#define BPTCK_ACT 2 ///< breakpoint is active (written to the process)
//@}
#ifndef SWIG
/// Visit all breakpoints.
/// To use this class, derive your own class from it and call for_all_bpts().
/// It is forbidden to add/del bpts from the visit_bpt() function.
/// If bpts are nevertheless modified, the enumeration should be stopped
struct bpt_visitor_t
{
int _for_all_bpts(int bvflags); ///< do not use this function.
range_t range; ///< if specified, restricts the address range
const char *name; ///< if specified, restricts bpts to the ones that match the given name
bpt_visitor_t(void) : range(0, BADADDR), name(NULL) {}
/// Defines action taken when breakpoint is visited
virtual int idaapi visit_bpt(const bpt_t *bpt) = 0;
int idaapi for_all_bpts(int bvflags)
{
return callui(ui_dbg_for_all_bpts, this, bvflags).i;
}
};
/// \defgroup BVF_ Breakpoint visitor flags
/// Passed as 'bvflags' parameter to bpt_visitor_t::_for_all_bpts()
/// \note it is forbidden to modify bpt states from the bpt_visitor_t::visit_bpt()
/// function if #BVF_STATE is not #BVFS_ANY
//@{
#define BVF_ABS 0x0001 ///< include absolute bpts
#define BVF_REL 0x0002 ///< include relative bpts
#define BVF_SYM 0x0004 ///< include symbolic bpts
#define BVF_SRC 0x0008 ///< include source bpts
#define BVF_ALL 0x000F ///< include all bpt location types
#define BVF_STATE 0x0030 ///< bpt state mask
#define BVFS_ANY 0x0000 ///< any state
#define BVFS_INPROC 0x0010 ///< written to process memory
#define BVFS_PENDING 0x0020 ///< pending
#define BVFS_DISABLED 0x0030 ///< disabled.
//@}
#endif // SWIG
//@} dbg_funcs_bpts
#ifndef __UI__
/// \defgroup dbg_funcs_tracing Tracing
/// \ingroup dbg_funcs
///
/// Trace instructions/functions/basic blocks
//--------------------------------------------------------------------
// T R A C I N G B U F F E R
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_trcbuf Tracing buffer
/// \ingroup dbg_funcs_tracing
///
/// Work with debugger trace buffer.
/// IDA memorizes various types of trace events in a circular buffer:
/// instruction tracing, function call and return, breakpoint access ...
//@{
/// Specify the new size of the circular buffer.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param size if 0, buffer isn't circular and events are never removed.
/// If the new size is smaller than the existing number of trace events,
/// a corresponding number of trace events are removed.
/// \note If you specify 0, all available memory can be quickly used !!!
inline bool idaapi set_trace_size(int size) { return callui(ui_dbg_set_trace_size, size).cnd; }
/// Clear all events in the trace buffer.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
inline void idaapi clear_trace(void) { callui(ui_dbg_clear_trace); }
/// Post a clear_trace() request
inline void idaapi request_clear_trace(void) { callui(ui_dbg_request_clear_trace); }
//@} dbg_funcs_trcbuf
//--------------------------------------------------------------------
// S T E P T R A C I N G
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_strace Step tracing
/// \ingroup dbg_funcs_tracing
///
/// Plugins can use these functions to implement a custom tracing engine.
/// When enabled, IDA uses single-stepping feature of the debugger
/// and generates a dbg_trace notification after each step in the current thread.
/// Tracing buffer is not maintained in this mode (you need to use one of the
/// higher level tracing types for it)
//@{
/// Get current state of step tracing.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_step_trace_enabled(void) { return callui(ui_dbg_is_step_trace_enabled).cnd; }
/// \name Enable/Disable step tracing
/// Enable or disable the step tracing
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
/// \param enable
/// - 1 : enable step tracing
/// - 0 : disable step tracing
/// - -1 : temporarily disable step tracing
/// (trace-over breakpoints are conserved:
/// these could re-enable step tracing later)
//@{
inline bool idaapi enable_step_trace(int enable = 1) { return callui(ui_dbg_enable_step_trace, enable).cnd; }
inline bool disable_step_trace(void) { return enable_step_trace(0); }
inline bool idaapi request_enable_step_trace(int enable = 1) { return callui(ui_dbg_request_enable_step_trace, enable).cnd; }
inline bool request_disable_step_trace(void) { return request_enable_step_trace(false); }
//@}
#endif // __UI__
/// \defgroup ST_ Step trace options
/// Flags returned by get_step_trace_options()
//@{
#define ST_OVER_DEBUG_SEG 0x01 ///< step tracing will be disabled when IP is in a debugger segment
#define ST_OVER_LIB_FUNC 0x02 ///< step tracing will be disabled when IP is in a library function
#define ST_ALREADY_LOGGED 0x04 ///< step tracing will be disabled when IP is already logged
#define ST_SKIP_LOOPS 0x08 ///< step tracing will try to skip loops already recorded
#define ST_DIFFERENTIAL 0x10 ///< tracing: log only new instructions (not previously logged)
/// mask of available options, to ensure compatibility with newer IDA versions
#define ST_OPTIONS_MASK (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC|ST_ALREADY_LOGGED|ST_SKIP_LOOPS|ST_DIFFERENTIAL)
#define ST_OPTIONS_DEFAULT (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC)
//@}
/// specific options for instruction tracing (see set_insn_trace_options())
#define IT_LOG_SAME_IP 0x01 ///< instruction tracing will log new instructions even when IP doesn't change
/// specific options for function tracing (see set_func_trace_options())
#define FT_LOG_RET 0x01 ///< function tracing will log returning instructions
/// specific options for basic block tracing (see set_bblk_trace_options())
#define BT_LOG_INSTS 0x01 ///< log all instructions in the current basic block
#ifndef __UI__
/// Get current step tracing options.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return \ref ST_
inline int idaapi get_step_trace_options(void) { return callui(ui_dbg_get_step_trace_options).i; }
/// Modify step tracing options.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
inline void idaapi set_step_trace_options(int options) { callui(ui_dbg_set_step_trace_options, options); }
/// Post a set_step_trace_options() request
inline void idaapi request_set_step_trace_options(int options) { callui(ui_dbg_request_set_step_trace_options, options); }
//@} dbg_funcs_strace
//--------------------------------------------------------------------
// I N S T R U C T I O N S T R A C I N G
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_trcins Instruction tracing
/// \ingroup dbg_funcs_tracing
///
/// When instruction tracing is active, each executed instruction is stored
/// in the tracing buffer.
/// Internally, IDA uses step tracing to record register values after the
/// execution of the instruction.
//@{
/// Get current state of instruction tracing.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_insn_trace_enabled(void) { return callui(ui_dbg_is_insn_trace_enabled).cnd; }
/// \name Enable/Disable instruction tracing
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
//@{
inline bool idaapi enable_insn_trace(bool enable = true) { return callui(ui_dbg_enable_insn_trace, enable).cnd; }
inline bool disable_insn_trace(void) { return enable_insn_trace(false); }
inline bool idaapi request_enable_insn_trace(bool enable = true) { return callui(ui_dbg_request_enable_insn_trace, enable).cnd; }
inline bool request_disable_insn_trace(void) { return request_enable_insn_trace(false); }
//@}
/// Get current instruction tracing options.
/// Also see #IT_LOG_SAME_IP
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_insn_trace_options(void) { return callui(ui_dbg_get_insn_trace_options).i; }
/// Modify instruction tracing options.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
inline void idaapi set_insn_trace_options(int options) { callui(ui_dbg_set_insn_trace_options, options); }
/// Post a set_insn_trace_options() request
inline void idaapi request_set_insn_trace_options(int options) { callui(ui_dbg_request_set_insn_trace_options, options); }
//@} dbg_funcs_trcins
//--------------------------------------------------------------------
// F U N C T I O N S T R A C I N G
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_trcfunc Functions tracing
/// \ingroup dbg_funcs_tracing
///
/// Each call to a function or return from a function is stored
/// in the tracing buffer.
//@{
/// Get current state of functions tracing.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline bool idaapi is_func_trace_enabled(void) { return callui(ui_dbg_is_func_trace_enabled).cnd; }
/// \name Enable/Disable functions tracing
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
//@{
inline bool idaapi enable_func_trace(bool enable = true) { return callui(ui_dbg_enable_func_trace, enable).cnd; }
inline bool disable_func_trace(void) { return enable_func_trace(false); }
inline bool idaapi request_enable_func_trace(bool enable = true) { return callui(ui_dbg_request_enable_func_trace, enable).cnd; }
inline bool request_disable_func_trace(void) { return request_enable_func_trace(false); }
//@}
/// Get current function tracing options.
/// Also see #FT_LOG_RET
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_func_trace_options(void) { return callui(ui_dbg_get_func_trace_options).i; }
/// Modify function tracing options.
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
inline void idaapi set_func_trace_options(int options) { callui(ui_dbg_set_func_trace_options, options); }
/// Post a set_func_trace_options() request
inline void idaapi request_set_func_trace_options(int options) { callui(ui_dbg_request_set_func_trace_options, options); }
//@} dbg_funcs_trcfunc
//--------------------------------------------------------------------
// B A S I C B L O C K T R A C I N G
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_trcbb Basic block tracing
/// \ingroup dbg_funcs_tracing
//@{
// Modify basic block tracing options.
// Type: Synchronous function - available as Request
// Notification: none (synchronous function)
/// \name Enable/Disable basic blocks tracing
/// \sq{Type, Synchronous function - available as request,
/// Notification, none (synchronous function)}
//@{
inline bool idaapi enable_bblk_trace(bool enable = true) { return callui(ui_dbg_enable_bblk_trace, enable).cnd; }
inline bool disable_bblk_trace(void) { return enable_bblk_trace(false); }
inline bool idaapi request_enable_bblk_trace(bool enable = true) { return callui(ui_dbg_request_enable_bblk_trace, enable).cnd; }
inline bool request_disable_bblk_trace(void) { return request_enable_bblk_trace(false); }
inline bool idaapi is_bblk_trace_enabled(void) { return callui(ui_dbg_is_bblk_trace_enabled).cnd; }
//@}
/// Get current basic block tracing options.
/// Also see #BT_LOG_INSTS
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_bblk_trace_options(void) { return callui(ui_dbg_get_bblk_trace_options).i; }
/// Modify basic block tracing options (see #BT_LOG_INSTS)
inline void idaapi set_bblk_trace_options(int options) { callui(ui_dbg_set_bblk_trace_options, options); }
/// Post a set_bblk_trace_options() request
inline void idaapi request_set_bblk_trace_options(int options) { callui(ui_dbg_request_set_bblk_trace_options, options); }
//@} dbg_funcs_trcbb
#endif // __UI__
//--------------------------------------------------------------------
// T R A C I N G E V E N T S
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_trcev Tracing events
/// \ingroup dbg_funcs_tracing
//@{
/// Trace event types
enum tev_type_t
{
tev_none = 0, ///< no event
tev_insn, ///< an instruction trace
tev_call, ///< a function call trace
tev_ret, ///< a function return trace
tev_bpt, ///< write, read/write, execution trace
tev_mem, ///< memory layout changed
tev_event, ///< debug event occurred
tev_max, ///< first unused event type
};
typedef qvector<debug_event_t> dbgevt_vec_t; ///< vector of debug events
/// Common information for all trace events
struct tev_info_t
{
tev_type_t type; ///< trace event type
thid_t tid; ///< thread where the event was recorded
ea_t ea; ///< address where the event occurred
};
typedef qvector<tev_info_t> tevinfo_vec_t; ///< vector of trace event info objects
/// Required typedef for get_insn_tev_reg_mem()
struct memreg_info_t
{
ea_t ea;
bytevec_t bytes;
};
DECLARE_TYPE_AS_MOVABLE(memreg_info_t);
typedef qvector<memreg_info_t> memreg_infos_t;
#ifndef __UI__
/// Get number of trace events available in trace buffer.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline int idaapi get_tev_qty(void) { return callui(ui_dbg_get_tev_qty).i; }
/// Get main information about a trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param[out] tev_info result
/// \return success
inline bool idaapi get_tev_info(int n, tev_info_t *tev_info) { return callui(ui_dbg_get_tev_info, n, tev_info).cnd; }
/// Read a register value from an instruction trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param regname name of desired register
/// \param[out] regval result
/// \return false if not an instruction event.
/// \note This is the value of the register before the execution of
/// the instruction.
inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_val, n, regname, regval).cnd; }
inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_val_i, n, regname, ival).cnd; }
/// Read the memory pointed by register values from an instruction trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param[out] memmap result
/// \return false if not an instruction event or no memory is available
inline bool idaapi get_insn_tev_reg_mem(int n, memreg_infos_t *memmap) { return callui(ui_dbg_get_insn_tev_reg_mem, n, memmap).cnd; }
/// Read the resulting register value from an instruction trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param regname name of desired register
/// \param[out] regval result
/// \return false if not an instruction trace event or register wasn't modified.
inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_result, n, regname, regval).cnd; }
inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_result_i, n, regname, ival).cnd; }
/// Get the called function from a function call trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \return #BADADDR if not a function call event.
inline ea_t idaapi get_call_tev_callee(int n) { ea_t ea; callui(ui_dbg_get_call_tev_callee, n, &ea); return ea; }
/// Get the return address from a function return trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \return #BADADDR if not a function return event.
inline ea_t idaapi get_ret_tev_return(int n) { ea_t ea; callui(ui_dbg_get_ret_tev_return, n, &ea); return ea; }
/// Get the address associated to a read, read/write or execution trace event.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \return #BADADDR if not a read, read/write or execution trace event.
/// \note Usually, a breakpoint is associated with a read, read/write or execution
/// trace event. However, the returned address could be any address in the
/// range of this breakpoint.
/// If the breakpoint was deleted after the trace event, the address no longer
/// corresponds to a valid breakpoint.
inline ea_t idaapi get_bpt_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_bpt_tev_ea, n, &ea); return ea; }
/// Get the memory layout, if any, for the specified tev object.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param[out] mi result
/// \return false if the tev_t object is not of type ::tev_mem, true otherwise,
/// with the new memory layout in "mi".
inline bool idaapi get_tev_memory_info(int n, meminfo_vec_t *mi) { return callui(ui_dbg_get_tev_memory_info, n, mi).cnd; }
/// Get the corresponding debug event, if any, for the specified tev object.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \param n number of trace event, is in range 0..get_tev_qty()-1.
/// 0 represents the latest added trace event.
/// \param[out] d result
/// \return false if the tev_t object doesn't have any associated debug
/// event, true otherwise, with the debug event in "d".
inline bool idaapi get_tev_event(int n, debug_event_t *d) { return callui(ui_dbg_get_tev_event, n, d).cnd; }
/// Get the base address of the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return the base address of the currently loaded trace
inline ea_t idaapi get_trace_base_address(void) { ea_t ea; callui(ui_dbg_get_trace_base_address, &ea); return ea; }
/// Set the base address of the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi set_trace_base_address(ea_t ea) { callui(ui_dbg_set_trace_base_address, ea); }
/// Add a thread to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_add_thread(thid_t tid) { callui(ui_dbg_add_thread, tid); }
/// Delete a thread from the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_del_thread(thid_t tid) { callui(ui_dbg_del_thread, tid); }
/// Add a new trace element to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_add_tev(tev_type_t type, thid_t tid, ea_t address) { callui(ui_dbg_add_tev, type, tid, address); }
#endif // __UI__
/// Structure used for dbg_add_many_tevs()
struct tev_reg_value_t
{
regval_t value;
int reg_idx;
tev_reg_value_t(int _reg_idx = -1, uint64 _value = uint64(-1)) : reg_idx(_reg_idx)
{
value._set_int(_value);
}
};
DECLARE_TYPE_AS_MOVABLE(tev_reg_value_t);
typedef qvector<tev_reg_value_t> tev_reg_values_t; ///< vector of trace event reg values
/// Structure used for dbg_add_many_tevs()
struct tev_info_reg_t
{
tev_info_t info;
tev_reg_values_t registers;
};
DECLARE_TYPE_AS_MOVABLE(tev_info_reg_t);
typedef qvector<tev_info_reg_t> tevinforeg_vec_t; ///< vector of trace elements
/// Se dbg_add_insn_tev()
enum save_reg_values_t
{
SAVE_ALL_VALUES = 0,
SAVE_DIFF,
SAVE_NONE
};
#ifndef __UI__
/// Add many new trace elements to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return false if the operation failed for any ::tev_info_t object
inline bool idaapi dbg_add_many_tevs(tevinforeg_vec_t *new_tevs) { return callui(ui_dbg_add_many_tevs, new_tevs).cnd; }
/// Add a new instruction trace element to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return false if the operation failed, true otherwise
inline bool idaapi dbg_add_insn_tev(thid_t tid, ea_t ea, save_reg_values_t save = SAVE_DIFF) { return callui(ui_dbg_add_insn_tev, tid, ea, save).cnd; }
/// Add a new breakpoint trace element to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
/// \return false if the operation failed, true otherwise
inline bool idaapi dbg_add_bpt_tev(thid_t tid, ea_t ea, ea_t bp) { return callui(ui_dbg_add_bpt_tev, tid, ea, bp).cnd; }
/// Add a new call trace element to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_add_call_tev(thid_t tid, ea_t caller, ea_t callee) { callui(ui_dbg_add_call_tev, tid, caller, callee); }
/// Add a new return trace element to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_add_ret_tev(thid_t tid, ea_t ret_insn, ea_t return_to) { callui(ui_dbg_add_ret_tev, tid, ret_insn, return_to); }
/// Add a new debug event to the current trace.
/// \sq{Type, Synchronous function,
/// Notification, none (synchronous function)}
inline void idaapi dbg_add_debug_event(debug_event_t *event) { callui(ui_dbg_add_debug_event, event); }
//@} dbg_funcs_trcev
//---------------------------------------------------------------------------
// Trace management functions
//---------------------------------------------------------------------------
/// \defgroup dbg_funcs_trcm Trace management functions
/// \ingroup dbg_funcs_tracing
//@{
/// Load a recorded trace file in the trace window.
/// If the call succeeds and 'buf' is not null, the description of the
/// trace stored in the binary trace file will be returned in 'buf'
inline bool idaapi load_trace_file(qstring *buf, const char *filename) { return callui(ui_dbg_load_trace_file, buf, filename).cnd; }
/// Save the current trace in the specified file
inline bool idaapi save_trace_file(const char *filename, const char *description) { return callui(ui_dbg_save_trace_file, filename, description).cnd; }
/// Is the specified file a valid trace file for the current database?
inline bool idaapi is_valid_trace_file(const char *filename) { return callui(ui_dbg_is_valid_trace_file, filename).cnd; }
/// Change the description of the specified trace file
inline bool idaapi set_trace_file_desc(const char *filename, const char *description) { return callui(ui_dbg_set_trace_file_desc, filename, description).cnd; }
/// Get the file header of the specified trace file
inline bool idaapi get_trace_file_desc(qstring *buf, const char *filename) { return callui(ui_dbg_get_trace_file_desc, buf, filename).cnd; }
/// Show the choose trace dialog
inline bool idaapi choose_trace_file(qstring *buf) { return callui(ui_dbg_choose_trace_file, buf).cnd; }
/// Show difference between the current trace and the one from 'filename'
inline bool idaapi diff_trace_file(const char *NONNULL filename) { return callui(ui_dbg_diff_trace_file, filename).cnd; }
/// Show the trace callgraph
inline bool idaapi graph_trace(void) { return callui(ui_dbg_graph_trace).cnd; }
/// Set highlight trace parameters.
inline void idaapi set_highlight_trace_options(
bool hilight,
bgcolor_t color,
bgcolor_t diff)
{
callui(ui_dbg_set_highlight_trace_options, hilight, color, diff);
}
/// Set platform name of current trace
inline void idaapi set_trace_platform(const char *platform) { callui(ui_dbg_set_trace_platform, platform); }
/// Get platform name of current trace
inline const char *idaapi get_trace_platform() { return callui(ui_dbg_get_trace_platform).cptr; }
/// Set dynamic register set of current trace
inline void idaapi set_trace_dynamic_register_set(dynamic_register_set_t &idaregs) { callui(ui_dbg_set_trace_dynamic_register_set, &idaregs); }
/// Get dynamic register set of current trace
inline void idaapi get_trace_dynamic_register_set(dynamic_register_set_t *idaregs) { callui(ui_dbg_get_trace_dynamic_register_set, idaregs); }
//@} dbg_funcs_trcm
#endif // __UI__
//---------------------------------------------------------------------------
// High level functions (usable from scripts)
//--------------------------------------------------------------------
/// \defgroup dbg_funcs_high High level functions
/// \ingroup dbg_funcs
///
/// These functions can be used from scripts
//@{
/// Wait for the next debugger event.
/// See also get_process_state() to get info about the current state
/// of the debugged application
/// Debugger event codes
enum dbg_event_code_t
{
DEC_NOTASK = -2, ///< process does not exist
DEC_ERROR = -1, ///< error
DEC_TIMEOUT = 0, ///< timeout
};
/// \defgroup WFNE_ Wait for debugger event flags
/// Passed as 'wfne' parameter to wait_for_next_event()
//@{
#define WFNE_ANY 0x0001 ///< return the first event (even if it doesn't suspend the process)
#define WFNE_SUSP 0x0002 ///< wait until the process gets suspended
#define WFNE_SILENT 0x0004 ///< 1: be slient, 0:display modal boxes if necessary
#define WFNE_CONT 0x0008 ///< continue from the suspended state
#define WFNE_NOWAIT 0x0010 ///< do not wait for any event, immediately return ::DEC_TIMEOUT
///< (to be used with #WFNE_CONT)
#define WFNE_USEC 0x0020 ///< timeout is specified in microseconds
///< (minimum non-zero timeout is 40000us)
//@}
/// \defgroup DOPT_ Debugger options
/// Passed as 'options' parameter to set_debugger_options()
//@{
#define DOPT_SEGM_MSGS 0x00000001 ///< log debugger segments modifications
#define DOPT_START_BPT 0x00000002 ///< break on process start
#define DOPT_THREAD_MSGS 0x00000004 ///< log thread starts/exits
#define DOPT_THREAD_BPT 0x00000008 ///< break on thread start/exit
#define DOPT_BPT_MSGS 0x00000010 ///< log breakpoints
//#define DOPT_BINS_BPT 0x00000020 // break on breakpoint instruction
#define DOPT_LIB_MSGS 0x00000040 ///< log library loads/unloads
#define DOPT_LIB_BPT 0x00000080 ///< break on library load/unload
#define DOPT_INFO_MSGS 0x00000100 ///< log debugging info events
#define DOPT_INFO_BPT 0x00000200 ///< break on debugging information
#define DOPT_REAL_MEMORY 0x00000400 ///< do not hide breakpoint instructions
#define DOPT_REDO_STACK 0x00000800 ///< reconstruct the stack
#define DOPT_ENTRY_BPT 0x00001000 ///< break on program entry point
#define DOPT_EXCDLG 0x00006000 ///< exception dialogs:
# define EXCDLG_NEVER 0x00000000 ///< never display exception dialogs
# define EXCDLG_UNKNOWN 0x00002000 ///< display for unknown exceptions
# define EXCDLG_ALWAYS 0x00006000 ///< always display
#define DOPT_LOAD_DINFO 0x00008000 ///< automatically load debug files (pdb)
#define DOPT_END_BPT 0x00010000 ///< evaluate event condition on process end
#define DOPT_TEMP_HWBPT 0x00020000 ///< when possible use hardware bpts for temp bpts
//@}
#ifndef __UI__
/// Wait for the next event.
///
/// This function (optionally) resumes the process execution,
/// and waits for a debugger event until a possible timeout occurs.
///
/// \param wfne combination of \ref WFNE_ constants
/// \param timeout number of seconds to wait, -1-infinity
/// \return either an event_id_t (if > 0), or a dbg_event_code_t (if <= 0)
inline dbg_event_code_t idaapi wait_for_next_event(int wfne, int timeout) { return dbg_event_code_t(callui(ui_dbg_wait_for_next_event, wfne, timeout).i); }
/// Get the current debugger event
inline const debug_event_t *idaapi get_debug_event(void) { return (const debug_event_t *)callui(ui_dbg_get_debug_event).vptr; }
/// Set debugger options.
/// Replaces debugger options with the specification combination \ref DOPT_
/// \return the old debugger options
inline uint idaapi set_debugger_options(uint options) { return callui(ui_dbg_set_debugger_options, options).i; }
/// Set remote debugging options.
/// Should be used before starting the debugger.
/// \param host If empty, IDA will use local debugger.
/// If NULL, the host will not be set.
/// \param pass If NULL, the password will not be set
/// \param port If -1, the default port number will be used
inline void idaapi set_remote_debugger(const char *host, const char *pass, int port=-1) { callui(ui_dbg_set_remote_debugger, host, pass, port); }
/// Get process options.
/// Any of the arguments may be NULL
inline void idaapi get_process_options(
qstring *path,
qstring *args,
qstring *sdir,
qstring *host,
qstring *pass,
int *port)
{
callui(ui_dbg_get_process_options, path, args, sdir, host, pass, port);
}
/// Set process options.
/// Any of the arguments may be NULL, which means 'do not modify'
inline void idaapi set_process_options(
const char *path,
const char *args,
const char *sdir,
const char *host,
const char *pass,
int port)
{
callui(ui_dbg_set_process_options, path, args, sdir, host, pass, port);
}
/// Retrieve the exception information.
/// You may freely modify the returned vector and add/edit/delete exceptions
/// You must call store_exceptions() after any modifications
/// Note: exceptions with code zero, multiple exception codes or names are prohibited
inline excvec_t *idaapi retrieve_exceptions(void) { return (excvec_t *)callui(ui_dbg_retrieve_exceptions).vptr; }
/// Update the exception information stored in the debugger module by
/// invoking its dbg->set_exception_info callback
inline bool idaapi store_exceptions(void) { return callui(ui_dbg_store_exceptions).cnd; }
/// Convenience function: define new exception code.
/// \param code exception code (cannot be 0)
/// \param name exception name (cannot be empty or NULL)
/// \param desc exception description (maybe NULL)
/// \param flags combination of \ref EXC_
/// \return failure message or NULL.
/// You must call store_exceptions() if this function succeeds
inline const char *idaapi define_exception(uint code, const char *name, const char *desc, int flags) { return callui(ui_dbg_define_exception, code, name, desc, flags).cptr; }
#endif // __UI__
//--------------------------------------------------------------------
/// Is set_dbg_options() present in ::debugger_t?
inline THREAD_SAFE bool have_set_options(const debugger_t *_dbg)
{
return _dbg != NULL && _dbg->set_dbg_options != NULL;
}
//--------------------------------------------------------------------
/// Convenience function to set debugger specific options. It checks if the debugger
/// is present and the function is present and calls it.
inline const char *idaapi set_dbg_options(
debugger_t *_dbg,
const char *keyword,
int pri,
int value_type,
const void *value)
{
const char *code = IDPOPT_BADKEY;
if ( have_set_options(_dbg) )
code = _dbg->set_dbg_options(keyword, pri, value_type, value);
return code;
}
inline const char *idaapi set_dbg_default_options(
debugger_t *_dbg,
const char *keyword,
int value_type,
const void *value)
{
return set_dbg_options(_dbg, keyword, IDPOPT_PRI_DEFAULT, value_type, value);
}
inline const char *idaapi set_int_dbg_options(
debugger_t *_dbg,
const char *keyword,
int32 value)
{
sval_t sv = value;
return set_dbg_default_options(_dbg, keyword, IDPOPT_NUM, &sv);
}
#ifndef __KERNEL__
/// Set options for ::dbg
inline const char *idaapi set_dbg_options(
const char *keyword,
int pri,
int value_type,
const void *value)
{
return set_dbg_options(dbg, keyword, pri, value_type, value);
}
/// Set ::dbg options with #IDPOPT_PRI_DEFAULT
inline const char *idaapi set_dbg_default_options(
const char *keyword,
int value_type,
const void *value)
{
return set_dbg_options(keyword, IDPOPT_PRI_DEFAULT, value_type, value);
}
/// Set an integer value option for ::dbg
inline const char *idaapi set_int_dbg_options(
const char *keyword,
int32 value)
{
sval_t sv = value;
return set_dbg_default_options(keyword, IDPOPT_NUM, &sv);
}
#endif // __KERNEL__
//@} dbg_funcs_high
//---------------------------------------------------------------------------
// S O U R C E I N F O R M A T I O N P R O V I D E R S
//---------------------------------------------------------------------------
/// \defgroup dbg_funcs_srcinfo Source information providers
/// \ingroup dbg_funcs
///
/// These providers supply information about the source files and lines
/// to the source level debugger.
///
/// \note objects that inherit from ::qrefcnt_obj_t must be freed
/// using the release() method. do not use the 'delete' operator!
/// See description for qrefcnt_obj_t::release()
///
/// Currently this interface is not frozen and may change.
/// We will freeze it once we settle things down.
//@{
class srcinfo_provider_t;
class idc_value_t;
class rangeset_t;
class source_item_t;
class argloc_t;
/// Maintain a reference count for source items
typedef qrefcnt_t<source_item_t> source_item_ptr;
/// Iterator for source items
typedef qiterator<source_item_ptr> _source_item_iterator;
/// Maintain a reference count for source item iterators
typedef qrefcnt_t<_source_item_iterator> source_item_iterator;
/// Vector of source items
typedef qvector<source_item_ptr> source_items_t;
//--------------------------------------------------------------------------
/// Execution context. Currently not defined in detail. Will probably
/// hold information about the execution context, like:
/// - thread id
/// - current register values
/// - stack frame address
class eval_ctx_t
{
int size_cb;
public:
eval_ctx_t(ea_t _ea) : size_cb(sizeof(*this)), ea(_ea) {}
ea_t ea;
};
#ifndef __UI__
class TWidget;
#endif
//--------------------------------------------------------------------------
/// Describes a source file
class source_file_t : public qrefcnt_obj_t
{
public:
/// Call this function to free source_file_t
virtual void idaapi release() override = 0;
/// Get source info provider.
/// There is no need to free or release it after using
virtual srcinfo_provider_t *idaapi get_provider(void) const = 0;
/// Get path to the source file (or a symbolic name).
/// \param[out] errbuf pointer to buffer for the error message
virtual const char *idaapi get_path(qstring *errbuf) = 0;
/// Open window with source code (optional function).
/// \param[out] strvec pointer to source text. the text should not be destroyed until the form is closed
/// \param[out] pview pointer to view that displays the source text (subview of TWidget)
/// \param lnnum,colnum cursor coordinates
virtual TWidget *open_srcview(strvec_t **strvec, TWidget **pview, int lnnum, int colnum) = 0;
/// Read entire file (colored lines).
/// \param[out] buf pointer to output buffer
/// \param[out] errbuf pointer to buffer for the error message
virtual bool idaapi read_file(strvec_t *buf, qstring *errbuf) = 0;
};
/// Maintain a reference count for source file objects
typedef qrefcnt_t<source_file_t> source_file_ptr;
/// Iterator for source files
typedef qiterator<source_file_ptr> _source_file_iterator;
/// Maintain a reference count for source file iterators
typedef qrefcnt_t<_source_file_iterator> source_file_iterator;
//--------------------------------------------------------------------------
/// Kinds of source items.
/// Source items are organized into trees. Each tree starts with a MODULE.
/// Each MODULE consists of FUNC and STTVAR global items.
/// Each FUNC consists of STMTs (statements).
/// Each STMT contains some EXPRs (expressions).
enum src_item_kind_t
{
SRCIT_NONE, ///< unknown
SRCIT_MODULE, ///< module
SRCIT_FUNC, ///< function
SRCIT_STMT, ///< a statement (if/while/for...)
SRCIT_EXPR, ///< an expression (a+b*c)
SRCIT_STTVAR, ///< static variable/code
SRCIT_LOCVAR ///< a stack, register, or register-relative local variable or parameter
};
//--------------------------------------------------------------------------
/// Describes a subdivision of source information
class source_item_t : public qrefcnt_obj_t
{
public:
/// Call this function to free source_item_t
virtual void idaapi release() override = 0;
/// Get source files of the item
virtual source_file_iterator idaapi get_source_files() = 0;
/// Get name of the item
virtual bool idaapi get_name(qstring *buf) const = 0;
/// Get line number of the item (1-based)
virtual int idaapi get_lnnum() const = 0;
/// Get ending line number (1-based.)
/// The returned line number is the next
/// line after the expression
virtual int idaapi get_end_lnnum() const = 0;
/// Get column number of the item.
/// If unknown, return -1
virtual int idaapi get_colnum() const = 0;
/// Get ending column number.
/// The returned column number is the next
/// column after the expression.
/// If unknown, return -1
virtual int idaapi get_end_colnum() const = 0;
/// Get starting address of the item
virtual ea_t idaapi get_ea() const = 0;
/// Get size of the item in bytes.
/// If the item is fragmented, return size
/// of the main fragment.
/// if unknown, return 0.
/// On error, return (asize_t) -1.
virtual asize_t idaapi get_size() const = 0;
/// Get item boundaries as a set of ranges.
/// This function will be used to determine what breakpoints to set for
/// stepping into/stepping over the item.
virtual bool idaapi get_item_bounds(rangeset_t *set) const = 0;
/// Get parent of the item.
/// \param max_kind maximal source item kind we are interested in.
/// for example, if max_kinds==#SRCIT_STMT, we are not interested
/// in expressions, only in the enclosing statement or function
virtual source_item_ptr idaapi get_parent(src_item_kind_t max_kind) const = 0;
/// Create an iterator to enumerate all children of the item
virtual source_item_iterator idaapi create_children_iterator() = 0;
/// Calculate a string to display as a hint.
/// \param hint output buffer for the hint (may by multiline & with colors)
/// \param ctx execution context. NULL means missing context.
/// \param nlines number of important lines in the hint
virtual bool idaapi get_hint(
qstring *hint,
const eval_ctx_t *ctx,
int *nlines) const = 0;
/// Evaluate item value (meaningful only for expression items).
/// \param ctx execution context. NULL means missing context.
/// \param res buffer for the result (or exception if evaluation failed)
/// \param errbuf buffer for the error message
virtual bool idaapi evaluate(
const eval_ctx_t *ctx,
idc_value_t *res,
qstring *errbuf) const = 0;
/// Do these two items have the same source?.
/// \retval false the source of the underlying data
/// differs between the two items.
/// \retval true when either the source of the underlying
/// data is the same for the two items, or
/// when such information is not available.
///
/// E.g., A DWARF implementation of source_item_t will
/// return true if the two items are backed by DIEs
/// that have the same file offset.
virtual bool idaapi equals(const source_item_t *other) const = 0;
/// \name Getters (for modification)
/// The following functions can be used to extract the item information
/// in order to modify it. For example, if the user wants to modify a variable
/// we will find what exactly needs to be modified.
//@{
/// Get item kind
virtual src_item_kind_t idaapi get_item_kind(const eval_ctx_t * /*ctx*/) const newapi { return SRCIT_NONE; }
/// Does this source item represent a statement?
bool is_stmt(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STMT; }
/// Does this source item represent a module?
bool is_module(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_MODULE; }
/// Does this source item represent a function?
bool is_func(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_FUNC; }
/// Does this source item represent an expression?
bool is_expr(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_EXPR; }
/// Does this source item represent a stack, register, or register-relative local variable or parameter?
bool is_locvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_LOCVAR; }
/// Does this source item represent a static variable or code?
bool is_sttvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STTVAR; }
/// Get source info provider.
/// The instance shouldn't be freed or released after using
virtual srcinfo_provider_t *idaapi get_provider(void) const = 0;
/// Get the location for this source item
virtual bool idaapi get_location(argloc_t * /*out*/, const eval_ctx_t * /*ctx*/) const newapi { return false; }
/// Get expression type
virtual bool idaapi get_expr_tinfo(tinfo_t *tif) const = 0;
//@}
};
#define SRCDBG_PROV_VERSION 4
//--------------------------------------------------------------------------
/// Describes the mechanism used to retrieve source file information
class srcinfo_provider_t
{
public:
/// size of this class
size_t cb;
/// \ref SPF_
int flags;
/// \defgroup SPF_ Source info provider property bits
/// Used by srcinfo_provider_t::flags
//@{
#define SPF_DECOMPILER 0x0001 ///< is a decompiler?
#define SPF_ENABLED 0x0002 ///< enabled by the user
///< (this bit is managed by ida)
#define SPF_ACTIVE 0x0004 ///< is willing to work with the current idb
///< (this bit is managed by ida)
#define SPF_VERSION_MASK 0xFF000000 ///< Version mask, in the flags.
///< No other flag should have a bit rank > 23.
//@}
/// internal (unique) name of srcinfo provider
const char *name;
/// external (displayable) name of srcinfo provider
const char *display_name;
srcinfo_provider_t(const char *_name, const char *_display_name, int _flags=0)
: cb(sizeof(*this)), flags(_flags), name(_name), display_name(_display_name)
{
flags |= SRCDBG_PROV_VERSION << 24;
}
/// Is the source info provider a decompiler?
bool is_decompiler(void) const { return (flags & SPF_DECOMPILER) != 0; }
/// Has the provider been enabled by the user?
bool is_enabled(void) const { return (flags & SPF_ENABLED) != 0; }
/// Is the provider willing to work with the current idb?
bool is_active(void) const { return (flags & SPF_ACTIVE) != 0; }
/// See #SPF_VERSION_MASK
uint8 get_version() const { return (flags >> 24) & 0xFF; }
/// Enable or disable the provider.
/// If the provider fails to initialize, it returns false, otherwise true
virtual bool idaapi enable_provider(bool enable) = 0;
/// Configure srcinfo provider.
/// See the description of ::set_options_t
virtual const char *idaapi set_options(
const char *keyword,
int value_type,
const void *value) = 0;
/// Inform the provider that a module got loaded.
/// The provider is not required to read the module information immediately;
/// it may postpone it until really required.
virtual void idaapi add_module(const char *path, ea_t base, asize_t size) = 0;
/// Inform the provider that a module got unloaded.
virtual void idaapi del_module(ea_t base) = 0;
/// Inform the provider that we will request for information now.
/// This function must be called before calling all functions below.
/// probably it will be called when the process gets suspended.
virtual void idaapi get_ready(void) = 0;
/// Ask the provider if the source information has changed
/// and the screen should be refreshed. UI will call this function
/// periodically (when idle). if it returns a flag value other than #SPCH_NONE,
/// then the source information must be refreshed.
virtual int idaapi get_change_flags(void) = 0;
/// \defgroup SPCH_ Source info changed flags
/// Returned by srcinfo_provider_t::get_change_flags()
//@{
#define SPCH_NONE 0x0000 ///< nothing has changed
#define SPCH_FILES 0x0001 ///< source files have changed
#define SPCH_ITEMS 0x0002 ///< source items have changed
#define SPCH_LINES 0x0004 ///< source line numbers have changed
//@}
/// Locate source item by address.
/// The kernel will inquire all registered providers and use the best reply.
/// \param ea linear address
/// \param size size of the item
/// \param level the desired item level:
/// - ::SRCIT_STMT: a statement
/// - ::SRCIT_EXPR: an expression
/// - ::SRCIT_FUNC: a global code item
/// - SRCIT_xxxVAR: a global data item (the exact type is not checked)
/// \param may_decompile meaningful only for the decompiler. if set to false
/// and the function at 'ea' has not been decompiled yet, fail.
virtual source_item_iterator idaapi find_source_items(
ea_t ea,
asize_t size,
src_item_kind_t level,
bool may_decompile) = 0;
/// Locate source item by a position in a source file.
/// if colnum == 0, return the statement that starts at the specified line.
/// if lnnum == 0, return information about all lines (colnum is ignored in this case)
virtual source_item_iterator idaapi find_source_items(source_file_t *sf, int lnnum, int colnum=0) = 0;
/// Create iterators to enumerate files.
/// \param filename name of the source file to enumerate
virtual source_file_iterator idaapi create_file_iterator(const char *filename=NULL) = 0;
/// Create iterators to enumerate items
virtual source_item_iterator idaapi create_item_iterator(const source_file_t *sf) = 0;
/// Apply the debug information (types, functions, globals)
/// from the module whose path is 'path', to the IDB
virtual bool idaapi apply_module_info(const char * /*path*/) { return false; }
/// Locate a global variable by its name.
/// \param name The variable name
/// \param ea The current address
/// \return the source item, or NULL
virtual source_item_ptr idaapi find_static_item(const char *name, ea_t ea) = 0;
};
//--------------------------------------------------------------------------
/// Register a source information provider.
/// Source information providers will call this function to register themselves
/// with IDA kernel.
/// Returns false: a service provider with this name already exists.
inline bool idaapi register_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_register_provider, sp).cnd; }
/// Unregister a source information provider.
/// Returns false: no such provider.
inline bool idaapi unregister_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_unregister_provider, sp).cnd; }
#ifndef __UI__
class source_view_t;
/// Create a source code view
inline source_view_t *create_source_viewer(
TWidget **out_ccv,
TWidget *parent,
TWidget *custview,
source_file_ptr sf,
strvec_t *lines,
int lnnum,
int colnum,
int flags)
{
return (source_view_t *) callui(
ui_create_source_viewer, out_ccv, parent, custview, &sf,
lines, lnnum, colnum, flags).vptr;
}
#endif
//--------------------------------------------------------------------------
/// Get one byte of the debugged process memory.
/// \param x pointer to byte value
/// \param ea linear address
/// \return true success
/// \return false address inaccessible or debugger not running
idaman bool ida_export get_dbg_byte(uint32 *x, ea_t ea);
/// Change one byte of the debugged process memory.
/// \param ea linear address
/// \param x byte value
/// \return true if the process memory has been modified
idaman bool ida_export put_dbg_byte(ea_t ea, uint32 x);
//@} dbg_funcs_srcinfo
//--------------------------------------------------------------------------
// D E B U G G E R M E M O R Y F U N C T I O N S F O R U I
//--------------------------------------------------------------------------
/// \defgroup dbg_funcs_mem Debugger memory functions for UI
/// \ingroup dbg_funcs
///
/// Inspect debugged process memory.
//@{
/// Set the memory information source for IDA kernel.
/// This function allows the kernel to use information coming from somewhere
/// other than the database (from the debugger, for example)
/// \param dbg_get_memory_config returns current memory configuration
/// in the dynamic memory allocated by qalloc().
/// The kernel will qfree() it automatically.
/// If this argument is NULL, then the debugged
/// process memory is not used.
/// - n: number of ::range_t elements in the answer
/// \param memory_read read bytes from the debugged process memory
/// \param memory_write write bytes to the debugged process memory
/// (don't forget to call invalidate_dbgmem_contents() from it)
idaman void ida_export set_dbgmem_source(
range_t *(idaapi*dbg_get_memory_config)(int *n),
int (idaapi*memory_read) (ea_t ea, void *buffer, int size),
int (idaapi*memory_write)(ea_t ea, const void *buffer, int size));
/// Invalidate the debugged process memory configuration.
/// Call this function if the debugged process might have changed its memory
/// layout (allocated more memory, for example)
idaman void ida_export invalidate_dbgmem_config(void);
/// Invalidate the debugged process memory contents.
/// Call this function each time the process has been stopped or the process
/// memory is modified.
/// If ea == #BADADDR, then the whole memory contents will be invalidated
idaman void ida_export invalidate_dbgmem_contents(ea_t ea, asize_t size);
/// Is the debugger currently running?
idaman bool ida_export is_debugger_on(void);
/// Is the address mapped to debugger memory?
idaman bool ida_export is_debugger_memory(ea_t ea);
//@} dbg_funcs_mem
//------------------------------------------------------------------------
#ifndef __UI__ // Not for the UI
/// \defgroup dbg_funcs_conv Misc
/// \ingroup dbg_funcs
///
/// Convenience functions offered by the user interface
//@{
inline ea_t idaapi get_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_tev_ea, n, &ea); return ea; }
inline int idaapi get_tev_type(int n) { return callui(ui_dbg_get_tev_type, n).i; }
inline int idaapi get_tev_tid(int n) { return callui(ui_dbg_get_tev_tid, n).i; }
inline bool idaapi get_module_info(ea_t ea, modinfo_t *modinfo) { return callui(ui_dbg_get_module_info, ea, modinfo).cnd; }
inline void idaapi bring_debugger_to_front(void) { callui(ui_dbg_bring_to_front); }
inline bool idaapi collect_stack_trace(thid_t tid, call_stack_t *trace) { return callui(ui_dbg_collect_stack_trace, tid, trace).cnd; }
inline const char *idaapi get_debugger_event_cond(void) { return callui(ui_dbg_get_event_cond).cptr; }
inline void idaapi set_debugger_event_cond(const char *NONNULL evcond) { callui(ui_dbg_set_event_cond, evcond); }
inline bool idaapi load_debugger(const char *dbgname, bool use_remote) { return callui(ui_dbg_load_debugger, dbgname, use_remote).cnd; }
inline void idaapi get_manual_regions(meminfo_vec_t *ranges) { callui(ui_dbg_get_manual_regions, ranges); }
inline void idaapi set_manual_regions(const meminfo_vec_t *ranges) { callui(ui_dbg_set_manual_regions, ranges); }
inline void idaapi edit_manual_regions() { callui(ui_dbg_edit_manual_regions); }
inline void idaapi enable_manual_regions(bool enable) { callui(ui_dbg_enable_manual_regions, enable); }
inline int idaapi hide_all_bpts(void) { return callui(ui_dbg_hide_all_bpts).i; }
inline int idaapi handle_debug_event(const debug_event_t *ev, int rqflags) { return callui(ui_dbg_handle_debug_event, ev, rqflags).i; }
inline bool idaapi add_virt_module(const modinfo_t *mod) { return callui(ui_dbg_add_vmod, mod).cnd; }
inline bool idaapi del_virt_module(const ea_t base) { return callui(ui_dbg_del_vmod, base).cnd; }
inline int idaapi set_bptloc_string(const char *s) { return callui(ui_dbg_set_bptloc_string, s).i; }
inline const char *idaapi get_bptloc_string(int i) { return callui(ui_dbg_get_bptloc_string, i).cptr; }
inline int idaapi internal_cleanup_appcall(thid_t tid) { return callui(ui_dbg_internal_cleanup_appcall, tid).i; }
inline int idaapi internal_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value) { return callui(ui_dbg_internal_get_sreg_base, answer, tid, sreg_value).i; }
inline int idaapi internal_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { return callui(ui_dbg_internal_ioctl, fn, buf, size, poutbuf, poutsize).i; }
inline ssize_t idaapi read_dbg_memory(ea_t ea, void *buffer, size_t size) { return callui(ui_dbg_read_memory, ea, buffer, size).ssize; }
inline ssize_t idaapi write_dbg_memory(ea_t ea, const void *buffer, size_t size) { return callui(ui_dbg_write_memory, ea, buffer, size).ssize; }
inline int idaapi get_reg_vals(thid_t tid, int clsmask, regval_t *values) { return callui(ui_dbg_read_registers, tid, clsmask, values).i; }
inline int idaapi set_reg_val(thid_t tid, int regidx, const regval_t *value) { return callui(ui_dbg_write_register, tid, regidx, value).i; }
inline int idaapi get_dbg_memory_info(meminfo_vec_t *ranges) { return callui(ui_dbg_get_memory_info, ranges).i; }
inline void idaapi set_bpt_group(bpt_t &bpt, const char *grp_name) { callui(ui_dbg_set_bpt_group, &bpt, grp_name); }
inline bool idaapi set_bptloc_group(const bpt_location_t &bptloc, const char *grp_name) { return callui(ui_dbg_set_bptloc_group, &bptloc, grp_name).cnd; }
inline bool idaapi get_bpt_group(qstring *grp_name, const bpt_location_t &bptloc) { return callui(ui_dbg_get_bpt_group, grp_name, &bptloc).cnd; }
inline size_t idaapi list_bptgrps(qstrvec_t *bptgrps) { return callui(ui_dbg_list_bptgrps, bptgrps).ssize; }
inline bool idaapi rename_bptgrp(const char *old_name, const char *new_name) { return callui(ui_dbg_rename_bptgrp, old_name, new_name).cnd; }
inline bool idaapi del_bptgrp(const char *name) { return callui(ui_dbg_del_bptgrp, name).cnd; }
inline ssize_t idaapi get_grp_bpts(bpt_vec_t *bpts, const char *grp_name) { return callui(ui_dbg_get_grp_bpts, bpts, grp_name).ssize; }
inline const char *bpt_t::get_cnd_elang() const { return (const char *)(callui(ui_dbg_internal_get_elang, this).cptr); }
inline bool bpt_t::set_cnd_elang(const char *name) { return callui(ui_dbg_internal_set_elang, this, name).cnd; }
inline srcinfo_provider_t *idaapi get_srcinfo_provider(const char *name) { return (srcinfo_provider_t *)callui(ui_dbg_get_srcinfo_provider, name).vptr; }
inline bool idaapi get_global_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_global_var, prov, ea, name, out).cnd; }
inline bool idaapi get_local_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_local_var, prov, ea, name, out).cnd; }
inline bool idaapi get_local_vars(srcinfo_provider_t *prov, ea_t ea, source_items_t *out) { return callui(ui_dbg_get_local_vars, prov, ea, out).cnd; }
inline void idaapi add_path_mapping(const char *src, const char *dst) { callui(ui_dbg_add_path_mapping, src, dst); }
inline bool idaapi get_current_source_file(qstring *out) { return callui(ui_dbg_get_current_source_file, out).cnd; }
inline int idaapi get_current_source_line(void) { return callui(ui_dbg_get_current_source_line).i; }
inline bool idaapi srcdbg_step_into(void) { return callui(ui_dbg_srcdbg_step_into).cnd; }
inline bool idaapi srcdbg_request_step_into(void) { return callui(ui_dbg_srcdbg_request_step_into).cnd; }
inline bool idaapi srcdbg_step_over(void) { return callui(ui_dbg_srcdbg_step_over).cnd; }
inline bool idaapi srcdbg_request_step_over(void) { return callui(ui_dbg_srcdbg_request_step_over).cnd; }
inline bool idaapi srcdbg_step_until_ret(void) { return callui(ui_dbg_srcdbg_step_until_ret).cnd; }
inline bool idaapi srcdbg_request_step_until_ret(void) { return callui(ui_dbg_srcdbg_request_step_until_ret).cnd; }
inline drc_t idaapi dbg_bin_search(ea_t *out, ea_t start_ea, ea_t end_ea, const compiled_binpat_vec_t &data, int srch_flags, qstring *errbuf)
{ return drc_t(callui(ui_dbg_bin_search, out, start_ea, end_ea, &data, srch_flags, errbuf).i); }
//@} dbg_funcs_conv
inline bool idaapi dbg_can_query(debugger_t *_dbg)
{
// Debugger can be queried IIF it is set and either currently in
// suspended state, or can be queried while not in suspended state
return _dbg != NULL && (_dbg->may_disturb() || get_process_state() < DSTATE_NOTASK);
}
#ifndef __KERNEL__
inline bool idaapi dbg_can_query(void)
{
return dbg_can_query(dbg);
}
#endif // __KERNEL__
#endif // __UI__
// internal kernel functions to lock the debugger memory configuration updates
// Do not use these functions! They will be removed!
idaman void ida_export lock_dbgmem_config(void);
idaman void ida_export unlock_dbgmem_config(void);
#endif