/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-98 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              E-mail: ig@estar.msk.su, ig@datarescue.com
 *                              FIDO:   2:5020/209
 *
 */

#ifndef DBG_HPP
#define DBG_HPP
#pragma pack(push, 1)           // IDA uses 1 byte alignments!

#include <idd.hpp>
#include <kernwin.hpp>          // for callui() and ui_notification_t

//
//      This file contains functions to control the debugging of a process.
//
// 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
//--------------------------------------------------------------------

// The following structure contains information about the current debugger
// (NULL if no debugger was loaded) - see IDD.HPP for details about this structure.
//
// All functions defined in this structure should only be called by the kernel !!!

idaman debugger_t ida_export_data *dbg; // Current debugger - NULL if no debugger

//--------------------------------------------------------------------
//               D E B U G G E R   C A L L B A C K S
//--------------------------------------------------------------------
// 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 occuring 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-levels events always return a debug_event_t structure as argument
//     (see IDD.HPP for details about this structure).
//
// - debugger asynchronous function result notification:
//     such a notification occurs only when a debugger properly terminated
//     the execution of an asynchronous function (see "debugger functions"
//     in this file).
//
//
// 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 "debugger functions" 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 can NEVER start directly an asynchronous function in a debugger
// notification handler ! Use the REQUEST QUEUE mechanism to start asynchronous
// functions from a handler.
//
// 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 obsolete values!

enum dbg_notification_t
{
  dbg_null = 0,

  // debugger low-level event notifications (see IDD.HPP for details).

  dbg_process_start,   // Parameter:  const debug_event_t *event
                       //   This event notification is also an asynchronous
                       //   function result notification for start_process() !

  dbg_process_exit,    // Parameter:  const debug_event_t *event
                       //   This event notification is also an asynchronous
                       //   function result notification for exit_process() !

  dbg_process_attach,  // Parameter:  const debug_event_t *event
                       //   This event notification is also an asynchronous
                       //   function result notification for attach_process() !

  dbg_process_detach,  // Parameter:  const debug_event_t *event
                       //   This event notification is also an asynchronous
                       //   function result notification for detach_process() !

  dbg_thread_start,    // Parameter:  const debug_event_t *event

  dbg_thread_exit,     // Parameter:  const debug_event_t *event

  dbg_library_load,    // Parameter:  const debug_event_t *event

  dbg_library_unload,  // Parameter:  const debug_event_t *event

  dbg_information,     // Parameter:  const debug_event_t *event

  dbg_exception,       // Parameters: const debug_event_t *event
                       //             int                 *warn = -1
                       //             Return (in *warn):
                       //              -1 - to display an exception warning dialog
                       //                   if the process is suspended.
                       //               0 - to never display an exception warning dialog.
                       //               1 - to always display an exception warning dialog.

  // debugger high-level event notifications

  dbg_suspend_process, // The process is now suspended.
                       // Parameter: none
                       //   This event notification is also an asynchronous
                       //   function result notification for suspend_process() !

  dbg_bpt,             // A user defined breakpoint was reached.
                       // Parameters: thid_t tid
                       //             ea_t        breakpoint_ea
                       //             int        *warn = -1
                       //             Return (in *warn):
                       //              -1 - to display a breakpoint warning dialog
                       //                   if the process is suspended.
                       //               0 - to never display a breakpoint warning dialog.
                       //               1 - to always display a breakpoint warning dialog.

  dbg_trace,           // A step occured (one instruction was executed). This event
                       // notification is only generated if step tracing is enabled.
                       // Parameters: thid_t tid
                       //             ea_t        ip
                       // Returns: 1-do not log this trace event; 0-log it

  dbg_request_error,   // An error occured during the processing of a request.
                       // Parameters: ui_notification_t  failed_command
                       //             dbg_notification_t failed_dbg_notification

  // debugger asynchronous function result notifications
  //   Please note some low-level event notifications also act as asynchronous
  //   function result notifications.

  dbg_step_into,       // Parameter: none

  dbg_step_over,       // Parameter: none

  dbg_run_to,          // Parameter: thid_t tid

  dbg_step_until_ret,  // Parameter: none


  dbg_last,            // The last debugger notification code
};

