/*BEGIN_LEGAL 
Intel Open Source License 

Copyright (c) 2002-2014 Intel Corporation. All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.  Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.  Neither the name of
the Intel Corporation nor the names of its contributors may be used to
endorse or promote products derived from this software without
specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
END_LEGAL */
// <ORIGINAL-AUTHOR>: Greg Lueck
// <COMPONENT>: debugger-protocol
// <FILE-TYPE>: component public header

#ifndef DEBUGGER_PROTOCOL_HPP
#define DEBUGGER_PROTOCOL_HPP

#include <string>
#include "fund.hpp"
#include "util.hpp"
#include "debugger-protocol/forward.hpp"

#if defined(DEBUGGER_PROTOCOL_BUILD_SHARED)
#   define DEBUGGER_PROTOCOL_API    FUND_EXPORT
#elif defined(DEBUGGER_PROTOCOL_USE_SHARED)
#   define DEBUGGER_PROTOCOL_API    FUND_IMPORT
#else
#   define DEBUGGER_PROTOCOL_API
#endif


/*! @mainpage DEBUGGER_PROTOCOL library
 *
 * The DEBUGGER_PROTOCOL library provides a low-level interface for communicating
 * between the back-end of a debugger and the front-end of a debugger.  The
 * library supports front-end and back-end users.
 *
 * The DEBUGGER_PROTOCOL library currently supports the GDB protocol, which means
 * a back-end using this API can communicate with GDB.  Likewise, a debugger
 * front-end using this API can communicate with a GDB back-end (target stub).
 * In the future, support may be added for other protocols.
 *
 * To get started writing a debugger front-end, see IFRONTEND.
 *
 * To get started writing a debugger back-end, see IBACKEND.
 */

/*! @brief The DEBUGGER_PROTOCOL library. */
namespace DEBUGGER_PROTOCOL {

/*!
 * Identifier representing a target thread, typically an O/S identifier.  The value zero is reserved.
 * Thread ID's may be reused once a thread exits.
 */
typedef unsigned long THREAD;

/*!
 * Identifier representing a register.  This is either one of the "generic" registers
 * (e.g. REG_PC) or a value 'REG_END + i' where \e i is an index into the \e regs
 * parameter to IBACKEND::SetRegisters() or IFRONTEND::SetRegisters().
 */
typedef unsigned REG;

/*!
 * Represents an ID to an "image", which is a loadable module in the target process.
 * An image can represent a DLL, shared library, or the main executable program.  Image
 * ID's may be reused once an image is unloaded.
 */
typedef unsigned long IMAGE;

/*!
 * An identifier representing a target process, typically an O/S process ID.  Process
 * ID's may be reused once a process exits.
 */
typedef unsigned long PROCESS;

/*!
 * O/S specific information about an image.  Pointers to this type must be cast according
 * to the \e os parameter that is passed to CreateBackEnd() or returned from
 * IFRONTEND::GetBackEndOs().
 *
 * - For OS_LINUX32 or OS_LINUX64, cast to IMAGE_INFO_LINUX, which is defined in
 *   "debugger-protocol/image-linux.hpp".
 *
 * - For OS_WINDOWS32 or OS_WINDOWS64, cast to IMAGE_INFO_WINDOWS, which is defined in
 *   "debugger-protocol/image-windows.hpp".
 */
typedef void IMAGE_INFO;

/*!
 * Identifies an O/S specific "event", according to the \e os parameter passed to
 * CreateBackEnd() or returned from IFRONTEND::GetBackEndOs().
 *
 * - For OS_LINUX32 and OS_LINUX64, this is a signal number.  In API's where the
 *   back-end reports an event to the front-end, the value zero indicates that the
 *   target process received an unknown signal.
 *
 * - For OS_WINDOWS32 and OS_WINDOWS64, this is an exception code.
 */
typedef unsigned long EVENT;

/*!
 * O/S specific additional information about an event, which is used when the back-end
 * supports BACKEND_FEATURE_EVENT_INFO.  Pointers to this type must be cast according
 * to the \e os parameter that is passed to CreateBackEnd() or returned from
 * IFRONTEND::GetBackEndOs().
 *
 * - For OS_LINUX32, cast to EVENT_INFO_LINUX32, which is defined in "debugger-protocol/event-linux.hpp".
 * - For OS_LINUX64, cast to EVENT_INFO_LINUX64, which is defined in "debugger-protocol/event-linux.hpp".
 *
 * - For OS_WINDOWS32, cast to EVENT_INFO_WINDOWS32 which is defined in "debugger-protocol/event-windows.hpp".
 * - For OS_WINDOWS64, cast to EVENT_INFO_WINDOWS64 which is defined in "debugger-protocol/event-windows.hpp".
 */
typedef void EVENT_INFO;

/*!
 * O/S specific information about a thread, which is used when the back-end supports
 * BACKEND_FEATURE_THREAD_INFO.  Pointers to this type must be cast according
 * to the \e os parameter that is passed CreateBackEnd() or returned from
 * IFRONTEND::GetBackEndOs().
 *
 * - For OS_LINUX32 or OS_LINUX64, cast to THREAD_INFO_LINUX, which is defined in
 *   "debugger-protocol/thread-linux.hpp".
 *
 * - For OS_WINDOWS32 or OS_WINDOWS64, cast to THREAD_INFO_WINDOWS, which is defined in
 *   "debugger-protocol/thread-windows.hpp".
 */
typedef void THREAD_INFO;


/*!
 * Flags that can be used with the Initialize() function.
 */
enum INITIALIZE_FLAG
{
    INITIALIZE_FLAG_NONE = 0,
    INITIALIZE_FLAG_TCP = (1<<0)        ///< Initialize for a TCP front- or back-end connection.
};
typedef FUND::UINT64 INITIALIZE_FLAGS;  ///< Bit mask of INITIALIZE_FLAG's.

/*!
 * Possible O/S types.
 */
enum OS
{
    OS_INVALID,
    OS_LINUX32,
    OS_LINUX64,
    OS_WINDOWS32,
    OS_WINDOWS64,
    OS_MAC32,
    OS_MAC64
};

/*!
 * Generic register ID's that are common for all targets.
 */
enum
{
    REG_INVALID,
    REG_PC,         ///< The program counter.
    REG_FP,         ///< The frame pointer.
    REG_SP,         ///< The stack pointer.
    REG_FLAGS,      ///< The flags.
    REG_END
};

/*!
 * Possible types of the debugger front-end.
 */
enum FRONTEND_TYPE
{
    FRONTEND_TYPE_UNKNOWN,              ///< Type not known.
    FRONTEND_TYPE_GDB,                  ///< The GNU debugger.
    FRONTEND_TYPE_IDB,                  ///< The Intel debugger.
    FRONTEND_TYPE_VISUAL_STUDIO_VSDBG,  ///< Visual Studio via VSDBG.
    FRONTEND_TYPE_VISUAL_STUDIO,        ///< Visual Studio via native connection.
    FRONTEND_TYPE_LLDB                  ///< The LLVM debugger.
};

/*!
 * Possible types of the debugger back-end.
 */
enum BACKEND_TYPE
{
    BACKEND_TYPE_UNKNOWN,       ///< Type not known.
    BACKEND_TYPE_PIN            ///< The Pin dynamic instrumentation system.
};

/*!
 * Possible features supported by a debugger front-end.
 */
enum FRONTEND_FEATURE
{
    FRONTEND_FEATURE_NONE = 0,     ///< No extended features supported.

    /*!
     * The front-end will dynamically change the expected register set based on the
     * target description returned by the back-end.  (See
     * ITARGET_DESCRIPTION::GetTargetDescription(), IFRONTEND::SetRegisters(), and
     * IBACKEND::SetRegisters().)
     */
    FRONTEND_FEATURE_DYNAMIC_REGISTERS = (1<<0),

    /*!
     * This option controls the behavior when two or more threads stop simultaneously.
     * For example, two threads might each trigger a breakpoint at the same time, or
     * one thread might trigger a breakpoint while another raises an exception.
     *
     * With the default behavior, the back-end reports each stop-reason separately.  The
     * front-end gets notified via INOTIFICATIONS::NotifyStopped() and one thread will
     * report a stop-reason via ICOMMANDS::GetThreadStopReason().  The back-end keeps
     * the other thread's stop-reason pending.  When the front-end continues execution,
     * the back-end calls NotifyStopped() again and reports the pending stop-reason
     * without actually resuming the target process.  In this mode, the back-end uses
     * various heuristics to maintain the consistency of the pending stop-reasons.  For
     * example, if there is a pending STOP_REASON_BREAKPOINT when the front-end removes
     * the associated breakpoint, the back-end will implicitly squash the pending
     * STOP_REASON_BREAKPOINT notification.
     *
     * If the front-end enables FRONTEND_FEATURE_MULTIPLE_STOP_REASONS, the algorithm is
     * different.  Instead, the back-end reports all stop-reasons simultaneously.  The
     * front-end is notified with a single call to INOTIFICATIONS::NotifyStopped() and
     * each thread reports its own stop-reason via ICOMMANDS::GetThreadStopReason().
     */
    FRONTEND_FEATURE_MULTIPLE_STOP_REASONS = (1<<1)
};
typedef FUND::UINT64 FRONTEND_FEATURES;     ///< Bit mask of FRONTEND_FEATURE's.

/*!
 * Possible features supported by a debugger back-end.
 */
enum BACKEND_FEATURE
{
    BACKEND_FEATURE_NONE = 0,  ///< No extended features supported.

