/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-2025 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.
/// (nullptr 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
///@}
inline bool idaapi is_valid_dstate(int state)
{
  return state == DSTATE_SUSP || state == DSTATE_NOTASK || state == DSTATE_RUN;
}

/// \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 nullptr 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, nullptr, 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 nullptr 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 = nullptr,
        const char *args = nullptr,
        const char *sdir = nullptr)
{
  return callui(ui_dbg_start_process, path, args, sdir).i;
}


/// Post a start_process() request

inline int idaapi request_start_process(
        const char *path = nullptr,
        const char *args = nullptr,
        const char *sdir = nullptr)
{
  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; }

/// Continue the execution of the process in the debugger backwards.
/// Can only be used with debuggers that support time-travel debugging.
/// \sq{Type,         Synchronous function - available as Request,
///     Notification, none (synchronous function)}
/// \note The continue_backwards() 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_backwards(void) { return callui(ui_dbg_continue_backwards).cnd; }

/// Post a continue_backwards() request.
/// \note This requires an explicit call to run_requests()

inline bool idaapi request_continue_backwards(void) { return callui(ui_dbg_request_continue_backwards).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] proclist 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.
/// \param event_id event to trigger upon attaching
/// \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 nullptr 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 one instruction backwards 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_backwards(void) { return callui(ui_dbg_step_into_backwards).cnd; }

/// Post a step_into_backwards() request

inline bool idaapi request_step_into_backwards(void) { return callui(ui_dbg_request_step_into_backwards).cnd; }


/// Execute one instruction backwards in the current thread,
/// but without entering into functions.
/// Other threads are kept suspended.
/// \sq{Type,         Asynchronous function - available as Request,
///     Notification, ::dbg_step_over}

inline bool idaapi step_over_backwards(void) { return callui(ui_dbg_step_over_backwards).cnd; }

/// Post a step_over_backwards() request

inline bool idaapi request_step_over_backwards(void) { return callui(ui_dbg_request_step_over_backwards).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 the process backwards until the given address is reached.
/// Technically, the debugger sets up a temporary breakpoint at
/// the given address, and continues (or starts) the execution of
/// the whole process.
/// \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_backwards(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_run_to_backwards, ea, pid, tid).cnd; }

/// Post a run_to_backwards() request

inline bool idaapi request_run_to_backwards(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_request_run_to_backwards, 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.
///@{

int idaapi set_bptloc_string(const char *s);
const char *idaapi get_bptloc_string(int i);

struct bpt_t;
struct bpt_location_t;
struct movbpt_info_t;
typedef qvector<movbpt_info_t> movbpt_infos_t;
typedef qvector<const bpt_t *> bpt_constptr_vec_t;
typedef qvector<bpt_t *> bptptr_vec_t;
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 bptaddrs_t : public eavec_t
{
  bpt_t *bpt;   // bpt described by this structure.
                // we need it to handle internal srcbpts
};

typedef qvector<bptaddrs_t> bpteas_t;



/// 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;
};
DECLARE_TYPE_AS_MOVABLE(bpt_location_t);

/// 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. 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)
  inode_t bptid;            ///< Internal breakpoint id

  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), bptid(0) {}

  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
};
DECLARE_TYPE_AS_MOVABLE(bpt_t);

struct movbpt_info_t
{
  bpt_location_t from;
  bpt_location_t to;
};
DECLARE_TYPE_AS_MOVABLE(movbpt_info_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 nullptr, 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, nullptr); }