//--------------------------------------------------------------------
//               D E B U G G E R    F U N C T I O N S
//--------------------------------------------------------------------
// 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, a run_to(address) function 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 the hook_to_notification_point() function
//   (see LOADER.HPP) 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(): 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 "debugger callbacks" in this file).
//
// - request_COMMAND(): 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 "debugger callbacks" in this file).
//
//
// The REQUEST QUEUE contains a list of memorized 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() occured in the asynchronous function result
//   notification handler (if any).
//
// - run_requests() was called.
//   Remark that, when called from a debugger notification handler, commands
//   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.
// 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.

bool idaapi run_requests(void);


// Get the current running request.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: ui_null if no running request
ui_notification_t idaapi get_running_request(void);
inline bool is_request_running(void) { return get_running_request() != ui_null; }


// Get the notification associated (if any) with the current running request.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: dbg_null if no running request
dbg_notification_t idaapi get_running_notification(void);


// Clear the queue of waiting requests.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Note: If a request is currently running, this one isn't stopped.

void idaapi clear_requests_queue(void);

//--------------------------------------------------------------------
//                P R O C E S S   C O M M A N D S
//--------------------------------------------------------------------
// Use the following functions to manipulate the debugged process.

// Return the state of the currently debugged process.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Returns one of DSTATE_.. constants

int idaapi get_process_state(void);

#define DSTATE_SUSP_FOR_EVENT   -2 // process is currently suspended to react to a debug event
                                   // but it will continue when the kernel gets back the control
#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
#define DSTATE_RUN_WAIT_ATTACH   2 // process is running, waiting for process properly attached
#define DSTATE_RUN_WAIT_END      3 // process is running, but the user asked to kill/detach the process
                                   //   remark: in this case, most events are ignored


// Start a process in the debugger
//     path    - path to the executable to start
//     args    - arguments to pass to process
//     sdir    - starting directory for the process
//   For all parameters, a NULL value indicates the debugger will take
//   the value from the defined Process Options.
// Type:         Asynchronous function - available as Request
// Notification: dbg_process_start
// Return:
//         -1 - impossible to create the process
//          0 - the starting of the process was cancelled by the user
//          1 - the process was properly started
// Note: You can also use the run_to() function to easily start the execution
//       of a process until a given address is reached.

int idaapi start_process(const char *path = NULL,
                         const char *args = NULL,
                         const char *sdir = NULL);
int idaapi request_start_process(const char *path = NULL,
                                 const char *args = NULL,
                                 const char *sdir = NULL);


// Suspend the process in the debugger.
// 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.

bool idaapi suspend_process(void);
bool idaapi request_suspend_process(void);


// Continue the execution of the process in the debugger.
// 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.

bool idaapi continue_process(void);
bool idaapi request_continue_process(void);


// Terminate the debugging of the current process.
// Type:         Asynchronous function - available as Request
// Notification: dbg_process_exit

bool idaapi exit_process(void);
bool idaapi request_exit_process(void);


// Take a snapshot of running processes and return their number.
// Type:         Synchronous function
// Notification: none (synchronous function)

int idaapi get_process_qty(void);


// Get information about a running process
//      n - number of process, is in range 0..get_process_qty()-1
// If process_info isn't NULL, it is filled with the information.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: NO_PROCESS if the process doesn't exist.
// Note: Always first call get_process_qty() to initialize the snapshot.

pid_t idaapi get_process_info(int n, process_info_t *process_info);
inline pid_t getn_process(int n) { return get_process_info(n, NULL); }


// Attach the debugger to a running process
//     process - PID of the process to attach to. If NO_PROCESS, a dialog box
//               will interactively ask the user for the process to attach to.
// Type:         Asynchronous function - available as Request
// Notification: dbg_process_attach
// Return:
//         -2 - impossible to find a compatible process
//         -1 - impossible to attach to the given process (process died, privilege
//              needed, not supported by the debugger plugin, ...)
//          0 - the user cancelled the attaching to the process
//          1 - the debugger properly attached to the process
// Note: This function shouldn't be called as a request if NO_PROCESS is used.

int idaapi attach_process(pid_t pid=NO_PROCESS, int event_id=-1);
int idaapi request_attach_process(pid_t pid, int event_id);


// Detach the debugger from the debugged process.
// Type:         Asynchronous function - available as Request
// Notification: dbg_process_detach