    /*!
     * The back-end supports the IBREAKPOINTS interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_BREAKPOINTS).  If a back-end does not
     * support this feature, the front-end will set breakpoints by overwriting
     * a target instruction with a software trap.  When such a breakpoint
     * triggers, the back-end stops the target with STOP_REASON_EVENT.
     */
    BACKEND_FEATURE_BREAKPOINTS = (1<<0),

    /*!
     * The back-end supports the ICUSTOM_BREAKPOINTS interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_CUSTOM_BREAKPOINTS).
     */
    BACKEND_FEATURE_CUSTOM_BREAKPOINTS = (1<<1),

    /*!
     * The back-end supports the ICUSTOM_COMMANDS interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_CUSTOM_COMMANDS).
     */
    BACKEND_FEATURE_CUSTOM_COMMANDS = (1<<2),

    /*!
     * The back-end supports the IKILL_WITH_NOTIFICATION interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_KILL_WITH_NOTIFICATION).
     */
    BACKEND_FEATURE_KILL_WITH_NOTIFICATION = (1<<3),

    /*!
     * The back-end supports the ITARGET_DESCRIPTION interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_TARGET_DESCRIPTION).
     */
    BACKEND_FEATURE_TARGET_DESCRIPTION = (1<<4),

    /*!
     * The back-end supports the IEVENT_INTERCEPTION interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_EVENT_INTERCEPTION).
     */
    BACKEND_FEATURE_EVENT_INTERCEPTION = (1<<5),

    /*!
     * The back-end supports the IIMAGE_EXTENSIONS interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_IMAGE_EXTENSIONS).
     */
    BACKEND_FEATURE_IMAGE_EXTENSIONS = (1<<6),

    /*!
     * The back-end supports the ITHREAD_EXTENSIONS interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_THREAD_EXTENSIONS).
     */
    BACKEND_FEATURE_THREAD_EXTENSIONS = (1<<7),

    /*!
     * The back-end supports additional event information via EVENT_INFO.  Back-ends that do
     * not support this feature can ignore the EVENT_INFO parameters in all methods.
     */
    BACKEND_FEATURE_EVENT_INFO = (1<<8),

    /*!
     * The back-end supports the ability to resume a thread with CONTINUE_MODE_GO_NEW_EVENT
     * or CONTINUE_MODE_STEP_NEW_EVENT.  Back-ends that do not support this feature will
     * never receives these modes in calls to ICOMMANDS::SetContinueMode().
     */
    BACKEND_FEATURE_CONTINUE_WITH_NEW_EVENT = (1<<9),

    /*!
     * The back-end supports the IPROCESS_INFO interface via
     * ICOMMANDS::GetInterface(INTERFACE_ID_PROCESS_INFO).
     */
    BACKEND_FEATURE_PROCESS_INFO = (1<<10)
};
typedef FUND::UINT64 BACKEND_FEATURES;  ///< Bit mask of BACKEND_FEATURE's.

/*!
 * Possible options for a communication endpoint.
 */
enum ENDPOINT_OPTION
{
    ENDPOINT_OPTION_NONE = 0,  ///< No options specified.

    /*!
     * Do not use run-length compression for response data sent by the back-end.
     * This option is ignored by the front-end because only the back-end will
     * attempt to compress the data it sends.  This option is useful because it
     * makes the ILOG_NOTIFICATIONS messages easier for a human to read.
     */
    ENDPOINT_OPTION_NO_COMPRESSION = (1<<0),

    /*!
     * This option only applies to endpoints that act as a server.  By default,
     * a server-like endpoint only allows a client to connect from the same
     * machine (i.e. via the TCP loopback address).  This option allows a server
     * to accept a connection even from a different machine (i.e. using the
     * INADDR_ANY local address).
     */
    ENDPOINT_OPTION_ALLOW_REMOTE_CLIENTS = (1<<1),

    /*!
     * This options requires from the backend to always send the thread id in the
     * reply packets.
     */
    ENDPOINT_OPTION_ALWAYS_SEND_THREAD = (1<<2),

    /*!
     * This option enables the backend to send textual representation of the stop
     * reason in the packet.
     */
    ENDPOINT_OPTION_SEND_STOP_REASON = (1<<3)
};
typedef FUND::UINT64 ENDPOINT_OPTIONS;      ///< Bit mask of ENDPOINT_OPTION's.

/*!
 * Back-ends can provide some optional features via interfaces that are obtained
 * by calling ICOMMANDS::GetInterface().  This enumeration defines the
 * set of possible optional interfaces.
 */
enum INTERFACE_ID
{
    INTERFACE_ID_BREAKPOINTS,               ///< Back-end defines IBREAKPOINTS.
    INTERFACE_ID_CUSTOM_BREAKPOINTS,        ///< Back-end defines ICUSTOM_BREAKPOINTS.
    INTERFACE_ID_CUSTOM_COMMANDS,           ///< Back-end defines ICUSTOM_COMMANDS.
    INTERFACE_ID_KILL_WITH_NOTIFICATION,    ///< Back-end defines IKILL_WITH_NOTIFICATION.
    INTERFACE_ID_TARGET_DESCRIPTION,        ///< Back-end defines ITARGET_DESCRIPTION.
    INTERFACE_ID_EVENT_INTERCEPTION,        ///< Back-end defines IEVENT_INTERCEPTION.
    INTERFACE_ID_IMAGE_EXTENSIONS,          ///< Back-end defines IIMAGE_EXTENSIONS.
    INTERFACE_ID_THREAD_EXTENSIONS,         ///< Back-end defines ITHREAD_EXTENSIONS.
    INTERFACE_ID_PROCESS_INFO               ///< Back-end defines IPROCESS_INFO.
};

/*!
 * Possible notifications that can be enabled with IIMAGE_EXTENSIONS::SetImageNotifications().
 */
enum IMAGE_NOTIFICATION
{
    IMAGE_NOTIFICATION_NONE = 0,        ///< Do not enable any image notifications.

    /*!
     * Enable STOP_REASON_IMAGE_LOAD and STOP_REASON_IMAGE_MULTIPLE notifications when an image is loaded.
     */
    IMAGE_NOTIFICATION_LOAD = (1<<0),

    /*!
     * Enable STOP_REASON_IMAGE_UNLOAD and STOP_REASON_IMAGE_MULTIPLE notifications when an image is unloaded.
     */
    IMAGE_NOTIFICATION_UNLOAD = (1<<1)
};
typedef FUND::UINT64 IMAGE_NOTIFICATIONS;   ///< Bit mask of IMAGE_NOTIFICATION's.

/*!
 * Possible notifications that can be enabled with ITHREAD_EXTENSIONS::SetThreadNotifications().
 */
enum THREAD_NOTIFICATION
{
    THREAD_NOTIFICATION_NONE = 0,           ///< Do not enable any thread notifications.
    THREAD_NOTIFICATION_START = (1<<0),     ///< Enable STOP_REASON_THREAD_START notifications.
    THREAD_NOTIFICATION_EXIT = (1<<1)       ///< Enable STOP_REASON_THREAD_EXIT notifications.
};
typedef FUND::UINT64 THREAD_NOTIFICATIONS;  ///< Bit mask of THREAD_NOTIFICATION's.


/*!
 * Possible continuation modes when debugger front-end continues a target thread.
 */
enum CONTINUE_MODE
{
    CONTINUE_MODE_FROZEN,               ///< Thread should remain frozen.

    /*!
     * Thread should resume execution.  If it had previously stopped with STOP_REASON_EVENT,
     * that event is not propagated back to the application.  The thread resumes as though
     * the event did not occur.
     */
    CONTINUE_MODE_GO_SQUASH_EVENT,

    /*!
     * Thread should resume execution.  If it had previously stopped with STOP_REASON_EVENT,
     * it continues executing with that event (e.g. by executing the application's handler).
     * If the application did not stop due to an event, the behavior is the same as with
     * CONTINUE_MODE_GO_SQUASH_EVENT.
     */
    CONTINUE_MODE_GO_PASS_EVENT,

    /*!
     * Thread should resume execution.  If it had previously stopped with STOP_REASON_EVENT,
     * that event is discarded.  Regardless of how the thread previously stopped, it resumes
     * as though it had received the specified event.  This mode is only supported by back-ends
     * that have the BACKEND_FEATURE_CONTINUE_WITH_NEW_EVENT feature.
     */
    CONTINUE_MODE_GO_NEW_EVENT,

