/*
 *      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 _IDD_HPP
#define _IDD_HPP
#pragma pack(push, 1)           // IDA uses 1 byte alignments!

//
//      This file contains definition of the interface to IDD modules
//      The interface consists of structures describing the target
//      debugged processor and a debugging API.


//      Versions history:
// 1    24.10.02        Initial version
// 2    17.09.03        FPU support
// 3    29.09.04        network error codes are added
// 4    15.10.04        breakpoint handling is improved
// 5    15.02.05        added remote file access functions
// 6    25.02.05        set_exception_info is added

#define         IDD_INTERFACE_VERSION   6


//====================================================================
//
//                       Process and Threads
//

typedef int process_id_t;
typedef int thread_id_t;

#define NO_PROCESS        0xFFFFFFFF // No process
#define PROCESS_NO_THREAD 0          // No thread
                                     // in PROCESS_START this value
                                     // can be used to specify that
                                     // the main thread has not been created
                                     // It will be initializated later
                                     // by a THREAD_START event.

struct process_info_t
{
  process_id_t pid;
  char name[MAXSTR];
};

//====================================================================
//
//                          Registers
//

typedef unsigned char register_class_t; // Each register is associated to
                                        // a register class.
                                        // example: "segment", "mmx", ...

struct register_info_t
{
  char *name;                         // Register full name
  ulong flags;                        // Register special features
#define REGISTER_READONLY 0x0001      //   the user can't modify the current value of this register
#define REGISTER_IP       0x0002      //   instruction pointer
#define REGISTER_SP       0x0004      //   stack pointer
#define REGISTER_FP       0x0008      //   frame pointer
#define REGISTER_ADDRESS  0x0010      // Register can contain an address
  register_class_t register_class;
  char dtyp;                          // Register size (dt_... constants)
  char* *bit_strings;                 // Strings corresponding to each bit of the register
                                      // (NULL = no bit, same name = multi-bits mask)
  int bit_strings_default;            // Mask of default bits
};

//====================================================================
//
//                           Memory
//

struct memory_info_t : public area_t
{
  memory_info_t(void) : perm(0) { name[0] = '\0'; sclass[0] = '\0'; }
  uchar perm;                  // Memory area permissions (0-no information): see segment.hpp
  char name[64];               // Memory area name (null string => kernel will give an appropriate name)
  char sclass[64];             // Memory area class name (null string => kernel will give an appropriate name)
};

//====================================================================
//
//                         Debug events
//

enum event_id_t
{
  NO_EVENT       = 0x00000000, // Not an interesting event
  PROCESS_START  = 0x00000001, // New process started
  PROCESS_EXIT   = 0x00000002, // Process stopped
  THREAD_START   = 0x00000004, // New thread started
  THREAD_EXIT    = 0x00000008, // Thread stopped
  BREAKPOINT     = 0x00000010, // Breakpoint reached
  STEP           = 0x00000020, // One instruction executed
  EXCEPTION      = 0x00000040, // Exception
  LIBRARY_LOAD   = 0x00000080, // New library loaded
  LIBRARY_UNLOAD = 0x00000100, // Library unloaded
  INFORMATION    = 0x00000200, // User-defined information
                               // This event can be used to return empty information
                               // This will cause IDA to call get_debug_event()
                               // immediately once more
  SYSCALL        = 0x00000400, // Syscall (not used yet)
  WINMESSAGE     = 0x00000800, // Window message (not used yet)
  PROCESS_ATTACH = 0x00001000, // Attached to running process
  PROCESS_DETACH = 0x00002000, // Detached from process
/*
  SIGNAL,
  DEBUG_STRING
  ...
*/
};


// Those structures describe particular debug events

struct module_info_t
{
  char name[MAXSTR];    // full name of the module.
  ea_t base;            // module base address. if unknown pass BADADDR
  asize_t size;         // module size. if unknown pass 0
  ea_t rebase_to;       // if not BADADDR, then rebase the program to the specified address
};

struct e_breakpoint_t
{
  ea_t ea;           // Possible address referenced by hardware breakpoints
};

struct e_exception_t
{
  int code;          // Exception code
  bool can_cont;     // Execution of the process can continue after this exception?
  ea_t ea;           // Possible address referenced by the exception
  char info[MAXSTR]; // Exception message
};

// This structure is used only when detailed information
//   on a debug event is needed.
struct debug_event_t
{
  debug_event_t(void) : eid(NO_EVENT) {}
  event_id_t   eid;        // Event code (used to decipher 'info' union)
  process_id_t pid;        // Process where the event occured
  thread_id_t  tid;        // Thread where the event occured
  ea_t ea;                 // Address where the event occured
  bool handled;            // Is event handled by the debugger?
                           // (from the system's point of view)
  union
  {
    module_info_t modinfo;         // PROCESS_START, PROCESS_ATTACH, LIBRARY_LOAD
    int exit_code;                 // PROCESS_EXIT, THREAD_EXIT
    char info[MAXSTR];             // LIBRARY_UNLOAD (unloaded library name)
                                   // INFORMATION (will be displayed in the
                                   //              messages window if not empty)
    e_breakpoint_t bpt;            // BREAKPOINT
    e_exception_t exc;             // EXCEPTION
  };
};

