If you find Xdebug useful, please consider supporting the project.

DBGP - A common debugger protocol specification

Version: 1.0
Status: draft 21
Authors: Shane Caraveo, ActiveState <shanec@ActiveState.com>
Derick Rethans <derick@derickrethans.nl>

Contents

1. Description

This document describes a simple protocol for use with language tools and engines for the purpose of debugging applications. It does not describe user interfaces or interactions with the debugger. The protocol provides a means of communication between a debugger engine (scripting engine, vm, etc.) and a debugger IDE (IDE, etc.). Any references to the debugger IDE UI are recommendations only, and are provided for additional explanation or as reasoning for specific design decisions.

1.1 Issues

1. The handling of proxy errors needs to be clarified. Without both IDE and debugger engine supporting commands to be received at arbitrary times, the proxy may have problems sending error or status information to either one. See section 5.3.2. We should think a bit more about what a proxy might need to do.

2. Requirements

  • extensibility, allow for vendor or language specific features
  • backwards and forwards compatibility
  • firewall and tunneling support
  • support for multiple languages
  • support for multiple processes or threads
  • support for dynamic and possibly for compiled languages

3. Terminology

IDE
An IDE, or other debugger UI IDE or tool.
debugger engine
The language engine being debugged.
proxy
An intermediary demon that acts as a proxy, and may also implement support for other features such as just in time debugging, ip security, etc.
session
a single thread in an application. multiple threads in an application will attach separately.
TRUE
a value defined as TRUE should be a numeric one.
FALSE
a value defined as FALSE should be a numeric zero.
NUM
a base 10 numeric value that is stringified.

4. Security

It is expected that implementations will provide security, such as ip filtering, ssh tunneling, etc. This protocol itself does not provide a means of securing the debugging session.

5. Initiating a debugging session

The debugger engine initiates a debugging session. The debugger engine will make a connection to a listening IDE, then wait for the IDE to initiate commands. The debugger engine does not step into the first line of execution until the IDE issues one of the continuation commands. The first thing that should happen in a debug session is that the IDE negotiates features using the feature_get and feature_set commands, and sets any additional data, such as breakpoints. Debugger engine implementations should store any data it receives if it is unable to process them prior to compiling and/or executing code. Commands such as stack_get should not be expected to work during this phase, otherwise known as the 'starting' state (see section 7.1 for status levels).

Likewise, at the end of a debug session, there is a 'stopping' state. This state is entered after all execution is complete. For most debugger engine implementations, only a 'stop' command can be accepted at this point, however some implementations may provide additional commands for retrieving various data from the engine for post debug session processing.

5.1 Standard DBGP port

The IDE listens on port 9000 for debugger connections, unless the IDE is using a proxy, in which case it may listen on any port. In that case, the IDE will tell the proxy which port it is listening on, and the proxy should listen on port 9000. While this document defines port 9000 as the standard DBGP port, an implementation may support the use of any port. Current implementations accept various forms of configuration that allow this port to be defined.

5.2 Connection Initialization

When a debugger engine connects to either a IDE or proxy, it must send an init packet:

<init appid="APPID"
      idekey="IDE_KEY"
      session="DBGP_COOKIE"
      thread="THREAD_ID"
      parent="PARENT_APPID"
      language="LANGUAGE_NAME"
      protocol_version="1.0"
      fileuri="file://path/to/file">

Attributes in the init element can include:

Attribute Description
appid defined by the debugger engine
idekey defined by the user. The DBGP_IDEKEY environment variable SHOULD be used if it is available, otherwise setting this value is debugger engine implementation specific. This value may be empty.
session If the environment variable DBGP_COOKIE exists, then the init packet MUST contain a session attribute with the value of the variable. This allows an IDE to execute a debugger engine, and maintain some state information between the execution and the protocol connection. This value should not be expected to be set in 'remote' debugging situations where the IDE is not in control of the process.
thread the systems thread id
parent the appid of the application that spawned the process. When an application is executed, it should set it's APPID into the environment. If an APPID already exists, it should first read that value and use it as the PARENT_APPID.
language debugger engine specific, must not contain additional information, such as version, etc.
protocol_version The highest version of this protocol supported
fileuri URI of the script file being debugged