    /*!
     * This is exactly like CONTINUE_MODE_GO_SQUASH_EVENT except the thread stops
     * after executing a single instruction.
     */
    CONTINUE_MODE_STEP_SQUASH_EVENT,

    /*!
     * This is exactly like CONTINUE_MODE_GO_PASS_EVENT except the thread stops
     * after executing one instruction.  If the event causes the thread to enter
     * a handler, execution stops before the first instruction of that handler.
     */
    CONTINUE_MODE_STEP_PASS_EVENT,

    /*!
     * This is exactly like CONTINUE_MODE_GO_NEW_EVENT except the thread stops
     * after executing one instruction.  If the event causes the thread to enter
     * a handler, execution stops before the first instruction of that handler.
     * This mode is only supported by back-ends that have the
     * BACKEND_FEATURE_CONTINUE_WITH_NEW_EVENT feature.
     */
    CONTINUE_MODE_STEP_NEW_EVENT
};

/*!
 * Possible reasons why an application thread might stop.
 */
enum STOP_REASON
{
    /*!
     * Thread triggered a breakpoint.  This can only happen for breakpoints set
     * via IBREAKPOINTS::SetBreakpoint(), not for breakpoints set by overwriting an
     * instruction with a software trap.
     */
    STOP_REASON_BREAKPOINT,

    /*!
     * Thread triggered a breakpoint that was initiated by the target.  Such breakpoints
     * do not correspond to IBREAKPOINTS::SetBreakpoint() nor do they correspond to
     * breakpoints set when the debugger front-end overwrites an instruction with a
     * software trap.  The front-end can get additional information about these
     * breakpoints via ICUSTOM_BREAKPOINTS::GetThreadStopMessage().
     */
    STOP_REASON_CUSTOM_BREAK,

    /*!
     * Thread was stopped by the back-end, for example in response to a call
     * to ICOMMANDS::Break() or because some other thread triggered a breakpoint.
     */
    STOP_REASON_STOPPED,

    STOP_REASON_STEP,           ///< Thread completed a single-step.
    STOP_REASON_EVENT,          ///< Thread received an O/S event, see EVENT.


    /* Notifications enabled by ITHREAD_EXTENSIONS::SetThreadNotifications() */

    /*!
     * New thread started and is stopped at the PC of its first instruction.
     */
    STOP_REASON_THREAD_START,

    /*!
     * A thread is about to exit and is stopped at the PC of its last instruction
     * (usually a system call which terminates the thread).  The thread will truly
     * exit when it is next continued or single-stepped.  Any attempt to change the
     * thread's registers will be ignored.
     */
    STOP_REASON_THREAD_EXIT,


    /* Notifications enabled by IIMAGE_EXTENSIONS::SetImageNotifications() */

    STOP_REASON_IMAGE_LOAD,     ///< Image loaded, see IIMAGE_EXTENSIONS::GetThreadStopImage().
    STOP_REASON_IMAGE_UNLOAD,   ///< Image unloaded, see IIMAGE_EXTENSIONS::GetThreadStopImage().

    /*!
     * More than one image was loaded or unloaded at the same time.  Use
     * IIMAGE_EXTENSIONS::GetImageCount() and IIMAGE_EXTENSIONS::GetImageId() to get the new
     * set of loaded images.
     */
    STOP_REASON_IMAGE_MULTIPLE
};

/*!
 * Return status for some methods that block.
 */
enum RESULT
{
    RESULT_OK,              ///< Method completed successfully.
    RESULT_ERROR,           ///< Method failed.
    RESULT_INTERRUPTED      ///< Method was interrupted.
};

/*!
 * Possible return values from IBACKEND::HandleCommands() when a debugger
 * session completes.
 */
enum SESSION_RESULT
{
    SESSION_RESULT_TERMINATED,      ///< Target process terminated or was killed by the front-end.
    SESSION_RESULT_DETACHED,        ///< Front-end detached via ICOMMANDS::Detach().
    SESSION_RESULT_INTERRUPTED,     ///< Session interrupted via IBACKEND::InterruptCommandThread().
    SESSION_RESULT_ERROR            ///< Communication failure with the front-end.
};

/*!
 * Flags used with IFRONTEND::InvalidateCachedState() to tell what information should be
 * invalidated.
 */
enum INVALIDATE_FLAG
{
    INVALIDATE_FLAG_REGISTERS = (1<<0)  ///< Invalidate the register values for a single thread.
};
typedef FUND::UINT64 INVALIDATE_FLAGS;  ///< Bit mask of INVALIDATE_FLAG's.


/*!
 * Information describing how to connect to an endpoint using a TCP transport.
 */
struct /*<POD>*/ TCP_INFO
{
    int _localPort;     ///< The local port of a socket listening for a connection.
};

/*!
 * Describes a single register in the target program.
 */
struct /*<POD>*/ REG_DESCRIPTION
{
    unsigned _widthInBits;      ///< Width (bits) of the register.  Currently, the width
                                ///<  must be a multiple of 8.
    REG _correspondingGeneric;  ///< The corresponding "generic" register ID, if any.  Or,
                                ///<  REG_INVALID, if there is no corresponding generic.
                                ///<  There should be exactly one register that corresponds
                                ///<  to each generic.  (E.g. there should be exactly one
                                ///<  REG_PC register.)
    bool _accelerated;          ///< If TRUE, the back-end automatically sends the value
                                ///<  of this register whenever the target program stops.
                                ///<  This saves a protocol request if the front-end
                                ///<  usually needs this register when the target stops.
    const char* _name;          ///< The textual name of the register
    int _gccId;            ///< The GCC/DWARF compiler registers number for this
                                ///< register (used for EH frame and other compiler
                                ///< information that is encoded in the executable files).
};


/*!
 * This function must be called before using any other function in the debugger-protocol
 * library.  Typically, it is called once from the application's start-up code, but it
 * is legal to call it more than once so long as each call has a matching call to
 * Cleanup().  The Initialize() and Cleanup() functions have no internal locking, so
 * callers must provide synchronization if they are called from multi-threaded code.
 *
 *  @param[in] flags    A bit-mask of flags indicating which library features the caller
 *                       intends to use.
 *
 * @return  TRUE on success.
 */
DEBUGGER_PROTOCOL_API bool Initialize(INITIALIZE_FLAGS flags);

/*!
 * This function should be called to clean up resources when the caller is done using
 * the debugger-protocol library.  The Initialize() and Cleanup() functions have no
 * internal locking, so callers must provide synchronization if they are called from
 * multi-threaded code.
 *
 *  @param[in] flags    The same flags that were passed to the matching call to
 *                       Initialize().
 *
 * @return  TRUE on success.
 */
DEBUGGER_PROTOCOL_API bool Cleanup(INITIALIZE_FLAGS flags);


/*!
 * Represents a communication endpoint for a debugger front-end.
 *
 * Clients using this interface need to be aware that the debugger alternates between
 * two modes: "run mode" and "command mode".  When the target application is running,
 * the debugger is in "run mode", and most attempts to send commands to the target
 * will fail.  Once the target application stops, the debugger enters "command mode"
 * and the user can send commands to the target process.
 */
class /*<INTERFACE>*/ IFRONTEND
{
public:
    /*!
     * If this front-end is a server, retrieve the communication information that
     * the back-end needs in order to connect.
     *
     *  @param[out] info    Receives the connection information.
     *
     * @return  TRUE on success (only if the front-end is a server).
     */
    virtual bool GetServerInfo(TCP_INFO *info) = 0;

    /*!
     * The front-end and back-end must communicate with each other using
     * the same set of target registers.  The front-end calls this method
     * to define the register set that it will use.  The back-end should call
     * IBACKEND::SetRegisters() with the same set of registers.
     *
     * This method must be called before the front-end calls any of the
     * following ICOMMANDS methods:
     *
     *  - GetRegisterValue()
     *  - SetRegisterValue()
     *  - ContinueThreads()
     *  - Any of the GetThreadStop*() methods
     *  - GetThreadExitStatus()
     *
     * A front-end can dynamically choose the register set if the back-end
     * supports the feature BACKEND_FEATURE_TARGET_DESCRIPTION.  To do this, the
     * front-end can call ITARGET_DESCRIPTION::GetTargetDescription() to query
     * the supported registers, and then dynamically create \a regs based on the
     * returned description.  Front-ends that support this ability should define
     * the feature FRONTEND_FEATURE_DYNAMIC_REGISTERS.
     *
     *  @param[in] regs     Describes the register set to use when
     *                       communicating with the back-end.  This
     *                       can either be a predefined description from
     *                       "debugger-protocol/regs-XXX.hpp" or it can
     *                       be a custom description.
     *  @param[in] nregs    The number of entries in \a regs.
     *
     * @return  TRUE on success.  FALSE if there is an error with \a regs or
     *           if registers have already been accessed via one of the ICOMMANDS
     *           methods listed above.
     */
    virtual bool SetRegisters(const REG_DESCRIPTION *regs, unsigned nregs) = 0;