bool idaapi detach_process(void);
bool idaapi request_detach_process(void);

//--------------------------------------------------------------------
//                         T H R E A D S
//--------------------------------------------------------------------

// Get number of threads.
// Type:         Synchronous function
// Notification: none (synchronous function)
int idaapi get_thread_qty(void);


// Get the ID of a thread
//     n - number of thread, is in range 0..get_thread_qty()-1
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: PROCESS_NO_THREAD if the thread doesn't exist.

thid_t idaapi getn_thread(int n);


// Get current thread ID
// Type:         Synchronous function
// Notification: none (synchronous function)
thid_t idaapi get_current_thread(void);


// Select the given thread as the current debugged thread.
// All thread related execution functions will work on this thread.
//     tid - ID of the thread to select
// The process must be suspended to select a new thread.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)
// Return: false if the thread doesn't exist.

bool idaapi select_thread(thid_t tid);
bool idaapi request_select_thread(thid_t tid);

//--------------------------------------------------------------------
//                         M O D U L E S
//--------------------------------------------------------------------

// Functions to enumerate modules loaded into the process
//      modinfo - structure to receive the answer
// Return: false if there are no (more) modules
// Typical loop to enumerate modules would look like:
//   module_info_t minfo;
//   for ( bool ok=get_first_module(&minfo); ok; ok=get_next_module(&minfo) )
//     ...

bool idaapi get_first_module(module_info_t *modinfo);
bool idaapi get_next_module(module_info_t *modinfo);


//--------------------------------------------------------------------
//    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
//--------------------------------------------------------------------
// Use the following functions to run instructions in the debugged process.


// Execute one instruction in the current thread.
// Other threads are kept suspended.
// Type:         Asynchronous function - available as Request
// Notification: dbg_step_into

bool idaapi step_into(void);
bool idaapi request_step_into(void);


// Execute one instruction in the current thread,
// but without entering into functions
// Others threads keep suspended.
// Type:         Asynchronous function - available as Request
// Notification: dbg_step_over

bool idaapi step_over(void);
bool idaapi request_step_over(void);


// Execute the process until the given address is reached.
// If no process is active, a new process is started.
// Type:         Asynchronous function - available as Request
// Notification: dbg_run_to
//
// Technically, the debugger setups a temporary breakpoint at
// the given address, and continue (or start) the execution of
// the whole process.
// So, all threads continue their execution !

bool idaapi run_to(ea_t ea);
bool idaapi request_run_to(ea_t ea);


// Execute instructions in the current thread until
// a function return instruction is reached.
// Other threads are kept suspended.
// Type:         Asynchronous function - available as Request
// Notification: dbg_step_until_ret

bool idaapi step_until_ret(void);
bool idaapi request_step_until_ret(void);

//--------------------------------------------------------------------
//                       R E G I S T E R S
//--------------------------------------------------------------------
// 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


// Read a register value from the current thread.
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi get_reg_val(const char *regname, regval_t *regval);

inline bool get_reg_val(const char *regname, ulonglong *ival)
{
  regval_t regval;
  if (!get_reg_val(regname, &regval)) return false;
  if (ival != NULL) *ival = regval.ival;
  return true;
}


// Write a register value to the current thread.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi set_reg_val(const char *regname, const regval_t *regval);
bool idaapi request_set_reg_val(const char *regname, const regval_t *regval);

inline bool set_reg_val(const char *regname, ulonglong ival)
{
  regval_t regval;
  regval.ival = ival;
  return set_reg_val(regname, &regval);
}


// Does a register contain an integer value?
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi is_reg_integer(const char *regname);

//--------------------------------------------------------------------
//                     B R E A K P O I N T S
//--------------------------------------------------------------------

// A breakpoint has the following characteristics:
struct bpt_t
{
  // read only characteristics:
  ea_t ea;                // starting address of the breakpoint
  asize_t size;           // size of the breakpoint (undefined if software breakpoint)
  bpttype_t type;         // type of the breakpoint
                          // see IDD.HPP for the available types.
  // modifiable characteristics:
  int pass_count;         // how many times does the execution reach this breakpoint ?
                          // (-1 if undefined)
  int flags;
#define BPT_BRK   0x01    // does the debugger stop on this breakpoint ?
#define BPT_TRACE 0x02    // does the debugger add trace information when
                          // this breakpoint is reached ?
  char condition[MAXSTR]; // an IDC expression which will be used as breakpoint condition
};


