You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2017 lines
81 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software and the related documents are Intel copyrighted materials, and your
* use of them is governed by the express license under which they were provided to
* you ("License"). Unless the License provides otherwise, you may not use, modify,
* copy, publish, distribute, disclose or transmit this software or the related
* documents without Intel's prior written permission.
*
* This software and the related documents are provided as is, with no express or
* implied warranties, other than those that are expressly stated in the License.
*/
// <COMPONENT>: debugger-protocol
// <FILE-TYPE>: component public header
#ifndef DEBUGGER_PROTOCOL_HPP
#define DEBUGGER_PROTOCOL_HPP
#include <string>
#include "util.hpp"
#include "debugger-protocol/forward.hpp"
#if defined(DEBUGGER_PROTOCOL_BUILD_SHARED)
# define DEBUGGER_PROTOCOL_API _STLP_EXPORT_DECLSPEC
#elif defined(DEBUGGER_PROTOCOL_USE_SHARED)
# define DEBUGGER_PROTOCOL_API _STLP_IMPORT_DECLSPEC
#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;
/*!
* Images list required by GDB (in System V R4 standard).
* Implemented only for Linux GDB.
*
*/
typedef void SVR4_IMAGES_LIST;
/*!
* Image info required by GDB (in System V R4 standard).
* Implemented only for Linux GDB.
*
*/
typedef void SVR4_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 UINT32 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),
/*!
* The front-end supports the 'N' stop reply packet.
* The 'N' packet is sent to the front-end in the special case when all resumed
* threads had been terminated, but the process is still running (i.e. has additional
* active threads which are stopped by the debugger).
*/
FRONTEND_FEATURE_NO_RESUMED = (1<<2)
};
typedef UINT32 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),
/*!
* The back-end supports System V R4 libraries extension
*/
BACKEND_FEATURE_SVR4_LIBRARIES = (1<<11)
};
typedef UINT32 BACKEND_FEATURES; ///< Bit mask of BACKEND_FEATURE's.
/*!
* Various properties for debugger transport connection
*/
struct /*<POD>*/ DEBUGGER_CONNECTION_PROPERTIES
{
enum DEBUGGER_CONNECTION_TYPE
{
NONE,
TCP_SERVER,
TCP_CLIENT
};
/*!
* Underlying connection type for the debugger transport
*/
DEBUGGER_CONNECTION_TYPE _type;
/*!
* TCP port of the debugger connection
* Available only on TCP_SERVER or TCP_CLIENT connection types
*/
int _tcpPort;
/*!
* TCP host of the debugger connection
* Available only on TCP_CLIENT connection type
*/
std::string _tcpHost;
};
/*!
* 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),
/*!
* This option enables the backend to send unlimited size packets to the
* frontend.
*/
ENDPOINT_OPTION_UNLIMITED_LENGTH_PACKETS = (1<<4)
};
typedef UINT32 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.
INTERFACE_ID_SVR4_LIBRARIES ///< Back-end defines ISVR4_LIBRARIES.
};
/*!
* 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 UINT32 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 UINT32 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
{
STOP_REASON_INVALID,
/*!
* 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 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;
/*!
* Tell the backend to disable some features.
* Note that this must be called before the frontend was connected to
* this backend.
*
* @param[out] maskFeatures Mask of backend features to disable
*
*/
virtual void MaskFeatures(BACKEND_FEATURES maskFeatures) = 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.
* @param[in] props Debugger connection properties (depends on the debugger type).
*
* @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, const DEBUGGER_CONNECTION_PROPERTIES& props);
/*!
* 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, invalid thread Id if \a iThread is out of range.
*
* @par Error Returns (when used by debugger front-end)
* Returns invalid thread Id if called during "run mode".
*/
virtual THREAD GetThreadId(unsigned iThread) = 0;
/*!
* Retrieves the ID of a thread in the application that caused current stop
* or invalid thread Id if the focus thread can not be safely determined,
* like when all stopped threads are blocked in OS.
*
* @return The ID of the focus thread as determined by the back-end.
*
* @par Error Returns (when used by debugger front-end)
* Returns invalid thread Id if called during "run mode".
*/
virtual THREAD GetFocusThreadId() = 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(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(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(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(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;
/*!
* Gets the loaded images list of the application according to the SVR4 format.
*
* @param[out] info Receives the image list
*
* @return TRUE on success.
*
*/
virtual bool GetSvr4ImageList(SVR4_IMAGES_LIST *info) = 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, 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(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(std::string &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(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