/* * 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. */ // : debugger-protocol // : component public header #ifndef DEBUGGER_PROTOCOL_HPP #define DEBUGGER_PROTOCOL_HPP #include #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 /**/ 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 /**/ TCP_INFO { int _localPort; ///< The local port of a socket listening for a connection. }; /*! * Describes a single register in the target program. */ struct /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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 /**/ 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