// Get number of breakpoints.
// Type:         Synchronous function
// Notification: none (synchronous function)

int idaapi get_bpt_qty(void);


// Get the characteristics of a breakpoint
//      n - number of breakpoint, is in range 0..get_bpt_qty()-1
// bpt is filled with the characteristics.
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi getn_bpt(int n, bpt_t *bpt);


// Get the characteristics of a breakpoint
//      address - any address in the breakpoint range
// If bpt isn't NULL, it is filled with the characteristics.
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi get_bpt(ea_t ea, bpt_t *bpt);
inline bool exist_bpt(ea_t ea) { return get_bpt(ea, NULL); }


// Add a new breakpoint in the debugged process
//     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.
//     size - size of the breakpoint (irrelevant for software breakpoints):
//            As for the address, hardware breakpoints can't always be setup
//            with random size.
//     type - type of the breakpoint (HWBPT_SOFT for software breakpoint)
// Only one breakpoint can exist at a given address.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_SOFT);
bool idaapi request_add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_SOFT);


// Delete an existing breakpoint in the debugged process
//      ea - any address in the breakpoint range
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi del_bpt(ea_t ea);
bool idaapi request_del_bpt(ea_t ea);


// Update modifiable characteristics of an existing breakpoint.
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi update_bpt(const bpt_t *bpt);


// Enable or disable an existing breakpoint.
// A disabled breakpoint isn't available anymore in the process.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi enable_bpt(ea_t ea, bool enable = true);
inline bool disable_bpt(ea_t ea) { return enable_bpt(ea, false); }
bool idaapi request_enable_bpt(ea_t ea, bool enable = true);
inline bool request_disable_bpt(ea_t ea) { return request_enable_bpt(ea, false); }

//--------------------------------------------------------------------
//                    T R A C I N G   B U F F E R
//--------------------------------------------------------------------
// 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
//     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.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Note: If you specify 0, all available memory can be quickly used !!!

bool idaapi set_trace_size(int size);


// Clear all events in the trace buffer
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

void idaapi clear_trace(void);
void idaapi request_clear_trace(void);

//--------------------------------------------------------------------
//                        S T E P    T R A C I N G
//--------------------------------------------------------------------
// To step trace, IDA activates the step-by-step feature of the processor,
// and generates a dbg_trace notification after each step in the current thread.
// Use this mechanism to implement your own custom tracing engine.
// This mechanism is currently only available for plugins !


// Get current state of step tracing.
// Type:         Synchronous function
// Notification: none (synchronous function)
bool idaapi is_step_trace_enabled(void);


// Enable or disable the step tracing
//    true - enable step tracing
//   false - disable step tracing
//      -1 - temporarly disable step tracing
//           (trace-over breakpoints are conserved:
//            these could reenable step tracing later)
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi enable_step_trace(int enable = true);
inline bool disable_step_trace(void) { return enable_step_trace(false); }
bool idaapi request_enable_step_trace(int enable = true);
inline bool request_disable_step_trace(void) { return request_enable_step_trace(false); }


// Get current step tracing options.
// Type:         Synchronous function
// Notification: none (synchronous function)

#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

int idaapi get_step_trace_options(void);


// Modify step tracing options.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

void idaapi set_step_trace_options(int options);
void idaapi request_set_step_trace_options(int options);

//--------------------------------------------------------------------
//               I N S T R U C T I O N S   T R A C I N G
//--------------------------------------------------------------------
// When instruction tracing is active, each executed instruction is stored
// in the tracing buffer.
// Internally, IDA uses step tracing to monitor register values after the
// execution of the instruction.


// Get current state of instructions tracing.
// Type:         Synchronous function
// Notification: none (synchronous function)
bool idaapi is_insn_trace_enabled(void);


// Enable or disable the instructions tracing
//    true - enable instructions tracing
//   false - disable instructions tracing
//      -1 - temporarly disable instructions tracing
//           (trace-over breakpoints are conserved:
//            these could reenable instructions tracing later)
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi enable_insn_trace(int enable = true);
inline bool disable_insn_trace(void) { return enable_insn_trace(false); }
bool idaapi request_enable_insn_trace(int enable = true);
inline bool request_disable_insn_trace(void) { return request_enable_insn_trace(false); }