/// 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 = nullptr,
        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
{
  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(nullptr) {}
  /// 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 'Tracing' 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 silent, 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
#define DOPT_FAST_STEP    0x00040000 ///< prevent debugger memory refreshes when single-stepping
#define DOPT_DISABLE_ASLR 0x00080000 ///< disable ASLR
///@}
#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 nullptr, the host will not be set.
/// \param pass  If nullptr, 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 nullptr

inline void idaapi get_process_options(
        qstring *path,
        qstring *args,
        launch_env_t *out_envs,
        qstring *sdir,
        qstring *host,
        qstring *pass,
        int *port)
{
  callui(ui_dbg_get_process_options, path, args, sdir, host, pass, port, out_envs);
}


/// Set process options.
/// Any of the arguments may be nullptr, which means 'do not modify'

inline void idaapi set_process_options(
        const char *path,
        const char *args,
        const launch_env_t *envs,
        const char *sdir,
        const char *host,
        const char *pass,
        int port)
{
  callui(ui_dbg_set_process_options, path, args, sdir, host, pass, port, envs);
}


/// 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 nullptr)
/// \param desc   exception description (maybe nullptr)
/// \param flags  combination of \ref EXC_
/// \return failure message or nullptr.
///         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() implemented in ::debugger_t?

inline THREAD_SAFE bool have_set_options(const debugger_t *_dbg)
{
  return _dbg != nullptr && _dbg->have_set_options();
}

/// Convenience function to set debugger specific options.
/// It checks if the debugger is present and calls function.

inline const char *idaapi set_dbg_options(
        debugger_t *_dbg,
        const char *keyword,
        int pri,
        int value_type,
        const void *value)
{
  const char *res = IDPOPT_BADKEY;
  if ( have_set_options(_dbg) )
    _dbg->set_dbg_options(&res, keyword, pri, value_type, value);
  return res;
}


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. nullptr 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. nullptr 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.
  /// \param keyword     keyword encountered in IDA.CFG/user config file.
  ///                    if nullptr, then an interactive dialog form should be displayed
  /// \param value_type  type of value of the keyword - one of \ref IDPOPT_T
  /// \param value       pointer to value
  /// \return one of \ref IDPOPT_RET, otherwise a pointer to an error message
  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=nullptr) = 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 nullptr
  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 out pointer to byte value
/// \param ea  linear address
/// \return success
/// \retval true   success
/// \retval false  address inaccessible or debugger not running

idaman bool ida_export get_dbg_byte(uint32 *out, 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 nullptr, 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

//------------------------------------------------------------------------
#if !defined(__UI__) && !defined(__KERNEL__)         // Not for the UI nor the kernel


/// \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 void idaapi bring_debugger_to_front(void)                                              { callui(ui_dbg_bring_to_front); }
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 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_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 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; }

/// Move a bpt into a folder in the breakpoint dirtree
/// if the folder didn't exists, it will be created
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param bpt bpt that will be moved
/// \param grp_name absolute path to the breakpoint dirtree folder
/// \return success
inline bool idaapi set_bpt_group(bpt_t &bpt, const char *grp_name)                            { return callui(ui_dbg_set_bpt_group, &bpt, grp_name).cnd; }

/// Move a bpt into a folder in the breakpoint dirtree based on the bpt_location
/// \ref find_bpt is called to retrieve the bpt and then \ref set_bpt_group
/// if the folder didn't exists, it will be created
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param bptloc bptlocation of the bpt that will be moved
/// \param grp_name absolute path to the breakpoint dirtree folder
/// \return success
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; }

/// Retrieve the absolute path to the folder of the bpt based on the bpt_location
/// \ref find_bpt is called to retrieve the bpt
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param[out] grp_name absolute path to the breakpoint dirtree folder, can be null
/// \param bptloc bptlocation of the bpt
/// \return success
/// \retval true breakpoint correclty moved to the directory
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; }

/// Retrieve the list of absolute path of all folders of bpt dirtree
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param[out] bptgrps list of absolute path in the bpt dirtree
/// \return number of folders returned
inline size_t idaapi list_bptgrps(qstrvec_t *bptgrps)                                         { return callui(ui_dbg_list_bptgrps, bptgrps).ssize; }

/// Rename a folder of bpt dirtree
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param old_name absolute path to the folder to be renamed
/// \param new_name absolute path of the new folder name
/// \return success
inline bool idaapi rename_bptgrp(const char *old_name, const char *new_name)                  { return callui(ui_dbg_rename_bptgrp, old_name, new_name).cnd; }