    /*!
     * If this front-end is a client, connect to a back-end which must be a server.
     * This method should not be called for server-like front-ends.
     *
     * After connecting, the target process is stopped and the debugger is in
     * "command mode".
     *
     *  @param[in] ip        The IP address of the machine running the back-end.
     *  @param[in] port      The port number for the back-end.
     *
     * @return  On success, an object that can be used to send commands to the back-end.
     *           NULL on failure.
     */
    virtual ICOMMANDS *ConnectToServer(const std::string &ip, int port) = 0;

    /*!
     * If this front-end is a server, wait for a connection from a back-end which
     * must be a client.  This method should not be called for client-like front-ends.
     *
     * After connecting, the target process is stopped and the debugger is in
     * "command mode".
     *
     *  @param[in] timeout  A timeout value (milliseconds).  This method fails if
     *                       the back-end doesn't connect in the timeout period.
     *                       If \a timeout is zero, wait forever.
     *
     * @return  On success, an object that can be used to send commands to the back-end.
     *           NULL on failure.
     */
    virtual ICOMMANDS *ConnectFromClient(unsigned timeout) = 0;

    /*!
     * Tells the type of the back-end client.  This is only useful after
     * a successful call to ConnectToServer() or ConnectFromClient().
     *
     * @return  The type of the back-end client, or BACKEND_TYPE_UNKNOWN if not
     *           connected.
     */
    virtual BACKEND_TYPE GetBackEndType() = 0;

    /*!
     * Tells the set of features supported by the back-end.  This is only useful after
     * a successful call to ConnectToServer() or ConnectFromClient().
     *
     * @return  If called after successfully connecting to the back-end, returns a
     *           bitwise 'or' of features supported by the back end.  If called before
     *           a successful connect, returns BACKEND_FEATURE_NONE.
     */
    virtual BACKEND_FEATURES GetBackEndFeatures() = 0;

    /*!
     * @return  If called after successfully connecting to the back-end, returns the
     *           O/S type of the target process.
     */
    virtual OS GetBackEndOs() = 0;

    /*!
     * This method should be called when the debugger is in "run mode" to check for
     * notifications from the back-end.  If \a block is TRUE, this call waits until
     * a notification is sent from the back-end.  If \a block is FALSE, this call
     * checks for a notification and returns immediately.
     *
     * When there is a notification, this methods calls exactly one of the methods
     * in \a receiver to indicate why the target stopped or exited.
     *
     *  @param[in] receiver     An object that receives notifications from
     *                           the debugger back-end.
     *  @param[in] block        If TRUE, call blocks until there is a notification.
     *
     * @return  TRUE on success, FALSE on communication error.  Note that this method
     *           returns TRUE even when there is no notification (e.g. when \a block
     *           is FALSE or when InterruptNotificationThread() interrupts this method).
     */
    virtual bool HandleNotifications(INOTIFICATIONS *receiver, bool block) = 0;

    /*!
     * Interrupt the thread executing the HandleNotifications() method, causing it to
     * return with TRUE status.  The InterruptNotificationThread() method returns
     * immediately, without waiting for HandleNotifications() to return.
     *
     * Calling this method enables a "sticky" interrupt flag.  Therefore, if no thread
     * is blocked in HandleNotifications(), the next call to that method will return
     * immediately.  The sticky interrupt flag is cleared by calling ClearInterruptFlag()
     * or ICOMMANDS::ContinueThreads().
     *
     * The following two usage models are supported.  The front-end may call this method
     * from a separate thread while another thread is blocked in HandleNotifications().
     * Or, when used on Unix, the front-end thread that is blocked in HandleNotifications()
     * may set up a signal handler that calls InterruptNotificationThread().
     */
    virtual void InterruptNotificationThread() = 0;

    /*!
     * Clears the "sticky" interrupt flag that is set by InterruptNotificationThread().
     * This method has no effect if the flag is not set.
     */
    virtual void ClearInterruptFlag() = 0;

    /*!
     * The front-end object may keep some information about the state of the target process
     * cached in order to get this information more quickly in the future.  The front-end
     * object will automatically invalidate this cached information whenever the target
     * resumes execution, so normally clients using the front-end don't need to be aware
     * of this caching.  However, if the client changes the target state in a way that
     * the front-end can't observe, the client should call InvalidateCachedState() to
     * explicitly invalidate any cached information.
     *
     * One scenario where this is required is when the client uses ICUSTOM_COMMANDS to
     * change the state of the target process.  Since the front-end object doesn't know
     * the side-effect of commands sent this way, the client is responsible for calling
     * InvalidateCachedState() if the custom command changes the target's state.
     *
     *  @param[in] thread   Tells which thread's information to invalidate.  This parameter
     *                       may be ignored, depending on the value of \a flags.
     *  @param[in] flags    Bit-mask of flags telling what information to invalidate.
     */
    virtual void InvalidateCachedState(THREAD thread, INVALIDATE_FLAGS flags) = 0;

    /*!
     * Register a listener that receives log messages about the debugger protocol.  This
     * is useful for debugging the debugger-protocol itself.
     *
     *  @param[in] receiver     Object that receives notifications.
     */
    virtual void AddDebugLogReceiver(ILOG_NOTIFICATIONS *receiver) = 0;

    /*!
     * Unregister a listener, so it no longer receives log messages.
     *
     *  @param[in] receiver     Object previously registered via AddDebugLogReceiver().
     */
    virtual void RemoveDebugLogReceiver(ILOG_NOTIFICATIONS *receiver) = 0;

    /*!
     * The destructor automatically disconnects from the back-end and unregisters any
     * listeners registered via AddDebugLogReceiver().
     */
    virtual ~IFRONTEND() {}
};

/*!
 * Create a new debugger front-end communication endpoint, which uses the GDB
 * remote protocol over a TCP transport.  A front-end typically connects to a
 * back-end in another process.  Either the front-end or the back-end must act
 * as a communication "server" and the other must act as a "client".  The
 * server establishes the communication channel and waits for the client to
 * connect to it.
 *
 * Before calling this function, Initialize() must be called with the flag
 * INITIALIZE_FLAG_TCP.
 *
 *  @param[in] isServer     Tells if the front-end acts as a server.
 *  @param[in] type         The type of the front-end client.
 *  @param[in] features     A bitwise 'or' of features that the front-end supports.
 *  @param[in] options      A bitwise 'or' of options that affect the front-end.
 *
 * @return  A new debugger front-end object.
 */
DEBUGGER_PROTOCOL_API IFRONTEND *CreateFrontEnd(bool isServer, FRONTEND_TYPE type,
    FRONTEND_FEATURES features, ENDPOINT_OPTIONS options);


/*!
 * Represents a communication endpoint for a debugger back-end.
 *
 * The IBACKEND object has only limited thread safety.  Aside from the following cases,
 * the caller must ensure that only one thread at a time calls into the IBACKEND object:
 *
 *  - It is permissible for a thread to call IBACKEND::InterruptCommandThread() while
 *    another thread calls any IBACKEND method.
 *  - It is permissible for a thread to call any INOTIFICATIONS method while another
 *    thread calls any IBACKEND method.
 */
class /*<INTERFACE>*/ IBACKEND
{
public:
    /*!
     * If this back-end is a server, retrieve the communication information that
     * the front-end needs in order to connect.
     *
     *  @param[out] info    Receives the connection information.
     *
     * @return  TRUE on success (only if the back-end is a server).
     */
    virtual bool GetServerInfo(TCP_INFO *info) = 0;

    /*!
     * This method defines the register set used to communicate with the
     * front-end.  It must be called before calling HandleCommands().
     *
     * If a back-end does NOT support BACKEND_FEATURE_TARGET_DESCRIPTION,
     * it can call SetRegisters() even before connecting with the front-end.
     *
     * If a back-end DOES support BACKEND_FEATURE_TARGET_DESCRIPTION, it
     * should wait until after connecting with the front-end.  Once connected,
     * query the front-end's feature with GetFrontEndFeatures() and see if
     * it supports FRONTEND_FEATURE_DYNAMIC_REGISTERS.  If not, call
     * SetRegisters() with a default set of registers.  If it does, call
     * SetRegisters() where \a regs matches the target description sent
     * to the front-end.
     *
     *  @param[in] regs     Describes the register set to use when
     *                       communicating with the front-end.  This
     *                       can either be a predefined description from
     *                       "debugger-protocol/regs-XXX.hpp" or it can
     *                       be a custom description.
     *  @param[in] nregs    The number of entries in \a regs.
     *
     * @return  TRUE on success.  FALSE if there is an error with \a regset
     *           or if SetRegisters() is called too late.
     */
    virtual bool SetRegisters(const REG_DESCRIPTION *regs, unsigned nregs) = 0;