The IDE responds by dropping socket connection, or starting with debugger commands.

The init packet may have child elements for additional vendor specific data. These are entirely optional and must not effect behavior of the debugger interaction. Suggested child elements include:

<engine version="1.abcd">product title</engine>
<author>author</author>
<company>company</company>
<license>licensing info</license>
<url>url</url>
<copyright>xxx</copyright>

5.3 Just in time debugging and debugger proxies

Proxies are supported to allow multiuser systems work with a defined port for debugging. Each IDE would listen on a unique port and notify the proxy what port it is listening on, along with a key value that is used by the debugger engine to specify which IDE it should be connected with.

With the exception of the init packet, all communications will be passed through without modifications. A proxy could also implement support for just in time debugging. In this case, a debugger engine would break (perhaps on an error or exception) and connect to the proxy. The proxy would then start the IDE (if it is not already running) and initiate a debugging session with it.

The method for handling just in time debugging is not defined by the protocol and is implementation specific. One example of how this may work is that the proxy has a configuration file that defines key's for each user, along with the path to the executable that will provide the UI for that user. The debugger engine would have to know this key value in advance and provide it to the proxy in the init packet (see IDE_KEY in section 5.2). The proxy would know if the IDE is running, since the IDE should have communicated with the proxy already, if it has not, the proxy could execute the IDE directly.

To support proxies and JIT daemons, the IDE should be configured with a port pointing to the proxy/JIT. The IDE then makes a connection to the proxy when it starts and sends the following command:

IDE command