// Get current instruction tracing options.
// Type:         Synchronous function
// Notification: none (synchronous function)

#define IT_LOG_SAME_IP 0x01 // instruction tracing will log instructions whose IP doesn't change

int idaapi get_insn_trace_options(void);


// Modify instruction tracing options.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

void idaapi set_insn_trace_options(int options);
void idaapi request_set_insn_trace_options(int options);

//--------------------------------------------------------------------
//                 F U N C T I O N S   T R A C I N G
//--------------------------------------------------------------------
// Each call to a function or return from a function is stored
// in the tracing buffer.


// Get current state of functions tracing.
// Type:         Synchronous function
// Notification: none (synchronous function)
bool idaapi is_func_trace_enabled(void);


// Enable or disable the functions tracing
//    true - enable functions tracing
//   false - disable functions tracing
//      -1 - temporarly disable functions tracing
//           (trace-over breakpoints are conserved:
//            these could reenable functions tracing later)
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

bool idaapi enable_func_trace(int enable = true);
inline bool disable_func_trace(void) { return enable_func_trace(false); }
bool idaapi request_enable_func_trace(int enable = true);
inline bool request_disable_func_trace(void) { return request_enable_func_trace(false); }


// Get current function tracing options.
// Type:         Synchronous function
// Notification: none (synchronous function)

#define FT_LOG_RET 0x01 // function tracing will log returning instructions

int idaapi get_func_trace_options(void);


// Modify function tracing options.
// Type:         Synchronous function - available as Request
// Notification: none (synchronous function)

void idaapi set_func_trace_options(int options);
void idaapi request_set_func_trace_options(int options);

//--------------------------------------------------------------------
//                   T R A C I N G   E V E N T S
//--------------------------------------------------------------------

// Trace event types:
enum tev_type_t
{
  tev_none = 0, // no event
  tev_insn,     // instruction trace event
  tev_call,     // function call trace event
  tev_ret,      // function return trace event
  tev_bpt,      // write, read/write, execution trace event
};

// 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 occured
};


// Get number of trace events available in trace buffer.
// Type:         Synchronous function
// Notification: none (synchronous function)

int idaapi get_tev_qty(void);


// Get main information about a trace event.
//      n - number of trace event, is in range 0..get_bpt_qty()-1
//          0 represents the latest added trace event.
// Return the type of a trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)

bool idaapi get_tev_info(int n, tev_info_t *tev_info);


// Read a register value from an instruction trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: false if not an instruction event.
// Note: This is the value of the register before the execution of
//       the instruction.

bool idaapi get_insn_tev_reg_val(int n, const char *regname, regval_t *regval);

inline bool get_insn_tev_reg_val(int n, const char *regname, ulonglong *ival)
{
  regval_t regval;
  if (!get_insn_tev_reg_val(n, regname, &regval)) return false;
  if (ival != NULL) *ival = regval.ival;
  return true;
}


// Read the resulting register value from an instruction trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: false if not an instruction trace event or register wasn't modified.

bool idaapi get_insn_tev_reg_result(int n, const char *regname, regval_t *regval);

inline bool get_insn_tev_reg_result(int n, const char *regname, ulonglong *ival)
{
  regval_t regval;
  if (!get_insn_tev_reg_result(n, regname, &regval)) return false;
  if (ival != NULL) *ival = regval.ival;
  return true;
}


// Return the called function from a function call trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: false if not a function call event.

ea_t idaapi get_call_tev_callee(int n);


// Return the return address from a function return trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: false if not a function return event.

ea_t idaapi get_ret_tev_return(int n);


// Return the address associated to a read, read/write or execution trace event.
// Type:         Synchronous function
// Notification: none (synchronous function)
// Return: false 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.

ea_t idaapi get_bpt_tev_ea(int n);

//--------------------------------------------------------------------
//      Utility functions
//--------------------------------------------------------------------
inline ea_t mapea(ea_t ea)
{
  if ( dbg->map_address != NULL )
    ea = dbg->map_address(ea);
  return ea;
}