    /*!
     * Retrieve an interface that can be used to send notifications to the debugger
     * front-end.  This method may be called even before the back-end is connected
     * to a front-end.
     *
     * @return  An interface that can be used to send notifications to the debugger
     *           front-end.
     */
    virtual INOTIFICATIONS *GetNotificationListener() = 0;

    /*!
     * This method is the first step when connecting to a front-end from a client-like
     * back-end.  When you use this method, the front-end must be a server.  The
     * connection sequence is as follows:
     *
     *  - Call ConnectToServer() to connect with the front-end.
     *
     *  - Tell the target process to stop and then call WaitForStopAfterConnect().
     *    The target process should call an INOTIFICATIONS method to indicate
     *    that it has stopped or exited.  If the target process is already stopped,
     *    you may call INOTIFICATIONS before calling WaitForStopAfterConnect().
     *
     *  - This is a good time to do any initialization that depends on the type
     *    or features of the front-end.  In particular, this is a good time to call
     *    SetRegisters() if you have not already done so.
     *
     *  - Call HandleCommands() to handle commands from the front-end.
     *
     *  @param[in] ip           The IP address of the machine running the front-end.
     *  @param[in] port         The port number for the front-end.
     *
     * @return  TRUE on success, FALSE on communication error.
     */
    virtual bool ConnectToServer(const std::string &ip, int port) = 0;

    /*!
     * This method is the first step when connecting to a front-end from a server-like
     * back-end.  When you use this method, the front-end must be a client.  The
     * connection sequence is as follows:
     *
     *  - Call ConnectFromClient() to connect with the front-end.
     *
     *  - Tell the target process to stop and then call WaitForStopAfterConnect().
     *    The target process should call an INOTIFICATIONS method to indicate
     *    that it has stopped or exited.  If the target process is already stopped,
     *    you may call INOTIFICATIONS before calling WaitForStopAfterConnect().
     *
     *  - This is a good time to do any initialization that depends on the type
     *    or features of the front-end.  In particular, this is a good time to call
     *    SetRegisters() if you have not already done so.
     *
     *  - Call HandleCommands() to handle commands from the front-end.
     *
     * This method might block indefinitely while waiting for the front-end to
     * connect, but it can be interrupted when another thread calls any of the
     * following methods:
     *
     *  - InterruptCommandThread()
     *  - INOTIFICATIONS::NotifyTerminatedExit()
     *  - INOTIFICATIONS::NotifyTerminatedEvent()
     *
     * After being interrupted, you may call ConnectFromClient() again to resume
     * waiting for the front-end to connect.
     *
     * @return  RESULT_OK on success, RESULT_ERROR on communication error, or
     *           RESULT_INTERRUPTED if interrupted.
     */
    virtual RESULT ConnectFromClient() = 0;

    /*!
     * Tells the type of the front-end client.  This is only useful after connecting
     * to the front-end via ConnectToServer() or ConnectFromClient().
     *
     * @return  The type of the front-end client, or FRONTEND_TYPE_UNKNOWN if not
     *           connected.
     */
    virtual FRONTEND_TYPE GetFrontEndType() = 0;

    /*!
     * Tells the set of features supported by the front-end.  This is only useful after
     * connecting to the front-end via ConnectToServer() or ConnectFromClient().
     *
     * @return  If called after successfully connecting to the front-end, returns a
     *           bitwise 'or' of features supported by the front-end.  If called before
     *           a successful connect, returns FRONTEND_FEATURE_NONE.
     */
    virtual FRONTEND_FEATURES GetFrontEndFeatures() = 0;

    /*!
     * This is the second step when connecting the back-end to a front-end.  See
     * ConnectToServer() or ConnectFromClient() for the connection sequence.  This
     * method blocks until one of the following occurs:
     *
     *  - The target process stops or exits and calls one of the INOTIFICATIONS methods.
     *  - Another thread calls InterruptCommandThread().
     *  - The timeout expires.
     *
     * If this method is interrupted via InterruptCommandThread(), you may call
     * WaitForStopAfterConnect() again to resume waiting for the application to stop.
     *
     *  @param[in] timeout  Timeout period (milliseconds).  The value zero means wait
     *                       forever.
     *
     * @return  RESULT_OK if the process stops or exits, RESULT_ERROR on timeout, or
     *           RESULT_INTERRUPTED if interrupted.
     */
    virtual RESULT WaitForStopAfterConnect(unsigned timeout) = 0;

    /*!
     * This is the last step when connecting the back-end to a front-end.  See
     * ConnectToServer() or ConnectFromClient() for the connection sequence.  This
     * method enters a loop that handles commands sent from the front-end.  Since
     * it doesn't return until the debugger session completes, it is typically called
     * from a dedicated thread.
     *
     * This method returns when one of the following occurs:
     *
     *  - The process exits and sends a notification via INOTIFICATIONS.
     *    If the process is already exited when HandleCommands() is called,
     *    this method returns immediately.
     *
     *  - The front-end kills the target process.
     *
     *  - The front-end detaches from the target process.
     *
     *  - Another thread calls InterruptCommandThread().
     *
     *  - There is a communication failure with the front-end (e.g. the
     *    front-end terminates unexpectedly).
     *
     * If this method is interrupted via InterruptCommandThread(), you may call
     * HandleCommands() again to resume handling commands from the front-end.
     *
     *  @param[in] receiver     An object that receives and responds to commands
     *                           from the debugger front-end.
     *
     * @return  A return code which tells why the debugger session completed.
     */
    virtual SESSION_RESULT HandleCommands(ICOMMANDS *receiver) = 0;

    /*!
     * Reset the debugger communication channel after a fork.  If the debugger
     * back-end process does a fork(), this must be called by the child of the
     * fork().  Since forking is specific to Unix hosts, this method is only
     * relevant on Unix.
     *
     * If this is a server-like back-end, the \a followChild parameter controls
     * whether a new debugger communication channel is created for the child process.
     * If \a followChild is TRUE, the child process may connect to a new front-end
     * via ConnectFromClient().  Note that the back-end in the child process is
     * distinct from the back-end in the parent process, and the child process
     * should call GetServerInfo() to get the new connection information.
     *
     * Client-like back-ends do not support the \a followChild parameter, and
     * passing TRUE will result in an error return from ResetAfterFork().
     *
     * Regardless of the setting of \a followChild, the child process should
     * eventually call the ~IBACKEND() destructor in order to clean up resources.
     *
     * Note that there are generally no multi-thread safety issues when calling
     * ResetAfterFork() because a Unix process has only a single thread after a fork().
     *
     *  @param[in] followChild      If TRUE, a new communication endpoint is created
     *                               in the child process.  If FALSE, the endpoint
     *                               is disabled in the child process.
     */
    virtual bool ResetAfterFork(bool followChild) = 0;

    /*!
     * Interrupt another thread blocked in ConnectFromClient(), WaitForStopAfterConnect(),
     * or HandleCommands().  The InterruptCommandThread() method returns immediately,
     * without waiting for the blocked thread to return.
     */
    virtual void InterruptCommandThread() = 0;

    /*!
     * If this is a server-like back-end, you may call this method to reset the back-end,
     * allowing it to connect to a new front-end.  This is typically called after HandleCommands()
     * returns with SESSION_RESULT_DETACHED in order to allow the back-end to connect to a
     * new front-end (or to reconnect to the same front-end).
     *
     * This method does not change the back-end's connection information, so GetServerInfo()
     * will return the same information as before this call.
     *
     * This method must be serialized with any other thread's usage of this IBACKEND object.
     * No other thread may call InterruptCommandThread() or any INOTIFICATIONS method while
     * this thread calls ResetServerConnection().
     *
     * @return  TRUE on success.
     */
    virtual bool ResetServerConnection() = 0;

    /*!
     * Register a listener that receives log messages about the debugger protocol.  This
     * is useful for debugging the debugger-protocol itself.
     *
     *  @param[in] receiver     Object that receives notifications.
     */
    virtual void AddDebugLogReceiver(ILOG_NOTIFICATIONS *receiver) = 0;

    /*!
     * Unregister a listener, so it no longer receives log messages.
     *
     *  @param[in] receiver     Object previously registered via AddDebugLogReceiver().
     */
    virtual void RemoveDebugLogReceiver(ILOG_NOTIFICATIONS *receiver) = 0;

