
#include <idd.hpp>

#ifdef REMOTE_DEBUGGER
#ifndef DEBUGGER_SERVER
#define DEBUGGER_CLIENT
#endif
#endif

#if defined(DEBUGGER_SERVER) || defined(DEBUGGER_CLIENT)
#define REMOTE_DEBUGGING
#endif

#define TIMEOUT         (1000/25)       // in milliseconds, timeout for polling
                                        // network and debugger

// functions exported by the local debugger client for the remote:

int  rpc_set_debug_names(const ea_t *ea, const char *const *name, int qty);
bool rpc_get_many_bytes(ea_t ea, void *buf, ssize_t size);
void rpc_smsg(const char *str);
void rpc_serror(const char *str);

// functions exported by the remote debugger client for the local:

#define DECLARE_REMOTE_FUNCTIONS(prefix)                                       \
int idaapi prefix ## init(bool _is_dll,                                        \
                       bool _debug_debugger,                                   \
                       ea_t begin_ea,                                          \
                       const char *_input_file_path);                          \
void idaapi prefix ## term(void);                                              \
int  idaapi prefix ## process_get_info(int n, process_info_t *info);           \
int  idaapi prefix ## detach_process(void);                                    \
int  idaapi prefix ## start_process(const char *path,                          \
                                const char *args,                              \
                                const char *startdir,                          \
                                bool is_gui,                                   \
                                ulong input_file_crc32);                       \
int  idaapi prefix ## get_debug_event(debug_event_t *event, bool ida_is_idle); \
int  idaapi prefix ## attach_process(process_id_t process_id, int event_id);   \
int  idaapi prefix ## prepare_to_pause_process(void);                          \
int  idaapi prefix ## exit_process(void);                                      \
int  idaapi prefix ## continue_after_event(const debug_event_t *event);        \
void idaapi prefix ## set_exception_info(const exception_info_t *info, int qty); \
void idaapi prefix ## stopped_at_debug_event(const debug_event_t *event);      \
int  idaapi prefix ## thread_suspend(thread_id_t thread_id);                   \
int  idaapi prefix ## thread_continue(thread_id_t thread_id);                  \
int  idaapi prefix ## thread_set_step(thread_id_t thread_id);                  \
int  idaapi prefix ## thread_read_registers(thread_id_t thread_id,             \
                                            regval_t *values,                  \
                                            int count);                        \
int  idaapi prefix ## thread_write_register(thread_id_t thread_id,             \
                                            int reg_idx,                       \
                                            const regval_t *value);            \
int  idaapi prefix ## thread_get_sreg_base(thread_id_t thread_id,              \
                                           int sreg_value,                     \
                                           ea_t *ea);                          \
int  idaapi prefix ## get_memory_info(memory_info_t **areas, int *qty);        \
ssize_t idaapi prefix ## read_memory(ea_t ea, void *buffer, size_t size);      \
ssize_t idaapi prefix ## write_memory(ea_t ea, const void *buffer, size_t size); \
int  idaapi prefix ## is_ok_bpt(bpttype_t type, ea_t ea, int len);             \
int  idaapi prefix ## add_bpt(bpttype_t type, ea_t ea, int len);               \
int  idaapi prefix ## del_bpt(ea_t ea, const uchar *orig_bytes, int len);      \
int  idaapi prefix ## open_file(const char *file, ulong *fsize);               \
void idaapi prefix ## close_file(int fn);                                      \
ssize_t idaapi prefix ## read_file(int fn, ulong off, void *buf, size_t size);

DECLARE_REMOTE_FUNCTIONS(remote_)
DECLARE_REMOTE_FUNCTIONS(rpc_)

#ifdef REMOTE_DEBUGGER
#define prefix rpc_
#else
#define prefix remote_
#endif

#define r_init                     paste(prefix, init)
#define r_term                     paste(prefix, term)
#define r_process_get_info         paste(prefix, process_get_info)
#define r_detach_process           paste(prefix, detach_process)
#define r_start_process            paste(prefix, start_process)
#define r_get_debug_event          paste(prefix, get_debug_event)
#define r_attach_process           paste(prefix, attach_process)
#define r_prepare_to_pause_process paste(prefix, prepare_to_pause_process)
#define r_exit_process             paste(prefix, exit_process)
#define r_continue_after_event     paste(prefix, continue_after_event)
#define r_set_exception_info       paste(prefix, set_exception_info)
#define r_stopped_at_debug_event   paste(prefix, stopped_at_debug_event)
#define r_thread_suspend           paste(prefix, thread_suspend)
#define r_thread_continue          paste(prefix, thread_continue)
#define r_thread_set_step          paste(prefix, thread_set_step)
#define r_thread_read_registers    paste(prefix, thread_read_registers)
#define r_thread_write_register    paste(prefix, thread_write_register)
#define r_get_memory_info          paste(prefix, get_memory_info)
#define r_read_memory              paste(prefix, read_memory)
#define r_write_memory             paste(prefix, write_memory)
#define r_is_ok_bpt                paste(prefix, is_ok_bpt)
#define r_add_bpt                  paste(prefix, add_bpt)
#define r_del_bpt                  paste(prefix, del_bpt)
#define r_thread_get_sreg_base     paste(prefix, thread_get_sreg_base)

#define paste(x, y) paste2(x, y)
#define paste2(x, y) x ## y

void neterr(const char *module);
bool close_remote(void);
bool open_remote(const char *hostname, int port_number);

extern bool has_pending_event;
extern bool poll_debug_events;
extern debugger_t debugger;

char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize);
char *debug_event_str(const debug_event_t *ev);