//---------------------------------------------------------------------------
//      High level functions (useable 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
};
// If the retured value > 0, then it is the event id (see idd.hpp, event_id_t)

dbg_event_code_t idaapi wait_for_next_event(int wfne, int timeout);
                           // wfne flag is combination of the following:
#define WFNE_ANY    0x0001 // return the first event (even if it doesn't suspend the process)
#define WFNE_SUSP   0x0002 // wait until the process gets suspended
#define WFNE_SILENT 0x0004 // 1: be slient, 0:display modal boxes if necessary
#define WFNE_CONT   0x0008 // continue from the suspended state


// Get the current debugger event

const debug_event_t *idaapi get_debug_event(void);


// Set debugger options
// Replaces debugger options with the specifiction combination of DOPT_..
// Returns the old debugger options

uint idaapi set_debugger_options(uint options);

#define DOPT_SEGM_MSGS    0x00000001 // print messages on debugger segments modifications
#define DOPT_START_BPT    0x00000002 // break on process start
#define DOPT_THREAD_MSGS  0x00000004 // print messages on thread start/exit
#define DOPT_THREAD_BPT   0x00000008 // break on thread start/exit
#define DOPT_BPT_MSGS     0x00000010 // print message on breakpoint
//#define DOPT_BINS_BPT     0x00000020 // break on breakpoint instruction
#define DOPT_LIB_MSGS     0x00000040 // print message on library load/unlad
#define DOPT_LIB_BPT      0x00000080 // break on library load/unlad
#define DOPT_INFO_MSGS    0x00000100 // print message on debugging information
#define DOPT_INFO_BPT     0x00000200 // break on debugging information
#define DOPT_REAL_MEMORY  0x00000400 // don't hide breakpoint instructions
#define DOPT_REDO_STACK   0x00000800 // reconstruct the stack
#define DOPT_ENTRY_BPT    0x00001000 // break on program entry point


// Set remote debugging options
// Should be used before starting the debugger. If host is empty,
// then IDA will use local debugger.

void idaapi set_remote_debugger(const char *host, const char *pass, int port=-1);


//--------------------------------------------------------------------
#ifndef __UI__         // Not for the UI

// Convenience functions offered by the user interface