    /*!
     * If there is an active connection to the front-end when the destructor is called,
     * the connection is ungracefully closed.
     */
    virtual ~IBACKEND() {}
};

/*!
 * Create a new debugger back-end communication endpoint, which uses the GDB
 * remote protocol over a TCP transport.  A back-end typically connects to a
 * front-end in another process.  Either the front-end or the back-end must act
 * as a communication "server" and the other must act as a "client".  The
 * server establishes the communication channel and waits for the client to
 * connect to it.
 *
 * Before calling this function, Initialize() must be called with the flag
 * INITIALIZE_FLAG_TCP.
 *
 *  @param[in] isServer     Tells if the back-end acts as a server.
 *  @param[in] os           The O/S type of the target program.
 *  @param[in] type         The type of the back-end client.
 *  @param[in] features     A bitwise 'or' of features supported by this back-end.
 *  @param[in] options      A bitwise 'or' of options that affect the back-end.
 *
 * @return  A new debugger back-end object.
 */
DEBUGGER_PROTOCOL_API IBACKEND *CreateBackEnd(bool isServer, OS os, BACKEND_TYPE type,
    BACKEND_FEATURES features, ENDPOINT_OPTIONS options);


/*!
 * This interface represents the basic commands that a debugger front-end can send to
 * the back-end.  Most of the methods in this interface may only be called when the
 * debugger is in "command mode", when all threads in the target process are stopped.
 * There are two different usage models.
 *
 * When used by a debugger front-end, the DEBUGGER_PROTOCOL library implements this
 * interface, and the front-end makes calls to it in order to send commands to the
 * back-end.  In this model, the front-end should expect that a call to a method in this
 * interface may fail due to a communication error with the back-end.  The "Error Returns"
 * section of each method describes this.
 *
 * When used by a back-end, the back-end implements this interface and the DEBUGGER_PROTOCOL
 * library calls it in order to notify the back-end of commands received from the front-end.
 * The DEBUGGER_PROTOCOL library will never incorrectly call a method when not in "command
 * mode", so the back-end need not check for this error condition.
 */
class /*<INTERFACE>*/ ICOMMANDS
{
public:
    /*!
     * @return  The current number of threads in the application.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns zero on communication error, or if called during "run mode".
     */
    virtual unsigned GetThreadCount() = 0;

    /*!
     * Retrieves the ID of a thread in the application.
     *
     *  @param[in] iThread  An index in the range [0, n-1], where \e n is the value
     *                       returned by GetThreadCount().
     *
     * @return  The ID of the indexed thread, zero if \a iThread is out of range.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns zero if called during "run mode".
     */
    virtual THREAD GetThreadId(unsigned iThread) = 0;

    /*!
     * Tells if a thread still exists in the application.
     *
     *  @param[in] thread   ID of a thread.
     *
     * @return  TRUE if the thread still exists.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool DoesThreadExist(THREAD thread) = 0;

    /*!
     * Tells how a thread should continue on the next call to ContinueThreads().
     * These settings remain in effect only until the next call to ContinueThreads().
     * Any thread with no explicit setting behaves as though \a mode is CONTINUE_MODE_FROZEN.
     *
     *  @param[in] thread       ID of a thread.
     *  @param[in] mode         Tells how to continue the thread.
     *  @param[in] evnt         If \a mode is CONTINUE_MODE_GO_NEW_EVENT or CONTINUE_MODE_STEP_NEW_EVENT,
     *                           \a evnt specifies the new event.
     *  @param[in] szEvntInfo   Size (bytes) of the \a evntInfo structure, if that parameter is non-NULL.
     *  @param[in] evntInfo     If the back-end supports BACKEND_FEATURE_EVENT_INFO and \a mode is
     *                           CONTINUE_MODE_GO_NEW_EVENT or CONTINUE_MODE_STEP_NEW_EVENT, \a evntInfo
     *                           gives additional information for the new event.  If \a evntInfo is
     *                           NULL, the back-end chooses a "generic" event of type \a evnt.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a evntInfo parameter is non-NULL and the back-end does not support
     *        BACKEND_FEATURE_EVENT_INFO.
     *      - The \a mode is CONTINUE_MODE_GO_NEW_EVENT or CONTINUE_MODE_STEP_NEW_EVENT,
     *        and the back-end does not support BACKEND_FEATURE_CONTINUE_WITH_NEW_EVENT.
     */
    virtual bool SetContinueMode(THREAD thread, CONTINUE_MODE mode, EVENT evnt,
        size_t szEvntInfo, const EVENT_INFO *evntInfo) = 0;

    /*!
     * Let all threads continue execution according to the settings made via
     * SetContinueMode().  It is an error to call this method if all threads
     * are set to CONTINUE_MODE_FROZEN.  This method returns immediately, without
     * waiting for the threads to stop again.  Calling this method puts the
     * debugger in "run mode".  When the target process stops again, the debugger
     * front-end is notified via one of the INOTIFICATIONS methods.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, of if called during "run mode".
     */
    virtual bool ContinueThreads() = 0;

    /*!
     * Tells why a thread stopped.  If a thread was frozen for the last call to ContinueThreads(),
     * its stop reason remains unchanged.
     *
     *  @param[in] thread       The ID of a thread.
     *  @param[out] reason      Tells why the thread stopped.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool GetThreadStopReason(THREAD thread, STOP_REASON *reason) = 0;

    /*!
     * Tells the O/S event that caused a thread to stop.
     *
     *  @param[in] thread       The ID of a thread.
     *  @param[out] evnt        Receives the O/S specific event that caused the thread
     *                           to stop.
     *  @param[in] szEvntInfo   Size (bytes) of the \a evntInfo structure if that parameter
     *                           is non-NULL.
     *  @param[out] evntInfo    If the back-end supports BACKEND_FEATURE_EVENT_INFO,
     *                           \a evntInfo may be non-NULL, in which case it receives
     *                           additional information about the event.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a thread did not stop with STOP_REASON_EVENT.
     *      - The \a evntInfo parameter is non-NULL and the back-end does not
     *        support BACKEND_FEATURE_EVENT_INFO.
     */
    virtual bool GetThreadStopEvent(THREAD thread, EVENT *evnt, size_t szEvntInfo,
        EVENT_INFO *evntInfo) = 0;

    /*!
     * This is the only method that may be called during "run mode".  It tells
     * the target process to stop, but does not wait for it to do so.  When the
     * target does stop, the debugger front-end is notified via one of the
     * INOTIFICATIONS methods.
     *
     * This method has no effect if called during "command mode".
     *
     * When called from a debugger front-end, the following two usage models are
     * supported.  The front-end may call this method from a separate thread while
     * another thread is blocked in IFRONTEND::HandleNotifications().  Or, when used
     * on Unix, the front-end thread that is blocked in IFRONTEND::HandleNotifications()
     * may set up a signal handler that calls Break().
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error.
     */
    virtual bool Break() = 0;