// Hardware breakpoint types
typedef int bpttype_t;
const bpttype_t
  BPT_EXEC  =  0,             // Execute instruction
  BPT_WRITE =  1,             // Write access
  BPT_RDWR  =  3,             // Read/write access
  BPT_SOFT  =  4;             // Software breakpoint


// Exception information
struct exception_info_t
{
  int code;
  ulong flags;
#define EXC_BREAK  0x0001 // break on the exception
#define EXC_HANDLE 0x0002 // should be handled by the debugger?
  bool break_on(void) const { return (flags & EXC_BREAK) != 0; }
  bool handle(void) const { return (flags & EXC_HANDLE) != 0; }
  qstring name;         // Exception standard name
  qstring desc;         // Long message used to display info about the exception
  exception_info_t(void) {}
  exception_info_t(int _code, ulong _flags, const char *_name, const char *_desc)
    : code(_code), flags(_flags), name(_name), desc(_desc) {}
};

// Instruction operand information
struct idd_opinfo_t
{
  ea_t addr;            // operand address (BADADDR - no address)
  uval_t value;         // operand value
  bool modified;        // the operand is modified (written) by the instruction
};

// register value
struct regval_t
{
#ifndef __WATCOMC__     // bad compiler
  union
  {
#endif
    ulonglong ival;     // 8:  integer value
    ushort    fval[6];  // 12: floating point value in the internal representation (see ieee.h)
#ifndef __WATCOMC__
  };
#endif
  regval_t(void) : ival(~ulonglong(0)) {}
};

//====================================================================
//
//     This structure describes a debugger API module.
//     (functions needed to debug a process on a specific
//      operating system)
//

struct debugger_t
{
  int version;                        // Expected kernel version,
                                      //   should be IDD_INTERFACE_VERSION
  char *name;                         // Short debugger name like win32 or linux
  int id;                             // Debugger API module id
#define DEBUGGER_ID_X86_IA32_WIN32_USER              0 // Userland win32 processes (win32 debugging APIs)
// #define DEBUGGER_ID_X86_IA32_WIN32_KERNEL           // ?
// #define DEBUGGER_ID_X86_IA32_WIN32_USER_WINDBG      // Translate functions to Microsoft WinDBG commands
// #define DEBUGGER_ID_X86_IA32_WIN32_KERNEL_WINDBG    // "
// #define DEBUGGER_ID_X86_IA32_WIN32_USER_SOFTICE     // Forward functions to a SoftIce plugin ?
// #define DEBUGGER_ID_X86_IA32_WIN32_KERNEL_SOFTICE   // "
#define DEBUGGER_ID_X86_IA32_LINUX_USER              1 // Userland linux processes (ptrace())
// #define DEBUGGER_ID_X86_IA32_LINUX_KERNEL           // ?
// #define DEBUGGER_ID_X86_IA32_BOCHS                  // Forward functions to Bochs emulator ?
// #define DEBUGGER_ID_JAVA
// ...

  ulong flags;                              // Debugger module special features
#define DBG_FLAG_REMOTE 0x01                // Remote debugger (requires remote host name)
  bool is_remote(void) const { return (flags & DBG_FLAG_REMOTE) != 0; }

  char*           *register_classes;        // Array of register class names
  int             register_classes_default; // Mask of default printed register classes
  register_info_t *registers;               // Array of registers
  int             registers_size;           // Number of registers

  int             memory_page_size;         // Size of a memory page

  const uchar     *bpt_bytes;               // Array of bytes for a breakpoint instruction
  int             bpt_size;                 // Size of this array

// Init/term (for local debuggers the parameters are ignored)

  bool (idaapi* init_debugger)(const char *hostname, int portnum, const char *password);

#if !defined(__WATCOMC__) && !defined(_MSC_VER)  // these compilers complain :(
  static const int default_port_number = 23946;
#define DEBUGGER_PORT_NUMBER debugger_t::default_port_number
#else
#define DEBUGGER_PORT_NUMBER 23946
#endif

  bool (idaapi* term_debugger)(void);

  // Return information about the n-th "compatible" running process.
  // If n is 0, the processes list is reinitialized.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* process_get_info)(int n, process_info_t *info);

  // Start an executable to debug
  // 1 - ok, 0 - failed, -2 - file not found (ask for process options)
  // 1|CRC32_MISMATCH - ok, but the input file crc does not match
  // -1 - network error
  int (idaapi* start_process)(const char *path,
                              const char *args,
                              const char *startdir,
                              ulong input_file_crc32);
#define CRC32_MISMATCH  0x40000000      // crc32 mismatch bit

  // Attach to an existing running process
  // 1-ok, 0-failed, -1-network error
  // event_id should be equal to -1 if not attaching to a crashed process
  int (idaapi* attach_process)(process_id_t pid, int event_id);

