2625 lines
109 KiB
C++
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
|