    /*!
     * Force all threads in the target application to terminate, killing the process.
     * There is NO notification sent via INOTIFICATIONS.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool Kill() = 0;

    /*!
     * Detach the debugger from the target application, and resume all threads.  Threads no
     * longer stop at breakpoints or notify the debugger front-end when an O/S event is received,
     * etc.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool Detach() = 0;

    /*!
     * Get the value of a register.
     *
     *  @param[in] thread   An ID for a thread.
     *  @param[in] reg      An ID for a register.  When called from a debugger front-end
     *                       \a reg may be a generic register ID.  However, the
     *                       DEBUGGER_PROTOCOL library never passes a generic ID, so the
     *                       back-end need not support this.
     *  @param[out] value   Receives the register's value.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool GetRegisterValue(THREAD thread, REG reg, UTIL::REGVALUE *value) = 0;

    /*!
     * Set the value of a register.
     *
     *  @param[in] thread   An ID for a thread.
     *  @param[in] reg      An ID for a register.  When called from a debugger front-end
     *                       \a reg may be a generic register ID.  However, the
     *                       DEBUGGER_PROTOCOL library never passes a generic ID, so the
     *                       back-end need not support this.
     *  @param[in] value    The new value for the register.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool SetRegisterValue(THREAD thread, REG reg, const UTIL::REGVALUE &value) = 0;

    /*!
     * Get the value of a memory region.
     *
     *  @param[in] range    Address range of the memory region.
     *  @param[out] value   Value and size of the memory range (target byte order).  The
     *                       size may be less than the specified range.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool GetMemoryValue(const UTIL::ANYRANGE &range, UTIL::DATA *value) = 0;

    /*!
     * Set the value of a memory range.
     *
     *  @param[in] addr             Starting address of the memory range.
     *  @param[in] value            Value and size of the data to write at that memory
     *                               range (target byte order).
     *  @param[out] sizeWritten     Receives the number of bytes successfully written,
     *                               which might be less than the size of \a value.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool SetMemoryValue(FUND::ANYADDR addr, const UTIL::DATA &value, size_t *sizeWritten) = 0;

    /*!
     * A back-end can provide some optional functionality through interfaces returned
     * by this method.  To define an optional interface, the back-end should also define
     * the corresponding BACKEND_FEATURE for that interface.
     *
     *  @param[in] id   An ID that tells which interface to return.
     *
     * @return  A pointer to an object that implements the requested interface.  Callers
     *           should cast this pointer to the appropriate interface.  If the back-end
     *           does not implement the interface, this method returns NULL.
     */
    virtual void *GetInterface(INTERFACE_ID id) = 0;

protected:
    virtual ~ICOMMANDS() {} ///< Do not call delete on ICOMMANDS.
};


/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_BREAKPOINTS.  This interface allows a front-end
 * to set breakpoints in a target-independent way.  The back-end decides how to implement
 * the breakpoint and notifies the front-end via STOP_REASON_BREAKPOINT.
 */
class /*<INTERFACE>*/ IBREAKPOINTS
{
public:
    /*!
     * Ask the back-end to set a breakpoint.
     *
     * The breakpoint may have either hardware or software semantics.  A non-zero
     * value for \a bpSize indicates a software semantic breakpoint.  This type of
     * breakpoint behaves as though the instruction at address \a addr was overwritten
     * by a trap instruction whose size is \a bpSize bytes.  After hitting a software
     * semantic breakpoint, the PC points \a bpSize bytes after the breakpoint location.
     * When resuming, the debugger front-end should clear the breakpoint, back up the
     * PC by \a bpSize bytes, and single-step over the breakpoint location.
     *
     * A zero value of \a bpSize indicates a hardware semantic breakpoint.  After
     * hitting this type of breakpoint, the PC points at the breakpoint location.  The
     * debugger front-end may resume from a hardware semantic breakpoint simply by
     * single-stepping or continuing.  It need not clear the breakpoint first.
     *
     * At most, only one breakpoint may be set at an address.  If there is a previous
     * breakpoint at \a addr, SetBreakpoint() overwrites it.
     *
     *  @param[in] addr     Address of the breakpoint.
     *  @param[in] bpSize   If zero, breakpoint has hardware semantics.  Otherwise,
     *                       it has software semantics, and the PC is bumped \a bpSize
     *                       bytes forward when the breakpoint is triggered.
     *  @param[out] wasSet  Receives TRUE if the breakpoint was successfully set.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool SetBreakpoint(FUND::ANYADDR addr, size_t bpSize, bool *wasSet) = 0;

    /*!
     * Ask the back-end to clear a breakpoint that was previously set via SetBreakpoint().
     *
     *  @param[in] addr         Address of the breakpoint.
     *  @param[out] wasCleared  Receives TRUE if \a addr corresponds to a previous
     *                           breakpoint and it was successfully cleared.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool ClearBreakpoint(FUND::ANYADDR addr, bool *wasCleared) = 0;

protected:
    virtual ~IBREAKPOINTS() {} ///< Do not call delete on IBREAKPOINTS.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_CUSTOM_BREAKPOINTS.  Back-ends that support this
 * interface support the concept of a "custom breakpoint", a breakpoint that the
 * back-end can decide to trigger based on some condition.  The back-end notifies
 * the front-end that such a breakpoint has triggered via STOP_REASON_CUSTOM_BREAK.
 * The front-end can determine why the breakpoint triggered by calling
 * ICUSTOM_BREAKPOINTS::GetThreadStopMessage().  Typically, a front-end can enable or
 * disable custom a breakpoint by sending a custom command via ICUSTOM_COMMANDS.
 */
class /*<INTERFACE>*/ ICUSTOM_BREAKPOINTS
{
public:
    /*!
     * Tells why a thread triggered a "custom breakpoint".  This is useful for threads
     * that stop with STOP_REASON_CUSTOM_BREAK.  The format of \a msg is not defined by
     * this API (it can be any format that the front-end and back-end agree upon).
     *
     * If the front-end is GDB, \a msg is a string with no trailing newline character,
     * which GDB displays to the user when process stops.  There can be embedded newline
     * characters in \a msg to print a multi-line description.
     *
     *  @param[in] thread   The ID of a thread.
     *  @param[out] msg     If the thread stopped with STOP_REASON_CUSTOM_BREAK, \a msg
     *                       describes the reason the breakpoint triggered.  If the thread
     *                       did not stop with STOP_REASON_CUSTOM_BREAK, \a msg is empty.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool GetThreadStopMessage(THREAD thread, std::string *msg) = 0;

protected:
    virtual ~ICUSTOM_BREAKPOINTS() {} ///< Do not call delete on ICUSTOM_BREAKPOINTS.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_CUSTOM_COMMANDS.
 */
class /*<INTERFACE>*/ ICUSTOM_COMMANDS
{
public:
    /*!
     * Ask the back-end to execute a custom command.  The formats of \a cmd and
     * \a response are not defined by this API (they can be any format that the
     * front-end and back-end agree upon).
     *
     * When the front-end is GDB, \a cmd is the text string that the user types
     * after the "monitor" command and \a response is displayed verbatim as a
     * response to the command.
     *
     *  @param[in] thread           The ID of the debugger's current "focus" thread.
     *  @param[in] cmd              The command string.
     *  @param[out] cmdRecognized   Receives TRUE if the back-end recognizes \a cmd.
     *                               If the back-end feels the command has some sort
     *                               of semantic error, it should set \a cmdRecognized
     *                               to TRUE and set \a response to a description of
     *                               the error.
     *  @param[out] response        Receives a response to the command.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool DoCustomCommand(THREAD thread, const std::string &cmd, bool *cmdRecognized,
        std::string *response) = 0;

protected:
    virtual ~ICUSTOM_COMMANDS() {} ///< Do not call delete on ICUSTOM_COMMANDS.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_KILL_WITH_NOTIFICATION.
 */
class /*<INTERFACE>*/ IKILL_WITH_NOTIFICATION
{
public:
    /*!
     * Tell the target application to terminate.
     *
     * This method returns immediately, putting the debugger in "run mode".  When
     * the target process actually terminates, the debugger front-end is notified
     * via INOTIFICATIONS::NotifyTerminatedExit().
     *
     *  @param[in] code     The application terminates with this exit code.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool KillWithNotification(FUND::INT64 code) = 0;

protected:
    virtual ~IKILL_WITH_NOTIFICATION() {} ///< Do not call delete on IKILL_WITH_NOTIFICATION.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_TARGET_DESCRIPTION.
 */
class /*<INTERFACE>*/ ITARGET_DESCRIPTION
{
public:
    /*!
     * Ask the back-end for a description of the target machine's features.  The format of the
     * returned information is not defined by this API (it can be any format that the front-end
     * and back-end agree upon).  However, the intent is that the information should describe
     * the target machine's registers, and possibly other information.
     *
     * When the front-end is GDB, \a name is the name of a "target feature" XML document.
     * By convention, the first name that GDB asks for is "target.xml".  However, that
     * document may include other documents, and GDB will make subsequent calls where
     * \a name references the included documents.
     *
     *  @param[in] name         Name of the description document to return.
     *  @param[out] content     On success, receives the requested description.  If the
     *                           document \a name is unknown, \a content is set
     *                           to be empty.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE on communication error, or if called during "run mode".
     */
    virtual bool GetTargetDescription(const std::string &name, UTIL::DATA *content) = 0;

protected:
    virtual ~ITARGET_DESCRIPTION() {} ///< Do not call delete on ITARGET_DESCRIPTION.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_EVENT_INTERCEPTION.
 */
class /*<INTERFACE>*/ IEVENT_INTERCEPTION
{
public:
    /*!
     * Notifies the back-end that the application need not notify the front-end if the
     * application receives an O/S specific event.  Instead, the application can handle
     * the event as it normally would.  This setting takes effect on the next call to
     * ContinueThreads().  These preferences are "sticky", so they remain in effect until
     * explicitly changed.
     *
     * Some targets may not support this request, or may only support it for certain
     * events.  The back-end is free to ignore the request and provide a notification for
     * the event anyway.
     *
     *  @param[in] evnt     An O/S specific event.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if called during "run mode".
     */
    virtual bool MarkEventNotIntercepted(EVENT evnt) = 0;

    /*!
     * Notifies the back-end that the application should stop and notify the
     * front-end whenever it receives any of this target's O/S events.  This is
     * the default behavior, so this method is only needed to override a previous
     * setting made via MarkEventNotIntercepted().  This setting takes effect on the
     * next call to ContinueThreads().
     *
     * Some targets may not support intercepting all events.  In such cases, this
     * method applies only to those events that can be intercepted.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if called during "run mode".
     */
    virtual bool MarkAllEventsIntercepted() = 0;

protected:
    virtual ~IEVENT_INTERCEPTION() {} ///< Do not call delete on IEVENT_INTERCEPTION.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_IMAGE_EXTENSIONS.
 */
class /*<INTERFACE>*/ IIMAGE_EXTENSIONS
{
public:
    /*!
     * Set the notifications that will be triggered when the target application loads or
     * unloads images.  By default, the back-end does not trigger any notifications when
     * images are loaded or unloaded.
     *
     *  @param[in] notifications    A bit-mask indicating which events should trigger
     *                               notifications.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     */
    virtual bool SetImageNotifications(IMAGE_NOTIFICATIONS notifications) = 0;