inline bool idaapi run_requests(void)                                                         { return callui(ui_dbg_run_requests).cnd; }
inline ui_notification_t idaapi get_running_request(void)                                     { return (ui_notification_t)callui(ui_dbg_get_running_request).i; }
inline dbg_notification_t idaapi get_running_notification(void)                               { return (dbg_notification_t)callui(ui_dbg_get_running_notification).i; }
inline void idaapi clear_requests_queue(void)                                                 { callui(ui_dbg_clear_requests_queue); }
inline int idaapi get_process_state(void)                                                     { return callui(ui_dbg_get_process_state).i; }
inline int idaapi start_process(const char *path, const char *args, const char *sdir)         { return callui(ui_dbg_start_process, path, args, sdir).i; }
inline int idaapi request_start_process(const char *path, const char *args, const char *sdir) { return callui(ui_dbg_request_start_process, path, args, sdir).i; }
inline bool idaapi suspend_process(void)                                                      { return callui(ui_dbg_suspend_process).cnd; }
inline bool idaapi request_suspend_process(void)                                              { return callui(ui_dbg_request_suspend_process).cnd; }
inline bool idaapi continue_process(void)                                                     { return callui(ui_dbg_continue_process).cnd; }
inline bool idaapi request_continue_process(void)                                             { return callui(ui_dbg_request_continue_process).cnd; }
inline bool idaapi exit_process(void)                                                         { return callui(ui_dbg_exit_process).cnd; }
inline bool idaapi request_exit_process(void)                                                 { return callui(ui_dbg_request_exit_process).cnd; }
inline int idaapi get_process_qty(void)                                                       { return callui(ui_dbg_get_process_qty).i; }
inline pid_t idaapi get_process_info(int n, process_info_t *process_info)                     { return (pid_t)callui(ui_dbg_get_process_info, n, process_info).i; }
inline int idaapi attach_process(pid_t pid, int event_id)                                     { return callui(ui_dbg_attach_process, pid, event_id).i; }
inline int idaapi request_attach_process(pid_t pid, int event_id)                             { return callui(ui_dbg_request_attach_process, pid, event_id).i; }
inline bool idaapi detach_process(void)                                                       { return callui(ui_dbg_detach_process).cnd; }
inline bool idaapi request_detach_process(void)                                               { return callui(ui_dbg_request_detach_process).cnd; }
inline int idaapi get_thread_qty(void)                                                        { return callui(ui_dbg_get_thread_qty).i; }
inline thid_t idaapi getn_thread(int n)                                                       { return (thid_t)callui(ui_dbg_getn_thread, n).i; }
inline bool idaapi select_thread(thid_t tid)                                                  { return callui(ui_dbg_select_thread, tid).cnd; }
inline bool idaapi request_select_thread(thid_t tid)                                          { return callui(ui_dbg_request_select_thread, tid).cnd; }
inline bool idaapi step_into(void)                                                            { return callui(ui_dbg_step_into).cnd; }
inline bool idaapi request_step_into(void)                                                    { return callui(ui_dbg_request_step_into).cnd; }
inline bool idaapi step_over(void)                                                            { return callui(ui_dbg_step_over).cnd; }
inline bool idaapi request_step_over(void)                                                    { return callui(ui_dbg_request_step_over).cnd; }
inline bool idaapi run_to(ea_t ea)                                                            { return callui(ui_dbg_run_to, ea).cnd; }
inline bool idaapi request_run_to(ea_t ea)                                                    { return callui(ui_dbg_request_run_to, ea).cnd; }
inline bool idaapi step_until_ret(void)                                                       { return callui(ui_dbg_step_until_ret).cnd; }
inline bool idaapi request_step_until_ret(void)                                               { return callui(ui_dbg_request_step_until_ret).cnd; }
inline bool idaapi get_reg_val(const char *regname, regval_t *regval)                         { return callui(ui_dbg_get_reg_val, regname, regval).cnd; }
inline bool idaapi set_reg_val(const char *regname, const regval_t *regval)                   { return callui(ui_dbg_set_reg_val, regname, regval).cnd; }
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; }
inline int idaapi get_bpt_qty(void)                                                           { return callui(ui_dbg_get_bpt_qty).i; }
inline bool idaapi getn_bpt(int n, bpt_t *bpt)                                                { return callui(ui_dbg_getn_bpt, n, bpt).cnd; }
inline bool idaapi get_bpt(ea_t ea, bpt_t *bpt)                                               { return callui(ui_dbg_get_bpt, ea, bpt).cnd; }
inline bool idaapi add_bpt(ea_t ea, asize_t size, bpttype_t type)                             { return callui(ui_dbg_add_bpt, ea, size, type).cnd; }
inline bool idaapi request_add_bpt(ea_t ea, asize_t size, bpttype_t type)                     { return callui(ui_dbg_request_add_bpt, ea, size, type).cnd; }
inline bool idaapi del_bpt(ea_t ea)                                                           { return callui(ui_dbg_del_bpt, ea).cnd; }
inline bool idaapi request_del_bpt(ea_t ea)                                                   { return callui(ui_dbg_request_del_bpt, ea).cnd; }
inline bool idaapi update_bpt(const bpt_t *bpt)                                               { return callui(ui_dbg_update_bpt, bpt).cnd; }
inline bool idaapi enable_bpt(ea_t ea, bool enable)                                           { return callui(ui_dbg_enable_bpt, ea, enable).cnd; }
inline bool idaapi request_enable_bpt(ea_t ea, bool enable)                                   { return callui(ui_dbg_request_enable_bpt, ea, enable).cnd; }
inline bool idaapi set_trace_size(int size)                                                   { return callui(ui_dbg_set_trace_size, size).cnd; }
inline void idaapi clear_trace(void)                                                          { callui(ui_dbg_clear_trace); }
inline void idaapi request_clear_trace(void)                                                  { callui(ui_dbg_request_clear_trace); }
inline bool idaapi is_step_trace_enabled(void)                                                { return callui(ui_dbg_is_step_trace_enabled).cnd; }
inline bool idaapi enable_step_trace(int enable)                                              { return callui(ui_dbg_enable_step_trace, enable).cnd; }
inline bool idaapi request_enable_step_trace(int enable)                                      { return callui(ui_dbg_request_enable_step_trace, enable).cnd; }
inline int idaapi get_step_trace_options(void)                                                { return callui(ui_dbg_get_step_trace_options).i; }
inline void idaapi set_step_trace_options(int options)                                        { callui(ui_dbg_set_step_trace_options, options); }
inline void idaapi request_set_step_trace_options(int options)                                { callui(ui_dbg_request_set_step_trace_options, options); }
inline bool idaapi is_insn_trace_enabled(void)                                                { return callui(ui_dbg_is_insn_trace_enabled).cnd; }
inline bool idaapi enable_insn_trace(int enable)                                              { return callui(ui_dbg_enable_insn_trace, enable).cnd; }
inline bool idaapi request_enable_insn_trace(int enable)                                      { return callui(ui_dbg_request_enable_insn_trace, enable).cnd; }
inline int idaapi get_insn_trace_options(void)                                                { return callui(ui_dbg_get_insn_trace_options).i; }
inline void idaapi set_insn_trace_options(int options)                                        { callui(ui_dbg_set_insn_trace_options, options); }
inline void idaapi request_set_insn_trace_options(int options)                                { callui(ui_dbg_request_set_insn_trace_options, options); }
inline bool idaapi is_func_trace_enabled(void)                                                { return callui(ui_dbg_is_func_trace_enabled).cnd; }
inline bool idaapi enable_func_trace(int enable)                                              { return callui(ui_dbg_enable_func_trace, enable).cnd; }
inline bool idaapi request_enable_func_trace(int enable)                                      { return callui(ui_dbg_request_enable_func_trace, enable).cnd; }
inline int idaapi get_func_trace_options(void)                                                { return callui(ui_dbg_get_func_trace_options).i; }
inline void idaapi set_func_trace_options(int options)                                        { callui(ui_dbg_set_func_trace_options, options); }
inline void idaapi request_set_func_trace_options(int options)                                { callui(ui_dbg_request_set_func_trace_options, options); }
inline int idaapi get_tev_qty(void)                                                           { return callui(ui_dbg_get_tev_qty).i; }
inline bool idaapi get_tev_info(int n, tev_info_t *tev_info)                                  { return callui(ui_dbg_get_tev_info, n, tev_info).cnd; }
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_result(int n, const char *regname, regval_t *regval)      { return callui(ui_dbg_get_insn_tev_reg_result, n, regname, regval).cnd; }
inline ea_t idaapi get_call_tev_callee(int n)                                                 { ea_t ea; callui(ui_dbg_get_call_tev_callee, n, &ea); return ea; }
inline ea_t idaapi get_ret_tev_return(int n)                                                  { ea_t ea; callui(ui_dbg_get_ret_tev_return, n, &ea); return ea; }
inline ea_t idaapi get_bpt_tev_ea(int n)                                                      { ea_t ea; callui(ui_dbg_get_bpt_tev_ea, n, &ea); return ea; }
inline bool idaapi is_reg_integer(const char *regname)                                        { return callui(ui_dbg_is_reg_integer, regname).cnd; }
inline bool idaapi get_first_module(module_info_t *modinfo)                                   { return callui(ui_dbg_get_first_module, modinfo).cnd; }
inline bool idaapi get_next_module(module_info_t *modinfo)                                    { return callui(ui_dbg_get_next_module, modinfo).cnd; }
inline void idaapi bring_debugger_to_front(void)                                              { callui(ui_dbg_bring_to_front); }
inline thid_t idaapi get_current_thread(void)                                                 { return callui(ui_dbg_get_current_thread).i; }
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); }
inline const debug_event_t *idaapi get_debug_event(void)                                      { return (const debug_event_t *)callui(ui_dbg_get_debug_event).vptr; }
inline uint idaapi set_debugger_options(uint options)                                         { return callui(ui_dbg_set_debugger_options, options).i; }
inline void idaapi set_remote_debugger(const char *host, const char *pass, int port)          { callui(ui_dbg_set_remote_debugger, host, pass, port); }
inline bool idaapi load_debugger(const char *dbgname, bool use_remote)                        { return callui(ui_dbg_load_debugger, dbgname, use_remote).cnd; }


#endif

#pragma pack(pop)
#endif