  // Detach from the debugged process
  // 1-ok, 0-failed, -1-network error
  int (idaapi* detach_process)(void);

  // rebase database if the debugged program has been rebased by the system
  void (idaapi *rebase_if_required_to)(ea_t new_base);

  // Prepare to pause the process
  // This function will prepare to pause the process
  // Normally the next get_debug_event() will pause the process
  // If the process is sleeping then the pause will not occur
  // until the process wakes up. The interface should take care of
  // this situation.
  // If this function is absent, then it won't be possible to pause the program
  // 1-ok, 0-failed, -1-network error
  int (idaapi* prepare_to_pause_process)(void);

  // Stop the process.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* exit_process)(void);

//-------------------------------------------
// The following functions manipulate events.
//
// Get a pending debug event and suspend the process
// returns: 1-got event, 0-no event, -1-error
// This function will be called regularly by IDA.
  int (idaapi* get_debug_event)(debug_event_t *event, bool ida_is_idle);

// Continue after handling the event
// 0-ok, 1-failed, -1-network error
  int (idaapi* continue_after_event)(const debug_event_t *event);

// Set exception handling
  void (idaapi* set_exception_info)(const exception_info_t *info, int qty);

// The following function will be called by the kernel each time
// when it has stopped the debugger process for some reason,
// refreshed the database and the screen.
// The debugger module may add information to the database if it wants.
// The reason for introducing this function is that when an event line
// LOAD_DLL happens, the database does not reflect the memory state yet
// and therefore we can't add information about the dll into the database
// in the get_debug_event() function.
// Only when the kernel has adjusted the database we can do it.
// Example: for imported PE DLLs we will add the exported function
// names to the database.
// This function pointer may be absent, i.e. NULL.
  void (idaapi *stopped_at_debug_event)(const debug_event_t *event, bool dlls_added);

  // The following functions manipulate threads.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* thread_suspend) (thread_id_t tid); // Suspend a running thread
  int (idaapi* thread_continue)(thread_id_t tid); // Resume a suspended thread
  int (idaapi* thread_set_step)(thread_id_t tid); // Run one instruction in the thread

  // The following functions manipulate registers.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* thread_read_registers)(thread_id_t tid, regval_t *values, int count); // Return current register values
  int (idaapi* thread_write_register)(thread_id_t tid, int reg_idx, const regval_t *value); // Write one register value
  // Get information about the base of a segment register
  // Currently used by the IBM PC module to resolve references like fs:0
  //   tid        - thread id
  //   sreg_value - value of the segment register (returned by get_reg_val())
  //   answer     - pointer to the answer. can't be NULL.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* thread_get_sreg_base)(thread_id_t tid, int sreg_value, ea_t *answer);

//
// The following functions manipulate bytes in the memory.
//
  // Get information on the memory areas
  // Allocates and fills areas and qty
  // The caller should qfree() it
  // Returns: -2-no changes, 1-ok, 0-the kernel will try slow algorithm (not recommended!)
  // -1 means that the process does not exist anymore
  int (idaapi* get_memory_info)(memory_info_t **areas, int *qty);

  // Read process memory
  // Returns number of read bytes
  // 0 mean read error
  // -1 means that the process does not exist anymore
  ssize_t (idaapi* read_memory)(ea_t ea, void *buffer, size_t size);

  // Write process memory
  // Returns number of written bytes, -1-fatal error
  ssize_t (idaapi* write_memory)(ea_t ea, const void *buffer, size_t size);

//
// The following functions manipulate hardware breakpoints.
//

  // Is it possible to set breakpoint?
  // Returns: BPT_...
  int (idaapi* is_ok_bpt)(bpttype_t type, ea_t ea, int len);
#define BPT_OK           0
#define BPT_INTERNAL_ERR 1
#define BPT_BAD_TYPE     2
#define BPT_BAD_ALIGN    3
#define BPT_BAD_ADDR     4
#define BPT_BAD_LEN      5
#define BPT_TOO_MANY     6
  // Add a breakpoint
  // Note: for software breakpoints, the kernel will save/restore
  // original byte values, the module should just write the bpt opcode.
  // 1-ok, 0-failed, -1-network error
  int (idaapi* add_bpt)(bpttype_t type, ea_t ea, int len);
  // Remove a breakpoint
  // Note: orig_bytes are used only for software breakpoints
  // to restore the old byte values overwritten by the breakpoint
  // For hardware breakpoints it must be NULL
  // 1-ok, 0-failed, -1-network error
  int (idaapi* del_bpt)(ea_t ea, const uchar *orig_bytes, int len);

// Open/close/read a remote file
  int  (idaapi* open_file)(const char *file, ulong *fsize); // -1-error
  void (idaapi* close_file)(int fn);
  ssize_t (idaapi* read_file)(int fn, ulong off, void *buf, size_t size);
};


#ifdef __BORLANDC__
#if sizeof(debugger_t) % 4
#error "Size of debugger_t is incorrect"
#endif
#endif

#pragma pack(pop)
#endif // _IDD_HPP
