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
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
|