    /*!
     * Tells the number of images currently loaded in the application.
     *
     *  @param[out] count   Receives the number of images.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     */
    virtual bool GetImageCount(unsigned *count) = 0;

    /*!
     * Retrieves the ID of an image in the application.
     *
     *  @param[in] iImage       An index in the range [0, n-1], where \e n is the value
     *                           provided by GetImageCount().
     *  @param[out] image       Receives the image identifier.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a iImage is out of range.
     *
     * @par Error Returns (when implemented by debugger back-end)
     *  Returns FALSE if \a iImage is out of range.
     */
    virtual bool GetImageId(unsigned iImage, IMAGE *image) = 0;

    /*!
     * Retrieves information about an image that is currently loaded in the application.
     * Note that this may not be used to retrieve information for an image that has
     * been reported via STOP_REASON_IMAGE_UNLOAD.
     *
     *  @param[in] image    The image.
     *  @param[in] szInfo   Size (bytes) of the \a info structure.
     *  @param[out] info    Receives information about the image.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a image is not valid.
     */
    virtual bool GetImageInfo(IMAGE image, size_t szInfo, IMAGE_INFO *info) = 0;

    /*!
     * Tells the image that was loaded or unloaded for a thread that stopped with
     * STOP_REASON_IMAGE_LOAD or STOP_REASON_IMAGE_UNLOAD.
     *
     *  @param[in] thread       The ID of a thread.
     *  @param[out] image       Receives the image identifier.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a thread did not stop with STOP_REASON_IMAGE_LOAD or STOP_REASON_IMAGE_UNLOAD.
     *
     * @par Error Returns (when implemented  by debugger back-end)
     *  Returns FALSE if \a thread did not stop with STOP_REASON_IMAGE_LOAD or
     *  STOP_REASON_IMAGE_UNLOAD.
     */
    virtual bool GetThreadStopImage(THREAD thread, IMAGE *image) = 0;

protected:
    virtual ~IIMAGE_EXTENSIONS() {} ///< Do not call delete on IIMAGE_EXTENSIONS.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_THREAD_EXTENSIONS.
 */
class /*<INTERFACE>*/ ITHREAD_EXTENSIONS
{
public:
    /*!
     * Set the notifications that will be triggered when threads start or exit in the
     * target application.  By default, the back-end does not trigger any notifications
     * when start or exit..
     *
     *  @param[in] notifications    A bit-mask indicating which events should trigger
     *                               notifications.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     */
    virtual bool SetThreadNotifications(THREAD_NOTIFICATIONS notifications) = 0;

    /*!
     * Retrieves information about a thread in the application.
     *
     *  @param[in] thread   ID of a thread.
     *  @param[in] szInfo   Size (bytes) of the \a info structure.
     *  @param[out] info    Receives information about the thread.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     */
    virtual bool GetThreadInfo(THREAD thread, size_t szInfo, THREAD_INFO *info) = 0;
 
    /*!
     * Tells the thread exit status for a thread that stopped with STOP_REASON_THREAD_EXIT.
     *
     *  @param[in] thread   The ID of a thread.
     *  @param[out] status  Receives the O/S specific thread exit status.
     *
     * @return  TRUE on success.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     *      - The \a thread did not stop with STOP_REASON_THREAD_EXIT.
     *
     * @par Error Returns (when implemented  by debugger back-end)
     *  Returns FALSE if \a thread did not stop with STOP_REASON_THREAD_EXIT.
     */
    virtual bool GetThreadExitStatus(THREAD thread, FUND::INT64 *status) = 0;

protected:
    virtual ~ITHREAD_EXTENSIONS() {} ///< Do not call delete on ITHREAD_EXTENSIONS.
};

/*!
 * An optional interface that can be returned from ICOMMANDS::GetInterface() if the
 * back-end defines BACKEND_FEATURE_PROCESS_INFO.
 */
class /*<INTERFACE>*/ IPROCESS_INFO
{
public:
    /*!
     * Get the O/S process ID of the target application.
     *
     *  @param[out] pid     Receives the process ID.
     *
     * @par Error Returns (when used by debugger front-end)
     *  Returns FALSE if:
     *      - Communication error with back-end.
     *      - Called during "run mode".
     */
    virtual bool GetProcessId(PROCESS *pid) = 0;

    /*!
     * Retrieves the address of the loader inside the target process memory layout.
     *
     * @param[out] addr    The address of the loader.
     *
     * @return  TRUE on success.
     *
     *  Returns FALSE if:
     *      - Not supported (client interface doesn't exist).
     */
    virtual bool GetLoaderInfoAddr(FUND::ANYADDR *addr) = 0;

    /*!
     * Retrieves the target application architecture description.
     *
     * @param[out] desc    The description of the architecture (OS specific).
     *
     * @return  TRUE on success.
     *
     *  Returns FALSE if:
     *      - Not supported (client interface doesn't exist).
     */
    virtual bool GetTargetApplicationArch(void **desc) = 0;

protected:
    virtual ~IPROCESS_INFO() {} ///< Do not call delete on IPROCESS_INFO.
};


/*!
 * This interface represents notifications sent from the debugger back-end to the front-end.
 * There are two different usage models.
 *
 * When used by a debugger front-end, the front-end implements this interface and the
 * DEBUGGER_PROTOCOL library calls it in order to notify the front-end of events sent from
 * the back-end.
 *
 * When used by a back-end, the DEBUGGER_PROTOCOL library implements this interface, and the
 * back-end makes calls to it when it wants to send a notification to the front-end.  In this
 * model, the back-end should expect that a call to a method may fail due to a communication
 * error with the front-end.  The "Error Returns" section of each method describes this.
 */
class /*<INTERFACE>*/ INOTIFICATIONS
{
public:
    /*!
     * Indicates that all threads in the application stopped and the debugger back-end is
     * ready to accept commands from the front-end.  Use ICOMMANDS::GetThreadStopReason()
     * to determine why each thread stopped.  When this notification is sent, the debugger
     * changes to "command mode".
     *
     *  @param[in] focus    If the application stops because one of the threads triggered a
     *                       breakpoint, received an O/S event, or completed a single-step;
     *                       \a focus specifies that thread.  If there is more than one such
     *                       thread, one is chosen arbitrarily.  If there is no such thread,
     *                       \a focus is one arbitrarily chosen thread in the application.
     *
     * @return  TRUE.
     *
     * @par Error Returns (when used by debugger back-end)
     *  Returns FALSE on communication error, or if called during "command mode".
     */
    virtual bool NotifyStopped(THREAD focus) = 0;

    /*!
     * Indicates that the application terminated due to calling exit() or some similar
     * O/S service.  Since the application no longer exists, the back-end may not be
     * able to accept further commands.
     *
     *  @param[in] code     The application's exit code (e.g. value passed to exit()).
     *
     * @return  TRUE.
     *
     * @par Error Returns (when used by debugger back-end)
     *  Returns FALSE on communication error, or if called during "command mode".
     */
    virtual bool NotifyTerminatedExit(FUND::INT64 code) = 0;

    /*!
     * Indicates that the application terminated due to some O/S event (e.g. receiving an
     * unhandled Unix signal).  Note that some O/S's (e.g. Windows) may instead report a
     * fatal event via NotifyStopped() and then report that the application terminated via
     * a separate call to NotifyTerminatedExit().
     *
     *  @param[in] evnt         Identifies the terminating event.
     *  @param[in] szEvntInfo   Size (bytes) of the \a evntInfo structure, if that parameter
     *                           is non-NULL.
     *  @param[in] evntInfo     If not NULL, tells additional information about the terminating
     *                           event.  This parameter will always be NULL when the back-end
     *                           does not support BACKEND_FEATURE_EVENT_INFO.
     *
     * @return  TRUE.
     *
     * @par Error Returns (when used by debugger back-end)
     *  Returns FALSE on communication error, or if called during "command mode".
     */
    virtual bool NotifyTerminatedEvent(EVENT evnt, size_t szEvntInfo,
        const EVENT_INFO *evntInfo) = 0;

protected:
    virtual ~INOTIFICATIONS() {} ///< Do not call delete on INOTIFICATIONS.
};


/*!
 * Clients of the DEBUGGER_PROTOCOL library can implement this interface to receive
 * a notification whenever a protocol message is sent or received.  This is useful for
 * debugging the debugger-protocol itself.
 */
class /*<INTERFACE>*/ ILOG_NOTIFICATIONS
{
public:
    /*!
     * Indicates that a protocol message was sent or received.
     *
     *  @param[in] message  A textual description of the protocol message.
     */
    virtual void NotifyLogMessage(const std::string &message) = 0;

protected:
    virtual ~ILOG_NOTIFICATIONS() {} ///< Do not call delete on ILOG_NOTIFICATIONS.
};

} // namespace
#endif // file guard