/// Delete a folder, bpt that were part of this folder are moved to the root folder
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param name full path to the folder to be deleted
/// \return success
inline bool idaapi del_bptgrp(const char *name)                                               { return callui(ui_dbg_del_bptgrp, name).cnd; }

/// Retrieve a copy the bpts stored in a folder
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param[out] bpts : pointer to a vector where the copy of bpts are stored
/// \param grp_name absolute path to the folder
/// \return number of bpts present in the vector
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; }

/// Enable (or disable) all bpts in a folder
/// \sq{Type,         Synchronous function,
///     Notification, none (synchronous function)}
/// \param bptgrp_name absolute path to the folder
/// \param enable by default true, enable bpts, false disable bpts
/// \retval -1 an error occured
/// \retval 0 no changes
/// \retval >0 nubmers of bpts udpated
inline int idaapi enable_bptgrp(const char *bptgrp_name, bool enable=true)                    { return callui(ui_dbg_enable_bptgrp, bptgrp_name, enable).i; }
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 bool idaapi srcdbg_request_step_into(void)                                             { return callui(ui_dbg_srcdbg_request_step_into).cnd; }
inline bool idaapi srcdbg_request_step_over(void)                                             { return callui(ui_dbg_srcdbg_request_step_over).cnd; }
inline bool idaapi srcdbg_request_step_until_ret(void)                                        { return callui(ui_dbg_srcdbg_request_step_until_ret).cnd; }
///@} dbg_funcs_conv
#endif // !__UI__ && !__KERNEL__

#ifndef __UI__
inline int  idaapi internal_cleanup_appcall(thid_t tid)                                       { return callui(ui_dbg_internal_cleanup_appcall, tid).i; }
inline int  idaapi hide_all_bpts(void)                                                        { return callui(ui_dbg_hide_all_bpts).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 bool idaapi get_module_info(ea_t ea, modinfo_t *modinfo)                               { return callui(ui_dbg_get_module_info, ea, modinfo).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); }
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 != nullptr && (_dbg->may_disturb() || get_process_state() < DSTATE_NOTASK);
}
inline bool idaapi dbg_can_query(void)
{
  return dbg_can_query(dbg);
}
inline bool idaapi load_debugger(const char *dbgname, bool use_remote)                        { return callui(ui_dbg_load_debugger, dbgname, use_remote).cnd; }
inline bool idaapi collect_stack_trace(thid_t tid, call_stack_t *trace)                       { return callui(ui_dbg_collect_stack_trace, tid, trace).cnd; }
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 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_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 void idaapi add_path_mapping(const char *src, const char *dst)                         { callui(ui_dbg_add_path_mapping, src, dst); }
inline bool idaapi srcdbg_step_into(void)                                                     { return callui(ui_dbg_srcdbg_step_into).cnd; }
inline bool idaapi srcdbg_step_over(void)                                                     { return callui(ui_dbg_srcdbg_step_over).cnd; }
inline bool idaapi srcdbg_step_until_ret(void)                                                { return callui(ui_dbg_srcdbg_step_until_ret).cnd; }
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 void idaapi set_debugger_event_cond(const char *NONNULL evcond)                        { callui(ui_dbg_set_event_cond, evcond); }
inline const char *idaapi get_debugger_event_cond(void)                                       { return callui(ui_dbg_get_event_cond).cptr; }
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; }
#endif // !__UI__

#ifdef __KERNEL__
inline bool idaapi set_bpt_group(bpt_t &bpt, const char *grp_name)                            { return get_bpt_kernel_interface()->set_bpt_dir(&bpt, grp_name); }
inline int  idaapi set_bptloc_string(const char *s)                                           { return get_bpt_kernel_interface()->add_bptloc_string(s); }
inline const char *idaapi get_bptloc_string(int i)                                            { return get_bpt_kernel_interface()->get_bptloc_string(i); }
#endif

// 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
