root/headers/os/kernel/debugger.h
/*
 * Copyright 2005-2016 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _DEBUGGER_H
#define _DEBUGGER_H


#include <signal.h>

#include <image.h>
#include <OS.h>

// include architecture specific definitions
#include <arch/x86/arch_debugger.h>
#include <arch/x86_64/arch_debugger.h>
#include <arch/ppc/arch_debugger.h>
#include <arch/m68k/arch_debugger.h>
#include <arch/mipsel/arch_debugger.h>
#include <arch/arm/arch_debugger.h>
#include <arch/arm64/arch_debugger.h>
#include <arch/riscv64/arch_debugger.h>
#include <arch/sparc/arch_debugger.h>


#if defined(__x86_64__)
        typedef struct x86_64_debug_cpu_state debug_cpu_state;
#elif defined(__i386__)
        typedef struct x86_debug_cpu_state debug_cpu_state;
#elif defined(__POWERPC__)
        typedef struct ppc_debug_cpu_state debug_cpu_state;
#elif defined(__M68K__)
        typedef struct m68k_debug_cpu_state debug_cpu_state;
#elif defined(__MIPSEL__)
        typedef struct mipsel_debug_cpu_state debug_cpu_state;
#elif defined(__arm__)
        typedef struct arm_debug_cpu_state debug_cpu_state;
#elif (defined(__riscv) && __riscv_xlen == 64)
        typedef struct riscv64_debug_cpu_state debug_cpu_state;
#elif defined(__sparc64__)
        typedef struct sparc_debug_cpu_state debug_cpu_state;
#elif defined(__aarch64__) || defined(__arm64__)
        typedef struct arm64_debug_cpu_state debug_cpu_state;
#else
        #error unsupported architecture
#endif


#ifdef __cplusplus
extern "C" {
#endif

extern status_t install_default_debugger(port_id debuggerPort);
extern port_id  install_team_debugger(team_id team, port_id debuggerPort);
extern status_t remove_team_debugger(team_id team);
extern status_t debug_thread(thread_id thread);
extern void             wait_for_debugger(void);

// EXPERIMENTAL: Self-debugging functions. Will fail when a team debugger is
// installed. A breakpoint/watchpoint hit will cause the default debugger to
// be installed for the team.
extern status_t set_debugger_breakpoint(void *address);
extern status_t clear_debugger_breakpoint(void *address);
extern status_t set_debugger_watchpoint(void *address, uint32 type,
                                        int32 length);
extern status_t clear_debugger_watchpoint(void *address);


// team debugging flags
enum {
        // event mask: If a flag is set, any of the team's threads will stop when
        // the respective event occurs. None of the flags are enabled by default.
        // Always enabled are debugger() calls and hardware exceptions, as well as
        // the deletion of the debugged team.
        B_TEAM_DEBUG_SIGNALS                                            = 0x00010000,
        B_TEAM_DEBUG_PRE_SYSCALL                                        = 0x00020000,
        B_TEAM_DEBUG_POST_SYSCALL                                       = 0x00040000,
        B_TEAM_DEBUG_TEAM_CREATION                                      = 0x00080000,
        B_TEAM_DEBUG_THREADS                                            = 0x00100000,
        B_TEAM_DEBUG_IMAGES                                                     = 0x00200000,
        B_TEAM_DEBUG_PREVENT_EXIT                                       = 0x00400000,

        // new thread handling
        B_TEAM_DEBUG_STOP_NEW_THREADS                           = 0x01000000,

        B_TEAM_DEBUG_USER_FLAG_MASK                                     = 0xffff0000,
};

// per-thread debugging flags
enum {
        // event mask: If a flag is set, the thread will stop when the respective
        // event occurs. If there is a corresponding team flag, it is sufficient,
        // if either is set. Per default none of the flags is set.
        B_THREAD_DEBUG_PRE_SYSCALL                                      = 0x00010000,
        B_THREAD_DEBUG_POST_SYSCALL                                     = 0x00020000,

        // child thread handling
        B_THREAD_DEBUG_STOP_CHILD_THREADS                       = 0x00100000,
        B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS      = 0x00200000,

        B_THREAD_DEBUG_USER_FLAG_MASK                           = 0xffff0000,
};

// in case of a B_EXCEPTION_OCCURRED event: the type of the exception
typedef enum {
        B_NON_MASKABLE_INTERRUPT        = 0,
        B_MACHINE_CHECK_EXCEPTION,
        B_SEGMENT_VIOLATION,
        B_ALIGNMENT_EXCEPTION,
        B_DIVIDE_ERROR,
        B_OVERFLOW_EXCEPTION,
        B_BOUNDS_CHECK_EXCEPTION,
        B_INVALID_OPCODE_EXCEPTION,
        B_SEGMENT_NOT_PRESENT,
        B_STACK_FAULT,
        B_GENERAL_PROTECTION_FAULT,
        B_FLOATING_POINT_EXCEPTION,
} debug_exception_type;

// Value indicating how a stopped thread shall continue.
enum {
        B_THREAD_DEBUG_HANDLE_EVENT = 0,        // handle the event normally
                                                                                // (e.g. a signal is delivered, a
                                                                                // CPU fault kills the team,...)
        B_THREAD_DEBUG_IGNORE_EVENT,            // ignore the event and continue as if
                                                                                // it didn't occur (e.g. a signal or
                                                                                // a CPU fault will be ignored)
};

// watchpoint types (ToDo: Check PPC support.)
enum {
        B_DATA_READ_WATCHPOINT = 0,                     // !x86
        B_DATA_WRITE_WATCHPOINT,
        B_DATA_READ_WRITE_WATCHPOINT,
};

// how to apply signal ignore masks
typedef enum {
        B_DEBUG_SIGNAL_MASK_AND = 0,
        B_DEBUG_SIGNAL_MASK_OR,
        B_DEBUG_SIGNAL_MASK_SET,
} debug_signal_mask_op;

#define B_DEBUG_SIGNAL_TO_MASK(signal) (1ULL << ((signal) - 1))

// maximal number of bytes to read/write via B_DEBUG_MESSAGE_{READ,WRITE]_MEMORY
enum {
        B_MAX_READ_WRITE_MEMORY_SIZE    = 1024,
};

// messages to the debug nub thread
typedef enum {
        B_DEBUG_MESSAGE_READ_MEMORY     = 0,    // read from the team's memory
        B_DEBUG_MESSAGE_WRITE_MEMORY,           // write to the team's memory
        B_DEBUG_MESSAGE_SET_TEAM_FLAGS,         // set the team's debugging flags
        B_DEBUG_MESSAGE_SET_THREAD_FLAGS,       // set a thread's debugging flags
        B_DEBUG_MESSAGE_CONTINUE_THREAD,        // continue a stopped thread
        B_DEBUG_MESSAGE_SET_CPU_STATE,          // change a stopped thread's CPU state
        B_DEBUG_MESSAGE_GET_CPU_STATE,          // get the thread's current CPU state
        B_DEBUG_MESSAGE_SET_BREAKPOINT,         // set a breakpoint
        B_DEBUG_MESSAGE_CLEAR_BREAKPOINT,       // clear a breakpoint
        B_DEBUG_MESSAGE_SET_WATCHPOINT,         // set a watchpoint
        B_DEBUG_MESSAGE_CLEAR_WATCHPOINT,       // clear a watchpoint
        B_DEBUG_MESSAGE_SET_SIGNAL_MASKS,       // set/get a thread's masks of signals
        B_DEBUG_MESSAGE_GET_SIGNAL_MASKS,       //  the debugger is interested in
        B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER,     // set/get the team's signal handler for
        B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER,     //  a signal
        B_DEBUG_MESSAGE_CLONE_AREA,                     // clone a team area into the debugger team

        B_DEBUG_MESSAGE_PREPARE_HANDOVER = 1000, // prepares the debugged team for being
                                                                                // handed over to another debugger;
                                                                                // the new debugger can just invoke
                                                                                // install_team_debugger()
        B_DEBUG_MESSAGE_WRITE_CORE_FILE,        // write a core file

        B_DEBUG_MESSAGE_START_PROFILER = 2000, // start/stop sampling
        B_DEBUG_MESSAGE_STOP_PROFILER,          //
} debug_nub_message;

// messages sent to the debugger
typedef enum {
        B_DEBUGGER_MESSAGE_THREAD_DEBUGGED = 0, // debugger message in reaction to
                                                                                        // an invocation of debug_thread()
        B_DEBUGGER_MESSAGE_DEBUGGER_CALL,               // thread called debugger()
        B_DEBUGGER_MESSAGE_BREAKPOINT_HIT,              // thread hit a breakpoint
        B_DEBUGGER_MESSAGE_WATCHPOINT_HIT,              // thread hit a watchpoint
        B_DEBUGGER_MESSAGE_SINGLE_STEP,                 // thread was single-stepped
        B_DEBUGGER_MESSAGE_PRE_SYSCALL,                 // begin of a syscall
        B_DEBUGGER_MESSAGE_POST_SYSCALL,                // end of a syscall
        B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,             // thread received a signal
        B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED,  // an exception occurred
        B_DEBUGGER_MESSAGE_TEAM_CREATED,                // the debugged team created a new
                                                                                        // one
        B_DEBUGGER_MESSAGE_TEAM_DELETED,                // the debugged team is gone
        B_DEBUGGER_MESSAGE_TEAM_EXEC,                   // the debugged team executes exec()
                                                                                        // (implies all images have been deleted)
        B_DEBUGGER_MESSAGE_THREAD_CREATED,              // a thread has been created
        B_DEBUGGER_MESSAGE_THREAD_DELETED,              // a thread has been deleted
        B_DEBUGGER_MESSAGE_IMAGE_CREATED,               // an image has been created
        B_DEBUGGER_MESSAGE_IMAGE_DELETED,               // an image has been deleted

        B_DEBUGGER_MESSAGE_PROFILER_UPDATE,             // flush the profiling buffer for a
                                                                                        // thread

        B_DEBUGGER_MESSAGE_HANDED_OVER,                 // the debugged team has been
                                                                                        // handed over to another debugger,
                                                                                        // sent to both debuggers
} debug_debugger_message;


// profile events -- when the buffer is in variable stack depth format, a sample
// count entry >= B_DEBUG_PROFILE_EVENT_BASE indicates a profile event
enum {
        B_DEBUG_PROFILE_EVENT_BASE                              = 0x80000000,
        B_DEBUG_PROFILE_EVENT_PARAMETER_MASK    = 0x0000ffff,
                // & with to get the event's parameter count

        B_DEBUG_PROFILE_IMAGE_EVENT                             = 0x80010001
                // single parameter: the respective image event counter
};


// #pragma mark -
// #pragma mark ----- messages to the debug nub thread -----

// B_DEBUG_MESSAGE_READ_MEMORY

typedef struct {
        port_id         reply_port;             // port to send the reply to
        void            *address;               // address from which to read
        int32           size;                   // number of bytes to read
} debug_nub_read_memory;

typedef struct {
        status_t        error;                  // B_OK, if reading went fine
        int32           size;                   // the number of bytes actually read
                                                                // > 0, iff error == B_OK
        char            data[B_MAX_READ_WRITE_MEMORY_SIZE];
                                                                // the read data
} debug_nub_read_memory_reply;

// B_DEBUG_MESSAGE_WRITE_MEMORY

typedef struct {
        port_id         reply_port;             // port to send the reply to
        void            *address;               // address to which to write
        int32           size;                   // number of bytes to write
        char            data[B_MAX_READ_WRITE_MEMORY_SIZE];
                                                                // data to write
} debug_nub_write_memory;

typedef struct {
        status_t        error;                  // B_OK, if writing went fine
        int32           size;                   // the number of bytes actually written
} debug_nub_write_memory_reply;

// B_DEBUG_MESSAGE_CLONE_AREA

typedef struct {
        port_id         reply_port;             // port to send the reply to
        const void      *address;               // address within area to clone
} debug_nub_clone_area;

typedef struct {
        area_id         area;                   // the ID of the newly cloned area, or an error
        const void      *address;               // corresponding address in clone
} debug_nub_clone_area_reply;

// B_DEBUG_MESSAGE_SET_TEAM_FLAGS

typedef struct {
        int32           flags;                  // the new team debugging flags
} debug_nub_set_team_flags;

// B_DEBUG_MESSAGE_SET_THREAD_FLAGS

typedef struct {
        thread_id       thread;                 // the thread
        int32           flags;                  // the new thread debugging flags
} debug_nub_set_thread_flags;

// B_DEBUG_MESSAGE_CONTINUE_THREAD

typedef struct {
        thread_id       thread;                 // the thread
        uint32          handle_event;   // how to handle the occurred event
        bool            single_step;    // true == single step, false == run full speed
} debug_nub_continue_thread;

// B_DEBUG_MESSAGE_SET_CPU_STATE

typedef struct {
        thread_id                       thread;                         // the thread
        debug_cpu_state         cpu_state;                      // the new CPU state
} debug_nub_set_cpu_state;

// B_DEBUG_MESSAGE_GET_CPU_STATE

typedef struct {
        port_id                                 reply_port;             // port to send the reply to
        thread_id                               thread;                 // the thread
} debug_nub_get_cpu_state;

typedef struct {
        status_t                                error;          // != B_OK, if something went wrong
                                                                                // (bad thread ID, thread not stopped)
        debug_debugger_message  message;        // the reason why the thread stopped
        debug_cpu_state                 cpu_state;      // the thread's CPU state
} debug_nub_get_cpu_state_reply;

// B_DEBUG_MESSAGE_SET_BREAKPOINT

typedef struct {
        port_id         reply_port;             // port to send the reply to
        void            *address;               // breakpoint address
} debug_nub_set_breakpoint;

typedef struct {
        status_t        error;                  // B_OK, if the breakpoint has been set
                                                                // successfully
} debug_nub_set_breakpoint_reply;

// B_DEBUG_MESSAGE_CLEAR_BREAKPOINT

typedef struct {
        void            *address;               // breakpoint address
} debug_nub_clear_breakpoint;

// B_DEBUG_MESSAGE_SET_WATCHPOINT

typedef struct {
        port_id         reply_port;             // port to send the reply to
        void            *address;               // watchpoint address
        uint32          type;                   // watchpoint type (see type constants above)
        int32           length;                 // number of bytes to watch (typically 1, 2,
                                                                // 4); architecture specific alignment
                                                                // restrictions apply.
} debug_nub_set_watchpoint;

typedef struct {
        status_t        error;                  // B_OK, if the watchpoint has been set
                                                                // successfully
} debug_nub_set_watchpoint_reply;

// B_DEBUG_MESSAGE_CLEAR_WATCHPOINT

typedef struct {
        void            *address;               // watchpoint address
} debug_nub_clear_watchpoint;

// B_DEBUG_MESSAGE_SET_SIGNAL_MASKS

typedef struct {
        thread_id                               thread;                         // the thread
        uint64                                  ignore_mask;            // the mask for signals the
                                                                                                // debugger wishes not to be
                                                                                                // notified of
        uint64                                  ignore_once_mask;       // the mask for signals the
                                                                                                // debugger wishes not to be
                                                                                                // notified of when they next
                                                                                                // occur
        debug_signal_mask_op    ignore_op;                      // what to do with ignore_mask
        debug_signal_mask_op    ignore_once_op;         // what to do with
                                                                                                // ignore_once_mask
} debug_nub_set_signal_masks;

// B_DEBUG_MESSAGE_GET_SIGNAL_MASKS

typedef struct {
        port_id         reply_port;                     // port to send the reply to
        thread_id       thread;                         // the thread
} debug_nub_get_signal_masks;

typedef struct {
        status_t        error;                          // B_OK, if the thread exists
        uint64          ignore_mask;            // the mask for signals the debugger wishes
                                                                        // not to be notified of
        uint64          ignore_once_mask;       // the mask for signals the debugger wishes
                                                                        // not to be notified of when they next
                                                                        // occur
} debug_nub_get_signal_masks_reply;

// B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER

typedef struct {
        int                                     signal;         // the signal
        struct sigaction        handler;        // the new signal handler
} debug_nub_set_signal_handler;

// B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER

typedef struct {
        port_id                         reply_port;     // port to send the reply to
        int                                     signal;         // the signal
} debug_nub_get_signal_handler;

typedef struct {
        status_t                        error;          // B_OK, if the thread exists
        struct sigaction        handler;        // the signal handler
} debug_nub_get_signal_handler_reply;

// B_DEBUG_MESSAGE_PREPARE_HANDOVER

// no parameters, no reply

// B_DEBUG_START_PROFILER

struct debug_profile_function {
        addr_t                  base;   // function base address
        size_t                  size;   // function size
};

typedef struct {
        port_id                         reply_port;             // port to send the reply to
        thread_id                       thread;                 // thread to profile
        bigtime_t                       interval;               // sample interval
        area_id                         sample_area;    // area into which the sample will be
                                                                                // written
        int32                           stack_depth;    // number of return address per hit
        bool                            variable_stack_depth;
                                                                                // variable number of samples per hit;
                                                                                // cf. debug_profiler_update
        bool                            profile_kernel; // sample kernel stack frames
} debug_nub_start_profiler;

typedef struct {
        status_t                        error;
        int32                           image_event;    // number of the last image event
        bigtime_t                       interval;               // actual sample interval (might
                                                                                // differ from the requested one)
} debug_nub_start_profiler_reply;

// B_DEBUG_STOP_PROFILER

typedef struct {
        port_id                         reply_port;             // port to send the reply to
        thread_id                       thread;                 // thread to profile
} debug_nub_stop_profiler;

// B_DEBUG_WRITE_CORE_FILE

typedef struct {
        port_id                         reply_port;             // port to send the reply to
        char                            path[B_PATH_NAME_LENGTH];
                                                                                // path of the core file; must not exist
                                                                                // yet; must be absolute
} debug_nub_write_core_file;

typedef struct {
        status_t        error;                                  // B_OK on success
} debug_nub_write_core_file_reply;


// reply is debug_profiler_update

// union of all messages structures sent to the debug nub thread
typedef union {
        debug_nub_read_memory                   read_memory;
        debug_nub_write_memory                  write_memory;
        debug_nub_clone_area                    clone_area;
        debug_nub_set_team_flags                set_team_flags;
        debug_nub_set_thread_flags              set_thread_flags;
        debug_nub_continue_thread               continue_thread;
        debug_nub_set_cpu_state                 set_cpu_state;
        debug_nub_get_cpu_state                 get_cpu_state;
        debug_nub_set_breakpoint                set_breakpoint;
        debug_nub_clear_breakpoint              clear_breakpoint;
        debug_nub_set_watchpoint                set_watchpoint;
        debug_nub_clear_watchpoint              clear_watchpoint;
        debug_nub_set_signal_masks              set_signal_masks;
        debug_nub_get_signal_masks              get_signal_masks;
        debug_nub_set_signal_handler    set_signal_handler;
        debug_nub_get_signal_handler    get_signal_handler;
        debug_nub_start_profiler                start_profiler;
        debug_nub_stop_profiler                 stop_profiler;
        debug_nub_write_core_file               write_core_file;
} debug_nub_message_data;


// #pragma mark -
// #pragma mark ----- messages to the debugger -----

// first member of all debugger messages -- not a message by itself
typedef struct {
        thread_id       thread;                 // the thread being the event origin
        team_id         team;                   // the thread's team
        port_id         nub_port;               // port to debug nub for this team (only set
                                                                // for synchronous messages)
} debug_origin;

// B_DEBUGGER_MESSAGE_THREAD_DEBUGGED

typedef struct {
        debug_origin            origin;
} debug_thread_debugged;

// B_DEBUGGER_MESSAGE_DEBUGGER_CALL

typedef struct {
        debug_origin            origin;
        void                            *message;       // address of the message passed to
                                                                        // debugger()
} debug_debugger_call;

// B_DEBUGGER_MESSAGE_BREAKPOINT_HIT

typedef struct {
        debug_origin            origin;
        debug_cpu_state         cpu_state;      // cpu state
} debug_breakpoint_hit;

// B_DEBUGGER_MESSAGE_WATCHPOINT_HIT

typedef struct {
        debug_origin            origin;
        debug_cpu_state         cpu_state;      // cpu state
} debug_watchpoint_hit;

// B_DEBUGGER_MESSAGE_SINGLE_STEP

typedef struct {
        debug_origin            origin;
        debug_cpu_state         cpu_state;      // cpu state
} debug_single_step;

// B_DEBUGGER_MESSAGE_PRE_SYSCALL

typedef struct {
        debug_origin    origin;
        uint32                  syscall;                // the syscall number
        uint8                   args[128];              // syscall arguments
} debug_pre_syscall;

// B_DEBUGGER_MESSAGE_POST_SYSCALL

typedef struct {
        debug_origin    origin;
        bigtime_t               start_time;             // time of syscall start
        bigtime_t               end_time;               // time of syscall completion
        uint64                  return_value;   // the syscall's return value
        uint32                  syscall;                // the syscall number
        uint8                   args[128];              // syscall arguments
} debug_post_syscall;

// B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED

typedef struct {
        debug_origin            origin;
        int                                     signal;         // the signal
        struct sigaction        handler;        // the signal handler
        siginfo_t                       info;           // the signal info
        bool                            deadly;         // true, if handling the signal will kill
                                                                        // the team
} debug_signal_received;

// B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED

typedef struct {
        debug_origin                    origin;
        debug_exception_type    exception;              // the exception
        int                                             signal;                 // the signal that will be sent,
                                                                                        // when the thread continues
                                                                                        // normally
} debug_exception_occurred;

// B_DEBUGGER_MESSAGE_TEAM_CREATED

typedef struct {
        debug_origin    origin;
        team_id                 new_team;               // the newly created team
} debug_team_created;

// B_DEBUGGER_MESSAGE_TEAM_DELETED

typedef struct {
        debug_origin    origin;                 // thread is < 0, team is the deleted team
                                                                        // (asynchronous message)
        status_t                status;                 // the exit code of the team
        int                             signal;                 // the signal causing the exit, < 0 if none
        team_usage_info usage;                  // the usage info of the team
} debug_team_deleted;

// B_DEBUGGER_MESSAGE_TEAM_EXEC

typedef struct {
        debug_origin    origin;
        int32                   image_event;    // number of the image event
} debug_team_exec;

// B_DEBUGGER_MESSAGE_THREAD_CREATED

typedef struct {
        debug_origin    origin;                 // the thread that created the new thread
        team_id                 new_thread;             // the newly created thread
} debug_thread_created;

// B_DEBUGGER_MESSAGE_THREAD_DELETED

typedef struct {
        debug_origin    origin;                 // the deleted thread (asynchronous message)
        status_t                status;                 // the exit code of the thread
} debug_thread_deleted;

// B_DEBUGGER_MESSAGE_IMAGE_CREATED

typedef struct {
        debug_origin    origin;
        image_info              info;                   // info for the image
        int32                   image_event;    // number of the image event
} debug_image_created;

// B_DEBUGGER_MESSAGE_IMAGE_DELETED

typedef struct {
        debug_origin    origin;
        image_info              info;                   // info for the image
        int32                   image_event;    // number of the image event
} debug_image_deleted;

// B_DEBUGGER_MESSAGE_PROFILER_UPDATE

typedef struct {
        debug_origin            origin;
        int32                           image_event;    // number of the last image event; all
                                                                                // samples were recorded after this
                                                                                // event and before the next one
        int32                           stack_depth;    // number of return addresses per tick
        int32                           sample_count;   // number of samples in the buffer
        int32                           dropped_ticks;  // number of ticks that had been
                                                                                // dropped, since the buffer was full
        bool                            variable_stack_depth;
                                                                                // the number of samples per hit is
                                                                                // variable, i.e. the format for the
                                                                                // samples of a hit in the buffer is
                                                                                //   <n> <sample 1> ... <sample n>
                                                                                // instead of
                                                                                //   <sample 1> ... <sample stack_depth>
        bool                            stopped;                // if true, the thread is no longer
                                                                                // being profiled
        bigtime_t                       last_cpu_time;  // only set if "stopped" is
} debug_profiler_update;

// B_DEBUGGER_MESSAGE_HANDED_OVER

typedef struct {
        debug_origin    origin;                 // thread is < 0, team is the deleted team
                                                                        // (asynchronous message)
        team_id                 debugger;               // the new debugger
        port_id                 debugger_port;  // the port the new debugger uses
        thread_id               causing_thread; // the thread that caused entering the
                                                                        // debugger in the first place, -1 if the
                                                                        // debugger wasn't attached automatically
} debug_handed_over;

// union of all messages structures sent to the debugger
typedef union {
        debug_thread_debugged                   thread_debugged;
        debug_debugger_call                             debugger_call;
        debug_breakpoint_hit                    breakpoint_hit;
        debug_watchpoint_hit                    watchpoint_hit;
        debug_single_step                               single_step;
        debug_pre_syscall                               pre_syscall;
        debug_post_syscall                              post_syscall;
        debug_signal_received                   signal_received;
        debug_exception_occurred                exception_occurred;
        debug_team_created                              team_created;
        debug_team_deleted                              team_deleted;
        debug_team_exec                                 team_exec;
        debug_thread_created                    thread_created;
        debug_thread_deleted                    thread_deleted;
        debug_image_created                             image_created;
        debug_image_deleted                             image_deleted;
        debug_profiler_update                   profiler_update;
        debug_handed_over                               handed_over;

        debug_origin                                    origin; // for convenience (no real message)
} debug_debugger_message_data;


extern void get_debug_message_string(debug_debugger_message message,
                char *buffer, int32 bufferSize);
extern void get_debug_exception_string(debug_exception_type exception,
                char *buffer, int32 bufferSize);


#ifdef __cplusplus
}       // extern "C"
#endif

#endif  // _DEBUGGER_H