proxyinit -p port -k ide_key -m [0|1]
-p the port that the IDE listens for debugging on. The address is retrieved from the connection information.
-k a IDE key, which the debugger engine will also use in it's debugging init command. this allows the proxy to match request to IDE. Typically the user will provide the session key as a configuration item.
-m this tells the demon that the IDE supports (or doesn't) multiple debugger sessions. if -m is missing, zero or no support is default.

IDE command

proxystop -k ide_key

The IDE sends a proxystop command when it wants the proxy server to stop listening for it.

The proxy should respond with a simple XML statement alerting the IDE to an error, or the success of the initialization (see section 6.5 for more details on the error element).

<proxyinit success="[0|1]"
           idekey="{ID}"
           address="{IP_ADDRESS}"
           port="{NUM}>
    <error id="app_specific_error_code">
        <message>UI Usable Message</message>
    </error>
</proxyinit>

Once the IDE has sent this command, and received a confirmation, it disconnects from the proxy. The IDE will only connect to the proxy when it initially wants to start accepting connections from the proxy, or when it wants to stop accepting connections from the proxy.

The address and port attributes of the returned proxyinit element are the address and port that the proxy is configured to listen for DBGP connections on. This information is returned to the IDE so that it may pass this information on to build systems or the user via some UI.

5.3.1 Init Packet Handling

If a proxy receives the init packet (see section 5.2), it will use the idekey attribute to pass the request to the correct IDE, or to do some other operation such as which may be required to implement security or initiate just in time debugging. The proxy will add the idekey as a attribute to the init packet when it passes it through to the IDE. The proxy may also add child elements with further information, and must add an attribute to the init element called 'proxied' with the attribute value being the ip address of the debugger engine. This is the only time the proxy should modify data being passed to the IDE.

5.3.2 Proxy Errors

If the proxy must send error data to the IDE, it may send an XML message with the root element named 'proxyerror'. This message will be in the format of the error packets defined in 6.3 below.

If the proxy must send error data to the debugger engine, it may send the proxyerror command defined in section 7 below.

5.3.3 Proxy Ports

The proxy listens for IDE connections on port 9001, and for debugger engine connections on port 9000. As with section 5.1, these ports may be configurable in the implementation.

5.4 Multiple Processes or Threads

The debugger protocol is designed to use a separate socket connection for each process or thread. The IDE may or may not support multiple debugger sessions. If it does not, the debugger engine must not attempt to start debug sessions for threads, and the IDE should not accept more than one socket connection for debugging. The IDE should tell the debugger engine whether it supports multiple debugger sessions, the debugger engine should assume that the IDE does not. The IDE can use the feature_set command with the feature name of 'multiple_sessions' to notify the debugger engine that it supports multiple session debugging. The IDE may also query the debugger engine specifically for multithreaded debugging support by using the feature_get command with a feature name of 'language_supports_threads'.

5.5 Feature Negotiation

Although the IDE may at any time during the debugging session send feature_get or feature_set commands, the IDE should be designed to negotiate the base set of features up front. Differing languages and debugger engines may operate in many ways, and the IDE should be prepared to handle these differences. Likewise, the IDE may dictate certain features or capabilities be supported by the debugger engine. In any case, the IDE should strive to work with all debugger engines that support this protocol. Therefore, this section describes a minimal set of features the debugger engine must support. These required features are outlined here in the form of discussion, actual implementation of feature arguments are detailed in section 7 under the feature_get and feature_set commands.

Data packet negotiation

IDE's may want to limit the size of data that is retrieved from debugger engines. While the debugger engines will define their own base default values, the IDE should negotiate these terms if it needs to. The debugger engine must support these requests from the IDE. This includes limits to the data size of a property or variable, and the depth limit to arrays, hashes, objects, or other tree like structures. The data size excludes the protocol overhead.

Asynchronous Communications

While the protocol does not depend on asynchronous socket support, certain design considerations may require that the IDE and/or debugger engine treat incoming and outgoing data in an asynchronous fashion.

For ease of design, some implementations may choose to utilize this protocol in a completely synchronous fashion, and not implement optional commands that require the debugger engine to behave in an asynchronous fashion. One example of this is the break command.

The break command is sent from the IDE while the debugger engine is in a run state. To support this, the debugger engine must periodically peek at the socket to see if there are any incoming commands. For this reason the break command is optional. If a command requires this type of asynchronous behavior on the part of the debugger engine it must be optional for the debugger engine to support it.

On the other hand, IDE's MUST at times behave in an asynchronous fashion. When an IDE tells the debugger engine to enter a 'run' state, it must watch the socket for incoming packets for stdout or stderr, if it has requested the data be sent to it from the debugger engine.

The form of asynchronous communications that may occur in this protocol are defined further in section 6.2 below.

6. Message Packets

The IDE sends simple ASCII commands to the debugger engine. The debugger engine responds with XML data. The XML data is prepended with a stringified integer representing the number of bytes in the XML data packet. The length and XML data are separated by a NULL byte. The XML data is ended with a NULL byte. Neither the IDE or debugger engine packets may contain NULL bytes within the packet since it is used as a separator. The IDE to debugger engine data element (behind --) MUST be encoded using base64.

IDE:       command [SPACE] [args] -- data [NULL]
DEBUGGER:  [NUMBER] [NULL] XML(data) [NULL]

Arguments to the IDE commands are in the same format as common command line arguments, and should be parseable by common code such as getopt, or Pythons Cmd module:

command -a value -b value ...

All numbers in the protocol are base 10 string representations, unless the number is noted to be debugger engine specific (e.g. the address attribute on property elements).

6.1 Why not XML both ways?

The primary reason is to avoid the requirement that a debugger engine has an XML parser available. XML is easy to generate, but requires additional libraries for parsing.

6.2 Packet Communications

The IDE sends a command, then waits for a response from the debugger engine. If the command is not received in a reasonable time (implementation dependent) it may assume the debugger engine has entered a non-responsive state. The exception to this is when the IDE sends a 'continuation' command which may not have an immediate response.

'continuation' commands include, but may not be limited to: run, step_into, step_over, step_out and eval. When the debugger engine receives such a command, it is considered to have entered a 'run state'.

During a 'continuation' command, the IDE should expect to possibly receive stdin and/or stderr packets from the debugger engine prior to receiving a response to the command itself. It may also possibly receive error packets from either the debugger engine, or a proxy if one is in use, either prior to the 'continuation' response, or in response to any other command.

Stdout and stderr, if requested by the IDE, may only be sent during commands that have put the debugger engine into a 'run' state.

If the debugger engine supports asynchronous commands, the IDE may also send commands while the debugger engine is in a 'run' state. These commands should be limited to commands such as the 'break' or 'status' commands for performance reasons, but this protocol does not impose such limitations. The debugger engine MUST respond to these commands prior to responding to the original 'run' command.

An example of communication between IDE and debugger engines. (this is not an example of the actual protocol.)

IDE:  feature_get supports_async
DBG:  yes
IDE:  stdin redirect
DBG:  ok
IDE:  stderr redirect
DBG:  ok
IDE:  run
DBG:  stdin data...
DBG:  stdin data...
DBG:  reached breakpoint, done running
IDE:  give me some variables
DBG:  ok, here they are
IDE:  evaluate this expression
DBG:  stderr data...
DBG:  ok, done
IDE:  run
IDE:  break
DBG:  ok, breaking
DBG:  at breakpoint, done running
IDE:  stop
DBG:  good bye

6.3 IDE to debugger engine communications

A debugging IDE (IDE) sends commands to the debugger engine in the form of command line arguments.

Some comments support a data argument that is included at the end of the "command line". This data is included in the packet's data length. The data itself is the last part of the command line, after the -- separator. The data must be base64 encoded:

command [SPACE] [arguments] [SPACE] -- base64(data) [NULL]

Standard arguments for all commands

-i      Transaction ID
        unique numerical ID for each command generated by the IDE

All the other arguments depend on which command is being sent.

6.3.1 Escaping Rules

If a value for an option includes a space or NULL character, the IDE MUST encapsulate the value in double quotes ("):

property_get -i 5 -n "$x['a b']"

In other cases, the value MAY be encapsulated in double quotes:

property_get -i 6 -n "$x['ab']"

Inside a double-quoted argument, the double-quote ("), back-slash (\) and NULL character (chr(0)) MUST be escaped with a back-slash. Single quotes (') MAY be escaped.

Escaping double-quote and single-quote:

property_get -i 7 -n "$x[\"a b\"]"
property_get -i 8 -n "$x['a b']"
property_get -i 9 -n "$x[\'a b\']"

Most languages don't support this, but we have if we have a NULL character in the string, like in $x chr(0) y, or, $x->f chr(0) oo, than they need to be quoted with a back-slash (\), as in:

property_get -i 10 -n "$x\0y"
property_get -i 11 -n "$x->f\0oo"

If the NULL character is already escaped according to a language, for example, as part of an array element key, then there is no un-escaped NULL character in the string any more, and hence does not need to be escaped again.

The Debugging Engine in this case would already have returned the XML attribute value $x[&quot;a\0b&quot;] [*], where the chr(0) is already escaped as \0.

XML decoding this gives $x["a\0b"], which can be used as argument as either one of:

property_get -i 12 -n $x["a\0b"]
property_get -i 13 -n "$x[\"a\\0b\"]"
[*]

With the extended_properties feature set to 1, the Debugger Engine would not have sent $x[&quot;a\0b&quot;] as attribute value, but rather it would have used <fullname encoding="base64"><![CDATA[JHhbImFcMGIiXQ==]]></fullname>, as the chr(0) in the name property would have triggered the use of base64 encoded XML element values.

Without extended_properties set to 1, the Debugger Engine would have sent the invalid XML attribute value &#0;.

6.4 debugger engine to IDE communications

The debugger engine always replies or sends XML data. The standard namespace for the root elements returned from the debugger engine MUST be urn:debugger_protocol_v1. Namespaces have been left out in the other examples in this document. The messages sent by the debugger engine must always be NULL terminated. The XML document tag must always be present to provide XML version and encoding information.

For simplification, data length and NULL bytes will be left out of the rest of the examples in this document.

Three base tags are used for the root tags:

6.4.1 response

This data packet is returned as response to continuation commands:

data_length
[NULL]
<?xml version="1.0" encoding="UTF-8"?>
<response xmlns="urn:debugger_protocol_v1"
          command="command_name"
          transaction_id="transaction_id"/>
[NULL]

6.4.2 stream

This data packet is sent when stream redirection is enabled through 7.15 stdout, stderr redirections. As the data is base64 encoded, the stream packet always has the encoding attribute set to base64:

data_length
[NULL]
<?xml version="1.0" encoding="UTF-8"?>
<stream xmlns="urn:debugger_protocol_v1"
        type="stdout|stderr"
        encoding="base64">
    ...Base64 Data...
</stream>
[NULL]

6.4.3 notify

This data packet is sent when 8.5 Notifications are enabled through setting the notify_ok feature (see 7.2.1 Feature names). As the data is base64 encoded, the notify packet always has the encoding attribute set to base64:

data_length
[NULL]
<?xml version="1.0" encoding="UTF-8"?>
<notify xmlns="urn:debugger_protocol_v1"
        xmlns:customNs="http://example.com/dbgp/example"
        name="notification_name"
        encoding="base64">
    <customNs:customElement/>
    ...Base64 Data...
</notify>
[NULL]

6.5 debugger engine errors

A debugger engine may need to relay error information back to the IDE in response to any command. The debugger engine may add an error element as a child of the response element. Note that this is not the same as getting language error messages, such as exception data. This is specifically a debugger engine error in response to a IDE command. IDEs and debugger engines may elect to support additional child elements in the error element, but should namespace the elements to avoid conflicts with other implementations.

<response command="command_name"
          transaction_id="transaction_id">
    <error code="error_code" customNs:apperr="app_specific_error_code">
        <customNs:message>UI Usable Message</customNs:message>
    </error>
</response>

6.5.1 Error Codes

The following are predefined error codes for the response to commands:

000 Command parsing errors

0 - no error
1 - parse error in command
2 - duplicate arguments in command
3 - invalid options (ie, missing a required option, invalid value for a
    passed option, not supported feature)
4 - Unimplemented command
5 - Command not available (Is used for async commands. For instance
    if the engine is in state "run" then only "break" and "status"
    are available).

100 File related errors

100 - can not open file (as a reply to a "source" command if the
      requested source file can't be opened)
101 - stream redirect failed

200 Breakpoint, or code flow errors

200 - breakpoint could not be set (for some reason the breakpoint
      could not be set due to problems registering it)
201 - breakpoint type not supported (for example I don't support
      'watch' yet and thus return this error)
202 - invalid breakpoint (the IDE tried to set a breakpoint on a
      line that does not exist in the file (ie "line 0" or lines
      past the end of the file)
203 - no code on breakpoint line (the IDE tried to set a breakpoint
      on a line which does not have any executable code. The
      debugger engine is NOT required to return this type if it
      is impossible to determine if there is code on a given
      location. (For example, in the PHP debugger backend this
      will only be returned in some special cases where the current
      scope falls into the scope of the breakpoint to be set)).
204 - Invalid breakpoint state (using an unsupported breakpoint state
      was attempted)
205 - No such breakpoint (used in breakpoint_get etc. to show that
      there is no breakpoint with the given ID)
206 - Error evaluating code (use from eval() (or perhaps
      property_get for a full name get))
207 - Invalid expression (the expression used for a non-eval()
      was invalid)

300 Data errors

300 - Can not get property (when the requested property to get did
      not exist, this is NOT used for an existing but uninitialized
      property, which just gets the type "uninitialised" (See:
      PreferredTypeNames)).
301 - Stack depth invalid (the -d stack depth parameter did not
      exist (ie, there were less stack elements than the number
      requested) or the parameter was < 0)
302 - Context invalid (an non existing context was requested)

900 Protocol errors

900 - Encoding not supported
998 - An internal exception in the debugger occurred
999 - Unknown error

6.6 file paths

All file paths passed between the IDE and debugger engine must be in the URI format specified by IETF RFC 1738 and 2396, and must be absolute paths.

6.7 Dynamic code and virtual files

The protocol reserves the URI scheme 'dbgp' for all virtual files generated and maintained by language engines. Such virtual files are usually managed by a language engine for dynamic code blocks, i.e. code created at runtime, without an association with a regular file. Any IDE seeing an URI with the 'dbgp' scheme has to use the 'source' command (See section 7.14) to obtain the contents of the file from the engine responsible for that URI.

All URIs in that scheme have the form:

dbgp:engine-specific-identifier

The engine-specific-identifier is some string which the debugger engine uses to keep track of the specific virtual file. The IDE must return the URI to the debugger engine unchanged through the source command to retrieve the virtual file.

7. Core Commands

Both IDE and debugger engine must support all core commands.

7.1 status

The status command is a simple way for the IDE to find out from the debugger engine whether execution may be continued or not. no body is required on request. If async support has been negotiated using feature_get/set the status command may be sent while the debugger engine is in a 'run state'.

The status attribute values of the response may be:

starting:
State prior to execution of any code
stopping:
State after completion of code execution. This typically happens at the end of code execution, allowing the IDE to further interact with the debugger engine (for example, to collect performance data, or use other extended commands).
stopped:
IDE is detached from process, no further interaction is possible.
running:
code is currently executing. Note that this state would only be seen with async support turned on, otherwise the typical state during IDE/debugger interaction would be 'break'
break:
code execution is paused, for whatever reason (see below), and the IDE/debugger can pass information back and forth.

The reason attribute value may be:

  • ok
  • error
  • aborted
  • exception

IDE

status -i transaction_id

debugger engine

<response command="status"
          status="starting"
          reason="ok"
          transaction_id="transaction_id">
    message data
</response>

7.2 Options and Configuration

The feature commands are used to request feature support from the debugger engine. This includes configuration options, some of which may be changed via feature_set, the ability to discover support for implemented commands, and to discover values for various features, such as the language version or name.

An example of usage would be to send a feature request with the string 'stdin' to find out if the engine supports redirection of the stdin stream through the debugger socket. The debugger engine must consider all commands as keys for this command, but may also have keys that are for features that do not map directly to commands.

7.2.1 Feature Names

The following features strings MUST be available:

language_supports_threads get [0|1]
language_name get {eg. PHP, Python, Perl}
language_version get {version string}
encoding get|set current encoding in use by the debugger session. The encoding can either be (7-bit) ASCII, or a code set which contains ASCII (Ex: ISO-8859-X, UTF-8). Use the supported_encodings feature to query which encodings are supported
protocol_version get {for now, always 1}
supports_async get {for commands such as break}
data_encoding get optional, allows to turn off the default base64 encoding of data. This should only be used for development and debugging of the debugger engines themselves, and not for general use. If implemented the value 'base64' must be supported to turn back on regular encoding. the value 'none' means no encoding is in use. all elements that use encoding must include an encoding attribute.
breakpoint_languages get some engines may support more than one language. This feature returns a string which is a comma separated list of supported languages. If the engine does not provide this feature, then it is assumed that the engine only supports the language defined in the feature language_name. One example of this is an XSLT debugger engine which supports XSLT, XML, HTML and XHTML. An IDE may need this information to to know what types of breakpoints an engine will accept.
breakpoint_types get returns a space separated list with all the breakpoint types that are supported. See 7.6 breakpoints for a list of the 6 defined breakpoint types.
resolved_breakpoints get returns whether the debugging engine supports the notion of resolving breakpoints. See the resolved attribute under 7.6 breakpoints for further information.
multiple_sessions get|set {0|1}
max_children get|set max number of array or object children to initially retrieve
max_data get|set max amount of variable data to initially retrieve.
max_depth get|set maximum depth that the debugger engine may return when sending arrays, hashs or object structures to the IDE.
extended_properties get|set {0|1} Extended properties are required if there are property names (name, fullname or classname) that can not be represented as valid XML attribute values (such as &#0;). See also 7.11 Properties, variables and values.

The following features strings MAY be available, if they are not, the IDE should assume that the feature is not available:

supported_encodings get returns a comma separated list of all supported encodings that can be set through the encoding feature
supports_postmortem get [0|1] This feature lets an IDE know that there is benefit to continuing interaction during the STOPPING state (sect. 7.1).
show_hidden get|set [0|1] This feature can get set by the IDE if it wants to have more detailed internal information on properties (eg. private members of classes, etc.) Zero means that hidden members are not shown to the IDE.
notify_ok get|set [0|1] See section 8.5 Notifications.

Additionally, all protocol commands supported must have a string, such as the following examples:

breakpoint_set
break
eval

7.2.2 feature_get

arguments for feature_get include:

-n feature_name

IDE

feature_get -i transaction_id -n feature_name

debugger engine

<response command="feature_get"
          feature_name="feature_name"
          supported="0|1"
          transaction_id="transaction_id">
    feature setting or available options, such as a list of
    supported encodings
</response>

The 'supported' attribute does NOT mean that the feature is supported, this is encoded in the text child of the response tag. The 'supported' attribute informs whether the feature with 'feature_name' is supported by feature_get in the engine, or when the command with name 'feature_get' is supported by the engine.

Example: Xdebug does not understand the 'breakpoint_languages' feature and will therefore set the supported attribute to '0'. It does however understand the feature 'language_supports_threads' and the 'supported' attribute is therefore set to '1', but as PHP does not support threads, the returned value is in this case "0".

7.2.3 feature_set

The feature set command allows a IDE to tell the debugger engine what additional capabilities it has. One example of this would be telling the debugger engine whether the IDE supports multiple debugger sessions (for threads, etc.). The debugger engine responds with telling the IDE whether it has enabled the feature or not.

Note: The IDE does not have to listen for additional debugger connections if it does not support debugging multiple sessions. debugger engines must handle connection failures gracefully.

arguments for feature_set include:

-n feature_name
-v value to be set

feature_set can be called at any time during a debug session to change values previously set. This allows a IDE to change encodings.

IDE

feature_set -i transaction_id -n feature_name -v value

debugger engine

<response command="feature_set"
          feature="feature_name"
          success="0|1"
          transaction_id="transaction_id"/>

If the feature is not supported, the debugger engine should return an error with the code set to 3 (invalid arguments).

7.5 continuation commands

resume the execution of the application.

run:
starts or resumes the script until a new breakpoint is reached, or the end of the script is reached.
step_into:
steps to the next statement, if there is a function call involved it will break on the first statement in that function
step_over:
steps to the next statement, if there is a function call on the line from which the step_over is issued then the debugger engine will stop at the statement after the function call in the same scope as from where the command was issued
step_out:
steps out of the current scope and breaks on the statement after returning from the current function. (Also called 'finish' in GDB)
stop:
ends execution of the script immediately, the debugger engine may not respond, though if possible should be designed to do so. The script will be terminated right away and be followed by a disconnection of the network connection from the IDE (and debugger engine if required in multi request apache processes).
detach (optional):
stops interaction with the debugger engine. Once this command is executed, the IDE will no longer be able to communicate with the debugger engine. This does not end execution of the script as does the stop command above, but rather detaches from debugging. Support of this continuation command is optional, and the IDE should verify support for it via the feature_get command. If the IDE has created stdin/stdout/stderr pipes for execution of the script (eg. an interactive shell or other console to catch script output), it should keep those open and usable by the process until the process has terminated normally.

The response to a continue command is a status response (see status above). The debugger engine does not send this response immediately, but rather when it reaches a breakpoint, or ends execution for any other reason.

IDE

run -i transaction_id

debugger engine

<response command="run"
          status="starting"
          reason="ok"
          transaction_id="transaction_id"/>

7.6 breakpoints

Breakpoints are locations or conditions at which a debugger engine pauses execution, responds to the IDE, and waits for further commands from the IDE. A failure in any breakpoint commands results in an error defined in section 6.5.

The following DBGP commands relate to breakpoints:

breakpoint_set Set a new breakpoint on the session.
breakpoint_get Get breakpoint info for the given breakpoint id.
breakpoint_update Update one or more attributes of a breakpoint.
breakpoint_remove Remove the given breakpoint on the session.
breakpoint_list Get a list of all of the session's breakpoints.

There are six different breakpoints types:

Type Req'd Attrs Description
line filename, lineno break on the given lineno in the given file
call function break on entry into new stack for function name
return function break on exit from stack for function name
exception exception break on exception of the given name
conditional expression, filename break when the given expression is true at the given filename and line number or just in given filename
watch expression break on write of the variable or address defined by the expression argument

A breakpoint has the following attributes. Note that some attributes are only applicable for some breakpoint types.

type breakpoint type (see table above for valid types)
filename The file the breakpoint is effective in. This must be a "file://" or "dbgp:" (See 6.7 Dynamic code and virtual files) URI.
lineno Line number on which breakpoint is effective. Line numbers are 1-based. If an implementation requires a numeric value to indicate that lineno is not set, it is suggested that -1 be used, although this is not enforced.
state Current state of the breakpoint. This must be one of enabled, disabled.
function Function name for call or return type breakpoints.
temporary Flag to define if breakpoint is temporary. A temporary breakpoint is one that is deleted after its first use. This is useful for features like "Run to Cursor". Once the debugger engine uses a temporary breakpoint, it should automatically remove the breakpoint from it's list of valid breakpoints.
resolved Flag to denote whether a breakpoint has been resolved. The value of the attribute is either resolved or unresolved. A resolved breakpoint is one where the debugger engine has established that it can actually break on: the file/line number (line type breakpoints), the function name (call and return type breakpoints), or the exception name (exception type breakpoints). For dynamic languages, that load files as the execution happens, this is useful for finding out invalid breakpoints. This is a read only flag. It MUST be included when the debugger engine does support resolving of breakpoints, and it MUST NOT be included if the debugger engine has no notion of resolved breakpoints. An IDE can use the resolved_breakpoints feature to find out whether a debugging engine supports resolved breakpoints.
hit_count Number of effective hits for the breakpoint in the current session. This value is maintained by the debugger engine (a.k.a. DBGP client). A breakpoint's hit count should be increment whenever it is considered to break execution (i.e. whenever debugging comes to this line). If the breakpoint is disabled then the hit count should NOT be incremented.
hit_value A numeric value used together with the hit_condition to determine if the breakpoint should pause execution or be skipped.
hit_condition

A string indicating a condition to use to compare hit_count and hit_value. The following values are legal:

>=
break if hit_count is greater than or equal to hit_value [default]
==
break if hit_count is equal to hit_value
%
break if hit_count is a multiple of hit_value
exception Exception name for exception type breakpoints.
expression The expression used for conditional and watch type breakpoints

Breakpoints should be maintained in the debugger engine at an application level, not the thread level. Debugger engines that support thread debugging MUST provide breakpoint id's that are global for the application, and must use all breakpoints for all threads where applicable.

As for any other commands, if there is error the debugger engine should return an error response as described in section 6.5.

7.6.1 breakpoint_set

This command is used by the IDE to set a breakpoint for the session.

IDE to debugger engine:

breakpoint_set -i TRANSACTION_ID [<arguments...>] -- base64(expression)

where the arguments are:

-t TYPE breakpoint type, see above for valid values [required]
-s STATE breakpoint state [optional, defaults to "enabled"]
-f FILENAME the filename to which the breakpoint belongs [optional]
-n LINENO the line number (lineno) of the breakpoint [optional]
-m FUNCTION function name [required for call or return breakpoint types]
-x EXCEPTION exception name [required for exception breakpoint types]
-h HIT_VALUE hit value (hit_value) used with the hit condition to determine if should break; a value of zero indicates hit count processing is disabled for this breakpoint [optional, defaults to zero (i.e. disabled)]
-o HIT_CONDITION hit condition string (hit_condition); see hit_condition documentation above; BTW 'o' stands for 'operator' [optional, defaults to '>=']
-r 0|1 Boolean value indicating if